No public description

PiperOrigin-RevId: 736467193
Change-Id: I381652c52b2d6f63386bdb0192919bfb9c427566
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..fd42169
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,25 @@
+# help out git with erroneous or incomplete email address mappings
+
+Piotr Drąg <raven@fedoraproject.org>
+Domingo Becker <beckerde@fedoraproject.org>
+Ulrich Drepper <drepper@x201.akkadia.org>
+Ulrich Drepper <drepper@redhat.com.roland>
+Hyu_gabaru Ryu_ichi <hyuuga@fedoraproject.org>
+kiyoto hashida  <khasida@fedoraproject.org>
+Claudio Rodrigo Pereyra Diaz <elsupergomez@fedoraproject.org>
+Gladys Guerrero <gguerrer@fedoraproject.org>
+Wei Liu <leahliu@fedoraproject.org>
+Michael Münch <micm@fedoraproject.org>
+Noah Sanci <nsanci@redhat.com>
+Noriko Mizumoto <noriko@fedoraproject.org>
+Cornelius Neckenig <tbull@fedoraproject.org>
+Francesco Tombolini <tombo@fedoraproject.org>
+Thomas Spura <tomspur@fedoraproject.org>
+Geert Warrink <warrink@fedoraproject.org>
+Yulia Poyarkova <ypoyarko@fedoraproject.org>
+Yuri Chornoivan <yurchor@fedoraproject.org>
+Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
+Daniel Cabrera <logan@fedoraproject.org>
+Thomas Canniot <mrtom@fedoraproject.org>
+Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz> наб via Elfutils-devel <elfutils-devel@sourceware.org>
+
diff --git a/AUTHORS b/AUTHORS
new file mode 100644
index 0000000..45cb1f8
--- /dev/null
+++ b/AUTHORS
@@ -0,0 +1,104 @@
+Aaron Merey
+Adam Markey
+Adrian Ratiu
+Ahelenia Ziemiańska
+Akihiko Odaki
+Alexander Cherepanov
+Alexander Kanavin
+Alexander Miller
+Alice Zhang
+Andreas Krebbel
+Andreas Schwab
+Andrei Homescu
+Anthony G. Basile
+Ben Woodard
+Chih-Hung Hsieh
+Claudio Rodrigo Pereyra Diaz
+Colin Cross
+Cornelius Neckenig
+Daniel Cabrera
+David Abdurachmanov
+Di Chen
+Dima Kogan
+Dimitris Glezos
+Dmitry V. Levin
+Dodji Seketeli
+Domingo Becker
+Eduardo Santiago
+Eli Schwartz
+Érico Nogueira
+Érico Rolim
+Filipe Brandenburger
+Florian Weimer
+Francesco Tombolini
+Frank Ch. Eigler
+Geert Warrink
+Gladys Guerrero
+Gustavo Romero
+Hayatsu Shunsuke
+H.J. Lu
+Hyu_gabaru Ryu_ichi
+Jakub Jelinek
+Jan Kratochvil
+Jan Pokorný
+Jason P. Leasure
+Jean Pihet
+Jeff Kenton
+Jim Wilson
+John M Mellor-Crummey
+John Ogness
+Jonathan Lebon
+Jonathon Anderson
+Jose E. Marchesi
+Josh Stone
+Joshua Watt
+Kevin Cernekee
+kiyoto hashida
+Konrad Kleine
+Kurt Roeckx
+Kyle McMartin
+Lei Zhang
+Lubomir Rintel
+Luca Boccassi
+Luiz Angelo Daros de Luca
+Mao Han
+Marek Polacek
+Mark Wielaard
+Martin Liska
+Masatake YAMATO
+Matt Fleming
+Matthias Klose
+Matthias Maennich
+Max Filippov
+Michael Forney
+Michael Münch
+Mike Frysinger
+Milian Wolff
+Namhyung Kim
+Noah Sanci
+Noriko Mizumoto
+Omar Sandoval
+Petr Machata
+Pino Toscano
+Piotr Drąg
+Ravi Bangoria
+Richard Henderson
+Roland McGrath
+Rosen Penev
+Ross Burton
+Saleem Abdulrasool
+Sergei Trofimovich
+Srđan Milaković
+Steven Chamberlain
+Thomas Canniot
+Thomas Spura
+Timm Bäder
+Tom Tromey
+Ulf Hermann
+Ulrich Drepper
+Wei Liu
+William Cohen
+Yonghong Song
+Yulia Poyarkova
+Yunlian Jiang
+Yuri Chornoivan
diff --git a/AUTHORS.sh b/AUTHORS.sh
new file mode 100644
index 0000000..ff048a6
--- /dev/null
+++ b/AUTHORS.sh
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+# Create the AUTHORS file, by searching the git history.
+
+# Run as "AUTHORS.sh" to get complete history
+# Run with "AUTHORS.sh commitish..commitish" for history between tags
+
+# shortlog will canonicalize the names using the file .mailmap
+git shortlog -s ${1-} |
+sed -e 's, via Elfutils-devel,,' |
+cut -b8- | # strip the commit counts
+sort | uniq
diff --git a/CONTRIBUTING b/CONTRIBUTING
new file mode 100644
index 0000000..5614728
--- /dev/null
+++ b/CONTRIBUTING
@@ -0,0 +1,142 @@
+The project home is http://elfutils.org/
+
+The current elfutils source code can be checked out with
+git clone git://sourceware.org/git/elfutils.git
+
+The developer mailinglist to send patches to is
+elfutils-devel@sourceware.org.
+https://sourceware.org/ml/elfutils-devel/
+
+To subscribe send an email to elfutils-devel-subscribe@sourceware.org
+Or use the form at https://sourceware.org/mailman/listinfo/elfutils-devel
+
+Please supply patches using git format-patch or using git send-email.
+
+Sign your work
+
+To facilitate tracking of who did what, we've adopted a "sign-off"
+procedure for patches based on the procedure used by the Linux kernel
+project.
+
+The sign-off is a simple line at the end of the explanation for the
+patch, which certifies that you wrote it or otherwise have the right
+to pass it on as a patch under an appropriate license. The rules are
+pretty simple: if you can certify the below:
+
+        Developer's Certificate of Origin
+
+        By making a contribution to this project, I certify that:
+
+	(a) The contribution was created in whole or in part by me,
+	    and I have the right to submit the contribution under each
+	    license indicated in, or otherwise designated as being
+	    applicable to, the file.
+
+        (b) The contribution was provided directly to me by some other
+            person who certified (a), and I have not modified it.
+
+        (c) I understand and agree that the project and the
+            contribution are public and that a record of the
+            contribution (including all personal information I submit
+            with it, including my sign-off) is maintained indefinitely
+            and may be redistributed.
+
+then you just add a line saying
+
+Signed-off-by: Random J Developer <random@developer.example.org>
+
+using a known identity (sorry, no anonymous contributions.)
+The name you use as your identity should not be an anonymous id
+or false name that misrepresents who you are.
+
+git commit --signoff will add such a Signed-off-by line at the end of
+the commit log message for you.
+
+The ideal patch contains a ChangeLog entry for the commit message and
+a test case for the bug fixed or feature added.
+
+The commit message is expected to start with a one line summary of
+what the patch does, prefixed with the main subdir the patch applies
+to. e.g libelf: Rewind the elf_frob function bar definitions.
+
+Finally please include an ChangeLog entry explicitly listing the files
+and what changed in each of them in the commit message. This will help
+a reviewer understand which changes are expected (and which might be
+accidential). Try to follow the GNU Change Log style:
+https://www.gnu.org/prep/standards/html_node/Style-of-Change-Logs.html
+Note that elfutils previously maintained separate ChangeLog
+files. These are no longer used. All changes should be documented in
+the git commit message.
+
+The testsuite (make check) is expected to have zero failing tests.
+Do not knowingly add tests that FAIL. If there are architectures or
+configurations where a tests is not supported make sure they are
+skipped instead of failing. Adding "exit 77" in the test shell wrapper
+indicates that a test was SKIPPED.
+
+We do allow binaries in the testsuite for tests that only need to
+read ELF or DWARF data and if generating the data in the testcase
+itself is difficult or would be architecture specific.
+The binaries should be bzip2 compressed. Add a note in the test
+wrapper run-<testcase>.sh script how to regenerate the binary.
+
+After sending your patch to the mailinglist one of the committers
+to the project will review it, give feedback, and if perfect they
+will commit it for you.
+
+All patches sent to the mailing list are tracked at
+https://patchwork.sourceware.org/project/elfutils/list/
+
+To use this from the command line you can use git-pw
+https://patchwork.readthedocs.io/projects/git-pw/en/latest/
+
+For using it with git-pw use these .git/config settings:
+  [pw]
+    server = https://patchwork.sourceware.org/api/1.2/
+    project = elfutils
+    token = <hex-token>
+    states = committed,accepted,superseded,deferred,rejected,under-review
+
+If you would like to help maintain the pending patch list your
+patchwork account can be added as maintainer for the elfutils project.
+
+You can become a maintainer/committer yourself after you have provided
+at least a handful of accepted patches and agree to the guidelines in
+this document for creating, reviewing, accepting and committing patches.
+
+To become a committer you need a sourceware account:
+https://sourceware.org/cgi-bin/pdw/ps_form.cgi
+Upload a SSH public key and have an existing maintainer sponsor you
+for the elfutils group.
+
+committers can push patches through:
+ssh://<user>@sourceware.org/git/elfutils.git
+
+The current webpages published at https://sourceware.org/elfutils/
+can be checked out with:
+git clone ssh://<user>@sourceware.org/git/elfutils-htdocs.git
+Patches should also be posted to the mailinglist.
+
+As a maintainer/committer you should still post patches as described
+above. And ideally they are reviewed and approved as above. If no
+other committer has reviewed or objected to your patch for a week
+you may use your own judgement whether you ping your patch or push
+it after "self-review". If you do, you should post a message to the
+mailinglist that the patch has been pushed.
+
+committers may also create git branches starting with <nickname>/...
+patches on these branches are works in progress, so might not be perfect
+yet, but should follow the above guidelines as much as possible and should
+be aimed at integration into main. For merging a branch into main
+the same process as above should be followed by posting the patches
+to the list first.
+
+Note that a branch starting with <nickname>/try... will be picked up
+by the Sourceware buildbot and can be used to test your patches before
+merging into the main branch:
+https://builder.sourceware.org/buildbot/#/builders?tags=elfutils-try
+
+committers/maintainers who repeatedly ignore the above guidelines,
+are hostile or offensive towards other committers or contributors,
+and don't correct their behavior after being asked by other committers
+will be removed as maintainer/committer.
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..94a9ed0
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,674 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The GNU General Public License is a free, copyleft license for
+software and other kinds of works.
+
+  The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works.  By contrast,
+the GNU General Public License is intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains free
+software for all its users.  We, the Free Software Foundation, use the
+GNU General Public License for most of our software; it applies also to
+any other work released this way by its authors.  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+  To protect your rights, we need to prevent others from denying you
+these rights or asking you to surrender the rights.  Therefore, you have
+certain responsibilities if you distribute copies of the software, or if
+you modify it: responsibilities to respect the freedom of others.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must pass on to the recipients the same
+freedoms that you received.  You must make sure that they, too, receive
+or can get the source code.  And you must show them these terms so they
+know their rights.
+
+  Developers that use the GNU GPL protect your rights with two steps:
+(1) assert copyright on the software, and (2) offer you this License
+giving you legal permission to copy, distribute and/or modify it.
+
+  For the developers' and authors' protection, the GPL clearly explains
+that there is no warranty for this free software.  For both users' and
+authors' sake, the GPL requires that modified versions be marked as
+changed, so that their problems will not be attributed erroneously to
+authors of previous versions.
+
+  Some devices are designed to deny users access to install or run
+modified versions of the software inside them, although the manufacturer
+can do so.  This is fundamentally incompatible with the aim of
+protecting users' freedom to change the software.  The systematic
+pattern of such abuse occurs in the area of products for individuals to
+use, which is precisely where it is most unacceptable.  Therefore, we
+have designed this version of the GPL to prohibit the practice for those
+products.  If such problems arise substantially in other domains, we
+stand ready to extend this provision to those domains in future versions
+of the GPL, as needed to protect the freedom of users.
+
+  Finally, every program is threatened constantly by software patents.
+States should not allow patents to restrict development and use of
+software on general-purpose computers, but in those that do, we wish to
+avoid the special danger that patents applied to a free program could
+make it effectively proprietary.  To prevent this, the GPL assures that
+patents cannot be used to render the program non-free.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                       TERMS AND CONDITIONS
+
+  0. Definitions.
+
+  "This License" refers to version 3 of the GNU General Public License.
+
+  "Copyright" also means copyright-like laws that apply to other kinds of
+works, such as semiconductor masks.
+
+  "The Program" refers to any copyrightable work licensed under this
+License.  Each licensee is addressed as "you".  "Licensees" and
+"recipients" may be individuals or organizations.
+
+  To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of an
+exact copy.  The resulting work is called a "modified version" of the
+earlier work or a work "based on" the earlier work.
+
+  A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+  To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy.  Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+  To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies.  Mere interaction with a user through
+a computer network, with no transfer of a copy, is not conveying.
+
+  An interactive user interface displays "Appropriate Legal Notices"
+to the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License.  If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+  1. Source Code.
+
+  The "source code" for a work means the preferred form of the work
+for making modifications to it.  "Object code" means any non-source
+form of a work.
+
+  A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+  The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form.  A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+  The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities.  However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work.  For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+  The Corresponding Source need not include anything that users
+can regenerate automatically from other parts of the Corresponding
+Source.
+
+  The Corresponding Source for a work in source code form is that
+same work.
+
+  2. Basic Permissions.
+
+  All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met.  This License explicitly affirms your unlimited
+permission to run the unmodified Program.  The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work.  This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+  You may make, run and propagate covered works that you do not
+convey, without conditions so long as your license otherwise remains
+in force.  You may convey covered works to others for the sole purpose
+of having them make modifications exclusively for you, or provide you
+with facilities for running those works, provided that you comply with
+the terms of this License in conveying all material for which you do
+not control copyright.  Those thus making or running the covered works
+for you must do so exclusively on your behalf, under your direction
+and control, on terms that prohibit them from making any copies of
+your copyrighted material outside their relationship with you.
+
+  Conveying under any other circumstances is permitted solely under
+the conditions stated below.  Sublicensing is not allowed; section 10
+makes it unnecessary.
+
+  3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+  No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+  When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such circumvention
+is effected by exercising rights under this License with respect to
+the covered work, and you disclaim any intention to limit operation or
+modification of the work as a means of enforcing, against the work's
+users, your or third parties' legal rights to forbid circumvention of
+technological measures.
+
+  4. Conveying Verbatim Copies.
+
+  You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+  You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+  5. Conveying Modified Source Versions.
+
+  You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these conditions:
+
+    a) The work must carry prominent notices stating that you modified
+    it, and giving a relevant date.
+
+    b) The work must carry prominent notices stating that it is
+    released under this License and any conditions added under section
+    7.  This requirement modifies the requirement in section 4 to
+    "keep intact all notices".
+
+    c) You must license the entire work, as a whole, under this
+    License to anyone who comes into possession of a copy.  This
+    License will therefore apply, along with any applicable section 7
+    additional terms, to the whole of the work, and all its parts,
+    regardless of how they are packaged.  This License gives no
+    permission to license the work in any other way, but it does not
+    invalidate such permission if you have separately received it.
+
+    d) If the work has interactive user interfaces, each must display
+    Appropriate Legal Notices; however, if the Program has interactive
+    interfaces that do not display Appropriate Legal Notices, your
+    work need not make them do so.
+
+  A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit.  Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+  6. Conveying Non-Source Forms.
+
+  You may convey a covered work in object code form under the terms
+of sections 4 and 5, provided that you also convey the
+machine-readable Corresponding Source under the terms of this License,
+in one of these ways:
+
+    a) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by the
+    Corresponding Source fixed on a durable physical medium
+    customarily used for software interchange.
+
+    b) Convey the object code in, or embodied in, a physical product
+    (including a physical distribution medium), accompanied by a
+    written offer, valid for at least three years and valid for as
+    long as you offer spare parts or customer support for that product
+    model, to give anyone who possesses the object code either (1) a
+    copy of the Corresponding Source for all the software in the
+    product that is covered by this License, on a durable physical
+    medium customarily used for software interchange, for a price no
+    more than your reasonable cost of physically performing this
+    conveying of source, or (2) access to copy the
+    Corresponding Source from a network server at no charge.
+
+    c) Convey individual copies of the object code with a copy of the
+    written offer to provide the Corresponding Source.  This
+    alternative is allowed only occasionally and noncommercially, and
+    only if you received the object code with such an offer, in accord
+    with subsection 6b.
+
+    d) Convey the object code by offering access from a designated
+    place (gratis or for a charge), and offer equivalent access to the
+    Corresponding Source in the same way through the same place at no
+    further charge.  You need not require recipients to copy the
+    Corresponding Source along with the object code.  If the place to
+    copy the object code is a network server, the Corresponding Source
+    may be on a different server (operated by you or a third party)
+    that supports equivalent copying facilities, provided you maintain
+    clear directions next to the object code saying where to find the
+    Corresponding Source.  Regardless of what server hosts the
+    Corresponding Source, you remain obligated to ensure that it is
+    available for as long as needed to satisfy these requirements.
+
+    e) Convey the object code using peer-to-peer transmission, provided
+    you inform other peers where the object code and Corresponding
+    Source of the work are being offered to the general public at no
+    charge under subsection 6d.
+
+  A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+  A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal, family,
+or household purposes, or (2) anything designed or sold for incorporation
+into a dwelling.  In determining whether a product is a consumer product,
+doubtful cases shall be resolved in favor of coverage.  For a particular
+product received by a particular user, "normally used" refers to a
+typical or common use of that class of product, regardless of the status
+of the particular user or of the way in which the particular user
+actually uses, or expects or is expected to use, the product.  A product
+is a consumer product regardless of whether the product has substantial
+commercial, industrial or non-consumer uses, unless such uses represent
+the only significant mode of use of the product.
+
+  "Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to install
+and execute modified versions of a covered work in that User Product from
+a modified version of its Corresponding Source.  The information must
+suffice to ensure that the continued functioning of the modified object
+code is in no case prevented or interfered with solely because
+modification has been made.
+
+  If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information.  But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+  The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or updates
+for a work that has been modified or installed by the recipient, or for
+the User Product in which it has been modified or installed.  Access to a
+network may be denied when the modification itself materially and
+adversely affects the operation of the network or violates the rules and
+protocols for communication across the network.
+
+  Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+  7. Additional Terms.
+
+  "Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law.  If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+  When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it.  (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.)  You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+  Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders of
+that material) supplement the terms of this License with terms:
+
+    a) Disclaiming warranty or limiting liability differently from the
+    terms of sections 15 and 16 of this License; or
+
+    b) Requiring preservation of specified reasonable legal notices or
+    author attributions in that material or in the Appropriate Legal
+    Notices displayed by works containing it; or
+
+    c) Prohibiting misrepresentation of the origin of that material, or
+    requiring that modified versions of such material be marked in
+    reasonable ways as different from the original version; or
+
+    d) Limiting the use for publicity purposes of names of licensors or
+    authors of the material; or
+
+    e) Declining to grant rights under trademark law for use of some
+    trade names, trademarks, or service marks; or
+
+    f) Requiring indemnification of licensors and authors of that
+    material by anyone who conveys the material (or modified versions of
+    it) with contractual assumptions of liability to the recipient, for
+    any liability that these contractual assumptions directly impose on
+    those licensors and authors.
+
+  All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10.  If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term.  If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+  If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+  Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions;
+the above requirements apply either way.
+
+  8. Termination.
+
+  You may not propagate or modify a covered work except as expressly
+provided under this License.  Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+  However, if you cease all violation of this License, then your
+license from a particular copyright holder is reinstated (a)
+provisionally, unless and until the copyright holder explicitly and
+finally terminates your license, and (b) permanently, if the copyright
+holder fails to notify you of the violation by some reasonable means
+prior to 60 days after the cessation.
+
+  Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+  Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License.  If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+  9. Acceptance Not Required for Having Copies.
+
+  You are not required to accept this License in order to receive or
+run a copy of the Program.  Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance.  However,
+nothing other than this License grants you permission to propagate or
+modify any covered work.  These actions infringe copyright if you do
+not accept this License.  Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+  10. Automatic Licensing of Downstream Recipients.
+
+  Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License.  You are not responsible
+for enforcing compliance by third parties with this License.
+
+  An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations.  If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+  You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License.  For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+  11. Patents.
+
+  A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based.  The
+work thus licensed is called the contributor's "contributor version".
+
+  A contributor's "essential patent claims" are all patent claims
+owned or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version.  For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+  Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+  In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement).  To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+  If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients.  "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+  If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+  A patent license is "discriminatory" if it does not include within
+the scope of its coverage, prohibits the exercise of, or is
+conditioned on the non-exercise of one or more of the rights that are
+specifically granted under this License.  You may not convey a covered
+work if you are a party to an arrangement with a third party that is
+in the business of distributing software, under which you make payment
+to the third party based on the extent of your activity of conveying
+the work, and under which the third party grants, to any of the
+parties who would receive the covered work from you, a discriminatory
+patent license (a) in connection with copies of the covered work
+conveyed by you (or copies made from those copies), or (b) primarily
+for and in connection with specific products or compilations that
+contain the covered work, unless you entered into that arrangement,
+or that patent license was granted, prior to 28 March 2007.
+
+  Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+  12. No Surrender of Others' Freedom.
+
+  If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you may
+not convey it at all.  For example, if you agree to terms that obligate you
+to collect a royalty for further conveying from those to whom you convey
+the Program, the only way you could satisfy both those terms and this
+License would be to refrain entirely from conveying the Program.
+
+  13. Use with the GNU Affero General Public License.
+
+  Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU Affero General Public License into a single
+combined work, and to convey the resulting work.  The terms of this
+License will continue to apply to the part which is the covered work,
+but the special requirements of the GNU Affero General Public License,
+section 13, concerning interaction through a network will apply to the
+combination as such.
+
+  14. Revised Versions of this License.
+
+  The Free Software Foundation may publish revised and/or new versions of
+the GNU General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+  Each version is given a distinguishing version number.  If the
+Program specifies that a certain numbered version of the GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation.  If the Program does not specify a version number of the
+GNU General Public License, you may choose any version ever published
+by the Free Software Foundation.
+
+  If the Program specifies that a proxy can decide which future
+versions of the GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+  Later license versions may give you additional or different
+permissions.  However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+  15. Disclaimer of Warranty.
+
+  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
+OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
+THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
+IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
+ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+  16. Limitation of Liability.
+
+  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
+THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
+GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
+USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
+DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
+PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
+EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGES.
+
+  17. Interpretation of Sections 15 and 16.
+
+  If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+state the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+Also add information on how to contact you by electronic and paper mail.
+
+  If the program does terminal interaction, make it output a short
+notice like this when it starts in an interactive mode:
+
+    <program>  Copyright (C) <year>  <name of author>
+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, your program's commands
+might be different; for a GUI interface, you would use an "about box".
+
+  You should also get your employer (if you work as a programmer) or school,
+if any, to sign a "copyright disclaimer" for the program, if necessary.
+For more information on this, and how to apply and follow the GNU GPL, see
+<http://www.gnu.org/licenses/>.
+
+  The GNU General Public License does not permit incorporating your program
+into proprietary programs.  If your program is a subroutine library, you
+may consider it more useful to permit linking proprietary applications with
+the library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.  But first, please read
+<http://www.gnu.org/philosophy/why-not-lgpl.html>.
diff --git a/COPYING-GPLV2 b/COPYING-GPLV2
new file mode 100644
index 0000000..d159169
--- /dev/null
+++ b/COPYING-GPLV2
@@ -0,0 +1,339 @@
+                    GNU GENERAL PUBLIC LICENSE
+                       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+                            Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+                    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+                            NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+                     END OF TERMS AND CONDITIONS
+
+            How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    <one line to give the program's name and a brief idea of what it does.>
+    Copyright (C) <year>  <name of author>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  <signature of Ty Coon>, 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/COPYING-LGPLV3 b/COPYING-LGPLV3
new file mode 100644
index 0000000..65c5ca8
--- /dev/null
+++ b/COPYING-LGPLV3
@@ -0,0 +1,165 @@
+                   GNU LESSER GENERAL PUBLIC LICENSE
+                       Version 3, 29 June 2007
+
+ Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+
+  This version of the GNU Lesser General Public License incorporates
+the terms and conditions of version 3 of the GNU General Public
+License, supplemented by the additional permissions listed below.
+
+  0. Additional Definitions.
+
+  As used herein, "this License" refers to version 3 of the GNU Lesser
+General Public License, and the "GNU GPL" refers to version 3 of the GNU
+General Public License.
+
+  "The Library" refers to a covered work governed by this License,
+other than an Application or a Combined Work as defined below.
+
+  An "Application" is any work that makes use of an interface provided
+by the Library, but which is not otherwise based on the Library.
+Defining a subclass of a class defined by the Library is deemed a mode
+of using an interface provided by the Library.
+
+  A "Combined Work" is a work produced by combining or linking an
+Application with the Library.  The particular version of the Library
+with which the Combined Work was made is also called the "Linked
+Version".
+
+  The "Minimal Corresponding Source" for a Combined Work means the
+Corresponding Source for the Combined Work, excluding any source code
+for portions of the Combined Work that, considered in isolation, are
+based on the Application, and not on the Linked Version.
+
+  The "Corresponding Application Code" for a Combined Work means the
+object code and/or source code for the Application, including any data
+and utility programs needed for reproducing the Combined Work from the
+Application, but excluding the System Libraries of the Combined Work.
+
+  1. Exception to Section 3 of the GNU GPL.
+
+  You may convey a covered work under sections 3 and 4 of this License
+without being bound by section 3 of the GNU GPL.
+
+  2. Conveying Modified Versions.
+
+  If you modify a copy of the Library, and, in your modifications, a
+facility refers to a function or data to be supplied by an Application
+that uses the facility (other than as an argument passed when the
+facility is invoked), then you may convey a copy of the modified
+version:
+
+   a) under this License, provided that you make a good faith effort to
+   ensure that, in the event an Application does not supply the
+   function or data, the facility still operates, and performs
+   whatever part of its purpose remains meaningful, or
+
+   b) under the GNU GPL, with none of the additional permissions of
+   this License applicable to that copy.
+
+  3. Object Code Incorporating Material from Library Header Files.
+
+  The object code form of an Application may incorporate material from
+a header file that is part of the Library.  You may convey such object
+code under terms of your choice, provided that, if the incorporated
+material is not limited to numerical parameters, data structure
+layouts and accessors, or small macros, inline functions and templates
+(ten or fewer lines in length), you do both of the following:
+
+   a) Give prominent notice with each copy of the object code that the
+   Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the object code with a copy of the GNU GPL and this license
+   document.
+
+  4. Combined Works.
+
+  You may convey a Combined Work under terms of your choice that,
+taken together, effectively do not restrict modification of the
+portions of the Library contained in the Combined Work and reverse
+engineering for debugging such modifications, if you also do each of
+the following:
+
+   a) Give prominent notice with each copy of the Combined Work that
+   the Library is used in it and that the Library and its use are
+   covered by this License.
+
+   b) Accompany the Combined Work with a copy of the GNU GPL and this license
+   document.
+
+   c) For a Combined Work that displays copyright notices during
+   execution, include the copyright notice for the Library among
+   these notices, as well as a reference directing the user to the
+   copies of the GNU GPL and this license document.
+
+   d) Do one of the following:
+
+       0) Convey the Minimal Corresponding Source under the terms of this
+       License, and the Corresponding Application Code in a form
+       suitable for, and under terms that permit, the user to
+       recombine or relink the Application with a modified version of
+       the Linked Version to produce a modified Combined Work, in the
+       manner specified by section 6 of the GNU GPL for conveying
+       Corresponding Source.
+
+       1) Use a suitable shared library mechanism for linking with the
+       Library.  A suitable mechanism is one that (a) uses at run time
+       a copy of the Library already present on the user's computer
+       system, and (b) will operate properly with a modified version
+       of the Library that is interface-compatible with the Linked
+       Version.
+
+   e) Provide Installation Information, but only if you would otherwise
+   be required to provide such information under section 6 of the
+   GNU GPL, and only to the extent that such information is
+   necessary to install and execute a modified version of the
+   Combined Work produced by recombining or relinking the
+   Application with a modified version of the Linked Version. (If
+   you use option 4d0, the Installation Information must accompany
+   the Minimal Corresponding Source and Corresponding Application
+   Code. If you use option 4d1, you must provide the Installation
+   Information in the manner specified by section 6 of the GNU GPL
+   for conveying Corresponding Source.)
+
+  5. Combined Libraries.
+
+  You may place library facilities that are a work based on the
+Library side by side in a single library together with other library
+facilities that are not Applications and are not covered by this
+License, and convey such a combined library under terms of your
+choice, if you do both of the following:
+
+   a) Accompany the combined library with a copy of the same work based
+   on the Library, uncombined with any other library facilities,
+   conveyed under the terms of this License.
+
+   b) Give prominent notice with the combined library that part of it
+   is a work based on the Library, and explaining where to find the
+   accompanying uncombined form of the same work.
+
+  6. Revised Versions of the GNU Lesser General Public License.
+
+  The Free Software Foundation may publish revised and/or new versions
+of the GNU Lesser General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+  Each version is given a distinguishing version number. If the
+Library as you received it specifies that a certain numbered version
+of the GNU Lesser General Public License "or any later version"
+applies to it, you have the option of following the terms and
+conditions either of that published version or of any later version
+published by the Free Software Foundation. If the Library as you
+received it does not specify a version number of the GNU Lesser
+General Public License, you may choose any version of the GNU Lesser
+General Public License ever published by the Free Software Foundation.
+
+  If the Library as you received it specifies that a proxy can decide
+whether future versions of the GNU Lesser General Public License shall
+apply, that proxy's public statement of acceptance of any version is
+permanent authorization for you to choose that version for the
+Library.
diff --git a/ChangeLog b/ChangeLog
new file mode 100644
index 0000000..6aed95b
--- /dev/null
+++ b/ChangeLog
@@ -0,0 +1,1097 @@
+2023-03-27  Di Chen  <dichen@redhat.com>
+
+	* NEWS: Support readelf -Ds for using dynamic segment to
+	print symbol table.
+
+2023-03-03  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Add ELFCOMPRESS_ZSTD support for libelf and elfcompress.
+
+2023-02-23  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Add old version code names.
+
+2023-02-21  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Check for -Wuse-after-free=3
+
+2023-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Error out when demangler is enabled, but
+	__cxa_demangle cannot be found.
+
+2023-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* configure.ac: Add some rlimit/affinity checks.
+
+2022-11-02  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_INIT): Set version to 0.188.
+	* NEWS: Likewise.
+
+2022-10-31  Aaron Merey  <amerey@redhat.com>
+
+	* NEWS: Add debuginfod_find_section.
+
+2022-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (rpm): Remove --sign.
+
+2022-10-22  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Use AC_PROG_CC with autoconf 2.70, or AC_PROG_CC_C99
+	for earlier versions. Use AC_PROG_LEX([noyywrap]).
+
+2022-09-13  Aleksei Vetrov  <vvvvvv@google.com>
+
+	* NEWS (libdwfl): Add dwfl_report_offline_memory.
+
+2022-09-27  Taketo Kabe  <kabe@sra-tohoku.co.jp>
+
+	* debuginfod/debuginfod-client.c: Correctly get timestamp when
+	compiling with -D_TIME_BITS=64 on 32bit environment.
+
+2022-04-28  Di Chen  <dichen@redhat.com>
+
+	* NEWS: Add readefl -D, --use-dynamic.
+
+2022-07-28  Di Chen  <dichen@redhat.com>
+
+	* NEWS: Add dwfl_frame_reg.
+
+2022-07-13  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Add dwfl_get_debuginfod_client.
+
+2022-06-02  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (OLD_LIBMICROHTTPD): New AM_CONDITIONAL based on
+	libmicrohttpd < 0.9.51.
+
+2022-05-02  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (AM_DISTCHECK_CONFIGURE_FLAGS): Remove
+	--enable-valgrind --enable-sanitize-undefined.
+
+2022-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_INIT): Set version to 0.187.
+	* NEWS: Add some more 0.187 items.
+
+2022-04-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* AUTHORS.sh, .mailmap: New files.
+	* AUTHORS: Regenerated to cover entire history of elfutils.
+
+2022-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_CHECK_FUNCS): Add mremap.
+
+2021-03-20  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Remove -m64 on 32bit target comments for
+	utrace_BIARCH check.
+
+2021-03-14  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Use AS_HELP_STRING instead of AC_HELP_STRING.
+
+2021-03-11  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Document new --relative option for addr2line.
+
+2022-03-10  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Move AC_PROG_CXX earlier. Check for both
+	-D_FORTIFY_SOURCE=3 and -D_FORTIFY_SOURCE=2 support. Also
+	set CXXFLAGS. Output final CFLAGS and CXXFLAGS setting.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Add --enable-sanitize-address.
+
+2021-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_INIT): Set version to 0.186.
+	* NEWS: Add translation item.
+
+2021-09-03  John Mellor-Crummey <johnmc@rice.edu>
+
+	* NEWS: Read inlining info in NVIDIA extended line map
+
+2021-08-10  Adrian Ratiu  <adrian.ratiu@collabora.com>
+
+	* configure.ac (AC_CACHE_CHECK): Rework std=gnu99 check to allow clang.
+
+2021-08-20  Saleem Abdulrasool  <abdulras@google.com>
+
+	* Add AC_CHECK_HEADERS for error.h and err.h.
+
+2021-07-28  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_CHECK_DECLS): Add reallocarray check.
+
+2021-05-22  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_INIT): Set version to 0.185.
+	* NEWS: Add 0.185 entries.
+
+2021-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_INIT): Set version to 0.184.
+	* NEWS: Add libdw, translation and debuginfod-client entries.
+
+2021-03-30  Frank Ch. Eigler  <fche@redhat.com>
+
+	* configure.ac: Look for pthread_setname_np.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* configure.ac: Add -Wno-packed-not-aligned check.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* configure.ac: Add -Wtrampolines check.
+
+2021-02-05  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (AC_INIT): Set version to 0.183.
+	(AC_COPYRIGHT): Update Copyright year.
+	* NEWS: Add 0.183 section.
+
+2021-02-01  Érico Nogueira  <ericonr@disroot.org>
+
+	* configure.ac: Check for GNU strerror_r.
+
+2021-01-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac [--enable-gcov]: Check for gcov, lcov, and genhtml.
+	* Makefile.am [GCOV] (coverage, coverage-clean): New targets.
+	* .gitignore: Update.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: Move subdirectory patterns to separate .gitignore files.
+
+	* .gitignore: Update.
+
+2020-12-15  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac (USE_NLS, AM_PO_SUBDIRS): Remove.
+	(AM_GNU_GETTEXT, AM_GNU_GETTEXT_VERSION,
+	AM_GNU_GETTEXT_REQUIRE_VERSION): Use these macros to setup the gettext
+	infrastructure.
+	* .gitignore: Update.
+
+	* Makefile.am (SUBDIRS): Remove m4.
+	* configure.ac (AC_CONFIG_FILES): Remove m4/Makefile.
+
+	* configure.ac (AC_CONFIG_MACRO_DIR): Remove.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac: Fix spelling typos in comments.
+	* NEWS: Fix spelling typos.
+	* NOTES: Likewise.
+	* TODO: Likewise.
+
+2020-12-11  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac (AM_CONDITIONAL): Remove HAVE_LIBASM and STANDALONE.
+
+	* configure.ac: Rewrite argp check.
+
+	* configure.ac (AC_MSG_FAILURE): Fix typo.
+
+2020-11-30  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac (LIBDEBUGINFOD_SONAME): New AC_SUBST variable.
+	(AC_CONFIG_FILES): Add debuginfod/debuginfod.h.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* configure.ac: Check for fts and obstack from outside libc.
+
+2020-10-28  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.182.
+	* NEWS: Add 0.182 section.
+
+2020-10-28  Tom Tromey  <tom@tromey.com>
+
+	* .gitignore: Add /tests/leb128.
+
+2020-10-01  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR25461
+	* configure.ac: Add --enable-debuginfod-urls[=URLS] option.
+
+2020-09-18  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Check availability of libzstd and zstd.
+
+2020-09-08  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.181.
+	* NEWS: Add 0.181 section.
+
+2020-08-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac (--enable-libdebuginfod): AC_DEFINE ENABLE_LIBDEBUGINFOD.
+
+2020-07-17  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set -DBAD_FTS=1 also for CXXFLAGS.
+
+2020-06-19  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (SUBDIRS): Always add debuginfod.
+	* configure.ac (debuginfod): Split off...
+	(libdebuginfod): ... this. Also add DUMME_DEBUGINFOD.
+
+2020-06-15  Sergei Trofimovich <slyfox@gentoo.org>
+
+	* configure.ac: Use READELF in build-id check.
+
+2020-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.180.
+	* NEWS: Add 0.180 section.
+	* .gitignore: Update with new generated file.
+
+2020-06-10  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (MODVERSION): Remove.
+
+2020-03-30  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.179.
+	* NEWS: Add 0.179 section.
+
+2020-03-25  Mark Wielaard  <mark@klomp.org>
+
+	* README: Update mailinglist subscription info.
+	* CONTRIBUTING: Likewise.
+
+2020-02-03  Frank Ch. Eigler  <fche@redhat.com>
+
+	* configure.ac: Tolerate CXX= for debuginfod configuration.
+
+2019-12-11  Omar Sandoval  <osandov@fb.com>
+
+	* configure.ac: Apply -Werror after user-defined CFLAGS in
+	-D_FORTIFY_SOURCE=2 check.
+
+2019-12-06  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Add ac_cv_buildid check.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.178.
+	NEWS: Add 0.178 section.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Add CXXFLAGS for gcov.
+
+2019-10-28  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod/: New directory for debuginfod code.
+	* Makefile.am (SUBDIRS): Recurse there.
+	* configure.ac (--enable-debuginfod): New flag & checks.
+
+2019-08-25  Jonathon Anderson <jma14@rice.edu>
+
+	* configure.ac: Add new --enable-valgrind-annotations
+	* configure.ac: Add new --with-valgrind (headers only)
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* configure.ac: Get rid of --enable-libebl-subdir.
+	* Makefile.am (SUBDIRS): Reorder backends and libcpu before libebl to
+	satisfy build dependencies.
+
+2019-08-13  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.177.
+	* NEWS: Mention elfclassify, readelf DW_AT_data_member_location
+	and DW_AT_discr_list attribute changes, dwarf.h DW_AT_GNU additions,
+	dwelf_elf_e_machine_string function, dwelf_elf_begin change and
+	C-SKY backend support.
+
+2019-02-14  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.176.
+	* NEWS: Mention riscv backend updates, new --enable-install-elfh
+	configure flag and fixed CVEs.
+	* GPG-KEY: Update.
+
+2019-01-18  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Add new --enable-install-elfh.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* configure.ac: Check for gawk.
+
+2018-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.172.
+	* NEWS: Mention bug fixes.
+
+2018-06-01  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.171.
+	* NEWS: Mention DWARF5, split-dwarf and GNU DebugFission support.
+
+2018-03-17  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac (CHECK_FUNCS): Check for process_vm_readv.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* configure.ac (HAVE_FALLTHROUGH): New define.
+
+2017-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* .gitignore: Remove tests/md5-sha1-test.
+
+2017-08-18  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* configure.ac: Check if the compiler supports
+	__attribute__((gcc_struct)).
+
+2017-09-19  Mark Wielaard  <mark@klomp.org>
+
+	* README: Add basic build instructions.
+
+2017-05-03  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* configure.ac: Test if symbol versioning is supported.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* configure.ac: Check if the compiler supports
+	__attribute__((visibility(...))).
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* configure.ac: Check if -fPIC, -fPIE, -Wl,-z,defs,
+	and -Wl,-z,relro are supported by the compiler.
+
+2017-08-02  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.170.
+	* NEWS: Mention new libdw dwarf_line_file function.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Mention dwarf_getmacros handling version 5 .debug_macro.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Mention dwarf_peel_type DWARF5 tags improvement.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Mention new DWARF5 calling conventions and defaulted member
+	function.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Mention new dwarf_default_lower_bound function.
+
+2017-07-25  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Mention new DWARF5 attributes, tags, character encodings
+	and language codes in dwarf.h.
+
+2017-07-18  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Don't check for linux/bpf.h.
+	* NEWS: Mention always build bpf backend.
+
+2017-07-14  Mark Wielaard  <mark@klomp.org>
+
+	* NEWS: Add 0.170 section and new strip options.
+
+2017-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.169. Update copyright year.
+	* NEWS: Add 0.169 section.
+
+2017-04-21  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* .gitignore: Add fillfile and peel_type tests.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* configure.ac: Add check for mempcpy.
+
+2017-02-09  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Add check for adding -D_FORTIFY_SOURCE=2 to CFLAGS.
+
+2017-01-12  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Define PACKAGE_URL for older autoconf.
+
+2016-12-27  Mark Wielaard  <mark@klomp.org>
+
+	* configure.ac: Set version to 0.168.
+	* NEWS: Add 0.168 updates.
+
+2016-12-24  Mark Wielaard  <mark@klomp.org>
+
+	* README: Move design notes to NOTES. Add URLs for home, releases,
+	bugs, git and mailinglist now on sourceware.
+	* NOTES: Add notes from README.
+	* CONTRIBUTING: Change fedorahosted.org references to new
+	sourceware.org locations.
+	* configure.ac (AC_INIT): Add package URL http://elfutils.org/
+	change bug-report to https://sourceware.org/bugzilla/
+	(AC_COPYRIGHT): Set to the elfutils developers.
+
+2016-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add test for bad fts.h. Add -DBAD_FTS=1 to CFLAGS
+	if necessary.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add check for whether gcc accepts
+	-Wimplict-fallthrough.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* configure.ac: Add memrchr, rawmemchr and powerof2 checks.
+
+2016-08-04  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.167.
+	* NEWS: Add 0.167 section.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* .gitignore: Remove src/ld. ldlex.c, ldscript.c and ldscript.h.
+	* configure.ac (enable generic): Removed.
+
+2016-06-28  Richard Henderson <rth@redhat.com>
+
+	* configure.ac (HAVE_LINUX_BPF_H): New test and conditional.
+
+2016-06-10  Mark Wielaard  <mjw@redhat.com>
+
+	* CONTRIBUTING: Extend patch, committer and maintainer guidelines.
+
+2016-05-02  Filipe Brandenburger  <filbranden@google.com>
+
+	* configure.ac (argp check): Pass pass &argv.
+	* configure.ac (-W<...> checks): Pass -Werror to the warning checks,
+	to ensure unsupported warning options are noticed during ./configure
+	time and not only later during build.
+
+2016-03-31  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.166.
+
+2016-03-02  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set program_prefix to eu- by default.
+	* NEWS (0.166): New sections, document --program-prefix default.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add check for whether gcc accepts -Wnull-dereference.
+
+2016-02-08  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add checks for sane -Wlogical-op and whether gcc
+	accepts -Wduplicated-cond.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.165.
+	* NEWS: Add 0.164 section.
+
+2016-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add BZ2_LIBS and LIBLZMA substitutions.
+	Add config/libelf.pc and config/libdw.pc config files.
+
+2015-12-31  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (AM_MAKEFLAGS): Set --no-print-directory.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Make zlib mandatory.
+
+2015-10-15  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.164.
+	* NEWS: Add 0.164 additions.
+
+2015-10-07  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add AM_SILENT_RULES([yes]).
+
+2015-09-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* configure.ac: Use -fPIC instead of -fpic to avoid relocation
+	overflows in some platforms.
+
+2015-07-11  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* .gitignore: Add more generated files, and anchor some of the
+	existing ones.
+
+2015-06-19  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.163.
+	* NEWS: Mention 0.163 is bug fixes only.
+
+2015-06-10  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.162.
+	* NEWS: Add 0.162 additions.
+
+2015-06-08  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (ADD_STACK_USAGE_WARNING): New conditional based on
+	gcc -Wstack-usage check.
+
+2015-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (MODVERSION): Define using LIBEBL_SUBDIR, eu_version
+	and ac_cv_build.
+
+2015-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (use_undefined): Use AC_LINK_IFELSE. AC_DEFINE
+	CHECK_UNDEFINED.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Check for bunzip2. Check flex and bison are
+	installed in maintainer-mode. Otherwise check libdw/known-dwarf.h
+	is already generated.
+
+2015-05-21  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add --enable-sanitize-undefined.
+	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Rename to...
+	(AM_DISTCHECK_CONFIGURE_FLAGS): this. Add --enable-sanitize-undefined.
+
+2015-05-04  Anthony G. Basile  <blueness@gentoo.org>
+
+	* configure.ac (argp_LDADD): Check if libc has argp and set
+	argp_LDADD accordingly.
+
+2015-05-03  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* configure.ac (DEMANGLE): Fix enable_demangler setting.
+
+2015-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (DEMANGLE): Explicitly set enable_demangler.
+
+2015-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (debugpred): Use and set use_debugpred_val.
+	(textrelcheck): Explicitly set enable_textrelcheck to yes or no.
+	(symbol-versioning): Likewise for enable_symbol_versioning.
+	AC_MSG_NOTICE overview of enabled/disabled features.
+
+2015-04-23  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* configure.ac: Add --disable-symbol-versioning.
+
+2015-04-14  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (ac_cv_c99): Add explicit checks for all GNU99
+	extensions used.
+
+2015-03-13  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (ac_cv_c99): Add explicit return.
+	(ac_cv_tls): Add stdlib.h include.
+
+2014-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.161.
+	* NEWS: Add dwarf.h additions.
+
+2014-12-15  Josh Stone  <jistone@redhat.com>
+
+	* .gitignore: Add config/compile as installed by automake 1.14.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add --disable-textrelcheck.
+
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: New section 0.161. Add dwarf_peel_type.
+
+2014-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.160.
+	* NEWS: Add removal of DW_TAG_mutable_type, LZMA .ko.xz kernel
+	module support, ARM THUMB functions and ppc64le ELFv2 abi backends.
+
+2014-08-15  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: Add dwarf_cu_die.
+
+2014-08-15  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: Add dwarf_cu_getdwarf.
+
+2014-07-18  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (AC_CHECK_TYPE): Test for struct user_regs_struct.
+
+2014-05-26  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: New section 0.160. Add unstrip --force.
+
+2014-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.159.
+	* NEWS: Add entries for version 0.159.
+
+2014-05-02  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: Add note about dwz support no longer being experimental and
+	new helper functions.
+	* configure.ac: Remove --enable-dwz.
+	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Remove --enable-dwz.
+
+2014-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (SUBDIRS): Add libdwelf.
+	* configure.ac (AC_CONFIG_FILES): Add libdwelf/Makefile.
+	* NEWS: Add note about libdwelf.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Remove mudflap enable arg and MUDFLAP conditional.
+
+2014-01-21  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS (Version 0.159): Add stack -i.
+
+2014-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS (Version 0.159): New. Add stack -d.
+
+2014-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.158.
+	* NEWS: Add entries for version 0.158.
+
+2013-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS (libdwfl): Add dwfl_getthread_frames.
+	(stack): New entry.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS (libdwfl): Add dwfl_module_getsym_info and
+	dwfl_module_addrinfo.
+	(addr2line): Add -x option.
+
+2013-12-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* NEWS (Version 0.158) (libdwfl): Added Dwfl_Thread_Callbacks,
+	Dwfl_Thread, Dwfl_Frame, dwfl_attach_state, dwfl_pid, dwfl_thread_dwfl,
+	dwfl_thread_tid, dwfl_frame_thread, dwfl_thread_state_registers,
+	dwfl_thread_state_register_pc, dwfl_getthreads, dwfl_thread_getframes
+	and dwfl_frame_pc.
+
+2013-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS (libdwfl): Add dwfl_module_getsymtab_first_global.
+
+2013-12-09  Josh Stone  <jistone@redhat.com>
+
+	* .gitignore: Add config/ar-lib, installed due to AM_PROG_AR.
+
+2013-12-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* configure.ac (CC_BIARCH): Remove AS_IF for it.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* configure.ac: New AC_CHECK_SIZEOF for long.  Call utrace_BIARCH, new
+	AC_SUBST for CC_BIARCH.
+
+2013-11-06  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (--enable-dwz): Add AC_MSG_WARN when disabled but
+	local system does have /usr/lib/debug/.dwz.
+
+2013-11-06  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (--enable-thread-safety): Add AC_MSG_WARN experimental
+	option.
+
+2013-11-01  Michael Forney  <mforney@mforney.org>
+
+	* configure.ac: Call AM_PROG_AR and AC_CHECK_TOOL for readelf and nm.
+
+2013-10-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* NEWS (Version 0.158): New.
+
+2013-09-30  Mark Wielaard  <mjw@redhat.com>
+
+	* NEWS: Update for readelf NT_SIGINFO and NT_FILE core notes.
+
+2013-09-27  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.157.
+	* NEWS: Add entries for version 0.157.
+
+2013-09-20  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add --enable-dwz.
+
+2013-07-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* configure.ac: Set version to 0.156.
+
+2013-07-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* NEWS: Remove bugfix only entries from Version 0.156.
+
+2013-07-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* NEWS: Add entries for Version 0.156.
+
+2013-04-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* NEWS (Version 0.156): New.
+
+2013-04-26  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac (AM_INIT_AUTOMAKE): Request parallel-tests.
+
+2013-04-25  Mark Wielaard  <mjw@redhat.com>
+
+	* .gitignore: Add config/test-driver as installed by automake 1.13.
+	* configure.ac (AM_INIT_AUTOMAKE): Require at least automake 1.11.
+
+2012-10-01  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add --enable-valgrind check.
+	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): Add --enable-valgrind.
+
+2012-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.155.
+
+2012-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Add --enable-dwz check, defaults to no.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* TODO: Add note on shdrs after elf_cntl (ELF_C_FDREAD).
+
+2012-06-22  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.154.
+
+2012-01-24  Mark Wielaard  <mjw@redhat.com>
+
+	* COPYING: Fix address. Updated version from gnulib.
+
+2012-01-23  Mark Wielaard  <mjw@redhat.com>
+
+	* configure.ac: Set version to 0.153, update copyright years.
+
+2012-01-20  Roland McGrath  <roland@hack.frob.com>
+
+	* configure.ac: Handle --enable-deterministic-archives.
+
+2011-10-08  Roland McGrath  <roland@hack.frob.com>
+
+	* configure.ac (eu_version): Use sed instead of ${x/y/z} syntax.
+	Use POSIX.2 $((...)) syntax instead of $[...].
+	Reported by Mike Frysinger <vapier@gentoo.org>.
+
+2011-10-08  Mike Frysinger  <vapier@gentoo.org>
+
+	* configure.ac: Fix use of AC_ARG_ENABLE to handle $enableval correctly.
+
+2011-10-02  Ulrich Drepper  <drepper@gmail.com>
+
+	* configure.ac: Check for __cxa_demangle in libstdc++.
+
+2011-02-08  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (C99 check): Use AC_LANG_SOURCE.
+
+	* configure.ac (ALL_LINGUAS): Remove variable, now obsolete.
+
+2010-09-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac (ALL_LINGUAS): Add languages which have some
+	translations.
+
+2010-04-15  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (LOCALEDIR, DATADIRNAME): Removed.
+
+2009-09-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Update for more modern autoconf.
+
+2009-08-26  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (zip_LIBS): Check for liblzma too.
+
+2009-04-19  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (eu_version): Round down here, not in version.h macros.
+
+2009-04-17  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (eu_version): Compute number 1000 times larger,
+	let $PACKAGE_VERSION be x.y.z as well as x.y (implied x.y.0).
+
+2009-01-23  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (zlib check): Check for gzdirect, need zlib >= 1.2.2.3.
+
+	* configure.ac (__thread check): Use AC_LINK_IFELSE, in case of
+	building with compiler support but no working runtime support.
+
+2009-01-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (rpm): The tarball is now bzip2-compressed.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Require gcc with TLS support.
+	Rename USE_TLS to USE_LOCKS.  The option is renamed to
+	--enable-thread-safety.
+
+2009-01-08  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (eu_ZIPLIB): Moved to m4/zip.am.
+
+2009-01-05  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (eu_ZIPLIB): New macro.
+	Use it to test for -lz, -lbz2, set .am ZLIB, BZLIB, zip_LIBS.
+
+2008-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: We need automake 1.8 now.
+
+2008-12-24  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac: Use automake flags dist-bzip2 no-dist-gzip,
+	distribute only in .tar.bz2 form now.
+
+2008-12-16  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (pkginclude_HEADERS): New variable, install version.h.
+	* configure.ac: Create it, substituting @eu_version@ with
+	PACKAGE_VERSION canonicalized to four digits of decimal.
+
+2008-08-25  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (--enable-tls): Set AM_CONDITIONAL USE_TLS too.
+
+2008-08-21  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (AH_BOTTOM): Emit #include <eu-config.h> and
+	move the contents to lib/eu-config.h instead of keeping them here.
+
+2007-12-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Add support for --enable-debugpred.
+	Update likely/unlikely macros for it.
+
+2007-06-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Remove traces of mini builds.
+	* configure.ac: Don't use libelf-po/POTFILES.in as config file
+	anymore.
+
+2007-05-16  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (AM_INIT_AUTOMAKE): Use -Wno-portability.
+
+2006-11-02  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add EXCEPTION file.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac: Use AM_MAINTAINER_MODE.
+
+2006-07-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac (internal_function): Don't use internal visibility.
+
+2006-07-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Add dummy automake conditional to get dependencies
+	for non-generic linker right.  See src/Makefile.am.
+
+2005-11-18  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (DISTCHECK_CONFIGURE_FLAGS): New variable.
+
+2005-11-16  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac: Define HAVE_LIBASM and STANDALONE conditionals.
+	In config.h, define ELFUTILS_HEADER macro.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (all_SUBDIRS): Add backends.
+	* configure.ac: Write backends/Makefile.
+
+	* configure.ac: Add --enable-tests-rpath option.
+
+2005-09-16  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac (ALLOW_UNALIGNED) [__ia64__ || __alpha__]:
+	Don't set it, since on IA64 you get error messages for unaligned
+	accesses, and on Alpha it's at least very slow.
+
+2005-08-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Fix GCOV make condition generation.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Add --enable-gcov option.
+
+2005-08-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Add --enable-gprof option.
+
+2005-07-27  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (all_SUBDIRS): Put libdwfl before libdw.
+
+2005-07-21  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac: Take --enable-libebl-subdir=DIR to set LIBEBL_SUBDIR.
+
+2005-06-01  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (all_SUBDIRS): Add libdwfl.
+	* configure.ac: Write libdwfl/Makefile.
+
+2005-05-19  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac [AH_BOTTOM] (INTDECL, _INTDECL): New macros.
+
+2005-05-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Define MODVERSION in config.h.
+
+2005-02-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (all_SUBDIRS): Don't add doc subdir for now.
+	* configure.ac: Don't use doc subdir for now.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Remove AM_GNU_GETTEXT use.  Use only AM_PO_SUBDIRS.
+
+2005-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac (AM_INIT_AUTOMAKE): Removed dist-bzip2.
+
+	* Makefile.am (EXTRA_DIST): Remove splint.rc.
+	* splint.rc: Removed.
+
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Make compile with gcc 4.0.
+
+2004-03-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Use AS_HELP_STRING where applicable.
+
+2004-01-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Check for C99 compiler.
+
+	* configure.ac: Change locking macros in config.h to at least
+	evaluate the parameter.  Define base_cpu to none for generic linker.
+
+2004-01-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Print error message in case --disable-generic is
+	used if no linker support for the architecture is available.
+
+2004-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Dont generate libebl-po/Makefile.in,
+	libdw-po/Makefile.in, libasm-po/Makefile.in.
+
+	* Makefile.am (all_SUBDIRS): Remove libebl-po, libdw-po, libasm-po.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Pretty printing of help message.
+
+	* configure.ac: Move AC_SYS_LARGEFILE test to the front.
+
+	* configure.ac: Add --enable-mudflap option.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Major cleanups.  Use aux dir.
+	* config.guess: Moved to new config subdir.
+	* config.rpath: Likewise.
+	* config.sub: Likewise.
+	* depcomp: Likewise.
+	* install-sh: Likewise.
+	* missing: Likewise.
+	* mkinstalldirs: Likewise.
+	* Makefile.am (mini_SUBDIRS): Add config.
+	(EXTRA_DIST): Remove config.rpath.
+
+	* configure.ac: Add AC_REVISION.
+
+	* configure.ac: Add --enable-mudflap option.
+
+2004-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* configure.ac: Drop libdwarf directory.  Add libdw-po.
+	* Makefile.am (all_SUBDIRS): Likewise.
+	* elfutils.spec: Don't distribute anything from libdwarf.
+
+2004-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support separate libelf built.
+
+	* elfutils.spec.in: Create separata elfutils-libelf-devel package.
+	Install libdw DSOs.
+
+	* configure.ac (AC_CONFIG_SRCDIR): Use libelf/libelf.h as the file
+	name.
+
+2003-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Remove references to libebl.so.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
+
+2000-08-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* The beginning.  See the NEWS file for the time being.
diff --git a/GPG-KEY b/GPG-KEY
new file mode 100644
index 0000000..dca558b
--- /dev/null
+++ b/GPG-KEY
@@ -0,0 +1,148 @@
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+
+mQINBFxDPtIBEAC8xePaWvq5cDMBYtrpdmR20YX5xrDXUeHgueSVE9Mw8yCan2Cq
+1Ac1jHYnXxp4Jj3q4tIS9Jq2oAbqxyvBMdJYqEz4z709eDnYBacZQcGqojLh3HI2
+P7lmmKxkL8rS3Q3Ug05mYT+MwgmRvIO1+kwQTcq1AeB9z9/zikgY1Jv1R86gH8G8
+4OPbJUowdE/mT3pQ+2UQnarCVPJ3WJtZNDXPRzskk0t5h+Mg5RtX+COoHfsvWHiE
+UTmHMfynw49GG/YF6jLSVzMlKMz3jdOePIArpm2BNUu8DvEn9at6daKR4Ah+ujDd
+08l9j8wFhJnenn/9+ENjm9kOGQWOmH/fEIOlMAATVdZEfHVfAWbgICPSrPyi+v3A
+CE4uEoaw85LgbAAbhzdswlLezLxS7LLTpfDZUFZfkho1MSGXaCQ475/iVAeuxi61
+B2VcmH4lOSH7HYNkMY8ggGk2/WG35eq8PZme8PvXUmLu+f2jzy9XFekIr+/Ks2Tc
+hCTYCw6bhSLPa19HapCxvWXgNcYzZ8jULqBXsAfj4NnzBTn6u5nsJ1reA8GoO9vL
+aQf3LDgr+UY/z+6N474lAVfr0eIdWzkWPvX8fcBCfiB944rPr+Q50RUfc9ngIKP4
+JsflhXTn601aL4r6qkCcBVqO/eRhb4vCAUo7csemTKzI/05ooGfQtZ3O5QARAQAB
+tB5NYXJrIFdpZWxhYXJkIDxtYXJrQGtsb21wLm9yZz6JAlEEEwEKADsCGwEFCwkI
+BwIGFQoJCAsCBBYCAwECHgECF4AWIQTsPP6I9soHiHdPXB0apEvmSd52CgUCXE37
+mQIZAQAKCRAapEvmSd52CuO9D/9Fi6LOrU+iYHjfIk+wT8jyhF1YNATnooa5W7y/
+4QlXOIyKmkXM/0faH1hZNGf4qVK4dBUewuhALMEzudkXEhzudg9KpB9SaHZNR5DZ
++YHo204zJ84P+aJa7F8FOScbNAiG4pFGC7sQxvtAz0skM0yLsdhNg2tM8lM3n9e/
+rO4EK7aR55ojzE9pCWhRSx/AKYT7545KzXuCRTky8fRcI8YeNNLPIseoV3QPkf7q
+Ni6YXl0yUHV5gQMCWqgbfdHAljd2+N1RZvdzfEOLVPLX4/dgxb36i9OKkuCAHLoL
+2UXfzcAElltHQundNi/xYzSizzEYBeIbVrbuqiJP1zmiPUKxHibkU3ThZZUbonKR
+NVPQe1hO47Cxyj1RxXl6Nt9uda3W9ow6Kr96Bjs3WVBSqsuohqaAlAxC6RccslrE
+w/7N7l8S423LJI6ZV+FvyJzmSAqkLNz/tuFSMj76uH4s1dLbRv8K4fcw1vZgqy/4
+jIhBFycn29hMNvImKbMnLDwC7K92lBGQ6hp75/0Hf1qHOpDaiyV9Qqzr3sTOMXJi
+Ym3ac5bDqJb9Mi5YPNB2OD3w3bDMGT5+eWjmw9RiYT5gNjY6nZhDiQS/PtIc6l3i
+2GaBjSdurwj47TlCWALj3ZiiEKiybanK5/YXdVXGchLnoNkxeI1YcANZhX60FWEy
+aHZsa7QbTWFyayBXaWVsYWFyZCA8bWp3QGdudS5vcmc+iQJOBBMBCgA4FiEE7Dz+
+iPbKB4h3T1wdGqRL5knedgoFAlxN+lMCGwEFCwkIBwIGFQoJCAsCBBYCAwECHgEC
+F4AACgkQGqRL5knedgo1bhAArI7kReYq4YtaxS8Pxb5MdPxiQVtvfkbycWCZ4owz
+PeEIkJqcbadNUiGSqCRR2xeT4kuzFZWILiZfBTwHwFM/bXRDK/FOn7F8aqUAV1tq
+2W70Z7BUpTwpAv7Xm5YvsfbTBZmllJltEiIrKIzULCtRKKVXgtOKg0sd/W2aXwyl
++OX+PVzu4mXXNEkO10J7VpnCvjyaJNeKgeJYQLizSWdEf7i6RX31yC29+GsSqika
+OHdfxJMM+bo/x/aCuYlgDB+OQ6LZzpXZO0C8B5SMgMfZaK1rxDtUtViajSyOFJ4I
+g6bcgc5qDCLnk407oEN1yBWps867uN/Bi4Dk+xh691feGsyq95DvPis2Ut+0X0/W
+i/uLg3uu/X5EcNHynwht7KaGCLeuOZKxvzfeudNeyKFX34HtFyE/2k9LR0mFX8Xn
+XQGBD9psOxcd2K8Rku9BjjKDZ/vf53sMh5vxUNo+zkd+5dLZWPnLrhkfQrepDBP+
+Tc/6W0VSZCP5/nKX6GjPwmELtZj4jGf33tgfNMJrmxGUjpDxtiJc7OroNC4he3F5
+AF4RNRa5VvHs6ah57swVvKyJmLH5mxxKIn39PspOhzVxSbkWNPLS+km2InPum+fm
+YKQL6IrHcqt/ecrR7o9GRgI0cJjLJ+wv93ti+gxsUWPbAUBaJPk24omIpQafFT/Y
+AEW0Hk1hcmsgV2llbGFhcmQgPG1qd0ByZWRoYXQuY29tPokCTgQTAQoAOBYhBOw8
+/oj2ygeId09cHRqkS+ZJ3nYKBQJcTfqnAhsBBQsJCAcCBhUKCQgLAgQWAgMBAh4B
+AheAAAoJEBqkS+ZJ3nYK6JIP/jGq2adAkk1IPsVx7X5argCXaI5o3aTG+N6BPMvi
+zGY4CyqTBmYAg3qRPWN4U+wxNFgzQ3nPfptJK6EDBAY4Lw+kKR4o8o5zPyjAjbc9
+/be5bvTwMFmMbzWxGWoJ4ch9W+wD4W+W8ssnJDbVi5Btp7kKyUgg3KP7oUQpxZ9M
+TgmKEmPuce9zOQ78q+LIPbkhI9zCS/1VCHkeVyn+TrnACoHx7sKgJoOwjVlcbW3S
+0sdCuaGg3+VLI3v3IpQ56UXIX6RVeLX9zVDZnAq72Age4HHcxjX97j16iL5ZhZRc
+24J5tpSkJgHt+RASOKHJGPIivCqKbQKhYc1G4MbFbGzclaLTXya3Q4ekFzo4ohd2
+ga7mgjG0SJ+aIU5wCYxEUDsqJLm+uH/nbQzXTxIoQhH5yub4OhW88z6LpwPGhLvz
+S2SuPJIXAlbGyrH70/uRZWkwKF/8mQjMCsLEYkZ9DRB815rUTc9CJkkeOlPXQUbx
+r2fDAgi0j3yAUxlrC7jESO/zUJrICbxChYAx9KMWG/2PsKbrGAAMKiC7+q6mY09Q
+63F/g1DEF2sb+bguMdWc7SEj64jFUf9wJ+vjU1F321Bkh/QWMABv6n+7EFkwnNky
+lCR5H1boOHO03TNT0jyLbBECR7/Mtpwt46c4+n9EPCmQyvdU3MVPORvZge1hzvuv
+fo22uQENBFxDuhkBCAC19Q021v7kTuwYKwEmbqQC5wvmbEMT4ldvQ8gWCUIFL9kT
+xM67IF0annsys+rrAyqqFUTq2onVmgjciu9upl6uDdV3wivCBEDN9ZLZAVHTSvii
+XDhnHUSg6EhCdZKhal9DKAi+vGSLSe14e2Kfoe4c6R0yDVI+Dn0OfUhlMXu2NoDS
+FLAdHsDHSCrE6xKO+BNgL2MPuMeXLhNitNIVrykoZMkFrUMcMsHrvrk05ah87RQO
+1e2ljenn8qxPRLdOVWc0TJiosjiy04vwDAYNUCPDL5W2Mp2bv2AeTPCzF1qkDnGK
+ZEqV2peWKCPB608lS1icw5oKtOl50PSgzTdaLVRXABEBAAGJAjYEGAEKACAWIQTs
+PP6I9soHiHdPXB0apEvmSd52CgUCXEO6GQIbDAAKCRAapEvmSd52Cpy8D/9tq4BQ
+3VwrDNCxycALqWvZSPv/AgsT6hRvQsLc6Yp0FEtz+frFPLWt7bylMrzKItpsr0G2
+FofWw0yNyHNYPmGlCi+SrWLJnUTEm5TZgwT+9kLt/mJ4B0J1gHkknXSo91S84DPa
+ik9CH0GmXIQyPANkDDlmp9W/Hk8oKxxvCx+SSsZ6ANXakcNVg/w4MhDW2HowW4sB
+vtltOFSgPRs9zISiNw//GYjeYrdOOnieMhszwpjQuK5XYnDhwiSap2D8nQlD/VpA
+a2CvE/fOFV2CJyKZfE0J8v5DZOU+SUwnty1f52ZA1s/OCysaK1LLdCXz3bQiybQZ
+hobcAneBVZFlNzf6xpR+pGtw3OVSyLQo4LSQf4lFszNy8FfE+BJ1/yUWFBjljLwI
+Hd4IW7Y17PugAc19fQ23krOIc3O4qsuYzqdhzYzqGbPvf7fY3Tz0BNcW5885KEQJ
+H7VJJLqpf3EELhmkLBONYiF10iggFSmn8WSQWbXm0kGRETvAzf+FYcJsKDu9QASD
+RNck8J20ZJGVLbZNdP+VuLOXCDAkSGIxi91TLi6bY0Mb2yNRgAq6cnIJUTAbcnw0
+5BLxRW+e8AS3HodjZHWzAMDPpZn5TFfJOXdDhdeePVGgkypxwnbeyTT3OjUEh37v
+r+XIgrTMpz+ZNpHxLr4bJatQEVK3H6Q3ZbQkMbkBDQRcQ7q3AQgAqSM4Wx4QvvCI
+f8is+57mLJhceB2kLt3VR67UFZC0ywcr5V0pvTuu2U1oUB+BVYC/A9UdnvWTyDef
+3xTCx0hAiiFhlMe6CkODOalmxI+KwPxD276+70tcxd8vR2FJviDQKw96f2hlLAnx
+R47GUp3cPfIgVfkvIXnXLMUJQvBhXeXqgYhOcAplI677n/zTeFjBtd/JqtyDoJ0D
+e1odEyC+ZZD/Jo5q80Sydhvb99BHQMgLTJTJPW1iRV2AK4xfBjxOMwqml9Lx4HRI
+pV/IHs3MTyhEpEA+I/eKpO6UxApHWHZ76Zm8BL8RwnfFaXjMueRhIGMFtJnLuNFc
+5mOLXa3uhwARAQABiQNsBBgBCgAgFiEE7Dz+iPbKB4h3T1wdGqRL5knedgoFAlxD
+urcCGwIBQAkQGqRL5knedgrAdCAEGQEKAB0WIQQSdoqWeVmQEHoNL9/8V+PMrNma
+eAUCXEO6twAKCRD8V+PMrNmaeEvuB/92qMj2mQN3CXRQUTlmzVNUJLJAwzjRDoSt
+3kqDrACJ2N8JLSxWFeHmEmrrmFPUmXfBUkT+F2W+OrsJlUtwepuTYROgLNZebFQd
+jB38oqsj8RMKb5ikWntRUka2xhSDRBa0IlpxHBWLHS8nEx1x4HB4uYRK3IpWShAV
+mWk7jiATGJLFYJGVo4TBfM27zCty8/GQN/3A2DAJ2OJbiJ12ByTgzztGdhJ69H/Q
+UltkK7eJUGMjPwhpmp07lrolyUurbzaLMQow4SLo/ZIxa0nPC+AoMSk06teichCZ
+wIyiU/70S0c/uL3RFhnTbgWcdQkAVpWdkwFqIES4xG5QLUu85/WT7lMQALJKKuOO
+pbOeKvyLV16Oo70OTms/LbmXU9+bjCjz7QISuzhI4rua0onjQzBaRXFYkfCjBudW
+aEpy/wP5wk6QlqxLkeZNCk0TswksLxQjyO2XgBcOnrSsQIEJ7VICG9PDvtVzbrSB
+YMjoDo58AyniEMVANyUnFYl1YBlFt506PDh86ZEqlpbbReAsYfEuBQdBfJhWph9W
+ZgJDVtEHUAxaiqisvNEbz4xRIAsxX/OxnQMdD09Xs50yvl38ERIadacejtQnAIYe
+EaUBsgQk3rt0+g9lm6trD7P4FXYhUD9vml6/n8TGB3UJi3lKpX41GSUC1y+oPna8
+p+EEmrm3BbB4fgnIkfYiEDNogvm2pe7nzUP7sNnE8RcyYcjUoEQ0Uo+HB6fk6NeB
+GKqaIKVexCcExnWKHvl0DZzGydvKx41nyzFI1sueg34LcWwpGHXzJyhmpjhNe1GO
+KtVGHCGKhKhppK4ntUZISciGh38wvKuFDohHO3JVZ9AhyRWKTuynzLarBpmvu11T
+Dbv0lfnZcghlWWHNlx8x8DdaEuFWXZTDuVXqGclmeV2hS0LomX33LCB4n0XkZtC9
+LsmTIsr+ZdVCAXUeX/pJONNxNF8G47lZLLgLWF9beuHWp3u1Io31fzh44TZxm1Z3
+1wCZjOrsL9bvy3xHyDFaDL+/7i6TXsSxtqTXuQENBFxDu6IBCACgVJJnY8zh8uHn
+8d/E7p4j+9ueTvTHMRYOS0kkGhHBC7JmxCw6/EvbnbTsI0CQeyIJHlmPIqDVgRVj
+ijcTWacd3vIdazzH9sqs65nl49yMnA23tIya4VWlbHC3J4x/LL84A4GaJO/FVF2v
+v6hVg3IGbopp5KX+pr6s56TiWddSDqMgjb7rSzjWuNyRK75ToctL7Y/Zn6st3Zio
+O7LXq3ghkWf8JR7ZaUFIY6P1qS5heiCHP0PxQJSrtpYzH3rKJoHpIkjxnsB/sD0C
+05cAdlzXBTUVTNLY+DPlQ7FeRkG+VK91briG4tvQ8ohhEiC9HuJu1AKMNWBZ9qeU
+wsXaJvNzABEBAAGJAjYEGAEKACAWIQTsPP6I9soHiHdPXB0apEvmSd52CgUCXEO7
+ogIbIAAKCRAapEvmSd52Ch8ZD/9wKuIlaRMSB1AMCwhGPaqXZahrJ649Y0jI4Jqp
+FKv2/U5hKHOG7bihRAeEj7pZzhlgBrkZg1SBdZ3vHs1ufElnfe5RQApdDm93daU5
+SP29iEivJQxKjF91EfEffl0trxxztBipI5/2D+kaS8cnNVfzo5ZEWy/cd6AShvRV
+HM7Y2QHc+mlaZhYhBvTtwC6avXNnG55WYgobGENeAwkyD072JF3XrxFb+XkcKxla
+9yRdWdHxJd5PYJqsKM+nVeJM226OwOyU235gfIhIP6pfGqF9UVH0uFoCYkVkUSjV
+d96Q+Cj0kdhTOrtLW1OY11d9TBxje42GOtc7X9Zzx1nhwU8rCCErF9/uJIJKlq7I
+08rMX3rFDTtizwN7g7ZBkDDiZO+BIKQPt/awA9NM+tda02hyfQokBBi+v8b/iKif
+KIfUaqPDo1PA5uxljdluyX8AXIotKjJXF6Elsiz7bVpcIc0ZXOOFr9ylmtZm51YN
+mOzDNznEBmol2oBZfsk2G55/QgShHmKUnvzKANBGfnfS/a/K7Hv4sfZAb58Prl6O
+mQSrkmhzFry/4BNLKq+nd4s8VXkJPpx3Ogf3DoIynqpNF0bwf52U5IgJSNcJN/Hr
+AwhaG1W+Y3LDe7S19M0cUzftEUeq3Jd89hoijC72tdba+BRfW0ncfvEcsk9QifSU
+1tvZxQ==
+=l2J7
+-----END PGP PUBLIC KEY BLOCK-----
+-----BEGIN PGP PUBLIC KEY BLOCK-----
+ 
+mQENBGXb21kBCADCyOpVSfJ6XHVp8+dspYCgkSwr26IF+SXHzt9dVyMChAKJIXib
+ty8NA/Huh3ZRNzFXdFM09yoYiglnYu3+r1rniliP1L1w3y0tDNxlvlLmVhM5WAfA
+IyZ9tI8X1XIfRLYsX70UM3jDvyoXkEQkjhQKDHrgBdBTNARHlHVykj44xD2TCwao
+vV0gFu2EmCN8TsMWLdQ1VymtYd/UFB6znlLzSglzzx4OYKyla6anbWqKxvB3siIH
+Pf/ULBh0JNTluH39kk486yE9Lh1z9H8FoVlUWcXvlr0rmPPQDl9se02bkd4rA/gD
+kRQmlUXxJIJCNYZiQ7k0nZSYQY6JzhY1szBLABEBAAG0H0Fhcm9uIE1lcmV5IDxh
+bWVyZXlAcmVkaGF0LmNvbT6JAVEEEwEIADsWIQRsK2MVY7jTMFeNPLR0/T+id55w
+cwUCZdvbWQIbAwULCQgHAgIiAgYVCgkICwIEFgIDAQIeBwIXgAAKCRB0/T+id55w
+cxHiCAC9evJD8CqSPOfuKFa2iITLoSM2ORdpsp5Wla9OpAV5GnUNKbR7KCLoG7OQ
+3Tth9qdHqrCIUigvj2xzcaovdyVRpDLBFG5cbrBB7Jqly0ptJhFUtx8wbDBammZq
+7ZAsLFP582ILqlLjcTIOUNk4ABuTDN9FIdewgWXMW7GPp5euJ4ucos2glySwLbC4
++6kZ1guYYbO3S9YWWyImP2Guf4KVi5kTF0USTklvszJLvwJNkYknQhxnDcWLeOPJ
+P4hOdHlwJSsaXcKyOn//FdMXRGDcknKcn43e03esXjflvz8HyXz4VbjEqDpOHS9i
+l/NOw6+C7+wcAvHDu583cMbuI7hziEYEEBEIAAYFAmXiB7IACgkQVZbdDOm/ZT2Q
+fwCfQSmNDkHu3ZxwvWs+mOFaYR3PGRAAnieQMVnPZd8kgGkVO/GNIJIBeuA7iF0E
+EBECAB0WIQRBoMESdLHof+KOTFPj134flRYZkQUCZeIIBAAKCRDj134flRYZkX4N
+AJ0Q8p1f7lmWgiHaHmD3DtuJ7uhWHACgk84evo0UsqVNi/4xHZ0wpVvxx+S5AQ0E
+ZdvbWQEIAKgzEcJMUfFgsUGwMO/I4mwjvB7+Jx90lSYjS3uM7E3jnYhu/en42skl
+nYEMxMR9EWUF6RZ78QiUvD/Ik6fP0YrMuTRBnZ7ZOd5zLPbgDIAOVeiVxFRwGOzj
+z01V/plDlz+zCQkS1tOPgpGKCzTol7/M9ks9AHqKE6DWrrk1LbER2qDyE6XMAe5b
+LNqdmtfJ2uf2XPThGGz0ujJ0MdistoRMechX9qBIBaLwxuA5edx+3iu6MdjMCeua
+yV+Yb4ePG+9IY3OmdC/3wNpJYOQvSsJz9PzX4Nf1PuIaT/JoQSmZa8aZYgtCVMCV
+t15UDdpPTyuFeXSBYLkuSQGM6DqARnEAEQEAAYkBNgQYAQgAIBYhBGwrYxVjuNMw
+V408tHT9P6J3nnBzBQJl29tZAhsMAAoJEHT9P6J3nnBzAJYH/1eX+r8VEDPU/TKA
+yqYW2Mg87jyo8+t2x0zFZfucni/0o3ejaSxSVtnWiFh79OWnACnbq0go+pT59X7V
+03VcYQgRpzLuD0OzcOmkHI4kgbB2Q3zNszlqb67Lkt+P9xy16DWS8N9qujfiTw6q
++xT/BsSxmOuWxexrRjui012g28TcihlQIRBOtJIA2vEwUWjuMkzno2Xbrxq99WH8
+iSr3bTGc/jpnMetW4iHE8VxUJ7ixvbcE4vWsfUqPyr/5U25a2D8XNmvqw9J1msNE
+5dlWzgmpLMHLVzKigvJffjsYxxLvekbSv/mJgonhDXUQvUnwy0bx41te/neXHrEv
+S0Zj1TU=
+=iz3/
+-----END PGP PUBLIC KEY BLOCK-----
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..c9d59d4
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,107 @@
+## Process this file with automake to create Makefile.in
+## Configure input file for elfutils.
+##
+## Copyright (C) 1996-2006, 2008, 2009, 2015 Red Hat, Inc.
+##
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+ACLOCAL_AMFLAGS = -I m4
+
+# automake already tells which subdir is being entered.
+# Don't make make repeat.
+AM_MAKEFLAGS = --no-print-directory
+
+pkginclude_HEADERS = version.h
+
+SUBDIRS = config lib libelf libcpu backends libebl libdwelf libdwfl libdw \
+	  libasm debuginfod src po doc tests
+
+EXTRA_DIST = elfutils.spec GPG-KEY NOTES CONTRIBUTING SECURITY \
+	     COPYING COPYING-GPLV2 COPYING-LGPLV3
+
+# Make sure the test install uses lib64 when $LIB will yield lib64.
+# Make sure the test build uses the same compiler, which on e.g. ppc64
+# determines which platform we are actually testing.
+# Run all tests under valgrind.
+AM_DISTCHECK_CONFIGURE_FLAGS = \
+	--libdir=`echo $(libdir) | sed "s,^$(exec_prefix),$$dc_install_base,"`\
+	CC="$(CC)"
+
+distcheck-hook:
+	chmod -R u+w $(distdir)
+
+rpm: dist
+	rpmbuild -ts elfutils-@PACKAGE_VERSION@.tar.bz2
+
+rpmbuild: dist
+	mkdir -p rpmbuild
+	rpmbuild -ta elfutils-@PACKAGE_VERSION@.tar.bz2 \
+		--define "_topdir $(shell pwd)/rpmbuild"
+
+if GCOV
+
+COVERAGE_OUTPUT_FILE = $(PACKAGE_NAME).lcov
+COVERAGE_OUTPUT_DIRECTORY = coverage
+COVERAGE_OUTPUT_INDEX_HTML = $(COVERAGE_OUTPUT_DIRECTORY)/index.html
+COVERAGE_TITLE = $(PACKAGE_NAME)-$(PACKAGE_VERSION)
+
+COVERAGE_DIRS = $(filter-out tests,$(SUBDIRS))
+src_COVERAGE_DIRS = $(patsubst %,$(srcdir)/%,$(COVERAGE_DIRS))
+build_COVERAGE_DIRS = $(patsubst %,$(builddir)/%,$(COVERAGE_DIRS))
+all_COVERAGE_DIRS = $(sort $(src_COVERAGE_DIRS) $(build_COVERAGE_DIRS))
+LCOV_DIRS_ARGS = $(patsubst %,--directory=%,$(all_COVERAGE_DIRS))
+
+CLEANFILES = $(COVERAGE_OUTPUT_FILE)
+
+.PHONY: coverage coverage-clean
+
+clean-local: coverage-clean
+distclean-local: coverage-clean
+
+coverage-clean:
+	-rm -rf $(COVERAGE_OUTPUT_DIRECTORY)
+
+coverage: $(COVERAGE_OUTPUT_INDEX_HTML)
+	@echo 'file://$(abs_builddir)/$(COVERAGE_OUTPUT_INDEX_HTML)'
+
+$(COVERAGE_OUTPUT_INDEX_HTML): $(COVERAGE_OUTPUT_FILE)
+	LC_ALL=C $(GENHTML) \
+		--legend \
+		--show-details \
+		--rc=genhtml_branch_coverage=1 \
+		--title='$(COVERAGE_TITLE)' \
+		--prefix='$(abspath $(abs_srcdir))' \
+		--prefix='$(realpath $(abs_srcdir))' \
+		--prefix='$(abspath $(abs_builddir)/..)' \
+		--prefix='$(realpath $(abs_builddir)/..)' \
+		--output-directory='$(COVERAGE_OUTPUT_DIRECTORY)' \
+		$<
+
+$(COVERAGE_OUTPUT_FILE):
+	$(LCOV) \
+		--capture \
+		--no-external \
+		--no-checksum \
+		--rc=lcov_branch_coverage=1 \
+		--gcov-tool='$(GCOV)' \
+		--output-file='$@' \
+		$(LCOV_DIRS_ARGS)
+
+endif
+
+# Tell version 3.79 and up of GNU make to not build goals in this
+# directory in parallel.
+.NOTPARALLEL:
diff --git a/NEWS b/NEWS
new file mode 100644
index 0000000..4549bb6
--- /dev/null
+++ b/NEWS
@@ -0,0 +1,1852 @@
+Version 0.191 "Bug fixes in C major"
+
+libdw: dwarf_addrdie now supports binaries lacking a .debug_aranges
+       section.
+
+       Improved support for DWARF package files.  Add new function
+       dwarf_cu_dwp_section_info.
+
+debuginfod: Caching eviction logic improvements to improve retention
+            of small/frequent/slow files such as Fedora's vdso.debug.
+
+srcfiles: Can now fetch the source files of a DWARF/ELF file and
+          place them into a zip.
+
+Version 0.190 "Woke!"
+
+CONTRIBUTING: Switch from real name policy to known identity policy.
+              Updated ChangeLog policy (no more separate ChangeLog files).
+              There is a SECURITY bug policy now.
+              The default branch is now 'main'.
+
+libelf: Add RELR support.
+
+libdw: Recognize .debug_[ct]u_index sections
+
+readelf: Support readelf -Ds, --use-dynamic --symbol.
+         Support .gdb_index version 9
+
+scrlines: New tool that compiles a list of source files associated
+          with a specified dwarf/elf file.
+
+debuginfod: Schema change (reindexing required, sorry!) for a 60%
+            compression in filename representation, which was a large
+            part of the sqlite index; also, more deliberate sqlite
+            -wal management during scanning using the
+            --scan-checkpoint option.
+
+backends: Various LoongArch updates.
+
+Version 0.189 "Don't deflate!"
+
+configure: eu-nm, eu-addr2line and eu-stack can provide demangled symbols
+           when linked with libstdc++. Use --disable-demangler to disable.
+
+           A new option --enable-sanitize-memory has been added for msan
+           sanitizer support.
+
+libelf: elf_compress now supports ELFCOMPRESS_ZSTD when build against
+        libzstd
+
+libdwfl: dwfl_module_return_value_location now returns 0 (no return type)
+         for DIEs that point to a DW_TAG_unspecified_type.
+
+elfcompress: -t, --type= now support zstd if libelf has been build with
+             ELFCOMPRESS_ZSTD support.
+
+backends: Add support for LoongArch and Synopsys ARCv2 processors.
+
+Version 0.188 "no section left behind"
+
+readelf: Add -D, --use-dynamic option.
+
+debuginfod-client: Add $DEBUGINFOD_HEADERS_FILE setting to supply outgoing
+                   HTTP headers. Add new function debuginfod_find_section.
+
+debuginfod: Add --disable-source-scan option.
+
+libdwfl: Add new function dwfl_get_debuginfod_client.
+         Add new function dwfl_frame_reg.
+         Add new function dwfl_report_offline_memory.
+
+Version 0.187 "no zero negatives"
+
+debuginfod: Support -C option for connection thread pooling.
+
+debuginfod-client: Negative cache file are now zero sized instead of
+                   no-permission files.
+
+addr2line: The -A, --absolute option, which shows file names including
+           the full compilation directory is now the default.  To get the
+           old behavior use the new option --relative.
+
+readelf, elflint: Recognize FDO Packaging Metadata ELF notes
+
+libdw, debuginfo-client: Load libcurl lazily only when files need to
+                         be fetched remotely. libcurl is now never
+                         loaded when DEBUGINFOD_URLS is unset. And when
+                         DEBUGINFOD_URLS is set, libcurl is only loaded
+                         when the debuginfod_begin function is called.
+
+Version 0.186 "Just In Time"
+
+debuginfod-client: Default $DEBUGINFOD_URLS is computed from drop-in files
+                   /etc/debuginfod/*.urls rather than hardcoded into the
+                   /etc/profile.d/debuginfod* scripts.
+                   Add $DEBUGINFOD_MAXSIZE and $DEBUGINFOD_MAXTIME settings
+                   for skipping large/slow transfers.
+                   Add $DEBUGINFOD_RETRY for retrying aborted lookups.
+
+debuginfod: Supply extra HTTP response headers, describing archive/file
+            names that satisfy the requested buildid content.
+            Support -d :memory: option for in-memory databases.
+            Protect against loops in federated server configurations.
+            Add -r option to use -I/-X regexes for grooming stale files.
+            Protect against wasted CPU from duplicate concurrent requests.
+            Limit the duration of groom ops roughly to rescan (-t) times.
+            Add --passive mode for serving from read-only database.
+            Several other performance improvements & prometheus metrics.
+
+libdw: Support for the NVIDIA Cuda line map extensions.
+       DW_LNE_NVIDIA_inlined_call and DW_LNE_NVIDIA_set_function_name
+       are defined in dwarf.h. New functions dwarf_linecontext and
+       dwarf_linefunctionname
+
+translations: Update Japanese translation.
+
+Version 0.185 "oops, I did it again"
+
+debuginfod-client: Simplify curl handle reuse so downloads which
+                   return an error are retried.
+
+elfcompress: Always exit with code 0 when the operation succeeds (even
+             when nothing was done). On error the exit code is now always 1.
+
+Version 0.184 "negative results"
+
+debuginfod: Use libarchive's bsdtar as the .deb-family file unpacker.
+
+debuginfod-client: Client caches negative results. If a query for a
+		   file failed with 404, an empty 000 permission
+		   file is created in the cache. This will prevent
+		   requesting the same file for the next 10 minutes.
+
+		   Client objects now carry long-lived curl handles
+		   for outgoing connections.  This makes it more
+		   efficient for multiple sequential queries, because
+		   the TCP connections and/or TLS state info are kept
+		   around awhile, avoiding O(100ms) setup latencies.
+
+libdw: handle DW_FORM_indirect when reading attributes
+
+translations: Update Polish translation.
+
+Version 0.183 "100+ commits"
+
+debuginfod: New thread-busy metric and more detailed error metrics.
+            New --fdcache-mintmp and tracking of filesystem freespace.
+            New increased webapi concurrency while grooming.
+
+debuginfod-client: DEBUGINFOD_SONAME macro added to debuginfod.h which
+                   can be used to dlopen the libdebuginfod.so library.
+                   New function debuginfod_set_verbose_fd and
+                   DEBUGINFOD_VERBOSE environment variable.
+
+config: profile.sh and profile.csh won't export DEBUGINFOD_URLS unless
+        configured --enable-debuginfod-urls[=URLS]
+
+elflint, readelf: Recognize SHF_GNU_RETAIN.
+                  Handle SHT_X86_64_UNWIND as valid relocation target.
+
+Version 0.182 "October Surprise!"
+
+backends: Support for tilegx has been removed.
+
+config: New /etc/profile.d files to provide default $DEBUGINFOD_URLS.
+
+debuginfod: More efficient package traversal, tolerate various errors
+            during scanning, grooming progress is more visible and
+            interruptible, more prometheus metrics.
+
+debuginfod-client: Now supports compressed (kernel) ELF images.
+
+libdwfl: Add ZSTD compression support.
+
+Version 0.181 "Show me your ARMs"
+
+libelf: elf_update now compensates (fixes up) a bad sh_addralign for
+        SHF_COMPRESSED sections.
+
+libdebuginfod: configure now takes --enable-libdebuginfod=dummy or
+               --disable-libdebuginfod for bootstrapping.
+               DEBUGINFOD_URLS now accepts "scheme-free" urls
+               (guessing at what the user meant, either http:// or file://)
+
+readelf, elflint: Handle aarch64 bti, pac bits in dynamic table and gnu
+                  property notes.
+
+libdw, readelf: Recognize DW_CFA_AARCH64_negate_ra_state. Allows unwinding
+                on arm64 for code that is compiled for PAC (Pointer
+                Authentication Code) as long as it isn't enabled.
+
+Version 0.180 "We got an L, we got an T, can we have a O?"
+
+elflint: Allow SHF_EXCLUDE as generic section flag when --gnu is given.
+
+libdw, readelf: Handle GCC LTO .gnu.debuglto_ prefix.
+
+libdw: Use correct CU to resolve file names in dwarf_decl_file.
+
+libdwfl: Handle debugaltlink in dwfl_standard_find_debuginfo.
+
+size: Also obey radix printing for bsd format.
+
+nm: Explicitly print weak 'V' or 'T' and common 'C' symbols.
+
+Version 0.179 "All your packages are belong to us!"
+
+debuginfod-client: When DEBUGINFOD_PROGRESS is set and the program doesn't
+                   install its own debuginfod_progressfn_t show download
+                   progress on stderr.
+                   DEBUGINFOD_TIMEOUT is now defined as seconds to get at
+                   least 100K, defaults to 90 seconds.
+                   Default to $XDG_CACHE_HOME/debuginfod_client.
+                   New functions debuginfod_set_user_data,
+                   debuginfod_get_user_data, debuginfod_get_url and
+                   debuginfod_add_http_header.
+                   Support for file:// URLs.
+
+debuginfod: Uses libarchive directly for reading rpm archives.
+            Support for indexing .deb/.ddeb archives through dpkg-deb
+            or bsdtar.
+            Generic archive support through -Z EXT[=CMD]. Which can be
+            used for example for arch-linux pacman files by using
+            -Z '.tar.zst=zstdcat'.
+            Better logging using User-Agent and X-Forwarded-For headers.
+            More prometheus metrics.
+            Support for eliding dots or extraneous slashes in path names.
+
+debuginfod-find: Accept /path/names in place of buildid hex.
+
+libelf: Handle PN_XNUM in elf_getphdrnum before shdr 0 is cached
+        Ensure zlib resource cleanup on failure.
+
+libdwfl: dwfl_linux_kernel_find_elf and dwfl_linux_kernel_report_offline
+         now find and handle a compressed vmlinuz image.
+
+readelf, elflint: Handle PT_GNU_PROPERTY.
+
+translations: Updated Ukrainian translation.
+
+Version 0.178 "All the build-id you can count!"
+
+debuginfod: New server, client tool and library to index and fetch
+            ELF/DWARF files addressed by build-id through HTTP.
+
+doc: There are now some manual pages for functions and tools.
+
+backends: The libebl libraries are no longer dynamically loaded through
+          dlopen, but are now compiled into libdw.so directly.
+
+readelf: -n, --notes now takes an optional "SECTION" argument.
+         -p and -x now also handle section numbers.
+         New option --dyn-sym to show just the dynamic symbol table.
+
+libcpu: Add RISC-V disassembler.
+
+libdw: Abbrevs and DIEs can now be read concurrently by multiple
+       threads through the same Dwarf handle.
+
+libdwfl: Will try to use debuginfod when installed as fallback to
+         retrieve ELF and DWARF debug data files by build-id.
+
+Version 0.177 "What is your category, class and taxonomy?"
+
+elfclassify: New tool to analyze ELF objects.
+
+readelf: Print DW_AT_data_member_location as decimal offset.
+         Decode DW_AT_discr_list block attributes.
+
+libdw: Add DW_AT_GNU_numerator, DW_AT_GNU_denominator and DW_AT_GNU_bias.
+
+libdwelf: Add dwelf_elf_e_machine_string.
+          dwelf_elf_begin now only returns NULL when there is an error
+          reading or decompressing a file. If the file is not an ELF file
+          an ELF handle of type ELF_K_NONE is returned.
+
+backends: Add support for C-SKY.
+
+Version 0.176 "At your own RISC-V"
+
+build: Add new --enable-install-elfh option.
+       Do NOT use this for system installs (it overrides glibc elf.h).
+
+backends: riscv improved core file and return value location support.
+
+Fixes CVE-2019-7146, CVE-2019-7148, CVE-2019-7149, CVE-2019-7150,
+      CVE-2019-7664, CVE-2019-7665
+
+Version 0.175
+
+readelf: Handle multiple .debug_macro sections.
+         Recognize and parse GNU Property notes, NT_VERSION notes
+         and GNU Build Attribute ELF Notes.
+
+strip: Handle SHT_GROUP correctly.
+       Add strip --reloc-debug-sections-only option.
+       Handle relocations against GNU compressed sections.
+
+libdwelf: New function dwelf_elf_begin.
+
+libcpu: Recognize bpf jump variants BPF_JLT, BPF_JLE, BPF_JSLT and BPF_JSLE.
+
+backends: RISCV handles ADD/SUB relocations. Handle SHT_X86_64_UNWIND.
+
+Fixes CVE-2018-18310, CVE-2018-18520 and CVE-2018-18521.
+
+Version 0.174 "extended shnum"
+
+libelf, libdw and all tools now handle extended shnum and shstrndx correctly.
+
+elfcompress: Don't rewrite input file if no section data needs updating.
+             Try harder to keep same file mode bits (suid) on rewrite.
+
+strip: Handle mixed (out of order) allocated/non-allocated sections.
+
+unstrip: Handle SHT_GROUP sections.
+
+backends: RISCV and M68K now have backend implementations to generate CFI based
+          backtraces.
+
+Fixes CVE-2018-16062, CVE-2018-16402 and CVE-2018-16403.
+
+Version 0.173 "crash free"
+
+More fixes for crashes and hangs found by afl-fuzz. In particular various
+functions now detect and break infinite loops caused by bad DIE tree cycles.
+
+readelf: Will now lookup the size and signedness of constant value types
+         to display them correctly (and not just how they were encoded).
+
+libdw: New function dwarf_next_lines to read CU-less .debug_line data.
+       dwarf_begin_elf now accepts ELF files containing just .debug_line
+       or .debug_frame sections (which can be read without needing a DIE
+       tree from the .debug_info section).
+       Removed dwarf_getscn_info, which was never implemented.
+
+backends: Handle BPF simple relocations.
+          The RISCV backends now handles ABI specific CFI and knows about
+          RISCV register types and names.
+
+Version 0.172 "DWARF5 bugs split!"
+
+No functional changes compared to 0.171 "DWARF5 split!".
+
+Various bug fixes in libdw and eu-readelf dealing with bad DWARF5 data.
+Thanks to running the afl fuzzer on eu-readelf and various testcases.
+
+eu-readelf -N is ~15% faster.
+
+Version 0.171 "DWARF5 split!"
+
+DWARF5 and split dwarf, including GNU DebugFission, are supported now.
+Data can be read from the new DWARF sections .debug_addr, .debug_line_str,
+.debug_loclists, .debug_str_offsets and .debug_rnglists.  Plus the new
+DWARF5 and GNU DebugFission encodings of the existing .debug sections.
+Also in split DWARF .dwo (DWARF object) files.  This support is mostly
+handled by existing functions (dwarf_getlocation*, dwarf_getsrclines,
+dwarf_ranges, dwarf_form*, etc.) now returning the data from the new
+sections and data formats.  But some new functions have been added
+to more easily get information about skeleton and split compile units
+(dwarf_get_units and dwarf_cu_info), handle new attribute data
+(dwarf_getabbrevattr_data) and to keep references to Dwarf_Dies
+that might come from different sections or files (dwarf_die_addr_die).
+
+Not yet supported are .dwp (Dwarf Package) and .sup (Dwarf Supplementary)
+files, the .debug_names index, the .debug_cu_index and .debug_tu_index
+sections. Only a single .debug_info (and .debug_types) section are
+currently handled.
+
+readelf: Handle all new DWARF5 sections.
+         --debug-dump=info+ will show split unit DIEs when found.
+         --dwarf-skeleton can be used when inspecting a .dwo file.
+	 Recognizes GNU locviews with --debug-dump=loc.
+
+libdw: New functions dwarf_die_addr_die, dwarf_get_units,
+       dwarf_getabbrevattr_data and dwarf_cu_info.
+       libdw will now try to resolve the alt file on first use of
+       an alt attribute FORM when not set yet with dwarf_set_alt.
+       dwarf_aggregate_size() now works with multi-dimensional arrays.
+
+libdwfl: Use process_vm_readv when available instead of ptrace.
+
+backends: Add a RISC-V backend.
+
+There were various improvements to build on Windows.
+The sha1 and md5 implementations have been removed, they weren't used.
+
+Version 0.170 "DWARF4 1/2"
+
+libdw: Added new DWARF5 attribute, tag, character encoding, language code,
+       calling convention, defaulted member function and macro constants
+       to dwarf.h.
+       New functions dwarf_default_lower_bound and dwarf_line_file.
+       dwarf_peel_type now handles DWARF5 immutable, packed and shared tags.
+       dwarf_getmacros now handles DWARF5 .debug_macro sections.
+
+strip: Add -R, --remove-section=SECTION and --keep-section=SECTION.
+
+backends: The bpf disassembler is now always build on all platforms.
+
+Version 0.169
+
+backends: Add support for EM_PPC64 GNU_ATTRIBUTES.
+          Frame pointer unwinding fallback support for i386, x86_64, aarch64.
+
+translations: Update Polish translation.
+
+Version 0.168 "kthxbye"
+
+http://elfutils.org/ is now hosted at http://sourceware.org/elfutils/
+
+libelf: gelf_newehdr and gelf_newehdr now return void *.
+
+libdw: dwarf.h corrected the DW_LANG_PLI constant name (was DW_LANG_PL1).
+
+readelf: Add optional --symbols[=SECTION] argument to select section name.
+
+Version 0.167 "disassemble this!"
+
+libasm: Add eBPF disassembler for EM_BPF files.
+
+backends: Add m68k and BPF backends.
+
+ld: Removed.
+
+dwelf: Add ELF/DWARF string table creation functions. dwelf_strtab_init,
+       dwelf_strtab_add, dwelf_strtab_add_len, dwelf_strtab_finalize,
+       dwelf_strent_off, dwelf_strent_str and dwelf_strtab_free.
+
+Version 0.166 "bugs be gone!"
+
+config: The default program prefix for the installed tools is now eu-.
+        Use configure --program-prefix="" to not use a program prefix.
+
+Version 0.165 "big DWARF & tiny ELF"
+
+elfcompress: New utility to compress or decompress ELF sections.
+
+readelf: Add -z,--decompress option.
+
+libelf: Add elf_compress, elf_compress_gnu, elf32_getchdr, elf64_getchdr
+        and gelf_getchdr.
+
+libdwelf: New function dwelf_scn_gnu_compressed_size.
+
+config: Add libelf and libdw pkg-config files.
+
+backends: sparc support for core and live backtraces.
+
+translations: Updated Polish translation.
+
+Version 0.164 "strip, no unstrip!"
+
+strip, unstrip: Handle ELF files with merged strtab/shstrtab tables.
+                Handle missing SHF_INFO_LINK section flags.
+
+libelf: Use int64_t for offsets in libelf.h instead of loff_t.
+
+libdw: dwarf.h Add preliminary DWARF5 DW_LANG_Haskell.
+
+libdwfl: dwfl_standard_find_debuginfo now searches any subdir of the binary
+         path under the debuginfo root when the separate debug file couldn't
+         be found by build-id.
+         dwfl_linux_proc_attach can now be called before any Dwfl_Modules
+         have been reported.
+
+backends: Better sparc and sparc64 support.
+
+translations: Updated Ukrainian translation.
+
+Provide default-yama-scope subpackage.
+
+Version 0.163 "size matters"
+
+Bug fixes only, no new features.
+
+Version 0.162 "hard hat"
+
+libdw: Install new header elfutils/known-dwarf.h.
+       dwarf.h Add preliminary DWARF5 constants DW_TAG_atomic_type,
+       DW_LANG_Fortran03, DW_LANG_Fortran08. dwarf_peel_type now also
+       handles DW_TAG_atomic_type.
+
+addr2line: Input addresses are now always interpreted as hexadecimal
+           numbers, never as octal or decimal numbers.
+           New option -a, --addresses to print address before each entry.
+           New option -C, --demangle to show demangled symbols.
+           New option --pretty-print to print all information on one line.
+
+ar: CVE-2014-9447 Directory traversal vulnerability in ar extraction.
+
+backends: x32 support.
+
+Version 0.161
+
+libdw: New function dwarf_peel_type. dwarf_aggregate_size now uses
+       dwarf_peel_type to also provide the sizes of qualified types.
+       dwarf_getmacros will now serve either of .debug_macro and
+       .debug_macinfo transparently.  New interfaces
+       dwarf_getmacros_off, dwarf_macro_getsrcfiles,
+       dwarf_macro_getparamcnt, and dwarf_macro_param are available
+       for more generalized inspection of macros and their parameters.
+       dwarf.h: Add DW_AT_GNU_deleted, DW_AT_noreturn, DW_LANG_C11,
+       DW_LANG_C_plus_plus_11 and DW_LANG_C_plus_plus_14.
+
+Version 0.160
+
+libdw: New functions dwarf_cu_getdwarf, dwarf_cu_die.
+       dwarf.h remove non-existing DW_TAG_mutable_type.
+
+libdwfl: Handle LZMA .ko.xz compressed kernel modules.
+
+unstrip: New option -F, --force to combining files even if some ELF headers
+         don't seem to match.
+
+backends: Handle ARM THUMB functions. Add support for ppc64le ELFv2 abi.
+
+Version 0.159
+
+stack: New option -d, --debugname to lookup DWARF debuginfo name for frame.
+       New option -i, --inlines to show inlined frames using DWARF debuginfo.
+
+libdwelf: New libdwelf.h header for libdw.so DWARF ELF Low-level Functions.
+          New function dwelf_elf_gnu_debuglink, dwelf_dwarf_gnu_debugaltlink,
+	  and dwelf_elf_gnu_build_id.
+
+libdw: Support for DWZ multifile forms DW_FORM_GNU_ref_alt and
+       DW_FORM_GNU_strp_alt is now enabled by default and no longer
+       experimental. Added new functions dwarf_getalt and dwarf_setalt
+       to get or set the alternative debug file used for the alt FORMs.
+       The dwfl_linux_proc_find_elf callback will now find ELF from
+       process memory for (deleted) files if the Dwfl has process state
+       attached.
+
+libdwfl: The dwfl_build_id_find_debuginfo and dwfl_standard_find_debuginfo
+         functions will now try to resolve and set the alternative debug file.
+
+backends: Add CFI unwinding for arm. Relies on .debug_frame.
+          Add arm process initial register state compatible mode to AARCH64.
+          Add aarch64 native and core unwind support.
+
+other: All separate elfutils-robustify patches have been merged.
+       CVE-2014-0172 Check overflow before calling malloc to uncompress data.
+
+Version 0.158
+
+libdwfl: dwfl_core_file_report has new parameter executable.
+         New functions dwfl_module_getsymtab_first_global,
+         dwfl_module_getsym_info and dwfl_module_addrinfo.
+         Added unwinder with type Dwfl_Thread_Callbacks, opaque types
+         Dwfl_Thread and Dwfl_Frame and functions dwfl_attach_state,
+         dwfl_pid, dwfl_thread_dwfl, dwfl_thread_tid, dwfl_frame_thread,
+         dwfl_thread_state_registers, dwfl_thread_state_register_pc,
+         dwfl_getthread_frames, dwfl_getthreads, dwfl_thread_getframes
+         and dwfl_frame_pc.
+
+addr2line: New option -x to show the section an address was found in.
+
+stack: New utility that uses the new unwinder for processes and cores.
+
+backends: Unwinder support for i386, x86_64, s390, s390x, ppc and ppc64.
+          aarch64 support.
+
+Version 0.157
+
+libdw: Add new functions dwarf_getlocations, dwarf_getlocation_attr
+       and dwarf_getlocation_die.
+
+readelf: Show contents of NT_SIGINFO and NT_FILE core notes.
+
+addr2line: Support -i, --inlines output option.
+
+backends: abi_cfi hook for arm, ppc and s390.
+
+Version 0.156
+
+lib: New macro COMPAT_VERSION_NEWPROTO.
+
+libdw: Handle GNU extension opcodes in dwarf_getlocation.
+
+libdwfl: Fix STB_GLOBAL over STB_WEAK preference in dwfl_module_addrsym.
+         Add minisymtab support.
+         Add parameter add_p_vaddr to dwfl_report_elf.
+         Use DT_DEBUG library search first.
+
+libebl: Handle new core note types in EBL.
+
+backends: Interpret NT_ARM_VFP.
+          Implement core file registers parsing for s390/s390x.
+
+readelf: Add --elf-section input option to inspect an embedded ELF file.
+         Add -U, --unresolved-address-offsets output control.
+         Add --debug-dump=decodedline support.
+         Accept version 8 .gdb_index section format.
+         Adjust output formatting width.
+         When highpc is in constant form print it also as address.
+         Display raw .debug_aranges. Use libdw only for decodedaranges.
+
+elflint: Add __bss_start__ to the list of allowed symbols.
+
+tests: Add configure --enable-valgrind option to run all tests under valgrind.
+       Enable automake parallel-tests for make check.
+
+translations: Updated Polish translation.
+
+Updates for Automake 1.13.
+
+Version 0.155
+
+libelf: elf*_xlatetomd now works for cross-endian ELF note data.
+        elf_getshdr now works consistently on non-mmaped ELF files after
+        calling elf_cntl(ELF_C_FDREAD).
+        Implement support for ar archives with 64-bit symbol table.
+
+libdw: dwarf.h corrected the DW_LANG_ObjC constant name (was DW_LANG_Objc).
+       Any existing sources using the old name will have to be updated.
+       Add DW_MACRO_GNU .debug_macro type encodings constants, DW_ATE_UTF
+       and DW_OP_GNU_parameter_ref to dwarf.h.
+       Experimental support for DWZ multifile forms DW_FORM_GNU_ref_alt
+       and DW_FORM_GNU_strp_alt.  Disabled by default.  Use configure
+       --enable-dwz to test it.
+
+readelf: Add .debug_macro parsing support.
+         Add .gdb_index version 7 parsing support.
+         Recognize DW_OP_GNU_parameter_ref.
+
+backends: Add support for Tilera TILE-Gx processor.
+
+translations: Updated Ukrainian translation.
+
+Version 0.154
+
+libelf: [g]elf[32|64]_offscn() do not match SHT_NOBITS sections at OFFSET.
+
+libdw: dwarf_highpc function now handles DWARF 4 DW_AT_high_pc constant form.
+       Fix bug using dwarf_next_unit to iterate over .debug_types.
+
+elflint: Now accepts gold linker produced executables.
+
+The license is now GPLv2/LGPLv3+ for the libraries and GPLv3+ for stand-alone
+programs. There is now also a formal CONTRIBUTING document describing how to
+submit patches.
+
+Version 0.153
+
+libdw: Support reading .zdebug_* DWARF sections compressed via zlib.
+
+libdwfl: Speed up dwfl_module_addrsym.
+
+nm: Support C++ demangling.
+
+ar: Support D modifier for "deterministic output" with no uid/gid/mtime info.
+    The U modifier is the inverse.
+    elfutils can be configured with the --enable-deterministic-archives
+    option to make the D behavior the default when U is not specified.
+
+ranlib: Support -D and -U flags with same meaning.
+
+readelf: Improve output of -wline. Add support for printing SDT elf notes.
+         Add printing of .gdb_index section.
+	 Support for typed DWARF stack, call_site and entry_value.
+
+strip: Add --reloc-debug-sections option.
+       Improved SHT_GROUP sections handling.
+
+Version 0.152
+
+Various build and warning nits fixed for newest GCC and Autoconf.
+
+libdwfl: Yet another prelink-related fix for another regression.
+	 Look for Linux kernel images in files named with compression suffixes.
+
+elfcmp: New flag --ignore-build-id to ignore differing build ID bits.
+	New flag -l/--verbose to print all differences.
+
+Version 0.151
+
+libdwfl: Fix for more prelink cases with separate debug file.
+
+strip: New flag --strip-sections to remove section headers entirely.
+
+Version 0.150
+
+libdw: Fix for handling huge .debug_aranges section.
+
+libdwfl: Fix for handling prelinked DSO with separate debug file.
+
+findtextrel: Fix diagnostics to work with usual section ordering.
+
+libebl: i386 backend fix for multi-register integer return value location.
+
+Version 0.149:
+
+libdw: Decode new DW_OP_GNU_implicit_pointer operation;
+       new function dwarf_getlocation_implicit_pointer.
+
+libdwfl: New function dwfl_dwarf_line.
+
+addr2line: New flag -F/--flags to print more DWARF line information details.
+
+strip: -g recognizes .gdb_index as a debugging section.
+
+Version 0.148:
+
+libdw: Accept DWARF 4 format: new functions dwarf_next_unit, dwarf_offdie_types.
+       New functions dwarf_lineisa, dwarf_linediscriminator, dwarf_lineop_index.
+
+libdwfl: Fixes in core-file handling, support cores from PIEs.
+	 When working from build IDs, don't open a named file that mismatches.
+
+readelf: Handle DWARF 4 formats.
+
+Version 0.147:
+
+libdw: Fixes in CFI handling, best possible handling of bogus CFA ops.
+
+libdwfl: Ignore R_*_NONE relocs, works around old (binutils) ld -r bugs.
+
+Version 0.146:
+
+libdwfl: New function dwfl_core_file_report.
+
+Version 0.145:
+
+Fix build with --disable-dependency-tracking.
+
+Fix build with most recent glibc headers.
+
+libelf: More robust to bogus section headers.
+
+libdw: Fix CFI decoding.
+
+libdwfl: Fix address bias returned by CFI accessors.
+	 Fix core file module layout identification.
+
+readelf: Fix CFI decoding.
+
+Version 0.144:
+
+libelf: New function elf_getphdrnum.
+	Now support using more than 65536 program headers in a file.
+
+libdw: New function dwarf_aggregate_size for computing (constant) type
+       sizes, including array_type cases with nontrivial calculation.
+
+readelf: Don't give errors for missing info under -a.
+	 Handle Linux "VMCOREINFO" notes under -n.
+
+Version 0.143:
+
+libdw: Various convenience functions for individual attributes now use
+       dwarf_attr_integrate to look up indirect inherited attributes.
+       Location expression handling now supports DW_OP_implicit_value.
+
+libdwfl: Support automatic decompression of files in XZ format,
+	 and of Linux kernel images made with bzip2 or LZMA (as well as gzip).
+
+Version 0.142:
+
+libelf: Add elf_getshdrnum alias for elf_getshnum and elf_getshdrstrndx alias
+	for elf_getshstrndx and deprecate original names.  Sun screwed up
+	their implementation and asked for a solution.
+
+libebl: Add support for STB_GNU_UNIQUE.
+
+elflint: Add support for STB_GNU_UNIQUE.
+
+readelf: Add -N option, speeds up DWARF printing without address->name lookups.
+
+libdw: Add support for decoding DWARF CFI into location description form.
+       Handle some new DWARF 3 expression operations previously omitted.
+       Basic handling of some new encodings slated for DWARF 4.
+
+Version 0.141:
+
+libebl: sparc backend fixes;
+	some more arm backend support
+
+libdwfl: fix dwfl_module_build_id for prelinked DSO case;
+	 fixes in core file support;
+	 dwfl_module_getsym interface improved for non-address symbols
+
+strip: fix infinite loop on strange inputs with -f
+
+addr2line: take -j/--section=NAME option for binutils compatibility
+	   (same effect as '(NAME)0x123' syntax already supported)
+
+Version 0.140:
+
+libelf: Fix regression in creation of section header
+
+libdwfl: Less strict behavior if DWARF reader is just used to display data
+
+Version 0.139:
+
+libcpu: Add Intel SSE4 disassembler support
+
+readelf: Implement call frame information and exception handling dumping.
+	 Add -e option.  Enable it implicitly for -a.
+
+elflint: Check PT_GNU_EH_FRAME program header entry.
+
+libdwfl: Support automatic gzip/bzip2 decompression of ELF files.
+
+Version 0.138:
+
+Install <elfutils/version.h> header file for applications to use in source
+version compatibility checks.
+
+libebl: backend fixes for i386 TLS relocs; backend support for NT_386_IOPERM
+
+libcpu: disassembler fixes
+
+libdwfl: bug fixes
+
+libelf: bug fixes
+
+nm: bug fixes for handling corrupt input files
+
+Version 0.137:
+
+Minor fixes for unreleased 0.136 release.
+
+Version 0.136:
+
+libdwfl: bug fixes; new "segment" interfaces;
+	 all the libdwfl-based tools now support --core=COREFILE option
+
+Version 0.135:
+
+libdwfl: bug fixes
+
+strip: changed handling of ET_REL files wrt symbol tables and relocs
+
+Version 0.134:
+
+elflint: backend improvements for sparc, alpha
+
+libdwfl, libelf: bug fixes
+
+Version 0.133:
+
+readelf, elflint, libebl: SHT_GNU_ATTRIBUTE section handling (readelf -A)
+
+readelf: core note handling for NT_386_TLS, NT_PPC_SPE, Alpha NT_AUXV
+
+libdwfl: bug fixes and optimization in relocation handling
+
+elfcmp: bug fix for non-allocated section handling
+
+ld: implement newer features of binutils linker.
+
+Version 0.132:
+
+libcpu: Implement x86 and x86-64 disassembler.
+libasm: Add interface for disassembler.
+
+all programs: add debugging of branch prediction.
+
+libelf: new function elf_scnshndx.
+
+Version 0.131:
+
+libdw: DW_FORM_ref_addr support; dwarf_formref entry point now deprecated;
+       bug fixes for oddly-formatted DWARF
+
+libdwfl: bug fixes in offline archive support, symbol table handling;
+	 apply partial relocations for dwfl_module_address_section on ET_REL
+
+libebl: powerpc backend support for Altivec registers
+
+Version 0.130:
+
+readelf: -p option can take an argument like -x for one section,
+	 or no argument (as before) for all SHF_STRINGS sections;
+	 new option --archive-index (or -c);
+	 improved -n output for core files, on many machines
+
+libelf: new function elf_getdata_rawchunk, replaces gelf_rawchunk;
+	new functions gelf_getnote, gelf_getauxv, gelf_update_auxv
+
+readelf, elflint: handle SHT_NOTE sections without requiring phdrs
+
+elflint: stricter checks on debug sections
+
+libdwfl: new functions dwfl_build_id_find_elf, dwfl_build_id_find_debuginfo,
+	 dwfl_module_build_id, dwfl_module_report_build_id;
+	 support dynamic symbol tables found via phdrs;
+	 dwfl_standard_find_debuginfo now uses build IDs when available
+
+unstrip: new option --list (or -n)
+
+libebl: backend improvements for sparc, alpha, powerpc
+
+Version 0.129:
+
+readelf: new options --hex-dump (or -x), --strings (or -p)
+
+addr2line: new option --symbols (or -S)
+
+Version 0.128:
+
+new program: unstrip
+
+elfcmp: new option --hash-inexact
+
+Version 0.127:
+
+libdw: new function dwarf_getsrcdirs
+
+libdwfl: new functions dwfl_module_addrsym, dwfl_report_begin_add,
+	 dwfl_module_address_section
+
+Version 0.126:
+
+new program: ar
+
+Version 0.125:
+
+elflint: Compare DT_GNU_HASH tests.
+
+move archives into -static RPMs
+
+libelf, elflint: better support for core file handling
+
+Version 0.124:
+
+libebl: sparc backend support for return value location
+
+libebl, libdwfl: backend register name support extended with more info
+
+libelf, libdw: bug fixes for unaligned accesses on machines that care
+
+readelf, elflint: trivial bugs fixed
+
+Version 0.123:
+
+libebl: Backend build fixes, thanks to Stepan Kasal.
+
+libebl: ia64 backend support for register names, return value location
+
+libdwfl: Handle truncated linux kernel module section names.
+
+libdwfl: Look for linux kernel "vmlinux" files with ".debug" suffix.
+
+elflint: Fix checks to permit --hash-style=gnu format.
+
+Version 0.122:
+
+libebl: add function to test for relative relocation
+
+elflint: fix and extend DT_RELCOUNT/DT_RELACOUNT checks
+
+elflint, readelf: add support for DT_GNU_HASH
+libelf: add elf_gnu_hash
+
+elflint, readelf: add support for 64-bit SysV-style hash tables
+
+libdwfl: new functions dwfl_module_getsymtab, dwfl_module_getsym.
+
+Version 0.121:
+
+libelf: bug fixes for rewriting existing files when using mmap.
+
+make all installed headers usable in C++ code.
+
+readelf: better output format.
+
+elflint: fix tests of dynamic section content.
+
+ld: Implement --as-needed, --execstack, PT_GNU_STACK.  Many small patches.
+
+libdw, libdwfl: handle files without aranges info.
+
+Version 0.120:
+
+Bug fixes.
+
+dwarf.h updated for DWARF 3.0 final specification.
+
+libdwfl: New function dwfl_version.
+
+The license is now GPL for most files.  The libelf, libebl, libdw,
+and libdwfl libraries have additional exceptions.  Add reference to
+OIN.
+
+Version 0.119:
+
+bug fixes
+
+Version 0.118:
+
+elflint: more tests.
+
+libdwfl: New function dwfl_module_register_names.
+
+libebl: New backend hook for register names.
+
+Version 0.117:
+
+libdwfl: New function dwfl_module_return_value_location.
+
+libebl: Backend improvements for several CPUs.
+
+Version 0.116:
+
+libdw: New functions dwarf_ranges, dwarf_entrypc, dwarf_diecu,
+       dwarf_entry_breakpoints.  Removed Dwarf_Func type and functions
+       dwarf_func_name, dwarf_func_lowpc, dwarf_func_highpc,
+       dwarf_func_entrypc, dwarf_func_die; dwarf_getfuncs callback now uses
+       Dwarf_Die, and dwarf_func_file, dwarf_func_line, dwarf_func_col
+       replaced by dwarf_decl_file, dwarf_decl_line, dwarf_decl_column;
+       dwarf_func_inline, dwarf_func_inline_instances now take Dwarf_Die.
+       Type Dwarf_Loc renamed to Dwarf_Op; dwarf_getloclist,
+       dwarf_addrloclists renamed dwarf_getlocation, dwarf_getlocation_addr.
+
+Version 0.115:
+
+libelf: speed-ups of non-mmap reading.
+
+strings: New program.
+
+Implement --enable-gcov option for configure.
+
+libdw: New function dwarf_getscopes_die.
+
+Version 0.114:
+
+libelf: new function elf_getaroff
+
+libdw: Added dwarf_func_die, dwarf_func_inline, dwarf_func_inline_instances.
+
+libdwfl: New functions dwfl_report_offline, dwfl_offline_section_address,
+	 dwfl_linux_kernel_report_offline.
+
+ranlib: new program
+
+Version 0.113:
+
+elflint: relax a bit. Allow version definitions for defined symbols against
+DSO versions also for symbols in nobits sections.  Allow .rodata section
+to have STRINGS and MERGE flag set.
+
+strip: add some more compatibility with binutils.
+
+Version 0.112:
+
+elfcmp: some more relaxation.
+
+elflint: many more tests, especially regarding to symbol versioning.
+
+libelf: Add elfXX_offscn and gelf_offscn.
+
+libasm: asm_begin interface changes.
+
+libebl: Add three new interfaces to directly access machine, class, and
+data encoding information.
+
+objdump: New program.  Just the beginning.
+
+Version 0.111:
+
+libdw: now contains all of libdwfl.  The latter is not installed anymore.
+
+elfcmp: little usability tweak, name and index of differing section is printed.
+
+Version 0.110:
+
+libelf: fix a number of problems with elf_update
+
+elfcmp: fix a few bugs.  Compare gaps.
+
+Fix a few PLT problems and mudflap build issues.
+
+libebl: Don't expose Ebl structure definition in libebl.h.  It's now private.
+
+Version 0.109:
+
+libebl: Check for matching modules.
+
+elflint: Check that copy relocations only happen for OBJECT or NOTYPE symbols.
+
+elfcmp: New program.
+
+libdwfl: New library.
+
+Version 0.108:
+
+strip: fix bug introduced in last change
+
+libdw: records returned by dwarf_getsrclines are now sorted by address
+
+Version 0.107:
+
+readelf: improve DWARF output format
+
+strip: support Linux kernel modules
+
+Version 0.106:
+
+libdw: Updated dwarf.h from DWARF3 spec
+libdw: add new functions dwarf_func_entrypc, dwarf_func_file, dwarf_func_line,
+dwarf_func_col, dwarf_getsrc_file
+
+Version 0.105:
+
+addr2line: New program
+
+libdw: add new functions: dwarf_addrdie, dwarf_macro_*, dwarf_getfuncs,
+dwarf_func_*.
+
+findtextrel: use dwarf_addrdie
+
+Version 0.104:
+
+findtextrel: New program.
+
+Version 0.103:
+
+libdw: Fix using libdw.h with gcc < 4 and C++ code.  Compiler bug.
+
+Version 0.102:
+
+More Makefile and spec file cleanups.
+
+Version 0.101:
+
+Remove most gettext autoconf handling.
+
+Add more warnings
+
+Fix resulting problems.  One actual bug found and fixed this way
+
+Version 0.100:
+
+libebl: Fix x86-64 relocations.
+
+Add -Wunused -Wextra warnings.
+
+Some cleanups resulting from those additional warnings.
+
+Lots of Makefile cleanup.
+
+Version 0.99:
+
+libelf: add gelf_checksum prototype to <libelf.h>
+
+libelf: fix elf*_checksum handling of NOBITS sections
+
+Finish mudflap support.
+
+Fix three bugs found by mudflap.
+
+ld: add as_needed support
+
+Version 0.98:
+
+readelf: in section to segment mapping, indicate read-only sections.
+
+elflint: more relaxation for GNU ld
+
+Version 0.97:
+
+Fix compiling with gcc 4.0.
+Some tests called elflint without appropriate LD_LIBRARY_PATH.
+
+Version 0.96:
+
+Fix support for platforms with lib64.
+
+Version 0.95:
+
+libebl: add ppc and ppc64 support
+
+readelf: fix minimal memory leak.
+
+Add support to compile with mudflap.
+
+Modernize configure.ac.  Move scripts in config subdir.
+
+Modernize *-po directory infrastructure.
+
+libelf: Add gelf_getlib and gelf_update_lib
+
+readelf: print liblist sections
+
+Version 0.94:
+
+Fix some minimal build problems.
+
+Version 0.93:
+
+ibdw: tons of new functionality and bug fixes.  Several interface changes.
+
+readelf: use libdw now.
+
+libdwarf: removed completely.
+
+Version 0.92:
+
+configuration changes.
+
+Version 0.91:
+
+libdw: fix memory handling.  Implement source line handling.
+nm: use libdw instead of libdwarf.
+libelf: change to GPL from OSL1 for now.
+
+Version 0.90:
+
+libebl: Recognize a few more section types and dynamic tags and return
+appropriate strings.
+
+Version 0.89:
+
+strip: fix overwriting of symbol table in input file.
+
+Version 0.88:
+
+libebl: Add some ia64 bits.
+
+Version 0.87:
+
+Bug fixes for big endian and some 64-bit machines.
+
+Version 0.86:
+
+strip: fix handling of Alpha and s390x which use incorrect hash bucket sizes.
+
+ld: tons of changes, moving towards usability.
+
+Version 0.85:
+
+strip: update section group symbol index if the associated symbol table changed
+
+libelf: fix two problems with generating output not via mmap
+
+elflint: add probably 10-15 more tests
+libebl: add support for some of the new tests
+
+ld: gazillion changes
+
+Version 0.84:
+
+elflint: deal with .rel.dyn section.  Fix a problem with rela platforms.
+Handle PT_GNU_STACK.  Change to write messages to stdout.
+
+readelf: fix a problem with version information in the symbol table output.
+
+strip: update all version symbol table entries
+
+Version 0.83:
+
+size: fix a warning
+
+strip: last changed caused problems when the symbol table is before the
+relocation section.  Fixed.  This fix also improved the asymptotic
+behavior if many symbol table sections are present.
+
+Version 0.82:
+
+Run strip tests with the correct libelf and libebl.
+
+libelf: fix bug in verneed byte order changing code.
+
+Version 0.81:
+
+strip: Remove unused symbol table entries.  This might require updating
+various other sections.
+
+Version 0.80:
+
+Fix some libelf problems with ET_REL files.
+
+Version 0.79:
+
+More warning changes, mainly by jbj.
+
+libdw: yet more new code.  dwarf_child and dwarf_sibling should now actually
+work.
+
+Version 0.78:
+
+libdw: 10+ new functions.  get-pubnames2 works now fully.  Almost all the
+code needed for nm is in place.
+
+Version 0.77:
+
+cleanups to compile cleanly with gcc 3.3 and -Werror.
+
+libdw: some new code.
+
+Version 0.76:
+
+libebl: Fix last patch to recognize relocation sections.   We must not
+use the name.
+
+Version 0.75:
+
+libebl: .debug_ranges is a DWARF 3 debug section
+libebl: recognize relocation sections for debug section
+Patches by Jakub Jelinek.
+
+Version 0.74:
+
+Cleanups and more SPARC support by Tom Callaway <tcallaway@redhat.com>.
+
+Version 0.73:
+
+64-bit cleanups for the programs.
+
+Version 0.72:
+
+libelf: and yet more fun with endian transformation at output time.
+
+Version 0.71:
+
+libelf: more fun with endian transformation at output time.  Add test for it.
+
+Version 0.70:
+
+libelf: Two little bugs left from previous patch to handle section output
+order.
+
+libelf: add unlikely in some more places.
+
+Version 0.69:
+
+libelf: fix output routines to handle case where section indices and
+ordre in the output file don't match correctly.  Patch by Jakub.
+
+elflint: fix test of note section content for 64-bit platforms and files
+with different byte order.
+
+Version 0.68:
+
+libebl: Fix SH_ENTSIZE_HASH definition (patch by Jakub)
+
+Version 0.67:
+
+libelf: correct mistake in error string handling.
+
+libelf: Implement ELF_F_PERMISSIVE.
+strip: Implement --permissive option.
+
+Version 0.66:
+
+strip: Implement -g option.
+
+libelf: Handle broken hash table entry sizes.
+
+libebl: New function ebl_debugscn_p.  Use it where appropriate.
+
+Version 0.65:
+
+libelf: Use correct file size for NOBITS section with ELF_F_LAYOUT set
+
+Version 0.64:
+
+libelf: Make error handling more robust.
+libelf: Use TLS in error handler if configured with --enable-tls
+
+tests: input files are now distributed, not uuencoded in the shell scripts
+
+libdw: implement error handling, dwarf_get_pubnames
+
+Version 0.63:
+
+Build (incomplete) libdw.
+
+Version 0.62:
+
+Get rid of libtool.
+
+Version 0.61:
+
+Fix URL of OSL.
+
+Version 0.60:
+
+libebl: Handle .gnu.warning.* sections correctly.
+
+size: Implement -t option.
+
+libebl: Add IA-64 support.
+libebl: Update SH relocations.
+libebl: Add Alpha support.
+libebl: Add Arm support.
+libebl: Add support for all currently known architecture to the loader.
+
+Version 0.59:
+
+nm: Implement -S option.  Correct portable output format.  Implement -s option.
+
+libelf: Take offset of archive into account in elf_rand.
+
+Version 0.58:
+
+strip: fix handling of ET_REL files.
+Add tests for strip.
+
+Version 0.57:
+
+strip: respect layout of input file
+
+Version 0.56:
+
+strip: handle files with large number of sections.
+
+Version 0.55:
+
+libelf: quite a few bug fixes by Alex Larsson.
+
+strip: implement -f option to place stripped sections into a separate
+file.  By Alex Larsson.
+
+Version 0.54:
+
+strip: don't let STT_SECTION symbols keeps sections from being removed
+
+elflint: local symbols are allowed in .dynsym
+elflint: special case .rel.dyn a bit
+
+Version 0.53:
+
+elflint: check types and flags of special sections defined in gABI
+
+libebl: add x86-64 support
+
+Version 0.52:
+
+Start improvement of debug info handling in nm.
+
+libasm: implement asm_adduleb128 and asm_addsleb128 and a test for them
+
+Version 0.51:
+
+Fix build on 64-bit platforms.
+
+Version 0.50:
+
+nm: print file/line number also for local symbols
+
+use versions scripts not libtool's useless -export-symbols option
+
+Version 0.49:
+
+Update to autoconf 2.54 and automake 1.7.
+
+elflint: check note sections
+
+libdwarf: a number of bug fixes
+
+readelf: print .debug_info section content
+
+dwarf.h: Update from draft 7
+
+Version 0.48:
+
+libcpu: beginning
+
+libelf: new function to read parts of the ELF file
+
+libebl: support for note section handling
+
+readelf: dump note sections
+
+Version 0.47:
+
+libelf: fix little new section-handling related bugs in elf_getshstrndx
+and elf_nextscn
+
+elflint: tests for mandatory content of dynamic section
+
+libasm: better handling of absolute symbols
+
+Version 0.46:
+
+libasm: rewrite to store Elf_Scn* instead of indices
+
+nm: finish many-section support
+
+nm: use debug in to print file/line info in sysv format
+
+libdwarf: fix a few bugs in DIE handling
+
+Version 0.45:
+
+libelf: major rewrite to keep Elf_Scn references valid until elf_end
+
+Version 0.44:
+
+libasm: Add support for bss, ABS, and COM sections.
+
+libebl: ebl_section_name takes now two index arguments to distinguish
+between special sections and extended sections
+
+Version 0.43:
+
+General: fix a few problem gcc 3.1 had with the code.
+
+libelf: implement {gelf,elf32,elf64}_checksum
+
+libelf: optimize DSO: fewer relocations, fewer PLTs
+
+add msg_tst test
+
+ld: use correct section header string table index; write correct index
+
+add dependencies for *.sym files
+
+Version 0.42:
+
+libelf: add elf_getshnum and elf_getshstrndx
+
+libebl: update section type name function
+
+elflint: tons of fixes wrt large number of sections.  New tests in this area.
+Same amount of other bug fixes.
+
+size, strip, nm: better support for large number of sections.  Including
+using correct section header string table
+
+libasm: correctly create data structures for large number of sections
+
+new tests asm-tst4 and asm-tst5 to check large number of sections
+
+libasm: implement section group generation
+
+elflint: more tests on section groups.  Improve performance on existing
+section group tests
+
+Version 0.41:
+
+ld: add undefined symbols to dynamic symbol table if --export-dynamic is
+not given
+
+ld: fix value of e_entry
+
+Version 0.40:
+
+elflint: print section names in error messages
+
+elflint: mustn't warn about multiple DT_NULL
+
+ld: don't emit all symbols if --export-dynamic is not given
+
+ld: correct compute symbol address in output file (section index was off by 1)
+
+ld: generate correct version info in dynsym without --export-dynamic and
+in symtab
+
+Version 0.39:
+
+Fix check of various e_*size entries in elflint.
+
+Handle text output in asm_newsym.
+
+Finish checks in asm-tst3.
+
+Version 0.38:
+
+Update to autoconf 2.53, automake 1.6, gettext 0.11+.
+
+Introduce *.sym files to restrict export from DSOs.
+
+Use attribute_hidden and internal_function to optimize DSO code.
+
+Add TLS definitions in elf.h and handle them in readelf.
+
+Fix bug in verdef section generation in ld.
+
+Add initial libasm code.
+
+Version 0.37:
+
+Implement better hash size optimization heuristic in ld.  It uses a formula
+taking number of tests into account.
+
+Lots of small bug fixes.
+
+Improve readelf output format.  Respect various sh_link/sh_info values.
+Correctly print versioning information for symbol tables.
+
+Version 0.36:
+
+Implement preprocessing of linker script.  Recognize -z combreloc.
+
+Version 0.35:
+
+Implement -z ignore|record for ld.
+
+Implement creating of .gnu.version_r and .gnu.version sections.  The
+.gnu.version does not yet contain correct info for defined and versioned
+symbols (means .gnu.version_d is not yet implemented).
+
+Implement gelf_update_* functions to create versioning data.
+
+Version 0.34:
+
+Add DT_RUNPATH/DT_RPATH entries to dynamic section.  Create .plt and
+.rel.plt sections (completely).  Add support for all four PLT related
+dynamic section entries.  Add callback function for PLT creation.
+
+More tests in elflint.  Add support for very strict checking which for
+now flags level 2 (deprecated features) usage.
+
+Version 0.33:
+
+Create dynamic symbol table, dynamic string table, and hash table to ld.
+
+Add hash table histogram support to readelf.
+
+Version 0.32:
+
+more work on elflint
+
+ld now creates the dynamic section and references it.  Start adding entries
+to dynamic section.
+
+Version 0.31:
+
+Start implementing elflint.
+
+Version 0.30:
+
+Fix handling of NOBITS sections in elf_getdata.
+
+Start implementing generation of executables and DSOs in ld.
+Generation of program header mostly done.  Address computation done.
+Extension of linker script syntax.
+
+Various cleanups.
+
+Implement section group handling in readelf.
+
+Version 0.29:
+
+Implement section groups.  This involved a lot of code moving.  The
+new code is entirely untested since gas/gcc are currently not able to
+create section groups.  ld works fine on files without section groups.
+
+Version 0.28:
+
+Fix problem with adding more section in elf_newscn.  The section pointers
+for the data buffers wasn't adjusted.
+
+Fix elf_getdata with nonzero second parameter.  Correctly handle creation
+of internal data buffer for machines without unaligned access.
+
+Version 0.27:
+
+Start adding support to selectively add sections.  Includes support for
+section groups.
+Add --gc-sections/--no-gc-sections options.
+Add general section merging support.
+
+Fix a bug in section group support in strip.
+
+Fix some potential problems with hash value in dynamic hash implementation.
+
+Version 0.26:
+
+section merging works in ld.
+
+Version 0.25:
+
+Actually create data structures from version map file and use it to hide
+symbols in ld.
+
+Implement -s -s for ld.
+
+Version 0.24:
+
+Improve relocation table output in readelf.  Avoid some crashes.
+Finish many section handling in readelf.
+
+Finish: finish implementation of ld -r.  At least some simple tests pass.
+
+Version 0.23:
+
+Fix a number of errors in ELF_C_WRITE handling.
+
+Almost finished implementation of ld -r.  The data sections are all copied.
+Handling of symbol tables is missing.
+
+Version 0.22:
+
+Handle DSO and archive input files correctly if -r option is given.
+
+Gracefully deal with no phdr in new file in libelf.
+Fix various small error handling problems.
+Don't mmap file for output unless the command says so.
+
+Add code to create ELF section header table to ld finalize routines.
+
+Version 0.21:
+
+Fix some problems with recursive handling of archives in libelf.
+
+Improve messages printed by nm.
+
+Add symbol binding name handling to libebl.  Fix section name handling in
+libebl.
+
+readelf and nm use more libebl functions.
+
+Handle XINDEX correctly in nm and string.
+
+Add first machine ld backend library (i386).
+Use it.  Recognize -r and --shared.  Avoid using -lxxx parameters for -r.
+Create ELF header in output file.  Change mode of output file according to
+output file type.  Reorganize callback initialization in ld.
+
+Version 0.20:
+
+Fix some memory leaks in libelf.
+
+Version 0.19:
+
+Implement reading version script.  Both inside linker scripts and via the
+--version-script command line parameter.  Uses the same code.
+What remains to be done is to implement a data structure which allows
+efficient matching against the version names to decide which pattern
+matches.
+
+Beginning of output generation and output writing functions.
+
+Version 0.18:
+
+Finish implementation for DSO input file handling.  Implement rpath, runpath,
+and LD_LIBRARY_PATH handling.
+
+Version 0.17:
+
+make handling of e_shnum overflow in libelf standard conforming
+
+ld now actually can handle DSOs in linker scripts.  Handling of DT_RUNPATH,
+DT_RPATH, -rpath, -rpath-link still remains to be implemented.
+
+fix handling of -L parameters.  Make actual use of the default_paths element.
+
+make re-definition of symbols in and from DSO compatible with existing linker
+
+Version 0.16:
+
+more work on assigning input sections to output sections.
+
+Add gelf_xlatetof and gelf_xlatetom which were accidentally left out.
+
+Fix memory handling of section headers.
+
+Version 0.15:
+
+Add many-section support to ld.  Add various new command line parameters.
+Allow pagesize to be specified in linker script or on the command line.
+Collect input sections in list for the output section according to the rules
+specified in the linker script.
+
+Version 0.14:
+
+Fix some problems in the internal list handling which had the result
+that we didn't look for some of the unresolved symbols.
+
+Free some memory if we know we don't need it anymore.
+
+Optimize the list of unresolved symbols.  Throw out symbols which are
+meanwhile resolved.
+
+Version 0.13:
+
+Got file reading correct now.  The files are all read while parsing
+the parameters.  No creating of data structures to describe the linker
+command line.  The symbol table is built up while reading the files.
+DSOs are handled now.  -( -) handling is optimized.
+
+Version 0.12:
+
+Linker read linker scripts everywhere.  Handles --whole-archive.  Recognizes
+--dynamic and --static.  Collects defined and undefined symbols.  Recognizes
+conflicts.
+
+libebl now defines functions to call the callbacks.  Add generic name handling
+in these new functions.  Remove the code from readelf and call the new
+functions.
+
+Version 0.11:
+
+Start of linker.  Basic argument parsing, finding of input files,
+linker script reading.
+
+Version 0.10:
+
+Implement dwarf_get_fde_n(), dwarf_get_abbrev(), dwarf_get_abbrev_tag(),
+dwarf_get_abbrev_code(), dwarf_get_abbrev_children_flag(),
+dwarf_get_abbrev_entry(), dwarf_get_fde_at_pc(), and tests for it.
+
+Version 0.9:
+
+Implement dwarf_get_fde_list_eh(), dwarf_get_cie_of_fde(),
+dwarf_get_fde_range(), dwarf_get_cie_info(), dwarf_get_fde_instr_bytes(),
+and tests for them.
+
+Version 0.8:
+
+Make handling of binaries in other byte order work and add tests for it.
+
+Version 0.7:
+
+Implement dwarf_get_aranges(), dwarf_get_arange(), dwarf_get_cu_die_offset(),
+dwarf_get_arange_info(), and tests for them.
+
+Version 0.6:
+
+Implement dwarf_get_global(), dwarf_globname(), dwarf_global_die_offset(),
+dwarf_global_cu_offset(), dwarf_global_name_offsets(), and tests for them
+
+Version 0.5:
+
+Implemented dwarf_srclines(), dwarf_srcfiles(), dwarf_linebeginstatement(),
+dwarf_lineendsequence(), dwarf_lineno(), dwarf_lineaddr(), dwarf_lineoff(),
+dwarf_linesrc(), dwarf_lineblock(), dwarf_lineprologueend(),
+dwarf_lineepiloguebegin(), and tests for them.
+
+Version 0.4:
+
+Implemented dwarf_loclist().
+
+Version 0.3:
+
+Implemented dwarf_dieoffset(), dwarf_die_CU_offset(), dwarf_diename() and
+tests.
+
+Implemented dwarf_attrlist(), dwarf_hasattr(), dwarf_attr(), dwarf_lowpc(),
+dwarf_highpc(), dwarf_bytesize(), dwarf_bitsize(), dwarf_bitoffset(),
+dwarf_srclang(), dwarf_arrayorder(), dwarf_hasform(), dwarf_whatform(),
+dwarf_whatattr(), dwarf_formref(), dwarf_global_formref(), dwarf_formaddr(),
+dwarf_formflag(), dwarf_formudata(), dwarf_formsdata(), dwarf_formblock,
+dwarf_formstring() and tests for them.
+
+Version 0.2:
+
+Implemented dwarf_offdie()), dwarf_tag(), dwarf_dieoffset(),
+dwarf_die_CU_offset(), dwarf_diename() and tests for them.
+
+Version 0.1:
+
+First libdwarf functions work.
+
+Version 0.0:
+
+libelf and parts of libebl are done.
diff --git a/NOTES b/NOTES
new file mode 100644
index 0000000..deae643
--- /dev/null
+++ b/NOTES
@@ -0,0 +1,95 @@
+Fundamental design decision:
+
+- the sizes of external and internal types are assumed to be the same.
+  This leaves byte ordering aside.  While assuming this the code can be
+  greatly simplified and speed increases.  Since no change violating this
+  assumption is in sight this is believed to be a worthwhile optimization.
+
+- the ABI of the backend modules is not guaranteed.  Really, no guarantee
+  whatsoever.  We are enforcing this in the code.  The modules and their
+  users must match.  No third-party EBL module are supported or allowed.
+  The only reason there are separate modules is to not have the code for
+  all architectures in all the binaries.
+
+- although the public libraries (libasm, libdw) have a stable API and are
+  backwards ABI compatible they, and the elfutils tools, do depend on each
+  others internals, and on internals of libelf to provide their interfaces.
+  So they should always be upgraded in lockstep when packaging the tools
+  and libraries separately. For one example of how to do that, see the
+  config/elfutils.spec.
+
+Some notes:
+
+- old GNU ld's behavior wrt DSOs seems to be severely broken.
+
+     y.o reference foo()
+     y1.o defines foo(), references bar()
+     y2.o defines bar()
+     libbar.so defines bar()
+
+  Running
+
+     gcc -o y y.o -lbar y1.o y2.o
+
+  uses the bar() definition from libbar.so and does not mention the definition
+  in y2.o at all (no duplicate symbol message).  Correct is to use the
+  definition in y2.o.
+
+
+     y.o reference foo()
+     y1.o defines foo(), references bar()
+     y2.o in liby2.a defines bar()
+     libbar.so defines bar()
+
+  Running
+
+     gcc -o y y.o -lbar y1.o -ly3
+
+  has to use the definition in -lbar and not pull the definition from liby3.a.
+
+
+- the old linker follows DT_NEEDED entries and adds the objects referenced
+  this way which define a symbol which is needed as a DT_NEEDED to the
+  generated binary.  This is wrong since the DT_NEEDED changes the search
+  path in the object (which is breadth first).
+
+
+- the old linker supported extern "C++", extern "java" in version scripts.
+  I believe this implementation is severely broken and needs a redesign
+  (how do wildcards work with these languages*?).  Therefore it is left
+  out for now.
+
+
+- what should happen if two sections in different files with the same
+  name have different types and/or the flags are different
+
+
+- section names in input files are mostly irrelevant.  Exceptions:
+
+  .comment/SHT_PROGBITS		in strip, ld
+
+  .debug		\
+  .line			|
+  .debug_srcinfo	|
+  .debug_sfnames	|
+  .debug_aranges	|
+  .debug_pubnames	|
+  .debug_info		|
+  .debug_abbrev		|
+  .debug_line		|
+  .debug_abbrev		 >	DWARF sections in ld
+  .debug_line		|
+  .debug_frame		|
+  .debug_str		|
+  .debug_loc		|
+  .debug_macinfo	|
+  .debug_weaknames	|
+  .debug_funcnames	|
+  .debug_typenames	|
+  .debug_varnames	/
+
+  Sections created in output files follow the naming of special section
+  from the gABI.
+
+  In no place is a section solely identified by its name.  Internal
+  references always use the section index.
diff --git a/README b/README
new file mode 100644
index 0000000..690febd
--- /dev/null
+++ b/README
@@ -0,0 +1,33 @@
+The elfutils project provides libraries and tools for ELF files and DWARF data.
+
+The project home is http://elfutils.org/
+
+Releases are published at ftp://sourceware.org/pub/elfutils/
+Which can also be found at https://sourceware.org/elfutils/ftp/
+
+To build a release do: ./configure && make && make check
+Please check the configure summary to make sure all recommended
+features are enabled. There should be no failures after make check.
+
+Please reports bugs at https://sourceware.org/bugzilla/
+
+The current elfutils source code can be checked out with
+git clone git://sourceware.org/git/elfutils.git
+
+To build a git checkout do:
+  autoreconf -i -f && \
+  ./configure --enable-maintainer-mode && \
+  make && make check
+
+The developer mailinglist to send patches to is
+elfutils-devel@sourceware.org.
+https://sourceware.org/ml/elfutils-devel/
+
+To subscribe send an email to elfutils-devel-subscribe@sourceware.org
+Or use the form at https://sourceware.org/mailman/listinfo/elfutils-devel
+
+See the CONTRIBUTING file for how to propose patches to the code.
+
+See the NOTES files for some design decisions and notes.
+
+See the SECURITY file for defining and handling security-sensitive bugs.
diff --git a/SECURITY b/SECURITY
new file mode 100644
index 0000000..677802c
--- /dev/null
+++ b/SECURITY
@@ -0,0 +1,56 @@
+
+The elfutils library and utilities aim to be generally robust and
+reliable.  However, elfutils routinely processes complex binary
+structured data.  This makes the code intricate and sometimes brittle.
+While elfutils developers use a variety of static and dynamic checker
+software (valgrind, sanitizers) in testing, bugs may remain.  Some of
+these bugs may have security-related implications.
+
+
+While many errors are cleanly detected at runtime, it is possible that
+vulnerabilities exist that could be exploitable.  These may arise from
+crafted / fuzzed / erroneous inputs, or perhaps even from valid inputs
+with unforseen characteristics.  Therefore, to minimize risks, users
+of elfutils tools and libraries should consider measures such as:
+
+- avoiding running complex elfutils analysis on untrustworthy inputs
+- avoiding running elfutils tools as privileged processes
+- applying common platform level protection mechanisms such as
+  selinux, syscall filtering, hardened compilation, etc.
+
+Since most elfutils tools are run in short-lived, local, interactive,
+development context rather than remotely "in production", we generally
+treat malfunctions as ordinary bugs rather than security vulnerabilities.
+
+
+Elfutils includes one network client/server: debuginfod.  The
+debuginfod man page contains a SECURITY section outlining the general
+risks.  tl;dr: many classes of server problems are delegated to
+front-end proxies and curated elf/dwarf archives of the operator;
+others to careful configuration of the debuginfod client.  These are
+not generally reportable as security vulnerabilities.  However, we are
+likely to accept security vulnerability reports related to:
+
+- availability: e.g., remotely exploitable server crash, but not
+  routine resource exhaustion or overload; client crash due to
+    unexpected valid traffic from trusted server
+
+- confidentiality: e.g., allowing the server to expose one client's
+  traffic to another client
+
+- integrity: e.g., causing the server to send erroneous
+  elf/dwarf/source data across the webapi; causing the client to
+    corrupt its cache to lose file integrity
+
+We welcome reports that are tangential to any of these subjects.
+
+Please report bugs via any of:
+- email to <elfutils-devel@sourceware.org>
+- https://sourceware.org/bugzilla/enter_bug.cgi?product=elfutils
+
+After considering the above exclusions, please report suspected
+security vulnerabilities confidentially via any of:
+
+- email to <mark@klomp.org>
+- email to <fche@elastic.org>
+- email to <secalert@redhat.com>
diff --git a/THANKS b/THANKS
new file mode 100644
index 0000000..887c067
--- /dev/null
+++ b/THANKS
@@ -0,0 +1,6 @@
+At least the following have submitted valuable patches:
+
+Jeff Johnson		building. rpm wrestling
+Alexander Larsson	separate debug info
+Jakub Jelinek		bug fixes, testing
+Denys Vlasenko		bug fuxes
diff --git a/TODO b/TODO
new file mode 100644
index 0000000..5ed5e21
--- /dev/null
+++ b/TODO
@@ -0,0 +1,195 @@
+		      ToDo list for elfutils                      -*-outline-*-
+                      ----------------------
+
+Time-stamp: <2009-02-05 22:08:01 drepper>
+
+* mkinstalldirs
+
+  Remove everywhere.  Use mkdir -p.
+
+* libelf:
+
+** verify section
+
+   Currently the elf_update function trusts the user blindly if the
+   ELF_F_LAYOUT flag is set.  This is OK if the data is prepared by a
+   ELF_C_NULL call but not if the user prepared the data herself
+
+** break out archive handling from elf_begin
+
+   The handling of archives (especially of the symbol tables) must be
+   broken out of elf_begin.  There are several different forms of
+   archives and only when having the archive handling separately this
+   remains maintainable.
+
+** shdrs in read-only files
+
+   When reading (ELF_C_READ*) then there is no need to malloc Shdr
+   structure in elfXX_getshdr if file is mmaped and unaligned access
+   is allowed or the structure is aligned.  Use ELF_F_MALLOCED flag
+   to differentiate.
+
+** shdrs after elf_cntl (ELF_C_FDREAD)
+
+   Similar to the above. After ELF_C_FDREAD the file is completely
+   in memory.  See also this mailing list thread:
+   https://fedorahosted.org/pipermail/elfutils-devel/2012-July/002368.html
+
+* libdw
+
+** More memory access checks needed
+
+   All accesses to the debug sections should make sure the offsets are
+   valid.  This is currently especially a problem with leb128 accesses.
+
+** Low level macro information operations
+
+   in 5.11.3 are not implemented.  gcc currently does not emit this
+   information so I cannot test it.
+
+** Rename dwarf_getabbrev
+
+
+* libcpu
+
+** x86
+
+*** Opcodes
+
+     crc32
+     extractps
+     pextrb
+     pextrd/pextrq
+     pextrw
+     pinsrq
+     popcnt 64-bit reg
+
+* nm:
+
+** add demangler support
+
+   Use demangler from libiberty.
+
+** add support to read debugging symbols
+
+   Implement -l option for BSD and POSIX format
+
+
+* strip:
+
+** support SHT_SYMTAB_SHNDX
+
+   should be removed if not needed anymore
+
+* ld:
+
+** sanity check .rel sh_info content
+
+   the sh_info of all .rel sections with the same name must point to
+   sections which also have the same name
+
+** use ld.so.conf
+
+   to locate shared libraries also use /etc/ld.so.conf
+
+** handle object files for different architectures
+
+   ld.so is expected to ignore object files for different architectures and
+   continue looking for a matching file (e.g., ignore 32-bit binaries on
+   64-bit platforms and vice versa).  We probably need the same in ld.
+
+** reuse after elf_end
+
+   Some files are closed using elf_end.  They are removed from memory only
+   if no reference is left (especially for archives this is a problem).
+   The old mapping should be reused in that case.  The problem is worse
+   for files which are not mapped read-only (archives again).
+
+** size for STT_SECTION entries
+
+   The STT_SECTION entries have zero for the size but can easily get
+   the size of the section.
+
+** .eh_frame_hdr
+
+   Not implemented at all in the moment except for recognition of the option
+   itself.
+
+** variables with aliases in executables
+
+   When linking an executable with a references against a variable in a
+   DSO, create symbol table entries for all the aliases of the variable
+   in the DSO and create a relocation for one of them (a non-weak
+   definition)
+
+* elflint
+
+** additional checks
+
+   1st GOT entry == _DYNAMIC
+
+   check versioning info:
+
+     always BASE in verdef
+     sh_size/sh_entsize matches last offset != 0
+
+   check whether any relocation is for a merge-able section
+
+   check TLS relocation dependencies
+
+   Check content of .eh_frame_hdr, .eh_frame, .gcc_except_table
+
+*** for x86
+
+    check that R_386_TLS_GD is followed by R_386_PLT32 for __tls_get_addr
+
+** relax
+
+   prelink generated files
+
+* elfcmp
+
+** treat relocation sections special
+
+   Differences in the relocation sections can be ignored if all
+   the same symbols with the same targets are present and the order
+   of overlapping relocations doesn't change.  There really never
+   should be overlapping relocations but who knows.
+
+* mcs
+
+  Sun has it.  Can modify sections which are not in segments.
+
+     -a string
+           Append string to the comment section of the ELF object
+           files. If  string contains embedded blanks, it must be
+           enclosed in quotation marks.
+
+     -c    Compress the contents of the comment  section  of  the
+           ELF  object  files. All duplicate entries are removed.
+           The ordering of the  remaining  entries  is  not  dis-
+           turbed.
+
+     -d    Delete the contents of the comment  section  from  the
+           ELF  object  files. The section header for the comment
+           section is also removed.
+
+     -n name
+           Specify the name of the comment section to  access  if
+           other  than  .comment.  By default, mcs deals with the
+           section named .comment. This option  can  be  used  to
+           specify  another  section.  mcs  can  take multiple -n
+           options to allow for specification of   multiple  sec-
+           tion comments.
+
+     -p    Print the contents of the comment section on the stan-
+           dard  output.  Each  section  printed is tagged by the
+           name of the file from which it  was  extracted,  using
+           the  format  file[member_name]:  for archive files and
+           file:  for other files.
+
+     -V    Print on standard error the version number of mcs.
+
+Local Variables:
+eval:(hide-sublevels 3)
+End:
diff --git a/backends/ChangeLog b/backends/ChangeLog
new file mode 100644
index 0000000..ddb4e0a
--- /dev/null
+++ b/backends/ChangeLog
@@ -0,0 +1,1467 @@
+2023-05-09  Youling Tang  <tangyouling@loongson.cn>
+
+	* Makefile.am (loongarch_SRCS): Add loongarch_initreg.c.
+	* loongarch_initreg.c: New file.
+	* loongarch_init.c (loongarch_init): Hook set_initial_registers_tid.
+
+2023-04-07  Youling Tang  <tangyouling@loongson.cn>
+
+	* Makefile.am (loongarch_SRCS): Add loongarch_corenote.c.
+	* loongarch_init.c (loongarch_init): Hook core_note.
+	* loongarch_corenote.c: New file.
+
+2023-04-07  Youling Tang  <tangyouling@loongson.cn>
+
+	* Makefile.am (loongarch_SRCS): Add loongarch_unwind.c.
+	* loongarch_init.c (loongarch_init): Hook unwind.
+	* loongarch_unwind.c: New file.
+
+2023-04-07  Youling Tang  <tangyouling@loongson.cn>
+
+	* Makefile.am (loongarch_SRCS): Add loongarch_retval.c.
+	* loongarch_init.c (loongarch_init): Hook return_value_location.
+	* loongarch_retval.c: New file.
+
+2023-04-07  Youling Tang  <tangyouling@loongson.cn>
+
+	* Makefile.am (loongarch_SRCS): Add loongarch_cfi.c and loongarch_regs.c.
+	* loongarch_cfi.c: New file.
+	* loongarch_regs.c: Likewise.
+	* loongarch_init.c (loongarch_init): Hook register_info and abi_cfi.
+
+2023-04-01  Youling Tang  <tangyouling@loongson.cn>
+
+	* loongarch_init.c (loongarch_init): Hook check_special_symbol.
+	* loongarch_symbol.c (loongarch_check_special_symbol): New function.
+
+2023-04-01  Youling Tang  <tangyouling@loongson.cn>
+
+	* loongarch_reloc.def: Add RELOC_TYPE B16 to RELAX.
+
+2023-02-07  Mark Wielaard  <mark@klomp.org>
+
+	* libebl_CPU.h (dwarf_peeled_die_type): Explicitly handle
+	DW_TAG_unspecified_type as if there was no DW_AT_type.
+
+2023-01-19  Mark Wielaard  <mark@klomp.org>
+
+	* sparc_reloc.def (NONE): Add EXEC and DYN.
+
+2022-12-21  Shahab Vahedi  <shahab@synopsys.email>
+
+	* Makefile.am (modules): Add arc.
+	(arc_SRCS): Added.
+	(libebl_backends_a_SOURCES): Append arc_SRCS.
+	* arc_init.c: New file.
+	* arc_reloc.def: New file.
+	* arc_symbol.c: New file.
+
+2022-12-02  Hengqi Chen  <hengqi.chen@gmail.com>
+
+	* Makefile.am (modules): Add loongarch.
+	* loongarch_init.c: New file.
+	* loongarch_reloc.def: New file.
+	* loongarch_symbol.c: New file.
+
+2022-08-09  Andreas Schwab  <schwab@suse.de>
+
+	* riscv_init.c (riscv_init): HOOK segment_type_name,
+	section_type_name, dynamic_tag_name and dynamic_tag_check.
+	* riscv_symbol.c (riscv_segment_type_name): New function.
+	(riscv_section_type_name): Likewise.
+	(riscv_dynamic_tag_name): Likewise.
+	(riscv_dynamic_tag_check): Likewise.
+
+2022-06-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (arm_SRCS): Add arm_machineflagname.c.
+	* arm_init.c (arm_init): Hook in arm_machine_flag_name.
+	* arm_machineflagname.c: New file.
+
+2022-02-16  Mark Wielaard  <mark@klomp.org>
+
+	* ppc_initreg.c (ppc_set_initial_registers_tid): Define struct
+	pt_regs32. Use PTRACE_GETREGSET.
+
+2021-09-29  William Cohen  <wcohen@redhat.com>
+
+	* riscv_init.c (riscv_return_value_location_lp64f): New function
+	declaration.
+	(riscv_return_value_location_lp64): Likewise.
+	(riscv_init): Set return_value_location based on elf class and
+	ehdr flags.
+	* riscv_retval.c (riscv_return_value_location_lp64d): Renamed to...
+	(riscv_return_value_location_lp64ifd): ...this. Handle single,
+	double, float _Complex and double _Complex cases.
+	(riscv_return_value_location_lp64d): New function.
+	(riscv_return_value_location_lp64f): Likewise.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* aarch64_symbol.c (aarch64_data_marker_symbol): Use startswith.
+	* arm_symbol.c (arm_data_marker_symbol): Likewise.
+
+2021-02-01  Érico Nogueira  <ericonr@disroot.org>
+
+	* ppc_initreg.c: Also include <asm/ptrace.h>.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* aarch64_retval.c (aarch64_return_value_location): Fix spelling typo
+	in comment.
+	* ppc_cfi.c (ppc_abi_cfi): Likewise.
+
+2020-11-17  Mark Wielard  <mark@klomp.org>
+
+	* x86_64_symbol.c (x86_64_check_reloc_target_type): New function.
+	* x86_64_init.c (x86_64_init): Hook check_reloc_target_type.
+
+2020-10-19  Mark Wielard  <mark@klomp.org>
+
+	* Makefile.am (modules): Remove tilegx.
+	(tilegx_SRCS): Removed.
+	(libebl_backends_a_SOURCES): Remove tilegx_SRCS.
+	* tilegx_corenote.c: Removed.
+	* tilegx_init.c: Removed.
+	* tilegx_regs.c: Removed.
+	* tilegx_reloc.def: Removed.
+	* tilegx_retval.c: Removed.
+	* tilegx_symbol.c: Removed.
+
+2020-10-19  Mark Wielard  <mark@klomp.org>
+
+	* Makefile.am (i386_SRCS): Remove i386_syscall.c.
+	(x86_64_SRCS): Remove x86_64_syscall.c.
+	(ppc_SRCS): Remove ppc_syscall.c.
+	* i386_init.c (i386_init): Remove syscall_abi HOOK.
+	* i386_syscall.c: Delete.
+	* ppc64_init.c (ppc64_init): Remove syscall_abi HOOK.
+	* ppc_syscall.c: Delete.
+	* x86_64_init.c (x86_64_init): Remove syscall_abi HOOK.
+	* x86_64_syscall.c: Delete.
+
+2020-08-28  Mark Wielard  <mark@klomp.org>
+
+	* aarch64_init.c (aarch64_init): Hook dynamic_tag_name and
+	dynamic_tag_check.
+	* aarch64_symbol.c (aarch64_dynamic_tag_name): New function.
+	(aarch64_dynamic_tag_check): Likewise.
+
+2020-06-16  Mark Wielard  <mark@klomp.org>
+
+	* common-reloc.c (reloc_nametable): Make zero a 1 char array.
+	Initialize it as an array { '\0' }.
+	(reloc_type_name): Access zero as an array.
+
+2020-06-10  Mark Wielard  <mark@klomp.org>
+
+	* aarch64_init.c (aarch64_init): Remove ehlen, return eh.
+	* alpha_init.c (alpha_init): Likewise.
+	* arm_init.c (arm_init): Likewise.
+	* bpf_init.c (bpf_init): Likewise.
+	* csky_init.c (csky_init): Likewise.
+	* i386_init.c (i386_init): Likewise.
+	* ia64_init.c (ia64_init): Likewise.
+	* m68k_init.c (m68k_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* riscv_init.c (riscv_init): Likewise.
+	* s390_init.c (s390_init): Likewise.
+	* sh_init.c (sh_init): Likewise.
+	* sparc_init.c (sparc_init): Likewise.
+	* tilegx_init.c (tilegx_init): Likewise.
+	* x86_64_init.c (x86_64_init): Likewise.
+	* libebl_CPU.h (init): Adjust EBLHOOK signature.
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Replace libcpu_{i386,x86_64,bpf}.a with libcpu.a.
+	Replace libcpu.a with libcpu_pic.a.
+	Combine libebl_CPU.so modules into libebl_backends{,_pic}.a.
+
+2019-07-13 Mao Han <han_mao@c-sky.com>
+
+	* Makefile.am: Add C-SKY.
+	* csky_attrs.c: New file.
+	* csky_cfi.c: New file.
+	* csky_corenote.c: Likewise.
+	* csky_init.c: Likewise.
+	* csky_initreg.c: Likewise.
+	* csky_regs.c: Likewise.
+	* csky_reloc.def: Likewise.
+	* csky_symbol.c: Likewise.
+
+2019-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* aarch64_init.c (aarch64_init.c): Remove eh->name;
+	* alpha_init.c (alpha_init.c): Remove eh->name;
+	* arm_init.c (arm_init.c): Remove eh->name;
+	* bpf_init.c (bpf_init.c): Remove eh->name;
+	* i386_init.c (i386_init.c): Remove eh->name;
+	* ia64_init.c (ia64_init.c): Remove eh->name;
+	* m68k_init.c (m68k_init.c): Remove eh->name;
+	* ppc64_init.c (ppc64_init.c): Remove eh->name;
+	* ppc_init.c (ppc_init.c): Remove eh->name;
+	* riscv_init.c (riscv_init.c): Remove eh->name;
+	* s390_init.c (s390_init.c): Remove eh->name;
+	* sh_init.c (sh_init.c): Remove eh->name;
+	* sparc_init.c (sparc_init.c): Remove eh->name;
+	* tilegx_init.c (tilegx_init.c): Remove eh->name;
+	* x86_64_init.c (x86_64_init.c): Remove eh->name;
+
+2019-04-14  Mark Wielaard  <mark@klomp.org>
+
+	* riscv_cfi.c: Fix BACKEND define.
+
+2019-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* s390_init.c (s390_init): Hook check_special_symbol.
+	* s390_symbol.c (s390_check_sepcial_symbol): New function.
+
+2018-12-27  Jim Wilson  <jimw@sifive.com>
+
+	* Makefile.am (riscv_SRCS): Add riscv64_corenote.c.
+	* riscv64_corenote.c: New file.
+	* riscv_corenote.c (BITS): New.
+	(BACKEND): Conditional on BITS.
+	(ULONG, UID_T, GID_T, ALIGN_ULONG, ALIGN_UID_T, ALIGN_GID_T): Likewise.
+	(TYPE_ULONG, TYPE_UID_T, TYPE_GID_T): Likewise.
+	(prstatus_regs): Use BITS/8 instead of 8.
+	(PRSTATUS_REGS_SIZE): Likewise.
+	* riscv_init.c (riscv64_core_note): Declare.
+	(riscv_init): If ELFCLASS64 then use riscv64_core_note hook.
+
+	* Makefile.am (riscv_SRCS): Add riscv_retval.c.
+	* riscv_init.c: Include libelfP.h.
+	(riscv_return_value_location_lp64d): Declare.
+	(riscv_init): Delete unused attribute from elf parameter.  Register
+	riscv_return_value_location_lp64d hook if 64-bit ELF and 64-bit FP
+	registers.
+	* riscv_retval.c: New file.
+
+	* riscv_corenote.c (prstatus_regs): Change offset from 1 to 8.
+	(PRSTATUS_REGSET_ITEMS): New.
+
+2018-11-06  Mark Wielaard  <mark@klomp.org>
+
+	* x86_64_symbol.c (x86_64_section_type_name): New function.
+	* x86_64_init.c (x86_64_int): Hook section_type_name.
+
+2018-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* ppc_initreg.c (ppc_set_initial_registers_tid): Use define instead of
+	const for size of dwarf_regs array.
+
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+	* riscv_symbol.c (riscv_reloc_simple_type): Add parameter addsub.
+	Set it for ADD and SUB relocations.
+	* aarch64_symbol.c (aarch64_reloc_simple_type): Add and ignore
+	third parameter.
+	* alpha_symbol.c (alpha_reloc_simple_type): Likewise.
+	* arm_symbol.c (arm_reloc_simple_type): Likewise.
+	* bpf_symbol.c (bpf_reloc_simple_type): Likewise.
+	* i386_symbol.c (i386_reloc_simple_type): Likewise.
+	* ia64_symbol.c (ia64_reloc_simple_type): Likewise.
+	* m68k_symbol.c (m68k_reloc_simple_type): Likewise.
+	* ppc64_symbol.c (ppc64_reloc_simple_type): Likewise.
+	* ppc_symbol.c (ppc_reloc_simple_type): Likewise.
+	* s390_symbol.c (s390_reloc_simple_type): Likewise.
+	* sh_symbol.c (sh_reloc_simple_type): Likewise.
+	* sparc_symbol.c (sparc_reloc_simple_type): Likewise.
+	* tilegx_symbol.c (tilegx_reloc_simple_type): Likewise.
+	* x86_64_symbol.c (x86_64_reloc_simple_type): Likewise.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* ppc64_init.c (ppc64_init): Use elf_getshdrstrndx.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* aarch64_symbol.c (aarch64_check_special_symbol): Drop ehdr argument,
+	use elf_getshdrstrndx.
+	* alpha_symbol.c (alpha_check_special_symbol): Drop ehdr argument.
+	* ppc64_symbol.c (ppc64_check_special_symbol): Likewise and use
+	elf_getshdrstrndx.
+	* ppc_symbol.c (ppc_check_special_symbol): Likewise.
+	* riscv_symbol.c (riscv_check_special_symbol): Likewise.
+
+2018-07-21  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* Makefile.am (m68k_SRCS): Add m68k_cfi.c and m68k_initreg.c.
+	* m68k_cfi.c: New file.
+	* m68k_initreg.c: New file.
+	* m68k_init.c (m68k_init): Hook abi_cfi and
+	set_initial_registers_tid.
+
+2018-07-19  Andreas Schwab  <schwab@suse.de>
+
+	* riscv_regs.c (riscv_register_info): Fix typo.
+
+2018-07-17  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile.am (riscv_SRCS): Add riscv_corenote.c.
+	* riscv_corenote.c: New file.
+	* riscv_init.c (riscv_init): Hook core_note.
+
+2018-07-11  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile.am (riscv_SRCS): Add riscv_initreg.c.
+	* riscv_initreg.c: New file.
+	* riscv_init.c (riscv_init): Hook set_initial_registers_tid.
+
+2018-06-16  Yonghong Song  <yhs@fb.com>
+
+	* Makefile.am (bpf_SRCS): Add bpf_symbol.c.
+	* bpf_init.c (bpf_init): Add reloc_simple_type HOOK.
+	* bpf_reloc.def: Add RELOC_TYPE 64_64 and 64_32.
+	* bpf_symbol.c: New file.
+
+2018-06-21  Mark Wielaard  <mark@klomp.org>
+
+	* bpf_reloc.def: Remove MAP_FD.
+
+2018-06-13  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile.am (riscv_SRCS): Add riscv_cfi.c and riscv_regs.c.
+	* riscv_cfi.c: New file.
+	* riscv_regs.c: Likewise.
+	* riscv_init.c (riscv_init): Hook register_info and abi_cfi.
+
+2018-05-15  Andreas Schwab  <schwab@suse.de>
+
+	* riscv_init.c (riscv_init): Hook check_special_symbol.
+	* riscv_symbol.c (riscv_check_special_symbol): New function.
+
+2018-04-19  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile.am (modules): Add riscv.
+	* riscv_init.c: New file.
+	* riscv_reloc.def: New file.
+	* riscv_symbol.c: New file.
+
+2018-04-11  Mark Wielaard  <mark@klomp.org>
+
+	* aarch64_cfi.c (aarch64_abi_cfi): Add rule for restoring SP from
+	CFA address.
+
+2018-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* ppc_initreg.c: Include ptrace.h before system.h and sys/user.h.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* aarch64_retval.c (aarch64_return_value_location): Use FALLTHROUGH
+	macro instead of comment.
+	* alpha_retval.c (alpha_return_value_location): Likewise.
+	* arm_regs.c (arm_register_info): Likewise.
+	* arm_retval.c (arm_return_value_location): Likewise.
+	* i386_regs.c (i386_register_info): Likewise.
+	* i386_retval.c (i386_return_value_location): Likewise.
+	* ia64_retval.c (ia64_return_value_location): Likewise.
+	* linux-core-note.c (core_note): Likewise.
+	* m68k_retval.c (m68k_return_value_location): Likewise.
+	* ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* ppc_regs.c (ppc_register_info): Likewise.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+	* s390_retval.c (s390_return_value_location): Likewise.
+	* sh_retval.c (sh_return_value_location): Likewise.
+	* sparc_retval.c (sparc_return_value_location): Likewise.
+	* tilegx_retval.c (tilegx_return_value_location): Likewise.
+	* x86_64_regs.c (x86_64_register_info): Likewise.
+	* x86_64_retval.c (x86_64_return_value_location): Likewise.
+
+2017-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (m68k_corenote_no_Wpacked_not_aligned): New variable.
+
+2017-08-18  Ulf Hermann <ulf.hermann@qt.io>
+
+	* linux-core-note.c: Use attribute_packed.
+
+2017-04-27  Ulf Hermann <ulf.hermann@qt.io>
+
+	* Makefile.am: Use dso_LDFLAGS.
+
+2017-07-27  Mark Wielaard  <mark@klomp.org>
+
+	* sparc_reloc.def: GOTDATA_OP_HIX22, GOTDATA_OP_LOX10 and
+	GOTDATA_OP can be used in ET_REL files.
+
+2017-07-19  Gustavo Romero <gromero@linux.vnet.ibm.com>
+
+	* ppc_corenote.c: Add offsets for ppc64 HTM SPRs: thfar, tfiar,
+	and texasr.
+	* ppc_regs.c: Add names for ppc64 HTM SPRs mappings.
+
+2017-07-20  Mark Wielaard  <mark@klomp.org>
+
+	* aarch64_init.c (aarch64_init): Hook data_marker_symbol.
+	* aarch64_symbol.c (aarch64_data_marker_symbol): New function.
+	* arm_init.c (arm_init): Hook data_marker_symbol.
+	* arm_symbol.c (aarch64_data_marker_symbol): New function.
+
+2017-07-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (cpu_bpf): Always define.
+	* bpf_init.c (disasm): Always hook.
+	* bpf_regs.c: Include bpf.h instead of linux/bpf.h. Don't define
+	MAX_BPF_REG.
+
+2017-02-17  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Add libeu.
+	(libebl_%so): Link with --no-undefined,-z,defs,-z,relro
+	and libeu.a.
+
+2017-06-17  Mark Wielaard  <mark@klomp.org>
+
+	* s390_initreg.c: Swap sys/ptrace.h and asm/ptrace.h include order.
+
+2017-06-15  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* ppc_symbol.c (ppc_machine_flag_check): New function.
+	* ppc_init.c (ppc_init): Hook it.
+
+2017-05-30  Mark Wielaard  <mark@klomp.org>
+
+	* ppc64_unwind.c: New file.
+	* ppc64_init.c (pcc64_init): Hook unwind.
+	* Makefile.am (ppc64_SRCS): Add ppc64_unwind.c
+
+2017-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* i386_unwind.c: New file.
+	* i386_init.c: Hook i386_unwind.
+	* Makefile.am (i386_SRCS): Add i386_unwind.c
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* aarch64_unwind.c: New file
+	* Makefile.am (aarch64_SRCS): Add aarch64_unwind.c
+	* aarch64_init.c (aarch64_init): Hook aarch64_unwind
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* x86_64_unwind.c: New file
+	* Makefile.am (x86_64_SRCS): Add x86_64_unwind.c
+	* x86_64_init.c (x86_64_init): Hook x86_64_unwind
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* aarch64_initreg.c: Compile register initialization only on linux.
+	* arm_initreg.c: Likewise.
+	* ppc_initreg.c: Likewise.
+	* s390_initreg.c: Likewise.
+	* x86_64_initreg.c: Likewise.
+
+2017-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* ppc64_init.c (ppc64_init): Add check_object_attribute HOOK.
+	* ppc_attrs.c (ppc_check_object_attribute): Add Single-precision hard
+	float.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* i386_regs.c (i386_register_info): Add fallthrough comment.
+	* i386_retval.c (i386_return_value_location): Move fallthrough
+	comment.
+	* linux-core-note.c (core_note): Adjust fallthrough comment.
+	* m68k_retval.c (m68k_return_value_location): Move fallthrough
+	comment.
+	* ppc_regs.c (ppc_register_info): Add fallthrough comment.
+	* x86_64_regs.c (x86_64_register_info): Likewise.
+
+2016-08-09  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_attrs.c (sparc_check_object_attribute): Fix the
+	calculation of GNU_SParc_HWCAPS and GNU_SParc_HWCAPS2 values as
+	comma-separated list of hw capability names.
+
+2016-07-10  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* m68k_corenote.c (ALIGN_PRSTATUS): Define.
+	* linux-core-note.c (struct EBLHOOK(prstatus)): Set alignment to
+	ALIGN_PRSTATUS if defined.
+
+2016-06-28  Richard Henderson <rth@redhat.com>
+
+	* Makefile.am (modules): Add bpf.
+	(libebl_pic): Add libebl_bpf_pic.a.
+	(am_libebl_bpf_pic_a_OBJECTS): New.
+	* bpf_init.c, bpf_regs.c, bpf_reloc.def: New files.
+	* common-reloc.c (copy_reloc_p): Honor NO_COPY_RELOC.
+	(init_reloc): Likewise.
+
+2016-05-20  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* Makefile.am (modules): Add m68k.
+	(libebl_pic): Add libebl_m68k_pic.a.
+	(m68k_SRCS, libebl_m68k_pic_a_SOURCES)
+	(am_libebl_m68k_pic_a_OBJECTS): Define.
+	* m68k_init.c: New file.
+	* m68k_symbol.c: New file.
+	* m68k_regs.c: New file.
+	* m68k_retval.c: New file.
+	* m68k_corenote.c: New file.
+	* m68k_reloc.def: New file.
+	* linux-core-note.c (ALIGN_INT): Only define if not defined.
+
+2016-02-26  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_initreg.c (EBLHOOK): Provide a dummy
+	sparc_set_initial_registers_tid for sparc32.  This fixes the build
+	in sparcv9-*-* targets.
+
+2016-02-26  Andreas Schwab  <schwab@suse.de>
+
+	* ppc_symbol.c (ppc_dynamic_tag_name): Add DT_PPC_OPT.
+	(ppc_dynamic_tag_check): Likewise.
+
+2015-12-28  Mark Wielaard  <mjw@redhat.com>
+
+	* i386_reloc.def: Add GOT32X.
+	* x86_64_reloc.def: Add GOTPCRELX and REX_GOTPCRELX.
+
+2016-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_corenote.c (aarch64_syscall_items): New Ebl_Core_Item[].
+	(EXTRA_NOTES): Add NT_ARM_SYSTEM_CALL.
+	* eblcorenotetypename.c (ebl_core_note_type_name):
+	Add ARM_SYSTEM_CALL.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_init.c (sparc_init): Hook sparc_set_initial_registers_tid.
+	* sparc_initreg.c: New file.
+	* Makefile.am (sparc_SRCS): Added sparc_initreg.c.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_corenote.c: Header comment typo fixed.
+	(PRSTATUS_REGSET_ITEMS): Defined, so the PC can be fetched from
+	core files.
+	* Makefile.am (sparc_SRCS): Added sparc_cfi.c
+	* sparc_cfi.c: New file.
+	* sparc_init.c (sparc_init): Set eh->frame_nregs, eh->ra_offset
+	and hook sparc_abi_cfi.
+
+2015-10-21  Chih-Hung Hsieh  <chh@google.com>
+
+	* ia64_retval.c (hfa_type): Move nested function 'hfa' to file scope.
+	* aarch64_regs.c (aarch64_register_info): Move nested function 'regtype'
+	to file scope.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc_symbol.c (ppc_check_special_symbol): Also allow _SDA_BASE_
+	in .data section.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (libebl_%.so): Add AM_V_at and AM_V_CCLD silencers.
+
+2015-10-06  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_attrs.c: New file.
+	* Makefile.am (sparc_SRCS): Added sparc_attrs.c
+	* sparc_init.c (sparc_init): Hook sparc_check_object_attribute.
+
+2015-10-02  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_init.c (RELOC_TYPE_ID): Defined.
+	* common-reloc.c (reloc_type_name): Apply target-specific
+	relocation ID extractors if defined.
+	(reloc_type_check): Likewise.
+	(reloc_valid_use): Likewise.
+
+2015-10-02  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* sparc_reloc.def: Added relocation types WDISP10, JMP_IREL and
+	IRELATIVE.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_attrs.c: Remove old-style function definitions.
+	* linux-core-note.c: Likewise.
+	* ppc_attrs.c: Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* aarch64_init.c (aarch64_init): Replace K&R function definition
+	with ansi-C definitions.
+	* alpha_init.c (alpha_init): Likewise.
+	* arm_init.c (arm_init): Likewise.
+	* i386_init.c (i386_init): Likewise.
+	* ia64_init.c (ia64_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* s390_init.c (s390_init): Likewise.
+	* sh_init.c (sh_init): Likewise.
+	* sparc_init.c (sparc_init): Likewise.
+	* tilegx_init.c (tilegx_init): Likewise.
+	* x86_64_init.c (x86_64_init): Likewise.
+
+2015-09-03  Mark Wielaard  <mjw@redhat.com>
+
+	* sparc_regs.c (sparc_register_info): Use ebl->class not ebl->machine.
+
+2015-06-26  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* i386_initreg.c: Reduce scope of some includes to match their usage.
+
+2015-04-28  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_reloc.def: Drop "64" from TLS_DTPMOD64, TLS_DTPREL64 and
+	TLS_TPREL64.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* Makefile.am (x86_64_SRCS): Add x32_corenote.c.
+	* linux-core-note.c (PR_REG): New.
+	(PRPSINFO_UID_T): Likewise.
+	(ALIGN_PRPSINFO_UID_T): Likewise.
+	(TYPE_PRPSINFO_UID_T): Likewise.
+	(PRPSINFO_GID_T): Likewise.
+	(ALIGN_PRPSINFO_GID_T): Likewise.
+	(TYPE_PRPSINFO_GID_T): Likewise.
+	(pr_reg): Replace ULONG with PR_REG.
+	(pr_uid): Replace UID_T with PRPSINFO_UID_T.
+	(uid): Likewise.
+	(pr_gid): Replace GID_T with PRPSINFO_GID_T.
+	(gid): Likewise.
+	* x32_corenote.c: New file.
+	* x86_64_corenote.c (BITS): New.  Support x32.
+	(BACKEND): Support x32.
+	(ULONG): Likewise.
+	(ALIGN_ULONG): Likewise.
+	(TYPE_ULONG): Likewise.
+	(PRPSINFO_UID_T): New.
+	(ALIGN_PRPSINFO_UID_T): Likewise.
+	(TYPE_PRPSINFO_UID_T): Likewise.
+	(PRPSINFO_GID_T): Likewise.
+	(ALIGN_PRPSINFO_GID_T): Likewise.
+	(TYPE_PRPSINFO_GID_T): Likewise.
+	(PR_REG): Likewise.
+	(ALIGN_PR_REG): Likewise.
+	* x86_64_init.c (x32_core_note): New.
+	(x86_64_init): Set eh->core_note to x32_core_note for x32.
+
+2015-03-23  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_symbol.c (aarch64_check_special_symbol): Accept
+	_GLOBAL_OFFSET_TABLE_ pointing anywhere in .got.
+
+2015-03-09  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_reloc.def (COPY): Add DYN.
+	* arm_reloc.def (COPY): Likewise.
+	* i386_reloc.def (COPY): Likewise.
+	* ia64_reloc.def (COPY): Likewise.
+	* ppc64_reloc.def (COPY): Likewise.
+	* ppc_reloc.def (COPY): Likewise.
+	* s390_reloc.def (COPY): Likewise.
+	* sh_reloc.def (COPY): Likewise.
+	* sparc_reloc.def (COPY): Likewise.
+	* tilegx_reloc.def (COPY): Likewise.
+	* x86_64_reloc.def (COPY): Likewise.
+
+2015-02-23  Petr Machata  <pmachata@redhat.com>
+
+	* arm_symbol.c (arm_symbol_type_name): New function.
+	* arm_init.c (arm_init): Initialize the hook.
+
+2014-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc_symbol.c (find_dyn_got): Check sh_entsize is not zero.
+
+2014-12-18  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am: Suppress output of textrel_check command.
+
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_symbol.c (ppc64_bss_plt_p): Remove ehdr argument.
+	* ppc_symbol.c (find_dyn_got): Likewise. Use elf_getphdrnum.
+	(ppc_check_special_symbol): Call find_dyn_got without ehdr.
+	(ppc_bss_plt_p): Remove ehdr argument.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_init.c (ppc64_init): Check section name is not NULL.
+
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (dwarf_peel_type): Removed.
+	(dwarf_peeled_die_type): Use libdw dwarf_peel_type.
+
+2014-07-18  Kyle McMartin  <kyle@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_initreg.c: Check HAVE_SYS_USER_REGS.
+	(aarch64_set_initial_registers_tid): Use user_regs_struct and
+	user_fpsimd_struct.
+	* arm_initreg.c: Check HAVE_SYS_USER_REGS.
+	(arm_set_initial_registers_tid): Use user_regs_struct in compat mode.
+
+2014-07-04  Menanteau Guy  <menantea@linux.vnet.ibm.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_init.c (ppc64_init): Hook check_st_other_bits.
+	* ppc64_reloc.def: TLSGD, TLSLD, TOCSAVE, ADDR16_HIGH, ADDR16_HIGHA,
+	TPREL16_HIGH, TPREL16_HIGHA, DTPREL16_HIGH, DTPREL16_HIGHA, JMP_IREL,
+	IRELATIVE, REL16, REL16_LO, REL16_HI and REL16_HA.
+	* ppc64_symbol.c (ppc64_dynamic_tag_name): Recognize DT_PPC64_OPT.
+	(ppc64_dynamic_tag_check): Likewise.
+	(ppc64_check_st_other_bits): New function.
+
+2014-07-04  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_retval.c (aarch64_return_value_location): Handle
+	DW_ATE_boolean.
+
+2014-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (dwarf_peel_type): Remove DW_TAG_mutable_type
+	handling.
+
+2014-06-17  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_init.c (arm_init): Set func_addr_mask.
+
+2014-06-20  Petr Machata  <pmachata@redhat.com>
+
+	* alpha_retval.c (alpha_return_value_location): Call
+	dwarf_peeled_die_type instead of inlining equivalent code.
+	* arm_retval.c (arm_return_value_location): Likewise.
+	* i386_retval.c (i386_return_value_location): Likewise.
+	* ia64_retval.c (ia64_return_value_location): Likewise.
+	* ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+	* s390_retval.c (s390_return_value_location): Likewise.
+	* sh_retval.c (sh_return_value_location): Likewise.
+	* sparc_retval.c (sparc_return_value_location): Likewise.
+	* tilegx_retval.c (tilegx_return_value_location): Likewise.
+	* x86_64_retval.c (x86_64_return_value_location): Likewise.
+
+2014-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_init.c (arm_init): Hook check_reloc_target_type.
+	* arm_symbol.c (arm_check_reloc_target_type): New function.
+	* ia64_init.c (ia64_init): Hook check_reloc_target_type.
+	* ia64_symbol.c (ia64_check_reloc_target_type): New function.
+
+2014-04-22  Kurt Roeckx  <kurt@roeckx.be>
+
+	* i386_initreg.c: Make Linux only.
+	* x86_64_initreg.c: Make Linux only.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove libelf and libdw definitions when MUDFLAP
+	is defined. Remove libmudflap from LINK line.
+
+2014-04-09  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (aarch64_SRCS): Add aarch64_initreg.c.
+	* aarch64_corenote.c (prstatus_regs): Mark pc_register.
+	* aarch64_init.c: Assign frame_nregs. Hook set_initial_registers_tid.
+	* aarch64_initreg: New file.
+
+2014-03-28  Jean Pihet  <jean.pihet@linaro.org>
+
+	* arm_initreg.c (arm_set_initial_registers_tid): Handle compat mode.
+	ARM compatible code running on AARCH64.
+
+2014-03-19  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_reloc.def: AARCH64_ABS32 and AARCH64_ABS64 are also valid
+	in ET_REL.
+
+2014-01-30  Petr Machata  <pmachata@redhat.com>
+
+	* aarch64_regs.c (aarch64_register_info.regtype): Make this
+	variadic printf-like function.  Call one vsnprintf instead of two
+	snprintf's.
+	(regtyper, regtypen): Drop.
+	(aarch64_register_info): Adjust callers.
+
+2014-01-26  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (arm_SRCS): Add arm_initreg.c.
+	* arm_init.c (arm_init): Define frame_nregs and hook
+	set_initial_registers_tid.
+	* arm_initreg.c: New file.
+
+2014-01-25  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_cfi.c (arm_abi_cfi): Restore SP (r13) from CFA.
+
+2014-01-24  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_reloc.def: Update list.
+
+2014-01-22  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (aarch64_regs_no_Wformat): Removed.
+	* aarch64_regs.c (regtype): Add bool nr argument. snprintf arg
+	when nr is true.
+	(regtyper): New function.
+	(regtypen): Likewise.
+	(aarch64_register_info): Call either regtyper or regtypen not
+	regtype directly.
+
+2014-01-14  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_symbol.c (aarch64_check_special_symbol): Check shdr is
+	not NULL before usage.
+
+2014-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc64_symbol.c (ppc64_machine_flag_check): New function.
+	* ppc64_init.c (ppc64_init): Hook machine_flag_check.
+
+2014-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (aarch64_SRCS): Add aarch64_cfi.c.
+	* aarch64_cfi.c: New file.
+	* aarch64_init.c (aarch64_init): Hook abi_cfi.
+	* aarch64_regs.c (aarch64_register_info): Set *prefix to "".
+
+2013-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* aarch64_init.c (aarch64_init): Hook check_special_symbol.
+	* aarch64_symbol.c (aarch64_check_special_symbol): New function.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (ppc64_SRCS): Add ppc64_resolve_sym.c.
+	* ppc64_resolve_sym.c: New file.
+	* ppc64_init.c: Hook resolve_sym_value and find function descriptor
+	table.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* s390_initreg.c (s390_set_initial_registers_tid): Use union
+	to avoid type-punning when assigning a double to a Dwarf_Word.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: s390 and s390x
+	* Makefile.am (s390_SRCS): Add s390_initreg.c and s390_unwind.c.
+	* s390_corenote.c (prstatus_regs): Set PC_REGISTER.  Reindent all the
+	entries.
+	* s390_init.c (s390_init): Initialize frame_nregs,
+	set_initial_registers_tid, normalize_pc and unwind.
+	* s390_initreg.c: New file.
+	* s390_unwind.c: New file.
+
+2013-12-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: ppc and ppc64
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add ppc_initreg.c.
+	* ppc64_init.c (ppc64_init): Initialize also frame_nregs,
+	set_initial_registers_tid and dwarf_to_regno.
+	* ppc_corenote.c (PRSTATUS_REGSET_ITEMS) <nip>: Set PC_REGISTER.
+	* ppc_init.c (ppc64_init): Initialize also frame_nregs,
+	set_initial_registers_tid and dwarf_to_regno.
+	* ppc_initreg.c: New file.
+
+2013-11-25  Petr Machata  <pmachata@redhat.com>
+
+	* Makefile.am (modules): Add aarch64.
+	(libebl_pic): Add libebl_aarch64_pic.a.
+	(aarch64_SRCS): New variable.
+	(libebl_aarch64_pic_a_SOURCES): Likewise.
+	(am_libebl_aarch64_pic_a_OBJECTS): Likewise.
+	(aarch64_regs_no_Wformat): Likewise.
+	* aarch64_corenote.c, aarch64_init.c: New files.
+	* aarch64_regs.c, aarch64_reloc.def: Likewise.
+	* aarch64_retval.c, aarch64_symbol.c: Likewise.
+	* libebl_CPU.h (dwarf_peel_type): New function.
+	(dwarf_peeled_die_type): Likewise.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (i386_SRCS): Add i386_initreg.c.
+	(x86_64_SRCS): Add x86_64_initreg.c.
+	* i386_initreg.c: New file.
+	* i386_init.c (i386_init): Initialize frame_nregs and
+	set_initial_registers_tid.
+	* x86_64_initreg.c: New file.
+	* x86_64_init.c (x86_64_init): Initialize frame_nregs and
+	set_initial_registers_tid.
+
+2013-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* ppc_cfi.c (ppc_abi_cfi): Use DW_CFA_val_offset for reg1, not
+	DW_CFA_val_expression.
+
+2013-08-29  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (arm_SRCS): Add arm_cfi.c.
+	* arm_cfi.c: New file.
+	* arm_init.c (arm_init): Initialize abi_cfi.
+
+2013-08-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add ppc_cfi.c.
+	(s390_SRCS): Add s390_cfi.c.
+	* ppc64_init.c (ppc64_init): Initialize abi_cfi.
+	* ppc_cfi.c: New file.
+	* ppc_init.c (ppc_init): Initialize abi_cfi.
+	* s390_cfi.c: New file.
+	* s390_init.c (s390_init): Initialize abi_cfi.
+
+2013-08-28  Mark Wielaard  <mjw@redhat.com>
+
+	* arm_regs.c (arm_register_info): Set *prefix to "".
+	* ppc_regs.c (ppc_register_info): Likewise.
+	* sh_regs.c (sh_register_info): Likewise.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2013-02-06  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl_CPU.h (DWARF_TAG_OR_RETURN): New macro.
+	* backends/alpha_retval.c (alpha_return_value_location): Use new
+	DWARF_TAG_OR_RETURN macro instead of dwarf_tag ().
+	* backends/arm_retval.c (arm_return_value_location): Likewise.
+	* backends/i386_retval.c (i386_return_value_location): Likewise.
+	* backends/ia64_retval.c (hfa_type): Likewise.
+	(ia64_return_value_location): Likewise.
+	* backends/ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* backends/ppc_retval.c (ppc_return_value_location): Likewise.
+	* backends/s390_retval.c (s390_return_value_location): Likewise.
+	* backends/sh_retval.c (sh_return_value_location): Likewise.
+	* backends/sparc_retval.c (sparc_return_value_location): Likewise.
+	* backends/tilegx_retval.c (tilegx_return_value_location): Likewise.
+	* backends/x86_64_retval.c (x86_64_return_value_location): Likewise.
+
+2013-01-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Roland McGrath <roland@hack.frob.com>
+
+	* Makefile.am (s390_SRCS): Add s390_corenote.c and s390x_corenote.c.
+	* linux-core-note.c (ALIGN_PR_REG): New definitions.
+	(struct EBLHOOK(prstatus)): Change field pr_reg to anonymous struct with
+	ALIGN_PR_REG.
+	(EXTRA_ITEMS): New macro.
+	* s390_corenote.c: New file.
+	* s390_init.c (s390x_core_note): New declaration.
+	(s390_init): Install s390x_core_note and s390_core_note.
+	* s390x_corenote.c: New file.
+
+2013-01-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* arm_corenote.c (vfp_items): Remove zero COUNT initializer.
+
+2012-10-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* linux-core-note.c (prstatus_items): Rename groups of sigpend and
+	sighold to signal2 and signal3.
+
+2012-09-24  Petr Machata  <pmachata@redhat.com>
+
+	* arm_corenote.c (vfp_items, vfp_regs): New const variables.
+	(EXTRA_NOTES): Use it for NT_ARM_VFP.
+	* linux-core-note.c (EXTRA_REGSET_ITEMS): New macro.
+
+2012-09-17  Petr Machata  <pmachata@redhat.com>
+
+	* arm_corenote.c (FPREGSET_SIZE): Change to 116.
+
+2012-08-22  Jeff Kenton  <jkenton@tilera.com>
+
+	* Makefile.am (modules): Add tilegx.
+	(libebl_pic): Add libebl_tilegx_pic.a.
+	(tilegx_SRCS): New variable.
+	(libebl_tilegx_pic_a_SOURCES): Likewise.
+	(am_libebl_tilegx_pic_a_OBJECTS): Likewise.
+	* tilegx_corenote.c: New file.
+	* tilegx_regs.c: New file.
+	* tilegx_reloc.def: New file.
+	* tilegx_init.c: New file.
+	* tilegx_retval.c: New file.
+	* tilegx_symbol.c: New file.
+
+2011-03-09  Mark Wielaard  <mjw@redhat.com>
+
+	* alpha_init.c (alpha_init): Initialize check_st_other_bits hook.
+	* alpha_symbol.c (alpha_check_st_other_bits): New function.
+
+2011-03-09  Roland McGrath  <roland@redhat.com>
+
+	* alpha_symbol.c (alpha_check_special_symbol): New function.
+	* alpha_init.c (alpha_init): Initialize hook.
+
+2010-11-08  Roland McGrath  <roland@redhat.com>
+
+	* i386_retval.c (loc_intreg): Typo fix.
+	Reported by Thorsten Glaser <tg@mirbsd.de>.
+
+2010-04-10  Matt Fleming  <matt@console-pimps.org>
+
+	* sh_corenote.c: New file.
+	* sh_regs.c: New file.
+	* sh_retval.c: New file.
+	* sh_symbol.c (sh_machine_flag_check): New function.
+	* Makefile.am (sh_SRCS): Add new files.
+	* sh_init.c (sh_init): Add initializers.
+
+2010-04-07  Roland McGrath  <roland@redhat.com>
+
+	* arm_reloc.def: Accept PC24 and ABS32 in EXEC|DYN too.
+
+2010-03-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* x86_64_reloc.def: Add entries for R_X86_64_SIZE32 and
+	R_X86_64_SIZE64.
+
+2010-02-18  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libebl_%.so): Use multi-target pattern rule instead of
+	intermediate dependency file for libebl_%.map, working around apparent
+	make -j timing-sensitive bugs.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2010-01-05  Roland McGrath  <roland@redhat.com>
+
+	* arm_retval.c (arm_return_value_location): Use dwarf_aggregate_size.
+	* ia64_retval.c (ia64_return_value_location): Likewise.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+	* ppc64_retval.c (ppc64_return_value_location): Likewise.
+	* sparc_retval.c (sparc_return_value_location): Likewise.
+
+	* ppc64_retval.c (ppc64_return_value_location):
+	Use vr2 for DW_TAG_array_type with DW_AT_GNU_vector.
+	* ppc_retval.c (ppc_return_value_location): Likewise.
+
+2010-01-04  Roland McGrath  <roland@redhat.com>
+
+	* linux-core-note.c (vmcoreinfo_items): New static const variable.
+	(EBLHOOK(core_note)): Update arguments for new protocol.
+	Validate the name as "CORE" or "LINUX" for known n_type cases.
+	Handle name "VMCOREINFO" n_type=0 with vmcoreinfo_items.
+	* i386_corenote.c (EXTRA_NOTES): Update parameter usage.
+	* x86_corenote.c (EXTRA_NOTES_IOPERM): Likewise.
+
+2009-09-10  Mark Wielaard  <mjw@redhat.com>
+
+	* sparc_retval.c: Fix license header.
+
+2009-08-07  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_reloc.def: Add PC64, GOTOFF64, GOTPC32, GOTPC32_TLSDESC,
+	TLSDESC_CALL, TLSDESC.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_cfi.c (x86_64_abi_cfi): New file.
+	* Makefile.am (x86_64_SRCS): Add it.
+	* x86_64_init.c (x86_64_init): Add initializer.
+
+	* i386_cfi.c (i386_abi_cfi): New file.
+	* Makefile.am (i386_SRCS): Add it.
+	* i386_init.c (i386_init): Initialize abi_cfi hook.
+
+2009-06-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_reloc.def: Add IRELATIVE entry.
+	* x86_64_reloc.def: Likewise.
+
+2009-04-16  Roland McGrath  <roland@redhat.com>
+
+	* arm_regs.c (arm_register_info): Handle VFP registers.
+
+	* i386_corenote.c (EXTRA_NOTES): NT_PRXFPREG -> NT_PRXFPREG
+
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+	* arm_retval.c: New file.
+	* arm_attrs.c: New file.
+	* Makefile.am (arm_SRCS): Add them.
+	* arm_symbol.c (arm_segment_type_name): New function.
+	(arm_section_type_name): New function.
+	(arm_machine_flag_check): New function.
+	* arm_init.c (arm_init): Initialize those hooks.
+
+	* arm_regs.c: New file.
+	* arm_corenote.c: New file.
+	* arm_auxv.c: New file.
+	* Makefile.am (arm_SRCS): Add them.
+	* arm_init.c (arm_init): Initialize core_note, register_info,
+	and auxv_info hooks.
+
+	* ia64_symbol.c (ia64_section_type_name): Remove "SHT_" prefixes.
+
+2009-04-01  Roland McGrath  <roland@redhat.com>
+
+	* sparc_reloc.def: Update table.
+	Data from Dave Miller <davem@davemloft.net>.
+
+2009-02-15  Roland McGrath  <roland@redhat.com>
+
+	* ppc_attrs.c (ppc_check_object_attribute): Handle tag
+	GNU_Power_ABI_Struct_Return.
+
+2008-10-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_reloc.def: Fix entries for TLS_GOTDESC, TLS_DESC_CALL, and
+	TLS_DESC.
+
+2008-08-01  Roland McGrath  <roland@redhat.com>
+
+	* x86_corenote.c: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+	* i386_corenote.c: Include it, use EXTRA_NOTES_IOPERM in EXTRA_NOTES.
+	* x86_64_corenote.c: Likewise.
+
+	* linux-core-note.c (prstatus_items): Use 'B' instead of 'b'
+	for sigpend and sighold.
+
+2008-07-04  Roland McGrath  <roland@redhat.com>
+
+	* i386_syscall.c: New file.
+	* x86_64_syscall.c: New file.
+	* ppc_syscall.c: New file.
+	* Makefile.am (i386_SRCS, x86_64_SRCS, ppc_SRCS, ppc64_SRCS): Add them.
+	* i386_init.c (i386_init): Initialize syscall_abi hook.
+	* x86_64_init.c (x86_64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+
+	* ppc_corenote.c (PRSTATUS_REGSET_ITEMS): Add nip.
+	Fix offset calculation for 64-bit case.
+
+2008-04-04  Roland McGrath  <roland@redhat.com>
+
+	* alpha_symbol.c (alpha_check_special_section): New function.
+	* alpha_init.c (alpha_init): Initialize check_special_section hook.
+
+2008-03-31  Roland McGrath  <roland@redhat.com>
+
+	* sparc_symbol.c (sparc_symbol_type_name): New function.
+	(sparc_dynamic_tag_name): New function.
+	(sparc_dynamic_tag_check): New function.
+	* sparc_init.c (sparc_init): Initialize those hooks.
+
+	* sparc_symbol.c (sparc_check_special_section): New function.
+	* sparc_init.c (sparc_init): Initialize check_special_section hook.
+
+2008-02-20  Roland McGrath  <roland@redhat.com>
+
+	* ppc_attrs.c: New file.
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add it.
+	* ppc_init.c (ppc_init): Initialize check_object_attribute hook.
+
+2008-02-14  Roland McGrath  <roland@redhat.com>
+
+	* alpha_auxv.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize auxv_info hook.
+
+2008-02-08  Roland McGrath  <roland@redhat.com>
+
+	* ppc_corenote.c (spe_regs): New const variable.
+	(EXTRA_NOTES): Use it for NT_PPC_SPE.
+
+2008-01-02  Roland McGrath  <roland@redhat.com>
+
+	* i386_corenote.c (tls_items): New const table.
+	(tls_info): New function, uses it.
+	(EXTRA_NOTES): Use it to handle NT_386_TLS.
+
+2008-01-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add x86-64 disassembler.
+	* x86_64_init.c (x86_64_init): Hook up disassembler.
+
+2007-12-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add x86 disassembler.
+	* i386_init.c (i386_init): Hook up disassembler.
+
+2007-12-15  Roland McGrath  <roland@redhat.com>
+
+	* ppc_regs.c (ppc_register_info): Return "spefscr", not "spr512".
+
+2007-10-18  Roland McGrath  <roland@redhat.com>
+
+	* ppc_regs.c (ppc_register_info): Assign 67 to "vscr".
+	Return "vector" and 32 bits for vscr and vrsave.
+	* ppc_corenote.c (altivec_regs): New variable.
+	(EXTRA_NOTES): New macro, handle NT_PPC_VMX.
+
+	* linux-core-note.c (EXTRA_REGSET): New macro.
+	Remove NT_PRXFPREG case.  Instead, use EXTRA_NOTES if defined.
+	* i386_corenote.c (EXTRA_NOTES): Define it.
+
+2007-10-09  Roland McGrath  <roland@redhat.com>
+
+	* sparc_auxv.c: New file.
+	* Makefile.am (sparc_SRCS): Add it.
+	* sparc_init.c (sparc_init): Initialize auxv_info hook.
+
+2007-10-08  Roland McGrath  <roland@redhat.com>
+
+	* linux-core-note.c (TIMEVAL_FIELD): New macro.
+	(prstatus_items): Use it.
+	* sparc_corenote.c: New file.
+	* sparc64_corenote.c: New file.
+	* Makefile.am (sparc_SRCS): Add them.
+	* sparc_init.c (sparc_init): Initialize core_note hook.
+
+	* sparc_symbol.c (sparc_machine_flag_check): New function.
+	* sparc_init.c (sparc_init): Use it.
+
+2007-09-27  Roland McGrath  <roland@redhat.com>
+
+	* alpha_retval.c: Use dwarf_attr_integrate and dwarf_hasattr_integrate.
+	* i386_retval.c: Likewise.
+	* ia64_retval.c: Likewise.
+	* ppc64_retval.c: Likewise.
+	* ppc_retval.c: Likewise.
+	* s390_retval.c: Likewise.
+	* sparc_retval.c: Likewise.
+	* x86_64_retval.c: Likewise.
+
+2007-10-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: More dependencies for the libebl_* libraries.
+
+2007-08-23  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_regs.c (x86_64_register_info): Put %rflags in "integer" set.
+
+2007-08-22  Roland McGrath  <roland@redhat.com>
+
+	* linux-core-note.c (prstatus_items): Add .group initializers.
+	(prpsinfo_items): Likewise.
+	* x86_64_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+	* i386_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+	* ppc_corenote.c (PRSTATUS_REGSET_ITEMS): Likewise.
+
+2007-08-20  Roland McGrath  <roland@redhat.com>
+
+	* ppc_symbol.c (ppc_check_special_symbol): For _GLOBAL_OFFSET_TABLE_
+	when DT_PPC_GOT is not found, anywhere in the section is valid.
+
+2007-08-19  Roland McGrath  <roland@redhat.com>
+
+	* i386_auxv.c: New file.
+	* Makefile.am (i386_SRCS, x86_64_SRCS): Add it.
+	* ppc_auxv.c: New file.
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add it.
+	* i386_init.c (i386_init): Initialize auxv_info hook.
+	* x86_64_init.c (x86_64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+
+	* alpha_corenote.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize core_note hook.
+
+	* ppc_corenote.c: New file.
+	* ppc64_corenote.c: New file.
+	* Makefile.am (ppc_SRCS, ppc64_SRCS): Add them.
+	* ppc_init.c (ppc_init): Initialize core_note hook.
+	* ppc64_init.c (ppc64_init): Likewise.
+
+	* linux-core-note.c: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+	* i386_corenote.c: Rewritten.
+	* x86_64_corenote.c: Likewise.
+
+2007-05-23  Roland McGrath  <roland@redhat.com>
+
+	* alpha_regs.c (alpha_register_info): fp -> s6
+
+2007-04-26  Roland McGrath  <roland@redhat.com>
+
+	* alpha_symbol.c (alpha_machine_section_flag_check): New function.
+	* alpha_init.c (alpha_init): Initialize hook.
+
+	* alpha_regs.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize register_info hook.
+
+2007-04-22  Roland McGrath  <roland@redhat.com>
+
+	* ppc_regs.c (ppc_register_info): Use some names instead of sprNNN:
+	mq, xer, lr, ctr, dsisr, dar, dec, vrsave.
+	Set *BITS to 64 for FPU registers.
+
+	* i386_regs.c (i386_register_info): Set *BITS to 16 for fctrl, fstat.
+	* x86_64_regs.c (x86_64_register_info): Likewise for fcw, fsw.
+
+2007-04-01  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_regs.c (x86_64_register_info): Add more registers from newer
+	ABI spec.
+
+2007-01-11  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_machine_section_flag_check): New function.
+	* ia64_init.c (ia64_init): Use it.
+
+	* ia64_symbol.c (ia64_section_type_name): Typo fix in string.
+
+2006-10-09  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_reloc_simple_type): Treat SECREL types as simple.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* sparc_retval.c: New file.
+	* Makefile.am (sparc_SRCS): Add it.
+	* sparc_init.c (sparc_init): Initialize return_value_location hook.
+
+2006-08-22  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Renamed i386_register_info.
+	Take new args, yield more info.
+	* i386_init.c (i386_init): Update initializer.
+	* ia64_regs.c (ia64_register_name): Likewise.
+	* ia64_init.c (ia64_init): Likewise.
+	* ppc_regs.c (ppc_register_name): Likewise.
+	* ppc64_init.c (ppc64_init): Likewise.
+	* ppc_init.c (ppc_init): Likewise.
+	* s390_regs.c (s390_register_name): Likewise.
+	* s390_init.c (s390_init): Likewise.
+	* sparc_regs.c (sparc_register_name): Likewise.
+	* sparc_init.c (sparc_init): Likewise.
+	* x86_64_regs.c (x86_64_register_name): Likewise.
+	* x86_64_init.c (x86_64_init): Likewise.
+
+2006-08-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (%.os): Don't depend on %.o, since we don't actually
+	need static object for anything here.  This rule is the only source of
+	.deps/ files.
+
+2006-06-23  Stepan Kasal  <skasal@redhat.com>
+
+	* Makefile.am (PACKAGE_VERSION): Remove superfluous definition.
+
+2006-08-03  Roland McGrath  <roland@redhat.com>
+
+	* sparc_regs.c (sparc_register_name): List 32 FPU regs only for
+	EM_SPARC.  EM_SPARC32PLUS also has 64.
+
+2006-07-21  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Fix return value when using stpcpy.
+	* ppc_regs.c (ppc_register_name): Likewise.
+	* s390_regs.c (s390_register_name): Likewise.
+
+	* ia64_retval.c: New file.
+	* Makefile.am (ia64_SRCS): Add it.
+	* ia64_init.c (ia64_init): Install return_value_location hook.
+
+	* ia64_regs.c: New file.
+	* Makefile.am (ia64_SRCS): Add it.
+	* ia64_init.c (ia64_init): Install register_name hook.
+
+2006-07-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* alpha_init.c: Initialize sysvhash_entrysize.
+	* s390_init.c: Likewise.
+
+2006-07-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* common-reloc.c (relative_reloc_p): New function.
+	(init_reloc): Hook it up.
+	* ia64_reloc.def: Define NO_RELATIVE_RELOC.
+
+2006-06-13  Roland McGrath  <roland@redhat.com>
+
+	* ppc64_retval.c: Remove SVR4_STRUCT_RETURN braino.
+
+2006-06-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* common-reloc.c (none_reloc_p): New function.
+	(init_reloc): Hook it up.
+
+2006-02-22  Roland McGrath  <roland@redhat.com>
+
+	* ppc64_retval.c (SVR4_STRUCT_RETURN): New macro.
+	(ppc64_return_value_location): Use registers for aggregate conditional
+	on that.
+	* ppc_retval.c (SVR4_STRUCT_RETURN): New macro.
+	(ppc_return_value_location): Use registers for aggregate conditional
+	on that.
+
+2006-01-12  Roland McGrath  <roland@redhat.com>
+
+	* s390_retval.c: New file.
+	* Makefile.am (s390_SRCS): Add it.
+	* s390_init.c (s390_init): Install return_value_location hook.
+
+2006-01-11  Roland McGrath  <roland@redhat.com>
+
+	* s390_regs.c: New file.
+	* Makefile.am (s390_SRCS): Add it.
+	* s390_init.c (s390_init): Install register_name hook.
+
+	* s390_reloc.def: Update bits per
+	Martin Schwidefsky <schwidefsky@de.ibm.com>.
+
+2005-12-10  Ulrich Drepper
+
+	* common-reloc.c (R_NAME): Generate string correctly.
+
+2005-12-05  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Use a table for the first 8 regs.
+	* x86_64_regs.c (x86_64_register_name): Likewise.
+
+2005-11-25  Roland McGrath  <roland@redhat.com>
+
+	* i386_regs.c (i386_register_name): Return 0, not 1, for gaps.
+
+	* i386_regs.c: New file.
+	* ppc_regs.c: New file.
+	* sparc_regs.c: New file.
+	* x86_64_regs.c: New file.
+	* Makefile.am
+	(i386_SRCS, x86_64_SRCS, ppc_SRCS, ppc64_SRCS, sparc_SRCS): Add them.
+	* i386_init.c: Initialize register_name hook.
+	* ppc_init.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* sparc_init.c: Likewise.
+	* x86_64_init.c: Likewise.
+
+2005-11-19  Roland McGrath  <roland@redhat.com>
+
+	* ppc64_reloc.def: REL30 -> ADDR30.
+
+2005-11-18  Roland McGrath  <roland@redhat.com>
+
+	* alpha_init.c: Use HOOK macro.
+	* arm_init.c: Likewise.
+	* i386_init.c: Likewise.
+	* ia64_init.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* ppc_init.c: Likewise.
+	* s390_init.c: Likewise.
+	* sh_init.c: Likewise.
+	* sparc_init.c: Likewise.
+	* x86_64_init.c: Likewise.
+
+2005-11-17  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (uninstall): Don't try to remove $(pkgincludedir).
+	(CLEANFILES): Add libebl_$(m).so.
+
+	* ppc_reloc.def: Update bits per Alan Modra <amodra@bigpond.net.au>.
+	* ppc64_reloc.def: Likewise.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* Contents moved here from ../libebl.
diff --git a/backends/Makefile.am b/backends/Makefile.am
new file mode 100644
index 0000000..bbb2aac
--- /dev/null
+++ b/backends/Makefile.am
@@ -0,0 +1,118 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2000-2010, 2013, 2014 Red Hat, Inc.
+## Copyright (C) 2012 Tilera Corporation
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+include $(top_srcdir)/config/eu.am
+if BUILD_STATIC
+AM_CFLAGS += $(fpic_CFLAGS)
+endif
+AM_CPPFLAGS += -I$(top_srcdir)/libebl -I$(top_srcdir)/libasm \
+	   -I$(top_srcdir)/libelf -I$(top_srcdir)/libdw
+
+noinst_LIBRARIES = libebl_backends.a libebl_backends_pic.a
+
+modules = i386 sh x86_64 ia64 alpha arm aarch64 sparc ppc ppc64 s390 \
+	  m68k bpf riscv csky loongarch arc
+
+i386_SRCS = i386_init.c i386_symbol.c i386_corenote.c i386_cfi.c \
+	    i386_retval.c i386_regs.c i386_auxv.c \
+	    i386_initreg.c i386_unwind.c
+
+sh_SRCS = sh_init.c sh_symbol.c sh_corenote.c sh_regs.c sh_retval.c
+
+x86_64_SRCS = x86_64_init.c x86_64_symbol.c x86_64_corenote.c x86_64_cfi.c \
+	      x86_64_retval.c x86_64_regs.c x86_64_initreg.c \
+	      x86_64_unwind.c x32_corenote.c
+
+
+ia64_SRCS = ia64_init.c ia64_symbol.c ia64_regs.c ia64_retval.c
+
+alpha_SRCS = alpha_init.c alpha_symbol.c alpha_retval.c alpha_regs.c \
+	     alpha_corenote.c alpha_auxv.c
+
+arm_SRCS = arm_init.c arm_symbol.c arm_regs.c arm_corenote.c \
+	   arm_auxv.c arm_attrs.c arm_retval.c arm_cfi.c arm_initreg.c \
+	   arm_machineflagname.c
+
+aarch64_SRCS = aarch64_init.c aarch64_regs.c aarch64_symbol.c	\
+	       aarch64_corenote.c aarch64_retval.c aarch64_cfi.c \
+	       aarch64_initreg.c aarch64_unwind.c
+
+sparc_SRCS = sparc_init.c sparc_symbol.c sparc_regs.c sparc_retval.c \
+	     sparc_corenote.c sparc64_corenote.c sparc_auxv.c sparc_attrs.c \
+             sparc_cfi.c sparc_initreg.c
+
+ppc_SRCS = ppc_init.c ppc_symbol.c ppc_retval.c ppc_regs.c \
+	   ppc_corenote.c ppc_auxv.c ppc_attrs.c \
+	   ppc_cfi.c ppc_initreg.c
+
+ppc64_SRCS = ppc64_init.c ppc64_symbol.c ppc64_retval.c ppc64_corenote.c \
+	     ppc64_unwind.c ppc64_resolve_sym.c
+
+s390_SRCS = s390_init.c s390_symbol.c s390_regs.c s390_retval.c \
+	    s390_corenote.c s390x_corenote.c s390_cfi.c s390_initreg.c \
+	    s390_unwind.c
+
+m68k_SRCS = m68k_init.c m68k_symbol.c m68k_regs.c \
+	    m68k_retval.c m68k_corenote.c m68k_cfi.c m68k_initreg.c
+
+# m68k prstatus core notes are described by a packed structure
+# which has not naturally aligned fields. Since we don't access
+# these fields directly, but take their offset to be used later
+# to extract the data through elfxx_xlatetom/memmove, this isn't
+# an issue.
+m68k_corenote_no_Wpacked_not_aligned = yes
+
+bpf_SRCS = bpf_init.c bpf_regs.c bpf_symbol.c
+
+riscv_SRCS = riscv_init.c riscv_symbol.c riscv_cfi.c riscv_regs.c \
+	     riscv_initreg.c riscv_corenote.c riscv64_corenote.c riscv_retval.c
+
+csky_SRCS = csky_attrs.c csky_init.c csky_symbol.c csky_cfi.c \
+	    csky_regs.c csky_initreg.c csky_corenote.c
+
+loongarch_SRCS = loongarch_init.c loongarch_symbol.c loongarch_cfi.c \
+	    loongarch_regs.c loongarch_retval.c loongarch_initreg.c \
+	    loongarch_unwind.c loongarch_corenote.c
+
+arc_SRCS = arc_init.c arc_symbol.c
+
+libebl_backends_a_SOURCES = $(i386_SRCS) $(sh_SRCS) $(x86_64_SRCS) \
+			    $(ia64_SRCS) $(alpha_SRCS) $(arm_SRCS) \
+			    $(aarch64_SRCS) $(sparc_SRCS) $(ppc_SRCS) \
+			    $(ppc64_SRCS) $(s390_SRCS) \
+			    $(m68k_SRCS) $(bpf_SRCS) $(riscv_SRCS) $(csky_SRCS) \
+			    $(loongarch_SRCS) $(arc_SRCS)
+
+libebl_backends_pic_a_SOURCES =
+am_libebl_backends_pic_a_OBJECTS = $(libebl_backends_a_SOURCES:.c=.os)
+
+noinst_HEADERS = libebl_CPU.h common-reloc.c linux-core-note.c x86_corenote.c
+EXTRA_DIST = $(modules:=_reloc.def)
+
+MOSTLYCLEANFILES = $(am_libebl_backends_pic_a_OBJECTS)
diff --git a/backends/aarch64_cfi.c b/backends/aarch64_cfi.c
new file mode 100644
index 0000000..a5579ab
--- /dev/null
+++ b/backends/aarch64_cfi.c
@@ -0,0 +1,85 @@
+/* arm64 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2013, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+
+/* ABI-specified state of DWARF CFI based on:
+
+   "DWARF for the ARM 64 bit architecture (AArch64) 1.0"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0057b/IHI0057B_aadwarf64.pdf
+
+   "Procedure Call Standard for the ARM 64 bit Architecture 1.0"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0055b/IHI0055B_aapcs64.pdf
+*/
+
+int
+aarch64_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer (r31) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (30), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* Callee-saved regs r19-r28.  */
+      SV (19), SV (20), SV (21), SV (22), SV (23),
+      SV (24), SV (25), SV (26), SV (27), SV (28),
+
+      /* The Frame Pointer (FP, r29) and Link Register (LR, r30).  */
+      SV (29), SV (30),
+
+      /* The Stack Pointer (r31) is restored from CFA address by default.  */
+      DW_CFA_val_offset, ULEB128_7 (31), ULEB128_7 (0),
+
+      /* Callee-saved fpregs v8-v15.  v0 == 64.  */
+      SV (72), SV (73), SV (74), SV (75),
+      SV (76), SV (77), SV (78), SV (79),
+#undef SV
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 30; /* lr.  */
+
+  return 0;
+}
diff --git a/backends/aarch64_corenote.c b/backends/aarch64_corenote.c
new file mode 100644
index 0000000..905a4b8
--- /dev/null
+++ b/backends/aarch64_corenote.c
@@ -0,0 +1,172 @@
+/* AArch64 specific core note handling.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+#define	ULONG			uint64_t
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_ULONG		8
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_ULONG		ELF_T_XWORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#define PRSTATUS_REGS_SIZE	(34 * 8)
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 32, .bits = 64 }, /* x0..x30, sp */
+  };
+
+#define PRSTATUS_REGSET_ITEMS						\
+  {									\
+    .name = "pc", .type = ELF_T_XWORD, .format = 'x',			\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + PRSTATUS_REGS_SIZE - 16),				\
+    .group = "register",						\
+    .pc_register = true							\
+  },									\
+  {									\
+    .name = "pstate", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + PRSTATUS_REGS_SIZE - 8),				\
+    .group = "register"							\
+  }
+
+static const Ebl_Register_Location aarch64_fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 64, .count = 32, .bits = 128 }, /* v0..v31 */
+  };
+
+static const Ebl_Core_Item aarch64_fpregset_items[] =
+  {
+    {
+      .name = "fpsr", .type = ELF_T_WORD, .format = 'x',
+      .offset = 512, .group = "register"
+    },
+    {
+      .name = "fpcr", .type = ELF_T_WORD, .format = 'x',
+      .offset = 516, .group = "register"
+    }
+  };
+
+static const Ebl_Core_Item aarch64_tls_items[] =
+  {
+    {
+      .name = "tls", .type = ELF_T_XWORD, .format = 'x',
+      .offset = 0, .group = "register"
+    }
+  };
+
+static const Ebl_Core_Item aarch64_syscall_items [] =
+  {
+    {
+      .name = "syscall", .type = ELF_T_WORD, .format = 'x',
+      .offset = 0, .group = "register"
+    }
+  };
+
+#define AARCH64_HWBP_REG(KIND, N)					\
+    {									\
+      .name = "DBG" KIND "VR" #N "_EL1", .type = ELF_T_XWORD, .format = 'x', \
+      .offset = 8 + N * 16, .group = "register"				\
+    },									\
+    {									\
+      .name = "DBG" KIND "CR" #N "_EL1", .type = ELF_T_WORD, .format = 'x', \
+      .offset = 16 + N * 16, .group = "register"			\
+    }
+
+#define AARCH64_BP_WP_GROUP(KIND, NAME)					\
+  static const Ebl_Core_Item NAME[] =					\
+    {									\
+      {									\
+	.name = "dbg_info", .type = ELF_T_WORD, .format = 'x',		\
+	.offset = 0, .group = "control"					\
+      },								\
+      /* N.B.: 4 bytes of padding here.  */				\
+									\
+      AARCH64_HWBP_REG(KIND, 0),					\
+      AARCH64_HWBP_REG(KIND, 1),					\
+      AARCH64_HWBP_REG(KIND, 2),					\
+      AARCH64_HWBP_REG(KIND, 3),					\
+      AARCH64_HWBP_REG(KIND, 4),					\
+      AARCH64_HWBP_REG(KIND, 5),					\
+      AARCH64_HWBP_REG(KIND, 6),					\
+      AARCH64_HWBP_REG(KIND, 7),					\
+      AARCH64_HWBP_REG(KIND, 8),					\
+      AARCH64_HWBP_REG(KIND, 9),					\
+      AARCH64_HWBP_REG(KIND, 10),					\
+      AARCH64_HWBP_REG(KIND, 11),					\
+      AARCH64_HWBP_REG(KIND, 12),					\
+      AARCH64_HWBP_REG(KIND, 13),					\
+      AARCH64_HWBP_REG(KIND, 14),					\
+      AARCH64_HWBP_REG(KIND, 15),					\
+									\
+      /* The DBGBVR+DBGBCR pair only takes 12 bytes.  There are 4 bytes	\
+	 of padding at the end of each pair.  The item formatter in	\
+	 readelf can skip those, but the missing 4 bytes at the end of	\
+	 the whole block cause it to assume the whole item bunch	\
+	 repeats, so it loops around to read more.  Insert an explicit	\
+	 (but invisible) padding word.  */				\
+      {									\
+	.name = "", .type = ELF_T_WORD, .format = 'h',			\
+	.offset = 260, .group = "register"				\
+      }									\
+    }
+
+AARCH64_BP_WP_GROUP ("B", aarch64_hw_bp_items);
+AARCH64_BP_WP_GROUP ("W", aarch64_hw_wp_items);
+
+#undef AARCH64_BP_WP_GROUP
+#undef AARCH64_HWBP_REG
+
+#define EXTRA_NOTES							\
+  EXTRA_REGSET_ITEMS (NT_FPREGSET, 528,					\
+		      aarch64_fpregset_regs, aarch64_fpregset_items)	\
+  EXTRA_ITEMS (NT_ARM_TLS, 8, aarch64_tls_items)			\
+  EXTRA_ITEMS (NT_ARM_HW_BREAK, 264, aarch64_hw_bp_items)		\
+  EXTRA_ITEMS (NT_ARM_HW_WATCH, 264, aarch64_hw_wp_items)		\
+  EXTRA_ITEMS (NT_ARM_SYSTEM_CALL, 4, aarch64_syscall_items)
+
+#include "linux-core-note.c"
diff --git a/backends/aarch64_init.c b/backends/aarch64_init.c
new file mode 100644
index 0000000..bed9295
--- /dev/null
+++ b/backends/aarch64_init.c
@@ -0,0 +1,66 @@
+/* Initialization of AArch64 specific backend library.
+   Copyright (C) 2013, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		aarch64_
+#define RELOC_PREFIX	R_AARCH64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on aarch64_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+aarch64_init (Elf *elf __attribute__ ((unused)),
+	      GElf_Half machine __attribute__ ((unused)),
+	      Ebl *eh)
+{
+  /* We handle it.  */
+  aarch64_init_reloc (eh);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, data_marker_symbol);
+  HOOK (eh, abi_cfi);
+
+  /* X0-X30 (31 regs) + SP + 1 Reserved + ELR, 30 Reserved regs (34-43)
+     + V0-V31 (32 regs, least significant 64 bits only)
+     + ALT_FRAME_RETURN_COLUMN (used when LR isn't used) = 97 DWARF regs. */
+  eh->frame_nregs = 97;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, unwind);
+
+  return eh;
+}
diff --git a/backends/aarch64_initreg.c b/backends/aarch64_initreg.c
new file mode 100644
index 0000000..daf6f37
--- /dev/null
+++ b/backends/aarch64_initreg.c
@@ -0,0 +1,92 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined(__aarch64__) && defined(__linux__)
+# include <linux/uio.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+/* Deal with old glibc defining user_pt_regs instead of user_regs_struct.  */
+# ifndef HAVE_SYS_USER_REGS
+#  define user_regs_struct user_pt_regs
+#  define user_fpsimd_struct user_fpsimd_state
+# endif
+#endif
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+bool
+aarch64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if !defined(__aarch64__) || !defined(__linux__)
+  return false;
+#else /* __aarch64__ */
+
+  /* General registers.  */
+  struct user_regs_struct gregs;
+  struct iovec iovec;
+  iovec.iov_base = &gregs;
+  iovec.iov_len = sizeof (gregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  /* X0..X30 plus SP.  */
+  if (! setfunc (0, 32, (Dwarf_Word *) &gregs.regs[0], arg))
+    return false;
+
+  /* PC.  */
+  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.pc, arg))
+    return false;
+
+  /* ELR cannot be found.  */
+
+  /* FP registers (only 64bits are used).  */
+  struct user_fpsimd_struct fregs;
+  iovec.iov_base = &fregs;
+  iovec.iov_len = sizeof (fregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) != 0)
+    return false;
+
+  Dwarf_Word dwarf_fregs[32];
+  for (int r = 0; r < 32; r++)
+    dwarf_fregs[r] = fregs.vregs[r] & 0xFFFFFFFF;
+
+  if (! setfunc (64, 32, dwarf_fregs, arg))
+    return false;
+
+  return true;
+#endif /* __aarch64__ */
+}
diff --git a/backends/aarch64_regs.c b/backends/aarch64_regs.c
new file mode 100644
index 0000000..23014bf
--- /dev/null
+++ b/backends/aarch64_regs.c
@@ -0,0 +1,108 @@
+/* Register names and numbers for AArch64 DWARF.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <dwarf.h>
+#include <stdarg.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+__attribute__ ((format (printf, 7, 8)))
+static ssize_t
+do_regtype (const char *setname, int type,
+           const char **setnamep, int *typep,
+           char *name, size_t namelen, const char *fmt, ...)
+{
+  *setnamep = setname;
+  *typep = type;
+
+  va_list ap;
+  va_start (ap, fmt);
+  int s = vsnprintf (name, namelen, fmt, ap);
+  va_end(ap);
+
+  if (s < 0 || (unsigned) s >= namelen)
+    return -1;
+  return s + 1;
+}
+
+ssize_t
+aarch64_register_info (Ebl *ebl __attribute__ ((unused)),
+		       int regno, char *name, size_t namelen,
+		       const char **prefix, const char **setnamep,
+		       int *bits, int *typep)
+{
+  if (name == NULL)
+    return 128;
+
+
+  *prefix = "";
+  *bits = 64;
+
+#define regtype(setname, type, ...) \
+    do_regtype(setname, type, setnamep, typep, name, namelen, __VA_ARGS__)
+
+  switch (regno)
+    {
+    case 0 ... 30:
+      return regtype ("integer", DW_ATE_signed, "x%d", regno);
+
+    case 31:
+      return regtype ("integer", DW_ATE_address, "sp");
+
+    case 32:
+      return 0;
+
+    case 33:
+      return regtype ("integer", DW_ATE_address, "elr");
+
+    case 34 ... 63:
+      return 0;
+
+    case 64 ... 95:
+      /* FP/SIMD register file supports a variety of data types--it
+	 can be thought of as a register holding a single integer or
+	 floating-point value, or a vector of 8-, 16-, 32- or 64-bit
+	 integers.  128-bit quad-word is the only singular value that
+	 covers the whole register, so mark the register thus.  */
+      *bits = 128;
+      return regtype ("FP/SIMD", DW_ATE_unsigned, "v%d", regno - 64);
+
+    case 96 ... 127:
+      return 0;
+
+    default:
+      return -1;
+    }
+}
diff --git a/backends/aarch64_reloc.def b/backends/aarch64_reloc.def
new file mode 100644
index 0000000..f894687
--- /dev/null
+++ b/backends/aarch64_reloc.def
@@ -0,0 +1,157 @@
+/* List the relocation types for AArch64.  -*- C -*-
+   Copyright (C) 2013, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (ABS64,		REL|EXEC|DYN)
+RELOC_TYPE (ABS32,		REL|EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL,		EXEC|DYN)
+RELOC_TYPE (TLS_TPREL,		EXEC|DYN)
+RELOC_TYPE (TLSDESC,		EXEC|DYN)
+
+/* R_AARCH64_NONE records that the section containing the place to be
+   relocated depends on the section defining the symbol mentioned in
+   the relocation directive[.]  (ARM IHI 0056B).  */
+RELOC_TYPE (NONE,		REL)
+
+RELOC_TYPE (ABS16,		REL)
+RELOC_TYPE (PREL64,		REL)
+RELOC_TYPE (PREL32,		REL)
+RELOC_TYPE (PREL16,		REL)
+RELOC_TYPE (MOVW_UABS_G0,	REL)
+RELOC_TYPE (MOVW_UABS_G0_NC,	REL)
+RELOC_TYPE (MOVW_UABS_G1,	REL)
+RELOC_TYPE (MOVW_UABS_G1_NC,	REL)
+RELOC_TYPE (MOVW_UABS_G2,	REL)
+RELOC_TYPE (MOVW_UABS_G2_NC,	REL)
+RELOC_TYPE (MOVW_UABS_G3,	REL)
+RELOC_TYPE (MOVW_SABS_G0,	REL)
+RELOC_TYPE (MOVW_SABS_G1,	REL)
+RELOC_TYPE (MOVW_SABS_G2,	REL)
+RELOC_TYPE (LD_PREL_LO19,	REL)
+RELOC_TYPE (ADR_PREL_LO21,	REL)
+RELOC_TYPE (ADR_PREL_PG_HI21,	REL)
+RELOC_TYPE (ADR_PREL_PG_HI21_NC, REL)
+RELOC_TYPE (ADD_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST8_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST16_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST32_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST64_ABS_LO12_NC,	REL)
+RELOC_TYPE (LDST128_ABS_LO12_NC, REL)
+RELOC_TYPE (TSTBR14,		REL)
+RELOC_TYPE (CONDBR19,		REL)
+RELOC_TYPE (JUMP26,		REL)
+RELOC_TYPE (CALL26,		REL)
+RELOC_TYPE (MOVW_PREL_G0,	REL)
+RELOC_TYPE (MOVW_PREL_G0_NC,	REL)
+RELOC_TYPE (MOVW_PREL_G1,	REL)
+RELOC_TYPE (MOVW_PREL_G1_NC,	REL)
+RELOC_TYPE (MOVW_PREL_G2,	REL)
+RELOC_TYPE (MOVW_PREL_G2_NC,	REL)
+RELOC_TYPE (MOVW_PREL_G3,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G0,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G0_NC,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G1,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G1_NC,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G2,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G2_NC,	REL)
+RELOC_TYPE (MOVW_GOTOFF_G3,	REL)
+RELOC_TYPE (GOTREL64,		REL)
+RELOC_TYPE (GOTREL32,		REL)
+RELOC_TYPE (GOT_LD_PREL19,	REL)
+RELOC_TYPE (LD64_GOTOFF_LO15,	REL)
+RELOC_TYPE (ADR_GOT_PAGE,	REL)
+RELOC_TYPE (LD64_GOT_LO12_NC,	REL)
+RELOC_TYPE (LD64_GOTPAGE_LO15,	REL)
+RELOC_TYPE (TLSGD_ADR_PREL21,	REL)
+RELOC_TYPE (TLSGD_ADR_PAGE21,	REL)
+RELOC_TYPE (TLSGD_ADD_LO12_NC,	REL)
+RELOC_TYPE (TLSGD_MOVW_G1,	REL)
+RELOC_TYPE (TLSGD_MOVW_G0_NC,	REL)
+RELOC_TYPE (TLSLD_ADR_PREL21,	REL)
+RELOC_TYPE (TLSLD_ADR_PAGE21,	REL)
+RELOC_TYPE (TLSLD_ADD_LO12_NC,	REL)
+RELOC_TYPE (TLSLD_MOVW_G1,	REL)
+RELOC_TYPE (TLSLD_MOVW_G0_NC,	REL)
+RELOC_TYPE (TLSLD_LD_PREL19,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G2,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G1,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G1_NC,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G0,	REL)
+RELOC_TYPE (TLSLD_MOVW_DTPREL_G0_NC,	REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_HI12,	REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_ADD_DTPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLD_LDST8_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST8_DTPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLD_LDST16_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST16_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST32_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST32_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST64_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST64_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSLD_LDST128_DTPREL_LO12,	REL)
+RELOC_TYPE (TLSLD_LDST128_DTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSIE_MOVW_GOTTPREL_G1,	REL)
+RELOC_TYPE (TLSIE_MOVW_GOTTPREL_G0_NC,	REL)
+RELOC_TYPE (TLSIE_ADR_GOTTPREL_PAGE21,	REL)
+RELOC_TYPE (TLSIE_LD64_GOTTPREL_LO12_NC, REL)
+RELOC_TYPE (TLSIE_LD_GOTTPREL_PREL19,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G2,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G1,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G1_NC,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G0,	REL)
+RELOC_TYPE (TLSLE_MOVW_TPREL_G0_NC,	REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_HI12,	REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_ADD_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST8_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST8_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST16_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST16_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST32_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST32_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST64_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST64_TPREL_LO12_NC,	REL)
+RELOC_TYPE (TLSLE_LDST128_TPREL_LO12,	REL)
+RELOC_TYPE (TLSLE_LDST128_TPREL_LO12_NC, REL)
+RELOC_TYPE (TLSDESC_LD_PREL19,		REL)
+RELOC_TYPE (TLSDESC_ADR_PREL21,		REL)
+RELOC_TYPE (TLSDESC_ADR_PAGE21,		REL)
+RELOC_TYPE (TLSDESC_LD64_LO12,		REL)
+RELOC_TYPE (TLSDESC_ADD_LO12,		REL)
+RELOC_TYPE (TLSDESC_OFF_G1,		REL)
+RELOC_TYPE (TLSDESC_OFF_G0_NC,		REL)
+RELOC_TYPE (TLSDESC_LDR,		REL)
+RELOC_TYPE (TLSDESC_ADD,		REL)
+RELOC_TYPE (TLSDESC_CALL,		REL)
diff --git a/backends/aarch64_retval.c b/backends/aarch64_retval.c
new file mode 100644
index 0000000..8eaebaf
--- /dev/null
+++ b/backends/aarch64_retval.c
@@ -0,0 +1,375 @@
+/* Function return value location for Linux/AArch64 ABI.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND aarch64_
+#include "libebl_CPU.h"
+
+static int
+skip_until (Dwarf_Die *child, int tag)
+{
+  int i;
+  while (DWARF_TAG_OR_RETURN (child) != tag)
+    if ((i = dwarf_siblingof (child, child)) != 0)
+      /* If there are no members, then this is not a HFA.  Errors
+	 are propagated.  */
+      return i;
+  return 0;
+}
+
+static int
+dwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep)
+{
+  int bits;
+  if (((bits = 8 * dwarf_bytesize (die)) < 0
+       && (bits = dwarf_bitsize (die)) < 0)
+      || bits % 8 != 0)
+    return -1;
+
+  *sizep = bits / 8;
+  return 0;
+}
+
+/* HFA (Homogeneous Floating-point Aggregate) is an aggregate type
+   whose members are all of the same floating-point type, which is
+   then base type of this HFA.  Instead of being floating-point types
+   directly, members can instead themselves be HFA.  Such HFA fields
+   are handled as if their type were HFA base type.
+
+   This function returns 0 if TYPEDIE is HFA, 1 if it is not, or -1 if
+   there were errors.  In the former case, *SIZEP contains byte size
+   of the base type (e.g. 8 for IEEE double).  *COUNT is set to the
+   number of leaf members of the HFA.  */
+static int hfa_type (Dwarf_Die *ftypedie, int tag,
+		     Dwarf_Word *sizep, Dwarf_Word *countp);
+
+/* Return 0 if MEMBDIE refers to a member with a floating-point or HFA
+   type, or 1 if it's not.  Return -1 for errors.  The meaning of the
+   remaining arguments is as documented at hfa_type.  */
+static int
+member_is_fp (Dwarf_Die *membdie, Dwarf_Word *sizep, Dwarf_Word *countp)
+{
+  Dwarf_Die typedie;
+  int tag = dwarf_peeled_die_type (membdie, &typedie);
+  switch (tag)
+    {
+    case DW_TAG_base_type:;
+      Dwarf_Word encoding;
+      Dwarf_Attribute attr_mem;
+      if (dwarf_attr_integrate (&typedie, DW_AT_encoding, &attr_mem) == NULL
+	  || dwarf_formudata (&attr_mem, &encoding) != 0)
+	return -1;
+
+      switch (encoding)
+	{
+	case DW_ATE_complex_float:
+	  *countp = 2;
+	  break;
+
+	case DW_ATE_float:
+	  *countp = 1;
+	  break;
+
+	default:
+	  return 1;
+	}
+
+      if (dwarf_bytesize_aux (&typedie, sizep) < 0)
+	return -1;
+
+      *sizep /= *countp;
+      return 0;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      return hfa_type (&typedie, tag, sizep, countp);
+    }
+
+  return 1;
+}
+
+static int
+hfa_type (Dwarf_Die *ftypedie, int tag, Dwarf_Word *sizep, Dwarf_Word *countp)
+{
+  assert (tag == DW_TAG_structure_type || tag == DW_TAG_class_type
+	  || tag == DW_TAG_union_type || tag == DW_TAG_array_type);
+
+  int i;
+  if (tag == DW_TAG_array_type)
+    {
+      Dwarf_Word tot_size;
+      if (dwarf_aggregate_size (ftypedie, &tot_size) < 0)
+	return -1;
+
+      /* For vector types, we don't care about the underlying
+	 type, but only about the vector type itself.  */
+      bool vec;
+      Dwarf_Attribute attr_mem;
+      if (dwarf_formflag (dwarf_attr_integrate (ftypedie, DW_AT_GNU_vector,
+						&attr_mem), &vec) == 0
+	  && vec)
+	{
+	  *sizep = tot_size;
+	  *countp = 1;
+
+	  return 0;
+	}
+
+      if ((i = member_is_fp (ftypedie, sizep, countp)) == 0)
+	{
+	  *countp = tot_size / *sizep;
+	  return 0;
+	}
+
+      return i;
+    }
+
+  /* Find first DW_TAG_member and determine its type.  */
+  Dwarf_Die member;
+  if ((i = dwarf_child (ftypedie, &member) != 0))
+    return i;
+
+  if ((i = skip_until (&member, DW_TAG_member)) != 0)
+    return i;
+
+  *countp = 0;
+  if ((i = member_is_fp (&member, sizep, countp)) != 0)
+    return i;
+
+  while ((i = dwarf_siblingof (&member, &member)) == 0
+	 && (i = skip_until (&member, DW_TAG_member)) == 0)
+    {
+      Dwarf_Word size, count;
+      if ((i = member_is_fp (&member, &size, &count)) != 0)
+	return i;
+
+      if (*sizep != size)
+	return 1;
+
+      *countp += count;
+    }
+
+  /* At this point we already have at least one FP member, which means
+     FTYPEDIE is an HFA.  So either return 0, or propagate error.  */
+  return i < 0 ? i : 0;
+}
+
+static int
+pass_in_gpr (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
+      { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 }
+    };
+
+  *locp = loc;
+  return size <= 8 ? 1 : 4;
+}
+
+static int
+pass_by_ref (const Dwarf_Op **locp)
+{
+  static const Dwarf_Op loc[] = { { .atom = DW_OP_breg0 } };
+
+  *locp = loc;
+  return 1;
+}
+
+static int
+pass_hfa (const Dwarf_Op **locp, Dwarf_Word size, Dwarf_Word count)
+{
+  assert (count >= 1 && count <= 4);
+  assert (size == 2 || size == 4 || size == 8 || size == 16);
+
+#define DEFINE_FPREG(NAME, SIZE)		\
+  static const Dwarf_Op NAME[] = {		\
+    { .atom = DW_OP_regx, .number = 64 },	\
+    { .atom = DW_OP_piece, .number = SIZE },	\
+    { .atom = DW_OP_regx, .number = 65 },	\
+    { .atom = DW_OP_piece, .number = SIZE },	\
+    { .atom = DW_OP_regx, .number = 66 },	\
+    { .atom = DW_OP_piece, .number = SIZE },	\
+    { .atom = DW_OP_regx, .number = 67 },	\
+    { .atom = DW_OP_piece, .number = SIZE }	\
+  }
+
+  switch (size)
+    {
+    case 2:;
+      DEFINE_FPREG (loc_hfa_2, 2);
+      *locp = loc_hfa_2;
+      break;
+
+    case 4:;
+      DEFINE_FPREG (loc_hfa_4, 4);
+      *locp = loc_hfa_4;
+      break;
+
+    case 8:;
+      DEFINE_FPREG (loc_hfa_8, 8);
+      *locp = loc_hfa_8;
+      break;
+
+    case 16:;
+      DEFINE_FPREG (loc_hfa_16, 16);
+      *locp = loc_hfa_16;
+      break;
+    }
+#undef DEFINE_FPREG
+
+  return count == 1 ? 1 : 2 * count;
+}
+
+static int
+pass_in_simd (const Dwarf_Op **locp)
+{
+  /* This is like passing single-element HFA.  Size doesn't matter, so
+     pretend it's for example double.  */
+  return pass_hfa (locp, 8, 1);
+}
+
+int
+aarch64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die typedie;
+  int tag = dwarf_peeled_die_type (functypedie, &typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size = (Dwarf_Word)-1;
+
+  /* If the argument type is a Composite Type that is larger than 16
+     bytes, then the argument is copied to memory allocated by the
+     caller and the argument is replaced by a pointer to the copy.  */
+  if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type
+      || tag == DW_TAG_class_type || tag == DW_TAG_array_type)
+    {
+      Dwarf_Word base_size, count;
+      switch (hfa_type (&typedie, tag, &base_size, &count))
+	{
+	default:
+	  return -1;
+
+	case 0:
+	  assert (count > 0);
+	  if (count <= 4)
+	    return pass_hfa (locp, base_size, count);
+	  FALLTHROUGH;
+
+	case 1:
+	  /* Not a HFA.  */
+	  if (dwarf_aggregate_size (&typedie, &size) < 0)
+	    return -1;
+	  if (size > 16)
+	    return pass_by_ref (locp);
+	}
+    }
+
+  if (tag == DW_TAG_base_type || dwarf_is_pointer (tag))
+    {
+      if (dwarf_bytesize_aux (&typedie, &size) < 0)
+	{
+	  if (dwarf_is_pointer (tag))
+	    size = 8;
+	  else
+	    return -1;
+	}
+
+      Dwarf_Attribute attr_mem;
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	      /* If the argument is a Half-, Single-, Double- or Quad-
+		 precision Floating-point [...] the argument is allocated
+		 to the least significant bits of register v[NSRN].  */
+	    case DW_ATE_float:
+	      switch (size)
+		{
+		case 2: /* half */
+		case 4: /* single */
+		case 8: /* double */
+		case 16: /* quad */
+		  return pass_in_simd (locp);
+
+		default:
+		  return -2;
+		}
+
+	    case DW_ATE_complex_float:
+	      switch (size)
+		{
+		case 8: /* float _Complex */
+		case 16: /* double _Complex */
+		case 32: /* long double _Complex */
+		  return pass_hfa (locp, size / 2, 2);
+
+		default:
+		  return -2;
+		}
+
+	      /* If the argument is an Integral or Pointer Type, the
+		 size of the argument is less than or equal to 8 bytes
+		 [...] the argument is copied to the least significant
+		 bits in x[NGRN].  */
+	    case DW_ATE_boolean:
+	    case DW_ATE_signed:
+	    case DW_ATE_unsigned:
+	    case DW_ATE_unsigned_char:
+	    case DW_ATE_signed_char:
+	      return pass_in_gpr (locp, size);
+	    }
+
+	  return -2;
+	}
+      else
+	return pass_in_gpr (locp, size);
+    }
+
+  *locp = NULL;
+  return 0;
+}
diff --git a/backends/aarch64_symbol.c b/backends/aarch64_symbol.c
new file mode 100644
index 0000000..15e0805
--- /dev/null
+++ b/backends/aarch64_symbol.c
@@ -0,0 +1,136 @@
+/* AArch64 specific symbolic name handling.
+   Copyright (C) 2013, 2015, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		aarch64_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+aarch64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			   int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_AARCH64_ABS64:
+      return ELF_T_XWORD;
+    case R_AARCH64_ABS32:
+      return ELF_T_WORD;
+    case R_AARCH64_ABS16:
+      return ELF_T_HALF;
+
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* If this is the _GLOBAL_OFFSET_TABLE_ symbol, then it should point in
+   the .got even if there is a .got.plt section.
+   https://sourceware.org/ml/libc-ports/2013-06/msg00057.html
+   https://bugzilla.redhat.com/show_bug.cgi?id=1201778
+ */
+bool
+aarch64_check_special_symbol (Elf *elf, const GElf_Sym *sym,
+                              const char *name, const GElf_Shdr *destshdr)
+{
+  if (name != NULL
+      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    {
+      size_t shstrndx;
+      if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+	return false;
+      const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
+      if (sname != NULL
+	  && (strcmp (sname, ".got") == 0 || strcmp (sname, ".got.plt") == 0))
+	{
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  sname = elf_strptr (elf, shstrndx, shdr->sh_name);
+		  if (sname != NULL && strcmp (sname, ".got") == 0)
+		    return (sym->st_value >= shdr->sh_addr
+			    && sym->st_value < shdr->sh_addr + shdr->sh_size);
+		}
+	    }
+	}
+    }
+
+  return false;
+}
+
+/* A data mapping symbol is a symbol with "$d" name or "$d.<any...>" name,
+   STT_NOTYPE, STB_LOCAL and st_size of zero. The indicate the stat of a
+   sequence of data items.  */
+bool
+aarch64_data_marker_symbol (const GElf_Sym *sym, const char *sname)
+{
+  return (sym != NULL && sname != NULL
+	  && sym->st_size == 0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL
+	  && GELF_ST_TYPE (sym->st_info) == STT_NOTYPE
+	  && (strcmp (sname, "$d") == 0 || startswith (sname, "$d.")));
+}
+
+const char *
+aarch64_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_AARCH64_BTI_PLT:
+      return "AARCH64_BTI_PLT";
+    case DT_AARCH64_PAC_PLT:
+      return "AARCH64_PAC_PLT";
+    case DT_AARCH64_VARIANT_PCS:
+      return "AARCH64_VARIANT_PCS";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+bool
+aarch64_dynamic_tag_check (int64_t tag)
+{
+  return (tag == DT_AARCH64_BTI_PLT
+	  || tag == DT_AARCH64_PAC_PLT
+	  || tag == DT_AARCH64_VARIANT_PCS);
+}
diff --git a/backends/aarch64_unwind.c b/backends/aarch64_unwind.c
new file mode 100644
index 0000000..e0a7e96
--- /dev/null
+++ b/backends/aarch64_unwind.c
@@ -0,0 +1,83 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2016 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND aarch64_
+#define FP_REG 29
+#define LR_REG 30
+#define SP_REG 31
+#define FP_OFFSET 0
+#define LR_OFFSET 8
+#define SP_OFFSET 16
+
+#include "libebl_CPU.h"
+
+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that?  */
+
+bool
+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
+                 ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+                 ebl_pid_memory_read_t *readfunc, void *arg,
+                 bool *signal_framep __attribute__ ((unused)))
+{
+  Dwarf_Word fp, lr, sp;
+
+  if (!getfunc(LR_REG, 1, &lr, arg))
+    return false;
+
+  if (lr == 0 || !setfunc(-1, 1, &lr, arg))
+    return false;
+
+  if (!getfunc(FP_REG, 1, &fp, arg))
+    fp = 0;
+
+  if (!getfunc(SP_REG, 1, &sp, arg))
+    sp = 0;
+
+  Dwarf_Word newLr, newFp, newSp;
+
+  if (!readfunc(fp + LR_OFFSET, &newLr, arg))
+    newLr = 0;
+
+  if (!readfunc(fp + FP_OFFSET, &newFp, arg))
+    newFp = 0;
+
+  newSp = fp + SP_OFFSET;
+
+  // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
+  setfunc(LR_REG, 1, &newLr, arg);
+  setfunc(FP_REG, 1, &newFp, arg);
+  setfunc(SP_REG, 1, &newSp, arg);
+
+  // If the fp is invalid, we might still have a valid lr.
+  // But if the fp is valid, then the stack should be moving in the right direction.
+  return fp == 0 || newSp > sp;
+}
diff --git a/backends/alpha_auxv.c b/backends/alpha_auxv.c
new file mode 100644
index 0000000..83e7199
--- /dev/null
+++ b/backends/alpha_auxv.c
@@ -0,0 +1,49 @@
+/* Alpha-specific auxv handling.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "bwx\0" "fix\0" "cix\0" "0x08\0"
+    "0x10\0" "0x20\0" "0x40\0" "0x80\0"
+    "max\0" "precise_trap\0"
+    "\0";
+  return 1;
+}
diff --git a/backends/alpha_corenote.c b/backends/alpha_corenote.c
new file mode 100644
index 0000000..6190df3
--- /dev/null
+++ b/backends/alpha_corenote.c
@@ -0,0 +1,70 @@
+/* PowerPC specific core note handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND	alpha_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 31, .bits = 64 }, /* r0-r30 */
+    { .offset = 32 * 8, .regno = 64, .count = 1, .bits = 64 }, /* pc */
+    { .offset = 33 * 8, .regno = 66, .count = 1, .bits = 64 }, /* unique */
+  };
+#define PRSTATUS_REGS_SIZE	(33 * 8)
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 32, .count = 32, .bits = 64 }, /* f0-f30, fpcr */
+  };
+#define FPREGSET_SIZE		(32 * 8)
+
+#define ULONG			uint64_t
+#define ALIGN_ULONG		8
+#define TYPE_ULONG		ELF_T_XWORD
+#define TYPE_LONG		ELF_T_SXWORD
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#include "linux-core-note.c"
diff --git a/backends/alpha_init.c b/backends/alpha_init.c
new file mode 100644
index 0000000..c69aec6
--- /dev/null
+++ b/backends/alpha_init.c
@@ -0,0 +1,63 @@
+/* Initialization of Alpha specific backend library.
+   Copyright (C) 2002-2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		alpha_
+#define RELOC_PREFIX	R_ALPHA_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on alpha_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+alpha_init (Elf *elf __attribute__ ((unused)),
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh)
+{
+  /* We handle it.  */
+  alpha_init_reloc (eh);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, machine_section_flag_check);
+  HOOK (eh, check_special_section);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, check_st_other_bits);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  eh->sysvhash_entrysize = sizeof (Elf64_Xword);
+
+  return eh;
+}
diff --git a/backends/alpha_regs.c b/backends/alpha_regs.c
new file mode 100644
index 0000000..436af3b
--- /dev/null
+++ b/backends/alpha_regs.c
@@ -0,0 +1,164 @@
+/* Register names and numbers for Alpha DWARF.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+ssize_t
+alpha_register_info (Ebl *ebl __attribute__ ((unused)),
+		     int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  if (name == NULL)
+    return 67;
+
+  if (regno < 0 || regno > 66 || namelen < 7)
+    return -1;
+
+  *prefix = "$";
+
+  *bits = 64;
+  *type = DW_ATE_signed;
+  *setname = "integer";
+  if (regno >= 32 && regno < 64)
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+    }
+
+  switch (regno)
+    {
+    case 0:
+      name[0] = 'v';
+      name[1] = '0';
+      namelen = 2;
+      break;
+
+    case 1 ... 8:
+      name[0] = 't';
+      name[1] = regno - 1 + '0';
+      namelen = 2;
+      break;
+
+    case 9 ... 15:
+      name[0] = 's';
+      name[1] = regno - 9 + '0';
+      namelen = 2;
+      break;
+
+    case 16 ... 21:
+      name[0] = 'a';
+      name[1] = regno - 16 + '0';
+      namelen = 2;
+      break;
+
+    case 22 ... 23:
+      name[0] = 't';
+      name[1] = regno - 22 + '8';
+      namelen = 2;
+      break;
+
+    case 24 ... 25:
+      name[0] = 't';
+      name[1] = '1';
+      name[2] = regno - 24 + '0';
+      namelen = 3;
+      break;
+
+    case 26:
+      *type = DW_ATE_address;
+      return stpcpy (name, "ra") + 1 - name;
+
+    case 27:
+      return stpcpy (name, "t12") + 1 - name;
+
+    case 28:
+      return stpcpy (name, "at") + 1 - name;
+
+    case 29:
+      *type = DW_ATE_address;
+      return stpcpy (name, "gp") + 1 - name;
+
+    case 30:
+      *type = DW_ATE_address;
+      return stpcpy (name, "sp") + 1 - name;
+
+    case 31:
+      return stpcpy (name, "zero") + 1 - name;
+
+    case 32 ... 32 + 9:
+      name[0] = 'f';
+      name[1] = regno - 32 + '0';
+      namelen = 2;
+      break;
+
+    case 32 + 10 ... 32 + 19:
+      name[0] = 'f';
+      name[1] = '1';
+      name[2] = regno - 32 - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 32 + 20 ... 32 + 29:
+      name[0] = 'f';
+      name[1] = '2';
+      name[2] = regno - 32 - 20 + '0';
+      namelen = 3;
+      break;
+
+    case 32 + 30:
+      return stpcpy (name, "f30") + 1 - name;
+
+    case 32 + 31:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "fpcr") + 1 - name;
+
+    case 64:
+      *type = DW_ATE_address;
+      return stpcpy (name, "pc") + 1 - name;
+
+    case 66:
+      *type = DW_ATE_address;
+      return stpcpy (name, "unique") + 1 - name;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/alpha_reloc.def b/backends/alpha_reloc.def
new file mode 100644
index 0000000..ed7e5c3
--- /dev/null
+++ b/backends/alpha_reloc.def
@@ -0,0 +1,63 @@
+/* List the relocation types for alpha.  -*- C -*-
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (REFLONG,		REL|EXEC|DYN)
+RELOC_TYPE (REFQUAD,		REL|EXEC|DYN)
+RELOC_TYPE (GPREL32,		REL)
+RELOC_TYPE (LITERAL,		REL)
+RELOC_TYPE (LITUSE,		REL)
+RELOC_TYPE (GPDISP,		REL)
+RELOC_TYPE (BRADDR,		REL)
+RELOC_TYPE (HINT,		REL)
+RELOC_TYPE (SREL16,		REL)
+RELOC_TYPE (SREL32,		REL)
+RELOC_TYPE (SREL64,		REL)
+RELOC_TYPE (GPRELHIGH,		REL)
+RELOC_TYPE (GPRELLOW,		REL)
+RELOC_TYPE (GPREL16,		REL)
+RELOC_TYPE (COPY,		0)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (TLS_GD_HI,		REL)
+RELOC_TYPE (TLSGD,		REL)
+RELOC_TYPE (TLS_LDM,		REL)
+RELOC_TYPE (DTPMOD64,		REL|EXEC|DYN)
+RELOC_TYPE (GOTDTPREL,		REL)
+RELOC_TYPE (DTPREL64,		REL|EXEC|DYN)
+RELOC_TYPE (DTPRELHI,		REL)
+RELOC_TYPE (DTPRELLO,		REL)
+RELOC_TYPE (DTPREL16,		REL)
+RELOC_TYPE (GOTTPREL,		REL)
+RELOC_TYPE (TPREL64,		REL|EXEC|DYN)
+RELOC_TYPE (TPRELHI,		REL)
+RELOC_TYPE (TPRELLO,		REL)
+RELOC_TYPE (TPREL16,		REL)
diff --git a/backends/alpha_retval.c b/backends/alpha_retval.c
new file mode 100644
index 0000000..9d2dd04
--- /dev/null
+++ b/backends/alpha_retval.c
@@ -0,0 +1,149 @@
+/* Function return value location for Alpha ELF ABI.
+   Copyright (C) 2005, 2007, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND alpha_
+#include "libebl_CPU.h"
+
+
+/* $0.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }
+  };
+#define nloc_intreg	1
+
+/* $f0, or pair $f0, $f1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg	1
+#define nloc_fpregpair	4
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in $0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+alpha_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	Dwarf_Word size;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 8;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+
+	    *locp = loc_fpreg;
+	    if (encoding == DW_ATE_float)
+	      {
+		if (size <= 8)
+		  return nloc_fpreg;
+		goto aggregate;
+	      }
+	    if (encoding == DW_ATE_complex_float)
+	      {
+		if (size <= 8 * 2)
+		  return nloc_fpregpair;
+		goto aggregate;
+	      }
+	  }
+	if (size <= 8)
+	  {
+	    *locp = loc_intreg;
+	    return nloc_intreg;
+	  }
+      }
+
+      FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_string_type:
+    case DW_TAG_array_type:
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/alpha_symbol.c b/backends/alpha_symbol.c
new file mode 100644
index 0000000..53a9e7b
--- /dev/null
+++ b/backends/alpha_symbol.c
@@ -0,0 +1,156 @@
+/* Alpha specific symbolic name handling.
+   Copyright (C) 2002-2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		alpha_
+#include "libebl_CPU.h"
+
+
+const char *
+alpha_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_ALPHA_PLTRO:
+      return "ALPHA_PLTRO";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+bool
+alpha_dynamic_tag_check (int64_t tag)
+{
+  return tag == DT_ALPHA_PLTRO;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+alpha_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			 int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_ALPHA_REFLONG:
+      return ELF_T_WORD;
+    case R_ALPHA_REFQUAD:
+      return ELF_T_XWORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+
+/* Check whether SHF_MASKPROC flags are valid.  */
+bool
+alpha_machine_section_flag_check (GElf_Xword sh_flags)
+{
+  return (sh_flags &~ (SHF_ALPHA_GPREL)) == 0;
+}
+
+bool
+alpha_check_special_section (Ebl *ebl,
+			     int ndx __attribute__ ((unused)),
+			     const GElf_Shdr *shdr,
+			     const char *sname __attribute__ ((unused)))
+{
+  if ((shdr->sh_flags
+       & (SHF_WRITE | SHF_EXECINSTR)) == (SHF_WRITE | SHF_EXECINSTR)
+      && shdr->sh_addr != 0)
+    {
+      /* This is ordinarily flagged, but is valid for an old-style PLT.
+
+	 Look for the SHT_DYNAMIC section and the DT_PLTGOT tag in it.
+	 Its d_ptr should match the .plt section's sh_addr.  */
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	{
+	  GElf_Shdr scn_shdr;
+	  if (likely (gelf_getshdr (scn, &scn_shdr) != NULL)
+	      && scn_shdr.sh_type == SHT_DYNAMIC
+	      && scn_shdr.sh_entsize != 0)
+	    {
+	      GElf_Addr pltgot = 0;
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      if (data != NULL)
+		for (size_t i = 0; i < data->d_size / scn_shdr.sh_entsize; ++i)
+		  {
+		    GElf_Dyn dyn;
+		    if (unlikely (gelf_getdyn (data, i, &dyn) == NULL))
+		      break;
+		    if (dyn.d_tag == DT_PLTGOT)
+		      pltgot = dyn.d_un.d_ptr;
+		    else if (dyn.d_tag == DT_ALPHA_PLTRO && dyn.d_un.d_val != 0)
+		      return false; /* This PLT should not be writable.  */
+		  }
+	      return pltgot == shdr->sh_addr;
+	    }
+	}
+    }
+
+  return false;
+}
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+alpha_check_special_symbol (Elf *elf __attribute__ ((unused)),
+			    const GElf_Sym *sym __attribute__ ((unused)),
+			    const char *name,
+			    const GElf_Shdr *destshdr __attribute__ ((unused)))
+{
+  if (name == NULL)
+    return false;
+
+  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    /* On Alpha any place in the section is valid.  */
+    return true;
+
+  return false;
+}
+
+/* Check whether only valid bits are set on the st_other symbol flag.
+   Standard ST_VISIBILITY have already been masked off.  */
+bool
+alpha_check_st_other_bits (unsigned char st_other)
+{
+  return ((((st_other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_NOPV)
+	   || ((st_other & STO_ALPHA_STD_GPLOAD) == STO_ALPHA_STD_GPLOAD))
+	  && (st_other &~ STO_ALPHA_STD_GPLOAD) == 0);
+}
diff --git a/backends/arc_init.c b/backends/arc_init.c
new file mode 100644
index 0000000..a7ccece
--- /dev/null
+++ b/backends/arc_init.c
@@ -0,0 +1,59 @@
+/* Initialization of ARC specific backend library.
+   Copyright (C) 2022 Synopsys Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* More details on an ARC elf can be found at:
+   https://github.com/foss-for-synopsys-dwc-arc-processors/ \
+	   arc-ABI-manual/blob/master/arcv3-elf.md   */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		arc_
+#define RELOC_PREFIX	R_ARC_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on arc_reloc.def.  */
+#include "common-reloc.c"
+
+Ebl *
+arc_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh)
+{
+  arc_init_reloc (eh);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, section_type_name);
+
+  /* /bld/gcc-stage2/arc-snps-linux-gnu/libgcc/libgcc.map.in
+     #define __LIBGCC_DWARF_FRAME_REGISTERS__.  */
+  eh->frame_nregs = 146;
+
+  return eh;
+}
diff --git a/backends/arc_reloc.def b/backends/arc_reloc.def
new file mode 100644
index 0000000..dfa3062
--- /dev/null
+++ b/backends/arc_reloc.def
@@ -0,0 +1,87 @@
+/* List the relocation types for ARC.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (8,			REL|EXEC|DYN)
+RELOC_TYPE (16,			REL|EXEC|DYN)
+RELOC_TYPE (24,			REL|EXEC|DYN)
+RELOC_TYPE (32,			REL|EXEC|DYN)
+RELOC_TYPE (N8,			REL|EXEC|DYN)
+RELOC_TYPE (N16,		REL|EXEC|DYN)
+RELOC_TYPE (N24,		REL|EXEC|DYN)
+RELOC_TYPE (N32,		REL|EXEC|DYN)
+RELOC_TYPE (SDA,		REL)
+RELOC_TYPE (SECTOFF,		REL)
+RELOC_TYPE (S21H_PCREL,		REL)
+RELOC_TYPE (S21W_PCREL,		REL)
+RELOC_TYPE (S25H_PCREL,		REL)
+RELOC_TYPE (S25W_PCREL,		REL)
+RELOC_TYPE (SDA32,		REL)
+RELOC_TYPE (SDA_LDST,		REL)
+RELOC_TYPE (SDA_LDST1,		REL)
+RELOC_TYPE (SDA_LDST2,		REL)
+RELOC_TYPE (SDA16_LD,		REL)
+RELOC_TYPE (SDA16_LD1,		REL)
+RELOC_TYPE (SDA16_LD2,		REL)
+RELOC_TYPE (S13_PCREL,		REL)
+RELOC_TYPE (W,			REL)
+RELOC_TYPE (32_ME,		REL)
+RELOC_TYPE (N32_ME,		REL)
+RELOC_TYPE (SECTOFF_ME,		REL)
+RELOC_TYPE (SDA32_ME,		REL)
+RELOC_TYPE (W_ME,		REL)
+RELOC_TYPE (SDA_12,		REL)
+RELOC_TYPE (SDA16_ST2,		REL)
+RELOC_TYPE (32_PCREL,		REL)
+RELOC_TYPE (PC32,		REL)
+RELOC_TYPE (GOTPC32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (S21W_PCREL_PLT,	REL)
+RELOC_TYPE (S25H_PCREL_PLT,	REL)
+RELOC_TYPE (JLI_SECTOFF,	REL)
+RELOC_TYPE (TLS_DTPMOD,		REL)
+RELOC_TYPE (TLS_DTPOFF,		REL)
+RELOC_TYPE (TLS_TPOFF,		REL)
+RELOC_TYPE (TLS_GD_GOT,		REL)
+RELOC_TYPE (TLS_GD_LD,		REL)
+RELOC_TYPE (TLS_GD_CALL,	REL)
+RELOC_TYPE (TLS_IE_GOT,		REL)
+RELOC_TYPE (TLS_DTPOFF_S9,	REL)
+RELOC_TYPE (TLS_LE_S9,		REL)
+RELOC_TYPE (TLS_LE_32,		REL)
+RELOC_TYPE (S25W_PCREL_PLT,	REL)
+RELOC_TYPE (S21H_PCREL_PLT,	REL)
+RELOC_TYPE (NPS_CMEM16,		REL)
diff --git a/backends/arc_symbol.c b/backends/arc_symbol.c
new file mode 100644
index 0000000..be69814
--- /dev/null
+++ b/backends/arc_symbol.c
@@ -0,0 +1,81 @@
+/* ARC specific symbolic name handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND arc_
+#include "libebl_CPU.h"
+
+
+/* Check whether machine flags are valid.  */
+bool
+arc_machine_flag_check (GElf_Word flags)
+{
+  return ((flags & ~EF_ARC_ALL_MSK) == 0);
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+arc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+		       int *addsub __attribute ((unused)))
+{
+  switch (type)
+    {
+    case R_ARC_32:
+      return ELF_T_WORD;
+    case R_ARC_16:
+      return ELF_T_HALF;
+    case R_ARC_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+arc_section_type_name (int type,
+		       char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_ARC_ATTRIBUTES:
+      return "ARC_ATTRIBUTES";
+    default:
+      break;
+    }
+
+  return NULL;
+}
diff --git a/backends/arm_attrs.c b/backends/arm_attrs.c
new file mode 100644
index 0000000..6842b77
--- /dev/null
+++ b/backends/arm_attrs.c
@@ -0,0 +1,241 @@
+/* Object attribute tags for ARM.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+#define KNOWN_VALUES(...) do				\
+  {							\
+    static const char *table[] = { __VA_ARGS__ };	\
+    if (value < sizeof table / sizeof table[0])		\
+      *value_name = table[value];			\
+  } while (0)
+
+bool
+arm_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			    const char *vendor, int tag, uint64_t value,
+			    const char **tag_name, const char **value_name)
+{
+  if (!strcmp (vendor, "aeabi"))
+    switch (tag)
+      {
+      case 4:
+	*tag_name = "CPU_raw_name";
+	return true;
+      case 5:
+	*tag_name = "CPU_name";
+	return true;
+      case 6:
+	*tag_name = "CPU_arch";
+	KNOWN_VALUES ("Pre-v4",
+		      "v4",
+		      "v4T",
+		      "v5T",
+		      "v5TE",
+		      "v5TEJ",
+		      "v6",
+		      "v6KZ",
+		      "v6T2",
+		      "v6K",
+		      "v7",
+		      "v6-M",
+		      "v6S-M");
+	return true;
+      case 7:
+	*tag_name = "CPU_arch_profile";
+	switch (value)
+	  {
+	  case 'A':
+	    *value_name = "Application";
+	    break;
+	  case 'R':
+	    *value_name = "Realtime";
+	    break;
+	  case 'M':
+	    *value_name = "Microcontroller";
+	    break;
+	  }
+	return true;
+      case 8:
+	*tag_name = "ARM_ISA_use";
+	KNOWN_VALUES ("No", "Yes");
+	return true;
+      case 9:
+	*tag_name = "THUMB_ISA_use";
+	KNOWN_VALUES ("No", "Thumb-1", "Thumb-2");
+	return true;
+      case 10:
+	*tag_name = "VFP_arch";
+	KNOWN_VALUES ("No", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16");
+	return true;
+      case 11:
+	*tag_name = "WMMX_arch";
+	KNOWN_VALUES ("No", "WMMXv1", "WMMXv2");
+	return true;
+      case 12:
+	*tag_name = "Advanced_SIMD_arch";
+	KNOWN_VALUES ("No", "NEONv1");
+	return true;
+      case 13:
+	*tag_name = "PCS_config";
+	KNOWN_VALUES ("None",
+		      "Bare platform",
+		      "Linux application",
+		      "Linux DSO",
+		      "PalmOS 2004",
+		      "PalmOS (reserved)",
+		      "SymbianOS 2004",
+		      "SymbianOS (reserved)");
+	return true;
+      case 14:
+	*tag_name = "ABI_PCS_R9_use";
+	KNOWN_VALUES ("V6", "SB", "TLS", "Unused");
+	return true;
+      case 15:
+	*tag_name = "ABI_PCS_RW_data";
+	KNOWN_VALUES ("Absolute", "PC-relative", "SB-relative", "None");
+	return true;
+      case 16:
+	*tag_name = "ABI_PCS_RO_data";
+	KNOWN_VALUES ("Absolute", "PC-relative", "None");
+	return true;
+      case 17:
+	*tag_name = "ABI_PCS_GOT_use";
+	KNOWN_VALUES ("None", "direct", "GOT-indirect");
+	return true;
+      case 18:
+	*tag_name = "ABI_PCS_wchar_t";
+	return true;
+      case 19:
+	*tag_name = "ABI_FP_rounding";
+	KNOWN_VALUES ("Unused", "Needed");
+	return true;
+      case 20:
+	*tag_name = "ABI_FP_denormal";
+	KNOWN_VALUES ("Unused", "Needed", "Sign only");
+	return true;
+      case 21:
+	*tag_name = "ABI_FP_exceptions";
+	KNOWN_VALUES ("Unused", "Needed");
+	return true;
+      case 22:
+	*tag_name = "ABI_FP_user_exceptions";
+	KNOWN_VALUES ("Unused", "Needed");
+	return true;
+      case 23:
+	*tag_name = "ABI_FP_number_model";
+	KNOWN_VALUES ("Unused", "Finite", "RTABI", "IEEE 754");
+	return true;
+      case 24:
+	*tag_name = "ABI_align8_needed";
+	KNOWN_VALUES ("No", "Yes", "4-byte");
+	return true;
+      case 25:
+	*tag_name = "ABI_align8_preserved";
+	KNOWN_VALUES ("No", "Yes, except leaf SP", "Yes");
+	return true;
+      case 26:
+	*tag_name = "ABI_enum_size";
+	KNOWN_VALUES ("Unused", "small", "int", "forced to int");
+	return true;
+      case 27:
+	*tag_name = "ABI_HardFP_use";
+	KNOWN_VALUES ("as VFP_arch", "SP only", "DP only", "SP and DP");
+	return true;
+      case 28:
+	*tag_name = "ABI_VFP_args";
+	KNOWN_VALUES ("AAPCS", "VFP registers", "custom");
+	return true;
+      case 29:
+	*tag_name = "ABI_WMMX_args";
+	KNOWN_VALUES ("AAPCS", "WMMX registers", "custom");
+	return true;
+      case 30:
+	*tag_name = "ABI_optimization_goals";
+	KNOWN_VALUES ("None",
+		      "Prefer Speed",
+		      "Aggressive Speed",
+		      "Prefer Size",
+		      "Aggressive Size",
+		      "Prefer Debug",
+		      "Aggressive Debug");
+	return true;
+      case 31:
+	*tag_name = "ABI_FP_optimization_goals";
+	KNOWN_VALUES ("None",
+		      "Prefer Speed",
+		      "Aggressive Speed",
+		      "Prefer Size",
+		      "Aggressive Size",
+		      "Prefer Accuracy",
+		      "Aggressive Accuracy");
+	return true;
+      case 34:
+	*tag_name = "CPU_unaligned_access";
+	KNOWN_VALUES ("None", "v6");
+	return true;
+      case 36:
+	*tag_name = "VFP_HP_extension";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      case 38:
+	*tag_name = "ABI_FP_16bit_format";
+	KNOWN_VALUES ("None", "IEEE 754", "Alternative Format");
+	return true;
+      case 64:
+	*tag_name = "nodefaults";
+	return true;
+      case 65:
+	*tag_name = "also_compatible_with";
+	return true;
+      case 66:
+	*tag_name = "T2EE_use";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      case 67:
+	*tag_name = "conformance";
+	return true;
+      case 68:
+	*tag_name = "Virtualization_use";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      case 70:
+	*tag_name = "MPextension_use";
+	KNOWN_VALUES ("Not Allowed", "Allowed");
+	return true;
+      }
+
+  return false;
+}
diff --git a/backends/arm_auxv.c b/backends/arm_auxv.c
new file mode 100644
index 0000000..3282baf
--- /dev/null
+++ b/backends/arm_auxv.c
@@ -0,0 +1,49 @@
+/* ARM-specific auxv handling.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "swp\0" "half\0" "thumb\0" "26bit\0"
+    "fast-mult\0" "fpa\0" "vfp\0" "edsp\0"
+    "java\0" "iwmmxt\0"
+    "\0";
+  return 1;
+}
diff --git a/backends/arm_cfi.c b/backends/arm_cfi.c
new file mode 100644
index 0000000..971a1fc
--- /dev/null
+++ b/backends/arm_cfi.c
@@ -0,0 +1,90 @@
+/* arm ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+
+/* ABI-specified state of DWARF CFI based on:
+
+   "DWARF for the ARM Architecture ABI r2.09"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0040b/IHI0040B_aadwarf.pdf
+
+   "Procedure Call Standard for the ARM Architecture ABI r2.09"
+http://infocenter.arm.com/help/topic/com.arm.doc.ihi0042e/IHI0042E_aapcs.pdf
+*/
+
+int
+arm_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer (r13) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (13), ULEB128_7 (0),
+
+      /* The Stack Pointer (r13) is restored from CFA address by default.  */
+      DW_CFA_val_offset, ULEB128_7 (13), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* Callee-saved regs r4-r8, r10, r11.  */
+      SV (4), SV (5), SV (6), SV (7), SV (8), SV (10), SV (11),
+
+      /* The link register contains the return address setup by caller.  */
+      SV (14),
+      DW_CFA_register, ULEB128_7 (15), ULEB128_7 (14), /* pc = lr */
+#undef SV
+
+      /* VFP S16-S31/D8-D15/Q4-Q7 are callee saved.
+         And uleb128 encoded with two bytes.  */
+#define ULEB128_8_2(x) ((x & 0x7f) | 0x80), 0x02
+#define SV(n) DW_CFA_same_value, ULEB128_8_2 (n)
+      SV (264), SV (265), SV (266), SV (267),
+      SV (268), SV (269), SV (270), SV (271),
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+#undef ULEB128_8_2
+#undef SV
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 4;
+
+  abi_info->return_address_register = 15; /* pc.  */
+
+  return 0;
+}
diff --git a/backends/arm_corenote.c b/backends/arm_corenote.c
new file mode 100644
index 0000000..c5d8d88
--- /dev/null
+++ b/backends/arm_corenote.c
@@ -0,0 +1,94 @@
+/* ARM specific core note handling.
+   Copyright (C) 2009, 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 16, .bits = 32 },	/* r0..r15 */
+    { .offset = 16 * 4, .regno = 128, .count = 1, .bits = 32 }, /* cpsr */
+  };
+#define PRSTATUS_REGS_SIZE	(18 * 4)
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "orig_r0", .type = ELF_T_SWORD, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 17),	      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 96, .count = 8, .bits = 96 }, /* f0..f7 */
+  };
+#define FPREGSET_SIZE	116
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+#define ARM_VFPREGS_SIZE ( 32 * 8 /*fpregs*/ + 4 /*fpscr*/ )
+static const Ebl_Register_Location vfp_regs[] =
+  {
+    { .offset = 0, .regno = 256, .count = 32, .bits = 64 }, /* fpregs */
+  };
+
+static const Ebl_Core_Item vfp_items[] =
+  {
+    {
+      .name = "fpscr", .group = "register",
+      .offset = 0,
+      .type = ELF_T_WORD, .format = 'x',
+    },
+  };
+
+#define	EXTRA_NOTES \
+  EXTRA_REGSET_ITEMS (NT_ARM_VFP, ARM_VFPREGS_SIZE, vfp_regs, vfp_items)
+
+#include "linux-core-note.c"
diff --git a/backends/arm_init.c b/backends/arm_init.c
new file mode 100644
index 0000000..70b7594
--- /dev/null
+++ b/backends/arm_init.c
@@ -0,0 +1,72 @@
+/* Initialization of Arm specific backend library.
+   Copyright (C) 2002, 2005, 2009, 2013, 2014, 2015, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		arm_
+#define RELOC_PREFIX	R_ARM_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on arm_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+arm_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh)
+{
+  /* We handle it.  */
+  arm_init_reloc (eh);
+  HOOK (eh, segment_type_name);
+  HOOK (eh, section_type_name);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, return_value_location);
+  HOOK (eh, abi_cfi);
+  HOOK (eh, check_reloc_target_type);
+  HOOK (eh, symbol_type_name);
+  HOOK (eh, data_marker_symbol);
+  HOOK (eh, machine_flag_name);
+
+  /* We only unwind the core integer registers.  */
+  eh->frame_nregs = 16;
+  HOOK (eh, set_initial_registers_tid);
+
+  /* Bit zero encodes whether an function address is THUMB or ARM. */
+  eh->func_addr_mask = ~(GElf_Addr)1;
+
+  return eh;
+}
diff --git a/backends/arm_initreg.c b/backends/arm_initreg.c
new file mode 100644
index 0000000..efcabaf
--- /dev/null
+++ b/backends/arm_initreg.c
@@ -0,0 +1,94 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#ifdef __linux__
+#if defined __arm__
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#ifdef __aarch64__
+# include <linux/uio.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+/* Deal with old glibc defining user_pt_regs instead of user_regs_struct.  */
+# ifndef HAVE_SYS_USER_REGS
+#  define user_regs_struct user_pt_regs
+# endif
+#endif
+#endif
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+bool
+arm_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+			       void *arg __attribute__ ((unused)))
+{
+#if !defined(__linux__) || (!defined __arm__ && !defined __aarch64__)
+  return false;
+#else	/* __arm__ || __aarch64__ */
+#if defined __arm__
+  struct user_regs user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+
+  Dwarf_Word dwarf_regs[16];
+  /* R0..R12 SP LR PC */
+  for (int i = 0; i < 16; i++)
+    dwarf_regs[i] = user_regs.uregs[i];
+
+  return setfunc (0, 16, dwarf_regs, arg);
+#elif defined __aarch64__
+  /* Compat mode: arm compatible code running on aarch64 */
+  int i;
+  struct user_regs_struct gregs;
+  struct iovec iovec;
+  iovec.iov_base = &gregs;
+  iovec.iov_len = sizeof (gregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  Dwarf_Word dwarf_regs[16];
+  /* R0..R12 SP LR PC, encoded as 32 bit quantities */
+  uint32_t *u32_ptr = (uint32_t *) &gregs.regs[0];
+  for (i = 0; i < 16; i++)
+    dwarf_regs[i] = u32_ptr[i];
+
+  return setfunc (0, 16, dwarf_regs, arg);
+#else
+# error "source file error, it cannot happen"
+#endif
+#endif
+}
diff --git a/backends/arm_machineflagname.c b/backends/arm_machineflagname.c
new file mode 100644
index 0000000..d700d5f
--- /dev/null
+++ b/backends/arm_machineflagname.c
@@ -0,0 +1,156 @@
+/* Arm-specific ELF flag names.
+   Copyright (C) 2022 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+const char *
+arm_machine_flag_name (Elf64_Word orig, Elf64_Word *flagref)
+{
+  unsigned version = EF_ARM_EABI_VERSION (*flagref) >> 24;
+  if (version != 0)
+    {
+      static const char vername[5][14] =
+        {
+	  "Version1 EABI",
+	  "Version2 EABI",
+	  "Version3 EABI",
+	  "Version4 EABI",
+	  "Version5 EABI",
+        };
+      *flagref &= ~((Elf64_Word) EF_ARM_EABIMASK);
+      return version <= 5 ? vername[version - 1] : NULL;
+    }
+  switch (EF_ARM_EABI_VERSION (orig))
+    {
+    case EF_ARM_EABI_VER2:
+      if ((*flagref & EF_ARM_DYNSYMSUSESEGIDX) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_DYNSYMSUSESEGIDX);
+	  return "dynamic symbols use segment index";
+	}
+      if ((*flagref & EF_ARM_MAPSYMSFIRST) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_MAPSYMSFIRST);
+	  return "mapping symbols precede others";
+	}
+      FALLTHROUGH;
+    case EF_ARM_EABI_VER1:
+      if ((*flagref & EF_ARM_SYMSARESORTED) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_SYMSARESORTED);
+	  return "sorted symbol tables";
+	}
+      break;
+    case EF_ARM_EABI_VER3:
+      break;
+    case EF_ARM_EABI_VER5:
+      if ((*flagref & EF_ARM_SOFT_FLOAT) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_SOFT_FLOAT);
+	  return "soft-float ABI";
+	}
+      if ((*flagref & EF_ARM_VFP_FLOAT) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_VFP_FLOAT);
+	  return "hard-float ABI";
+	}
+      FALLTHROUGH;
+    case EF_ARM_EABI_VER4:
+      if ((*flagref & EF_ARM_BE8) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_BE8);
+	  return "BE8";
+	}
+      if ((*flagref & EF_ARM_LE8) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_LE8);
+	  return "LE8";
+	}
+      break;
+    case EF_ARM_EABI_UNKNOWN:
+      if ((*flagref & EF_ARM_INTERWORK) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_INTERWORK);
+	  return "interworking enabled";
+	}
+      if ((*flagref & EF_ARM_APCS_26) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_APCS_26);
+	  return "uses APCS/26";
+	}
+      if ((*flagref & EF_ARM_APCS_FLOAT) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_APCS_FLOAT);
+	  return "uses APCS/float";
+	}
+      if ((*flagref & EF_ARM_PIC) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_PIC);
+	  return "position independent";
+	}
+      if ((*flagref & EF_ARM_ALIGN8) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_ALIGN8);
+	  return "8 bit structure alignment";
+	}
+      if ((*flagref & EF_ARM_NEW_ABI) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_NEW_ABI);
+	  return "uses new ABI";
+	}
+      if ((*flagref & EF_ARM_OLD_ABI) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_OLD_ABI);
+	  return "uses old ABI";
+	}
+      if ((*flagref & EF_ARM_SOFT_FLOAT) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_SOFT_FLOAT);
+	  return "software FP";
+	}
+      if ((*flagref & EF_ARM_VFP_FLOAT) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_VFP_FLOAT);
+	  return "VFP";
+	}
+      if ((*flagref & EF_ARM_MAVERICK_FLOAT) != 0)
+	{
+	  *flagref &= ~((Elf64_Word) EF_ARM_MAVERICK_FLOAT);
+	  return "Maverick FP";
+	}
+      break;
+    default:
+      break;
+    }
+  return NULL;
+}
diff --git a/backends/arm_regs.c b/backends/arm_regs.c
new file mode 100644
index 0000000..a46a4c9
--- /dev/null
+++ b/backends/arm_regs.c
@@ -0,0 +1,120 @@
+/* Register names and numbers for ARM DWARF.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+ssize_t
+arm_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  if (name == NULL)
+    return 320;
+
+  if (regno < 0 || regno > 320 || namelen < 5)
+    return -1;
+
+  *prefix = "";
+  *bits = 32;
+  *type = DW_ATE_signed;
+  *setname = "integer";
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 12:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 13 ... 15:
+      *type = DW_ATE_address;
+      name[0] = "slp"[regno - 13];
+      name[1] = "prc"[regno - 13];
+      namelen = 2;
+      break;
+
+    case 16 + 0 ... 16 + 7:
+      regno += 96 - 16;
+      FALLTHROUGH;
+    case 96 + 0 ... 96 + 7:
+      *setname = "FPA";
+      *type = DW_ATE_float;
+      *bits = 96;
+      name[0] = 'f';
+      name[1] = regno - 96 + '0';
+      namelen = 2;
+      break;
+
+    case 128:
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "spsr") + 1 - name;
+
+    case 256 + 0 ... 256 + 9:
+      *setname = "VFP";
+      *type = DW_ATE_float;
+      *bits = 64;
+      name[0] = 'd';
+      name[1] = regno - 256 + '0';
+      namelen = 2;
+      break;
+
+    case 256 + 10 ... 256 + 31:
+      *setname = "VFP";
+      *type = DW_ATE_float;
+      *bits = 64;
+      name[0] = 'd';
+      name[1] = (regno - 256) / 10 + '0';
+      name[2] = (regno - 256) % 10 + '0';
+      namelen = 3;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/arm_reloc.def b/backends/arm_reloc.def
new file mode 100644
index 0000000..113648e
--- /dev/null
+++ b/backends/arm_reloc.def
@@ -0,0 +1,157 @@
+/* List the relocation types for arm.  -*- C -*-
+   Copyright (C) 2005-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		REL) /* It really is used in ET_REL on ARM.  */
+RELOC_TYPE (PC24,		REL|EXEC|DYN)
+RELOC_TYPE (ABS32,		REL|EXEC|DYN)
+RELOC_TYPE (REL32,		REL)
+RELOC_TYPE (PC13,		REL)
+RELOC_TYPE (ABS16,		REL)
+RELOC_TYPE (ABS12,		REL)
+RELOC_TYPE (THM_ABS5,		REL)
+RELOC_TYPE (ABS8,		REL)
+RELOC_TYPE (SBREL32,		REL)
+RELOC_TYPE (THM_PC22,		REL)
+RELOC_TYPE (THM_PC8,		REL)
+RELOC_TYPE (AMP_VCALL9,		REL)
+RELOC_TYPE (TLS_DESC,		EXEC|DYN)
+RELOC_TYPE (THM_SWI8,		REL)
+RELOC_TYPE (XPC25,		REL)
+RELOC_TYPE (THM_XPC22,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF32,	EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (CALL,		REL)
+RELOC_TYPE (JUMP24,		REL)
+RELOC_TYPE (THM_JUMP24,		REL)
+RELOC_TYPE (BASE_ABS,		REL)
+RELOC_TYPE (ALU_PCREL_7_0,	REL)
+RELOC_TYPE (ALU_PCREL_15_8,	REL)
+RELOC_TYPE (ALU_PCREL_23_15,	REL)
+RELOC_TYPE (LDR_SBREL_11_0,	REL)
+RELOC_TYPE (ALU_SBREL_19_12,	REL)
+RELOC_TYPE (ALU_SBREL_27_20,	REL)
+RELOC_TYPE (TARGET1,		REL)
+RELOC_TYPE (SBREL31,		REL)
+RELOC_TYPE (V4BX,		REL)
+RELOC_TYPE (TARGET2,		REL)
+RELOC_TYPE (PREL31,		REL)
+RELOC_TYPE (MOVW_ABS_NC,	REL)
+RELOC_TYPE (MOVT_ABS,		REL)
+RELOC_TYPE (MOVW_PREL_NC,	REL)
+RELOC_TYPE (MOVT_PREL,		REL)
+RELOC_TYPE (THM_MOVW_ABS_NC,	REL)
+RELOC_TYPE (THM_MOVT_ABS,	REL)
+RELOC_TYPE (THM_MOVW_PREL_NC,	REL)
+RELOC_TYPE (THM_MOVT_PREL,	REL)
+RELOC_TYPE (THM_JUMP19,		REL)
+RELOC_TYPE (THM_JUMP6,		REL)
+RELOC_TYPE (THM_ALU_PREL_11_0,	REL)
+RELOC_TYPE (THM_PC12,		REL)
+RELOC_TYPE (ABS32_NOI,		REL)
+RELOC_TYPE (REL32_NOI,		REL)
+RELOC_TYPE (ALU_PC_G0_NC,	REL)
+RELOC_TYPE (ALU_PC_G0,		REL)
+RELOC_TYPE (ALU_PC_G1_NC,	REL)
+RELOC_TYPE (ALU_PC_G1,		REL)
+RELOC_TYPE (ALU_PC_G2,		REL)
+RELOC_TYPE (LDR_PC_G1,		REL)
+RELOC_TYPE (LDR_PC_G2,		REL)
+RELOC_TYPE (LDRS_PC_G0,		REL)
+RELOC_TYPE (LDRS_PC_G1,		REL)
+RELOC_TYPE (LDRS_PC_G2,		REL)
+RELOC_TYPE (LDC_PC_G0,		REL)
+RELOC_TYPE (LDC_PC_G1,		REL)
+RELOC_TYPE (LDC_PC_G2,		REL)
+RELOC_TYPE (ALU_SB_G0_NC,	REL)
+RELOC_TYPE (ALU_SB_G0,		REL)
+RELOC_TYPE (ALU_SB_G1_NC,	REL)
+RELOC_TYPE (ALU_SB_G1,		REL)
+RELOC_TYPE (ALU_SB_G2,		REL)
+RELOC_TYPE (LDR_SB_G0,		REL)
+RELOC_TYPE (LDR_SB_G1,		REL)
+RELOC_TYPE (LDR_SB_G2,		REL)
+RELOC_TYPE (LDRS_SB_G0,		REL)
+RELOC_TYPE (LDRS_SB_G1,		REL)
+RELOC_TYPE (LDRS_SB_G2,		REL)
+RELOC_TYPE (LDC_SB_G0,		REL)
+RELOC_TYPE (LDC_SB_G1,		REL)
+RELOC_TYPE (LDC_SB_G2,		REL)
+RELOC_TYPE (MOVW_BREL_NC,	REL)
+RELOC_TYPE (MOVT_BREL,		REL)
+RELOC_TYPE (MOVW_BREL,		REL)
+RELOC_TYPE (THM_MOVW_BREL_NC,	REL)
+RELOC_TYPE (THM_MOVT_BREL,	REL)
+RELOC_TYPE (THM_MOVW_BREL,	REL)
+RELOC_TYPE (TLS_GOTDESC,	REL)
+RELOC_TYPE (TLS_CALL,		REL)
+RELOC_TYPE (TLS_DESCSEQ,	REL)
+RELOC_TYPE (THM_TLS_CALL,	REL)
+RELOC_TYPE (PLT32_ABS,		REL)
+RELOC_TYPE (GOT_ABS,		REL)
+RELOC_TYPE (GOT_PREL,		REL)
+RELOC_TYPE (GOT_BREL12,		REL)
+RELOC_TYPE (GOTOFF12,		REL)
+RELOC_TYPE (GOTRELAX,		REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (THM_PC11,		REL)
+RELOC_TYPE (THM_PC9,		REL)
+RELOC_TYPE (TLS_GD32,		REL)
+RELOC_TYPE (TLS_LDM32,		REL)
+RELOC_TYPE (TLS_LDO32,		REL)
+RELOC_TYPE (TLS_IE32,		REL)
+RELOC_TYPE (TLS_LE32,		REL)
+RELOC_TYPE (TLS_LDO12,		REL)
+RELOC_TYPE (TLS_LE12,		REL)
+RELOC_TYPE (TLS_IE12GP,		REL)
+
+RELOC_TYPE (ME_TOO,		REL)
+RELOC_TYPE (THM_TLS_DESCSEQ16,	REL)
+RELOC_TYPE (THM_TLS_DESCSEQ32,	REL)
+RELOC_TYPE (THM_GOT_BREL12,	REL)
+
+RELOC_TYPE (IRELATIVE,		EXEC|DYN)
+
+RELOC_TYPE (RXPC25,		REL)
+RELOC_TYPE (RSBREL32,		REL)
+RELOC_TYPE (THM_RPC22,		REL)
+RELOC_TYPE (RREL32,		REL)
+RELOC_TYPE (RABS22,		REL)
+RELOC_TYPE (RPC24,		REL)
+RELOC_TYPE (RBASE,		REL)
diff --git a/backends/arm_retval.c b/backends/arm_retval.c
new file mode 100644
index 0000000..fa6d391
--- /dev/null
+++ b/backends/arm_retval.c
@@ -0,0 +1,126 @@
+/* Function return value location for ARM EABI.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND arm_
+#include "libebl_CPU.h"
+
+
+/* r0, or pair r0, r1, or aggregate up to r0-r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregs(n)	(2 * (n))
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+arm_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 4;
+	    else
+	      return -1;
+	  }
+	if (size <= 16)
+	  {
+	  intreg:
+	    *locp = loc_intreg;
+	    return size <= 4 ? nloc_intreg : nloc_intregs ((size + 3) / 4);
+	  }
+
+      aggregate:
+	*locp = loc_aggregate;
+	return nloc_aggregate;
+      }
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0
+	  && size > 0 && size <= 4)
+	goto intreg;
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/arm_symbol.c b/backends/arm_symbol.c
new file mode 100644
index 0000000..a733cff
--- /dev/null
+++ b/backends/arm_symbol.c
@@ -0,0 +1,160 @@
+/* Arm specific symbolic name handling.
+   Copyright (C) 2002-2009, 2014, 2015, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		arm_
+#include "libebl_CPU.h"
+
+
+const char *
+arm_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (segment)
+    {
+    case PT_ARM_EXIDX:
+      return "ARM_EXIDX";
+    }
+  return NULL;
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+arm_section_type_name (int type,
+		       char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_ARM_EXIDX:
+      return "ARM_EXIDX";
+    case SHT_ARM_PREEMPTMAP:
+      return "ARM_PREEMPTMAP";
+    case SHT_ARM_ATTRIBUTES:
+      return "ARM_ATTRIBUTES";
+    }
+
+  return NULL;
+}
+
+/* Check whether machine flags are valid.  */
+bool
+arm_machine_flag_check (GElf_Word flags)
+{
+  switch (flags & EF_ARM_EABIMASK)
+    {
+    case EF_ARM_EABI_UNKNOWN:
+    case EF_ARM_EABI_VER1:
+    case EF_ARM_EABI_VER2:
+    case EF_ARM_EABI_VER3:
+    case EF_ARM_EABI_VER4:
+    case EF_ARM_EABI_VER5:
+      break;
+    default:
+      return false;
+    }
+
+  return ((flags &~ (EF_ARM_EABIMASK
+		     | EF_ARM_RELEXEC
+		     | EF_ARM_HASENTRY
+		     | EF_ARM_INTERWORK
+		     | EF_ARM_APCS_26
+		     | EF_ARM_APCS_FLOAT
+		     | EF_ARM_PIC
+		     | EF_ARM_ALIGN8
+		     | EF_ARM_NEW_ABI
+		     | EF_ARM_OLD_ABI
+		     | EF_ARM_SOFT_FLOAT
+		     | EF_ARM_VFP_FLOAT
+		     | EF_ARM_MAVERICK_FLOAT
+		     | EF_ARM_SYMSARESORTED
+		     | EF_ARM_DYNSYMSUSESEGIDX
+		     | EF_ARM_MAPSYMSFIRST
+		     | EF_ARM_EABIMASK
+		     | EF_ARM_BE8
+		     | EF_ARM_LE8)) == 0);
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+arm_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+		       int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_ARM_ABS32:
+      return ELF_T_WORD;
+    case R_ARM_ABS16:
+      return ELF_T_HALF;
+    case R_ARM_ABS8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* The SHT_ARM_EXIDX section type is a valid target for relocation.  */
+bool
+arm_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
+{
+  return sh_type == SHT_ARM_EXIDX;
+}
+
+const char *
+arm_symbol_type_name (int type,
+		      char *buf __attribute__ ((unused)),
+		      size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case STT_ARM_TFUNC:
+      return "ARM_TFUNC";
+    }
+  return NULL;
+}
+
+/* A data mapping symbol is a symbol with "$d" name or "$d.<any...>" name,
+ *    STT_NOTYPE, STB_LOCAL and st_size of zero. The indicate the stat of a
+ *       sequence of data items.  */
+bool
+arm_data_marker_symbol (const GElf_Sym *sym, const char *sname)
+{
+  return (sym != NULL && sname != NULL
+          && sym->st_size == 0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL
+          && GELF_ST_TYPE (sym->st_info) == STT_NOTYPE
+          && (strcmp (sname, "$d") == 0 || startswith (sname, "$d.")));
+}
diff --git a/backends/bpf_init.c b/backends/bpf_init.c
new file mode 100644
index 0000000..f20f339
--- /dev/null
+++ b/backends/bpf_init.c
@@ -0,0 +1,54 @@
+/* Initialization of BPF specific backend library.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		bpf_
+#define RELOC_PREFIX	R_BPF_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on bpf_reloc.def.  */
+#define NO_RELATIVE_RELOC
+#define NO_COPY_RELOC
+#include "common-reloc.c"
+
+
+Ebl *
+bpf_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh)
+{
+  /* We handle it.  */
+  bpf_init_reloc (eh);
+  HOOK (eh, register_info);
+  HOOK (eh, disasm);
+  HOOK (eh, reloc_simple_type);
+
+  return eh;
+}
diff --git a/backends/bpf_regs.c b/backends/bpf_regs.c
new file mode 100644
index 0000000..1863a16
--- /dev/null
+++ b/backends/bpf_regs.c
@@ -0,0 +1,60 @@
+/* Register names and numbers for BPF DWARF.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "bpf.h"
+
+#define BACKEND bpf_
+#include "libebl_CPU.h"
+
+ssize_t
+bpf_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  ssize_t len;
+
+  if (name == NULL)
+    return MAX_BPF_REG;
+  if (regno < 0 || regno >= MAX_BPF_REG)
+    return -1;
+
+  *prefix = "";
+  *setname = "integer";
+  *bits = 64;
+  *type = DW_ATE_signed;
+
+  len = snprintf(name, namelen, "r%d", regno);
+  return ((size_t)len < namelen ? len : -1);
+}
diff --git a/backends/bpf_reloc.def b/backends/bpf_reloc.def
new file mode 100644
index 0000000..59f519b
--- /dev/null
+++ b/backends/bpf_reloc.def
@@ -0,0 +1,32 @@
+/* List the relocation types for BPF.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (64_64,		REL)
+RELOC_TYPE (64_32,		REL)
diff --git a/backends/bpf_symbol.c b/backends/bpf_symbol.c
new file mode 100644
index 0000000..85c948a
--- /dev/null
+++ b/backends/bpf_symbol.c
@@ -0,0 +1,55 @@
+/* BPF specific symbolic name handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND bpf_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+bpf_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+		       int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_BPF_64_64:
+      return ELF_T_XWORD;
+    case R_BPF_64_32:
+      return ELF_T_WORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/backends/common-reloc.c b/backends/common-reloc.c
new file mode 100644
index 0000000..b780bfe
--- /dev/null
+++ b/backends/common-reloc.c
@@ -0,0 +1,165 @@
+/* Common code for ebl reloc functions.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+// GOOGLE
+#include "google-dependency-inject.h"
+
+#include "libebl_CPU.h"
+#include <assert.h>
+
+#define R_TYPE(name)		PASTE (RELOC_PREFIX, name)
+#define PASTE(a, b)		PASTE_1 (a, b)
+#define PASTE_1(a, b)		a##b
+#define R_NAME(name)		R_NAME_1 (RELOC_PREFIX, name)
+#define R_NAME_1(prefix, type)	R_NAME_2 (prefix, type)
+#define R_NAME_2(prefix, type)	#prefix #type
+
+#define RELOC_TYPES		STRINGIFIED_PASTE (BACKEND, reloc.def)
+#define STRINGIFIED_PASTE(a, b)	STRINGIFY (PASTE (a, b))
+#define STRINGIFY(x)		STRINGIFY_1 (x)
+#define STRINGIFY_1(x)		#x
+
+/* Provide a table of reloc type names, in a PIC-friendly fashion.  */
+
+static const struct EBLHOOK(reloc_nametable)
+{
+  char zero[1];
+#define	RELOC_TYPE(type, uses) \
+  char name_##type[sizeof R_NAME (type)];
+#include RELOC_TYPES
+#undef RELOC_TYPE
+} EBLHOOK(reloc_nametable) =
+  {
+    { '\0' },
+#define	RELOC_TYPE(type, uses) R_NAME (type),
+#include RELOC_TYPES
+#undef RELOC_TYPE
+  };
+#define reloc_namestr (&EBLHOOK(reloc_nametable).zero)
+
+static const uint_fast16_t EBLHOOK(reloc_nameidx)[] =
+{
+#define	RELOC_TYPE(type, uses) \
+  [R_TYPE (type)] = offsetof (struct EBLHOOK(reloc_nametable), name_##type),
+#include RELOC_TYPES
+#undef RELOC_TYPE
+};
+#define nreloc \
+  ((int) (sizeof EBLHOOK(reloc_nameidx) / sizeof EBLHOOK(reloc_nameidx)[0]))
+
+#define REL	(1 << (ET_REL - 1))
+#define EXEC	(1 << (ET_EXEC - 1))
+#define DYN	(1 << (ET_DYN - 1))
+static const uint8_t EBLHOOK(reloc_valid)[] =
+{
+#define	RELOC_TYPE(type, uses) [R_TYPE (type)] = uses,
+#include RELOC_TYPES
+#undef RELOC_TYPE
+};
+#undef REL
+#undef EXEC
+#undef DYN
+
+const char *
+EBLHOOK(reloc_type_name) (int reloc,
+			  char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+#ifdef RELOC_TYPE_ID
+  reloc = RELOC_TYPE_ID (reloc);
+#endif
+
+  if (reloc >= 0 && reloc < nreloc && EBLHOOK(reloc_nameidx)[reloc] != 0)
+    return reloc_namestr[EBLHOOK(reloc_nameidx)[reloc]];
+  return NULL;
+}
+
+bool
+EBLHOOK(reloc_type_check) (int reloc)
+{
+#ifdef RELOC_TYPE_ID
+  reloc = RELOC_TYPE_ID (reloc);
+#endif
+
+  return reloc >= 0 && reloc < nreloc && EBLHOOK(reloc_nameidx)[reloc] != 0;
+}
+
+bool
+EBLHOOK(reloc_valid_use) (Elf *elf, int reloc)
+{
+  uint8_t uses;
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  assert (ehdr != NULL);
+  uint8_t type = ehdr->e_type;
+
+#ifdef RELOC_TYPE_ID
+  reloc = RELOC_TYPE_ID (reloc);
+#endif
+
+  uses = EBLHOOK(reloc_valid)[reloc];
+  return type > ET_NONE && type < ET_CORE && (uses & (1 << (type - 1)));
+}
+
+#ifndef NO_COPY_RELOC
+bool
+EBLHOOK(copy_reloc_p) (int reloc)
+{
+  return reloc == R_TYPE (COPY);
+}
+#endif
+
+bool
+EBLHOOK(none_reloc_p) (int reloc)
+{
+  return reloc == R_TYPE (NONE);
+}
+
+#ifndef NO_RELATIVE_RELOC
+bool
+EBLHOOK(relative_reloc_p) (int reloc)
+{
+  return reloc == R_TYPE (RELATIVE);
+}
+#endif
+
+static void
+EBLHOOK(init_reloc) (Ebl *ebl)
+{
+  ebl->reloc_type_name = EBLHOOK(reloc_type_name);
+  ebl->reloc_type_check = EBLHOOK(reloc_type_check);
+  ebl->reloc_valid_use = EBLHOOK(reloc_valid_use);
+  ebl->none_reloc_p = EBLHOOK(none_reloc_p);
+#ifndef NO_COPY_RELOC
+  ebl->copy_reloc_p = EBLHOOK(copy_reloc_p);
+#endif
+#ifndef NO_RELATIVE_RELOC
+  ebl->relative_reloc_p = EBLHOOK(relative_reloc_p);
+#endif
+}
diff --git a/backends/csky_attrs.c b/backends/csky_attrs.c
new file mode 100644
index 0000000..177f0ba
--- /dev/null
+++ b/backends/csky_attrs.c
@@ -0,0 +1,67 @@
+/* C-SKY ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND csky_
+#include "libebl_CPU.h"
+
+bool
+csky_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			    const char *vendor, int tag,
+			    uint64_t value __attribute__ ((unused)),
+			    const char **tag_name,
+			    const char **value_name __attribute__ ((unused)))
+{
+  if (!strcmp (vendor, "csky"))
+    switch (tag)
+      {
+      case 4:
+	*tag_name = "CSKY_ARCH_NAME";
+	return true;
+
+      case 5:
+	*tag_name = "CSKY_CPU_NAME";
+	return true;
+
+      case 6:
+        *tag_name = "CSKY_ISA_FLAGS";
+        return true;
+
+      case 7:
+        *tag_name = "CSKY_ISA_EXT_FLAGS";
+        return true;
+      }
+
+  return false;
+}
diff --git a/backends/csky_cfi.c b/backends/csky_cfi.c
new file mode 100644
index 0000000..7277dbd
--- /dev/null
+++ b/backends/csky_cfi.c
@@ -0,0 +1,60 @@
+/* C-SKY ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND csky_
+#include "libebl_CPU.h"
+
+
+int
+csky_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      DW_CFA_def_cfa, ULEB128_7 (14), ULEB128_7 (0),
+      DW_CFA_val_offset, ULEB128_7 (14), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      SV(4), SV (5), SV (6), SV (7), SV (8), SV (9),
+      SV(10), SV (11), SV (15), SV (16), SV (17)
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 15; /* lr.  */
+
+  return 0;
+}
diff --git a/backends/csky_corenote.c b/backends/csky_corenote.c
new file mode 100644
index 0000000..a1479bd
--- /dev/null
+++ b/backends/csky_corenote.c
@@ -0,0 +1,61 @@
+/* C-SKY specific core note handling.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND	csky_
+#include "libebl_CPU.h"
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 36, .bits = 32 } /* r0..r31 */
+  };
+#define PRSTATUS_REGS_SIZE	(36 * 4)
+
+#include "linux-core-note.c"
diff --git a/backends/csky_init.c b/backends/csky_init.c
new file mode 100644
index 0000000..b2863ce
--- /dev/null
+++ b/backends/csky_init.c
@@ -0,0 +1,60 @@
+/* Initialization of C-SKY specific backend library.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		csky_
+#define RELOC_PREFIX	R_CKCORE_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on csky_reloc.def.  */
+#include "common-reloc.c"
+
+Ebl *
+csky_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh)
+{
+  /* We handle it.  */
+  csky_init_reloc (eh);
+  HOOK (eh, abi_cfi);
+  HOOK (eh, core_note);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, register_info);
+  HOOK (eh, section_type_name);
+  HOOK (eh, set_initial_registers_tid);
+
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 38;
+
+  return eh;
+}
diff --git a/backends/csky_initreg.c b/backends/csky_initreg.c
new file mode 100644
index 0000000..81a0da3
--- /dev/null
+++ b/backends/csky_initreg.c
@@ -0,0 +1,87 @@
+/* Fetch live process registers from TID. C-SKY version.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined __CSKY__ && defined __linux__
+# include <sys/uio.h>
+# include <sys/procfs.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND csky_
+#include "libebl_CPU.h"
+
+bool
+csky_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if !defined __CSKY__ || !defined __linux__
+  return false;
+#else /* __CSKY__ */
+  struct pt_regs user_regs;
+  struct iovec iovec;
+  iovec.iov_base = &user_regs;
+  iovec.iov_len = sizeof (user_regs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  Dwarf_Word dwarf_regs[38];
+
+  /* lr.  */
+  dwarf_regs[15] = user_regs.lr;
+  /* sp.  */
+  dwarf_regs[14] = user_regs.usp;
+  /* r0 ~ r13.  */
+  dwarf_regs[0] = user_regs.a0;
+  dwarf_regs[1] = user_regs.a1;
+  dwarf_regs[2] = user_regs.a2;
+  dwarf_regs[3] = user_regs.a3;
+  for (int i = 4; i < 14; i++)
+    dwarf_regs[i] = user_regs.regs[i - 4];
+  /* r ~ r13.  */
+  for (int i = 16; i < 31; i++)
+    dwarf_regs[i] = user_regs.exregs[i - 16];
+  /* tls.  */
+  dwarf_regs[31] = user_regs.tls;
+  /* hi.  */
+  dwarf_regs[36] = user_regs.rhi;
+  /* lo.  */
+  dwarf_regs[37] = user_regs.rlo;
+  /* pc.  */
+  dwarf_regs[32] = user_regs.pc;
+  setfunc (-1, 1, &dwarf_regs[32], arg);
+
+  return setfunc (0, 38, dwarf_regs, arg);
+#endif
+}
diff --git a/backends/csky_regs.c b/backends/csky_regs.c
new file mode 100644
index 0000000..6d45c04
--- /dev/null
+++ b/backends/csky_regs.c
@@ -0,0 +1,101 @@
+/* Register names and numbers for C-SKY DWARF.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND csky_
+#include "libebl_CPU.h"
+
+ssize_t
+csky_register_info (Ebl *ebl  __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 38;
+
+  *prefix = "";
+  *bits = 32;
+  *type = DW_ATE_signed;
+  *setname = "integer";
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 13:
+    case 16 ... 30:
+      name[0] = 'r';
+      name[1] = regno / 10 + '0';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 14:
+      stpcpy (name, "sp");
+      namelen = 2;
+      break;
+
+    case 15:
+      stpcpy (name, "lr");
+      namelen = 2;
+      break;
+
+    case 31:
+      stpcpy (name, "tls");
+      namelen = 3;
+      break;
+
+    case 36:
+      stpcpy (name, "hi");
+      namelen = 2;
+      break;
+
+    case 37:
+      stpcpy (name, "lo");
+      namelen = 2;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/csky_reloc.def b/backends/csky_reloc.def
new file mode 100644
index 0000000..1108f0c
--- /dev/null
+++ b/backends/csky_reloc.def
@@ -0,0 +1,86 @@
+/* List the relocation types for csky.  -*- C -*-
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+
+RELOC_TYPE (NONE,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (PCRELIMM8BY4,	REL)
+RELOC_TYPE (PCRELIMM11BY2,	REL)
+RELOC_TYPE (PCREL32,		REL|DYN)
+RELOC_TYPE (PCRELJSR_IMM11BY2,	REL)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (ADDRGOT,		REL)
+RELOC_TYPE (ADDRPLT,		REL)
+RELOC_TYPE (PCREL_IMM26BY2,	REL)
+RELOC_TYPE (PCREL_IMM16BY2,	REL)
+RELOC_TYPE (PCREL_IMM16BY4,	REL)
+RELOC_TYPE (PCREL_IMM10BY2,	REL)
+RELOC_TYPE (PCREL_IMM10BY4,	REL)
+RELOC_TYPE (ADDR_HI16,		REL|DYN)
+RELOC_TYPE (ADDR_LO16,		REL|DYN)
+RELOC_TYPE (GOTPC_HI16,		REL)
+RELOC_TYPE (GOTPC_LO16,		REL)
+RELOC_TYPE (GOTOFF_HI16,	REL)
+RELOC_TYPE (GOTOFF_LO16,	REL)
+RELOC_TYPE (GOT12,		REL)
+RELOC_TYPE (GOT_HI16,		REL)
+RELOC_TYPE (GOT_LO16,		REL)
+RELOC_TYPE (PLT12,		REL)
+RELOC_TYPE (PLT_HI16,		REL)
+RELOC_TYPE (PLT_LO16,		REL)
+RELOC_TYPE (ADDRGOT_HI16,	REL)
+RELOC_TYPE (ADDRGOT_LO16,	REL)
+RELOC_TYPE (ADDRPLT_HI16,	REL)
+RELOC_TYPE (ADDRPLT_LO16,	REL)
+RELOC_TYPE (PCREL_JSR_IMM26BY2,	REL|DYN)
+RELOC_TYPE (TOFFSET_LO16,	REL)
+RELOC_TYPE (DOFFSET_LO16,	REL)
+RELOC_TYPE (PCREL_IMM18BY2,	REL)
+RELOC_TYPE (DOFFSET_IMM18,	REL)
+RELOC_TYPE (DOFFSET_IMM18BY2,	REL)
+RELOC_TYPE (DOFFSET_IMM18BY4,	REL)
+RELOC_TYPE (GOT_IMM18BY4,	REL)
+RELOC_TYPE (PLT_IMM18BY4,	REL)
+RELOC_TYPE (PCREL_IMM7BY4,	REL)
+RELOC_TYPE (TLS_LE32,		REL)
+RELOC_TYPE (TLS_IE32,		REL)
+RELOC_TYPE (TLS_GD32,		REL)
+RELOC_TYPE (TLS_LDM32,		REL)
+RELOC_TYPE (TLS_LDO32,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF32,	EXEC|DYN)
diff --git a/backends/csky_symbol.c b/backends/csky_symbol.c
new file mode 100644
index 0000000..79b5bf9
--- /dev/null
+++ b/backends/csky_symbol.c
@@ -0,0 +1,77 @@
+/* C-SKY specific symbolic name handling.
+   Copyright (C) 2019 Hangzhou C-SKY Microsystems co.,ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND csky_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+csky_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_CKCORE_ADDR32:
+      return ELF_T_WORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+bool
+csky_machine_flag_check (GElf_Word flags)
+{
+  switch (flags & EF_CSKY_ABIMASK)
+    {
+    case EF_CSKY_ABIV2:
+      return true;
+    case EF_CSKY_ABIV1:
+    default:
+      return false;
+    }
+}
+
+const char *
+csky_section_type_name (int type,
+		       char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  if (type == SHT_CSKY_ATTRIBUTES)
+    return "CSKY_ATTRIBUTES";
+
+  return NULL;
+}
diff --git a/backends/i386_auxv.c b/backends/i386_auxv.c
new file mode 100644
index 0000000..dba63fe
--- /dev/null
+++ b/backends/i386_auxv.c
@@ -0,0 +1,52 @@
+/* i386 specific auxv handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "fpu\0" "vme\0" "de\0" "pse\0" "tsc\0" "msr\0" "pae\0" "mce\0"
+    "cx8\0" "apic\0" "10\0" "sep\0" "mtrr\0" "pge\0" "mca\0" "cmov\0"
+    "pat\0" "pse36\0" "pn\0" "clflush\0" "20\0" "dts\0" "acpi\0" "mmx\0"
+    "fxsr\0" "sse\0" "sse2\0" "ss\0" "ht\0" "tm\0" "ia64\0" "pbe\0" "\0";
+  return 1;
+}
+
+__typeof (i386_auxv_info) x86_64_auxv_info
+			  __attribute__ ((alias ("i386_auxv_info")));
diff --git a/backends/i386_cfi.c b/backends/i386_cfi.c
new file mode 100644
index 0000000..31f85f7
--- /dev/null
+++ b/backends/i386_cfi.c
@@ -0,0 +1,68 @@
+/* i386 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+int
+i386_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* Call-saved regs.  */
+      DW_CFA_same_value, ULEB128_7 (3), /* %ebx */
+      DW_CFA_same_value, ULEB128_7 (5), /* %ebp */
+      DW_CFA_same_value, ULEB128_7 (6), /* %esi */
+      DW_CFA_same_value, ULEB128_7 (7), /* %edi */
+
+      /* The CFA is the SP.  */
+      DW_CFA_val_offset, ULEB128_7 (4), ULEB128_7 (0),
+
+      /* Segment registers are call-saved if ever used at all.  */
+      DW_CFA_same_value, ULEB128_7 (40), /* %es */
+      DW_CFA_same_value, ULEB128_7 (41), /* %cs */
+      DW_CFA_same_value, ULEB128_7 (42), /* %ss */
+      DW_CFA_same_value, ULEB128_7 (43), /* %ds */
+      DW_CFA_same_value, ULEB128_7 (44), /* %fs */
+      DW_CFA_same_value, ULEB128_7 (45), /* %gs */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 4;
+
+  abi_info->return_address_register = 8; /* %eip */
+
+  return 0;
+}
diff --git a/backends/i386_corenote.c b/backends/i386_corenote.c
new file mode 100644
index 0000000..15cd66b
--- /dev/null
+++ b/backends/i386_corenote.c
@@ -0,0 +1,138 @@
+/* i386 specific core note handling.
+   Copyright (C) 2007-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 32 }
+#define SR(at, n, dwreg)						\
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 16, .pad = 2 }
+
+    GR (0, 1, 3),		/* %ebx */
+    GR (1, 2, 1),		/* %ecx-%edx */
+    GR (3, 2, 6),		/* %esi-%edi */
+    GR (5, 1, 5),		/* %ebp */
+    GR (6, 1, 0),		/* %eax */
+    SR (7, 1, 43),		/* %ds */
+    SR (8, 1, 40),		/* %es */
+    SR (9, 1, 44),		/* %fs */
+    SR (10, 1, 45),		/* %gs */
+    /*  11, 1,			   orig_eax */
+    GR (12, 1, 8),		/* %eip */
+    SR (13, 1, 41),		/* %cs */
+    GR (14, 1, 9),		/* eflags */
+    GR (15, 1, 4),		/* %esp */
+    SR (16, 1, 42),		/* %ss */
+
+#undef	GR
+#undef	SR
+  };
+#define PRSTATUS_REGS_SIZE	(17 * 4)
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "orig_eax", .type = ELF_T_SWORD, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (4 * 11),	      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 37, .count = 2, .bits = 32 }, /* fctrl-fstat */
+    { .offset = 7 * 4, .regno = 11, .count = 8, .bits = 80 }, /* stN */
+  };
+#define FPREGSET_SIZE	108
+
+static const Ebl_Register_Location prxfpreg_regs[] =
+  {
+    { .offset = 0, .regno = 37, .count = 2, .bits = 16 }, /* fctrl-fstat */
+    { .offset = 24, .regno = 39, .count = 1, .bits = 32 }, /* mxcsr */
+    { .offset = 32, .regno = 11, .count = 8, .bits = 80, .pad = 6 }, /* stN */
+    { .offset = 32 + 128, .regno = 21, .count = 8, .bits = 128 }, /* xmm */
+  };
+
+#define	EXTRA_NOTES \
+  EXTRA_REGSET (NT_PRXFPREG, 512, prxfpreg_regs) \
+  case NT_386_TLS: \
+    return tls_info (nhdr->n_descsz, regs_offset, nregloc, reglocs, \
+		     nitems, items);				    \
+  EXTRA_NOTES_IOPERM
+
+static const Ebl_Core_Item tls_items[] =
+  {
+    { .type = ELF_T_WORD, .offset = 0x0, .format = 'd', .name = "index" },
+    { .type = ELF_T_WORD, .offset = 0x4, .format = 'x', .name = "base" },
+    { .type = ELF_T_WORD, .offset = 0x8, .format = 'x', .name = "limit" },
+    { .type = ELF_T_WORD, .offset = 0xc, .format = 'x', .name = "flags" },
+  };
+
+static int
+tls_info (GElf_Word descsz, GElf_Word *regs_offset,
+	  size_t *nregloc, const Ebl_Register_Location **reglocs,
+	  size_t *nitems, const Ebl_Core_Item **items)
+{
+  if (descsz % 16 != 0)
+    return 0;
+
+  *regs_offset = 0;
+  *nregloc = 0;
+  *reglocs = NULL;
+  *nitems = sizeof tls_items / sizeof tls_items[0];
+  *items = tls_items;
+  return 1;
+}
+
+#include "x86_corenote.c"
+#include "linux-core-note.c"
diff --git a/backends/i386_init.c b/backends/i386_init.c
new file mode 100644
index 0000000..579e5fa
--- /dev/null
+++ b/backends/i386_init.c
@@ -0,0 +1,64 @@
+/* Initialization of i386 specific backend library.
+   Copyright (C) 2000-2009, 2013, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		i386_
+#define RELOC_PREFIX	R_386_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on i386_reloc.def.  */
+#include "common-reloc.c"
+
+Ebl *
+i386_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh)
+{
+  /* We handle it.  */
+  i386_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, core_note);
+  generic_debugscn_p = eh->debugscn_p;
+  HOOK (eh, debugscn_p);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, auxv_info);
+  HOOK (eh, disasm);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  For i386 it is 17, why?  */
+  eh->frame_nregs = 9;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, unwind);
+
+  return eh;
+}
diff --git a/backends/i386_initreg.c b/backends/i386_initreg.c
new file mode 100644
index 0000000..c344282
--- /dev/null
+++ b/backends/i386_initreg.c
@@ -0,0 +1,79 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if (defined __i386__ || defined __x86_64__) && defined(__linux__)
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+bool
+i386_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if (!defined __i386__ && !defined __x86_64__) || !defined(__linux__)
+  return false;
+#else /* __i386__ || __x86_64__ */
+  struct user_regs_struct user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+  Dwarf_Word dwarf_regs[9];
+# if defined __i386__
+  dwarf_regs[0] = user_regs.eax;
+  dwarf_regs[1] = user_regs.ecx;
+  dwarf_regs[2] = user_regs.edx;
+  dwarf_regs[3] = user_regs.ebx;
+  dwarf_regs[4] = user_regs.esp;
+  dwarf_regs[5] = user_regs.ebp;
+  dwarf_regs[6] = user_regs.esi;
+  dwarf_regs[7] = user_regs.edi;
+  dwarf_regs[8] = user_regs.eip;
+# elif defined __x86_64__
+  dwarf_regs[0] = user_regs.rax;
+  dwarf_regs[1] = user_regs.rcx;
+  dwarf_regs[2] = user_regs.rdx;
+  dwarf_regs[3] = user_regs.rbx;
+  dwarf_regs[4] = user_regs.rsp;
+  dwarf_regs[5] = user_regs.rbp;
+  dwarf_regs[6] = user_regs.rsi;
+  dwarf_regs[7] = user_regs.rdi;
+  dwarf_regs[8] = user_regs.rip;
+# else /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
+#  error "source file error, it cannot happen"
+# endif /* (__i386__ || __x86_64__) && (!__i386__ && !__x86_64__) */
+  return setfunc (0, 9, dwarf_regs, arg);
+#endif /* __i386__ || __x86_64__ */
+}
diff --git a/backends/i386_regs.c b/backends/i386_regs.c
new file mode 100644
index 0000000..7ec93bb
--- /dev/null
+++ b/backends/i386_regs.c
@@ -0,0 +1,153 @@
+/* Register names and numbers for i386 DWARF.
+   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+ssize_t
+i386_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 46;
+
+  if (regno < 0 || regno > 45 || namelen < 6)
+    return -1;
+
+  *prefix = "%";
+  *bits = 32;
+  *type = DW_ATE_unsigned;
+  if (regno < 11)
+    {
+      *setname = "integer";
+      if (regno < 9)
+	*type = DW_ATE_signed;
+    }
+  else if (regno < 19)
+    {
+      *setname = "x87";
+      *type = DW_ATE_float;
+      *bits = 80;
+    }
+  else if (regno < 29)
+    {
+      *setname = "SSE";
+      *bits = 128;
+    }
+  else if (regno < 37)
+    {
+      *setname = "MMX";
+      *bits = 64;
+    }
+  else if (regno < 40)
+    *setname = "FPU-control";
+  else
+    {
+      *setname = "segment";
+      *bits = 16;
+    }
+
+  switch (regno)
+    {
+      static const char baseregs[][2] =
+	{
+	  "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "ip"
+	};
+
+    case 4:
+    case 5:
+    case 8:
+      *type = DW_ATE_address;
+      FALLTHROUGH;
+    case 0 ... 3:
+    case 6 ... 7:
+      name[0] = 'e';
+      name[1] = baseregs[regno][0];
+      name[2] = baseregs[regno][1];
+      namelen = 3;
+      break;
+
+    case 9:
+      return stpcpy (name, "eflags") + 1 - name;
+    case 10:
+      return stpcpy (name, "trapno") + 1 - name;
+
+    case 11 ... 18:
+      name[0] = 's';
+      name[1] = 't';
+      name[2] = regno - 11 + '0';
+      namelen = 3;
+      break;
+
+    case 21 ... 28:
+      name[0] = 'x';
+      name[1] = 'm';
+      name[2] = 'm';
+      name[3] = regno - 21 + '0';
+      namelen = 4;
+      break;
+
+    case 29 ... 36:
+      name[0] = 'm';
+      name[1] = 'm';
+      name[2] = regno - 29 + '0';
+      namelen = 3;
+      break;
+
+    case 37:
+      *bits = 16;
+      return stpcpy (name, "fctrl") + 1 - name;
+    case 38:
+      *bits = 16;
+      return stpcpy (name, "fstat") + 1 - name;
+    case 39:
+      return stpcpy (name, "mxcsr") + 1 - name;
+
+    case 40 ... 45:
+      name[0] = "ecsdfg"[regno - 40];
+      name[1] = 's';
+      namelen = 2;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/i386_reloc.def b/backends/i386_reloc.def
new file mode 100644
index 0000000..a6a03f3
--- /dev/null
+++ b/backends/i386_reloc.def
@@ -0,0 +1,71 @@
+/* List the relocation types for i386.	-*- C -*-
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (32,			REL|EXEC|DYN)
+RELOC_TYPE (PC32,		REL|EXEC|DYN)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
+RELOC_TYPE (32PLT,		REL)
+RELOC_TYPE (TLS_TPOFF,		EXEC|DYN)
+RELOC_TYPE (TLS_IE,		REL)
+RELOC_TYPE (TLS_GOTIE,		REL)
+RELOC_TYPE (TLS_LE,		REL)
+RELOC_TYPE (TLS_GD,		REL)
+RELOC_TYPE (TLS_LDM,		REL)
+RELOC_TYPE (16,			REL)
+RELOC_TYPE (PC16,		REL)
+RELOC_TYPE (8,			REL)
+RELOC_TYPE (PC8,		REL)
+RELOC_TYPE (TLS_GD_32,		REL)
+RELOC_TYPE (TLS_GD_PUSH,	REL)
+RELOC_TYPE (TLS_GD_CALL,	REL)
+RELOC_TYPE (TLS_GD_POP,		REL)
+RELOC_TYPE (TLS_LDM_32,		REL)
+RELOC_TYPE (TLS_LDM_PUSH,	REL)
+RELOC_TYPE (TLS_LDM_CALL,	REL)
+RELOC_TYPE (TLS_LDM_POP,	REL)
+RELOC_TYPE (TLS_LDO_32,		REL)
+RELOC_TYPE (TLS_IE_32,		REL)
+RELOC_TYPE (TLS_LE_32,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPOFF32,	EXEC|DYN)
+RELOC_TYPE (TLS_GOTDESC,	REL)
+RELOC_TYPE (TLS_DESC_CALL,	REL)
+RELOC_TYPE (TLS_DESC,		EXEC)
+RELOC_TYPE (IRELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOT32X,		REL)
diff --git a/backends/i386_retval.c b/backends/i386_retval.c
new file mode 100644
index 0000000..8a9c2a2
--- /dev/null
+++ b/backends/i386_retval.c
@@ -0,0 +1,139 @@
+/* Function return value location for Linux/i386 ABI.
+   Copyright (C) 2005-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+
+/* %eax, or pair %eax, %edx.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %st(0).  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg11 }
+  };
+#define nloc_fpreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %eax.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+i386_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Word size;
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 4;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	    if (encoding == DW_ATE_float)
+	      {
+		if (size > 16)
+		  return -2;
+		*locp = loc_fpreg;
+		return nloc_fpreg;
+	      }
+	  }
+	*locp = loc_intreg;
+	if (size <= 4)
+	  return nloc_intreg;
+	if (size <= 8)
+	  return nloc_intregpair;
+      }
+    FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/i386_symbol.c b/backends/i386_symbol.c
new file mode 100644
index 0000000..a4b6ec0
--- /dev/null
+++ b/backends/i386_symbol.c
@@ -0,0 +1,76 @@
+/* i386 specific symbolic name handling.
+   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool
+i386_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
+{
+  return type == R_386_GOTPC;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+i386_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_386_32:
+      return ELF_T_SWORD;
+    case R_386_16:
+      return ELF_T_HALF;
+    case R_386_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check section name for being that of a debug information section.  */
+bool (*generic_debugscn_p) (const char *);
+bool
+i386_debugscn_p (const char *name)
+{
+  return (generic_debugscn_p (name)
+	  || strcmp (name, ".stab") == 0
+	  || strcmp (name, ".stabstr") == 0);
+}
diff --git a/backends/i386_unwind.c b/backends/i386_unwind.c
new file mode 100644
index 0000000..5c9a5de
--- /dev/null
+++ b/backends/i386_unwind.c
@@ -0,0 +1,84 @@
+/* Get previous frame state for an existing frame state using frame pointers.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+/* Register numbers for frame and stack pointers.  We take advantage of
+   them being next to each other when calling getfunc and setfunc.  */
+#define ESP 4
+#define EBP (ESP + 1)
+
+/* Most basic frame pointer chasing with EBP as frame pointer.
+   PC = *(FP + 4), SP = FP + 8, FP = *FP.  */
+bool
+i386_unwind (Ebl *ebl __attribute__ ((unused)),
+	     Dwarf_Addr pc __attribute__ ((unused)),
+	     ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+	     ebl_pid_memory_read_t *readfunc, void *arg,
+	     bool *signal_framep __attribute__ ((unused)))
+{
+  /* sp = 0, fp = 1 */
+  Dwarf_Word regs[2];
+
+  /* Get current stack and frame pointers.  */
+  if (! getfunc (ESP, 2, regs, arg))
+    return false;
+
+  Dwarf_Word sp = regs[0];
+  Dwarf_Word fp = regs[1];
+
+  /* Sanity check.  We only support traditional stack frames.  */
+  if (fp == 0 || sp == 0 || fp < sp)
+    return false;
+
+  /* Get the return address from the stack, it is our new pc.  */
+  Dwarf_Word ret_addr;
+  if (! readfunc (fp + 4, &ret_addr, arg) || ret_addr == 0)
+    return false;
+
+  /* Get new sp and fp.  Sanity check again.  */
+  sp = fp + 8;
+  if (! readfunc (fp, &fp, arg) || fp == 0 || sp >= fp)
+    return false;
+
+  /* Set new sp, fp and pc.  */
+  regs[0] = sp;
+  regs[1] = fp;
+  if (! setfunc (ESP, 2, regs, arg) || ! setfunc (-1, 1, &ret_addr, arg))
+    return false;
+
+  return true;
+}
diff --git a/backends/ia64_init.c b/backends/ia64_init.c
new file mode 100644
index 0000000..b46b35c
--- /dev/null
+++ b/backends/ia64_init.c
@@ -0,0 +1,60 @@
+/* Initialization of IA-64 specific backend library.
+   Copyright (C) 2002, 2003, 2005, 2006, 2007, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		ia64_
+#define RELOC_PREFIX	R_IA64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on ia64_reloc.def.  */
+#include "common-reloc.c"
+
+Ebl *
+ia64_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh)
+{
+  /* We handle it.  */
+  ia64_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, segment_type_name);
+  HOOK (eh, section_type_name);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, machine_section_flag_check);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+  HOOK (eh, check_reloc_target_type);
+
+  return eh;
+}
diff --git a/backends/ia64_regs.c b/backends/ia64_regs.c
new file mode 100644
index 0000000..a27fe63
--- /dev/null
+++ b/backends/ia64_regs.c
@@ -0,0 +1,273 @@
+/* Register names and numbers for IA64 DWARF.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND i386_
+#include "libebl_CPU.h"
+
+ssize_t
+ia64_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 687 + 64;
+
+  if (regno < 0 || regno > 687 + 63 || namelen < 12)
+    return -1;
+
+  *prefix = "ar.";
+  *setname = "application";
+  *bits = 64;
+  *type = DW_ATE_signed;
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = (regno - 0) + '0';
+      namelen = 2;
+      *setname = "integer";
+      *prefix = "";
+      break;
+
+    case 10 ... 99:
+      name[0] = 'r';
+      name[1] = (regno - 0) / 10 + '0';
+      name[2] = (regno - 0) % 10 + '0';
+      namelen = 3;
+      *setname = "integer";
+      *prefix = "";
+      break;
+
+    case 100 ... 127:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = (regno - 100) / 10 + '0';
+      name[3] = (regno - 0) % 10 + '0';
+      namelen = 4;
+      *setname = "integer";
+      *prefix = "";
+      break;
+
+    case 128 + 0 ... 128 + 9:
+      name[0] = 'f';
+      name[1] = (regno - 128) + '0';
+      namelen = 2;
+      *type = DW_ATE_float;
+      *bits = 128;
+      *setname = "FPU";
+      *prefix = "";
+      break;
+
+    case 128 + 10 ... 128 + 99:
+      name[0] = 'f';
+      name[1] = (regno - 128) / 10 + '0';
+      name[2] = (regno - 128) % 10 + '0';
+      namelen = 3;
+      *setname = "FPU";
+      *prefix = "";
+      break;
+
+    case 128 + 100 ... 128 + 127:
+      name[0] = 'f';
+      name[1] = '1';
+      name[2] = (regno - 128 - 100) / 10 + '0';
+      name[3] = (regno - 128) % 10 + '0';
+      namelen = 4;
+      *type = DW_ATE_float;
+      *bits = 128;
+      *setname = "FPU";
+      *prefix = "";
+      break;
+
+    case 320 + 0 ... 320 + 7:
+      name[0] = 'b';
+      name[1] = (regno - 320) + '0';
+      namelen = 2;
+      *type = DW_ATE_address;
+      *setname = "branch";
+      *prefix = "";
+      break;
+
+    case 328 ... 333:
+      {
+	static const char named_special[][5] =
+	  {
+	    "vfp", "vrap", "pr", "ip", "psr", "cfm"
+	  };
+	*setname = "special";
+	*prefix = "";
+	*type = regno == 331 ? DW_ATE_address : DW_ATE_unsigned;
+	return stpcpy (name, named_special[regno - 328]) + 1 - name;
+      }
+
+    case 590:
+      *setname = "special";
+      *prefix = "";
+      *type = DW_ATE_unsigned;
+      return stpcpy (name, "bof") + 1 - name;
+
+    case 334 + 0 ... 334 + 7:
+      name[0] = 'k';
+      name[1] = 'r';
+      name[2] = (regno - 334) + '0';
+      namelen = 3;
+      *prefix = "";
+      break;
+
+    case 334 + 8 ... 334 + 127:
+      {
+	static const char named_ar[][9] =
+	  {
+	    [16 - 8] = "rsc",
+	    [17 - 8] = "bsp",
+	    [18 - 8] = "bspstore",
+	    [19 - 8] = "rnat",
+	    [21 - 8] = "fcr",
+	    [24 - 8] = "eflag",
+	    [25 - 8] = "csd",
+	    [26 - 8] = "ssd",
+	    [27 - 8] = "cflg",
+	    [28 - 8] = "fsr",
+	    [29 - 8] = "fir",
+	    [30 - 8] = "fdr",
+	    [32 - 8] = "ccv",
+	    [36 - 8] = "unat",
+	    [40 - 8] = "fpsr",
+	    [44 - 8] = "itc",
+	    [64 - 8] = "pfs",
+	    [65 - 8] = "lc",
+	    [66 - 8] = "ec",
+	  };
+	const size_t idx = regno - (334 + 8);
+	*type = DW_ATE_unsigned;
+	if (idx == 1 || idx == 2)
+	  *type = DW_ATE_address;
+	if (idx < sizeof named_ar / sizeof named_ar[0]
+	    && named_ar[idx][0] != '\0')
+	  return stpcpy (name, named_ar[idx]) + 1 - name;
+
+	name[0] = 'a';
+	name[1] = 'r';
+	switch (regno - 334)
+	  {
+	  case 0 ... 9:
+	    name[2] = (regno - 334) + '0';
+	    namelen = 3;
+	    break;
+	  case 10 ... 99:
+	    name[2] = (regno - 334) / 10 + '0';
+	    name[3] = (regno - 334) % 10 + '0';
+	    namelen = 4;
+	    break;
+	  case 100 ... 127:
+	    name[2] = '1';
+	    name[3] = (regno - 334 - 100) / 10 + '0';
+	    name[4] = (regno - 334) % 10 + '0';
+	    namelen = 5;
+	    break;
+	  }
+	*prefix = "";
+	break;
+      }
+
+    case 462 + 0 ... 462 + 9:
+      name[0] = 'n';
+      name[1] = 'a';
+      name[2] = 't';
+      name[3] = (regno - 462) + '0';
+      namelen = 4;
+      *setname = "NAT";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 462 + 10 ... 462 + 99:
+      name[0] = 'n';
+      name[1] = 'a';
+      name[2] = 't';
+      name[3] = (regno - 462) / 10 + '0';
+      name[4] = (regno - 462) % 10 + '0';
+      namelen = 5;
+      *setname = "NAT";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 462 + 100 ... 462 + 127:
+      name[0] = 'n';
+      name[1] = 'a';
+      name[2] = 't';
+      name[3] = '1';
+      name[4] = (regno - 462 - 100) / 10 + '0';
+      name[5] = (regno - 462) % 10 + '0';
+      namelen = 6;
+      *setname = "NAT";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 687 + 0 ... 687 + 9:
+      name[0] = 'p';
+      name[1] = (regno - 687) + '0';
+      namelen = 2;
+      *setname = "predicate";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    case 687 + 10 ... 687 + 63:
+      name[0] = 'p';
+      name[1] = (regno - 687) / 10 + '0';
+      name[2] = (regno - 687) % 10 + '0';
+      namelen = 3;
+      *setname = "predicate";
+      *type = DW_ATE_boolean;
+      *bits = 1;
+      *prefix = "";
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/ia64_reloc.def b/backends/ia64_reloc.def
new file mode 100644
index 0000000..2428925
--- /dev/null
+++ b/backends/ia64_reloc.def
@@ -0,0 +1,113 @@
+/* List the relocation types for ia64.  -*- C -*-
+   Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (IMM14,		REL)
+RELOC_TYPE (IMM22,		REL)
+RELOC_TYPE (IMM64,		REL)
+RELOC_TYPE (DIR32MSB,		REL|EXEC|DYN)
+RELOC_TYPE (DIR32LSB,		REL|EXEC|DYN)
+RELOC_TYPE (DIR64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (DIR64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (GPREL22,		REL)
+RELOC_TYPE (GPREL64I,		REL)
+RELOC_TYPE (GPREL32MSB,		REL)
+RELOC_TYPE (GPREL32LSB,		REL)
+RELOC_TYPE (GPREL64MSB,		REL)
+RELOC_TYPE (GPREL64LSB,		REL)
+RELOC_TYPE (LTOFF22,		REL)
+RELOC_TYPE (LTOFF64I,		REL)
+RELOC_TYPE (PLTOFF22,		REL)
+RELOC_TYPE (PLTOFF64I,		REL)
+RELOC_TYPE (PLTOFF64MSB,	REL)
+RELOC_TYPE (PLTOFF64LSB,	REL)
+RELOC_TYPE (FPTR64I,		REL)
+RELOC_TYPE (FPTR32MSB,		REL|EXEC|DYN)
+RELOC_TYPE (FPTR32LSB,		REL|EXEC|DYN)
+RELOC_TYPE (FPTR64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (FPTR64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL60B,		REL)
+RELOC_TYPE (PCREL21B,		REL)
+RELOC_TYPE (PCREL21M,		REL)
+RELOC_TYPE (PCREL21F,		REL)
+RELOC_TYPE (PCREL32MSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL32LSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (PCREL64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_FPTR22,	REL)
+RELOC_TYPE (LTOFF_FPTR64I,	REL)
+RELOC_TYPE (LTOFF_FPTR32MSB,	REL)
+RELOC_TYPE (LTOFF_FPTR32LSB,	REL)
+RELOC_TYPE (LTOFF_FPTR64MSB,	REL)
+RELOC_TYPE (LTOFF_FPTR64LSB,	REL)
+RELOC_TYPE (SEGREL32MSB,	REL)
+RELOC_TYPE (SEGREL32LSB,	REL)
+RELOC_TYPE (SEGREL64MSB,	REL)
+RELOC_TYPE (SEGREL64LSB,	REL)
+RELOC_TYPE (SECREL32MSB,	REL)
+RELOC_TYPE (SECREL32LSB,	REL)
+RELOC_TYPE (SECREL64MSB,	REL)
+RELOC_TYPE (SECREL64LSB,	REL)
+RELOC_TYPE (REL32MSB,		EXEC|DYN)
+RELOC_TYPE (REL32LSB,		EXEC|DYN)
+RELOC_TYPE (REL64MSB,		EXEC|DYN)
+RELOC_TYPE (REL64LSB,		EXEC|DYN)
+RELOC_TYPE (LTV32MSB,		REL)
+RELOC_TYPE (LTV32LSB,		REL)
+RELOC_TYPE (LTV64MSB,		REL)
+RELOC_TYPE (LTV64LSB,		REL)
+RELOC_TYPE (PCREL21BI,		REL)
+RELOC_TYPE (PCREL22,		REL)
+RELOC_TYPE (PCREL64I,		REL)
+RELOC_TYPE (IPLTMSB,		REL|EXEC|DYN)
+RELOC_TYPE (IPLTLSB,		REL|EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (SUB,		0)
+RELOC_TYPE (LTOFF22X,		REL)
+RELOC_TYPE (LDXMOV,		REL)
+RELOC_TYPE (TPREL14,		REL)
+RELOC_TYPE (TPREL22,		REL)
+RELOC_TYPE (TPREL64I,		REL)
+RELOC_TYPE (TPREL64MSB,		REL|EXEC|DYN)
+RELOC_TYPE (TPREL64LSB,		REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_TPREL22,	REL)
+RELOC_TYPE (DTPMOD64MSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPMOD64LSB,	REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_DTPMOD22,	REL)
+RELOC_TYPE (DTPREL14,		REL)
+RELOC_TYPE (DTPREL22,		REL)
+RELOC_TYPE (DTPREL64I,		REL)
+RELOC_TYPE (DTPREL32MSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPREL32LSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPREL64MSB,	REL|EXEC|DYN)
+RELOC_TYPE (DTPREL64LSB,	REL|EXEC|DYN)
+RELOC_TYPE (LTOFF_DTPREL22,	REL)
+
+#define NO_RELATIVE_RELOC	1
diff --git a/backends/ia64_retval.c b/backends/ia64_retval.c
new file mode 100644
index 0000000..7e12236
--- /dev/null
+++ b/backends/ia64_retval.c
@@ -0,0 +1,365 @@
+/* Function return value location for IA64 ABI.
+   Copyright (C) 2006-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND ia64_
+#include "libebl_CPU.h"
+
+
+/* r8, or pair r8, r9, or aggregate up to r8-r11.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg8 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg9 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg10 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg11 }, { .atom = DW_OP_piece, .number = 8 },
+  };
+#define nloc_intreg	1
+#define nloc_intregs(n)	(2 * (n))
+
+/* f8, or aggregate up to f8-f15.  */
+#define DEFINE_FPREG(size) 						      \
+  static const Dwarf_Op loc_fpreg_##size[] =				      \
+    {									      \
+      { .atom = DW_OP_regx, .number = 128 + 8 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 9 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 10 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 11 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 12 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 13 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 14 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+      { .atom = DW_OP_regx, .number = 128 + 15 },			      \
+      { .atom = DW_OP_piece, .number = size },				      \
+    }
+#define nloc_fpreg	1
+#define nloc_fpregs(n)	(2 * (n))
+
+DEFINE_FPREG (4);
+DEFINE_FPREG (8);
+DEFINE_FPREG (10);
+
+#undef DEFINE_FPREG
+
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r8.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg8, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+static inline int
+compute_hfa (const Dwarf_Op *loc, int nregs,
+	     const Dwarf_Op **locp, int fpregs_used)
+{
+  if (fpregs_used == 0)
+    *locp = loc;
+  else if (*locp != loc)
+    return 9;
+  return fpregs_used + nregs;
+}
+
+/* If this type is an HFA small enough to be returned in FP registers,
+   return the number of registers to use.  Otherwise 9, or -1 for errors.  */
+static int
+hfa_type (Dwarf_Die *typedie, Dwarf_Word size,
+	  const Dwarf_Op **locp, int fpregs_used)
+{
+  /* Descend the type structure, counting elements and finding their types.
+     If we find a datum that's not an FP type (and not quad FP), punt.
+     If we find a datum that's not the same FP type as the first datum, punt.
+     If we count more than eight total homogeneous FP data, punt.  */
+
+  int tag = DWARF_TAG_OR_RETURN (typedie);
+  switch (tag)
+    {
+      Dwarf_Attribute attr_mem;
+
+    case -1:
+      return -1;
+
+    case DW_TAG_base_type:;
+      Dwarf_Word encoding;
+      if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						 &attr_mem), &encoding) != 0)
+	return -1;
+
+#define hfa(loc, nregs) compute_hfa(loc, nregs, locp, fpregs_used)
+      switch (encoding)
+	{
+	case DW_ATE_float:
+	  switch (size)
+	    {
+	    case 4:		/* float */
+	      return hfa (loc_fpreg_4, 1);
+	    case 8:		/* double */
+	      return hfa (loc_fpreg_8, 1);
+	    case 10:       /* x86-style long double, not really used */
+	      return hfa (loc_fpreg_10, 1);
+	    }
+	  break;
+
+	case DW_ATE_complex_float:
+	  switch (size)
+	    {
+	    case 4 * 2:	/* complex float */
+	      return hfa (loc_fpreg_4, 2);
+	    case 8 * 2:	/* complex double */
+	      return hfa (loc_fpreg_8, 2);
+	    case 10 * 2:	/* complex long double (x86-style) */
+	      return hfa (loc_fpreg_10, 2);
+	    }
+	  break;
+	}
+      break;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:;
+      Dwarf_Die child_mem;
+      switch (dwarf_child (typedie, &child_mem))
+	{
+	default:
+	  return -1;
+
+	case 1:			/* No children: empty struct.  */
+	  break;
+
+	case 0:;		/* Look at each element.  */
+	  int max_used = fpregs_used;
+	  do
+	    switch (dwarf_tag (&child_mem))
+	      {
+	      case -1:
+		return -1;
+
+	      case DW_TAG_member:;
+		Dwarf_Die child_type_mem;
+		Dwarf_Die *child_typedie
+		  = dwarf_formref_die (dwarf_attr_integrate (&child_mem,
+							     DW_AT_type,
+							     &attr_mem),
+				       &child_type_mem);
+		Dwarf_Word child_size;
+		if (dwarf_aggregate_size (child_typedie, &child_size) != 0)
+		  return -1;
+		if (tag == DW_TAG_union_type)
+		  {
+		    int used = hfa_type (child_typedie, child_size,
+					 locp, fpregs_used);
+		    if (used < 0 || used > 8)
+		      return used;
+		    if (used > max_used)
+		      max_used = used;
+		  }
+		else
+		  {
+		    fpregs_used = hfa_type (child_typedie, child_size,
+					    locp, fpregs_used);
+		    if (fpregs_used < 0 || fpregs_used > 8)
+		      return fpregs_used;
+		  }
+	      }
+	  while (dwarf_siblingof (&child_mem, &child_mem) == 0);
+	  if (tag == DW_TAG_union_type)
+	    fpregs_used = max_used;
+	  break;
+	}
+      break;
+
+    case DW_TAG_array_type:
+      if (size == 0)
+	break;
+
+      Dwarf_Die base_type_mem;
+      Dwarf_Die *base_typedie
+	= dwarf_formref_die (dwarf_attr_integrate (typedie, DW_AT_type,
+						   &attr_mem),
+			     &base_type_mem);
+      Dwarf_Word base_size;
+      if (dwarf_aggregate_size (base_typedie, &base_size) != 0)
+	return -1;
+
+      int used = hfa_type (base_typedie, base_size, locp, 0);
+      if (used < 0 || used > 8)
+	return used;
+      if (size % (*locp)[1].number != 0)
+	return 0;
+      fpregs_used += used * (size / (*locp)[1].number);
+      break;
+
+    default:
+      return 9;
+    }
+
+  return fpregs_used;
+}
+
+int
+ia64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 8;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	    case DW_ATE_float:
+	      switch (size)
+		{
+		case 4:		/* float */
+		  *locp = loc_fpreg_4;
+		  return nloc_fpreg;
+		case 8:		/* double */
+		  *locp = loc_fpreg_8;
+		  return nloc_fpreg;
+		case 10:       /* x86-style long double, not really used */
+		  *locp = loc_fpreg_10;
+		  return nloc_fpreg;
+		case 16:	/* long double, IEEE quad format */
+		  *locp = loc_intreg;
+		  return nloc_intregs (2);
+		}
+	      return -2;
+
+	    case DW_ATE_complex_float:
+	      switch (size)
+		{
+		case 4 * 2:	/* complex float */
+		  *locp = loc_fpreg_4;
+		  return nloc_fpregs (2);
+		case 8 * 2:	/* complex double */
+		  *locp = loc_fpreg_8;
+		  return nloc_fpregs (2);
+		case 10 * 2:	/* complex long double (x86-style) */
+		  *locp = loc_fpreg_10;
+		  return nloc_fpregs (2);
+		case 16 * 2:	/* complex long double (IEEE quad) */
+		  *locp = loc_intreg;
+		  return nloc_intregs (4);
+		}
+	      return -2;
+	    }
+	}
+
+    intreg:
+      *locp = loc_intreg;
+      if (size <= 8)
+	return nloc_intreg;
+      if (size <= 32)
+	return nloc_intregs ((size + 7) / 8);
+
+    large:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) != 0)
+	return -1;
+
+      /* If this qualifies as an homogeneous floating-point aggregate
+	 (HFA), then it should be returned in FP regs. */
+      int nfpreg = hfa_type (typedie, size, locp, 0);
+      if (nfpreg < 0)
+	return nfpreg;
+      else if (nfpreg > 0 && nfpreg <= 8)
+	return nfpreg == 1 ? nloc_fpreg : nloc_fpregs (nfpreg);
+
+      if (size > 32)
+	goto large;
+
+      goto intreg;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/ia64_symbol.c b/backends/ia64_symbol.c
new file mode 100644
index 0000000..0c038f0
--- /dev/null
+++ b/backends/ia64_symbol.c
@@ -0,0 +1,158 @@
+/* IA-64 specific symbolic name handling.
+   Copyright (C) 2002-2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <assert.h>
+
+#define BACKEND		ia64_
+#include "libebl_CPU.h"
+
+
+const char *
+ia64_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (segment)
+    {
+    case PT_IA_64_ARCHEXT:
+      return "IA_64_ARCHEXT";
+    case PT_IA_64_UNWIND:
+      return "IA_64_UNWIND";
+    case PT_IA_64_HP_OPT_ANOT:
+      return "IA_64_HP_OPT_ANOT";
+    case PT_IA_64_HP_HSL_ANOT:
+      return "IA_64_HP_HSL_ANOT";
+    case PT_IA_64_HP_STACK:
+      return "IA_64_HP_STACK";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+const char *
+ia64_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+		       size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_IA_64_PLT_RESERVE:
+      return "IA_64_PLT_RESERVE";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+/* Check dynamic tag.  */
+bool
+ia64_dynamic_tag_check (int64_t tag)
+{
+  return tag == DT_IA_64_PLT_RESERVE;
+}
+
+/* Check whether machine flags are valid.  */
+bool
+ia64_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ EF_IA_64_ABI64) == 0);
+}
+
+/* Check whether SHF_MASKPROC flags are valid.  */
+bool
+ia64_machine_section_flag_check (GElf_Xword sh_flags)
+{
+  return (sh_flags &~ (SHF_IA_64_SHORT | SHF_IA_64_NORECOV)) == 0;
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+ia64_section_type_name (int type,
+			char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_IA_64_EXT:
+      return "IA_64_EXT";
+    case SHT_IA_64_UNWIND:
+      return "IA_64_UNWIND";
+    }
+
+  return NULL;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+ia64_reloc_simple_type (Ebl *ebl, int type,
+			int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+      /* The SECREL types when used with non-allocated sections
+	 like .debug_* are the same as direct absolute relocs
+	 applied to those sections, since a 0 section address is assumed.
+	 So we treat them the same here.  */
+
+    case R_IA64_SECREL32MSB:
+    case R_IA64_DIR32MSB:
+      if (ebl->data == ELFDATA2MSB)
+	return ELF_T_WORD;
+      break;
+    case R_IA64_SECREL32LSB:
+    case R_IA64_DIR32LSB:
+      if (ebl->data == ELFDATA2LSB)
+	return ELF_T_WORD;
+      break;
+    case R_IA64_DIR64MSB:
+    case R_IA64_SECREL64MSB:
+      if (ebl->data == ELFDATA2MSB)
+	return ELF_T_XWORD;
+      break;
+    case R_IA64_SECREL64LSB:
+    case R_IA64_DIR64LSB:
+      if (ebl->data == ELFDATA2LSB)
+	return ELF_T_XWORD;
+      break;
+    }
+
+  return ELF_T_NUM;
+}
+
+/* The SHT_IA_64_UNWIND section type is a valid target for relocation.  */
+bool
+ia64_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)), Elf64_Word sh_type)
+{
+  return sh_type == SHT_IA_64_UNWIND;
+}
diff --git a/backends/libebl_CPU.h b/backends/libebl_CPU.h
new file mode 100644
index 0000000..d138f5f
--- /dev/null
+++ b/backends/libebl_CPU.h
@@ -0,0 +1,100 @@
+/* Common interface for libebl modules.
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2013, 2014 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBEBL_CPU_H
+#define _LIBEBL_CPU_H 1
+
+#include <dwarf.h>
+#include <libeblP.h>
+
+#define EBLHOOK(name)	EBLHOOK_1(BACKEND, name)
+#define EBLHOOK_1(a, b)	EBLHOOK_2(a, b)
+#define EBLHOOK_2(a, b)	a##b
+
+/* Constructor.  */
+extern Ebl *EBLHOOK(init) (Elf *elf, GElf_Half machine, Ebl *eh);
+
+#include "ebl-hooks.h"
+
+#define HOOK(eh, name)	eh->name = EBLHOOK(name)
+
+extern bool (*generic_debugscn_p) (const char *) attribute_hidden;
+
+/* Helper for retval.  Return dwarf_tag (die), but calls return -1
+   if there where previous errors that leave die NULL.  */
+#define DWARF_TAG_OR_RETURN(die)  \
+  ({ Dwarf_Die *_die = (die);	  \
+     if (_die == NULL) return -1; \
+     dwarf_tag (_die); })
+
+/* Get a type die corresponding to DIE.  Peel CV qualifiers off
+   it.  Returns zero if the DIE doesn't have a type, or the type
+   is DW_TAG_unspecified_type.  Returns -1 on error.  Otherwise
+   returns the result tag DW_AT value.  */
+static inline int
+dwarf_peeled_die_type (Dwarf_Die *die, Dwarf_Die *result)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Attribute *attr = dwarf_attr_integrate (die, DW_AT_type, &attr_mem);
+  if (attr == NULL)
+    /* The function has no return value, like a `void' function in C.  */
+    return 0;
+
+  if (result == NULL)
+    return -1;
+
+  if (dwarf_formref_die (attr, result) == NULL)
+    return -1;
+
+  if (dwarf_peel_type (result, result) != 0)
+    return -1;
+
+  int tag = dwarf_tag (result);
+  if (tag == DW_TAG_unspecified_type)
+    return 0; /* Treat an unspecified type as if there was no type.  */
+
+  return tag;
+}
+
+static inline bool
+dwarf_is_pointer (int tag)
+{
+  return tag == DW_TAG_pointer_type
+	 || tag == DW_TAG_ptr_to_member_type
+	 || tag == DW_TAG_reference_type
+	 || tag == DW_TAG_rvalue_reference_type;
+}
+
+#define CASE_POINTER \
+  case DW_TAG_pointer_type: \
+  case DW_TAG_ptr_to_member_type: \
+  case DW_TAG_reference_type: \
+  case DW_TAG_rvalue_reference_type
+
+#endif	/* libebl_CPU.h */
diff --git a/backends/linux-core-note.c b/backends/linux-core-note.c
new file mode 100644
index 0000000..238ec16
--- /dev/null
+++ b/backends/linux-core-note.c
@@ -0,0 +1,316 @@
+/* Common core note type descriptions for Linux.
+   Copyright (C) 2007-2010 Red Hat, Inc.
+   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <string.h>
+
+/* The including CPU_corenote.c file provides prstatus_regs and
+   defines macros ULONG, [PUG]ID_T, and ALIGN_*, TYPE_*.
+
+   Here we describe the common layout used in <linux/elfcore.h>.  */
+
+#define	CHAR			int8_t
+#define	ALIGN_CHAR		1
+#define	TYPE_CHAR		ELF_T_BYTE
+#define	SHORT			uint16_t
+#define ALIGN_SHORT		2
+#define TYPE_SHORT		ELF_T_HALF
+#define	INT			int32_t
+#ifndef ALIGN_INT
+# define ALIGN_INT		4
+#endif
+#define TYPE_INT		ELF_T_SWORD
+#ifndef PR_REG
+# define PR_REG			ULONG
+#endif
+#ifndef ALIGN_PR_REG
+# define ALIGN_PR_REG		ALIGN_ULONG
+#endif
+#ifndef PRPSINFO_UID_T
+# define PRPSINFO_UID_T		UID_T
+# define ALIGN_PRPSINFO_UID_T	ALIGN_UID_T
+# define TYPE_PRPSINFO_UID_T	TYPE_UID_T
+#endif
+#ifndef PRPSINFO_GID_T
+# define PRPSINFO_GID_T		GID_T
+# define ALIGN_PRPSINFO_GID_T	ALIGN_GID_T
+# define TYPE_PRPSINFO_GID_T	TYPE_GID_T
+#endif
+
+#define FIELD(type, name) type name __attribute__ ((aligned (ALIGN_##type)))
+
+struct EBLHOOK(siginfo)
+{
+  FIELD (INT, si_signo);
+  FIELD (INT, si_code);
+  FIELD (INT, si_errno);
+};
+
+struct EBLHOOK(timeval)
+{
+  FIELD (ULONG, tv_sec);
+  FIELD (ULONG, tv_usec);
+};
+
+/* On sparc64, tv_usec (suseconds_t) is actually 32 bits with 32 bits padding.
+   The 'T'|0x80 value for .format indicates this as a special kludge.  */
+#if SUSECONDS_HALF
+# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T'|0x80, .count = 2)
+#else
+# define TIMEVAL_FIELD(name)	FIELD (time, ULONG, name, 'T', .count = 2)
+#endif
+
+
+struct EBLHOOK(prstatus)
+{
+  struct EBLHOOK(siginfo) pr_info;
+  FIELD (SHORT, pr_cursig);
+  FIELD (ULONG, pr_sigpend);
+  FIELD (ULONG, pr_sighold);
+  FIELD (PID_T, pr_pid);
+  FIELD (PID_T, pr_ppid);
+  FIELD (PID_T, pr_pgrp);
+  FIELD (PID_T, pr_sid);
+  struct EBLHOOK(timeval) pr_utime;
+  struct EBLHOOK(timeval) pr_stime;
+  struct EBLHOOK(timeval) pr_cutime;
+  struct EBLHOOK(timeval) pr_cstime;
+  struct
+  {
+    FIELD (PR_REG, pr_reg[PRSTATUS_REGS_SIZE / sizeof (PR_REG)]);
+  }
+#ifdef ALIGN_PR_REG
+    __attribute__ ((aligned (ALIGN_PR_REG)))
+#endif
+    ;
+  FIELD (INT, pr_fpvalid);
+}
+#ifdef ALIGN_PRSTATUS
+  attribute_packed __attribute__ ((aligned (ALIGN_PRSTATUS)))
+#endif
+;
+
+#define	FNAMESZ	16
+#define	PRARGSZ	80
+
+struct EBLHOOK(prpsinfo)
+{
+  FIELD (CHAR, pr_state);
+  FIELD (CHAR, pr_sname);
+  FIELD (CHAR, pr_zomb);
+  FIELD (CHAR, pr_nice);
+  FIELD (ULONG, pr_flag);
+  FIELD (PRPSINFO_UID_T, pr_uid);
+  FIELD (PRPSINFO_GID_T, pr_gid);
+  FIELD (PID_T, pr_pid);
+  FIELD (PID_T, pr_ppid);
+  FIELD (PID_T, pr_pgrp);
+  FIELD (PID_T, pr_sid);
+  FIELD (CHAR, pr_fname[FNAMESZ]);
+  FIELD (CHAR, pr_psargs[PRARGSZ]);
+};
+
+#undef	FIELD
+
+#define FIELD(igroup, itype, item, fmt, ...)			\
+    {								\
+      .name = #item,						\
+      .group = #igroup,					\
+      .offset = offsetof (struct EBLHOOK(prstatus), pr_##item),	\
+      .type = TYPE_##itype,					\
+      .format = fmt,						\
+      __VA_ARGS__						\
+    }
+
+static const Ebl_Core_Item prstatus_items[] =
+  {
+    FIELD (signal, INT, info.si_signo, 'd'),
+    FIELD (signal, INT, info.si_code, 'd'),
+    FIELD (signal, INT, info.si_errno, 'd'),
+    FIELD (signal, SHORT, cursig, 'd'),
+
+    /* Use different group name for a newline delimiter.  */
+    FIELD (signal2, ULONG, sigpend, 'B'),
+    FIELD (signal3, ULONG, sighold, 'B'),
+    FIELD (identity, PID_T, pid, 'd', .thread_identifier = true),
+    FIELD (identity, PID_T, ppid, 'd'),
+    FIELD (identity, PID_T, pgrp, 'd'),
+    FIELD (identity, PID_T, sid, 'd'),
+    TIMEVAL_FIELD (utime),
+    TIMEVAL_FIELD (stime),
+    TIMEVAL_FIELD (cutime),
+    TIMEVAL_FIELD (cstime),
+#ifdef PRSTATUS_REGSET_ITEMS
+    PRSTATUS_REGSET_ITEMS,
+#endif
+    FIELD (register, INT, fpvalid, 'd'),
+  };
+
+#undef	FIELD
+
+#define FIELD(igroup, itype, item, fmt, ...)			\
+    {								\
+      .name = #item,						\
+      .group = #igroup,					\
+      .offset = offsetof (struct EBLHOOK(prpsinfo), pr_##item),	\
+      .type = TYPE_##itype,					\
+      .format = fmt,						\
+      __VA_ARGS__						\
+    }
+
+static const Ebl_Core_Item prpsinfo_items[] =
+  {
+    FIELD (state, CHAR, state, 'd'),
+    FIELD (state, CHAR, sname, 'c'),
+    FIELD (state, CHAR, zomb, 'd'),
+    FIELD (state, CHAR, nice, 'd'),
+    FIELD (state, ULONG, flag, 'x'),
+    FIELD (identity, PRPSINFO_UID_T, uid, 'd'),
+    FIELD (identity, PRPSINFO_GID_T, gid, 'd'),
+    FIELD (identity, PID_T, pid, 'd'),
+    FIELD (identity, PID_T, ppid, 'd'),
+    FIELD (identity, PID_T, pgrp, 'd'),
+    FIELD (identity, PID_T, sid, 'd'),
+    FIELD (command, CHAR, fname, 's', .count = FNAMESZ),
+    FIELD (command, CHAR, psargs, 's', .count = PRARGSZ),
+  };
+
+static const Ebl_Core_Item vmcoreinfo_items[] =
+  {
+    {
+      .type = ELF_T_BYTE, .format = '\n'
+    }
+  };
+
+#undef	FIELD
+
+int
+EBLHOOK(core_note) (const GElf_Nhdr *nhdr, const char *name,
+		    GElf_Word *regs_offset, size_t *nregloc,
+		    const Ebl_Register_Location **reglocs,
+		    size_t *nitems, const Ebl_Core_Item **items)
+{
+  switch (nhdr->n_namesz)
+    {
+    case sizeof "CORE" - 1:	/* Buggy old Linux kernels.  */
+      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
+	break;
+      return 0;
+
+    case sizeof "CORE":
+      if (memcmp (name, "CORE", nhdr->n_namesz) == 0)
+	break;
+      /* Buggy old Linux kernels didn't terminate "LINUX".  */
+      FALLTHROUGH;
+
+    case sizeof "LINUX":
+      if (memcmp (name, "LINUX", nhdr->n_namesz) == 0)
+	break;
+      return 0;
+
+    case sizeof "VMCOREINFO":
+      if (nhdr->n_type != 0
+	  || memcmp (name, "VMCOREINFO", sizeof "VMCOREINFO") != 0)
+	return 0;
+      *regs_offset = 0;
+      *nregloc = 0;
+      *reglocs = NULL;
+      *nitems = 1;
+      *items = vmcoreinfo_items;
+      return 1;
+
+    default:
+      return 0;
+    }
+
+  switch (nhdr->n_type)
+    {
+    case NT_PRSTATUS:
+      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prstatus)))
+	return 0;
+      *regs_offset = offsetof (struct EBLHOOK(prstatus), pr_reg);
+      *nregloc = sizeof prstatus_regs / sizeof prstatus_regs[0];
+      *reglocs = prstatus_regs;
+      *nitems = sizeof prstatus_items / sizeof prstatus_items[0];
+      *items = prstatus_items;
+      return 1;
+
+    case NT_PRPSINFO:
+      if (nhdr->n_descsz != sizeof (struct EBLHOOK(prpsinfo)))
+	return 0;
+      *regs_offset = 0;
+      *nregloc = 0;
+      *reglocs = NULL;
+      *nitems = sizeof prpsinfo_items / sizeof prpsinfo_items[0];
+      *items = prpsinfo_items;
+      return 1;
+
+#define EXTRA_REGSET(type, size, table)					      \
+    case type:								      \
+      if (nhdr->n_descsz != size)					      \
+	return 0;							      \
+      *regs_offset = 0;							      \
+      *nregloc = sizeof table / sizeof table[0];			      \
+      *reglocs = table;							      \
+      *nitems = 0;							      \
+      *items = NULL;							      \
+      return 1;
+
+#define EXTRA_REGSET_ITEMS(type, size, table, extra_items)		      \
+    case type:								      \
+      if (nhdr->n_descsz != size)					      \
+	return 0;							      \
+      *regs_offset = 0;							      \
+      *nregloc = sizeof table / sizeof table[0];			      \
+      *reglocs = table;							      \
+      *nitems = sizeof extra_items / sizeof extra_items[0];		      \
+      *items = extra_items;						      \
+      return 1;
+
+#define EXTRA_ITEMS(type, size, extra_items)				      \
+    case type:								      \
+      if (nhdr->n_descsz != size)					      \
+	return 0;							      \
+      *regs_offset = 0;							      \
+      *nregloc = 0;							      \
+      *reglocs = NULL;							      \
+      *nitems = sizeof extra_items / sizeof extra_items[0];		      \
+      *items = extra_items;						      \
+      return 1;
+
+#ifdef FPREGSET_SIZE
+    EXTRA_REGSET (NT_FPREGSET, FPREGSET_SIZE, fpregset_regs)
+#endif
+
+#ifdef EXTRA_NOTES
+    EXTRA_NOTES
+#endif
+    }
+
+  return 0;
+}
diff --git a/backends/loongarch_cfi.c b/backends/loongarch_cfi.c
new file mode 100644
index 0000000..5f3cd2c
--- /dev/null
+++ b/backends/loongarch_cfi.c
@@ -0,0 +1,83 @@
+/* LoongArch ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limted.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+/* LoongArch ELF ABI specification:
+https://loongson.github.io/LoongArch-Documentation/LoongArch-ELF-ABI-EN.html#_register_convention
+*/
+int
+loongarch_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer ($r3) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (3), ULEB128_7 (0),
+
+      /* The Stack Pointer ($r3) is restored from CFA address by default.  */
+      DW_CFA_val_offset, ULEB128_7 (3), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* The return address register contains the return address setup by
+	 caller.  */
+      SV (1),
+
+      /* Callee-saved registers $s0-$s7.  */
+      SV (23), SV (24), SV (25), SV (26), SV (27), SV (28),
+      SV (29), SV (30), SV (31),
+
+      /* The Frame Pointer ($fp, $r22) */
+      SV(22),
+
+      /* Callee-saved registers $fs0-$fs7.  */
+      SV (56), SV (57), SV (58), SV (59), SV (60), SV (61),
+      SV (62), SV (63),
+#undef SV
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 1; /* ra.  */
+
+  return 0;
+}
diff --git a/backends/loongarch_corenote.c b/backends/loongarch_corenote.c
new file mode 100644
index 0000000..b549edc
--- /dev/null
+++ b/backends/loongarch_corenote.c
@@ -0,0 +1,114 @@
+/* LoongArch specific core note handling.
+   Copyright (C) 2023 Loongson Technology Corporation Limited.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+#define	ULONG			uint64_t
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_ULONG		8
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_ULONG		ELF_T_XWORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#define PRSTATUS_REGS_SIZE	(45 * 8)
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 0, .count = 32, .bits = 64 }, /* r0..r31 */
+  };
+
+#define PRSTATUS_REGSET_ITEMS						\
+  {									\
+    .name = "orig_a0", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 32 * 8),						\
+    .group = "register"							\
+  },									\
+  {									\
+    .name = "csr_era", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 33 * 8),						\
+    .group = "register",						\
+    .pc_register = true							\
+  },									\
+  {									\
+    .name = "csr_badvaddr", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 34 * 8),						\
+    .group = "register"							\
+  },									\
+  {									\
+    .name = "csr_crmd", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 35 * 8),						\
+    .group = "register"							\
+  },									\
+  {									\
+    .name = "csr_prmd", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 36 * 8),						\
+    .group = "register"							\
+  },									\
+  {									\
+    .name = "csr_euen", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 37 * 8),						\
+    .group = "register"							\
+  },									\
+  {									\
+    .name = "csr_ecfg", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 38 * 8),						\
+    .group = "register"							\
+  },									\
+  {									\
+    .name = "csr_estat", .type = ELF_T_XWORD, .format = 'x',		\
+    .offset = (offsetof (struct EBLHOOK(prstatus), pr_reg)		\
+	       + 39 * 8),						\
+    .group = "register"							\
+  }
+  /* 40 ~ 44 reserved */
+
+#include "linux-core-note.c"
diff --git a/backends/loongarch_init.c b/backends/loongarch_init.c
new file mode 100644
index 0000000..2f0d46c
--- /dev/null
+++ b/backends/loongarch_init.c
@@ -0,0 +1,62 @@
+/* Initialization of LoongArch specific backend library.
+   Copyright (C) 2022 Hengqi Chen
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limted.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		loongarch_
+#define RELOC_PREFIX	R_LARCH_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on loongarch_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+loongarch_init (Elf *elf __attribute__ ((unused)),
+	        GElf_Half machine __attribute__ ((unused)),
+	        Ebl *eh)
+{
+  loongarch_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 74;
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, return_value_location);
+  HOOK (eh, unwind);
+
+  return eh;
+}
diff --git a/backends/loongarch_initreg.c b/backends/loongarch_initreg.c
new file mode 100644
index 0000000..74cb62f
--- /dev/null
+++ b/backends/loongarch_initreg.c
@@ -0,0 +1,88 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limted.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined __loongarch__ && defined __linux__
+# include <sys/uio.h>
+# include <sys/procfs.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+bool
+loongarch_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+				 ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				 void *arg __attribute__ ((unused)))
+{
+#if !defined __loongarch__ || !defined __linux__
+  return false;
+#else /* __loongarch__ */
+
+  /* General registers.  */
+  struct user_regs_struct gregs;
+  struct iovec iovec;
+  iovec.iov_base = &gregs;
+  iovec.iov_len = sizeof (gregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  /* $r0 is constant 0.  */
+  Dwarf_Word zero = 0;
+  if (! setfunc (0, 1, &zero, arg))
+    return false;
+
+  /* $r1-$r31.  */
+  if (! setfunc (1, 32, (Dwarf_Word *) &gregs.regs[1], arg))
+    return false;
+
+  /* PC.  */
+  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs.csr_era, arg))
+    return false;
+
+  /* Floating-point registers (only 64bits are used).  */
+  struct user_fp_struct fregs;
+  iovec.iov_base = &fregs;
+  iovec.iov_len = sizeof (fregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_FPREGSET, &iovec) != 0)
+    return false;
+
+  /* $f0-$f31 */
+  if (! setfunc (32, 32, (Dwarf_Word *) &fregs.fpr[0], arg))
+    return false;
+
+  return true;
+#endif /* __loongarch__ */
+}
diff --git a/backends/loongarch_regs.c b/backends/loongarch_regs.c
new file mode 100644
index 0000000..4a4b205
--- /dev/null
+++ b/backends/loongarch_regs.c
@@ -0,0 +1,141 @@
+/* Register names and numbers for LoongArch DWARF.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limted.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+ssize_t
+loongarch_register_info (Ebl *ebl, int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  if (name == NULL)
+    return 64;
+
+  *prefix = "";
+
+  if (regno < 32)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = ebl->class == ELFCLASS64 ? 64 : 32;
+    }
+  else
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+      *bits = 64;
+    }
+
+  switch (regno)
+    {
+    case 0:
+      return stpcpy (name, "zero") + 1 - name;
+
+    case 1:
+      *type = DW_ATE_address;
+      return stpcpy (name, "ra") + 1 - name;
+
+    case 2:
+      *type = DW_ATE_address;
+      return stpcpy (name, "tp") + 1 - name;
+
+    case 3:
+      *type = DW_ATE_address;
+      return stpcpy (name, "sp") + 1 - name;
+
+    case 4 ... 11:
+      name[0] = 'a';
+      name[1] = regno - 4 + '0';
+      namelen = 2;
+      break;
+
+    case 12 ... 20:
+      name[0] = 't';
+      name[1] = regno - 12 + '0';
+      namelen = 2;
+      break;
+
+    case 21:
+      return stpcpy (name, "u0") + 1 - name;
+
+    case 22:
+      *type = DW_ATE_address;
+      return stpcpy (name, "fp") + 1 - name;
+
+    case 23 ... 31:
+      name[0] = 's';
+      name[1] = regno - 23 + '0';
+      namelen = 2;
+      break;
+
+    case 32 ... 39:
+      name[0] = 'f';
+      name[1] = 'a';
+      name[2] = regno - 32 + '0';
+      namelen = 3;
+      break;
+
+    case 40 ... 49:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = regno - 40 + '0';
+      namelen = 3;
+      break;
+
+    case 50 ... 55:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = '1';
+      name[3] = regno - 50 + '0';
+      namelen = 4;
+      break;
+
+    case 56 ... 63:
+      name[0] = 'f';
+      name[1] = 's';
+      name[2] = regno - 56 + '0';
+      namelen = 3;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/loongarch_reloc.def b/backends/loongarch_reloc.def
new file mode 100644
index 0000000..cdc8321
--- /dev/null
+++ b/backends/loongarch_reloc.def
@@ -0,0 +1,147 @@
+/* List the relocation types for LoongArch.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,			REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,			EXEC|DYN)
+RELOC_TYPE (32,				REL|EXEC|DYN)
+RELOC_TYPE (64,				REL|EXEC|DYN)
+RELOC_TYPE (RELATIVE,			EXEC|DYN)
+RELOC_TYPE (COPY,			EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,			EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD32,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD64,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL32,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL64,		EXEC|DYN)
+RELOC_TYPE (TLS_TPREL32,		EXEC|DYN)
+RELOC_TYPE (TLS_TPREL64,		EXEC|DYN)
+RELOC_TYPE (IRELATIVE,			EXEC|DYN)
+RELOC_TYPE (MARK_LA,			REL)
+RELOC_TYPE (MARK_PCREL,			REL)
+RELOC_TYPE (SOP_PUSH_PCREL,		REL)
+RELOC_TYPE (SOP_PUSH_ABSOLUTE,		REL)
+RELOC_TYPE (SOP_PUSH_DUP,		REL)
+RELOC_TYPE (SOP_PUSH_GPREL,		REL)
+RELOC_TYPE (SOP_PUSH_TLS_TPREL,		REL)
+RELOC_TYPE (SOP_PUSH_TLS_GOT,		REL)
+RELOC_TYPE (SOP_PUSH_TLS_GD,		REL)
+RELOC_TYPE (SOP_PUSH_PLT_PCREL,		REL)
+RELOC_TYPE (SOP_ASSERT,			REL)
+RELOC_TYPE (SOP_NOT,			REL)
+RELOC_TYPE (SOP_SUB,			REL)
+RELOC_TYPE (SOP_SL,			REL)
+RELOC_TYPE (SOP_SR,			REL)
+RELOC_TYPE (SOP_ADD,			REL)
+RELOC_TYPE (SOP_AND,			REL)
+RELOC_TYPE (SOP_IF_ELSE,		REL)
+RELOC_TYPE (SOP_POP_32_S_10_5,		REL)
+RELOC_TYPE (SOP_POP_32_U_10_12,		REL)
+RELOC_TYPE (SOP_POP_32_S_10_12,		REL)
+RELOC_TYPE (SOP_POP_32_S_10_16,		REL)
+RELOC_TYPE (SOP_POP_32_S_10_16_S2,	REL)
+RELOC_TYPE (SOP_POP_32_S_5_20,		REL)
+RELOC_TYPE (SOP_POP_32_S_0_5_10_16_S2,	REL)
+RELOC_TYPE (SOP_POP_32_S_0_10_10_16_S2,	REL)
+RELOC_TYPE (SOP_POP_32_U,		REL)
+RELOC_TYPE (ADD8,			REL)
+RELOC_TYPE (ADD16,			REL)
+RELOC_TYPE (ADD24,			REL)
+RELOC_TYPE (ADD32,			REL)
+RELOC_TYPE (ADD64,			REL)
+RELOC_TYPE (SUB8,			REL)
+RELOC_TYPE (SUB16,			REL)
+RELOC_TYPE (SUB24,			REL)
+RELOC_TYPE (SUB32,			REL)
+RELOC_TYPE (SUB64,			REL)
+RELOC_TYPE (GNU_VTINHERIT,		REL)
+RELOC_TYPE (GNU_VTENTRY,		REL)
+
+/* reserved 59-63 */
+
+RELOC_TYPE (B16,			REL)
+RELOC_TYPE (B21,			REL)
+RELOC_TYPE (B26,			REL)
+RELOC_TYPE (ABS_HI20,			REL)
+RELOC_TYPE (ABS_LO12,			REL)
+RELOC_TYPE (ABS64_LO20,			REL)
+RELOC_TYPE (ABS64_HI12,			REL)
+RELOC_TYPE (PCALA_HI20,			REL)
+RELOC_TYPE (PCALA_LO12,			REL)
+RELOC_TYPE (PCALA64_LO20,		REL)
+RELOC_TYPE (PCALA64_HI12,		REL)
+RELOC_TYPE (GOT_PC_HI20,		REL)
+RELOC_TYPE (GOT_PC_LO12,		REL)
+RELOC_TYPE (GOT64_PC_LO20,		REL)
+RELOC_TYPE (GOT64_PC_HI12,		REL)
+RELOC_TYPE (GOT_HI20,			REL)
+RELOC_TYPE (GOT_LO12,			REL)
+RELOC_TYPE (GOT64_LO20,			REL)
+RELOC_TYPE (GOT64_HI12,			REL)
+RELOC_TYPE (TLS_LE_HI20,		REL)
+RELOC_TYPE (TLS_LE_LO12,		REL)
+RELOC_TYPE (TLS_LE64_LO20,		REL)
+RELOC_TYPE (TLS_LE64_HI12,		REL)
+RELOC_TYPE (TLS_IE_PC_HI20,		REL)
+RELOC_TYPE (TLS_IE_PC_LO12,		REL)
+RELOC_TYPE (TLS_IE64_PC_LO20,		REL)
+RELOC_TYPE (TLS_IE64_PC_HI12,		REL)
+RELOC_TYPE (TLS_IE_HI20,		REL)
+RELOC_TYPE (TLS_IE_LO12,		REL)
+RELOC_TYPE (TLS_IE64_LO20,		REL)
+RELOC_TYPE (TLS_IE64_HI12,		REL)
+RELOC_TYPE (TLS_LD_PC_HI20,		REL)
+RELOC_TYPE (TLS_LD_HI20,		REL)
+RELOC_TYPE (TLS_GD_PC_HI20,		REL)
+RELOC_TYPE (TLS_GD_HI20,		REL)
+RELOC_TYPE (32_PCREL,			REL)
+RELOC_TYPE (RELAX,			REL)
+RELOC_TYPE (DELETE,			REL)
+RELOC_TYPE (ALIGN,			REL)
+RELOC_TYPE (PCREL20_S2,			REL)
+RELOC_TYPE (CFA,			REL)
+RELOC_TYPE (ADD6,			REL)
+RELOC_TYPE (SUB6,			REL)
+RELOC_TYPE (ADD_ULEB128,		REL)
+RELOC_TYPE (SUB_ULEB128,		REL)
+RELOC_TYPE (64_PCREL,			REL)
+RELOC_TYPE (CALL36,			REL)
+RELOC_TYPE (TLS_DESC_PC_HI20,		REL)
+RELOC_TYPE (TLS_DESC_PC_LO12,		REL)
+RELOC_TYPE (TLS_DESC64_PC_LO20,		REL)
+RELOC_TYPE (TLS_DESC64_PC_HI12,		REL)
+RELOC_TYPE (TLS_DESC_HI20,		REL)
+RELOC_TYPE (TLS_DESC_LO12,		REL)
+RELOC_TYPE (TLS_DESC64_LO20,		REL)
+RELOC_TYPE (TLS_DESC64_HI12,		REL)
+RELOC_TYPE (TLS_DESC_LD,		REL)
+RELOC_TYPE (TLS_DESC_CALL,		REL)
+RELOC_TYPE (TLS_LE_HI20_R,		REL)
+RELOC_TYPE (TLS_LE_ADD_R,		REL)
+RELOC_TYPE (TLS_LE_LO12_R,		REL)
+RELOC_TYPE (TLS_LD_PCREL20_S2,		REL)
+RELOC_TYPE (TLS_GD_PCREL20_S2,		REL)
+RELOC_TYPE (TLS_DESC_PCREL20_S2,	REL)
diff --git a/backends/loongarch_retval.c b/backends/loongarch_retval.c
new file mode 100644
index 0000000..23b33ed
--- /dev/null
+++ b/backends/loongarch_retval.c
@@ -0,0 +1,202 @@
+/* Function return value location for Linux/LoongArch ABI.
+   Copyright (C) 2013 Red Hat, Inc.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limited.
+
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+static int
+dwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep)
+{
+  int bits;
+  if (((bits = 8 * dwarf_bytesize (die)) < 0
+       && (bits = dwarf_bitsize (die)) < 0)
+      || bits % 8 != 0)
+    return -1;
+
+  *sizep = bits / 8;
+  return 0;
+}
+
+static int
+pass_in_gpr (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_reg4 }, { .atom = DW_OP_piece, .number = 8 },
+      { .atom = DW_OP_reg5 }, { .atom = DW_OP_piece, .number = 8 }
+    };
+
+  *locp = loc;
+  return size <= 8 ? 1 : 4;
+}
+
+static int
+pass_by_ref (const Dwarf_Op **locp)
+{
+  static const Dwarf_Op loc[] = { { .atom = DW_OP_breg4 } };
+
+  *locp = loc;
+  return 1;
+}
+
+static int
+pass_in_fpr (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_regx, .number = 32 },
+      { .atom = DW_OP_piece, .number = 8 },
+      { .atom = DW_OP_regx, .number = 33 },
+      { .atom = DW_OP_piece, .number = 8 }
+    };
+
+  *locp = loc;
+  return size <= 8 ? 1 : 4;
+}
+
+int
+loongarch_return_value_location(Dwarf_Die *functypedie,
+                                const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die typedie;
+  int tag = dwarf_peeled_die_type (functypedie, &typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size = (Dwarf_Word)-1;
+
+  /* If the argument type is a Composite Type that is larger than 16
+     bytes, then the argument is copied to memory allocated by the
+     caller and the argument is replaced by a pointer to the copy.  */
+  if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type
+      || tag == DW_TAG_class_type || tag == DW_TAG_array_type)
+    {
+      if (dwarf_aggregate_size (&typedie, &size) < 0)
+	return -1;
+
+      /* Aggregates larger than 2*GRLEN bits are passed by reference.  */
+      if (size > 16)
+	return pass_by_ref (locp);
+      /* Aggregates whose total size is no more than GRLEN bits are passed in
+	 a register.  Aggregates whose total size is no more than 2*GRLEN bits
+	 are passed in a pair of registers.  */
+      else
+	return pass_in_gpr (locp, size);
+    }
+
+  if (tag == DW_TAG_base_type || dwarf_is_pointer (tag))
+    {
+      if (dwarf_bytesize_aux (&typedie, &size) < 0)
+	{
+	  if (dwarf_is_pointer (tag))
+	    size = 8;
+	  else
+	    return -1;
+	}
+
+      Dwarf_Attribute attr_mem;
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	    case DW_ATE_boolean:
+	    case DW_ATE_signed:
+	    case DW_ATE_unsigned:
+	    case DW_ATE_unsigned_char:
+	    case DW_ATE_signed_char:
+	      /* Scalars that are at most GRLEN bits wide are passed in a single
+		 argument register.  Scalars that are 2*GRLEN bits wide are
+		 passed in a pair of argument registers.  Scalars wider than
+		 2*GRLEN are passed by reference.  */
+	      return pass_in_gpr (locp, size);
+
+	    case DW_ATE_float:
+	      /* A real floating-point argument is passed in a floating-point
+		 argument register if it is no more than FLEN bits wide,
+		 otherwise it is passed according to the integer calling
+		 convention.  */
+	      switch (size)
+		{
+		case 4: /* single */
+                case 8: /* double */
+                  return pass_in_fpr (locp, size);
+
+                case 16: /* quad */
+	          return pass_in_gpr (locp, size);
+
+		default:
+		  return -2;
+		}
+
+	    case DW_ATE_complex_float:
+	      /* A complex floating-point number is passed as though it were a
+		 struct containing two floating-point reals.  */
+	      switch (size)
+		{
+		case 8: /* float _Complex */
+                case 16: /* double _Complex */
+                  return pass_in_fpr (locp, size);
+
+                case 32: /* long double _Complex */
+		  return pass_by_ref (locp);
+
+		default:
+		  return -2;
+		}
+	    }
+
+	  return -2;
+	}
+      else
+	return pass_in_gpr (locp, size);
+    }
+
+  *locp = NULL;
+  return 0;
+}
diff --git a/backends/loongarch_symbol.c b/backends/loongarch_symbol.c
new file mode 100644
index 0000000..5ce55ba
--- /dev/null
+++ b/backends/loongarch_symbol.c
@@ -0,0 +1,116 @@
+/* LoongArch specific symbolic name handling.
+   Copyright (C) 2022 Hengqi Chen
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND loongarch_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+loongarch_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			     int *addsub)
+{
+  switch (type)
+    {
+    case R_LARCH_32:
+      return ELF_T_WORD;
+    case R_LARCH_64:
+      return ELF_T_XWORD;
+    case R_LARCH_ADD16:
+      *addsub = 1;
+      return ELF_T_HALF;
+    case R_LARCH_ADD32:
+      *addsub = 1;
+      return ELF_T_WORD;
+    case R_LARCH_ADD64:
+      *addsub = 1;
+      return ELF_T_XWORD;
+    case R_LARCH_SUB16:
+      *addsub = -1;
+      return ELF_T_HALF;
+    case R_LARCH_SUB32:
+      *addsub = -1;
+      return ELF_T_WORD;
+    case R_LARCH_SUB64:
+      *addsub = -1;
+      return ELF_T_XWORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+bool
+loongarch_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ (EF_LARCH_ABI_MODIFIER_MASK
+		     | EF_LARCH_OBJABI_V1)) == 0);
+}
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+loongarch_check_special_symbol (Elf *elf, const GElf_Sym *sym,
+			    const char *name, const GElf_Shdr *destshdr)
+{
+  if (name != NULL
+      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    {
+      size_t shstrndx;
+      if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+	return false;
+      const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
+      if (sname != NULL
+	  && (strcmp (sname, ".got") == 0 || strcmp (sname, ".got.plt") == 0))
+	{
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  sname = elf_strptr (elf, shstrndx, shdr->sh_name);
+		  if (sname != NULL && strcmp (sname, ".got") == 0)
+		    return (sym->st_value >= shdr->sh_addr
+			    && sym->st_value < shdr->sh_addr + shdr->sh_size);
+		}
+	    }
+	}
+    }
+
+  return false;
+}
diff --git a/backends/loongarch_unwind.c b/backends/loongarch_unwind.c
new file mode 100644
index 0000000..fb74808
--- /dev/null
+++ b/backends/loongarch_unwind.c
@@ -0,0 +1,84 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2023 OpenAnolis community LoongArch SIG.
+   Copyright (C) 2023 Loongson Technology Corporation Limited.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND loongarch_
+#define RA_REG 1
+#define SP_REG 3
+#define FP_REG 22
+
+#define RA_OFFSET 8
+#define FP_OFFSET 16
+
+#include "libebl_CPU.h"
+
+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that?  */
+
+bool
+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr pc __attribute__ ((unused)),
+                 ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+                 ebl_pid_memory_read_t *readfunc, void *arg,
+                 bool *signal_framep __attribute__ ((unused)))
+{
+  Dwarf_Word fp, ra, sp;
+
+  if (!getfunc(RA_REG, 1, &ra, arg))
+    return false;
+
+  if (ra == 0 || !setfunc(-1, 1, &ra, arg))
+    return false;
+
+  if (!getfunc(FP_REG, 1, &fp, arg))
+    fp = 0;
+
+  if (!getfunc(SP_REG, 1, &sp, arg))
+    sp = 0;
+
+  Dwarf_Word newRa, newFp, newSp;
+
+  if (!readfunc(fp - RA_OFFSET, &newRa, arg))
+    newRa = 0;
+
+  if (!readfunc(fp - FP_OFFSET, &newFp, arg))
+    newFp = 0;
+
+  newSp = fp;
+
+  // These are not fatal if they don't work. They will just prevent unwinding at the next frame.
+  setfunc(RA_REG, 1, &newRa, arg);
+  setfunc(FP_REG, 1, &newFp, arg);
+  setfunc(SP_REG, 1, &newSp, arg);
+
+  // If the fp is invalid, we might still have a valid ra.
+  // But if the fp is valid, then the stack should be moving in the right direction.
+  return fp == 0 || newSp > sp;
+}
diff --git a/backends/m68k_cfi.c b/backends/m68k_cfi.c
new file mode 100644
index 0000000..9303fb2
--- /dev/null
+++ b/backends/m68k_cfi.c
@@ -0,0 +1,58 @@
+/* m68k ABI-specified defaults for DWARF CFI.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+int
+m68k_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* Call-saved registers %d2-%d7, %a2-%a6.  */
+      SV (2), SV (3), SV (4), SV (5), SV (6), SV (7),
+      SV (10), SV (11), SV (12), SV (13), SV (14),
+
+      /* The CFA is the SP.  */
+      DW_CFA_val_offset, ULEB128_7 (15), ULEB128_7 (0),
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 24; /* %pc */
+
+  return 0;
+}
diff --git a/backends/m68k_corenote.c b/backends/m68k_corenote.c
new file mode 100644
index 0000000..3c1d019
--- /dev/null
+++ b/backends/m68k_corenote.c
@@ -0,0 +1,72 @@
+/* M68K specific core note handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND	m68k_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = 0, .regno = 1, .count = 14, .bits = 32 }, /* d1-d7, a0-a6 */
+    { .offset = 14 * 4, .regno = 0, .count = 1, .bits = 32 }, /* d0 */
+    { .offset = 15 * 4, .regno = 15, .count = 1, .bits = 32 }, /* a7 */
+    { .offset = 18 * 4, .regno = 24, .count = 1, .bits = 32 } /* pc */
+  };
+#define PRSTATUS_REGS_SIZE	(20 * 4)
+
+#define ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_INT		2
+#define ALIGN_ULONG		2
+#define ALIGN_PID_T		2
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define ALIGN_PRSTATUS		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 16, .count = 8, .bits = 96 }, /* fp0-fp7 */
+  };
+#define FPREGSET_SIZE	(27 * 4)
+
+#include "linux-core-note.c"
diff --git a/backends/m68k_init.c b/backends/m68k_init.c
new file mode 100644
index 0000000..7b94f23
--- /dev/null
+++ b/backends/m68k_init.c
@@ -0,0 +1,58 @@
+/* Initialization of M68K specific backend library.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		m68k_
+#define RELOC_PREFIX	R_68K_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on m68k_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+m68k_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh)
+{
+  /* We handle it.  */
+  m68k_init_reloc (eh);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 25;
+  HOOK (eh, set_initial_registers_tid);
+
+  return eh;
+}
diff --git a/backends/m68k_initreg.c b/backends/m68k_initreg.c
new file mode 100644
index 0000000..61f260f
--- /dev/null
+++ b/backends/m68k_initreg.c
@@ -0,0 +1,82 @@
+/* Fetch live process registers from TID.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#if defined __m68k__ && defined __linux__
+# include <sys/types.h>
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+bool
+m68k_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+				ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if !defined __m68k__ || !defined __linux__
+  return false;
+#else /* __m68k__ */
+  struct user_regs_struct user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+
+  Dwarf_Word dwarf_regs[16];
+  dwarf_regs[0] = user_regs.d0;
+  dwarf_regs[1] = user_regs.d1;
+  dwarf_regs[2] = user_regs.d2;
+  dwarf_regs[3] = user_regs.d3;
+  dwarf_regs[4] = user_regs.d4;
+  dwarf_regs[5] = user_regs.d5;
+  dwarf_regs[6] = user_regs.d6;
+  dwarf_regs[7] = user_regs.d7;
+  dwarf_regs[8] = user_regs.a0;
+  dwarf_regs[9] = user_regs.a1;
+  dwarf_regs[10] = user_regs.a2;
+  dwarf_regs[11] = user_regs.a3;
+  dwarf_regs[12] = user_regs.a4;
+  dwarf_regs[13] = user_regs.a5;
+  dwarf_regs[14] = user_regs.a6;
+  dwarf_regs[15] = user_regs.usp;
+
+  /* D0..D7, A0..A7.  */
+  if (! setfunc (0, 16, dwarf_regs, arg))
+    return false;
+
+  /* PC.  */
+  dwarf_regs[0] = user_regs.pc;
+  if (! setfunc (24, 1, dwarf_regs, arg))
+    return false;
+
+  return true;
+#endif /* __m68k__ */
+}
diff --git a/backends/m68k_regs.c b/backends/m68k_regs.c
new file mode 100644
index 0000000..cb99f55
--- /dev/null
+++ b/backends/m68k_regs.c
@@ -0,0 +1,96 @@
+/* Register names and numbers for M68K DWARF.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+ssize_t
+m68k_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 25;
+
+  if (regno < 0 || regno > 24 || namelen < 5)
+    return -1;
+
+  *prefix = "%";
+  *setname = "integer";
+  *bits = 32;
+
+  switch (regno)
+    {
+    case 0 ... 7:
+      *type = DW_ATE_signed;
+      name[0] = 'd';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 8 ... 15:
+      *type = DW_ATE_address;
+      name[0] = 'a';
+      name[1] = regno - 8 + '0';
+      namelen = 2;
+      break;
+
+    case 16 ... 23:
+      *type = DW_ATE_float;
+      *setname = "FPU";
+      *bits = 96;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = regno - 16 + '0';
+      namelen = 3;
+      break;
+
+    case 24:
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'c';
+      namelen = 2;
+      break;
+
+    /* Can't happen.  */
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/m68k_reloc.def b/backends/m68k_reloc.def
new file mode 100644
index 0000000..b7cc4df
--- /dev/null
+++ b/backends/m68k_reloc.def
@@ -0,0 +1,70 @@
+/* List the relocation types for m68k.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (32,			REL|EXEC|DYN)
+RELOC_TYPE (16,			REL|EXEC|DYN)
+RELOC_TYPE (8,			REL|EXEC|DYN)
+RELOC_TYPE (PC32,		REL|EXEC|DYN)
+RELOC_TYPE (PC16,		REL|EXEC|DYN)
+RELOC_TYPE (PC8,		REL|EXEC|DYN)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (GOT16,		REL)
+RELOC_TYPE (GOT8,		REL)
+RELOC_TYPE (GOT32O,		REL)
+RELOC_TYPE (GOT16O,		REL)
+RELOC_TYPE (GOT8O,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (PLT16,		REL)
+RELOC_TYPE (PLT8,		REL)
+RELOC_TYPE (PLT32O,		REL)
+RELOC_TYPE (PLT16O,		REL)
+RELOC_TYPE (PLT8O,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (TLS_GD32,		REL)
+RELOC_TYPE (TLS_GD16,		REL)
+RELOC_TYPE (TLS_GD8,		REL)
+RELOC_TYPE (TLS_LDM32,		REL)
+RELOC_TYPE (TLS_LDM16,		REL)
+RELOC_TYPE (TLS_LDM8,		REL)
+RELOC_TYPE (TLS_LDO32,		REL)
+RELOC_TYPE (TLS_LDO16,		REL)
+RELOC_TYPE (TLS_LDO8,		REL)
+RELOC_TYPE (TLS_IE32,		REL)
+RELOC_TYPE (TLS_IE16,		REL)
+RELOC_TYPE (TLS_IE8,		REL)
+RELOC_TYPE (TLS_LE32,		REL)
+RELOC_TYPE (TLS_LE16,		REL)
+RELOC_TYPE (TLS_LE8,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPREL32,	EXEC|DYN)
diff --git a/backends/m68k_retval.c b/backends/m68k_retval.c
new file mode 100644
index 0000000..bf41f86
--- /dev/null
+++ b/backends/m68k_retval.c
@@ -0,0 +1,150 @@
+/* Function return value location for Linux/m68k ABI.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+
+/* %d0, or pair %d0, %d1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %a0.  */
+static const Dwarf_Op loc_ptrreg[] =
+  {
+    { .atom = DW_OP_reg8 }
+  };
+#define nloc_ptrreg	1
+
+/* %fp0.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg16 }
+  };
+#define nloc_fpreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %a0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_reg8 }
+  };
+#define nloc_aggregate 1
+
+int
+m68k_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Word size;
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 4;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	    if (encoding == DW_ATE_float)
+	      {
+		if (size > 12)
+		  return -2;
+		*locp = loc_fpreg;
+		return nloc_fpreg;
+	      }
+	  }
+	if (tag == DW_TAG_pointer_type || tag == DW_TAG_ptr_to_member_type)
+	  {
+	    *locp = loc_ptrreg;
+	    return nloc_ptrreg;
+	  }
+	*locp = loc_intreg;
+	if (size <= 4)
+	  return nloc_intreg;
+	if (size <= 8)
+	  return nloc_intregpair;
+      }
+      FALLTHROUGH;
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/m68k_symbol.c b/backends/m68k_symbol.c
new file mode 100644
index 0000000..9551cdf
--- /dev/null
+++ b/backends/m68k_symbol.c
@@ -0,0 +1,71 @@
+/* m68k specific symbolic name handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND m68k_
+#include "libebl_CPU.h"
+
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool
+m68k_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
+{
+  switch (type)
+    {
+    case R_68K_GOT32:
+    case R_68K_GOT16:
+    case R_68K_GOT8:
+      return true;
+    }
+  return false;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+m68k_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_68K_32:
+      return ELF_T_SWORD;
+    case R_68K_16:
+      return ELF_T_HALF;
+    case R_68K_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
diff --git a/backends/ppc64_corenote.c b/backends/ppc64_corenote.c
new file mode 100644
index 0000000..9d6a6a4
--- /dev/null
+++ b/backends/ppc64_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "ppc_corenote.c"
diff --git a/backends/ppc64_init.c b/backends/ppc64_init.c
new file mode 100644
index 0000000..ffc9842
--- /dev/null
+++ b/backends/ppc64_init.c
@@ -0,0 +1,105 @@
+/* Initialization of PPC64 specific backend library.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#define BACKEND		ppc64_
+#define RELOC_PREFIX	R_PPC64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on ppc64_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+ppc64_init (Elf *elf __attribute__ ((unused)),
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh)
+{
+  /* We handle it.  */
+  ppc64_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, copy_reloc_p);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, check_st_other_bits);
+  HOOK (eh, bss_plt_p);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = (114 - 1) + 32;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, dwarf_to_regno);
+  HOOK (eh, unwind);
+  HOOK (eh, resolve_sym_value);
+
+  /* Find the function descriptor .opd table for resolve_sym_value.  */
+  if (elf != NULL)
+    {
+      GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+      size_t shstrndx;
+      if (ehdr != NULL && ehdr->e_type != ET_REL
+	  && elf_getshdrstrndx (elf, &shstrndx) == 0)
+	{
+	  /* We could also try through DT_PPC64_OPD and DT_PPC64_OPDSZ. */
+	  GElf_Shdr opd_shdr_mem, *opd_shdr;
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      opd_shdr = gelf_getshdr (scn, &opd_shdr_mem);
+	      if (opd_shdr != NULL
+		  && (opd_shdr->sh_flags & SHF_ALLOC) != 0
+		  && opd_shdr->sh_type == SHT_PROGBITS
+		  && opd_shdr->sh_size > 0)
+		{
+		  const char *name = elf_strptr (elf, shstrndx,
+						 opd_shdr->sh_name);
+		  if (name != NULL && strcmp (name, ".opd") == 0)
+		    {
+		      eh->fd_addr = opd_shdr->sh_addr;
+		      eh->fd_data = elf_getdata (scn, NULL);
+		      break;
+		    }
+		}
+	    }
+	}
+    }
+
+  return eh;
+}
diff --git a/backends/ppc64_reloc.def b/backends/ppc64_reloc.def
new file mode 100644
index 0000000..15a73ba
--- /dev/null
+++ b/backends/ppc64_reloc.def
@@ -0,0 +1,161 @@
+/* List the relocation types for ppc64.  -*- C -*-
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (ADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR24,		REL)
+RELOC_TYPE (ADDR16,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_LO,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HI,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HA,		REL)		/* note 1 */
+RELOC_TYPE (ADDR14,		REL)		/* note 1 */
+RELOC_TYPE (ADDR14_BRTAKEN,	REL)		/* note 1 */
+RELOC_TYPE (ADDR14_BRNTAKEN,	REL)		/* note 1 */
+RELOC_TYPE (REL24,		REL)
+RELOC_TYPE (REL14,		REL)
+RELOC_TYPE (REL14_BRTAKEN,	REL)
+RELOC_TYPE (REL14_BRNTAKEN,	REL)
+RELOC_TYPE (GOT16,		REL)
+RELOC_TYPE (GOT16_LO,		REL)
+RELOC_TYPE (GOT16_HI,		REL)
+RELOC_TYPE (GOT16_HA,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (UADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (UADDR16,		REL)
+RELOC_TYPE (REL32,		REL|EXEC|DYN)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (PLTREL32,		REL)
+RELOC_TYPE (PLT16_LO,		REL)
+RELOC_TYPE (PLT16_HI,		REL)
+RELOC_TYPE (PLT16_HA,		REL)
+RELOC_TYPE (SECTOFF,		REL)
+RELOC_TYPE (SECTOFF_LO,		REL)
+RELOC_TYPE (SECTOFF_HI,		REL)
+RELOC_TYPE (SECTOFF_HA,		REL)
+RELOC_TYPE (ADDR30,		REL)		/* note 1 */
+RELOC_TYPE (ADDR64,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR16_HIGHER,	REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HIGHERA,	REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HIGHEST,	REL)		/* note 1 */
+RELOC_TYPE (ADDR16_HIGHESTA,	REL)		/* note 1 */
+RELOC_TYPE (UADDR64,		REL|EXEC|DYN)
+RELOC_TYPE (REL64,		REL|EXEC|DYN)
+RELOC_TYPE (PLT64,		REL)
+RELOC_TYPE (PLTREL64,		REL)
+RELOC_TYPE (TOC16,		REL)
+RELOC_TYPE (TOC16_LO,		REL)
+RELOC_TYPE (TOC16_HI,		REL)
+RELOC_TYPE (TOC16_HA,		REL)
+RELOC_TYPE (TOC,		REL)
+RELOC_TYPE (PLTGOT16,		REL)
+RELOC_TYPE (PLTGOT16_LO,	REL)
+RELOC_TYPE (PLTGOT16_HI,	REL)
+RELOC_TYPE (PLTGOT16_HA,	REL)
+RELOC_TYPE (ADDR16_DS,		REL)		/* note 1 */
+RELOC_TYPE (ADDR16_LO_DS,	REL)		/* note 1 */
+RELOC_TYPE (GOT16_DS,		REL)
+RELOC_TYPE (GOT16_LO_DS,	REL)
+RELOC_TYPE (PLT16_LO_DS,	REL)
+RELOC_TYPE (SECTOFF_DS,		REL)
+RELOC_TYPE (SECTOFF_LO_DS,	REL)
+RELOC_TYPE (TOC16_DS,		REL)
+RELOC_TYPE (TOC16_LO_DS,	REL)
+RELOC_TYPE (PLTGOT16_DS,	REL)
+RELOC_TYPE (PLTGOT16_LO_DS,	REL)
+RELOC_TYPE (TLS,		REL)
+RELOC_TYPE (DTPMOD64,		REL|EXEC|DYN)	/* note 3 */
+RELOC_TYPE (TPREL16,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_LO,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HI,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HA,		REL)		/* note 2 */
+RELOC_TYPE (TPREL64,		REL|EXEC|DYN)	/* note 3 */
+RELOC_TYPE (DTPREL16,		REL)
+RELOC_TYPE (DTPREL16_LO,	REL)
+RELOC_TYPE (DTPREL16_HI,	REL)
+RELOC_TYPE (DTPREL16_HA,	REL)
+RELOC_TYPE (DTPREL64,		REL|EXEC|DYN)	/* note 3 */
+RELOC_TYPE (GOT_TLSGD16,	REL)
+RELOC_TYPE (GOT_TLSGD16_LO,	REL)
+RELOC_TYPE (GOT_TLSGD16_HI,	REL)
+RELOC_TYPE (GOT_TLSGD16_HA,	REL)
+RELOC_TYPE (GOT_TLSLD16,	REL)
+RELOC_TYPE (GOT_TLSLD16_LO,	REL)
+RELOC_TYPE (GOT_TLSLD16_HI,	REL)
+RELOC_TYPE (GOT_TLSLD16_HA,	REL)
+RELOC_TYPE (GOT_TPREL16_DS,	REL)
+RELOC_TYPE (GOT_TPREL16_LO_DS,	REL)
+RELOC_TYPE (GOT_TPREL16_HI,	REL)
+RELOC_TYPE (GOT_TPREL16_HA,	REL)
+RELOC_TYPE (GOT_DTPREL16_DS,	REL)
+RELOC_TYPE (GOT_DTPREL16_LO_DS, REL)
+RELOC_TYPE (GOT_DTPREL16_HI,	REL)
+RELOC_TYPE (GOT_DTPREL16_HA,	REL)
+RELOC_TYPE (TPREL16_DS,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_LO_DS,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHER,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHERA,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHEST,	REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HIGHESTA,	REL)		/* note 2 */
+RELOC_TYPE (DTPREL16_DS,	REL)
+RELOC_TYPE (DTPREL16_LO_DS,	REL)
+RELOC_TYPE (DTPREL16_HIGHER,	REL)
+RELOC_TYPE (DTPREL16_HIGHERA,	REL)
+RELOC_TYPE (DTPREL16_HIGHEST,	REL)
+RELOC_TYPE (DTPREL16_HIGHESTA,	REL)
+RELOC_TYPE (TLSGD,		REL)
+RELOC_TYPE (TLSLD,		REL)
+RELOC_TYPE (TOCSAVE,		REL)
+RELOC_TYPE (ADDR16_HIGH,	REL)
+RELOC_TYPE (ADDR16_HIGHA,	REL)
+RELOC_TYPE (TPREL16_HIGH,	REL)
+RELOC_TYPE (TPREL16_HIGHA,	REL)
+RELOC_TYPE (DTPREL16_HIGH,	REL)
+RELOC_TYPE (DTPREL16_HIGHA,	REL)
+RELOC_TYPE (JMP_IREL,		REL)
+RELOC_TYPE (IRELATIVE,		REL)
+RELOC_TYPE (REL16,		REL)
+RELOC_TYPE (REL16_LO,		REL)
+RELOC_TYPE (REL16_HI,		REL)
+RELOC_TYPE (REL16_HA,		REL)
+
+/* Notes from Alan Modra:
+
+   1) These can appear in DYN and EXEC with improper assembly, but they
+   aren't really kosher.
+
+   2) These can appear in DYN with improper assembly (or silly gcc
+      attributes, I think).  Again, not kosher.
+
+   3) These are legal in REL for PowerOpen compatible assembler syntax,
+      ie. TOC managed by compiler.
+*/
diff --git a/backends/ppc64_resolve_sym.c b/backends/ppc64_resolve_sym.c
new file mode 100644
index 0000000..03f6558
--- /dev/null
+++ b/backends/ppc64_resolve_sym.c
@@ -0,0 +1,63 @@
+/* Resolve symbol values through .opd function descriptors.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc64_
+#include "libebl_CPU.h"
+
+/* Resolve a function descriptor if addr points into the .opd section.
+   The .opd section contains function descriptors consisting of 3 addresses.
+   function, toc and chain. We are just interested in the first.
+   http://refspecs.linuxfoundation.org/ELF/ppc64/PPC-elf64abi-1.9.html#FUNC-DES
+
+   Returns true if the given address could be resolved, false otherwise.
+*/
+bool
+ppc64_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+{
+  if (ebl->fd_data != NULL && *addr >= ebl->fd_addr
+      && *addr + sizeof (Elf64_Addr) <= ebl->fd_addr + ebl->fd_data->d_size)
+    {
+      GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem);
+      if (ehdr != NULL)
+	{
+	  Elf_Data opd_in, opd_out;
+	  opd_in.d_buf = ebl->fd_data->d_buf + (*addr - ebl->fd_addr);
+	  opd_out.d_buf = addr;
+	  opd_out.d_size = opd_in.d_size = sizeof (Elf64_Addr);
+	  opd_out.d_type = opd_in.d_type = ELF_T_ADDR;
+	  if (elf64_xlatetom (&opd_out, &opd_in,
+			      ehdr->e_ident[EI_DATA]) != NULL)
+	    return true;
+	}
+    }
+  return false;
+}
diff --git a/backends/ppc64_retval.c b/backends/ppc64_retval.c
new file mode 100644
index 0000000..1c20c89
--- /dev/null
+++ b/backends/ppc64_retval.c
@@ -0,0 +1,194 @@
+/* Function return value location for Linux/PPC64 ABI.
+   Copyright (C) 2005-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND ppc64_
+#include "libebl_CPU.h"
+
+
+/* r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg3 }
+  };
+#define nloc_intreg	1
+
+/* f1, or f1:f2, or f1:f4.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_regx, .number = 36 }, { .atom = DW_OP_piece, .number = 8 },
+  };
+#define nloc_fpreg	1
+#define nloc_fp2regs	4
+#define nloc_fp4regs	8
+
+/* vr2.  */
+static const Dwarf_Op loc_vmxreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 1124 + 2 }
+  };
+#define nloc_vmxreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r3.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg3, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+ppc64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 8;
+	    else
+	      return -1;
+	}
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  if (encoding == DW_ATE_float || encoding == DW_ATE_complex_float)
+	    {
+	      *locp = loc_fpreg;
+	      if (size <= 8)
+		return nloc_fpreg;
+	      if (size <= 16)
+		return nloc_fp2regs;
+	      if (size <= 32)
+		return nloc_fp4regs;
+	    }
+	}
+      if (size <= 8)
+	{
+	intreg:
+	  *locp = loc_intreg;
+	  return nloc_intreg;
+	}
+
+      FALLTHROUGH;
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_array_type:
+      {
+	Dwarf_Attribute attr_mem;
+	bool is_vector;
+	if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector,
+						  &attr_mem), &is_vector) == 0
+	    && is_vector)
+	  {
+	    *locp = loc_vmxreg;
+	    return nloc_vmxreg;
+	  }
+      }
+      FALLTHROUGH;
+
+    case DW_TAG_string_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0 && size <= 8)
+	{
+	  if (tag == DW_TAG_array_type)
+	    {
+	      /* Check if it's a character array.  */
+	      Dwarf_Attribute attr_mem, *attr;
+	      attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	      typedie = dwarf_formref_die (attr, &die_mem);
+	      tag = DWARF_TAG_OR_RETURN (typedie);
+	      if (tag != DW_TAG_base_type)
+		goto aggregate;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_byte_size,
+							 &attr_mem),
+				   &size) != 0)
+		return -1;
+	      if (size != 1)
+		goto aggregate;
+	    }
+	  goto intreg;
+	}
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/ppc64_symbol.c b/backends/ppc64_symbol.c
new file mode 100644
index 0000000..81b94cf
--- /dev/null
+++ b/backends/ppc64_symbol.c
@@ -0,0 +1,134 @@
+/* PPC64 specific symbolic name handling.
+   Copyright (C) 2004, 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		ppc64_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+ppc64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			 int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_PPC64_ADDR64:
+    case R_PPC64_UADDR64:
+      return ELF_T_XWORD;
+    case R_PPC64_ADDR32:
+    case R_PPC64_UADDR32:
+      return ELF_T_WORD;
+    case R_PPC64_UADDR16:
+      return ELF_T_HALF;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+
+const char *
+ppc64_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_PPC64_GLINK:
+      return "PPC64_GLINK";
+    case DT_PPC64_OPD:
+      return "PPC64_OPD";
+    case DT_PPC64_OPDSZ:
+      return "PPC64_OPDSZ";
+    case DT_PPC64_OPT:
+      return "PPC64_OPT";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+
+bool
+ppc64_dynamic_tag_check (int64_t tag)
+{
+  return (tag == DT_PPC64_GLINK
+	  || tag == DT_PPC64_OPD
+	  || tag == DT_PPC64_OPDSZ
+	  || tag == DT_PPC64_OPT);
+}
+
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+ppc64_check_special_symbol (Elf *elf,
+			    const GElf_Sym *sym __attribute__ ((unused)),
+			    const char *name __attribute__ ((unused)),
+			    const GElf_Shdr *destshdr)
+{
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+    return false;
+  const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
+  if (sname == NULL)
+    return false;
+  return strcmp (sname, ".opd") == 0;
+}
+
+
+/* Check if backend uses a bss PLT in this file.  */
+bool
+ppc64_bss_plt_p (Elf *elf __attribute__ ((unused)))
+{
+  return true;
+}
+
+/* Check whether machine flags are valid.  PPC64 has three possible values:
+   0 - for unspecified ABI, or not using any specific ABI features.
+   1 - for the original ELF PPC64 ABI using function descriptors.
+   2 - for the revised ELFv2 PPC64 ABI without function descriptors.  */
+bool
+ppc64_machine_flag_check (GElf_Word flags)
+{
+  return flags == 0 || flags == 1 || flags == 2;
+}
+
+bool
+ppc64_check_st_other_bits (unsigned char st_other)
+{
+  return (PPC64_LOCAL_ENTRY_OFFSET (st_other) != 0);
+}
diff --git a/backends/ppc64_unwind.c b/backends/ppc64_unwind.c
new file mode 100644
index 0000000..4fa0b5a
--- /dev/null
+++ b/backends/ppc64_unwind.c
@@ -0,0 +1,76 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc64_
+
+#define LR_REG 65 /* Not 108, see ppc_dwarf_to_regno.  */
+#define SP_REG  1
+
+#define LR_OFFSET 16
+
+#include "libebl_CPU.h"
+
+/* Simplistic fallback frame unwinder. SP points to the backchain (contains
+   address of previous stack pointer). At SP offset 16 is the LR save area
+   (contains the value of the previous LR).  */
+
+bool
+EBLHOOK(unwind) (Ebl *ebl __attribute__ ((unused)),
+		 Dwarf_Addr pc __attribute__ ((unused)),
+                 ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+                 ebl_pid_memory_read_t *readfunc, void *arg,
+                 bool *signal_framep __attribute__ ((unused)))
+{
+  Dwarf_Word sp, newSp, lr, newLr;
+
+  /* Stack pointer points to the backchain which contains the previous sp.  */
+  if (! getfunc (SP_REG, 1, &sp, arg))
+    sp = 0;
+
+  /* Link register contains previous program counter.  */
+  if (! getfunc (LR_REG, 1, &lr, arg)
+      || lr == 0
+      || ! setfunc (-1, 1, &lr, arg))
+    return false;
+
+  if (! readfunc(sp, &newSp, arg))
+    newSp = 0;
+
+  if (! readfunc(newSp + LR_OFFSET, &newLr, arg))
+    newLr = 0;
+
+  setfunc(SP_REG, 1, &newSp, arg);
+  setfunc(LR_REG, 1, &newLr, arg);
+
+  /* Sanity check the stack grows down.  */
+  return newSp > sp;
+}
diff --git a/backends/ppc_attrs.c b/backends/ppc_attrs.c
new file mode 100644
index 0000000..48d7129
--- /dev/null
+++ b/backends/ppc_attrs.c
@@ -0,0 +1,86 @@
+/* Object attribute tags for PowerPC.
+   Copyright (C) 2008, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+bool
+ppc_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			    const char *vendor, int tag, uint64_t value,
+			    const char **tag_name, const char **value_name)
+{
+  if (!strcmp (vendor, "gnu"))
+    switch (tag)
+      {
+      case 4:
+	*tag_name = "GNU_Power_ABI_FP";
+	static const char *fp_kinds[] =
+	  {
+	    "Hard or soft float",
+	    "Hard float",
+	    "Soft float",
+	    "Single-precision hard float",
+	  };
+	if (value < sizeof fp_kinds / sizeof fp_kinds[0])
+	  *value_name = fp_kinds[value];
+	return true;
+
+      case 8:
+	*tag_name = "GNU_Power_ABI_Vector";
+	static const char *vector_kinds[] =
+	  {
+	    "Any", "Generic", "AltiVec", "SPE"
+	  };
+	if (value < sizeof vector_kinds / sizeof vector_kinds[0])
+	  *value_name = vector_kinds[value];
+	return true;
+
+      case 12:
+	*tag_name = "GNU_Power_ABI_Struct_Return";
+	static const char *struct_return_kinds[] =
+	  {
+	    "Any", "r3/r4", "Memory"
+	  };
+	if (value < sizeof struct_return_kinds / sizeof struct_return_kinds[0])
+	  *value_name = struct_return_kinds[value];
+	return true;
+      }
+
+  return false;
+}
+
+__typeof (ppc_check_object_attribute)
+     ppc64_check_object_attribute
+     __attribute__ ((alias ("ppc_check_object_attribute")));
diff --git a/backends/ppc_auxv.c b/backends/ppc_auxv.c
new file mode 100644
index 0000000..a27a1da
--- /dev/null
+++ b/backends/ppc_auxv.c
@@ -0,0 +1,55 @@
+/* i386 specific auxv handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "ppcle\0" "truele\0" "3\0" "4\0" "5\0" "6\0" "7\0" "8\0" "9\0"
+    "power6x\0" "dfp\0" "pa6t\0" "arch_2_05\0"
+    "ic_snoop\0" "smt\0" "booke\0" "cellbe\0"
+    "power5+\0" "power5\0" "power4\0" "notb\0"
+    "efpdouble\0" "efpsingle\0" "spe\0" "ucache\0"
+    "4xxmac\0" "mmu\0" "fpu\0" "altivec\0"
+    "ppc601\0" "ppc64\0" "ppc32\0" "\0";
+  return 1;
+}
+
+__typeof (ppc_auxv_info) ppc64_auxv_info
+			 __attribute__ ((alias ("ppc_auxv_info")));
diff --git a/backends/ppc_cfi.c b/backends/ppc_cfi.c
new file mode 100644
index 0000000..b470036
--- /dev/null
+++ b/backends/ppc_cfi.c
@@ -0,0 +1,77 @@
+/* ppc ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2012, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+int
+ppc_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* This instruction is provided in every CIE.  It is not repeated here:
+	 DW_CFA_def_cfa, ULEB128_7 (1), ULEB128_7 (0)  */
+      /* r1 is assumed to be restored from cfa address,
+	 r1 acts as a stack frame pointer.  */
+      DW_CFA_val_offset, ULEB128_7 (1), ULEB128_7 (0),
+      /* lr is not callee-saved but it needs to be preserved as it is pre-set
+	 by the caller.  */
+      DW_CFA_same_value, ULEB128_7 (65), /* lr */
+
+      /* Callee-saved regs.  */
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      SV (2),			/* r2 is TOC pointer.  */
+      SV (13),			/* Reserved as system thread id (is it for CFI?).  */
+      /* r14-r31 are non-volatile registers.  */
+      SV (14), SV (15), SV (16), SV (17), SV (18), SV (19), SV (20), SV (21),
+      SV (22), SV (23), SV (24), SV (25), SV (26), SV (27), SV (28), SV (29),
+      SV (30), SV (31)
+      /* VMX registers v20-v31 and vrsave are non-volatile but they are
+	 assigned DWARF registers 1144-1156 (v20-v31) which is outside of the
+	 CFI supported range.  */
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = ebl->class == ELFCLASS64 ? 8 : 4;
+
+  abi_info->return_address_register = 65;
+
+  return 0;
+}
+
+__typeof (ppc_abi_cfi)
+     ppc64_abi_cfi
+     __attribute__ ((alias ("ppc_abi_cfi")));
diff --git a/backends/ppc_corenote.c b/backends/ppc_corenote.c
new file mode 100644
index 0000000..2b4ada7
--- /dev/null
+++ b/backends/ppc_corenote.c
@@ -0,0 +1,145 @@
+/* PowerPC specific core note handling.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		32
+# define BACKEND	ppc_
+#else
+# define BITS 		64
+# define BACKEND	ppc64_
+#endif
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = BITS }
+
+    GR (0, 32, 0),		/* r0-r31 */
+    /*	32, 1,			   nip */
+    GR (33, 1, 66),		/* msr */
+    /*	34, 1,			   orig_gpr3 */
+    GR (35, 1, 109),		/* ctr */
+    GR (36, 1, 108),		/* lr */
+    GR (37, 1, 101),		/* xer */
+    GR (38, 1, 64),		/* cr */
+    GR (39, 1, 100),		/* mq */
+    /*  40, 1,			   trap */
+    GR (41, 1, 119),		/* dar */
+    GR (42, 1, 118),		/* dsisr */
+
+#undef	GR
+  };
+#define PRSTATUS_REGS_SIZE	(BITS / 8 * 48)
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 32, .count = 32, .bits = 64 }, /* f0-f31 */
+    { .offset = 32 * 8 + 4, .regno = 65, .count = 1, .bits = 32 } /* fpscr */
+  };
+#define FPREGSET_SIZE		(33 * 8)
+
+static const Ebl_Register_Location altivec_regs[] =
+  {
+    /* vr0-vr31 */
+    { .offset = 0, .regno = 1124, .count = 32, .bits = 128 },
+    /* vscr XXX 67 is an unofficial assignment */
+    { .offset = 32 * 16, .regno = 67, .count = 1, .bits = 32, .pad = 12 },
+    /* vrsave */
+    { .offset = 33 * 16, .regno = 356, .count = 1, .bits = 32, .pad = 12 }
+  };
+
+static const Ebl_Register_Location spe_regs[] =
+  {
+    /* evr0-evr31
+    { .offset = 0, .regno = ???, .count = 32, .bits = 32 },
+     * acc *
+    { .offset = 32 * 4, .regno = ???, .count = 1, .bits = 64 }, */
+    /* spefscr */
+    { .offset = 34 * 4, .regno = 612, .count = 1, .bits = 32 }
+  };
+
+static const Ebl_Register_Location tm_spr_regs[] =
+  {
+    /* tfhar */
+    { .offset = 0, .regno = 114, .count = 1, .bits = 64 },
+    /* texasr */
+    { .offset = 8, .regno = 116, .count = 1, .bits = 64 },
+    /* tfiar */
+    { .offset = 16, .regno = 115, .count = 1, .bits = 64 }
+  };
+
+#define EXTRA_NOTES \
+  EXTRA_REGSET (NT_PPC_VMX, 34 * 16, altivec_regs) \
+  EXTRA_REGSET (NT_PPC_SPE, 35 * 4, spe_regs) \
+  EXTRA_REGSET (NT_PPC_TM_SPR, 3 * 8, tm_spr_regs)
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_LONG		ELF_T_SWORD
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_LONG		ELF_T_SXWORD
+#endif
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_WORD
+#define TYPE_GID_T		ELF_T_WORD
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "nip", .type = ELF_T_ADDR, .format = 'x',			      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[32]),		      \
+    .group = "register", .pc_register = true				      \
+  },								      	      \
+  {									      \
+    .name = "orig_gpr3", .type = TYPE_LONG, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[34]),		      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+#include "linux-core-note.c"
diff --git a/backends/ppc_init.c b/backends/ppc_init.c
new file mode 100644
index 0000000..08468f8
--- /dev/null
+++ b/backends/ppc_init.c
@@ -0,0 +1,67 @@
+/* Initialization of PPC specific backend library.
+   Copyright (C) 2004, 2005, 2006, 2007, 2008, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		ppc_
+#define RELOC_PREFIX	R_PPC_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on ppc_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+ppc_init (Elf *elf __attribute__ ((unused)),
+	  GElf_Half machine __attribute__ ((unused)),
+	  Ebl *eh)
+{
+  /* We handle it.  */
+  ppc_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, bss_plt_p);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = (114 - 1) + 32;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, dwarf_to_regno);
+
+  return eh;
+}
diff --git a/backends/ppc_initreg.c b/backends/ppc_initreg.c
new file mode 100644
index 0000000..8ed72fb
--- /dev/null
+++ b/backends/ppc_initreg.c
@@ -0,0 +1,132 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#if defined(__powerpc__) && defined(__linux__)
+# include <sys/ptrace.h>
+# include <asm/ptrace.h>
+# ifndef PTRACE_GETREGSET
+#  include <linux/ptrace.h>
+# endif
+# include <sys/user.h>
+# include <sys/uio.h>
+#endif
+
+#include "system.h"
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+bool
+ppc_dwarf_to_regno (Ebl *ebl __attribute__ ((unused)), unsigned *regno)
+{
+  switch (*regno)
+  {
+    case 108:
+      // LR uses both 65 and 108 numbers, there is no consistency for it.
+      *regno = 65;
+      return true;
+    case 0 ... 107:
+    case 109 ... (114 - 1) -1:
+      return true;
+    case 1200 ... 1231:
+      *regno = *regno - 1200 + (114 - 1);
+      return true;
+    default:
+      return false;
+  }
+  abort ();
+}
+
+__typeof (ppc_dwarf_to_regno)
+     ppc64_dwarf_to_regno
+     __attribute__ ((alias ("ppc_dwarf_to_regno")));
+
+bool
+ppc_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+			       void *arg __attribute__ ((unused)))
+{
+#if !defined(__powerpc__) || !defined(__linux__)
+  return false;
+#else /* __powerpc__ */
+
+/* pt_regs for 32bit processes. Same as 64bit pt_regs but all registers
+   are 32bit instead of 64bit long.  */
+#define GPRS 32
+  struct pt_regs32
+  {
+    uint32_t gpr[GPRS];
+    uint32_t nip;
+    uint32_t msr;
+    uint32_t orig_gpr3;
+    uint32_t ctr;
+    uint32_t link;
+    uint32_t xer;
+    uint32_t ccr;
+    uint32_t mq;
+    uint32_t trap;
+    uint32_t dar;
+    uint32_t dsisr;
+    uint32_t result;
+  };
+
+  struct pt_regs regs;
+  struct pt_regs32 *regs32 = (struct pt_regs32 *) &regs;
+  struct iovec iovec;
+  iovec.iov_base = &regs;
+  iovec.iov_len = sizeof (regs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  /* Did we get the full pt_regs or less (the 32bit pt_regs)?  */
+  bool get32 = iovec.iov_len < sizeof (struct pt_regs);
+  Dwarf_Word dwarf_regs[GPRS];
+  for (unsigned gpr = 0; gpr < GPRS; gpr++)
+    dwarf_regs[gpr] = get32 ? regs32->gpr[gpr] : regs.gpr[gpr];
+  if (! setfunc (0, GPRS, dwarf_regs, arg))
+    return false;
+  // LR uses both 65 and 108 numbers, there is no consistency for it.
+  Dwarf_Word link = get32 ? regs32->link : regs.link;
+  if (! setfunc (65, 1, &link, arg))
+    return false;
+  /* Registers like msr, ctr, xer, dar, dsisr etc. are probably irrelevant
+     for CFI.  */
+  Dwarf_Word pc = get32 ? (Dwarf_Word) regs32->nip : regs.nip;
+  return setfunc (-1, 1, &pc, arg);
+#endif /* __powerpc__ */
+}
+
+__typeof (ppc_set_initial_registers_tid)
+     ppc64_set_initial_registers_tid
+     __attribute__ ((alias ("ppc_set_initial_registers_tid")));
diff --git a/backends/ppc_regs.c b/backends/ppc_regs.c
new file mode 100644
index 0000000..43d2534
--- /dev/null
+++ b/backends/ppc_regs.c
@@ -0,0 +1,208 @@
+/* Register names and numbers for PowerPC DWARF.
+   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+ssize_t
+ppc_register_info (Ebl *ebl __attribute__ ((unused)),
+		   int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  if (name == NULL)
+    return 1156;
+
+  if (regno < 0 || regno > 1155 || namelen < 8)
+    return -1;
+
+  *prefix = "";
+  *bits = ebl->machine == EM_PPC64 ? 64 : 32;
+  *type = (regno < 32 ? DW_ATE_signed
+	   : regno < 64 ? DW_ATE_float : DW_ATE_unsigned);
+
+  if (regno < 32 || regno == 64 || regno == 66)
+    *setname = "integer";
+  else if (regno < 64 || regno == 65)
+    {
+      *setname = "FPU";
+      if (ebl->machine != EM_PPC64 && regno < 64)
+	*bits = 64;
+    }
+  else if (regno == 67 || regno == 356 || regno == 612 || regno >= 1124)
+    {
+      *setname = "vector";
+      *bits = regno >= 1124 ? 128 : 32;
+    }
+  else
+    *setname = "privileged";
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 31:
+      name[0] = 'r';
+      name[1] = regno / 10 + '0';
+      name[2] = regno % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 32 + 0 ... 32 + 9:
+      name[0] = 'f';
+      name[1] = (regno - 32) + '0';
+      namelen = 2;
+      break;
+
+    case 32 + 10 ... 32 + 31:
+      name[0] = 'f';
+      name[1] = (regno - 32) / 10 + '0';
+      name[2] = (regno - 32) % 10 + '0';
+      namelen = 3;
+      break;
+
+    case 64:
+      return stpcpy (name, "cr") + 1 - name;
+    case 65:
+      return stpcpy (name, "fpscr") + 1 - name;
+    case 66:
+      return stpcpy (name, "msr") + 1 - name;
+    case 67:			/* XXX unofficial assignment */
+      return stpcpy (name, "vscr") + 1 - name;
+
+    case 70 + 0 ... 70 + 9:
+      name[0] = 's';
+      name[1] = 'r';
+      name[2] = (regno - 70) + '0';
+      namelen = 3;
+      break;
+
+    case 70 + 10 ... 70 + 15:
+      name[0] = 's';
+      name[1] = 'r';
+      name[2] = (regno - 70) / 10 + '0';
+      name[3] = (regno - 70) % 10 + '0';
+      namelen = 4;
+      break;
+
+    case 101:
+      return stpcpy (name, "xer") + 1 - name;
+    case 108:
+      return stpcpy (name, "lr") + 1 - name;
+    case 109:
+      return stpcpy (name, "ctr") + 1 - name;
+    case 118:
+      return stpcpy (name, "dsisr") + 1 - name;
+    case 119:
+      return stpcpy (name, "dar") + 1 - name;
+    case 122:
+      return stpcpy (name, "dec") + 1 - name;
+    case 356:
+      return stpcpy (name, "vrsave") + 1 - name;
+    case 612:
+      return stpcpy (name, "spefscr") + 1 - name;
+    case 100:
+      if (*bits == 32)
+	return stpcpy (name, "mq") + 1 - name;
+      FALLTHROUGH;
+    case 102 ... 107:
+      name[0] = 's';
+      name[1] = 'p';
+      name[2] = 'r';
+      name[3] = (regno - 100) + '0';
+      namelen = 4;
+      break;
+
+    case 114:
+      return stpcpy (name, "tfhar") + 1 - name;
+    case 115:
+      return stpcpy (name, "tfiar") + 1 - name;
+    case 116:
+      return stpcpy (name, "texasr") + 1 - name;
+
+    case 110 ... 113:
+    case 117:
+    case 120 ... 121:
+    case 123 ... 199:
+      name[0] = 's';
+      name[1] = 'p';
+      name[2] = 'r';
+      name[3] = (regno - 100) / 10 + '0';
+      name[4] = (regno - 100) % 10 + '0';
+      namelen = 5;
+      break;
+
+    case 200 ... 355:
+    case 357 ... 611:
+    case 613 ... 999:
+      name[0] = 's';
+      name[1] = 'p';
+      name[2] = 'r';
+      name[3] = (regno - 100) / 100 + '0';
+      name[4] = ((regno - 100) % 100 / 10) + '0';
+      name[5] = (regno - 100) % 10 + '0';
+      namelen = 6;
+      break;
+
+    case 1124 + 0 ... 1124 + 9:
+      name[0] = 'v';
+      name[1] = 'r';
+      name[2] = (regno - 1124) + '0';
+      namelen = 3;
+      break;
+
+    case 1124 + 10 ... 1124 + 31:
+      name[0] = 'v';
+      name[1] = 'r';
+      name[2] = (regno - 1124) / 10 + '0';
+      name[3] = (regno - 1124) % 10 + '0';
+      namelen = 4;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
+
+__typeof (ppc_register_info)
+     ppc64_register_info __attribute__ ((alias ("ppc_register_info")));
diff --git a/backends/ppc_reloc.def b/backends/ppc_reloc.def
new file mode 100644
index 0000000..3723a9c
--- /dev/null
+++ b/backends/ppc_reloc.def
@@ -0,0 +1,137 @@
+/* List the relocation types for ppc.  -*- C -*-
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (ADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (ADDR24,		REL)
+RELOC_TYPE (ADDR16,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR16_LO,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR16_HI,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR16_HA,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR14,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR14_BRTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (ADDR14_BRNTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL24,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL14,		REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL14_BRTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (REL14_BRNTAKEN,	REL|EXEC|DYN)	/* note 1 */
+RELOC_TYPE (GOT16,		REL)
+RELOC_TYPE (GOT16_LO,		REL)
+RELOC_TYPE (GOT16_HI,		REL)
+RELOC_TYPE (GOT16_HA,		REL)
+RELOC_TYPE (PLTREL24,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (LOCAL24PC,		REL)
+RELOC_TYPE (UADDR32,		REL|EXEC|DYN)
+RELOC_TYPE (UADDR16,		REL)		/* note 2 */
+RELOC_TYPE (REL32,		REL|EXEC|DYN)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (PLTREL32,		REL)
+RELOC_TYPE (PLT16_LO,		REL)
+RELOC_TYPE (PLT16_HI,		REL)
+RELOC_TYPE (PLT16_HA,		REL)
+RELOC_TYPE (SDAREL16,		REL)
+RELOC_TYPE (SECTOFF,		REL)
+RELOC_TYPE (SECTOFF_LO,		REL)
+RELOC_TYPE (SECTOFF_HI,		REL)
+RELOC_TYPE (SECTOFF_HA,		REL)
+RELOC_TYPE (TLS,		REL)
+RELOC_TYPE (DTPMOD32,		EXEC|DYN)	/* note 2 */
+RELOC_TYPE (TPREL16,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_LO,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HI,		REL)		/* note 2 */
+RELOC_TYPE (TPREL16_HA,		REL)		/* note 2 */
+RELOC_TYPE (TPREL32,		EXEC|DYN)	/* note 2 */
+RELOC_TYPE (DTPREL16,		REL)
+RELOC_TYPE (DTPREL16_LO,	REL)
+RELOC_TYPE (DTPREL16_HI,	REL)
+RELOC_TYPE (DTPREL16_HA,	REL)
+RELOC_TYPE (DTPREL32,		EXEC|DYN)	/* note 2 */
+RELOC_TYPE (GOT_TLSGD16,	REL)
+RELOC_TYPE (GOT_TLSGD16_LO,	REL)
+RELOC_TYPE (GOT_TLSGD16_HI,	REL)
+RELOC_TYPE (GOT_TLSGD16_HA,	REL)
+RELOC_TYPE (GOT_TLSLD16,	REL)
+RELOC_TYPE (GOT_TLSLD16_LO,	REL)
+RELOC_TYPE (GOT_TLSLD16_HI,	REL)
+RELOC_TYPE (GOT_TLSLD16_HA,	REL)
+RELOC_TYPE (GOT_TPREL16,	REL)
+RELOC_TYPE (GOT_TPREL16_LO,	REL)
+RELOC_TYPE (GOT_TPREL16_HI,	REL)
+RELOC_TYPE (GOT_TPREL16_HA,	REL)
+RELOC_TYPE (GOT_DTPREL16,	REL)
+RELOC_TYPE (GOT_DTPREL16_LO,	REL)
+RELOC_TYPE (GOT_DTPREL16_HI,	REL)
+RELOC_TYPE (GOT_DTPREL16_HA,	REL)
+RELOC_TYPE (EMB_NADDR32,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16_LO,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16_HI,	REL)		/* note 3 */
+RELOC_TYPE (EMB_NADDR16_HA,	REL)		/* note 3 */
+RELOC_TYPE (EMB_SDAI16,		REL)		/* note 3 */
+RELOC_TYPE (EMB_SDA2I16,	REL)		/* note 3 */
+RELOC_TYPE (EMB_SDA2REL,	REL)		/* note 3 */
+RELOC_TYPE (EMB_SDA21,		REL)		/* note 3 */
+RELOC_TYPE (EMB_MRKREF,		REL)		/* note 3 */
+RELOC_TYPE (EMB_RELSEC16,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELST_LO,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELST_HI,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELST_HA,	REL)		/* note 3 */
+RELOC_TYPE (EMB_BIT_FLD,	REL)		/* note 3 */
+RELOC_TYPE (EMB_RELSDA,		REL)		/* note 3 */
+RELOC_TYPE (DIAB_SDA21_LO,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_SDA21_HI,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_SDA21_HA,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_RELSDA_LO,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_RELSDA_HI,	REL)		/* note 3 */
+RELOC_TYPE (DIAB_RELSDA_HA,	REL)		/* note 3 */
+RELOC_TYPE (REL16,		REL)		/* note 2 */
+RELOC_TYPE (REL16_LO,		REL)		/* note 2 */
+RELOC_TYPE (REL16_HI,		REL)		/* note 2 */
+RELOC_TYPE (REL16_HA,		REL)		/* note 2 */
+RELOC_TYPE (TOC16,		REL)		/* note 2 */
+
+/* Notes from Alan Modra:
+
+   1) These relocs should not really appear in EXEC or DYN, but they do,
+   primarily due to improper assembly or non-pic shared objects.  They
+   will cause TEXTREL to be set.  I marked them in the table, because
+   numerous people seem to think non-pic shared libs are a good idea.
+
+   2) As for (1), these relocs can appear anywhere with improper
+   assembler.  I should probably make ld reject anything other than the
+   cases allowed in this table.	 Not seen in the wild, so I haven't
+   added the other cases.
+
+   3) Not used in SYSV4
+*/
diff --git a/backends/ppc_retval.c b/backends/ppc_retval.c
new file mode 100644
index 0000000..5144712
--- /dev/null
+++ b/backends/ppc_retval.c
@@ -0,0 +1,190 @@
+/* Function return value location for Linux/PPC ABI.
+   Copyright (C) 2005, 2006, 2007, 2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND ppc_
+#include "libebl_CPU.h"
+
+
+/* This is the SVR4 ELF ABI convention, but AIX and Linux do not use it.  */
+#define SVR4_STRUCT_RETURN 0
+
+
+/* r3, or pair r3, r4, or quad r3-r6.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg4 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg5 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg6 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+#define nloc_intregquad	8
+
+/* f1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 33 }
+  };
+#define nloc_fpreg	1
+
+/* vr2.  */
+static const Dwarf_Op loc_vmxreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 1124 + 2 }
+  };
+#define nloc_vmxreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in r3.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg3, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+/* XXX We should check the SHT_GNU_ATTRIBUTES bits here (or in ppc_init).  */
+static bool
+ppc_altivec_abi (void)
+{
+  return true;
+}
+
+int
+ppc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 4;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (size <= 8)
+	{
+	  if (tag == DW_TAG_base_type)
+	    {
+	      Dwarf_Attribute attr_mem;
+	      Dwarf_Word encoding;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_encoding,
+							 &attr_mem),
+				   &encoding) != 0)
+		return -1;
+	      if (encoding == DW_ATE_float)
+		{
+		  *locp = loc_fpreg;
+		  return nloc_fpreg;
+		}
+	    }
+	intreg:
+	  *locp = loc_intreg;
+	  return size <= 4 ? nloc_intreg : nloc_intregpair;
+	}
+
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_array_type:
+      {
+	Dwarf_Attribute attr_mem;
+	bool is_vector;
+	if (dwarf_formflag (dwarf_attr_integrate (typedie, DW_AT_GNU_vector,
+						  &attr_mem), &is_vector) == 0
+	    && is_vector
+	    && dwarf_aggregate_size (typedie, &size) == 0)
+	  switch (size)
+	    {
+	    case 16:
+	      if (ppc_altivec_abi ())
+		{
+		  *locp = loc_vmxreg;
+		  return nloc_vmxreg;
+		}
+	      *locp = loc_intreg;
+	      return nloc_intregquad;
+	    }
+      }
+      FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+      if (SVR4_STRUCT_RETURN
+	  && dwarf_aggregate_size (typedie, &size) == 0
+	  && size > 0 && size <= 8)
+	goto intreg;
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/ppc_symbol.c b/backends/ppc_symbol.c
new file mode 100644
index 0000000..5a169d5
--- /dev/null
+++ b/backends/ppc_symbol.c
@@ -0,0 +1,188 @@
+/* PPC specific symbolic name handling.
+   Copyright (C) 2004, 2005, 2007, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		ppc_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+ppc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+		       int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_PPC_ADDR32:
+    case R_PPC_UADDR32:
+      return ELF_T_WORD;
+    case R_PPC_UADDR16:
+      return ELF_T_HALF;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+
+/* Check whether machine flags are valid.  */
+bool
+ppc_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ (EF_PPC_EMB
+		     | EF_PPC_RELOCATABLE
+		     | EF_PPC_RELOCATABLE_LIB)) == 0);
+}
+
+
+const char *
+ppc_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+		      size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_PPC_GOT:
+      return "PPC_GOT";
+    case DT_PPC_OPT:
+      return "PPC_OPT";
+    default:
+      break;
+    }
+  return NULL;
+}
+
+
+bool
+ppc_dynamic_tag_check (int64_t tag)
+{
+  return (tag == DT_PPC_GOT
+	  || tag == DT_PPC_OPT);
+}
+
+
+/* Look for DT_PPC_GOT.  */
+static bool
+find_dyn_got (Elf *elf, GElf_Addr *addr)
+{
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    return false;
+
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (phdr == NULL || phdr->p_type != PT_DYNAMIC)
+	continue;
+
+      Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      Elf_Data *data = elf_getdata (scn, NULL);
+      if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC && data != NULL
+	  && shdr->sh_entsize != 0)
+	for (unsigned int j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
+	  {
+	    GElf_Dyn dyn_mem;
+	    GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
+	    if (dyn != NULL && dyn->d_tag == DT_PPC_GOT)
+	      {
+		*addr = dyn->d_un.d_ptr;
+		return true;
+	      }
+	  }
+
+      /* There is only one PT_DYNAMIC entry.  */
+      break;
+    }
+
+  return false;
+}
+
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+ppc_check_special_symbol (Elf *elf, const GElf_Sym *sym,
+			  const char *name, const GElf_Shdr *destshdr)
+{
+  if (name == NULL)
+    return false;
+
+  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    {
+      /* In -msecure-plt mode, DT_PPC_GOT is present and must match.  */
+      GElf_Addr gotaddr;
+      if (find_dyn_got (elf, &gotaddr))
+	return sym->st_value == gotaddr;
+
+      /* In -mbss-plt mode, any place in the section is valid.  */
+      return true;
+    }
+
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+    return false;
+  const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
+  if (sname == NULL)
+    return false;
+
+  /* Small data area.  Normally points to .sdata, in which case we
+     check it is at an offset of 0x8000.  It might however fall in the
+     .data section, in which case we cannot check the offset.  The
+     size always should be zero.  */
+  if (strcmp (name, "_SDA_BASE_") == 0)
+    return (((strcmp (sname, ".sdata") == 0
+	      && sym->st_value == destshdr->sh_addr + 0x8000)
+	     || strcmp (sname, ".data") == 0)
+	    && sym->st_size == 0);
+
+  if (strcmp (name, "_SDA2_BASE_") == 0)
+    return (strcmp (sname, ".sdata2") == 0
+	    && sym->st_value == destshdr->sh_addr + 0x8000
+	    && sym->st_size == 0);
+
+  return false;
+}
+
+
+/* Check if backend uses a bss PLT in this file.  */
+bool
+ppc_bss_plt_p (Elf *elf)
+{
+  GElf_Addr addr;
+  return ! find_dyn_got (elf, &addr);
+}
diff --git a/backends/riscv64_corenote.c b/backends/riscv64_corenote.c
new file mode 100644
index 0000000..dbcb89d
--- /dev/null
+++ b/backends/riscv64_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "riscv_corenote.c"
diff --git a/backends/riscv_cfi.c b/backends/riscv_cfi.c
new file mode 100644
index 0000000..1c52ea8
--- /dev/null
+++ b/backends/riscv_cfi.c
@@ -0,0 +1,75 @@
+/* RISC-V ABI-specified defaults for DWARF CFI.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND riscv64_
+#include "libebl_CPU.h"
+
+
+int
+riscv_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* The initial Canonical Frame Address is the value of the
+         Stack Pointer (r2) as setup in the previous frame. */
+      DW_CFA_def_cfa, ULEB128_7 (2), ULEB128_7 (0),
+
+      /* The Stack Pointer (r2) is restored from CFA address by default.  */
+      DW_CFA_val_offset, ULEB128_7 (2), ULEB128_7 (0),
+
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* The return address register contains the return address setup by
+	 caller.  */
+      SV (1),
+
+      /* Callee-saved registers s0-s11, fs0-fs11.  */
+      SV(8), SV (9), SV (18), SV (19), SV (20), SV (21),
+      SV (22), SV (23), SV (24), SV (25), SV (26), SV (27),
+
+      SV (40), SV (41),  SV (50),  SV (51), SV (52),  SV (53),
+      SV (54), SV (55),  SV (56),  SV (57), SV (58),  SV (59),
+#undef SV
+
+      /* XXX Note: registers intentionally unused by the program,
+	 for example as a consequence of the procedure call standard
+	 should be initialized as if by DW_CFA_same_value.  */
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = -4;
+
+  abi_info->return_address_register = 1; /* ra.  */
+
+  return 0;
+}
diff --git a/backends/riscv_corenote.c b/backends/riscv_corenote.c
new file mode 100644
index 0000000..416dffc
--- /dev/null
+++ b/backends/riscv_corenote.c
@@ -0,0 +1,88 @@
+/* RISC-V specific core note handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS		32
+# define BACKEND	riscv_
+#else
+# define BITS		64
+# define BACKEND	riscv64_
+#endif
+
+#include "libebl_CPU.h"
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define UID_T			uint16_t
+# define GID_T			uint16_t
+# define ALIGN_ULONG		4
+# define ALIGN_UID_T		2
+# define ALIGN_GID_T		2
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_UID_T		ELF_T_HALF
+# define TYPE_GID_T		ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define UID_T			uint32_t
+# define GID_T			uint32_t
+# define ALIGN_ULONG		8
+# define ALIGN_UID_T		4
+# define ALIGN_GID_T		4
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_UID_T		ELF_T_WORD
+# define TYPE_GID_T		ELF_T_WORD
+#endif
+
+#define PID_T			int32_t
+#define ALIGN_PID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    { .offset = BITS/8, .regno = 1, .count = 31, .bits = BITS } /* x1..x31 */
+  };
+#define PRSTATUS_REGS_SIZE	(32 * (BITS/8))
+
+#define PRSTATUS_REGSET_ITEMS						\
+  {									\
+    .name = "pc", .type = ELF_T_ADDR, .format = 'x',			\
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[0]),		\
+    .group = "register", .pc_register = true				\
+  }
+
+#include "linux-core-note.c"
diff --git a/backends/riscv_init.c b/backends/riscv_init.c
new file mode 100644
index 0000000..f2d4608
--- /dev/null
+++ b/backends/riscv_init.c
@@ -0,0 +1,89 @@
+/* Initialization of RISC-V specific backend library.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		riscv_
+#define RELOC_PREFIX	R_RISCV_
+#include "libebl_CPU.h"
+
+#include "libelfP.h"
+
+/* This defines the common reloc hooks based on riscv_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (EBLHOOK (return_value_location))
+  riscv_return_value_location_lp64d attribute_hidden;
+
+extern __typeof (EBLHOOK (return_value_location))
+    riscv_return_value_location_lp64f attribute_hidden;
+
+extern __typeof (EBLHOOK (return_value_location))
+    riscv_return_value_location_lp64 attribute_hidden;
+
+extern __typeof (EBLHOOK (core_note)) riscv64_core_note attribute_hidden;
+
+Ebl *
+riscv_init (Elf *elf,
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh)
+{
+  /* We handle it.  */
+  riscv_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, register_info);
+  HOOK (eh, abi_cfi);
+  HOOK (eh, disasm);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 66;
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, segment_type_name);
+  HOOK (eh, section_type_name);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  if (eh->class == ELFCLASS64)
+    eh->core_note = riscv64_core_note;
+  else
+    HOOK (eh, core_note);
+  if (eh->class == ELFCLASS64)
+    {
+      if ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
+          == EF_RISCV_FLOAT_ABI_DOUBLE)
+        eh->return_value_location = riscv_return_value_location_lp64d;
+      else if ((elf->state.elf64.ehdr->e_flags & EF_RISCV_FLOAT_ABI)
+               == EF_RISCV_FLOAT_ABI_SINGLE)
+        eh->return_value_location = riscv_return_value_location_lp64f;
+      else
+        eh->return_value_location = riscv_return_value_location_lp64;
+    }
+
+  return eh;
+}
diff --git a/backends/riscv_initreg.c b/backends/riscv_initreg.c
new file mode 100644
index 0000000..e31a4df
--- /dev/null
+++ b/backends/riscv_initreg.c
@@ -0,0 +1,77 @@
+/* Fetch live process registers from TID.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined __riscv && defined __linux__
+# include <sys/uio.h>
+# include <sys/procfs.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND riscv_
+#include "libebl_CPU.h"
+
+bool
+riscv_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+				 ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				 void *arg __attribute__ ((unused)))
+{
+#if !defined __riscv || !defined __linux__
+  return false;
+#else /* __riscv */
+
+  /* General registers.  */
+  elf_gregset_t gregs;
+  struct iovec iovec;
+  iovec.iov_base = &gregs;
+  iovec.iov_len = sizeof (gregs);
+  if (ptrace (PTRACE_GETREGSET, tid, NT_PRSTATUS, &iovec) != 0)
+    return false;
+
+  /* X0 is constant 0.  */
+  Dwarf_Word zero = 0;
+  if (! setfunc (0, 1, &zero, arg))
+    return false;
+
+  /* X1..X31.  */
+  if (! setfunc (1, 32, (Dwarf_Word *) &gregs[1], arg))
+    return false;
+
+  /* PC.  */
+  if (! setfunc (-1, 1, (Dwarf_Word *) &gregs[0], arg))
+    return false;
+
+  /* FP registers not yet supported.  */
+
+  return true;
+#endif /* __riscv */
+}
diff --git a/backends/riscv_regs.c b/backends/riscv_regs.c
new file mode 100644
index 0000000..d5961ad
--- /dev/null
+++ b/backends/riscv_regs.c
@@ -0,0 +1,177 @@
+/* Register names and numbers for RISC-V DWARF.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND riscv_
+#include "libebl_CPU.h"
+
+ssize_t
+riscv_register_info (Ebl *ebl, int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  if (name == NULL)
+    return 64;
+
+  *prefix = "";
+
+  if (regno < 32)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+      *bits = ebl->class == ELFCLASS64 ? 64 : 32;
+    }
+  else
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+      *bits = 64;
+    }
+
+  switch (regno)
+    {
+    case 0:
+      return stpcpy (name, "zero") + 1 - name;
+
+    case 1:
+      *type = DW_ATE_address;
+      return stpcpy (name, "ra") + 1 - name;
+
+    case 2:
+      *type = DW_ATE_address;
+      return stpcpy (name, "sp") + 1 - name;
+
+    case 3:
+      *type = DW_ATE_address;
+      return stpcpy (name, "gp") + 1 - name;
+
+    case 4:
+      *type = DW_ATE_address;
+      return stpcpy (name, "tp") + 1 - name;
+
+    case 5 ... 7:
+      name[0] = 't';
+      name[1] = regno - 5 + '0';
+      namelen = 2;
+      break;
+
+    case 8 ... 9:
+      name[0] = 's';
+      name[1] = regno - 8 + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 17:
+      name[0] = 'a';
+      name[1] = regno - 10 + '0';
+      namelen = 2;
+      break;
+
+    case 18 ... 25:
+      name[0] = 's';
+      name[1] = regno - 18 + '2';
+      namelen = 2;
+      break;
+
+    case 26 ... 27:
+      name[0] = 's';
+      name[1] = '1';
+      name[2] = regno - 26 + '0';
+      namelen = 3;
+      break;
+
+    case 28 ... 31:
+      name[0] = 't';
+      name[1] = regno - 28 + '3';
+      namelen = 2;
+      break;
+
+    case 32 ... 39:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = regno - 32 + '0';
+      namelen = 3;
+      break;
+
+    case 40 ... 41:
+      name[0] = 'f';
+      name[1] = 's';
+      name[2] = regno - 40 + '0';
+      namelen = 3;
+      break;
+
+    case 42 ... 49:
+      name[0] = 'f';
+      name[1] = 'a';
+      name[2] = regno - 42 + '0';
+      namelen = 3;
+      break;
+
+    case 50 ... 57:
+      name[0] = 'f';
+      name[1] = 's';
+      name[2] = regno - 50 + '2';
+      namelen = 3;
+      break;
+
+    case 58 ... 59:
+      name[0] = 'f';
+      name[1] = 's';
+      name[2] = '1';
+      name[3] = regno - 58 + '0';
+      namelen = 4;
+      break;
+
+    case 60 ... 61:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = regno - 60 + '8';
+      namelen = 3;
+      break;
+
+    case 62 ... 63:
+      name[0] = 'f';
+      name[1] = 't';
+      name[2] = '1';
+      name[3] = regno - 62 + '0';
+      namelen = 4;
+      break;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/riscv_reloc.def b/backends/riscv_reloc.def
new file mode 100644
index 0000000..f52f648
--- /dev/null
+++ b/backends/riscv_reloc.def
@@ -0,0 +1,87 @@
+/* List the relocation types for RISC-V.  -*- C -*-
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		EXEC|DYN)
+RELOC_TYPE (32,			REL|EXEC|DYN)
+RELOC_TYPE (64,			REL|EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPMOD64,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL32,	EXEC|DYN)
+RELOC_TYPE (TLS_DTPREL64,	EXEC|DYN)
+RELOC_TYPE (TLS_TPREL32,	EXEC|DYN)
+RELOC_TYPE (TLS_TPREL64,	EXEC|DYN)
+RELOC_TYPE (BRANCH,		REL)
+RELOC_TYPE (JAL,		REL)
+RELOC_TYPE (CALL,		REL)
+RELOC_TYPE (CALL_PLT,		REL)
+RELOC_TYPE (GOT_HI20,		REL)
+RELOC_TYPE (TLS_GOT_HI20,	REL)
+RELOC_TYPE (TLS_GD_HI20,	REL)
+RELOC_TYPE (PCREL_HI20,		REL)
+RELOC_TYPE (PCREL_LO12_I,	REL)
+RELOC_TYPE (PCREL_LO12_S,	REL)
+RELOC_TYPE (HI20,		REL)
+RELOC_TYPE (LO12_I,		REL)
+RELOC_TYPE (LO12_S,		REL)
+RELOC_TYPE (TPREL_HI20,		REL)
+RELOC_TYPE (TPREL_LO12_I,	REL)
+RELOC_TYPE (TPREL_LO12_S,	REL)
+RELOC_TYPE (TPREL_ADD,		REL)
+RELOC_TYPE (ADD8,		REL)
+RELOC_TYPE (ADD16,		REL)
+RELOC_TYPE (ADD32,		REL)
+RELOC_TYPE (ADD64,		REL)
+RELOC_TYPE (SUB8,		REL)
+RELOC_TYPE (SUB16,		REL)
+RELOC_TYPE (SUB32,		REL)
+RELOC_TYPE (SUB64,		REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (ALIGN,		REL)
+RELOC_TYPE (RVC_BRANCH,		REL)
+RELOC_TYPE (RVC_JUMP,		REL)
+RELOC_TYPE (RVC_LUI,		REL)
+RELOC_TYPE (GPREL_I,		REL)
+RELOC_TYPE (GPREL_S,		REL)
+RELOC_TYPE (TPREL_I,		REL)
+RELOC_TYPE (TPREL_S,		REL)
+RELOC_TYPE (RELAX,		REL)
+RELOC_TYPE (SUB6,		REL)
+RELOC_TYPE (SET6,		REL)
+RELOC_TYPE (SET8,		REL)
+RELOC_TYPE (SET16,		REL)
+RELOC_TYPE (SET32,		REL)
+RELOC_TYPE (32_PCREL,		REL)
+RELOC_TYPE (IRELATIVE,		EXEC|DYN)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (SET_ULEB128,	REL)
+RELOC_TYPE (SUB_ULEB128,	REL)
diff --git a/backends/riscv_retval.c b/backends/riscv_retval.c
new file mode 100644
index 0000000..0a1e02f
--- /dev/null
+++ b/backends/riscv_retval.c
@@ -0,0 +1,312 @@
+/* Function return value location for Linux/RISC-V ABI.
+   Copyright (C) 2018 Sifive, Inc.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND riscv_
+#include "libebl_CPU.h"
+
+static int
+dwarf_bytesize_aux (Dwarf_Die *die, Dwarf_Word *sizep)
+{
+  int bits;
+  if (((bits = 8 * dwarf_bytesize (die)) < 0
+       && (bits = dwarf_bitsize (die)) < 0)
+      || bits % 8 != 0)
+    return -1;
+
+  *sizep = bits / 8;
+  return 0;
+}
+
+static int
+pass_in_gpr_lp64 (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_reg10 }, { .atom = DW_OP_piece, .number = 8 },
+      { .atom = DW_OP_reg11 }, { .atom = DW_OP_piece, .number = 8 }
+    };
+
+  *locp = loc;
+  return size <= 8 ? 1 : 4;
+}
+
+static int
+pass_by_ref (const Dwarf_Op **locp)
+{
+  static const Dwarf_Op loc[] = { { .atom = DW_OP_breg10 } };
+
+  *locp = loc;
+  return 1;
+}
+
+static int
+pass_in_fpr_lp64f (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_regx, .number = 42 },
+      { .atom = DW_OP_piece, .number = 4 },
+      { .atom = DW_OP_regx, .number = 43 },
+      { .atom = DW_OP_piece, .number = 4 }
+    };
+
+  *locp = loc;
+  return size <= 4 ? 1 : 4;
+}
+
+static int
+pass_in_fpr_lp64d (const Dwarf_Op **locp, Dwarf_Word size)
+{
+  static const Dwarf_Op loc[] =
+    {
+      { .atom = DW_OP_regx, .number = 42 },
+      { .atom = DW_OP_piece, .number = 8 },
+      { .atom = DW_OP_regx, .number = 43 },
+      { .atom = DW_OP_piece, .number = 8 }
+    };
+
+  *locp = loc;
+  return size <= 8 ? 1 : 4;
+}
+
+static int
+flatten_aggregate_arg (Dwarf_Die *typedie __attribute__ ((unused)),
+		       Dwarf_Die *arg0 __attribute__ ((unused)),
+		       Dwarf_Die *arg1 __attribute__ ((unused)))
+{
+  /* ??? */
+  return 1;
+}
+
+static int
+pass_by_flattened_arg (const Dwarf_Op **locp __attribute__ ((unused)),
+		       Dwarf_Word size __attribute__ ((unused)),
+		       Dwarf_Die *arg0 __attribute__ ((unused)),
+		       Dwarf_Die *arg1 __attribute__ ((unused)))
+{
+  /* ??? */
+  return -2;
+}
+
+int
+riscv_return_value_location_lp64ifd (int fp, Dwarf_Die *functypedie,
+                                     const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die typedie;
+  int tag = dwarf_peeled_die_type (functypedie, &typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size = (Dwarf_Word)-1;
+
+  /* If the argument type is a Composite Type that is larger than 16
+     bytes, then the argument is copied to memory allocated by the
+     caller and the argument is replaced by a pointer to the copy.  */
+  if (tag == DW_TAG_structure_type || tag == DW_TAG_union_type
+      || tag == DW_TAG_class_type || tag == DW_TAG_array_type)
+    {
+      Dwarf_Die arg0, arg1;
+
+      if (dwarf_aggregate_size (&typedie, &size) < 0)
+	return -1;
+      /* A struct containing just one floating-point real is passed as though
+	 it were a standalone floating-point real.  A struct containing two
+	 floating-point reals is passed in two floating-point registers, if
+	 neither is more than FLEN bits wide.  A struct containing just one
+	 complex floating-point number is passed as though it were a struct
+	 containing two floating-point reals.  A struct containing one
+	 floating-point real and one integer (or bitfield), in either order,
+	 is passed in a floating-point register and an integer register,
+	 provided the floating-point real is no more than FLEN bits wide and
+	 the integer is no more than XLEN bits wide.  */
+      if (tag == DW_TAG_structure_type
+	  && flatten_aggregate_arg (&typedie, &arg0, &arg1))
+	return pass_by_flattened_arg (locp, size, &arg0, &arg1);
+      /* Aggregates larger than 2*XLEN bits are passed by reference.  */
+      else if (size > 16)
+	return pass_by_ref (locp);
+      /* Aggregates whose total size is no more than XLEN bits are passed in
+	 a register.  Aggregates whose total size is no more than 2*XLEN bits
+	 are passed in a pair of registers.  */
+      else
+	return pass_in_gpr_lp64 (locp, size);
+    }
+
+  if (tag == DW_TAG_base_type || dwarf_is_pointer (tag))
+    {
+      if (dwarf_bytesize_aux (&typedie, &size) < 0)
+	{
+	  if (dwarf_is_pointer (tag))
+	    size = 8;
+	  else
+	    return -1;
+	}
+
+      Dwarf_Attribute attr_mem;
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (&typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	    case DW_ATE_boolean:
+	    case DW_ATE_signed:
+	    case DW_ATE_unsigned:
+	    case DW_ATE_unsigned_char:
+	    case DW_ATE_signed_char:
+	      /* Scalars that are at most XLEN bits wide are passed in a single
+		 argument register.  Scalars that are 2*XLEN bits wide are
+		 passed in a pair of argument registers.  Scalars wider than
+		 2*XLEN are passed by reference; there are none for LP64D.  */
+	      return pass_in_gpr_lp64 (locp, size);
+
+	    case DW_ATE_float:
+	      /* A real floating-point argument is passed in a floating-point
+		 argument register if it is no more than FLEN bits wide,
+		 otherwise it is passed according to the integer calling
+		 convention.  */
+	      switch (size)
+		{
+		case 4: /* single */
+                  switch (fp)
+                    {
+                    case EF_RISCV_FLOAT_ABI_DOUBLE:
+                    case EF_RISCV_FLOAT_ABI_SINGLE:
+                      return pass_in_fpr_lp64d (locp, size);
+                    case EF_RISCV_FLOAT_ABI_SOFT:
+                      return pass_in_gpr_lp64 (locp, size);
+                    default:
+                      return -2;
+                    }
+                case 8: /* double */
+                  switch (fp)
+                    {
+                    case EF_RISCV_FLOAT_ABI_DOUBLE:
+                      return pass_in_fpr_lp64d (locp, size);
+                    case EF_RISCV_FLOAT_ABI_SINGLE:
+                    case EF_RISCV_FLOAT_ABI_SOFT:
+                      return pass_in_gpr_lp64 (locp, size);
+                    default:
+                      return -2;
+                    }
+
+                case 16: /* quad */
+		  return pass_in_gpr_lp64 (locp, size);
+
+		default:
+		  return -2;
+		}
+
+	    case DW_ATE_complex_float:
+	      /* A complex floating-point number is passed as though it were a
+		 struct containing two floating-point reals.  */
+	      switch (size)
+		{
+		case 8: /* float _Complex */
+                  switch (fp)
+                    {
+                    case EF_RISCV_FLOAT_ABI_DOUBLE:
+                    case EF_RISCV_FLOAT_ABI_SINGLE:
+                      return pass_in_fpr_lp64f (locp, size);
+                    case EF_RISCV_FLOAT_ABI_SOFT:
+                      /* Double the size so the vals are two registers. */
+                      return pass_in_gpr_lp64 (locp, size * 2);
+                    default:
+                      return -2;
+                    }
+
+                case 16: /* double _Complex */
+                  switch (fp)
+                    {
+                    case EF_RISCV_FLOAT_ABI_DOUBLE:
+                      return pass_in_fpr_lp64d (locp, size);
+                    case EF_RISCV_FLOAT_ABI_SINGLE:
+                    case EF_RISCV_FLOAT_ABI_SOFT:
+                      return pass_in_gpr_lp64 (locp, size);
+                    default:
+                      return -2;
+                    }
+
+                case 32: /* long double _Complex */
+		  return pass_by_ref (locp);
+
+		default:
+		  return -2;
+		}
+	    }
+
+	  return -2;
+	}
+      else
+	return pass_in_gpr_lp64 (locp, size);
+    }
+
+  *locp = NULL;
+  return 0;
+}
+
+int
+riscv_return_value_location_lp64d (Dwarf_Die *functypedie,
+                                   const Dwarf_Op **locp)
+{
+  return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_DOUBLE,
+                                              functypedie, locp);
+}
+
+int
+riscv_return_value_location_lp64f (Dwarf_Die *functypedie,
+                                   const Dwarf_Op **locp)
+{
+  return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_SINGLE,
+                                              functypedie, locp);
+}
+
+int
+riscv_return_value_location_lp64 (Dwarf_Die *functypedie,
+                                  const Dwarf_Op **locp)
+{
+  return riscv_return_value_location_lp64ifd (EF_RISCV_FLOAT_ABI_SOFT,
+                                              functypedie, locp);
+}
diff --git a/backends/riscv_symbol.c b/backends/riscv_symbol.c
new file mode 100644
index 0000000..c149b8b
--- /dev/null
+++ b/backends/riscv_symbol.c
@@ -0,0 +1,166 @@
+/* RISC-V specific symbolic name handling.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND riscv_
+#include "libebl_CPU.h"
+
+
+/* Check for the simple reloc types.  */
+Elf_Type
+riscv_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			 int *addsub)
+{
+  switch (type)
+    {
+    case R_RISCV_SET8:
+      return ELF_T_BYTE;
+    case R_RISCV_SET16:
+      return ELF_T_HALF;
+    case R_RISCV_32:
+    case R_RISCV_SET32:
+      return ELF_T_WORD;
+    case R_RISCV_64:
+      return ELF_T_XWORD;
+    case R_RISCV_ADD16:
+      *addsub = 1;
+      return ELF_T_HALF;
+    case R_RISCV_SUB16:
+      *addsub = -1;
+      return ELF_T_HALF;
+    case R_RISCV_ADD32:
+      *addsub = 1;
+      return ELF_T_WORD;
+    case R_RISCV_SUB32:
+      *addsub = -1;
+      return ELF_T_WORD;
+    case R_RISCV_ADD64:
+      *addsub = 1;
+      return ELF_T_XWORD;
+    case R_RISCV_SUB64:
+      *addsub = -1;
+      return ELF_T_XWORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check whether machine flags are valid.  */
+bool
+riscv_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ (EF_RISCV_RVC
+		     | EF_RISCV_FLOAT_ABI)) == 0);
+}
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+bool
+riscv_check_special_symbol (Elf *elf, const GElf_Sym *sym,
+			    const char *name, const GElf_Shdr *destshdr)
+{
+  if (name == NULL)
+    return false;
+
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+    return false;
+  const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
+  if (sname == NULL)
+    return false;
+
+  /* _GLOBAL_OFFSET_TABLE_ points to the start of the .got section, but it
+     is preceded by the .got.plt section in the output .got section.  */
+  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    return (strcmp (sname, ".got") == 0
+	    && sym->st_value >= destshdr->sh_addr
+	    && sym->st_value < destshdr->sh_addr + destshdr->sh_size);
+
+  /* __global_pointer$ points to the .sdata section with an offset of
+     0x800.  It might however fall in the .got section, in which case we
+     cannot check the offset.  The size always should be zero.  */
+  if (strcmp (name, "__global_pointer$") == 0)
+    return (((strcmp (sname, ".sdata") == 0
+	      && sym->st_value == destshdr->sh_addr + 0x800)
+	     || strcmp (sname, ".got") == 0)
+	    && sym->st_size == 0);
+
+  return false;
+}
+
+const char *
+riscv_segment_type_name (int segment, char *buf __attribute__ ((unused)),
+			 size_t len __attribute__ ((unused)))
+{
+  switch (segment)
+    {
+    case PT_RISCV_ATTRIBUTES:
+      return "RISCV_ATTRIBUTES";
+    }
+  return NULL;
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+riscv_section_type_name (int type,
+			 char *buf __attribute__ ((unused)),
+			 size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case SHT_RISCV_ATTRIBUTES:
+      return "RISCV_ATTRIBUTES";
+    }
+
+  return NULL;
+}
+
+const char *
+riscv_dynamic_tag_name (int64_t tag, char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_RISCV_VARIANT_CC:
+      return "RISCV_VARIANT_CC";
+    }
+  return NULL;
+}
+
+bool
+riscv_dynamic_tag_check (int64_t tag)
+{
+  return tag == DT_RISCV_VARIANT_CC;
+}
diff --git a/backends/s390_cfi.c b/backends/s390_cfi.c
new file mode 100644
index 0000000..cb49486
--- /dev/null
+++ b/backends/s390_cfi.c
@@ -0,0 +1,65 @@
+/* s390 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2012, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+int
+s390_abi_cfi (Ebl *ebl, Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* This instruction is provided in every CIE.  It is not repeated here:
+	 DW_CFA_def_cfa, ULEB128_7 (15), ULEB128_7 (96)  */
+      /* r14 is not callee-saved but it needs to be preserved as it is pre-set
+	 by the caller.  */
+      DW_CFA_same_value, ULEB128_7 (14), /* r14 */
+
+      /* Callee-saved regs.  */
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      SV (6), SV (7), SV (8), SV (9), SV (10),		       /* r6-r13, r15 */
+      SV (11), SV (12), SV (13), SV (15),
+      SV (16 + 8), SV (16 + 9), SV (16 + 10), SV (16 + 11),    /* f8-f15 */
+      SV (16 + 12), SV (16 + 13), SV (16 + 14), SV (16 + 15)
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = ebl->class == ELFCLASS64 ? 8 : 4;
+
+  abi_info->return_address_register = 14;
+
+  return 0;
+}
diff --git a/backends/s390_corenote.c b/backends/s390_corenote.c
new file mode 100644
index 0000000..7ca3516
--- /dev/null
+++ b/backends/s390_corenote.c
@@ -0,0 +1,189 @@
+/* S390-specific core note handling.
+   Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		32
+# define BACKEND	s390_
+#else
+# define BITS 		64
+# define BACKEND	s390x_
+#endif
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg, b...)						\
+    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = b }
+
+    GR ( 0,  1, 64, BITS),				/* pswm */
+    GR ( 1,  1, 65, BITS, .pc_register = true ),	/* pswa */
+    GR ( 2, 16,  0, BITS),				/* r0-r15 */
+    GR (18, 16, 48,   32),				/* ar0-ar15 */
+
+#undef	GR
+  };
+
+  /* orig_r2 is at offset (BITS == 32 ? 34 * 4 : 26 * 8).  */
+#define PRSTATUS_REGS_SIZE	(BITS / 8 * (BITS == 32 ? 35 : 27))
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+#define FPR(at, n, dwreg)						\
+    { .offset = at * 64/8, .regno = dwreg, .count = n, .bits = 64 }
+
+    /* fpc is at offset 0, see fpregset_items, it has no assigned DWARF regno.
+       Bytes at offsets 4 to 7 are unused.  */
+    FPR (1 +  0, 1, 16),	/* f0 */
+    FPR (1 +  1, 1, 20),	/* f1 */
+    FPR (1 +  2, 1, 17),	/* f2 */
+    FPR (1 +  3, 1, 21),	/* f3 */
+    FPR (1 +  4, 1, 18),	/* f4 */
+    FPR (1 +  5, 1, 22),	/* f5 */
+    FPR (1 +  6, 1, 19),	/* f6 */
+    FPR (1 +  7, 1, 23),	/* f7 */
+    FPR (1 +  8, 1, 24),	/* f8 */
+    FPR (1 +  9, 1, 28),	/* f9 */
+    FPR (1 + 10, 1, 25),	/* f10 */
+    FPR (1 + 11, 1, 29),	/* f11 */
+    FPR (1 + 12, 1, 26),	/* f12 */
+    FPR (1 + 13, 1, 30),	/* f13 */
+    FPR (1 + 14, 1, 27),	/* f14 */
+    FPR (1 + 15, 1, 31),	/* f15 */
+
+#undef	FPR
+  };
+
+static const Ebl_Core_Item fpregset_items[] =
+  {
+    {
+      .name = "fpc", .group = "register", .offset = 0, .type = ELF_T_WORD,
+      .format = 'x',
+    },
+  };
+
+/* Do not set FPREGSET_SIZE so that we can supply fpregset_items.  */
+#define EXTRA_NOTES_FPREGSET \
+    EXTRA_REGSET_ITEMS (NT_FPREGSET, 17 * 8, fpregset_regs, fpregset_items)
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_LONG		ELF_T_SWORD
+# define UID_T			uint16_t
+# define GID_T			uint16_t
+# define ALIGN_UID_T		2
+# define ALIGN_GID_T		2
+# define TYPE_UID_T		ELF_T_HALF
+# define TYPE_GID_T		ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_LONG		ELF_T_SXWORD
+# define UID_T			uint32_t
+# define GID_T			uint32_t
+# define ALIGN_UID_T		4
+# define ALIGN_GID_T		4
+# define TYPE_UID_T		ELF_T_WORD
+# define TYPE_GID_T		ELF_T_WORD
+#endif
+#define PID_T			int32_t
+#define ALIGN_PID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+/* s390 psw_compat_t has alignment 8 bytes where it is inherited from.  */
+#define ALIGN_PR_REG		8
+
+#define PRSTATUS_REGSET_ITEMS					\
+  {								\
+    .name = "orig_r2", .type = TYPE_LONG, .format = 'd',	\
+    .offset = offsetof (struct EBLHOOK(prstatus),		\
+			pr_reg[BITS == 32 ? 34 : 26]),		\
+    .group = "register"						\
+  }
+
+#if BITS == 32
+
+static const Ebl_Core_Item high_regs_items[] =
+  {
+#define HR(n)								\
+    {									\
+      .name = "high_r" #n , .group = "register", .offset = (n) * 4,	\
+      .type = ELF_T_WORD, .format = 'x',				\
+    }
+
+    /* Upper halves of r0-r15 are stored here.
+       FIXME: They are currently not combined with the r0-r15 lower halves.  */
+    HR (0), HR (1), HR (2), HR (3), HR (4), HR (5), HR (6), HR (7),
+    HR (8), HR (9), HR (10), HR (11), HR (12), HR (13), HR (14), HR (15)
+
+#undef HR
+  };
+
+#define EXTRA_NOTES_HIGH_GPRS \
+  EXTRA_ITEMS (NT_S390_HIGH_GPRS, 16 * 4, high_regs_items)
+
+#else /* BITS == 64 */
+
+#define EXTRA_NOTES_HIGH_GPRS
+
+#endif /* BITS == 64 */
+
+static const Ebl_Core_Item last_break_items[] =
+  {
+    {
+      .name = "last_break", .group = "system", .offset = BITS == 32 ? 4 : 0,
+      .type = BITS == 32 ? ELF_T_WORD : ELF_T_XWORD, .format = 'x',
+    },
+  };
+
+static const Ebl_Core_Item system_call_items[] =
+  {
+    {
+      .name = "system_call", .group = "system", .offset = 0, .type = ELF_T_WORD,
+      .format = 'd',
+    },
+  };
+
+#define	EXTRA_NOTES							  \
+  EXTRA_NOTES_FPREGSET							  \
+  EXTRA_NOTES_HIGH_GPRS							  \
+  EXTRA_ITEMS (NT_S390_LAST_BREAK, 8, last_break_items)	  \
+  EXTRA_ITEMS (NT_S390_SYSTEM_CALL, 4, system_call_items)
+
+#include "linux-core-note.c"
diff --git a/backends/s390_init.c b/backends/s390_init.c
new file mode 100644
index 0000000..fd79502
--- /dev/null
+++ b/backends/s390_init.c
@@ -0,0 +1,74 @@
+/* Initialization of S/390 specific backend library.
+   Copyright (C) 2005, 2006, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		s390_
+#define RELOC_PREFIX	R_390_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on arm_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (s390_core_note) s390x_core_note;
+
+
+Ebl *
+s390_init (Elf *elf __attribute__ ((unused)),
+	   GElf_Half machine __attribute__ ((unused)),
+	   Ebl *eh)
+{
+  /* We handle it.  */
+  s390_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, check_special_symbol);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+  if (eh->class == ELFCLASS64)
+    eh->core_note = s390x_core_note;
+  else
+    HOOK (eh, core_note);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS 34.
+     But from the gcc/config/s390/s390.h "Register usage." comment it looks as
+     if #32 (Argument pointer) and #33 (Condition code) are not used for
+     unwinding.  */
+  eh->frame_nregs = 32;
+  HOOK (eh, set_initial_registers_tid);
+  if (eh->class == ELFCLASS32)
+    HOOK (eh, normalize_pc);
+  HOOK (eh, unwind);
+
+  /* Only the 64-bit format uses the incorrect hash table entry size.  */
+  if (eh->class == ELFCLASS64)
+    eh->sysvhash_entrysize = sizeof (Elf64_Xword);
+
+  return eh;
+}
diff --git a/backends/s390_initreg.c b/backends/s390_initreg.c
new file mode 100644
index 0000000..23bf8ed
--- /dev/null
+++ b/backends/s390_initreg.c
@@ -0,0 +1,95 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <assert.h>
+#if defined(__s390__) && defined(__linux__)
+# include <sys/user.h>
+# include <sys/ptrace.h>
+# include <asm/ptrace.h>
+#endif
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+bool
+s390_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				void *arg __attribute__ ((unused)))
+{
+#if !defined(__s390__) || !defined(__linux__)
+  return false;
+#else /* __s390__ */
+  struct user user_regs;
+  ptrace_area parea;
+  parea.process_addr = (uintptr_t) &user_regs;
+  parea.kernel_addr = 0;
+  parea.len = sizeof (user_regs);
+  if (ptrace (PTRACE_PEEKUSR_AREA, tid, &parea, NULL) != 0)
+    return false;
+  /* If we run as s390x we get the 64-bit registers of tid.
+     But -m31 executable seems to use only the 32-bit parts of its
+     registers so we ignore the upper half.  */
+  Dwarf_Word dwarf_regs[16];
+  for (unsigned u = 0; u < 16; u++)
+    dwarf_regs[u] = user_regs.regs.gprs[u];
+  if (! setfunc (0, 16, dwarf_regs, arg))
+    return false;
+  /* Avoid conversion double -> integer.  */
+  eu_static_assert (sizeof user_regs.regs.fp_regs.fprs[0]
+		    == sizeof dwarf_regs[0]);
+  for (unsigned u = 0; u < 16; u++)
+    {
+      // Store the double bits as is in the Dwarf_Word without conversion.
+      union
+	{
+	  double d;
+	  Dwarf_Word w;
+	} fpr = { .d = user_regs.regs.fp_regs.fprs[u] };
+      dwarf_regs[u] = fpr.w;
+    }
+
+  if (! setfunc (16, 16, dwarf_regs, arg))
+    return false;
+  dwarf_regs[0] = user_regs.regs.psw.addr;
+  return setfunc (-1, 1, dwarf_regs, arg);
+#endif /* __s390__ */
+}
+
+void
+s390_normalize_pc (Ebl *ebl __attribute__ ((unused)), Dwarf_Addr *pc)
+{
+  assert (ebl->class == ELFCLASS32);
+
+  /* Clear S390 bit 31.  */
+  *pc &= (1U << 31) - 1;
+}
diff --git a/backends/s390_regs.c b/backends/s390_regs.c
new file mode 100644
index 0000000..ba6178a
--- /dev/null
+++ b/backends/s390_regs.c
@@ -0,0 +1,146 @@
+/* Register names and numbers for S/390 DWARF.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+
+/*
+zseries (64)
+
+0-15	gpr0-gpr15	x
+16-19	fpr[0246]
+20-24	fpr[13578]
+25-27	fpr1[024]
+28	fpr9
+29-31	fpr1[135]
+32-47	cr0-cr15	x
+48-63	ar0-ar15	x
+64	psw_mask
+65	psw_address
+*/
+
+
+ssize_t
+s390_register_info (Ebl *ebl __attribute__ ((unused)),
+		    int regno, char *name, size_t namelen,
+		    const char **prefix, const char **setname,
+		    int *bits, int *type)
+{
+  if (name == NULL)
+    return 66;
+
+  if (regno < 0 || regno > 65 || namelen < 7)
+    return -1;
+
+  *prefix = "%";
+
+  *bits = ebl->class == ELFCLASS64 ? 64 : 32;
+  *type = DW_ATE_unsigned;
+  if (regno < 16)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+    }
+  else if (regno < 32)
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+      *bits = 64;
+    }
+  else if (regno < 48 || regno > 63)
+    *setname = "control";
+  else
+    {
+      *setname = "access";
+      *bits = 32;
+    }
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16 ... 31:
+      name[0] = 'f';
+      regno = (regno & 8) | ((regno & 4) >> 2) | ((regno & 3) << 1);
+      namelen = 1;
+      if (regno >= 10)
+	{
+	  regno -= 10;
+	  name[namelen++] = '1';
+	}
+      name[namelen++] = regno + '0';
+      break;
+
+    case 32 + 0 ... 32 + 9:
+    case 48 + 0 ... 48 + 9:
+      name[0] = regno < 48 ? 'c' : 'a';
+      name[1] = (regno & 15) + '0';
+      namelen = 2;
+      break;
+
+    case 32 + 10 ... 32 + 15:
+    case 48 + 10 ... 48 + 15:
+      name[0] = regno < 48 ? 'c' : 'a';
+      name[1] = '1';
+      name[2] = (regno & 15) - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 64:
+      return stpcpy (name, "pswm") + 1 - name;
+    case 65:
+      *type = DW_ATE_address;
+      return stpcpy (name, "pswa") + 1 - name;
+
+    default:
+      *setname = NULL;
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/s390_reloc.def b/backends/s390_reloc.def
new file mode 100644
index 0000000..cdef9eb
--- /dev/null
+++ b/backends/s390_reloc.def
@@ -0,0 +1,91 @@
+/* List the relocation types for s390.  -*- C -*-
+   Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* 	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,               0)
+RELOC_TYPE (8,                  REL|EXEC|DYN)
+RELOC_TYPE (12,                 REL|EXEC|DYN)
+RELOC_TYPE (16,                 REL|EXEC|DYN)
+RELOC_TYPE (32,                 REL|EXEC|DYN)
+RELOC_TYPE (PC32,               REL|EXEC|DYN)
+RELOC_TYPE (GOT12,              REL)
+RELOC_TYPE (GOT32,              REL)
+RELOC_TYPE (PLT32,              REL)
+RELOC_TYPE (COPY,               EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,           EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,           EXEC|DYN)
+RELOC_TYPE (RELATIVE,           EXEC|DYN)
+RELOC_TYPE (GOTOFF32,           REL)
+RELOC_TYPE (GOTPC,              REL)
+RELOC_TYPE (GOT16,              REL)
+RELOC_TYPE (PC16,               REL|EXEC|DYN)
+RELOC_TYPE (PC16DBL,            REL|EXEC|DYN)
+RELOC_TYPE (PLT16DBL,           REL)
+RELOC_TYPE (PC32DBL,            REL|EXEC|DYN)
+RELOC_TYPE (PLT32DBL,           REL)
+RELOC_TYPE (GOTPCDBL,           REL)
+RELOC_TYPE (64,                 REL|EXEC|DYN)
+RELOC_TYPE (PC64,               REL|EXEC|DYN)
+RELOC_TYPE (GOT64,              REL)
+RELOC_TYPE (PLT64,              REL)
+RELOC_TYPE (GOTENT,             REL)
+RELOC_TYPE (GOTOFF16,           REL)
+RELOC_TYPE (GOTOFF64,           REL)
+RELOC_TYPE (GOTPLT12,           REL)
+RELOC_TYPE (GOTPLT16,           REL)
+RELOC_TYPE (GOTPLT32,           REL)
+RELOC_TYPE (GOTPLT64,           REL)
+RELOC_TYPE (GOTPLTENT,          REL)
+RELOC_TYPE (PLTOFF16,           REL)
+RELOC_TYPE (PLTOFF32,           REL)
+RELOC_TYPE (PLTOFF64,           REL)
+RELOC_TYPE (TLS_LOAD,           REL)
+RELOC_TYPE (TLS_GDCALL,         REL)
+RELOC_TYPE (TLS_LDCALL,         REL)
+RELOC_TYPE (TLS_GD32,           REL)
+RELOC_TYPE (TLS_GD64,           REL)
+RELOC_TYPE (TLS_GOTIE12,        REL)
+RELOC_TYPE (TLS_GOTIE32,        REL)
+RELOC_TYPE (TLS_GOTIE64,        REL)
+RELOC_TYPE (TLS_LDM32,          REL)
+RELOC_TYPE (TLS_LDM64,          REL)
+RELOC_TYPE (TLS_IE32,           REL)
+RELOC_TYPE (TLS_IE64,           REL)
+RELOC_TYPE (TLS_IEENT,          REL)
+RELOC_TYPE (TLS_LE32,           REL)
+RELOC_TYPE (TLS_LE64,           REL)
+RELOC_TYPE (TLS_LDO32,          REL)
+RELOC_TYPE (TLS_LDO64,          REL)
+RELOC_TYPE (TLS_DTPMOD,         DYN)
+RELOC_TYPE (TLS_DTPOFF,         DYN)
+RELOC_TYPE (TLS_TPOFF,          DYN)
+RELOC_TYPE (20,                 REL|EXEC|DYN)
+RELOC_TYPE (GOT20,              REL)
+RELOC_TYPE (GOTPLT20,           REL)
+RELOC_TYPE (TLS_GOTIE20,        REL)
diff --git a/backends/s390_retval.c b/backends/s390_retval.c
new file mode 100644
index 0000000..0a01d27
--- /dev/null
+++ b/backends/s390_retval.c
@@ -0,0 +1,143 @@
+/* Function return value location for S/390 ABI.
+   Copyright (C) 2006, 2007, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+
+/* %r2, or pair %r2, %r3.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg2 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg3 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %f0.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg16 },
+  };
+#define nloc_fpreg	1
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %r2.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg2, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+s390_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Die cudie;
+	uint8_t asize;
+	if (dwarf_diecu (typedie, &cudie, &asize, NULL) == NULL)
+	  return -1;
+
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr (typedie, DW_AT_byte_size,
+					 &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = asize;
+	    else
+	      return -1;
+	  }
+	if (tag == DW_TAG_base_type)
+	  {
+	    Dwarf_Word encoding;
+	    if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						       &attr_mem),
+				 &encoding) != 0)
+	      return -1;
+	    if (encoding == DW_ATE_float && size <= 8)
+	      {
+		*locp = loc_fpreg;
+		return nloc_fpreg;
+	      }
+	  }
+	if (size <= 8)
+	  {
+	    *locp = loc_intreg;
+	    return size <= asize ? nloc_intreg : nloc_intregpair;
+	  }
+      }
+      FALLTHROUGH;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/s390_symbol.c b/backends/s390_symbol.c
new file mode 100644
index 0000000..9e80eca
--- /dev/null
+++ b/backends/s390_symbol.c
@@ -0,0 +1,95 @@
+/* S/390-specific symbolic name handling.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+#include <string.h>
+
+#define BACKEND		s390_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+s390_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_390_64:
+      return ELF_T_SXWORD;
+    case R_390_32:
+      return ELF_T_SWORD;
+    case R_390_16:
+      return ELF_T_HALF;
+    case R_390_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* The _GLOBAL_OFFSET_TABLE_ symbol might point to the DT_PLTGOT,
+   which is in the .got section, even if the symbol itself is
+   associated with the is a .got.plt section.
+   https://sourceware.org/ml/binutils/2018-07/msg00200.html  */
+bool
+s390_check_special_symbol (Elf *elf, const GElf_Sym *sym,
+                              const char *name, const GElf_Shdr *destshdr)
+{
+  if (name != NULL
+      && strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+    {
+      size_t shstrndx;
+      if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+	return false;
+      const char *sname = elf_strptr (elf, shstrndx, destshdr->sh_name);
+      if (sname != NULL
+	  && (strcmp (sname, ".got") == 0 || strcmp (sname, ".got.plt") == 0))
+	{
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  sname = elf_strptr (elf, shstrndx, shdr->sh_name);
+		  if (sname != NULL && strcmp (sname, ".got") == 0)
+		    return (sym->st_value >= shdr->sh_addr
+			    && sym->st_value < shdr->sh_addr + shdr->sh_size);
+		}
+	    }
+	}
+    }
+
+  return false;
+}
diff --git a/backends/s390_unwind.c b/backends/s390_unwind.c
new file mode 100644
index 0000000..752bc28
--- /dev/null
+++ b/backends/s390_unwind.c
@@ -0,0 +1,139 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define BACKEND s390_
+#include "libebl_CPU.h"
+
+/* s390/s390x do not annotate signal handler frame by CFI.  It would be also
+   difficult as PC points into a stub built on stack.  Function below is called
+   only if unwinder could not find CFI.  Function then verifies the register
+   state for this frame really belongs to a signal frame.  In such case it
+   fetches original registers saved by the signal frame.  */
+
+bool
+s390_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+	     ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
+	     void *arg, bool *signal_framep)
+{
+  /* Caller already assumed caller adjustment but S390 instructions are 4 bytes
+     long.  Undo it.  */
+  if ((pc & 0x3) != 0x3)
+    return false;
+  pc++;
+  /* We can assume big-endian read here.  */
+  Dwarf_Word instr;
+  if (! readfunc (pc, &instr, arg))
+    return false;
+  /* Fetch only the very first two bytes.  */
+  instr = (instr >> (ebl->class == ELFCLASS64 ? 48 : 16)) & 0xffff;
+  /* See GDB s390_sigtramp_frame_sniffer.  */
+  /* Check for 'svc' as the first instruction.  */
+  if (((instr >> 8) & 0xff) != 0x0a)
+    return false;
+  /* Check for 'sigreturn' or 'rt_sigreturn' as the second instruction.  */
+  if ((instr & 0xff) != 119 && (instr & 0xff) != 173)
+    return false;
+  /* See GDB s390_sigtramp_frame_unwind_cache.  */
+  Dwarf_Word this_sp;
+  if (! getfunc (0 + 15, 1, &this_sp, arg))
+    return false;
+  unsigned word_size = ebl->class == ELFCLASS64 ? 8 : 4;
+  Dwarf_Addr next_cfa = this_sp + 16 * word_size + 32;
+  /* "New-style RT frame" is not supported,
+     assuming "Old-style RT frame and all non-RT frames".
+     Pointer to the array of saved registers is at NEXT_CFA + 8.  */
+  Dwarf_Word sigreg_ptr;
+  if (! readfunc (next_cfa + 8, &sigreg_ptr, arg))
+    return false;
+  /* Skip PSW mask.  */
+  sigreg_ptr += word_size;
+  /* Read PSW address.  */
+  Dwarf_Word val;
+  if (! readfunc (sigreg_ptr, &val, arg))
+    return false;
+  if (! setfunc (-1, 1, &val, arg))
+    return false;
+  sigreg_ptr += word_size;
+  /* Then the GPRs.  */
+  Dwarf_Word gprs[16];
+  for (int i = 0; i < 16; i++)
+    {
+      if (! readfunc (sigreg_ptr, &gprs[i], arg))
+	return false;
+      sigreg_ptr += word_size;
+    }
+  /* Then the ACRs.  Skip them, they are not used in CFI.  */
+  for (int i = 0; i < 16; i++)
+    sigreg_ptr += 4;
+  /* The floating-point control word.  */
+  sigreg_ptr += 8;
+  /* And finally the FPRs.  */
+  Dwarf_Word fprs[16];
+  for (int i = 0; i < 16; i++)
+    {
+      if (! readfunc (sigreg_ptr, &val, arg))
+	return false;
+      if (ebl->class == ELFCLASS32)
+	{
+	  Dwarf_Addr val_low;
+	  if (! readfunc (sigreg_ptr + 4, &val_low, arg))
+	    return false;
+	  val = (val << 32) | val_low;
+	}
+      fprs[i] = val;
+      sigreg_ptr += 8;
+    }
+  /* If we have them, the GPR upper halves are appended at the end.  */
+  if (ebl->class == ELFCLASS32)
+    {
+      /* Skip signal number.  */
+      sigreg_ptr += 4;
+      for (int i = 0; i < 16; i++)
+	{
+	  if (! readfunc (sigreg_ptr, &val, arg))
+	    return false;
+	  Dwarf_Word val_low = gprs[i];
+	  val = (val << 32) | val_low;
+	  gprs[i] = val;
+	  sigreg_ptr += 4;
+	}
+    }
+  if (! setfunc (0, 16, gprs, arg))
+    return false;
+  if (! setfunc (16, 16, fprs, arg))
+    return false;
+  *signal_framep = true;
+  return true;
+}
diff --git a/backends/s390x_corenote.c b/backends/s390x_corenote.c
new file mode 100644
index 0000000..427bf7d
--- /dev/null
+++ b/backends/s390x_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "s390_corenote.c"
diff --git a/backends/sh_corenote.c b/backends/sh_corenote.c
new file mode 100644
index 0000000..9268f56
--- /dev/null
+++ b/backends/sh_corenote.c
@@ -0,0 +1,88 @@
+/* SH specific core note handling.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed Matt Fleming <matt@console-pimps.org>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#define BACKEND		sh_
+#include "libebl_CPU.h"
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * 4, .regno = dwreg, .count = n, .bits = 32 }
+    GR (0, 16, 0),		/* r0-r15 */
+    GR (16, 1, 16),		/* pc */
+    GR (17, 1, 17),		/* pr */
+    GR (18, 1, 22),		/* sr */
+    GR (19, 1, 18),		/* gbr */
+    GR (20, 1, 20),		/* mach */
+    GR (21, 1, 21),		/* macl */
+    /*  22, 1,			   tra */
+#undef GR
+  };
+#define PRSTATUS_REGS_SIZE	(23 * 4)
+
+#define	ULONG			uint32_t
+#define PID_T			int32_t
+#define	UID_T			uint16_t
+#define	GID_T			uint16_t
+#define ALIGN_ULONG		4
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		2
+#define ALIGN_GID_T		2
+#define TYPE_ULONG		ELF_T_WORD
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_HALF
+#define TYPE_GID_T		ELF_T_HALF
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "tra", .type = ELF_T_ADDR, .format = 'x',			      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[22]),		      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 25, .count = 16, .bits = 32 }, /* fr0-fr15 */
+    { .offset = 16, .regno = 87, .count = 16, .bits = 32 }, /* xf0-xf15 */
+    { .offset = 32, .regno = 24, .count = 1, .bits = 32 }, /* fpscr */
+    { .offset = 33, .regno = 23, .count = 1, .bits = 32 }  /* fpul */
+  };
+#define FPREGSET_SIZE		(50 * 4)
+
+#include "linux-core-note.c"
diff --git a/backends/sh_init.c b/backends/sh_init.c
new file mode 100644
index 0000000..05cf8b1
--- /dev/null
+++ b/backends/sh_init.c
@@ -0,0 +1,57 @@
+/* Initialization of SH specific backend library.
+   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		sh_
+#define RELOC_PREFIX	R_SH_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on sh_reloc.def.  */
+#include "common-reloc.c"
+
+
+Ebl *
+sh_init (Elf *elf __attribute__ ((unused)),
+	 GElf_Half machine __attribute__ ((unused)),
+	 Ebl *eh)
+{
+  /* We handle it.  */
+  sh_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, gotpc_reloc_check);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, core_note);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+
+  return eh;
+}
diff --git a/backends/sh_regs.c b/backends/sh_regs.c
new file mode 100644
index 0000000..d433236
--- /dev/null
+++ b/backends/sh_regs.c
@@ -0,0 +1,191 @@
+/* Register names and numbers for SH DWARF.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Matt Fleming <matt@console-pimps.org>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+ssize_t
+sh_register_info (Ebl *ebl __attribute__ ((unused)),
+		  int regno, char *name, size_t namelen,
+		  const char **prefix, const char **setname,
+		  int *bits, int *type)
+{
+  if (name == NULL)
+    return 104;
+
+  if (regno < 0 || regno > 103 || namelen < 6)
+    return -1;
+
+  *prefix = "";
+  *bits = 32;
+  *type = DW_ATE_signed;
+
+  switch (regno)
+    {
+    case 0 ... 9:
+      *setname = "integer";
+      name[0] = 'r';
+      name[1] = regno + '0';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      *setname = "integer";
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16:
+      *setname = "system";
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'c';
+      namelen = 2;
+      break;
+
+    case 17:
+      *setname = "system";
+      *type = DW_ATE_address;
+      name[0] = 'p';
+      name[1] = 'r';
+      namelen = 2;
+      break;
+
+    case 18:
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      name[0] = 's';
+      name[1] = 'r';
+      namelen = 2;
+      break;
+
+    case 19:
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      name[0] = 'g';
+      name[1] = 'b';
+      name[2] = 'r';
+      namelen = 3;
+      break;
+
+    case 20:
+      *setname = "system";
+      name[0] = 'm';
+      name[1] = 'a';
+      name[2] = 'c';
+      name[3] = 'h';
+      namelen = 4;
+      break;
+
+    case 21:
+      *setname = "system";
+      name[0] = 'm';
+      name[1] = 'a';
+      name[2] = 'c';
+      name[3] = 'l';
+      namelen = 4;
+
+      break;
+
+    case 23:
+      *setname = "system";
+      *type = DW_ATE_unsigned;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = 'u';
+      name[3] = 'l';
+      namelen = 4;
+      break;
+
+    case 24:
+      *setname = "system";
+      *type = DW_ATE_unsigned;
+      name[0] = 'f';
+      name[1] = 'p';
+      name[2] = 's';
+      name[3] = 'c';
+      name[4] = 'r';
+      namelen = 5;
+      break;
+
+    case 25 ... 34:
+      *setname = "fpu";
+      *type = DW_ATE_float;
+      name[0] = 'f';
+      name[1] = 'r';
+      name[2] = regno - 25 + '0';
+      namelen = 3;
+      break;
+
+    case 35 ... 40:
+      *setname = "fpu";
+      *type = DW_ATE_float;
+      name[0] = 'f';
+      name[1] = 'r';
+      name[2] = '1';
+      name[3] = regno - 35 + '0';
+      namelen = 4;
+      break;
+
+    case 87 ... 96:
+      *type = DW_ATE_float;
+      *setname = "fpu";
+      name[0] = 'x';
+      name[1] = 'f';
+      name[2] = regno - 87 + '0';
+      namelen = 3;
+      break;
+
+    case 97 ... 103:
+      *type = DW_ATE_float;
+      *setname = "fpu";
+      name[0] = 'x';
+      name[1] = 'f';
+      name[2] = '1';
+      name[3] = regno - 97 + '0';
+      namelen = 4;
+      break;
+
+    default:
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/sh_reloc.def b/backends/sh_reloc.def
new file mode 100644
index 0000000..aded361
--- /dev/null
+++ b/backends/sh_reloc.def
@@ -0,0 +1,67 @@
+/* List the relocation types for SH.  -*- C -*-
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,		0)
+RELOC_TYPE (DIR32,		REL|DYN)
+RELOC_TYPE (REL32,		REL|DYN)
+RELOC_TYPE (DIR8WPN,		REL)
+RELOC_TYPE (IND12W,		REL)
+RELOC_TYPE (DIR8WPL,		REL)
+RELOC_TYPE (DIR8WPZ,		REL)
+RELOC_TYPE (DIR8BP,		REL)
+RELOC_TYPE (DIR8W,		REL)
+RELOC_TYPE (DIR8L,		REL)
+RELOC_TYPE (SWITCH16,		REL)
+RELOC_TYPE (SWITCH32,		REL)
+RELOC_TYPE (USES,		REL)
+RELOC_TYPE (COUNT,		REL)
+RELOC_TYPE (ALIGN,		REL)
+RELOC_TYPE (CODE,		REL)
+RELOC_TYPE (DATA,		REL)
+RELOC_TYPE (LABEL,		REL)
+RELOC_TYPE (SWITCH8,		REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (TLS_GD_32,		REL)
+RELOC_TYPE (TLS_LD_32,		REL)
+RELOC_TYPE (TLS_LDO_32,		REL)
+RELOC_TYPE (TLS_IE_32,		REL)
+RELOC_TYPE (TLS_LE_32,		REL)
+RELOC_TYPE (TLS_DTPMOD32,	DYN)
+RELOC_TYPE (TLS_DTPOFF32,	DYN)
+RELOC_TYPE (TLS_TPOFF32,	DYN)
+RELOC_TYPE (GOT32,		REL)
+RELOC_TYPE (PLT32,		REL)
+RELOC_TYPE (COPY,		EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,		EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,		EXEC|DYN)
+RELOC_TYPE (RELATIVE,		EXEC|DYN)
+RELOC_TYPE (GOTOFF,		REL)
+RELOC_TYPE (GOTPC,		REL)
diff --git a/backends/sh_retval.c b/backends/sh_retval.c
new file mode 100644
index 0000000..eac83b7
--- /dev/null
+++ b/backends/sh_retval.c
@@ -0,0 +1,130 @@
+/* Function return value location for Linux/SH ABI.
+   Copyright (C) 2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Matt Fleming <matt@console-pimps.org>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+
+/* This is the SVR4 ELF ABI convention, but AIX and Linux do not use it.  */
+#define SVR4_STRUCT_RETURN 0
+
+
+/* r0, or pair r0, r1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* fr0 or fr1.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_reg25 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg26 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg	1
+#define nloc_fpregpair	2
+
+int
+sh_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    if (dwarf_is_pointer (tag))
+	      size = 4;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (size <= 8)
+	{
+	  if (tag == DW_TAG_base_type)
+	    {
+	      Dwarf_Attribute attr_mem;
+	      Dwarf_Word encoding;
+	      if (dwarf_formudata (dwarf_attr_integrate (typedie,
+							 DW_AT_encoding,
+							 &attr_mem),
+				   &encoding) != 0)
+		return -1;
+	      if (encoding == DW_ATE_float)
+		{
+		  *locp = loc_fpreg;
+		  return size <= 4 ? nloc_fpreg : nloc_fpregpair;
+		}
+	    }
+	  *locp = loc_intreg;
+	  return size <= 4 ? nloc_intreg : nloc_intregpair;
+	}
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/sh_symbol.c b/backends/sh_symbol.c
new file mode 100644
index 0000000..2761d92
--- /dev/null
+++ b/backends/sh_symbol.c
@@ -0,0 +1,95 @@
+/* SH specific relocation handling.
+   Copyright (C) 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND sh_
+#include "libebl_CPU.h"
+
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool
+sh_gotpc_reloc_check (Elf *elf __attribute__ ((unused)), int type)
+{
+  return type == R_SH_GOTPC;
+}
+
+/* Check for the simple reloc types.  */
+Elf_Type
+sh_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+		      int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_SH_DIR32:
+      return ELF_T_WORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check whether machine flags are valid.  */
+bool
+sh_machine_flag_check (GElf_Word flags)
+{
+  switch (flags & EF_SH_MACH_MASK)
+    {
+    case EF_SH_UNKNOWN:
+    case EF_SH1:
+    case EF_SH2:
+    case EF_SH3:
+    case EF_SH_DSP:
+    case EF_SH3_DSP:
+    case EF_SH4AL_DSP:
+    case EF_SH3E:
+    case EF_SH4:
+    case EF_SH2E:
+    case EF_SH4A:
+    case EF_SH2A:
+    case EF_SH4_NOFPU:
+    case EF_SH4A_NOFPU:
+    case EF_SH4_NOMMU_NOFPU:
+    case EF_SH2A_NOFPU:
+    case EF_SH3_NOMMU:
+    case EF_SH2A_SH4_NOFPU:
+    case EF_SH2A_SH3_NOFPU:
+    case EF_SH2A_SH4:
+    case EF_SH2A_SH3E:
+      break;
+    default:
+      return false;
+    }
+
+  return ((flags &~ (EF_SH_MACH_MASK)) == 0);
+}
diff --git a/backends/sparc64_corenote.c b/backends/sparc64_corenote.c
new file mode 100644
index 0000000..cef6431
--- /dev/null
+++ b/backends/sparc64_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 64
+#include "sparc_corenote.c"
diff --git a/backends/sparc_attrs.c b/backends/sparc_attrs.c
new file mode 100644
index 0000000..974e8fb
--- /dev/null
+++ b/backends/sparc_attrs.c
@@ -0,0 +1,105 @@
+/* Object attribute tags for SPARC.
+   Copyright (C) 2015 Oracle, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+bool
+sparc_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+			      const char *vendor, int tag, uint64_t value,
+			      const char **tag_name, const char **value_name)
+{
+  static const char *hwcaps[32] =
+    {
+      "mul32", "div32", "fsmuld", "v8plus", "popc", "vis", "vis2",
+      "asi_blk_init", "fmaf", "vis3", "hpc", "random", "trans",
+      "fjfmau", "ima", "asi_cache_sparing", "aes", "des", "kasumi",
+      "camellia", "md5", "sha1", "sha256", "sha512", "mpmul", "mont",
+      "pause", "cbcond", "crc32c", "resv30", "resv31"
+    };
+
+  
+  static const char *hwcaps2[32] =
+    {
+      "fjathplus", "vis3b", "adp", "sparc5", "mwait", "xmpmul", "xmont",
+      "nsec", "resv8", "resv9" , "resv10", "resv11", "fjathhpc", "fjdes",
+      "fjaes", "resv15", "resv16", "resv17", "resv18", "resv19", "resv20",
+      "resv21", "resv22", "resv23", "resv24", "resv25", "resv26", "resv27",
+      "resv28", "resv29", "resv30", "resv31",
+    };
+
+  /* NAME should be big enough to hold any possible comma-separated
+     list (no repetitions allowed) of attribute names from one of the
+     arrays above.  */
+  static char name[32*17+32+1];
+  name[0] = '\0';
+
+  if (!strcmp (vendor, "gnu"))
+    switch (tag)
+      {
+      case 4:
+      case 8:
+        {
+          const char **caps;
+          int cap;
+          
+          if (tag == 4)
+            {
+              *tag_name = "GNU_Sparc_HWCAPS";
+              caps = hwcaps;
+            }
+          else
+            {
+              *tag_name = "GNU_Sparc_HWCAPS2";
+              caps = hwcaps2;
+            }
+          
+          char *s = name;
+          for (cap = 0; cap < 32; cap++)
+            if (value & (1U << cap))
+              {
+                if (*s != '\0')
+                  s = strcat (s, ",");
+                s = strcat (s, caps[cap]);
+              }
+          
+          *value_name = s;
+          return true;
+        }
+      }
+
+  return false;
+}
+
diff --git a/backends/sparc_auxv.c b/backends/sparc_auxv.c
new file mode 100644
index 0000000..2da349c
--- /dev/null
+++ b/backends/sparc_auxv.c
@@ -0,0 +1,46 @@
+/* SPARC-specific auxv handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+int
+EBLHOOK(auxv_info) (GElf_Xword a_type, const char **name, const char **format)
+{
+  if (a_type != AT_HWCAP)
+    return 0;
+
+  *name = "HWCAP";
+  *format = "b"
+    "flush\0" "stbar\0" "swap\0" "muldiv\0" "v9\0" "ultra3\0" "v9v\0" "\0";
+  return 1;
+}
diff --git a/backends/sparc_cfi.c b/backends/sparc_cfi.c
new file mode 100644
index 0000000..dcc17bd
--- /dev/null
+++ b/backends/sparc_cfi.c
@@ -0,0 +1,83 @@
+/* SPARC defaults for DWARF CFI.
+   Copyright (C) 2015 Oracle Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+int
+sparc_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+#define SV(n) DW_CFA_same_value, ULEB128_7 (n)
+      /* %g0 .. %g7 */
+      SV (0), SV (1), SV (2), SV (3), SV (4), SV (5), SV (6), SV (7),
+      /* %o0 .. %o7 */
+      SV (8), SV (9), SV (10), SV (11), SV (12), SV (13), SV (14), SV (15),
+      /* %l0 .. %l7 */
+      SV (16), SV (17), SV (18), SV (19), SV (20), SV (21), SV (22), SV (23),
+      /* %i0 .. %i7 */
+      SV (24), SV (25), SV (26), SV (27), SV (28), SV (29), SV (30), SV (31),
+      /* %f0 .. %f32 */
+      SV (32), SV (33), SV (34), SV (35), SV (36), SV (37), SV (38), SV (39),
+      SV (40), SV (41), SV (42), SV (43), SV (44), SV (45), SV (46), SV (47),
+      SV (48), SV (49), SV (50), SV (51), SV (52), SV (53), SV (54), SV (55),
+      SV (56), SV (57), SV (58), SV (59), SV (60), SV (61), SV (52), SV (63),
+      /* %f33 .. %63
+         Note that there are DWARF columns for the odd registers, even
+         if they don't exist in hardware) */
+      SV (64), SV (65), SV (66), SV (67), SV (68), SV (69), SV (70), SV (71),
+      SV (72), SV (73), SV (74), SV (75), SV (76), SV (77), SV (78), SV (79),
+      SV (80), SV (81), SV (82), SV (83), SV (84), SV (85), SV (86), SV (87),
+      SV (88), SV (89), SV (90), SV (91), SV (92), SV (93), SV (94), SV (95),
+      /* %fcc[0123] */
+      SV (96), SV (97), SV (98), SV (99),
+      /* %icc/%xcc */
+      SV (100),
+      /* Soft frame-pointer */
+      SV (101),
+      /* %gsr */
+      SV (102)
+#undef SV
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 4;
+
+  abi_info->return_address_register = 31; /* %i7 */
+
+  return 0;
+}
+
diff --git a/backends/sparc_corenote.c b/backends/sparc_corenote.c
new file mode 100644
index 0000000..c9b6ff3
--- /dev/null
+++ b/backends/sparc_corenote.c
@@ -0,0 +1,120 @@
+/* SPARC specific core note handling.
+   Copyright (C) 2007 Red Hat, Inc.
+   Copyright (C) 2015 Oracle, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		32
+# define BACKEND	sparc_
+#else
+# define BITS 		64
+# define BACKEND	sparc64_
+#endif
+#include "libebl_CPU.h"
+
+#define GR(at, n, dwreg)						\
+    { .offset = at * BITS/8, .regno = dwreg, .count = n, .bits = BITS }
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+    GR (0, 32, 0),		/* %g0-%g7, %o0-%o7, %i0-%i7 */
+#if BITS == 32
+    GR (32, 1, 65),		/* %psr */
+    GR (33, 2, 68),		/* %pc, %npc */
+    GR (35, 1, 64),		/* %y */
+    GR (36, 1, 66),		/* %wim, %tbr */
+#else
+    GR (32, 1, 82),		/* %state */
+    GR (33, 2, 80),		/* %pc, %npc */
+    GR (35, 1, 85),		/* %y */
+#endif
+  };
+#define PRSTATUS_REGS_SIZE	(BITS / 8 * (32 + (BITS == 32 ? 6 : 4)))
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+#if BITS == 32
+    GR (0, 32, 32),		/* %f0-%f31 */
+    /* 				   padding word */
+    GR (33, 1, 70),		/* %fsr */
+    /* 	       			   qcnt, q_entrysize, en, q, padding */
+# define FPREGSET_SIZE		(34 * 4 + 4 + 64 * 4 + 4)
+#else
+    GR (0, 32, 32),		/* %f0-%f31 */
+    GR (32, 1, 83),		/* %fsr */
+    /*  33, 1, 			   %gsr */
+    GR (34, 1, 84),		/* %fprs */
+# define FPREGSET_SIZE		(35 * 8)
+#endif
+  };
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define TYPE_LONG		ELF_T_SWORD
+# define UID_T			uint16_t
+# define GID_T			uint16_t
+# define ALIGN_UID_T		2
+# define ALIGN_GID_T		2
+# define TYPE_UID_T		ELF_T_HALF
+# define TYPE_GID_T		ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define TYPE_LONG		ELF_T_SXWORD
+# define UID_T			uint32_t
+# define GID_T			uint32_t
+# define ALIGN_UID_T		4
+# define ALIGN_GID_T		4
+# define TYPE_UID_T		ELF_T_WORD
+# define TYPE_GID_T		ELF_T_WORD
+# define SUSECONDS_HALF		1
+#endif
+#define PID_T			int32_t
+#define ALIGN_PID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "pc", .type = ELF_T_ADDR, .format = 'x',			      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg[33]),		      \
+    .group = "register", .pc_register = true				      \
+  }
+
+#include "linux-core-note.c"
diff --git a/backends/sparc_init.c b/backends/sparc_init.c
new file mode 100644
index 0000000..647a789
--- /dev/null
+++ b/backends/sparc_init.c
@@ -0,0 +1,78 @@
+/* Initialization of SPARC specific backend library.
+   Copyright (C) 2002, 2005, 2006, 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		sparc_
+#define RELOC_PREFIX	R_SPARC_
+#include "libebl_CPU.h"
+
+/* In SPARC some relocations use the most significative 24 bits of the
+   r_type field to encode a secondary addend.  Make sure the routines
+   in common-reloc.c acknowledge this.  */
+#define RELOC_TYPE_ID(type) ((type) & 0xff)
+
+/* This defines the common reloc hooks based on sparc_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (EBLHOOK (core_note)) sparc64_core_note attribute_hidden;
+
+Ebl *
+sparc_init (Elf *elf __attribute__ ((unused)),
+	    GElf_Half machine __attribute__ ((unused)),
+	    Ebl *eh)
+{
+  /* We handle it.  */
+  sparc_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, machine_flag_check);
+  HOOK (eh, check_special_section);
+  HOOK (eh, symbol_type_name);
+  HOOK (eh, dynamic_tag_name);
+  HOOK (eh, dynamic_tag_check);
+  if (eh->class == ELFCLASS64)
+    eh->core_note = sparc64_core_note;
+  else
+    HOOK (eh, core_note);
+  HOOK (eh, auxv_info);
+  HOOK (eh, register_info);
+  HOOK (eh, return_value_location);
+  HOOK (eh, check_object_attribute);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/sparc.h define FIRST_PSEUDO_REGISTER  */
+  eh->frame_nregs = 103;
+  /* The CFI Dwarf register with the "return address" in sparc
+     actually contains the call address.  The return address is
+     located 8 bytes after it.  */
+  eh->ra_offset = 8;
+  HOOK (eh, set_initial_registers_tid);
+
+  return eh;
+}
diff --git a/backends/sparc_initreg.c b/backends/sparc_initreg.c
new file mode 100644
index 0000000..c4b321c
--- /dev/null
+++ b/backends/sparc_initreg.c
@@ -0,0 +1,129 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2015 Oracle, In
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "system.h"
+#include <stdlib.h>
+#ifdef __sparc__
+# include <asm/ptrace.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+bool
+EBLHOOK (set_initial_registers_tid) (pid_t tid __attribute__ ((unused)),
+                                     ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+                                     void *arg __attribute__ ((unused)))
+{
+#if !defined(__sparc__) || !defined( __arch64__)
+  return false;
+#else /* __sparc__ */
+
+
+  /* The pt_regs structure filled in by PTRACE_GETREGS provides the
+     PC, the global registers and the output registers.  Note how the
+     %g0 register is not explicitly provided in the structure (it's
+     value is always 0) and the resulting weird packing in the u_regs
+     array: the last element is not used.  */
+  
+  struct pt_regs regs;
+  if (ptrace (PTRACE_GETREGS, tid, &regs, 0) == -1)
+    return false;
+
+  /* PC: no DWARF number  */
+  if (!setfunc (-1, 1, (Dwarf_Word *) &regs.tpc, arg))
+    return false;
+  
+  /* Global registers: DWARF 0 .. 7  */
+  Dwarf_Word zero = 0;
+  if (!setfunc (0, 1, &zero, arg))
+    return false;
+  if (!setfunc (1, 7, (Dwarf_Word *) &regs.u_regs[0], arg))
+    return false;
+
+  /* Output registers: DWARF  8 .. 15  */
+  if (!setfunc (8, 8, (Dwarf_Word *) &regs.u_regs[7], arg))
+    return false;
+
+  /* Local and input registers must be read from the stack.  They are
+     saved in the previous stack frame.  The stack pointer is %o6,
+     read above.  */
+
+  Dwarf_Word locals_outs[16];
+  Dwarf_Word sp = regs.u_regs[13];
+
+  if (sp & 1)
+    {
+      /* Registers are 64 bits, and we need to apply the 2047 stack
+         bias in order to get the real stack pointer.  */
+
+      sp += 2047;
+
+      for (unsigned i = 0; i < 16; i++)
+        {
+          locals_outs[i] = ptrace (PTRACE_PEEKDATA, tid,
+                                   (void *) (uintptr_t) (sp + (i * 8)),
+                                   NULL);
+          if (errno != 0)
+            return false;
+        }
+    }
+  else
+    {
+      /* Registers are 32 bits.  */
+
+      for (unsigned i = 0; i < 8; i++)
+        {
+          Dwarf_Word tuple = ptrace (PTRACE_PEEKDATA, tid,
+                                     (void *) (uintptr_t) (sp + (i * 8)),
+                                     NULL);
+          if (errno != 0)
+            return false;
+
+          locals_outs[2*i] = (tuple >> 32) & 0xffffffff;
+          locals_outs[2*i+1] = tuple & 0xffffffff;
+        }
+    }
+
+  
+  /* Local registers:  DWARF 16 .. 23 */
+  if (!setfunc (16, 8, &locals_outs[0], arg))
+    return false;
+  
+  /* Input registers: DWARF 24 .. 31 */
+  if (!setfunc (24, 8, &locals_outs[8], arg))
+    return false;
+
+  return true;
+#endif
+}
diff --git a/backends/sparc_regs.c b/backends/sparc_regs.c
new file mode 100644
index 0000000..2bddcf4
--- /dev/null
+++ b/backends/sparc_regs.c
@@ -0,0 +1,111 @@
+/* Register names and numbers for SPARC DWARF.
+   Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+ssize_t
+sparc_register_info (Ebl *ebl,
+		     int regno, char *name, size_t namelen,
+		     const char **prefix, const char **setname,
+		     int *bits, int *type)
+{
+  const int nfp = 32 + (ebl->class == ELFCLASS32 ? 0 : 16);
+  const int nspec = ebl->class == ELFCLASS32 ? 8 : 6;
+
+  if (name == NULL)
+    return 32 + nfp + nspec;
+
+  if (regno < 0 || regno >= 32 + nfp + nspec || namelen < 6)
+    return -1;
+
+  *bits = ebl->class == ELFCLASS32 ? 32 : 64;
+  *type = DW_ATE_signed;
+
+  *prefix = "%";
+
+  if (regno >= 32 + nfp)
+    {
+      regno -= 32 + nfp;
+      static const char names[2][8][6] =
+	{
+	  { "y", "psr", "wim", "tbr", "pc", "npc", "fsr", "csr" }, /* v8 */
+	  { "pc", "npc", "state", "fsr", "fprs", "y" } /* v9 */
+	};
+      *setname = "control";
+      *type = DW_ATE_unsigned;
+      if ((ebl->class == ELFCLASS64 ? 0 : 4) + 1 - (unsigned int) regno <= 1)
+	*type = DW_ATE_address;
+      return stpncpy (name, names[ebl->class == ELFCLASS64][regno],
+		      namelen) + 1 - name;
+    }
+
+  if (regno < 32)
+    {
+      *setname = "integer";
+      name[0] = "goli"[regno >> 3];
+      name[1] = (regno & 7) + '0';
+      namelen = 2;
+      if ((regno & 8) && (regno & 7) == 6)
+	*type = DW_ATE_address;
+    }
+  else
+    {
+      *setname = "FPU";
+      *type = DW_ATE_float;
+
+      regno -= 32;
+      if (regno >= 32)
+	regno = 32 + 2 * (regno - 32);
+      else
+	*bits = 32;
+
+      name[0] = 'f';
+      if (regno < 10)
+	{
+	  name[1] = regno + '0';
+	  namelen = 2;
+	}
+      else
+	{
+	  name[1] = regno / 10 + '0';
+	  name[2] = regno % 10 + '0';
+	  namelen = 3;
+	}
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/sparc_reloc.def b/backends/sparc_reloc.def
new file mode 100644
index 0000000..f0eeb5c
--- /dev/null
+++ b/backends/sparc_reloc.def
@@ -0,0 +1,124 @@
+/* List the relocation types for sparc.  -*- C -*-
+   Copyright (C) 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* 	    NAME,		REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,               REL|EXEC|DYN)
+RELOC_TYPE (8,                  REL)
+RELOC_TYPE (16,                 REL)
+RELOC_TYPE (32,                 REL|DYN)
+RELOC_TYPE (DISP8,              REL)
+RELOC_TYPE (DISP16,             REL)
+RELOC_TYPE (DISP32,             REL)
+RELOC_TYPE (WDISP30,            REL)
+RELOC_TYPE (WDISP22,            REL)
+RELOC_TYPE (HI22,               REL)
+RELOC_TYPE (22,                 REL)
+RELOC_TYPE (13,                 REL)
+RELOC_TYPE (LO10,               REL)
+RELOC_TYPE (GOT10,              REL)
+RELOC_TYPE (GOT13,              REL)
+RELOC_TYPE (GOT22,              REL)
+RELOC_TYPE (PC10,               REL)
+RELOC_TYPE (PC22,               REL)
+RELOC_TYPE (WPLT30,             REL)
+RELOC_TYPE (COPY,               EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,           EXEC|DYN)
+RELOC_TYPE (JMP_SLOT,           EXEC|DYN)
+RELOC_TYPE (RELATIVE,           EXEC|DYN)
+RELOC_TYPE (UA32,               REL)
+RELOC_TYPE (PLT32,              REL)
+RELOC_TYPE (HIPLT22,            REL)
+RELOC_TYPE (LOPLT10,            REL)
+RELOC_TYPE (PCPLT32,            REL)
+RELOC_TYPE (PCPLT22,            REL)
+RELOC_TYPE (PCPLT10,            REL)
+RELOC_TYPE (10,                 REL)
+RELOC_TYPE (11,                 REL)
+RELOC_TYPE (64,                 REL|DYN)
+RELOC_TYPE (OLO10,              REL)
+RELOC_TYPE (HH22,               REL)
+RELOC_TYPE (HM10,               REL)
+RELOC_TYPE (LM22,               REL)
+RELOC_TYPE (PC_HH22,            REL)
+RELOC_TYPE (PC_HM10,            REL)
+RELOC_TYPE (PC_LM22,            REL)
+RELOC_TYPE (WDISP16,            REL)
+RELOC_TYPE (WDISP19,            REL)
+RELOC_TYPE (GLOB_JMP,		EXEC|DYN)
+RELOC_TYPE (7,                  REL)
+RELOC_TYPE (5,                  REL)
+RELOC_TYPE (6,                  REL)
+RELOC_TYPE (DISP64,             REL)
+RELOC_TYPE (PLT64,              REL)
+RELOC_TYPE (HIX22,              REL)
+RELOC_TYPE (LOX10,              REL)
+RELOC_TYPE (H44,                REL)
+RELOC_TYPE (M44,                REL)
+RELOC_TYPE (L44,                REL)
+RELOC_TYPE (REGISTER,           REL)
+RELOC_TYPE (UA64,               REL)
+RELOC_TYPE (UA16,               REL)
+RELOC_TYPE (TLS_GD_HI22,        REL)
+RELOC_TYPE (TLS_GD_LO10,        REL)
+RELOC_TYPE (TLS_GD_ADD,         REL)
+RELOC_TYPE (TLS_GD_CALL,        REL)
+RELOC_TYPE (TLS_LDM_HI22,       REL)
+RELOC_TYPE (TLS_LDM_LO10,       REL)
+RELOC_TYPE (TLS_LDM_ADD,        REL)
+RELOC_TYPE (TLS_LDM_CALL,       REL)
+RELOC_TYPE (TLS_LDO_HIX22,      REL)
+RELOC_TYPE (TLS_LDO_LOX10,      REL)
+RELOC_TYPE (TLS_LDO_ADD,        REL)
+RELOC_TYPE (TLS_IE_HI22,        REL)
+RELOC_TYPE (TLS_IE_LO10,        REL)
+RELOC_TYPE (TLS_IE_LD,          REL)
+RELOC_TYPE (TLS_IE_LDX,         REL)
+RELOC_TYPE (TLS_IE_ADD,         REL)
+RELOC_TYPE (TLS_LE_HIX22,       REL)
+RELOC_TYPE (TLS_LE_LOX10,       REL)
+RELOC_TYPE (TLS_DTPMOD32,       DYN)
+RELOC_TYPE (TLS_DTPMOD64,       DYN)
+RELOC_TYPE (TLS_DTPOFF32,       DYN)
+RELOC_TYPE (TLS_DTPOFF64,       DYN)
+RELOC_TYPE (TLS_TPOFF32,        DYN)
+RELOC_TYPE (TLS_TPOFF64,        DYN)
+RELOC_TYPE (GOTDATA_HIX22,	REL)
+RELOC_TYPE (GOTDATA_LOX10,	REL)
+RELOC_TYPE (GOTDATA_OP_HIX22,	REL|DYN)
+RELOC_TYPE (GOTDATA_OP_LOX10,	REL|DYN)
+RELOC_TYPE (GOTDATA_OP,		REL|DYN)
+RELOC_TYPE (H34,		REL)
+RELOC_TYPE (SIZE32,		REL)
+RELOC_TYPE (SIZE64,		REL)
+RELOC_TYPE (WDISP10,		REL)
+RELOC_TYPE (JMP_IREL,		REL)
+RELOC_TYPE (IRELATIVE,		REL)
+RELOC_TYPE (GNU_VTINHERIT,	REL)
+RELOC_TYPE (GNU_VTENTRY,	REL)
+RELOC_TYPE (REV32,		REL)
diff --git a/backends/sparc_retval.c b/backends/sparc_retval.c
new file mode 100644
index 0000000..8b3fb62
--- /dev/null
+++ b/backends/sparc_retval.c
@@ -0,0 +1,158 @@
+/* Function return value location for SPARC.
+   Copyright (C) 2006-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND sparc_
+#include "libebl_CPU.h"
+
+
+/* %o0, or pair %o0, %o1.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg8 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_reg9 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %f0 or pair %f0, %f1, or quad %f0..%f3.  */
+static const Dwarf_Op loc_fpreg[] =
+  {
+    { .atom = DW_OP_regx, .number = 32 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 33 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 34 }, { .atom = DW_OP_piece, .number = 4 },
+    { .atom = DW_OP_regx, .number = 35 }, { .atom = DW_OP_piece, .number = 4 },
+  };
+#define nloc_fpreg	1
+#define nloc_fpregpair	4
+#define nloc_fpregquad	8
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %o0.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg8, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+int
+sparc_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+	  {
+	    uint8_t asize;
+	    Dwarf_Die cudie;
+	    if (dwarf_is_pointer (tag)
+		&& dwarf_diecu (typedie, &cudie, &asize, NULL) != NULL)
+	      size = asize;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+	  if (encoding == DW_ATE_float)
+	    {
+	      *locp = loc_fpreg;
+	      if (size <= 4)
+		return nloc_fpreg;
+	      if (size <= 8)
+		return nloc_fpregpair;
+	      if (size <= 16)
+		return nloc_fpregquad;
+	    }
+	}
+      if (size <= 8)
+	{
+	intreg:
+	  *locp = loc_intreg;
+	  return size <= 4 ? nloc_intreg : nloc_intregpair;
+	}
+
+    aggregate:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) == 0
+	  && size > 0 && size <= 8)
+	goto intreg;
+      goto aggregate;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/sparc_symbol.c b/backends/sparc_symbol.c
new file mode 100644
index 0000000..e8ee391
--- /dev/null
+++ b/backends/sparc_symbol.c
@@ -0,0 +1,149 @@
+/* SPARC specific symbolic name handling.
+   Copyright (C) 2002, 2003, 2005, 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Jakub Jelinek <jakub@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND		sparc_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+sparc_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			 int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_SPARC_8:
+      return ELF_T_BYTE;
+    case R_SPARC_16:
+    case R_SPARC_UA16:
+      return ELF_T_HALF;
+    case R_SPARC_32:
+    case R_SPARC_UA32:
+      return ELF_T_WORD;
+    case R_SPARC_64:
+    case R_SPARC_UA64:
+      return ELF_T_XWORD;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Check whether machine flags are valid.  */
+bool
+sparc_machine_flag_check (GElf_Word flags)
+{
+  return ((flags &~ (EF_SPARCV9_MM
+		     | EF_SPARC_LEDATA
+		     | EF_SPARC_32PLUS
+		     | EF_SPARC_SUN_US1
+		     | EF_SPARC_SUN_US3)) == 0);
+}
+
+bool
+sparc_check_special_section (Ebl *ebl,
+			     int ndx __attribute__ ((unused)),
+			     const GElf_Shdr *shdr,
+			     const char *sname __attribute__ ((unused)))
+{
+  if ((shdr->sh_flags & (SHF_WRITE | SHF_EXECINSTR))
+      == (SHF_WRITE | SHF_EXECINSTR))
+    {
+      /* This is ordinarily flagged, but is valid for a PLT on SPARC.
+
+	 Look for the SHT_DYNAMIC section and the DT_PLTGOT tag in it.
+	 Its d_ptr should match the .plt section's sh_addr.  */
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	{
+	  GElf_Shdr scn_shdr;
+	  if (likely (gelf_getshdr (scn, &scn_shdr) != NULL)
+	      && scn_shdr.sh_type == SHT_DYNAMIC
+	      && scn_shdr.sh_entsize != 0)
+	    {
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      if (data != NULL)
+		for (size_t i = 0; i < data->d_size / scn_shdr.sh_entsize; ++i)
+		  {
+		    GElf_Dyn dyn;
+		    if (unlikely (gelf_getdyn (data, i, &dyn) == NULL))
+		      break;
+		    if (dyn.d_tag == DT_PLTGOT)
+		      return dyn.d_un.d_ptr == shdr->sh_addr;
+		  }
+	      break;
+	    }
+	}
+    }
+
+  return false;
+}
+
+const char *
+sparc_symbol_type_name (int type,
+			char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case STT_SPARC_REGISTER:
+      return "SPARC_REGISTER";
+    }
+  return NULL;
+}
+
+const char *
+sparc_dynamic_tag_name (int64_t tag,
+			char *buf __attribute__ ((unused)),
+			size_t len __attribute__ ((unused)))
+{
+  switch (tag)
+    {
+    case DT_SPARC_REGISTER:
+      return "SPARC_REGISTER";
+    }
+  return NULL;
+}
+
+bool
+sparc_dynamic_tag_check (int64_t tag)
+{
+  switch (tag)
+    {
+    case DT_SPARC_REGISTER:
+      return true;
+    }
+  return false;
+}
diff --git a/backends/x32_corenote.c b/backends/x32_corenote.c
new file mode 100644
index 0000000..bd6560d
--- /dev/null
+++ b/backends/x32_corenote.c
@@ -0,0 +1,2 @@
+#define BITS 32
+#include "x86_64_corenote.c"
diff --git a/backends/x86_64_cfi.c b/backends/x86_64_cfi.c
new file mode 100644
index 0000000..6db8ac4
--- /dev/null
+++ b/backends/x86_64_cfi.c
@@ -0,0 +1,63 @@
+/* x86-64 ABI-specified defaults for DWARF CFI.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+int
+x86_64_abi_cfi (Ebl *ebl __attribute__ ((unused)), Dwarf_CIE *abi_info)
+{
+  static const uint8_t abi_cfi[] =
+    {
+      /* Call-saved regs.  */
+      DW_CFA_same_value, ULEB128_7 (0), /* %rbx */
+      DW_CFA_same_value, ULEB128_7 (6), /* %rbp */
+      DW_CFA_same_value, ULEB128_7 (12), /* %r12 */
+      DW_CFA_same_value, ULEB128_7 (13), /* %r13 */
+      DW_CFA_same_value, ULEB128_7 (14), /* %r14 */
+      DW_CFA_same_value, ULEB128_7 (15), /* %r15 */
+      DW_CFA_same_value, ULEB128_7 (16), /* %r16 */
+
+      /* The CFA is the SP.  */
+      DW_CFA_val_offset, ULEB128_7 (7), ULEB128_7 (0),
+    };
+
+  abi_info->initial_instructions = abi_cfi;
+  abi_info->initial_instructions_end = &abi_cfi[sizeof abi_cfi];
+  abi_info->data_alignment_factor = 8;
+
+  abi_info->return_address_register = 16; /* %rip */
+
+  return 0;
+}
diff --git a/backends/x86_64_corenote.c b/backends/x86_64_corenote.c
new file mode 100644
index 0000000..1bacc60
--- /dev/null
+++ b/backends/x86_64_corenote.c
@@ -0,0 +1,139 @@
+/* x86-64 specific core note handling.
+   Copyright (C) 2005, 2007, 2008 Red Hat, Inc.
+   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <elf.h>
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/time.h>
+
+#ifndef BITS
+# define BITS 		64
+# define BACKEND	x86_64_
+#else
+# define BITS 		32
+# define BACKEND	x32_
+#endif
+#include "libebl_CPU.h"
+
+
+static const Ebl_Register_Location prstatus_regs[] =
+  {
+#define GR(at, n, dwreg)						\
+    { .offset = at * 8, .regno = dwreg, .count = n, .bits = 64 }
+#define SR(at, n, dwreg)						\
+    { .offset = at * 8, .regno = dwreg, .count = n, .bits = 16, .pad = 6 }
+
+    GR (0, 1, 15),		/* %r15 */
+    GR (1, 1, 14),		/* %r14 */
+    GR (2, 1, 13),		/* %r13 */
+    GR (3, 1, 12),		/* %r12 */
+    GR (4, 1, 6),		/* %rbp */
+    GR (5, 1, 3),		/* %rbx */
+    GR (6, 1, 11),		/* %r11 */
+    GR (7, 1, 10),		/* %r10 */
+    GR (8, 1, 9),		/* %r9 */
+    GR (9, 1, 8),		/* %r8 */
+    GR (10,1, 0),		/* %rax */
+    GR (11,1, 2),		/* %rcx */
+    GR (12,1, 1),		/* %rdx */
+    GR (13,2, 4),		/* %rsi-%rdi */
+    /*  15,1,			    orig_rax */
+    GR (16,1, 16),		/* %rip */
+    SR (17,1, 51),		/* %cs */
+    GR (18,1, 49),		/* %rFLAGS */
+    GR (19,1, 7),		/* %rsp */
+    SR (20,1, 52),		/* %ss */
+    GR (21,2, 58),		/* %fs.base-%gs.base */
+    SR (23,1, 53),		/* %ds */
+    SR (24,1, 50),		/* %es */
+    SR (25,2, 54),		/* %fs-%gs */
+
+#undef	GR
+#undef	SR
+  };
+#define PRSTATUS_REGS_SIZE	(27 * 8)
+
+#if BITS == 32
+# define ULONG			uint32_t
+# define ALIGN_ULONG		4
+# define TYPE_ULONG		ELF_T_WORD
+# define PRPSINFO_UID_T		uint16_t
+# define ALIGN_PRPSINFO_UID_T	2
+# define TYPE_PRPSINFO_UID_T	ELF_T_HALF
+# define PRPSINFO_GID_T		uint16_t
+# define ALIGN_PRPSINFO_GID_T	2
+# define TYPE_PRPSINFO_GID_T	ELF_T_HALF
+#else
+# define ULONG			uint64_t
+# define ALIGN_ULONG		8
+# define TYPE_ULONG		ELF_T_XWORD
+# define PRPSINFO_UID_T		uint32_t
+# define ALIGN_PRPSINFO_UID_T	4
+# define TYPE_PRPSINFO_UID_T	TYPE_UID_T
+# define PRPSINFO_GID_T		uint32_t
+# define ALIGN_PRPSINFO_GID_T	4
+# define TYPE_PRPSINFO_GID_T	TYPE_GID_T
+#endif
+#define PR_REG			uint64_t
+#define ALIGN_PR_REG		8
+#define PID_T			int32_t
+#define	UID_T			uint32_t
+#define	GID_T			uint32_t
+#define ALIGN_PID_T		4
+#define ALIGN_UID_T		4
+#define ALIGN_GID_T		4
+#define TYPE_PID_T		ELF_T_SWORD
+#define TYPE_UID_T		ELF_T_SWORD
+#define TYPE_GID_T		ELF_T_SWORD
+
+#define PRSTATUS_REGSET_ITEMS						      \
+  {									      \
+    .name = "orig_rax", .type = ELF_T_SXWORD, .format = 'd',		      \
+    .offset = offsetof (struct EBLHOOK(prstatus), pr_reg) + (8 * 15),	      \
+    .group = "register"	       			  	       	 	      \
+  }
+
+static const Ebl_Register_Location fpregset_regs[] =
+  {
+    { .offset = 0, .regno = 65, .count = 2, .bits = 16 }, /* fcw-fsw */
+    { .offset = 24, .regno = 64, .count = 1, .bits = 32 }, /* mxcsr */
+    { .offset = 32, .regno = 33, .count = 8, .bits = 80, .pad = 6 }, /* stN */
+    { .offset = 32 + 128, .regno = 17, .count = 16, .bits = 128 }, /* xmm */
+  };
+#define FPREGSET_SIZE	512
+
+#define	EXTRA_NOTES	EXTRA_NOTES_IOPERM
+
+#include "x86_corenote.c"
+#include "linux-core-note.c"
diff --git a/backends/x86_64_init.c b/backends/x86_64_init.c
new file mode 100644
index 0000000..be965fa
--- /dev/null
+++ b/backends/x86_64_init.c
@@ -0,0 +1,69 @@
+/* Initialization of x86-64 specific backend library.
+   Copyright (C) 2002-2009, 2013, 2018 Red Hat, Inc.
+   Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define BACKEND		x86_64_
+#define RELOC_PREFIX	R_X86_64_
+#include "libebl_CPU.h"
+
+/* This defines the common reloc hooks based on x86_64_reloc.def.  */
+#include "common-reloc.c"
+
+extern __typeof (EBLHOOK (core_note)) x32_core_note attribute_hidden;
+
+Ebl *
+x86_64_init (Elf *elf __attribute__ ((unused)),
+	     GElf_Half machine __attribute__ ((unused)),
+	     Ebl *eh)
+{
+  /* We handle it.  */
+  x86_64_init_reloc (eh);
+  HOOK (eh, reloc_simple_type);
+  HOOK (eh, section_type_name);
+  if (eh->class == ELFCLASS32)
+    eh->core_note = x32_core_note;
+  else
+    HOOK (eh, core_note);
+  HOOK (eh, return_value_location);
+  HOOK (eh, register_info);
+  HOOK (eh, auxv_info);
+  HOOK (eh, disasm);
+  HOOK (eh, abi_cfi);
+  /* gcc/config/ #define DWARF_FRAME_REGISTERS.  */
+  eh->frame_nregs = 17;
+  HOOK (eh, set_initial_registers_tid);
+  HOOK (eh, unwind);
+  HOOK (eh, check_reloc_target_type);
+
+  return eh;
+}
diff --git a/backends/x86_64_initreg.c b/backends/x86_64_initreg.c
new file mode 100644
index 0000000..50e9002
--- /dev/null
+++ b/backends/x86_64_initreg.c
@@ -0,0 +1,73 @@
+/* Fetch live process registers from TID.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#if defined(__x86_64__) && defined(__linux__)
+# include <sys/user.h>
+# include <sys/ptrace.h>
+#endif
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+bool
+x86_64_set_initial_registers_tid (pid_t tid __attribute__ ((unused)),
+			  ebl_tid_registers_t *setfunc __attribute__ ((unused)),
+				  void *arg __attribute__ ((unused)))
+{
+#if !defined(__x86_64__) || !defined(__linux__)
+  return false;
+#else /* __x86_64__ */
+  struct user_regs_struct user_regs;
+  if (ptrace (PTRACE_GETREGS, tid, NULL, &user_regs) != 0)
+    return false;
+  Dwarf_Word dwarf_regs[17];
+  dwarf_regs[0] = user_regs.rax;
+  dwarf_regs[1] = user_regs.rdx;
+  dwarf_regs[2] = user_regs.rcx;
+  dwarf_regs[3] = user_regs.rbx;
+  dwarf_regs[4] = user_regs.rsi;
+  dwarf_regs[5] = user_regs.rdi;
+  dwarf_regs[6] = user_regs.rbp;
+  dwarf_regs[7] = user_regs.rsp;
+  dwarf_regs[8] = user_regs.r8;
+  dwarf_regs[9] = user_regs.r9;
+  dwarf_regs[10] = user_regs.r10;
+  dwarf_regs[11] = user_regs.r11;
+  dwarf_regs[12] = user_regs.r12;
+  dwarf_regs[13] = user_regs.r13;
+  dwarf_regs[14] = user_regs.r14;
+  dwarf_regs[15] = user_regs.r15;
+  dwarf_regs[16] = user_regs.rip;
+  return setfunc (0, 17, dwarf_regs, arg);
+#endif /* __x86_64__ */
+}
diff --git a/backends/x86_64_regs.c b/backends/x86_64_regs.c
new file mode 100644
index 0000000..ef987da
--- /dev/null
+++ b/backends/x86_64_regs.c
@@ -0,0 +1,186 @@
+/* Register names and numbers for x86-64 DWARF.
+   Copyright (C) 2005, 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <string.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+ssize_t
+x86_64_register_info (Ebl *ebl __attribute__ ((unused)),
+		      int regno, char *name, size_t namelen,
+		      const char **prefix, const char **setname,
+		      int *bits, int *type)
+{
+  if (name == NULL)
+    return 67;
+
+  if (regno < 0 || regno > 66 || namelen < 7)
+    return -1;
+
+  *prefix = "%";
+  *bits = 64;
+  *type = DW_ATE_unsigned;
+  if (regno < 17)
+    {
+      *setname = "integer";
+      *type = DW_ATE_signed;
+    }
+  else if (regno < 33)
+    {
+      *setname = "SSE";
+      *bits = 128;
+    }
+  else if (regno < 41)
+    {
+      *setname = "x87";
+      *type = DW_ATE_float;
+      *bits = 80;
+    }
+  else if (regno < 49)
+    *setname = "MMX";
+  else if (regno > 49 && regno < 60)
+    {
+      *setname = "segment";
+      *bits = 16;
+    }
+  else
+    *setname = "control";
+
+  switch (regno)
+    {
+      static const char baseregs[][2] =
+	{
+	  "ax", "dx", "cx", "bx", "si", "di", "bp", "sp"
+	};
+
+    case 6 ... 7:
+      *type = DW_ATE_address;
+      FALLTHROUGH;
+    case 0 ... 5:
+      name[0] = 'r';
+      name[1] = baseregs[regno][0];
+      name[2] = baseregs[regno][1];
+      namelen = 3;
+      break;
+
+    case 8 ... 9:
+      name[0] = 'r';
+      name[1] = regno - 8 + '8';
+      namelen = 2;
+      break;
+
+    case 10 ... 15:
+      name[0] = 'r';
+      name[1] = '1';
+      name[2] = regno - 10 + '0';
+      namelen = 3;
+      break;
+
+    case 16:
+      *type = DW_ATE_address;
+      name[0] = 'r';
+      name[1] = 'i';
+      name[2] = 'p';
+      namelen = 3;
+      break;
+
+    case 17 ... 26:
+      name[0] = 'x';
+      name[1] = 'm';
+      name[2] = 'm';
+      name[3] = regno - 17 + '0';
+      namelen = 4;
+      break;
+
+    case 27 ... 32:
+      name[0] = 'x';
+      name[1] = 'm';
+      name[2] = 'm';
+      name[3] = '1';
+      name[4] = regno - 27 + '0';
+      namelen = 5;
+      break;
+
+    case 33 ... 40:
+      name[0] = 's';
+      name[1] = 't';
+      name[2] = regno - 33 + '0';
+      namelen = 3;
+      break;
+
+    case 41 ... 48:
+      name[0] = 'm';
+      name[1] = 'm';
+      name[2] = regno - 41 + '0';
+      namelen = 3;
+      break;
+
+    case 50 ... 55:
+      name[0] = "ecsdfg"[regno - 50];
+      name[1] = 's';
+      namelen = 2;
+      break;
+
+    case 58 ... 59:
+      *type = DW_ATE_address;
+      *bits = 64;
+      name[0] = regno - 58 + 'f';
+      return stpcpy (&name[1], "s.base") + 1 - name;
+
+    case 49:
+      *setname = "integer";
+      return stpcpy (name, "rflags") + 1 - name;
+    case 62:
+      return stpcpy (name, "tr") + 1 - name;
+    case 63:
+      return stpcpy (name, "ldtr") + 1 - name;
+    case 64:
+      return stpcpy (name, "mxcsr") + 1 - name;
+
+    case 65 ... 66:
+      *bits = 16;
+      name[0] = 'f';
+      name[1] = "cs"[regno - 65];
+      name[2] = 'w';
+      namelen = 3;
+      break;
+
+    default:
+      return 0;
+    }
+
+  name[namelen++] = '\0';
+  return namelen;
+}
diff --git a/backends/x86_64_reloc.def b/backends/x86_64_reloc.def
new file mode 100644
index 0000000..07a7c3d
--- /dev/null
+++ b/backends/x86_64_reloc.def
@@ -0,0 +1,65 @@
+/* List the relocation types for x86-64.  -*- C -*-
+   Copyright (C) 2000, 2001, 2002, 2003, 2005, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/*	    NAME,	REL|EXEC|DYN	*/
+
+RELOC_TYPE (NONE,	0)
+RELOC_TYPE (64,		REL|EXEC|DYN)
+RELOC_TYPE (PC32,	REL|EXEC|DYN)
+RELOC_TYPE (GOT32,	REL)
+RELOC_TYPE (PLT32,	REL)
+RELOC_TYPE (COPY,	EXEC|DYN)
+RELOC_TYPE (GLOB_DAT,	EXEC|DYN)
+RELOC_TYPE (JUMP_SLOT,	EXEC|DYN)
+RELOC_TYPE (RELATIVE,	EXEC|DYN)
+RELOC_TYPE (GOTPCREL,	REL)
+RELOC_TYPE (32,		REL|EXEC|DYN)
+RELOC_TYPE (32S,	REL)
+RELOC_TYPE (16,		REL)
+RELOC_TYPE (PC16,	REL)
+RELOC_TYPE (8,		REL)
+RELOC_TYPE (PC8,	REL)
+RELOC_TYPE (DTPMOD64,	EXEC|DYN)
+RELOC_TYPE (DTPOFF64,	EXEC|DYN)
+RELOC_TYPE (TPOFF64,	EXEC|DYN)
+RELOC_TYPE (TLSGD,	REL)
+RELOC_TYPE (TLSLD,	REL)
+RELOC_TYPE (DTPOFF32,	REL)
+RELOC_TYPE (GOTTPOFF,	REL)
+RELOC_TYPE (TPOFF32,	REL)
+RELOC_TYPE (PC64,	REL|EXEC|DYN)
+RELOC_TYPE (GOTOFF64,	REL)
+RELOC_TYPE (GOTPC32,	REL)
+RELOC_TYPE (SIZE32,	REL|EXEC|DYN)
+RELOC_TYPE (SIZE64,	REL|EXEC|DYN)
+RELOC_TYPE (GOTPC32_TLSDESC, REL)
+RELOC_TYPE (TLSDESC_CALL, REL)
+RELOC_TYPE (TLSDESC,	REL|EXEC|DYN)
+RELOC_TYPE (IRELATIVE,	EXEC|DYN)
+RELOC_TYPE (GOTPCRELX,	REL)
+RELOC_TYPE (REX_GOTPCRELX, REL)
diff --git a/backends/x86_64_retval.c b/backends/x86_64_retval.c
new file mode 100644
index 0000000..c29ee0e
--- /dev/null
+++ b/backends/x86_64_retval.c
@@ -0,0 +1,193 @@
+/* Function return value location for Linux/x86-64 ABI.
+   Copyright (C) 2005-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+
+/* %rax, or pair %rax, %rdx.  */
+static const Dwarf_Op loc_intreg[] =
+  {
+    { .atom = DW_OP_reg0 }, { .atom = DW_OP_piece, .number = 8 },
+    { .atom = DW_OP_reg1 }, { .atom = DW_OP_piece, .number = 8 },
+  };
+#define nloc_intreg	1
+#define nloc_intregpair	4
+
+/* %st(0), or pair %st(0), %st(1).  */
+static const Dwarf_Op loc_x87reg[] =
+  {
+    { .atom = DW_OP_regx, .number = 33 },
+    { .atom = DW_OP_piece, .number = 10 },
+    { .atom = DW_OP_regx, .number = 34 },
+    { .atom = DW_OP_piece, .number = 10 },
+  };
+#define nloc_x87reg	1
+#define nloc_x87regpair	4
+
+/* %xmm0, or pair %xmm0, %xmm1.  */
+static const Dwarf_Op loc_ssereg[] =
+  {
+    { .atom = DW_OP_reg17 }, { .atom = DW_OP_piece, .number = 16 },
+    { .atom = DW_OP_reg18 }, { .atom = DW_OP_piece, .number = 16 },
+  };
+#define nloc_ssereg	1
+#define nloc_sseregpair	4
+
+/* The return value is a structure and is actually stored in stack space
+   passed in a hidden argument by the caller.  But, the compiler
+   helpfully returns the address of that space in %rax.  */
+static const Dwarf_Op loc_aggregate[] =
+  {
+    { .atom = DW_OP_breg0, .number = 0 }
+  };
+#define nloc_aggregate 1
+
+
+int
+x86_64_return_value_location (Dwarf_Die *functypedie, const Dwarf_Op **locp)
+{
+  /* Start with the function's type, and get the DW_AT_type attribute,
+     which is the type of the return value.  */
+  Dwarf_Die die_mem, *typedie = &die_mem;
+  int tag = dwarf_peeled_die_type (functypedie, typedie);
+  if (tag <= 0)
+    return tag;
+
+  Dwarf_Word size;
+  switch (tag)
+    {
+    case -1:
+      return -1;
+
+    case DW_TAG_subrange_type:
+      if (! dwarf_hasattr_integrate (typedie, DW_AT_byte_size))
+	{
+	  Dwarf_Attribute attr_mem, *attr;
+	  attr = dwarf_attr_integrate (typedie, DW_AT_type, &attr_mem);
+	  typedie = dwarf_formref_die (attr, &die_mem);
+	  tag = DWARF_TAG_OR_RETURN (typedie);
+	}
+      FALLTHROUGH;
+
+    case DW_TAG_base_type:
+    case DW_TAG_enumeration_type:
+    CASE_POINTER:
+      {
+	Dwarf_Attribute attr_mem;
+	if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_byte_size,
+						   &attr_mem), &size) != 0)
+          {
+	    if (dwarf_is_pointer (tag))
+	      size = 8;
+	    else
+	      return -1;
+	  }
+      }
+
+      if (tag == DW_TAG_base_type)
+	{
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Word encoding;
+	  if (dwarf_formudata (dwarf_attr_integrate (typedie, DW_AT_encoding,
+						     &attr_mem),
+			       &encoding) != 0)
+	    return -1;
+
+	  switch (encoding)
+	    {
+	    case DW_ATE_complex_float:
+	      switch (size)
+		{
+		case 4 * 2:	/* complex float */
+		case 8 * 2:	/* complex double */
+		  *locp = loc_ssereg;
+		  return nloc_sseregpair;
+		case 16 * 2:	/* complex long double */
+		  *locp = loc_x87reg;
+		  return nloc_x87regpair;
+		}
+	      return -2;
+
+	    case DW_ATE_float:
+	      switch (size)
+		{
+		case 4:	/* float */
+		case 8:	/* double */
+		  *locp = loc_ssereg;
+		  return nloc_ssereg;
+		case 16:	/* long double */
+		  /* XXX distinguish __float128, which is sseregpair?? */
+		  *locp = loc_x87reg;
+		  return nloc_x87reg;
+		}
+	      return -2;
+	    }
+	}
+
+    intreg:
+      *locp = loc_intreg;
+      if (size <= 8)
+	return nloc_intreg;
+      if (size <= 16)
+	return nloc_intregpair;
+
+    large:
+      *locp = loc_aggregate;
+      return nloc_aggregate;
+
+    case DW_TAG_structure_type:
+    case DW_TAG_class_type:
+    case DW_TAG_union_type:
+    case DW_TAG_array_type:
+      if (dwarf_aggregate_size (typedie, &size) != 0)
+	goto large;
+      if (size > 16)
+	goto large;
+
+      /* XXX
+	 Must examine the fields in picayune ways to determine the
+	 actual answer.  This will be right for small C structs
+	 containing integer types and similarly simple cases.
+      */
+
+      goto intreg;
+    }
+
+  /* XXX We don't have a good way to return specific errors from ebl calls.
+     This value means we do not understand the type, but it is well-formed
+     DWARF and might be valid.  */
+  return -2;
+}
diff --git a/backends/x86_64_symbol.c b/backends/x86_64_symbol.c
new file mode 100644
index 0000000..d5f62e8
--- /dev/null
+++ b/backends/x86_64_symbol.c
@@ -0,0 +1,81 @@
+/* x86_64 specific symbolic name handling.
+   Copyright (C) 2002, 2005, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <elf.h>
+#include <stddef.h>
+
+#define BACKEND		x86_64_
+#include "libebl_CPU.h"
+
+/* Check for the simple reloc types.  */
+Elf_Type
+x86_64_reloc_simple_type (Ebl *ebl __attribute__ ((unused)), int type,
+			  int *addsub __attribute__ ((unused)))
+{
+  switch (type)
+    {
+    case R_X86_64_64:
+      return ELF_T_XWORD;
+    case R_X86_64_32:
+      return ELF_T_WORD;
+    case R_X86_64_32S:
+      return ELF_T_SWORD;
+    case R_X86_64_16:
+      return ELF_T_HALF;
+    case R_X86_64_8:
+      return ELF_T_BYTE;
+    default:
+      return ELF_T_NUM;
+    }
+}
+
+/* Return symbolic representation of section type.  */
+const char *
+x86_64_section_type_name (int type,
+			  char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+  if (type == SHT_X86_64_UNWIND)
+    return "X86_64_UNWIND";
+
+  return NULL;
+}
+
+/* The SHT_X86_64_UNWIND section type is a valid target for relocation.  */
+bool
+x86_64_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)),
+				Elf64_Word sh_type)
+{
+  return sh_type == SHT_X86_64_UNWIND;
+}
diff --git a/backends/x86_64_unwind.c b/backends/x86_64_unwind.c
new file mode 100644
index 0000000..ade64c0
--- /dev/null
+++ b/backends/x86_64_unwind.c
@@ -0,0 +1,86 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2016 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <assert.h>
+
+#define BACKEND x86_64_
+#include "libebl_CPU.h"
+
+/* There was no CFI. Maybe we happen to have a frame pointer and can unwind from that?  */
+
+bool
+x86_64_unwind (Ebl *ebl __attribute__ ((unused)),
+               Dwarf_Addr pc __attribute__ ((unused)),
+               ebl_tid_registers_t *setfunc, ebl_tid_registers_get_t *getfunc,
+               ebl_pid_memory_read_t *readfunc, void *arg,
+               bool *signal_framep __attribute__ ((unused)))
+{
+  // Register 6 is supposed to be rbp, thus the conventional frame pointer
+  const int fpReg = 6;
+  const int spReg = 7;
+
+  Dwarf_Word fp;
+  if (!getfunc(fpReg, 1, &fp, arg) || fp == 0)
+    return false;
+
+  // Try to read old sp, so that we can avoid infinite loops below
+  Dwarf_Word sp;
+  if (!getfunc(spReg, 1, &sp, arg))
+    sp = 0;
+
+  Dwarf_Word prev_fp;
+  if (!readfunc(fp, &prev_fp, arg))
+    prev_fp = 0;
+
+  Dwarf_Word ret;
+  if (!readfunc(fp + 8, &ret, arg))
+    return false;
+
+  if (!setfunc(fpReg, 1, &prev_fp, arg))
+    return false;
+
+  fp += 16; // Pop fp and return address and write result to sp
+  if (!setfunc(spReg, 1, &fp, arg))
+    return false;
+
+  if (!setfunc(-1, 1, &ret, arg))
+    return false;
+
+  // If the sp didn't move up we don't actually have a new stack
+  // frame but rather some random data that doesn't include frame
+  // pointers. Break the unwinding then.
+  if (sp >= fp)
+    return false;
+
+  return true;
+}
diff --git a/backends/x86_corenote.c b/backends/x86_corenote.c
new file mode 100644
index 0000000..629462c
--- /dev/null
+++ b/backends/x86_corenote.c
@@ -0,0 +1,51 @@
+/* x86-specific core note handling, pieces common to x86-64 and i386.
+   Copyright (C) 2005-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define	EXTRA_NOTES_IOPERM \
+  case NT_386_IOPERM: \
+    return ioperm_info (nhdr->n_descsz, \
+			regs_offset, nregloc, reglocs, nitems, items);
+
+static int
+ioperm_info (GElf_Word descsz, GElf_Word *regs_offset,
+	     size_t *nregloc, const Ebl_Register_Location **reglocs,
+	     size_t *nitems, const Ebl_Core_Item **items)
+{
+  static const Ebl_Core_Item ioperm_item =
+    { .type = ELF_T_WORD, .format = 'b', .name = "ioperm" };
+
+  if (descsz % 4 != 0)
+    return 0;
+
+  *regs_offset = 0;
+  *nregloc = 0;
+  *reglocs = NULL;
+  *nitems = 1;
+  *items = &ioperm_item;
+  return 1;
+}
diff --git a/config.h b/config.h
new file mode 100644
index 0000000..d51ae48
--- /dev/null
+++ b/config.h
@@ -0,0 +1,231 @@
+/* GOOGLE: Generated by configure to build in the Google environment. */
+/* cmdline: ./configure --enable-maintainer-mode --without-lzma --with-zstd --disable-debuginfod --disable-libdebuginfod */
+
+/* config.h.  Generated from config.h.in by configure.  */
+/* config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Building with -fsanitize=undefined or not */
+#define CHECK_UNDEFINED 0
+
+/* Should ar and ranlib use -D behavior by default? */
+#define DEFAULT_AR_DETERMINISTIC false
+
+/* Build dummy libdebuginfod */
+/* #undef DUMMY_LIBDEBUGINFOD */
+
+/* Build debuginfod */
+/* #undef ENABLE_DEBUGINFOD */
+
+/* Enable libdebuginfod */
+/* #undef ENABLE_LIBDEBUGINFOD */
+
+/* Define to 1 if translation of program messages to the user's native
+   language is requested. */
+#define ENABLE_NLS 1
+
+/* Define to 1 if you have the Mac OS X function
+   CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
+/* #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES */
+
+/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
+   the CoreFoundation framework. */
+/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
+
+/* define if the compiler supports basic C++11 syntax */
+#define HAVE_CXX11 1
+
+/* Define if the GNU dcgettext() function is already present or preinstalled.
+   */
+#define HAVE_DCGETTEXT 1
+
+/* Define to 1 if you have the declaration of `mempcpy', and to 0 if you
+   don't. */
+#define HAVE_DECL_MEMPCPY 1
+
+/* Define to 1 if you have the declaration of `memrchr', and to 0 if you
+   don't. */
+#define HAVE_DECL_MEMRCHR 1
+
+/* Define to 1 if you have the declaration of `powerof2', and to 0 if you
+   don't. */
+#define HAVE_DECL_POWEROF2 1
+
+/* Define to 1 if you have the declaration of `rawmemchr', and to 0 if you
+   don't. */
+/* GOOGLE: musl support */
+#if defined(__GLIBC__) || defined(__NEWLIB__) || defined(__UCLIBC__)
+#define HAVE_DECL_RAWMEMCHR 1
+#else
+/* #undef HAVE_DECL_RAWMEMCHR */
+#endif
+
+/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you
+   don't. */
+#define HAVE_DECL_REALLOCARRAY 1
+
+/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
+   don't. */
+#define HAVE_DECL_STRERROR_R 1
+
+/* Define to 1 if you have the <error.h> header file. */
+/* GOOGLE: musl support */
+#if defined(__BIONIC__) || defined(__GLIBC__) || defined(__NEWLIB__) || \
+    defined(__UCLIBC__)
+#define HAVE_ERROR_H 1
+#else
+/* #undef HAVE_ERROR_H */
+#endif
+
+/* Define to 1 if you have the <err.h> header file. */
+/* GOOGLE: musl support */
+#if defined(__NEWLIB__)
+/* undef HAVE_ERR_H */
+#else
+#define HAVE_ERR_H 1
+#endif
+
+/* Define to 1 if you have the <execinfo.h> header file. */
+#define HAVE_EXECINFO_H 1
+
+/* Defined if __attribute__((fallthrough)) is supported */
+/* GOOGLE: #undef HAVE_FALLTHROUGH */
+
+/* Defined if __attribute__((gcc_struct)) is supported */
+/* GOOGLE: #undef HAVE_GCC_STRUCT */
+
+/* Define to 1 if you have the `getrlimit' function. */
+#define HAVE_GETRLIMIT 1
+
+/* Define if the GNU gettext() function is already present or preinstalled. */
+#define HAVE_GETTEXT 1
+
+/* Define if you have the iconv() function and it works. */
+/* #undef HAVE_ICONV */
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 0 if libarchive is not available */
+/* #undef HAVE_LIBARCHIVE */
+
+/* Define to 1 if you have the `mremap' function. */
+#define HAVE_MREMAP 1
+
+/* Define to 1 if you have the `process_vm_readv' function. */
+#define HAVE_PROCESS_VM_READV 1
+
+/* Enable pthread_setname_np */
+#define HAVE_PTHREAD_SETNAME_NP 1
+
+/* Define to 1 if you have the `sched_getaffinity' function. */
+#define HAVE_SCHED_GETAFFINITY 1
+
+/* Define to 1 if you have the <sched.h> header file. */
+#define HAVE_SCHED_H 1
+
+/* Define to 1 if `stdatomic.h` is provided by the system, 0 otherwise. */
+#define HAVE_STDATOMIC_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define if you have `strerror_r'. */
+#define HAVE_STRERROR_R 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the <sys/resource.h> header file. */
+#define HAVE_SYS_RESOURCE_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if <sys/user.h> defines struct user_regs_struct */
+#define HAVE_SYS_USER_REGS 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Defined if __attribute__((visibility())) is supported */
+#define HAVE_VISIBILITY 1
+
+/* Name of package */
+#define PACKAGE "elfutils"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "https://sourceware.org/bugzilla"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "elfutils"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "elfutils 0.191"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "elfutils"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL "http://elfutils.org/"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "0.191"
+
+/* The size of `long', as computed by sizeof. */
+#define SIZEOF_LONG 8
+
+/* Define to 1 if all of the C90 standard headers exist (not just the ones
+   required in a freestanding environment). This macro is provided for
+   backward compatibility; new code need not use it. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if strerror_r returns char *. */
+#define STRERROR_R_CHAR_P 1
+
+/* Support bzip2 decompression via -lbz2. */
+#define USE_BZLIB 1
+
+/* Defined if demangling is enabled */
+#define USE_DEMANGLE 1
+
+/* Defined if libraries should be thread-safe. */
+/* #undef USE_LOCKS */
+
+/* Support LZMA (xz) decompression via -llzma. */
+/* #undef USE_LZMA */
+
+/* Support gzip decompression via -lz. */
+#define USE_ZLIB 1
+
+/* Support ZSTD (zst) decompression via -lzstd. */
+#define USE_ZSTD 1
+
+/* zstd compression support */
+#define USE_ZSTD_COMPRESS 1
+
+/* Version number of package */
+#define VERSION "0.191"
+
+/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
+   `char[]'. */
+#define YYTEXT_POINTER 1
+
+/* Number of bits in a file offset, on hosts where this is settable. */
+/* #undef _FILE_OFFSET_BITS */
+
+/* Define for large files, on AIX-style hosts. */
+/* #undef _LARGE_FILES */
+
+#include <eu-config.h>
diff --git a/config/10-default-yama-scope.conf b/config/10-default-yama-scope.conf
new file mode 100644
index 0000000..4df2090
--- /dev/null
+++ b/config/10-default-yama-scope.conf
@@ -0,0 +1,35 @@
+# When yama is enabled in the kernel it might be used to filter any user
+# space access which requires PTRACE_MODE_ATTACH like ptrace attach, access
+# to /proc/PID/{mem,personality,stack,syscall}, and the syscalls
+# process_vm_readv and process_vm_writev which are used for interprocess
+# services, communication and introspection (like synchronisation, signaling,
+# debugging, tracing and profiling) of processes.
+#
+# Usage of ptrace attach is restricted by normal user permissions. Normal
+# unprivileged processes cannot interact through ptrace with processes
+# that they cannot send signals to or processes that are running set-uid
+# or set-gid.
+#
+# yama ptrace scope can be used to reduce these permissions even more.
+# This should normally not be done because it will break various programs
+# relying on the default ptrace security restrictions. But can be used
+# if you don't have any other way to separate processes in their own
+# domains. A different way to restrict ptrace is to set the selinux
+# deny_ptrace boolean. Both mechanisms will break some programs relying
+# on the ptrace system call and might force users to elevate their
+# privileges to root to do their work.
+#
+# For more information see Documentation/security/Yama.txt in the kernel
+# sources. Which also describes the defaults when CONFIG_SECURITY_YAMA
+# is enabled in a kernel build (currently 1 for ptrace_scope).
+#
+# This runtime kernel parameter can be set to the following options:
+# (Note that setting this to anything except zero will break programs!)
+#
+# 0 - Default attach security permissions.
+# 1 - Restricted attach. Only child processes plus normal permissions.
+# 2 - Admin-only attach. Only executables with CAP_SYS_PTRACE.
+# 3 - No attach. No process may call ptrace at all. Irrevocable.
+#
+kernel.yama.ptrace_scope = 0
+
diff --git a/config/ChangeLog b/config/ChangeLog
new file mode 100644
index 0000000..ce1f74f
--- /dev/null
+++ b/config/ChangeLog
@@ -0,0 +1,643 @@
+2023-02-21  Mark Wielaard  <mark@klomp.org>
+
+	* eu.am (USE_AFTER_FREE3_WARNING): Define.
+	(AM_CFLAGS): Use USE_AFTER_FREE3_WARNING.
+
+2022-10-02  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.188.
+	Include %{_mandir}/man8/debuginfod*.8* for new
+	debuginfod-service.8 man page.
+	Remove duplicate %{_sysconfdir}/sysconfig/debuginfod.
+
+2022-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Escape % in comments.
+
+2022-10-27  Mark Wielaard  <mark@klomp.org>
+
+	* eu.am: Use grep -F instead of fgrep.
+
+2022-10-27  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Add BuildRequires socat.
+
+2022-08-17  Martin Liska  <mliska@suse.cz>
+
+	* debuginfod.service: Add new debuginfod.sysconfig
+	value DEBUGINFOD_EXTRA_ARGS.
+	* debuginfod.sysconfig: Likewise.
+
+2022-08-16  Martin Liska  <mliska@suse.cz>
+
+	* profile.csh.in: Support nullglob in profile.*.in files.
+	* profile.sh.in: Likewise.
+
+2022-08-17  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.sysconfig: Clarify cmdline vs client-env variables.
+
+2022-05-03  Mark Wielaard  <mark@klomp.org>
+
+	* profile.csh.in: Move the 2>/dev/null inside the sh -c '' quotes.
+
+2022-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.187.
+
+2022-01-19  Ahelenia Ziemiańska <nabijaczleweli@nabijaczleweli.xyz>
+
+	* profile.csh.in: Set DEBUGINFOD_URLS directly. Use "$0" and :
+	in sh -c.
+	* profile.sh.in: Set DEBUGINFOD_URLS directly. Don't use sh -c.
+	Use $() instead of ``.
+
+2022-04-07  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in (debuginfod-client): Add an explicit requires
+	on elfutils-libs and elfutils-libelf.
+
+2021-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.186.
+
+2021-10-03  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR27783
+	* profile.sh, profile.csh: Rewrite to document and set DEBUGINFOD_URLS
+	from /etc/debuginfod/*.urls files.
+	* Makefile.am: Install the configury-specified .urls file.
+	* elfutils.spec: Package it.
+
+2021-09-05  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* eu.am (STACK_USAGE_NO_ERROR): New variable.
+
+2021-07-06  Alice Zhang  <alizhang@redhat.com>
+
+	* debuginfod.sysconfig: Introduce default retry limit.
+
+2021-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.185.
+
+2021-05-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* elfutils.spec.in: Add procps to BuildRequires: for %check.
+
+2021-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.184.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* eu.am (NO_PACKED_NOT_ALIGNED_WARNING): New variable.
+	(AM_CFLAGS): Use NO_PACKED_NOT_ALIGNED_WARNING.
+	(AM_CXXFLAGS): Likewise.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* eu.am (TRAMPOLINES_WARNING): New variable.
+	(AM_CFLAGS): Use TRAMPOLINES_WARNING.
+	(AM_CXXFLAGS): Likewise.
+
+2021-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Escape %%check in comment.
+
+2021-02-05  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.183.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* 10-default-yama-scope.conf: Fix spelling typo in comment.
+	* upload-release.sh: Likewise.
+	* elfutils.spec.in: Fix spelling typos in %changelog.
+
+2020-11-04  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* profile.sh.in, profile.csh.in: Do not define $DEBUGINFOD_URLS unless
+	configured using --enable-debuginfod-urls.
+
+2020-11-02  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (pkgconfig_DATA, install-data-local, uninstall-local):
+	Conditionalize on LIBDEBUGINFOD instead of DEBUGINFOD.
+
+2020-10-31  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (install-data-local, uninstall-local): Conditionalize
+	on DEBUGINFOD.
+
+2020-10-30  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.182.
+
+2020-10-31  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.service: Bump up TimeoutStopSec.
+
+2020-10-30  Frank Ch. Eigler  <fche@redhat.com>
+
+	* elfutils.spec.in: Fix debuginfod config/state file attributes
+	for non-lossy updates.
+
+2020-10-08  Frank Ch. Eigler  <fche@redhat.com>
+
+	* Makefile.am (uninstall-local): Uninstall the new profile.d files.
+
+2020-10-01  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR25461
+	* profile.sh.in, profile.csh.in: New files for /etc/profile.d
+	to define $DEBUGINFOD_URLS.
+	* elfutils.spec.in: Configure with --enable-debuginfod-urls.
+	* Makefile.am: Install them.
+
+2020-09-18  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Add BuildRequires for libzstd-devel and zstd.
+	* libdw.pc.in: Requires.private libzstd.
+
+2020-09-08  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.181.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* upload-release.sh: Use /usr/bin/env bash.
+
+2020-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.189.
+
+2020-04-21  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.sysconfig (DEBUGINFOD_PATHS): Add /var/lib/pulp.
+
+2020-03-30  Mark Wielaard  <mark@klomp.org>
+
+	* upload-release.sh: chmod uploaded dir and files to make them
+	readable.
+
+2020-03-30  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.179.
+
+2020-03-25  Frank Ch. Eigler <fche@redhat.com>
+
+	* elfutils.spec.in: *Require: bsdtar instead of dpkg.
+
+2020-03-04  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in (package debuginfod): Remove Requires: rpm.
+	Add Requires: dpkg.
+
+2020-01-12  Frank Ch. Eigler  <fche@redhat.com>
+
+	* elfutils.spec.in: Typo fix for "Requires: debuginfod-client".
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.service: Set PrivateTmp=yes.
+
+2020-01-01  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (pkgconfig_DATA): Conditionalize libdebuginfod.pc
+	on DEBUGINFOD.
+
+2019-12-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* elfutils.spec.in (debuginfod): Add BuildRequire dpkg
+	for deb testing.  (Available on Fedora & EPEL, not base RHEL.)
+
+2019-12-05  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Add explicit version-release requires for all
+	packages.
+
+2019-11-28  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in (debuginfod): Add an explicit Requires
+	elfutils-debuginfod-client.
+
+2019-11-27  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Move all versioned libdebuginfod libraries
+	from debuginfod-client-devel to debuginfod-client.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Remove Group tags, remove fedora and rhel
+	specifics, introduce elfutils-libs subpackage, move Requires
+	and BuildRequires around for new subpackage, remove dot at end
+	of Summary tags, add post/postun ldconfig for libs and
+	debuginfod-client, remove default defattr(-,root,root) for file
+	lists, order binaries by name.
+
+2019-11-25  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Add BuildRequires curl.
+
+2019-10-28  Frank Ch. Eigler  <fche@redhat.com>
+
+	* eu.am (AM_CXXFLAGS): Clone & amend AM_CFLAGS for c++11 code.
+	* debuginfod.service, debuginfod.sysconfig: New files: systemd.
+	* Makefile.am: Install them.
+	* elfutils.spec.in: Add debuginfod and debuginfod-client subrpms.
+
+2019-08-29  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in (%description devel): Remove libebl text.
+	(%install): Don't touch backend lib.*.so* files.
+	(%files): Remove backends dir and so files.
+	(%files devel): Remove libebl.h and libebl.a
+
+2019-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in (License): Add GFDL.
+	(%install): Correct sub-shell syntax, use (), not {}.
+	(%files): Add man1/eu-*.1*.
+	Add eu-stack. Add COPYING-GFDL.
+	(%files libelf-devel): Add man3/elf_*.3*.
+
+2019-08-14  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* elfutils.spec.in (%files): Add %{_bindir}/eu-elfclassify.
+
+2019-08-13  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (elfutils.spec.in): Use git --get user.name and
+	user.email.
+
+2019-04-15  Mark Wielaard  <mark@klomp.org>
+
+	* upload-release.sh: Add git tag --verify.
+
+2019-02-14  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.176.
+
+2018-11-19  Mark Wielaard  <mark@klomp.org>
+
+	* eu.am (AM_CFLAGS): Add -Wtrampolines.
+
+2018-07-04  Mark Wielaard  <mark@klomp.org>
+
+	* upload-release.sh: New file.
+
+2018-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.172.
+
+2018-06-01  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.171.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* eu.am (IMPLICIT_FALLTHROUGH_WARNING): Set to 5.
+
+2017-11-02  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Config files under /usr/lib/sysctl.d (_sysctldir)
+	aren't %config.
+
+2017-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* eu.am (AM_CFLAGS): Handle -Wno-packed-not-aligned.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* eu.am: Use fpic_CFLAGS.
+
+2016-08-02  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.170.
+
+2017-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* elfutils.spec.in: Update for 0.169.
+
+2016-12-27  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.168 and new project location.
+
+2016-12-24  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.pc.in: Set URL to http://elfutils.org/
+	* libelf.pc.in: Likewise.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am: Check HAVE_IMPLICIT_FALLTHROUGH_WARNING.
+	(AM_CFLAGS): Add IMPLICIT_FALLTHROUGH_WARNING.
+
+2016-08-04  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.167.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Remove eu-ld.
+
+2016-03-31  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.166.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am: Check HAVE_NULL_DEREFERENCE_WARNING.
+	(AM_CFLAGS): Add NULL_DEREFERENCE_WARNING.
+
+2016-02-09  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am: Check SANE_LOGICAL_OP_WARNING and
+	HAVE_DUPLICATED_COND_WARNING.
+	(AM_CFLAGS): Add LOGICAL_OP_WARNING and DUPLICATED_COND_WARNING.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Add elfcompress. Update for 0.165.
+
+2016-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* libelf.pc.in: New file.
+	* libdw.pc.in: Likewise.
+	* Makefile.am (EXTRA_DIST): Add libelf.pc.in and libdw.pc.in.
+	(pkgconfigdir): New variable.
+	(pkgconfigdir_DATA): Likewise.
+	* elfutils.spec.in (files devel): Add libdw.pc.
+	(files libelf-devel): Add libelf.pc.
+
+2015-10-15  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.164.
+
+2015-10-07  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am (ARFLAGS): Set to "cr".
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* eu.am (print-%): New target to print any variable.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* eu.am (%.os): Add AM_V_CC silencers.
+
+2015-09-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* eu.am (%.os): Use -fPIC instead of -fpic to avoid relocation
+	overflows in some platforms.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am (AM_CFLAGS): Add -Wold-style-definition -Wstrict-prototypes.
+
+2015-08-04  Mark Wielaard  <mjw@redhat.com>
+
+	* 10-default-yama-scope.conf: New file.
+	* Makefile.am (EXTRA_DIST): Add 10-default-yama-scope.conf.
+	* elfutils.spec.in (Requires): default-yama-scope.
+	(default-yama-scope): New package.
+
+2015-06-19  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.163.
+
+2015-06-11  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in (devel): Include elfutils/known-dwarf.h and
+	elfutils/version.h.
+
+2015-06-10  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.162.
+
+2015-05-23  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am (STACK_USAGE_WARNING): New variable set based on
+	ADD_STACK_USAGE_WARNING conditional.
+	(AM_CFLAGS): Use STACK_USAGE_WARNING variable.
+
+2015-05-23  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am (AM_CFLAGS): Add -Wstack-usage=262144.
+
+2015-04-23  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* eu.am (DEFS.os): New variable.
+
+2015-03-18  Petr Machata  <pmachata@redhat.com>
+
+	* known-dwarf.awk (comment): Drop all uses of this variable.
+	(END): Always emit the non-_DESC variant.  Emit
+	DWARF_ALL_KNOWN_DW_ instead of ALL_KNOWN_DW_*, and
+	DWARF_ONE_KNOWN_DW_ instead of ONE_KNOWN_DW_*.
+
+2015-02-20  Petr Machata  <pmachata@redhat.com>
+
+	* known-dwarf.awk (END): Drop useless variables lo, hi.  Merge two
+	continue-checks in one.
+
+2014-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.161.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am: Define textrel_msg, textrel_found and textrel_check based
+	on FATAL_TEXTREL.
+
+2014-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.160.
+
+2014-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.159.
+	(%files devel): Add libdwelf.h.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am (AM_CFLAGS): Don't add -fmudflap.
+	(COMPILE.os): Don't remove no_mudflap.os.
+
+2014-01-22  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am (AM_CFLAGS): Unconditionally add -Wformat=2.
+
+2014-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for 0.158.
+
+2013-11-01  Michael Forney  <mforney@mforney.org>
+
+	* eu.am: Use READELF.
+
+2013-09-30  Mark Wielaard  <mjw@redhat.com>
+
+	* elfutils.spec.in: Update for readelf NT_SIGINFO and NT_FILE
+	core notes.
+
+2013-09-27  Mark Wielaard  <mjw@redhat.com>
+
+	* config/elfutils.spec.in: Update for 0.157.
+
+2013-07-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* config/elfutils.spec.in: Update for 0.156.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* eu.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2012-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* config/elfutils.spec.in: Update for 0.155.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* known-dwarf.awk: "Generated by" header had wrong file names,
+	mention config/known-dwarf.awk and libdw/dwarf.h contents.
+
+2012-06-22  Mark Wielaard  <mjw@redhat.com>
+
+	* config/elfutils.spec.in: Update for 0.154.
+
+2012-02-23  Mark Wielaard  <mjw@redhat.com>
+
+	* config/elfutils.spec.in: Update for 0.153.
+
+2011-10-31  Mark Wielaard  <mjw@redhat.com>
+
+	* known-dwarf.awk: Use gawk.
+
+2010-07-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Add more BuildRequires.
+	Ship the .mo files with the libelf subpackage.
+
+2010-04-15  Roland McGrath  <roland@redhat.com>
+
+	* eu.am (DEFS): Add -DLOCALEDIR=... here.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* eu.am: New file.
+
+2009-04-19  Roland McGrath  <roland@redhat.com>
+
+	* version.h.in: Revert last change.
+
+2009-04-17  Roland McGrath  <roland@redhat.com>
+
+	* version.h.in (_ELFUTILS_PREREQ): Multiple major by 1000000 and minor
+	by 1000; now _ELFUTILS_VERSION is 789000 for version 0.789.
+
+2009-01-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Distribute <elfutils/version.h> in
+	elfutils-libelf-devel.
+
+2009-01-22  Roland McGrath  <roland@redhat.com>
+
+	* known-dwarf.awk: Handle DW_FOO_BAR_* sets better.
+
+2009-01-11  Roland McGrath  <roland@redhat.com>
+
+	* known-dwarf.awk: New file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2008-12-24  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am ($(srcdir)/elfutils.spec.in): Rewrite awk magic.
+	Put the target inside [if MAINTAINER_MODE].
+
+2008-12-16  Roland McGrath  <roland@redhat.com>
+
+	* version.h.in: New file.
+
+2008-01-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Add m4 to build requirements.
+
+2008-01-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Changes for disasm branch merge.
+
+2007-08-08  Roland McGrath  <roland@redhat.com>
+
+	* elfutils.spec.in (License): Canonicalize.
+
+2007-04-23  Roland McGrath  <roland@redhat.com>
+
+	* elfutils.spec.in: Distribute eu-unstrip.
+
+2005-08-13  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am ($(srcdir)/elfutils.spec.in): Add missing $.
+
+2005-07-28  Roland McGrath  <roland@redhat.com>
+
+	* elfutils.spec.in: Remove libdwfl.so from package.
+
+2005-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Distribute eu-elfcmp.
+
+2005-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Distribute eu-addr2line.
+
+2005-03-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Distribute libdw.{a,so,h}.
+
+2005-02-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Ignore result of cvs run.
+
+	* elfutils.spec.in: Simplify build process by not using a subdir.
+	This means we can use %configure.
+
+2005-02-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Automatically added changelog from NEWS file on dist.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Make sure RPM_OPT_FLAGS is used.  During
+	%build, really do build the binaries.
+	Remove --enable-shared configure parameters.
+
+2005-02-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in (BuildRequires): Up gcc requirement to 3.4.
+
+2004-11-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Some more changes for the RPM with the fake
+	binaries.
+
+2004-01-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.spec.in: Update BuildRequires.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: New file.
+	* config.guess: Moved to here from toplevel.
+	* config.rpath: Likewise.
+	* config.sub: Likewise.
+	* depcomp: Likewise.
+	* install-sh: Likewise.
+	* missing: Likewise.
+	* mkinstalldirs: Likewise.
+	* elfutils.spec.in: New file.
diff --git a/config/Makefile.am b/config/Makefile.am
new file mode 100644
index 0000000..0d3ba16
--- /dev/null
+++ b/config/Makefile.am
@@ -0,0 +1,73 @@
+## Process this file with automake to produce Makefile.in -*-Makefile-*-
+## Configure input file for elfutils.
+##
+## Copyright (C) 2004, 2005, 2008, 2009, 2011, 2015, 2016 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+EXTRA_DIST = elfutils.spec.in known-dwarf.awk 10-default-yama-scope.conf \
+	     libelf.pc.in libdw.pc.in libdebuginfod.pc.in \
+	     debuginfod.service debuginfod.sysconfig profile.sh.in profile.csh.in
+
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = libelf.pc libdw.pc
+if LIBDEBUGINFOD
+pkgconfig_DATA += libdebuginfod.pc
+
+install-data-local:
+	$(INSTALL_DATA) profile.sh -D $(DESTDIR)$(sysconfdir)/profile.d/debuginfod.sh
+	$(INSTALL_DATA) profile.csh -D $(DESTDIR)$(sysconfdir)/profile.d/debuginfod.csh
+	mkdir -p $(DESTDIR)$(sysconfdir)/debuginfod
+	if [ -n "@DEBUGINFOD_URLS@" ]; then \
+		echo "@DEBUGINFOD_URLS@" > $(DESTDIR)$(sysconfdir)/debuginfod/elfutils.urls; \
+	fi
+
+uninstall-local:
+	rm -f $(DESTDIR)$(sysconfdir)/profile.d/debuginfod.sh
+	rm -f $(DESTDIR)$(sysconfdir)/profile.d/debuginfod.csh
+	rm -f $(DESTDIR)$(sysconfdir)/debuginfod/elfutils.urls
+	-rmdir $(DESTDIR)$(sysconfdir)/debuginfod
+endif
+
+if MAINTAINER_MODE
+$(srcdir)/elfutils.spec.in: $(top_srcdir)/NEWS
+	@tmpname=$$(mktemp $${TMPDIR:-/tmp}/elfutils.XXXXXX); \
+	date +'* %a %b %e %Y' | tr '[\n]' '[ ]' > $$tmpname; \
+	username=$$(git config --get user.name); \
+	useremail=$$(git config --get user.email); \
+	echo -n "$$username <$$useremail> " >> $$tmpname; \
+	awk '\
+	  $$1 == "Version" && started { exit } \
+	  $$1 == "Version" { started=1; line=""; sub(/:/,"",$$2); \
+			     print $$2 "-1"; next } \
+	  NF > 0 { line = (line != "") ? (line " " $$0) : ("- " $$0) } \
+	  NF == 0 && line != "" { print line; line="" } \
+	  END { if (line != "") print line; print "" }' $< \
+	| fold -s -w 70 | sed '1!s/^[^-]/  &/' >> $$tmpname; \
+	sed "/^%changelog/r $$tmpname" $@ > $@.new; \
+	rm -f $$tmpname; \
+	mv -f $@.new $@
+endif
diff --git a/config/debuginfod.service b/config/debuginfod.service
new file mode 100644
index 0000000..4c7785a
--- /dev/null
+++ b/config/debuginfod.service
@@ -0,0 +1,17 @@
+[Unit]
+Description=elfutils debuginfo-over-http server
+Documentation=http://elfutils.org/
+After=network.target
+
+[Service]
+EnvironmentFile=/etc/sysconfig/debuginfod
+User=debuginfod
+Group=debuginfod
+#CacheDirectory=debuginfod
+ExecStart=/usr/bin/debuginfod -d /var/cache/debuginfod/debuginfod.sqlite -p $DEBUGINFOD_PORT $DEBUGINFOD_VERBOSE $DEBUGINFOD_PRAGMAS $DEBUGINFOD_PATHS $DEBUGINFOD_EXTRA_ARGS
+# Stopping can take a long time if scanning of large archives is in progress
+TimeoutStopSec=60
+PrivateTmp=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/config/debuginfod.sysconfig b/config/debuginfod.sysconfig
new file mode 100644
index 0000000..4ffb7e0
--- /dev/null
+++ b/config/debuginfod.sysconfig
@@ -0,0 +1,26 @@
+#################
+# debuginfod command line options
+# see [man debuginfod]
+
+# required
+DEBUGINFOD_PORT="8002"
+
+# add more -v for more verbosity
+DEBUGINFOD_EXTRA_ARGS="-t43200 -F -R"
+
+# some common places to find trustworthy ELF/DWARF files and RPMs
+DEBUGINFOD_PATHS="/usr/lib/debug /usr/bin /usr/libexec /usr/sbin /usr/lib /usr/lib64 /var/cache/yum /var/cache/dnf /var/lib/pulp"
+
+# prefer sqlite database durability over performance
+#DEBUGINFOD_PRAGMAS="-D 'pragma synchronous=full;'"
+
+#################
+# these environment variables affect federated queries to upstream servers
+# see [man debuginfod-client-config]
+
+#DEBUGINFOD_URLS="http://secondhost:8002 http://thirdhost:8002"
+#DEBUGINFOD_TIMEOUT="5"
+#DEBUGINFOD_RETRY_LIMIT="2"
+#DEBUGINFOD_CACHE_DIR=""
+#DEBUGINFOD_VERBOSE="1"
+#DEBUGINFOD_PROGRESS="1"
diff --git a/config/elfutils.spec.in b/config/elfutils.spec.in
new file mode 100644
index 0000000..d6621c9
--- /dev/null
+++ b/config/elfutils.spec.in
@@ -0,0 +1,1304 @@
+# -*- rpm-spec-*-
+Name: elfutils
+Version: @PACKAGE_VERSION@
+Release: 1
+URL: http://elfutils.org/
+License: GPLv3+ and (GPLv2+ or LGPLv3+) and GFDL
+Source: ftp://sourceware.org/pub/elfutils/%{version}/elfutils-%{version}.tar.bz2
+Summary: A collection of utilities and DSOs to handle ELF files and DWARF data
+
+Requires: elfutils-libelf = %{version}-%{release}
+Requires: elfutils-libs = %{version}-%{release}
+# Can be a Recommends if rpm supports that
+Requires: elfutils-debuginfod-client = %{version}-%{release}
+
+BuildRequires: gcc
+# For libstdc++ demangle support
+BuildRequires: gcc-c++
+
+BuildRequires: gettext
+BuildRequires: bison
+BuildRequires: flex
+
+# Compression support
+BuildRequires: zlib-devel
+BuildRequires: bzip2-devel
+BuildRequires: xz-devel
+BuildRequires: libzstd-devel
+
+# For debuginfod
+BuildRequires: pkgconfig(libmicrohttpd) >= 0.9.33
+BuildRequires: pkgconfig(libcurl) >= 7.29.0
+BuildRequires: pkgconfig(sqlite3) >= 3.7.17
+BuildRequires: pkgconfig(libarchive) >= 3.1.2
+
+# For tests need to bunzip2 test files.
+BuildRequires: bzip2
+BuildRequires: zstd
+# For the run-debuginfod-find.sh test case in %%check for /usr/sbin/ss etc.
+BuildRequires: iproute
+BuildRequires: procps
+BuildRequires: bsdtar
+BuildRequires: curl
+# For run-debuginfod-response-headers.sh test case
+BuildRequires: socat
+
+%define _gnu %{nil}
+%define _programprefix eu-
+
+%description
+Elfutils is a collection of utilities, including stack (to show
+backtraces), nm (for listing symbols from object files), size
+(for listing the section sizes of an object or archive file),
+strip (for discarding symbols), readelf (to see the raw ELF file
+structures), elflint (to check for well-formed ELF files) and
+elfcompress (to compress or decompress ELF sections).
+
+%package libs
+Summary: Libraries to handle compiled objects
+License: GPLv2+ or LGPLv3+
+Requires: elfutils-libelf = %{version}-%{release}
+Requires: default-yama-scope
+# Can be a Recommends if rpm supports that
+Requires: elfutils-debuginfod-client = %{version}-%{release}
+
+%description libs
+The elfutils-libs package contains libraries which implement DWARF, ELF,
+and machine-specific ELF handling and process introspection.  These
+libraries are used by the programs in the elfutils package.  The
+elfutils-devel package enables building other programs using these
+libraries.
+
+%package devel
+Summary: Development libraries to handle compiled objects
+License: GPLv2+ or LGPLv3+
+Requires: elfutils-libs = %{version}-%{release}
+Requires: elfutils-libelf-devel = %{version}-%{release}
+# Can be a Recommends if rpm supports that
+Requires: elfutils-debuginfod-client-devel = %{version}-%{release}
+
+%description devel
+The elfutils-devel package contains the libraries to create
+applications for handling compiled objects.  libdw provides access
+to the DWARF debugging information.  libasm provides a programmable
+assembler interface.
+
+%package devel-static
+Summary: Static archives to handle compiled objects
+License: GPLv2+ or LGPLv3+
+Requires: elfutils-devel = %{version}-%{release}
+Requires: elfutils-libelf-devel-static = %{version}-%{release}
+
+%description devel-static
+The elfutils-devel-static package contains the static archives
+with the code to handle compiled objects.
+
+%package libelf
+Summary: Library to read and write ELF files
+License: GPLv2+ or LGPLv3+
+
+%description libelf
+The elfutils-libelf package provides a DSO which allows reading and
+writing ELF files on a high level.  Third party programs depend on
+this package to read internals of ELF files.  The programs of the
+elfutils package use it also to generate new ELF files.
+
+%package libelf-devel
+Summary: Development support for libelf
+License: GPLv2+ or LGPLv3+
+Requires: elfutils-libelf = %{version}-%{release}
+Conflicts: libelf-devel
+
+%description libelf-devel
+The elfutils-libelf-devel package contains the libraries to create
+applications for handling compiled objects.  libelf allows you to
+access the internals of the ELF object file format, so you can see the
+different sections of an ELF file.
+
+%package libelf-devel-static
+Summary: Static archive of libelf
+License: GPLv2+ or LGPLv3+
+Requires: elfutils-libelf-devel = %{version}-%{release}
+Conflicts: libelf-devel
+
+%description libelf-devel-static
+The elfutils-libelf-static package contains the static archive
+for libelf.
+
+%package default-yama-scope
+Summary: Default yama attach scope sysctl setting
+License: GPLv2+ or LGPLv3+
+Provides: default-yama-scope
+BuildArch: noarch
+
+%description default-yama-scope
+Yama sysctl setting to enable default attach scope settings
+enabling programs to use ptrace attach, access to
+/proc/PID/{mem,personality,stack,syscall}, and the syscalls
+process_vm_readv and process_vm_writev which are used for
+interprocess services, communication and introspection
+(like synchronisation, signaling, debugging, tracing and
+profiling) of processes.
+
+%package debuginfod-client
+Summary: Library and command line client for build-id HTTP ELF/DWARF server
+License: GPLv3+ and (GPLv2+ or LGPLv3+)
+# For debuginfod-find binary
+Requires: elfutils-libs = %{version}-%{release}
+Requires: elfutils-libelf = %{version}-%{release}
+
+%package debuginfod-client-devel
+Summary: Libraries and headers to build debuginfod client applications
+License: GPLv2+ or LGPLv3+
+Requires: elfutils-debuginfod-client = %{version}-%{release}
+
+%package debuginfod
+Summary: HTTP ELF/DWARF file server addressed by build-id
+License: GPLv3+
+Requires: elfutils-libs = %{version}-%{release}
+Requires: elfutils-libelf = %{version}-%{release}
+Requires: elfutils-debuginfod-client = %{version}-%{release}
+BuildRequires: systemd
+Requires(post):   systemd
+Requires(preun):  systemd
+Requires(postun): systemd
+Requires(pre): shadow-utils
+# To extract .deb files with a bsdtar (= libarchive) subshell
+Requires: bsdtar
+
+%description debuginfod-client
+The elfutils-debuginfod-client package contains shared libraries
+dynamically loaded from -ldw, which use a debuginfod service
+to look up debuginfo and associated data. Also includes a
+command-line frontend.
+
+%description debuginfod-client-devel
+The elfutils-debuginfod-client-devel package contains the libraries
+to create applications to use the debuginfod service.
+
+%description debuginfod
+The elfutils-debuginfod package contains the debuginfod binary
+and control files for a service that can provide ELF/DWARF
+files to remote clients, based on build-id identification.
+The ELF/DWARF file searching functions in libdwfl can query
+such servers to download those files on demand.
+
+%prep
+%setup -q
+
+%build
+%configure --program-prefix=%{_programprefix} --enable-debuginfod --enable-debuginfod-urls
+make -s %{?_smp_mflags}
+
+%install
+rm -rf ${RPM_BUILD_ROOT}
+mkdir -p ${RPM_BUILD_ROOT}%{_prefix}
+
+%make_install
+
+chmod +x ${RPM_BUILD_ROOT}%{_prefix}/%{_lib}/lib*.so*
+mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/debuginfod
+touch ${RPM_BUILD_ROOT}%{_localstatedir}/cache/debuginfod/debuginfod.sqlite
+
+# XXX Nuke unpackaged files
+( cd ${RPM_BUILD_ROOT}
+  rm -f .%{_includedir}/elfutils/libasm.h
+  rm -f .%{_libdir}/libasm.so
+  rm -f .%{_libdir}/libasm.a
+)
+
+install -Dm0644 config/10-default-yama-scope.conf ${RPM_BUILD_ROOT}%{_sysctldir}/10-default-yama-scope.conf
+
+install -Dm0644 config/debuginfod.service ${RPM_BUILD_ROOT}%{_unitdir}/debuginfod.service
+install -Dm0644 config/debuginfod.sysconfig ${RPM_BUILD_ROOT}%{_sysconfdir}/sysconfig/debuginfod
+mkdir -p ${RPM_BUILD_ROOT}%{_localstatedir}/cache/debuginfod
+touch ${RPM_BUILD_ROOT}%{_localstatedir}/cache/debuginfod/debuginfod.sqlite
+
+%check
+make -s %{?_smp_mflags} check
+
+%post libs -p /sbin/ldconfig
+%postun libs -p /sbin/ldconfig
+%post libelf -p /sbin/ldconfig
+%postun libelf -p /sbin/ldconfig
+%post debuginfod-client -p /sbin/ldconfig
+%postun debuginfod-client -p /sbin/ldconfig
+
+%post default-yama-scope
+# Due to circular dependencies might not be installed yet, so double check.
+# (systemd -> elfutils-libs -> default-yama-scope -> systemd)
+if [ -x /usr/lib/systemd/systemd-sysctl ] ; then
+%sysctl_apply 10-default-yama-scope.conf
+fi
+
+%files
+%license COPYING COPYING-GPLV2 COPYING-LGPLV3 doc/COPYING-GFDL
+%doc README TODO CONTRIBUTING SECURITY
+%{_bindir}/eu-addr2line
+%{_bindir}/eu-ar
+%{_bindir}/eu-elfclassify
+%{_bindir}/eu-elfcmp
+%{_bindir}/eu-elfcompress
+%{_bindir}/eu-elflint
+%{_bindir}/eu-findtextrel
+%{_bindir}/eu-make-debug-archive
+%{_bindir}/eu-nm
+%{_bindir}/eu-objdump
+%{_bindir}/eu-ranlib
+%{_bindir}/eu-readelf
+%{_bindir}/eu-size
+%{_bindir}/eu-srcfiles
+%{_bindir}/eu-stack
+%{_bindir}/eu-strings
+%{_bindir}/eu-strip
+%{_bindir}/eu-unstrip
+%{_mandir}/man1/eu-*.1*
+
+%files libs
+%license COPYING-GPLV2 COPYING-LGPLV3
+%{_libdir}/libasm-%{version}.so
+%{_libdir}/libdw-%{version}.so
+%{_libdir}/libasm.so.*
+%{_libdir}/libdw.so.*
+
+%files devel
+%{_includedir}/dwarf.h
+%dir %{_includedir}/elfutils
+%{_includedir}/elfutils/elf-knowledge.h
+%{_includedir}/elfutils/known-dwarf.h
+#%%{_includedir}/elfutils/libasm.h
+%{_includedir}/elfutils/libdw.h
+%{_includedir}/elfutils/libdwfl.h
+%{_includedir}/elfutils/libdwelf.h
+%{_includedir}/elfutils/version.h
+#%%{_libdir}/libasm.so
+%{_libdir}/libdw.so
+%{_libdir}/pkgconfig/libdw.pc
+
+%files devel-static
+%{_libdir}/libdw.a
+#%%{_libdir}/libasm.a
+
+%files libelf
+%license COPYING-GPLV2 COPYING-LGPLV3
+%{_libdir}/libelf-%{version}.so
+%{_libdir}/libelf.so.*
+%{_datadir}/locale/*/LC_MESSAGES/elfutils.mo
+
+%files libelf-devel
+%{_includedir}/libelf.h
+%{_includedir}/gelf.h
+%{_includedir}/nlist.h
+%{_libdir}/libelf.so
+%{_libdir}/pkgconfig/libelf.pc
+%{_mandir}/man3/elf_*.3*
+
+%files libelf-devel-static
+%{_libdir}/libelf.a
+
+%files default-yama-scope
+%{_sysctldir}/10-default-yama-scope.conf
+
+%files debuginfod-client
+%defattr(-,root,root)
+%{_libdir}/libdebuginfod-%{version}.so
+%{_libdir}/libdebuginfod.so.*
+%{_bindir}/debuginfod-find
+%{_mandir}/man1/debuginfod-find.1*
+%{_mandir}/man7/debuginfod*.7*
+%config(noreplace) %{_sysconfdir}/profile.d/*
+%config(noreplace) %{_sysconfdir}/debuginfod/*
+  
+%files debuginfod-client-devel
+%defattr(-,root,root)
+%{_libdir}/pkgconfig/libdebuginfod.pc
+%{_mandir}/man3/debuginfod_*.3*
+%{_mandir}/man7/debuginfod*.7*
+%{_includedir}/elfutils/debuginfod.h
+%{_libdir}/libdebuginfod.so
+
+%files debuginfod
+%defattr(-,root,root)
+%{_bindir}/debuginfod
+%config(noreplace) %{_sysconfdir}/sysconfig/debuginfod
+%{_unitdir}/debuginfod.service
+%{_mandir}/man8/debuginfod*.8*
+%{_mandir}/man7/debuginfod*.7*
+
+%dir %attr(0700,debuginfod,debuginfod) %{_localstatedir}/cache/debuginfod
+%ghost %attr(0600,debuginfod,debuginfod) %{_localstatedir}/cache/debuginfod/debuginfod.sqlite
+
+%pre debuginfod
+getent group debuginfod >/dev/null || groupadd -r debuginfod
+getent passwd debuginfod >/dev/null || \
+    useradd -r -g debuginfod -d /var/cache/debuginfod -s /sbin/nologin \
+            -c "elfutils debuginfo server" debuginfod
+exit 0
+
+%post debuginfod
+%systemd_post debuginfod.service
+
+%postun debuginfod
+%systemd_postun_with_restart debuginfod.service
+
+%changelog
+* Fri Mar  1 2024 Aaron Merey <amerey@redhat.com> 0.191-1
+- dwarf_addrdie now supports binaries lacking a .debug_aranges
+  section.
+- Improved support for DWARF package files.  Add new function
+  dwarf_cu_dwp_section_info.
+- debuginfod: Caching eviction logic improvements to improve retention
+  of small/frequent/slow files such as Fedora's vdso.debug.
+- srcfiles: Can now fetch the source files of a DWARF/ELF file and
+  place them into a zip.
+
+* Fri Nov  3 2023 Mark Wielaard <mark@klomp.org> 0.190-1
+- CONTRIBUTING: Switch from real name policy to known identity policy.
+  Updated ChangeLog policy (no more separate ChangeLog files).
+  There is a SECURITY bug policy now. The default branch is now 'main'.
+- libelf: Add RELR support.
+- libdw: Recognize .debug_[ct]u_index sections.
+- readelf: Support readelf -Ds, --use-dynamic --symbol.
+  Support .gdb_index version 9
+- scrlines: New tool that compiles a list of source files associated
+  with a specified dwarf/elf file.
+- debuginfod: Schema change (reindexing required, sorry!) for a 60%
+  compression in filename representation, which was a large
+  part of the sqlite index; also, more deliberate sqlite
+  -wal management during scanning using the --scan-checkpoint option.
+- backends: Various LoongArch updates.
+
+* Fri Mar  3 2023 Mark Wielaard <mark@klomp.org> 0.189-1
+- configure: eu-nm, eu-addr2line and eu-stack can provide demangled
+  symbols when linked with libstdc++. Use --disable-demangler to disable.
+  A new option --enable-sanitize-memory has been added for msan sanitizer
+  support.
+- libelf: elf_compress now supports ELFCOMPRESS_ZSTD when build
+  against libzstd
+- libdwfl: dwfl_module_return_value_location now returns 0 (no return
+  type) for DIEs that point to a DW_TAG_unspecified_type.
+- elfcompress: -t, --type= now support zstd if libelf has been build
+  with ELFCOMPRESS_ZSTD support.
+- backends: Add support for LoongArch and Synopsys ARCv2 processors.
+
+* Wed Nov  2 2022 Mark Wielaard <mark@klomp.org> 0.188-1
+- readelf: Add -D, --use-dynamic option.
+- debuginfod-client: Add $DEBUGINFOD_HEADERS_FILE setting to supply
+  outgoing HTTP headers.
+  Add new function debuginfod_find_section.
+- debuginfod: Add --disable-source-scan option.
+- libdwfl: Add new function dwfl_get_debuginfod_client.
+  Add new function dwfl_frame_reg.
+  Add new function dwfl_report_offline_memory.
+
+* Mon Apr 25 2022 Mark Wielaard <mark@klomp.org> 0.187-1
+- debuginfod: Support -C option for connection thread pooling.
+- debuginfod-client: Negative cache file are now zero sized instead
+  of no-permission files.
+- addr2line: The -A, --absolute option, which shows file names
+  includingthe full compilation directory is now the
+  default.  To get theold behavior use the new option --relative.
+- readelf, elflint: Recognize FDO Packaging Metadata ELF notes
+- libdw, debuginfo-client: Load libcurl lazily only when files need
+  to be fetched remotely. libcurl is now never loaded when
+  DEBUGINFOD_URLS is unset. And whenDEBUGINFOD_URLS is set,
+  libcurl is only loaded when the debuginfod_begin function is
+  called.
+
+* Wed Nov 10 2021 Mark Wielaard <mark@klomp.org> 0.186-1
+- debuginfod-client: Default $DEBUGINFOD_URLS is computed from
+  drop-in files /etc/debuginfod/*.urls rather than
+  hardcoded into the /etc/profile.d/debuginfod*
+  scripts.
+  Add $DEBUGINFOD_MAXSIZE and $DEBUGINFOD_MAXTIME settings
+  for skipping large/slow transfers.
+  Add $DEBUGINFOD_RETRY for retrying aborted lookups.
+- debuginfod: Supply extra HTTP response headers, describing
+  archive/file names that satisfy the requested buildid content.
+  Support -d :memory: option for in-memory databases.
+  Protect against loops in federated server configurations.
+  Add -r option to use -I/-X regexes for grooming stale files.
+  Protect against wasted CPU from duplicate concurrent requests.
+  Limit the duration of groom ops roughly to rescan (-t) times.
+  Add --passive mode for serving from read-only database.
+  Several other performance improvements & prometheus metrics.
+- libdw: Support for the NVIDIA Cuda line map extensions.
+  DW_LNE_NVIDIA_inlined_call and DW_LNE_NVIDIA_set_function_name
+  are defined in dwarf.h. New functions dwarf_linecontext and
+  dwarf_linefunctionname.
+- translations: Update Japanese translation.
+
+* Sat May 22 2021 Mark Wielaard <mark@klomp.org> 0.185-1
+- debuginfod-client: Simplify curl handle reuse so downloads which
+                     return an error are retried.
+- elfcompress: Always exit with code 0 when the operation succeeds
+               (even when nothing was done). On error the exit code is
+               now always 1.
+
+* Mon May 10 2021  Mark Wielaard <mark@klomp.org> 0.184-1
+- debuginfod: Use libarchive's bsdtar as the .deb-family file unpacker.
+- debuginfod-client: Client caches negative results. If a query for a
+		   file failed with 404, an empty 000 permission
+		   file is created in the cache. This will prevent
+		   requesting the same file for the next 10 minutes.
+- 		   Client objects now carry long-lived curl handles
+		   for outgoing connections.  This makes it more
+		   efficient for multiple sequential queries, because
+		   the TCP connections and/or TLS state info are kept
+		   around awhile, avoiding O(100ms) setup latencies.
+- libdw: handle DW_FORM_indirect when reading attributes
+- translations: Update Polish translation.
+
+* Fri Feb  5 2021 Mark Wielaard <mark@klomp.org> 0.183-1
+- debuginfod: New thread-busy metric and more detailed error metrics.
+  New --fdcache-mintmp and tracking of filesystem freespace.
+- debigonfod-client: DEBUGINFOD_SONAME macro added to debuginfod.h can
+  be used to dlopen the libdebuginfod.so library.
+  New function debuginfod_set_verbose_fd and DEBUGINFOD_VERBOSE
+  environment variable.
+- config: profile.sh and profile.csh won't export DEBUGINFOD_URLS
+  unless configured --enable-debuginfod-urls[=URLS]
+- elflint, readelf: Recognize SHF_GNU_RETAIN.
+  Handle SHT_X86_64_UNWIND as valid relocation target type.
+
+* Sat Oct 31 2020 Mark Wielaard <mark@klomp.org> 0.182-1
+- backends: Support for tilegx has been removed.
+- config: New /etc/profile.d files to provide default $DEBUGINFOD_URLS.
+- debuginfod: More efficient package traversal, tolerate various
+  errors during scanning, grooming progress is more visible and
+  interruptible, more prometheus metrics.
+- debuginfod-client: Now supports compressed (kernel) ELF images.
+- libdwfl: Add ZSTD compression support.
+
+* Tue Sep  8 2020 Mark Wielaard <mark@klomp.org> 0.181-1
+- libelf: elf_update now compensates (fixes up) a bad sh_addralign
+  for SHF_COMPRESSED sections.
+- libdebuginfod: configure now takes --enable-libdebuginfod=dummy or
+  --disable-libdebuginfod for bootstrapping.
+  DEBUGINFOD_URLS now accepts "scheme-free" urls
+  (guessing at what the user meant, either http:// or file://)
+- readelf, elflint: Handle aarch64 bti, pac bits in dynamic table and
+  gnu property notes.
+- libdw, readelf: Recognize DW_CFA_AARCH64_negate_ra_state. Allows
+  unwinding on arm64 for code that is compiled for PAC
+  (Pointer Authentication Code) as long as it isn't enabled.
+
+* Thu Jun 11 2020 Mark Wielaard <mark@klomp.org> 0.180-1
+- elflint: Allow SHF_EXCLUDE as generic section flag when --gnu is given.
+- libdw, readelf: Handle GCC LTO .gnu.debuglto_ prefix.
+- libdw: Use correct CU to resolve file names in dwarf_decl_file.
+- libdwfl: Handle debugaltlink in dwfl_standard_find_debuginfo.
+- size: Also obey radix printing for bsd format.
+- nm: Explicitly print weak 'V' or 'T' and common 'C' symbols.
+
+* Mon Mar 30 2020 Mark Wielaard <mark@klomp.org> 0.179-1
+- debuginfod-client: When DEBUGINFOD_PROGRESS is set and the program
+  doesn't install its own debuginfod_progressfn_t show download
+  progress on stderr.
+  DEBUGINFOD_TIMEOUT is now defined as seconds to get at least 100K,
+  defaults to 90 seconds.
+  Default to $XDG_CACHE_HOME/debuginfod_client.
+  New functions debuginfod_set_user_data, debuginfod_get_user_data,
+  debuginfod_get_url and debuginfod_add_http_header.
+  Support for file:// URLs.
+- debuginfod: Uses libarchive directly for reading rpm archives.
+  Support for indexing .deb/.ddeb archives through dpkg-deb or bsdtar.
+  Generic archive support through -Z EXT[=CMD]. Which can be used for
+  example for arch-linux pacman files by using -Z '.tar.zst=zstdcat'.
+  Better logging using User-Agent and X-Forwarded-For headers.
+  More prometheus metrics.
+  Support for eliding dots or extraneous slashes in path names.
+- debuginfod-find: Accept /path/names in place of buildid hex.
+- libelf: Handle PN_XNUM in elf_getphdrnum before shdr 0 is cached.
+  Ensure zlib resource cleanup on failure.
+- libdwfl: dwfl_linux_kernel_find_elf and dwfl_linux_kernel_report_offline
+  now find and handle a compressed vmlinuz image.
+- readelf, elflint: Handle PT_GNU_PROPERTY.
+- translations: Updated Ukrainian translation.
+
+* Tue Nov 26 2019 Mark Wielaard <mark@klomp.org> 0.178-1
+- debuginfod: New server, client tool and library to index and fetch
+              ELF/DWARF files addressed by build-id through HTTP.
+- doc: There are now some manual pages for functions and tools.
+- backends: The libebl libraries are no longer dynamically loaded
+            through dlopen, but are now compiled into libdw.so directly.
+- readelf: -n, --notes now takes an optional "SECTION" argument.
+           -p and -x now also handle section numbers.
+           New option --dyn-sym to show just the dynamic symbol table.
+- libcpu: Add RISC-V disassembler.
+- libdw: Abbrevs and DIEs can now be read concurrently by multiple
+         threads through the same Dwarf handle.
+- libdwfl: Will try to use debuginfod when installed as fallback to
+           retrieve ELF and DWARF debug data files by build-id.
+
+* Tue Aug 13 2019 Mark Wielaard <mark@klomp.org> 0.177-1
+- elfclassify: New tool to analyze ELF objects.
+- readelf: Print DW_AT_data_member_location as decimal offset.
+           Decode DW_AT_discr_list block attributes.
+- libdw: Add DW_AT_GNU_numerator, DW_AT_GNU_denominator and DW_AT_GNU_bias.
+- libdwelf: Add dwelf_elf_e_machine_string.
+            dwelf_elf_begin now only returns NULL when there is an error
+            reading or decompressing a file. If the file is not an ELF file
+            an ELF handle of type ELF_K_NONE is returned.
+- backends: Add support for C-SKY.
+
+* Thu Feb 14 2019 Mark Wielaard <mark@klomp.org> 0.176-1
+- build: Add new --enable-install-elfh option.
+  Do NOT use this for system installs (it overrides glibc elf.h).
+- backends: riscv improved core file and return value location support.
+- Fixes CVE-2019-7146, CVE-2019-7148, CVE-2019-7149, CVE-2019-7150,
+        CVE-2019-7664, CVE-2019-7665.
+
+* Wed Nov 14 2018 Mark Wielaard <mark@klomp.org> 0.175-1
+- readelf: Handle multiple .debug_macro sections.
+  Recognize and parse GNU Property notes, NT_VERSION notes and
+  GNU Build Attribute ELF Notes.
+- strip: Handle SHT_GROUP correctly.
+  Add strip --reloc-debug-sections-only option.
+  Handle relocations against GNU compressed sections.
+- libdwelf: New function dwelf_elf_begin.
+- libcpu: Recognize bpf jump variants BPF_JLT, BPF_JLE, BPF_JSLT
+  and BPF_JSLE.
+- backends: RISCV handles ADD/SUB relocations.
+  Handle SHT_X86_64_UNWIND.
+- Fixes CVE-2018-18310, CVE-2018-18520 and CVE-2018-18521.
+
+* Fri Sep 14 2018 Mark Wielaard <mark@klomp> 0.174-1
+- libelf, libdw and all tools now handle extended shnum and shstrndx
+  correctly.
+- elfcompress: Don't rewrite input file if no section data needs
+  updating.  Try harder to keep same file mode bits (suid) on rewrite.
+- strip: Handle mixed (out of order) allocated/non-allocated sections.
+- unstrip: Handle SHT_GROUP sections.
+- backends: RISCV and M68K now have backend implementations to
+  generate CFI based backtraces.
+- Fixes CVE-2018-16062, CVE-2018-16402 and CVE-2018-16403.
+
+* Fri Jun 29 2018 Mark Wielaard,,, <mark@klomp.org> 0.173-1
+- More fixes for crashes and hangs found by afl-fuzz. In particular
+  various functions now detect and break infinite loops caused by bad
+  DIE tree cycles.
+- readelf: Will now lookup the size and signedness of constant value
+  types to display them correctly (and not just how they were encoded).
+- libdw: New function dwarf_next_lines to read CU-less .debug_line data.
+  dwarf_begin_elf now accepts ELF files containing just .debug_line
+  or .debug_frame sections (which can be read without needing a DIE
+  tree from the .debug_info section).
+  Removed dwarf_getscn_info, which was never implemented.
+- backends: Handle BPF simple relocations.
+  The RISCV backends now handles ABI specific CFI and knows about
+  RISCV register types and names.
+
+* Mon Jun 11 2018 Mark Wielaard <mark@klomp.org> 0.172-1
+- No functional changes compared to 0.171.
+- Various bug fixes in libdw and eu-readelf dealing with bad DWARF5
+  data. Thanks to running the afl fuzzer on eu-readelf and various
+  testcases.
+- eu-readelf -N is ~15% faster.
+
+* Fri Jun 01 2018 Mark Wielaard <mark@klomp.org> 0.171-1
+- DWARF5 and split dwarf, including GNU DebugFission, support.
+- readelf: Handle all new DWARF5 sections.
+  --debug-dump=info+ will show split unit DIEs when found.
+  --dwarf-skeleton can be used when inspecting a .dwo file.
+  Recognizes GNU locviews with --debug-dump=loc.
+- libdw: New functions dwarf_die_addr_die, dwarf_get_units,
+  dwarf_getabbrevattr_data and dwarf_cu_info.
+  libdw will now try to resolve the alt file on first use
+  when not set yet with dwarf_set_alt.
+  dwarf_aggregate_size() now works with multi-dimensional arrays.
+- libdwfl: Use process_vm_readv when available instead of ptrace.
+- backends: Add a RISC-V backend.
+
+* Wed Aug  2 2017 Mark Wielaard <mark@klomp.org> 0.170-1
+- libdw: Added new DWARF5 attribute, tag, character encoding,
+  language code, calling convention, defaulted member function
+  and macro constants to dwarf.h.
+  New functions dwarf_default_lower_bound and dwarf_line_file.
+  dwarf_peel_type now handles DWARF5 immutable, packed and shared tags.
+  dwarf_getmacros now handles DWARF5 .debug_macro sections.
+- strip: Add -R, --remove-section=SECTION and --keep-section=SECTION.
+- backends: The bpf disassembler is now always build on all platforms.
+
+* Fri May  5 2017 Mark Wielaard <mark@klomp.org> 0.169-1
+- backends: Add support for EM_PPC64 GNU_ATTRIBUTES.
+  Frame pointer unwinding fallback support for i386, x86_64, aarch64.
+- translations: Update Polish translation.
+
+* Tue Dec 27 2016 Mark Wielaard <mark@klomp.org> 0.168-1
+- http://elfutils.org/ is now hosted at http://sourceware.org/elfutils/
+- libelf: gelf_newehdr and gelf_newehdr now return void *.
+- libdw: dwarf.h corrected the DW_LANG_PLI constant name (was DW_LANG_PL1).
+- readelf: Add optional --symbols[=SECTION] argument to select section name.
+
+* Thu Aug  4 2016 Mark Wielaard <mjw@redhat.com> 0.167-1
+- libasm: Add eBPF disassembler for EM_BPF files.
+- backends: Add m68k and BPF backends.
+- ld: Removed.
+- dwelf: Add ELF/DWARF string table creation functions.
+  dwelf_strtab_init, dwelf_strtab_add, dwelf_strtab_add_len,
+  dwelf_strtab_finalize, dwelf_strent_off, dwelf_strent_str and
+  dwelf_strtab_free.
+
+* Thu Mar 31 2016 Mark Wielaard <mjw@redhat.com> 0.166-1
+- config: The default program prefix for the installed tools is now
+  eu-. Use configure --program-prefix="" to not use a program prefix.
+
+* Fri Jan  8 2016 Mark Wielaard <mjw@redhat.com> 0.165-1
+- elfcompress: New utility to compress or decompress ELF sections.
+- readelf: Add -z,--decompress option.
+- libelf: Add elf_compress, elf_compress_gnu, elf32_getchdr,
+  elf64_getchdr and gelf_getchdr.
+- libdwelf: New function dwelf_scn_gnu_compressed_size.
+- config: Add libelf and libdw pkg-config files.
+- backends: sparc support for core and live backtraces.
+- translations: Updated Polish translation.
+
+* Thu Oct 15 2015 Mark Wielaard <mjw@redhat.com> 0.164-1
+- strip, unstrip: Handle ELF files with merged strtab/shstrtab
+  tables. Handle missing SHF_INFO_LINK section flags.
+- libelf: Use int64_t for offsets in libelf.h instead of loff_t.
+- libdw: dwarf.h Add preliminary DWARF5 DW_LANG_Haskell.
+- libdwfl: dwfl_standard_find_debuginfo now searches any subdir of
+  the binary path under the debuginfo root when the separate
+  debug file couldn't be found by build-id.
+  dwfl_linux_proc_attach can now be called before any Dwfl_Modules
+  have been reported.
+- backends: Better sparc and sparc64 support.
+- translations: Updated Ukrainian translation.
+- Provide default-yama-scope subpackage.
+
+* Fri Jun 19 2015 Mark Wielaard <mjw@redhat.com> 0.163-1
+- Bug fixes only, no new features.
+
+* Wed Jun 10 2015 Mark Wielaard <mjw@redhat.com> 0.162-1
+- libdw: Install new header elfutils/known-dwarf.h.
+  dwarf.h Add preliminary DWARF5 constants DW_TAG_atomic_type,
+  DW_LANG_Fortran03, DW_LANG_Fortran08. dwarf_peel_type now also
+  handles DW_TAG_atomic_type.
+- addr2line: Input addresses are now always interpreted as
+  hexadecimal numbers, never as octal or decimal numbers.
+  New option -a, --addresses to print address before each entry.
+  New option -C, --demangle to show demangled symbols.
+  New option --pretty-print to print all information on one line.
+- ar: CVE-2014-9447 Directory traversal vulnerability in ar
+  extraction.
+- backends: x32 support.
+
+* Thu Dec 18 2014 Mark Wielaard <mjw@redhat.com> 0.161-1
+- libdw: New function dwarf_peel_type. dwarf_aggregate_size now uses
+  dwarf_peel_type to also provide the sizes of qualified types.
+  dwarf_getmacros will now serve either of .debug_macro and
+  .debug_macinfo transparently.  New interfaces dwarf_getmacros_off,
+  dwarf_macro_getsrcfiles, dwarf_macro_getparamcnt, and
+  dwarf_macro_param are available for more generalized inspection of
+  macros and their parameters.
+  dwarf.h: Add DW_AT_GNU_deleted, DW_AT_noreturn, DW_LANG_C11,
+  DW_LANG_C_plus_plus_11 and DW_LANG_C_plus_plus_14.
+
+* Mon Aug 25 2014 Mark Wielaard <mjw@redhat.com> 0.160-1
+- libdw: New functions dwarf_cu_getdwarf, dwarf_cu_die.
+  dwarf.h remove non-existing DW_TAG_mutable_type.
+- libdwfl: Handle LZMA .ko.xz compressed kernel modules.
+- unstrip: New option -F, --force to combining files even if some ELF
+  headers don't seem to match.
+- backends: Handle ARM THUMB functions. Add support for ppc64le ELFv2 abi.
+
+* Sat May 17 2014 Mark Wielaard <mjw@redhat.com> 0.159-1
+- stack: New option -d, --debugname to lookup DWARF debuginfo name 
+  for frame.  New option -i, --inlines to show inlined frames 
+  using DWARF debuginfo.
+- libdwelf: New libdwelf.h header for libdw.so DWARF ELF Low-level 
+  Functions.  New function dwelf_elf_gnu_debuglink, 
+  dwelf_dwarf_gnu_debugaltlink, and dwelf_elf_gnu_build_id.
+- libdw: Support for DWZ multifile forms DW_FORM_GNU_ref_alt and      
+  DW_FORM_GNU_strp_alt is now enabled by default and no longer        
+  experimental. Added new functions dwarf_getalt and dwarf_setalt       
+  to get or set the alternative debug file used for the alt FORMs.     
+  The dwfl_linux_proc_find_elf callback will now find ELF from       
+  process memory for (deleted) files if the Dwfl has process state     
+  attached.
+- libdwfl: The dwfl_build_id_find_debuginfo and 
+  dwfl_standard_find_debuginfo functions will now try to 
+  resolve and set the alternative debug file.
+- backends: Add CFI unwinding for arm. Relies on .debug_frame.        
+  Add arm process initial register state compatible mode to AARCH64. 
+  Add aarch64 native and core unwind support.
+- other: All separate elfutils-robustify patches have been merged.    
+  CVE-2014-0172 Check overflow before calling malloc to uncompress 
+  data.
+
+* Fri Jan  3 2014 Mark Wielaard <mjw@redhat.com> 0.158-1
+- libdwfl: dwfl_core_file_report has new parameter executable.
+  New functions dwfl_module_getsymtab_first_global,
+  dwfl_module_getsym_info and dwfl_module_addrinfo.
+  Added unwinder with type Dwfl_Thread_Callbacks, opaque types
+  Dwfl_Thread and Dwfl_Frame and functions dwfl_attach_state,
+  dwfl_pid, dwfl_thread_dwfl, dwfl_thread_tid, dwfl_frame_thread,
+  dwfl_thread_state_registers, dwfl_thread_state_register_pc,
+  dwfl_getthread_frames, dwfl_getthreads, dwfl_thread_getframes
+  and dwfl_frame_pc.
+- addr2line: New option -x to show the section an address was found in.
+- stack: New utility that uses the new unwinder for processes and cores.
+- backends: Unwinder support for i386, x86_64, s390, s390x, ppc and ppc64.
+  aarch64 support.
+
+* Mon Sep 30 2013 Mark Wielaard <mjw@redhat.com> 0.157-1
+- libdw: Add new functions dwarf_getlocations, dwarf_getlocation_attr 
+         and dwarf_getlocation_die.
+- readelf: Show contents of NT_SIGINFO and NT_FILE core notes.
+- addr2line: Support -i, --inlines output option.
+- backends: abi_cfi hook for arm, ppc and s390.
+
+* Thu Jul 25 2013 Jan Kratochvil <jan.kratochvil@redhat.com> 0.156-1
+- lib: New macro COMPAT_VERSION_NEWPROTO.
+- libdw: Handle GNU extension opcodes in dwarf_getlocation.
+- libdwfl: Fix STB_GLOBAL over STB_WEAK preference in 
+  dwfl_module_addrsym.          Add minisymtab support.          Add 
+  parameter add_p_vaddr to dwfl_report_elf.          Use DT_DEBUG 
+  library search first.
+- libebl: Handle new core note types in EBL.
+- backends: Interpret NT_ARM_VFP.           Implement core file 
+  registers parsing for s390/s390x.
+- readelf: Add --elf-section input option to inspect an embedded ELF 
+  file.          Add -U, --unresolved-address-offsets output control.   
+         Add --debug-dump=decodedline support.          Accept version 
+  8 .gdb_index section format.          Adjust output formatting width. 
+           When highpc is in constant form print it also as address.    
+        Display raw .debug_aranges. Use libdw only for decodedaranges.
+- elflint: Add __bss_start__ to the list of allowed symbols.
+- tests: Add configure --enable-valgrind option to run all tests 
+  under valgrind.        Enable automake parallel-tests for make check.
+- translations: Updated Polish translation.
+- Updates for Automake 1.13.
+
+* Fri Aug 24 2012 Mark Wielaard <mjw@redhat.com> 0.155-1
+- libelf: elf*_xlatetomd now works for cross-endian ELF note data.    
+       elf_getshdr now works consistently on non-mmaped ELF files after 
+          calling elf_cntl(ELF_C_FDREAD).         Implement support for 
+  ar archives with 64-bit symbol table.
+- libdw: dwarf.h corrected the DW_LANG_ObjC constant name (was 
+  DW_LANG_Objc).        Any existing sources using the old name will 
+  have to be updated.        Add DW_MACRO_GNU .debug_macro type 
+  encodings constants, DW_ATE_UTF        and DW_OP_GNU_parameter_ref to 
+  dwarf.h.        Experimental support for DWZ multifile forms 
+  DW_FORM_GNU_ref_alt        and DW_FORM_GNU_strp_alt.  Disabled by 
+  default.  Use configure        --enable-dwz to test it.
+- readelf: Add .debug_macro parsing support.          Add .gdb_index 
+  version 7 parsing support.          Recognize DW_OP_GNU_parameter_ref.
+- backends: Add support for Tilera TILE-Gx processor.
+- translations: Updated Ukrainian translation.
+
+* Fri Jun 22 2012 Mark Wielaard <mjw@redhat.com> 0.154-1
+- libelf: [g]elf[32|64]_offscn() do not match SHT_NOBITS sections at 
+  OFFSET.
+- libdw: dwarf_highpc function now handles DWARF 4 DW_AT_high_pc 
+  constant form.        Fix bug using dwarf_next_unit to iterate over 
+  .debug_types.
+- elflint: Now accepts gold linker produced executables.
+- The license is now GPLv2/LGPLv3+ for the libraries and GPLv3+ for 
+  stand-alone programs. There is now also a formal CONTRIBUTING 
+  document describing how to submit patches.
+
+* Thu Feb 23 2012 Mark Wielaard <mjw@redhat.com> 0.153-1
+- libdw: Support reading .zdebug_* DWARF sections compressed via zlib.
+- libdwfl: Speed up dwfl_module_addrsym.
+- nm: Support C++ demangling.
+- ar: Support D modifier for "deterministic output" with no 
+  uid/gid/mtime info.     The U modifier is the inverse.     elfutils 
+  can be configured with the --enable-deterministic-archives     option 
+  to make the D behavior the default when U is not specified.
+- ranlib: Support -D and -U flags with same meaning.
+- readelf: Improve output of -wline. Add support for printing SDT elf 
+  notes.          Add printing of .gdb_index section. 	 Support for 
+  typed DWARF stack, call_site and entry_value.
+- strip: Add --reloc-debug-sections option.        Improved SHT_GROUP 
+  sections handling.
+
+* Tue Feb 15 2011  <drepper@gmail.com> 0.152-1
+- Various build and warning nits fixed for newest GCC and Autoconf.
+- libdwfl: Yet another prelink-related fix for another regression.
+  	 Look for Linux kernel images in files named with compression
+  suffixes.
+- elfcmp: New flag --ignore-build-id to ignore differing build ID
+  bits. 	New flag -l/--verbose to print all differences.
+
+* Wed Jan 12 2011  <drepper@gmail.com> 0.151-1
+- libdwfl: Fix for more prelink cases with separate debug file.
+- strip: New flag --strip-sections to remove section headers entirely.
+
+* Mon Nov 22 2010  <drepper@gmail.com> 0.150-1
+- libdw: Fix for handling huge .debug_aranges section.
+- libdwfl: Fix for handling prelinked DSO with separate debug file.
+- findtextrel: Fix diagnostics to work with usual section ordering.
+- libebl: i386 backend fix for multi-register integer return value
+  location.
+
+* Mon Sep 13 2010  <drepper@redhat.com> 0.149-1
+- libdw: Decode new DW_OP_GNU_implicit_pointer operation;        new
+  function dwarf_getlocation_implicit_pointer.
+- libdwfl: New function dwfl_dwarf_line.
+- addr2line: New flag -F/--flags to print more DWARF line information
+  details.
+- strip: -g recognizes .gdb_index as a debugging section.
+
+* Mon Jun 28 2010  <drepper@redhat.com> 0.148-1
+- libdw: Accept DWARF 4 format: new functions dwarf_next_unit,
+  dwarf_offdie_types.        New functions dwarf_lineisa,
+  dwarf_linediscriminator, dwarf_lineop_index.
+- libdwfl: Fixes in core-file handling, support cores from PIEs.
+  	 When working from build IDs, don't open a named file that
+  mismatches.
+- readelf: Handle DWARF 4 formats.
+
+* Mon May  3 2010 Ulrich Drepper <drepper@redhat.com> 0.147-1
+- libdw: Fixes in CFI handling, best possible handling of bogus CFA
+  ops.
+- libdwfl: Ignore R_*_NONE relocs, works around old (binutils) ld -r
+  bugs.
+
+* Wed Apr 21 2010  <drepper@redhat.com> 0.146-1
+- libdwfl: New function dwfl_core_file_report.
+
+* Tue Feb 23 2010 Ulrich Drepper <drepper@redhat.com> 0.145-1
+- Fix build with --disable-dependency-tracking.
+- Fix build with most recent glibc headers.
+- libelf: More robust to bogus section headers.
+- libdw: Fix CFI decoding.
+- libdwfl: Fix address bias returned by CFI accessors. 	 Fix core
+  file module layout identification.
+- readelf: Fix CFI decoding.
+
+* Thu Jan 14 2010  <drepper@redhat.com> 0.144-1
+- libelf: New function elf_getphdrnum. 	Now support using more than
+  65536 program headers in a file.
+- libdw: New function dwarf_aggregate_size for computing (constant)
+  type        sizes, including array_type cases with nontrivial
+  calculation.
+- readelf: Don't give errors for missing info under -a.
+  Handle Linux "VMCOREINFO" notes under -n.
+
+* Mon Sep 21 2009  <drepper@redhat.com> 0.143-1
+- libdw: Various convenience functions for individual attributes now
+  use dwarf_attr_integrate to look up indirect inherited
+  attributes.  Location expression handling now supports
+  DW_OP_implicit_value.
+- libdwfl: Support automatic decompression of files in XZ format,
+  and of Linux kernel images made with bzip2 or LZMA (as well
+  as gzip).
+
+* Mon Jun 29 2009  <drepper@redhat.com> 0.142-1
+- libelf: Add elf_getshdrnum alias for elf_getshnum and elf_getshdrstrndx alias
+  for elf_getshstrndx and deprecate original names.  Sun screwed up
+  their implementation and asked for a solution.
+- libebl: Add support for STB_GNU_UNIQUE.
+- elflint: Add support for STB_GNU_UNIQUE.
+- readelf: Add -N option, speeds up DWARF printing without address->name lookups.
+- libdw: Add support for decoding DWARF CFI into location description form.
+  Handle some new DWARF 3 expression operations previously omitted.
+  Basic handling of some new encodings slated for DWARF
+
+* Thu Apr 23 2009 Ulrich Drepper <drepper@redhat.com> 0.141-1
+- libebl: sparc backend fixes; 	some more arm backend support
+- libdwfl: fix dwfl_module_build_id for prelinked DSO case;
+  fixes in core file support; 	 dwfl_module_getsym interface
+  improved for non-address symbols
+- strip: fix infinite loop on strange inputs with -f
+- addr2line: take -j/--section=NAME option for binutils compatibility
+  	   (same effect as '(NAME)0x123' syntax already supported)
+
+* Mon Feb 16 2009 Ulrich Drepper <drepper@redhat.com> 0.140-1
+- libelf: Fix regression in creation of section header
+- libdwfl: Less strict behavior if DWARF reader is just used to
+  display data
+
+* Thu Jan 22 2009 Ulrich Drepper <drepper@redhat.com> 0.139-1
+- libcpu: Add Intel SSE4 disassembler support
+- readelf: Implement call frame information and exception handling
+  dumping.          Add -e option.  Enable it implicitly for -a.
+- elflint: Check PT_GNU_EH_FRAME program header entry.
+- libdwfl: Support automatic gzip/bzip2 decompression of ELF files.
+
+* Wed Dec 31 2008 Roland McGrath <roland@redhat.com> 0.138-1
+- Install <elfutils/version.h> header file for applications to use in
+  source version compatibility checks.
+- libebl: backend fixes for i386 TLS relocs; backend support for
+  NT_386_IOPERM
+- libcpu: disassembler fixes
+- libdwfl: bug fixes
+- libelf: bug fixes
+- nm: bug fixes for handling corrupt input files
+
+* Tue Aug 26 2008 Ulrich Drepper <drepper@redhat.com> 0.137-1
+- Minor fixes for unreleased 0.136 release.
+
+* Mon Aug 25 2008 Ulrich Drepper <drepper@redhat.com> 0.136-1
+- libdwfl: bug fixes; new segment interfaces;	 all the libdwfl-based
+ tools now support --core=COREFILE option
+
+* Mon May 12 2008 Ulrich Drepper <drepper@redhat.com> 0.135-1
+- libdwfl: bug fixes
+- strip: changed handling of ET_REL files wrt symbol tables and relocs
+
+* Tue Apr  8 2008 Ulrich Drepper <drepper@redhat.com> 0.134-1
+- elflint: backend improvements for sparc, alpha
+- libdwfl, libelf: bug fixes
+
+* Sat Mar  1 2008 Ulrich Drepper <drepper@redhat.com> 0.133-1
+- readelf, elflint, libebl: SHT_GNU_ATTRIBUTE section handling (readelf -A)
+- readelf: core note handling for NT_386_TLS, NT_PPC_SPE, Alpha NT_AUXV
+- libdwfl: bug fixes and optimization in relocation handling
+- elfcmp: bug fix for non-allocated section handling
+- ld: implement newer features of binutils linker.
+
+* Mon Jan 21 2008 Ulrich Drepper <drepper@redhat.com> 0.132-1
+- libcpu: Implement x86 and x86-64 disassembler.
+- libasm: Add interface for disassembler.
+- all programs: add debugging of branch prediction.
+- libelf: new function elf_scnshndx.
+
+* Sun Nov 11 2007 Ulrich Drepper <drepper@redhat.com> 0.131-1
+- libdw: DW_FORM_ref_addr support; dwarf_formref entry point now depreca
+ted;       bug fixes for oddly-formatted DWARF
+- libdwfl: bug fixes in offline archive support, symbol table handling;
+	 apply partial relocations for dwfl_module_address_section on
+ET_REL
+- libebl: powerpc backend support for Altivec registers
+
+* Mon Oct 15 2007 Ulrich Drepper <drepper@redhat.com> 0.130-1
+- readelf: -p option can take an argument like -x for one section,
+	 or no argument (as before) for all SHF_STRINGS sections;
+	 new option --archive-index (or -c);	 improved -n output for
+core files, on many machines
+- libelf: new function elf_getdata_rawchunk, replaces gelf_rawchunk;
+	new functions gelf_getnote, gelf_getauxv, gelf_update_auxv
+- readelf, elflint: handle SHT_NOTE sections without requiring phdrs
+- elflint: stricter checks on debug sections
+- libdwfl: new functions dwfl_build_id_find_elf, dwfl_build_id_find_debu
+ginfo,	 dwfl_module_build_id, dwfl_module_report_build_id;	 suppo
+rt dynamic symbol tables found via phdrs;	 dwfl_standard_find_de
+buginfo now uses build IDs when available
+- unstrip: new option --list (or -n)
+- libebl: backend improvements for sparc, alpha, powerpc
+
+* Tue Aug 14 2007 Ulrich Drepper <drepper@redhat.com> 0.129-1
+- readelf: new options --hex-dump (or -x), --strings (or -p)
+- addr2line: new option --symbols (or -S)
+
+* Wed Apr 18 2007 Ulrich Drepper <drepper@redhat.com> 0.127-1
+- libdw: new function dwarf_getsrcdirs
+- libdwfl: new functions dwfl_module_addrsym, dwfl_report_begin_add,
+	 dwfl_module_address_section
+
+* Mon Feb  5 2007 Ulrich Drepper <drepper@redhat.com> 0.126-1
+- new program: ar
+
+* Mon Dec 18 2006 Ulrich Drepper <drepper@redhat.com> 0.125-1
+- elflint: Compare DT_GNU_HASH tests.
+- move archives into -static RPMs
+- libelf, elflint: better support for core file handling
+
+* Tue Oct 10 2006 Ulrich Drepper <drepper@redhat.com> 0.124-1
+- libebl: sparc backend support for return value location
+- libebl, libdwfl: backend register name support extended with more info
+- libelf, libdw: bug fixes for unaligned accesses on machines that care
+- readelf, elflint: trivial bugs fixed
+
+* Mon Aug 14 2006 Roland McGrath <roland@redhat.com> 0.123-1
+- libebl: Backend build fixes, thanks to Stepan Kasal.
+- libebl: ia64 backend support for register names, return value location
+- libdwfl: Handle truncated linux kernel module section names.
+- libdwfl: Look for linux kernel vmlinux files with .debug suffix.
+- elflint: Fix checks to permit --hash-style=gnu format.
+
+* Wed Jul 12 2006 Ulrich Drepper <drepper@redhat.com> 0.122-1
+- libebl: add function to test for relative relocation
+- elflint: fix and extend DT_RELCOUNT/DT_RELACOUNT checks
+- elflint, readelf: add support for DT_GNU_HASHlibelf: add elf_gnu_hash
+- elflint, readelf: add support for 64-bit SysV-style hash tables
+- libdwfl: new functions dwfl_module_getsymtab, dwfl_module_getsym.
+
+* Wed Jun 14 2006  <drepper@redhat.com> 0.121-1
+- libelf: bug fixes for rewriting existing files when using mmap.
+- make all installed headers usable in C++ code.
+- readelf: better output format.
+- elflint: fix tests of dynamic section content.
+- ld: Implement --as-needed, --execstack, PT_GNU_STACK.  Many small patc
+hes.
+- libdw, libdwfl: handle files without aranges info.
+
+* Tue Apr  4 2006 Ulrich Drepper <drepper@redhat.com> 0.120-1
+- Bug fixes.
+- dwarf.h updated for DWARF 3.0 final specification.
+- libdwfl: New function dwfl_version.
+- The license is now GPL for most files.  The libelf, libebl, libdw,and
+libdwfl libraries have additional exceptions.  Add reference toOIN.
+
+* Thu Jan 12 2006 Roland McGrath <roland@redhat.com> 0.119-1
+- elflint: more tests.
+- libdwfl: New function dwfl_module_register_names.
+- libebl: New backend hook for register names.
+
+* Tue Dec  6 2005 Ulrich Drepper <drepper@redhat.com> 0.118-1
+- elflint: more tests.
+- libdwfl: New function dwfl_module_register_names.
+- libebl: New backend hook for register names.
+
+* Thu Nov 17 2005 Ulrich Drepper <drepper@redhat.com> 0.117-1
+- libdwfl: New function dwfl_module_return_value_location.
+- libebl: Backend improvements for several CPUs.
+
+* Mon Oct 31 2005 Ulrich Drepper <drepper@redhat.com> 0.116-1
+- libdw: New functions dwarf_ranges, dwarf_entrypc, dwarf_diecu,       d
+warf_entry_breakpoints.  Removed Dwarf_Func type and functions       d
+warf_func_name, dwarf_func_lowpc, dwarf_func_highpc,       dwarf_func_
+entrypc, dwarf_func_die; dwarf_getfuncs callback now uses       Dwarf_
+Die, and dwarf_func_file, dwarf_func_line, dwarf_func_col       replac
+ed by dwarf_decl_file, dwarf_decl_line, dwarf_decl_column;       dwarf
+_func_inline, dwarf_func_inline_instances now take Dwarf_Die.       Ty
+pe Dwarf_Loc renamed to Dwarf_Op; dwarf_getloclist,       dwarf_addrlo
+clists renamed dwarf_getlocation, dwarf_getlocation_addr.
+
+* Fri Sep  2 2005 Ulrich Drepper <drepper@redhat.com> 0.115-1
+- libelf: speed-ups of non-mmap reading.
+- strings: New program.
+- Implement --enable-gcov option for configure.
+- libdw: New function dwarf_getscopes_die.
+
+* Wed Aug 24 2005 Ulrich Drepper <drepper@redhat.com> 0.114-1
+- libelf: new function elf_getaroff
+- libdw: Added dwarf_func_die, dwarf_func_inline, dwarf_func_inline_inst
+ances.
+- libdwfl: New functions dwfl_report_offline, dwfl_offline_section_addre
+ss,	 dwfl_linux_kernel_report_offline.
+- ranlib: new program
+
+* Mon Aug 15 2005 Ulrich Drepper <drepper@redhat.com> 0.114-1
+- libelf: new function elf_getaroff
+- ranlib: new program
+
+* Wed Aug 10 2005 Ulrich Drepper <@redhat.com> 0.113-1
+- elflint: relax a bit. Allow version definitions for defined symbols ag
+ainstDSO versions also for symbols in nobits sections.  Allow .rodata
+sectionto have STRINGS and MERGE flag set.
+- strip: add some more compatibility with binutils.
+
+* Sat Aug  6 2005 Ulrich Drepper <@redhat.com> 0.113-1
+- elflint: relax a bit. Allow version definitions for defined symbols ag
+ainstDSO versions also for symbols in nobits sections.  Allow .rodata
+sectionto have STRINGS and MERGE flag set.
+
+* Sat Aug  6 2005 Ulrich Drepper <@redhat.com> 0.113-1
+- elflint: relax a bit. Allow version definitions for defined symbols ag
+ainstDSO versions also for symbols in nobits sections.
+
+* Fri Aug  5 2005 Ulrich Drepper <@redhat.com> 0.112-1
+- elfcmp: some more relaxation.
+- elflint: many more tests, especially regarding to symbol versioning.
+- libelf: Add elfXX_offscn and gelf_offscn.
+- libasm: asm_begin interface changes.
+- libebl: Add three new interfaces to directly access machine, class, an
+ddata encoding information.
+- objdump: New program.  Just the beginning.
+
+* Thu Jul 28 2005 Ulrich Drepper <@redhat.com> 0.111-1
+- libdw: now contains all of libdwfl.  The latter is not installed anymore.
+- elfcmp: little usability tweak, name and index of differing section is
+ printed.
+
+* Sun Jul 24 2005 Ulrich Drepper <@redhat.com> 0.110-1
+- libelf: fix a numbe rof problems with elf_update
+- elfcmp: fix a few bugs.  Compare gaps.
+- Fix a few PLT problems and mudflap build issues.
+- libebl: Don't expose Ebl structure definition in libebl.h.  It's now p
+rivate.
+
+* Thu Jul 21 2005 Ulrich Drepper <@redhat.com> 0.109-1
+- libebl: Check for matching modules.
+- elflint: Check that copy relocations only happen for OBJECT or NOTYPE
+symbols.
+- elfcmp: New program.
+- libdwfl: New library.
+
+* Mon May  9 2005 Ulrich Drepper <@redhat.com> 0.108-1
+- strip: fix bug introduced in last change
+- libdw: records returned by dwarf_getsrclines are now sorted by address
+
+* Sun May  8 2005 Ulrich Drepper <@redhat.com> 0.108-1
+- strip: fix bug introduced in last change
+
+* Sun May  8 2005 Ulrich Drepper <@redhat.com> 0.107-1
+- readelf: improve DWARF output format
+- strip: support Linux kernel modules
+
+* Fri Apr 29 2005 Ulrich Drepper <drepper@redhat.com> 0.107-1
+- readelf: improve DWARF output format
+
+* Mon Apr  4 2005 Ulrich Drepper <drepper@redhat.com> 0.106-1
+- libdw: Updated dwarf.h from DWARF3 speclibdw: add new functions dwarf_f
+unc_entrypc, dwarf_func_file, dwarf_func_line,dwarf_func_col, dwarf_ge
+tsrc_file
+
+* Fri Apr  1 2005 Ulrich Drepper <drepper@redhat.com> 0.105-1
+- addr2line: New program
+- libdw: add new functions: dwarf_addrdie, dwarf_macro_*, dwarf_getfuncs
+,dwarf_func_*.
+- findtextrel: use dwarf_addrdie
+
+* Mon Mar 28 2005 Ulrich Drepper <drepper@redhat.com> 0.104-1
+- findtextrel: New program.
+
+* Mon Mar 21 2005 Ulrich Drepper <drepper@redhat.com> 0.103-1
+- libdw: Fix using libdw.h with gcc < 4 and C++ code.  Compiler bug.
+
+* Tue Feb 22 2005 Ulrich Drepper <drepper@redhat.com> 0.102-1
+- More Makefile and spec file cleanups.
+
+* Fri Jan 16 2004 Jakub Jelinek <jakub@redhat.com> 0.94-1
+- upgrade to 0.94
+
+* Fri Jan 16 2004 Jakub Jelinek <jakub@redhat.com> 0.93-1
+- upgrade to 0.93
+
+* Thu Jan  8 2004 Jakub Jelinek <jakub@redhat.com> 0.92-1
+- full version
+- macroized spec file for GPL or OSL builds
+- include only libelf under GPL plus wrapper scripts
+
+* Wed Jan  7 2004 Jakub Jelinek <jakub@redhat.com> 0.91-2
+- macroized spec file for GPL or OSL builds
+
+* Wed Jan  7 2004 Ulrich Drepper <drepper@redhat.com>
+- split elfutils-devel into two packages.
+
+* Wed Jan  7 2004 Jakub Jelinek <jakub@redhat.com> 0.91-1
+- include only libelf under GPL plus wrapper scripts
+
+* Tue Dec 23 2003 Jeff Johnson <jbj@redhat.com> 0.89-3
+- readelf, not readline, in %%description (#111214).
+
+* Fri Sep 26 2003 Bill Nottingham <notting@redhat.com> 0.89-1
+- update to 0.89 (fix eu-strip)
+
+* Tue Sep 23 2003 Jakub Jelinek <jakub@redhat.com> 0.86-3
+- update to 0.86 (fix eu-strip on s390x/alpha)
+- libebl is an archive now; remove references to DSO
+
+* Mon Jul 14 2003 Jeff Johnson <jbj@redhat.com> 0.84-3
+- upgrade to 0.84 (readelf/elflint improvements, rawhide bugs fixed).
+
+* Fri Jul 11 2003 Jeff Johnson <jbj@redhat.com> 0.83-3
+- upgrade to 0.83 (fix invalid ELf handle on *.so strip, more).
+
+* Wed Jul  9 2003 Jeff Johnson <jbj@redhat.com> 0.82-3
+- upgrade to 0.82 (strip tests fixed on big-endian).
+
+* Tue Jul  8 2003 Jeff Johnson <jbj@redhat.com> 0.81-3
+- upgrade to 0.81 (strip excludes unused symtable entries, test borked).
+
+* Thu Jun 26 2003 Jeff Johnson <jbj@redhat.com> 0.80-3
+- upgrade to 0.80 (debugedit changes for kernel in progress).
+
+* Wed Jun 04 2003 Elliot Lee <sopwith@redhat.com>
+- rebuilt
+
+* Wed May 21 2003 Jeff Johnson <jbj@redhat.com> 0.79-2
+- upgrade to 0.79 (correct formats for size_t, more of libdw "works").
+
+* Mon May 19 2003 Jeff Johnson <jbj@redhat.com> 0.78-2
+- upgrade to 0.78 (libdwarf bugfix, libdw additions).
+
+* Mon Feb 24 2003 Elliot Lee <sopwith@redhat.com>
+- debuginfo rebuild
+
+* Thu Feb 20 2003 Jeff Johnson <jbj@redhat.com> 0.76-2
+- use the correct way of identifying the section via the sh_info link.
+
+* Sat Feb 15 2003 Jakub Jelinek <jakub@redhat.com> 0.75-2
+- update to 0.75 (eu-strip -g fix)
+
+* Tue Feb 11 2003 Jakub Jelinek <jakub@redhat.com> 0.74-2
+- update to 0.74 (fix for writing with some non-dirty sections)
+
+* Thu Feb  6 2003 Jeff Johnson <jbj@redhat.com> 0.73-3
+- another -0.73 update (with sparc fixes).
+- do "make check" in %%check, not %%install, section.
+
+* Mon Jan 27 2003 Jeff Johnson <jbj@redhat.com> 0.73-2
+- update to 0.73 (with s390 fixes).
+
+* Wed Jan 22 2003 Tim Powers <timp@redhat.com>
+- rebuilt
+
+* Wed Jan 22 2003 Jakub Jelinek <jakub@redhat.com> 0.72-4
+- fix arguments to gelf_getsymshndx and elf_getshstrndx
+- fix other warnings
+- re-enable checks on s390x
+
+* Sat Jan 11 2003 Karsten Hopp <karsten@redhat.de> 0.72-3
+- temporarily disable checks on s390x, until someone has
+  time to look at it
+
+* Thu Dec 12 2002 Jakub Jelinek <jakub@redhat.com> 0.72-2
+- update to 0.72
+
+* Wed Dec 11 2002 Jakub Jelinek <jakub@redhat.com> 0.71-2
+- update to 0.71
+
+* Wed Dec 11 2002 Jeff Johnson <jbj@redhat.com> 0.69-4
+- update to 0.69.
+- add "make check" and segfault avoidance patch.
+- elfutils-libelf needs to run ldconfig.
+
+* Tue Dec 10 2002 Jeff Johnson <jbj@redhat.com> 0.68-2
+- update to 0.68.
+
+* Fri Dec  6 2002 Jeff Johnson <jbj@redhat.com> 0.67-2
+- update to 0.67.
+
+* Tue Dec  3 2002 Jeff Johnson <jbj@redhat.com> 0.65-2
+- update to 0.65.
+
+* Mon Dec  2 2002 Jeff Johnson <jbj@redhat.com> 0.64-2
+- update to 0.64.
+
+* Sun Dec 1 2002 Ulrich Drepper <drepper@redhat.com> 0.64
+- split packages further into elfutils-libelf
+
+* Sat Nov 30 2002 Jeff Johnson <jbj@redhat.com> 0.63-2
+- update to 0.63.
+
+* Fri Nov 29 2002 Ulrich Drepper <drepper@redhat.com> 0.62
+- Adjust for dropping libtool
+
+* Sun Nov 24 2002 Jeff Johnson <jbj@redhat.com> 0.59-2
+- update to 0.59
+
+* Thu Nov 14 2002 Jeff Johnson <jbj@redhat.com> 0.56-2
+- update to 0.56
+
+* Thu Nov  7 2002 Jeff Johnson <jbj@redhat.com> 0.54-2
+- update to 0.54
+
+* Sun Oct 27 2002 Jeff Johnson <jbj@redhat.com> 0.53-2
+- update to 0.53
+- drop x86_64 hack, ICE fixed in gcc-3.2-11.
+
+* Sat Oct 26 2002 Jeff Johnson <jbj@redhat.com> 0.52-3
+- get beehive to punch a rhpkg generated package.
+
+* Wed Oct 23 2002 Jeff Johnson <jbj@redhat.com> 0.52-2
+- build in 8.0.1.
+- x86_64: avoid gcc-3.2 ICE on x86_64 for now.
+
+* Tue Oct 22 2002 Ulrich Drepper <drepper@redhat.com> 0.52
+- Add libelf-devel to conflicts for elfutils-devel
+
+* Mon Oct 21 2002 Ulrich Drepper <drepper@redhat.com> 0.50
+- Split into runtime and devel package
+
+* Fri Oct 18 2002 Ulrich Drepper <drepper@redhat.com> 0.49
+- integrate into official sources
+
+* Wed Oct 16 2002 Jeff Johnson <jbj@redhat.com> 0.46-1
+- Swaddle.
diff --git a/config/eu.am b/config/eu.am
new file mode 100644
index 0000000..e6c241f
--- /dev/null
+++ b/config/eu.am
@@ -0,0 +1,149 @@
+## Common automake fragments for elfutils subdirectory makefiles.
+##
+## Copyright (C) 2010, 2014, 2016 Red Hat, Inc.
+## Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org>
+##
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+
+DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -DLOCALEDIR='"${localedir}"'
+AM_CPPFLAGS = -I. -I$(srcdir) -I$(top_srcdir)/lib -I..
+
+# Drop the 'u' flag that automake adds by default. It is incompatible
+# with deterministic archives.
+ARFLAGS = cr
+
+# Warn about stack usage of more than 256K = 262144 bytes.
+if ADD_STACK_USAGE_WARNING
+STACK_USAGE_WARNING=-Wstack-usage=262144
+STACK_USAGE_NO_ERROR=-Wno-error=stack-usage=
+else
+STACK_USAGE_WARNING=
+STACK_USAGE_NO_ERROR=
+endif
+
+if SANE_LOGICAL_OP_WARNING
+LOGICAL_OP_WARNING=-Wlogical-op
+else
+LOGICAL_OP_WARNING=
+endif
+
+if HAVE_DUPLICATED_COND_WARNING
+DUPLICATED_COND_WARNING=-Wduplicated-cond
+else
+DUPLICATED_COND_WARNING=
+endif
+
+if HAVE_NULL_DEREFERENCE_WARNING
+NULL_DEREFERENCE_WARNING=-Wnull-dereference
+else
+NULL_DEREFERENCE_WARNING=
+endif
+
+if HAVE_IMPLICIT_FALLTHROUGH_WARNING
+# Use strict fallthrough. Only __attribute__((fallthrough)) will prevent the
+# warning
+if HAVE_IMPLICIT_FALLTHROUGH_5_WARNING
+IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough=5
+else
+IMPLICIT_FALLTHROUGH_WARNING=-Wimplicit-fallthrough
+endif
+else
+IMPLICIT_FALLTHROUGH_WARNING=
+endif
+
+if HAVE_TRAMPOLINES_WARNING
+TRAMPOLINES_WARNING=-Wtrampolines
+else
+TRAMPOLINES_WARNING=
+endif
+
+if HAVE_NO_PACKED_NOT_ALIGNED_WARNING
+NO_PACKED_NOT_ALIGNED_WARNING=-Wno-packed-not-aligned
+else
+NO_PACKED_NOT_ALIGNED_WARNING=
+endif
+
+if HAVE_USE_AFTER_FREE3_WARNING
+USE_AFTER_FREE3_WARNING=-Wuse-after-free=3
+else
+USE_AFTER_FREE3_WARNING=
+endif
+
+AM_CFLAGS = -std=gnu99 -Wall -Wshadow -Wformat=2 \
+	    -Wold-style-definition -Wstrict-prototypes $(TRAMPOLINES_WARNING) \
+	    $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
+	    $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
+	    $(USE_AFTER_FREE3_WARNING) \
+	    $(if $($(*F)_no_Werror),,-Werror) \
+	    $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
+	    $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
+	    $(if $($(*F)_no_Wpacked_not_aligned),$(NO_PACKED_NOT_ALIGNED_WARNING),) \
+	    $($(*F)_CFLAGS)
+
+AM_CXXFLAGS = -std=c++11 -Wall -Wshadow \
+	   $(TRAMPOLINES_WARNING) \
+	   $(LOGICAL_OP_WARNING) $(DUPLICATED_COND_WARNING) \
+	   $(NULL_DEREFERENCE_WARNING) $(IMPLICIT_FALLTHROUGH_WARNING) \
+	   $(if $($(*F)_no_Werror),,-Werror) \
+	   $(if $($(*F)_no_Wunused),,-Wunused -Wextra) \
+	   $(if $($(*F)_no_Wstack_usage),,$(STACK_USAGE_WARNING)) \
+	   $(if $($(*F)_no_Wpacked_not_aligned),$(NO_PACKED_NOT_ALIGNED_WARNING),) \
+	   $($(*F)_CXXFLAGS)
+
+COMPILE.os = $(filter-out -fprofile-arcs -ftest-coverage, $(COMPILE))
+
+DEFS.os = -DPIC -DSHARED
+if SYMBOL_VERSIONING
+DEFS.os += -DSYMBOL_VERSIONING
+else
+endif
+
+%.os: %.c %.o
+if AMDEP
+	$(AM_V_CC)if $(COMPILE.os) -c -o $@ $(fpic_CFLAGS) $(DEFS.os) -MT $@ -MD -MP \
+	  -MF "$(DEPDIR)/$*.Tpo" `test -f '$<' || echo '$(srcdir)/'`$<; \
+	then cat "$(DEPDIR)/$*.Tpo" >> "$(DEPDIR)/$*.Po"; \
+	     rm -f "$(DEPDIR)/$*.Tpo"; \
+	else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
+	fi
+else
+	$(AM_V_CC)$(COMPILE.os) -c -o $@ $(fpic_CFLAGS) $(DEFS.os) $<
+endif
+
+CLEANFILES = *.gcno *.gcda
+
+textrel_msg = echo "WARNING: TEXTREL found in '$@'"
+if FATAL_TEXTREL
+textrel_found = $(textrel_msg); exit 1
+else
+textrel_found = $(textrel_msg)
+endif
+textrel_check = if $(READELF) -d $@ | grep -F -q TEXTREL; then $(textrel_found); fi
+
+print-%:
+	@echo $*=$($*)
diff --git a/config/known-dwarf.awk b/config/known-dwarf.awk
new file mode 100755
index 0000000..bc9b02d
--- /dev/null
+++ b/config/known-dwarf.awk
@@ -0,0 +1,56 @@
+#!/bin/gawk -f
+
+## Copyright (C) 2012, 2015 Red Hat, Inc.
+##
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+$1 == "enum" { set = ""; next }
+
+set == "" && $1 ~ /DW_([A-Z_]+)_([^ ]+)/ {
+  set = $1;
+  sub(/^DW_/, "", set);
+  sub(/_[^[:upper:]_].*$/, "", set);
+  if (set ~ /LANG_.+/) set = "LANG";
+}
+
+$1 ~ /DW([_A-Z]+)_([^ ]+)/ {
+  match($1, ("DW_" set "_([^ ]+)"), fields);
+  elt = fields[1];
+  if (set in DW)
+    DW[set] = DW[set] "," elt;
+  else
+    DW[set] = elt;
+}
+
+END {
+  print "/* Generated by config/known-dwarf.awk from libdw/dwarf.h contents.  */";
+  n = asorti(DW, sets);
+  for (i = 1; i <= n; ++i) {
+    set = sets[i];
+    if (what && what != set) continue;
+    split(DW[set], elts, ",");
+    m = asort(elts);
+    if (m == 0) continue;
+    print "\n#define DWARF_ALL_KNOWN_DW_" set " \\";
+    for (j = 1; j <= m; ++j) {
+      elt = elts[j];
+      if (elt ~ /(low?|hi|high)_user$/)
+	continue;
+      print "  DWARF_ONE_KNOWN_DW_" set " (" elt ", DW_" set "_" elt ") \\";
+    }
+    print "  /* End of DW_" set "_*.  */";
+  }
+}
diff --git a/config/libdebuginfod.pc.in b/config/libdebuginfod.pc.in
new file mode 100644
index 0000000..46722a7
--- /dev/null
+++ b/config/libdebuginfod.pc.in
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: debuginfod
+Description: elfutils library to query debuginfo files from debuginfod servers
+Version: @VERSION@
+URL: http://elfutils.org/
+
+Libs: -L${libdir} -ldebuginfod
+Cflags: -I${includedir}
diff --git a/config/libdw.pc.in b/config/libdw.pc.in
new file mode 100644
index 0000000..2e83a43
--- /dev/null
+++ b/config/libdw.pc.in
@@ -0,0 +1,22 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdw
+Description: elfutils library for DWARF data and ELF file or process inspection
+Version: @VERSION@
+URL: http://elfutils.org/
+
+Libs: -L${libdir} -ldw
+Cflags: -I${includedir}
+
+# We need the exact matching elfutils libelf version since internal data
+# structures are used.
+Requires: libelf = @VERSION@
+
+# We support various compressed ELF images, but don't export any of the
+# data structures or functions.  zlib (gz) is always required, bzip2 (bz2)
+# lzma (xz) and zstd () are optional. But bzip2 doesn't have a pkg-config file.
+Requires.private: zlib @LIBLZMA@ @LIBZSTD@
+Libs.private: @BZ2_LIB@
diff --git a/config/libelf.pc.in b/config/libelf.pc.in
new file mode 100644
index 0000000..0d2ce96
--- /dev/null
+++ b/config/libelf.pc.in
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libelf
+Description: elfutils libelf library to read and write ELF files
+Version: @VERSION@
+URL: http://elfutils.org/
+
+Libs: -L${libdir} -lelf
+Cflags: -I${includedir}
+
+Requires.private: zlib @LIBZSTD@
diff --git a/config/profile.csh.in b/config/profile.csh.in
new file mode 100644
index 0000000..d962d96
--- /dev/null
+++ b/config/profile.csh.in
@@ -0,0 +1,16 @@
+# $HOME/.login* or similar files may first set $DEBUGINFOD_URLS.
+# If $DEBUGINFOD_URLS is not set there, we set it from system *.url files.
+# $HOME/.*rc or similar files may then amend $DEBUGINFOD_URLS.
+# See also [man debuginfod-client-config] for other environment variables
+# such as $DEBUGINFOD_MAXSIZE, $DEBUGINFOD_MAXTIME, $DEBUGINFOD_PROGRESS.
+
+if (! $?DEBUGINFOD_URLS) then
+    set prefix="@prefix@"
+    set DEBUGINFOD_URLS=`sh -c 'cat /dev/null "$0"/*.urls 2>/dev/null; :' "@sysconfdir@/debuginfod" | tr '\n' ' '`
+    if ( "$DEBUGINFOD_URLS" != "" ) then
+        setenv DEBUGINFOD_URLS "$DEBUGINFOD_URLS"
+    else
+        unset DEBUGINFOD_URLS
+    endif
+    unset prefix
+endif
diff --git a/config/profile.sh.in b/config/profile.sh.in
new file mode 100644
index 0000000..3f4397d
--- /dev/null
+++ b/config/profile.sh.in
@@ -0,0 +1,12 @@
+# $HOME/.profile* or similar files may first set $DEBUGINFOD_URLS.
+# If $DEBUGINFOD_URLS is not set there, we set it from system *.url files.
+# $HOME/.*rc or similar files may then amend $DEBUGINFOD_URLS.
+# See also [man debuginfod-client-config] for other environment variables
+# such as $DEBUGINFOD_MAXSIZE, $DEBUGINFOD_MAXTIME, $DEBUGINFOD_PROGRESS.
+
+if [ -z "$DEBUGINFOD_URLS" ]; then
+    prefix="@prefix@"
+    DEBUGINFOD_URLS=$(cat /dev/null "@sysconfdir@/debuginfod"/*.urls 2>/dev/null | tr '\n' ' ')
+    [ -n "$DEBUGINFOD_URLS" ] && export DEBUGINFOD_URLS || unset DEBUGINFOD_URLS
+    unset prefix
+fi
diff --git a/config/upload-release.sh b/config/upload-release.sh
new file mode 100755
index 0000000..ba43aa1
--- /dev/null
+++ b/config/upload-release.sh
@@ -0,0 +1,62 @@
+#!/usr/bin/env bash
+
+# Must be run in the source directory.
+# Should have passed make distcheck.
+# And all final changes should already have been pushed.
+# Backup copy will be created in $HOME/elfutils-$VERSION
+
+# Any error is fatal
+set -e
+
+# We take one arguent, the version (e.g. 0.173)
+if [ $# -ne 1 ]; then
+  echo "$0 <version> (e.g. 0.169)"
+  exit 1
+fi
+
+VERSION="$1"
+
+echo Make sure the git repo is tagged, signed and pushed
+echo git tag -s -m \"elfutils $VERSION release\" elfutils-$VERSION
+echo git push --tags
+
+# Create a temporary directory and make sure it is cleaned up.
+tempdir=$(mktemp -d) || exit
+trap "rm -rf -- ${tempdir}" EXIT
+
+pushd "${tempdir}"
+
+# Checkout
+git clone git://sourceware.org/git/elfutils.git
+cd elfutils
+git tag --verify "elfutils-${VERSION}"
+git checkout -b "$VERSION" "elfutils-${VERSION}"
+
+# Create dist
+autoreconf -v -f -i
+./configure --enable-maintainer-mode
+make -j$(nproc) && make dist
+
+# Sign
+mkdir $VERSION
+cp elfutils-$VERSION.tar.bz2 $VERSION/
+cd $VERSION/
+gpg -b elfutils-$VERSION.tar.bz2
+cd ..
+
+# Backup copy
+cp -r $VERSION $HOME/elfutils-$VERSION
+
+# Upload
+scp -r $VERSION sourceware.org:/sourceware/ftp/pub/elfutils/
+ssh sourceware.org "(cd /sourceware/ftp/pub/elfutils \
+  && chmod go+rx $VERSION \
+  && chmod go+r  $VERSION/elfutils-$VERSION.tar.bz2* \
+  && ln -sf $VERSION/elfutils-$VERSION.tar.bz2 elfutils-latest.tar.bz2 \
+  && ln -sf $VERSION/elfutils-$VERSION.tar.bz2.sig elfutils-latest.tar.bz2.sig \
+  && ls -lah elfutils-latest*)"
+
+# Cleanup
+popd
+trap - EXIT
+exit
diff --git a/config/version.h.in b/config/version.h.in
new file mode 100644
index 0000000..34e62c3
--- /dev/null
+++ b/config/version.h.in
@@ -0,0 +1,38 @@
+/* Version information about elfutils development libraries.
+   Copyright (C) 2008 Red Hat, Inc.
+
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ELFUTILS_VERSION_H
+#define _ELFUTILS_VERSION_H	1
+
+#define _ELFUTILS_VERSION	@eu_version@
+
+#define _ELFUTILS_PREREQ(major, minor) \
+  (_ELFUTILS_VERSION >= ((major) * 1000 + (minor)))
+
+#endif	/* elfutils/version.h */
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..bbe8673
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,941 @@
+dnl Process this file with autoconf to produce a configure script.
+dnl Configure input file for elfutils.                     -*-autoconf-*-
+dnl
+dnl Copyright (C) 1996-2019 Red Hat, Inc.
+dnl Copyright (C) 2022, 2023 Mark J. Wielaard <mark@klomp.org>
+dnl
+dnl This file is part of elfutils.
+dnl
+dnl  This file is free software; you can redistribute it and/or modify
+dnl  it under the terms of the GNU General Public License as published by
+dnl  the Free Software Foundation; either version 3 of the License, or
+dnl  (at your option) any later version.
+dnl
+dnl  elfutils is distributed in the hope that it will be useful, but
+dnl  WITHOUT ANY WARRANTY; without even the implied warranty of
+dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+dnl  GNU General Public License for more details.
+dnl
+dnl  You should have received a copy of the GNU General Public License
+dnl  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+AC_INIT([elfutils],[0.191],[https://sourceware.org/bugzilla],[elfutils],[http://elfutils.org/])
+
+dnl Workaround for older autoconf < 2.64
+m4_ifndef([AC_PACKAGE_URL],
+         [AC_DEFINE([PACKAGE_URL], ["http://elfutils.org/"],
+                    [Define to home page for this package])
+          AC_SUBST([PACKAGE_URL], ["http://elfutils.org/"])])
+
+LIBDEBUGINFOD_SONAME=libdebuginfod.so.1
+AC_SUBST([LIBDEBUGINFOD_SONAME])
+
+# We want eu- as default program prefix if none was given by the user.
+# But if the user explicitly provided --program-prefix="" then pretend
+# it wasn't set at all (NONE). We want to test this really early before
+# configure has a chance to use the value.
+
+if test "x$program_prefix" = "xNONE"; then
+  AC_MSG_NOTICE([No --program-prefix given, using "eu-"])
+  program_prefix="eu-"
+elif test "x$program_prefix" = "x"; then
+  AC_MSG_NOTICE([Using no program-prefix])
+  program_prefix=NONE
+fi
+
+AC_CONFIG_AUX_DIR([config])
+AC_CONFIG_FILES([config/Makefile])
+
+AC_COPYRIGHT([Copyright (C) 1996-2024 The elfutils developers.])
+AC_PREREQ(2.63)			dnl Minimum Autoconf version required.
+
+dnl We use GNU make extensions; automake 1.10 defaults to -Wportability.
+AM_INIT_AUTOMAKE([gnits 1.11 -Wno-portability dist-bzip2 no-dist-gzip parallel-tests])
+AM_MAINTAINER_MODE
+
+AM_SILENT_RULES([yes])
+
+AC_CONFIG_SRCDIR([libelf/libelf.h])
+AC_CONFIG_FILES([Makefile])
+AC_CONFIG_HEADERS([config.h])
+
+dnl The RPM spec file.  We substitute a few values in the file.
+AC_CONFIG_FILES([elfutils.spec:config/elfutils.spec.in])
+
+dnl debuginfo-server client & server parts.
+AC_CONFIG_FILES([debuginfod/Makefile debuginfod/debuginfod.h])
+
+AC_CANONICAL_HOST
+
+AC_ARG_ENABLE(deterministic-archives,
+[AS_HELP_STRING([--enable-deterministic-archives],
+		[ar and ranlib default to -D behavior])], [
+if test "${enableval}" = no; then
+  default_ar_deterministic=false
+else
+  default_ar_deterministic=true
+fi], [default_ar_deterministic=false])
+AC_DEFINE_UNQUOTED(DEFAULT_AR_DETERMINISTIC, $default_ar_deterministic,
+		   [Should ar and ranlib use -D behavior by default?])
+
+AC_ARG_ENABLE([thread-safety],
+AS_HELP_STRING([--enable-thread-safety],
+               [enable thread safety of libraries EXPERIMENTAL]),
+               use_locks=$enableval, use_locks=no)
+AM_CONDITIONAL(USE_LOCKS, test "$use_locks" = yes)
+AS_IF([test "$use_locks" = yes], [AC_DEFINE(USE_LOCKS)])
+AS_IF([test "$use_locks" = yes],
+      [AC_MSG_WARN([thread-safety is EXPERIMENTAL tests might fail.])])
+
+AH_TEMPLATE([USE_LOCKS], [Defined if libraries should be thread-safe.])
+
+m4_version_prereq([2.70], [AC_PROG_CC], [AC_PROG_CC_C99])
+AC_PROG_CXX
+AC_PROG_RANLIB
+AC_PROG_YACC
+AC_PROG_LEX([noyywrap])
+# Only available since automake 1.12
+m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
+AC_CHECK_TOOL([READELF], [readelf])
+AC_CHECK_TOOL([NM], [nm])
+
+AC_CACHE_CHECK([whether gcc supports __attribute__((visibility()))],
+	ac_cv_visibility, [dnl
+save_CFLAGS="$CFLAGS"
+CFLAGS="$save_CFLAGS -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl
+int __attribute__((visibility("hidden")))
+foo (int a)
+{
+  return a;
+}])], ac_cv_visibility=yes, ac_cv_visibility=no)
+CFLAGS="$save_CFLAGS"])
+if test "$ac_cv_visibility" = "yes"; then
+	AC_DEFINE([HAVE_VISIBILITY], [1],
+		  [Defined if __attribute__((visibility())) is supported])
+fi
+
+AC_CACHE_CHECK([whether gcc supports __attribute__((gcc_struct))],
+	ac_cv_gcc_struct, [dnl
+save_CFLAGS="$CFLAGS"
+CFLAGS="$save_CFLAGS -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl
+struct test { int x; } __attribute__((gcc_struct));
+])], ac_cv_gcc_struct=yes, ac_cv_gcc_struct=no)
+CFLAGS="$save_CFLAGS"])
+if test "$ac_cv_gcc_struct" = "yes"; then
+	AC_DEFINE([HAVE_GCC_STRUCT], [1],
+		  [Defined if __attribute__((gcc_struct)) is supported])
+fi
+
+AC_CACHE_CHECK([whether gcc supports -fPIC], ac_cv_fpic, [dnl
+save_CFLAGS="$CFLAGS"
+CFLAGS="$save_CFLAGS -fPIC -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE()], ac_cv_fpic=yes, ac_cv_fpic=no)
+CFLAGS="$save_CFLAGS"
+])
+if test "$ac_cv_fpic" = "yes"; then
+	fpic_CFLAGS="-fPIC"
+else
+	fpic_CFLAGS=""
+fi
+AC_SUBST([fpic_CFLAGS])
+
+AC_CACHE_CHECK([whether gcc supports -fPIE], ac_cv_fpie, [dnl
+save_CFLAGS="$CFLAGS"
+CFLAGS="$save_CFLAGS -fPIE -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE()], ac_cv_fpie=yes, ac_cv_fpie=no)
+CFLAGS="$save_CFLAGS"
+])
+if test "$ac_cv_fpie" = "yes"; then
+	fpie_CFLAGS="-fPIE"
+else
+	fpie_CFLAGS=""
+fi
+AC_SUBST([fpie_CFLAGS])
+
+dso_LDFLAGS="-shared"
+
+NO_UNDEFINED=-Wl,--no-undefined
+AC_ARG_ENABLE([sanitize-memory],
+              AS_HELP_STRING([--enable-sanitize-memory],
+                             [Use clang memory sanitizer]),
+                             [use_msan=$enableval], [use_msan=no])
+if test "$use_msan" = yes; then
+  old_CFLAGS="$CFLAGS"
+  old_CXXFLAGS="$CXXFLAGS"
+  old_LDFLAGS="$LDFLAGS"
+  # -fsanitize=memory is not compatible with -D_FORTIFY_SOURCE, -Wl,-z,defs and --no-undefined
+  CFLAGS="$CFLAGS -fsanitize=memory -fsanitize-memory-track-origins -D_FORTIFY_SOURCE=0"
+  CXXFLAGS="$CXXFLAGS -fsanitize=memory -fsanitize-memory-track-origins -D_FORTIFY_SOURCE=0"
+  LDFLAGS="-shared"
+  AC_LINK_IFELSE([AC_LANG_SOURCE([int main (int argc, char **argv) { return 0; }])], use_msan=yes, use_msan=no)
+  AS_IF([test "x$use_msan" = xyes],
+        ac_cv_zdefs=no NO_UNDEFINED=,
+        AC_MSG_WARN([clang memory sanitizer not available])
+        CFLAGS="$old_CFLAGS" CXXFLAGS="$old_CXXFLAGS")
+  LDFLAGS="$old_LDFLAGS"
+fi
+AC_SUBST(NO_UNDEFINED)
+AM_CONDITIONAL(USE_MEMORY_SANITIZER, test "$use_msan" = yes)
+
+ZDEFS_LDFLAGS="-Wl,-z,defs"
+AC_CACHE_CHECK([whether gcc supports $ZDEFS_LDFLAGS], ac_cv_zdefs, [dnl
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$ZDEFS_LDFLAGS $save_LDFLAGS"
+AC_LINK_IFELSE([AC_LANG_PROGRAM()], ac_cv_zdefs=yes, ac_cv_zdefs=no)
+LDFLAGS="$save_LDFLAGS"
+])
+if test "$ac_cv_zdefs" = "yes"; then
+	dso_LDFLAGS="$dso_LDFLAGS $ZDEFS_LDFLAGS"
+fi
+
+# We really want build-ids. Warn and force generating them if gcc was
+# configure without --enable-linker-build-id
+AC_CACHE_CHECK([whether the compiler generates build-ids], ac_cv_buildid, [dnl
+AC_LINK_IFELSE([AC_LANG_PROGRAM()],[ac_cv_buildid=yes; $READELF -n conftest$EXEEXT | grep -q NT_GNU_BUILD_ID || ac_cv_buildid=no],AC_MSG_FAILURE([unexpected compile failure]))])
+if test "$ac_cv_buildid" = "no"; then
+	AC_MSG_WARN([compiler doesn't generate build-id by default])
+	LDFLAGS="$LDFLAGS -Wl,--build-id"
+fi
+
+ZRELRO_LDFLAGS="-Wl,-z,relro"
+AC_CACHE_CHECK([whether gcc supports $ZRELRO_LDFLAGS], ac_cv_zrelro, [dnl
+save_LDFLAGS="$LDFLAGS"
+LDFLAGS="$ZRELRO_LDFLAGS $save_LDFLAGS"
+AC_LINK_IFELSE([AC_LANG_PROGRAM()], ac_cv_zrelro=yes, ac_cv_zrelro=no)
+LDFLAGS="$save_LDFLAGS"
+])
+if test "$ac_cv_zrelro" = "yes"; then
+	dso_LDFLAGS="$dso_LDFLAGS $ZRELRO_LDFLAGS"
+fi
+
+AC_SUBST([dso_LDFLAGS])
+
+AC_CACHE_CHECK([for __thread support], ac_cv_tls, [dnl
+# Use the same flags that we use for our DSOs, so the test is representative.
+# Some old compiler/linker/libc combinations fail some ways and not others.
+save_CFLAGS="$CFLAGS"
+save_LDFLAGS="$LDFLAGS"
+CFLAGS="$fpic_CFLAGS $CFLAGS"
+LDFLAGS="$dso_LDFLAGS $LDFLAGS"
+AC_LINK_IFELSE([dnl
+AC_LANG_PROGRAM([[#include <stdlib.h>
+#undef __thread
+static __thread int a; int foo (int b) { return a + b; }]],
+		[[exit (foo (0));]])],
+	       ac_cv_tls=yes, ac_cv_tls=no)
+CFLAGS="$save_CFLAGS"
+LDFLAGS="$save_LDFLAGS"])
+AS_IF([test "x$ac_cv_tls" != xyes],
+      AC_MSG_ERROR([__thread support required]))
+
+dnl Before 4.9 gcc doesn't ship stdatomic.h, but the necessary atomics are
+dnl available by (at least) 4.7. So if the system doesn't have a stdatomic.h we
+dnl fall back on one copied from FreeBSD that handles the difference.
+AC_CACHE_CHECK([whether gcc provides stdatomic.h], ac_cv_has_stdatomic,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <stdatomic.h>]])],
+		     ac_cv_has_stdatomic=yes, ac_cv_has_stdatomic=no)])
+AM_CONDITIONAL(HAVE_STDATOMIC_H, test "x$ac_cv_has_stdatomic" = xyes)
+AS_IF([test "x$ac_cv_has_stdatomic" = xyes], [AC_DEFINE(HAVE_STDATOMIC_H)])
+
+AH_TEMPLATE([HAVE_STDATOMIC_H], [Define to 1 if `stdatomic.h` is provided by the
+                                 system, 0 otherwise.])
+
+dnl This test must come as early as possible after the compiler configuration
+dnl tests, because the choice of the file model can (in principle) affect
+dnl whether functions and headers are available, whether they work, etc.
+AC_SYS_LARGEFILE
+
+dnl Older glibc had a broken fts that didn't work with Large File Systems.
+dnl We want the version that can handler LFS, but include workaround if we
+dnl get a bad one. Add define to CFLAGS (not AC_DEFINE it) since we need to
+dnl check it before including config.h (which might define _FILE_OFFSET_BITS).
+AC_CACHE_CHECK([whether fts.h is bad when included (with LFS)], ac_cv_bad_fts,
+  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#include <fts.h>]])],
+		     ac_cv_bad_fts=no, ac_cv_bad_fts=yes)])
+AS_IF([test "x$ac_cv_bad_fts" = "xyes"],
+      [CFLAGS="$CFLAGS -DBAD_FTS=1" CXXFLAGS="$CXXFLAGS -DBAD_FTS=1"])
+
+# See if we can add -D_FORTIFY_SOURCE=2 or =3. Don't do it if it is already
+# (differently) defined or if it generates warnings/errors because we
+# don't use the right optimisation level (string.h will warn about that).
+AC_MSG_CHECKING([whether to add -D_FORTIFY_SOURCE=2 or =3 to CFLAGS])
+case "$CFLAGS" in
+  *-D_FORTIFY_SOURCE=*)
+    AC_MSG_RESULT([no, already there])
+    ;;
+  *)
+    save_CFLAGS="$CFLAGS"
+    # Try 3 first.
+    CFLAGS="-D_FORTIFY_SOURCE=3 $save_CFLAGS -Werror"
+    fortified_cflags=""
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+      #include <string.h>
+      int main() { return 0; }
+    ]])], [ AC_MSG_RESULT([yes -D_FORTIFY_SOURCE=3])
+            fortified_cflags="-D_FORTIFY_SOURCE=3" ], [])
+
+    # If that didn't work, try 2.
+    if test -z "$fortified_cflags"; then
+      CFLAGS="-D_FORTIFY_SOURCE=2 $save_CFLAGS -Werror"
+      AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+        #include <string.h>
+        int main() { return 0; }
+      ]])], [ AC_MSG_RESULT([yes -D_FORTIFY_SOURCE=2])
+              fortified_cflags="-D_FORTIFY_SOURCE=2" ],
+              [ AC_MSG_RESULT([no, cannot be used])])
+    fi
+    CFLAGS="$fortified_cflags $save_CFLAGS"
+    CXXFLAGS="$fortified_cflags $CXXFLAGS"
+    ;;
+esac
+
+dnl enable debugging of branch prediction.
+AC_ARG_ENABLE([debugpred],
+AS_HELP_STRING([--enable-debugpred],[build binaries with support to debug branch prediction]),
+[use_debugpred=$enableval], [use_debugpred=no])
+case $use_debugpred in
+ yes) use_debugpred_val=1 ;;
+ *)   use_debugpred_val=0 ;;
+esac
+AC_SUBST([DEBUGPRED], $use_debugpred_val)
+
+dnl Enable gprof support.
+AC_ARG_ENABLE([gprof],
+AS_HELP_STRING([--enable-gprof],[build binaries with gprof support]), [use_gprof=$enableval], [use_gprof=no])
+if test "$use_gprof" = yes; then
+  CFLAGS="$CFLAGS -pg"
+  LDFLAGS="$LDFLAGS -pg"
+fi
+AM_CONDITIONAL(GPROF, test "$use_gprof" = yes)
+
+# Enable gcov support.
+AC_ARG_ENABLE([gcov],
+AS_HELP_STRING([--enable-gcov],[build binaries with gcov support]), [use_gcov=$enableval], [use_gcov=no])
+if test "$use_gcov" = yes; then
+  CFLAGS="$CFLAGS -fprofile-arcs -ftest-coverage"
+  CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage"
+  LDFLAGS="$LDFLAGS -fprofile-arcs"
+  AC_CHECK_PROG([GCOV], [gcov], [gcov])
+  AC_CHECK_PROG([LCOV], [lcov], [lcov])
+  AC_CHECK_PROG([GENHTML], [genhtml], [genhtml])
+fi
+AM_CONDITIONAL(GCOV, test "$use_gcov" = yes)
+
+AC_ARG_ENABLE([sanitize-undefined],
+              AS_HELP_STRING([--enable-sanitize-undefined],
+                             [Use gcc undefined behaviour sanitizer]),
+                             [use_undefined=$enableval], [use_undefined=no])
+if test "$use_undefined" = yes; then
+  old_CFLAGS="$CFLAGS"
+  old_CXXFLAGS="$CXXFLAGS"
+  # We explicitly use unaligned access when possible (see ALLOW_UNALIGNED)
+  # We want to fail immediately on first error, don't try to recover.
+  CFLAGS="$CFLAGS -fsanitize=undefined -fno-sanitize-recover"
+  CXXFLAGS="$CXXFLAGS -fsanitize=undefined -fno-sanitize-recover"
+  AC_LINK_IFELSE([AC_LANG_SOURCE([int main (int argc, char **argv) { return 0; }])], use_undefined=yes, use_undefined=no)
+  AS_IF([test "x$use_undefined" != xyes],
+        AC_MSG_WARN([gcc undefined behaviour sanitizer not available])
+        CFLAGS="$old_CFLAGS" CXXFLAGS="$old_CXXFLAGS")
+fi
+case $use_undefined in
+ yes) check_undefined_val=1 ;;
+ *)   check_undefined_val=0 ;;
+esac
+AC_DEFINE_UNQUOTED(CHECK_UNDEFINED, $check_undefined_val,
+		   [Building with -fsanitize=undefined or not])
+
+AC_ARG_ENABLE([sanitize-address],
+              AS_HELP_STRING([--enable-sanitize-address],
+                             [Use gcc address sanitizer]),
+                             [use_address=$enableval], [use_address=no])
+if test "$use_address" = yes; then
+  old_CFLAGS="$CFLAGS"
+  old_CXXFLAGS="$CXXFLAGS"
+  old_LDFLAGS="$LDFLAGS"
+  # We want to fail immediately on first error, don't try to recover.
+  CFLAGS="$CFLAGS -fsanitize=address -fno-sanitize-recover"
+  CXXFLAGS="$CXXFLAGS -fsanitize=address -fno-sanitize-recover"
+  # Some compilers don't handle -fsanatize=address correctly with --no-undefined
+  LDFLAGS="-Wl,-z,defs -shared"
+  AC_LINK_IFELSE([AC_LANG_SOURCE([int main (int argc, char **argv) { return 0; }])], use_address=yes, use_address=no)
+  AS_IF([test "x$use_address" != xyes],
+        AC_MSG_WARN([gcc address sanitizer not available])
+        CFLAGS="$old_CFLAGS" CXXFLAGS="$old_CXXFLAGS")
+  LDFLAGS="$old_LDFLAGS"
+fi
+AM_CONDITIONAL(USE_ADDRESS_SANITIZER, test "$use_address" = yes)
+
+AC_ARG_ENABLE([valgrind],
+AS_HELP_STRING([--enable-valgrind],[run all tests under valgrind]),
+[use_valgrind=$enableval], [use_valgrind=no])
+if test "$use_valgrind" = yes; then
+  if test "$use_address" = yes; then
+    AC_MSG_ERROR([cannot enable valgrind and sanitize address together])
+  fi
+  AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no)
+  if test "$HAVE_VALGRIND" = "no"; then
+    AC_MSG_ERROR([valgrind not found])
+  fi
+fi
+AM_CONDITIONAL(USE_VALGRIND, test "$use_valgrind" = yes)
+
+AC_ARG_WITH([valgrind],
+AS_HELP_STRING([--with-valgrind],[include directory for Valgrind headers]),
+[with_valgrind_headers=$withval], [with_valgrind_headers=no])
+if test "x$with_valgrind_headers" != xno; then
+    save_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS -I$with_valgrind_headers"
+    AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+      #include <valgrind/valgrind.h>
+      int main() { return 0; }
+    ]])], [ HAVE_VALGRIND_HEADERS="yes"
+            CFLAGS="$save_CFLAGS -I$with_valgrind_headers" ],
+          [ AC_MSG_ERROR([invalid valgrind include directory: $with_valgrind_headers]) ])
+fi
+
+AC_ARG_ENABLE([valgrind-annotations],
+AS_HELP_STRING([--enable-valgrind-annotations],[insert extra annotations for better valgrind support]),
+[use_vg_annotations=$enableval], [use_vg_annotations=no])
+if test "$use_vg_annotations" = yes; then
+    if test "x$HAVE_VALGRIND_HEADERS" != "xyes"; then
+      AC_MSG_CHECKING([whether Valgrind headers are available])
+      AC_COMPILE_IFELSE([AC_LANG_SOURCE([[
+        #include <valgrind/valgrind.h>
+        int main() { return 0; }
+      ]])], [ AC_MSG_RESULT([yes]) ],
+            [ AC_MSG_ERROR([valgrind annotations requested but no headers are available]) ])
+    fi
+fi
+AM_CONDITIONAL(USE_VG_ANNOTATIONS, test "$use_vg_annotations" = yes)
+
+AC_ARG_ENABLE([install-elfh],
+AS_HELP_STRING([--enable-install-elfh],[install elf.h in include dir]),
+               [install_elfh=$enableval], [install_elfh=no])
+AM_CONDITIONAL(INSTALL_ELFH, test "$install_elfh" = yes)
+
+AM_CONDITIONAL(BUILD_STATIC, [dnl
+test "$use_gprof" = yes -o "$use_gcov" = yes])
+
+AC_ARG_ENABLE([tests-rpath],
+AS_HELP_STRING([--enable-tests-rpath],[build $ORIGIN-using rpath into tests]),
+	       [tests_use_rpath=$enableval], [tests_use_rpath=no])
+AM_CONDITIONAL(TESTS_RPATH, test "$tests_use_rpath" = yes)
+
+dnl zlib is mandatory.
+save_LIBS="$LIBS"
+LIBS=
+eu_ZIPLIB(zlib,ZLIB,z,gzdirect,gzip)
+AS_IF([test "x$with_zlib" = xno], [AC_MSG_ERROR([zlib not found but is required])])
+LIBS="$save_LIBS"
+
+dnl Test for bzlib and xz/lzma/zstd, gives BZLIB/LZMALIB/ZSTD .am
+dnl conditional and config.h USE_BZLIB/USE_LZMALIB/USE_ZSTD #define.
+save_LIBS="$LIBS"
+LIBS=
+eu_ZIPLIB(bzlib,BZLIB,bz2,BZ2_bzdopen,bzip2)
+# We need this since bzip2 doesn't have a pkgconfig file.
+BZ2_LIB="$LIBS"
+AC_SUBST([BZ2_LIB])
+eu_ZIPLIB(lzma,LZMA,lzma,lzma_auto_decoder,[LZMA (xz)])
+AS_IF([test "x$with_lzma" = xyes], [LIBLZMA="liblzma"], [LIBLZMA=""])
+AC_SUBST([LIBLZMA])
+eu_ZIPLIB(zstd,ZSTD,zstd,ZSTD_decompress,[ZSTD (zst)])
+AS_IF([test "x$with_zstd" = xyes], [LIBZSTD="libzstd"], [LIBLZSTD=""])
+AC_SUBST([LIBZSTD])
+zstd_LIBS="$LIBS"
+AC_SUBST([zstd_LIBS])
+zip_LIBS="$LIBS"
+LIBS="$save_LIBS"
+AC_SUBST([zip_LIBS])
+
+dnl zstd compression support requires libzstd 1.4.0+
+AS_IF([test "x$with_zstd" = xyes], [
+      PKG_PROG_PKG_CONFIG
+      PKG_CHECK_MODULES([ZSTD_COMPRESS],[libzstd >= 1.4.0],
+                        [with_zstd_compress="yes"],[with_zstd_compress="no"])],
+      [with_zstd_compress="no"])
+AM_CONDITIONAL(USE_ZSTD_COMPRESS, test "x$with_zstd_compress" = "xyes")
+AS_IF([test "x$with_zstd_compress" = "xyes"],
+      [AC_DEFINE([USE_ZSTD_COMPRESS], [1], [zstd compression support])])
+
+AC_CHECK_DECLS([memrchr, rawmemchr],[],[],
+               [#define _GNU_SOURCE
+                #include <string.h>])
+AC_CHECK_DECLS([powerof2],[],[],[#include <sys/param.h>])
+AC_CHECK_DECLS([mempcpy],[],[],
+               [#define _GNU_SOURCE
+                #include <string.h>])
+AC_CHECK_DECLS([reallocarray],[],[],
+               [#define _GNU_SOURCE
+                #include <stdlib.h>])
+
+AC_CHECK_FUNCS([process_vm_readv mremap])
+
+AS_IF([test "x$ac_cv_func_mremap" = "xno"],
+      [AC_MSG_WARN([elf_update needs mremap to support ELF_C_RDWR_MMAP])])
+
+AC_CHECK_HEADERS([error.h])
+AC_CHECK_HEADERS([err.h])
+
+dnl for debuginfod concurrency heuristics
+AC_CHECK_HEADERS([sched.h])
+AC_CHECK_FUNCS([sched_getaffinity])
+AC_CHECK_HEADERS([sys/resource.h])
+AC_CHECK_FUNCS([getrlimit])
+
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -D_GNU_SOURCE"
+AC_FUNC_STRERROR_R()
+CFLAGS="$old_CFLAGS"
+
+AC_ARG_ENABLE([demangler],
+AS_HELP_STRING([--disable-demangler],
+	       [Disable libstdc++ demangle support]),
+	       [], [enable_demangler=yes])
+AS_IF([test "x$enable_demangler" = xyes],
+AC_CHECK_LIB([stdc++], [__cxa_demangle], [dnl
+AC_DEFINE([USE_DEMANGLE], [1], [Defined if demangling is enabled])])
+AM_CONDITIONAL(DEMANGLE, test "x$ac_cv_lib_stdcpp___cxa_demangle" = "xyes")
+AS_IF([test "x$ac_cv_lib_stdcpp___cxa_demangle" = "xyes"],
+      [enable_demangler=yes],
+      [AC_MSG_ERROR([[__cxa_demangle not found in libstdc++, use --disable-demangler to disable demangler support.]])]),
+AM_CONDITIONAL(DEMANGLE, false))
+
+AC_ARG_ENABLE([textrelcheck],
+AS_HELP_STRING([--disable-textrelcheck],
+               [Disable textrelcheck being a fatal error]))
+AM_CONDITIONAL(FATAL_TEXTREL, [test "x$enable_textrelcheck" != "xno"])
+AS_IF([test "x$enable_textrelcheck" != "xno"],
+      [enable_textrelcheck=yes],[enable_textrelcheck=no])
+
+AC_ARG_ENABLE([symbol-versioning],
+AS_HELP_STRING([--disable-symbol-versioning],
+               [Disable symbol versioning in shared objects]))
+
+AC_CACHE_CHECK([whether symbol versioning is supported], ac_cv_symbol_versioning, [dnl
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([dnl
+#define NEW_VERSION(name, version) \
+  asm (".symver " #name "," #name "@@@" #version);
+int foo(int x) { return x + 1; }
+NEW_VERSION (foo, ELFUTILS_12.12)
+])], ac_cv_symbol_versioning=yes, ac_cv_symbol_versioning=no)])
+if test "$ac_cv_symbol_versioning" = "no"; then
+    if test "x$enable_symbol_versioning" != "xno"; then
+        AC_MSG_ERROR([Symbol versioning is not supported.
+                      Use --disable-symbol-versioning to build without.])
+    fi
+fi
+
+AM_CONDITIONAL(SYMBOL_VERSIONING, [test "x$enable_symbol_versioning" != "xno"])
+AS_IF([test "x$enable_symbol_versioning" = "xno"],
+      [AC_MSG_WARN([Disabling symbol versioning breaks ABI compatibility.])
+       enable_symbol_versioning=no],[enable_symbol_versioning=yes])
+
+AC_CACHE_CHECK([whether gcc accepts -Wstack-usage], ac_cv_stack_usage, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wstack-usage=262144 -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_stack_usage=yes, ac_cv_stack_usage=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(ADD_STACK_USAGE_WARNING, [test "x$ac_cv_stack_usage" != "xno"])
+
+# -Wlogical-op was too fragile in the past, make sure we get a sane one.
+AC_CACHE_CHECK([whether gcc has a sane -Wlogical-op], ac_cv_logical_op, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wlogical-op -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE(
+	[#define FLAG 1
+	int f (int r, int f) { return (r && (FLAG || (FLAG & f))); }])],
+		  ac_cv_logical_op=yes, ac_cv_logical_op=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(SANE_LOGICAL_OP_WARNING,
+	       [test "x$ac_cv_logical_op" != "xno"])
+
+# -Wduplicated-cond was added by GCC6
+AC_CACHE_CHECK([whether gcc accepts -Wduplicated-cond], ac_cv_duplicated_cond, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wduplicated-cond -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_duplicated_cond=yes, ac_cv_duplicated_cond=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_DUPLICATED_COND_WARNING,
+	       [test "x$ac_cv_duplicated_cond" != "xno"])
+
+# -Wnull-dereference was added by GCC6
+AC_CACHE_CHECK([whether gcc accepts -Wnull-dereference], ac_cv_null_dereference, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wnull-dereference -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_null_dereference=yes, ac_cv_null_dereference=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_NULL_DEREFERENCE_WARNING,
+	       [test "x$ac_cv_null_dereference" != "xno"])
+
+# -Wimplicit-fallthrough was added by GCC7
+AC_CACHE_CHECK([whether gcc accepts -Wimplicit-fallthrough], ac_cv_implicit_fallthrough, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wimplicit-fallthrough -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_implicit_fallthrough=yes, ac_cv_implicit_fallthrough=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_IMPLICIT_FALLTHROUGH_WARNING,
+	       [test "x$ac_cv_implicit_fallthrough" != "xno"])
+
+# Check whether the compiler additionally accepts -Wimplicit-fallthrough=5
+# GCC accepts this and 5 means "don't parse any fallthrough comments and
+# only accept the fallthrough attribute"
+AC_CACHE_CHECK([whether the compiler accepts -Wimplicit-fallthrough=5], ac_cv_implicit_fallthrough_5, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wimplicit-fallthrough=5 -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_implicit_fallthrough_5=yes, ac_cv_implicit_fallthrough_5=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_IMPLICIT_FALLTHROUGH_5_WARNING,
+	       [test "x$ac_cv_implicit_fallthrough_5" != "xno"])
+
+# Assume the fallthrough attribute is supported if -Wimplict-fallthrough is supported
+if test "$ac_cv_implicit_fallthrough" = "yes"; then
+	AC_DEFINE([HAVE_FALLTHROUGH], [1],
+		  [Defined if __attribute__((fallthrough)) is supported])
+fi
+
+AC_CACHE_CHECK([whether the compiler accepts -Wtrampolines], ac_cv_trampolines, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wtrampolines -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_trampolines=yes, ac_cv_trampolines=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_TRAMPOLINES_WARNING,
+	       [test "x$ac_cv_trampolines" != "xno"])
+
+AC_CACHE_CHECK([whether the compiler accepts -Wno-packed-not-aligned], ac_cv_no_packed_not_aligned, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wno-packed-not-aligned -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_no_packed_not_aligned=yes, ac_cv_no_packed_not_aligned=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_NO_PACKED_NOT_ALIGNED_WARNING,
+	       [test "x$ac_cv_no_packed_not_aligned" != "xno"])
+
+AC_CACHE_CHECK([whether the compiler accepts -Wuse-after-free=3], ac_cv_use_after_free3, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -Wuse-after-free=3 -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+		  ac_cv_use_after_free3=yes, ac_cv_use_after_free3=no)
+CFLAGS="$old_CFLAGS"])
+AM_CONDITIONAL(HAVE_USE_AFTER_FREE3_WARNING,
+	       [test "x$ac_cv_use_after_free3" != "xno"])
+
+AC_CACHE_CHECK([whether the compiler accepts -fno-addrsig], ac_cv_fno_addrsig, [dnl
+old_CFLAGS="$CFLAGS"
+CFLAGS="$CFLAGS -fno-addrsig -Werror"
+AC_COMPILE_IFELSE([AC_LANG_SOURCE([])],
+                  ac_cv_fno_addrsig=yes, ac_cv_fno_addrsig=no)
+CFLAGS="$old_CFLAGS"])
+AS_IF([test "x$ac_cv_fno_addrsig" = "xyes"], CFLAGS="$CFLAGS -fno-addrsig")
+
+saved_LIBS="$LIBS"
+AC_SEARCH_LIBS([argp_parse], [argp])
+LIBS="$saved_LIBS"
+case "$ac_cv_search_argp_parse" in
+        no) AC_MSG_FAILURE([failed to find argp_parse]) ;;
+        -l*) argp_LDADD="$ac_cv_search_argp_parse" ;;
+        *) argp_LDADD= ;;
+esac
+AC_SUBST([argp_LDADD])
+
+saved_LIBS="$LIBS"
+AC_SEARCH_LIBS([fts_close], [fts])
+LIBS="$saved_LIBS"
+case "$ac_cv_search_fts_close" in
+        no) AC_MSG_FAILURE([failed to find fts_close]) ;;
+        -l*) fts_LIBS="$ac_cv_search_fts_close" ;;
+        *) fts_LIBS= ;;
+esac
+AC_SUBST([fts_LIBS])
+
+saved_LIBS="$LIBS"
+AC_SEARCH_LIBS([_obstack_free], [obstack])
+LIBS="$saved_LIBS"
+case "$ac_cv_search__obstack_free" in
+        no) AC_MSG_FAILURE([failed to find _obstack_free]) ;;
+        -l*) obstack_LIBS="$ac_cv_search__obstack_free" ;;
+        *) obstack_LIBS= ;;
+esac
+AC_SUBST([obstack_LIBS])
+
+dnl The directories with content.
+
+dnl Documentation.
+AC_CONFIG_FILES([doc/Makefile])
+
+dnl Support library.
+AC_CONFIG_FILES([lib/Makefile])
+
+dnl ELF library.
+AC_CONFIG_FILES([libelf/Makefile])
+
+dnl Higher-level ELF support library.
+AC_CONFIG_FILES([libebl/Makefile])
+
+dnl DWARF-ELF Lower-level Functions support library.
+AC_CONFIG_FILES([libdwelf/Makefile])
+
+dnl DWARF library.
+AC_CONFIG_FILES([libdw/Makefile])
+
+dnl Higher-level DWARF support library.
+AC_CONFIG_FILES([libdwfl/Makefile])
+
+dnl CPU handling library.
+AC_CONFIG_FILES([libcpu/Makefile])
+
+dnl Assembler library.
+AC_CONFIG_FILES([libasm/Makefile])
+
+dnl CPU-specific backend libraries.
+AC_CONFIG_FILES([backends/Makefile])
+
+dnl Tools.
+AC_CONFIG_FILES([src/Makefile po/Makefile.in])
+
+dnl Test suite.
+AC_CONFIG_FILES([tests/Makefile])
+
+dnl pkgconfig files
+AC_CONFIG_FILES([config/libelf.pc config/libdw.pc config/libdebuginfod.pc])
+
+dnl As long as "git grep 'PRI[diouxX]' po" reports matches in
+dnl translatable strings, we must use need-formatstring-macros here.
+AM_GNU_GETTEXT([external], [need-formatstring-macros])
+
+dnl AM_GNU_GETTEXT_VERSION is still needed for old versions
+dnl of autoreconf that do not recognize AM_GNU_GETTEXT_REQUIRE_VERSION.
+dnl 0.19.6 is the first version of gettext that provides
+dnl AM_GNU_GETTEXT_REQUIRE_VERSION support.
+AM_GNU_GETTEXT_VERSION([0.19.6])
+AM_GNU_GETTEXT_REQUIRE_VERSION([0.19.6])
+
+dnl Appended to the config.h file.
+dnl We hide all kinds of configuration magic in lib/eu-config.h.
+AH_BOTTOM([#include <eu-config.h>])
+
+dnl Version compatibility header.
+AC_CONFIG_FILES([version.h:config/version.h.in])
+AC_SUBST([eu_version])
+
+# 1.234<whatever> -> 1234<whatever>
+case "$PACKAGE_VERSION" in
+[[0-9]].*) eu_version=`echo "$PACKAGE_VERSION" | sed 's@\.@@'` ;;
+*)     	   AC_MSG_ERROR([confused by version number '$PACKAGE_VERSION']) ;;
+esac
+case "$eu_version" in
+*.*)
+  # 1234.567 -> "1234", "567"
+  eu_extra_version="${eu_version#*.}"
+  eu_version="${eu_version%%.*}"
+  case "$eu_extra_version" in
+  [[0-9]][[0-9]][[0-9]]) ;;
+  [[0-9]][[0-9]])	eu_extra_version="${eu_extra_version}0" ;;
+  [[0-9]])	   	eu_extra_version="${eu_extra_version}00" ;;
+  *) AC_MSG_ERROR([confused by version number '$PACKAGE_VERSION']) ;;
+  esac
+  ;;
+*)
+  eu_extra_version=000
+  ;;
+esac
+
+case "$eu_version" in
+      0[[0-9]][[0-9]][[0-9]]) eu_version="${eu_version#0}$eu_extra_version" ;;
+[[0-9]][[0-9]][[0-9]][[0-9]]) eu_version="${eu_version}$eu_extra_version" ;;
+[[0-9]][[0-9]][[0-9]])	      eu_version="${eu_version}0$eu_extra_version" ;;
+[[0-9]][[0-9]])	  	      eu_version="${eu_version}00$eu_extra_version";;
+*) AC_MSG_ERROR([confused by version number '$PACKAGE_VERSION']) ;;
+esac
+
+# Round up to the next release API (x.y) version.
+eu_version=$(( (eu_version + 999) / 1000 ))
+
+AC_CHECK_SIZEOF(long)
+
+# On aarch64 before glibc 2.20 we would get the kernel user_pt_regs instead
+# of the user_regs_struct from sys/user.h. They are structurally the same
+# but we get either one or the other.
+AC_CHECK_TYPE([struct user_regs_struct],
+              [sys_user_has_user_regs=yes], [sys_user_has_user_regs=no],
+              [[#include <sys/ptrace.h>]
+               [#include <sys/time.h>]
+               [#include <sys/user.h>]])
+if test "$sys_user_has_user_regs" = "yes"; then
+  AC_DEFINE(HAVE_SYS_USER_REGS, 1,
+            [Define to 1 if <sys/user.h> defines struct user_regs_struct])
+fi
+
+# On a 64-bit host where can can use $CC -m32, we'll run two sets of tests.
+utrace_BIARCH
+CC_BIARCH="$CC $utrace_biarch"
+AC_SUBST([CC_BIARCH])
+
+# In maintainer mode we really need flex and bison.
+# Otherwise we really need a release dir with maintainer files generated.
+if test "x$enable_maintainer_mode" = xyes; then
+  AC_CHECK_PROG(HAVE_FLEX, flex, yes, no)
+  if test "$HAVE_FLEX" = "no"; then
+    AC_MSG_ERROR([flex needed in maintainer mode])
+  fi
+  AC_CHECK_PROG(HAVE_BISON, bison, yes, no)
+  if test "$HAVE_BISON" = "no"; then
+    AC_MSG_ERROR([bison needed in maintainer mode])
+  fi
+  AC_CHECK_PROG(HAVE_GAWK, gawk, yes, no)
+  if test "$HAVE_GAWK" = "no"; then
+    AC_MSG_ERROR([gawk needed in maintainer mode])
+  fi
+else
+  if test ! -f ${srcdir}/libdw/known-dwarf.h; then
+    AC_MSG_ERROR([No libdw/known-dwarf.h. configure --enable-maintainer-mode])
+  fi
+fi
+
+# The testfiles are all compressed, we need bunzip2 when running make check
+AC_CHECK_PROG(HAVE_BUNZIP2, bunzip2, yes, no)
+if test "$HAVE_BUNZIP2" = "no"; then
+  AC_MSG_WARN([No bunzip2, needed to run make check])
+fi
+
+# For tests that need to use zstd compression
+AC_CHECK_PROG(HAVE_ZSTD, zstd, yes, no)
+AM_CONDITIONAL([HAVE_ZSTD],[test "x$HAVE_ZSTD" = "xyes"])
+
+# For tests that need to use C++11
+AX_CXX_COMPILE_STDCXX(11, noext, optional)
+AS_IF([test "x$HAVE_CXX11" = "x1"], [HAVE_CXX11=yes], [HAVE_CXX11=no])
+AM_CONDITIONAL([HAVE_CXX11],[test "x$HAVE_CXX11" = "xyes"])
+
+# Look for libcurl for libdebuginfod minimum version as per rhel7.
+AC_ARG_ENABLE([libdebuginfod],AS_HELP_STRING([--enable-libdebuginfod], [Build debuginfod client library (can be =dummy)]))
+AS_IF([test "x$enable_libdebuginfod" != "xno"], [
+    if test "x$enable_libdebuginfod" != "xdummy"; then
+      AC_MSG_NOTICE([checking libdebuginfod dependencies, --disable-libdebuginfod or --enable-libdebuginfo=dummy to skip])
+      enable_libdebuginfod=yes # presume success
+      PKG_PROG_PKG_CONFIG
+      PKG_CHECK_MODULES([libcurl],[libcurl >= 7.29.0],[],[enable_libdebuginfod=no])
+      if test "x$enable_libdebuginfod" = "xno"; then
+        AC_MSG_ERROR([dependencies not found, use --disable-libdebuginfod to disable or --enable-libdebuginfod=dummy to build a (bootstrap) dummy library.])
+      fi
+    else
+      AC_MSG_NOTICE([building (bootstrap) dummy libdebuginfo library])
+    fi
+])
+
+AC_CHECK_LIB(pthread, pthread_setname_np, [
+                      AC_DEFINE([HAVE_PTHREAD_SETNAME_NP],[1],[Enable pthread_setname_np])])
+
+AS_IF([test "x$enable_libdebuginfod" = "xyes" || test "x$enable_libdebuginfod" = "xdummy"],
+      [AC_DEFINE([ENABLE_LIBDEBUGINFOD], [1], [Enable libdebuginfod])])
+AS_IF([test "x$enable_libdebuginfod" = "xdummy"],
+      [AC_DEFINE([DUMMY_LIBDEBUGINFOD], [1], [Build dummy libdebuginfod])])
+AM_CONDITIONAL([LIBDEBUGINFOD],[test "x$enable_libdebuginfod" = "xyes" || test "x$enable_libdebuginfod" = "xdummy"])
+AM_CONDITIONAL([DUMMY_LIBDEBUGINFOD],[test "x$enable_libdebuginfod" = "xdummy"])
+AC_CHECK_HEADERS([execinfo.h])
+
+# Look for libmicrohttpd, libarchive, sqlite for debuginfo server and srcfiles tool
+# minimum versions as per rhel7.
+AC_ARG_ENABLE([debuginfod],AS_HELP_STRING([--enable-debuginfod], [Build debuginfod server]))
+AS_IF([test "x$enable_debuginfod" != "xno"], [
+    if test "x$HAVE_CXX11" = "xno"; then
+      AC_MSG_ERROR([the compiler does not support C++11, use --disable-debuginfod to disable.])
+    fi
+    AC_MSG_NOTICE([checking debuginfod dependencies, --disable-debuginfod to skip])
+    if test "x$enable_libdebuginfod" = "xno"; then
+      AC_MSG_ERROR([need libdebuginfod (or dummy), use --disable-debuginfod to disable.])
+    fi
+    enable_debuginfod=yes # presume success
+    AC_DEFINE([HAVE_LIBARCHIVE], [1], [Define to 1 if libarchive is available]) # presume success
+    PKG_PROG_PKG_CONFIG
+    PKG_CHECK_MODULES([libmicrohttpd],[libmicrohttpd >= 0.9.33],[],[enable_debuginfod=no])
+    PKG_CHECK_MODULES([oldlibmicrohttpd],[libmicrohttpd < 0.9.51],[old_libmicrohttpd=yes],[old_libmicrohttpd=no])
+    PKG_CHECK_MODULES([sqlite3],[sqlite3 >= 3.7.17],[],[enable_debuginfod=no])
+    PKG_CHECK_MODULES([libarchive],[libarchive >= 3.1.2],[],[enable_debuginfod=no], AC_DEFINE([HAVE_LIBARCHIVE], [0], [Define to 0 if libarchive is not available]))
+    if test "x$enable_debuginfod" = "xno"; then
+      AC_MSG_ERROR([dependencies not found, use --disable-debuginfod to disable.])
+    fi
+])
+
+AS_IF([test "x$enable_debuginfod" != "xno"],AC_DEFINE([ENABLE_DEBUGINFOD],[1],[Build debuginfod]))
+AM_CONDITIONAL([DEBUGINFOD],[test "x$enable_debuginfod" = "xyes"])
+AM_CONDITIONAL([OLD_LIBMICROHTTPD],[test "x$old_libmicrohttpd" = "xyes"])
+
+dnl for /etc/profile.d/elfutils.{csh,sh}
+default_debuginfod_urls=""
+AC_ARG_ENABLE(debuginfod-urls,
+            [AS_HELP_STRING([--enable-debuginfod-urls@<:@=URLS@:>@],[add URLS to profile.d DEBUGINFOD_URLS])],
+            [if test "x${enableval}" = "xyes";
+             then default_debuginfod_urls="https://debuginfod.elfutils.org/";
+             elif test "x${enableval}" != "xno"; then
+             default_debuginfod_urls="${enableval}";
+             fi],
+            [default_debuginfod_urls=""])
+AC_SUBST(DEBUGINFOD_URLS, $default_debuginfod_urls)                
+AC_CONFIG_FILES([config/profile.sh config/profile.csh])
+
+AC_OUTPUT
+
+AC_MSG_NOTICE([
+=====================================================================
+        elfutils: ${PACKAGE_VERSION} (eu_version: ${eu_version})
+=====================================================================
+
+    Prefix                             : ${prefix}
+    Program prefix ("eu-" recommended) : ${program_prefix}
+    Source code location               : ${srcdir}
+    Maintainer mode                    : ${enable_maintainer_mode}
+    build arch                         : ${ac_cv_build}
+
+    CFLAGS=${CFLAGS}
+    CXXFLAGS=${CXXFLAGS}
+
+  RECOMMENDED FEATURES (should all be yes)
+    gzip support                       : ${with_zlib}
+    bzip2 support                      : ${with_bzlib}
+    lzma/xz support                    : ${with_lzma}
+    zstd support                       : ${with_zstd}
+    zstd compression support           : ${with_zstd_compress}
+    libstdc++ demangle support         : ${enable_demangler}
+    File textrel check                 : ${enable_textrelcheck}
+    Symbol versioning                  : ${enable_symbol_versioning}
+
+  NOT RECOMMENDED FEATURES (should all be no)
+    Experimental thread safety         : ${use_locks}
+    install elf.h                      : ${install_elfh}
+
+  OTHER FEATURES
+    Deterministic archives by default  : ${default_ar_deterministic}
+    Native language support            : ${USE_NLS}
+    Extra Valgrind annotations         : ${use_vg_annotations}
+    libdebuginfod client support       : ${enable_libdebuginfod}
+    Debuginfod server support          : ${enable_debuginfod}
+    Default DEBUGINFOD_URLS            : ${default_debuginfod_urls}
+
+  EXTRA TEST FEATURES (used with make check)
+    have bunzip2 installed (required)  : ${HAVE_BUNZIP2}
+    have zstd installed                : ${HAVE_ZSTD}
+    C++11                              : ${HAVE_CXX11}
+    debug branch prediction            : ${use_debugpred}
+    gprof support                      : ${use_gprof}
+    gcov support                       : ${use_gcov}
+    run all tests under valgrind       : ${use_valgrind}
+    gcc undefined behaviour sanitizer  : ${use_undefined}
+    gcc address sanitizer              : ${use_address}
+    clang memory sanitizer             : ${use_msan}
+    use rpath in tests                 : ${tests_use_rpath}
+    test biarch                        : ${utrace_cv_cc_biarch}
+])
+
+if test "$install_elfh" = yes; then
+  if test "${prefix}" = "/usr/local" -o "${prefix}" = "/usr"; then
+    AC_MSG_WARN([installing elf.h in ${includedir} might conflict with glibc/system elf.h])
+  fi
+fi
diff --git a/debuginfod/ChangeLog b/debuginfod/ChangeLog
new file mode 100644
index 0000000..0e4810b
--- /dev/null
+++ b/debuginfod/ChangeLog
@@ -0,0 +1,1167 @@
+2023-04-21  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (groom): Fix -r / -X logic.
+
+2023-04-13  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (archive_classify, scan_archive_file): Catch and
+	propagate exceptions during archive scans.
+
+2023-03-30  Jan Alexander Steffens (heftig) <heftig@archlinux.org>
+
+	* debuginfod-client.c (update_atime): New function.
+	(extract_section, debuginfod_query_server): Call it.
+
+2023-03-30  Jan Alexander Steffens (heftig) <heftig@archlinux.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Don't modify
+	atime unintentionally.
+	* debuginfod.cxx (extract_section, handle_buildid_r_match): Ditto.
+
+2023-03-30  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Avoid sscanf on
+	mixed-case component of string.
+
+2023-03-29  Jan Alexander Steffens (heftig) <heftig@archlinux.org>
+
+	* debuginfod-client.c (debuginfod_query_server): s/futimes/futimens/
+	* debuginfod.cxx (extract_section, handle_buildid_r_match): Ditto.
+
+2023-03-29  lilydjwg  <lilydjwg@gmail.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Handle dl_size in
+	progress to account for possible curl 8.0.1 changes to
+	CURLINFO_CONTENT_LENGTH_DOWNLOAD*.
+
+2023-03-17  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Do not create an
+	empty file in the cache if the query was cancelled by the progressfn.
+
+2023-02-07  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (cache_find_section): Avoid returning -ENOENT
+	if debuginfo wasn't found.
+
+2023-02-06  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.h.in: Guard debuginfod_client typedef with
+	_ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF.
+
+2023-01-10  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Use
+	CURL_AT_LEAST_VERSION(7.85.0) for CURLOPT_PROTOCOLS_STR.
+
+2023-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR29975 & PR29976
+	* debuginfod.cxx (default_concurrency): New function to guess a
+	reasonable default for -c/-C on large but constrained machines.
+
+2022-12-21  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c: Define CURL_AT_LEAST_VERSION.
+
+2022-12-21  Andrew Paprocki  <andrew@ishiboo.com>
+
+	* debuginfod-client.c: Make compilable against newer curl.  PR29926
+
+2022-11-15  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Initialize
+	response_data early.
+
+2022-11-07  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_find_section): Don't treat 0 as an
+	error code.
+
+2022-11-04  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_find_section): Ensure rc
+	is always updated with the most recent error code.
+
+2022-11-03  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (handle_buildid): Correctly manage lifetime
+	of debuginfod_client federation callout object.
+
+2022-11-02  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (extract_section): Mark static.
+
+2022-11-01  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (path_escape): Add early return.
+
+2022-10-31  Aaron Merey  <amerey@redhat.com>
+
+	* Makefile.am (libdebuginfod_so_LDLIBS): Add libelf.
+	* debuginfod-client.c (debuginfod_find_section): New function.
+	(path_escape): New function.
+	(extract_section): New function.
+	(cache_find_section): New function.
+	(debuginfod_query_server): Add support for section queries.
+	* debuginfod-find.c (main): Add support for section queries.
+	* debuginfod.cxx (extract_section): New function.
+	(handle_buildid_f_match): Add section parameter.  When non-empty,
+	try to create response from section contents.
+	(handle_buildid_r_match): Add section parameter.  When non-empty,
+	try to create response from section contents.
+	(handle_buildid_match): Add section parameter. Pass to
+	handle_buildid_{f,r}_match.
+	(handle_buildid): Handle section name when artifacttype is set to
+	"section".  Query upstream servers via debuginfod_find_section
+	when necessary.
+	(debuginfod.h.in): Add declaration for debuginfod_find_section.
+	(libdebuginfod.map): Add debuginfod_find_section.
+
+2022-10-18  Daniel Thornburgh <dthorn@google.com>
+
+  * debuginfod-client.c (debuginfod_query_server): Add DEBUGINFOD_HEADERS_FILE
+  setting to supply outgoing HTTP headers.
+
+2022-10-17  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (main): Report libmicrohttpd version.
+
+2022-09-28  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Switch sign of some
+	error codes from positive to negative.
+
+2022-09-08  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Clear
+	->winning_headers along with ->url at the start of any new query.
+
+2022-09-08  Martin Liska  <mliska@suse.cz>
+
+	* debuginfod-client.c (debuginfod_get_headers): Add to DUMMY_LIBDEBUGINFOD.
+
+2022-09-06  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (header_callback): Don't copy \r in x-d headers.
+	Print all headers in verbose_fd mode.
+	* debuginfod-find.c (parse_opt): Set verbose_fd only at verbosity >= 2.
+	* debuginfod.cxx (handle_buildid): Clean up header forwarding
+	string processing.
+	* debuginfod.h.in: (debuginfod_get_headers): Tweak wording.
+	* libdebuginfod.map: Use ELFUTILS_0.188 for new function.
+
+2022-07-15  Noah Sanci  <nsanci@redhat.com>
+
+	* debuginfod-client.c (header_callback): Ignore headers without
+	X-DEBUGINFOD prefix.
+	(debuginfod_query_server): Removed verbose printing headers when
+	undesired.
+	(debuginfod_get_headers): Created.
+	* debuginfod-find.c (main): Verbose printing headers.
+	* debuginfod.cxx (handle_buildid): Add headers prefixed with
+	X-DEBUGINFOD from federated servers to this server's response
+	headers.
+	* debuginfod.h.in (debuginfod_get_headers): Created.
+	* libdebuginfod.map: New elfutils version added.
+
+2022-09-02  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod.cxx (parse_opt): If '-C' is given with no arg, do not
+	update connection_pool since it will be done at a later point.
+	(main): Use auto-sized connection_pool if '-C' isn't given with an
+	arg. Do not use MHD_USE_THREAD_PER_CONNECTION.
+
+2022-08-17  Martin Liska  <mliska@suse.cz>
+
+	* debuginfod.cxx (handle_buildid): Update HTTP statistics only if
+	it comes from HTTP request.
+
+2022-08-17  Martin Liska  <mliska@suse.cz>
+
+	* debuginfod.cxx: Print filename for "cannot open archive".
+
+2022-08-15  Frank Ch. Eigler <fche@redhat.com>
+
+	PR29474
+	* debuginfod.cxx (handle_buildid_r_match): Don't trigger false-404's
+	for concurrently prefetched target files.
+
+2022-08-02  Josef Cejka <jcejka@suse.de>
+
+	* debuginfod.cxx (groom): Don't evaluate regex unless needed.
+
+2022-07-29  Josef Cejka <jcejka@suse.de>
+
+	* debuginfod.cxx: Create db indexes for fast delete while grooming.
+
+2022-06-03  Michael Trapp <michael.trapp@sap.com>
+
+	* debuginfod.cxx (scan_source_info): New global.
+	(parse_opt, elf_classify): Use it.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_clean_cache): Move utime call to
+	before fts traversal.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_init_cache): Remove.
+	(debuginfod_query_server): Don't call debuginfod_init_cache, call
+	mkdir then debuginfod_clean_cache.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_config_cache): Always open with
+	O_CREATE first, then use fstat, only write the cache_config_default_s
+	value if st_size == 0, otherwise read value from file.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (conninfo): Always provide servname to getnameinfo.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Add
+	curl_easy_setopt_ck macro, use it for all curl_easy_setopt calls.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_write_callback): Check result
+	of curl_easy_getinfo.
+
+2022-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (main): Define use_epoll. Set to MHD_USE_EPOLL
+	based on MHD_VERSION. Don't use MHD_USE_THREAD_PER_CONNECTION
+	when use_poll is set.
+
+2022-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (main): Define mhd_flags. Use mhd_flags for
+	MHD_start_daemon. Try again with MHD_USE_DUAL_STACK removed if
+	that fails. Update clog to say either IPV4 or IPV4 and IPV6.
+	stop either ithe d46 or d4 daemonr.
+
+2022-05-09  Noah Sanci  <nsanci@redhat.com>
+
+	* debuginfod.cxx (main): Set nonzero defaults for fdcache.
+
+2022-05-04  Frank Ch. Eigler <fche@redhat.com>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Correct fd leak
+	for cache negative-hit unlink case.
+	(debuginfod_config_cache, debuginfod_init_cache): Correct
+	minor fd leaks.
+	* debuginfod-find.c  (main): Ditto.
+
+2022-04-22  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdebuginfod): Add -lpthread.
+	(libdebuginfod_so_LDLIBS): Likewise.
+	* debuginfod-client.c (init_control): New static pthread_once_t.
+	(libcurl_init): New static function.
+	(debuginfod_begin): Use ptrace_once to call libcurl_init.
+	(libdebuginfod_ctor): Removed.
+	(libdebuginfod_dtor): Likewise.
+
+2022-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (main): Add MHD_USE_ITC to MHD_start_daemon flags.
+
+2022-04-13  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server):
+	Drop st_mode check. Add st_size > 0 check.
+	Save target_mtime before calling
+	debuginfod_config_cache. unlink target_cache_path
+	on EACCESS. Create target_cache_path with DEFFILEMODE.
+
+2022-04-03  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (main): Use single dual-stack daemon setup,
+	rather than duplicate ipv4 and ipv6.
+	(conninfo, handle_buildid): Represent ipv4-mapped ipv6 addresses
+	in their native ipv4 form for logging and X-F-F: purposes.
+	* debuginfod-client.c (debuginfod_add_http_header): Tolerate
+	colons in http header values.
+
+2022-04-03  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (main): Use MHD_USE_EPOLL for libmicrohttpd, to
+	encourage more round-robin dispatch of incoming connections.
+
+2021-12-09  Alexander Kanavin <alex@linutronix.de>
+
+	* debuginfod-client.c (cache_clean_default_interval_s): Change type to
+	long from time_t.
+	(cache_miss_default_s): Likewise.
+	(cache_default_max_unused_age_s): Likewise.
+
+2021-12-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (database_stats_report): Don't format clog
+	using 'right' and 'setw(20)'.
+
+2021-12-08  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (connection_pool): New global.
+	(parse_opt): Parse & check -C option to set it.
+	(error_cb): New callback for libmicrohttpd error counting.
+	(main): Activate MHD_OPTION_THREAD_POOL_SIZE if appropriate.
+	Activate error_cb.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (main): Call debuginfod_pool_groom before exit.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (add_mhd_response_header): New function.
+	(reportable_exception::mhd_send_response): Call
+	MHD_add_response_header.
+	(add_mhd_last_modified): Likewise.
+	(handle_buildid_f_match): Likewise.
+	(handle_buildid_r_match): Likewise.
+	(handle_metrics): Likewise. And check MHD_Response was actually
+	created.
+	(handle_root): Likewise.
+
+2021-12-08  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (intern): Call set_metrics() holding the fdcache mutex.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Free winning_headers.
+	Reset response_data_size when clearing response_data.
+
+2021-12-01  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Free tmp_url on
+	realloc error. curl_free escaped_string on error. Fix error out
+	goto on curl_easy_init failure. Only cleanup data[i] handle and
+	response_data if it was initialized.
+
+2021-12-01  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (timestamp): Use gmtime_r instead of gmtime.
+	(add_mhd_last_modified): Likewise.
+
+2021-11-10  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* debuginfod.cxx: include "system.h" under 'extern "C"' block.
+
+2021-11-05  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28430
+	* debuginfod.cxx (parse_opt): Add "--passive" flag.  Complain
+	about inconsistent flags.
+	(main): In passive mode, suppress scan/groom/traverse threads and
+	other read-write database ops.
+
+2021-11-04  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28514
+	* debuginfod.cxx (groom): Rework into separate decision/action
+	phases.  Add new metrics to monitor progress.  Limit indefinite
+	operation times to avoid starving rescan.
+
+2021-10-23  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28240
+	* debuginfod-client.c (debuginfod_query_server): Correct
+	negative-hit cache check sequence for root user.
+
+2021-10-15  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Set
+	CURLOPT_PROTOCOLS.
+
+2021-10-06  Di Chen <dichen@redhat.com>
+
+	PR28242
+	* debuginfod.cxx (inc_metrics, add_metrics): Add two-tag variants.
+	(handler_cb): Call it with artifacttype for http_responses_* metrics.
+	(handle_buildid): Sanitize artifacttype if necessary.
+	(dwarf_extract_source_path): Pass sanitizable string param.
+
+2021-09-17  Noah Sanci  <nsanci@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): curl_multi_perform
+	now occurs before checking if response headers have arrived.
+
+2021-09-14  Frank Ch. Eigler <fche@redhat.com>
+
+	PRPR28339
+	* debuginfod.cxx (waitq::fronters): New field.
+	(waitq::wait_idle): Respect it.
+	(waitq::done_front): New function.
+	(thread_main_scanner): Call it to match wait_front().
+
+2021-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (libarchive_fdcache::lookup): Add endl after
+	obatched(clog) line.
+2021-09-13  Noah Sanci  <nsanci@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Removed constant
+	operations from a loop. curl_free memory.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* debuginfod-client.c (debuginfod_begin): Remove cast of calloc return
+	value.
+
+2021-08-28  Mark Wielaard  <mjw@redhat.com>
+
+	* debuginfod.cxx (parse_opt): Turn the -d arg ":memory:" into
+	"file::memory:?cache=shared" for the db_path.
+
+2021-08-20  Di Chen  <dichen@redhat.com>
+
+	* debuginfod.cxx (options): Add ARGP_KEY_FORWARDED_TTL_LIMIT.
+	(forwarded_ttl_limit): New static unsigned.
+	(parse_opt): Handle ARGP_KEY_FORWARDED_TTL_LIMIT.
+	(handle_buildid): Check forwarded_ttl_limit.
+	(main): Log forwarded ttl limit.
+
+2021-08-20  Saleem Abdulrasool  <abdulras@google.com>
+
+	* debuginfod.cxx: Remove error.h include.
+
+2021-08-19  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28249
+	* debuginfod.cxx (handler_cb): Fix after_you unique_set key
+	to the entire incoming URL.
+
+2021-08-02  Noah Sanci  <nsanci@redhat.com>
+
+	PR27277
+	* debuginfod-client.c (struct debuginfod_client): New field
+	winning_headers.
+	(struct handle_data): New field response_data, response_data_size.
+	(header_callback): Store received headers in response_data.
+	(debuginfod_query_server): Activate CURLOPT_HEADERFUNCTION.
+	Save winning response_data.
+	(debuginfod_end): free client winning headers.
+	* debuginfod.cxx (handle_buildid_f_match): remove X-DEBUGINFOD-FILE
+	path. Add X-DEBUGINFOD-FILE and X-DEBUGINFOD-SIZE headers.
+	(handle_buildid_r_match): remove X-DEBUGINFOD-FILE path. Add
+	X-DEBUGINFOD-FILE, X-DEBUGINFOD-SIZE
+	headers, and X-ARCHIVE headers.
+
+2021-07-26  Noah Sanci  <nsanci@redhat.com>
+
+	PR27982
+	* debuginfod-client.c (globals): added default_maxsize and
+	default_maxtime.
+	(debuginfod_query_server): Added DEBUGINFOD_MAXSIZE and
+	DEBUGINFOD_MAXTIME envvar processing.
+	* debuginfod.cxx (handler_cb): If the requested file exceeds
+	maxsize return code 406.
+	* debuginfod.h.in: Added DEBUGINFOD_MAXSIZE_ENV_VAR and
+	DEBUGINFOD_MAXTIME_ENV_VAR.
+
+2021-07-16  Noah Sanci  <nsanci@redhat.com>
+
+	PR28034
+	* debuginfod-client.c (debuginfod_query_server): % escape filename
+	so the completed url is processed properly.
+
+2021-06-28 Noah Sanci <nsanci@redhat.com>
+
+	PR25978
+	* debuginfod.cxx (options): Added --fdcache-prefetch-fds/mbs options.
+	(set_metric): Added a condition for fdcache_mintmp to ensure no
+	negative percentages or percentages larger than 100% are given.
+	(globals): Added fdcache_prefetch_mbs/fdcache_prefetch_fds.
+	(set_metrics): Differentiate between lru and prefetch metrics.
+	(intern): Added prefetch functionality for nuking preexisting copies
+	and incrementing prefetch metrics.
+	(lookup): Search prefetch cache and increment associated metrics. Upon
+	finding in the prefetch cache move the element to the lru cache.
+	(limit): Arguments updated. Update size of prefetch cache.
+	(main): Log prefetch and cache fds/mbs
+
+2021-07-06  Alice Zhang  <alizhang@redhat.com>
+
+	PR27531
+	* debuginfod-client.c (debuginfod_query_server): Retry failed queries
+	if error code is not ENOENT.
+	* debuginfod.h.in: Introduce DEBUGINFOD_RETRY_LIMIT_ENV_VAR.
+
+2021-07-01  Noah Sanci <nsanci@redhat.com>
+
+	PR27711
+	* debuginfod.cxx (options): Add --regex-groom, -r option.
+	(regex_groom): New static bool defaults to false.
+	(parse_opt): Handle 'r' option by setting regex_groom to true.
+	(groom): Introduce and use reg_include and reg_exclude.
+
+2021-07-09  Noah Sanci  <nsanci@redhat.com>
+
+	PR27983
+	* debuginfod-client.c (debuginfod_query_server): As full-length
+	urls are generated with standardized formats, ignore duplicates.
+	Created out1 and changed out2 error gotos. Updated url creation print
+	statements.
+	(globals): Removed url_delim_char, as it was no longer used.
+
+2021-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_begin): Don't use client if
+	calloc call failed.
+
+2021-06-03  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27863
+	* debuginfod.cxx (unique_set, unique_set_reserver): New classes.
+	(handler_cb): Use them to implement "after-you" queueing.
+
+2021-05-14  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27859
+	* debuginfod-client.c (debuginfod_client): Retain only
+	long-lived multi handle from PR27701 work.
+	(debuginfo_begin,debuginfod_end): ctor/dtor for surviving field only.
+	(debuginfod_query_server): Rework to reuse multi handle only.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* debuginfod-client.c (debuginfod_query_server): Use startswith.
+	(debuginfod_add_http_header): Likewise.
+	* debuginfod.cxx: Likewise.
+
+2021-05-04  Alice Zhang <alizhang@redhat.com>
+
+	* debuginfod-client.c (cache_miss_default_s): New static time_t,
+	defaults to 600 (10 minutes).
+	(cache_miss_filename): New static char pointer.
+	(debuginfod_config_cache): New static function.
+	(debuginfod_clean_cache): Use debuginfod_config_cache for
+	interval_path and max_unused_path.
+	(debuginfod_query_server): Check whether target_cache_path exists
+	as negative cache file and create target_cache_path when the server
+	returns ENOENT. Check cache_miss_path fir cache miss time.
+
+2021-04-26  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27571
+	* debuginfod-client.c (debuginfod_query_server): Chmod 0400 files
+	delivered into the cache to prevent accidental modification.
+
+2021-04-26  Frank Ch. Eigler <fche@redhat.com>
+
+	PR26125
+	* debuginfod-client.c (debuginfod_clean_cache): For directory
+	rmdir, check mtime first.
+	(debuginfod_query_server): Try mkdir / mkstemp up to twice,
+	in case of race.
+
+2021-04-23  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27701
+	* debuginfod-client.c (struct debuginfod_client): Add long-lived
+	CURL easy and multi handles.
+	(debuginfo_begin,debuginfod_end): ctor/dtor for these.
+	(debuginfod_query_server): Rework to reuse easy & multi handles.
+	(*_envvar): Just use the DEBUGINFOD_*_ENV_VAR directly instead.
+
+	* debuginfod.cxx (dc_pool): New pile of reusable debuginfod_client
+	objects for upstream federation connections.
+	(debuginfod_pool_{begin,end,groom}): New functions.
+	(handle_buildid): Use them.
+	(handler_cb): Fix keep-alive given libmicrohttpd convention of multiple
+	callbacks.
+
+2021-04-15  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (groom): Only update database stats once.
+
+2021-04-15  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (elf_classify): Recognize symtab-only stripped files
+	like fedora's libicudata as debuginfo files.
+
+2021-03-30  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (main): Set child thread names.
+
+2021-03-07  Timm Bäder <tbaeder@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Tweak
+	double/long clamping arithmetic to avoid UB and warnings.
+
+2021-02-25  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (handler_cb): Filter webapi for bad
+	artifacttype keywords early for metric hygiene.
+
+2021-02-14  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (main -U): Use bsdtar unconditionally.  Also map
+	the debian-compatible .ipk (openembedded distro family) to same.
+
+2021-02-04  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27092 low-memory handling
+	* debuginfod.cxx (fdcache_mintmp): New parameter, with cmd-line option.
+	(parse_opt): Parse it.
+	(main): Default it.
+	(statfs_free_enough_p): New function.
+	(libarchive_fdcache::*): Call it to trigger emergency fdcache flush.
+	(thread_main_scanner): Call it to report filesystem fullness metrics.
+	(groom): Ditto.
+	(set/add_metric): Take double rather than int64_t values.
+	(archive_exception): Propagate suberror to metric label.
+	(main): Detect pthread creation fatal errors properly.
+
+2021-02-02  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27323
+	* debuginfod.cxx (dbq): New read-only database connection for queries
+	only.
+	(signal_handler): Interrupt it.
+	(main): Open / close it.
+	(handle_buildid): Use it for webapi queries only.
+	(database_stats_report): Make more interruptible.  Report sqlite3
+	operation times to the prometheus metrics.
+	(groom): Make more interruptible.
+	(thread_main_fts_source_paths, thread_main_groom): Ensure
+	state/progress metrics are fresh even in case of exceptions.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Fix spelling typos in
+	comments.
+	* debuginfod.cxx: Likewise.
+	(parse_opt): Fix spelling typos in error diagnostics.
+
+2020-12-08  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am [LIBDEBUGINFOD]: Create libdebuginfod.so.1 first, turn
+	libdebuginfod.so into symlink.
+
+2020-11-30  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (libdebuginfod.so): Replace $@.$(VERSION) with
+	$(LIBDEBUGINFOD_SONAME).
+	(install, uninstall, MOSTLYCLEANFILES): Replace
+	libdebuginfod.so.$(VERSION) with $(LIBDEBUGINFOD_SONAME).
+	(VERSION): Remove.
+	* debuginfod.h: Rename to ...
+	* debuginfod.h.in ... this.
+	(DEBUGINFOD_SONAME): New macro.
+
+2020-11-30  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (libdebuginfod.so$(EXEEXT)): Drop $(EXEEXT) suffix.
+
+2020-11-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (step_ok_done): Correct typo in prom metric label.
+
+2020-11-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (tmp_ms_metric): Switch from gettimeofday to
+	clock_gettime(CLOCK_MONOTONIC) for time-interval measurements.
+	(handler_cb, scan_source_paths, groom): Ditto.
+
+2020-11-23  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (tmp_ms_metric): New class for RAII timing metrics.
+	(sqlite_ps::reset, step*): Call it to track sqlite3 performance.
+	(sqlite_exception ctor): Increment sqlite3 error_count.
+
+2020-11-23  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Initialize
+	struct handle_data errbuf to the empty string.
+
+2020-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_set_verbose_fd): New function.
+	(struct debuginfod_client): Add verbose_fd.
+	(struct handle_data): Add errbuf.
+	(debuginfod_query_server): Produce verbose output when
+	debuginfod_client verbose_fd is set. Only clear old data and set
+	default_headers when any work is done. Always goto out when setting
+	rc to an error value. Use CURLOPT_ERRORBUFFER to get more error
+	output when verbose output is requested.
+	* debuginfod.h (DEBUGINFOD_VERBOSE_ENV_VAR): New.
+	(debuginfod_set_verbose_fd): Added.
+	* debuginfod-find.c (parse_opt): Set debuginfod_set_verbose_fd on -v.
+	* bdebuginfod.map (ELFUTILS_0.183): New section, add
+	debuginfod_set_verbose_fd.
+
+2020-11-21  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (handle_root): New function.
+	(handler_cb): Handle "/" and report url1 in webapi error.
+
+2020-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-find.c (progressfn): Use clock_gettime to print Progress
+	at most 5 times a second.
+
+2020-11-19  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (tmp_inc_metric): New class.
+	(handler_cb): Use it to track webapi operations.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* debuginfod-client.c (debuginfod_init_cache): Use ACCESSPERMS for
+	mkdir, DEFFILEMODE for open with O_CREAT.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* debuginfod.cxx: include libintl.h.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* Makefile.am (debuginfod_LDADD): Add argp_LDADD and fts_LIBS.
+	(debuginfod_find_LDADD): Likewise.
+	(libdebuginfod_so_LDLIBS): Add fts_LIBS.
+
+2020-10-31  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (scan_source_file, scan_archive_file): Add new scanned_bytes_total,
+	scanned_files_total metrics.
+	(archive_classify): Exit early if interrupted.
+	(scan_source_paths): Perform realpath/regex checks only on FTS_F files.
+	Tweak metrics.
+
+2020-10-30  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26775 cont'd.
+	* debuginfod.cxx (thread_main_scanner): Ensure control doesn't
+	leave infinite loop until program exit, even if SIGUSR2.
+	(scan_source_paths): Have traverser clean scanq on
+	SIGUSR2.  Emit additional traversed_total metrics.
+	(groom): Emit additional groomed_total metrics.
+	(thread_main_groom): Restore previous thread_work_total
+	metric.
+
+2020-10-29  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26775
+	* debuginfod.cxx (forced_*_count): Make these global.
+	(runq::clear): New function.
+	(thread_main_scanner): Check for pending SIGUSR2; interrupt.
+	(scan_source_paths): Check for pending SIGUSR2; interrupt.
+	(groom): Report prometheus stats before groom also.  Check for
+	pending SIGUSR1; interrupt.  Increment thread_work_total for
+	each file scanned, not the entire cycle.
+
+2020-10-29  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26810
+	* debuginfod.cxx (handle_buildid_*_match): Throw exceptions for
+	more lower level libc errors.
+	(handle_buildid_match): Catch & report exceptions but return 0
+	for continued iteration in the caller.
+
+2020-10-25  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Translate
+	CURLE_PEER_FAILED_VERIFICATION to ECONNREFUSED.
+
+2020-10-20  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26756: more prometheus metrics
+	* debuginfod.cxx (*_exception): Add counters for error occurrences.
+	(fdcache::*): Add counters for fdcache operations and status.
+	(fdcache::set_metric): New fn for overall stat counts.
+	(fdcache::limit): ... allow metric-less use from dtors.
+
+2020-10-20  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (handle_buildid*): Add a parameter for detecting
+	internally-originated lookups for dwz resolution.
+
+2020-09-18  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (scan_source_file, archive_classify): Store only
+	canonicalized file names in sdef & sref records in the database.
+
+2020-09-08  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (BUILD_STATIC): Include libcurl_LIBS in libdebuginfod
+	when NOT DUMMY_LIBDEBUGINFOD.
+
+2020-09-16  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-find.c: Fix license block comment.
+
+2020-09-15  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-find.c (main): Use dwelf_elf_begin.
+
+2020-07-03  Alice Zhang <alizhang@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Use strncasecmp
+	to compare effective_url. Try CURLINFO_SCHEME as fallback.
+
+2020-06-19  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (bin_PROGRAMS): Guard with DEBUGINFOD and
+	LIBDEBUGINFOD.
+	(debuginfod_LDADD): Remove libcurl.
+	(libdebuginfod): When static and DUMMY_LIBDEBUGINFO remove libcurl.
+	(noinst_LIBRARIES): Guard with LIBDEBUGINFOD.
+	(AM_CPPFLAGS): Add -Wno-unused-parameter when DUMMY_LIBDEBUGINFOD.
+	(pkginclude_headers): Guard with LIBDEBUGINFOD
+	(libdebuginfod_so_LIBS): Likewise.
+	(+libdebuginfod_so_LDLIBS): Likewise.
+	(install): Likewise.
+	(uninstall): Likewise.
+	* debuginfod-client.c: Include dummy functions when
+	DUMMY_LIBDEBUGINFOD.
+	* debuginfod.cxx: Remove curl.h include.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Check malloc.
+	Move curl_multi_init call before handle_data malloc call.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Replace sizeof
+	build_id_bytes check with strlen build_id check.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Increase suffix
+	array and prepare having to escape 1 character with 2.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_clean_cache): Handle failing
+	fopen (interval_path).
+
+2020-03-29  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_add_http_header): Check header
+	contains precisely one colon that isn't the first or last char.
+
+2020-03-29  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (struct debuginfod_client): Add a flag field
+	for progressfn printing.
+	(default_progressfn): Set it if printing \rsomething.
+	(debuginfod_end): Terminate with \n if flag set, i.e., only if the
+	default_progressfn was actually called.
+
+2020-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (parse_opt): Check port is not zero.
+
+2020-03-28  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (handle_buildid_r_match): During archive
+	extraction / fdcache prefetching, set the mtime of each
+	file in the cache.
+
+2020-03-27  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.c (main): Extract buildid from /binary/ if
+	given instead of hex string.
+	* Makefile.am: Add elfutils library prereqs for debuginfod-find.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.h, libdebuginfod.map: New functions for _add_url_header.
+	* debuginfod-client.c (struct debuginfod_client): Add headers fields.
+	(debuginfod_add_http_header): New client api to add outgoing headers.
+	(add_default_headers): Renamed from add_extra_headers, skip if flag.
+	(debuginfod_query_server): Pass accumulated headers to libcurl.
+	(debuginfod_end): Clean accumulated headers.
+	(debuginfod_find_*): Add default headers at this point.
+	* debuginfod.cxx (handle_buildid): Add conn pointer.  Use it to relay
+	incoming UA and XFF headers to federated upstream debuginfods.
+
+2020-03-26  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (handler_cb): Export two families of metrics for
+	prometheus traffic analysis: response times and data amounts.
+
+2020-03-26  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (parse_opt): For -U, prefer dpkg-deb
+	after all if access(3)-able, fallback to bsdtar.
+
+2020-03-25  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.cxx (parse_opt): Associate a bsdtar subshell with
+	the .deb & .ddeb extensions, instead of dpkg-deb.
+
+2020-03-26  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Don't
+	set CURLOPT_PATH_AS_IS on old curl.  Mostly harmless.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Set
+	CURLOPT_PATH_AS_IS, to propagate file names verbatim.
+	* debuginfod.cxx (canon_pathname): Implement RFC3986
+	style pathname canonicalization.
+	(handle_buildid): Canonicalize incoming webapi source
+	paths, accept either one.
+	(scan_source_file, archive_classify): Store both
+	original and canonicalized dwarf-source file names.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (handle_buildid): In case of federated fallback
+	queries, handle errors analogously to local ENOENT/404.
+	(handle_metrics): Return a size-of-response value.
+	(handler_cb): Add code to time entire application-side processing
+	stage + response sizes + http codes, so as to emit a complete
+	httpd-flavoured log line for each webapi request.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Print the
+	default_progressfn terminating \n message only if that progressfn
+	is actually set.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.c (main): Correct /source full-pathness check for
+	"debuginfod-find -v source deadbeef /pathname" case.
+
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (struct debuginfod_client): Add url field.
+	(struct handle_data): Add client field as backpointer.
+	(debuginfod_write_callback): Compute & save URL.
+	(default_progressfn): Print front pieces of the URL.
+	(debuginfod_query_server): Clear URL and cleanup after progressfn.
+	* debuginfod-find.c (main): Print URL at transfer conclusion.
+
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.h, libdebuginfod.map: New functions for _get/set_user().
+	* debuginfod-client.c: Implement them.
+	* debuginfod-find.c: Include a token call just for testing them.
+
+2020-03-03  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Update
+	cache_path even when new default path already exists.
+
+2020-02-27  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (xalloc_str): New macro. Call
+	asprintf with error checking.
+	(debuginfod_query_server): Use XDG_CACHE_HOME as a default
+	cache location if it is set. Replace snprintf with xalloc_str.
+
+2020-02-26  Konrad Kleine <kkleine@redhat.com>
+
+	* debuginfod-client.c (debuginfod_query_server): Handle curl's
+	response code correctly when DEBUGINFOD_URLS begin with file://
+
+2020-02-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (parse_opt): Treat -R as if -Z.rpm .
+
+2020-02-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (fdcache_prefetch): New parameter.
+	(parse_opt): Parse it.
+	(main): Default it.
+	(fdcache::fd_size_mb): Change to double for accuracy.
+	(fdcache::probe): New function.
+	(fdcache::intern): New option to intern at end of LRU.
+	(fdcache::lookup): Clean fdcache.
+	(handle_buildid_r_match): Implement multi-stage archive
+	parsing, with optional prefetching of extracted contents
+	into the fdcache.
+
+2020-02-19  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c (debuginfod_clean_cache): Restrict
+	cleanup to client-pattern files.
+
+2020-02-05  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (argp options): Add -Z option.
+	(canonicalized_archive_entry_pathname): New function for
+	distro-agnostic file name matching/storage.
+
+2020-01-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (dwarf_extract_source_paths): Don't print
+	"skipping hat" messages at verbosity <=3, too noisy.
+
+2020-01-19  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (scanq): Rework to let groomer/fts threads
+	synchronize with an empty workqueue, and lock out workqueue
+	consumers.
+	(thread_groom): Adopt new scanq idle APIs to lock out scanners.
+	(thread_main_fts_source_paths): Adopt new scanq idler API to
+	avoid being restarted while scanners haven't even finished yet.
+	(thread_main_*): Increment thread_work_total metric only after
+	a work cycle is completed, not when it begins.
+
+2020-01-18  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (thread_main_scanner): Handle empty source_paths[].
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (libarchive_fdcache): New class/facility to own a
+	cache of temporary files that were previously extracted from an
+	archive.  If only it could store just unlinked fd's instead of
+	filenames.
+	(handle_buildid_r_match): Use it to answer dwz/altdebug and webapi
+	requests.
+	(groom): Clean it.
+	(main): Initialize the cache control parameters from heuristics.
+	Use a consistent tmpdir for these and tmp files elsewhere.
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (conninfo): Print User-Agent and X-Forwarded-For
+	request headers, after mild safety-censorship (for easier machine
+	processing).
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx: Rework threading model.
+	(workq): New class for concurrent work-queue.
+	(semaphore): Removed class, now unused.
+	(scan_source_file_path): Rework into ...
+	(scan_source_file): New function.
+	(thread_main_scan_source_file_path): Nuke.
+	(scan_source_archive_path): Rework into ...
+	(scan_archive_file): New function.
+	(thread_main_scanner): New function for scanner threads.
+	(thread_main_fts_source_paths): New function for traversal thread.
+	(scan_source_paths): ... doing this.
+	(thread_groom): Tweak metrics for consistency.
+	(main): Start 1 traversal and N scanner threads if needed.
+
+2019-01-02  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (default_connect_timeout): Removed.
+	(default_transfer_timeout): Removed.
+	(default_timeout): New. Default to 90 seconds.
+	(debuginfod_query_server): Parse server_timeout_envvar as one number.
+	Set as CURLOPT_LOW_SPEED_TIME, with CURL_OPT_LOW_SPEED_LIMITE as 100K.
+
+2020-01-09  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (add_extra_headers): New function,
+	based on mjw's draft.
+	(debuginfod_query_server): Call it.
+
+2019-12-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (*_rpm_*): Rename to *_archive_* throughout.
+	(scan_archives): New read-mostly global to identify archive
+	file extensions and corresponding extractor commands.
+	(parse_opt): Handle new -U flag.
+
+2019-12-19  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client.c (default_progressfn): New function.
+	(debuginfod_begin): Use it if $DEBUGINFOD_PROGRESS set.
+	(server_timeout): Bump to 30 seconds.
+	(debuginfod_query_server): Call progressfn -after- rather than
+	before curl ops, to make it likely that a successful transfer
+	results in final a=b call.  Tweak cleanup sequence.
+	* debuginfod.h: Document $DEBUGINFOD_PROGRESS name.
+
+2019-12-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Check
+	server_urls_envvar early.
+
+2019-12-03  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (debuginfod_query_server): Use separate
+	local variables for CURLcode curl_res and CURLMcode curlm_res.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (BUILD_STATIC): Add needed libraries for libdw and
+	libdebuginfod.
+
+2019-11-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx (groom): Add a sqlite3_db_release_memory()
+	at the end of periodic grooming to try to shrink the process.
+
+2019-11-24  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (test_webapi_sleep): Removed.
+	(handler_cb): Don't check test_webapi_sleep and sleep.
+	(main): Don't set test_webapi_sleep.
+
+2019-11-24  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.cxx (add_metric): New function.
+	(scan_source_file_path): Record metrics for
+	found_executable_total, found_debuginfo_total and
+	found_sourcerefs_total.
+	(scan_source_rpm_path): Likewise.
+
+2019-11-07  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx: Add /metrics endpoint.  Add numerous
+	calls to new functions inc_metric/set_metric to populate
+	threadsafe map containing stats.  Add http content-type
+	response headers throughout.
+	(thread_main_*): Simplify counter/timer flow.
+	(main): Reorder web service shutdown to leave http running
+	as long as possible.
+	* debuginfod.8: Document it, add security caution.
+
+2019-11-06  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx: Add new -L (symlink-following) mode.
+	* debuginfod.8: Document it.
+
+2019-11-04  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfo-client.c (debuginfod_set_progressfn): New function
+	for progress/interrupt callback.
+	(debuginfod_clean_cache, debuginfod_query_server): Call it.
+	* debuginfo.h: Declare it.
+	* debuginfod_set_progressfn.3, *_find_debuginfo.3: Document it.
+	* Makefile.am: Install it.
+	* libdebuginfod.map: Export it all under ELFUTILS_0.178 symversion.
+
+	* debuginfod-find.c: Add -v option to activate progress cb.
+	* debuginfod-find.1: Document it.
+	* debuginfod.cxx: Add $DEBUGINFOD_TEST_WEBAPI_SLEEP env var
+	to insert sleep in webapi callbacks, to help manual testing.
+
+2019-10-28  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.cxx: New file: debuginfod server.
+	* debuginfod.8: New file: man page.
+	* Makefile.am: Build it.
+
+2019-10-28  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod-client.c: New file: debuginfod client library.
+	* debuginfod.h: New file: header for same.
+	* libdebuginfod.map: New file: govern its solib exports.
+	* debuginfod-find.c: New file: command line frontend.
+	* debuginfod-find.1, debuginfod_find_source.3,
+	debuginfod_find_executable.3, debuginfod_find_debuginfo.3:
+	New man pages.
diff --git a/debuginfod/Makefile.am b/debuginfod/Makefile.am
new file mode 100644
index 0000000..125be97
--- /dev/null
+++ b/debuginfod/Makefile.am
@@ -0,0 +1,147 @@
+## Makefile.am for libdebuginfod library subdirectory in elfutils.
+##
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2019 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+	   -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \
+	   $(libmicrohttpd_CFLAGS) $(libcurl_CFLAGS) $(sqlite3_CFLAGS) \
+	   $(libarchive_CFLAGS)
+
+# Disable eu- prefixing for artifacts (binaries & man pages) in this
+# directory, since they do not conflict with binutils tools.
+program_prefix=
+program_transform_name = s,x,x,
+
+if BUILD_STATIC
+libasm = ../libasm/libasm.a
+libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl) -ldl -lpthread
+libelf = ../libelf/libelf.a -lz
+if DUMMY_LIBDEBUGINFOD
+libdebuginfod = ./libdebuginfod.a
+else
+libdebuginfod = ./libdebuginfod.a -lpthread $(libcurl_LIBS)
+endif
+else
+libasm = ../libasm/libasm.so
+libdw = ../libdw/libdw.so
+libelf = ../libelf/libelf.so
+libdebuginfod = ./libdebuginfod.so
+endif
+libebl = ../libebl/libebl.a
+libeu = ../lib/libeu.a
+
+AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw:.
+
+bin_PROGRAMS =
+if DEBUGINFOD
+bin_PROGRAMS += debuginfod
+endif
+
+if LIBDEBUGINFOD
+bin_PROGRAMS += debuginfod-find
+endif
+
+debuginfod_SOURCES = debuginfod.cxx
+debuginfod_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(argp_LDADD) $(fts_LIBS) $(libmicrohttpd_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -lpthread -ldl
+
+debuginfod_find_SOURCES = debuginfod-find.c
+debuginfod_find_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(argp_LDADD) $(fts_LIBS)
+
+if LIBDEBUGINFOD
+noinst_LIBRARIES = libdebuginfod.a
+noinst_LIBRARIES += libdebuginfod_pic.a
+endif
+
+libdebuginfod_a_SOURCES = debuginfod-client.c
+libdebuginfod_pic_a_SOURCES = debuginfod-client.c
+am_libdebuginfod_pic_a_OBJECTS = $(libdebuginfod_a_SOURCES:.c=.os)
+
+if DUMMY_LIBDEBUGINFOD
+AM_CPPFLAGS += -Wno-unused-parameter
+endif
+
+if LIBDEBUGINFOD
+pkginclude_HEADERS = debuginfod.h
+endif
+
+if LIBDEBUGINFOD
+libdebuginfod_so_LIBS = libdebuginfod_pic.a
+if DUMMY_LIBDEBUGINFOD
+libdebuginfod_so_LDLIBS =
+else
+libdebuginfod_so_LDLIBS = -lpthread $(libcurl_LIBS) $(fts_LIBS) $(libelf)
+endif
+$(LIBDEBUGINFOD_SONAME): $(srcdir)/libdebuginfod.map $(libdebuginfod_so_LIBS)
+	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
+		-Wl,--soname,$(LIBDEBUGINFOD_SONAME) \
+		-Wl,--version-script,$< \
+		$(NO_UNDEFINED) \
+		-Wl,--whole-archive $(libdebuginfod_so_LIBS) -Wl,--no-whole-archive \
+		$(libdebuginfod_so_LDLIBS)
+	@$(textrel_check)
+
+libdebuginfod.so: $(LIBDEBUGINFOD_SONAME)
+	ln -fs $< $@
+
+install: install-am libdebuginfod.so
+	$(mkinstalldirs) $(DESTDIR)$(libdir)
+	$(INSTALL_PROGRAM) $(LIBDEBUGINFOD_SONAME) \
+		$(DESTDIR)$(libdir)/libdebuginfod-$(PACKAGE_VERSION).so
+	ln -fs libdebuginfod-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/$(LIBDEBUGINFOD_SONAME)
+	ln -fs libdebuginfod-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdebuginfod.so
+
+uninstall: uninstall-am
+	rm -f $(DESTDIR)$(libdir)/libdebuginfod-$(PACKAGE_VERSION).so
+	rm -f $(DESTDIR)$(libdir)/$(LIBDEBUGINFOD_SONAME)
+	rm -f $(DESTDIR)$(libdir)/libdebuginfod.so
+	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
+endif
+
+EXTRA_DIST = libdebuginfod.map
+MOSTLYCLEANFILES = $(am_libdebuginfod_pic_a_OBJECTS) $(LIBDEBUGINFOD_SONAME)
+CLEANFILES += $(am_libdebuginfod_pic_a_OBJECTS) libdebuginfod.so
+
+# automake std-options override: arrange to pass LD_LIBRARY_PATH
+installcheck-binPROGRAMS: $(bin_PROGRAMS)
+	bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
+	  case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
+	   *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
+	  esac; \
+	  f=`echo "$$p" | \
+	     sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  for opt in --help --version; do \
+	    if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \
+	       $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \
+		 && test -n "`cat c$${pid}_.out`" \
+		 && test -z "`cat c$${pid}_.err`"; then :; \
+	    else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
+	  done; \
+	done; rm -f c$${pid}_.???; exit $$bad
diff --git a/debuginfod/debuginfod-client.c b/debuginfod/debuginfod-client.c
new file mode 100644
index 0000000..0ee7db3
--- /dev/null
+++ b/debuginfod/debuginfod-client.c
@@ -0,0 +1,2068 @@
+/* Retrieve ELF / DWARF / source files from the debuginfod.
+   Copyright (C) 2019-2021 Red Hat, Inc.
+   Copyright (C) 2021, 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+/* cargo-cult from libdwfl linux-kernel-modules.c */
+/* In case we have a bad fts we include this before config.h because it
+   can't handle _FILE_OFFSET_BITS.
+   Everything we need here is fine if its declarations just come first.
+   Also, include sys/types.h before fts. On some systems fts.h is not self
+   contained. */
+#ifdef BAD_FTS
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+#include "config.h"
+#include "debuginfod.h"
+#include "system.h"
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <gelf.h>
+
+/* We might be building a bootstrap dummy library, which is really simple. */
+#ifdef DUMMY_LIBDEBUGINFOD
+
+debuginfod_client *debuginfod_begin (void) { errno = ENOSYS; return NULL; }
+int debuginfod_find_debuginfo (debuginfod_client *c, const unsigned char *b,
+                               int s, char **p) { return -ENOSYS; }
+int debuginfod_find_executable (debuginfod_client *c, const unsigned char *b,
+                                int s, char **p) { return -ENOSYS; }
+int debuginfod_find_source (debuginfod_client *c, const unsigned char *b,
+                            int s, const char *f, char **p)  { return -ENOSYS; }
+int debuginfod_find_section (debuginfod_client *c, const unsigned char *b,
+			     int s, const char *scn, char **p)
+			      { return -ENOSYS; }
+void debuginfod_set_progressfn(debuginfod_client *c,
+			       debuginfod_progressfn_t fn) { }
+void debuginfod_set_verbose_fd(debuginfod_client *c, int fd) { }
+void debuginfod_set_user_data (debuginfod_client *c, void *d) { }
+void* debuginfod_get_user_data (debuginfod_client *c) { return NULL; }
+const char* debuginfod_get_url (debuginfod_client *c) { return NULL; }
+int debuginfod_add_http_header (debuginfod_client *c,
+				const char *h) { return -ENOSYS; }
+const char* debuginfod_get_headers (debuginfod_client *c) { return NULL; }
+
+void debuginfod_end (debuginfod_client *c) { }
+
+#else /* DUMMY_LIBDEBUGINFOD */
+
+#include <assert.h>
+#include <dirent.h>
+#include <stdio.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <regex.h>
+#include <string.h>
+#include <stdbool.h>
+#include <linux/limits.h>
+#include <time.h>
+#include <utime.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <curl/curl.h>
+
+/* If fts.h is included before config.h, its indirect inclusions may not
+   give us the right LFS aliases of these functions, so map them manually.  */
+#ifdef BAD_FTS
+  #ifdef _FILE_OFFSET_BITS
+    #define open open64
+    #define fopen fopen64
+  #endif
+#else
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+/* Older curl.h don't define CURL_AT_LEAST_VERSION.  */
+#ifndef CURL_AT_LEAST_VERSION
+  #define CURL_VERSION_BITS(x,y,z) ((x)<<16|(y)<<8|(z))
+  #define CURL_AT_LEAST_VERSION(x,y,z) \
+    (LIBCURL_VERSION_NUM >= CURL_VERSION_BITS(x, y, z))
+#endif
+
+#include <pthread.h>
+
+static pthread_once_t init_control = PTHREAD_ONCE_INIT;
+
+static void
+libcurl_init(void)
+{
+  curl_global_init(CURL_GLOBAL_DEFAULT);
+}
+
+struct debuginfod_client
+{
+  /* Progress/interrupt callback function. */
+  debuginfod_progressfn_t progressfn;
+
+  /* Stores user data. */
+  void* user_data;
+
+  /* Stores current/last url, if any. */
+  char* url;
+
+  /* Accumulates outgoing http header names/values. */
+  int user_agent_set_p; /* affects add_default_headers */
+  struct curl_slist *headers;
+
+  /* Flags the default_progressfn having printed something that
+     debuginfod_end needs to terminate. */
+  int default_progressfn_printed_p;
+
+  /* Indicates whether the last query was cancelled by progressfn.  */
+  bool progressfn_cancel;
+
+  /* File descriptor to output any verbose messages if > 0.  */
+  int verbose_fd;
+
+  /* Maintain a long-lived curl multi-handle, which keeps a
+     connection/tls/dns cache to recently seen servers. */
+  CURLM *server_mhandle;
+  
+  /* Can contain all other context, like cache_path, server_urls,
+     timeout or other info gotten from environment variables, the
+     handle data, etc. So those don't have to be reparsed and
+     recreated on each request.  */
+  char * winning_headers;
+};
+
+/* The cache_clean_interval_s file within the debuginfod cache specifies
+   how frequently the cache should be cleaned. The file's st_mtime represents
+   the time of last cleaning.  */
+static const char *cache_clean_interval_filename = "cache_clean_interval_s";
+static const long cache_clean_default_interval_s = 86400; /* 1 day */
+
+/* The cache_miss_default_s within the debuginfod cache specifies how
+   frequently the empty file should be released.*/
+static const long cache_miss_default_s = 600; /* 10 min */
+static const char *cache_miss_filename = "cache_miss_s";
+
+/* The cache_max_unused_age_s file within the debuginfod cache specifies the
+   the maximum time since last access that a file will remain in the cache.  */
+static const char *cache_max_unused_age_filename = "max_unused_age_s";
+static const long cache_default_max_unused_age_s = 604800; /* 1 week */
+
+/* Location of the cache of files downloaded from debuginfods.
+   The default parent directory is $HOME, or '/' if $HOME doesn't exist.  */
+static const char *cache_default_name = ".debuginfod_client_cache";
+static const char *cache_xdg_name = "debuginfod_client";
+
+/* URLs of debuginfods, separated by url_delim. */
+static const char *url_delim =  " ";
+
+/* Timeout for debuginfods, in seconds (to get at least 100K). */
+static const long default_timeout = 90;
+
+/* Default retry count for download error. */
+static const long default_retry_limit = 2;
+
+/* Data associated with a particular CURL easy handle. Passed to
+   the write callback.  */
+struct handle_data
+{
+  /* Cache file to be written to in case query is successful.  */
+  int fd;
+
+  /* URL queried by this handle.  */
+  char url[PATH_MAX];
+
+  /* error buffer for this handle.  */
+  char errbuf[CURL_ERROR_SIZE];
+
+  /* This handle.  */
+  CURL *handle;
+
+  /* The client object whom we're serving. */
+  debuginfod_client *client;
+
+  /* Pointer to handle that should write to fd. Initially points to NULL,
+     then points to the first handle that begins writing the target file
+     to the cache. Used to ensure that a file is not downloaded from
+     multiple servers unnecessarily.  */
+  CURL **target_handle;
+  /* Response http headers for this client handle, sent from the server */
+  char *response_data;
+  size_t response_data_size;
+};
+
+static size_t
+debuginfod_write_callback (char *ptr, size_t size, size_t nmemb, void *data)
+{
+  ssize_t count = size * nmemb;
+
+  struct handle_data *d = (struct handle_data*)data;
+
+  /* Indicate to other handles that they can abort their transfer.  */
+  if (*d->target_handle == NULL)
+    {
+      *d->target_handle = d->handle;
+      /* update the client object */
+      const char *url = NULL;
+      CURLcode curl_res = curl_easy_getinfo (d->handle,
+                                             CURLINFO_EFFECTIVE_URL, &url);
+      if (curl_res == CURLE_OK && url)
+        {
+          free (d->client->url);
+          d->client->url = strdup(url); /* ok if fails */
+        }
+    }
+
+  /* If this handle isn't the target handle, abort transfer.  */
+  if (*d->target_handle != d->handle)
+    return -1;
+
+  return (size_t) write(d->fd, (void*)ptr, count);
+}
+
+/* handle config file read and write */
+static int
+debuginfod_config_cache(debuginfod_client *c, char *config_path,
+			long cache_config_default_s,
+			struct stat *st)
+{
+  int fd = open(config_path, O_CREAT | O_RDWR, DEFFILEMODE);
+  if (fd < 0)
+    return -errno;
+
+  if (fstat (fd, st) < 0)
+    {
+      int ret = -errno;
+      close (fd);
+      return ret;
+    }
+
+  if (st->st_size == 0)
+    {
+      if (dprintf(fd, "%ld", cache_config_default_s) < 0)
+	{
+	  int ret = -errno;
+	  close (fd);
+	  return ret;
+	}
+
+      close (fd);
+      return cache_config_default_s;
+    }
+
+  long cache_config;
+  /* PR29696 - NB: When using fdopen, the file descriptor is NOT
+     dup'ed and will be closed when the stream is closed. Manually
+     closing fd after fclose is called will lead to a race condition
+     where, if reused, the file descriptor will compete for its
+     regular use before being incorrectly closed here.  */
+  FILE *config_file = fdopen(fd, "r");
+  if (config_file)
+    {
+      if (fscanf(config_file, "%ld", &cache_config) != 1)
+	cache_config = cache_config_default_s;
+      if (0 != fclose (config_file) && c->verbose_fd >= 0)
+	dprintf (c->verbose_fd, "fclose failed with %s (err=%d)\n",
+		 strerror (errno), errno);
+    }
+  else
+    {
+      cache_config = cache_config_default_s;
+      if (0 != close (fd) && c->verbose_fd >= 0)
+	dprintf (c->verbose_fd, "close failed with %s (err=%d)\n",
+		 strerror (errno), errno);
+    }
+  return cache_config;
+}
+
+/* Delete any files that have been unmodied for a period
+   longer than $DEBUGINFOD_CACHE_CLEAN_INTERVAL_S.  */
+static int
+debuginfod_clean_cache(debuginfod_client *c,
+		       char *cache_path, char *interval_path,
+		       char *max_unused_path)
+{
+  time_t clean_interval, max_unused_age;
+  int rc = -1;
+  struct stat st;
+
+  /* Create new interval file.  */
+  rc = debuginfod_config_cache(c, interval_path,
+			       cache_clean_default_interval_s, &st);
+  if (rc < 0)
+    return rc;
+  clean_interval = (time_t)rc;
+
+  /* Check timestamp of interval file to see whether cleaning is necessary.  */
+  if (time(NULL) - st.st_mtime < clean_interval)
+    /* Interval has not passed, skip cleaning.  */
+    return 0;
+
+  /* Update timestamp representing when the cache was last cleaned.
+     Do it at the start to reduce the number of threads trying to do a
+     cleanup simultaneously.  */
+  utime (interval_path, NULL);
+
+  /* Read max unused age value from config file.  */
+  rc = debuginfod_config_cache(c, max_unused_path,
+			       cache_default_max_unused_age_s, &st);
+  if (rc < 0)
+    return rc;
+  max_unused_age = (time_t)rc;
+
+  char * const dirs[] = { cache_path, NULL, };
+
+  FTS *fts = fts_open(dirs, 0, NULL);
+  if (fts == NULL)
+    return -errno;
+
+  regex_t re;
+  const char * pattern = ".*/[a-f0-9]+(/debuginfo|/executable|/source.*|)$"; /* include dirs */
+  if (regcomp (&re, pattern, REG_EXTENDED | REG_NOSUB) != 0)
+    return -ENOMEM;
+
+  FTSENT *f;
+  long files = 0;
+  time_t now = time(NULL);
+  while ((f = fts_read(fts)) != NULL)
+    {
+      /* ignore any files that do not match the pattern.  */
+      if (regexec (&re, f->fts_path, 0, NULL, 0) != 0)
+        continue;
+
+      files++;
+      if (c->progressfn) /* inform/check progress callback */
+        if ((c->progressfn) (c, files, 0))
+          break;
+
+      switch (f->fts_info)
+        {
+        case FTS_F:
+          /* delete file if max_unused_age has been met or exceeded w.r.t. atime.  */
+          if (now - f->fts_statp->st_atime >= max_unused_age)
+            (void) unlink (f->fts_path);
+          break;
+
+        case FTS_DP:
+          /* Remove if old & empty.  Weaken race against concurrent creation by 
+             checking mtime. */
+          if (now - f->fts_statp->st_mtime >= max_unused_age)
+            (void) rmdir (f->fts_path);
+          break;
+
+        default:
+          ;
+        }
+    }
+  fts_close (fts);
+  regfree (&re);
+
+  return 0;
+}
+
+
+#define MAX_BUILD_ID_BYTES 64
+
+
+static void
+add_default_headers(debuginfod_client *client)
+{
+  if (client->user_agent_set_p)
+    return;
+
+  /* Compute a User-Agent: string to send.  The more accurately this
+     describes this host, the likelier that the debuginfod servers
+     might be able to locate debuginfo for us. */
+
+  char* utspart = NULL;
+  struct utsname uts;
+  int rc = 0;
+  rc = uname (&uts);
+  if (rc == 0)
+    rc = asprintf(& utspart, "%s/%s", uts.sysname, uts.machine);
+  if (rc < 0)
+    utspart = NULL;
+
+  FILE *f = fopen ("/etc/os-release", "r");
+  if (f == NULL)
+    f = fopen ("/usr/lib/os-release", "r");
+  char *id = NULL;
+  char *version = NULL;
+  if (f != NULL)
+    {
+      while (id == NULL || version == NULL)
+        {
+          char buf[128];
+          char *s = &buf[0];
+          if (fgets (s, sizeof(buf), f) == NULL)
+            break;
+
+          int len = strlen (s);
+          if (len < 3)
+            continue;
+          if (s[len - 1] == '\n')
+            {
+              s[len - 1] = '\0';
+              len--;
+            }
+
+          char *v = strchr (s, '=');
+          if (v == NULL || strlen (v) < 2)
+            continue;
+
+          /* Split var and value. */
+          *v = '\0';
+          v++;
+
+          /* Remove optional quotes around value string. */
+          if (*v == '"' || *v == '\'')
+            {
+              v++;
+              s[len - 1] = '\0';
+            }
+          if (strcmp (s, "ID") == 0)
+            id = strdup (v);
+          if (strcmp (s, "VERSION_ID") == 0)
+            version = strdup (v);
+        }
+      fclose (f);
+    }
+
+  char *ua = NULL;
+  rc = asprintf(& ua, "User-Agent: %s/%s,%s,%s/%s",
+                PACKAGE_NAME, PACKAGE_VERSION,
+                utspart ?: "",
+                id ?: "",
+                version ?: "");
+  if (rc < 0)
+    ua = NULL;
+
+  if (ua)
+    (void) debuginfod_add_http_header (client, ua);
+
+  free (ua);
+  free (id);
+  free (version);
+  free (utspart);
+}
+
+/* Add HTTP headers found in the given file, one per line. Blank lines or invalid
+ * headers are ignored.
+ */
+static void
+add_headers_from_file(debuginfod_client *client, const char* filename)
+{
+  int vds = client->verbose_fd;
+  FILE *f = fopen (filename, "r");
+  if (f == NULL)
+    {
+      if (vds >= 0)
+	dprintf(vds, "header file %s: %s\n", filename, strerror(errno));
+      return;
+    }
+
+  while (1)
+    {
+      char buf[8192];
+      char *s = &buf[0];
+      if (feof(f))
+        break;
+      if (fgets (s, sizeof(buf), f) == NULL)
+        break;
+      for (char *c = s; *c != '\0'; ++c)
+        if (!isspace(*c))
+          goto nonempty;
+      continue;
+    nonempty:
+      ;
+      size_t last = strlen(s)-1;
+      if (s[last] == '\n')
+        s[last] = '\0';
+      int rc = debuginfod_add_http_header(client, s);
+      if (rc < 0 && vds >= 0)
+        dprintf(vds, "skipping bad header: %s\n", strerror(-rc));
+    }
+  fclose (f);
+}
+
+
+#define xalloc_str(p, fmt, args...)        \
+  do                                       \
+    {                                      \
+      if (asprintf (&p, fmt, args) < 0)    \
+        {                                  \
+          p = NULL;                        \
+          rc = -ENOMEM;                    \
+          goto out;                        \
+        }                                  \
+    } while (0)
+
+
+/* Offer a basic form of progress tracing */
+static int
+default_progressfn (debuginfod_client *c, long a, long b)
+{
+  const char* url = debuginfod_get_url (c);
+  int len = 0;
+
+  /* We prefer to print the host part of the URL to keep the
+     message short. */
+  if (url != NULL)
+    {
+      const char* buildid = strstr(url, "buildid/");
+      if (buildid != NULL)
+        len = (buildid - url);
+      else
+        len = strlen(url);
+    }
+
+  if (b == 0 || url==NULL) /* early stage */
+    dprintf(STDERR_FILENO,
+            "\rDownloading %c", "-/|\\"[a % 4]);
+  else if (b < 0) /* download in progress but unknown total length */
+    dprintf(STDERR_FILENO,
+            "\rDownloading from %.*s %ld",
+            len, url, a);
+  else /* download in progress, and known total length */
+    dprintf(STDERR_FILENO,
+            "\rDownloading from %.*s %ld/%ld",
+            len, url, a, b);
+  c->default_progressfn_printed_p = 1;
+
+  return 0;
+}
+
+/* This is a callback function that receives http response headers in buffer for use
+ * in this program. https://curl.se/libcurl/c/CURLOPT_HEADERFUNCTION.html is the
+ * online documentation.
+ */
+static size_t
+header_callback (char * buffer, size_t size, size_t numitems, void * userdata)
+{
+  struct handle_data *data = (struct handle_data *) userdata;
+  if (size != 1)
+    return 0;
+  if (data->client
+      && data->client->verbose_fd >= 0
+      && numitems > 2)
+    dprintf (data->client->verbose_fd, "header %.*s", (int)numitems, buffer);
+  // Some basic checks to ensure the headers received are of the expected format
+  if (strncasecmp(buffer, "X-DEBUGINFOD", 11)
+      || buffer[numitems-2] != '\r'
+      || buffer[numitems-1] != '\n'
+      || (buffer == strstr(buffer, ":")) ){
+    return numitems;
+  }
+  /* Temporary buffer for realloc */
+  char *temp = NULL;
+  if (data->response_data == NULL)
+    {
+      temp = malloc(numitems);
+      if (temp == NULL)
+        return 0;
+    }
+  else
+    {
+      temp = realloc(data->response_data, data->response_data_size + numitems);
+      if (temp == NULL)
+        return 0;
+    }
+
+  memcpy(temp + data->response_data_size, buffer, numitems-1);
+  data->response_data = temp;
+  data->response_data_size += numitems-1;
+  data->response_data[data->response_data_size-1] = '\n';
+  data->response_data[data->response_data_size] = '\0';
+  return numitems;
+}
+
+/* Copy SRC to DEST, s,/,#,g */
+
+static void
+path_escape (const char *src, char *dest)
+{
+  unsigned q = 0;
+
+  for (unsigned fi=0; q < PATH_MAX-2; fi++) /* -2, escape is 2 chars.  */
+    switch (src[fi])
+      {
+      case '\0':
+        dest[q] = '\0';
+	return;
+      case '/': /* escape / to prevent dir escape */
+        dest[q++]='#';
+        dest[q++]='#';
+        break;
+      case '#': /* escape # to prevent /# vs #/ collisions */
+        dest[q++]='#';
+        dest[q++]='_';
+        break;
+      default:
+        dest[q++]=src[fi];
+      }
+
+  dest[q] = '\0';
+}
+
+/* Attempt to update the atime */
+static void
+update_atime (int fd)
+{
+  struct timespec tvs[2];
+
+  tvs[0].tv_sec = tvs[1].tv_sec = 0;
+  tvs[0].tv_nsec = UTIME_NOW;
+  tvs[1].tv_nsec = UTIME_OMIT;
+
+  (void) futimens (fd, tvs);  /* best effort */
+}
+
+/* Attempt to read an ELF/DWARF section with name SECTION from FD and write
+   it to a separate file in the debuginfod cache.  If successful the absolute
+   path of the separate file containing SECTION will be stored in USR_PATH.
+   FD_PATH is the absolute path for FD.
+
+   If the section cannot be extracted, then return a negative error code.
+   -ENOENT indicates that the parent file was able to be read but the
+   section name was not found.  -EEXIST indicates that the section was
+   found but had type SHT_NOBITS.  */
+
+static int
+extract_section (int fd, const char *section, char *fd_path, char **usr_path)
+{
+  elf_version (EV_CURRENT);
+
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+  if (elf == NULL)
+    return -EIO;
+
+  size_t shstrndx;
+  int rc = elf_getshdrstrndx (elf, &shstrndx);
+  if (rc < 0)
+    {
+      rc = -EIO;
+      goto out;
+    }
+
+  int sec_fd = -1;
+  char *escaped_name = NULL;
+  char *sec_path_tmp = NULL;
+  Elf_Scn *scn = NULL;
+
+  /* Try to find the target section and copy the contents into a
+     separate file.  */
+  while (true)
+    {
+      scn = elf_nextscn (elf, scn);
+      if (scn == NULL)
+	{
+	  rc = -ENOENT;
+	  goto out;
+	}
+      GElf_Shdr shdr_storage;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_storage);
+      if (shdr == NULL)
+	{
+	  rc = -EIO;
+	  goto out;
+	}
+
+      const char *scn_name = elf_strptr (elf, shstrndx, shdr->sh_name);
+      if (scn_name == NULL)
+	{
+	  rc = -EIO;
+	  goto out;
+	}
+      if (strcmp (scn_name, section) == 0)
+	{
+	  /* We found the desired section.  */
+	  if (shdr->sh_type == SHT_NOBITS)
+	    {
+	      rc = -EEXIST;
+	      goto out;
+	    }
+
+	  Elf_Data *data = NULL;
+	  data = elf_rawdata (scn, NULL);
+	  if (data == NULL)
+	    {
+	      rc = -EIO;
+	      goto out;
+	    }
+
+	  if (data->d_buf == NULL)
+	    {
+	      rc = -EIO;
+	      goto out;
+	    }
+
+	  /* Compute the absolute filename we'll write the section to.
+	     Replace the last component of FD_PATH with the path-escaped
+	     section filename.  */
+	  int i = strlen (fd_path);
+          while (i >= 0)
+	    {
+	      if (fd_path[i] == '/')
+		{
+		  fd_path[i] = '\0';
+		  break;
+		}
+	      --i;
+	    }
+
+	  escaped_name = malloc (strlen (section) * 2 + 1);
+	  if (escaped_name == NULL)
+	    {
+	      rc = -ENOMEM;
+	      goto out;
+	    }
+	  path_escape (section, escaped_name);
+
+	  rc = asprintf (&sec_path_tmp, "%s/section-%s.XXXXXX",
+			 fd_path, escaped_name);
+	  if (rc == -1)
+	    {
+	      rc = -ENOMEM;
+	      goto out1;
+	    }
+
+	  sec_fd = mkstemp (sec_path_tmp);
+	  if (sec_fd < 0)
+	    {
+	      rc = -EIO;
+	      goto out2;
+	    }
+
+	  ssize_t res = write_retry (sec_fd, data->d_buf, data->d_size);
+	  if (res < 0 || (size_t) res != data->d_size)
+	    {
+	      rc = -EIO;
+	      goto out3;
+	    }
+
+	  /* Success.  Rename tmp file and update USR_PATH.  */
+	  char *sec_path;
+	  if (asprintf (&sec_path, "%s/section-%s", fd_path, section) == -1)
+	    {
+	      rc = -ENOMEM;
+	      goto out3;
+	    }
+
+	  rc = rename (sec_path_tmp, sec_path);
+	  if (rc < 0)
+	    {
+	      free (sec_path);
+	      rc = -EIO;
+	      goto out3;
+	    }
+
+	  if (usr_path != NULL)
+	    *usr_path = sec_path;
+	  else
+	    free (sec_path);
+	  update_atime(fd);
+	  rc = sec_fd;
+	  goto out2;
+	}
+    }
+
+out3:
+  close (sec_fd);
+  unlink (sec_path_tmp);
+
+out2:
+  free (sec_path_tmp);
+
+out1:
+  free (escaped_name);
+
+out:
+  elf_end (elf);
+  return rc;
+}
+
+/* Search TARGET_CACHE_DIR for a debuginfo or executable file containing
+   an ELF/DWARF section with name SCN_NAME.  If found, extract the section
+   to a separate file in TARGET_CACHE_DIR and return a file descriptor
+   for the section file. The path for this file will be stored in USR_PATH.
+   Return a negative errno if unsuccessful.  -ENOENT indicates that SCN_NAME
+   is confirmed to not exist.  */
+
+static int
+cache_find_section (const char *scn_name, const char *target_cache_dir,
+		    char **usr_path)
+{
+  int debug_fd;
+  int rc = -EEXIST;
+  char parent_path[PATH_MAX];
+
+  /* Check the debuginfo first.  */
+  snprintf (parent_path, PATH_MAX, "%s/debuginfo", target_cache_dir);
+  debug_fd = open (parent_path, O_RDONLY);
+  if (debug_fd >= 0)
+    {
+      rc = extract_section (debug_fd, scn_name, parent_path, usr_path);
+      close (debug_fd);
+    }
+
+  /* If the debuginfo file couldn't be found or the section type was
+     SHT_NOBITS, check the executable.  */
+  if (rc == -EEXIST)
+    {
+      snprintf (parent_path, PATH_MAX, "%s/executable", target_cache_dir);
+      int exec_fd = open (parent_path, O_RDONLY);
+
+      if (exec_fd >= 0)
+	{
+	  rc = extract_section (exec_fd, scn_name, parent_path, usr_path);
+	  close (exec_fd);
+
+	  /* Don't return -ENOENT if the debuginfo wasn't opened.  The
+	     section may exist in the debuginfo but not the executable.  */
+	  if (debug_fd < 0 && rc == -ENOENT)
+	    rc = -EREMOTE;
+	}
+    }
+
+  return rc;
+}
+
+/* Query each of the server URLs found in $DEBUGINFOD_URLS for the file
+   with the specified build-id and type (debuginfo, executable, source or
+   section).  If type is source, then type_arg should be a filename.  If
+   type is section, then type_arg should be the name of an ELF/DWARF
+   section.  Otherwise type_arg may be NULL.  Return a file descriptor
+   for the target if successful, otherwise return an error code.
+*/
+static int
+debuginfod_query_server (debuginfod_client *c,
+			 const unsigned char *build_id,
+                         int build_id_len,
+                         const char *type,
+                         const char *type_arg,
+                         char **path)
+{
+  char *server_urls;
+  char *urls_envvar;
+  const char *section = NULL;
+  const char *filename = NULL;
+  char *cache_path = NULL;
+  char *maxage_path = NULL;
+  char *interval_path = NULL;
+  char *cache_miss_path = NULL;
+  char *target_cache_dir = NULL;
+  char *target_cache_path = NULL;
+  char *target_cache_tmppath = NULL;
+  char suffix[PATH_MAX + 1]; /* +1 for zero terminator.  */
+  char build_id_bytes[MAX_BUILD_ID_BYTES * 2 + 1];
+  int vfd = c->verbose_fd;
+  int rc;
+
+  c->progressfn_cancel = false;
+
+  if (strcmp (type, "source") == 0)
+    filename = type_arg;
+  else if (strcmp (type, "section") == 0)
+    {
+      section = type_arg;
+      if (section == NULL)
+	return -EINVAL;
+    }
+
+  if (vfd >= 0)
+    {
+      dprintf (vfd, "debuginfod_find_%s ", type);
+      if (build_id_len == 0) /* expect clean hexadecimal */
+	dprintf (vfd, "%s", (const char *) build_id);
+      else
+	for (int i = 0; i < build_id_len; i++)
+	  dprintf (vfd, "%02x", build_id[i]);
+      if (filename != NULL)
+	dprintf (vfd, " %s\n", filename);
+      dprintf (vfd, "\n");
+    }
+
+  /* Is there any server we can query?  If not, don't do any work,
+     just return with ENOSYS.  Don't even access the cache.  */
+  urls_envvar = getenv(DEBUGINFOD_URLS_ENV_VAR);
+  if (vfd >= 0)
+    dprintf (vfd, "server urls \"%s\"\n",
+	     urls_envvar != NULL ? urls_envvar : "");
+  if (urls_envvar == NULL || urls_envvar[0] == '\0')
+    {
+      rc = -ENOSYS;
+      goto out;
+    }
+
+  /* Clear the obsolete data from a previous _find operation. */
+  free (c->url);
+  c->url = NULL;
+  free (c->winning_headers);
+  c->winning_headers = NULL;
+
+  /* PR 27982: Add max size if DEBUGINFOD_MAXSIZE is set. */
+  long maxsize = 0;
+  const char *maxsize_envvar;
+  maxsize_envvar = getenv(DEBUGINFOD_MAXSIZE_ENV_VAR);
+  if (maxsize_envvar != NULL)
+    maxsize = atol (maxsize_envvar);
+
+  /* PR 27982: Add max time if DEBUGINFOD_MAXTIME is set. */
+  long maxtime = 0;
+  const char *maxtime_envvar;
+  maxtime_envvar = getenv(DEBUGINFOD_MAXTIME_ENV_VAR);
+  if (maxtime_envvar != NULL)
+    maxtime = atol (maxtime_envvar);
+  if (maxtime && vfd >= 0)
+    dprintf(vfd, "using max time %lds\n", maxtime);
+
+  const char *headers_file_envvar;
+  headers_file_envvar = getenv(DEBUGINFOD_HEADERS_FILE_ENV_VAR);
+  if (headers_file_envvar != NULL)
+    add_headers_from_file(c, headers_file_envvar);
+
+  /* Maxsize is valid*/
+  if (maxsize > 0)
+    {
+      if (vfd)
+        dprintf (vfd, "using max size %ldB\n", maxsize);
+      char *size_header = NULL;
+      rc = asprintf (&size_header, "X-DEBUGINFOD-MAXSIZE: %ld", maxsize);
+      if (rc < 0)
+        {
+          rc = -ENOMEM;
+          goto out;
+        }
+      rc = debuginfod_add_http_header(c, size_header);
+      free(size_header);
+      if (rc < 0)
+        goto out;
+    }
+  add_default_headers(c);
+
+  /* Copy lowercase hex representation of build_id into buf.  */
+  if (vfd >= 0)
+    dprintf (vfd, "checking build-id\n");
+  if ((build_id_len >= MAX_BUILD_ID_BYTES) ||
+      (build_id_len == 0 &&
+       strlen ((const char *) build_id) > MAX_BUILD_ID_BYTES*2))
+    {
+      rc = -EINVAL;
+      goto out;
+    }
+
+  if (build_id_len == 0) /* expect clean hexadecimal */
+    strcpy (build_id_bytes, (const char *) build_id);
+  else
+    for (int i = 0; i < build_id_len; i++)
+      sprintf(build_id_bytes + (i * 2), "%02x", build_id[i]);
+
+  if (filename != NULL)
+    {
+      if (vfd >= 0)
+	dprintf (vfd, "checking filename\n");
+      if (filename[0] != '/') // must start with /
+	{
+	  rc = -EINVAL;
+	  goto out;
+	}
+
+      path_escape (filename, suffix);
+      /* If the DWARF filenames are super long, this could exceed
+         PATH_MAX and truncate/collide.  Oh well, that'll teach
+         them! */
+    }
+  else if (section != NULL)
+    path_escape (section, suffix);
+  else
+    suffix[0] = '\0';
+
+  if (suffix[0] != '\0' && vfd >= 0)
+    dprintf (vfd, "suffix %s\n", suffix);
+
+  /* set paths needed to perform the query
+
+     example format
+     cache_path:        $HOME/.cache
+     target_cache_dir:  $HOME/.cache/0123abcd
+     target_cache_path: $HOME/.cache/0123abcd/debuginfo
+     target_cache_path: $HOME/.cache/0123abcd/source#PATH#TO#SOURCE ?
+
+     $XDG_CACHE_HOME takes priority over $HOME/.cache.
+     $DEBUGINFOD_CACHE_PATH takes priority over $HOME/.cache and $XDG_CACHE_HOME.
+  */
+
+  /* Determine location of the cache. The path specified by the debuginfod
+     cache environment variable takes priority.  */
+  char *cache_var = getenv(DEBUGINFOD_CACHE_PATH_ENV_VAR);
+  if (cache_var != NULL && strlen (cache_var) > 0)
+    xalloc_str (cache_path, "%s", cache_var);
+  else
+    {
+      /* If a cache already exists in $HOME ('/' if $HOME isn't set), then use
+         that. Otherwise use the XDG cache directory naming format.  */
+      xalloc_str (cache_path, "%s/%s", getenv ("HOME") ?: "/", cache_default_name);
+
+      struct stat st;
+      if (stat (cache_path, &st) < 0)
+        {
+          char cachedir[PATH_MAX];
+          char *xdg = getenv ("XDG_CACHE_HOME");
+
+          if (xdg != NULL && strlen (xdg) > 0)
+            snprintf (cachedir, PATH_MAX, "%s", xdg);
+          else
+            snprintf (cachedir, PATH_MAX, "%s/.cache", getenv ("HOME") ?: "/");
+
+          /* Create XDG cache directory if it doesn't exist.  */
+          if (stat (cachedir, &st) == 0)
+            {
+              if (! S_ISDIR (st.st_mode))
+                {
+                  rc = -EEXIST;
+                  goto out;
+                }
+            }
+          else
+            {
+              rc = mkdir (cachedir, 0700);
+
+              /* Also check for EEXIST and S_ISDIR in case another client just
+                 happened to create the cache.  */
+              if (rc < 0
+                  && (errno != EEXIST
+                      || stat (cachedir, &st) != 0
+                      || ! S_ISDIR (st.st_mode)))
+                {
+                  rc = -errno;
+                  goto out;
+                }
+            }
+
+          free (cache_path);
+          xalloc_str (cache_path, "%s/%s", cachedir, cache_xdg_name);
+        }
+    }
+
+  xalloc_str (target_cache_dir, "%s/%s", cache_path, build_id_bytes);
+  if (section != NULL)
+    xalloc_str (target_cache_path, "%s/%s-%s", target_cache_dir, type, suffix);
+  else
+    xalloc_str (target_cache_path, "%s/%s%s", target_cache_dir, type, suffix);
+  xalloc_str (target_cache_tmppath, "%s.XXXXXX", target_cache_path);
+
+  /* XXX combine these */
+  xalloc_str (interval_path, "%s/%s", cache_path, cache_clean_interval_filename);
+  xalloc_str (cache_miss_path, "%s/%s", cache_path, cache_miss_filename);
+  xalloc_str (maxage_path, "%s/%s", cache_path, cache_max_unused_age_filename);
+
+  if (vfd >= 0)
+    dprintf (vfd, "checking cache dir %s\n", cache_path);
+
+  /* Make sure cache dir exists. debuginfo_clean_cache will then make
+     sure the interval, cache_miss and maxage files exist.  */
+  if (mkdir (cache_path, ACCESSPERMS) != 0
+      && errno != EEXIST)
+    {
+      rc = -errno;
+      goto out;
+    }
+
+  rc = debuginfod_clean_cache(c, cache_path, interval_path, maxage_path);
+  if (rc != 0)
+    goto out;
+
+  /* Check if the target is already in the cache. */
+  int fd = open(target_cache_path, O_RDONLY);
+  if (fd >= 0)
+    {
+      struct stat st;
+      if (fstat(fd, &st) != 0)
+        {
+          rc = -errno;
+          close (fd);
+          goto out;
+        }
+
+      /* If the file is non-empty, then we are done. */
+      if (st.st_size > 0)
+        {
+          if (path != NULL)
+            {
+              *path = strdup(target_cache_path);
+              if (*path == NULL)
+                {
+                  rc = -errno;
+                  close (fd);
+                  goto out;
+                }
+            }
+          /* Success!!!! */
+          update_atime(fd);
+          rc = fd;
+          goto out;
+        }
+      else
+        {
+          /* The file is empty. Attempt to download only if enough time
+             has passed since the last attempt. */
+          time_t cache_miss;
+          time_t target_mtime = st.st_mtime;
+
+          close(fd); /* no need to hold onto the negative-hit file descriptor */
+          
+          rc = debuginfod_config_cache(c, cache_miss_path,
+                                       cache_miss_default_s, &st);
+          if (rc < 0)
+            goto out;
+
+          cache_miss = (time_t)rc;
+          if (time(NULL) - target_mtime <= cache_miss)
+            {
+              rc = -ENOENT;
+              goto out;
+            }
+          else
+            /* TOCTOU non-problem: if another task races, puts a working
+               download or an empty file in its place, unlinking here just
+               means WE will try to download again as uncached. */
+            unlink(target_cache_path);
+        }
+    }
+  else if (errno == EACCES)
+    /* Ensure old 000-permission files are not lingering in the cache. */
+    unlink(target_cache_path);
+
+  if (section != NULL)
+    {
+      /* Try to extract the section from a cached file before querying
+	 any servers.  */
+      rc = cache_find_section (section, target_cache_dir, path);
+
+      /* If the section was found or confirmed to not exist, then we
+	 are done.  */
+      if (rc >= 0 || rc == -ENOENT)
+	goto out;
+    }
+
+  long timeout = default_timeout;
+  const char* timeout_envvar = getenv(DEBUGINFOD_TIMEOUT_ENV_VAR);
+  if (timeout_envvar != NULL)
+    timeout = atoi (timeout_envvar);
+
+  if (vfd >= 0)
+    dprintf (vfd, "using timeout %ld\n", timeout);
+
+  /* make a copy of the envvar so it can be safely modified.  */
+  server_urls = strdup(urls_envvar);
+  if (server_urls == NULL)
+    {
+      rc = -ENOMEM;
+      goto out;
+    }
+  /* thereafter, goto out0 on error*/
+
+  /* Because of a race with cache cleanup / rmdir, try to mkdir/mkstemp up to twice. */
+  for(int i=0; i<2; i++) {
+    /* (re)create target directory in cache */
+    (void) mkdir(target_cache_dir, 0700); /* files will be 0400 later */
+
+    /* NB: write to a temporary file first, to avoid race condition of
+       multiple clients checking the cache, while a partially-written or empty
+       file is in there, being written from libcurl. */
+    fd = mkstemp (target_cache_tmppath);
+    if (fd >= 0) break;
+  }
+  if (fd < 0) /* Still failed after two iterations. */
+    {
+      rc = -errno;
+      goto out0;
+    }
+
+  /* Initialize the memory to zero */
+  char *strtok_saveptr;
+  char **server_url_list = NULL;
+  char *server_url = strtok_r(server_urls, url_delim, &strtok_saveptr);
+  /* Count number of URLs.  */
+  int num_urls = 0;
+
+  while (server_url != NULL)
+    {
+      /* PR 27983: If the url is already set to be used use, skip it */
+      char *slashbuildid;
+      if (strlen(server_url) > 1 && server_url[strlen(server_url)-1] == '/')
+        slashbuildid = "buildid";
+      else
+        slashbuildid = "/buildid";
+
+      char *tmp_url;
+      if (asprintf(&tmp_url, "%s%s", server_url, slashbuildid) == -1)
+        {
+          rc = -ENOMEM;
+          goto out1;
+        }
+      int url_index;
+      for (url_index = 0; url_index < num_urls; ++url_index)
+        {
+          if(strcmp(tmp_url, server_url_list[url_index]) == 0)
+            {
+              url_index = -1;
+              break;
+            }
+        }
+      if (url_index == -1)
+        {
+          if (vfd >= 0)
+            dprintf(vfd, "duplicate url: %s, skipping\n", tmp_url);
+          free(tmp_url);
+        }
+      else
+        {
+          num_urls++;
+          char ** realloc_ptr;
+          realloc_ptr = reallocarray(server_url_list, num_urls,
+                                         sizeof(char*));
+          if (realloc_ptr == NULL)
+            {
+              free (tmp_url);
+              rc = -ENOMEM;
+              goto out1;
+            }
+          server_url_list = realloc_ptr;
+          server_url_list[num_urls-1] = tmp_url;
+        }
+      server_url = strtok_r(NULL, url_delim, &strtok_saveptr);
+    }
+
+  int retry_limit = default_retry_limit;
+  const char* retry_limit_envvar = getenv(DEBUGINFOD_RETRY_LIMIT_ENV_VAR);
+  if (retry_limit_envvar != NULL)
+    retry_limit = atoi (retry_limit_envvar);
+
+  CURLM *curlm = c->server_mhandle;
+  assert (curlm != NULL);
+
+  /* Tracks which handle should write to fd. Set to the first
+     handle that is ready to write the target file to the cache.  */
+  CURL *target_handle = NULL;
+  struct handle_data *data = malloc(sizeof(struct handle_data) * num_urls);
+  if (data == NULL)
+    {
+      rc = -ENOMEM;
+      goto out1;
+    }
+
+  /* thereafter, goto out2 on error.  */
+
+ /*The beginning of goto block query_in_parallel.*/
+ query_in_parallel:
+  rc = -ENOENT; /* Reset rc to default.*/
+
+  /* Initialize handle_data with default values. */
+  for (int i = 0; i < num_urls; i++)
+    {
+      data[i].handle = NULL;
+      data[i].fd = -1;
+      data[i].errbuf[0] = '\0';
+      data[i].response_data = NULL;
+      data[i].response_data_size = 0;
+    }
+
+  char *escaped_string = NULL;
+  size_t escaped_strlen = 0;
+  if (filename)
+    {
+      escaped_string = curl_easy_escape(&target_handle, filename+1, 0);
+      if (!escaped_string)
+        {
+          rc = -ENOMEM;
+          goto out2;
+        }
+      char *loc = escaped_string;
+      escaped_strlen = strlen(escaped_string);
+      while ((loc = strstr(loc, "%2F")))
+        {
+          loc[0] = '/';
+          //pull the string back after replacement
+          // loc-escaped_string finds the distance from the origin to the new location
+          // - 2 accounts for the 2F which remain and don't need to be measured.
+          // The two above subtracted from escaped_strlen yields the remaining characters
+          // in the string which we want to pull back
+          memmove(loc+1, loc+3,escaped_strlen - (loc-escaped_string) - 2);
+          //Because the 2F was overwritten in the memmove (as desired) escaped_strlen is
+          // now two shorter.
+          escaped_strlen -= 2;
+        }
+    }
+  /* Initialize each handle.  */
+  for (int i = 0; i < num_urls; i++)
+    {
+      if ((server_url = server_url_list[i]) == NULL)
+        break;
+      if (vfd >= 0)
+	dprintf (vfd, "init server %d %s\n", i, server_url);
+
+      data[i].fd = fd;
+      data[i].target_handle = &target_handle;
+      data[i].handle = curl_easy_init();
+      if (data[i].handle == NULL)
+        {
+          if (filename) curl_free (escaped_string);
+          rc = -ENETUNREACH;
+          goto out2;
+        }
+      data[i].client = c;
+
+      if (filename) /* must start with / */
+        {
+          /* PR28034 escape characters in completed url to %hh format. */
+          snprintf(data[i].url, PATH_MAX, "%s/%s/%s/%s", server_url,
+                   build_id_bytes, type, escaped_string);
+        }
+      else if (section)
+	snprintf(data[i].url, PATH_MAX, "%s/%s/%s/%s", server_url,
+		 build_id_bytes, type, section);
+      else
+        snprintf(data[i].url, PATH_MAX, "%s/%s/%s", server_url, build_id_bytes, type);
+      if (vfd >= 0)
+	dprintf (vfd, "url %d %s\n", i, data[i].url);
+
+      /* Some boilerplate for checking curl_easy_setopt.  */
+#define curl_easy_setopt_ck(H,O,P) do {			\
+      CURLcode curl_res = curl_easy_setopt (H,O,P);	\
+      if (curl_res != CURLE_OK)				\
+	{						\
+	  if (vfd >= 0)					\
+	    dprintf (vfd,				\
+	             "Bad curl_easy_setopt: %s\n",	\
+		     curl_easy_strerror(curl_res));	\
+	  rc = -EINVAL;					\
+	  goto out2;					\
+	}						\
+      } while (0)
+
+      /* Only allow http:// + https:// + file:// so we aren't being
+	 redirected to some unsupported protocol.  */
+#if CURL_AT_LEAST_VERSION(7, 85, 0)
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_PROTOCOLS_STR,
+			  "http,https,file");
+#else
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_PROTOCOLS,
+			  (CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FILE));
+#endif
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_URL, data[i].url);
+      if (vfd >= 0)
+	curl_easy_setopt_ck(data[i].handle, CURLOPT_ERRORBUFFER,
+			    data[i].errbuf);
+      curl_easy_setopt_ck(data[i].handle,
+			  CURLOPT_WRITEFUNCTION,
+			  debuginfod_write_callback);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_WRITEDATA, (void*)&data[i]);
+      if (timeout > 0)
+	{
+	  /* Make sure there is at least some progress,
+	     try to get at least 100K per timeout seconds.  */
+	  curl_easy_setopt_ck (data[i].handle, CURLOPT_LOW_SPEED_TIME,
+			       timeout);
+	  curl_easy_setopt_ck (data[i].handle, CURLOPT_LOW_SPEED_LIMIT,
+			       100 * 1024L);
+	}
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_FILETIME, (long) 1);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_FOLLOWLOCATION, (long) 1);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_FAILONERROR, (long) 1);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_NOSIGNAL, (long) 1);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_HEADERFUNCTION,
+			  header_callback);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_HEADERDATA,
+			  (void *) &(data[i]));
+#if LIBCURL_VERSION_NUM >= 0x072a00 /* 7.42.0 */
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_PATH_AS_IS, (long) 1);
+#else
+      /* On old curl; no big deal, canonicalization here is almost the
+         same, except perhaps for ? # type decorations at the tail. */
+#endif
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_AUTOREFERER, (long) 1);
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_ACCEPT_ENCODING, "");
+      curl_easy_setopt_ck(data[i].handle, CURLOPT_HTTPHEADER, c->headers);
+
+      curl_multi_add_handle(curlm, data[i].handle);
+    }
+
+  if (filename) curl_free(escaped_string);
+  /* Query servers in parallel.  */
+  if (vfd >= 0)
+    dprintf (vfd, "query %d urls in parallel\n", num_urls);
+  int still_running;
+  long loops = 0;
+  int committed_to = -1;
+  bool verbose_reported = false;
+  struct timespec start_time, cur_time;
+
+  free (c->winning_headers);
+  c->winning_headers = NULL;
+  if ( maxtime > 0 && clock_gettime(CLOCK_MONOTONIC_RAW, &start_time) == -1)
+    {
+      rc = -errno;
+      goto out2;
+    }
+  long delta = 0;
+  do
+    {
+      /* Check to see how long querying is taking. */
+      if (maxtime > 0)
+        {
+          if (clock_gettime(CLOCK_MONOTONIC_RAW, &cur_time) == -1)
+            {
+              rc = -errno;
+              goto out2;
+            }
+          delta = cur_time.tv_sec - start_time.tv_sec;
+          if ( delta >  maxtime)
+            {
+              dprintf(vfd, "Timeout with max time=%lds and transfer time=%lds\n", maxtime, delta );
+              rc = -ETIME;
+              goto out2;
+            }
+        }
+      /* Wait 1 second, the minimum DEBUGINFOD_TIMEOUT.  */
+      curl_multi_wait(curlm, NULL, 0, 1000, NULL);
+      CURLMcode curlm_res = curl_multi_perform(curlm, &still_running);
+
+      /* If the target file has been found, abort the other queries.  */
+      if (target_handle != NULL)
+	{
+	  for (int i = 0; i < num_urls; i++)
+	    if (data[i].handle != target_handle)
+	      curl_multi_remove_handle(curlm, data[i].handle);
+	    else
+              {
+	        committed_to = i;
+                if (c->winning_headers == NULL)
+                  {
+                    c->winning_headers = data[committed_to].response_data;
+                    data[committed_to].response_data = NULL;
+                    data[committed_to].response_data_size = 0;
+                  }
+
+              }
+	}
+
+      if (vfd >= 0 && !verbose_reported && committed_to >= 0)
+	{
+	  bool pnl = (c->default_progressfn_printed_p && vfd == STDERR_FILENO);
+	  dprintf (vfd, "%scommitted to url %d\n", pnl ? "\n" : "",
+		   committed_to);
+	  if (pnl)
+	    c->default_progressfn_printed_p = 0;
+	  verbose_reported = true;
+	}
+
+      if (curlm_res != CURLM_OK)
+        {
+          switch (curlm_res)
+            {
+            case CURLM_CALL_MULTI_PERFORM: continue;
+            case CURLM_OUT_OF_MEMORY: rc = -ENOMEM; break;
+            default: rc = -ENETUNREACH; break;
+            }
+          goto out2;
+        }
+
+      long dl_size = -1;
+      if (target_handle && (c->progressfn || maxsize > 0))
+        {
+          /* Get size of file being downloaded. NB: If going through
+             deflate-compressing proxies, this number is likely to be
+             unavailable, so -1 may show. */
+          CURLcode curl_res;
+#if CURL_AT_LEAST_VERSION(7, 55, 0)
+          curl_off_t cl;
+          curl_res = curl_easy_getinfo(target_handle,
+                                       CURLINFO_CONTENT_LENGTH_DOWNLOAD_T,
+                                       &cl);
+          if (curl_res == CURLE_OK && cl >= 0)
+            dl_size = (cl > LONG_MAX ? LONG_MAX : (long)cl);
+#else
+          double cl;
+          curl_res = curl_easy_getinfo(target_handle,
+                                       CURLINFO_CONTENT_LENGTH_DOWNLOAD,
+                                       &cl);
+          if (curl_res == CURLE_OK && cl >= 0)
+            dl_size = (cl >= (double)(LONG_MAX+1UL) ? LONG_MAX : (long)cl);
+#endif
+          /* If Content-Length is -1, try to get the size from
+             X-Debuginfod-Size */
+          if (dl_size == -1 && c->winning_headers != NULL)
+            {
+              long xdl;
+              char *hdr = strcasestr(c->winning_headers, "x-debuginfod-size");
+              size_t off = strlen("x-debuginfod-size:");
+
+              if (hdr != NULL && sscanf(hdr + off, "%ld", &xdl) == 1)
+                dl_size = xdl;
+            }
+        }
+
+      if (c->progressfn) /* inform/check progress callback */
+        {
+          loops ++;
+          long pa = loops; /* default param for progress callback */
+          if (target_handle) /* we've committed to a server; report its download progress */
+            {
+              /* PR30809: Check actual size of cached file.  This same
+                 fd is shared by all the multi-curl handles (but only
+                 one will end up writing to it).  Another way could be
+                 to tabulate totals in debuginfod_write_callback(). */
+              struct stat cached;
+              int statrc = fstat(fd, &cached);
+              if (statrc == 0)
+                pa = (long) cached.st_size;
+              else
+                {
+                  /* Otherwise, query libcurl for its tabulated total.
+                     However, that counts http body length, not
+                     decoded/decompressed content length, so does not
+                     measure quite the same thing as dl. */
+                  CURLcode curl_res;
+#if CURL_AT_LEAST_VERSION(7, 55, 0)
+                  curl_off_t dl;
+                  curl_res = curl_easy_getinfo(target_handle,
+                                               CURLINFO_SIZE_DOWNLOAD_T,
+                                               &dl);
+                  if (curl_res == 0 && dl >= 0)
+                    pa = (dl > LONG_MAX ? LONG_MAX : (long)dl);
+#else
+                  double dl;
+                  curl_res = curl_easy_getinfo(target_handle,
+                                               CURLINFO_SIZE_DOWNLOAD,
+                                               &dl);
+                  if (curl_res == 0)
+                    pa = (dl >= (double)(LONG_MAX+1UL) ? LONG_MAX : (long)dl);
+#endif
+                }
+            }
+
+          if ((*c->progressfn) (c, pa, dl_size == -1 ? 0 : dl_size))
+	    {
+	      c->progressfn_cancel = true;
+              break;
+	    }
+        }
+
+      /* Check to see if we are downloading something which exceeds maxsize, if set.*/
+      if (target_handle && dl_size > maxsize && maxsize > 0)
+        {
+          if (vfd >=0)
+            dprintf(vfd, "Content-Length too large.\n");
+          rc = -EFBIG;
+          goto out2;
+        }
+    } while (still_running);
+
+  /* Check whether a query was successful. If so, assign its handle
+     to verified_handle.  */
+  int num_msg;
+  rc = -ENOENT;
+  CURL *verified_handle = NULL;
+  do
+    {
+      CURLMsg *msg;
+
+      msg = curl_multi_info_read(curlm, &num_msg);
+      if (msg != NULL && msg->msg == CURLMSG_DONE)
+        {
+	  if (vfd >= 0)
+	    {
+	      bool pnl = (c->default_progressfn_printed_p
+			  && vfd == STDERR_FILENO);
+	      dprintf (vfd, "%sserver response %s\n", pnl ? "\n" : "",
+		       curl_easy_strerror (msg->data.result));
+	      if (pnl)
+		c->default_progressfn_printed_p = 0;
+	      for (int i = 0; i < num_urls; i++)
+		if (msg->easy_handle == data[i].handle)
+		  {
+		    if (strlen (data[i].errbuf) > 0)
+		      dprintf (vfd, "url %d %s\n", i, data[i].errbuf);
+		    break;
+		  }
+	    }
+
+          if (msg->data.result != CURLE_OK)
+            {
+              long resp_code;
+              CURLcode ok0;
+              /* Unsuccessful query, determine error code.  */
+              switch (msg->data.result)
+                {
+                case CURLE_COULDNT_RESOLVE_HOST: rc = -EHOSTUNREACH; break; // no NXDOMAIN
+                case CURLE_URL_MALFORMAT: rc = -EINVAL; break;
+                case CURLE_COULDNT_CONNECT: rc = -ECONNREFUSED; break;
+                case CURLE_PEER_FAILED_VERIFICATION: rc = -ECONNREFUSED; break;
+                case CURLE_REMOTE_ACCESS_DENIED: rc = -EACCES; break;
+                case CURLE_WRITE_ERROR: rc = -EIO; break;
+                case CURLE_OUT_OF_MEMORY: rc = -ENOMEM; break;
+                case CURLE_TOO_MANY_REDIRECTS: rc = -EMLINK; break;
+                case CURLE_SEND_ERROR: rc = -ECONNRESET; break;
+                case CURLE_RECV_ERROR: rc = -ECONNRESET; break;
+                case CURLE_OPERATION_TIMEDOUT: rc = -ETIME; break;
+                case CURLE_HTTP_RETURNED_ERROR:
+                  ok0 = curl_easy_getinfo (msg->easy_handle,
+                                          CURLINFO_RESPONSE_CODE,
+				          &resp_code);
+                  /* 406 signals that the requested file was too large */
+                  if ( ok0 == CURLE_OK && resp_code == 406)
+                    rc = -EFBIG;
+		  else if (section != NULL && resp_code == 503)
+		    rc = -EINVAL;
+                  else
+                    rc = -ENOENT;
+                  break;
+                default: rc = -ENOENT; break;
+                }
+            }
+          else
+            {
+              /* Query completed without an error. Confirm that the
+                 response code is 200 when using HTTP/HTTPS and 0 when
+                 using file:// and set verified_handle.  */
+
+              if (msg->easy_handle != NULL)
+                {
+                  char *effective_url = NULL;
+                  long resp_code = 500;
+                  CURLcode ok1 = curl_easy_getinfo (target_handle,
+						    CURLINFO_EFFECTIVE_URL,
+						    &effective_url);
+                  CURLcode ok2 = curl_easy_getinfo (target_handle,
+						    CURLINFO_RESPONSE_CODE,
+						    &resp_code);
+                  if(ok1 == CURLE_OK && ok2 == CURLE_OK && effective_url)
+                    {
+                      if (strncasecmp (effective_url, "HTTP", 4) == 0)
+                        if (resp_code == 200)
+                          {
+                            verified_handle = msg->easy_handle;
+                            break;
+                          }
+                      if (strncasecmp (effective_url, "FILE", 4) == 0)
+                        if (resp_code == 0)
+                          {
+                            verified_handle = msg->easy_handle;
+                            break;
+                          }
+                    }
+                  /* - libcurl since 7.52.0 version start to support
+                       CURLINFO_SCHEME;
+                     - before 7.61.0, effective_url would give us a
+                       url with upper case SCHEME added in the front;
+                     - effective_url between 7.61 and 7.69 can be lack
+                       of scheme if the original url doesn't include one;
+                     - since version 7.69 effective_url will be provide
+                       a scheme in lower case.  */
+                  #if LIBCURL_VERSION_NUM >= 0x073d00 /* 7.61.0 */
+                  #if LIBCURL_VERSION_NUM <= 0x074500 /* 7.69.0 */
+                  char *scheme = NULL;
+                  CURLcode ok3 = curl_easy_getinfo (target_handle,
+                                                    CURLINFO_SCHEME,
+                                                    &scheme);
+                  if(ok3 == CURLE_OK && scheme)
+                    {
+                      if (startswith (scheme, "HTTP"))
+                        if (resp_code == 200)
+                          {
+                            verified_handle = msg->easy_handle;
+                            break;
+                          }
+                    }
+                  #endif
+                  #endif
+                }
+            }
+        }
+    } while (num_msg > 0);
+
+  /* Create an empty file in the cache if the query fails with ENOENT and
+     it wasn't cancelled early.  */
+  if (rc == -ENOENT && !c->progressfn_cancel)
+    {
+      int efd = open (target_cache_path, O_CREAT|O_EXCL, DEFFILEMODE);
+      if (efd >= 0)
+        close(efd);
+    }
+  else if (rc == -EFBIG)
+    goto out2;
+
+  /* If the verified_handle is NULL and rc != -ENOENT, the query fails with
+   * an error code other than 404, then do several retry within the retry_limit.
+   * Clean up all old handles and jump back to the beginning of query_in_parallel,
+   * reinitialize handles and query again.*/
+  if (verified_handle == NULL)
+    {
+      if (rc != -ENOENT && retry_limit-- > 0)
+        {
+	  if (vfd >= 0)
+            dprintf (vfd, "Retry failed query, %d attempt(s) remaining\n", retry_limit);
+	  /* remove all handles from multi */
+          for (int i = 0; i < num_urls; i++)
+            {
+              curl_multi_remove_handle(curlm, data[i].handle); /* ok to repeat */
+              curl_easy_cleanup (data[i].handle);
+              free(data[i].response_data);
+            }
+            free(c->winning_headers);
+            c->winning_headers = NULL;
+	    goto query_in_parallel;
+	}
+      else
+	goto out2;
+    }
+
+  if (vfd >= 0)
+    {
+      bool pnl = c->default_progressfn_printed_p && vfd == STDERR_FILENO;
+      dprintf (vfd, "%sgot file from server\n", pnl ? "\n" : "");
+      if (pnl)
+	c->default_progressfn_printed_p = 0;
+    }
+
+  /* we've got one!!!! */
+  time_t mtime;
+#if defined(_TIME_BITS) && _TIME_BITS == 64
+  CURLcode curl_res = curl_easy_getinfo(verified_handle, CURLINFO_FILETIME_T, (void*) &mtime);
+#else
+  CURLcode curl_res = curl_easy_getinfo(verified_handle, CURLINFO_FILETIME, (void*) &mtime);
+#endif
+  if (curl_res == CURLE_OK)
+    {
+      struct timespec tvs[2];
+      tvs[0].tv_sec = 0;
+      tvs[0].tv_nsec = UTIME_OMIT;
+      tvs[1].tv_sec = mtime;
+      tvs[1].tv_nsec = 0;
+      (void) futimens (fd, tvs);  /* best effort */
+    }
+
+  /* PR27571: make cache files casually unwriteable; dirs are already 0700 */
+  (void) fchmod(fd, 0400);
+  /* PR31248: lseek back to beginning */
+  (void) lseek(fd, 0, SEEK_SET);
+                
+  /* rename tmp->real */
+  rc = rename (target_cache_tmppath, target_cache_path);
+  if (rc < 0)
+    {
+      rc = -errno;
+      goto out2;
+      /* Perhaps we need not give up right away; could retry or something ... */
+    }
+
+  /* remove all handles from multi */
+  for (int i = 0; i < num_urls; i++)
+    {
+      curl_multi_remove_handle(curlm, data[i].handle); /* ok to repeat */
+      curl_easy_cleanup (data[i].handle);
+      free (data[i].response_data);
+    }
+
+  for (int i = 0; i < num_urls; ++i)
+    free(server_url_list[i]);
+  free(server_url_list);
+  free (data);
+  free (server_urls);
+
+  /* don't close fd - we're returning it */
+  /* don't unlink the tmppath; it's already been renamed. */
+  if (path != NULL)
+   *path = strdup(target_cache_path);
+
+  rc = fd;
+  goto out;
+
+/* error exits */
+ out2:
+  /* remove all handles from multi */
+  for (int i = 0; i < num_urls; i++)
+    {
+      if (data[i].handle != NULL)
+	{
+	  curl_multi_remove_handle(curlm, data[i].handle); /* ok to repeat */
+	  curl_easy_cleanup (data[i].handle);
+	  free (data[i].response_data);
+	}
+    }
+
+  unlink (target_cache_tmppath);
+  close (fd); /* before the rmdir, otherwise it'll fail */
+  (void) rmdir (target_cache_dir); /* nop if not empty */
+  free(data);
+
+ out1:
+  for (int i = 0; i < num_urls; ++i)
+    free(server_url_list[i]);
+  free(server_url_list);
+
+ out0:
+  free (server_urls);
+
+/* general purpose exit */
+ out:
+  /* Reset sent headers */
+  curl_slist_free_all (c->headers);
+  c->headers = NULL;
+  c->user_agent_set_p = 0;
+  
+  /* Conclude the last \r status line */
+  /* Another possibility is to use the ANSI CSI n K EL "Erase in Line"
+     code.  That way, the previously printed messages would be erased,
+     and without a newline. */
+  if (c->default_progressfn_printed_p)
+    dprintf(STDERR_FILENO, "\n");
+
+  if (vfd >= 0)
+    {
+      if (rc < 0)
+	dprintf (vfd, "not found %s (err=%d)\n", strerror (-rc), rc);
+      else
+	dprintf (vfd, "found %s (fd=%d)\n", target_cache_path, rc);
+    }
+
+  free (cache_path);
+  free (maxage_path);
+  free (interval_path);
+  free (cache_miss_path);
+  free (target_cache_dir);
+  free (target_cache_path);
+  free (target_cache_tmppath);
+  return rc;
+}
+
+
+
+/* See debuginfod.h  */
+debuginfod_client  *
+debuginfod_begin (void)
+{
+  /* Initialize libcurl lazily, but only once.  */
+  pthread_once (&init_control, libcurl_init);
+
+  debuginfod_client *client;
+  size_t size = sizeof (struct debuginfod_client);
+  client = calloc (1, size);
+
+  if (client != NULL)
+    {
+      if (getenv(DEBUGINFOD_PROGRESS_ENV_VAR))
+	client->progressfn = default_progressfn;
+      if (getenv(DEBUGINFOD_VERBOSE_ENV_VAR))
+	client->verbose_fd = STDERR_FILENO;
+      else
+	client->verbose_fd = -1;
+
+      // allocate 1 curl multi handle
+      client->server_mhandle = curl_multi_init ();
+      if (client->server_mhandle == NULL)
+	goto out1;
+    }
+
+  // extra future initialization
+  
+  goto out;
+
+ out1:
+  free (client);
+  client = NULL;
+
+ out:  
+  return client;
+}
+
+void
+debuginfod_set_user_data(debuginfod_client *client,
+                         void *data)
+{
+  client->user_data = data;
+}
+
+void *
+debuginfod_get_user_data(debuginfod_client *client)
+{
+  return client->user_data;
+}
+
+const char *
+debuginfod_get_url(debuginfod_client *client)
+{
+  return client->url;
+}
+
+const char *
+debuginfod_get_headers(debuginfod_client *client)
+{
+  return client->winning_headers;
+}
+
+void
+debuginfod_end (debuginfod_client *client)
+{
+  if (client == NULL)
+    return;
+
+  curl_multi_cleanup (client->server_mhandle);
+  curl_slist_free_all (client->headers);
+  free (client->winning_headers);
+  free (client->url);
+  free (client);
+}
+
+int
+debuginfod_find_debuginfo (debuginfod_client *client,
+			   const unsigned char *build_id, int build_id_len,
+                           char **path)
+{
+  return debuginfod_query_server(client, build_id, build_id_len,
+                                 "debuginfo", NULL, path);
+}
+
+
+/* See debuginfod.h  */
+int
+debuginfod_find_executable(debuginfod_client *client,
+			   const unsigned char *build_id, int build_id_len,
+                           char **path)
+{
+  return debuginfod_query_server(client, build_id, build_id_len,
+                                 "executable", NULL, path);
+}
+
+/* See debuginfod.h  */
+int debuginfod_find_source(debuginfod_client *client,
+			   const unsigned char *build_id, int build_id_len,
+                           const char *filename, char **path)
+{
+  return debuginfod_query_server(client, build_id, build_id_len,
+                                 "source", filename, path);
+}
+
+int
+debuginfod_find_section (debuginfod_client *client,
+			 const unsigned char *build_id, int build_id_len,
+			 const char *section, char **path)
+{
+  int rc = debuginfod_query_server(client, build_id, build_id_len,
+				   "section", section, path);
+  if (rc != -EINVAL)
+    return rc;
+
+  /* The servers may have lacked support for section queries.  Attempt to
+     download the debuginfo or executable containing the section in order
+     to extract it.  */
+  rc = -EEXIST;
+  int fd = -1;
+  char *tmp_path = NULL;
+
+  fd = debuginfod_find_debuginfo (client, build_id, build_id_len, &tmp_path);
+  if (client->progressfn_cancel)
+    {
+      if (fd >= 0)
+	{
+	  /* This shouldn't happen, but we'll check this condition
+	     just in case.  */
+	  close (fd);
+	  free (tmp_path);
+	}
+      return -ENOENT;
+    }
+  if (fd >= 0)
+    {
+      rc = extract_section (fd, section, tmp_path, path);
+      close (fd);
+    }
+
+  if (rc == -EEXIST)
+    {
+      /* Either the debuginfo couldn't be found or the section should
+	 be in the executable.  */
+      fd = debuginfod_find_executable (client, build_id,
+				       build_id_len, &tmp_path);
+      if (fd >= 0)
+	{
+	  rc = extract_section (fd, section, tmp_path, path);
+	  close (fd);
+	}
+      else
+	/* Update rc so that we return the most recent error code.  */
+	rc = fd;
+    }
+
+  free (tmp_path);
+  return rc;
+}
+
+/* Add an outgoing HTTP header.  */
+int debuginfod_add_http_header (debuginfod_client *client, const char* header)
+{
+  /* Sanity check header value is of the form Header: Value.
+     It should contain at least one colon that isn't the first or
+     last character.  */
+  char *colon = strchr (header, ':'); /* first colon */
+  if (colon == NULL /* present */
+      || colon == header /* not at beginning - i.e., have a header name */
+      || *(colon + 1) == '\0') /* not at end - i.e., have a value */
+    /* NB: but it's okay for a value to contain other colons! */
+    return -EINVAL;
+
+  struct curl_slist *temp = curl_slist_append (client->headers, header);
+  if (temp == NULL)
+    return -ENOMEM;
+
+  /* Track if User-Agent: is being set.  If so, signal not to add the
+     default one. */
+  if (startswith (header, "User-Agent:"))
+    client->user_agent_set_p = 1;
+
+  client->headers = temp;
+  return 0;
+}
+
+
+void
+debuginfod_set_progressfn(debuginfod_client *client,
+			  debuginfod_progressfn_t fn)
+{
+  client->progressfn = fn;
+}
+
+void
+debuginfod_set_verbose_fd(debuginfod_client *client, int fd)
+{
+  client->verbose_fd = fd;
+}
+
+#endif /* DUMMY_LIBDEBUGINFOD */
diff --git a/debuginfod/debuginfod-find.c b/debuginfod/debuginfod-find.c
new file mode 100644
index 0000000..3073109
--- /dev/null
+++ b/debuginfod/debuginfod-find.c
@@ -0,0 +1,258 @@
+/* Command-line frontend for retrieving ELF / DWARF / source files
+   from the debuginfod.
+   Copyright (C) 2019-2020 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#include "config.h"
+#include "printversion.h"
+#include "debuginfod.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <argp.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libdwelf.h>
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Short description of program.  */
+static const char doc[] = N_("Request debuginfo-related content "
+                             "from debuginfods listed in $" DEBUGINFOD_URLS_ENV_VAR ".");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("debuginfo BUILDID\n"
+                                  "debuginfo PATH\n"
+                                  "executable BUILDID\n"
+                                  "executable PATH\n"
+                                  "source BUILDID /FILENAME\n"
+                                  "source PATH /FILENAME\n"
+				  "section BUILDID SECTION-NAME\n"
+				  "section PATH SECTION-NAME\n");
+
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+  {
+   { "verbose", 'v', NULL, 0, "Increase verbosity.", 0 },
+   { NULL, 0, NULL, 0, NULL, 0 }
+  };
+
+/* debuginfod connection handle.  */
+static debuginfod_client *client;
+static int verbose;
+
+int progressfn(debuginfod_client *c __attribute__((__unused__)),
+	       long a, long b)
+{
+  static bool first = true;
+  static struct timespec last;
+  struct timespec now;
+  uint64_t delta;
+  if (!first)
+    {
+      clock_gettime (CLOCK_MONOTONIC, &now);
+      delta = ((now.tv_sec - last.tv_sec) * 1000000
+	       + (now.tv_nsec - last.tv_nsec) / 1000);
+    }
+  else
+    {
+      first = false;
+      delta = 250000;
+    }
+
+  /* Show progress the first time and then at most 5 times a second. */
+  if (delta > 200000)
+    {
+      fprintf (stderr, "Progress %ld / %ld\n", a, b);
+      clock_gettime (CLOCK_MONOTONIC, &last);
+    }
+  return 0;
+}
+
+
+static error_t parse_opt (int key, char *arg, struct argp_state *state)
+{
+  (void) arg;
+  (void) state;
+  switch (key)
+    {
+    case 'v': verbose++;
+      debuginfod_set_progressfn (client, & progressfn);
+      if (verbose > 1)
+        debuginfod_set_verbose_fd (client, STDERR_FILENO);
+      break;
+    default: return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+  {
+   options, parse_opt, args_doc, doc, NULL, NULL, NULL
+  };
+
+
+
+int
+main(int argc, char** argv)
+{
+  elf_version (EV_CURRENT);
+
+  client = debuginfod_begin ();
+  if (client == NULL)
+    {
+      fprintf(stderr, "Couldn't create debuginfod client context\n");
+      return 1;
+    }
+
+  /* Exercise user data pointer, to support testing only. */
+  debuginfod_set_user_data (client, (void *)"Progress");
+
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER|ARGP_NO_ARGS, &remaining, NULL);
+
+  if (argc < 2 || remaining+1 == argc) /* no arguments or at least two non-option words */
+    {
+      argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
+      return 1;
+    }
+
+  /* If we were passed an ELF file name in the BUILDID slot, look in there. */
+  unsigned char* build_id = (unsigned char*) argv[remaining+1];
+  int build_id_len = 0; /* assume text */
+
+  int any_non_hex = 0;
+  int i;
+  for (i = 0; build_id[i] != '\0'; i++)
+    if ((build_id[i] >= '0' && build_id[i] <= '9') ||
+        (build_id[i] >= 'a' && build_id[i] <= 'f'))
+      ;
+    else
+      any_non_hex = 1;
+
+  int fd = -1;
+  Elf* elf = NULL;
+  if (any_non_hex) /* raw build-id */
+    {
+      fd = open ((char*) build_id, O_RDONLY);
+      if (fd < 0)
+        fprintf (stderr, "Cannot open %s: %s\n", build_id, strerror(errno));
+    }
+  if (fd >= 0)
+    {
+      elf = dwelf_elf_begin (fd);
+      if (elf == NULL)
+        fprintf (stderr, "Cannot open as ELF file %s: %s\n", build_id,
+		 elf_errmsg (-1));
+    }
+  if (elf != NULL)
+    {
+      const void *extracted_build_id;
+      ssize_t s = dwelf_elf_gnu_build_id(elf, &extracted_build_id);
+      if (s > 0)
+        {
+          /* Success: replace the build_id pointer/len with the binary blob
+             that elfutils is keeping for us.  It'll remain valid until elf_end(). */
+          build_id = (unsigned char*) extracted_build_id;
+          build_id_len = s;
+        }
+      else
+        fprintf (stderr, "Cannot extract build-id from %s: %s\n", build_id, elf_errmsg(-1));
+    }
+
+  char *cache_name;
+  int rc = 0;
+
+  /* Check whether FILETYPE is valid and call the appropriate
+     debuginfod_find_* function. If FILETYPE is "source"
+     then ensure a FILENAME was also supplied as an argument.  */
+  if (strcmp(argv[remaining], "debuginfo") == 0)
+    rc = debuginfod_find_debuginfo(client,
+				   build_id, build_id_len,
+				   &cache_name);
+  else if (strcmp(argv[remaining], "executable") == 0)
+    rc = debuginfod_find_executable(client,
+                                    build_id, build_id_len,
+				    &cache_name);
+  else if (strcmp(argv[remaining], "source") == 0)
+    {
+      if (remaining+2 == argc || argv[remaining+2][0] != '/')
+        {
+          fprintf(stderr, "If FILETYPE is \"source\" then absolute /FILENAME must be given\n");
+          return 1;
+        }
+      rc = debuginfod_find_source(client,
+                                  build_id, build_id_len,
+				  argv[remaining+2], &cache_name);
+    }
+  else if (strcmp(argv[remaining], "section") == 0)
+    {
+      if (remaining+2 >= argc)
+	{
+	  fprintf(stderr,
+		  "If FILETYPE is \"section\" then a section name must be given\n");
+	  return 1;
+	}
+      rc = debuginfod_find_section(client, build_id, build_id_len,
+				   argv[remaining+2], &cache_name);
+    }
+  else
+    {
+      argp_help (&argp, stderr, ARGP_HELP_USAGE, argv[0]);
+      return 1;
+    }
+
+  if (verbose)
+    {
+      const char* headers = debuginfod_get_headers(client);
+      if (headers)
+        fprintf(stderr, "Headers:\n%s", headers);
+      const char* url = debuginfod_get_url (client);
+      if (url != NULL)
+        fprintf(stderr, "Downloaded from %s\n", url);
+    }
+
+  debuginfod_end (client);
+  if (elf)
+    elf_end(elf);
+  if (fd >= 0)
+    close (fd);
+
+  if (rc < 0)
+    {
+      fprintf(stderr, "Server query failed: %s\n", strerror(-rc));
+      return 1;
+    }
+  else
+    close (rc);
+
+  printf("%s\n", cache_name);
+  free (cache_name);
+
+  return 0;
+}
diff --git a/debuginfod/debuginfod.cxx b/debuginfod/debuginfod.cxx
new file mode 100644
index 0000000..560880f
--- /dev/null
+++ b/debuginfod/debuginfod.cxx
@@ -0,0 +1,4749 @@
+/* Debuginfo-over-http server.
+   Copyright (C) 2019-2024 Red Hat, Inc.
+   Copyright (C) 2021, 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+/* cargo-cult from libdwfl linux-kernel-modules.c */
+/* In case we have a bad fts we include this before config.h because it
+   can't handle _FILE_OFFSET_BITS.
+   Everything we need here is fine if its declarations just come first.
+   Also, include sys/types.h before fts. On some systems fts.h is not self
+   contained. */
+#ifdef BAD_FTS
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+  #include "config.h"
+#endif
+
+// #define _GNU_SOURCE
+#ifdef HAVE_SCHED_H
+extern "C" {
+#include <sched.h>
+}
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+extern "C" {
+#include <sys/resource.h>
+}
+#endif
+
+#ifdef HAVE_EXECINFO_H
+extern "C" {
+#include <execinfo.h>
+}
+#endif
+
+#include "debuginfod.h"
+#include <dwarf.h>
+
+#include <argp.h>
+#ifdef __GNUC__
+#undef __attribute__ /* glibc bug - rhbz 1763325 */
+#endif
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <pthread.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/vfs.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <math.h>
+#include <float.h>
+
+
+/* If fts.h is included before config.h, its indirect inclusions may not
+   give us the right LFS aliases of these functions, so map them manually.  */
+#ifdef BAD_FTS
+  #ifdef _FILE_OFFSET_BITS
+    #define open open64
+    #define fopen fopen64
+  #endif
+#else
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+#include <cstring>
+#include <vector>
+#include <set>
+#include <unordered_set>
+#include <map>
+#include <string>
+#include <iostream>
+#include <iomanip>
+#include <ostream>
+#include <sstream>
+#include <mutex>
+#include <deque>
+#include <condition_variable>
+#include <exception>
+#include <thread>
+// #include <regex> // on rhel7 gcc 4.8, not competent
+#include <regex.h>
+// #include <algorithm>
+using namespace std;
+
+#include <gelf.h>
+#include <libdwelf.h>
+
+#include <microhttpd.h>
+
+#if MHD_VERSION >= 0x00097002
+// libmicrohttpd 0.9.71 broke API
+#define MHD_RESULT enum MHD_Result
+#else
+#define MHD_RESULT int
+#endif
+
+#include <curl/curl.h>
+#include <archive.h>
+#include <archive_entry.h>
+#include <sqlite3.h>
+
+#ifdef __linux__
+#include <sys/syscall.h>
+#endif
+
+#ifdef __linux__
+#define tid() syscall(SYS_gettid)
+#else
+#define tid() pthread_self()
+#endif
+
+extern "C" {
+#include "printversion.h"
+#include "system.h"
+}
+
+
+inline bool
+string_endswith(const string& haystack, const string& needle)
+{
+  return (haystack.size() >= needle.size() &&
+	  equal(haystack.end()-needle.size(), haystack.end(),
+                needle.begin()));
+}
+
+
+// Roll this identifier for every sqlite schema incompatibility.
+#define BUILDIDS "buildids10"
+
+#if SQLITE_VERSION_NUMBER >= 3008000
+#define WITHOUT_ROWID "without rowid"
+#else
+#define WITHOUT_ROWID ""
+#endif
+
+static const char DEBUGINFOD_SQLITE_DDL[] =
+  "pragma foreign_keys = on;\n"
+  "pragma synchronous = 0;\n" // disable fsync()s - this cache is disposable across a machine crash
+  "pragma journal_mode = wal;\n" // https://sqlite.org/wal.html
+  "pragma wal_checkpoint = truncate;\n" // clean out any preexisting wal file
+  "pragma journal_size_limit = 0;\n" // limit steady state file (between grooming, which also =truncate's)
+  "pragma auto_vacuum = incremental;\n" // https://sqlite.org/pragma.html
+  "pragma busy_timeout = 1000;\n" // https://sqlite.org/pragma.html
+  // NB: all these are overridable with -D option
+
+  // Normalization table for interning file names
+  "create table if not exists " BUILDIDS "_fileparts (\n"
+  "        id integer primary key not null,\n"
+  "        name text unique not null\n"
+  "        );\n"
+  "create table if not exists " BUILDIDS "_files (\n"
+  "        id integer primary key not null,\n"
+  "        dirname integer not null,\n"
+  "        basename integer not null,\n"
+  "        unique (dirname, basename),\n"
+  "        foreign key (dirname) references " BUILDIDS "_fileparts(id) on delete cascade,\n"
+  "        foreign key (basename) references " BUILDIDS "_fileparts(id) on delete cascade\n"
+  "        );\n"
+  "create view if not exists " BUILDIDS "_files_v as\n" // a 
+  "        select f.id, n1.name || '/' || n2.name as name\n"
+  "        from " BUILDIDS "_files f, " BUILDIDS "_fileparts n1, " BUILDIDS "_fileparts n2\n"
+  "        where f.dirname = n1.id and f.basename = n2.id;\n"
+  
+  // Normalization table for interning buildids
+  "create table if not exists " BUILDIDS "_buildids (\n"
+  "        id integer primary key not null,\n"
+  "        hex text unique not null);\n"
+  // Track the completion of scanning of a given file & sourcetype at given time
+  "create table if not exists " BUILDIDS "_file_mtime_scanned (\n"
+  "        mtime integer not null,\n"
+  "        file integer not null,\n"
+  "        size integer not null,\n" // in bytes
+  "        sourcetype text(1) not null\n"
+  "            check (sourcetype IN ('F', 'R')),\n"
+  "        foreign key (file) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        primary key (file, mtime, sourcetype)\n"
+  "        ) " WITHOUT_ROWID ";\n"
+  "create table if not exists " BUILDIDS "_f_de (\n"
+  "        buildid integer not null,\n"
+  "        debuginfo_p integer not null,\n"
+  "        executable_p integer not null,\n"
+  "        file integer not null,\n"
+  "        mtime integer not null,\n"
+  "        foreign key (file) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (buildid) references " BUILDIDS "_buildids(id) on update cascade on delete cascade,\n"
+  "        primary key (buildid, file, mtime)\n"
+  "        ) " WITHOUT_ROWID ";\n"
+  // Index for faster delete by file identifier
+  "create index if not exists " BUILDIDS "_f_de_idx on " BUILDIDS "_f_de (file, mtime);\n"
+  "create table if not exists " BUILDIDS "_f_s (\n"
+  "        buildid integer not null,\n"
+  "        artifactsrc integer not null,\n"
+  "        file integer not null,\n" // NB: not necessarily entered into _mtime_scanned
+  "        mtime integer not null,\n"
+  "        foreign key (file) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (artifactsrc) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (buildid) references " BUILDIDS "_buildids(id) on update cascade on delete cascade,\n"
+  "        primary key (buildid, artifactsrc, file, mtime)\n"
+  "        ) " WITHOUT_ROWID ";\n"
+  "create table if not exists " BUILDIDS "_r_de (\n"
+  "        buildid integer not null,\n"
+  "        debuginfo_p integer not null,\n"
+  "        executable_p integer not null,\n"
+  "        file integer not null,\n"
+  "        mtime integer not null,\n"
+  "        content integer not null,\n"
+  "        foreign key (file) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (content) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (buildid) references " BUILDIDS "_buildids(id) on update cascade on delete cascade,\n"
+  "        primary key (buildid, debuginfo_p, executable_p, file, content, mtime)\n"
+  "        ) " WITHOUT_ROWID ";\n"
+  // Index for faster delete by archive file identifier
+  "create index if not exists " BUILDIDS "_r_de_idx on " BUILDIDS "_r_de (file, mtime);\n"
+  "create table if not exists " BUILDIDS "_r_sref (\n" // outgoing dwarf sourcefile references from rpm
+  "        buildid integer not null,\n"
+  "        artifactsrc integer not null,\n"
+  "        foreign key (artifactsrc) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (buildid) references " BUILDIDS "_buildids(id) on update cascade on delete cascade,\n"
+  "        primary key (buildid, artifactsrc)\n"
+  "        ) " WITHOUT_ROWID ";\n"
+  "create table if not exists " BUILDIDS "_r_sdef (\n" // rpm contents that may satisfy sref
+  "        file integer not null,\n"
+  "        mtime integer not null,\n"
+  "        content integer not null,\n"
+  "        foreign key (file) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        foreign key (content) references " BUILDIDS "_files(id) on update cascade on delete cascade,\n"
+  "        primary key (content, file, mtime)\n"
+  "        ) " WITHOUT_ROWID ";\n"
+  // create views to glue together some of the above tables, for webapi D queries
+  "create view if not exists " BUILDIDS "_query_d as \n"
+  "select\n"
+  "        b.hex as buildid, n.mtime, 'F' as sourcetype, f0.name as source0, n.mtime as mtime, null as source1\n"
+  "        from " BUILDIDS "_buildids b, " BUILDIDS "_files_v f0, " BUILDIDS "_f_de n\n"
+  "        where b.id = n.buildid and f0.id = n.file and n.debuginfo_p = 1\n"
+  "union all select\n"
+  "        b.hex as buildid, n.mtime, 'R' as sourcetype, f0.name as source0, n.mtime as mtime, f1.name as source1\n"
+  "        from " BUILDIDS "_buildids b, " BUILDIDS "_files_v f0, " BUILDIDS "_files_v f1, " BUILDIDS "_r_de n\n"
+  "        where b.id = n.buildid and f0.id = n.file and f1.id = n.content and n.debuginfo_p = 1\n"
+  ";"
+  // ... and for E queries
+  "create view if not exists " BUILDIDS "_query_e as \n"
+  "select\n"
+  "        b.hex as buildid, n.mtime, 'F' as sourcetype, f0.name as source0, n.mtime as mtime, null as source1\n"
+  "        from " BUILDIDS "_buildids b, " BUILDIDS "_files_v f0, " BUILDIDS "_f_de n\n"
+  "        where b.id = n.buildid and f0.id = n.file and n.executable_p = 1\n"
+  "union all select\n"
+  "        b.hex as buildid, n.mtime, 'R' as sourcetype, f0.name as source0, n.mtime as mtime, f1.name as source1\n"
+  "        from " BUILDIDS "_buildids b, " BUILDIDS "_files_v f0, " BUILDIDS "_files_v f1, " BUILDIDS "_r_de n\n"
+  "        where b.id = n.buildid and f0.id = n.file and f1.id = n.content and n.executable_p = 1\n"
+  ";"
+  // ... and for S queries
+  "create view if not exists " BUILDIDS "_query_s as \n"
+  "select\n"
+  "        b.hex as buildid, fs.name as artifactsrc, 'F' as sourcetype, f0.name as source0, n.mtime as mtime, null as source1, null as source0ref\n"
+  "        from " BUILDIDS "_buildids b, " BUILDIDS "_files_v f0, " BUILDIDS "_files_v fs, " BUILDIDS "_f_s n\n"
+  "        where b.id = n.buildid and f0.id = n.file and fs.id = n.artifactsrc\n"
+  "union all select\n"
+  "        b.hex as buildid, f1.name as artifactsrc, 'R' as sourcetype, f0.name as source0, sd.mtime as mtime, f1.name as source1, fsref.name as source0ref\n"
+  "        from " BUILDIDS "_buildids b, " BUILDIDS "_files_v f0, " BUILDIDS "_files_v f1, " BUILDIDS "_files_v fsref, "
+  "        " BUILDIDS "_r_sdef sd, " BUILDIDS "_r_sref sr, " BUILDIDS "_r_de sde\n"
+  "        where b.id = sr.buildid and f0.id = sd.file and fsref.id = sde.file and f1.id = sd.content\n"
+  "        and sr.artifactsrc = sd.content and sde.buildid = sr.buildid\n"
+  ";"
+  // and for startup overview counts
+  "drop view if exists " BUILDIDS "_stats;\n"
+  "create view if not exists " BUILDIDS "_stats as\n"
+  "          select 'file d/e' as label,count(*) as quantity from " BUILDIDS "_f_de\n"
+  "union all select 'file s',count(*) from " BUILDIDS "_f_s\n"
+  "union all select 'archive d/e',count(*) from " BUILDIDS "_r_de\n"
+  "union all select 'archive sref',count(*) from " BUILDIDS "_r_sref\n"
+  "union all select 'archive sdef',count(*) from " BUILDIDS "_r_sdef\n"
+  "union all select 'buildids',count(*) from " BUILDIDS "_buildids\n"
+  "union all select 'filenames',count(*) from " BUILDIDS "_files\n"
+  "union all select 'fileparts',count(*) from " BUILDIDS "_fileparts\n"  
+  "union all select 'files scanned (#)',count(*) from " BUILDIDS "_file_mtime_scanned\n"
+  "union all select 'files scanned (mb)',coalesce(sum(size)/1024/1024,0) from " BUILDIDS "_file_mtime_scanned\n"
+#if SQLITE_VERSION_NUMBER >= 3016000
+  "union all select 'index db size (mb)',page_count*page_size/1024/1024 as size FROM pragma_page_count(), pragma_page_size()\n"
+#endif
+  ";\n"
+
+// schema change history & garbage collection
+//
+// XXX: we could have migration queries here to bring prior-schema
+// data over instead of just dropping it.  But that could incur
+// doubled storage costs.
+//
+// buildids10: split the _files table into _parts
+  "" // <<< we are here
+// buildids9: widen the mtime_scanned table
+  "DROP VIEW IF EXISTS buildids9_stats;\n"
+  "DROP INDEX IF EXISTS buildids9_r_de_idx;\n"
+  "DROP INDEX IF EXISTS buildids9_f_de_idx;\n"
+  "DROP VIEW IF EXISTS buildids9_query_s;\n"
+  "DROP VIEW IF EXISTS buildids9_query_e;\n"
+  "DROP VIEW IF EXISTS buildids9_query_d;\n"
+  "DROP TABLE IF EXISTS buildids9_r_sdef;\n"
+  "DROP TABLE IF EXISTS buildids9_r_sref;\n"
+  "DROP TABLE IF EXISTS buildids9_r_de;\n"
+  "DROP TABLE IF EXISTS buildids9_f_s;\n"
+  "DROP TABLE IF EXISTS buildids9_f_de;\n"
+  "DROP TABLE IF EXISTS buildids9_file_mtime_scanned;\n"
+  "DROP TABLE IF EXISTS buildids9_buildids;\n"
+  "DROP TABLE IF EXISTS buildids9_files;\n"
+// buildids8: slim the sref table
+  "drop table if exists buildids8_f_de;\n"
+  "drop table if exists buildids8_f_s;\n"
+  "drop table if exists buildids8_r_de;\n"
+  "drop table if exists buildids8_r_sref;\n"
+  "drop table if exists buildids8_r_sdef;\n"
+  "drop table if exists buildids8_file_mtime_scanned;\n"
+  "drop table if exists buildids8_files;\n"
+  "drop table if exists buildids8_buildids;\n"
+// buildids7: separate _norm table into dense subtype tables
+  "drop table if exists buildids7_f_de;\n"
+  "drop table if exists buildids7_f_s;\n"
+  "drop table if exists buildids7_r_de;\n"
+  "drop table if exists buildids7_r_sref;\n"
+  "drop table if exists buildids7_r_sdef;\n"
+  "drop table if exists buildids7_file_mtime_scanned;\n"
+  "drop table if exists buildids7_files;\n"
+  "drop table if exists buildids7_buildids;\n"
+// buildids6: drop bolo/rfolo again, represent sources / rpmcontents in main table
+  "drop table if exists buildids6_norm;\n"
+  "drop table if exists buildids6_files;\n"
+  "drop table if exists buildids6_buildids;\n"
+  "drop view if exists buildids6;\n"
+// buildids5: redefine srcfile1 column to be '.'-less (for rpms)
+  "drop table if exists buildids5_norm;\n"
+  "drop table if exists buildids5_files;\n"
+  "drop table if exists buildids5_buildids;\n"
+  "drop table if exists buildids5_bolo;\n"
+  "drop table if exists buildids5_rfolo;\n"
+  "drop view if exists buildids5;\n"
+// buildids4: introduce rpmfile RFOLO
+  "drop table if exists buildids4_norm;\n"
+  "drop table if exists buildids4_files;\n"
+  "drop table if exists buildids4_buildids;\n"
+  "drop table if exists buildids4_bolo;\n"
+  "drop table if exists buildids4_rfolo;\n"
+  "drop view if exists buildids4;\n"
+// buildids3*: split out srcfile BOLO
+  "drop table if exists buildids3_norm;\n"
+  "drop table if exists buildids3_files;\n"
+  "drop table if exists buildids3_buildids;\n"
+  "drop table if exists buildids3_bolo;\n"
+  "drop view if exists buildids3;\n"
+// buildids2: normalized buildid and filenames into interning tables;
+  "drop table if exists buildids2_norm;\n"
+  "drop table if exists buildids2_files;\n"
+  "drop table if exists buildids2_buildids;\n"
+  "drop view if exists buildids2;\n"
+  // buildids1: made buildid and artifacttype NULLable, to represent cached-negative
+//           lookups from sources, e.g. files or rpms that contain no buildid-indexable content
+  "drop table if exists buildids1;\n"
+// buildids: original
+  "drop table if exists buildids;\n"
+  ;
+
+static const char DEBUGINFOD_SQLITE_CLEANUP_DDL[] =
+  "pragma wal_checkpoint = truncate;\n" // clean out any preexisting wal file
+  ;
+
+
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+  {
+   { NULL, 0, NULL, 0, "Scanners:", 1 },
+   { "scan-file-dir", 'F', NULL, 0, "Enable ELF/DWARF file scanning.", 0 },
+   { "scan-rpm-dir", 'R', NULL, 0, "Enable RPM scanning.", 0 },
+   { "scan-deb-dir", 'U', NULL, 0, "Enable DEB scanning.", 0 },
+   { "scan-archive", 'Z', "EXT=CMD", 0, "Enable arbitrary archive scanning.", 0 },
+   // "source-oci-imageregistry"  ...
+
+   { NULL, 0, NULL, 0, "Options:", 2 },
+   { "logical", 'L', NULL, 0, "Follow symlinks, default=ignore.", 0 },
+   { "rescan-time", 't', "SECONDS", 0, "Number of seconds to wait between rescans, 0=disable.", 0 },
+   { "groom-time", 'g', "SECONDS", 0, "Number of seconds to wait between database grooming, 0=disable.", 0 },
+   { "maxigroom", 'G', NULL, 0, "Run a complete database groom/shrink pass at startup.", 0 },
+   { "concurrency", 'c', "NUM", 0, "Limit scanning thread concurrency to NUM, default=#CPUs.", 0 },
+   { "connection-pool", 'C', "NUM", OPTION_ARG_OPTIONAL,
+     "Use webapi connection pool with NUM threads, default=unlim.", 0 },
+   { "include", 'I', "REGEX", 0, "Include files matching REGEX, default=all.", 0 },
+   { "exclude", 'X', "REGEX", 0, "Exclude files matching REGEX, default=none.", 0 },
+   { "port", 'p', "NUM", 0, "HTTP port to listen on, default 8002.", 0 },
+   { "database", 'd', "FILE", 0, "Path to sqlite database.", 0 },
+   { "ddl", 'D', "SQL", 0, "Apply extra sqlite ddl/pragma to connection.", 0 },
+   { "verbose", 'v', NULL, 0, "Increase verbosity.", 0 },
+   { "regex-groom", 'r', NULL, 0,"Uses regexes from -I and -X arguments to groom the database.",0},
+#define ARGP_KEY_FDCACHE_FDS 0x1001
+   { "fdcache-fds", ARGP_KEY_FDCACHE_FDS, "NUM", OPTION_HIDDEN, NULL, 0 },
+#define ARGP_KEY_FDCACHE_MBS 0x1002
+   { "fdcache-mbs", ARGP_KEY_FDCACHE_MBS, "MB", 0, "Maximum total size of archive file fdcache.", 0 },
+#define ARGP_KEY_FDCACHE_PREFETCH 0x1003
+   { "fdcache-prefetch", ARGP_KEY_FDCACHE_PREFETCH, "NUM", 0, "Number of archive files to prefetch into fdcache.", 0 },
+#define ARGP_KEY_FDCACHE_MINTMP 0x1004
+   { "fdcache-mintmp", ARGP_KEY_FDCACHE_MINTMP, "NUM", 0, "Minimum free space% on tmpdir.", 0 },
+#define ARGP_KEY_FDCACHE_PREFETCH_MBS 0x1005
+   { "fdcache-prefetch-mbs", ARGP_KEY_FDCACHE_PREFETCH_MBS, "MB", OPTION_HIDDEN, NULL, 0},
+#define ARGP_KEY_FDCACHE_PREFETCH_FDS 0x1006
+   { "fdcache-prefetch-fds", ARGP_KEY_FDCACHE_PREFETCH_FDS, "NUM", OPTION_HIDDEN, NULL, 0},
+#define ARGP_KEY_FORWARDED_TTL_LIMIT 0x1007
+   {"forwarded-ttl-limit", ARGP_KEY_FORWARDED_TTL_LIMIT, "NUM", 0, "Limit of X-Forwarded-For hops, default 8.", 0},
+#define ARGP_KEY_PASSIVE 0x1008
+   { "passive", ARGP_KEY_PASSIVE, NULL, 0, "Do not scan or groom, read-only database.", 0 },
+#define ARGP_KEY_DISABLE_SOURCE_SCAN 0x1009
+   { "disable-source-scan", ARGP_KEY_DISABLE_SOURCE_SCAN, NULL, 0, "Do not scan dwarf source info.", 0 },
+#define ARGP_SCAN_CHECKPOINT 0x100A
+   { "scan-checkpoint", ARGP_SCAN_CHECKPOINT, "NUM", 0, "Number of files scanned before a WAL checkpoint.", 0 },
+   { NULL, 0, NULL, 0, NULL, 0 },
+  };
+
+/* Short description of program.  */
+static const char doc[] = "Serve debuginfo-related content across HTTP from files under PATHs.";
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = "[PATH ...]";
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+static unsigned default_concurrency();
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+  {
+   options, parse_opt, args_doc, doc, NULL, NULL, NULL
+  };
+
+
+static string db_path;
+static sqlite3 *db;  // single connection, serialized across all our threads!
+static sqlite3 *dbq; // webapi query-servicing readonly connection, serialized ditto!
+static unsigned verbose;
+static volatile sig_atomic_t interrupted = 0;
+static volatile sig_atomic_t forced_rescan_count = 0;
+static volatile sig_atomic_t sigusr1 = 0;
+static volatile sig_atomic_t forced_groom_count = 0;
+static volatile sig_atomic_t sigusr2 = 0;
+static unsigned http_port = 8002;
+static unsigned rescan_s = 300;
+static unsigned groom_s = 86400;
+static bool maxigroom = false;
+static unsigned concurrency = default_concurrency();
+static int connection_pool = 0;
+static set<string> source_paths;
+static bool scan_files = false;
+static map<string,string> scan_archives;
+static vector<string> extra_ddl;
+static regex_t file_include_regex;
+static regex_t file_exclude_regex;
+static bool regex_groom = false;
+static bool traverse_logical;
+static long fdcache_mbs;
+static long fdcache_prefetch;
+static long fdcache_mintmp;
+static unsigned forwarded_ttl_limit = 8;
+static bool scan_source_info = true;
+static string tmpdir;
+static bool passive_p = false;
+static long scan_checkpoint = 256;
+
+static void set_metric(const string& key, double value);
+static void inc_metric(const string& key);
+static void add_metric(const string& metric,
+                       double value);
+static void set_metric(const string& metric,
+                       const string& lname, const string& lvalue,
+                       double value);
+static void inc_metric(const string& metric,
+                       const string& lname, const string& lvalue);
+static void add_metric(const string& metric,
+                       const string& lname, const string& lvalue,
+                       double value);
+static void inc_metric(const string& metric,
+                       const string& lname, const string& lvalue,
+                       const string& rname, const string& rvalue);
+static void add_metric(const string& metric,
+                       const string& lname, const string& lvalue,
+                       const string& rname, const string& rvalue,                       
+                       double value);
+
+
+class tmp_inc_metric { // a RAII style wrapper for exception-safe scoped increment & decrement
+  string m, n, v;
+public:
+  tmp_inc_metric(const string& mname, const string& lname, const string& lvalue):
+    m(mname), n(lname), v(lvalue)
+  {
+    add_metric (m, n, v, 1);
+  }
+  ~tmp_inc_metric()
+  {
+    add_metric (m, n, v, -1);
+  }
+};
+
+class tmp_ms_metric { // a RAII style wrapper for exception-safe scoped timing
+  string m, n, v;
+  struct timespec ts_start;
+public:
+  tmp_ms_metric(const string& mname, const string& lname, const string& lvalue):
+    m(mname), n(lname), v(lvalue)
+  {
+    clock_gettime (CLOCK_MONOTONIC, & ts_start);
+  }
+  ~tmp_ms_metric()
+  {
+    struct timespec ts_end;
+    clock_gettime (CLOCK_MONOTONIC, & ts_end);
+    double deltas = (ts_end.tv_sec - ts_start.tv_sec)
+      + (ts_end.tv_nsec - ts_start.tv_nsec)/1.e9;
+
+    add_metric (m + "_milliseconds_sum", n, v, (deltas*1000.0));
+    inc_metric (m + "_milliseconds_count", n, v);
+  }
+};
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  int rc;
+  switch (key)
+    {
+    case 'v': verbose ++; break;
+    case 'd':
+      /* When using the in-memory database make sure it is shareable,
+	 so we can open it twice as read/write and read-only.  */
+      if (strcmp (arg, ":memory:") == 0)
+	db_path = "file::memory:?cache=shared";
+      else
+	db_path = string(arg);
+      break;
+    case 'p': http_port = (unsigned) atoi(arg);
+      if (http_port == 0 || http_port > 65535)
+        argp_failure(state, 1, EINVAL, "port number");
+      break;
+    case 'F': scan_files = true; break;
+    case 'R':
+      scan_archives[".rpm"]="cat"; // libarchive groks rpm natively
+      break;
+    case 'U':
+      scan_archives[".deb"]="(bsdtar -O -x -f - data.tar\\*)<";
+      scan_archives[".ddeb"]="(bsdtar -O -x -f - data.tar\\*)<";
+      scan_archives[".ipk"]="(bsdtar -O -x -f - data.tar\\*)<";
+      // .udeb too?
+      break;
+    case 'Z':
+      {
+        char* extension = strchr(arg, '=');
+        if (arg[0] == '\0')
+          argp_failure(state, 1, EINVAL, "missing EXT");
+        else if (extension)
+          scan_archives[string(arg, (extension-arg))]=string(extension+1);
+        else
+          scan_archives[string(arg)]=string("cat");
+      }
+      break;
+    case 'L':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-L option inconsistent with passive mode");
+      traverse_logical = true;
+      break;
+    case 'D':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-D option inconsistent with passive mode");
+      extra_ddl.push_back(string(arg));
+      break;
+    case 't':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-t option inconsistent with passive mode");
+      rescan_s = (unsigned) atoi(arg);
+      break;
+    case 'g':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-g option inconsistent with passive mode");
+      groom_s = (unsigned) atoi(arg);
+      break;
+    case 'G':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-G option inconsistent with passive mode");
+      maxigroom = true;
+      break;
+    case 'c':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-c option inconsistent with passive mode");
+      concurrency = (unsigned) atoi(arg);
+      if (concurrency < 1) concurrency = 1;
+      break;
+    case 'C':
+      if (arg)
+        {
+          connection_pool = atoi(arg);
+          if (connection_pool < 2)
+            argp_failure(state, 1, EINVAL, "-C NUM minimum 2");
+        }
+      break;
+    case 'I':
+      // NB: no problem with unconditional free here - an earlier failed regcomp would exit program
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-I option inconsistent with passive mode");
+      regfree (&file_include_regex);
+      rc = regcomp (&file_include_regex, arg, REG_EXTENDED|REG_NOSUB);
+      if (rc != 0)
+        argp_failure(state, 1, EINVAL, "regular expression");
+      break;
+    case 'X':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-X option inconsistent with passive mode");
+      regfree (&file_exclude_regex);
+      rc = regcomp (&file_exclude_regex, arg, REG_EXTENDED|REG_NOSUB);
+      if (rc != 0)
+        argp_failure(state, 1, EINVAL, "regular expression");
+      break;
+    case 'r':
+      if (passive_p)
+        argp_failure(state, 1, EINVAL, "-r option inconsistent with passive mode");
+      regex_groom = true;
+      break;
+    case ARGP_KEY_FDCACHE_FDS:
+      // deprecated
+      break;
+    case ARGP_KEY_FDCACHE_MBS:
+      fdcache_mbs = atol (arg);
+      break;
+    case ARGP_KEY_FDCACHE_PREFETCH:
+      fdcache_prefetch = atol (arg);
+      break;
+    case ARGP_KEY_FDCACHE_MINTMP:
+      fdcache_mintmp = atol (arg);
+      if( fdcache_mintmp > 100 || fdcache_mintmp < 0 )
+        argp_failure(state, 1, EINVAL, "fdcache mintmp percent");
+      break;
+    case ARGP_KEY_FORWARDED_TTL_LIMIT:
+      forwarded_ttl_limit = (unsigned) atoi(arg);
+      break;
+    case ARGP_KEY_ARG:
+      source_paths.insert(string(arg));
+      break;
+    case ARGP_KEY_FDCACHE_PREFETCH_FDS:
+      // deprecated
+      break;
+    case ARGP_KEY_FDCACHE_PREFETCH_MBS:
+      // deprecated
+      break;
+    case ARGP_KEY_PASSIVE:
+      passive_p = true;
+      if (source_paths.size() > 0
+          || maxigroom
+          || extra_ddl.size() > 0
+          || traverse_logical)
+        // other conflicting options tricky to check
+        argp_failure(state, 1, EINVAL, "inconsistent options with passive mode");
+      break;
+    case ARGP_KEY_DISABLE_SOURCE_SCAN:
+      scan_source_info = false;
+      break;
+    case ARGP_SCAN_CHECKPOINT:
+      scan_checkpoint = atol (arg);
+      if (scan_checkpoint < 0)
+        argp_failure(state, 1, EINVAL, "scan checkpoint");        
+      break;
+      // case 'h': argp_state_help (state, stderr, ARGP_HELP_LONG|ARGP_HELP_EXIT_OK);
+    default: return ARGP_ERR_UNKNOWN;
+    }
+
+  return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+static void add_mhd_response_header (struct MHD_Response *r,
+				     const char *h, const char *v);
+
+// represent errors that may get reported to an ostream and/or a libmicrohttpd connection
+
+struct reportable_exception
+{
+  int code;
+  string message;
+
+  reportable_exception(int c, const string& m): code(c), message(m) {}
+  reportable_exception(const string& m): code(503), message(m) {}
+  reportable_exception(): code(503), message() {}
+
+  void report(ostream& o) const; // defined under obatched() class below
+
+  MHD_RESULT mhd_send_response(MHD_Connection* c) const {
+    MHD_Response* r = MHD_create_response_from_buffer (message.size(),
+                                                       (void*) message.c_str(),
+                                                       MHD_RESPMEM_MUST_COPY);
+    add_mhd_response_header (r, "Content-Type", "text/plain");
+    MHD_RESULT rc = MHD_queue_response (c, code, r);
+    MHD_destroy_response (r);
+    return rc;
+  }
+};
+
+
+struct sqlite_exception: public reportable_exception
+{
+  sqlite_exception(int rc, const string& msg):
+    reportable_exception(string("sqlite3 error: ") + msg + ": " + string(sqlite3_errstr(rc) ?: "?")) {
+    inc_metric("error_count","sqlite3",sqlite3_errstr(rc));
+  }
+};
+
+struct libc_exception: public reportable_exception
+{
+  libc_exception(int rc, const string& msg):
+    reportable_exception(string("libc error: ") + msg + ": " + string(strerror(rc) ?: "?")) {
+    inc_metric("error_count","libc",strerror(rc));
+  }
+};
+
+
+struct archive_exception: public reportable_exception
+{
+  archive_exception(const string& msg):
+    reportable_exception(string("libarchive error: ") + msg) {
+      inc_metric("error_count","libarchive",msg);
+  }
+  archive_exception(struct archive* a, const string& msg):
+    reportable_exception(string("libarchive error: ") + msg + ": " + string(archive_error_string(a) ?: "?")) {
+    inc_metric("error_count","libarchive",msg + ": " + string(archive_error_string(a) ?: "?"));
+  }
+};
+
+
+struct elfutils_exception: public reportable_exception
+{
+  elfutils_exception(int rc, const string& msg):
+    reportable_exception(string("elfutils error: ") + msg + ": " + string(elf_errmsg(rc) ?: "?")) {
+    inc_metric("error_count","elfutils",elf_errmsg(rc));
+  }
+};
+
+
+////////////////////////////////////////////////////////////////////////
+
+template <typename Payload>
+class workq
+{
+  unordered_set<Payload> q; // eliminate duplicates
+  mutex mtx;
+  condition_variable cv;
+  bool dead;
+  unsigned idlers;   // number of threads busy with wait_idle / done_idle
+  unsigned fronters; // number of threads busy with wait_front / done_front
+
+public:
+  workq() { dead = false; idlers = 0; fronters = 0; }
+  ~workq() {}
+
+  void push_back(const Payload& p)
+  {
+    unique_lock<mutex> lock(mtx);
+    q.insert (p);
+    set_metric("thread_work_pending","role","scan", q.size());
+    cv.notify_all();
+  }
+
+  // kill this workqueue, wake up all idlers / scanners
+  void nuke() {
+    unique_lock<mutex> lock(mtx);
+    // optional: q.clear();
+    dead = true;
+    cv.notify_all();
+  }
+
+  // clear the workqueue, when scanning is interrupted with USR2
+  void clear() {
+    unique_lock<mutex> lock(mtx);
+    q.clear();
+    set_metric("thread_work_pending","role","scan", q.size());
+    // NB: there may still be some live fronters
+    cv.notify_all(); // maybe wake up waiting idlers
+  }
+
+  // block this scanner thread until there is work to do and no active idler
+  bool wait_front (Payload& p)
+  {
+    unique_lock<mutex> lock(mtx);
+    while (!dead && (q.size() == 0 || idlers > 0))
+      cv.wait(lock);
+    if (dead)
+      return false;
+    else
+      {
+        p = * q.begin();
+        q.erase (q.begin());
+        fronters ++; // prevent idlers from starting awhile, even if empty q
+        set_metric("thread_work_pending","role","scan", q.size());
+        // NB: don't wake up idlers yet!  The consumer is busy
+        // processing this element until it calls done_front().
+        return true;
+      }
+  }
+
+  // notify waitq that scanner thread is done with that last item
+  void done_front ()
+  {
+    unique_lock<mutex> lock(mtx);
+    fronters --;
+    if (q.size() == 0 && fronters == 0)
+      cv.notify_all(); // maybe wake up waiting idlers
+  }
+  
+  // block this idler thread until there is no work to do
+  void wait_idle ()
+  {
+    unique_lock<mutex> lock(mtx);
+    cv.notify_all(); // maybe wake up waiting scanners
+    while (!dead && ((q.size() != 0) || fronters > 0))
+      cv.wait(lock);
+    idlers ++;
+  }
+
+  void done_idle ()
+  {
+    unique_lock<mutex> lock(mtx);
+    idlers --;
+    cv.notify_all(); // maybe wake up waiting scanners, but probably not (shutting down)
+  }
+};
+
+typedef struct stat stat_t;
+typedef pair<string,stat_t> scan_payload;
+inline bool operator< (const scan_payload& a, const scan_payload& b)
+{
+  return a.first < b.first; // don't bother compare the stat fields
+}
+
+namespace std { // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
+  template<> struct hash<::scan_payload>
+  {
+    std::size_t operator() (const ::scan_payload& p) const noexcept
+    {
+      return hash<string>()(p.first);
+    }
+  };
+  template<> struct equal_to<::scan_payload>
+  {
+    std::size_t operator() (const ::scan_payload& a, const ::scan_payload& b) const noexcept
+    {
+      return a.first == b.first;
+    }
+  };
+}
+
+static workq<scan_payload> scanq; // just a single one
+// producer & idler: thread_main_fts_source_paths()
+// consumer: thread_main_scanner()
+// idler: thread_main_groom()
+
+
+////////////////////////////////////////////////////////////////////////
+
+// Unique set is a thread-safe structure that lends 'ownership' of a value
+// to a thread.  Other threads requesting the same thing are made to wait.
+// It's like a semaphore-on-demand.
+template <typename T>
+class unique_set
+{
+private:
+  set<T> values;
+  mutex mtx;
+  condition_variable cv;
+public:
+  unique_set() {}
+  ~unique_set() {}
+
+  void acquire(const T& value)
+  {
+    unique_lock<mutex> lock(mtx);
+    while (values.find(value) != values.end())
+      cv.wait(lock);
+    values.insert(value);
+  }
+
+  void release(const T& value)
+  {
+    unique_lock<mutex> lock(mtx);
+    // assert (values.find(value) != values.end());
+    values.erase(value);
+    cv.notify_all();
+  }
+};
+
+
+// This is the object that's instantiate to uniquely hold a value in a
+// RAII-pattern way.
+template <typename T>
+class unique_set_reserver
+{
+private:
+  unique_set<T>& please_hold;
+  T mine;
+public:
+  unique_set_reserver(unique_set<T>& t, const T& value):
+    please_hold(t), mine(value)  { please_hold.acquire(mine); }
+  ~unique_set_reserver() { please_hold.release(mine); }
+};
+
+
+////////////////////////////////////////////////////////////////////////
+
+// periodic_barrier is a concurrency control object that lets N threads
+// periodically (based on counter value) agree to wait at a barrier,
+// let one of them carry out some work, then be set free
+
+class periodic_barrier
+{
+private:
+  unsigned period; // number of count() reports to trigger barrier activation
+  unsigned threads; // number of threads participating
+  mutex mtx; // protects all the following fields
+  unsigned counter; // count of count() reports in the current generation
+  unsigned generation; // barrier activation generation
+  unsigned waiting; // number of threads waiting for barrier
+  bool dead; // bring out your
+  condition_variable cv;
+public:
+  periodic_barrier(unsigned t, unsigned p):
+    period(p), threads(t), counter(0), generation(0), waiting(0), dead(false) { }
+  virtual ~periodic_barrier() {}
+
+  virtual void periodic_barrier_work() noexcept = 0;
+  void nuke() {
+    unique_lock<mutex> lock(mtx);
+    dead = true;
+    cv.notify_all();
+  }
+  
+  void count()
+  {
+    unique_lock<mutex> lock(mtx);
+    unsigned prev_generation = this->generation;
+    if (counter < period-1) // normal case: counter just freely running
+      {
+        counter ++;
+        return;
+      }
+    else if (counter == period-1) // we're the doer
+      {
+        counter = period; // entering barrier holding phase
+        cv.notify_all();
+        while (waiting < threads-1 && !dead)
+          cv.wait(lock);
+        // all other threads are now stuck in the barrier
+        this->periodic_barrier_work(); // NB: we're holding the mutex the whole time
+        // reset for next barrier, releasing other waiters
+        counter = 0;
+        generation ++;
+        cv.notify_all();
+        return;
+      }
+    else if (counter == period) // we're a waiter, in holding phase
+      {
+        waiting ++;
+        cv.notify_all();
+        while (counter == period && generation == prev_generation && !dead)
+          cv.wait(lock);
+        waiting --;
+        return;
+      }
+  }
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+// Print a standard timestamp.
+static ostream&
+timestamp (ostream &o)
+{
+  char datebuf[80];
+  char *now2 = NULL;
+  time_t now_t = time(NULL);
+  struct tm now;
+  struct tm *nowp = gmtime_r (&now_t, &now);
+  if (nowp)
+    {
+      (void) strftime (datebuf, sizeof (datebuf), "%c", nowp);
+      now2 = datebuf;
+    }
+
+  return o << "[" << (now2 ? now2 : "") << "] "
+           << "(" << getpid () << "/" << tid() << "): ";
+}
+
+
+// A little class that impersonates an ostream to the extent that it can
+// take << streaming operations.  It batches up the bits into an internal
+// stringstream until it is destroyed; then flushes to the original ostream.
+// It adds a timestamp
+class obatched
+{
+private:
+  ostream& o;
+  stringstream stro;
+  static mutex lock;
+public:
+  obatched(ostream& oo, bool timestamp_p = true): o(oo)
+  {
+    if (timestamp_p)
+      timestamp(stro);
+  }
+  ~obatched()
+  {
+    unique_lock<mutex> do_not_cross_the_streams(obatched::lock);
+    o << stro.str();
+    o.flush();
+  }
+  operator ostream& () { return stro; }
+  template <typename T> ostream& operator << (const T& t) { stro << t; return stro; }
+};
+mutex obatched::lock; // just the one, since cout/cerr iostreams are not thread-safe
+
+
+void reportable_exception::report(ostream& o) const {
+  obatched(o) << message << endl;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+// RAII style sqlite prepared-statement holder that matches { } block lifetime
+
+struct sqlite_ps
+{
+private:
+  sqlite3* db;
+  const string nickname;
+  const string sql;
+  sqlite3_stmt *pp;
+
+  sqlite_ps(const sqlite_ps&); // make uncopyable
+  sqlite_ps& operator=(const sqlite_ps &); // make unassignable
+
+public:
+  sqlite_ps (sqlite3* d, const string& n, const string& s): db(d), nickname(n), sql(s) {
+    // tmp_ms_metric tick("sqlite3","prep",nickname);
+    if (verbose > 4)
+      obatched(clog) << nickname << " prep " << sql << endl;
+    int rc = sqlite3_prepare_v2 (db, sql.c_str(), -1 /* to \0 */, & this->pp, NULL);
+    if (rc != SQLITE_OK)
+      throw sqlite_exception(rc, "prepare " + sql);
+  }
+
+  sqlite_ps& reset()
+  {
+    tmp_ms_metric tick("sqlite3","reset",nickname);
+    sqlite3_reset(this->pp);
+    return *this;
+  }
+
+  sqlite_ps& bind(int parameter, const string& str)
+  {
+    if (verbose > 4)
+      obatched(clog) << nickname << " bind " << parameter << "=" << str << endl;
+    int rc = sqlite3_bind_text (this->pp, parameter, str.c_str(), -1, SQLITE_TRANSIENT);
+    if (rc != SQLITE_OK)
+      throw sqlite_exception(rc, "sqlite3 bind");
+    return *this;
+  }
+
+  sqlite_ps& bind(int parameter, int64_t value)
+  {
+    if (verbose > 4)
+      obatched(clog) << nickname << " bind " << parameter << "=" << value << endl;
+    int rc = sqlite3_bind_int64 (this->pp, parameter, value);
+    if (rc != SQLITE_OK)
+      throw sqlite_exception(rc, "sqlite3 bind");
+    return *this;
+  }
+
+  sqlite_ps& bind(int parameter)
+  {
+    if (verbose > 4)
+      obatched(clog) << nickname << " bind " << parameter << "=" << "NULL" << endl;
+    int rc = sqlite3_bind_null (this->pp, parameter);
+    if (rc != SQLITE_OK)
+      throw sqlite_exception(rc, "sqlite3 bind");
+    return *this;
+  }
+
+
+  void step_ok_done() {
+    tmp_ms_metric tick("sqlite3","step_done",nickname);
+    int rc = sqlite3_step (this->pp);
+    if (verbose > 4)
+      obatched(clog) << nickname << " step-ok-done(" << sqlite3_errstr(rc) << ") " << sql << endl;
+    if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW)
+      throw sqlite_exception(rc, "sqlite3 step");
+    (void) sqlite3_reset (this->pp);
+  }
+
+
+  int step() {
+    tmp_ms_metric tick("sqlite3","step",nickname);
+    int rc = sqlite3_step (this->pp);
+    if (verbose > 4)
+      obatched(clog) << nickname << " step(" << sqlite3_errstr(rc) << ") " << sql << endl;
+    return rc;
+  }
+
+  ~sqlite_ps () { sqlite3_finalize (this->pp); }
+  operator sqlite3_stmt* () { return this->pp; }
+};
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+struct sqlite_checkpoint_pb: public periodic_barrier
+{
+  // NB: don't use sqlite_ps since it can throw exceptions during ctor etc.
+  sqlite_checkpoint_pb(unsigned t, unsigned p):
+    periodic_barrier(t, p) { }
+  
+  void periodic_barrier_work() noexcept
+  {
+    (void) sqlite3_exec (db, "pragma wal_checkpoint(truncate);", NULL, NULL, NULL);
+  }
+};
+  
+static periodic_barrier* scan_barrier = 0; // initialized in main()
+
+
+////////////////////////////////////////////////////////////////////////
+
+// RAII style templated autocloser
+
+template <class Payload, class Ignore>
+struct defer_dtor
+{
+public:
+  typedef Ignore (*dtor_fn) (Payload);
+
+private:
+  Payload p;
+  dtor_fn fn;
+
+public:
+  defer_dtor(Payload _p, dtor_fn _fn): p(_p), fn(_fn) {}
+  ~defer_dtor() { (void) (*fn)(p); }
+
+private:
+  defer_dtor(const defer_dtor<Payload,Ignore>&); // make uncopyable
+  defer_dtor& operator=(const defer_dtor<Payload,Ignore> &); // make unassignable
+};
+
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+static string
+header_censor(const string& str)
+{
+  string y;
+  for (auto&& x : str)
+    {
+      if (isalnum(x) || x == '/' || x == '.' || x == ',' || x == '_' || x == ':')
+        y += x;
+    }
+  return y;
+}
+
+
+static string
+conninfo (struct MHD_Connection * conn)
+{
+  char hostname[256]; // RFC1035
+  char servname[256];
+  int sts = -1;
+
+  if (conn == 0)
+    return "internal";
+
+  /* Look up client address data. */
+  const union MHD_ConnectionInfo *u = MHD_get_connection_info (conn,
+                                                               MHD_CONNECTION_INFO_CLIENT_ADDRESS);
+  struct sockaddr *so = u ? u->client_addr : 0;
+
+  if (so && so->sa_family == AF_INET) {
+    sts = getnameinfo (so, sizeof (struct sockaddr_in),
+                       hostname, sizeof (hostname),
+                       servname, sizeof (servname),
+                       NI_NUMERICHOST | NI_NUMERICSERV);
+  } else if (so && so->sa_family == AF_INET6) {
+    struct sockaddr_in6* addr6 = (struct sockaddr_in6*) so;
+    if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+      struct sockaddr_in addr4;
+      memset (&addr4, 0, sizeof(addr4));
+      addr4.sin_family = AF_INET;
+      addr4.sin_port = addr6->sin6_port;
+      memcpy (&addr4.sin_addr.s_addr, addr6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
+      sts = getnameinfo ((struct sockaddr*) &addr4, sizeof (addr4),
+                         hostname, sizeof (hostname),
+                         servname, sizeof (servname),
+                         NI_NUMERICHOST | NI_NUMERICSERV);
+    } else {
+      sts = getnameinfo (so, sizeof (struct sockaddr_in6),
+                         hostname, sizeof (hostname),
+                         servname, sizeof (servname),
+                         NI_NUMERICHOST | NI_NUMERICSERV);
+    }
+  }
+  
+  if (sts != 0) {
+    hostname[0] = servname[0] = '\0';
+  }
+
+  // extract headers relevant to administration
+  const char* user_agent = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, "User-Agent") ?: "";
+  const char* x_forwarded_for = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, "X-Forwarded-For") ?: "";
+  // NB: these are untrustworthy, beware if machine-processing log files
+
+  return string(hostname) + string(":") + string(servname) +
+    string(" UA:") + header_censor(string(user_agent)) +
+    string(" XFF:") + header_censor(string(x_forwarded_for));
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+
+/* Wrapper for MHD_add_response_header that logs an error if we
+   couldn't add the specified header.  */
+static void
+add_mhd_response_header (struct MHD_Response *r,
+			 const char *h, const char *v)
+{
+  if (MHD_add_response_header (r, h, v) == MHD_NO)
+    obatched(clog) << "Error: couldn't add '" << h << "' header" << endl;
+}
+
+static void
+add_mhd_last_modified (struct MHD_Response *resp, time_t mtime)
+{
+  struct tm now;
+  struct tm *nowp = gmtime_r (&mtime, &now);
+  if (nowp != NULL)
+    {
+      char datebuf[80];
+      size_t rc = strftime (datebuf, sizeof (datebuf), "%a, %d %b %Y %T GMT",
+                            nowp);
+      if (rc > 0 && rc < sizeof (datebuf))
+        add_mhd_response_header (resp, "Last-Modified", datebuf);
+    }
+
+  add_mhd_response_header (resp, "Cache-Control", "public");
+}
+
+// quote all questionable characters of str for safe passage through a sh -c expansion.
+static string
+shell_escape(const string& str)
+{
+  string y;
+  for (auto&& x : str)
+    {
+      if (! isalnum(x) && x != '/')
+        y += "\\";
+      y += x;
+    }
+  return y;
+}
+
+
+// PR25548: Perform POSIX / RFC3986 style path canonicalization on the input string.
+//
+// Namely:
+//    //         ->   /
+//    /foo/../   ->   /
+//    /./        ->   /
+//
+// This mapping is done on dwarf-side source path names, which may
+// include these constructs, so we can deal with debuginfod clients
+// that accidentally canonicalize the paths.
+//
+// realpath(3) is close but not quite right, because it also resolves
+// symbolic links.  Symlinks at the debuginfod server have nothing to
+// do with the build-time symlinks, thus they must not be considered.
+//
+// see also curl Curl_dedotdotify() aka RFC3986, which we mostly follow here
+// see also libc __realpath()
+// see also llvm llvm::sys::path::remove_dots()
+static string
+canon_pathname (const string& input)
+{
+  string i = input; // 5.2.4 (1)
+  string o;
+
+  while (i.size() != 0)
+    {
+      // 5.2.4 (2) A
+      if (i.substr(0,3) == "../")
+        i = i.substr(3);
+      else if(i.substr(0,2) == "./")
+        i = i.substr(2);
+
+      // 5.2.4 (2) B
+      else if (i.substr(0,3) == "/./")
+        i = i.substr(2);
+      else if (i == "/.")
+        i = ""; // no need to handle "/." complete-path-segment case; we're dealing with file names
+
+      // 5.2.4 (2) C
+      else if (i.substr(0,4) == "/../") {
+        i = i.substr(3);
+        string::size_type sl = o.rfind("/");
+        if (sl != string::npos)
+          o = o.substr(0, sl);
+        else
+          o = "";
+      } else if (i == "/..")
+        i = ""; // no need to handle "/.." complete-path-segment case; we're dealing with file names
+
+      // 5.2.4 (2) D
+      // no need to handle these cases; we're dealing with file names
+      else if (i == ".")
+        i = "";
+      else if (i == "..")
+        i = "";
+
+      // POSIX special: map // to /
+      else if (i.substr(0,2) == "//")
+        i = i.substr(1);
+
+      // 5.2.4 (2) E
+      else {
+        string::size_type next_slash = i.find("/", (i[0]=='/' ? 1 : 0)); // skip first slash
+        o += i.substr(0, next_slash);
+        if (next_slash == string::npos)
+          i = "";
+        else
+          i = i.substr(next_slash);
+      }
+    }
+
+  return o;
+}
+
+
+// Estimate available free space for a given filesystem via statfs(2).
+// Return true if the free fraction is known to be smaller than the
+// given minimum percentage.  Also update a related metric.
+bool statfs_free_enough_p(const string& path, const string& label, long minfree = 0)
+{
+  struct statfs sfs;
+  int rc = statfs(path.c_str(), &sfs);
+  if (rc == 0)
+    {
+      double s = (double) sfs.f_bavail / (double) sfs.f_blocks;
+      set_metric("filesys_free_ratio","purpose",label, s);
+      return ((s * 100.0) < minfree);
+    }
+  return false;
+}
+
+
+
+// A map-like class that owns a cache of file descriptors (indexed by
+// file / content names).
+//
+// If only it could use fd's instead of file names ... but we can't
+// dup(2) to create independent descriptors for the same unlinked
+// files, so would have to use some goofy linux /proc/self/fd/%d
+// hack such as the following
+
+#if 0
+int superdup(int fd)
+{
+#ifdef __linux__
+  char *fdpath = NULL;
+  int rc = asprintf(& fdpath, "/proc/self/fd/%d", fd);
+  int newfd;
+  if (rc >= 0)
+    newfd = open(fdpath, O_RDONLY);
+  else
+    newfd = -1;
+  free (fdpath);
+  return newfd;
+#else
+  return -1;
+#endif
+}
+#endif
+
+class libarchive_fdcache
+{
+private:
+  mutex fdcache_lock;
+
+  typedef pair<string,string> key; // archive, entry
+  struct fdcache_entry
+  {
+    string fd; // file name (probably in $TMPDIR), not an actual open fd (EMFILE)
+    double fd_size_mb; // slightly rounded up megabytes
+    time_t freshness; // when was this entry created or requested last
+    unsigned request_count; // how many requests were made; or 0=prefetch only
+    double latency; // how many seconds it took to extract the file
+  };
+
+  map<key,fdcache_entry> entries; // optimized for lookup
+  time_t last_cleaning;
+  long max_fds;
+  long max_mbs;
+
+public:
+  void set_metrics()
+  {
+    double fdcache_mb = 0.0;
+    double prefetch_mb = 0.0;
+    unsigned fdcache_count = 0;
+    unsigned prefetch_count = 0;
+    for (auto &i : entries) {
+      if (i.second.request_count) {
+        fdcache_mb += i.second.fd_size_mb;
+        fdcache_count ++;
+      } else {
+        prefetch_mb += i.second.fd_size_mb;
+        prefetch_count ++;
+      }
+    }
+    set_metric("fdcache_bytes", fdcache_mb*1024.0*1024.0);
+    set_metric("fdcache_count", fdcache_count);
+    set_metric("fdcache_prefetch_bytes", prefetch_mb*1024.0*1024.0);
+    set_metric("fdcache_prefetch_count", prefetch_count);
+  }
+
+  void intern(const string& a, const string& b, string fd, off_t sz,
+              bool requested_p, double lat)
+  {
+    {
+      unique_lock<mutex> lock(fdcache_lock);
+      time_t now = time(NULL);
+      // there is a chance it's already in here, just wasn't found last time
+      // if so, there's nothing to do but count our luck
+      auto i = entries.find(make_pair(a,b));
+      if (i != entries.end())
+        {
+          inc_metric("fdcache_op_count","op","redundant_intern");
+          if (requested_p) i->second.request_count ++; // repeat prefetch doesn't count
+          i->second.freshness = now;
+          // We need to nuke the temp file, since interning passes
+          // responsibility over the path to this structure.  It is
+          // possible that the caller still has an fd open, but that's
+          // OK.
+          unlink (fd.c_str());
+          return;
+        }
+      double mb = (sz+65535)/1048576.0; // round up to 64K block
+      fdcache_entry n = { .fd=fd, .fd_size_mb=mb,
+                          .freshness=now, .request_count = requested_p?1U:0U,
+                          .latency=lat};
+      entries.insert(make_pair(make_pair(a,b),n));
+      
+      if (requested_p)
+        inc_metric("fdcache_op_count","op","enqueue");
+      else
+        inc_metric("fdcache_op_count","op","prefetch_enqueue");
+      
+      if (verbose > 3)
+        obatched(clog) << "fdcache interned a=" << a << " b=" << b
+                       << " fd=" << fd << " mb=" << mb << " front=" << requested_p
+                       << " latency=" << lat << endl;
+      
+      set_metrics();
+    }
+
+    // NB: we age the cache at lookup time too
+    if (statfs_free_enough_p(tmpdir, "tmpdir", fdcache_mintmp))
+      {
+        inc_metric("fdcache_op_count","op","emerg-flush");
+        obatched(clog) << "fdcache emergency flush for filling tmpdir" << endl;
+        this->limit(0); // emergency flush
+      }
+    else // age cache normally
+      this->limit(max_mbs);
+  }
+
+  int lookup(const string& a, const string& b)
+  {
+    int fd = -1;
+    {
+      unique_lock<mutex> lock(fdcache_lock);
+      auto i = entries.find(make_pair(a,b));
+      if (i != entries.end())
+        {
+          if (i->second.request_count == 0) // was a prefetch!
+            {
+              inc_metric("fdcache_prefetch_saved_milliseconds_count");
+              add_metric("fdcache_prefetch_saved_milliseconds_sum", i->second.latency*1000.);
+            }
+          i->second.request_count ++;
+          i->second.freshness = time(NULL);
+          // brag about our success
+          inc_metric("fdcache_op_count","op","prefetch_access"); // backward compat
+          inc_metric("fdcache_saved_milliseconds_count");
+          add_metric("fdcache_saved_milliseconds_sum", i->second.latency*1000.);
+          fd = open(i->second.fd.c_str(), O_RDONLY); 
+        }
+    }
+
+    if (fd >= 0)
+      inc_metric("fdcache_op_count","op","lookup_hit");
+    else
+      inc_metric("fdcache_op_count","op","lookup_miss");
+    
+    // NB: no need to age the cache after just a lookup
+
+    return fd;
+  }
+
+  int probe(const string& a, const string& b) // just a cache residency check - don't modify state, don't open
+  {
+    unique_lock<mutex> lock(fdcache_lock);
+    auto i = entries.find(make_pair(a,b));
+    if (i != entries.end()) {
+      inc_metric("fdcache_op_count","op","probe_hit");
+      return true;
+    } else {
+      inc_metric("fdcache_op_count","op","probe_miss");
+      return false;
+   }
+  }
+  
+  void clear(const string& a, const string& b)
+  {
+    unique_lock<mutex> lock(fdcache_lock);
+    auto i = entries.find(make_pair(a,b));
+    if (i != entries.end()) {
+      inc_metric("fdcache_op_count","op",
+                 i->second.request_count > 0 ? "clear" : "prefetch_clear");
+      unlink (i->second.fd.c_str());
+      entries.erase(i);
+      set_metrics();
+      return;
+    }
+  }
+
+  void limit(long maxmbs, bool metrics_p = true)
+  {
+    time_t now = time(NULL);
+
+    // avoid overly frequent limit operations
+    if (maxmbs > 0 && (now - this->last_cleaning) < 10) // probably not worth parametrizing
+      return;
+    this->last_cleaning = now;
+    
+    if (verbose > 3 && (this->max_mbs != maxmbs))
+      obatched(clog) << "fdcache limited to maxmbs=" << maxmbs << endl;
+
+    unique_lock<mutex> lock(fdcache_lock);
+    
+    this->max_mbs = maxmbs;
+    double total_mb = 0.0;
+
+    map<double, pair<string,string>> sorted_entries;
+    for (auto &i: entries)
+      {
+        total_mb += i.second.fd_size_mb;
+
+        // need a scalar quantity that combines these inputs in a sensible way:
+        //
+        // 1) freshness of this entry (last time it was accessed)
+        // 2) size of this entry
+        // 3) number of times it has been accessed (or if just prefetched with 0 accesses)
+        // 4) latency it required to extract
+        //
+        // The lower the "score", the earlier garbage collection will
+        // nuke it, so to prioritize entries for preservation, the
+        // score should be higher, and vice versa.
+        time_t factor_1_freshness = (now - i.second.freshness); // seconds
+        double factor_2_size = i.second.fd_size_mb; // megabytes
+        unsigned factor_3_accesscount = i.second.request_count; // units
+        double factor_4_latency = i.second.latency; // seconds
+
+        #if 0
+        double score = - factor_1_freshness; // simple LRU
+        #endif
+
+        double score = 0.
+          - log1p(factor_1_freshness)                // penalize old file
+          - log1p(factor_2_size)                     // penalize large file
+          + factor_4_latency * factor_3_accesscount; // reward slow + repeatedly read files
+
+        if (verbose > 4)
+          obatched(clog) << "fdcache scored score=" << score
+                         << " a=" << i.first.first << " b=" << i.first.second
+                         << " f1=" << factor_1_freshness << " f2=" << factor_2_size
+                         << " f3=" << factor_3_accesscount << " f4=" << factor_4_latency
+                         << endl;
+        
+        sorted_entries.insert(make_pair(score, i.first));
+      }
+
+    unsigned cleaned = 0;
+    unsigned entries_original = entries.size();
+    double cleaned_score_min = DBL_MAX;
+    double cleaned_score_max = DBL_MIN;
+    
+    // drop as many entries[] as needed to bring total mb down to the threshold
+    for (auto &i: sorted_entries) // in increasing score order!
+      {
+        if (this->max_mbs > 0 // if this is not a "clear entire table"
+            && total_mb < this->max_mbs) // we've cleared enough to meet threshold
+          break; // stop clearing
+
+        auto j = entries.find(i.second);
+        if (j == entries.end())
+          continue; // should not happen
+
+        if (cleaned == 0)
+          cleaned_score_min = i.first;
+        cleaned++;
+        cleaned_score_max = i.first;
+        
+        if (verbose > 3)
+          obatched(clog) << "fdcache evicted score=" << i.first
+                         << " a=" << i.second.first << " b=" << i.second.second
+                         << " fd=" << j->second.fd << " mb=" << j->second.fd_size_mb
+                         << " rq=" << j->second.request_count << " lat=" << j->second.latency
+                         << " fr=" << (now - j->second.freshness)
+                         << endl;
+        if (metrics_p)
+          inc_metric("fdcache_op_count","op","evict");
+        
+        total_mb -= j->second.fd_size_mb;
+        unlink (j->second.fd.c_str());
+        entries.erase(j);
+      }
+
+    if (metrics_p)
+      inc_metric("fdcache_op_count","op","evict_cycle");
+    
+    if (verbose > 1 && cleaned > 0)
+      {
+        obatched(clog) << "fdcache evicted num=" << cleaned << " of=" << entries_original
+                       << " min=" << cleaned_score_min << " max=" << cleaned_score_max
+                       << endl;
+      }
+    
+    if (metrics_p) set_metrics();
+  }
+
+
+  ~libarchive_fdcache()
+  {
+    // unlink any fdcache entries in $TMPDIR
+    // don't update metrics; those globals may be already destroyed
+    limit(0, false);
+  }
+};
+static libarchive_fdcache fdcache;
+
+/* Search ELF_FD for an ELF/DWARF section with name SECTION.
+   If found copy the section to a temporary file and return
+   its file descriptor, otherwise return -1.
+
+   The temporary file's mtime will be set to PARENT_MTIME.
+   B_SOURCE should be a description of the parent file suitable
+   for printing to the log.  */
+
+static int
+extract_section (int elf_fd, int64_t parent_mtime,
+		 const string& b_source, const string& section,
+                 const timespec& extract_begin)
+{
+  /* Search the fdcache.  */
+  struct stat fs;
+  int fd = fdcache.lookup (b_source, section);
+  if (fd >= 0)
+    {
+      if (fstat (fd, &fs) != 0)
+	{
+	  if (verbose)
+	    obatched (clog) << "cannot fstate fdcache "
+			    << b_source << " " << section << endl;
+	  close (fd);
+	  return -1;
+	}
+      if ((int64_t) fs.st_mtime != parent_mtime)
+	{
+	  if (verbose)
+	    obatched(clog) << "mtime mismatch for "
+			   << b_source << " " << section << endl;
+	  close (fd);
+	  return -1;
+	}
+      /* Success.  */
+      return fd;
+    }
+
+  Elf *elf = elf_begin (elf_fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+  if (elf == NULL)
+    return -1;
+
+  /* Try to find the section and copy the contents into a separate file.  */
+  try
+    {
+      size_t shstrndx;
+      int rc = elf_getshdrstrndx (elf, &shstrndx);
+      if (rc < 0)
+	throw elfutils_exception (rc, "getshdrstrndx");
+
+      Elf_Scn *scn = NULL;
+      while (true)
+	{
+	  scn = elf_nextscn (elf, scn);
+	  if (scn == NULL)
+	    break;
+	  GElf_Shdr shdr_storage;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_storage);
+	  if (shdr == NULL)
+	    break;
+
+	  const char *scn_name = elf_strptr (elf, shstrndx, shdr->sh_name);
+	  if (scn_name == NULL)
+	    break;
+	  if (scn_name == section)
+	    {
+	      Elf_Data *data = NULL;
+
+	      /* We found the desired section.  */
+	      data = elf_rawdata (scn, NULL);
+	      if (data == NULL)
+		throw elfutils_exception (elf_errno (), "elfraw_data");
+	      if (data->d_buf == NULL)
+		{
+		  obatched(clog) << "section " << section
+				 << " is empty" << endl;
+		  break;
+		}
+
+	      /* Create temporary file containing the section.  */
+	      char *tmppath = NULL;
+	      rc = asprintf (&tmppath, "%s/debuginfod-section.XXXXXX", tmpdir.c_str());
+	      if (rc < 0)
+		throw libc_exception (ENOMEM, "cannot allocate tmppath");
+	      defer_dtor<void*,void> tmmpath_freer (tmppath, free);
+	      fd = mkstemp (tmppath);
+	      if (fd < 0)
+		throw libc_exception (errno, "cannot create temporary file");
+
+	      ssize_t res = write_retry (fd, data->d_buf, data->d_size);
+	      if (res < 0 || (size_t) res != data->d_size) {
+                close (fd);
+                unlink (tmppath);
+		throw libc_exception (errno, "cannot write to temporary file");
+              }
+
+	      /* Set mtime to be the same as the parent file's mtime.  */
+	      struct timespec tvs[2];
+	      if (fstat (elf_fd, &fs) != 0) {
+                close (fd);
+                unlink (tmppath);
+		throw libc_exception (errno, "cannot fstat file");
+              }
+              
+	      tvs[0].tv_sec = 0;
+	      tvs[0].tv_nsec = UTIME_OMIT;
+	      tvs[1] = fs.st_mtim;
+	      (void) futimens (fd, tvs);
+
+              struct timespec extract_end;
+              clock_gettime (CLOCK_MONOTONIC, &extract_end);
+              double extract_time = (extract_end.tv_sec - extract_begin.tv_sec)
+                + (extract_end.tv_nsec - extract_begin.tv_nsec)/1.e9;
+              
+	      /* Add to fdcache.  */
+	      fdcache.intern (b_source, section, tmppath, data->d_size, true, extract_time);
+	      break;
+	    }
+	}
+    }
+  catch (const reportable_exception &e)
+    {
+      e.report (clog);
+      close (fd);
+      fd = -1;
+    }
+
+  elf_end (elf);
+  return fd;
+}
+
+static struct MHD_Response*
+handle_buildid_f_match (bool internal_req_t,
+                        int64_t b_mtime,
+                        const string& b_source0,
+                        const string& section,
+                        int *result_fd)
+{
+  (void) internal_req_t; // ignored
+
+  struct timespec extract_begin;
+  clock_gettime (CLOCK_MONOTONIC, &extract_begin);
+  
+  int fd = open(b_source0.c_str(), O_RDONLY);
+  if (fd < 0)
+    throw libc_exception (errno, string("open ") + b_source0);
+  
+  // NB: use manual close(2) in error case instead of defer_dtor, because
+  // in the normal case, we want to hand the fd over to libmicrohttpd for
+  // file transfer.
+
+  struct stat s;
+  int rc = fstat(fd, &s);
+  if (rc < 0)
+    {
+      close(fd);
+      throw libc_exception (errno, string("fstat ") + b_source0);
+    }
+
+  if ((int64_t) s.st_mtime != b_mtime)
+    {
+      if (verbose)
+        obatched(clog) << "mtime mismatch for " << b_source0 << endl;
+      close(fd);
+      return 0;
+    }
+
+  if (!section.empty ())
+    {
+      int scn_fd = extract_section (fd, s.st_mtime, b_source0, section, extract_begin);
+      close (fd);
+
+      if (scn_fd >= 0)
+	fd = scn_fd;
+      else
+	{
+	  if (verbose)
+	    obatched (clog) << "cannot find section " << section
+			    << " for " << b_source0 << endl;
+	  return 0;
+	}
+
+      rc = fstat(fd, &s);
+      if (rc < 0)
+	{
+	  close (fd);
+	  throw libc_exception (errno, string ("fstat ") + b_source0
+				       + string (" ") + section);
+	}
+    }
+
+  struct MHD_Response* r = MHD_create_response_from_fd ((uint64_t) s.st_size, fd);
+  inc_metric ("http_responses_total","result","file");
+  if (r == 0)
+    {
+      if (verbose)
+	obatched(clog) << "cannot create fd-response for " << b_source0
+		       << " section=" << section << endl;
+      close(fd);
+    }
+  else
+    {
+      add_mhd_response_header (r, "Content-Type", "application/octet-stream");
+      add_mhd_response_header (r, "X-DEBUGINFOD-SIZE",
+			       to_string(s.st_size).c_str());
+      add_mhd_response_header (r, "X-DEBUGINFOD-FILE", b_source0.c_str());
+      add_mhd_last_modified (r, s.st_mtime);
+      if (verbose > 1)
+	obatched(clog) << "serving file " << b_source0 << " section=" << section << endl;
+      /* libmicrohttpd will close it. */
+      if (result_fd)
+        *result_fd = fd;
+    }
+
+  return r;
+}
+
+// For security/portability reasons, many distro-package archives have
+// a "./" in front of path names; others have nothing, others have
+// "/".  Canonicalize them all to a single leading "/", with the
+// assumption that this matches the dwarf-derived file names too.
+string canonicalized_archive_entry_pathname(struct archive_entry *e)
+{
+  string fn = archive_entry_pathname(e);
+  if (fn.size() == 0)
+    return fn;
+  if (fn[0] == '/')
+    return fn;
+  if (fn[0] == '.')
+    return fn.substr(1);
+  else
+    return string("/")+fn;
+}
+
+
+
+static struct MHD_Response*
+handle_buildid_r_match (bool internal_req_p,
+                        int64_t b_mtime,
+                        const string& b_source0,
+                        const string& b_source1,
+                        const string& section,
+                        int *result_fd)
+{
+  struct timespec extract_begin;
+  clock_gettime (CLOCK_MONOTONIC, &extract_begin);
+
+  struct stat fs;
+  int rc = stat (b_source0.c_str(), &fs);
+  if (rc != 0)
+    throw libc_exception (errno, string("stat ") + b_source0);
+
+  if ((int64_t) fs.st_mtime != b_mtime)
+    {
+      if (verbose)
+        obatched(clog) << "mtime mismatch for " << b_source0 << endl;
+      return 0;
+    }
+
+  // check for a match in the fdcache first
+  int fd = fdcache.lookup(b_source0, b_source1);
+  while (fd >= 0) // got one!; NB: this is really an if() with a possible branch out to the end
+    {
+      rc = fstat(fd, &fs);
+      if (rc < 0) // disappeared?
+        {
+          if (verbose)
+            obatched(clog) << "cannot fstat fdcache " << b_source0 << endl;
+          close(fd);
+          fdcache.clear(b_source0, b_source1);
+          break; // branch out of if "loop", to try new libarchive fetch attempt
+        }
+
+      if (!section.empty ())
+	{
+	  int scn_fd = extract_section (fd, fs.st_mtime,
+					b_source0 + ":" + b_source1,
+					section, extract_begin);
+	  close (fd);
+	  if (scn_fd >= 0)
+	    fd = scn_fd;
+	  else
+	    {
+	      if (verbose)
+	        obatched (clog) << "cannot find section " << section
+				<< " for archive " << b_source0
+				<< " file " << b_source1 << endl;
+	      return 0;
+	    }
+
+	  rc = fstat(fd, &fs);
+	  if (rc < 0)
+	    {
+	      close (fd);
+	      throw libc_exception (errno,
+		string ("fstat archive ") + b_source0 + string (" file ") + b_source1
+		+ string (" section ") + section);
+	    }
+	}
+
+      struct MHD_Response* r = MHD_create_response_from_fd (fs.st_size, fd);
+      if (r == 0)
+        {
+          if (verbose)
+            obatched(clog) << "cannot create fd-response for " << b_source0 << endl;
+          close(fd);
+          break; // branch out of if "loop", to try new libarchive fetch attempt
+        }
+
+      inc_metric ("http_responses_total","result","archive fdcache");
+
+      add_mhd_response_header (r, "Content-Type", "application/octet-stream");
+      add_mhd_response_header (r, "X-DEBUGINFOD-SIZE",
+			       to_string(fs.st_size).c_str());
+      add_mhd_response_header (r, "X-DEBUGINFOD-ARCHIVE", b_source0.c_str());
+      add_mhd_response_header (r, "X-DEBUGINFOD-FILE", b_source1.c_str());
+      add_mhd_last_modified (r, fs.st_mtime);
+      if (verbose > 1)
+	obatched(clog) << "serving fdcache archive " << b_source0
+		       << " file " << b_source1
+		       << " section=" << section << endl;
+      /* libmicrohttpd will close it. */
+      if (result_fd)
+        *result_fd = fd;
+      return r;
+      // NB: see, we never go around the 'loop' more than once
+    }
+
+  // no match ... grumble, must process the archive
+  string archive_decoder = "/dev/null";
+  string archive_extension = "";
+  for (auto&& arch : scan_archives)
+    if (string_endswith(b_source0, arch.first))
+      {
+        archive_extension = arch.first;
+        archive_decoder = arch.second;
+      }
+  FILE* fp;
+  
+  defer_dtor<FILE*,int>::dtor_fn dfn;
+  if (archive_decoder != "cat")
+    {
+      string popen_cmd = archive_decoder + " " + shell_escape(b_source0);
+      fp = popen (popen_cmd.c_str(), "r"); // "e" O_CLOEXEC?
+      dfn = pclose;
+      if (fp == NULL)
+        throw libc_exception (errno, string("popen ") + popen_cmd);
+    }
+  else
+    {
+      fp = fopen (b_source0.c_str(), "r");
+      dfn = fclose;
+      if (fp == NULL)
+        throw libc_exception (errno, string("fopen ") + b_source0);
+    }
+  defer_dtor<FILE*,int> fp_closer (fp, dfn);
+
+  struct archive *a;
+  a = archive_read_new();
+  if (a == NULL)
+    throw archive_exception("cannot create archive reader");
+  defer_dtor<struct archive*,int> archive_closer (a, archive_read_free);
+
+  rc = archive_read_support_format_all(a);
+  if (rc != ARCHIVE_OK)
+    throw archive_exception(a, "cannot select all format");
+  rc = archive_read_support_filter_all(a);
+  if (rc != ARCHIVE_OK)
+    throw archive_exception(a, "cannot select all filters");
+
+  rc = archive_read_open_FILE (a, fp);
+  if (rc != ARCHIVE_OK)
+    {
+      obatched(clog) << "cannot open archive from pipe " << b_source0 << endl;
+      throw archive_exception(a, "cannot open archive from pipe");
+    }
+
+  // archive traversal is in three stages, no, four stages:
+  // 1) skip entries whose names do not match the requested one
+  // 2) extract the matching entry name (set r = result)
+  // 3) extract some number of prefetched entries (just into fdcache)
+  // 4) abort any further processing
+  struct MHD_Response* r = 0;                 // will set in stage 2
+  unsigned prefetch_count =
+    internal_req_p ? 0 : fdcache_prefetch;    // will decrement in stage 3
+
+  while(r == 0 || prefetch_count > 0) // stage 1, 2, or 3
+    {
+      if (interrupted)
+        break;
+
+      struct archive_entry *e;
+      rc = archive_read_next_header (a, &e);
+      if (rc != ARCHIVE_OK)
+        break;
+
+      if (! S_ISREG(archive_entry_mode (e))) // skip non-files completely
+        continue;
+
+      string fn = canonicalized_archive_entry_pathname (e);
+      if ((r == 0) && (fn != b_source1)) // stage 1
+        continue;
+
+      if (fdcache.probe (b_source0, fn) && // skip if already interned
+          fn != b_source1) // but only if we'd just be prefetching, PR29474
+        continue;
+
+      // extract this file to a temporary file
+      char* tmppath = NULL;
+      rc = asprintf (&tmppath, "%s/debuginfod-fdcache.XXXXXX", tmpdir.c_str());
+      if (rc < 0)
+        throw libc_exception (ENOMEM, "cannot allocate tmppath");
+      defer_dtor<void*,void> tmmpath_freer (tmppath, free);
+      fd = mkstemp (tmppath);
+      if (fd < 0)
+        throw libc_exception (errno, "cannot create temporary file");
+      // NB: don't unlink (tmppath), as fdcache will take charge of it.
+
+      // NB: this can take many uninterruptible seconds for a huge file
+      rc = archive_read_data_into_fd (a, fd);
+      if (rc != ARCHIVE_OK) // e.g. ENOSPC!
+        {
+          close (fd);
+          unlink (tmppath);
+          throw archive_exception(a, "cannot extract file");
+        }
+
+      // Set the mtime so the fdcache file mtimes, even prefetched ones,
+      // propagate to future webapi clients.
+      struct timespec tvs[2];
+      tvs[0].tv_sec = 0;
+      tvs[0].tv_nsec = UTIME_OMIT;
+      tvs[1].tv_sec = archive_entry_mtime(e);
+      tvs[1].tv_nsec = archive_entry_mtime_nsec(e);
+      (void) futimens (fd, tvs);  /* best effort */
+
+      struct timespec extract_end;
+      clock_gettime (CLOCK_MONOTONIC, &extract_end);
+      double extract_time = (extract_end.tv_sec - extract_begin.tv_sec)
+        + (extract_end.tv_nsec - extract_begin.tv_nsec)/1.e9;
+      
+      if (r != 0) // stage 3
+        {
+          // NB: now we know we have a complete reusable file; make fdcache
+          // responsible for unlinking it later.
+          fdcache.intern(b_source0, fn,
+                         tmppath, archive_entry_size(e),
+                         false, extract_time); // prefetched ones go to the prefetch cache
+          prefetch_count --;
+          close (fd); // we're not saving this fd to make a mhd-response from!
+          continue;
+        }
+
+      // NB: now we know we have a complete reusable file; make fdcache
+      // responsible for unlinking it later.
+      fdcache.intern(b_source0, b_source1,
+                     tmppath, archive_entry_size(e),
+                     true, extract_time); // requested ones go to the front of the line
+
+      if (!section.empty ())
+	{
+	  int scn_fd = extract_section (fd, b_mtime,
+					b_source0 + ":" + b_source1,
+					section, extract_begin);
+	  close (fd);
+	  if (scn_fd >= 0)
+	    fd = scn_fd;
+	  else
+	    {
+	      if (verbose)
+	        obatched (clog) << "cannot find section " << section
+				<< " for archive " << b_source0
+				<< " file " << b_source1 << endl;
+	      return 0;
+	    }
+
+	  rc = fstat(fd, &fs);
+	  if (rc < 0)
+	    {
+	      close (fd);
+	      throw libc_exception (errno,
+		string ("fstat ") + b_source0 + string (" ") + section);
+	    }
+	  r = MHD_create_response_from_fd (fs.st_size, fd);
+	}
+      else
+	r = MHD_create_response_from_fd (archive_entry_size(e), fd);
+
+      inc_metric ("http_responses_total","result",archive_extension + " archive");
+      if (r == 0)
+        {
+          if (verbose)
+            obatched(clog) << "cannot create fd-response for " << b_source0 << endl;
+          close(fd);
+          break; // assume no chance of better luck around another iteration; no other copies of same file
+        }
+      else
+        {
+          add_mhd_response_header (r, "Content-Type",
+                                   "application/octet-stream");
+          add_mhd_response_header (r, "X-DEBUGINFOD-SIZE",
+                                   to_string(archive_entry_size(e)).c_str());
+          add_mhd_response_header (r, "X-DEBUGINFOD-ARCHIVE", b_source0.c_str());
+          add_mhd_response_header (r, "X-DEBUGINFOD-FILE", b_source1.c_str());
+          add_mhd_last_modified (r, archive_entry_mtime(e));
+          if (verbose > 1)
+	    obatched(clog) << "serving archive " << b_source0
+			   << " file " << b_source1
+			   << " section=" << section << endl;
+          /* libmicrohttpd will close it. */
+          if (result_fd)
+            *result_fd = fd;
+          continue;
+        }
+    }
+
+  // XXX: rpm/file not found: delete this R entry?
+  return r;
+}
+
+
+static struct MHD_Response*
+handle_buildid_match (bool internal_req_p,
+                      int64_t b_mtime,
+                      const string& b_stype,
+                      const string& b_source0,
+                      const string& b_source1,
+                      const string& section,
+                      int *result_fd)
+{
+  try
+    {
+      if (b_stype == "F")
+        return handle_buildid_f_match(internal_req_p, b_mtime, b_source0,
+				      section, result_fd);
+      else if (b_stype == "R")
+        return handle_buildid_r_match(internal_req_p, b_mtime, b_source0,
+				      b_source1, section, result_fd);
+    }
+  catch (const reportable_exception &e)
+    {
+      e.report(clog);
+      // Report but swallow libc etc. errors here; let the caller
+      // iterate to other matches of the content.
+    }
+
+  return 0;
+}
+
+
+static int
+debuginfod_find_progress (debuginfod_client *, long a, long b)
+{
+  if (verbose > 4)
+    obatched(clog) << "federated debuginfod progress=" << a << "/" << b << endl;
+
+  return interrupted;
+}
+
+
+// a little lru pool of debuginfod_client*s for reuse between query threads
+
+mutex dc_pool_lock;
+deque<debuginfod_client*> dc_pool;
+
+debuginfod_client* debuginfod_pool_begin()
+{
+  unique_lock<mutex> lock(dc_pool_lock);
+  if (dc_pool.size() > 0)
+    {
+      inc_metric("dc_pool_op_count","op","begin-reuse");
+      debuginfod_client *c = dc_pool.front();
+      dc_pool.pop_front();
+      return c;
+    }
+  inc_metric("dc_pool_op_count","op","begin-new");
+  return debuginfod_begin();
+}
+
+
+void debuginfod_pool_groom()
+{
+  unique_lock<mutex> lock(dc_pool_lock);
+  while (dc_pool.size() > 0)
+    {
+      inc_metric("dc_pool_op_count","op","end");
+      debuginfod_end(dc_pool.front());
+      dc_pool.pop_front();
+    }
+}
+
+
+void debuginfod_pool_end(debuginfod_client* c)
+{
+  unique_lock<mutex> lock(dc_pool_lock);
+  inc_metric("dc_pool_op_count","op","end-save");
+  dc_pool.push_front(c); // accelerate reuse, vs. push_back
+}
+
+
+static struct MHD_Response*
+handle_buildid (MHD_Connection* conn,
+                const string& buildid /* unsafe */,
+                string& artifacttype /* unsafe, cleanse on exception/return */,
+                const string& suffix /* unsafe */,
+                int *result_fd)
+{
+  // validate artifacttype
+  string atype_code;
+  if (artifacttype == "debuginfo") atype_code = "D";
+  else if (artifacttype == "executable") atype_code = "E";
+  else if (artifacttype == "source") atype_code = "S";
+  else if (artifacttype == "section") atype_code = "I";
+  else {
+    artifacttype = "invalid"; // PR28242 ensure http_resposes metrics don't propagate unclean user data 
+    throw reportable_exception("invalid artifacttype");
+  }
+
+  if (conn != 0)
+    inc_metric("http_requests_total", "type", artifacttype);
+
+  string section;
+  if (atype_code == "I")
+    {
+      if (suffix.size () < 2)
+	throw reportable_exception ("invalid section suffix");
+
+      // Remove leading '/'
+      section = suffix.substr(1);
+    }
+
+  if (atype_code == "S" && suffix == "")
+     throw reportable_exception("invalid source suffix");
+
+  // validate buildid
+  if ((buildid.size() < 2) || // not empty
+      (buildid.size() % 2) || // even number
+      (buildid.find_first_not_of("0123456789abcdef") != string::npos)) // pure tasty lowercase hex
+    throw reportable_exception("invalid buildid");
+
+  if (verbose > 1)
+    obatched(clog) << "searching for buildid=" << buildid << " artifacttype=" << artifacttype
+         << " suffix=" << suffix << endl;
+
+  // If invoked from the scanner threads, use the scanners' read-write
+  // connection.  Otherwise use the web query threads' read-only connection.
+  sqlite3 *thisdb = (conn == 0) ? db : dbq;
+
+  sqlite_ps *pp = 0;
+
+  if (atype_code == "D")
+    {
+      pp = new sqlite_ps (thisdb, "mhd-query-d",
+                          "select mtime, sourcetype, source0, source1 from " BUILDIDS "_query_d where buildid = ? "
+                          "order by mtime desc");
+      pp->reset();
+      pp->bind(1, buildid);
+    }
+  else if (atype_code == "E")
+    {
+      pp = new sqlite_ps (thisdb, "mhd-query-e",
+                          "select mtime, sourcetype, source0, source1 from " BUILDIDS "_query_e where buildid = ? "
+                          "order by mtime desc");
+      pp->reset();
+      pp->bind(1, buildid);
+    }
+  else if (atype_code == "S")
+    {
+      // PR25548
+      // Incoming source queries may come in with either dwarf-level OR canonicalized paths.
+      // We let the query pass with either one.
+
+      pp = new sqlite_ps (thisdb, "mhd-query-s",
+                          "select mtime, sourcetype, source0, source1 from " BUILDIDS "_query_s where buildid = ? and artifactsrc in (?,?) "
+                          "order by sharedprefix(source0,source0ref) desc, mtime desc");
+      pp->reset();
+      pp->bind(1, buildid);
+      // NB: we don't store the non-canonicalized path names any more, but old databases
+      // might have them (and no canon ones), so we keep searching for both.
+      pp->bind(2, suffix);
+      pp->bind(3, canon_pathname(suffix));
+    }
+  else if (atype_code == "I")
+    {
+      pp = new sqlite_ps (thisdb, "mhd-query-i",
+	"select mtime, sourcetype, source0, source1, 1 as debug_p from " BUILDIDS "_query_d where buildid = ? "
+	"union all "
+	"select mtime, sourcetype, source0, source1, 0 as debug_p from " BUILDIDS "_query_e where buildid = ? "
+	"order by debug_p desc, mtime desc");
+      pp->reset();
+      pp->bind(1, buildid);
+      pp->bind(2, buildid);
+    }
+  unique_ptr<sqlite_ps> ps_closer(pp); // release pp if exception or return
+
+  bool do_upstream_section_query = true;
+
+  // consume all the rows
+  while (1)
+    {
+      int rc = pp->step();
+      if (rc == SQLITE_DONE) break;
+      if (rc != SQLITE_ROW)
+        throw sqlite_exception(rc, "step");
+
+      int64_t b_mtime = sqlite3_column_int64 (*pp, 0);
+      string b_stype = string((const char*) sqlite3_column_text (*pp, 1) ?: ""); /* by DDL may not be NULL */
+      string b_source0 = string((const char*) sqlite3_column_text (*pp, 2) ?: ""); /* may be NULL */
+      string b_source1 = string((const char*) sqlite3_column_text (*pp, 3) ?: ""); /* may be NULL */
+
+      if (verbose > 1)
+        obatched(clog) << "found mtime=" << b_mtime << " stype=" << b_stype
+             << " source0=" << b_source0 << " source1=" << b_source1 << endl;
+
+      // Try accessing the located match.
+      // XXX: in case of multiple matches, attempt them in parallel?
+      auto r = handle_buildid_match (conn ? false : true,
+                                     b_mtime, b_stype, b_source0, b_source1,
+				     section, result_fd);
+      if (r)
+        return r;
+
+      // If a debuginfo file matching BUILDID was found but didn't contain
+      // the desired section, then the section should not exist.  Don't
+      // bother querying upstream servers.
+      if (!section.empty () && (sqlite3_column_int (*pp, 4) == 1))
+	{
+	  struct stat st;
+
+	  // For "F" sourcetype, check if the debuginfo exists. For "R"
+	  // sourcetype, check if the debuginfo was interned into the fdcache.
+	  if ((b_stype == "F" && (stat (b_source0.c_str (), &st) == 0))
+	      || (b_stype == "R" && fdcache.probe (b_source0, b_source1)))
+	    do_upstream_section_query = false;
+	}
+    }
+  pp->reset();
+
+  if (!do_upstream_section_query)
+    throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found");
+
+  // We couldn't find it in the database.  Last ditch effort
+  // is to defer to other debuginfo servers.
+
+  int fd = -1;
+  debuginfod_client *client = debuginfod_pool_begin ();
+  if (client == NULL)
+    throw libc_exception(errno, "debuginfod client pool alloc");
+  defer_dtor<debuginfod_client*,void> client_closer (client, debuginfod_pool_end);
+  
+  debuginfod_set_progressfn (client, & debuginfod_find_progress);
+
+  if (conn)
+    {
+      // Transcribe incoming User-Agent:
+      string ua = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, "User-Agent") ?: "";
+      string ua_complete = string("User-Agent: ") + ua;
+      debuginfod_add_http_header (client, ua_complete.c_str());
+      
+      // Compute larger XFF:, for avoiding info loss during
+      // federation, and for future cyclicity detection.
+      string xff = MHD_lookup_connection_value (conn, MHD_HEADER_KIND, "X-Forwarded-For") ?: "";
+      if (xff != "")
+        xff += string(", "); // comma separated list
+      
+      unsigned int xff_count = 0;
+      for (auto&& i : xff){
+        if (i == ',') xff_count++;
+      }
+
+      // if X-Forwarded-For: exceeds N hops,
+      // do not delegate a local lookup miss to upstream debuginfods.
+      if (xff_count >= forwarded_ttl_limit)
+        throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found, --forwared-ttl-limit reached \
+and will not query the upstream servers");
+
+      // Compute the client's numeric IP address only - so can't merge with conninfo()
+      const union MHD_ConnectionInfo *u = MHD_get_connection_info (conn,
+                                                                   MHD_CONNECTION_INFO_CLIENT_ADDRESS);
+      struct sockaddr *so = u ? u->client_addr : 0;
+      char hostname[256] = ""; // RFC1035
+      if (so && so->sa_family == AF_INET) {
+        (void) getnameinfo (so, sizeof (struct sockaddr_in), hostname, sizeof (hostname), NULL, 0,
+                            NI_NUMERICHOST);
+      } else if (so && so->sa_family == AF_INET6) {
+        struct sockaddr_in6* addr6 = (struct sockaddr_in6*) so;
+        if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+          struct sockaddr_in addr4;
+          memset (&addr4, 0, sizeof(addr4));
+          addr4.sin_family = AF_INET;
+          addr4.sin_port = addr6->sin6_port;
+          memcpy (&addr4.sin_addr.s_addr, addr6->sin6_addr.s6_addr+12, sizeof(addr4.sin_addr.s_addr));
+          (void) getnameinfo ((struct sockaddr*) &addr4, sizeof (addr4),
+                              hostname, sizeof (hostname), NULL, 0,
+                              NI_NUMERICHOST);
+        } else {
+          (void) getnameinfo (so, sizeof (struct sockaddr_in6), hostname, sizeof (hostname), NULL, 0,
+                              NI_NUMERICHOST);
+        }
+      }
+          
+      string xff_complete = string("X-Forwarded-For: ")+xff+string(hostname);
+      debuginfod_add_http_header (client, xff_complete.c_str());
+    }
+  
+  if (artifacttype == "debuginfo")
+    fd = debuginfod_find_debuginfo (client,
+                                    (const unsigned char*) buildid.c_str(),
+                                    0, NULL);
+  else if (artifacttype == "executable")
+    fd = debuginfod_find_executable (client,
+                                     (const unsigned char*) buildid.c_str(),
+                                     0, NULL);
+  else if (artifacttype == "source")
+    fd = debuginfod_find_source (client,
+                                 (const unsigned char*) buildid.c_str(),
+                                 0, suffix.c_str(), NULL);
+  else if (artifacttype == "section")
+    fd = debuginfod_find_section (client,
+                                  (const unsigned char*) buildid.c_str(),
+                                  0, section.c_str(), NULL);
+  
+  if (fd >= 0)
+    {
+      if (conn != 0)
+	inc_metric ("http_responses_total","result","upstream");
+      struct stat s;
+      int rc = fstat (fd, &s);
+      if (rc == 0)
+        {
+          auto r = MHD_create_response_from_fd ((uint64_t) s.st_size, fd);
+          if (r)
+            {
+              add_mhd_response_header (r, "Content-Type",
+				       "application/octet-stream");
+              // Copy the incoming headers
+              const char * hdrs = debuginfod_get_headers(client);
+              string header_dup;
+              if (hdrs)
+                header_dup = string(hdrs);
+              // Parse the "header: value\n" lines into (h,v) tuples and pass on
+              while(1)
+                {
+                  size_t newline = header_dup.find('\n');
+                  if (newline == string::npos) break;
+                  size_t colon = header_dup.find(':');
+                  if (colon == string::npos) break;
+                  string header = header_dup.substr(0,colon);
+                  string value = header_dup.substr(colon+1,newline-colon-1);
+                  // strip leading spaces from value
+                  size_t nonspace = value.find_first_not_of(" ");
+                  if (nonspace != string::npos)
+                    value = value.substr(nonspace);
+                  add_mhd_response_header(r, header.c_str(), value.c_str());
+                  header_dup = header_dup.substr(newline+1);
+                }
+
+              add_mhd_last_modified (r, s.st_mtime);
+              if (verbose > 1)
+                obatched(clog) << "serving file from upstream debuginfod/cache" << endl;
+              if (result_fd)
+                *result_fd = fd;
+              return r; // NB: don't close fd; libmicrohttpd will
+            }
+        }
+      close (fd);
+    }
+  else
+    switch(fd)
+      {
+      case -ENOSYS:
+        break;
+      case -ENOENT:
+        break;
+      default: // some more tricky error
+        throw libc_exception(-fd, "upstream debuginfod query failed");
+      }
+
+  throw reportable_exception(MHD_HTTP_NOT_FOUND, "not found");
+}
+
+
+////////////////////////////////////////////////////////////////////////
+
+static map<string,double> metrics; // arbitrary data for /metrics query
+// NB: store int64_t since all our metrics are integers; prometheus accepts double
+static mutex metrics_lock;
+// NB: these objects get released during the process exit via global dtors
+// do not call them from within other global dtors
+
+// utility function for assembling prometheus-compatible
+// name="escaped-value" strings
+// https://prometheus.io/docs/instrumenting/exposition_formats/
+static string
+metric_label(const string& name, const string& value)
+{
+  string x = name + "=\"";
+  for (auto&& c : value)
+    switch(c)
+      {
+      case '\\': x += "\\\\"; break;
+      case '\"': x += "\\\""; break;
+      case '\n': x += "\\n"; break;
+      default: x += c; break;
+      }
+  x += "\"";
+  return x;
+}
+
+
+// add prometheus-format metric name + label tuple (if any) + value
+
+static void
+set_metric(const string& metric, double value)
+{
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[metric] = value;
+}
+static void
+inc_metric(const string& metric)
+{
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[metric] ++;
+}
+static void
+set_metric(const string& metric,
+           const string& lname, const string& lvalue,
+           double value)
+{
+  string key = (metric + "{" + metric_label(lname, lvalue) + "}");
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[key] = value;
+}
+
+static void
+inc_metric(const string& metric,
+           const string& lname, const string& lvalue)
+{
+  string key = (metric + "{" + metric_label(lname, lvalue) + "}");
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[key] ++;
+}
+static void
+add_metric(const string& metric,
+           const string& lname, const string& lvalue,
+           double value)
+{
+  string key = (metric + "{" + metric_label(lname, lvalue) + "}");
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[key] += value;
+}
+static void
+add_metric(const string& metric,
+           double value)
+{
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[metric] += value;
+}
+
+
+// and more for higher arity labels if needed
+
+static void
+inc_metric(const string& metric,
+           const string& lname, const string& lvalue,
+           const string& rname, const string& rvalue)
+{
+  string key = (metric + "{"
+                + metric_label(lname, lvalue) + ","
+                + metric_label(rname, rvalue) + "}");
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[key] ++;
+}
+static void
+add_metric(const string& metric,
+           const string& lname, const string& lvalue,
+           const string& rname, const string& rvalue,
+           double value)
+{
+  string key = (metric + "{"
+                + metric_label(lname, lvalue) + ","
+                + metric_label(rname, rvalue) + "}");
+  unique_lock<mutex> lock(metrics_lock);
+  metrics[key] += value;
+}
+
+static struct MHD_Response*
+handle_metrics (off_t* size)
+{
+  stringstream o;
+  {
+    unique_lock<mutex> lock(metrics_lock);
+    for (auto&& i : metrics)
+      o << i.first
+        << " "
+        << std::setprecision(std::numeric_limits<double>::digits10 + 1)
+        << i.second
+        << endl;
+  }
+  const string& os = o.str();
+  MHD_Response* r = MHD_create_response_from_buffer (os.size(),
+                                                     (void*) os.c_str(),
+                                                     MHD_RESPMEM_MUST_COPY);
+  if (r != NULL)
+    {
+      *size = os.size();
+      add_mhd_response_header (r, "Content-Type", "text/plain");
+    }
+  return r;
+}
+
+static struct MHD_Response*
+handle_root (off_t* size)
+{
+  static string version = "debuginfod (" + string (PACKAGE_NAME) + ") "
+			  + string (PACKAGE_VERSION);
+  MHD_Response* r = MHD_create_response_from_buffer (version.size (),
+						     (void *) version.c_str (),
+						     MHD_RESPMEM_PERSISTENT);
+  if (r != NULL)
+    {
+      *size = version.size ();
+      add_mhd_response_header (r, "Content-Type", "text/plain");
+    }
+  return r;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+/* libmicrohttpd callback */
+static MHD_RESULT
+handler_cb (void * /*cls*/,
+            struct MHD_Connection *connection,
+            const char *url,
+            const char *method,
+            const char * /*version*/,
+            const char * /*upload_data*/,
+            size_t * /*upload_data_size*/,
+            void ** ptr)
+{
+  struct MHD_Response *r = NULL;
+  string url_copy = url;
+
+  /* libmicrohttpd always makes (at least) two callbacks: once just
+     past the headers, and one after the request body is finished
+     being received.  If we process things early (first callback) and
+     queue a response, libmicrohttpd would suppress http keep-alive
+     (via connection->read_closed = true). */
+  static int aptr; /* just some random object to use as a flag */
+  if (&aptr != *ptr)
+    {
+      /* do never respond on first call */
+      *ptr = &aptr;
+      return MHD_YES;
+    }
+  *ptr = NULL;                     /* reset when done */
+  
+  const char *maxsize_string = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, "X-DEBUGINFOD-MAXSIZE");
+  long maxsize = 0;
+  if (maxsize_string != NULL && maxsize_string[0] != '\0')
+    maxsize = atol(maxsize_string);
+  else
+    maxsize = 0;
+
+#if MHD_VERSION >= 0x00097002
+  enum MHD_Result rc;
+#else
+  int rc = MHD_NO; // mhd
+#endif
+  int http_code = 500;
+  off_t http_size = -1;
+  struct timespec ts_start, ts_end;
+  clock_gettime (CLOCK_MONOTONIC, &ts_start);
+  double afteryou = 0.0;
+  string artifacttype, suffix;
+
+  try
+    {
+      if (string(method) != "GET")
+        throw reportable_exception(400, "we support GET only");
+
+      /* Start decoding the URL. */
+      size_t slash1 = url_copy.find('/', 1);
+      string url1 = url_copy.substr(0, slash1); // ok even if slash1 not found
+
+      if (slash1 != string::npos && url1 == "/buildid")
+        {
+          // PR27863: block this thread awhile if another thread is already busy
+          // fetching the exact same thing.  This is better for Everyone.
+          // The latecomer says "... after you!" and waits.
+          add_metric ("thread_busy", "role", "http-buildid-after-you", 1);
+#ifdef HAVE_PTHREAD_SETNAME_NP
+          (void) pthread_setname_np (pthread_self(), "mhd-buildid-after-you");
+#endif
+          struct timespec tsay_start, tsay_end;
+          clock_gettime (CLOCK_MONOTONIC, &tsay_start);
+          static unique_set<string> busy_urls;
+          unique_set_reserver<string> after_you(busy_urls, url_copy);
+          clock_gettime (CLOCK_MONOTONIC, &tsay_end);
+          afteryou = (tsay_end.tv_sec - tsay_start.tv_sec) + (tsay_end.tv_nsec - tsay_start.tv_nsec)/1.e9;
+          add_metric ("thread_busy", "role", "http-buildid-after-you", -1);
+          
+          tmp_inc_metric m ("thread_busy", "role", "http-buildid");
+#ifdef HAVE_PTHREAD_SETNAME_NP
+          (void) pthread_setname_np (pthread_self(), "mhd-buildid");
+#endif
+          size_t slash2 = url_copy.find('/', slash1+1);
+          if (slash2 == string::npos)
+            throw reportable_exception("/buildid/ webapi error, need buildid");
+
+          string buildid = url_copy.substr(slash1+1, slash2-slash1-1);
+
+          size_t slash3 = url_copy.find('/', slash2+1);
+
+          if (slash3 == string::npos)
+            {
+              artifacttype = url_copy.substr(slash2+1);
+              suffix = "";
+            }
+          else
+            {
+              artifacttype = url_copy.substr(slash2+1, slash3-slash2-1);
+              suffix = url_copy.substr(slash3); // include the slash in the suffix
+            }
+
+          // get the resulting fd so we can report its size
+          int fd;
+          r = handle_buildid(connection, buildid, artifacttype, suffix, &fd);
+          if (r)
+            {
+              struct stat fs;
+              if (fstat(fd, &fs) == 0)
+                http_size = fs.st_size;
+              // libmicrohttpd will close (fd);
+            }
+        }
+      else if (url1 == "/metrics")
+        {
+          tmp_inc_metric m ("thread_busy", "role", "http-metrics");
+          artifacttype = "metrics";
+          inc_metric("http_requests_total", "type", artifacttype);
+          r = handle_metrics(& http_size);
+        }
+      else if (url1 == "/")
+        {
+          artifacttype = "/";
+          inc_metric("http_requests_total", "type", artifacttype);
+          r = handle_root(& http_size);
+        }
+      else
+        throw reportable_exception("webapi error, unrecognized '" + url1 + "'");
+
+      if (r == 0)
+        throw reportable_exception("internal error, missing response");
+
+      if (maxsize > 0 && http_size > maxsize)
+        {
+          MHD_destroy_response(r);
+          throw reportable_exception(406, "File too large, max size=" + std::to_string(maxsize));
+        }
+
+      rc = MHD_queue_response (connection, MHD_HTTP_OK, r);
+      http_code = MHD_HTTP_OK;
+      MHD_destroy_response (r);
+    }
+  catch (const reportable_exception& e)
+    {
+      inc_metric("http_responses_total","result","error");
+      e.report(clog);
+      http_code = e.code;
+      http_size = e.message.size();
+      rc = e.mhd_send_response (connection);
+    }
+
+  clock_gettime (CLOCK_MONOTONIC, &ts_end);
+  double deltas = (ts_end.tv_sec - ts_start.tv_sec) + (ts_end.tv_nsec - ts_start.tv_nsec)/1.e9;
+  // afteryou: delay waiting for other client's identical query to complete
+  // deltas: total latency, including afteryou waiting
+  obatched(clog) << conninfo(connection)
+                 << ' ' << method << ' ' << url
+                 << ' ' << http_code << ' ' << http_size
+                 << ' ' << (int)(afteryou*1000) << '+' << (int)((deltas-afteryou)*1000) << "ms"
+                 << endl;
+
+  // related prometheus metrics
+  string http_code_str = to_string(http_code);
+  add_metric("http_responses_transfer_bytes_sum",
+             "code", http_code_str, "type", artifacttype, http_size);
+  inc_metric("http_responses_transfer_bytes_count",
+             "code", http_code_str, "type", artifacttype);
+
+  add_metric("http_responses_duration_milliseconds_sum",
+             "code", http_code_str, "type", artifacttype, deltas*1000); // prometheus prefers _seconds and floating point
+  inc_metric("http_responses_duration_milliseconds_count",
+             "code", http_code_str, "type", artifacttype);
+
+  add_metric("http_responses_after_you_milliseconds_sum",
+             "code", http_code_str, "type", artifacttype, afteryou*1000);
+  inc_metric("http_responses_after_you_milliseconds_count",
+             "code", http_code_str, "type", artifacttype);
+
+  return rc;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+// borrowed originally from src/nm.c get_local_names()
+
+static void
+dwarf_extract_source_paths (Elf *elf, set<string>& debug_sourcefiles)
+  noexcept // no exceptions - so we can simplify the altdbg resource release at end
+{
+  Dwarf* dbg = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
+  if (dbg == NULL)
+    return;
+
+  Dwarf* altdbg = NULL;
+  int    altdbg_fd = -1;
+
+  // DWZ handling: if we have an unsatisfied debug-alt-link, add an
+  // empty string into the outgoing sourcefiles set, so the caller
+  // should know that our data is incomplete.
+  const char *alt_name_p;
+  const void *alt_build_id; // elfutils-owned memory
+  ssize_t sz = dwelf_dwarf_gnu_debugaltlink (dbg, &alt_name_p, &alt_build_id);
+  if (sz > 0) // got one!
+    {
+      string buildid;
+      unsigned char* build_id_bytes = (unsigned char*) alt_build_id;
+      for (ssize_t idx=0; idx<sz; idx++)
+        {
+          buildid += "0123456789abcdef"[build_id_bytes[idx] >> 4];
+          buildid += "0123456789abcdef"[build_id_bytes[idx] & 0xf];
+        }
+
+      if (verbose > 3)
+        obatched(clog) << "Need altdebug buildid=" << buildid << endl;
+
+      // but is it unsatisfied the normal elfutils ways?
+      Dwarf* alt = dwarf_getalt (dbg);
+      if (alt == NULL)
+        {
+          // Yup, unsatisfied the normal way.  Maybe we can satisfy it
+          // from our own debuginfod database.
+          int alt_fd;
+          struct MHD_Response *r = 0;
+          try
+            {
+              string artifacttype = "debuginfo";
+              r = handle_buildid (0, buildid, artifacttype, "", &alt_fd);
+            }
+          catch (const reportable_exception& e)
+            {
+              // swallow exceptions
+            }
+
+          // NB: this is not actually recursive!  This invokes the web-query
+          // path, which cannot get back into the scan code paths.
+          if (r)
+            {
+              // Found it!
+              altdbg_fd = dup(alt_fd); // ok if this fails, downstream failures ok
+              alt = altdbg = dwarf_begin (altdbg_fd, DWARF_C_READ);
+              // NB: must close this dwarf and this fd at the bottom of the function!
+              MHD_destroy_response (r); // will close alt_fd
+              if (alt)
+                dwarf_setalt (dbg, alt);
+            }
+        }
+      else
+        {
+          // NB: dwarf_setalt(alt) inappropriate - already done!
+          // NB: altdbg will stay 0 so nothing tries to redundantly dealloc.
+        }
+
+      if (alt)
+        {
+          if (verbose > 3)
+            obatched(clog) << "Resolved altdebug buildid=" << buildid << endl;
+        }
+      else // (alt == NULL) - signal possible presence of poor debuginfo
+        {
+          debug_sourcefiles.insert("");
+          if (verbose > 3)
+            obatched(clog) << "Unresolved altdebug buildid=" << buildid << endl;
+        }
+    }
+
+  Dwarf_Off offset = 0;
+  Dwarf_Off old_offset;
+  size_t hsize;
+
+  while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL, NULL) == 0)
+    {
+      Dwarf_Die cudie_mem;
+      Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
+
+      if (cudie == NULL)
+        continue;
+      if (dwarf_tag (cudie) != DW_TAG_compile_unit)
+        continue;
+
+      const char *cuname = dwarf_diename(cudie) ?: "unknown";
+
+      Dwarf_Files *files;
+      size_t nfiles;
+      if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
+        continue;
+
+      // extract DW_AT_comp_dir to resolve relative file names
+      const char *comp_dir = "";
+      const char *const *dirs;
+      size_t ndirs;
+      if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0 &&
+          dirs[0] != NULL)
+        comp_dir = dirs[0];
+      if (comp_dir == NULL)
+        comp_dir = "";
+
+      if (verbose > 3)
+        obatched(clog) << "searching for sources for cu=" << cuname << " comp_dir=" << comp_dir
+                       << " #files=" << nfiles << " #dirs=" << ndirs << endl;
+
+      if (comp_dir[0] == '\0' && cuname[0] != '/')
+        {
+          if (verbose > 3)
+            obatched(clog) << "skipping cu=" << cuname << " due to empty comp_dir" << endl;
+          continue;
+        }
+
+      for (size_t f = 1; f < nfiles; f++)
+        {
+          const char *hat = dwarf_filesrc (files, f, NULL, NULL);
+          if (hat == NULL)
+            continue;
+
+          if (string(hat) == "<built-in>") // gcc intrinsics, don't bother record
+            continue;
+
+          string waldo;
+          if (hat[0] == '/') // absolute
+            waldo = (string (hat));
+          else if (comp_dir[0] != '\0') // comp_dir relative
+            waldo = (string (comp_dir) + string("/") + string (hat));
+          else
+           {
+             if (verbose > 3)
+               obatched(clog) << "skipping hat=" << hat << " due to empty comp_dir" << endl;
+             continue;
+           }
+
+          // NB: this is the 'waldo' that a dbginfo client will have
+          // to supply for us to give them the file The comp_dir
+          // prefixing is a definite complication.  Otherwise we'd
+          // have to return a setof comp_dirs (one per CU!) with
+          // corresponding filesrc[] names, instead of one absolute
+          // resoved set.  Maybe we'll have to do that anyway.  XXX
+
+          if (verbose > 4)
+            obatched(clog) << waldo
+                           << (debug_sourcefiles.find(waldo)==debug_sourcefiles.end() ? " new" : " dup") <<  endl;
+
+          debug_sourcefiles.insert (waldo);
+        }
+    }
+
+  dwarf_end(dbg);
+  if (altdbg)
+    dwarf_end(altdbg);
+  if (altdbg_fd >= 0)
+    close(altdbg_fd);
+}
+
+
+
+static void
+elf_classify (int fd, bool &executable_p, bool &debuginfo_p, string &buildid, set<string>& debug_sourcefiles)
+{
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, NULL);
+  if (elf == NULL)
+    return;
+
+  try // catch our types of errors and clean up the Elf* object
+    {
+      if (elf_kind (elf) != ELF_K_ELF)
+        {
+          elf_end (elf);
+          return;
+        }
+
+      GElf_Ehdr ehdr_storage;
+      GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_storage);
+      if (ehdr == NULL)
+        {
+          elf_end (elf);
+          return;
+        }
+      auto elf_type = ehdr->e_type;
+
+      const void *build_id; // elfutils-owned memory
+      ssize_t sz = dwelf_elf_gnu_build_id (elf, & build_id);
+      if (sz <= 0)
+        {
+          // It's not a diagnostic-worthy error for an elf file to lack build-id.
+          // It might just be very old.
+          elf_end (elf);
+          return;
+        }
+
+      // build_id is a raw byte array; convert to hexadecimal *lowercase*
+      unsigned char* build_id_bytes = (unsigned char*) build_id;
+      for (ssize_t idx=0; idx<sz; idx++)
+        {
+          buildid += "0123456789abcdef"[build_id_bytes[idx] >> 4];
+          buildid += "0123456789abcdef"[build_id_bytes[idx] & 0xf];
+        }
+
+      // now decide whether it's an executable - namely, any allocatable section has
+      // PROGBITS;
+      if (elf_type == ET_EXEC || elf_type == ET_DYN)
+        {
+          size_t shnum;
+          int rc = elf_getshdrnum (elf, &shnum);
+          if (rc < 0)
+            throw elfutils_exception(rc, "getshdrnum");
+
+          executable_p = false;
+          for (size_t sc = 0; sc < shnum; sc++)
+            {
+              Elf_Scn *scn = elf_getscn (elf, sc);
+              if (scn == NULL)
+                continue;
+
+              GElf_Shdr shdr_mem;
+              GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+              if (shdr == NULL)
+                continue;
+
+              // allocated (loadable / vm-addr-assigned) section with available content?
+              if ((shdr->sh_type == SHT_PROGBITS) && (shdr->sh_flags & SHF_ALLOC))
+                {
+                  if (verbose > 4)
+                    obatched(clog) << "executable due to SHF_ALLOC SHT_PROGBITS sc=" << sc << endl;
+                  executable_p = true;
+                  break; // no need to keep looking for others
+                }
+            } // iterate over sections
+        } // executable_p classification
+
+      // now decide whether it's a debuginfo - namely, if it has any .debug* or .zdebug* sections
+      // logic mostly stolen from fweimer@redhat.com's elfclassify drafts
+      size_t shstrndx;
+      int rc = elf_getshdrstrndx (elf, &shstrndx);
+      if (rc < 0)
+        throw elfutils_exception(rc, "getshdrstrndx");
+
+      Elf_Scn *scn = NULL;
+      bool symtab_p = false;
+      bool bits_alloc_p = false;
+      while (true)
+        {
+          scn = elf_nextscn (elf, scn);
+          if (scn == NULL)
+            break;
+          GElf_Shdr shdr_storage;
+          GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_storage);
+          if (shdr == NULL)
+            break;
+          const char *section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
+          if (section_name == NULL)
+            break;
+          if (startswith (section_name, ".debug_line") ||
+              startswith (section_name, ".zdebug_line"))
+            {
+              debuginfo_p = true;
+              if (scan_source_info)
+                dwarf_extract_source_paths (elf, debug_sourcefiles);
+              break; // expecting only one .*debug_line, so no need to look for others
+            }
+          else if (startswith (section_name, ".debug_") ||
+                   startswith (section_name, ".zdebug_"))
+            {
+              debuginfo_p = true;
+              // NB: don't break; need to parse .debug_line for sources
+            }
+          else if (shdr->sh_type == SHT_SYMTAB)
+            {
+              symtab_p = true;
+            }
+          else if (shdr->sh_type != SHT_NOBITS
+                   && shdr->sh_type != SHT_NOTE
+                   && (shdr->sh_flags & SHF_ALLOC) != 0)
+            {
+              bits_alloc_p = true;
+            }
+        }
+
+      // For more expansive elf/split-debuginfo classification, we
+      // want to identify as debuginfo "strip -s"-produced files
+      // without .debug_info* (like libicudata), but we don't want to
+      // identify "strip -g" executables (with .symtab left there).
+      if (symtab_p && !bits_alloc_p)
+        debuginfo_p = true;
+    }
+  catch (const reportable_exception& e)
+    {
+      e.report(clog);
+    }
+  elf_end (elf);
+}
+
+
+// Intern the given file name in two parts (dirname & basename) and
+// return the resulting file's id.
+static int64_t
+register_file_name(sqlite_ps& ps_upsert_fileparts,
+                   sqlite_ps& ps_upsert_file,
+                   sqlite_ps& ps_lookup_file,
+                   const string& name)
+{
+  std::size_t slash = name.rfind('/');
+  string dirname, filename;
+  if (slash == std::string::npos)
+    {
+      dirname = "";
+      filename = name;
+    }
+  else
+    {
+      dirname = name.substr(0, slash);
+      filename = name.substr(slash+1);
+    }
+
+  // intern the two substrings
+  ps_upsert_fileparts
+    .reset()
+    .bind(1, dirname)
+    .step_ok_done();
+  ps_upsert_fileparts
+    .reset()
+    .bind(1, filename)
+    .step_ok_done();
+
+  // intern the tuple
+  ps_upsert_file
+    .reset()
+    .bind(1, dirname)
+    .bind(2, filename)
+    .step_ok_done();
+
+  // look up the tuple's id
+  ps_lookup_file
+    .reset()
+    .bind(1, dirname)
+    .bind(2, filename);
+  int rc = ps_lookup_file.step();
+  if (rc != SQLITE_ROW) throw sqlite_exception(rc, "step");
+  
+  int64_t id = sqlite3_column_int64 (ps_lookup_file, 0);
+  ps_lookup_file.reset();
+  return id;
+}
+
+
+
+static void
+scan_source_file (const string& rps, const stat_t& st,
+                  sqlite_ps& ps_upsert_buildids,
+                  sqlite_ps& ps_upsert_fileparts,
+                  sqlite_ps& ps_upsert_file,
+                  sqlite_ps& ps_lookup_file,
+                  sqlite_ps& ps_upsert_de,
+                  sqlite_ps& ps_upsert_s,
+                  sqlite_ps& ps_query,
+                  sqlite_ps& ps_scan_done,
+                  unsigned& fts_cached,
+                  unsigned& fts_executable,
+                  unsigned& fts_debuginfo,
+                  unsigned& fts_sourcefiles)
+{
+  int64_t fileid = register_file_name(ps_upsert_fileparts, ps_upsert_file, ps_lookup_file, rps);
+
+  /* See if we know of it already. */
+  int rc = ps_query
+    .reset()
+    .bind(1, fileid)
+    .bind(2, st.st_mtime)
+    .step();
+  ps_query.reset();
+  if (rc == SQLITE_ROW) // i.e., a result, as opposed to DONE (no results)
+    // no need to recheck a file/version we already know
+    // specifically, no need to elf-begin a file we already determined is non-elf
+    // (so is stored with buildid=NULL)
+    {
+      fts_cached++;
+      return;
+    }
+
+  bool executable_p = false, debuginfo_p = false; // E and/or D
+  string buildid;
+  set<string> sourcefiles;
+
+  int fd = open (rps.c_str(), O_RDONLY);
+  try
+    {
+      if (fd >= 0)
+        elf_classify (fd, executable_p, debuginfo_p, buildid, sourcefiles);
+      else
+        throw libc_exception(errno, string("open ") + rps);
+      add_metric ("scanned_bytes_total","source","file",
+                  st.st_size);
+      inc_metric ("scanned_files_total","source","file");
+    }
+  // NB: we catch exceptions here too, so that we can
+  // cache the corrupt-elf case (!executable_p &&
+  // !debuginfo_p) just below, just as if we had an
+  // EPERM error from open(2).
+  catch (const reportable_exception& e)
+    {
+      e.report(clog);
+    }
+
+  if (fd >= 0)
+    close (fd);
+
+  if (buildid == "")
+    {
+      // no point storing an elf file without buildid
+      executable_p = false;
+      debuginfo_p = false;
+    }
+  else
+    {
+      // register this build-id in the interning table
+      ps_upsert_buildids
+        .reset()
+        .bind(1, buildid)
+        .step_ok_done();
+    }
+
+  if (executable_p)
+    fts_executable ++;
+  if (debuginfo_p)
+    fts_debuginfo ++;
+  if (executable_p || debuginfo_p)
+    {
+      ps_upsert_de
+        .reset()
+        .bind(1, buildid)
+        .bind(2, debuginfo_p ? 1 : 0)
+        .bind(3, executable_p ? 1 : 0)
+        .bind(4, fileid)
+        .bind(5, st.st_mtime)
+        .step_ok_done();
+    }
+  if (executable_p)
+    inc_metric("found_executable_total","source","files");
+  if (debuginfo_p)
+    inc_metric("found_debuginfo_total","source","files");
+
+  if (sourcefiles.size() && buildid != "")
+    {
+      fts_sourcefiles += sourcefiles.size();
+
+      for (auto&& dwarfsrc : sourcefiles)
+        {
+          char *srp = realpath(dwarfsrc.c_str(), NULL);
+          if (srp == NULL) // also if DWZ unresolved dwarfsrc=""
+            continue; // unresolvable files are not a serious problem
+          // throw libc_exception(errno, "fts/file realpath " + srcpath);
+          string srps = string(srp);
+          free (srp);
+
+          struct stat sfs;
+          rc = stat(srps.c_str(), &sfs);
+          if (rc != 0)
+            continue;
+
+          if (verbose > 2)
+            obatched(clog) << "recorded buildid=" << buildid << " file=" << srps
+                           << " mtime=" << sfs.st_mtime
+                           << " as source " << dwarfsrc << endl;
+
+          // PR25548: store canonicalized dwarfsrc path
+          string dwarfsrc_canon = canon_pathname (dwarfsrc);
+          if (dwarfsrc_canon != dwarfsrc)
+            {
+              if (verbose > 3)
+                obatched(clog) << "canonicalized src=" << dwarfsrc << " alias=" << dwarfsrc_canon << endl;
+            }
+
+          int64_t fileid1 = register_file_name (ps_upsert_fileparts, ps_upsert_file, ps_lookup_file, dwarfsrc_canon);
+          int64_t fileid2 = register_file_name (ps_upsert_fileparts, ps_upsert_file, ps_lookup_file, srps);
+
+          ps_upsert_s
+            .reset()
+            .bind(1, buildid)
+            .bind(2, fileid1)
+            .bind(3, fileid2)
+            .bind(4, sfs.st_mtime)
+            .step_ok_done();
+
+          inc_metric("found_sourcerefs_total","source","files");
+        }
+    }
+
+  ps_scan_done
+    .reset()
+    .bind(1, fileid)
+    .bind(2, st.st_mtime)
+    .bind(3, st.st_size)
+    .step_ok_done();
+
+  if (verbose > 2)
+    obatched(clog) << "recorded buildid=" << buildid << " file=" << rps
+                   << " mtime=" << st.st_mtime << " atype="
+                   << (executable_p ? "E" : "")
+                   << (debuginfo_p ? "D" : "") << endl;
+}
+
+
+
+
+
+// Analyze given archive file of given age; record buildids / exec/debuginfo-ness of its
+// constituent files with given upsert statements.
+static void
+archive_classify (const string& rps, string& archive_extension, int64_t archiveid,
+                  sqlite_ps& ps_upsert_buildids, sqlite_ps& ps_upsert_fileparts, sqlite_ps& ps_upsert_file,
+                  sqlite_ps& ps_lookup_file,
+                  sqlite_ps& ps_upsert_de, sqlite_ps& ps_upsert_sref, sqlite_ps& ps_upsert_sdef,
+                  time_t mtime,
+                  unsigned& fts_executable, unsigned& fts_debuginfo, unsigned& fts_sref, unsigned& fts_sdef,
+                  bool& fts_sref_complete_p)
+{
+  string archive_decoder = "/dev/null";
+  for (auto&& arch : scan_archives)
+    if (string_endswith(rps, arch.first))
+      {
+        archive_extension = arch.first;
+        archive_decoder = arch.second;
+      }
+
+  FILE* fp;
+  defer_dtor<FILE*,int>::dtor_fn dfn;
+  if (archive_decoder != "cat")
+    {
+      string popen_cmd = archive_decoder + " " + shell_escape(rps);
+      fp = popen (popen_cmd.c_str(), "r"); // "e" O_CLOEXEC?
+      dfn = pclose;
+      if (fp == NULL)
+        throw libc_exception (errno, string("popen ") + popen_cmd);
+    }
+  else
+    {
+      fp = fopen (rps.c_str(), "r");
+      dfn = fclose;
+      if (fp == NULL)
+        throw libc_exception (errno, string("fopen ") + rps);
+    }
+  defer_dtor<FILE*,int> fp_closer (fp, dfn);
+
+  struct archive *a;
+  a = archive_read_new();
+  if (a == NULL)
+    throw archive_exception("cannot create archive reader");
+  defer_dtor<struct archive*,int> archive_closer (a, archive_read_free);
+
+  int rc = archive_read_support_format_all(a);
+  if (rc != ARCHIVE_OK)
+    throw archive_exception(a, "cannot select all formats");
+  rc = archive_read_support_filter_all(a);
+  if (rc != ARCHIVE_OK)
+    throw archive_exception(a, "cannot select all filters");
+
+  rc = archive_read_open_FILE (a, fp);
+  if (rc != ARCHIVE_OK)
+    {
+      obatched(clog) << "cannot open archive from pipe " << rps << endl;
+      throw archive_exception(a, "cannot open archive from pipe");
+    }
+
+  if (verbose > 3)
+    obatched(clog) << "libarchive scanning " << rps << " id " << archiveid << endl;
+
+  bool any_exceptions = false;
+  while(1) // parse archive entries
+    {
+    if (interrupted)
+      break;
+
+    try
+        {
+          struct archive_entry *e;
+          rc = archive_read_next_header (a, &e);
+          if (rc != ARCHIVE_OK)
+            break;
+
+          if (! S_ISREG(archive_entry_mode (e))) // skip non-files completely
+            continue;
+
+          string fn = canonicalized_archive_entry_pathname (e);
+
+          if (verbose > 3)
+            obatched(clog) << "libarchive checking " << fn << endl;
+
+          // extract this file to a temporary file
+          char* tmppath = NULL;
+          rc = asprintf (&tmppath, "%s/debuginfod-classify.XXXXXX", tmpdir.c_str());
+          if (rc < 0)
+            throw libc_exception (ENOMEM, "cannot allocate tmppath");
+          defer_dtor<void*,void> tmmpath_freer (tmppath, free);
+          int fd = mkstemp (tmppath);
+          if (fd < 0)
+            throw libc_exception (errno, "cannot create temporary file");
+          unlink (tmppath); // unlink now so OS will release the file as soon as we close the fd
+          defer_dtor<int,int> minifd_closer (fd, close);
+
+          rc = archive_read_data_into_fd (a, fd);
+          if (rc != ARCHIVE_OK) {
+            close (fd);
+            throw archive_exception(a, "cannot extract file");
+          }
+
+          // finally ... time to run elf_classify on this bad boy and update the database
+          bool executable_p = false, debuginfo_p = false;
+          string buildid;
+          set<string> sourcefiles;
+          elf_classify (fd, executable_p, debuginfo_p, buildid, sourcefiles);
+          // NB: might throw
+
+          if (buildid != "") // intern buildid
+            {
+              ps_upsert_buildids
+                .reset()
+                .bind(1, buildid)
+                .step_ok_done();
+            }
+
+          int64_t fileid = register_file_name (ps_upsert_fileparts, ps_upsert_file, ps_lookup_file, fn);
+
+          if (sourcefiles.size() > 0) // sref records needed
+            {
+              // NB: we intern each source file once.  Once raw, as it
+              // appears in the DWARF file list coming back from
+              // elf_classify() - because it'll end up in the
+              // _norm.artifactsrc column.  We don't also put another
+              // version with a '.' at the front, even though that's
+              // how rpm/cpio packs names, because we hide that from
+              // the database for storage efficiency.
+
+              for (auto&& s : sourcefiles)
+                {
+                  if (s == "")
+                    {
+                      fts_sref_complete_p = false;
+                      continue;
+                    }
+
+                  // PR25548: store canonicalized source path
+                  const string& dwarfsrc = s;
+                  string dwarfsrc_canon = canon_pathname (dwarfsrc);
+                  if (dwarfsrc_canon != dwarfsrc)
+                    {
+                      if (verbose > 3)
+                        obatched(clog) << "canonicalized src=" << dwarfsrc << " alias=" << dwarfsrc_canon << endl;
+                    }
+
+                  int64_t srcfileid = register_file_name(ps_upsert_fileparts, ps_upsert_file, ps_lookup_file,
+                                                         dwarfsrc_canon);
+                
+                  ps_upsert_sref
+                    .reset()
+                    .bind(1, buildid)
+                    .bind(2, srcfileid)
+                    .step_ok_done();
+
+                  fts_sref ++;
+                }
+            }
+
+          if (executable_p)
+            fts_executable ++;
+          if (debuginfo_p)
+            fts_debuginfo ++;
+
+          if (executable_p || debuginfo_p)
+            {
+              ps_upsert_de
+                .reset()
+                .bind(1, buildid)
+                .bind(2, debuginfo_p ? 1 : 0)
+                .bind(3, executable_p ? 1 : 0)
+                .bind(4, archiveid)
+                .bind(5, mtime)
+                .bind(6, fileid)
+                .step_ok_done();
+            }
+          else // potential source - sdef record
+            {
+              fts_sdef ++;
+              ps_upsert_sdef
+                .reset()
+                .bind(1, archiveid)
+                .bind(2, mtime)
+                .bind(3, fileid)
+                .step_ok_done();
+            }
+
+          if ((verbose > 2) && (executable_p || debuginfo_p))
+            obatched(clog) << "recorded buildid=" << buildid << " rpm=" << rps << " file=" << fn
+                           << " mtime=" << mtime << " atype="
+                           << (executable_p ? "E" : "")
+                           << (debuginfo_p ? "D" : "")
+                           << " sourcefiles=" << sourcefiles.size() << endl;
+
+        }
+      catch (const reportable_exception& e)
+        {
+          e.report(clog);
+          any_exceptions = true;
+          // NB: but we allow the libarchive iteration to continue, in
+          // case we can still gather some useful information.  That
+          // would allow some webapi queries to work, until later when
+          // this archive is rescanned.  (Its vitals won't go into the
+          // _file_mtime_scanned table until after a successful scan.)
+        }
+    }
+
+  if (any_exceptions)
+    throw reportable_exception("exceptions encountered during archive scan");
+}
+
+
+
+// scan for archive files such as .rpm
+static void
+scan_archive_file (const string& rps, const stat_t& st,
+                   sqlite_ps& ps_upsert_buildids,
+                   sqlite_ps& ps_upsert_fileparts,
+                   sqlite_ps& ps_upsert_file,
+                   sqlite_ps& ps_lookup_file,
+                   sqlite_ps& ps_upsert_de,
+                   sqlite_ps& ps_upsert_sref,
+                   sqlite_ps& ps_upsert_sdef,
+                   sqlite_ps& ps_query,
+                   sqlite_ps& ps_scan_done,
+                   unsigned& fts_cached,
+                   unsigned& fts_executable,
+                   unsigned& fts_debuginfo,
+                   unsigned& fts_sref,
+                   unsigned& fts_sdef)
+{
+  // intern the archive file name
+  int64_t archiveid = register_file_name (ps_upsert_fileparts, ps_upsert_file, ps_lookup_file, rps);
+
+  /* See if we know of it already. */
+  int rc = ps_query
+    .reset()
+    .bind(1, archiveid)
+    .bind(2, st.st_mtime)
+    .step();
+  ps_query.reset();
+  if (rc == SQLITE_ROW) // i.e., a result, as opposed to DONE (no results)
+    // no need to recheck a file/version we already know
+    // specifically, no need to parse this archive again, since we already have
+    // it as a D or E or S record,
+    // (so is stored with buildid=NULL)
+    {
+      fts_cached ++;
+      return;
+    }
+
+  // extract the archive contents
+  unsigned my_fts_executable = 0, my_fts_debuginfo = 0, my_fts_sref = 0, my_fts_sdef = 0;
+  bool my_fts_sref_complete_p = true;
+  bool any_exceptions = false;
+  try
+    {
+      string archive_extension;
+      archive_classify (rps, archive_extension, archiveid,
+                        ps_upsert_buildids, ps_upsert_fileparts, ps_upsert_file, ps_lookup_file,
+                        ps_upsert_de, ps_upsert_sref, ps_upsert_sdef, // dalt
+                        st.st_mtime,
+                        my_fts_executable, my_fts_debuginfo, my_fts_sref, my_fts_sdef,
+                        my_fts_sref_complete_p);
+      add_metric ("scanned_bytes_total","source",archive_extension + " archive",
+                  st.st_size);
+      inc_metric ("scanned_files_total","source",archive_extension + " archive");
+      add_metric("found_debuginfo_total","source",archive_extension + " archive",
+                 my_fts_debuginfo);
+      add_metric("found_executable_total","source",archive_extension + " archive",
+                 my_fts_executable);
+      add_metric("found_sourcerefs_total","source",archive_extension + " archive",
+                 my_fts_sref);
+    }
+  catch (const reportable_exception& e)
+    {
+      e.report(clog);
+      any_exceptions = true;
+    }
+
+  if (verbose > 2)
+    obatched(clog) << "scanned archive=" << rps
+                   << " mtime=" << st.st_mtime
+                   << " executables=" << my_fts_executable
+                   << " debuginfos=" << my_fts_debuginfo
+                   << " srefs=" << my_fts_sref
+                   << " sdefs=" << my_fts_sdef
+                   << " exceptions=" << any_exceptions
+                   << endl;
+
+  fts_executable += my_fts_executable;
+  fts_debuginfo += my_fts_debuginfo;
+  fts_sref += my_fts_sref;
+  fts_sdef += my_fts_sdef;
+
+  if (any_exceptions)
+    throw reportable_exception("exceptions encountered during archive scan");
+
+  if (my_fts_sref_complete_p) // leave incomplete?
+    ps_scan_done
+      .reset()
+      .bind(1, archiveid)
+      .bind(2, st.st_mtime)
+      .bind(3, st.st_size)
+      .step_ok_done();
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+
+// The thread that consumes file names off of the scanq.  We hold
+// the persistent sqlite_ps's at this level and delegate file/archive
+// scanning to other functions.
+static void
+scan ()
+{
+  // all the prepared statements fit to use, the _f_ set:
+  sqlite_ps ps_f_upsert_buildids (db, "file-buildids-intern", "insert or ignore into " BUILDIDS "_buildids VALUES (NULL, ?);");
+  sqlite_ps ps_f_upsert_fileparts (db, "file-fileparts-intern", "insert or ignore into " BUILDIDS "_fileparts VALUES (NULL, ?);");
+  sqlite_ps ps_f_upsert_file (db, "file-file-intern", "insert or ignore into " BUILDIDS "_files VALUES (NULL, \n"
+                              "(select id from " BUILDIDS "_fileparts where name = ?),\n"
+                              "(select id from " BUILDIDS "_fileparts where name = ?));");
+  sqlite_ps ps_f_lookup_file (db, "file-file-lookup",
+                              "select f.id\n"
+                              " from " BUILDIDS "_files f, " BUILDIDS "_fileparts p1, " BUILDIDS "_fileparts p2 \n"
+                              " where f.dirname = p1.id and f.basename = p2.id and p1.name = ? and p2.name = ?;\n");
+  sqlite_ps ps_f_upsert_de (db, "file-de-upsert",
+                          "insert or ignore into " BUILDIDS "_f_de "
+                          "(buildid, debuginfo_p, executable_p, file, mtime) "
+                          "values ((select id from " BUILDIDS "_buildids where hex = ?),"
+                            "        ?,?,?,?);");
+  sqlite_ps ps_f_upsert_s (db, "file-s-upsert",
+                         "insert or ignore into " BUILDIDS "_f_s "
+                         "(buildid, artifactsrc, file, mtime) "
+                         "values ((select id from " BUILDIDS "_buildids where hex = ?),"
+                         "      ?,?,?);");
+  sqlite_ps ps_f_query (db, "file-negativehit-find",
+                        "select 1 from " BUILDIDS "_file_mtime_scanned where sourcetype = 'F' "
+                        "and file = ? and mtime = ?;");
+  sqlite_ps ps_f_scan_done (db, "file-scanned",
+                          "insert or ignore into " BUILDIDS "_file_mtime_scanned (sourcetype, file, mtime, size)"
+                          "values ('F', ?,?,?);");
+
+  // and now for the _r_ set
+  sqlite_ps ps_r_upsert_buildids (db, "rpm-buildid-intern", "insert or ignore into " BUILDIDS "_buildids VALUES (NULL, ?);");
+  sqlite_ps ps_r_upsert_fileparts (db, "rpm-fileparts-intern", "insert or ignore into " BUILDIDS "_fileparts VALUES (NULL, ?);");
+  sqlite_ps ps_r_upsert_file (db, "rpm-file-intern", "insert or ignore into " BUILDIDS "_files VALUES (NULL, \n"
+                              "(select id from " BUILDIDS "_fileparts where name = ?),\n"
+                              "(select id from " BUILDIDS "_fileparts where name = ?));");
+  sqlite_ps ps_r_lookup_file (db, "rpm-file-lookup",
+                              "select f.id\n"
+                              " from " BUILDIDS "_files f, " BUILDIDS "_fileparts p1, " BUILDIDS "_fileparts p2 \n"
+                              " where f.dirname = p1.id and f.basename = p2.id and p1.name = ? and p2.name = ?;\n");
+  sqlite_ps ps_r_upsert_de (db, "rpm-de-insert",
+                          "insert or ignore into " BUILDIDS "_r_de (buildid, debuginfo_p, executable_p, file, mtime, content) values ("
+                          "(select id from " BUILDIDS "_buildids where hex = ?), ?, ?, ?, ?, ?);");
+  sqlite_ps ps_r_upsert_sref (db, "rpm-sref-insert",
+                            "insert or ignore into " BUILDIDS "_r_sref (buildid, artifactsrc) values ("
+                            "(select id from " BUILDIDS "_buildids where hex = ?), "
+                            "?);");
+  sqlite_ps ps_r_upsert_sdef (db, "rpm-sdef-insert",
+                            "insert or ignore into " BUILDIDS "_r_sdef (file, mtime, content) values ("
+                            "?, ?, ?);");
+  sqlite_ps ps_r_query (db, "rpm-negativehit-query",
+                      "select 1 from " BUILDIDS "_file_mtime_scanned where "
+                      "sourcetype = 'R' and file = ? and mtime = ?;");
+  sqlite_ps ps_r_scan_done (db, "rpm-scanned",
+                          "insert or ignore into " BUILDIDS "_file_mtime_scanned (sourcetype, file, mtime, size)"
+                          "values ('R', ?, ?, ?);");
+  
+
+  unsigned fts_cached = 0, fts_executable = 0, fts_debuginfo = 0, fts_sourcefiles = 0;
+  unsigned fts_sref = 0, fts_sdef = 0;
+
+  add_metric("thread_count", "role", "scan", 1);
+  add_metric("thread_busy", "role", "scan", 1);
+  while (! interrupted)
+    {
+      scan_payload p;
+
+      add_metric("thread_busy", "role", "scan", -1);
+      // NB: threads may be blocked within either of these two waiting
+      // states, if the work queue happens to run dry.  That's OK.
+      if (scan_barrier) scan_barrier->count();
+      bool gotone = scanq.wait_front(p);
+      add_metric("thread_busy", "role", "scan", 1);
+
+      if (! gotone) continue; // go back to waiting
+
+      try
+        {
+          bool scan_archive = false;
+          for (auto&& arch : scan_archives)
+            if (string_endswith(p.first, arch.first))
+              scan_archive = true;
+
+          if (scan_archive)
+            scan_archive_file (p.first, p.second,
+                               ps_r_upsert_buildids,
+                               ps_r_upsert_fileparts,
+                               ps_r_upsert_file,
+                               ps_r_lookup_file,
+                               ps_r_upsert_de,
+                               ps_r_upsert_sref,
+                               ps_r_upsert_sdef,
+                               ps_r_query,
+                               ps_r_scan_done,
+                               fts_cached,
+                               fts_executable,
+                               fts_debuginfo,
+                               fts_sref,
+                               fts_sdef);
+
+          if (scan_files) // NB: maybe "else if" ?
+            scan_source_file (p.first, p.second,
+                              ps_f_upsert_buildids,
+                              ps_f_upsert_fileparts,
+                              ps_f_upsert_file,
+                              ps_f_lookup_file,
+                              ps_f_upsert_de,
+                              ps_f_upsert_s,
+                              ps_f_query,
+                              ps_f_scan_done,
+                              fts_cached, fts_executable, fts_debuginfo, fts_sourcefiles);
+        }
+      catch (const reportable_exception& e)
+        {
+          e.report(cerr);
+        }
+
+      scanq.done_front(); // let idlers run
+      
+      if (fts_cached || fts_executable || fts_debuginfo || fts_sourcefiles || fts_sref || fts_sdef)
+        {} // NB: not just if a successful scan - we might have encountered -ENOSPC & failed
+      (void) statfs_free_enough_p(db_path, "database"); // report sqlite filesystem size
+      (void) statfs_free_enough_p(tmpdir, "tmpdir"); // this too, in case of fdcache/tmpfile usage
+
+      // finished a scanning step -- not a "loop", because we just
+      // consume the traversal loop's work, whenever
+      inc_metric("thread_work_total","role","scan");
+    }
+
+  add_metric("thread_busy", "role", "scan", -1);
+}
+
+
+// Use this function as the thread entry point, so it can catch our
+// fleet of exceptions (incl. the sqlite_ps ctors) and report.
+static void*
+thread_main_scanner (void* arg)
+{
+  (void) arg;
+  while (! interrupted)
+    try
+      {
+        scan();
+      }
+    catch (const reportable_exception& e)
+      {
+        e.report(cerr);
+      }
+  return 0;
+}
+
+
+
+// The thread that traverses all the source_paths and enqueues all the
+// matching files into the file/archive scan queue.
+static void
+scan_source_paths()
+{
+  // NB: fedora 31 glibc/fts(3) crashes inside fts_read() on empty
+  // path list.
+  if (source_paths.empty())
+    return;
+
+  // Turn the source_paths into an fts(3)-compatible char**.  Since
+  // source_paths[] does not change after argv processing, the
+  // c_str()'s are safe to keep around awile.
+  vector<const char *> sps;
+  for (auto&& sp: source_paths)
+    sps.push_back(sp.c_str());
+  sps.push_back(NULL);
+
+  FTS *fts = fts_open ((char * const *)sps.data(),
+                      (traverse_logical ? FTS_LOGICAL : FTS_PHYSICAL|FTS_XDEV)
+                      | FTS_NOCHDIR /* multithreaded */,
+                      NULL);
+  if (fts == NULL)
+    throw libc_exception(errno, "cannot fts_open");
+  defer_dtor<FTS*,int> fts_cleanup (fts, fts_close);
+
+  struct timespec ts_start, ts_end;
+  clock_gettime (CLOCK_MONOTONIC, &ts_start);
+  unsigned fts_scanned = 0, fts_regex = 0;
+
+  FTSENT *f;
+  while ((f = fts_read (fts)) != NULL)
+  {
+    if (interrupted) break;
+
+    if (sigusr2 != forced_groom_count) // stop early if groom triggered
+      {
+        scanq.clear(); // clear previously issued work for scanner threads
+        break;
+      }
+
+    fts_scanned ++;
+
+    if (verbose > 2)
+      obatched(clog) << "fts traversing " << f->fts_path << endl;
+
+    switch (f->fts_info)
+      {
+      case FTS_F:
+        {
+          /* Found a file.  Convert it to an absolute path, so
+             the buildid database does not have relative path
+             names that are unresolvable from a subsequent run
+             in a different cwd. */
+          char *rp = realpath(f->fts_path, NULL);
+          if (rp == NULL)
+            continue; // ignore dangling symlink or such
+          string rps = string(rp);
+          free (rp);
+
+          bool ri = !regexec (&file_include_regex, rps.c_str(), 0, 0, 0);
+          bool rx = !regexec (&file_exclude_regex, rps.c_str(), 0, 0, 0);
+          if (!ri || rx)
+            {
+              if (verbose > 3)
+                obatched(clog) << "fts skipped by regex "
+                               << (!ri ? "I" : "") << (rx ? "X" : "") << endl;
+              fts_regex ++;
+              if (!ri)
+                inc_metric("traversed_total","type","file-skipped-I");
+              if (rx)
+                inc_metric("traversed_total","type","file-skipped-X");
+            }
+          else
+            {
+              scanq.push_back (make_pair(rps, *f->fts_statp));
+              inc_metric("traversed_total","type","file");
+            }
+        }
+        break;
+
+      case FTS_ERR:
+      case FTS_NS:
+        // report on some types of errors because they may reflect fixable misconfiguration
+        {
+          auto x = libc_exception(f->fts_errno, string("fts traversal ") + string(f->fts_path));
+          x.report(cerr);
+        }
+        inc_metric("traversed_total","type","error");
+        break;
+
+      case FTS_SL: // ignore, but count because debuginfod -L would traverse these
+        inc_metric("traversed_total","type","symlink");
+        break;
+
+      case FTS_D: // ignore
+        inc_metric("traversed_total","type","directory");
+        break;
+
+      default: // ignore
+        inc_metric("traversed_total","type","other");
+        break;
+      }
+  }
+  clock_gettime (CLOCK_MONOTONIC, &ts_end);
+  double deltas = (ts_end.tv_sec - ts_start.tv_sec) + (ts_end.tv_nsec - ts_start.tv_nsec)/1.e9;
+
+  obatched(clog) << "fts traversed source paths in " << deltas << "s, scanned=" << fts_scanned
+                 << ", regex-skipped=" << fts_regex << endl;
+}
+
+
+static void*
+thread_main_fts_source_paths (void* arg)
+{
+  (void) arg; // ignore; we operate on global data
+
+  set_metric("thread_tid", "role","traverse", tid());
+  add_metric("thread_count", "role", "traverse", 1);
+
+  time_t last_rescan = 0;
+
+  while (! interrupted)
+    {
+      sleep (1);
+      scanq.wait_idle(); // don't start a new traversal while scanners haven't finished the job
+      scanq.done_idle(); // release the hounds
+      if (interrupted) break;
+
+      time_t now = time(NULL);
+      bool rescan_now = false;
+      if (last_rescan == 0) // at least one initial rescan is documented even for -t0
+        rescan_now = true;
+      if (rescan_s > 0 && (long)now > (long)(last_rescan + rescan_s))
+        rescan_now = true;
+      if (sigusr1 != forced_rescan_count)
+        {
+          forced_rescan_count = sigusr1;
+          rescan_now = true;
+        }
+      if (rescan_now)
+        {
+          set_metric("thread_busy", "role","traverse", 1);
+          try
+            {
+              scan_source_paths();
+            }
+          catch (const reportable_exception& e)
+            {
+              e.report(cerr);
+            }
+          last_rescan = time(NULL); // NB: now was before scanning
+          // finished a traversal loop
+          inc_metric("thread_work_total", "role","traverse");
+          set_metric("thread_busy", "role","traverse", 0);
+        }
+    }
+
+  return 0;
+}
+
+
+
+////////////////////////////////////////////////////////////////////////
+
+static void
+database_stats_report()
+{
+  sqlite_ps ps_query (db, "database-overview",
+                      "select label,quantity from " BUILDIDS "_stats");
+
+  obatched(clog) << "database record counts:" << endl;
+  while (1)
+    {
+      if (interrupted) break;
+      if (sigusr1 != forced_rescan_count) // stop early if scan triggered
+        break;
+
+      int rc = ps_query.step();
+      if (rc == SQLITE_DONE) break;
+      if (rc != SQLITE_ROW)
+        throw sqlite_exception(rc, "step");
+
+      obatched(clog)
+        << ((const char*) sqlite3_column_text(ps_query, 0) ?: (const char*) "NULL")
+        << " "
+        << (sqlite3_column_text(ps_query, 1) ?: (const unsigned char*) "NULL")
+        << endl;
+
+      set_metric("groom", "statistic",
+                 ((const char*) sqlite3_column_text(ps_query, 0) ?: (const char*) "NULL"),
+                 (sqlite3_column_double(ps_query, 1)));
+    }
+}
+
+
+// Do a round of database grooming that might take many minutes to run.
+void groom()
+{
+  obatched(clog) << "grooming database" << endl;
+
+  struct timespec ts_start, ts_end;
+  clock_gettime (CLOCK_MONOTONIC, &ts_start);
+
+  // scan for files that have disappeared
+  sqlite_ps files (db, "check old files",
+                   "select distinct s.mtime, s.file, f.name from "
+                   BUILDIDS "_file_mtime_scanned s, " BUILDIDS "_files_v f "
+                   "where f.id = s.file");
+  // NB: Because _ftime_mtime_scanned can contain both F and
+  // R records for the same file, this query would return duplicates if the
+  // DISTINCT qualifier were not there.
+  files.reset();
+
+  // DECISION TIME - we enumerate stale fileids/mtimes
+  deque<pair<int64_t,int64_t> > stale_fileid_mtime;
+  
+  time_t time_start = time(NULL);
+  while(1)
+    {
+      // PR28514: limit grooming iteration to O(rescan time), to avoid
+      // slow filesystem tests over many files locking out rescans for
+      // too long.
+      if (rescan_s > 0 && (long)time(NULL) > (long)(time_start + rescan_s))
+        {
+          inc_metric("groomed_total", "decision", "aborted");
+          break;
+        }
+
+      if (interrupted) break;
+
+      int rc = files.step();
+      if (rc != SQLITE_ROW)
+        break;
+
+      int64_t mtime = sqlite3_column_int64 (files, 0);
+      int64_t fileid = sqlite3_column_int64 (files, 1);
+      const char* filename = ((const char*) sqlite3_column_text (files, 2) ?: "");
+      struct stat s;
+      bool regex_file_drop = 0;
+
+      if (regex_groom)
+        {
+          bool reg_include = !regexec (&file_include_regex, filename, 0, 0, 0);
+          bool reg_exclude = !regexec (&file_exclude_regex, filename, 0, 0, 0);
+          regex_file_drop = !reg_include || reg_exclude; // match logic of scan_source_paths  
+        }
+
+      rc = stat(filename, &s);
+      if ( regex_file_drop ||  rc < 0 || (mtime != (int64_t) s.st_mtime) )
+        {
+          if (verbose > 2)
+            obatched(clog) << "groom: stale file=" << filename << " mtime=" << mtime << endl;
+          stale_fileid_mtime.push_back(make_pair(fileid,mtime));
+          inc_metric("groomed_total", "decision", "stale");
+          set_metric("thread_work_pending","role","groom", stale_fileid_mtime.size());
+        }
+      else
+        inc_metric("groomed_total", "decision", "fresh");
+      
+      if (sigusr1 != forced_rescan_count) // stop early if scan triggered
+        break;
+    }
+  files.reset();
+
+  // ACTION TIME
+
+  // Now that we know which file/mtime tuples are stale, actually do
+  // the deletion from the database.  Doing this during the SELECT
+  // iteration above results in undefined behaviour in sqlite, as per
+  // https://www.sqlite.org/isolation.html
+
+  // We could shuffle stale_fileid_mtime[] here.  It'd let aborted
+  // sequences of nuke operations resume at random locations, instead
+  // of just starting over.  But it doesn't matter much either way,
+  // as long as we make progress.
+
+  sqlite_ps files_del_f_de (db, "nuke f_de", "delete from " BUILDIDS "_f_de where file = ? and mtime = ?");
+  sqlite_ps files_del_r_de (db, "nuke r_de", "delete from " BUILDIDS "_r_de where file = ? and mtime = ?");
+  sqlite_ps files_del_scan (db, "nuke f_m_s", "delete from " BUILDIDS "_file_mtime_scanned "
+                            "where file = ? and mtime = ?");
+
+  while (! stale_fileid_mtime.empty())
+    {
+      auto stale = stale_fileid_mtime.front();
+      stale_fileid_mtime.pop_front();
+      set_metric("thread_work_pending","role","groom", stale_fileid_mtime.size());
+
+      // PR28514: limit grooming iteration to O(rescan time), to avoid
+      // slow nuke_* queries over many files locking out rescans for too
+      // long.  We iterate over the files in random() sequence to avoid
+      // partial checks going over the same set.
+      if (rescan_s > 0 && (long)time(NULL) > (long)(time_start + rescan_s))
+        {
+          inc_metric("groomed_total", "action", "aborted");
+          break;
+        }
+
+      if (interrupted) break;
+
+      int64_t fileid = stale.first;
+      int64_t mtime = stale.second;
+      files_del_f_de.reset().bind(1,fileid).bind(2,mtime).step_ok_done();
+      files_del_r_de.reset().bind(1,fileid).bind(2,mtime).step_ok_done();
+      files_del_scan.reset().bind(1,fileid).bind(2,mtime).step_ok_done();
+      inc_metric("groomed_total", "action", "cleaned");
+      
+       if (sigusr1 != forced_rescan_count) // stop early if scan triggered
+        break;
+    }
+  stale_fileid_mtime.clear(); // no need for this any longer
+  set_metric("thread_work_pending","role","groom", stale_fileid_mtime.size());
+      
+  // delete buildids with no references in _r_de or _f_de tables;
+  // cascades to _r_sref & _f_s records
+  sqlite_ps buildids_del (db, "nuke orphan buildids",
+                          "delete from " BUILDIDS "_buildids "
+                          "where not exists (select 1 from " BUILDIDS "_f_de d where " BUILDIDS "_buildids.id = d.buildid) "
+                          "and not exists (select 1 from " BUILDIDS "_r_de d where " BUILDIDS "_buildids.id = d.buildid)");
+  buildids_del.reset().step_ok_done();
+
+  if (interrupted) return;
+
+  // NB: "vacuum" is too heavy for even daily runs: it rewrites the entire db, so is done as maxigroom -G
+  sqlite_ps g1 (db, "incremental vacuum", "pragma incremental_vacuum");
+  g1.reset().step_ok_done();
+  sqlite_ps g2 (db, "optimize", "pragma optimize");
+  g2.reset().step_ok_done();
+  sqlite_ps g3 (db, "wal checkpoint", "pragma wal_checkpoint=truncate");
+  g3.reset().step_ok_done();
+
+  database_stats_report();
+
+  (void) statfs_free_enough_p(db_path, "database"); // report sqlite filesystem size
+
+  sqlite3_db_release_memory(db); // shrink the process if possible
+  sqlite3_db_release_memory(dbq); // ... for both connections
+  debuginfod_pool_groom(); // and release any debuginfod_client objects we've been holding onto
+
+#if 0 /* PR31265: don't jettison cache unnecessarily */
+  
+  fdcache.limit(0); // release the fdcache contents
+  fdcache.limit(fdcache_mbs); // restore status quo parameters
+#endif
+  
+  clock_gettime (CLOCK_MONOTONIC, &ts_end);
+  double deltas = (ts_end.tv_sec - ts_start.tv_sec) + (ts_end.tv_nsec - ts_start.tv_nsec)/1.e9;
+
+  obatched(clog) << "groomed database in " << deltas << "s" << endl;
+}
+
+
+static void*
+thread_main_groom (void* /*arg*/)
+{
+  set_metric("thread_tid", "role", "groom", tid());
+  add_metric("thread_count", "role", "groom", 1);
+
+  time_t last_groom = 0;
+
+  while (1)
+    {
+      sleep (1);
+      scanq.wait_idle(); // PR25394: block scanners during grooming!
+      if (interrupted) break;
+
+      time_t now = time(NULL);
+      bool groom_now = false;
+      if (last_groom == 0) // at least one initial groom is documented even for -g0
+        groom_now = true;
+      if (groom_s > 0 && (long)now > (long)(last_groom + groom_s))
+        groom_now = true;
+      if (sigusr2 != forced_groom_count)
+        {
+          forced_groom_count = sigusr2;
+          groom_now = true;
+        }
+      if (groom_now)
+        {
+          set_metric("thread_busy", "role", "groom", 1);
+          try
+            {
+              groom ();
+            }
+          catch (const sqlite_exception& e)
+            {
+              obatched(cerr) << e.message << endl;
+            }
+          last_groom = time(NULL); // NB: now was before grooming
+          // finished a grooming loop
+          inc_metric("thread_work_total", "role", "groom");
+          set_metric("thread_busy", "role", "groom", 0);
+        }
+
+      scanq.done_idle();
+    }
+
+  return 0;
+}
+
+
+////////////////////////////////////////////////////////////////////////
+
+
+static void
+signal_handler (int /* sig */)
+{
+  interrupted ++;
+
+  if (db)
+    sqlite3_interrupt (db);
+  if (dbq)
+    sqlite3_interrupt (dbq);
+
+  // NB: don't do anything else in here
+}
+
+static void
+sigusr1_handler (int /* sig */)
+{
+   sigusr1 ++;
+  // NB: don't do anything else in here
+}
+
+static void
+sigusr2_handler (int /* sig */)
+{
+   sigusr2 ++;
+  // NB: don't do anything else in here
+}
+
+
+static void // error logging callback from libmicrohttpd internals
+error_cb (void *arg, const char *fmt, va_list ap)
+{
+  (void) arg;
+  inc_metric("error_count","libmicrohttpd",fmt);
+  char errmsg[512];
+  (void) vsnprintf (errmsg, sizeof(errmsg), fmt, ap); // ok if slightly truncated
+  obatched(cerr) << "libmicrohttpd error: " << errmsg; // MHD_DLOG calls already include \n
+}
+
+
+// A user-defined sqlite function, to score the sharedness of the
+// prefix of two strings.  This is used to compare candidate debuginfo
+// / source-rpm names, so that the closest match
+// (directory-topology-wise closest) is found.  This is important in
+// case the same sref (source file name) is in many -debuginfo or
+// -debugsource RPMs, such as when multiple versions/releases of the
+// same package are in the database.
+
+static void sqlite3_sharedprefix_fn (sqlite3_context* c, int argc, sqlite3_value** argv)
+{
+  if (argc != 2)
+    sqlite3_result_error(c, "expect 2 string arguments", -1);
+  else if ((sqlite3_value_type(argv[0]) != SQLITE_TEXT) ||
+           (sqlite3_value_type(argv[1]) != SQLITE_TEXT))
+    sqlite3_result_null(c);
+  else
+    {
+      const unsigned char* a = sqlite3_value_text (argv[0]);
+      const unsigned char* b = sqlite3_value_text (argv[1]);
+      int i = 0;
+      while (*a != '\0' && *b != '\0' && *a++ == *b++)
+        i++;
+      sqlite3_result_int (c, i);
+    }
+}
+
+
+static unsigned
+default_concurrency() // guaranteed >= 1
+{
+  // Prior to PR29975 & PR29976, we'd just use this: 
+  unsigned sth = std::thread::hardware_concurrency();
+  // ... but on many-CPU boxes, admins or distros may throttle
+  // resources in such a way that debuginfod would mysteriously fail.
+  // So we reduce the defaults:
+
+  unsigned aff = 0;
+#ifdef HAVE_SCHED_GETAFFINITY
+  {
+    int ret;
+    cpu_set_t mask;
+    CPU_ZERO(&mask);
+    ret = sched_getaffinity(0, sizeof(mask), &mask);
+    if (ret == 0)
+      aff = CPU_COUNT(&mask);
+  }
+#endif
+  
+  unsigned fn = 0;
+#ifdef HAVE_GETRLIMIT
+  {
+    struct rlimit rlim;
+    int rc = getrlimit(RLIMIT_NOFILE, &rlim);
+    if (rc == 0)
+      fn = max((rlim_t)1, (rlim.rlim_cur - 100) / 4);
+    // at least 2 fds are used by each listener thread etc.
+    // plus a bunch to account for shared libraries and such
+  }
+#endif
+
+  unsigned d = min(max(sth, 1U),
+                   min(max(aff, 1U),
+                       max(fn, 1U)));
+  return d;
+}
+
+
+// 30879: Something to help out in case of an uncaught exception.
+void my_terminate_handler()
+{
+#if defined(__GLIBC__)
+  void *array[40];
+  int size = backtrace (array, 40);
+  backtrace_symbols_fd (array, size, STDERR_FILENO);
+#endif
+#if defined(__GLIBCXX__) || defined(__GLIBCPP__)
+  __gnu_cxx::__verbose_terminate_handler();
+#endif
+  abort();
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  (void) setlocale (LC_ALL, "");
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+  (void) textdomain (PACKAGE_TARNAME);
+
+  std::set_terminate(& my_terminate_handler);
+
+  /* Tell the library which version we are expecting.  */
+  elf_version (EV_CURRENT);
+
+  tmpdir = string(getenv("TMPDIR") ?: "/tmp");
+
+  /* Set computed default values. */
+  db_path = string(getenv("HOME") ?: "/") + string("/.debuginfod.sqlite"); /* XDG? */
+  int rc = regcomp (& file_include_regex, ".*", REG_EXTENDED|REG_NOSUB); // match everything
+  if (rc != 0)
+    error (EXIT_FAILURE, 0, "regcomp failure: %d", rc);
+  rc = regcomp (& file_exclude_regex, "^$", REG_EXTENDED|REG_NOSUB); // match nothing
+  if (rc != 0)
+    error (EXIT_FAILURE, 0, "regcomp failure: %d", rc);
+
+  // default parameters for fdcache are computed from system stats
+  struct statfs sfs;
+  rc = statfs(tmpdir.c_str(), &sfs);
+  if (rc < 0)
+    fdcache_mbs = 1024; // 1 gigabyte
+  else
+    fdcache_mbs = sfs.f_bavail * sfs.f_bsize / 1024 / 1024 / 4; // 25% of free space
+  fdcache_mintmp = 25; // emergency flush at 25% remaining (75% full)
+  fdcache_prefetch = 64; // guesstimate storage is this much less costly than re-decompression
+
+  /* Parse and process arguments.  */
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
+  if (remaining != argc)
+      error (EXIT_FAILURE, 0,
+             "unexpected argument: %s", argv[remaining]);
+
+  if (scan_archives.size()==0 && !scan_files && source_paths.size()>0)
+    obatched(clog) << "warning: without -F -R -U -Z, ignoring PATHs" << endl;
+
+  fdcache.limit(fdcache_mbs);
+
+  (void) signal (SIGPIPE, SIG_IGN); // microhttpd can generate it incidentally, ignore
+  (void) signal (SIGINT, signal_handler); // ^C
+  (void) signal (SIGHUP, signal_handler); // EOF
+  (void) signal (SIGTERM, signal_handler); // systemd
+  (void) signal (SIGUSR1, sigusr1_handler); // end-user
+  (void) signal (SIGUSR2, sigusr2_handler); // end-user
+
+  /* Get database ready. */
+  if (! passive_p)
+    {
+      rc = sqlite3_open_v2 (db_path.c_str(), &db, (SQLITE_OPEN_READWRITE
+                                                   |SQLITE_OPEN_URI
+                                                   |SQLITE_OPEN_PRIVATECACHE
+                                                   |SQLITE_OPEN_CREATE
+                                                   |SQLITE_OPEN_FULLMUTEX), /* thread-safe */
+                            NULL);
+      if (rc == SQLITE_CORRUPT)
+        {
+          (void) unlink (db_path.c_str());
+          error (EXIT_FAILURE, 0,
+                 "cannot open %s, deleted database: %s", db_path.c_str(), sqlite3_errmsg(db));
+        }
+      else if (rc)
+        {
+          error (EXIT_FAILURE, 0,
+                 "cannot open %s, consider deleting database: %s", db_path.c_str(), sqlite3_errmsg(db));
+        }
+    }
+
+  // open the readonly query variant
+  // NB: PRIVATECACHE allows web queries to operate in parallel with
+  // much other grooming/scanning operation.
+  rc = sqlite3_open_v2 (db_path.c_str(), &dbq, (SQLITE_OPEN_READONLY
+                                                |SQLITE_OPEN_URI
+                                                |SQLITE_OPEN_PRIVATECACHE
+                                                |SQLITE_OPEN_FULLMUTEX), /* thread-safe */
+                        NULL);
+  if (rc)
+    {
+      error (EXIT_FAILURE, 0,
+             "cannot open %s, consider deleting database: %s", db_path.c_str(), sqlite3_errmsg(dbq));
+    }
+
+
+  obatched(clog) << "opened database " << db_path
+                 << (db?" rw":"") << (dbq?" ro":"") << endl;
+  obatched(clog) << "sqlite version " << sqlite3_version << endl;
+  obatched(clog) << "service mode " << (passive_p ? "passive":"active") << endl;
+
+  // add special string-prefix-similarity function used in rpm sref/sdef resolution
+  rc = sqlite3_create_function(dbq, "sharedprefix", 2, SQLITE_UTF8, NULL,
+                               & sqlite3_sharedprefix_fn, NULL, NULL);
+  if (rc != SQLITE_OK)
+    error (EXIT_FAILURE, 0,
+           "cannot create sharedprefix function: %s", sqlite3_errmsg(dbq));
+
+  if (! passive_p)
+    {
+      if (verbose > 3)
+        obatched(clog) << "ddl: " << DEBUGINFOD_SQLITE_DDL << endl;
+      rc = sqlite3_exec (db, DEBUGINFOD_SQLITE_DDL, NULL, NULL, NULL);
+      if (rc != SQLITE_OK)
+        {
+          error (EXIT_FAILURE, 0,
+                 "cannot run database schema ddl: %s", sqlite3_errmsg(db));
+        }
+    }
+
+  obatched(clog) << "libmicrohttpd version " << MHD_get_version() << endl;
+  
+  /* If '-C' wasn't given or was given with no arg, pick a reasonable default
+     for the number of worker threads.  */
+  if (connection_pool == 0)
+    connection_pool = default_concurrency();
+
+  /* Note that MHD_USE_EPOLL and MHD_USE_THREAD_PER_CONNECTION don't
+     work together.  */
+  unsigned int use_epoll = 0;
+#if MHD_VERSION >= 0x00095100
+  use_epoll = MHD_USE_EPOLL;
+#endif
+
+  unsigned int mhd_flags = (
+#if MHD_VERSION >= 0x00095300
+			    MHD_USE_INTERNAL_POLLING_THREAD
+#else
+			    MHD_USE_SELECT_INTERNALLY
+#endif
+			    | MHD_USE_DUAL_STACK
+			    | use_epoll
+#if MHD_VERSION >= 0x00095200
+			    | MHD_USE_ITC
+#endif
+			    | MHD_USE_DEBUG); /* report errors to stderr */
+
+  // Start httpd server threads.  Use a single dual-homed pool.
+  MHD_Daemon *d46 = MHD_start_daemon (mhd_flags, http_port,
+				      NULL, NULL, /* default accept policy */
+				      handler_cb, NULL, /* handler callback */
+				      MHD_OPTION_EXTERNAL_LOGGER,
+				      error_cb, NULL,
+				      MHD_OPTION_THREAD_POOL_SIZE,
+				      (int)connection_pool,
+				      MHD_OPTION_END);
+
+  MHD_Daemon *d4 = NULL;
+  if (d46 == NULL)
+    {
+      // Cannot use dual_stack, use ipv4 only
+      mhd_flags &= ~(MHD_USE_DUAL_STACK);
+      d4 = MHD_start_daemon (mhd_flags, http_port,
+			     NULL, NULL, /* default accept policy */
+			     handler_cb, NULL, /* handler callback */
+			     MHD_OPTION_EXTERNAL_LOGGER,
+			     error_cb, NULL,
+			     (connection_pool
+			      ? MHD_OPTION_THREAD_POOL_SIZE
+			      : MHD_OPTION_END),
+			     (connection_pool
+			      ? (int)connection_pool
+			      : MHD_OPTION_END),
+			     MHD_OPTION_END);
+      if (d4 == NULL)
+	{
+	  sqlite3 *database = db;
+	  sqlite3 *databaseq = dbq;
+	  db = dbq = 0; // for signal_handler not to freak
+	  sqlite3_close (databaseq);
+	  sqlite3_close (database);
+	  error (EXIT_FAILURE, 0, "cannot start http server at port %d",
+		 http_port);
+	}
+
+    }
+  obatched(clog) << "started http server on"
+                 << (d4 != NULL ? " IPv4 " : " IPv4 IPv6 ")
+                 << "port=" << http_port << endl;
+
+  // add maxigroom sql if -G given
+  if (maxigroom)
+    {
+      obatched(clog) << "maxigrooming database, please wait." << endl;
+      extra_ddl.push_back("create index if not exists " BUILDIDS "_r_sref_arc on " BUILDIDS "_r_sref(artifactsrc);");
+      extra_ddl.push_back("delete from " BUILDIDS "_r_sdef where not exists (select 1 from " BUILDIDS "_r_sref b where " BUILDIDS "_r_sdef.content = b.artifactsrc);");
+      extra_ddl.push_back("drop index if exists " BUILDIDS "_r_sref_arc;");
+
+      // NB: we don't maxigroom the _files interning table.  It'd require a temp index on all the
+      // tables that have file foreign-keys, which is a lot.
+
+      // NB: with =delete, may take up 3x disk space total during vacuum process
+      //     vs.  =off (only 2x but may corrupt database if program dies mid-vacuum)
+      //     vs.  =wal (>3x observed, but safe)
+      extra_ddl.push_back("pragma journal_mode=delete;");
+      extra_ddl.push_back("vacuum;");
+      extra_ddl.push_back("pragma journal_mode=wal;");
+    }
+
+  // run extra -D sql if given
+  if (! passive_p)
+    for (auto&& i: extra_ddl)
+      {
+        if (verbose > 1)
+          obatched(clog) << "extra ddl:\n" << i << endl;
+        rc = sqlite3_exec (db, i.c_str(), NULL, NULL, NULL);
+        if (rc != SQLITE_OK && rc != SQLITE_DONE && rc != SQLITE_ROW)
+          error (0, 0,
+                 "warning: cannot run database extra ddl %s: %s", i.c_str(), sqlite3_errmsg(db));
+
+        if (maxigroom)
+          obatched(clog) << "maxigroomed database" << endl;
+      }
+
+  if (! passive_p)
+    obatched(clog) << "search concurrency " << concurrency << endl;
+  obatched(clog) << "webapi connection pool " << connection_pool
+                 << (connection_pool ? "" : " (unlimited)") << endl;
+  if (! passive_p) {
+    obatched(clog) << "rescan time " << rescan_s << endl;
+    obatched(clog) << "scan checkpoint " << scan_checkpoint << endl;
+  }
+  obatched(clog) << "fdcache mbs " << fdcache_mbs << endl;
+  obatched(clog) << "fdcache prefetch " << fdcache_prefetch << endl;
+  obatched(clog) << "fdcache tmpdir " << tmpdir << endl;
+  obatched(clog) << "fdcache tmpdir min% " << fdcache_mintmp << endl;
+  if (! passive_p)
+    obatched(clog) << "groom time " << groom_s << endl;
+  obatched(clog) << "forwarded ttl limit " << forwarded_ttl_limit << endl;
+
+  if (scan_archives.size()>0)
+    {
+      obatched ob(clog);
+      auto& o = ob << "accepting archive types ";
+      for (auto&& arch : scan_archives)
+	o << arch.first << "(" << arch.second << ") ";
+      o << endl;
+    }
+  const char* du = getenv(DEBUGINFOD_URLS_ENV_VAR);
+  if (du && du[0] != '\0') // set to non-empty string?
+    obatched(clog) << "upstream debuginfod servers: " << du << endl;
+
+  vector<pthread_t> all_threads;
+
+  if (! passive_p)
+    {
+      pthread_t pt;
+      rc = pthread_create (& pt, NULL, thread_main_groom, NULL);
+      if (rc)
+        error (EXIT_FAILURE, rc, "cannot spawn thread to groom database\n");
+      else
+        {
+#ifdef HAVE_PTHREAD_SETNAME_NP
+          (void) pthread_setname_np (pt, "groom");
+#endif
+          all_threads.push_back(pt);
+        }
+
+      if (scan_files || scan_archives.size() > 0)
+        {
+          if (scan_checkpoint > 0)
+            scan_barrier = new sqlite_checkpoint_pb(concurrency, (unsigned) scan_checkpoint);
+
+          rc = pthread_create (& pt, NULL, thread_main_fts_source_paths, NULL);
+          if (rc)
+            error (EXIT_FAILURE, rc, "cannot spawn thread to traverse source paths\n");
+#ifdef HAVE_PTHREAD_SETNAME_NP
+          (void) pthread_setname_np (pt, "traverse");
+#endif
+          all_threads.push_back(pt);
+
+          for (unsigned i=0; i<concurrency; i++)
+            {
+              rc = pthread_create (& pt, NULL, thread_main_scanner, NULL);
+              if (rc)
+                error (EXIT_FAILURE, rc, "cannot spawn thread to scan source files / archives\n");
+#ifdef HAVE_PTHREAD_SETNAME_NP
+              (void) pthread_setname_np (pt, "scan");
+#endif
+              all_threads.push_back(pt);
+            }
+        }
+    }
+  
+  /* Trivial main loop! */
+  set_metric("ready", 1);
+  while (! interrupted)
+    pause ();
+  scanq.nuke(); // wake up any remaining scanq-related threads, let them die
+  if (scan_barrier) scan_barrier->nuke(); // ... in case they're stuck in a barrier
+  set_metric("ready", 0);
+
+  if (verbose)
+    obatched(clog) << "stopping" << endl;
+
+  /* Join all our threads. */
+  for (auto&& it : all_threads)
+    pthread_join (it, NULL);
+
+  /* Stop all the web service threads. */
+  if (d46) MHD_stop_daemon (d46);
+  if (d4) MHD_stop_daemon (d4);
+
+  if (! passive_p)
+    {
+      /* With all threads known dead, we can clean up the global resources. */
+      rc = sqlite3_exec (db, DEBUGINFOD_SQLITE_CLEANUP_DDL, NULL, NULL, NULL);
+      if (rc != SQLITE_OK)
+        {
+          error (0, 0,
+                 "warning: cannot run database cleanup ddl: %s", sqlite3_errmsg(db));
+        }
+    }
+
+  debuginfod_pool_groom ();
+  delete scan_barrier;
+
+  // NB: no problem with unconditional free here - an earlier failed regcomp would exit program
+  (void) regfree (& file_include_regex);
+  (void) regfree (& file_exclude_regex);
+
+  sqlite3 *database = db;
+  sqlite3 *databaseq = dbq;
+  db = dbq = 0; // for signal_handler not to freak
+  (void) sqlite3_close (databaseq);
+  if (! passive_p)
+    (void) sqlite3_close (database);
+
+  return 0;
+}
diff --git a/debuginfod/debuginfod.h.in b/debuginfod/debuginfod.h.in
new file mode 100644
index 0000000..4a256ba
--- /dev/null
+++ b/debuginfod/debuginfod.h.in
@@ -0,0 +1,121 @@
+/* External declarations for the libdebuginfod client library.
+   Copyright (C) 2019-2020 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+   * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+   * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DEBUGINFOD_CLIENT_H
+#define _DEBUGINFOD_CLIENT_H 1
+
+/* Names of environment variables that control the client logic. */
+#define DEBUGINFOD_URLS_ENV_VAR "DEBUGINFOD_URLS"
+#define DEBUGINFOD_CACHE_PATH_ENV_VAR "DEBUGINFOD_CACHE_PATH"
+#define DEBUGINFOD_TIMEOUT_ENV_VAR "DEBUGINFOD_TIMEOUT"
+#define DEBUGINFOD_PROGRESS_ENV_VAR "DEBUGINFOD_PROGRESS"
+#define DEBUGINFOD_VERBOSE_ENV_VAR "DEBUGINFOD_VERBOSE"
+#define DEBUGINFOD_RETRY_LIMIT_ENV_VAR "DEBUGINFOD_RETRY_LIMIT"
+#define DEBUGINFOD_MAXSIZE_ENV_VAR "DEBUGINFOD_MAXSIZE"
+#define DEBUGINFOD_MAXTIME_ENV_VAR "DEBUGINFOD_MAXTIME"
+#define DEBUGINFOD_HEADERS_FILE_ENV_VAR "DEBUGINFOD_HEADERS_FILE"
+
+/* The libdebuginfod soname.  */
+#define DEBUGINFOD_SONAME "@LIBDEBUGINFOD_SONAME@"
+
+/* Handle for debuginfod-client connection.  */
+#ifndef _ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF
+typedef struct debuginfod_client debuginfod_client;
+#define _ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF 1
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Create a handle for a new debuginfod-client session.  */
+debuginfod_client *debuginfod_begin (void);
+
+/* Query the urls contained in $DEBUGINFOD_URLS for a file with
+   the specified type and build id.  If build_id_len == 0, the
+   build_id is supplied as a lowercase hexadecimal string; otherwise
+   it is a binary blob of given length.
+
+   If successful, return a file descriptor to the target, otherwise
+   return a posix error code.  If successful, set *path to a
+   strdup'd copy of the name of the same file in the cache.
+   Caller must free() it later. */
+
+int debuginfod_find_debuginfo (debuginfod_client *client,
+			       const unsigned char *build_id,
+                               int build_id_len,
+                               char **path);
+
+int debuginfod_find_executable (debuginfod_client *client,
+				const unsigned char *build_id,
+                                int build_id_len,
+                                char **path);
+
+int debuginfod_find_source (debuginfod_client *client,
+			    const unsigned char *build_id,
+                            int build_id_len,
+                            const char *filename,
+                            char **path);
+
+int debuginfod_find_section (debuginfod_client *client,
+			     const unsigned char *build_id,
+			     int build_id_len,
+			     const char *section,
+			     char **path);
+
+typedef int (*debuginfod_progressfn_t)(debuginfod_client *c, long a, long b);
+void debuginfod_set_progressfn(debuginfod_client *c,
+			       debuginfod_progressfn_t fn);
+
+void debuginfod_set_verbose_fd(debuginfod_client *c, int fd);
+
+/* Set the user parameter.  */
+void debuginfod_set_user_data (debuginfod_client *client, void *value);
+
+/* Get the user parameter.  */
+void* debuginfod_get_user_data (debuginfod_client *client);
+
+/* Get the current or last active URL, if known.  */
+const char* debuginfod_get_url (debuginfod_client *client);
+
+/* Returns set of x-debuginfod* header lines received from current or
+   last active transfer, \n separated, if known. */
+const char* debuginfod_get_headers(debuginfod_client *client);
+
+/* Add an outgoing HTTP request  "Header: Value".  Copies string.  */
+int debuginfod_add_http_header (debuginfod_client *client, const char* header);
+
+/* Release debuginfod client connection context handle.  */
+void debuginfod_end (debuginfod_client *client);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _DEBUGINFOD_CLIENT_H */
diff --git a/debuginfod/libdebuginfod.map b/debuginfod/libdebuginfod.map
new file mode 100644
index 0000000..6334373
--- /dev/null
+++ b/debuginfod/libdebuginfod.map
@@ -0,0 +1,24 @@
+ELFUTILS_0 { };
+ELFUTILS_0.178 {
+  global:
+  debuginfod_begin;
+  debuginfod_end;
+  debuginfod_find_debuginfo;
+  debuginfod_find_executable;
+  debuginfod_find_source;
+  debuginfod_set_progressfn;
+} ELFUTILS_0;
+ELFUTILS_0.179 {
+  global:
+  debuginfod_set_user_data;
+  debuginfod_get_user_data;
+  debuginfod_get_url;
+  debuginfod_add_http_header;
+} ELFUTILS_0.178;
+ELFUTILS_0.183 {
+  debuginfod_set_verbose_fd;
+} ELFUTILS_0.179;
+ELFUTILS_0.188 {
+  debuginfod_get_headers;
+  debuginfod_find_section;
+} ELFUTILS_0.183;
diff --git a/doc/ChangeLog b/doc/ChangeLog
new file mode 100644
index 0000000..7f2d6ff
--- /dev/null
+++ b/doc/ChangeLog
@@ -0,0 +1,294 @@
+2023-02-14  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.8: Add .TP before -g.
+
+2023-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Tweak -c/-C documentation for heuristic defaults.
+
+2022-10-31  Aaron Merey  <amerey@redhat.com>
+
+	* Makefile.am (notrans_dist_man3_MANS): Add debuginfod_find_section.3.
+	* debuginfod_find_section.3: New file.
+	* debuginfod_find_debuginfo.3: Document debuginfod_find_section.
+	* debuginfod.8: Document section webapi.
+
+2022-10-28  Arsen Arsenović  <arsen@aarsen.me>
+
+	* readelf.1: Document the --syms alias.
+
+2022-10-18  Daniel Thornburgh  <dthorn@google.com>
+
+	* debuginfod_find_debuginfo.3: Document DEBUGINFOD_HEADERS_FILE.
+
+2022-09-02  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod_find_debuginfo.3: Tweaked debuginfod_get_headers docs.
+
+2022-07-15  Noah Sanci  <nsanci@redhat.com>
+
+	* debuginfod_find_debuginfo.3: Explained debuginfod_get_headers
+	usage.
+	* debuginfod_get_headers.3: Created.
+
+2022-09-02  Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod.8 (-C): Update description.
+
+2022-06-03  Michael Trapp <michael.trapp@sap.com>
+
+	* debuginfod.8 (--disable-source-scan): Document.
+
+2022-05-09  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Tweak prefetch descriptions.
+
+2022-01-31  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-client-config.7: Elaborate DEBUGINFOD_URLS.
+
+2021-12-08  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28661
+	* debuginfod.8 (-C): Document new flag.
+
+2021-11-05  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28430
+	* debuginfod.8 (--passive): Document new flag & operation mode.
+
+2021-08-28  Di Chen  <dichen@redhat.com>
+
+	* debuginfod.8 (-d): Document ":memory:" as in-memory database.
+
+2021-08-20  Di Chen  <dichen@redhat.com>
+
+	* debuginfod.8: Add --forwarded-ttl-limit=NUM documentation.
+
+2021-07-28  Alice Zhang <alizhang@redhat.com>
+
+	PR27950
+	* debuginfod-client-config.7: New file to store all cache config
+	infos.
+	* debuginfod-find.1: Removed redundant occurrences of environment
+	variables & cache control files.
+	* debuginfod.8: Likewise.
+	* debuginfod_find_debuginfo.3: Likewise.
+	* Makefile.am: Updated to include debuginfod-client-config.7
+	* man3, man7: Symlinks for source tree man page testing.
+
+2021-08-04  Noah Sanci  <nsanci@redhat.com>
+
+	PR27277
+	* debuginfod-find.1: Increasing verbosity describes the downloaded
+	file.
+	* debuginfod.8: Describe X-DEBUGINFOD-FILE, X-DEBUGINFOD-SIZE, and
+	X-DEBUGINFOD-ARCHIVE.
+
+2021-07-26  Noah Sanci <nsanci@redhat.com>
+
+	PR27982
+	* debuginfod-find.1: Document DEBUGINFOD_MAXTIME
+	and DEBUGINFOD_MAXSIZE.
+
+2021-04-23  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27701
+	* debuginfod_find_debuginfo.3: Specify sequential reuse policy of
+	debuginfod_client objects.
+
+2021-02-04  Frank Ch. Eigler <fche@redhat.com>
+
+	* debuginfod.8: Mention new --fdcache-mintmp option.
+
+2020-12-11  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* debuginfod.8: Fix spelling typos.
+	* debuginfod_find_debuginfo.3: Likewise.
+	* elfutils.sgml: Likewise.
+	* readelf.1: Likewise.
+
+2020-12-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* debuginfod_find_debuginfo.3: Document DEBUGINFOD_SONAME macro.
+
+2020-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod_find_debuginfo.3: Document debuginfod_set_verbose_fd
+	and DEBUGINFOD_VERBOSE.
+	* debuginfod_set_verbose_fd.3: New redirect to
+	debuginfod_find_debuginfo.3
+
+2020-10-29  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26775
+	* debuginfod.8: Document that SIGUSR1 interrupts the groom
+	cycle, and SIGUSR2 interrupts rescan.
+
+2020-10-25  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod_find_debuginfo.3 (ECONNREFUSED): Document that this
+	is also returned for a bad HTTPS server certificate.
+
+2020-10-07  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.1: Add missing .br for SYNOPSIS section.
+
+2020-06-19  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am: Guard all client manpages with LIBDEBUGINFOD.
+
+2020-03-29  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod_find_debuginfo.3 (HTTP HEADER): Document the expected
+	header format and purpose.
+
+2020-03-28  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Document valid --port=NUM range, excludes 0.
+
+2020-03-27  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.1: Document /path/-based buildid passing.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod_add_http_header.3: New function, documented ...
+	* debuginfod_find_debuginfo.3: ... here.
+	* Makefile.am (notrans_dist_*_man3): Add it.
+
+2020-03-26  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8 (-R): Note zstd compression complications
+	and workaround.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.1, debuginfod_find_debuginfo.3: Document
+	source path canonicalization.
+
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod_get_url.3: New function, documented ...
+	* debuginfod_find_debuginfo.3: ... here.
+	* Makefile.am (notrans_dist_*_man3): Add it.
+
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod_get_user.3, _set_user.3: New functions, documented ...
+	* debuginfod_find_debuginfo.3: ... here.
+	* Makefile.am (notrans_dist_*_man3): List all debuginfod .3 functions.
+
+2020-02-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Note that -R works just like -Z.rpm .
+
+2020-02-25  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Document new --fdcache-prefetch option.
+
+2020-02-05  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Document new -Z flag and tweak other bits.
+
+2020-01-10  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod_find_debuginfo.3 (DEBUGINFOD_PROGRESS): Mention progress
+	output goes to stderr.
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com
+
+	* debuginfod.8: Document --fdcache-fds and --fdcache-mbs opts.
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod.8: Rework sections dealing with traversal/scanning,
+	explaining new threading model.
+
+2020-01-02  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod.8 (DEBUGINFOD_TIMEOUT): Document as seconds to
+	provide 100K, default 90.
+	* debuginfod-find.1 (DEBUGINFOD_TIMEOUT): Likewise.
+	* debuginfod_find_debuginfo.3 (DEBUGINFOD_TIMEOUT): Likewise.
+
+2019-12-22  Frank Ch. Eigler  <fche@redhat.com
+
+	* debuginfod.8: Add -U (DEB) flag, generalize RPM to "archive".
+
+2019-12-04  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-find.1: Bump default timeout to 30.
+	* debuginfod_find_debuginfo.3: Ditto.
+	Document $DEBUGINFOD_PROGRESS.
+
+2019-11-26  Frank Ch. Eigler  <fche@redhat.com>
+	    Aaron Merey  <amerey@redhat.com>
+
+	* debuginfod.8, find-debuginfo.1, debuginfod_*.3: New files.
+
+2019-09-02  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.1 (symbols): Add optional section name.
+	(dyn-sym): Document new option.
+
+2019-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* COPYING: Rename to...
+	* COPYING-GFDL: ... this.
+
+2019-08-23  Ben Woodard  <woodard@redhat.com>
+
+	* Updated the eu-readelf man page to make it match the options
+	that eu-readelf actually supports.
+
+2019-08-22  Ben Woodard  <woodard@redhat.com>S
+
+	* Move the .1 man pages to the correct place.
+
+2019-08-21  Ben Woodard  <woodard@redhat.com>
+
+	* Updated Changelog
+	* Added README
+
+2019-08-20  Ben Woodard  <woodard@redhat.com>
+
+	* Added eu-elfclassify.1 man page based upon --help
+	* Forked binutils readelf page to make eu-readelf.1 man page
+	* Modified eu-readelf.1 to add -n:: option.
+	* Disabled sgml file building per mjw.
+	* Added man pages to Makefile.am
+
+2019-06-20  Ben Woodard  <woodard@redhat.com>
+
+	* Added the beginnings of some man pages
+
+2019-08-21  Ben Woodard  <woodard@redhat.com>
+
+	* Updated Changelog
+	* Added README
+
+2019-08-20  Ben Woodard  <woodard@redhat.com>
+
+	* Added eu-elfclassify.1 man page based upon --help
+	* Forked binutils readelf page to make eu-readelf.1 man page
+	* Modified eu-readelf.1 to add -n:: option.
+	* Disabled sgml file building per mjw.
+	* Added man pages to Makefile.am
+
+2019-06-20 Ben Woodard <woodard@redhat.com>
+
+	* Added the beginnings of some man pages
+
+2005-04-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfutils.sgml: Some typo fixes and a few extensions.
+	Patch by Eric Christopher <echristo@redhat.com>.
+
+2005-02-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Prefer pdf.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/doc/Makefile.am b/doc/Makefile.am
new file mode 100644
index 0000000..87de4f0
--- /dev/null
+++ b/doc/Makefile.am
@@ -0,0 +1,47 @@
+## Process this file with automake to create Makefile.in
+## Configure input file for elfutils.
+##
+## Copyright (C) 1996-2001, 2002, 2005, 2019-2020 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+EXTRA_DIST = COPYING-GFDL README
+dist_man1_MANS=readelf.1 elfclassify.1 srcfiles.1
+notrans_dist_man3_MANS=elf_update.3 elf_getdata.3 elf_clone.3 elf_begin.3
+notrans_dist_man7_MANS=
+notrans_dist_man8_MANS=
+notrans_dist_man1_MANS=
+
+if DEBUGINFOD
+if !LIBDEBUGINFOD
+notrans_dist_man7_MANS += debuginfod-client-config.7
+endif
+notrans_dist_man8_MANS += debuginfod.8 debuginfod.service.8
+endif
+
+if LIBDEBUGINFOD
+notrans_dist_man7_MANS += debuginfod-client-config.7
+notrans_dist_man3_MANS += debuginfod_add_http_header.3
+notrans_dist_man3_MANS += debuginfod_begin.3
+notrans_dist_man3_MANS += debuginfod_end.3
+notrans_dist_man3_MANS += debuginfod_find_debuginfo.3
+notrans_dist_man3_MANS += debuginfod_find_executable.3
+notrans_dist_man3_MANS += debuginfod_find_source.3
+notrans_dist_man3_MANS += debuginfod_find_section.3
+notrans_dist_man3_MANS += debuginfod_get_user_data.3
+notrans_dist_man3_MANS += debuginfod_get_url.3
+notrans_dist_man3_MANS += debuginfod_set_progressfn.3
+notrans_dist_man3_MANS += debuginfod_set_user_data.3
+notrans_dist_man1_MANS += debuginfod-find.1
+endif
diff --git a/doc/README b/doc/README
new file mode 100644
index 0000000..67f61fa
--- /dev/null
+++ b/doc/README
@@ -0,0 +1,20 @@
+The elfutils documentation is very much a work in
+progress. Contributions are welcome.
+Please reports bugs at https://sourceware.org/bugzilla/
+Please send additions and patches to: elfutils-devel@sourceware.org
+
+The elfutils utilities are a new implementation of many of the
+utilities found in binutils and consequently, the documentation for
+most of the tools has been the the man pages for binutils. For example
+you could refer to readelf's man page for instructions on
+eu-readelf. This has been fine up until this point but as tools gain
+new capabilities, they will need to have their own individual man
+page. Forking the man pages from binutils is acceptable and the
+current plan of action.
+
+New utilities that do not have an analog in binutils can have their
+initial man pages generated using a tool like help2man.
+
+The C language interfaces for libelf, libdw, and libdwfl are in
+particular need of documentation. The aspirational goal is write these
+in sphinx.
\ No newline at end of file
diff --git a/doc/debuginfod-client-config.7 b/doc/debuginfod-client-config.7
new file mode 100644
index 0000000..53d8280
--- /dev/null
+++ b/doc/debuginfod-client-config.7
@@ -0,0 +1,136 @@
+'\"! tbl | nroff \-man
+'\" t macro stdmacro
+.if \n(zZ=1 .ig zZ
+
+.TH DEBUGINFOD-CLIENT-CONFIG 7
+.SH NAME
+debuginfod-client-config \- debuginfod client environment variables, cache control files and etc.
+
+.SH SYNOPSIS
+Several environment variables and control files control the behaviour of debuginfod client applications.
+
+.\" The preceding section permits this man page to be viewed as if self-contained.
+.zZ
+.\" The following section (only) gets included into other man pages via .so
+
+
+.SH ENVIRONMENT VARIABLES
+.TP
+.B $TMPDIR
+This environment variable points to a file system to be used for
+temporary files.  The default is /tmp.
+
+.TP
+.B $DEBUGINFOD_URLS
+This environment variable contains a list of URL prefixes for trusted
+debuginfod instances.  Alternate URL prefixes are separated by space.
+This environment variable may be set by /etc/profile.d scripts
+reading /etc/debuginfod/*.urls files.
+
+.TP
+.B $DEBUGINFOD_CACHE_PATH
+This environment variable governs the location of the cache where
+downloaded files and cache-control files are kept.  The default
+directory is chosen based on other environment variables, see below.
+
+.TP
+.B $DEBUGINFOD_PROGRESS
+This environment variable governs the default progress function.  If
+set, and if a progressfn is not explicitly set, then the library will
+configure a default progressfn.  This function will append a simple
+progress message periodically to stderr.  The default is no progress
+function output.
+
+.TP
+.B $DEBUGINFOD_VERBOSE
+This environment variable governs the default file descriptor for
+verbose output.  If set, and if a verbose fd is not explicitly set,
+then the verbose output will be produced on STDERR_FILENO.
+
+.TP
+.B $DEBUGINFOD_RETRY_LIMIT
+This environment variable governs the default limit of retry attempts. If a
+query failed with errno other than ENOENT, will initiate several attempts
+within the limit.
+
+.TP
+.B $DEBUGINFOD_TIMEOUT
+This environment variable governs the download \fIcommencing\fP
+timeout for each debuginfod HTTP connection.  A server that fails to
+provide at least 100K of data within this many seconds is skipped. The
+default is 90 seconds.  (Zero or negative means "no timeout".)
+
+.TP
+.B $DEBUGINFOD_MAXTIME
+This environment variable dictates how long the client will wait to
+\fIcomplete\fP the download a file found on a server in seconds. It is best
+used to ensure that a file is downloaded quickly or be rejected. The
+default is 0 (infinite time).
+
+.TP
+.B $DEBUGINFOD_MAXSIZE
+This environment variable dictates the maximum size of a file to
+download in bytes. This is best used if the user would like to ensure
+only small files are downloaded. A value of 0 causes no consideration
+for size, and the client may attempt to download a file of any size.
+The default is 0 (infinite size).
+
+.TP
+.B $DEBUGINFOD_HEADERS_FILE
+This environment variable points to a file that supplies headers to
+outbound HTTP requests, one per line. The header lines shouldn't end with
+CRLF, unless that's the system newline convention. Whitespace-only lines
+are skipped.
+
+.SH CACHE
+
+Before each query, the debuginfod client library checks for a need to
+clean the cache.  If it's time to clean, the library traverses the
+cache directory and removes downloaded debuginfo-related artifacts and
+newly empty directories, if they have not been accessed recently.
+
+Control files are located directly under the cache directory.  They
+contain simple decimal numbers to set cache-related configuration
+parameters.  If the files do not exist, the client library creates the
+files with the default parameter values as content.
+
+After each query, the debuginfod client library deposits newly
+received files into a directory & file that is named based on the
+build-id.  A failed query is also cached by a special file.  The
+naming convention used for these artifacts is deliberately
+\fBundocumented\fP.
+
+.TP
+.B $XDG_CACHE_HOME/debuginfod_client/
+Default cache directory, if $XDG_CACHE_HOME is set.
+.PD
+
+.TP
+.B $HOME/.cache/debuginfod_client/
+Default cache directory, if $XDG_CACHE_HOME is not set.
+.PD
+
+.TP
+.B $HOME/.debuginfod_client_cache/
+Deprecated cache directory, used only if preexisting.
+.PD
+
+.TP
+.B cache_clean_interval_s
+This control file gives the interval between cache cleaning rounds, in
+seconds.  The default is 86400, one day.  0 means "immediately".
+
+.TP
+.B max_unused_age_s
+This control file sets how long unaccessed debuginfo-related files
+are retained, in seconds.  The default is 604800, one week.  0 means
+"immediately".
+
+.TP
+.B cache_miss_s
+This control file sets how long to remember a query failure, in
+seconds.  New queries for the same artifacts within this time window
+are short-circuited (returning an immediate failure instead of sending
+a new query to servers).  This accelerates queries that probably would
+still fail.  The default is 600, 10 minutes.  0 means "forget
+immediately".
diff --git a/doc/debuginfod-find.1 b/doc/debuginfod-find.1
new file mode 100644
index 0000000..7d577ba
--- /dev/null
+++ b/doc/debuginfod-find.1
@@ -0,0 +1,147 @@
+'\"! tbl | nroff \-man
+'\" t macro stdmacro
+
+.de SAMPLE
+.br
+.RS 0
+.nf
+.nh
+..
+.de ESAMPLE
+.hy
+.fi
+.RE
+..
+
+.TH DEBUGINFOD-FIND 1
+.SH NAME
+debuginfod-find \- request debuginfo-related data
+
+.SH SYNOPSIS
+.B debuginfod-find [\fIOPTION\fP]... debuginfo \fIBUILDID\fP
+.br
+.B debuginfod-find [\fIOPTION\fP]... debuginfo \fIPATH\fP
+.br
+.B debuginfod-find [\fIOPTION\fP]... executable \fIBUILDID\fP
+.br
+.B debuginfod-find [\fIOPTION\fP]... executable \fIPATH\fP
+.br
+.B debuginfod-find [\fIOPTION\fP]... source \fIBUILDID\fP \fI/FILENAME\fP
+.br
+.B debuginfod-find [\fIOPTION\fP]... source \fIPATH\fP \fI/FILENAME\fP
+
+.SH DESCRIPTION
+\fBdebuginfod-find\fP queries one or more \fBdebuginfod\fP servers for
+debuginfo-related data.  In case of a match, it saves the the
+requested file into a local cache, prints the file name to standard
+output, and exits with a success status of 0.  In case of any error,
+it exits with a failure status and an error message to standard error.
+
+.\" Much of the following text is duplicated with debuginfod.8
+
+The debuginfod system uses buildids to identify debuginfo-related data.
+These are stored as binary notes in ELF/DWARF files, and are
+represented as lowercase hexadecimal.  For example, for a program
+/bin/ls, look at the ELF note GNU_BUILD_ID:
+
+.SAMPLE
+% readelf -n /bin/ls | grep -A4 build.id
+Note section [ 4] '.note.gnu.buildid' of 36 bytes at offset 0x340:
+Owner          Data size  Type
+GNU                   20  GNU_BUILD_ID
+Build ID: 8713b9c3fb8a720137a4a08b325905c7aaf8429d
+.ESAMPLE
+
+Then the hexadecimal BUILDID is simply:
+
+.SAMPLE
+8713b9c3fb8a720137a4a08b325905c7aaf8429d
+.ESAMPLE
+
+In place of the hexadecimal \fIBUILDID\fP, debuginfod-find also
+accepts a path name to to an ELF binary, from which it extracts the
+buildid.  In this case, ensure the file name has some character other
+than \fB[0-9a-f]\fP.  Files ambiguously named files like
+"\fBdeadbeef\fP" can be passed with a \fB./deadbeef\fP extra path
+component.
+
+
+.SS debuginfo \fIBUILDID\fP
+
+If the given buildid is known to a server, this request will result
+in a binary object that contains the customary \fB.*debug_*\fP
+sections.  This may be a split debuginfo file as created by
+\fBstrip\fP, or it may be an original unstripped executable.
+
+.SS executable \fIBUILDID\fP
+
+If the given buildid is known to the server, this request will result
+in a binary object that contains the normal executable segments.  This
+may be a executable stripped by \fBstrip\fP, or it may be an original
+unstripped executable.  \fBET_DYN\fP shared libraries are considered
+to be a type of executable.
+
+.SS source \fIBUILDID\fP \fI/SOURCE/FILE\fP
+
+If the given buildid is known to the server, this request will result
+in a binary object that contains the source file mentioned.  The path
+should be absolute.  Relative path names commonly appear in the DWARF
+file's source directory, but these paths are relative to
+individual compilation unit AT_comp_dir paths, and yet an executable
+is made up of multiple CUs.  Therefore, to disambiguate, debuginfod
+expects source queries to prefix relative path names with the CU
+compilation-directory, followed by a mandatory "/".
+
+Note: for software packaged by distributions, the CU
+compilation-directory may not be obvious.  It can be found by
+inspecting AT_comp_dir values in downloaded debuginfo.  For example,
+the comp_dir of the Fedora 37 version of /bin/ls can be found as
+follows:
+
+.SAMPLE
+% debuginfod-find debuginfo /bin/ls
+~/.cache/debuginfod_client/03529d48345409576cd5c82a56ad08555088d353/
+% eu-readelf -w ~/.cache/debuginfod_client/03529d48345409576cd5c82a56ad08555088d353/debuginfo | grep comp_dir
+           comp_dir             (line_strp) "/usr/src/debug/coreutils-9.1-6.fc37.x86_64/separate"
+.ESAMPLE
+
+Note: the caller may or may not elide \fB../\fP or \fB/./\fP or extraneous
+\fB///\fP sorts of path components in the directory names.  debuginfod
+accepts both forms.  Specifically, debuginfod canonicalizes path names
+according to RFC3986 section 5.2.4 (Remove Dot Segments), plus reducing
+any \fB//\fP to \fB/\fP in the path.
+
+For example:
+.TS
+l l.
+#include <stdio.h>	source BUILDID /usr/include/stdio.h
+/path/to/foo.c	source BUILDID /path/to/foo.c
+\../bar/foo.c AT_comp_dir=/zoo/	source BUILDID /zoo//../bar/foo.c
+.TE
+
+.SH "OPTIONS"
+
+.TP
+.B "\-v"
+Increase verbosity, including printing frequent download-progress messages
+and printing the http response headers from the server.
+
+
+.SH "SECURITY"
+
+debuginfod-find \fBdoes not\fP include any particular security
+features.  It trusts that the binaries returned by the debuginfod(s)
+are accurate.  Therefore, the list of servers should include only
+trustworthy ones.  If accessed across HTTP rather than HTTPS, the
+network should be trustworthy.  Authentication information through
+the internal \fIlibcurl\fP library is not currently enabled, except
+for the basic plaintext \%\fIhttp[s]://userid:password@hostname/\fP style.
+(The debuginfod server does not perform authentication, but a front-end
+proxy server could.)
+
+.nr zZ 1
+.so man7/debuginfod-client-config.7
+
+.SH "SEE ALSO"
+.I "debuginfod(8)"
+.I "debuginfod_find_debuginfod(3)"
diff --git a/doc/debuginfod.8 b/doc/debuginfod.8
new file mode 100644
index 0000000..42e0fc9
--- /dev/null
+++ b/doc/debuginfod.8
@@ -0,0 +1,532 @@
+'\"! tbl | nroff \-man
+'\" t macro stdmacro
+
+.de SAMPLE
+.br
+.RS 0
+.nf
+.nh
+..
+.de ESAMPLE
+.hy
+.fi
+.RE
+..
+.TH DEBUGINFOD 8
+.SH NAME
+debuginfod \- debuginfo-related http file-server daemon
+
+.SH SYNOPSIS
+.B debuginfod
+[\fIOPTION\fP]... [\fIPATH\fP]...
+
+.SH DESCRIPTION
+\fBdebuginfod\fP serves debuginfo-related artifacts over HTTP.  It
+periodically scans a set of directories for ELF/DWARF files and their
+associated source code, as well as archive files containing the above, to
+build an index by their buildid.  This index is used when remote
+clients use the HTTP webapi, to fetch these files by the same buildid.
+
+If a debuginfod cannot service a given buildid artifact request
+itself, and it is configured with information about upstream
+debuginfod servers, it queries them for the same information, just as
+\fBdebuginfod-find\fP would.  If successful, it locally caches then
+relays the file content to the original requester.
+
+Indexing the given PATHs proceeds using multiple threads.  One thread
+periodically traverses all the given PATHs logically or physically
+(see the \fB\-L\fP option).  Duplicate PATHs are ignored.  You may use
+a file name for a PATH, but source code indexing may be incomplete;
+prefer using a directory that contains the binaries.  The traversal
+thread enumerates all matching files (see the \fB\-I\fP and \fB\-X\fP
+options) into a work queue.  A collection of scanner threads (see the
+\fB\-c\fP option) wait at the work queue to analyze files in parallel.
+
+If the \fB\-F\fP option is given, each file is scanned as an ELF/DWARF
+file.  Source files are matched with DWARF files based on the
+AT_comp_dir (compilation directory) attributes inside it.  Caution:
+source files listed in the DWARF may be a path \fIanywhere\fP in the
+file system, and debuginfod will readily serve their content on
+demand.  (Imagine a doctored DWARF file that lists \fI/etc/passwd\fP
+as a source file.)  If this is a concern, audit your binaries:
+
+.SAMPLE
+% eu-srcfiles -e BINARY
+.ESAMPLE
+
+If any of the \fB\-R\fP, \fB-U\fP, or \fB-Z\fP options is given, each
+file is scanned as an archive file that may contain ELF/DWARF/source
+files.  Archive files are recognized by extension.  If \-R is given,
+".rpm" files are scanned; if \-U is given, ".deb" and ".ddeb" files
+are scanned; if \-Z is given, the listed extensions are scanned.
+
+Because of complications such as DWZ-compressed debuginfo, it may
+require \fItwo\fP traversal passes to identify all source code.
+Source files for binaries in archives are only served from archives,
+so the caution for \-F does not apply.  If the same source file may be
+found in multiple different archives, a heuristic chooses the one
+closest to the archive holding the debuginfo.  ("closest" means
+"longest common archive name prefix").  Note that due to Debian/Ubuntu
+packaging policies & mechanisms, debuginfod cannot resolve source
+files for DEB/DDEB at all.  Consider using the
+\-\-disable\-source\-scan option.
+
+If no PATH is listed, or none of the scanning options is given, then
+\fBdebuginfod\fP will simply serve content that it accumulated into
+its index in all previous runs, periodically groom the database, and
+federate to any upstream debuginfod servers.  In \fIpassive\fP mode,
+\fBdebuginfod\fP will only serve content from a read-only index and
+federated upstream servers, but will not scan or groom.
+
+.SH OPTIONS
+
+.TP
+.B "\-F"
+Activate ELF/DWARF file scanning.  The default is off.
+
+.TP
+.B "\-Z EXT" "\-Z EXT=CMD"
+Activate an additional pattern in archive scanning.  Files with name
+extension EXT (include the dot) will be processed.  If CMD is given,
+it is invoked with the file name added to its argument list, and
+should produce a common archive on its standard output.  Otherwise,
+the file is read as if CMD were "cat".  Since debuginfod internally
+uses \fBlibarchive\fP to read archive files, it can accept a wide
+range of archive formats and compression modes.  The default is no
+additional patterns.  This option may be repeated.
+
+.TP
+.B "\-R"
+Activate RPM patterns in archive scanning.  The default is off.
+Equivalent to \fB\%\-Z\~.rpm=cat\fP, since libarchive can natively
+process RPM archives.  If your version of libarchive is much older
+than 2020, be aware that some distributions have switched to an
+incompatible zstd compression for their payload.  You may experiment
+with \fB\%\-Z\ .rpm='(rpm2cpio|zstdcat)<'\fP instead of \fB\-R\fP.
+
+.TP
+.B "\-U"
+Activate DEB/DDEB patterns in archive scanning.  The default is off.
+Equivalent to \fB\%\-Z\ .deb='(bsdtar\ \-O\ \-x\ \-f\ \-\ data.tar\\*)<\fP'
+and same for \fB.ddeb\fP and \fB.ipk\fP.
+
+.TP
+.B "\-d FILE" "\-\-database=FILE"
+Set the path of the sqlite database used to store the index.  This
+file is disposable in the sense that a later rescan will repopulate
+data.  It will contain absolute file path names, so it may not be
+portable across machines.  It may be frequently read/written, so it
+should be on a fast filesystem.  It should not be shared across
+machines or users, to maximize sqlite locking performance.  For quick
+testing the magic string ":memory:" can be used to use an one-time
+memory-only database.  The default database file is
+\%$HOME/.debuginfod.sqlite.
+
+.TP
+.B "\-\-passive"
+Set the server to passive mode, where it only services webapi
+requests, including participating in federation.  It performs no
+scanning, no grooming, and so only opens the sqlite database
+read-only.  This way a database can be safely shared between a active
+scanner/groomer server and multiple passive ones, thereby sharing
+service load.  Archive pattern options must still be given, so
+debuginfod can recognize file name extensions for unpacking.
+
+.TP
+.B "\-D SQL" "\-\-ddl=SQL"
+Execute given sqlite statement after the database is opened and
+initialized as extra DDL (SQL data definition language).  This may be
+useful to tune performance-related pragmas or indexes.  May be
+repeated.  The default is nothing extra.
+
+.TP
+.B "\-p NUM" "\-\-port=NUM"
+Set the TCP port number (0 < NUM < 65536) on which debuginfod should
+listen, to service HTTP requests.  Both IPv4 and IPV6 sockets are
+opened, if possible.  The webapi is documented below.  The default
+port number is 8002.
+
+.TP
+.B "\-I REGEX"  "\-\-include=REGEX"  "\-X REGEX"  "\-\-exclude=REGEX"
+Govern the inclusion and exclusion of file names under the search
+paths.  The regular expressions are interpreted as unanchored POSIX
+extended REs, thus may include alternation.  They are evaluated
+against the full path of each file, based on its \fBrealpath(3)\fP
+canonicalization.  By default, all files are included and none are
+excluded.  A file that matches both include and exclude REGEX is
+excluded.  (The \fIcontents\fP of archive files are not subject to
+inclusion or exclusion filtering: they are all processed.)  Only the
+last of each type of regular expression given is used.
+
+.TP
+.B "\-t SECONDS"  "\-\-rescan\-time=SECONDS"
+Set the rescan time for the file and archive directories.  This is the
+amount of time the traversal thread will wait after finishing a scan,
+before doing it again.  A rescan for unchanged files is fast (because
+the index also stores the file mtimes).  A time of zero is acceptable,
+and means that only one initial scan should performed.  The default
+rescan time is 300 seconds.  Receiving a SIGUSR1 signal triggers a new
+scan, independent of the rescan time (including if it was zero),
+interrupting a groom pass (if any).
+
+.TP
+.B "\-r"
+Apply the -I and -X during groom cycles, so that most content related
+to files excluded by the regexes are removed from the index.  Not all
+content can be practically removed, so eventually a "\-G"
+"maximal-groom" operation may be needed.
+
+.TP
+.B "\-g SECONDS" "\-\-groom\-time=SECONDS"
+Set the groom time for the index database.  This is the amount of time
+the grooming thread will wait after finishing a grooming pass before
+doing it again.  A groom operation quickly rescans all previously
+scanned files, only to see if they are still present and current, so
+it can deindex obsolete files.  See also the \fIDATA MANAGEMENT\fP
+section.  The default groom time is 86400 seconds (1 day).  A time of
+zero is acceptable, and means that only one initial groom should be
+performed.  Receiving a SIGUSR2 signal triggers a new grooming pass,
+independent of the groom time (including if it was zero), interrupting
+a rescan pass (if any)..
+
+.TP
+.B "\-G"
+Run an extraordinary maximal-grooming pass at debuginfod startup.
+This pass can take considerable time, because it tries to remove any
+debuginfo-unrelated content from the archive-related parts of the index.
+It should not be run if any recent archive-related indexing operations
+were aborted early.  It can take considerable space, because it
+finishes up with an sqlite "vacuum" operation, which repacks the
+database file by triplicating it temporarily.  The default is not to
+do maximal-grooming.  See also the \fIDATA MANAGEMENT\fP section.
+
+.TP
+.B "\-c NUM"  "\-\-concurrency=NUM"
+Set the concurrency limit for the scanning queue threads, which work
+together to process archives & files located by the traversal thread.
+This important for controlling CPU-intensive operations like parsing
+an ELF file and especially decompressing archives.  The default is
+related to the number of processors on the system and other
+constraints; the minimum is 1.
+
+.TP
+.B "\-C" "\-C=NUM" "\-\-connection\-pool" "\-\-connection\-pool=NUM"
+Set the size of the pool of threads serving webapi queries.  The
+following table summarizes the interpretaton of this option and its
+optional NUM parameter.
+.TS
+l l.
+no option, \-C	use a fixed thread pool sized automatically
+\-C=NUM	use a fixed thread pool sized NUM, minimum 2
+.TE
+
+The first mode is a simple and safe configuration related to the
+number of processors and other constraints. The second mode is
+suitable for tuned load-limiting configurations facing unruly traffic.
+
+.TP
+.B "\-L"
+Traverse symbolic links encountered during traversal of the PATHs,
+including across devices - as in \fIfind\ -L\fP.  The default is to
+traverse the physical directory structure only, stay on the same
+device, and ignore symlinks - as in \fIfind\ -P\ -xdev\fP.  Caution: a
+loops in the symbolic directory tree might lead to \fIinfinite
+traversal\fP.
+
+.TP
+.B "\-\-fdcache\-mbs=MB"
+Configure limits on a cache that keeps recently extracted files from
+archives.  Up to a total of MB megabytes will be kept extracted, in
+order to avoid having to decompress their archives over and over
+again. The default MB values depend on the concurrency of the system,
+and on the available disk space on the $TMPDIR or \fB/tmp\fP
+filesystem.  (This is because that is where the most recently used
+extracted files are kept.)  While previous versions used plain LRU,
+the cache now attempts to preserve more frequently & recently accessed
+files, and especially those that took a long time to extract (e.g.,
+vdso.debug!), and penalizes large / old files.
+
+.TP
+.B "\-\-fdcache\-prefetch=NUM"
+Up to NUM other files from an archive may be prefetched into the
+cache before they are even requested.  If unspecified, these values
+depend on concurrency of the system and on the available disk space on
+the $TMPDIR.  Allocating more will improve performance in environments
+where multiple different parts of several large archives are being
+accessed.
+
+.TP
+.B "\-\-fdcache\-mintmp=NUM"
+Configure a disk space threshold for emergency flushing of the caches.
+The filesystem holding the caches is checked periodically.  If the
+available space falls below the given percentage, the caches are
+flushed, and the fdcaches will stay disabled until the next groom
+cycle.  This mechanism, along a few associated /metrics on the webapi,
+are intended to give an operator notice about storage scarcity - which
+can translate to RAM scarcity if the disk happens to be on a RAM
+virtual disk.  The default threshold is 25%.
+
+.TP
+.B "\-\-forwarded\-ttl\-limit=NUM"
+Configure limits of X-Forwarded-For hops. if X-Forwarded-For
+exceeds N hops, it will not delegate a local lookup miss to
+upstream debuginfods. The default limit is 8.
+
+.TP
+.B "\-\-disable\-source\-scan"
+Disable scan of the dwarf source info of debuginfo sections.
+If a setup has no access to source code, the source info is not
+required.
+
+.TP
+.B "\-\-scan\-checkpoint=NUM"
+Run a synchronized SQLITE WAL checkpoint operation after every NUM
+completed archive or file scans.  This may slow down parallel scanning
+phase somewhat, but generate much smaller "-wal" temporary files on
+busy servers.  The default is 256.  Disabled if 0.
+
+.TP
+.B "\-v"
+Increase verbosity of logging to the standard error file descriptor.
+May be repeated to increase details.  The default verbosity is 0.
+
+.SH WEBAPI
+
+.\" Much of the following text is duplicated with debuginfod-find.1
+
+debuginfod's webapi resembles ordinary file service, where a GET
+request with a path containing a known buildid results in a file.
+Unknown buildid / request combinations result in HTTP error codes.
+This file service resemblance is intentional, so that an installation
+can take advantage of standard HTTP management infrastructure.
+
+For most queries, some custom http headers are added to the response,
+providing additional metadata about the buildid-related response.  For example:
+
+.SAMPLE
+% debuginfod-find -v debuginfo /bin/ls |& grep -i x-debuginfo
+x-debuginfod-size: 502024
+x-debuginfod-archive: /mnt/fedora_koji_prod/koji/packages/coreutils/9.3/4.fc39/x86_64/coreutils-debuginfo-9.3-4.fc39.x86_64.rpm
+x-debuginfod-file: /usr/lib/debug/usr/bin/ls-9.3-4.fc39.x86_64.debug
+.ESAMPLE
+
+.TP
+X-DEBUGINFOD-SIZE
+The size of the file, in bytes.  This may differ from the http Content-Length:
+field (if present), due to compression in transit.
+
+.TP
+X-DEBUGINFOD-FILE
+The full path name of the file related to the given buildid.
+
+.TP
+X-DEBUGINFOD-ARCHIVE
+The full path name of the archive that contained the above file, if any.
+
+
+
+
+There are a handful of buildid-related requests.  In each case, the
+buildid is encoded as a lowercase hexadecimal string.  For example,
+for a program \fI/bin/ls\fP, look at the ELF note GNU_BUILD_ID:
+
+.SAMPLE
+% readelf -n /bin/ls | grep -A4 build.id
+Note section [ 4] '.note.gnu.buildid' of 36 bytes at offset 0x340:
+Owner          Data size  Type
+GNU                   20  GNU_BUILD_ID
+Build ID: 8713b9c3fb8a720137a4a08b325905c7aaf8429d
+.ESAMPLE
+
+Then the hexadecimal BUILDID is simply:
+
+.SAMPLE
+8713b9c3fb8a720137a4a08b325905c7aaf8429d
+.ESAMPLE
+
+.SS /buildid/\fIBUILDID\fP/debuginfo
+
+If the given buildid is known to the server, this request will result
+in a binary object that contains the customary \fB.*debug_*\fP
+sections.  This may be a split debuginfo file as created by
+\fBstrip\fP, or it may be an original unstripped executable.
+
+.SS /buildid/\fIBUILDID\fP/executable
+
+If the given buildid is known to the server, this request will result
+in a binary object that contains the normal executable segments.  This
+may be a executable stripped by \fBstrip\fP, or it may be an original
+unstripped executable.  \fBET_DYN\fP shared libraries are considered
+to be a type of executable.
+
+.SS /buildid/\fIBUILDID\fP/source\fI/SOURCE/FILE\fP
+
+If the given buildid is known to the server, this request will result
+in a binary object that contains the source file mentioned.  The path
+should be absolute.  Relative path names commonly appear in the DWARF
+file's source directory, but these paths are relative to
+individual compilation unit AT_comp_dir paths, and yet an executable
+is made up of multiple CUs.  Therefore, to disambiguate, debuginfod
+expects source queries to prefix relative path names with the CU
+compilation-directory, followed by a mandatory "/".
+
+Note: the caller may or may not elide \fB../\fP or \fB/./\fP or extraneous
+\fB///\fP sorts of path components in the directory names.  debuginfod
+accepts both forms.  Specifically, debuginfod canonicalizes path names
+according to RFC3986 section 5.2.4 (Remove Dot Segments), plus reducing
+any \fB//\fP to \fB/\fP in the path.
+
+For example:
+.TS
+l l.
+#include <stdio.h>	/buildid/BUILDID/source/usr/include/stdio.h
+/path/to/foo.c	/buildid/BUILDID/source/path/to/foo.c
+\../bar/foo.c AT_comp_dir=/zoo/	/buildid/BUILDID/source/zoo//../bar/foo.c
+.TE
+
+Note: the client should %-escape characters in /SOURCE/FILE that are
+not shown as "unreserved" in section 2.3 of RFC3986. Some characters
+that will be escaped include "+", "\\", "$", "!", the 'space' character,
+and ";". RFC3986 includes a more comprehensive list of these characters.
+
+.SS /buildid/\fIBUILDID\fP/section\fI/SECTION\fP
+If the given buildid is known to the server, the server will attempt to
+extract the contents of an ELF/DWARF section named SECTION from the
+debuginfo file matching BUILDID.  If the debuginfo file can't be found
+or the section has type SHT_NOBITS, then the server will attempt to extract
+the section from the executable matching BUILDID.  If the section is
+successfully extracted then this request results in a binary object
+of the section's contents.  Note that this result is the raw binary
+contents of the section, not an ELF file.
+
+.SS /metrics
+
+This endpoint returns a Prometheus formatted text/plain dump of a
+variety of statistics about the operation of the debuginfod server.
+The exact set of metrics and their meanings may change in future
+versions.
+
+.SH DATA MANAGEMENT
+
+debuginfod stores its index in an sqlite database in a densely packed
+set of interlinked tables.  While the representation is as efficient
+as we have been able to make it, it still takes a considerable amount
+of data to record all debuginfo-related data of potentially a great
+many files.  This section offers some advice about the implications.
+
+As a general explanation for size, consider that debuginfod indexes
+ELF/DWARF files, it stores their names and referenced source file
+names, and buildids will be stored.  When indexing archives, it stores
+every file name \fIof or in\fP an archive, every buildid, plus every
+source file name referenced from a DWARF file.  (Indexing archives
+takes more space because the source files often reside in separate
+subpackages that may not be indexed at the same pass, so extra
+metadata has to be kept.)
+
+Getting down to numbers, in the case of Fedora RPMs (essentially,
+gzip-compressed cpio files), the sqlite index database tends to be
+from 0.5% to 3% of their size.  It's larger for binaries that are
+assembled out of a great many source files, or packages that carry
+much debuginfo-unrelated content.  It may be even larger during the
+indexing phase due to temporary sqlite write-ahead-logging files;
+these are checkpointed (cleaned out and removed) at shutdown.  It may
+be helpful to apply tight \-I or \-X regular-expression constraints to
+exclude files from scanning that you know have no debuginfo-relevant
+content.
+
+As debuginfod runs in normal \fIactive\fP mode, it periodically
+rescans its target directories, and any new content found is added to
+the database.  Old content, such as data for files that have
+disappeared or that have been replaced with newer versions is removed
+at a periodic \fIgrooming\fP pass.  This means that the sqlite files
+grow fast during initial indexing, slowly during index rescans, and
+periodically shrink during grooming.  There is also an optional
+one-shot \fImaximal grooming\fP pass is available.  It removes
+information debuginfo-unrelated data from the archive content index
+such as file names found in archives ("archive sdef" records) that are
+not referred to as source files from any binaries find in archives
+("archive sref" records).  This can save considerable disk space.
+However, it is slow and temporarily requires up to twice the database
+size as free space.  Worse: it may result in missing source-code info
+if the archive traversals were interrupted, so that not all source
+file references were known.  Use it rarely to polish a complete index.
+
+You should ensure that ample disk space remains available.  (The flood
+of error messages on -ENOSPC is ugly and nagging.  But, like for most
+other errors, debuginfod will resume when resources permit.)  If
+necessary, debuginfod can be stopped, the database file moved or
+removed, and debuginfod restarted.
+
+sqlite offers several performance-related options in the form of
+pragmas.  Some may be useful to fine-tune the defaults plus the
+debuginfod extras.  The \-D option may be useful to tell debuginfod to
+execute the given bits of SQL after the basic schema creation
+commands.  For example, the "synchronous", "cache_size",
+"auto_vacuum", "threads", "journal_mode" pragmas may be fun to tweak
+via \-D, if you're searching for peak performance.  The "optimize",
+"wal_checkpoint" pragmas may be useful to run periodically, outside
+debuginfod.  The default settings are performance- rather than
+reliability-oriented, so a hardware crash might corrupt the database.
+In these cases, it may be necessary to manually delete the sqlite
+database and start over.
+
+As debuginfod changes in the future, we may have no choice but to
+change the database schema in an incompatible manner.  If this
+happens, new versions of debuginfod will issue SQL statements to
+\fIdrop\fP all prior schema & data, and start over.  So, disk space
+will not be wasted for retaining a no-longer-useable dataset.
+
+In summary, if your system can bear a 0.5%-3% index-to-archive-dataset
+size ratio, and slow growth afterwards, you should not need to
+worry about disk space.  If a system crash corrupts the database,
+or you want to force debuginfod to reset and start over, simply
+erase the sqlite file before restarting debuginfod.
+
+In contrast, in \fIpassive\fP mode, all scanning and grooming is
+disabled, and the index database remains read-only.  This makes the
+database more suitable for sharing between servers or sites with
+simple one-way replication, and data management considerations are
+generally moot.
+
+.SH SECURITY
+
+debuginfod \fBdoes not\fP include any particular security features.
+While it is robust with respect to inputs, some abuse is possible.  It
+forks a new thread for each incoming HTTP request, which could lead to
+a denial-of-service in terms of RAM, CPU, disk I/O, or network I/O.
+If this is a problem, users are advised to install debuginfod with a
+HTTPS reverse-proxy front-end that enforces site policies for
+firewalling, authentication, integrity, authorization, and load
+control.
+
+Front-end proxies may elide sensitive path name components in
+X-DEBUGINFOD-FILE/ARCHIVE response headers.  For example, using Apache
+httpd's \fBmod_headers\fP, you can remove the entire directory name
+prefix:
+
+.SAMPLE
+Header edit x-debuginfod-archive ".*/" ""
+.ESAMPLE
+
+When relaying queries to upstream debuginfods, debuginfod \fBdoes not\fP
+include any particular security features.  It trusts that the binaries
+returned by the debuginfods are accurate.  Therefore, the list of
+servers should include only trustworthy ones.  If accessed across HTTP
+rather than HTTPS, the network should be trustworthy.  Authentication
+information through the internal \fIlibcurl\fP library is not currently
+enabled.
+
+.nr zZ 1
+.so man7/debuginfod-client-config.7
+
+.SH ADDITIONAL FILES
+.TP
+.B $HOME/.debuginfod.sqlite
+Default database file.
+.PD
+
+
+.SH "SEE ALSO"
+.I "debuginfod-find(1)"
+.I "sqlite3(1)"
+.I \%https://prometheus.io/docs/instrumenting/exporters/
diff --git a/doc/debuginfod.service.8 b/doc/debuginfod.service.8
new file mode 100644
index 0000000..b22b757
--- /dev/null
+++ b/doc/debuginfod.service.8
@@ -0,0 +1,30 @@
+'\"! tbl | nroff \-man
+'\" t macro stdmacro
+
+.TH DEBUGINFOD.SERVICE 8
+.SH NAME
+debuginfod.service \- debuginfo related information server for systemd
+
+.SH SYNOPSIS
+.B /usr/lib/systemd/system/debuginfod.service
+
+.SH DESCRIPTION
+\fBdebuginfod.service\fP integrates the debuginfod daemon with
+systemd, serving debuginfo-related artifacts over HTTP.
+The data is stored in /var/cache/debuginfod/debuginfod.sqlite.
+Configure /etc/sysconfig/debuginfod to set the below environment
+variables as well as those listed in \fBdebuginfod\fP(8).
+.SH Environment variables
+\fB$DEBUGINFOD_PORT\fP - Changes port of \fBdebuginfod\fP service
+daemon.
+.br
+\fB$DEBUGINFOD_VERBOSE\fP - Change verbosity of reporting in
+\fBdebuginfod\fP service daemon log file.
+.br
+\fB$DEBUGINFOD_PATHS\fP - Changes paths to scan for \fBdebuginfod\fP service daemon.
+.SH FILES
+/usr/lib/systemd/system/debuginfod.service, /var/cache/debuginfod/debuginfod.sqlite
+/etc/sysconfig/debuginfod
+
+.SH SEE ALSO
+debuginfod(8), debuginfod-find(1), systemctl(1), systemd.service(5)
diff --git a/doc/debuginfod_add_http_header.3 b/doc/debuginfod_add_http_header.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_add_http_header.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_begin.3 b/doc/debuginfod_begin.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_begin.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_end.3 b/doc/debuginfod_end.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_end.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_find_debuginfo.3 b/doc/debuginfod_find_debuginfo.3
new file mode 100644
index 0000000..0d55366
--- /dev/null
+++ b/doc/debuginfod_find_debuginfo.3
@@ -0,0 +1,332 @@
+'\"! tbl | nroff \-man
+'\" t macro stdmacro
+
+.de SAMPLE
+.br
+.RS 0
+.nf
+.nh
+..
+.de ESAMPLE
+.hy
+.fi
+.RE
+..
+
+.TH DEBUGINFOD_FIND_* 3
+.SH NAME
+debuginfod_find_debuginfo \- request debuginfo from debuginfod
+
+.SH SYNOPSIS
+.nf
+.B #include <elfutils/debuginfod.h>
+.PP
+Link with \fB-ldebuginfod\fP.
+
+CONNECTION HANDLE
+
+.BI "debuginfod_client *debuginfod_begin(void);"
+.BI "void debuginfod_end(debuginfod_client *" client ");"
+
+LOOKUP FUNCTIONS
+
+.BI "int debuginfod_find_debuginfo(debuginfod_client *" client ","
+.BI "                              const unsigned char *" build_id ","
+.BI "                              int " build_id_len ","
+.BI "                              char ** " path ");"
+.BI "int debuginfod_find_executable(debuginfod_client *" client ","
+.BI "                               const unsigned char *" build_id ","
+.BI "                               int " build_id_len ","
+.BI "                               char ** " path ");"
+.BI "int debuginfod_find_source(debuginfod_client *" client ","
+.BI "                           const unsigned char *" build_id ","
+.BI "                           int " build_id_len ","
+.BI "                           const char *" filename ","
+.BI "                           char ** " path ");"
+.BI "int debuginfod_find_section(debuginfod_client *" client ","
+.BI "                           const unsigned char *" build_id ","
+.BI "                           int " build_id_len ","
+.BI "                           const char * " section ","
+.BI "                           char ** " path ");"
+
+
+OPTIONAL FUNCTIONS
+
+.BI "typedef int (*debuginfod_progressfn_t)(debuginfod_client *" client ","
+.BI "                                       long a, long b);"
+.BI "void debuginfod_set_progressfn(debuginfod_client *" client ","
+.BI "                               debuginfod_progressfn_t " progressfn ");"
+.BI "void debuginfod_set_verbose_fd(debuginfod_client *" client ","
+.BI "                               int " fd ");"
+.BI "void debuginfod_set_user_data(debuginfod_client *" client ","
+.BI "                              void *" data ");"
+.BI "void* debuginfod_get_user_data(debuginfod_client *" client ");"
+.BI "const char* debuginfod_get_url(debuginfod_client *" client ");"
+.BI "int debuginfod_add_http_header(debuginfod_client *" client ","
+.BI "                               const char* " header ");"
+.BI "const char* debuginfod_get_headers(debuginfod_client *" client ");"
+
+.SH DESCRIPTION
+
+.BR debuginfod_begin ()
+creates a \fBdebuginfod_client\fP connection handle that should be used
+with all other calls.
+.BR debuginfod_end ()
+should be called on the \fBclient\fP handle to release all state and
+storage when done.
+
+.BR debuginfod_find_debuginfo (),
+.BR debuginfod_find_executable (),
+and
+.BR debuginfod_find_source ()
+query the debuginfod server URLs contained in
+.BR $DEBUGINFOD_URLS
+(see below) for the debuginfo, executable or source file with the
+given \fIbuild_id\fP. \fIbuild_id\fP should be a pointer to either
+a null-terminated, lowercase hex string or a binary blob. If
+\fIbuild_id\fP is given as a hex string, \fIbuild_id_len\fP should
+be 0. Otherwise \fIbuild_id_len\fP should be the number of bytes in
+the binary blob.
+
+.BR debuginfod_find_source ()
+also requires a \fIfilename\fP in order to specify a particular
+source file. \fIfilename\fP should be an absolute path that includes
+the compilation directory of the CU associated with the source file.
+Relative path names commonly appear in the DWARF file's source directory,
+but these paths are relative to individual compilation unit AT_comp_dir
+paths, and yet an executable is made up of multiple CUs. Therefore, to
+disambiguate, debuginfod expects source queries to prefix relative path
+names with the CU compilation-directory, followed by a mandatory "/".
+
+Note: the caller may or may not elide \fB../\fP or \fB/./\fP or extraneous
+\fB///\fP sorts of path components in the directory names.  debuginfod
+accepts both forms.  Specifically, debuginfod canonicalizes path names
+according to RFC3986 section 5.2.4 (Remove Dot Segments), plus reducing
+any \fB//\fP to \fB/\fP in the path.
+
+.BR debuginfod_find_section ()
+queries the debuginfod server URLs contained in
+.BR $DEBUGINFOD_URLS
+for the binary contents of an ELF/DWARF section contained in a debuginfo
+or executable file with the given \fIbuild_id\fP. \fIsection\fP should
+be the name of the desired ELF/DWARF section.  If a server does not support
+section queries, debuginfod_find_section may query the server for the
+debuginfo and/or executable with \fIbuild_id\fP in order to retrieve
+and extract the section.
+
+If \fIpath\fP is not NULL and the query is successful, \fIpath\fP is set
+to the path of the file in the cache. The caller must \fBfree\fP() this value.
+
+The URLs in \fB$DEBUGINFOD_URLS\fP may be queried in parallel. As soon
+as a debuginfod server begins transferring the target file all of the
+connections to the other servers are closed.
+
+A \fBclient\fP handle should be used from only one thread at a time.
+A handle may be reused for a series of lookups, which can improve
+performance due to retention of connections and caches.
+
+.SH "RETURN VALUE"
+
+\fBdebuginfod_begin\fP returns the \fBdebuginfod_client\fP handle to
+use with all other calls.  On error \fBNULL\fP will be returned and
+\fBerrno\fP will be set.
+
+If a find family function is successful, the resulting file is saved
+to the client cache and a file descriptor to that file is returned.
+The file descriptor points to the beginning of the file.  The caller
+needs to \fBclose\fP() this descriptor.  Otherwise, a negative error
+code is returned.
+
+.SH "OPTIONAL FUNCTIONS"
+
+A small number of optional functions are available to tune or query
+the operation of the debuginfod client.
+
+.SS "PROGRESS CALLBACK"
+
+As the \fBdebuginfod_find_*\fP() functions may block for seconds or
+longer, a progress callback function is called periodically, if
+configured with
+.BR debuginfod_set_progressfn ().
+This function sets a new progress callback function (or NULL) for the
+client handle.
+
+The given callback function is called from the context of each thread
+that is invoking any of the other lookup functions.  It is given two
+numeric parameters that, if thought of as a numerator \fIa\fP and
+denominator \fIb\fP, together represent a completion fraction
+\fIa/b\fP.  The denominator may be zero initially, until a quantity
+such as an exact download size becomes known.
+
+The progress callback function is also the supported way to
+\fIinterrupt\fP the download operation.  (The library does \fInot\fP
+modify or trigger signals.)  The progress callback must return 0 to
+continue the work, or any other value to stop work as soon as
+possible.  Consequently, the \fBdebuginfod_find_*\fP() function will
+likely return with an error, but might still succeed.
+
+.SS "VERBOSE OUTPUT"
+
+The \fBdebuginfod_find_*\fP() functions may use several techniques
+to retrieve the requested files, through the cache or through one
+or multiple servers or file URLs. To show how a query is handled the
+.BR debuginfod_set_verbose_fd ()
+can be used to set a particular file descriptor on which verbose
+output is given about the query steps and eventual errors encountered.
+
+.SS "USER DATA POINTER"
+
+A single \fIvoid *\fP pointer associated with the connection handle
+may be set any time via
+.BR \%debuginfod_set_user_data () ,
+and retrieved via
+.BR \%debuginfod_get_user_data () .
+The value is undefined if unset.
+
+.SS "URL"
+
+The URL of the current or most recent outgoing download, if known,
+may be retrieved via
+.BR \%debuginfod_get_url ()
+from the progressfn callback, or afterwards.  It may be NULL.
+The resulting string is owned by the library, and must not be modified
+or freed.  The caller should copy it if it is needed beyond the release
+of the client object.
+
+.SS "HTTP HEADER"
+
+Before each lookup function is initiated, a client application may
+add HTTP request headers.  These are reset after each lookup function.
+.BR \%debuginfod_add_http_header ()
+may be called with strings of the form
+.BR \%"Header:\~value" .
+These strings are copied by the library.  A zero return value
+indicates success, but out-of-memory conditions may result in
+a non-zero \fI-ENOMEM\fP. If the string is in the wrong form
+\fI-EINVAL\fP will be returned.
+
+\fI$DEBUGINFOD_HEADERS_FILE\fP specifies a file to supply headers to
+outgoing requests. Each non-whitespace line of this file is handled
+as if
+.BR \%debuginfod_add_http_header ()
+were called on the contents.
+
+Note that the current debuginfod-client library implementation uses
+libcurl, but you shouldn't rely on that fact. Don't use this function
+for replacing any standard headers, except for the User-Agent mentioned
+below. You can use this function to add authorization information for
+access control, or to provide optional headers to the server for
+logging purposes.
+
+By default, the library adds a descriptive \fIUser-Agent:\fP
+header to outgoing requests.  If the client application adds
+a header with the same name, this default is suppressed.
+
+During or after a lookup, a client application may call
+.BR \%debuginfod_get_headers ()
+to gather the subset of HTTP response headers received from the
+current or most recent debuginfod server.  Only those headers prefixed
+with
+.BR X-DEBUGINFOD
+(case-insensitive) are kept.  They are returned as a single string,
+with each "header: value" terminated with a \\n (not \\r\\n as in
+HTTP).  It may be NULL.  The resulting string is owned by the library,
+and must not be modified or freed.  The caller should copy the
+returned string if it is needed beyond the release of the client
+object.
+
+.SH "MACROS"
+
+.SS "DEBUGINFOD_SONAME"
+
+Defined to the string that could be passed to
+.BR dlopen (3)
+if the library is loaded at runtime, for example
+
+.PP
+.in +4n
+.EX
+void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, RTLD_LAZY);
+.EE
+.in
+
+.SH "SECURITY"
+.BR debuginfod_find_* ()
+functions \fBdo not\fP include any particular security
+features.  They trust that the binaries returned by the debuginfod(s)
+are accurate.  Therefore, the list of servers should include only
+trustworthy ones.  If accessed across HTTP rather than HTTPS, the
+network should be trustworthy.  Passing user authentication information
+through the internal \fIlibcurl\fP library is not currently enabled, except
+for the basic plaintext \%\fIhttp[s]://userid:password@hostname/\fP style.
+(The debuginfod server does not perform authentication, but a front-end
+proxy server could.)
+
+.SH "ERRORS"
+The following list is not comprehensive. Error codes may also
+originate from calls to various C Library functions.
+
+.TP
+.BR EACCESS
+Denied access to resource located at the URL.
+
+.TP
+.BR ECONNREFUSED
+Unable to connect to remote host. Also returned when an HTTPS connection
+couldn't be verified (bad certificate).
+
+.TP
+.BR ECONNRESET
+Unable to either send or receive network data.
+
+.TP
+.BR EHOSTUNREACH
+Unable to resolve remote host.
+
+.TP
+.BR EINVAL
+One or more arguments are incorrectly formatted. \fIbuild_id\fP may
+be too long (greater than 256 characters), \fIfilename\fP may not
+be an absolute path or a debuginfod URL is malformed.
+
+.TP
+.BR EIO
+Unable to write data received from server to local file.
+
+.TP
+.BR EMLINK
+Too many HTTP redirects.
+
+.TP
+.BR ENETUNREACH
+Unable to initialize network connection.
+
+.TP
+.BR ENOENT
+Could not find the resource located at URL. Often this error code
+indicates that a debuginfod server was successfully contacted but
+the server could not find the target file.
+
+.TP
+.BR ENOMEM
+System is unable to allocate resources.
+
+.TP
+.BR ENOSYS
+\fB$DEBUGINFOD_URLS\fP is not defined.
+
+.TP
+.BR ETIME
+Query failed due to timeout. \fB$DEBUGINFOD_TIMEOUT\fP and
+\fB$DEBUGINFOD_MAXTIME\fP control this.
+
+.TP
+.BR EF2BIG
+Query aborted due to the file requested being too big.  The
+\fB$DEBUGINFOD_MAXSIZE\fP controls this.
+
+.nr zZ 1
+.so man7/debuginfod-client-config.7
+
+.SH "SEE ALSO"
+.I "debuginfod(8)"
diff --git a/doc/debuginfod_find_executable.3 b/doc/debuginfod_find_executable.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_find_executable.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_find_section.3 b/doc/debuginfod_find_section.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_find_section.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_find_source.3 b/doc/debuginfod_find_source.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_find_source.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_get_headers.3 b/doc/debuginfod_get_headers.3
new file mode 100644
index 0000000..1db5598
--- /dev/null
+++ b/doc/debuginfod_get_headers.3
@@ -0,0 +1,2 @@
+.so man3/debuginfod_find_debuginfo.3
+
diff --git a/doc/debuginfod_get_url.3 b/doc/debuginfod_get_url.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_get_url.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_get_user_data.3 b/doc/debuginfod_get_user_data.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_get_user_data.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_set_progressfn.3 b/doc/debuginfod_set_progressfn.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_set_progressfn.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/debuginfod_set_user_data.3 b/doc/debuginfod_set_user_data.3
new file mode 100644
index 0000000..1627993
--- /dev/null
+++ b/doc/debuginfod_set_user_data.3
@@ -0,0 +1 @@
+.so man3/debuginfod_find_debuginfo.3
diff --git a/doc/elf_begin.3 b/doc/elf_begin.3
new file mode 100644
index 0000000..6a1d0c2
--- /dev/null
+++ b/doc/elf_begin.3
@@ -0,0 +1,37 @@
+.\" Modified Thu Sep 5 2017 by Ben Woodard <woodard@redhat.com>
+.\"
+.TH ELF_BEGIN 3 2017-09-05 "Libelf" "Libelf Programmer's Manual"
+.SH NAME
+elf_begin \- Return descriptor for ELF file.
+.nf
+.SH SYNOPSIS
+.B #include <libelf.h>
+.sp
+.BI "Elf *elf_begin (int " filedes ", Elf_Cmd " cmd ", Elf *" ref ");"
+.BI "Elf *elf_clone (int " filedes ", Elf_Cmd " cmd ");"
+.BI "int elf_end (Elf *" elf ");"
+.fi
+.SH DESCRIPTION
+The
+.BR elf_begin ()
+.SH RETURN VALUE
+.SH ERRORS
+elf_begin ELF_E_NO_VERSION ELF_E_INVALID_FILE ELF_E_INVALID_CMD ELF_E_NOMEM
+elf_clone ELF_E_NOMEM
+elf_end
+.SH ATTRIBUTES
+For an explanation of the terms used in this section, see
+.BR attributes (7).
+.TS
+allbox;
+lbw29 lb lb
+l l l.
+Interface       Attribute       Value
+T{
+.BR elf_begin (),
+.BR elf_clone (),
+.BR elf_end ()
+T}      Thread safety   MT-Safe
+.TE
+
+.SH SEE ALSO
diff --git a/doc/elf_clone.3 b/doc/elf_clone.3
new file mode 100644
index 0000000..38ec921
--- /dev/null
+++ b/doc/elf_clone.3
@@ -0,0 +1,14 @@
+.\" Modified Thu Sep 5 2017 by Ben Woodard <woodard@redhat.com>
+.\"
+.TH ELF_CLONE 3 2017-09-05 "Libelf" "Libelf Programmer's Manual"
+.SH NAME
+elf_clone \- Create a clone of an existing ELF descriptor.
+.nf
+.SH SYNOPSIS
+.B #include <libelf.h>
+.sp
+.BI "Elf *elf_clone (int " filedes ", Elf_Cmd " cmd ");"
+.fi
+.SH DESCRIPTION
+The
+.BR elf_clone ()
diff --git a/doc/elf_getdata.3 b/doc/elf_getdata.3
new file mode 100644
index 0000000..44d9304
--- /dev/null
+++ b/doc/elf_getdata.3
@@ -0,0 +1,28 @@
+.\" Modified Thu Aug 17 2017 by Ben Woodard <woodard@redhat.com>
+.\"
+.TH ELF_GETDATA 3 2017-08-17 "Libelf" "Libelf Programmer's Manual"
+.SH NAME
+elf_getdata \- Get washed data of section
+.nf
+.SH SYNOPSIS
+.B #include <libelf.h>
+.sp
+.BI "Elf_Data * elf_getdata (Elf_Scn *" scn ", Elf_Data *" data ");"
+.fi
+.SH DESCRIPTION
+The
+.BR elf_getdata ()
+function allows the user to retrieve the data buffers of the section
+.I scn
+ . There can be more than one buffer if the user explicitly added them.
+When a file is read the libelf library creates exactly one data buffer.
+
+The first buffer in the list can be obtained by passing a null pointer in the
+parameter data. To get the next data buffer the previously returned value must
+be passed in the data parameter. If there are no more buffer left in the list a
+null pointer is returned.
+
+If the data parameter is not a null pointer it must be a descriptor for a
+buffer associated with the section scn . If this is not the case a null pointer
+is returned. To facilitate error handling elf_getdata also returns a null
+pointer if the scn parameter is a null pointer.
diff --git a/doc/elf_update.3 b/doc/elf_update.3
new file mode 100644
index 0000000..d0a7ab1
--- /dev/null
+++ b/doc/elf_update.3
@@ -0,0 +1,14 @@
+.\" Modified Thu Sep 5 2017 by Ben Woodard <woodard@redhat.com>
+.\"
+.TH ELF_UPDATE 3 2017-09-05 "Libelf" "Libelf Programmer's Manual"
+.SH NAME
+elf_update \- update an ELF descriptor
+.nf
+.SH SYNOPSIS
+.B #include <libelf.h>
+.sp
+.BI "off_t elf_update (Elf *" elf ", Elf_Cmd " cmd ");"
+.fi
+.SH DESCRIPTION
+The
+.BR elf_update ()
diff --git a/doc/elfclassify.1 b/doc/elfclassify.1
new file mode 100644
index 0000000..cbfdae4
--- /dev/null
+++ b/doc/elfclassify.1
@@ -0,0 +1,197 @@
+.\" Copyright 2019 Red Hat Inc.
+.\" Tue 2019-Aug 20 Ben Woodard <woodard@redhat.com>
+.\"                 Florian Wiemer <fwiemer@redhat.com>
+.\"                 Mark Wielaard <mjw@redhat.com>
+.\" Contact elfutils-devel@sourceware.org to correct errors or typos.
+.TH EU-ELFCLASSIFY 1 "2019-Aug-20" "elfutils" 
+.SH "NAME"
+eu-elfclassify \- Determine the type of an ELF file.
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+eu-elfclassify [\fB\-\-core\fR]
+        [\fB\-\-debug-only\fR]
+        [\fB\-\-elf\fR]
+        [\fB\-\-elf\-archive\fR]
+        [\fB\-\-elf\-file\fR]
+        [\fB\-\-executable\fR]
+        [\fB\-\-library\fR]
+        [\fB\-\-linux\-kernel\-module\fR]
+        [\fB\-\-loadable\fR]
+        [\fB\-\-program\fR]
+        [\fB\-\-shared\fR]
+        [\fB\-\-unstripped\fR]
+        [\fB\-f\fR|\fB \-\-file\fR]
+        [\fB\-\-no\-stdin\fR]
+        [\fB\-\-stdin\fR]
+        [\fB\-\-stdin0\fR]
+        [\fB\-z\fR|\fB \-\-compressed\fR]
+        [\fB\-\-matching\fR]
+        [\fB\-\-no\-print\fR]
+        [\fB\-\-not\-matching\fR]
+        [\fB\-\-print\fR]
+        [\fB\-\-print0\fR]
+        [\fB\-q\fR|\fB \-\-quiet\fR]
+        [\fB\-v\fR|\fB \-\-verbose\fR]
+        [\fB\-?\fR|\fB \-\-help\fR]
+        [\fB\-\-usage\fR]
+        [\fB\-V\fR|\fB \-\-version\fR]
+	\fIelffile\fR...
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+\&\fBeu-elfclassify\fR identifies the primary purpose of a particular kind of
+ \s-1ELF\s0 file or files
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+The long and short forms of options, shown here as alternatives, are
+equivalent. All of the classification options must apply at the same time to a
+particular file.  Classification options can be negated using a
+\fB\-\-not\-\fR  prefix.
+.SS "Classification Options"
+.IX Subsection "Classification Options"
+.IP "\fB\-\-core\fR" 4
+.IX Item "--core"
+.PD
+File is an ELF core dump file.
+.IP "\FB\-\-debug\-only\fR" 4
+.IX Item "--debug-only"
+.PD
+File is a debug only ELF file (separate .debug, .dwo or dwz multi-file).
+.IP "\fB\-\-elf\fR" 4
+.IX Item "--elf"
+.PD
+File looks like an ELF object or archive/static library (default).
+.IP "\fB\-\-elf\-archive\fR" 4
+.IX Item "--elf-archive"
+.PD
+File is an ELF archive or static library.
+.IP "\fB\-\-elf\-file\fR" 4
+.IX Item "--elf-file"
+.PD
+File is an regular ELF object (not an archive/static library).
+.IP "\fB\-\-executable\fR" 4
+.IX Item "--executable"
+.PD
+File is (primarily) an ELF program executable (not primarily a DS.O)
+.IP "\fB\-\-library\fR" 4
+.IX Item "--library"
+.PD
+File is an ELF shared object (DSO) (might also be an executable).
+.IP "\fB\-\-linux\-kernel\-module\fR" 4
+.IX Item "--linux-kernel-module"
+.PD
+File is a linux kernel module.
+.IP "\fB\-\-loadable\fR" 4
+.IX Item "--loadable"
+.PD
+File is a loadable ELF object (program or shared object).
+.IP "\fB\--program\fR" 4
+.IX Item "--program"
+.PD
+File is an ELF program executable (might also be a DSO).
+.IP "\fB\-\-shared\fR" 4
+.IX Item "--shared"
+.PD
+File is (primarily) an ELF shared object (DSO) (not primarily an executable).
+.IP "\fB\-\-unstripped\fR" 4
+.IX Item "--unstripped"
+.PD
+File is an ELF file with symbol table or .debug_* sections and can be stripped
+further.
+.SS "Input flags"
+.IX Subsection "Input flags"
+.IP "\fB\-f\fR" 4
+.IX Item "-f"
+.PD 0
+.IP "\fB\-\-file\fR" 4
+.IX Item "--file"
+.PD
+Only classify regular (not symlink nor special device) files.
+.IP "\fB\-\-no\-stdin\fR" 4
+.IX Item "--no-stdin"
+.PD
+Do not read files from standard input (default).
+.IP "\fB\-\-stdin\fR" 4
+.IX Item "--stdin"
+.PD
+Also read file names to process from standard input, separated by newlines.
+.IP "\fB\-\-stdin0\fR" 4
+.IX Item "--stdin0"
+.PD
+Also read file names to process from standard input, separated by ASCII NUL
+bytes.
+.IP "\fB\-z\fR" 4
+.IX Item "-z"
+.PD 0
+.IP "\fB\-\-compressed\fR" 4
+.IX Item "--compressed"
+.PD
+Try to open compressed files or embedded (kernel) ELF images.
+.SS "Output flags"
+.IX Subsection "Output flags"
+.IP "\fB\-\-matching\fR" 4
+.IX Item "--matching"
+.PD
+If printing file names, print matching files (default).
+.IP "\fB\-\-no\-print\fR" 4
+.IX Item "--no-print"
+.PD
+Do not output file names.
+.IP "\fB\-\-not\-matching\fR" 4
+.IX Item "--not-matching"
+.PD
+If printing file names, print files that do not match.
+.IP "\fB\-\-print\fR" 4
+.IX Item "--print"
+.PD
+Output names of files, separated by newline.
+.IP "\fB\-\-print0\fR" 4
+.IX Item "--print0"
+.PD
+Output names of files, separated by ASCII NUL.
+.SS " Additional flags"
+.IX Subsection " Additional flags"
+.IP "\fB\-q\fR" 4
+.IX Item "-q,"
+.PD
+.IP "\fB\-\-quiet\fR" 4
+.IX Item "--quiet"
+.PD
+Suppress some error output (counterpart to --verbose).
+.IP "\fB\-v\fR" 4
+.IX Item "-v"
+.PD
+.IP "\fB\-\-verbose\fR" 4
+.IX Item "--verbose"
+.PD
+Output additional information (can be specified multiple times).
+.IP "\fB\-?\fR" 4
+.IX Item "-?"
+.PD
+.IP "\fB\-\-help\fR" 4
+.IX Item "--help"
+.PD
+Give this help list.
+.IP "\fB\-\-usage\fR" 4
+.IX Item "--usage"
+.PD
+Give a short usage message.
+.IP "\fB\-V\fR" 4
+.IX Item "-V"
+.PD
+.IP "\fB\-\-version\fR" 4
+.IX Item "--version"
+.PD
+Print program version.
+
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Written by Florian Wiemer.
+.SH "REPORTING BUGS"
+.IX Header "REPORTING BUGS"
+Please reports bugs at https://sourceware.org/bugzilla/
+.SH "COPYRIGHT"
+.IX Header "COPYRIGHT"
+Copyright © 2019 Red Hat Inc.  License GPLv3+: GNU GPL version 3 or
+later <https://gnu.org/licenses/gpl.html>.  This is free software: you
+are free to change and redistribute it.  There is NO WARRANTY, to the
+extent permitted by law.
diff --git a/doc/elfutils.sgml b/doc/elfutils.sgml
new file mode 100644
index 0000000..e8a483a
--- /dev/null
+++ b/doc/elfutils.sgml
@@ -0,0 +1,444 @@
+<!doctype book PUBLIC "-//OASIS//DTD DocBook V4.1//EN"[
+<!ENTITY package "<filename>new-bu</filename>">
+]>
+
+<book>
+  <title>New Binutils User's and Reference Manual</title>
+
+  <chapter>
+    <title><filename>libelf</filename> <acronym>ABI</acronym></title>
+
+    <simpara>The <acronym>ABI</acronym> of the
+    <filename>libelf</filename> implemented in the &package; package
+    is following that of Sun's implementation which in turn in derived
+    from the original SysVr4 implementation.  There are some
+    extensions over Sun's versions, though, which makes it impossible
+    to replace this implementation with Sun's.</simpara>
+
+    <beginpage>
+
+    <refentry xreflabel="Elf_Data" id="ElfUData">
+      <refnamediv>
+	<refname>Elf_Data</refname>
+	<refpurpose>Descriptor for Data Buffer</refpurpose>
+      </refnamediv>
+
+      <refsynopsisdiv>
+	<synopsis>
+#include &lt;libelf.h&gt;
+</synopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+	<title>Description</title>
+
+	<simpara>The <structname>Elf_Data</structname> structure is as
+	a descriptor for a data buffer associated with a section.
+	Every data buffer is associated with a specific section (see
+	<!-- xref --><structname>Elf_Scn</structname>).</simpara>
+
+	<simpara>A data buffer is created when reading a file.  In
+	this case only a single buffer is present in the section.  The
+	user can add as many sections as wanted to a section and they
+	can be retrieved using the <function>elf_getdata</function>
+	and <function>elf_rawdata</function> functions.<!-- xref
+	--></simpara>
+
+	<simpara>The <structname>Elf_Data</structname> structure
+	contains the following members:</simpara>
+
+	<programlisting>
+   void         *d_buf
+   Elf_Type      d_type
+   size_t        d_size
+   off_t         d_off
+   size_t        d_align
+   unsigned int  d_version
+</programlisting>
+
+	<simpara>All of these members can be modified directly by the
+	user.  They can be used to resize a section, to change its
+	content or type, and many more tasks.  This is also true for
+	the data read from a file.  The meaning of each member is as
+	follows:</simpara>
+
+	<variablelist>
+	  <varlistentry>
+	    <term><structfield>d_buf</structfield></term>
+	    <listitem>
+	      <simpara>The <structfield>d_buf</structfield> member is
+	      the pointer to the buffer with the actual data.  When
+	      the ELF file was read from a file the first and only
+	      data buffer of a section is allocated by the
+	      <filename>libelf</filename> library.  The user should
+	      not try to resize or free this buffer.  When the user
+	      adds a new data buffer to a section the associated
+	      memory block is normally allocated by the user.  It is
+	      important that the buffer must have a lifetime at least
+	      until the ELF file is closed entirely (important when
+	      the buffer is allocated on the stack).  If the buffer is
+	      not allocated on the stack it is the user's
+	      responsibility to free the buffer after it is not used
+	      anymore.  The <structfield>d_buf</structfield> member
+	      can contain a null pointer if the data buffer is
+	      empty.</simpara>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>d_type</structfield></term>
+	    <listitem>
+	      <simpara>The <structfield>d_type</structfield>
+	      determines how the data of the buffer is interpreted.
+	      This type is determined from the section type and must
+	      be the same for all data buffers for a section.  See
+	      <!-- xref --><type>Elf_Type</type> for more information.
+	      The <function><link linkend="elfUgetdata"
+	      endterm="elfUgetdata.refname"></link></function>
+	      function uses this information to convert the data of
+	      the buffer between the external form and the form
+	      represented to the user and back if necessary.</simpara>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>d_version</structfield></term>
+	    <listitem>
+	      <simpara>The <structfield>d_version</structfield>
+              contains the ELF version of the file.</simpara>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>d_size</structfield></term>
+	    <listitem>
+	      <simpara>The <structfield>d_size</structfield> contains
+              the size of the buffer in bytes.</simpara>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>d_off</structfield></term>
+	    <listitem>
+	      <simpara>The <structfield>d_off</structfield> is the
+              offset into the section in bytes.</simpara>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term><structfield>d_align</structfield></term>
+	    <listitem>
+	      <simpara>The <structfield>d_align</structfield> is the
+              address alignment of the section in bytes.</simpara>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </refsect1>
+    </refentry>
+
+    <beginpage>
+
+    <refentry id="elfUgetdata">
+      <refnamediv>
+	<refname id="elfUgetdata.refname">elf_getdata</refname>
+	<refpurpose>Get washed data of section</refpurpose>
+      </refnamediv>
+
+      <refsynopsisdiv>
+	<funcsynopsis>
+	  <funcsynopsisinfo>
+#include &lt;libelf.h&gt;
+</funcsynopsisinfo>
+	  <funcprototype>
+	    <funcdef>Elf_Data *<function>elf_getdata</function></funcdef>
+	    <paramdef>Elf_Scn *<parameter>scn</parameter></paramdef>
+	    <paramdef>Elf_Data *<parameter>data</parameter></paramdef>
+	  </funcprototype>
+	</funcsynopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+	<title>Description</title>
+
+	<simpara>The <function>elf_getdata</function> function allows
+	the user to retrieve the data buffers of the section
+	<parameter>scn</parameter>.  There can be more than one buffer
+	if the user explicitly added them.  When a file is read the
+	<filename>libelf</filename> library creates exactly one data
+	buffer.</simpara>
+
+	<simpara>The first buffer in the list can be obtained by
+	passing a null pointer in the parameter
+	<parameter>data</parameter>.  To get the next data buffer the
+	previously returned value must be passed in the
+	<parameter>data</parameter> parameter.  If there are no more
+	buffer left in the list a null pointer is returned.</simpara>
+
+	<simpara>If the <parameter>data</parameter> parameter is not a
+	null pointer it must be a descriptor for a buffer
+	associated with the section <parameter>scn</parameter>.  If
+	this is not the case a null pointer is returned.  To
+	facilitate error handling <function>elf_getdata</function>
+	also returns a null pointer if the <parameter>scn</parameter>
+	parameter is a null pointer.</simpara>
+      </refsect1>
+    </refentry>
+
+    <refentry>
+      <refnamediv>
+	<refname id="elfUupdate.refname">elf_update</refname>
+	<refpurpose>update an ELF descriptor</refpurpose>
+      </refnamediv>
+
+      <refsynopsisdiv>
+	<funcsynopsis>
+	  <funcsynopsisinfo>
+#include &lt;libelf.h&gt;
+</funcsynopsisinfo>
+	  <funcprototype>
+	    <funcdef>off_t <function>elf_update</function></funcdef>
+	    <paramdef>Elf *<parameter>elf</parameter></paramdef>
+	    <paramdef>Elf_Cmd <parameter>cmd</parameter></paramdef>
+	  </funcprototype>
+	</funcsynopsis>
+      </refsynopsisdiv>
+
+      <refsect1>
+	<title>Description</title>
+
+	<simpara>The user is responsible for filling in the following
+	fields in the named data structures:</simpara>
+
+	<table>
+	  <title>Fields not set by <function>elf_update</function></title>
+	  <tgroup cols="3">
+            <colspec colwidth="90pt">
+            <colspec colwidth="110pt">
+	    <thead>
+	      <row>
+		<entry>Data Structure</entry>
+		<entry>Member</entry>
+		<entry>Exception</entry>
+	      </row>
+	    </thead>
+	    <tbody>
+	      <row>
+		<entry morerows="8"><type>Elfxx_Ehdr</type></entry>
+		<entry>e_ident[EI_DATA]</entry>
+		<entry>see below</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_type</entry>
+		<!-- <entry morerows="1"></entry> -->
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_machine</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_version</entry>
+		<entry>see below</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_entry</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_phoff</entry>
+		<entry>if <symbol>ELF_F_LAYOUT</symbol> is used</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_shoff</entry>
+		<entry>if <symbol>ELF_F_LAYOUT</symbol> is used</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_flags</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>e_shstrndx</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry morerows="7">Elfxx_Phdr</entry>
+		<entry>p_type</entry>
+		<entry morerows="7"></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_offset</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_vaddr</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_paddr</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_filesz</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_memsz</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_flags</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>p_align</entry>
+		<entry></entry>
+	      </row>
+
+	      <row>
+		<entry morerows="9">Elfxx_Shdr</entry>
+		<entry>sh_name</entry>
+		<entry morerows="3"></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_type</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_flags</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_addr</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_offset</entry>
+		<entry>if <symbol>ELF_F_LAYOUT</symbol> is used</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_size</entry>
+		<entry>if <symbol>ELF_F_LAYOUT</symbol> is used</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_link</entry>
+		<!-- <entry morerows="1"></entry> -->
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_info</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_addralign</entry>
+		<entry>if <symbol>ELF_F_LAYOUT</symbol> is used</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>sh_entsize</entry>
+		<entry></entry>
+	      </row>
+
+	      <row>
+		<entry morerows="5">Elf_Data</entry>
+		<entry>d_buf</entry>
+		<entry morerows="2"></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>d_type</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>d_size</entry>
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>d_off</entry>
+		<entry>if <symbol>ELF_F_LAYOUT</symbol> is used</entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>d_align</entry>
+		<!-- <entry morerows="1"></entry> -->
+		<entry></entry>
+	      </row>
+	      <row>
+		<entry></entry>
+		<entry>d_version</entry>
+		<entry></entry>
+	      </row>
+	    </tbody>
+	  </tgroup>
+	</table>
+
+	<simpara>Two fields of the ELF header are handled in a special
+	way:</simpara>
+
+	<variablelist>
+	  <varlistentry>
+	    <term>e_version</term>
+	    <listitem>
+	      <simpara>The user can set this field to the vvalue for
+	      the version to be used.  It is an error if the library
+	      cannot handle this version.  If the field contains the
+	      value <symbol>EV_NONE</symbol> the library will fill in
+	      its own internal version.</simpara>
+	    </listitem>
+	  </varlistentry>
+
+	  <varlistentry>
+	    <term>e_ident[EI_DATA]</term>
+	    <listitem>
+	      <simpara>The user should fill in the byte ordering for
+	      the file.  If the value of the field is
+	      <symbol>ELFDATANONE</symbol> the library replaces it
+	      with the native byte ordering for the machine.</simpara>
+	    </listitem>
+	  </varlistentry>
+	</variablelist>
+      </refsect1>
+    </refentry>
+  </chapter>
+
+  <chapter>
+    <title><filename>libelf</filename> Internals</title>
+
+    <simpara>Since the binary format handling tools need constant
+    attention since there are always new machines and variants
+    therefore coming out it is important to have the implementation
+    well documented.  Only this way extensions can be made in the
+    right places and the mistakes of the past avoided.</simpara>
+  </chapter>
+</book>
+<!-- Keep this comment at the end of the file
+Local variables:
+mode: sgml
+sgml-omitag:nil
+sgml-shorttag:t
+End:
+-->
diff --git a/doc/srcfiles.1 b/doc/srcfiles.1
new file mode 100644
index 0000000..f121659
--- /dev/null
+++ b/doc/srcfiles.1
@@ -0,0 +1,156 @@
+.\" Copyright 2023 Red Hat Inc.
+.\" Mon 2023-Sept 23 Housam Alamour <halamour@redhat.com>
+.\" Contact elfutils-devel@sourceware.org to correct errors or typos.
+.TH EU-SRCFILES 1 "2023-Sept-25" "elfutils"
+
+.de SAMPLE
+.br
+.RS 0
+.nf
+.nh
+\fB
+..
+.de ESAMPLE
+\fP
+.hy
+.fi
+.RE
+..
+
+.SH "NAME"
+eu-srcfiles \- Lists the source files of a DWARF/ELF file.
+
+.SH "SYNOPSIS"
+eu-srcfiles [\fB\-0\fR|\fB\-\-null\fR] [\fB\-c\fR|\fB\-\-cu\-only\fR] [\fB\-v\fR|\fB\-\-verbose\fR] [\fB\-z\fR|\fB\-\-zip\fR] INPUT
+
+.SH "DESCRIPTION"
+\fBeu-srcfiles\fR lists all the source files of a given DWARF/ELF
+file.  This list is based on a search of the DWARF debuginfo, which
+may be automatically fetched by debuginfod if applicable.  The target
+file may be an executable, a coredump, a process, or even the running
+kernel.  The default input is the file 'a.out'.  The source file names are
+made unique by prepending the full path name and then printed to standard output. The source files can be
+placed in a zip file that is sent to stdout.
+
+Note that all occurrences of '/./' and '/../' in the path name are canonicalized.
+
+.SH "INPUT OPTIONS"
+The long and short forms of options, shown here as alternatives, are
+equivalent.
+.TP
+\fB--core=COREFILE\fR
+Find addresses from signatures found in COREFILE.
+
+.TP
+\fB--debuginfo-path=PATH\fR
+Search path for separate debuginfo files.
+
+.TP
+\fB-e FILE\fR, \fB--executable=FILE\fR
+Find addresses in FILE.
+
+.TP
+\fB-k\fR, \fB--kernel\fR
+Find addresses in the running kernel.
+
+.TP
+\fB-K\fR, \fB--offline-kernel[=RELEASE]\fR
+Kernel with all modules.
+
+.TP
+\fB-M FILE\fR, \fB--linux-process-map=FILE\fR
+Find addresses in files mapped as read from FILE in Linux /proc/PID/maps format.
+
+.TP
+\fB-p PID\fR, \fB--pid=PID\fR
+Find addresses in files mapped into process PID.
+
+.TP
+\fB-?\fR, \fB--help\fR
+Give this help list.
+
+.TP
+\fB--usage\fR
+Give a short usage message.
+
+.TP
+\fB-V\fR, \fB--version\fR
+Print program version.
+
+.SH "OUTPUT OPTIONS"
+
+.TP
+\fB\-0, \-\-null\fR
+Separate items by a null instead of a newline.
+
+.TP
+\fB\-b, \-\-no-backup\fR
+Disables local source file search when
+debuginfod fails to fetch files.  This
+option is only applicable when fetching and
+zipping files.
+
+.TP
+\fB\-c, \-\-cu\-only\fR
+Only list the CU (compilation unit) names.
+
+.TP
+\fB\-v, \-\-verbose\fR
+Increase verbosity of logging messages.
+
+.TP
+\fB\-z, \-\-zip\fR
+Zip all the source files and send to stdout.
+By default, files will be automatically fetched by
+debuginfod (if applicable) or locally as a
+backup. Any source files that were not found
+will not be archived.
+
+
+.SH EXAMPLES
+
+List all source files for a binary.
+.SAMPLE
+eu-srcfiles -e /bin/ls
+.ESAMPLE
+
+List all compilation units (CU) names for a given process (including shared libraries).
+.SAMPLE
+eu-srcfiles -c -p $$
+.ESAMPLE
+
+List source files of a binary based on its buildid, using debuginfod.
+.SAMPLE
+binary=`debuginfod-find executable 9c22d8d9e42bd051ffdc1064fdfd456ba781c629`
+eu-srcfiles -c -e $binary
+.ESAMPLE
+
+Show the source code of the first CU of a shared library.
+.SAMPLE
+binary=/usr/lib64/libc.so.6
+srcfile=`eu-srcfiles -c -e $binary | head -1`
+cat `debuginfod-find source $binary $srcfile`
+.ESAMPLE
+
+List the source files of a kernel image.
+.SAMPLE
+eu-srcfiles -e /boot/vmlinuz-`uname -r`
+.ESAMPLE
+
+Zip all the source files for a binary.
+.SAMPLE
+eu-srcfiles -z -e /bin/ls > ls.zip
+.ESAMPLE
+
+
+.SH "AUTHOR"
+Written by Housam Alamour.
+
+.SH "REPORTING BUGS"
+Please reports bugs at https://sourceware.org/bugzilla/
+
+.SH "COPYRIGHT"
+Copyright (c) 2023 Red Hat Inc.  License GPLv3+: GNU GPL version 3 or
+later <https://gnu.org/licenses/gpl.html>.  This is free software: you
+are free to change and redistribute it.  There is NO WARRANTY, to the
+extent permitted by law.
diff --git a/google-dependency-inject.h b/google-dependency-inject.h
new file mode 100644
index 0000000..8416ab2
--- /dev/null
+++ b/google-dependency-inject.h
@@ -0,0 +1,27 @@
+// GOOGLE: force include analysis to make these includes available
+#if 0
+#include "aarch64_reloc.def"
+#include "alpha_reloc.def"
+#include "arc_reloc.def"
+#include "arm_reloc.def"
+#include "bpf_reloc.def"
+#include "csky_reloc.def"
+#include "i386_reloc.def"
+#include "ia64_reloc.def"
+#include "loongarch_reloc.def"
+#include "m68k_reloc.def"
+#include "ppc64_reloc.def"
+#include "ppc_reloc.def"
+#include "riscv_reloc.def"
+#include "s390_reloc.def"
+#include "sh_reloc.def"
+#include "sparc_reloc.def"
+#include "tilegx_reloc.def"
+#include "x86_64_reloc.def"
+
+#include "i386.mnemonics"
+#include "x86_64.mnemonics"
+
+#include "i386_dis.h"
+#include "x86_64_dis.h"
+#endif
diff --git a/lib/ChangeLog b/lib/ChangeLog
new file mode 100644
index 0000000..5ab9477
--- /dev/null
+++ b/lib/ChangeLog
@@ -0,0 +1,434 @@
+2022-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (xmalloc_CFLAGS): Remove.
+
+2022-09-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* color.c: Don't include unistd.h.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* system.h: Use BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN.
+
+2022-10-16  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* system.h: Add sys/mman.h as system dependend header.
+	* common.h: Remove ar.h, byteswap.h and endian.h.
+	* elf32_checksum.c: Remove endian.h.
+	* elf32_getphdr.c: Remove unistd.h and system.h.
+	* elf32_getshdr.c: Remove unistd.h.h and system.h.
+	* elf32_updatefile.c: Remove unistd.h, sys/mman.h and system.h.
+	* elf32_updatenull.c: Remove endian.h and system.h.
+
+2022-08-05  Mark Wielaard  <mark@klomp.org>
+
+	* dynamicsizehash_concurrent.c (resize_helper): Add documentation.
+	(resize_master): Renamed to...
+	(resize_coordinator): ...this. And add documentation.
+	(resize_worker): Add documentation.
+	(FIND): Add documentation.
+
+2022-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* printversion.c (print_version): Update copyright year.
+
+2022-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* system.h: define error_exit.
+
+2021-02-14  Alexander Miller  <alex.miller@gmx.de>
+
+	* eu-config.h (used_in_asm): New macro.
+	(NEW_INTDEF): New macro.
+	(NEW_VERSION): Mark symbol as used_in_asm.  Use @@ symver and change
+	asm name instead.  New variant using symver attribute if available.
+	(OLD_VERSION): Update new symbol name. Indent asm directives.  New
+	variant using symver attribute.
+	(COMPAT_VERSION_NEWPROTO): Mark symbol as used_in_asm.  Reorder
+	lines.  Replace asm with __asm__ in declaration.  New variant using
+	symver attribute.
+	(COMPAT_VERSION): Likewise.
+
+2021-09-10  Colin Cross <ccross@google.com>
+
+	* error.c (error): Call fflush on stdout and stderr. Setup errno and
+	call verr, verrx, vwarn or vwarnx based on status and errnum.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* color.c (parse_opt): Replace asprintf followed by error(EXIT_FAILURE)
+	with xasprintf.
+
+	* xasprintf.c: New file.
+	* Makefile.am (libeu_a_SOURCES): Add it.
+	* libeu.h (xasprintf): New prototype.
+
+	* dynamicsizehash.c (INIT(NAME)): Remove cast of calloc return value.
+	* dynamicsizehash_concurrent.c (INIT(NAME)): Remove cast of malloc
+	return value.
+
+2021-08-23  Saleem Abdulrasool  <abdulras@google.com>
+
+	* system.h: Remove inline definition for error and error_message_count
+	in the fallback path.
+	* Makefile.am (libeu_a_SOURCES): Add error.c.
+	* error.c: New file, moves the previous inline definitions to avoid
+	multiple definitions properly rather than relying on -fcommon and vague
+	linkage.
+
+2021-08-21  Saleem Abdulrasool  <abdulras@google.com>
+
+	* fixedsizehash.h: Remove unused STROF macro.
+
+2021-08-20  Saleem Abdulrasool  <abdulras@google.com>
+
+	* system.h: Check for HAVE_ERROR_H and HAVE_ERR_H and define
+	error_message_cont and error if necessary.
+
+2021-08-20  Saleem Abdulrasool  <abdulras@google.com>
+
+	* fixedsizehash.h: Remove sys/cdefs.h include. Unconditionally
+	define STROF and CONCAT macros.
+
+2021-07-28  Mark Wielaard  <mark@klomp.org>
+
+	* system.h (reallocarray): New static inline fallback function.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* system.h (startswith): New function.
+	(pwrite_retry): Cast to char *.
+	(write_retry): Likewise.
+	(pread_retry): Likewise.
+
+2021-02-05  Mark Wielaard  <mark@klomp.org>
+
+	* printversion.c (print_version): Update copyright year.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* color.c (parse_opt): Replace gettext(...) and
+	dgettext("elfutils, ...) with _(...).
+	* printversion.c (print_version): Replace gettext(...) with _(...).
+	* system.h (sgettext): Likewise.
+
+	* eu-config.h (_): New macro.
+	* xmalloc.c (_): Remove.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* system.h (ACCESSPERMS): Define macro if it doesn't exist.
+	(ALLPERMS): Likewise.
+	(DEFFILEMODE): Likewise.
+
+2020-06-11  Mark Wielaaard  <mark@klomp.org>
+
+	* printversion.c (print_version): Update copyright year.
+
+2019-08-25  Srđan Milaković  <sm108@rice.edu>
+
+	* dynamicsizehash_concurrent.{c,h}: New files.
+	* Makefile.am (noinst_HEADERS): Added dynamicsizehash_concurrent.h.
+
+2019-08-25  Jonathon Anderson  <jma14@rice.edu>
+
+	* stdatomic-fbsd.h: New file, taken from FreeBSD.
+	* atomics.h: New file.
+	* Makefile.am (noinst_HEADERS): Added *.h above.
+
+2019-05-03  Rosen Penev  <rosenp@gmail.com>
+
+	* color.c (parse_opt): Cast program_invocation_short_name to char *.
+
+2018-11-04  Mark Wielaard  <mark@klomp.org>
+
+	* bpf.h: Add BPF_JLT, BPF_JLE, BPF_JSLT and BPF_JSLE.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* color.c: Remove error.h, add system.h include.
+	* system.h: Add error.h include.
+	* xmalloc.c: Remove error.h include.
+
+2018-06-01  Mark Wielaard  <mark@klomp.org>
+
+	* printversion.c (print_version): Update copyright year.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* eu-config.h (FALLTHROUGH): New macro.
+
+2017-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* md5.{c,h}: Removed.
+	* sha1.{c,h}: Likewise.
+	* Makefile.am (libeu_a_SOURCES): Remove md5.c and sha1.c.
+	(noinst_HEADERS): Remove md5.h and sha1.h.
+
+2017-08-18  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* eu-config.h: Define attribute_packed to either
+	__attribute__((packed)) or __attribute__((packed, gcc_struct)).
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* eu-config.h: Define attribute_hidden to be empty if the compiler
+	doesn't support it.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Use fpic_CFLAGS.
+
+2017-07-18  Mark Wielaard  <mark@klomp.org>
+
+	* bpf.h: New file.
+	* Makefile.am (noinst_HEADERS): Add bpf.h
+
+2017-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* printversion.c (print_version): Update copyright year.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* crc32.c: include config.h.
+	* system.h: Don't include config.h.
+
+2017-02-16  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am (libeu_a_SOURCES): Remove version.c, add printversion.c
+	(noinst_HEADERS): Add printversion.h
+	* version.c: Moved to printversion.c.
+	* printversion.c: New file, moved from version.c,
+	remove stdio.h, argp.h, system.h includes,
+	add printversion.h include.
+	* printversion.h: New file.
+	* system.h: Remove argp.h include,
+	(ARGP_PROGRAM_VERSION_HOOK_DEF, ARGP_PROGRAM_BUG_ADDRESS_DEF): Remove.
+	(print_version): Remove.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* system.h: Provide mempcpy if it doesn't exist.
+	* xstrndup.c: Include system.h.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* crc32_file.c: Use _SC_PAGESIZE rather than _SC_PAGE_SIZE.
+
+2017-02-14  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* color.h: New file.
+	* color.c: Include color.h.
+	* libeu.h: Remove color handling.
+	* Makefile.am (noinst_HEADERS): Add color.h.
+
+2016-12-29  Luiz Angelo Daros de Luca  <luizluca@gmail.com>
+
+	* crc32_file.c: Include system.h.
+	* system.h: Remove semi-colon after TEMP_FAILURE_RETRY definition.
+
+2016-12-24  Mark Wielaard  <mark@klomp.org>
+
+	* version.c: New source file.
+	* Makefile.am (libeu_a_SOURCES): Add version.c
+	* system.h (print_version): New function definition.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* fixedsizehash.h (CONCAT): Use __CONCAT when available.
+	* system.h: Include config.h and errno.h.
+	(powerof2): Define if not already defined.
+	(TEMP_FAILURE_RETRY): Define when not yet defined.
+
+2015-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* Makefile.am (noinst_HEADERS): Add libeu.h.
+	* color.c: Remove system.h include, add libeu.h include.
+	* crc32_file.c: Likewise.
+	* fixedsizehash.h: Remove sys/param.h include.
+	* libeu.h: New file.
+	* system.h: Include sys/param.h.
+	(xmalloc, xcalloc, xrealloc, xstrdup, xstrndup, crc32, crc32_file,
+	color_argp, color_enum, color_*): Move definitions to libeu.h.
+	* xstrdup.c: Remove system.h include, add libeu.h include.
+	* xstrndup.c: Remove system.h include, add libeu.h and stdint.h
+	includes.
+
+2015-09-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* Makefile.am (AM_CFLAGS): Use -fPIC instead of -fpic to avoid relocation
+	overflows in some platforms.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dynamicsizehash.c: Remove old-style function definitions.
+	* md5.c: Likewise.
+	* sha1.c: Likewise.
+	* xmalloc.c: Likewise.
+	* xstrdup.c: Likewise.
+	* xstrndup.c: Likewise.
+
+2015-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* eu-config.h (ALLOW_UNALIGNED): Define when ! CHECK_UNDEFINED.
+
+2015-04-23  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* eu-config.h: Use SYMBOL_VERSIONING as guard.
+
+2014-01-17  Lei Zhang  <thestig@google.com>
+
+	* crc32_file.c: Include config.h.
+
+2013-12-12  Josh Stone  <jistone@redhat.com>
+
+	* dynamicsizehash.c (lookup): Add a shortcut around division.
+
+2013-04-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* eu-config.h (COMPAT_VERSION_NEWPROTO): New.  Twice.
+
+2013-04-26  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* system.h (LE64, BE64): Move here the definitions from
+	libdwfl/link_map.c.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2012-10-09  Adam Markey  <adam@etinternational.com>
+
+	* system.h: Changed pwrite_retry, write_retry, and pread_retry to
+	handle case where not all data was read/written.
+
+2012-10-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* system.h (eu_static_assert): New macro.
+
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am (libeu_a_SOURCES): Add color.c.
+	* system.h: Declare color_argp.  Define color_enum.  Declare
+	color_* variables.
+	* color.c: New file.
+
+2011-10-02  Ulrich Drepper  <drepper@gmail.com>
+
+	* system.h: Declare __cxa_demangle.
+
+2011-07-09  Roland McGrath  <roland@hack.frob.com>
+
+	* sha1.c (be64_copy): New function.
+	(sha1_finish_ctx): Use it.
+	* md5.c (le64_copy): New function.
+	(md5_finish_ctx): Use it.
+	* system.h (LE32, BE32): New macros, using <endian.h> and <byteswap.h>.
+	* md5.c (SWAP): Use LE32.
+	* sha1.c (SWAP): Use BE32.
+
+2010-06-16  Roland McGrath  <roland@redhat.com>
+
+	* dynamicsizehash.h (HASHTYPE): New macro.
+	(struct): Use size_t for table sizes.
+	* dynamicsizehash.c: Likewise.  Use HASHTYPE for hash values.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2009-08-09  Roland McGrath  <roland@redhat.com>
+
+	* eu-config.h (OLD_VERSION, NEW_VERSION, COMPAT_VERSION): New macros.
+
+2009-01-23  Roland McGrath  <roland@redhat.com>
+
+	* eu-config.h: Add multiple inclusion protection.
+
+2009-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* system.h (ARGP_PROGRAM_VERSION_HOOK_DEF): Define.
+	(ARGP_PROGRAM_BUG_ADDRESS_DEF): Define.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* eu-config.h: Remove tls_key_t, key_create, getspecific, setspecific,
+	once_define, and once_execute macros.  Use USE_LOCKS instead of
+	USE_TLS.
+
+2008-08-25  Roland McGrath  <roland@redhat.com>
+
+	* eu-config.h [USE_TLS] (RWLOCK_CALL): New macro.
+	(rwlock_init, rwlock_fini, rwlock_rdlock, rwlock_wrlock, rwlock_unlock):
+	Use it.
+
+2008-08-24  Roland McGrath  <roland@redhat.com>
+
+	* eu-config.h: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+
+2008-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libeu_a_SOURCES): Add sha1.c.
+	(noinst_HEADERS): Add sha1.h.
+	* sha1.c: New file.
+	* sha1.h: New file.
+
+2008-01-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libeu_a_SOURCES): Add md5.c.
+	(noinst_HEADERS): Add md5.h.
+	* md5.c: New file.
+	* md5.h: New file.
+
+2006-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libeu_a_SOURCES): We don't need xstrdup in the moment.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* system.h: Define pwrite_retry, write_retry, and pread_retry.
+
+2005-08-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (xmalloc_CFLAGS): Define only if !GPROF.
+
+2005-05-03  Roland McGrath  <roland@redhat.com>
+
+	* crc32_file.c: New file.
+	* Makefile.am (libeu_a_SOURCES): Add it.
+	* system.h: Declare crc32_file.
+
+2005-04-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Use -ffunction-sections for xmalloc.c.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* dynamicsizehash.c (lookup): Mark val parameter as possibly unused.
+
+2005-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* fixedsizehash.h: Mark unused parameters.  Correct CLASS and
+	const order for fshash_find.
+
+	* Makefile.am: Cleanup AM_CFLAGS handling.  Add -Wunused -Wextra.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fpic and -fmudflap.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+2003-09-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -fpic.
+
+	* Makefile.am (noinst_HEADERS): Add list.h.
+	* list.h: New file.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/lib/Makefile.am b/lib/Makefile.am
new file mode 100644
index 0000000..b3bb929
--- /dev/null
+++ b/lib/Makefile.am
@@ -0,0 +1,43 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 1996-2011 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CFLAGS += $(fpic_CFLAGS)
+AM_CPPFLAGS += -I$(srcdir)/../libelf
+
+noinst_LIBRARIES = libeu.a
+
+libeu_a_SOURCES = xasprintf.c xstrdup.c xstrndup.c xmalloc.c next_prime.c \
+		  crc32.c crc32_file.c \
+		  color.c error.c printversion.c
+
+noinst_HEADERS = fixedsizehash.h libeu.h system.h dynamicsizehash.h list.h \
+		 eu-config.h color.h printversion.h bpf.h \
+		 atomics.h stdatomic-fbsd.h dynamicsizehash_concurrent.h
+EXTRA_DIST = dynamicsizehash.c dynamicsizehash_concurrent.c
diff --git a/lib/atomics.h b/lib/atomics.h
new file mode 100644
index 0000000..ffd12f8
--- /dev/null
+++ b/lib/atomics.h
@@ -0,0 +1,37 @@
+/* Conditional wrapper header for C11-style atomics.
+   Copyright (C) 2019-2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+
+#if HAVE_STDATOMIC_H
+/* If possible, use the compiler's preferred atomics.  */
+# include <stdatomic.h>
+#else
+/* Otherwise, try to use the builtins provided by this compiler.  */
+# include "stdatomic-fbsd.h"
+#endif /* HAVE_STDATOMIC_H */
diff --git a/lib/bpf.h b/lib/bpf.h
new file mode 100644
index 0000000..efb26f8
--- /dev/null
+++ b/lib/bpf.h
@@ -0,0 +1,86 @@
+/* Minimal extended BPF constants as alternative for linux/bpf.h.  */
+
+#ifndef _ELFUTILS_BPF_H
+#define _ELFUTILS_BPF_H 1
+
+#include <stdint.h>
+
+#define BPF_CLASS(code) ((code) & 0x07)
+
+#define BPF_LD    0x00
+#define BPF_LDX   0x01
+#define BPF_ST    0x02
+#define BPF_STX   0x03
+#define BPF_ALU   0x04
+#define BPF_JMP   0x05
+#define BPF_RET   0x06
+#define BPF_MISC  0x07
+
+#define BPF_ALU64 0x07
+
+#define BPF_JNE  0x50
+#define BPF_JSGT 0x60
+#define BPF_JSGE 0x70
+#define BPF_CALL 0x80
+#define BPF_EXIT 0x90
+#define BPF_JLT  0xa0
+#define BPF_JLE  0xb0
+#define BPF_JSLT 0xc0
+#define BPF_JSLE 0xd0
+
+#define BPF_W 0x00
+#define BPF_H 0x08
+#define BPF_B 0x10
+
+#define BPF_IMM 0x00
+#define BPF_ABS 0x20
+#define BPF_IND 0x40
+#define BPF_MEM 0x60
+#define BPF_LEN 0x80
+#define BPF_MSH 0xa0
+
+#define BPF_DW   0x18
+#define BPF_XADD 0xc0
+
+#define BPF_ADD 0x00
+#define BPF_SUB 0x10
+#define BPF_MUL 0x20
+#define BPF_DIV 0x30
+#define BPF_OR  0x40
+#define BPF_AND 0x50
+#define BPF_LSH 0x60
+#define BPF_RSH 0x70
+#define BPF_NEG 0x80
+#define BPF_MOD 0x90
+#define BPF_XOR 0xa0
+
+#define BPF_MOV  0xb0
+#define BPF_ARSH 0xc0
+
+#define BPF_JA   0x00
+#define BPF_JEQ  0x10
+#define BPF_JGT  0x20
+#define BPF_JGE  0x30
+#define BPF_JSET 0x40
+
+#define BPF_K 0x00
+#define BPF_X 0x08
+
+#define BPF_END   0xd0
+#define BPF_TO_LE 0x00
+#define BPF_TO_BE 0x08
+
+#define BPF_PSEUDO_MAP_FD 1
+
+#define MAX_BPF_REG 10
+
+struct bpf_insn
+{
+  uint8_t code;
+  uint8_t dst_reg:4;
+  uint8_t src_reg:4;
+  int16_t off;
+  int32_t imm;
+};
+
+#endif
diff --git a/lib/color.c b/lib/color.c
new file mode 100644
index 0000000..8063dc2
--- /dev/null
+++ b/lib/color.c
@@ -0,0 +1,234 @@
+/* Handling of color output.
+   Copyright (C) 2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2011.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <stdlib.h>
+#include <string.h>
+#include "system.h"
+#include "libeu.h"
+#include "color.h"
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Option values.  */
+#define OPT_COLOR 0x100100
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { "color", OPT_COLOR, "WHEN", OPTION_ARG_OPTIONAL,
+    N_("colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"), 0 },
+
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Parser data structure.  */
+const struct argp color_argp =
+  {
+    options, parse_opt, NULL, NULL, NULL, NULL, NULL
+  };
+
+/* Coloring mode.  */
+enum color_enum color_mode;
+
+/* Colors to use for the various components.  */
+char *color_address = "";
+char *color_bytes = "";
+char *color_mnemonic = "";
+char *color_operand = NULL;
+char *color_operand1 = "";
+char *color_operand2 = "";
+char *color_operand3 = "";
+char *color_operand4 = "";
+char *color_operand5 = "";
+char *color_label = "";
+char *color_undef = "";
+char *color_undef_tls = "";
+char *color_undef_weak = "";
+char *color_symbol = "";
+char *color_tls = "";
+char *color_weak = "";
+
+const char color_off[] = "\e[0m";
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case OPT_COLOR:
+      if (arg == NULL)
+	color_mode = color_always;
+      else
+	{
+	  static const struct
+	  {
+	    const char str[7];
+	    enum color_enum mode;
+	  } values[] =
+	      {
+		{ "always", color_always },
+		{ "yes", color_always },
+		{ "force", color_always },
+		{ "never", color_never },
+		{ "no", color_never },
+		{ "none", color_never },
+		{ "auto", color_auto },
+		{ "tty", color_auto },
+		{ "if-tty", color_auto }
+	      };
+	  const int nvalues = sizeof (values) / sizeof (values[0]);
+	  int i;
+	  for (i = 0; i < nvalues; ++i)
+	    if (strcmp (arg, values[i].str) == 0)
+	      {
+		color_mode = values[i].mode;
+		if (color_mode == color_auto)
+		  color_mode
+		    = isatty (STDOUT_FILENO) ? color_always : color_never;
+		break;
+	      }
+	  if (i == nvalues)
+	    {
+	      error (0, 0, _("\
+%s: invalid argument '%s' for '--color'\n\
+valid arguments are:\n\
+  - 'always', 'yes', 'force'\n\
+  - 'never', 'no', 'none'\n\
+  - 'auto', 'tty', 'if-tty'\n"),
+		     program_invocation_short_name, arg);
+	      argp_help (&color_argp, stderr, ARGP_HELP_SEE,
+			 (char *) program_invocation_short_name);
+	      exit (EXIT_FAILURE);
+	    }
+	}
+
+      if (color_mode == color_always)
+	{
+	  const char *env = getenv ("ELFUTILS_COLORS");
+	  if (env != NULL)
+	    {
+	      do
+		{
+		  const char *start = env;
+		  while (*env != '=' && *env != '\0')
+		    ++env;
+		  if (*env == '=' && env != start)
+		    {
+		      size_t name_len = env - start;
+		      const char *val = ++env;
+		      env = strchrnul (env, ':');
+		      if (val != env)
+			{
+			  static const struct
+			  {
+			    unsigned char len;
+			    const char name[sizeof (char *) - 1];
+			    char **varp;
+			  } known[] =
+			      {
+#define E(name, var) { sizeof (#name) - 1, #name,  &color_##var }
+				E (a, address),
+				E (b, bytes),
+				E (m, mnemonic),
+				E (o, operand),
+				E (o1, operand1),
+				E (o2, operand2),
+				E (o3, operand3),
+				E (o4, operand4),
+				E (o5, operand5),
+				E (l, label),
+				E (u, undef),
+				E (ut, undef_tls),
+				E (uw, undef_weak),
+				E (sy, symbol),
+				E (st, tls),
+				E (sw, weak),
+			      };
+			  const size_t nknown = (sizeof (known)
+						 / sizeof (known[0]));
+
+			  for (size_t i = 0; i < nknown; ++i)
+			    if (name_len == known[i].len
+				&& memcmp (start, known[i].name, name_len) == 0)
+			      {
+				*known[i].varp =
+				  xasprintf ("\e[%.*sm", (int) (env - val), val);
+				break;
+			      }
+			}
+		      if (*env == ':')
+			++env;
+		    }
+		}
+	      while (*env != '\0');
+
+	      if (color_operand != NULL)
+		{
+		  if (color_operand1[0] == '\0')
+		    color_operand1 = color_operand;
+		  if (color_operand2[0] == '\0')
+		    color_operand2 = color_operand;
+		  if (color_operand3[0] == '\0')
+		    color_operand3 = color_operand;
+		  if (color_operand4[0] == '\0')
+		    color_operand4 = color_operand;
+		  if (color_operand5[0] == '\0')
+		    color_operand5 = color_operand;
+		}
+	    }
+#if 0
+	  else
+	    {
+	      // XXX Just for testing.
+	      color_address = xstrdup ("\e[38;5;166;1m");
+	      color_bytes = xstrdup ("\e[38;5;141m");
+	      color_mnemonic = xstrdup ("\e[38;5;202;1m");
+	      color_operand1 = xstrdup ("\e[38;5;220m");
+	      color_operand2 = xstrdup ("\e[38;5;48m");
+	      color_operand = xstrdup ("\e[38;5;112m");
+	      color_label = xstrdup ("\e[38;5;21m");
+	    }
+#endif
+	}
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
diff --git a/lib/color.h b/lib/color.h
new file mode 100644
index 0000000..cb24143
--- /dev/null
+++ b/lib/color.h
@@ -0,0 +1,65 @@
+/* Handling of color output.
+   Copyright (C) 2017 The Qt Company
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2011.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifndef COLOR_H
+#define COLOR_H 1
+
+/* Command line parser.  */
+extern const struct argp color_argp;
+
+/* Coloring mode.  */
+enum color_enum
+  {
+    color_never = 0,
+    color_always,
+    color_auto
+  } __attribute__ ((packed));
+extern enum color_enum color_mode;
+
+/* Colors to use for the various components.  */
+extern char *color_address;
+extern char *color_bytes;
+extern char *color_mnemonic;
+extern char *color_operand1;
+extern char *color_operand2;
+extern char *color_operand3;
+extern char *color_operand4;
+extern char *color_operand5;
+extern char *color_label;
+extern char *color_undef;
+extern char *color_undef_tls;
+extern char *color_undef_weak;
+extern char *color_symbol;
+extern char *color_tls;
+extern char *color_weak;
+
+extern const char color_off[];
+
+#endif /* color.h */
diff --git a/lib/crc32.c b/lib/crc32.c
new file mode 100644
index 0000000..758602e
--- /dev/null
+++ b/lib/crc32.c
@@ -0,0 +1,102 @@
+/* Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include "system.h"
+
+
+/* Table computed with Mark Adler's makecrc.c utility.  */
+static const uint32_t crc32_table[256] =
+{
+  0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419,
+  0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4,
+  0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07,
+  0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+  0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856,
+  0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
+  0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4,
+  0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+  0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
+  0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a,
+  0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599,
+  0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+  0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190,
+  0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f,
+  0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e,
+  0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+  0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed,
+  0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
+  0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3,
+  0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+  0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a,
+  0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5,
+  0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010,
+  0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+  0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17,
+  0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6,
+  0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
+  0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+  0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344,
+  0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
+  0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a,
+  0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+  0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1,
+  0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c,
+  0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef,
+  0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+  0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe,
+  0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31,
+  0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c,
+  0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+  0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b,
+  0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
+  0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1,
+  0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+  0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
+  0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7,
+  0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66,
+  0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+  0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605,
+  0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8,
+  0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b,
+  0x2d02ef8d
+};
+
+uint32_t
+crc32 (uint32_t crc, unsigned char *buf, size_t len)
+{
+  unsigned char *end;
+
+  crc = ~crc;
+  for (end = buf + len; buf < end; ++buf)
+    crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8);
+  return ~crc;
+}
diff --git a/lib/crc32_file.c b/lib/crc32_file.c
new file mode 100644
index 0000000..f7607d0
--- /dev/null
+++ b/lib/crc32_file.c
@@ -0,0 +1,92 @@
+/* Compute CRC32 checksum of file contents.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libeu.h"
+#include <errno.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include "system.h"
+
+int
+crc32_file (int fd, uint32_t *resp)
+{
+  unsigned char buffer[1024 * 8];
+  uint32_t crc = 0;
+  off_t off = 0;
+  ssize_t count;
+
+  struct stat st;
+  if (fstat (fd, &st) == 0)
+    {
+      /* Try mapping in the file data.  */
+      size_t mapsize = st.st_size;
+      void *mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE, fd, 0);
+      if (mapped == MAP_FAILED && errno == ENOMEM)
+	{
+	  const size_t pagesize = sysconf (_SC_PAGESIZE);
+	  mapsize = ((mapsize / 2) + pagesize - 1) & -pagesize;
+	  while (mapsize >= pagesize
+		 && (mapped = mmap (NULL, mapsize, PROT_READ, MAP_PRIVATE,
+				    fd, 0)) == MAP_FAILED && errno == ENOMEM)
+	    mapsize /= 2;
+	}
+      if (mapped != MAP_FAILED)
+	{
+	  do
+	    {
+	      if (st.st_size <= (off_t) mapsize)
+		{
+		  *resp = crc32 (crc, mapped, st.st_size);
+		  munmap (mapped, mapsize);
+		  return 0;
+		}
+	      crc = crc32 (crc, mapped, mapsize);
+	      off += mapsize;
+	      st.st_size -= mapsize;
+	    } while (mmap (mapped, mapsize, PROT_READ, MAP_FIXED|MAP_PRIVATE,
+			   fd, off) == mapped);
+	  munmap (mapped, mapsize);
+	}
+    }
+
+  while ((count = TEMP_FAILURE_RETRY (pread (fd, buffer, sizeof buffer,
+					     off))) > 0)
+    {
+      off += count;
+      crc = crc32 (crc, buffer, count);
+    }
+
+  *resp = crc;
+
+  return count == 0 ? 0 : -1;
+}
diff --git a/lib/dynamicsizehash.c b/lib/dynamicsizehash.c
new file mode 100644
index 0000000..76c86da
--- /dev/null
+++ b/lib/dynamicsizehash.c
@@ -0,0 +1,315 @@
+/* Copyright (C) 2000-2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <system.h>
+
+/* Before including this file the following macros must be defined:
+
+   NAME      name of the hash table structure.
+   TYPE      data type of the hash table entries
+   COMPARE   comparison function taking two pointers to TYPE objects
+
+   The following macros if present select features:
+
+   ITERATE   iterating over the table entries is possible
+   REVERSE   iterate in reverse order of insert
+ */
+
+
+static size_t
+lookup (NAME *htab, HASHTYPE hval, TYPE val __attribute__ ((unused)))
+{
+  /* First hash function: simply take the modul but prevent zero.  Small values
+     can skip the division, which helps performance when this is common.  */
+  size_t idx = 1 + (hval < htab->size ? hval : hval % htab->size);
+
+  if (htab->table[idx].hashval != 0)
+    {
+      HASHTYPE hash;
+
+      if (htab->table[idx].hashval == hval
+	  && COMPARE (htab->table[idx].data, val) == 0)
+	return idx;
+
+      /* Second hash function as suggested in [Knuth].  */
+      hash = 1 + hval % (htab->size - 2);
+
+      do
+	{
+	  if (idx <= hash)
+	    idx = htab->size + idx - hash;
+	  else
+	    idx -= hash;
+
+	  /* If entry is found use it.  */
+	  if (htab->table[idx].hashval == hval
+	      && COMPARE (htab->table[idx].data, val) == 0)
+	    return idx;
+	}
+      while (htab->table[idx].hashval);
+    }
+  return idx;
+}
+
+
+static void
+insert_entry_2 (NAME *htab, HASHTYPE hval, size_t idx, TYPE data)
+{
+#ifdef ITERATE
+  if (htab->table[idx].hashval == 0)
+    {
+# ifdef REVERSE
+      htab->table[idx].next = htab->first;
+      htab->first = &htab->table[idx];
+# else
+      /* Add the new value to the list.  */
+      if (htab->first == NULL)
+	htab->first = htab->table[idx].next = &htab->table[idx];
+      else
+	{
+	  htab->table[idx].next = htab->first->next;
+	  htab->first = htab->first->next = &htab->table[idx];
+	}
+# endif
+    }
+#endif
+
+  htab->table[idx].hashval = hval;
+  htab->table[idx].data = data;
+
+  ++htab->filled;
+  if (100 * htab->filled > 90 * htab->size)
+    {
+      /* Table is filled more than 90%.  Resize the table.  */
+#ifdef ITERATE
+      __typeof__ (htab->first) first;
+# ifndef REVERSE
+      __typeof__ (htab->first) runp;
+# endif
+#else
+      size_t old_size = htab->size;
+#endif
+#define _TABLE(name) \
+      name##_ent *table = htab->table
+#define TABLE(name) _TABLE (name)
+      TABLE(NAME);
+
+      htab->size = next_prime (htab->size * 2);
+      htab->filled = 0;
+#ifdef ITERATE
+      first = htab->first;
+      htab->first = NULL;
+#endif
+      htab->table = calloc ((1 + htab->size), sizeof (htab->table[0]));
+      if (htab->table == NULL)
+	{
+	  /* We cannot enlarge the table.  Live with what we got.  This
+	     might lead to an infinite loop at some point, though.  */
+	  htab->table = table;
+	  return;
+	}
+
+      /* Add the old entries to the new table.  When iteration is
+	 supported we maintain the order.  */
+#ifdef ITERATE
+# ifdef REVERSE
+      while (first != NULL)
+	{
+	  insert_entry_2 (htab, first->hashval,
+			  lookup (htab, first->hashval, first->data),
+			  first->data);
+
+	  first = first->next;
+	}
+# else
+      assert (first != NULL);
+      runp = first = first->next;
+      do
+	insert_entry_2 (htab, runp->hashval,
+			lookup (htab, runp->hashval, runp->data), runp->data);
+      while ((runp = runp->next) != first);
+# endif
+#else
+      for (idx = 1; idx <= old_size; ++idx)
+	if (table[idx].hashval != 0)
+	  insert_entry_2 (htab, table[idx].hashval,
+			  lookup (htab, table[idx].hashval, table[idx].data),
+			  table[idx].data);
+#endif
+
+      free (table);
+    }
+}
+
+
+int
+#define INIT(name) _INIT (name)
+#define _INIT(name) \
+  name##_init
+INIT(NAME) (NAME *htab, size_t init_size)
+{
+  /* We need the size to be a prime.  */
+  init_size = next_prime (init_size);
+
+  /* Initialize the data structure.  */
+  htab->size = init_size;
+  htab->filled = 0;
+#ifdef ITERATE
+  htab->first = NULL;
+#endif
+  htab->table = calloc ((init_size + 1), sizeof (htab->table[0]));
+  if (htab->table == NULL)
+    return -1;
+
+  return 0;
+}
+
+
+int
+#define FREE(name) _FREE (name)
+#define _FREE(name) \
+  name##_free
+FREE(NAME) (NAME *htab)
+{
+  free (htab->table);
+  return 0;
+}
+
+
+int
+#define INSERT(name) _INSERT (name)
+#define _INSERT(name) \
+  name##_insert
+INSERT(NAME) (NAME *htab, HASHTYPE hval, TYPE data)
+{
+  size_t idx;
+
+  /* Make the hash value nonzero.  */
+  hval = hval ?: 1;
+
+  idx = lookup (htab, hval, data);
+
+  if (htab->table[idx].hashval != 0)
+    /* We don't want to overwrite the old value.  */
+    return -1;
+
+  /* An empty bucket has been found.  */
+  insert_entry_2 (htab, hval, idx, data);
+  return 0;
+}
+
+
+#ifdef OVERWRITE
+int
+#define INSERT(name) _INSERT (name)
+#define _INSERT(name) \
+  name##_overwrite
+INSERT(NAME) (NAME *htab, HASHTYPE hval, TYPE data)
+{
+  size_t idx;
+
+  /* Make the hash value nonzero.  */
+  hval = hval ?: 1;
+
+  idx = lookup (htab, hval, data);
+
+  /* The correct bucket has been found.  */
+  insert_entry_2 (htab, hval, idx, data);
+  return 0;
+}
+#endif
+
+
+TYPE
+#define FIND(name) _FIND (name)
+#define _FIND(name) \
+  name##_find
+FIND(NAME) (NAME *htab, HASHTYPE hval, TYPE val)
+{
+  size_t idx;
+
+  /* Make the hash value nonzero.  */
+  hval = hval ?: 1;
+
+  idx = lookup (htab, hval, val);
+
+  if (htab->table[idx].hashval == 0)
+    return NULL;
+
+  return htab->table[idx].data;
+}
+
+
+#ifdef ITERATE
+# define ITERATEFCT(name) _ITERATEFCT (name)
+# define _ITERATEFCT(name) \
+  name##_iterate
+TYPE
+ITERATEFCT(NAME) (NAME *htab, void **ptr)
+{
+  void *p = *ptr;
+
+# define TYPENAME(name) _TYPENAME (name)
+# define _TYPENAME(name) name##_ent
+
+# ifdef REVERSE
+  if (p == NULL)
+    p = htab->first;
+  else
+    p = ((TYPENAME(NAME) *) p)->next;
+
+  if (p == NULL)
+    {
+      *ptr = NULL;
+      return NULL;
+    }
+# else
+  if (p == NULL)
+    {
+      if (htab->first == NULL)
+	return NULL;
+      p = htab->first->next;
+    }
+  else
+    {
+      if (p == htab->first)
+	return NULL;
+
+      p = ((TYPENAME(NAME) *) p)->next;
+    }
+# endif
+
+  /* Prepare the next element.  If possible this will pull the data
+     into the cache, for reading.  */
+  __builtin_prefetch (((TYPENAME(NAME) *) p)->next, 0, 2);
+
+  return ((TYPENAME(NAME) *) (*ptr = p))->data;
+}
+#endif
diff --git a/lib/dynamicsizehash.h b/lib/dynamicsizehash.h
new file mode 100644
index 0000000..ccd41d0
--- /dev/null
+++ b/lib/dynamicsizehash.h
@@ -0,0 +1,127 @@
+/* Copyright (C) 2000-2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+
+/* Before including this file the following macros must be defined:
+
+   NAME      name of the hash table structure.
+   TYPE      data type of the hash table entries
+
+   The following macros if present select features:
+
+   ITERATE   iterating over the table entries is possible
+   HASHTYPE  integer type for hash values, default unsigned long int
+ */
+
+
+/* Optionally include an entry pointing to the first used entry.  */
+#ifdef ITERATE
+# define FIRST(name)	name##_ent *first;
+# define NEXT(name)	struct name##_ent *next;
+#else
+# define FIRST(name)
+# define NEXT(name)
+#endif
+
+#ifndef HASHTYPE
+# define HASHTYPE unsigned long int
+#endif
+
+
+/* Defined separately.  */
+extern size_t next_prime (size_t seed);
+
+
+/* Table entry type.  */
+#define _DYNHASHENTTYPE(name) \
+  typedef struct name##_ent						      \
+  {									      \
+    HASHTYPE hashval;							      \
+    TYPE data;								      \
+    NEXT (name)								      \
+  } name##_ent
+#define DYNHASHENTTYPE(name) _DYNHASHENTTYPE (name)
+DYNHASHENTTYPE (NAME);
+
+
+/* Type of the dynamic hash table data structure.  */
+#define _DYNHASHTYPE(name) \
+typedef struct								      \
+{									      \
+  size_t size;								      \
+  size_t filled;							      \
+  name##_ent *table;							      \
+  FIRST	(name)								      \
+} name
+#define DYNHASHTYPE(name) _DYNHASHTYPE (name)
+DYNHASHTYPE (NAME);
+
+
+
+#define _FUNCTIONS(name) \
+/* Initialize the hash table.  */					      \
+extern int name##_init (name *htab, size_t init_size);			      \
+									      \
+/* Free resources allocated for hash table.  */				      \
+extern int name##_free (name *htab);					      \
+									      \
+/* Insert new entry.  */						      \
+extern int name##_insert (name *htab, HASHTYPE hval, TYPE data);	      \
+									      \
+/* Insert new entry, possibly overwrite old entry.  */			      \
+extern int name##_overwrite (name *htab, HASHTYPE hval, TYPE data);	      \
+									      \
+/* Find entry in hash table.  */					      \
+extern TYPE name##_find (name *htab, HASHTYPE hval, TYPE val);
+#define FUNCTIONS(name) _FUNCTIONS (name)
+FUNCTIONS (NAME)
+
+
+#ifdef ITERATE
+# define _XFUNCTIONS(name) \
+/* Get next element in table.  */					      \
+extern TYPE name##_iterate (name *htab, void **ptr);
+# define XFUNCTIONS(name) _XFUNCTIONS (name)
+XFUNCTIONS (NAME)
+#endif
+
+#ifndef NO_UNDEF
+# undef DYNHASHENTTYPE
+# undef DYNHASHTYPE
+# undef FUNCTIONS
+# undef _FUNCTIONS
+# undef XFUNCTIONS
+# undef _XFUNCTIONS
+# undef NAME
+# undef TYPE
+# undef ITERATE
+# undef COMPARE
+# undef FIRST
+# undef NEXT
+#endif
diff --git a/lib/dynamicsizehash_concurrent.c b/lib/dynamicsizehash_concurrent.c
new file mode 100644
index 0000000..2ea545e
--- /dev/null
+++ b/lib/dynamicsizehash_concurrent.c
@@ -0,0 +1,496 @@
+/* Copyright (C) 2000-2019 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Srdan Milakovic <sm108@rice.edu>, 2019.
+   Derived from Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <stdlib.h>
+#include <system.h>
+#include <pthread.h>
+
+/* Before including this file the following macros must be defined:
+
+   NAME      name of the hash table structure.
+   TYPE      data type of the hash table entries
+ */
+
+
+static size_t
+lookup (NAME *htab, HASHTYPE hval)
+{
+  /* First hash function: simply take the modulus but prevent zero.  Small values
+      can skip the division, which helps performance when this is common.  */
+  size_t idx = 1 + (hval < htab->size ? hval : hval % htab->size);
+
+  HASHTYPE hash;
+
+  hash = atomic_load_explicit(&htab->table[idx].hashval,
+                              memory_order_acquire);
+  if (hash == hval)
+    return idx;
+  else if (hash == 0)
+    return 0;
+
+  /* Second hash function as suggested in [Knuth].  */
+  HASHTYPE second_hash = 1 + hval % (htab->size - 2);
+
+  for(;;)
+    {
+      if (idx <= second_hash)
+          idx = htab->size + idx - second_hash;
+      else
+          idx -= second_hash;
+
+      hash = atomic_load_explicit(&htab->table[idx].hashval,
+                                  memory_order_acquire);
+      if (hash == hval)
+	return idx;
+      else if (hash == 0)
+	return 0;
+    }
+}
+
+static int
+insert_helper (NAME *htab, HASHTYPE hval, TYPE val)
+{
+  /* First hash function: simply take the modulus but prevent zero.  Small values
+      can skip the division, which helps performance when this is common.  */
+  size_t idx = 1 + (hval < htab->size ? hval : hval % htab->size);
+
+  TYPE val_ptr;
+  HASHTYPE hash;
+
+  hash = atomic_load_explicit(&htab->table[idx].hashval,
+                              memory_order_acquire);
+  if (hash == hval)
+    return -1;
+  else if (hash == 0)
+    {
+      val_ptr = NULL;
+      atomic_compare_exchange_strong_explicit(&htab->table[idx].val_ptr,
+                                              (uintptr_t *) &val_ptr,
+                                              (uintptr_t) val,
+                                              memory_order_acquire,
+                                              memory_order_acquire);
+
+      if (val_ptr == NULL)
+        {
+          atomic_store_explicit(&htab->table[idx].hashval, hval,
+                                memory_order_release);
+          return 0;
+        }
+      else
+        {
+          do
+            {
+              hash = atomic_load_explicit(&htab->table[idx].hashval,
+                                          memory_order_acquire);
+            }
+          while (hash == 0);
+          if (hash == hval)
+            return -1;
+        }
+    }
+
+  /* Second hash function as suggested in [Knuth].  */
+  HASHTYPE second_hash = 1 + hval % (htab->size - 2);
+
+  for(;;)
+    {
+      if (idx <= second_hash)
+          idx = htab->size + idx - second_hash;
+      else
+          idx -= second_hash;
+
+      hash = atomic_load_explicit(&htab->table[idx].hashval,
+                                  memory_order_acquire);
+      if (hash == hval)
+        return -1;
+      else if (hash == 0)
+        {
+          val_ptr = NULL;
+          atomic_compare_exchange_strong_explicit(&htab->table[idx].val_ptr,
+                                                  (uintptr_t *) &val_ptr,
+                                                  (uintptr_t) val,
+                                                  memory_order_acquire,
+                                                  memory_order_acquire);
+
+          if (val_ptr == NULL)
+            {
+              atomic_store_explicit(&htab->table[idx].hashval, hval,
+                                    memory_order_release);
+              return 0;
+            }
+          else
+            {
+              do
+                {
+                  hash = atomic_load_explicit(&htab->table[idx].hashval,
+                                              memory_order_acquire);
+                }
+              while (hash == 0);
+              if (hash == hval)
+                return -1;
+            }
+        }
+    }
+}
+
+#define NO_RESIZING 0u
+#define ALLOCATING_MEMORY 1u
+#define MOVING_DATA 3u
+#define CLEANING 2u
+
+#define STATE_BITS 2u
+#define STATE_INCREMENT (1u << STATE_BITS)
+#define STATE_MASK (STATE_INCREMENT - 1)
+#define GET_STATE(A) ((A) & STATE_MASK)
+
+#define IS_NO_RESIZE_OR_CLEANING(A) (((A) & 0x1u) == 0)
+
+#define GET_ACTIVE_WORKERS(A) ((A) >> STATE_BITS)
+
+#define INITIALIZATION_BLOCK_SIZE 256
+#define MOVE_BLOCK_SIZE 256
+#define CEIL(A, B) (((A) + (B) - 1) / (B))
+
+/* Initializes records and copies the data from the old table.
+   It can share work with other threads.  Only the coordinator
+   will pass blocking as 1, other worker threads pass 0.  */
+static void resize_helper(NAME *htab, int blocking)
+{
+  size_t num_old_blocks = CEIL(htab->old_size, MOVE_BLOCK_SIZE);
+  size_t num_new_blocks = CEIL(htab->size, INITIALIZATION_BLOCK_SIZE);
+
+  size_t my_block;
+  size_t num_finished_blocks = 0;
+
+  while ((my_block = atomic_fetch_add_explicit(&htab->next_init_block, 1,
+                                                memory_order_acquire))
+                                                    < num_new_blocks)
+    {
+      size_t record_it = my_block * INITIALIZATION_BLOCK_SIZE;
+      size_t record_end = (my_block + 1) * INITIALIZATION_BLOCK_SIZE;
+      if (record_end > htab->size)
+          record_end = htab->size;
+
+      while (record_it++ != record_end)
+        {
+          atomic_init(&htab->table[record_it].hashval, (uintptr_t) NULL);
+          atomic_init(&htab->table[record_it].val_ptr, (uintptr_t) NULL);
+        }
+
+      num_finished_blocks++;
+    }
+
+  atomic_fetch_add_explicit(&htab->num_initialized_blocks,
+                            num_finished_blocks, memory_order_release);
+  while (atomic_load_explicit(&htab->num_initialized_blocks,
+                              memory_order_acquire) != num_new_blocks);
+
+  /* All block are initialized, start moving */
+  num_finished_blocks = 0;
+  while ((my_block = atomic_fetch_add_explicit(&htab->next_move_block, 1,
+                                                memory_order_acquire))
+                                                    < num_old_blocks)
+    {
+      size_t record_it = my_block * MOVE_BLOCK_SIZE;
+      size_t record_end = (my_block + 1) * MOVE_BLOCK_SIZE;
+      if (record_end > htab->old_size)
+          record_end = htab->old_size;
+
+      while (record_it++ != record_end)
+        {
+          TYPE val_ptr = (TYPE) atomic_load_explicit(
+              &htab->old_table[record_it].val_ptr,
+              memory_order_acquire);
+          if (val_ptr == NULL)
+              continue;
+
+          HASHTYPE hashval = atomic_load_explicit(
+              &htab->old_table[record_it].hashval,
+              memory_order_acquire);
+          assert(hashval);
+
+          insert_helper(htab, hashval, val_ptr);
+        }
+
+      num_finished_blocks++;
+    }
+
+  atomic_fetch_add_explicit(&htab->num_moved_blocks, num_finished_blocks,
+                            memory_order_release);
+
+  /* The coordinating thread will block here waiting for all blocks to
+     be moved.  */
+  if (blocking)
+      while (atomic_load_explicit(&htab->num_moved_blocks,
+                                  memory_order_acquire) != num_old_blocks);
+}
+
+/* Called by the main thread holding the htab->resize_rwl lock to
+   coordinate the moving of hash table data. Allocates the new hash
+   table and frees the old one when moving all data is done.  */
+static void
+resize_coordinator(NAME *htab)
+{
+  htab->old_size = htab->size;
+  htab->old_table = htab->table;
+
+  htab->size = next_prime(htab->size * 2);
+  htab->table = malloc((1 + htab->size) * sizeof(htab->table[0]));
+  assert(htab->table);
+
+  /* Change state from ALLOCATING_MEMORY to MOVING_DATA */
+  atomic_fetch_xor_explicit(&htab->resizing_state,
+                            ALLOCATING_MEMORY ^ MOVING_DATA,
+                            memory_order_release);
+
+  resize_helper(htab, 1);
+
+  /* Change state from MOVING_DATA to CLEANING */
+  size_t resize_state = atomic_fetch_xor_explicit(&htab->resizing_state,
+                                                  MOVING_DATA ^ CLEANING,
+                                                  memory_order_acq_rel);
+  while (GET_ACTIVE_WORKERS(resize_state) != 0)
+      resize_state = atomic_load_explicit(&htab->resizing_state,
+                                          memory_order_acquire);
+
+  /* There are no more active workers */
+  atomic_store_explicit(&htab->next_init_block, 0, memory_order_relaxed);
+  atomic_store_explicit(&htab->num_initialized_blocks, 0,
+                        memory_order_relaxed);
+
+  atomic_store_explicit(&htab->next_move_block, 0, memory_order_relaxed);
+  atomic_store_explicit(&htab->num_moved_blocks, 0, memory_order_relaxed);
+
+  free(htab->old_table);
+
+  /* Change state to NO_RESIZING */
+  atomic_fetch_xor_explicit(&htab->resizing_state, CLEANING ^ NO_RESIZING,
+                            memory_order_relaxed);
+
+}
+
+/* Called by any thread that wants to do an insert or find operation
+   but notices it cannot get the htab->resize_rwl lock because another
+   thread is resizing the hash table.  Try to help out by moving table
+   data if still necessary.  */
+static void
+resize_worker(NAME *htab)
+{
+  size_t resize_state = atomic_load_explicit(&htab->resizing_state,
+                                              memory_order_acquire);
+
+  /* If the resize has finished */
+  if (IS_NO_RESIZE_OR_CLEANING(resize_state))
+      return;
+
+  /* Register as worker and check if the resize has finished in the meantime*/
+  resize_state = atomic_fetch_add_explicit(&htab->resizing_state,
+                                            STATE_INCREMENT,
+                                            memory_order_acquire);
+  if (IS_NO_RESIZE_OR_CLEANING(resize_state))
+    {
+      atomic_fetch_sub_explicit(&htab->resizing_state, STATE_INCREMENT,
+                                memory_order_relaxed);
+      return;
+    }
+
+  /* Wait while the new table is being allocated. */
+  while (GET_STATE(resize_state) == ALLOCATING_MEMORY)
+      resize_state = atomic_load_explicit(&htab->resizing_state,
+                                          memory_order_acquire);
+
+  /* Check if the resize is done */
+  assert(GET_STATE(resize_state) != NO_RESIZING);
+  if (GET_STATE(resize_state) == CLEANING)
+    {
+      atomic_fetch_sub_explicit(&htab->resizing_state, STATE_INCREMENT,
+                                memory_order_relaxed);
+      return;
+    }
+
+  resize_helper(htab, 0);
+
+  /* Deregister worker */
+  atomic_fetch_sub_explicit(&htab->resizing_state, STATE_INCREMENT,
+                            memory_order_release);
+}
+
+
+int
+#define INIT(name) _INIT (name)
+#define _INIT(name) \
+  name##_init
+INIT(NAME) (NAME *htab, size_t init_size)
+{
+  /* We need the size to be a prime.  */
+  init_size = next_prime (init_size);
+
+  /* Initialize the data structure.  */
+  htab->size = init_size;
+  atomic_init(&htab->filled, 0);
+  atomic_init(&htab->resizing_state, 0);
+
+  atomic_init(&htab->next_init_block, 0);
+  atomic_init(&htab->num_initialized_blocks, 0);
+
+  atomic_init(&htab->next_move_block, 0);
+  atomic_init(&htab->num_moved_blocks, 0);
+
+  pthread_rwlock_init(&htab->resize_rwl, NULL);
+
+  htab->table = malloc ((init_size + 1) * sizeof (htab->table[0]));
+  if (htab->table == NULL)
+      return -1;
+
+  for (size_t i = 0; i <= init_size; i++)
+    {
+      atomic_init(&htab->table[i].hashval, (uintptr_t) NULL);
+      atomic_init(&htab->table[i].val_ptr, (uintptr_t) NULL);
+    }
+
+  return 0;
+}
+
+
+int
+#define FREE(name) _FREE (name)
+#define _FREE(name) \
+name##_free
+FREE(NAME) (NAME *htab)
+{
+  pthread_rwlock_destroy(&htab->resize_rwl);
+  free (htab->table);
+  return 0;
+}
+
+
+int
+#define INSERT(name) _INSERT (name)
+#define _INSERT(name) \
+name##_insert
+INSERT(NAME) (NAME *htab, HASHTYPE hval, TYPE data)
+{
+  int incremented = 0;
+
+  for(;;)
+    {
+      /* If we cannot get the resize_rwl lock someone is resizing
+	 hash table, try to help out by moving table data.  */
+      while (pthread_rwlock_tryrdlock(&htab->resize_rwl) != 0)
+          resize_worker(htab);
+
+      size_t filled;
+      if (!incremented)
+        {
+          filled = atomic_fetch_add_explicit(&htab->filled, 1,
+                                              memory_order_acquire);
+          incremented = 1;
+        }
+      else
+        {
+          filled = atomic_load_explicit(&htab->filled,
+                                        memory_order_acquire);
+        }
+
+
+      if (100 * filled > 90 * htab->size)
+        {
+          /* Table is filled more than 90%.  Resize the table.  */
+
+          size_t resizing_state = atomic_load_explicit(&htab->resizing_state,
+                                                        memory_order_acquire);
+          if (resizing_state == 0 &&
+              atomic_compare_exchange_strong_explicit(&htab->resizing_state,
+                                                      &resizing_state,
+                                                      ALLOCATING_MEMORY,
+                                                      memory_order_acquire,
+                                                      memory_order_acquire))
+            {
+              /* Main resizing thread, will coordinate moving data.  */
+              pthread_rwlock_unlock(&htab->resize_rwl);
+
+              pthread_rwlock_wrlock(&htab->resize_rwl);
+              resize_coordinator(htab);
+              pthread_rwlock_unlock(&htab->resize_rwl);
+
+            }
+          else
+            {
+              /* Worker thread, will help moving data.  */
+              pthread_rwlock_unlock(&htab->resize_rwl);
+              resize_worker(htab);
+            }
+        }
+      else
+        {
+          /* Lock acquired, no need for resize*/
+          break;
+        }
+    }
+
+  int ret_val = insert_helper(htab, hval, data);
+  if (ret_val == -1)
+      atomic_fetch_sub_explicit(&htab->filled, 1, memory_order_relaxed);
+  pthread_rwlock_unlock(&htab->resize_rwl);
+  return ret_val;
+}
+
+
+
+TYPE
+#define FIND(name) _FIND (name)
+#define _FIND(name) \
+  name##_find
+FIND(NAME) (NAME *htab, HASHTYPE hval)
+{
+  /* If we cannot get the resize_rwl lock someone is resizing
+     the hash table, try to help out by moving table data.  */
+  while (pthread_rwlock_tryrdlock(&htab->resize_rwl) != 0)
+    resize_worker(htab);
+
+  size_t idx;
+
+  /* Make the hash data nonzero.  */
+  hval = hval ?: 1;
+  idx = lookup(htab, hval);
+
+  if (idx == 0)
+    {
+      pthread_rwlock_unlock(&htab->resize_rwl);
+      return NULL;
+    }
+
+  /* get a copy before unlocking the lock */
+  TYPE ret_val = (TYPE) atomic_load_explicit(&htab->table[idx].val_ptr,
+                                             memory_order_relaxed);
+
+  pthread_rwlock_unlock(&htab->resize_rwl);
+  return ret_val;
+}
diff --git a/lib/dynamicsizehash_concurrent.h b/lib/dynamicsizehash_concurrent.h
new file mode 100644
index 0000000..73e66e9
--- /dev/null
+++ b/lib/dynamicsizehash_concurrent.h
@@ -0,0 +1,118 @@
+/* Copyright (C) 2000-2019 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Srdan Milakovic <sm108@rice.edu>, 2019.
+   Derived from Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <pthread.h>
+#include "atomics.h"
+/* Before including this file the following macros must be defined:
+
+   NAME      name of the hash table structure.
+   TYPE      data type of the hash table entries
+
+   The following macros if present select features:
+
+   ITERATE   iterating over the table entries is possible
+   HASHTYPE  integer type for hash values, default unsigned long int
+ */
+
+
+
+#ifndef HASHTYPE
+# define HASHTYPE unsigned long int
+#endif
+
+#ifndef RESIZE_BLOCK_SIZE
+# define RESIZE_BLOCK_SIZE 256
+#endif
+
+/* Defined separately.  */
+extern size_t next_prime (size_t seed);
+
+
+/* Table entry type.  */
+#define _DYNHASHCONENTTYPE(name)       \
+  typedef struct name##_ent         \
+  {                                 \
+    _Atomic(HASHTYPE) hashval;      \
+    atomic_uintptr_t val_ptr;       \
+  } name##_ent
+#define DYNHASHENTTYPE(name) _DYNHASHCONENTTYPE (name)
+DYNHASHENTTYPE (NAME);
+
+/* Type of the dynamic hash table data structure.  */
+#define _DYNHASHCONTYPE(name) \
+typedef struct                                     \
+{                                                  \
+  size_t size;                                     \
+  size_t old_size;                                 \
+  atomic_size_t filled;                            \
+  name##_ent *table;                               \
+  name##_ent *old_table;                           \
+  atomic_size_t resizing_state;                    \
+  atomic_size_t next_init_block;                   \
+  atomic_size_t num_initialized_blocks;            \
+  atomic_size_t next_move_block;                   \
+  atomic_size_t num_moved_blocks;                  \
+  pthread_rwlock_t resize_rwl;                     \
+} name
+#define DYNHASHTYPE(name) _DYNHASHCONTYPE (name)
+DYNHASHTYPE (NAME);
+
+
+
+#define _FUNCTIONS(name)                                            \
+/* Initialize the hash table.  */                                   \
+extern int name##_init (name *htab, size_t init_size);              \
+                                                                    \
+/* Free resources allocated for hash table.  */                     \
+extern int name##_free (name *htab);                                \
+                                                                    \
+/* Insert new entry.  */                                            \
+extern int name##_insert (name *htab, HASHTYPE hval, TYPE data);    \
+                                                                    \
+/* Find entry in hash table.  */                                    \
+extern TYPE name##_find (name *htab, HASHTYPE hval);
+#define FUNCTIONS(name) _FUNCTIONS (name)
+FUNCTIONS (NAME)
+
+
+#ifndef NO_UNDEF
+# undef DYNHASHENTTYPE
+# undef DYNHASHTYPE
+# undef FUNCTIONS
+# undef _FUNCTIONS
+# undef XFUNCTIONS
+# undef _XFUNCTIONS
+# undef NAME
+# undef TYPE
+# undef ITERATE
+# undef COMPARE
+# undef FIRST
+# undef NEXT
+#endif
diff --git a/lib/error.c b/lib/error.c
new file mode 100644
index 0000000..5186fc1
--- /dev/null
+++ b/lib/error.c
@@ -0,0 +1,75 @@
+/* Definitions for error fallback functions.
+   Copyright (C) 2021 Google, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#if !defined(HAVE_ERROR_H) && defined(HAVE_ERR_H)
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <err.h>
+
+unsigned int error_message_count = 0;
+
+void error(int status, int errnum, const char *format, ...) {
+  va_list argp;
+  int saved_errno = errno;
+
+  fflush (stdout);
+
+  va_start(argp, format);
+  if (status)
+    {
+      if (errnum)
+        {
+          errno = errnum;
+          verr (status, format, argp);
+        }
+      else
+        verrx (status, format, argp);
+    }
+  else
+    {
+      if (errnum)
+        {
+          errno = errnum;
+          vwarn (format, argp);
+        }
+      else
+        vwarnx (format, argp);
+    }
+  va_end(argp);
+
+  fflush (stderr);
+
+  ++error_message_count;
+
+  errno = saved_errno;
+}
+#endif
diff --git a/lib/eu-config.h b/lib/eu-config.h
new file mode 100644
index 0000000..feb079d
--- /dev/null
+++ b/lib/eu-config.h
@@ -0,0 +1,259 @@
+/* Configuration definitions.
+   Copyright (C) 2008, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef EU_CONFIG_H
+#define EU_CONFIG_H	1
+
+#ifdef USE_LOCKS
+# include <pthread.h>
+# include <assert.h>
+# define rwlock_define(class,name)	class pthread_rwlock_t name
+# define once_define(class,name)  class pthread_once_t name = PTHREAD_ONCE_INIT
+# define RWLOCK_CALL(call)		\
+  ({ int _err = pthread_rwlock_ ## call; assert_perror (_err); })
+# define ONCE_CALL(call)  \
+  ({ int _err = pthread_ ## call; assert_perror (_err); })
+# define rwlock_init(lock)		RWLOCK_CALL (init (&lock, NULL))
+# define rwlock_fini(lock)		RWLOCK_CALL (destroy (&lock))
+# define rwlock_rdlock(lock)		RWLOCK_CALL (rdlock (&lock))
+# define rwlock_wrlock(lock)		RWLOCK_CALL (wrlock (&lock))
+# define rwlock_unlock(lock)		RWLOCK_CALL (unlock (&lock))
+# define once(once_control, init_routine)  \
+  ONCE_CALL (once (&once_control, init_routine))
+#else
+/* Eventually we will allow multi-threaded applications to use the
+   libraries.  Therefore we will add the necessary locking although
+   the macros used expand to nothing for now.  */
+# define rwlock_define(class,name) class int name
+# define rwlock_init(lock) ((void) (lock))
+# define rwlock_fini(lock) ((void) (lock))
+# define rwlock_rdlock(lock) ((void) (lock))
+# define rwlock_wrlock(lock) ((void) (lock))
+# define rwlock_unlock(lock) ((void) (lock))
+# define once_define(class,name)
+# define once(once_control, init_routine)	init_routine()
+#endif	/* USE_LOCKS */
+
+#include <libintl.h>
+/* gettext helper macros.  */
+#define N_(Str) Str
+#define _(Str) dgettext ("elfutils", Str)
+
+/* Compiler-specific definitions.  */
+#define strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name)));
+
+#ifdef __i386__
+# define internal_function __attribute__ ((regparm (3), stdcall))
+#else
+# define internal_function /* nothing */
+#endif
+
+#define internal_strong_alias(name, aliasname) \
+  extern __typeof (name) aliasname __attribute__ ((alias (#name))) internal_function;
+
+#ifdef HAVE_VISIBILITY
+#define attribute_hidden \
+  __attribute__ ((visibility ("hidden")))
+#else
+#define attribute_hidden /* empty */
+#endif
+
+#ifdef HAVE_GCC_STRUCT
+#define attribute_packed \
+  __attribute__ ((packed, gcc_struct))
+#else
+#define attribute_packed \
+  __attribute__ ((packed))
+#endif
+
+/* Define ALLOW_UNALIGNED if the architecture allows operations on
+   unaligned memory locations.  */
+#define SANITIZE_UNDEFINED 1
+#if (defined __i386__ || defined __x86_64__) && ! CHECK_UNDEFINED
+# define ALLOW_UNALIGNED	1
+#else
+# define ALLOW_UNALIGNED	0
+#endif
+
+#if DEBUGPRED
+# ifdef __x86_64__
+asm (".section predict_data, \"aw\"; .previous\n"
+     ".section predict_line, \"a\"; .previous\n"
+     ".section predict_file, \"a\"; .previous");
+#  ifndef PIC
+#   define debugpred__(e, E) \
+  ({ long int _e = !!(e); \
+     asm volatile (".pushsection predict_data; ..predictcnt%=: .quad 0; .quad 0\n" \
+                   ".section predict_line; .quad %c1\n" \
+                   ".section predict_file; .quad %c2; .popsection\n" \
+                   "addq $1,..predictcnt%=(,%0,8)" \
+                   : : "r" (_e == E), "i" (__LINE__), "i" (__FILE__)); \
+    __builtin_expect (_e, E); \
+  })
+#  endif
+# elif defined __i386__
+asm (".section predict_data, \"aw\"; .previous\n"
+     ".section predict_line, \"a\"; .previous\n"
+     ".section predict_file, \"a\"; .previous");
+#  ifndef PIC
+#   define debugpred__(e, E) \
+  ({ long int _e = !!(e); \
+     asm volatile (".pushsection predict_data; ..predictcnt%=: .long 0; .long 0\n" \
+                   ".section predict_line; .long %c1\n" \
+                   ".section predict_file; .long %c2; .popsection\n" \
+                   "incl ..predictcnt%=(,%0,8)" \
+                   : : "r" (_e == E), "i" (__LINE__), "i" (__FILE__)); \
+    __builtin_expect (_e, E); \
+  })
+#  endif
+# endif
+# ifdef debugpred__
+#  define unlikely(e) debugpred__ (e,0)
+#  define likely(e) debugpred__ (e,1)
+# endif
+#endif
+#ifndef likely
+# define unlikely(expr) __builtin_expect (!!(expr), 0)
+# define likely(expr) __builtin_expect (!!(expr), 1)
+#endif
+
+#define obstack_calloc(ob, size) \
+  ({ size_t _s = (size); memset (obstack_alloc (ob, _s), '\0', _s); })
+#define obstack_strdup(ob, str) \
+  ({ const char *_s = (str); obstack_copy0 (ob, _s, strlen (_s)); })
+#define obstack_strndup(ob, str, n) \
+  ({ const char *_s = (str); obstack_copy0 (ob, _s, strnlen (_s, n)); })
+
+#if __STDC_VERSION__ >= 199901L
+# define flexarr_size /* empty */
+#else
+# define flexarr_size 0
+#endif
+
+/* Calling conventions.  */
+#ifdef __i386__
+# define CALLING_CONVENTION regparm (3), stdcall
+# define AND_CALLING_CONVENTION , regparm (3), stdcall
+#else
+# define CALLING_CONVENTION
+# define AND_CALLING_CONVENTION
+#endif
+
+/* Avoid PLT entries.  */
+#ifdef PIC
+# define INTUSE(name) _INTUSE(name)
+# define _INTUSE(name) __##name##_internal
+# define INTDEF(name) _INTDEF(name)
+# define _INTDEF(name) \
+  extern __typeof__ (name) __##name##_internal __attribute__ ((alias (#name)));
+# define INTDECL(name) _INTDECL(name)
+# define _INTDECL(name) \
+  extern __typeof__ (name) __##name##_internal attribute_hidden;
+#else
+# define INTUSE(name) name
+# define INTDEF(name) /* empty */
+# define INTDECL(name) /* empty */
+#endif
+
+/* This macro is used by the tests conditionalize for standalone building.  */
+#define ELFUTILS_HEADER(name) <lib##name.h>
+
+/* Don't reorder with global asm blocks or optimize away. (Doesn't reliably
+   keep it in the same LTO partition, though; -flto-partition=none may be
+   still needed for some gcc versions < 10.) */
+#ifdef __has_attribute
+# if __has_attribute(no_reorder)
+#  define used_in_asm __attribute__ ((externally_visible, no_reorder))
+# endif
+#endif
+#ifndef used_in_asm
+# define used_in_asm /* empty */
+#endif
+
+#ifdef SYMBOL_VERSIONING
+# define NEW_INTDEF(name) __typeof (name) INTUSE(name) \
+  __attribute__ ((alias ("_new." #name))) attribute_hidden;
+# ifdef __has_attribute
+#  if __has_attribute(symver)
+#   define NEW_VERSION(name, version) \
+  __typeof (name) name __asm__ ("_new." #name) \
+    __attribute__ ((symver (#name "@@" #version)));
+#   define OLD_VERSION(name, version) _OLD_VERSION1(name, __COUNTER__, version)
+#   define _OLD_VERSION1(name, num, version) _OLD_VERSION2(name, num, version)
+#   define _OLD_VERSION2(name, num, version) \
+  __typeof (name) _compat_old##num##_##name \
+    __asm__ ("_compat." #version "." #name) \
+    __attribute__ ((alias ("_new." #name), symver (#name "@" #version)));
+#   define COMPAT_VERSION_NEWPROTO(name, version, prefix) \
+  __typeof (_compat_##prefix##_##name) _compat_##prefix##_##name \
+    __asm__ ("_compat." #version "." #name) \
+    __attribute__ ((symver (#name "@" #version)));
+#   define COMPAT_VERSION(name, version, prefix) \
+  asm (".symver _compat." #version "." #name "," #name "@" #version); \
+  __typeof (name) _compat_##prefix##_##name \
+    __asm__ ("_compat." #version "." #name) \
+    __attribute__ ((symver (#name "@" #version)));
+#  endif
+# endif
+# ifndef NEW_VERSION
+#  define OLD_VERSION(name, version) \
+  asm (".globl _compat." #version "." #name "\n\t" \
+       "_compat." #version "." #name " = _new." #name "\n\t" \
+       ".symver _compat." #version "." #name "," #name "@" #version);
+#  define NEW_VERSION(name, version) \
+  __typeof (name) name __asm__ ("_new." #name) used_in_asm; \
+  asm (".symver _new." #name ", " #name "@@" #version);
+#  define COMPAT_VERSION_NEWPROTO(name, version, prefix) \
+  __typeof (_compat_##prefix##_##name) _compat_##prefix##_##name \
+    __asm__ ("_compat." #version "." #name) used_in_asm; \
+  asm (".symver _compat." #version "." #name ", " #name "@" #version);
+#  define COMPAT_VERSION(name, version, prefix) \
+  __typeof (name) _compat_##prefix##_##name \
+    __asm__ ("_compat." #version "." #name) used_in_asm; \
+  asm (".symver _compat." #version "." #name ", " #name "@" #version);
+# endif
+#else
+# define NEW_INTDEF(name) INTDEF(name)
+# define OLD_VERSION(name, version) /* Nothing for static linking.  */
+# define NEW_VERSION(name, version) /* Nothing for static linking.  */
+# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \
+  error "should use #ifdef SYMBOL_VERSIONING"
+# define COMPAT_VERSION(name, version, prefix) \
+  error "should use #ifdef SYMBOL_VERSIONING"
+#endif
+
+#ifndef FALLTHROUGH
+# ifdef HAVE_FALLTHROUGH
+#  define FALLTHROUGH __attribute__ ((fallthrough))
+# else
+#  define FALLTHROUGH ((void) 0)
+# endif
+#endif
+
+#endif	/* eu-config.h */
diff --git a/lib/fixedsizehash.h b/lib/fixedsizehash.h
new file mode 100644
index 0000000..14f0fb8
--- /dev/null
+++ b/lib/fixedsizehash.h
@@ -0,0 +1,266 @@
+/* Fixed size hash table with internal linking.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <system.h>
+
+#define CONCAT_EXPANDED(t1,t2) t1 ## t2
+#define CONCAT(t1,t2) CONCAT_EXPANDED(t1,t2)
+
+/* Before including this file the following macros must be defined:
+
+   TYPE           data type of the hash table entries
+   HASHFCT        name of the hashing function to use
+   HASHTYPE       type used for the hashing value
+   COMPARE        comparison function taking two pointers to TYPE objects
+   CLASS          can be defined to `static' to avoid exporting the functions
+   PREFIX         prefix to be used for function and data type names
+   STORE_POINTER  if defined the table stores a pointer and not an element
+                  of type TYPE
+   INSERT_HASH    if defined alternate insert function which takes a hash
+                  value is defined
+   NO_FINI_FCT    if defined the fini function is not defined
+*/
+
+
+/* Defined separately.  */
+extern size_t next_prime (size_t seed);
+
+
+/* Set default values.  */
+#ifndef HASHTYPE
+# define HASHTYPE size_t
+#endif
+
+#ifndef CLASS
+# define CLASS
+#endif
+
+#ifndef PREFIX
+# define PREFIX
+#endif
+
+
+/* The data structure.  */
+struct CONCAT(PREFIX,fshash)
+{
+  size_t nslots;
+  struct CONCAT(PREFIX,fshashent)
+  {
+    HASHTYPE hval;
+#ifdef STORE_POINTER
+# define ENTRYP(el) (el).entry
+    TYPE *entry;
+#else
+# define ENTRYP(el) &(el).entry
+    TYPE entry;
+#endif
+  } table[0];
+};
+
+
+/* Constructor for the hashing table.  */
+CLASS struct CONCAT(PREFIX,fshash) *
+CONCAT(PREFIX,fshash_init) (size_t nelems)
+{
+  struct CONCAT(PREFIX,fshash) *result;
+  /* We choose a size for the hashing table 150% over the number of
+     entries.  This will guarantee short medium search lengths.  */
+  const size_t max_size_t = ~((size_t) 0);
+
+  if (nelems >= (max_size_t / 3) * 2)
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  /* Adjust the size to be used for the hashing table.  */
+  nelems = next_prime (MAX ((nelems * 3) / 2, 10));
+
+  /* Allocate the data structure for the result.  */
+  result = (struct CONCAT(PREFIX,fshash) *)
+    xcalloc (sizeof (struct CONCAT(PREFIX,fshash))
+	     + (nelems + 1) * sizeof (struct CONCAT(PREFIX,fshashent)), 1);
+  if (result == NULL)
+    return NULL;
+
+  result->nslots = nelems;
+
+  return result;
+}
+
+
+#ifndef NO_FINI_FCT
+CLASS void
+CONCAT(PREFIX,fshash_fini) (struct CONCAT(PREFIX,fshash) *htab)
+{
+  free (htab);
+}
+#endif
+
+
+static struct CONCAT(PREFIX,fshashent) *
+CONCAT(PREFIX,fshash_lookup) (struct CONCAT(PREFIX,fshash) *htab,
+			      HASHTYPE hval, TYPE *data)
+{
+  size_t idx = 1 + hval % htab->nslots;
+
+  if (htab->table[idx].hval != 0)
+    {
+      HASHTYPE hash;
+
+      /* See whether this is the same entry.  */
+      if (htab->table[idx].hval == hval
+	  && COMPARE (data, ENTRYP (htab->table[idx])) == 0)
+	return &htab->table[idx];
+
+      /* Second hash function as suggested in [Knuth].  */
+      hash = 1 + hval % (htab->nslots - 2);
+
+      do
+	{
+	  if (idx <= hash)
+	    idx = htab->nslots + idx - hash;
+	  else
+	    idx -= hash;
+
+	  if (htab->table[idx].hval == hval
+	      && COMPARE (data, ENTRYP(htab->table[idx])) == 0)
+	    return &htab->table[idx];
+	}
+      while (htab->table[idx].hval != 0);
+    }
+
+  return &htab->table[idx];
+}
+
+
+CLASS int
+__attribute__ ((unused))
+CONCAT(PREFIX,fshash_insert) (struct CONCAT(PREFIX,fshash) *htab,
+			      const char *str,
+			      size_t len __attribute__ ((unused)), TYPE *data)
+{
+  HASHTYPE hval = HASHFCT (str, len ?: strlen (str));
+  struct CONCAT(PREFIX,fshashent) *slot;
+
+  slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data);
+ if (slot->hval != 0)
+    /* We don't want to overwrite the old value.  */
+    return -1;
+
+  slot->hval = hval;
+#ifdef STORE_POINTER
+  slot->entry = data;
+#else
+  slot->entry = *data;
+#endif
+
+  return 0;
+}
+
+
+#ifdef INSERT_HASH
+CLASS int
+__attribute__ ((unused))
+CONCAT(PREFIX,fshash_insert_hash) (struct CONCAT(PREFIX,fshash) *htab,
+				   HASHTYPE hval, TYPE *data)
+{
+  struct CONCAT(PREFIX,fshashent) *slot;
+
+  slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data);
+  if (slot->hval != 0)
+    /* We don't want to overwrite the old value.  */
+    return -1;
+
+  slot->hval = hval;
+#ifdef STORE_POINTER
+  slot->entry = data;
+#else
+  slot->entry = *data;
+#endif
+
+  return 0;
+}
+#endif
+
+
+CLASS int
+__attribute__ ((unused))
+CONCAT(PREFIX,fshash_overwrite) (struct CONCAT(PREFIX,fshash) *htab,
+				 const char *str,
+				 size_t len __attribute__ ((unused)),
+				 TYPE *data)
+{
+  HASHTYPE hval = HASHFCT (str, len ?: strlen (str));
+  struct CONCAT(PREFIX,fshashent) *slot;
+
+  slot = CONCAT(PREFIX,fshash_lookup) (htab, hval, data);
+  slot->hval = hval;
+#ifdef STORE_POINTER
+  slot->entry = data;
+#else
+  slot->entry = *data;
+#endif
+
+  return 0;
+}
+
+
+CLASS const TYPE *
+CONCAT(PREFIX,fshash_find) (const struct CONCAT(PREFIX,fshash) *htab,
+			    const char *str,
+			    size_t len __attribute__ ((unused)), TYPE *data)
+{
+  HASHTYPE hval = HASHFCT (str, len ?: strlen (str));
+  struct CONCAT(PREFIX,fshashent) *slot;
+
+  slot = CONCAT(PREFIX,fshash_lookup) ((struct CONCAT(PREFIX,fshash) *) htab,
+				       hval, data);
+  if (slot->hval == 0)
+    /* Not found.  */
+    return NULL;
+
+  return ENTRYP(*slot);
+}
+
+
+/* Unset the macros we expect.  */
+#undef TYPE
+#undef HASHFCT
+#undef HASHTYPE
+#undef COMPARE
+#undef CLASS
+#undef PREFIX
+#undef INSERT_HASH
+#undef STORE_POINTER
+#undef NO_FINI_FCT
diff --git a/lib/libeu.h b/lib/libeu.h
new file mode 100644
index 0000000..e849a79
--- /dev/null
+++ b/lib/libeu.h
@@ -0,0 +1,48 @@
+/* Declarations for the common library.
+   Copyright (C) 2006-2011 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LIBEU_H
+#define LIBEU_H
+
+#include <stddef.h>
+#include <stdint.h>
+
+extern void *xmalloc (size_t) __attribute__ ((__malloc__));
+extern void *xcalloc (size_t, size_t) __attribute__ ((__malloc__));
+extern void *xrealloc (void *, size_t) __attribute__ ((__malloc__));
+
+extern char *xstrdup (const char *) __attribute__ ((__malloc__));
+extern char *xstrndup (const char *, size_t) __attribute__ ((__malloc__));
+
+extern char *xasprintf(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2))) __attribute__ ((__malloc__));
+
+extern uint32_t crc32 (uint32_t crc, unsigned char *buf, size_t len);
+extern int crc32_file (int fd, uint32_t *resp);
+
+#endif
diff --git a/lib/list.h b/lib/list.h
new file mode 100644
index 0000000..fc5c73c
--- /dev/null
+++ b/lib/list.h
@@ -0,0 +1,100 @@
+/* Copyright (C) 2001, 2002, 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LIST_H
+#define LIST_H	1
+
+/* Add element to the end of a circular, double-linked list.  */
+#define CDBL_LIST_ADD_REAR(first, newp) \
+  do {									      \
+    __typeof (newp) _newp = (newp);					      \
+    assert (_newp->next == NULL);					      \
+    assert (_newp->previous == NULL);					      \
+    if (unlikely ((first) == NULL))					      \
+      (first) = _newp->next = _newp->previous = _newp;			      \
+    else								      \
+      {									      \
+	_newp->next = (first);						      \
+	_newp->previous = (first)->previous;				      \
+	_newp->previous->next = _newp->next->previous = _newp;		      \
+      }									      \
+  } while (0)
+
+/* Remove element from circular, double-linked list.  */
+#define CDBL_LIST_DEL(first, elem) \
+  do {									      \
+    __typeof (elem) _elem = (elem);					      \
+    /* Check whether the element is indeed on the list.  */		      \
+    assert (first != NULL && _elem != NULL				      \
+	    && (first != elem						      \
+		|| ({ __typeof (elem) _runp = first->next;		      \
+		      while (_runp != first)				      \
+			if (_runp == _elem)				      \
+			  break;					      \
+			else						      \
+		          _runp = _runp->next;				      \
+		      _runp == _elem; })));				      \
+    if (unlikely (_elem->next == _elem))				      \
+      first = NULL;							      \
+    else								      \
+      {									      \
+	_elem->next->previous = _elem->previous;			      \
+	_elem->previous->next = _elem->next;				      \
+	if (unlikely (first == _elem))					      \
+	  first = _elem->next;						      \
+      }									      \
+     assert ((_elem->next = _elem->previous = NULL, 1));		      \
+  } while (0)
+
+
+/* Add element to the front of a single-linked list.  */
+#define SNGL_LIST_PUSH(first, newp) \
+  do {									      \
+    __typeof (newp) _newp = (newp);					      \
+    assert (_newp->next == NULL);					      \
+    _newp->next = first;						      \
+    first = _newp;							      \
+  } while (0)
+
+
+/* Add element to the rear of a circular single-linked list.  */
+#define CSNGL_LIST_ADD_REAR(first, newp) \
+  do {									      \
+    __typeof (newp) _newp = (newp);					      \
+    assert (_newp->next == NULL);					      \
+    if (unlikely ((first) == NULL))					      \
+      (first) = _newp->next = _newp;					      \
+    else								      \
+      {									      \
+	_newp->next = (first)->next;					      \
+	(first) = (first)->next = _newp;				      \
+      }									      \
+  } while (0)
+
+
+#endif	/* list.h */
diff --git a/lib/next_prime.c b/lib/next_prime.c
new file mode 100644
index 0000000..f2c921e
--- /dev/null
+++ b/lib/next_prime.c
@@ -0,0 +1,66 @@
+/* Determine prime number.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+
+
+/* Test whether CANDIDATE is a prime.  */
+static int
+is_prime (size_t candidate)
+{
+  /* No even number and none less than 10 will be passed here.  */
+  size_t divn = 3;
+  size_t sq = divn * divn;
+
+  while (sq < candidate && candidate % divn != 0)
+    {
+      size_t old_sq = sq;
+      ++divn;
+      sq += 4 * divn;
+      if (sq < old_sq)
+	return 1;
+      ++divn;
+    }
+
+  return candidate % divn != 0;
+}
+
+
+/* We need primes for the table size.  */
+size_t
+next_prime (size_t seed)
+{
+  /* Make it definitely odd.  */
+  seed |= 1;
+
+  while (!is_prime (seed))
+    seed += 2;
+
+  return seed;
+}
diff --git a/lib/printversion.c b/lib/printversion.c
new file mode 100644
index 0000000..2e6c54b
--- /dev/null
+++ b/lib/printversion.c
@@ -0,0 +1,44 @@
+/* Common argp_print_version_hook for all tools.
+   Copyright (C) 2016, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "printversion.h"
+
+void
+print_version (FILE *stream, struct argp_state *state)
+{
+  fprintf (stream, "%s (%s) %s\n", state->name, PACKAGE_NAME, PACKAGE_VERSION);
+  fprintf (stream, _("\
+Copyright (C) %s The elfutils developers <%s>.\n\
+This is free software; see the source for copying conditions.  There is NO\n\
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
+"), "2024", PACKAGE_URL);
+}
diff --git a/lib/printversion.h b/lib/printversion.h
new file mode 100644
index 0000000..6811aa5
--- /dev/null
+++ b/lib/printversion.h
@@ -0,0 +1,59 @@
+/* Common argp_print_version_hook for all tools.
+   Copyright (C) 2017 The Qt Company Ltd.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef PRINTVERSION_H
+#define PRINTVERSION_H 1
+
+#include <argp.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/* Defined in version.c.  Common ARGP_PROGRAM_VERSION_HOOK_DEF.  */
+void print_version (FILE *stream, struct argp_state *state);
+
+/* We need define two variables, argp_program_version_hook and
+   argp_program_bug_address, in all programs.  argp.h declares these
+   variables as non-const (which is correct in general).  But we can
+   do better, it is not going to change.  So we want to move them into
+   the .rodata section.  Define macros to do the trick.  The default
+   linkage for consts in C++ is internal, so declare them extern.  */
+extern void (*const apvh) (FILE *, struct argp_state *);
+#define ARGP_PROGRAM_VERSION_HOOK_DEF \
+  void (*const apvh) (FILE *, struct argp_state *) \
+   __asm ("argp_program_version_hook")
+extern const char *const apba__;
+#define ARGP_PROGRAM_BUG_ADDRESS_DEF \
+  const char *const apba__ __asm ("argp_program_bug_address")
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // PRINTVERSION_H
diff --git a/lib/system.h b/lib/system.h
new file mode 100644
index 0000000..0db12d9
--- /dev/null
+++ b/lib/system.h
@@ -0,0 +1,228 @@
+/* Declarations for common convenience functions.
+   Copyright (C) 2006-2011 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   Copyright (C) 2023 Khem Raj.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef LIB_SYSTEM_H
+#define LIB_SYSTEM_H	1
+
+#include <config.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* System dependent headers */
+#include <byteswap.h>
+#include <endian.h>
+#include <sys/mman.h>
+#include <sys/param.h>
+#include <unistd.h>
+
+#if defined(HAVE_ERROR_H)
+#include <error.h>
+#elif defined(HAVE_ERR_H)
+extern int error_message_count;
+void error(int status, int errnum, const char *format, ...);
+#else
+#error "err.h or error.h must be available"
+#endif
+
+/* error (EXIT_FAILURE, ...) should be noreturn but on some systems it
+   isn't.  This may cause warnings about code that should not be reachable.
+   So have an explicit error_exit wrapper that is noreturn (because it
+   calls exit explicitly).  */
+#define error_exit(errnum,...) do { \
+    error (EXIT_FAILURE,errnum,__VA_ARGS__); \
+    exit (EXIT_FAILURE); \
+  } while (0)
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define LE32(n)	(n)
+# define LE64(n)	(n)
+# define BE32(n)	bswap_32 (n)
+# define BE64(n)	bswap_64 (n)
+#elif BYTE_ORDER == BIG_ENDIAN
+# define BE32(n)	(n)
+# define BE64(n)	(n)
+# define LE32(n)	bswap_32 (n)
+# define LE64(n)	bswap_64 (n)
+#else
+# error "Unknown byte order"
+#endif
+
+#ifndef MAX
+#define MAX(m, n) ((m) < (n) ? (n) : (m))
+#endif
+
+#ifndef MIN
+#define MIN(m, n) ((m) < (n) ? (m) : (n))
+#endif
+
+#if !HAVE_DECL_POWEROF2
+#define powerof2(x) (((x) & ((x) - 1)) == 0)
+#endif
+
+#if !HAVE_DECL_MEMPCPY
+#define mempcpy(dest, src, n) \
+    ((void *) ((char *) memcpy (dest, src, n) + (size_t) n))
+#endif
+
+#if !HAVE_DECL_REALLOCARRAY
+static inline void *
+reallocarray (void *ptr, size_t nmemb, size_t size)
+{
+  if (size > 0 && nmemb > SIZE_MAX / size)
+    {
+      errno = ENOMEM;
+      return NULL;
+    }
+  return realloc (ptr, nmemb * size);
+}
+#endif
+
+/* Return TRUE if the start of STR matches PREFIX, FALSE otherwise.  */
+
+static inline int
+startswith (const char *str, const char *prefix)
+{
+  return strncmp (str, prefix, strlen (prefix)) == 0;
+}
+
+/* A special gettext function we use if the strings are too short.  */
+#define sgettext(Str) \
+  ({ const char *__res = strrchr (_(Str), '|');			      \
+     __res ? __res + 1 : Str; })
+
+#define gettext_noop(Str) Str
+
+#ifndef TEMP_FAILURE_RETRY
+#define TEMP_FAILURE_RETRY(expression) \
+  ({ ssize_t __res; \
+     do \
+       __res = expression; \
+     while (__res == -1 && errno == EINTR); \
+     __res; })
+#endif
+
+#ifndef ACCESSPERMS
+#define ACCESSPERMS (S_IRWXU|S_IRWXG|S_IRWXO) /* 0777 */
+#endif
+
+#ifndef ALLPERMS
+#define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) /* 07777 */
+#endif
+
+#ifndef DEFFILEMODE
+#define DEFFILEMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)/* 0666 */
+#endif
+
+static inline ssize_t __attribute__ ((unused))
+pwrite_retry (int fd, const void *buf, size_t len, off_t off)
+{
+  ssize_t recvd = 0;
+
+  do
+    {
+      ssize_t ret = TEMP_FAILURE_RETRY (pwrite (fd, ((char *)buf) + recvd, len - recvd,
+						off + recvd));
+      if (ret <= 0)
+	return ret < 0 ? ret : recvd;
+
+      recvd += ret;
+    }
+  while ((size_t) recvd < len);
+
+  return recvd;
+}
+
+static inline ssize_t __attribute__ ((unused))
+write_retry (int fd, const void *buf, size_t len)
+{
+  ssize_t recvd = 0;
+
+  do
+    {
+      ssize_t ret = TEMP_FAILURE_RETRY (write (fd, ((char *)buf) + recvd, len - recvd));
+      if (ret <= 0)
+	return ret < 0 ? ret : recvd;
+
+      recvd += ret;
+    }
+  while ((size_t) recvd < len);
+
+  return recvd;
+}
+
+static inline ssize_t __attribute__ ((unused))
+pread_retry (int fd, void *buf, size_t len, off_t off)
+{
+  ssize_t recvd = 0;
+
+  do
+    {
+      ssize_t ret = TEMP_FAILURE_RETRY (pread (fd, ((char *)buf) + recvd, len - recvd,
+					       off + recvd));
+      if (ret <= 0)
+	return ret < 0 ? ret : recvd;
+
+      recvd += ret;
+    }
+  while ((size_t) recvd < len);
+
+  return recvd;
+}
+
+/* The demangler from libstdc++.  */
+extern char *__cxa_demangle (const char *mangled_name, char *output_buffer,
+			     size_t *length, int *status);
+
+/* A static assertion.  This will cause a compile-time error if EXPR,
+   which must be a compile-time constant, is false.  */
+
+#define eu_static_assert(expr)						\
+  extern int never_defined_just_used_for_checking[(expr) ? 1 : -1]	\
+    __attribute__ ((unused))
+
+/* We really want a basename implementation that doesn't modify the
+   input argument.  Normally you get that from string.h with _GNU_SOURCE
+   define.  But some libc implementations don't define it and other
+   define it, but provide an implementation that still modifies the
+   argument.  So define our own and poison a bare basename symbol.  */
+static inline const char *
+xbasename(const char *s)
+{
+  const char *p = strrchr(s, '/');
+  return p ? p+1 : s;
+}
+#pragma GCC poison basename
+
+#endif /* system.h */
diff --git a/lib/xasprintf.c b/lib/xasprintf.c
new file mode 100644
index 0000000..d61fad9
--- /dev/null
+++ b/lib/xasprintf.c
@@ -0,0 +1,51 @@
+/* A wrapper around vasprintf that dies in case of an error.
+   Copyright (c) 2021 Dmitry V. Levin <ldv@altlinux.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "libeu.h"
+#include "system.h"
+
+char *
+xasprintf (const char *fmt, ...)
+{
+  char *res;
+  va_list ap;
+
+  va_start (ap, fmt);
+  if (unlikely (vasprintf (&res, fmt, ap) < 0))
+    error (EXIT_FAILURE, 0, _("memory exhausted"));
+  va_end(ap);
+
+  return res;
+}
diff --git a/lib/xmalloc.c b/lib/xmalloc.c
new file mode 100644
index 0000000..de7211f
--- /dev/null
+++ b/lib/xmalloc.c
@@ -0,0 +1,74 @@
+/* Convenience functions for allocation.
+   Copyright (C) 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include "system.h"
+
+
+/* Allocate N bytes of memory dynamically, with error checking.  */
+void *
+xmalloc (size_t n)
+{
+  void *p;
+
+  p = malloc (n);
+  if (p == NULL)
+    error (EXIT_FAILURE, 0, _("memory exhausted"));
+  return p;
+}
+
+
+/* Allocate memory for N elements of S bytes, with error checking.  */
+void *
+xcalloc (size_t n, size_t s)
+{
+  void *p;
+
+  p = calloc (n, s);
+  if (p == NULL)
+    error (EXIT_FAILURE, 0, _("memory exhausted"));
+  return p;
+}
+
+
+/* Change the size of an allocated block of memory P to N bytes,
+   with error checking.  */
+void *
+xrealloc (void *p, size_t n)
+{
+  p = realloc (p, n);
+  if (p == NULL)
+    error (EXIT_FAILURE, 0, _("memory exhausted"));
+  return p;
+}
diff --git a/lib/xstrdup.c b/lib/xstrdup.c
new file mode 100644
index 0000000..ff1e3d4
--- /dev/null
+++ b/lib/xstrdup.c
@@ -0,0 +1,42 @@
+/* Convenience function for string allocation.
+   Copyright (C) 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libeu.h"
+
+
+/* Return a newly allocated copy of STRING.  */
+char *
+xstrdup (const char *string)
+{
+  return strcpy (xmalloc (strlen (string) + 1), string);
+}
diff --git a/lib/xstrndup.c b/lib/xstrndup.c
new file mode 100644
index 0000000..a257aa9
--- /dev/null
+++ b/lib/xstrndup.c
@@ -0,0 +1,46 @@
+/* Convenience function for string allocation.
+   Copyright (C) 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <string.h>
+#include "libeu.h"
+#include "system.h"
+
+/* Return a newly allocated copy of STRING.  */
+char *
+xstrndup (const char *string, size_t n)
+{
+  char *res;
+  size_t len = strnlen (string, n);
+  *((char *) mempcpy ((res = xmalloc (len + 1)), string, len)) = '\0';
+  return res;
+}
diff --git a/libasm/ChangeLog b/libasm/ChangeLog
new file mode 100644
index 0000000..f23d591
--- /dev/null
+++ b/libasm/ChangeLog
@@ -0,0 +1,321 @@
+2023-02-17  Mark Wielaard  <mark@klomp.org>
+
+	* asm_end.c (free_section): free scnp->content last.
+
+2022-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* disasm_begin.c: Include libeblP.h.
+	* disasm_cb.c: Likewise.
+	* bpf_disasm.c: Likewise and include common.h.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* asm_abort.c: Don't include unistd.h.
+	* asm_addint8.c: Don't include byteswap.h and endian.h.
+	* asm_begin.c: Don't include unistd.h and system.h.
+	* asm_end.c: Likewise.
+	* libasmP.h: Include system.h.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* asm_align.c (__libasm_ensure_section_space): Remove casts of calloc
+	return values.
+	* asm_begin.c (asm_begin): Remove cast of malloc return value.
+	* asm_fill.c (asm_fill): Likewise.
+	* asm_newabssym.c (asm_newabssym): Likewise.
+	* asm_newcomsym.c (asm_newcomsym): Likewise.
+	* asm_newscn.c (asm_newscn): Likewise.
+	* asm_newscngrp.c (asm_newscngrp): Likewise.
+	* asm_newsubscn.c (asm_newsubscn): Likewise.
+	* asm_newsym.c (asm_newsym): Likewise.
+	* disasm_begin.c (disasm_begin): Likewise.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* libasmP.h (asm_emit_symbol_p): Use startswith.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* libasmP.h (_): Remove.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* asm_begin.c (prepare_binary_output): Fix spelling typo in comment.
+	* asm_end.c (binary_end): Likewise.
+
+2020-12-11  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (GCC_INCLUDE): Remove.
+
+2020-12-09  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (noinst_PROGRAMS): Rename to noinst_DATA.
+	(libasm_so_SOURCES): Remove.
+	(CLEANFILES): Add libasm.so.
+
+2020-11-30  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (libasm.so$(EXEEXT)): Drop $(EXEEXT) suffix.
+
+2020-10-29  Mark Wielaard  <mark@klomp.org>
+
+	* asm_align.c (__libasm_ensure_section_space): Use calloc, not
+	malloc to allocate extra space.
+
+2020-07-19  Mark Wielaard  <mark@klomp.org>
+
+	* libasmP.h: Include libebl.h after libasm.h.
+
+2020-07-05  Mark Wielaard  <mark@klomp.org>
+
+	* libasm.h: Include gelf.h.
+
+2020-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* asm_end.c (text_end): Call fflush instead of fclose.
+
+2020-01-08  Mark Wielaard  <mark@klomp.org>
+
+	* libasm.h: Don't include libebl.h. Define an opaque Ebl handle.
+	* libasmP.h: Do include libebl.h.
+
+2019-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libasm_so_DEPS): Replace libebl.a with libebl_pic.a.
+
+2019-03-06  Mark Wielaard  <mark@klomp.org>
+
+	* asm_end.c (binary_end): Check return value of gelf_update_ehdr.
+
+2018-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* disasm_cb.c (read_symtab_exec): Check sh_entsize is not zero.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* asm_end.c: Remove error.h include.
+	* asm_newscn.c: Likewise.
+	* i386_gendis.c: Likewise and add system.h include.
+	* i386_lex.l: Likewise.
+	* i386_parse.y: Likewise.
+
+2017-02-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Use dso_LDFLAGS.
+
+2017-02-17  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Add libasm_so_DEPS to specify external libraries
+	that have to be linked in, and libasm_so_LIBS to specify the
+	archives libasm consists of. The dependencies include libeu.a.
+	(libasm_so_LDLIBS): Add $(libasm_so_DEPS).
+	(libasm_so$(EXEEXT): Use $(libasm_so_LIBS),
+	add --no-undefined,-z,defs,-z,relro,
+	drop the manual enumeration of dependencies,
+	specify the correct path for libasm.map.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* asm_end.c (binary_end): Fix nesting of braces.
+
+2017-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* asm_newsym.c (asm_newsym): Increase TEMPSYMLEN to 13.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* disasm_str.c: Include system.h.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* asm_align.c: Remove sys/param.h include.
+
+2016-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (AM_CPPFLAGS): Add libdwelf.
+	(libasm.so): Add libdw.
+	* asm_begin.c (prepare_binary_output): Use dwelf_strtab instead of
+	ebl_strtab.
+	* asm_end.c (binary_end): Likewise.
+	(__libasm_finictx): Likewise.
+	* asm_newabssym.c (asm_newabssym):  Likewise.
+	* asm_newcomsym.c (asm_newcomsym): Likewise.
+	* asm_newscn.c (binary_newscn): Likewise.
+	* asm_newscngrp.c (asm_newscngrp): Likewise.
+	* asm_newsym.c (asm_newsym): Likewise.
+	* libasmP.h: Likewise.
+	* symbolhash.c (COMPARE): Likewise.
+	* symbolhash.h (COMPARE): Likewise.
+
+2016-06-28  Richard Henderson <rth@redhat.com>
+
+	* disasm_cb.c (disasm_cb): Pass ebl to disasm hook.
+
+2016-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* asm_begin.c (prepare_text_output): Only call __fsetlocking when
+	result isn't NULL.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (libasm.so): Add AM_V_CCLD and AM_V_at silencers.
+
+2015-09-23  Mark Wielaard  <mjw@redhat.com>
+
+	* asm_align.c (__libasm_ensure_section_space): Mark as
+	internal_function.
+	* asm_end.c (__libasm_finictx): Likewise.
+	* asm_error.c (__libasm_seterrno): Likewise.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* asm_*.c: Remove old-style function definitions.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* asm_addint8.c (FCT): Replace K&R function definition
+	with ansi-C definitions.
+	* asm_adduint8.c (UFCT): Likewise.
+	* asm_begin.c (asm_begin): Likewise.
+
+2014-12-18  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am: Suppress output of textrel_check command.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libasm.so): Use textrel_check.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove !MUDFLAP conditions.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2011-02-08  Roland McGrath  <roland@redhat.com>
+
+	* asm_newscn.c (asm_newscn): Remove unused variable.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Use USE_LOCKS instead of USE_TLS.
+	* asm_error.c: Always use __thread.  Remove all !USE_TLS code.
+
+2008-12-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am [USE_TLS]: Like libasm.so with libpthread.
+
+2008-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* libasm.h (DisasmGetSymCB_t): Change type of fourth and fifth
+	parameter.
+	* disasm_cb.c: Adjust accordingly.
+
+2008-01-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (euinclude): Variable removed.
+	(pkginclude_HEADERS): Set this instead of euinclude_HEADERS.
+
+2007-12-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* disasm_cb.c: Add initial support to resolve addresses to symbols.
+
+2007-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* disasm_begin.c: New file.
+	* disasm_cb.c: New file.
+	* disasm_end.c: New file.
+	* disasm_str.c: New file.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (CLEANFILES): Add libasm.so.$(VERSION).
+
+2005-11-13  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (INCLUDES): Search in libdw.
+
+2005-09-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* asm_error.c (asm_errmsg): Unify error message.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Use $(LINK) not $(CC) when creating DSO.
+	(%.os): Use COMPILE.os.
+	(COMPILE.os): Filter out gconv options.
+
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -std=gnu99.
+	* asm_abort.c: Don't try to remove output file if there is none.
+	* asm_addint8.c: In print mode, print to file not stdout.
+	* asm_addsleb128.c: Likewise.
+	* asm_adduleb128.c: Likewise.
+	* asm_newscn.c: Likewise.
+	* asm_align.c: Implement print mode.
+	* asm_begin.c (asm_begin): Change interface.  Take binary class and
+	byte order information from new Ebl parameter.
+	* libasm.h: Adjust prototype.
+	* asm_end.c (text_end): Close file if necesary.
+	* asm_error.c: Add new error ASM_E_IOERROR.
+	* libasmP.h: Add ASM_E_IOERROR definition.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2.
+
+	* asm_end.c (text_end): Mark parameter as possibly unused.
+
+2005-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Remove lint handling.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* asm_end.c (binary_end): Don't terminate with error() in case
+	something goes wrong.
+
+	* Makefile.am: Check for text relocations in constructed DSO.
+
+	* Makefile.am (AM_CFLAGS): More warnings.  Add -fmudflap for MUDFLAP.
+
+	* asm_end.c (binary_end): Remove shadowing variables.
+	Little cleanups.
+
+	* asm_newsym.c: Allocate memory for the string parameter.
+
+2005-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* asm_newscn_ingrp.c (asm_newscn_ingrp): Use INTUSE to reference
+	asm_newscn.
+
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* asm_error.c: Make compile with gcc 4.0.
+
+2004-01-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+2004-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* libasmP.h (_): Use elfutils domain.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+2003-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in: Depend on libebl.a, not libebl.so.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/libasm/Makefile.am b/libasm/Makefile.am
new file mode 100644
index 0000000..1e6b63e
--- /dev/null
+++ b/libasm/Makefile.am
@@ -0,0 +1,89 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2002-2010 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(top_srcdir)/libelf -I$(top_srcdir)/libebl -I$(top_srcdir)/libdw -I$(top_srcdir)/libdwelf
+
+VERSION = 1
+
+lib_LIBRARIES = libasm.a
+noinst_LIBRARIES = libasm_pic.a
+noinst_DATA = $(noinst_LIBRARIES:_pic.a=.so)
+pkginclude_HEADERS = libasm.h
+
+libasm_a_SOURCES = asm_begin.c asm_abort.c asm_end.c asm_error.c \
+		   asm_getelf.c asm_newscn.c asm_newscn_ingrp.c \
+		   asm_newsubscn.c asm_newsym.c asm_newcomsym.c \
+		   asm_newabssym.c \
+		   asm_newscngrp.c asm_scngrp_newsignature.c \
+		   asm_fill.c asm_align.c asm_addstrz.c \
+		   asm_addint8.c asm_adduint8.c \
+		   asm_addint16.c asm_adduint16.c \
+		   asm_addint32.c asm_adduint32.c \
+		   asm_addint64.c asm_adduint64.c \
+		   asm_adduleb128.c asm_addsleb128.c \
+		   disasm_begin.c disasm_cb.c disasm_end.c disasm_str.c \
+		   symbolhash.c
+
+libasm_pic_a_SOURCES =
+am_libasm_pic_a_OBJECTS = $(libasm_a_SOURCES:.c=.os)
+
+libasm_so_DEPS = ../lib/libeu.a ../libebl/libebl_pic.a ../libelf/libelf.so ../libdw/libdw.so
+libasm_so_LDLIBS = $(libasm_so_DEPS)
+if USE_LOCKS
+libasm_so_LDLIBS += -lpthread
+endif
+
+libasm_so_LIBS = libasm_pic.a
+libasm.so: $(srcdir)/libasm.map $(libasm_so_LIBS) $(libasm_so_DEPS)
+	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
+		-Wl,--soname,$@.$(VERSION) \
+		-Wl,--version-script,$< \
+		$(NO_UNDEFINED) \
+		-Wl,--whole-archive $(libasm_so_LIBS) -Wl,--no-whole-archive \
+		$(libasm_so_LDLIBS)
+	@$(textrel_check)
+	$(AM_V_at)ln -fs $@ $@.$(VERSION)
+
+install: install-am libasm.so
+	$(mkinstalldirs) $(DESTDIR)$(libdir)
+	$(INSTALL_PROGRAM) libasm.so $(DESTDIR)$(libdir)/libasm-$(PACKAGE_VERSION).so
+	ln -fs libasm-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libasm.so.$(VERSION)
+	ln -fs libasm.so.$(VERSION) $(DESTDIR)$(libdir)/libasm.so
+
+uninstall: uninstall-am
+	rm -f $(DESTDIR)$(libdir)/libasm-$(PACKAGE_VERSION).so
+	rm -f $(DESTDIR)$(libdir)/libasm.so.$(VERSION)
+	rm -f $(DESTDIR)$(libdir)/libasm.so
+	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
+
+noinst_HEADERS = libasmP.h symbolhash.h
+EXTRA_DIST = libasm.map
+
+CLEANFILES += $(am_libasm_pic_a_OBJECTS) libasm.so libasm.so.$(VERSION)
diff --git a/libasm/asm_abort.c b/libasm/asm_abort.c
new file mode 100644
index 0000000..696298c
--- /dev/null
+++ b/libasm/asm_abort.c
@@ -0,0 +1,59 @@
+/* Abort operations on the assembler context, free all resources.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libasmP.h>
+#include <libelf.h>
+
+
+int
+asm_abort (AsmCtx_t *ctx)
+{
+  if (ctx == NULL)
+    /* Something went wrong earlier.  */
+    return -1;
+
+  if (likely (! ctx->textp))
+    /* First free the ELF file.  We don't care about the result.  */
+    (void) elf_end (ctx->out.elf);
+
+  /* Now close the temporary file and remove it.  */
+  if (ctx->fd != -1)
+    (void) unlink (ctx->tmp_fname);
+
+  /* Free the resources.  */
+  __libasm_finictx (ctx);
+
+  return 0;
+}
diff --git a/libasm/asm_addint16.c b/libasm/asm_addint16.c
new file mode 100644
index 0000000..4ae4597
--- /dev/null
+++ b/libasm/asm_addint16.c
@@ -0,0 +1,32 @@
+/* Add integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define SIZE 16
+
+#include "asm_addint8.c"
diff --git a/libasm/asm_addint32.c b/libasm/asm_addint32.c
new file mode 100644
index 0000000..776cf6f
--- /dev/null
+++ b/libasm/asm_addint32.c
@@ -0,0 +1,32 @@
+/* Add integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define SIZE 32
+
+#include "asm_addint8.c"
diff --git a/libasm/asm_addint64.c b/libasm/asm_addint64.c
new file mode 100644
index 0000000..ee33834
--- /dev/null
+++ b/libasm/asm_addint64.c
@@ -0,0 +1,32 @@
+/* Add integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define SIZE 64
+
+#include "asm_addint8.c"
diff --git a/libasm/asm_addint8.c b/libasm/asm_addint8.c
new file mode 100644
index 0000000..7f823e0
--- /dev/null
+++ b/libasm/asm_addint8.c
@@ -0,0 +1,119 @@
+/* Add integer to a section.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <libasmP.h>
+
+#ifndef SIZE
+# define SIZE 8
+#endif
+
+#define FCT(size) _FCT(size)
+#define _FCT(size) asm_addint##size
+#define TYPE(size) _TYPE(size)
+#define _TYPE(size) int##size##_t
+#define BSWAP(size) _BSWAP(size)
+#define _BSWAP(size) bswap_##size
+
+
+int
+FCT(SIZE) (AsmScn_t *asmscn, TYPE(SIZE) num)
+{
+  if (asmscn == NULL)
+    return -1;
+
+  if (asmscn->type == SHT_NOBITS && unlikely (num != 0))
+    {
+      __libasm_seterrno (ASM_E_TYPE);
+      return -1;
+    }
+
+  if (unlikely (asmscn->ctx->textp))
+    {
+      // XXX Needs to use backend specified pseudo-ops
+      if (SIZE == 8)
+	fprintf (asmscn->ctx->out.file, "\t.byte\t%" PRId8 "\n", (int8_t) num);
+      else if (SIZE == 16)
+	fprintf (asmscn->ctx->out.file, "\t.value\t%" PRId16 "\n",
+		 (int16_t) num);
+      else if (SIZE == 32)
+	fprintf (asmscn->ctx->out.file, "\t.long\t%" PRId32 "\n",
+		 (int32_t) num);
+      else
+	{
+	  // XXX This is not necessary for 64-bit machines
+	  bool is_leb = (elf_getident (asmscn->ctx->out.elf, NULL)[EI_DATA]
+			 == ELFDATA2LSB);
+
+	  fprintf (asmscn->ctx->out.file,
+		   "\t.long\t%" PRId32 "\n\t.long\t%" PRId32 "\n",
+		   (int32_t) (is_leb
+			      ? num % 0x100000000ll : num / 0x100000000ll),
+		   (int32_t) (is_leb
+			      ? num / 0x100000000ll : num % 0x100000000ll));
+	}
+    }
+  else
+    {
+#if SIZE > 8
+      bool is_leb = (elf_getident (asmscn->ctx->out.elf, NULL)[EI_DATA]
+		     == ELFDATA2LSB);
+#endif
+      TYPE(SIZE) var = num;
+
+      /* Make sure we have enough room.  */
+      if (__libasm_ensure_section_space (asmscn, SIZE / 8) != 0)
+	return -1;
+
+#if SIZE > 8
+      if ((BYTE_ORDER == LITTLE_ENDIAN && !is_leb)
+	  || (BYTE_ORDER == BIG_ENDIAN && is_leb))
+	var = BSWAP(SIZE) (var);
+#endif
+
+      /* Copy the variable value.  */
+      if (likely (asmscn->type == SHT_NOBITS))
+	memcpy (&asmscn->content->data[asmscn->content->len], &var, SIZE / 8);
+
+      /* Adjust the pointer in the data buffer.  */
+      asmscn->content->len += SIZE / 8;
+
+      /* Increment the offset in the (sub)section.  */
+      asmscn->offset += SIZE / 8;
+    }
+
+  return 0;
+}
+INTDEF(FCT(SIZE))
diff --git a/libasm/asm_addsleb128.c b/libasm/asm_addsleb128.c
new file mode 100644
index 0000000..dc62c95
--- /dev/null
+++ b/libasm/asm_addsleb128.c
@@ -0,0 +1,97 @@
+/* Add signed little endian base 128 integer to a section.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <string.h>
+
+#include <libasmP.h>
+
+
+int
+asm_addsleb128 (AsmScn_t *asmscn, int32_t num)
+{
+  if (asmscn == NULL)
+    return -1;
+
+  if (asmscn->type == SHT_NOBITS && unlikely (num != 0))
+    {
+      __libasm_seterrno (ASM_E_TYPE);
+      return -1;
+    }
+
+  if (unlikely (asmscn->ctx->textp))
+    fprintf (asmscn->ctx->out.file, "\t.sleb128\t%" PRId32 "\n", num);
+  else
+    {
+      char tmpbuf[(sizeof (num) * 8 + 6) / 7];
+      char *dest = tmpbuf;
+      uint32_t byte;
+      int32_t endval = num >> 31;
+
+      if (num == 0)
+	byte = 0;
+      else
+	while (1)
+	  {
+	    byte = num & 0x7f;
+
+	    num >>= 7;
+	    if (num == endval)
+	      /* This is the last byte.  */
+	      break;
+
+	    *dest++ = byte | 0x80;
+	  }
+
+      *dest++ = byte;
+
+      /* Number of bytes produced.  */
+      size_t nbytes = dest - tmpbuf;
+
+      /* Make sure we have enough room.  */
+      if (__libasm_ensure_section_space (asmscn, nbytes) != 0)
+	return -1;
+
+      /* Copy the bytes.  */
+      if (likely (asmscn->type != SHT_NOBITS))
+	memcpy (&asmscn->content->data[asmscn->content->len], tmpbuf, nbytes);
+
+      /* Adjust the pointer in the data buffer.  */
+      asmscn->content->len += nbytes;
+
+      /* Increment the offset in the (sub)section.  */
+      asmscn->offset += nbytes;
+    }
+
+  return 0;
+}
diff --git a/libasm/asm_addstrz.c b/libasm/asm_addstrz.c
new file mode 100644
index 0000000..26e06bb
--- /dev/null
+++ b/libasm/asm_addstrz.c
@@ -0,0 +1,125 @@
+/* Add string to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <libasmP.h>
+
+
+/* Add zero terminated string STR of size LEN to (sub)section ASMSCN.  */
+int
+asm_addstrz (AsmScn_t *asmscn, const char *str, size_t len)
+{
+  if (asmscn == NULL)
+    return -1;
+
+  if (unlikely (asmscn->type == SHT_NOBITS))
+    {
+      if (len == 0)
+	{
+	  if (str[0] != '\0')
+	    {
+	      __libasm_seterrno (ASM_E_TYPE);
+	      return -1;
+	    }
+	}
+      else
+	{
+	  size_t cnt;
+
+	  for (cnt = 0; cnt < len; ++cnt)
+	    if (str[cnt] != '\0')
+	      {
+		__libasm_seterrno (ASM_E_TYPE);
+		return -1;
+	      }
+	}
+    }
+
+  if (len == 0)
+    len = strlen (str) + 1;
+
+  if (unlikely (asmscn->ctx->textp))
+    {
+      bool nextline = true;
+
+      do
+	{
+	  if (nextline)
+	    {
+	      fputs ("\t.string\t\"", asmscn->ctx->out.file);
+	      nextline = false;
+	    }
+
+	  if (*str == '\0')
+	    fputs ("\\000", asmscn->ctx->out.file);
+	  else if (! isascii (*str))
+	    fprintf (asmscn->ctx->out.file, "\\%03o",
+		     (unsigned int) *((unsigned char *)str));
+	  else if (*str == '\\')
+	    fputs ("\\\\", asmscn->ctx->out.file);
+	  else if (*str == '\n')
+	    {
+	      fputs ("\\n\"", asmscn->ctx->out.file);
+	      nextline = true;
+	    }
+	  else
+	    fputc (*str, asmscn->ctx->out.file);
+
+	  ++str;
+	}
+      while (--len > 0 && (len > 1 || *str != '\0'));
+
+      if (! nextline)
+	fputs ("\"\n", asmscn->ctx->out.file);
+    }
+  else
+    {
+      /* Make sure there is enough room.  */
+      if (__libasm_ensure_section_space (asmscn, len) != 0)
+	return -1;
+
+      /* Copy the string.  */
+      memcpy (&asmscn->content->data[asmscn->content->len], str, len);
+
+      /* Adjust the pointer in the data buffer.  */
+      asmscn->content->len += len;
+
+      /* Increment the offset in the (sub)section.  */
+      asmscn->offset += len;
+    }
+
+  return 0;
+}
diff --git a/libasm/asm_adduint16.c b/libasm/asm_adduint16.c
new file mode 100644
index 0000000..65a1303
--- /dev/null
+++ b/libasm/asm_adduint16.c
@@ -0,0 +1,32 @@
+/* Add unsigned integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define SIZE 16
+
+#include "asm_adduint8.c"
diff --git a/libasm/asm_adduint32.c b/libasm/asm_adduint32.c
new file mode 100644
index 0000000..9a3ec6d
--- /dev/null
+++ b/libasm/asm_adduint32.c
@@ -0,0 +1,32 @@
+/* Add unsigned integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define SIZE 32
+
+#include "asm_adduint8.c"
diff --git a/libasm/asm_adduint64.c b/libasm/asm_adduint64.c
new file mode 100644
index 0000000..b2c57a4
--- /dev/null
+++ b/libasm/asm_adduint64.c
@@ -0,0 +1,32 @@
+/* Add unsigned integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define SIZE 64
+
+#include "asm_adduint8.c"
diff --git a/libasm/asm_adduint8.c b/libasm/asm_adduint8.c
new file mode 100644
index 0000000..18b67dd
--- /dev/null
+++ b/libasm/asm_adduint8.c
@@ -0,0 +1,54 @@
+/* Add unsigned integer to a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libasmP.h>
+
+#ifndef SIZE
+# define SIZE 8
+#endif
+
+#define UFCT(size) _UFCT(size)
+#define _UFCT(size) asm_adduint##size
+#define FCT(size) _FCT(size)
+#define _FCT(size) asm_addint##size
+#define UTYPE(size) _UTYPE(size)
+#define _UTYPE(size) uint##size##_t
+#define TYPE(size) _TYPE(size)
+#define _TYPE(size) int##size##_t
+
+
+int
+UFCT(SIZE) (AsmScn_t *asmscn, UTYPE(SIZE) num)
+{
+  return INTUSE(FCT(SIZE)) (asmscn, (TYPE(SIZE)) num);
+}
diff --git a/libasm/asm_adduleb128.c b/libasm/asm_adduleb128.c
new file mode 100644
index 0000000..96438cc
--- /dev/null
+++ b/libasm/asm_adduleb128.c
@@ -0,0 +1,93 @@
+/* Add integer to a section.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <string.h>
+
+#include "libasmP.h"
+
+
+int
+asm_adduleb128 (AsmScn_t *asmscn, uint32_t num)
+{
+  if (asmscn == NULL)
+    return -1;
+
+  if (asmscn->type == SHT_NOBITS && unlikely (num != 0))
+    {
+      __libasm_seterrno (ASM_E_TYPE);
+      return -1;
+    }
+
+  if (unlikely (asmscn->ctx->textp))
+    fprintf (asmscn->ctx->out.file, "\t.uleb128\t%" PRIu32 "\n", num);
+  else
+    {
+      char tmpbuf[(sizeof (num) * 8 + 6) / 7];
+      char *dest = tmpbuf;
+      uint32_t byte;
+
+      while (1)
+	{
+	  byte = num & 0x7f;
+
+	  num >>= 7;
+	  if (num == 0)
+	    /* This is the last byte.  */
+	    break;
+
+	  *dest++ = byte | 0x80;
+	}
+
+      *dest++ = byte;
+
+      /* Number of bytes produced.  */
+      size_t nbytes = dest - tmpbuf;
+
+      /* Make sure we have enough room.  */
+      if (__libasm_ensure_section_space (asmscn, nbytes) != 0)
+	return -1;
+
+      /* Copy the bytes.  */
+      if (likely (asmscn->type != SHT_NOBITS))
+	memcpy (&asmscn->content->data[asmscn->content->len], tmpbuf, nbytes);
+
+      /* Adjust the pointer in the data buffer.  */
+      asmscn->content->len += nbytes;
+
+      /* Increment the offset in the (sub)section.  */
+      asmscn->offset += nbytes;
+    }
+
+  return 0;
+}
diff --git a/libasm/asm_align.c b/libasm/asm_align.c
new file mode 100644
index 0000000..3a97675
--- /dev/null
+++ b/libasm/asm_align.c
@@ -0,0 +1,174 @@
+/* Align section.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdlib.h>
+
+#include <libasmP.h>
+#include <system.h>
+
+
+int
+asm_align (AsmScn_t *asmscn, GElf_Word value)
+{
+  if (asmscn == NULL)
+    /* An earlier error.  */
+    return -1;
+
+      /* The alignment value must be a power of two.  */
+  if (unlikely (! powerof2 (value)))
+    {
+      __libasm_seterrno (ASM_E_INVALID);
+      return -1;
+    }
+
+  if (unlikely (asmscn->ctx->textp))
+    {
+      fprintf (asmscn->ctx->out.file, "\t.align %" PRId32 ", ",
+	       (int32_t) value);
+      if (asmscn->pattern->len == 1)
+	fprintf (asmscn->ctx->out.file, "%02hhx\n", asmscn->pattern->bytes[0]);
+      else
+	{
+	  fputc_unlocked ('"', asmscn->ctx->out.file);
+
+	  for (size_t cnt = 0; cnt < asmscn->pattern->len; ++cnt)
+	    fprintf (asmscn->ctx->out.file, "\\x%02hhx",
+		     asmscn->pattern->bytes[cnt]);
+
+	  fputs_unlocked ("\"\n", asmscn->ctx->out.file);
+	}
+      return 0;
+    }
+
+  rwlock_wrlock (asmscn->ctx->lock);
+
+  int result = 0;
+
+  /* Fillbytes necessary?  */
+  if ((asmscn->offset & (value - 1)) != 0)
+    {
+      /* Add fillbytes.  */
+      size_t cnt = value - (asmscn->offset & (value - 1));
+
+      /* Ensure there is enough room to add the fill bytes.  */
+      result = __libasm_ensure_section_space (asmscn, cnt);
+      if (result != 0)
+	goto out;
+
+      /* Fill in the bytes.  We align the pattern according to the
+	 current offset.  */
+      size_t byteptr = asmscn->offset % asmscn->pattern->len;
+
+      /* Update the total size.  */
+      asmscn->offset += cnt;
+
+      do
+	{
+	  asmscn->content->data[asmscn->content->len++]
+	    = asmscn->pattern->bytes[byteptr++];
+
+	  if (byteptr == asmscn->pattern->len)
+	    byteptr = 0;
+	}
+      while (--cnt > 0);
+    }
+
+  /* Remember the maximum alignment for this subsection.  */
+  if (asmscn->max_align < value)
+    {
+      asmscn->max_align = value;
+
+      /* Update the parent as well (if it exists).  */
+      if (asmscn->subsection_id != 0)
+	{
+	  rwlock_wrlock (asmscn->data.up->ctx->lock);
+
+	  if (asmscn->data.up->max_align < value)
+	    asmscn->data.up->max_align = value;
+
+	  rwlock_unlock (asmscn->data.up->ctx->lock);
+	}
+    }
+
+ out:
+  rwlock_unlock (asmscn->ctx->lock);
+
+  return result;
+}
+
+
+/* Ensure there are at least LEN bytes available in the output buffer
+   for ASMSCN.  */
+int
+internal_function
+__libasm_ensure_section_space (AsmScn_t *asmscn, size_t len)
+{
+  /* The blocks with the section content are kept in a circular
+     single-linked list.  */
+  size_t size;
+
+  if (asmscn->content == NULL)
+    {
+      /* This is the first block.  */
+      size = MAX (2 * len, 960);
+
+      asmscn->content = calloc (1, sizeof (struct AsmData) + size);
+      if (asmscn->content == NULL)
+	return -1;
+
+      asmscn->content->next = asmscn->content;
+    }
+  else
+    {
+      struct AsmData *newp;
+
+      if (asmscn->content->maxlen - asmscn->content->len >= len)
+	/* Nothing to do, there is enough space.  */
+	return 0;
+
+      size = MAX (2 *len, MIN (32768, 2 * asmscn->offset));
+
+      newp = calloc (1, sizeof (struct AsmData) + size);
+      if (newp == NULL)
+	return -1;
+
+      newp->next = asmscn->content->next;
+      asmscn->content = asmscn->content->next = newp;
+    }
+
+  asmscn->content->len = 0;
+  asmscn->content->maxlen = size;
+
+  return 0;
+}
diff --git a/libasm/asm_begin.c b/libasm/asm_begin.c
new file mode 100644
index 0000000..9e4dfe4
--- /dev/null
+++ b/libasm/asm_begin.c
@@ -0,0 +1,178 @@
+/* Create descriptor for assembling.
+   Copyright (C) 2002, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <gelf.h>
+#include "libasmP.h"
+
+
+static AsmCtx_t *
+prepare_text_output (AsmCtx_t *result)
+{
+  if (result->fd == -1)
+    result->out.file = stdout;
+  else
+    {
+      result->out.file = fdopen (result->fd, "a");
+      if (result->out.file == NULL)
+	{
+	  close (result->fd);
+	  free (result);
+	  result = NULL;
+	}
+      else
+	__fsetlocking (result->out.file, FSETLOCKING_BYCALLER);
+    }
+
+  return result;
+}
+
+
+static AsmCtx_t *
+prepare_binary_output (AsmCtx_t *result, Ebl *ebl)
+{
+  GElf_Ehdr *ehdr;
+  GElf_Ehdr ehdr_mem;
+
+  /* Create the ELF descriptor for the file.  */
+  result->out.elf = elf_begin (result->fd, ELF_C_WRITE_MMAP, NULL);
+  if (result->out.elf == NULL)
+    {
+    err_libelf:
+      unlink (result->tmp_fname);
+      close (result->fd);
+      free (result);
+      __libasm_seterrno (ASM_E_LIBELF);
+      return NULL;
+    }
+
+  /* Create the ELF header for the output file.  */
+  int class = ebl_get_elfclass (ebl);
+  if (gelf_newehdr (result->out.elf, class) == 0)
+    goto err_libelf;
+
+  ehdr = gelf_getehdr (result->out.elf, &ehdr_mem);
+  /* If this failed we are in trouble.  */
+  assert (ehdr != NULL);
+
+  /* We create an object file.  */
+  ehdr->e_type = ET_REL;
+  /* Set the ELF version.  */
+  ehdr->e_version = EV_CURRENT;
+
+  /* Use the machine, class, and endianness values from the Ebl descriptor.  */
+  ehdr->e_machine = ebl_get_elfmachine (ebl);
+  ehdr->e_ident[EI_CLASS] = class;
+  ehdr->e_ident[EI_DATA] = ebl_get_elfdata (ebl);
+
+  memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
+
+  /* Write the ELF header information back.  */
+  (void) gelf_update_ehdr (result->out.elf, ehdr);
+
+  /* No section so far.  */
+  result->section_list = NULL;
+
+  /* Initialize the hash table.  */
+  asm_symbol_tab_init (&result->symbol_tab, 67);
+  result->nsymbol_tab = 0;
+  /* And the string tables.  */
+  result->section_strtab = dwelf_strtab_init (true);
+  result->symbol_strtab = dwelf_strtab_init (true);
+
+  /* We have no section groups so far.  */
+  result->groups = NULL;
+  result->ngroups = 0;
+
+  return result;
+}
+
+
+AsmCtx_t *
+asm_begin (const char *fname, Ebl *ebl, bool textp)
+{
+  if (fname == NULL && ! textp)
+    return NULL;
+
+  size_t fname_len = fname != NULL ? strlen (fname) : 0;
+
+  /* Create the file descriptor.  We do not generate the output file
+     right away.  Instead we create a temporary file in the same
+     directory which, if everything goes alright, will replace a
+     possibly existing file with the given name.  */
+  AsmCtx_t *result = malloc (sizeof (AsmCtx_t) + 2 * fname_len + 9);
+  if (result == NULL)
+    return NULL;
+
+      /* Initialize the lock.  */
+      rwlock_init (result->lock);
+
+  if (fname != NULL)
+    {
+      /* Create the name of the temporary file.  */
+      result->fname = stpcpy (mempcpy (result->tmp_fname, fname, fname_len),
+			      ".XXXXXX") + 1;
+      memcpy (result->fname, fname, fname_len + 1);
+
+      /* Create the temporary file.  */
+      result->fd = mkstemp (result->tmp_fname);
+      if (result->fd == -1)
+	{
+	  int save_errno = errno;
+	  free (result);
+	  __libasm_seterrno (ASM_E_CANNOT_CREATE);
+	  errno = save_errno;
+	  return NULL;
+	}
+    }
+  else
+    result->fd = -1;
+
+  /* Initialize the counter for temporary symbols.  */
+  result->tempsym_count = 0;
+
+  /* Now we differentiate between textual and binary output.   */
+  result->textp = textp;
+  if (textp)
+    result = prepare_text_output (result);
+  else
+    result = prepare_binary_output (result, ebl);
+
+  return result;
+}
diff --git a/libasm/asm_end.c b/libasm/asm_end.c
new file mode 100644
index 0000000..29165ac
--- /dev/null
+++ b/libasm/asm_end.c
@@ -0,0 +1,616 @@
+/* Finalize operations on the assembler context, free all resources.
+   Copyright (C) 2002, 2003, 2005, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include <libasmP.h>
+#include <libelf.h>
+
+
+static int
+text_end (AsmCtx_t *ctx __attribute__ ((unused)))
+{
+  if (fflush (ctx->out.file) != 0)
+    {
+      __libasm_seterrno (ASM_E_IOERROR);
+      return -1;
+    }
+
+  return 0;
+}
+
+
+static int
+binary_end (AsmCtx_t *ctx)
+{
+  void *symtab = NULL;
+  Dwelf_Strent *symscn_strent = NULL;
+  Dwelf_Strent *strscn_strent = NULL;
+  Dwelf_Strent *xndxscn_strent = NULL;
+  Elf_Scn *shstrscn;
+  Dwelf_Strent *shstrscn_strent;
+  size_t shstrscnndx;
+  size_t symscnndx = 0;
+  size_t strscnndx = 0;
+  size_t xndxscnndx = 0;
+  Elf_Data *data;
+  Elf_Data *shstrtabdata;
+  Elf_Data *strtabdata = NULL;
+  Elf_Data *xndxdata = NULL;
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  AsmScn_t *asmscn;
+  int result = 0;
+
+  /* Iterate over the created sections and compute the offsets of the
+     various subsections and fill in the content.  */
+  for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
+    {
+#if 0
+      Elf_Scn *scn = elf_getscn (ctx->out.elf, asmscn->data.main.scnndx);
+#else
+      Elf_Scn *scn = asmscn->data.main.scn;
+#endif
+      off_t offset = 0;
+      AsmScn_t *asmsubscn = asmscn;
+
+      do
+	{
+	  struct AsmData *content = asmsubscn->content;
+	  bool first = true;
+
+	  offset = ((offset + asmsubscn->max_align - 1)
+		    & ~(asmsubscn->max_align - 1));
+
+	  /* Update the offset for this subsection.  This field now
+	     stores the offset of the first by in this subsection.  */
+	  asmsubscn->offset = offset;
+
+	  /* Note that the content list is circular.  */
+	  if (content != NULL)
+	    do
+	      {
+		Elf_Data *newdata = elf_newdata (scn);
+
+		if (newdata == NULL)
+		  {
+		    __libasm_seterrno (ASM_E_LIBELF);
+		    return -1;
+		  }
+
+		newdata->d_buf = content->data;
+		newdata->d_type = ELF_T_BYTE;
+		newdata->d_size = content->len;
+		newdata->d_off = offset;
+		newdata->d_align = first ? asmsubscn->max_align : 1;
+
+		offset += content->len;
+	      }
+	    while ((content = content->next) != asmsubscn->content);
+	}
+      while ((asmsubscn = asmsubscn->subnext) != NULL);
+    }
+
+
+  /* Create the symbol table if necessary.  */
+  if (ctx->nsymbol_tab > 0)
+    {
+      /* Create the symbol table and string table section names.  */
+      symscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".symtab", 8);
+      strscn_strent = dwelf_strtab_add_len (ctx->section_strtab, ".strtab", 8);
+
+      /* Create the symbol string table section.  */
+      Elf_Scn *strscn = elf_newscn (ctx->out.elf);
+      strtabdata = elf_newdata (strscn);
+      shdr = gelf_getshdr (strscn, &shdr_mem);
+      if (strtabdata == NULL || shdr == NULL)
+	{
+	  __libasm_seterrno (ASM_E_LIBELF);
+	  return -1;
+	}
+      strscnndx = elf_ndxscn (strscn);
+
+      dwelf_strtab_finalize (ctx->symbol_strtab, strtabdata);
+
+      shdr->sh_type = SHT_STRTAB;
+      assert (shdr->sh_entsize == 0);
+
+      (void) gelf_update_shdr (strscn, shdr);
+
+      /* Create the symbol table section.  */
+      Elf_Scn *symscn = elf_newscn (ctx->out.elf);
+      data = elf_newdata (symscn);
+      shdr = gelf_getshdr (symscn, &shdr_mem);
+      if (data == NULL || shdr == NULL)
+	{
+	  __libasm_seterrno (ASM_E_LIBELF);
+	  return -1;
+	}
+      symscnndx = elf_ndxscn (symscn);
+
+      /* We know how many symbols there will be in the symbol table.  */
+      data->d_size = gelf_fsize (ctx->out.elf, ELF_T_SYM,
+				 ctx->nsymbol_tab + 1, EV_CURRENT);
+      symtab = malloc (data->d_size);
+      if (symtab == NULL)
+	return -1;
+      data->d_buf = symtab;
+      data->d_type = ELF_T_SYM;
+      data->d_off = 0;
+
+      /* Clear the first entry.  */
+      GElf_Sym syment;
+      memset (&syment, '\0', sizeof (syment));
+      (void) gelf_update_sym (data, 0, &syment);
+
+      /* Iterate over the symbol table.  */
+      void *runp = NULL;
+      int ptr_local = 1;	/* Start with index 1; zero remains unused.  */
+      int ptr_nonlocal = ctx->nsymbol_tab;
+      uint32_t *xshndx = NULL;
+      AsmSym_t *sym;
+      while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
+	if (asm_emit_symbol_p (dwelf_strent_str (sym->strent)))
+	  {
+	    assert (ptr_local <= ptr_nonlocal);
+
+	    syment.st_name = dwelf_strent_off (sym->strent);
+	    syment.st_info = GELF_ST_INFO (sym->binding, sym->type);
+	    syment.st_other = 0;
+	    syment.st_value = sym->scn->offset + sym->offset;
+	    syment.st_size = sym->size;
+
+	    /* Add local symbols at the beginning, the other from
+	       the end.  */
+	    int ptr = sym->binding == STB_LOCAL ? ptr_local++ : ptr_nonlocal--;
+
+	    /* Determine the section index.  We have to handle the
+	       overflow correctly.  */
+	    Elf_Scn *scn = (sym->scn->subsection_id == 0
+			    ? sym->scn->data.main.scn
+			    : sym->scn->data.up->data.main.scn);
+
+	    Elf32_Word ndx;
+	    if (unlikely (scn == ASM_ABS_SCN))
+	      ndx = SHN_ABS;
+	    else if (unlikely (scn == ASM_COM_SCN))
+	      ndx = SHN_COMMON;
+	    else if (unlikely ((ndx = elf_ndxscn (scn)) >= SHN_LORESERVE))
+	      {
+		if (unlikely (xshndx == NULL))
+		  {
+		    /* The extended section index section does not yet
+		       exist.  */
+		    Elf_Scn *xndxscn;
+
+		    xndxscn = elf_newscn (ctx->out.elf);
+		    xndxdata = elf_newdata (xndxscn);
+		    shdr = gelf_getshdr (xndxscn, &shdr_mem);
+		    if (xndxdata == NULL || shdr == NULL)
+		      {
+			__libasm_seterrno (ASM_E_LIBELF);
+			return -1;
+		      }
+		    xndxscnndx = elf_ndxscn (xndxscn);
+
+		    shdr->sh_type = SHT_SYMTAB_SHNDX;
+		    shdr->sh_entsize = sizeof (Elf32_Word);
+		    shdr->sh_addralign = sizeof (Elf32_Word);
+		    shdr->sh_link = symscnndx;
+
+		    (void) gelf_update_shdr (xndxscn, shdr);
+
+		    xndxscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
+							   ".symtab_shndx",
+							   14);
+
+		    /* Note that using 'elf32_fsize' instead of
+		       'gelf_fsize' here is correct.  */
+		    xndxdata->d_size = elf32_fsize (ELF_T_WORD,
+						    ctx->nsymbol_tab + 1,
+						    EV_CURRENT);
+		    xshndx = xndxdata->d_buf = calloc (1, xndxdata->d_size);
+		    if (xshndx == NULL)
+		      return -1;
+		    /* Using ELF_T_WORD here relies on the fact that the
+		       32- and 64-bit types are the same size.  */
+		    xndxdata->d_type = ELF_T_WORD;
+		    xndxdata->d_off = 0;
+		  }
+
+		/* Store the real section index in the extended section
+		   index table.  */
+		assert ((size_t) ptr < ctx->nsymbol_tab + 1);
+		xshndx[ptr] = ndx;
+
+		/* And signal that this happened.  */
+		ndx = SHN_XINDEX;
+	      }
+	    syment.st_shndx = ndx;
+
+	    /* Remember where we put the symbol.  */
+	    sym->symidx = ptr;
+
+	    (void) gelf_update_sym (data, ptr, &syment);
+	  }
+
+      assert (ptr_local == ptr_nonlocal + 1);
+
+      shdr->sh_type = SHT_SYMTAB;
+      shdr->sh_link = strscnndx;
+      shdr->sh_info = ptr_local;
+      shdr->sh_entsize = gelf_fsize (ctx->out.elf, ELF_T_SYM, 1, EV_CURRENT);
+      shdr->sh_addralign = gelf_fsize (ctx->out.elf, ELF_T_ADDR, 1,
+				       EV_CURRENT);
+
+      (void) gelf_update_shdr (symscn, shdr);
+    }
+
+
+  /* Create the section header string table section and fill in the
+     references in the section headers.  */
+  shstrscn = elf_newscn (ctx->out.elf);
+  shstrtabdata = elf_newdata (shstrscn);
+  shdr = gelf_getshdr (shstrscn, &shdr_mem);
+  if (shstrscn == NULL || shstrtabdata == NULL || shdr == NULL)
+    {
+      __libasm_seterrno (ASM_E_LIBELF);
+      return -1;
+    }
+
+
+  /* Add the name of the section header string table.  */
+  shstrscn_strent = dwelf_strtab_add_len (ctx->section_strtab,
+					  ".shstrtab", 10);
+
+  dwelf_strtab_finalize (ctx->section_strtab, shstrtabdata);
+
+  shdr->sh_type = SHT_STRTAB;
+  assert (shdr->sh_entsize == 0);
+  shdr->sh_name = dwelf_strent_off (shstrscn_strent);
+
+  (void) gelf_update_shdr (shstrscn, shdr);
+
+
+  /* Create the section groups.  */
+  if (ctx->groups != NULL)
+    {
+      AsmScnGrp_t *runp = ctx->groups->next;
+
+      do
+	{
+	  Elf_Scn *scn;
+	  Elf32_Word *grpdata;
+
+	  scn = runp->scn;
+	  assert (scn != NULL);
+	  shdr = gelf_getshdr (scn, &shdr_mem);
+	  assert (shdr != NULL);
+
+	  data = elf_newdata (scn);
+	  if (data == NULL)
+	    {
+	      __libasm_seterrno (ASM_E_LIBELF);
+	      return -1;
+	    }
+
+	  /* It is correct to use 'elf32_fsize' instead of 'gelf_fsize'
+	     here.  */
+	  data->d_size = elf32_fsize (ELF_T_WORD, runp->nmembers + 1,
+				      EV_CURRENT);
+	  grpdata = data->d_buf = malloc (data->d_size);
+	  if (grpdata == NULL)
+	    return -1;
+	  data->d_type = ELF_T_WORD;
+	  data->d_off = 0;
+	  data->d_align = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
+
+	  /* The first word of the section is filled with the flag word.  */
+	  *grpdata++ = runp->flags;
+
+	  if (runp->members != NULL)
+	    {
+	      AsmScn_t *member = runp->members->data.main.next_in_group;
+
+	      do
+		{
+		  /* Only sections, not subsections, can be registered
+		     as member of a group.  The subsections get
+		     automatically included.  */
+		  assert (member->subsection_id == 0);
+
+		  *grpdata++ = elf_ndxscn (member->data.main.scn);
+		}
+	      while ((member = member->data.main.next_in_group)
+		     != runp->members->data.main.next_in_group);
+	    }
+
+	  /* Construct the section header.  */
+	  shdr->sh_name = dwelf_strent_off (runp->strent);
+	  shdr->sh_type = SHT_GROUP;
+	  shdr->sh_flags = 0;
+	  shdr->sh_link = symscnndx;
+	  /* If the user did not specify a signature we use the initial
+	     empty symbol in the symbol table as the signature.  */
+	  shdr->sh_info = (runp->signature != NULL
+			   ? runp->signature->symidx : 0);
+
+	  (void) gelf_update_shdr (scn, shdr);
+	}
+      while ((runp = runp->next) != ctx->groups->next);
+    }
+
+
+  /* Add the name to the symbol section.  */
+  if (likely (symscnndx != 0))
+    {
+      Elf_Scn *scn = elf_getscn (ctx->out.elf, symscnndx);
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+
+      shdr->sh_name = dwelf_strent_off (symscn_strent);
+
+      (void) gelf_update_shdr (scn, shdr);
+
+
+      /* Add the name to the string section.  */
+      assert (strscnndx != 0);
+      scn = elf_getscn (ctx->out.elf, strscnndx);
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+
+      shdr->sh_name = dwelf_strent_off (strscn_strent);
+
+      (void) gelf_update_shdr (scn, shdr);
+
+
+      /* Add the name to the extended symbol index section.  */
+      if (xndxscnndx != 0)
+	{
+	  scn = elf_getscn (ctx->out.elf, xndxscnndx);
+
+	  shdr = gelf_getshdr (scn, &shdr_mem);
+
+	  shdr->sh_name = dwelf_strent_off (xndxscn_strent);
+
+	  (void) gelf_update_shdr (scn, shdr);
+	}
+    }
+
+
+  /* Iterate over the created sections and fill in the names.  */
+  for (asmscn = ctx->section_list; asmscn != NULL; asmscn = asmscn->allnext)
+    {
+      shdr = gelf_getshdr (asmscn->data.main.scn, &shdr_mem);
+      /* This better should not fail.  */
+      assert (shdr != NULL);
+
+      shdr->sh_name = dwelf_strent_off (asmscn->data.main.strent);
+
+      /* We now know the maximum alignment.  */
+      shdr->sh_addralign = asmscn->max_align;
+
+      (void) gelf_update_shdr (asmscn->data.main.scn, shdr);
+    }
+
+  /* Put the reference to the section header string table in the ELF
+     header.  */
+  ehdr = gelf_getehdr (ctx->out.elf, &ehdr_mem);
+  assert (ehdr != NULL);
+
+  shstrscnndx = elf_ndxscn (shstrscn);
+  if (unlikely (shstrscnndx > SHN_HIRESERVE)
+      || unlikely (shstrscnndx == SHN_XINDEX))
+    {
+      /* The index of the section header string sectio is too large.  */
+      Elf_Scn *scn = elf_getscn (ctx->out.elf, 0);
+
+      /* Get the header for the zeroth section.  */
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      /* This better does not fail.  */
+      assert (shdr != NULL);
+
+      /* The sh_link field of the zeroth section header contains the value.  */
+      shdr->sh_link = shstrscnndx;
+
+      (void) gelf_update_shdr (scn, shdr);
+
+      /* This is the sign for the overflow.  */
+      ehdr->e_shstrndx = SHN_XINDEX;
+    }
+  else
+    ehdr->e_shstrndx = elf_ndxscn (shstrscn);
+
+  if (unlikely (gelf_update_ehdr (ctx->out.elf, ehdr) == 0))
+    {
+      __libasm_seterrno (ASM_E_LIBELF);
+      result = -1;
+    }
+
+  /* Write out the ELF file.  */
+  if (unlikely (elf_update (ctx->out.elf, ELF_C_WRITE_MMAP) < 0))
+    {
+      __libasm_seterrno (ASM_E_LIBELF);
+      result = -1;
+    }
+
+  /* We do not need the section header and symbol string tables anymore.  */
+  free (shstrtabdata->d_buf);
+  if (strtabdata != NULL)
+    free (strtabdata->d_buf);
+  /* We might have allocated the extended symbol table index.  */
+  if (xndxdata != NULL)
+    free (xndxdata->d_buf);
+
+  /* Free section groups memory.  */
+  AsmScnGrp_t *scngrp = ctx->groups;
+  if (scngrp != NULL)
+    do
+      free (elf_getdata (scngrp->scn, NULL)->d_buf);
+    while ((scngrp = scngrp->next) != ctx->groups);
+
+  /* Finalize the ELF handling.  */
+  if (unlikely (elf_end (ctx->out.elf)) != 0)
+    {
+      __libasm_seterrno (ASM_E_LIBELF);
+      result = -1;
+    }
+
+  /* Free the temporary resources.  */
+  free (symtab);
+
+  return result;
+}
+
+
+int
+asm_end (AsmCtx_t *ctx)
+{
+  int result;
+
+  if (ctx == NULL)
+    /* Something went wrong earlier.  */
+    return -1;
+
+  result = unlikely (ctx->textp) ? text_end (ctx) : binary_end (ctx);
+  if (result != 0)
+    return result;
+
+  /* Make the new file globally readable and user/group-writable.  */
+  if (fchmod (ctx->fd, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH) != 0)
+    {
+      __libasm_seterrno (ASM_E_CANNOT_CHMOD);
+      return -1;
+    }
+
+  /* Rename output file.  */
+  if (rename (ctx->tmp_fname, ctx->fname) != 0)
+    {
+      __libasm_seterrno (ASM_E_CANNOT_RENAME);
+      return -1;
+    }
+
+  /* Free the resources.  */
+  __libasm_finictx (ctx);
+
+  return 0;
+}
+
+
+static void
+free_section (AsmScn_t *scnp)
+{
+  void *oldp;
+
+  if (scnp->subnext != NULL)
+    free_section (scnp->subnext);
+
+  /* This is a circular single linked list.  */
+  struct AsmData *data = scnp->content;
+  if (data != NULL)
+    {
+      while (data != scnp->content)
+	{
+	  oldp = data;
+	  data = data->next;
+	  free (oldp);
+	}
+      free (scnp->content);
+    }
+  free (scnp);
+}
+
+
+void
+internal_function
+__libasm_finictx (AsmCtx_t *ctx)
+{
+  /* Iterate through section table and free individual entries.  */
+  AsmScn_t *scn = ctx->section_list;
+  while (scn != NULL)
+    {
+      AsmScn_t *oldp = scn;
+      scn = scn->allnext;
+      free_section (oldp);
+    }
+
+  /* Free the resources of the symbol table.  */
+  void *runp = NULL;
+  AsmSym_t *sym;
+  while ((sym = asm_symbol_tab_iterate (&ctx->symbol_tab, &runp)) != NULL)
+    free (sym);
+  asm_symbol_tab_free (&ctx->symbol_tab);
+
+
+  /* Free section groups.  */
+  AsmScnGrp_t *scngrp = ctx->groups;
+  if (scngrp != NULL)
+    do
+      {
+	AsmScnGrp_t *oldp = scngrp;
+
+	scngrp = scngrp->next;
+	free (oldp);
+      }
+    while (scngrp != ctx->groups);
+
+
+  if (unlikely (ctx->textp))
+    {
+      /* Close the stream.  */
+      fclose (ctx->out.file);
+    }
+  else
+    {
+      /* Close the output file.  */
+      /* XXX We should test for errors here but what would we do if we'd
+	 find any.  */
+      (void) close (ctx->fd);
+
+      /* And the string tables.  */
+      dwelf_strtab_free (ctx->section_strtab);
+      dwelf_strtab_free (ctx->symbol_strtab);
+    }
+
+  /* Initialize the lock.  */
+  rwlock_fini (ctx->lock);
+
+  /* Finally free the data structure.   */
+  free (ctx);
+}
diff --git a/libasm/asm_error.c b/libasm/asm_error.c
new file mode 100644
index 0000000..2b76939
--- /dev/null
+++ b/libasm/asm_error.c
@@ -0,0 +1,94 @@
+/* Error handling in libasm.
+   Copyright (C) 2002, 2004, 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+
+#include "libasmP.h"
+
+
+/* This is the key for the thread specific memory.  */
+static __thread int global_error;
+
+
+int
+asm_errno (void)
+{
+  int result = global_error;
+  global_error = ASM_E_NOERROR;
+  return result;
+}
+
+
+void
+internal_function
+__libasm_seterrno (int value)
+{
+  global_error = value;
+}
+
+
+/* Return the appropriate message for the error.  */
+static const char *msgs[ASM_E_NUM] =
+{
+  [ASM_E_NOERROR] = N_("no error"),
+  [ASM_E_NOMEM] = N_("out of memory"),
+  [ASM_E_CANNOT_CREATE] = N_("cannot create output file"),
+  [ASM_E_INVALID] = N_("invalid parameter"),
+  [ASM_E_CANNOT_CHMOD] = N_("cannot change mode of output file"),
+  [ASM_E_CANNOT_RENAME] = N_("cannot rename output file"),
+  [ASM_E_DUPLSYM] = N_("duplicate symbol"),
+  [ASM_E_TYPE] = N_("invalid section type for operation"),
+  [ASM_E_IOERROR] = N_("error during output of data"),
+  [ASM_E_ENOSUP] = N_("no backend support available"),
+};
+
+const char *
+asm_errmsg (int error)
+{
+  int last_error = global_error;
+
+  if (error < -1)
+    return _("unknown error");
+  if (error == 0 && last_error == 0)
+    /* No error.  */
+    return NULL;
+
+  if (error != -1)
+    last_error = error;
+
+  if (last_error == ASM_E_LIBELF)
+    return elf_errmsg (-1);
+
+  return _(msgs[last_error]);
+}
diff --git a/libasm/asm_fill.c b/libasm/asm_fill.c
new file mode 100644
index 0000000..783555e
--- /dev/null
+++ b/libasm/asm_fill.c
@@ -0,0 +1,73 @@
+/* Determine fill pattern for a section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <libasmP.h>
+#include <system.h>
+
+
+int
+asm_fill (AsmScn_t *asmscn, void *bytes, size_t len)
+{
+  struct FillPattern *pattern;
+  struct FillPattern *old_pattern;
+
+  if (asmscn == NULL)
+    /* Some earlier error.  */
+    return -1;
+
+  if (bytes == NULL)
+    /* Use the default pattern.  */
+    pattern = (struct FillPattern *) __libasm_default_pattern;
+  else
+    {
+      /* Allocate appropriate memory.  */
+      pattern = malloc (sizeof (struct FillPattern) + len);
+      if (pattern == NULL)
+	return -1;
+
+      pattern->len = len;
+      memcpy (pattern->bytes, bytes, len);
+    }
+
+  old_pattern = asmscn->pattern;
+  asmscn->pattern = pattern;
+
+  /* Free the old data structure if we have allocated it.  */
+  if (old_pattern != __libasm_default_pattern)
+    free (old_pattern);
+
+  return 0;
+}
diff --git a/libasm/asm_getelf.c b/libasm/asm_getelf.c
new file mode 100644
index 0000000..2a5c37b
--- /dev/null
+++ b/libasm/asm_getelf.c
@@ -0,0 +1,43 @@
+/* Return ELF descriptor associated with the assembler context.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include <libasmP.h>
+
+
+Elf *
+asm_getelf (AsmCtx_t *ctx)
+{
+  return ctx != NULL ? ctx->out.elf : NULL;
+}
diff --git a/libasm/asm_newabssym.c b/libasm/asm_newabssym.c
new file mode 100644
index 0000000..728d604
--- /dev/null
+++ b/libasm/asm_newabssym.c
@@ -0,0 +1,131 @@
+/* Create new ABS symbol.
+   Copyright (C) 2002, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libasmP.h>
+#include <system.h>
+
+
+/* Object for special COMMON section.  */
+static const AsmScn_t __libasm_abs_scn =
+  {
+    .data = {
+      .main = {
+	.scn = ASM_ABS_SCN
+      }
+    }
+  };
+
+
+AsmSym_t *
+asm_newabssym (AsmCtx_t *ctx, const char *name, GElf_Xword size,
+	       GElf_Addr value, int type, int binding)
+{
+  AsmSym_t *result;
+
+  if (ctx == NULL)
+    /* Something went wrong before.  */
+    return NULL;
+
+  /* Common symbols are public.  Therefore the user must provide a
+     name.  */
+  if (name == NULL)
+    {
+      __libasm_seterrno (ASM_E_INVALID);
+      return NULL;
+    }
+
+  rwlock_wrlock (ctx->lock);
+
+  result = malloc (sizeof (AsmSym_t));
+  if (result == NULL)
+    return NULL;
+
+  result->scn = (AsmScn_t *) &__libasm_abs_scn;
+  result->size = size;
+  result->type = type;
+  result->binding = binding;
+  result->symidx = 0;
+  result->strent = dwelf_strtab_add (ctx->symbol_strtab, name);
+
+  /* The value of an ABS symbol must not be modified.  Since there are
+     no subsection and the initial offset of the section is 0 we can
+     get the alignment recorded by storing it into the offset
+     field.  */
+  result->offset = value;
+
+  if (unlikely (ctx->textp))
+    {
+      /* An absolute symbol can be defined by giving a symbol a
+	 specific value.  */
+      if (binding == STB_GLOBAL)
+	fprintf (ctx->out.file, "\t.globl %s\n", name);
+      else if (binding == STB_WEAK)
+	fprintf (ctx->out.file, "\t.weak %s\n", name);
+
+      if (type == STT_OBJECT)
+	fprintf (ctx->out.file, "\t.type %s,@object\n", name);
+      else if (type == STT_FUNC)
+	fprintf (ctx->out.file, "\t.type %s,@function\n", name);
+
+      fprintf (ctx->out.file, "%s = %llu\n",
+	       name, (unsigned long long int) value);
+
+      if (size != 0)
+	fprintf (ctx->out.file, "\t.size %s, %llu\n",
+		 name, (unsigned long long int) size);
+    }
+  else
+    {
+      /* Put the symbol in the hash table so that we can later find it.  */
+      if (asm_symbol_tab_insert (&ctx->symbol_tab, elf_hash (name), result)
+	  != 0)
+	{
+	  /* The symbol already exists.  */
+	  __libasm_seterrno (ASM_E_DUPLSYM);
+	  free (result);
+	  result = NULL;
+	}
+      else if (name != NULL && asm_emit_symbol_p (name))
+	/* Only count non-private symbols.  */
+	++ctx->nsymbol_tab;
+    }
+
+  rwlock_unlock (ctx->lock);
+
+  return result;
+}
diff --git a/libasm/asm_newcomsym.c b/libasm/asm_newcomsym.c
new file mode 100644
index 0000000..750a138
--- /dev/null
+++ b/libasm/asm_newcomsym.c
@@ -0,0 +1,114 @@
+/* Create new COMMON symbol.
+   Copyright (C) 2002, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libasmP.h>
+#include <system.h>
+
+
+/* Object for special COMMON section.  */
+static const AsmScn_t __libasm_com_scn =
+  {
+    .data = {
+      .main = {
+	.scn = ASM_COM_SCN
+      }
+    }
+  };
+
+
+AsmSym_t *
+asm_newcomsym (AsmCtx_t *ctx, const char *name, GElf_Xword size,
+	       GElf_Addr align)
+{
+  AsmSym_t *result;
+
+  if (ctx == NULL)
+    /* Something went wrong before.  */
+    return NULL;
+
+  /* Common symbols are public.  Therefore the user must provide a
+     name.  */
+  if (name == NULL)
+    {
+      __libasm_seterrno (ASM_E_INVALID);
+      return NULL;
+    }
+
+  rwlock_wrlock (ctx->lock);
+
+  result = malloc (sizeof (AsmSym_t));
+  if (result == NULL)
+    return NULL;
+
+  result->scn = (AsmScn_t *) &__libasm_com_scn;
+  result->size = size;
+  /* XXX Do we have to allow a different type?  */
+  result->type = STT_OBJECT;
+  /* XXX Do we have to allow a different binding?  */
+  result->binding = STB_GLOBAL;
+  result->symidx = 0;
+  result->strent = dwelf_strtab_add (ctx->symbol_strtab, name);
+
+  /* The value of a COM symbol is the alignment.  Since there are no
+     subsection and the initial offset of the section is 0 we can get
+     the alignment recorded by storing it into the offset field.  */
+  result->offset = align;
+
+  if (unlikely (ctx->textp))
+    fprintf (ctx->out.file, "\t.comm %s, %" PRIuMAX ", %" PRIuMAX "\n",
+	     name, (uintmax_t) size, (uintmax_t) align);
+  else
+    {
+      /* Put the symbol in the hash table so that we can later find it.  */
+      if (asm_symbol_tab_insert (&ctx->symbol_tab, elf_hash (name), result)
+	  != 0)
+	{
+	  /* The symbol already exists.  */
+	  __libasm_seterrno (ASM_E_DUPLSYM);
+	  free (result);
+	  result = NULL;
+	}
+      else if (name != NULL && asm_emit_symbol_p (name))
+	/* Only count non-private symbols.  */
+	++ctx->nsymbol_tab;
+    }
+
+  rwlock_unlock (ctx->lock);
+
+  return result;
+}
diff --git a/libasm/asm_newscn.c b/libasm/asm_newscn.c
new file mode 100644
index 0000000..f28c40f
--- /dev/null
+++ b/libasm/asm_newscn.c
@@ -0,0 +1,216 @@
+/* Create new section in output file.
+   Copyright (C) 2002-2011, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libasmP.h>
+#include <libelf.h>
+#include <system.h>
+
+
+/* Memory for the default pattern.  The type uses a flexible array
+   which does work well with a static initializer.  Work around this by
+   wrapping it in a union, whose second member is a char array 1 byte larger
+   than struct FillPattern.  According to 6.7.9, this does what we need:
+
+        If an object that has static or thread storage duration is not
+        initialized explicitly, then ... if it is a union, the first named
+        member is initialized (recursively) according to these rules, and
+        any padding is initialized to zero bits.  */
+
+static const union
+{
+  struct FillPattern pattern;
+  char zeroes[sizeof(struct FillPattern) + 1];
+} xdefault_pattern =
+  {
+    .pattern =
+    {
+      .len = 1
+    },
+  };
+const struct FillPattern *__libasm_default_pattern = &xdefault_pattern.pattern;
+
+
+static AsmScn_t *
+text_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags)
+{
+  /* Buffer where we construct the flag string.  */
+  char flagstr[sizeof (GElf_Xword) * 8 + 5];
+  char *wp = flagstr;
+  const char *typestr = "";
+
+  /* Only write out the flag string if this is the first time the
+     section is selected.  Some assemblers cannot cope with the
+     .section pseudo-op otherwise.  */
+  wp = stpcpy (wp, ", \"");
+
+  if (flags & SHF_WRITE)
+    *wp++ = 'w';
+  if (flags & SHF_ALLOC)
+    *wp++ = 'a';
+  if (flags & SHF_EXECINSTR)
+    *wp++ = 'x';
+  if (flags & SHF_MERGE)
+    *wp++ = 'M';
+  if (flags & SHF_STRINGS)
+    *wp++ = 'S';
+  if (flags & SHF_LINK_ORDER)
+    *wp++ = 'L';
+
+  *wp++ = '"';
+
+  if (type == SHT_PROGBITS)
+    typestr = ",@progbits";
+  else if (type == SHT_NOBITS)
+    typestr = ",@nobits";
+
+  /* Terminate the string.  */
+  *wp = '\0';
+
+  fprintf (result->ctx->out.file, "\t.section \"%s\"%s%s\n",
+	   result->name, flagstr, typestr);
+
+  return result;
+}
+
+
+static AsmScn_t *
+binary_newscn (AsmScn_t *result, GElf_Word type, GElf_Xword flags,
+	       size_t scnname_len)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr;
+  Elf_Scn *scn;
+
+  /* The initial subsection has the number zero.  */
+  result->subsection_id = 0;
+
+  /* We start at offset zero.  */
+  result->offset = 0;
+  /* And generic alignment.  */
+  result->max_align = 1;
+
+  /* No output yet.  */
+  result->content = NULL;
+
+  /* Put the default fill pattern in place.  */
+  result->pattern = (struct FillPattern *) __libasm_default_pattern;
+
+  /* There are no subsections so far.  */
+  result->subnext = NULL;
+
+  /* Add the name to the section header string table.  */
+  result->data.main.strent = dwelf_strtab_add_len (result->ctx->section_strtab,
+						   result->name, scnname_len);
+  assert (result->data.main.strent != NULL);
+
+  /* Create the new ELF section.  */
+  result->data.main.scn = scn = elf_newscn (result->ctx->out.elf);
+  if (scn == NULL)
+    {
+      free (result);
+      __libasm_seterrno (ASM_E_LIBELF);
+      return NULL;
+    }
+
+  /* Not part of a section group (yet).  */
+  result->data.main.next_in_group = NULL;
+
+  /* Remember the flags.  */
+  shdr = gelf_getshdr (scn, &shdr_mem);
+
+  shdr->sh_flags = flags;
+  result->type = shdr->sh_type = type;
+
+  (void) gelf_update_shdr (scn, shdr);
+
+  return result;
+}
+
+
+AsmScn_t *
+asm_newscn (AsmCtx_t *ctx, const char *scnname, GElf_Word type,
+	    GElf_Xword flags)
+{
+  size_t scnname_len = strlen (scnname) + 1;
+  AsmScn_t *result;
+
+  /* If no context is given there might be an earlier error.  */
+  if (ctx == NULL)
+    return NULL;
+
+  /* Check whether only flags are set which areselectable by the user.  */
+  if (unlikely ((flags & ~(SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE
+			   | SHF_STRINGS | SHF_LINK_ORDER)) != 0)
+      /* We allow only two section types: data and data without file
+	 representation.  */
+      || (type != SHT_PROGBITS && unlikely (type != SHT_NOBITS)))
+    {
+      __libasm_seterrno (ASM_E_INVALID);
+      return NULL;
+    }
+
+  rwlock_wrlock (ctx->lock);
+
+  /* This is a new section.  */
+  result = malloc (sizeof (AsmScn_t) + scnname_len);
+  if (result != NULL)
+    {
+      /* Add the name.  */
+      memcpy (result->name, scnname, scnname_len);
+
+      /* Add the reference to the context.  */
+      result->ctx = ctx;
+
+      /* Perform operations according to output mode.  */
+      result = (unlikely (ctx->textp)
+		? text_newscn (result, type, flags)
+		: binary_newscn (result, type, flags, scnname_len));
+
+      /* If everything went well finally add the new section to the hash
+	 table.  */
+      if (result != NULL)
+	{
+	  result->allnext = ctx->section_list;
+	  ctx->section_list = result;
+	}
+    }
+
+  rwlock_unlock (ctx->lock);
+
+  return result;
+}
+INTDEF(asm_newscn)
diff --git a/libasm/asm_newscn_ingrp.c b/libasm/asm_newscn_ingrp.c
new file mode 100644
index 0000000..fd45be6
--- /dev/null
+++ b/libasm/asm_newscn_ingrp.c
@@ -0,0 +1,77 @@
+/* Create new section, which is member of a group, in output file.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+
+#include "libasmP.h"
+
+
+AsmScn_t *
+asm_newscn_ingrp (AsmCtx_t *ctx, const char *scnname, GElf_Word type,
+		  GElf_Xword flags, AsmScnGrp_t *grp)
+{
+  AsmScn_t *result = INTUSE (asm_newscn) (ctx, scnname, type, flags);
+
+  if (likely (result != NULL))
+    {
+      /* We managed to create a section group.  Add it to the section
+	 group.  */
+      if (grp->nmembers == 0)
+	{
+	  assert (grp->members == NULL);
+	  grp->members = result->data.main.next_in_group = result;
+	}
+      else
+	{
+	  result->data.main.next_in_group
+	    = grp->members->data.main.next_in_group;
+	  grp->members = grp->members->data.main.next_in_group = result;
+	}
+
+      ++grp->nmembers;
+
+      /* Set the SHF_GROUP flag.  */
+      if (likely (! ctx->textp))
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (result->data.main.scn, &shdr_mem);
+
+	  assert (shdr != NULL);
+	  shdr->sh_flags |= SHF_GROUP;
+
+	  (void) gelf_update_shdr (result->data.main.scn, shdr);
+	}
+    }
+
+  return result;
+}
diff --git a/libasm/asm_newscngrp.c b/libasm/asm_newscngrp.c
new file mode 100644
index 0000000..0ca87fb
--- /dev/null
+++ b/libasm/asm_newscngrp.c
@@ -0,0 +1,102 @@
+/* Create new section group.
+   Copyright (C) 2002, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libasmP.h"
+#include <system.h>
+
+
+
+AsmScnGrp_t *
+asm_newscngrp (AsmCtx_t *ctx, const char *grpname, AsmSym_t *signature,
+	       Elf32_Word flags)
+{
+  AsmScnGrp_t *result;
+  size_t grpname_len = strlen (grpname) + 1;
+
+  if (ctx == NULL)
+    return NULL;
+
+  if ((flags & ~GRP_COMDAT) != 0)
+    {
+      /* This is not a supported flag.  */
+      __libasm_seterrno (ASM_E_INVALID);
+      return NULL;
+    }
+
+  result = malloc (sizeof (AsmScnGrp_t) + grpname_len);
+  if (result == NULL)
+    return NULL;
+
+  result->signature = signature;
+  result->members = NULL;
+  result->nmembers = 0;
+  result->flags = flags;
+
+  memcpy (result->name, grpname, grpname_len);
+  result->strent = dwelf_strtab_add_len (ctx->section_strtab, result->name,
+					 grpname_len);
+
+  if (unlikely (ctx->textp))
+    // XXX TBI.  What is the format?
+    abort ();
+  else
+    {
+      result->scn = elf_newscn (ctx->out.elf);
+      if (result->scn == NULL)
+	{
+	  /* Couldn't allocate a new section.  */
+	  __libasm_seterrno (ASM_E_LIBELF);
+	  free (result);
+	  return NULL;
+	}
+    }
+
+  /* Enqueue is the context data structure.  */
+  if (ctx->ngroups == 0)
+    {
+      assert (ctx->groups == NULL);
+      ctx->groups = result->next = result;
+    }
+  else
+    {
+      result->next = ctx->groups->next;
+      ctx->groups = ctx->groups->next = result;
+    }
+  ++ctx->ngroups;
+
+  return result;
+}
diff --git a/libasm/asm_newsubscn.c b/libasm/asm_newsubscn.c
new file mode 100644
index 0000000..2f2ba78
--- /dev/null
+++ b/libasm/asm_newsubscn.c
@@ -0,0 +1,97 @@
+/* Create new subsection section in given section.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libasmP.h>
+#include <system.h>
+
+
+AsmScn_t *
+asm_newsubscn (AsmScn_t *asmscn, unsigned int nr)
+{
+  AsmScn_t *runp;
+  AsmScn_t *newp;
+
+  /* Just return if no section is given.  The error must have been
+     somewhere else.  */
+  if (asmscn == NULL)
+    return NULL;
+
+  /* Determine whether there is already a subsection with this number.  */
+  runp = asmscn->subsection_id == 0 ? asmscn : asmscn->data.up;
+  while (1)
+    {
+      if (runp->subsection_id == nr)
+	/* Found it.  */
+	return runp;
+
+      if (runp->subnext == NULL || runp->subnext->subsection_id > nr)
+	break;
+
+      runp = runp->subnext;
+    }
+
+  newp = malloc (sizeof (AsmScn_t));
+  if (newp == NULL)
+    return NULL;
+
+  /* Same assembler context than the original section.  */
+  newp->ctx = runp->ctx;
+
+  /* User provided the subsectio nID.  */
+  newp->subsection_id = nr;
+
+  /* Inherit the parent's type.  */
+  newp->type = runp->type;
+
+  /* Pointer to the zeroth subsection.  */
+  newp->data.up = runp->subsection_id == 0 ? runp : runp->data.up;
+
+  /* We start at offset zero.  */
+  newp->offset = 0;
+  /* And generic alignment.  */
+  newp->max_align = 1;
+
+  /* No output yet.  */
+  newp->content = NULL;
+
+  /* Inherit the fill pattern from the section this one is derived from.  */
+  newp->pattern = asmscn->pattern;
+
+  /* Enqueue at the right position in the list.  */
+  newp->subnext = runp->subnext;
+  runp->subnext = newp;
+
+  return newp;
+}
diff --git a/libasm/asm_newsym.c b/libasm/asm_newsym.c
new file mode 100644
index 0000000..a89ee12
--- /dev/null
+++ b/libasm/asm_newsym.c
@@ -0,0 +1,136 @@
+/* Define new symbol for current position in given section.
+   Copyright (C) 2002, 2005, 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libasmP.h>
+#include <system.h>
+
+
+AsmSym_t *
+asm_newsym (AsmScn_t *asmscn, const char *name, GElf_Xword size,
+	    int type, int binding)
+{
+/* We don't really expect labels with many digits, but in theory it could
+   be 10 digits (plus ".L" and a zero terminator).  */
+#define TEMPSYMLEN 13
+  char tempsym[TEMPSYMLEN];
+  AsmSym_t *result;
+
+  if (asmscn == NULL)
+    /* Something went wrong before.  */
+    return NULL;
+
+  /* Generate a temporary symbol if necessary.  */
+  if (name == NULL)
+    {
+      /* If a local symbol name is created the symbol better have
+	 local binding.  */
+      if (binding != STB_LOCAL)
+	{
+	  __libasm_seterrno (ASM_E_INVALID);
+	  return NULL;
+	}
+
+      // XXX This requires getting the format from the machine backend.  */
+      snprintf (tempsym, TEMPSYMLEN, ".L%07u", asmscn->ctx->tempsym_count++);
+
+      name = tempsym;
+    }
+
+  size_t name_len = strlen (name) + 1;
+
+  result = malloc (sizeof (AsmSym_t) + name_len);
+  if (result == NULL)
+    return NULL;
+
+  rwlock_wrlock (asmscn->ctx->lock);
+
+  result->scn = asmscn;
+  result->offset = asmscn->offset;
+  result->size = size;
+  result->type = type;
+  result->binding = binding;
+  result->symidx = 0;
+  result->strent = dwelf_strtab_add (asmscn->ctx->symbol_strtab,
+				     memcpy (result + 1, name, name_len));
+
+  if (unlikely (asmscn->ctx->textp))
+    {
+      /* We are only interested in the name and don't need to know whether
+	 it is a local name or not.  */
+      /* First print the binding pseudo-op.  */
+      if (binding == STB_GLOBAL)
+	fprintf (asmscn->ctx->out.file, "\t.globl\t%s\n", name);
+      else if (binding == STB_WEAK)
+	fprintf (asmscn->ctx->out.file, "\t.weak\t%s\n", name);
+
+      /* Next the symbol type.  */
+      if (type == STT_OBJECT)
+	fprintf (asmscn->ctx->out.file, "\t.type\t%s,@object\n", name);
+      else if (type == STT_FUNC)
+	fprintf (asmscn->ctx->out.file, "\t.type\t%s,@function\n", name);
+
+      /* Finally the size and the label.  */
+      fprintf (asmscn->ctx->out.file, "\t.size\t%s,%" PRIuMAX "\n%s:\n",
+	       name, (uintmax_t) size, name);
+    }
+  else
+    {
+      /* Put the symbol in the hash table so that we can later find it.  */
+      if (asm_symbol_tab_insert (&asmscn->ctx->symbol_tab, elf_hash (name),
+				 result) != 0)
+	{
+	  /* The symbol already exists.  */
+	  __libasm_seterrno (ASM_E_DUPLSYM);
+	  /* Note that we can free the entry since there must be no
+	     reference in the string table to the string.  We can only
+	     fail to insert the symbol into the symbol table if there
+	     is already a symbol with this name.  In this case the
+	     dwelf_strtab_add function would use the previously provided
+	     name.  */
+	  free (result);
+	  result = NULL;
+	}
+      else if (name != tempsym && asm_emit_symbol_p (name))
+	/* Only count non-private symbols.  */
+	++asmscn->ctx->nsymbol_tab;
+    }
+
+  rwlock_unlock (asmscn->ctx->lock);
+
+  return result;
+}
diff --git a/libasm/asm_scngrp_newsignature.c b/libasm/asm_scngrp_newsignature.c
new file mode 100644
index 0000000..2fbb334
--- /dev/null
+++ b/libasm/asm_scngrp_newsignature.c
@@ -0,0 +1,46 @@
+/* Update signature of section group.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libasmP.h"
+
+
+int
+asm_scngrp_newsignature (AsmScnGrp_t *grp, AsmSym_t *signature)
+{
+  if (grp == NULL || signature == NULL)
+    return 1;
+
+  grp->signature =  signature;
+
+  return 0;
+}
diff --git a/libasm/disasm_begin.c b/libasm/disasm_begin.c
new file mode 100644
index 0000000..78db90c
--- /dev/null
+++ b/libasm/disasm_begin.c
@@ -0,0 +1,64 @@
+/* Create context descriptor for disassembler.
+   Copyright (C) 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "libasmP.h"
+#include "libeblP.h"
+
+
+DisasmCtx_t *
+disasm_begin (Ebl *ebl, Elf *elf, DisasmGetSymCB_t symcb)
+{
+  if (ebl == NULL)
+    return NULL;
+
+  if (ebl->disasm == NULL)
+    {
+      __libasm_seterrno (ASM_E_ENOSUP);
+      return NULL;
+    }
+
+  DisasmCtx_t *ctx = malloc (sizeof (DisasmCtx_t));
+  if (ctx == NULL)
+    {
+      __libasm_seterrno (ASM_E_NOMEM);
+      return NULL;
+    }
+
+  ctx->ebl = ebl;
+  ctx->elf = elf;
+  ctx->symcb = symcb;
+
+  return ctx;
+}
diff --git a/libasm/disasm_cb.c b/libasm/disasm_cb.c
new file mode 100644
index 0000000..9353e2e
--- /dev/null
+++ b/libasm/disasm_cb.c
@@ -0,0 +1,181 @@
+/* Copyright (C) 2005, 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "libasmP.h"
+#include "libeblP.h"
+
+
+struct symtoken
+{
+  DisasmCtx_t *ctx;
+  void *symcbarg;
+};
+
+
+static int
+default_elf_getsym (GElf_Addr addr, Elf32_Word scnndx, GElf_Addr value,
+		    char **buf, size_t *buflen, void *arg)
+{
+  struct symtoken *symtoken = (struct symtoken *) arg;
+
+  /* First try the user provided function.  */
+  if (symtoken->ctx->symcb != NULL)
+    {
+      int res = symtoken->ctx->symcb (addr, scnndx, value, buf, buflen,
+				      symtoken->symcbarg);
+      if (res >= 0)
+	return res;
+    }
+
+  // XXX Look up in ELF file.
+
+  return -1;
+}
+
+
+struct symaddrpair
+{
+  GElf_Addr addr;
+  const char *name;
+};
+
+
+static void
+read_symtab_exec (DisasmCtx_t *ctx)
+{
+  /* We simply use all we can get our hands on.  This will produce
+     some duplicate information but this is no problem, we simply
+     ignore the latter definitions.  */
+  Elf_Scn *scn= NULL;
+  while ((scn = elf_nextscn (ctx->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      Elf_Data *data;
+      if (shdr == NULL || shdr->sh_type != SHT_SYMTAB
+	  || (data = elf_getdata (scn, NULL)) == NULL)
+	continue;
+
+      int xndxscnidx = elf_scnshndx (scn);
+      Elf_Data *xndxdata = NULL;
+      if (xndxscnidx > 0)
+	xndxdata = elf_getdata (elf_getscn (ctx->elf, xndxscnidx), NULL);
+
+      /* Iterate over all symbols.  Add all defined symbols.  */
+      if (shdr->sh_entsize == 0)
+	continue;
+      int nsyms = shdr->sh_size / shdr->sh_entsize;
+      for (int cnt = 1; cnt < nsyms; ++cnt)
+	{
+	  Elf32_Word xshndx;
+	  GElf_Sym sym_mem;
+	  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem,
+					    &xshndx);
+	  if (sym == NULL)
+	    continue;
+
+	  /* Undefined symbols are useless here.  */
+	  if (sym->st_shndx == SHN_UNDEF)
+	    continue;
+
+
+	}
+    }
+}
+
+
+static void
+read_symtab (DisasmCtx_t *ctx)
+{
+  /* Find the symbol table(s).  */
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (ctx->elf, &ehdr_mem);
+  if (ehdr == NULL)
+    return;
+
+  switch (ehdr->e_type)
+    {
+    case ET_EXEC:
+    case ET_DYN:
+      read_symtab_exec (ctx);
+      break;
+
+    case ET_REL:
+      // XXX  Handle
+      break;
+
+    default:
+      break;
+    }
+}
+
+
+static int
+null_elf_getsym (GElf_Addr addr __attribute__ ((unused)),
+		 Elf32_Word scnndx __attribute__ ((unused)),
+		 GElf_Addr value __attribute__ ((unused)),
+		 char **buf __attribute__ ((unused)),
+		 size_t *buflen __attribute__ ((unused)),
+		 void *arg __attribute__ ((unused)))
+{
+  return -1;
+}
+
+
+int
+disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp, const uint8_t *end,
+	   GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb,
+	   void *outcbarg, void *symcbarg)
+{
+  struct symtoken symtoken;
+  DisasmGetSymCB_t getsym = ctx->symcb ?: null_elf_getsym;
+
+  if (ctx->elf != NULL)
+    {
+      /* Read all symbols of the ELF file and stuff them into a hash
+	 table.  The key is the address and the section index.  */
+      read_symtab (ctx);
+
+      symtoken.ctx = ctx;
+      symtoken.symcbarg = symcbarg;
+
+      symcbarg = &symtoken;
+
+      getsym = default_elf_getsym;
+    }
+
+  return ctx->ebl->disasm (ctx->ebl, startp, end, addr, fmt, outcb,
+			   getsym, outcbarg, symcbarg);
+}
+INTDEF (disasm_cb)
diff --git a/libasm/disasm_end.c b/libasm/disasm_end.c
new file mode 100644
index 0000000..6878030
--- /dev/null
+++ b/libasm/disasm_end.c
@@ -0,0 +1,45 @@
+/* Release descriptor for disassembler.
+   Copyright (C) 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "libasmP.h"
+
+
+int
+disasm_end (DisasmCtx_t *ctx)
+{
+  free (ctx);
+
+  return 0;
+}
diff --git a/libasm/disasm_str.c b/libasm/disasm_str.c
new file mode 100644
index 0000000..c14e6d5
--- /dev/null
+++ b/libasm/disasm_str.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <system.h>
+#include "libasmP.h"
+
+
+struct buffer
+{
+  char *buf;
+  size_t len;
+};
+
+
+static int
+buffer_cb (char *str, size_t len, void *arg)
+{
+  struct buffer *buffer = (struct buffer *) arg;
+
+  if (len > buffer->len)
+    /* Return additional needed space.  */
+    return len - buffer->len;
+
+  buffer->buf = mempcpy (buffer->buf, str, len);
+  buffer->len = len;
+
+  return 0;
+}
+
+
+int
+disasm_str (DisasmCtx_t *ctx, const uint8_t **startp, const uint8_t *end,
+	    GElf_Addr addr, const char *fmt, char **bufp, size_t len,
+	    void *symcbarg)
+{
+  struct buffer buffer = { .buf = *bufp, .len = len };
+
+  int res = INTUSE(disasm_cb) (ctx, startp, end, addr, fmt, buffer_cb, &buffer,
+			       symcbarg);
+  *bufp = buffer.buf;
+  return res;
+}
diff --git a/libasm/libasm.h b/libasm/libasm.h
new file mode 100644
index 0000000..b67b77d
--- /dev/null
+++ b/libasm/libasm.h
@@ -0,0 +1,203 @@
+/* Interface for libasm.
+   Copyright (C) 2002, 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBASM_H
+#define _LIBASM_H 1
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <gelf.h>
+
+typedef struct ebl Ebl;
+
+
+/* Opaque type for the assembler context descriptor.  */
+typedef struct AsmCtx AsmCtx_t;
+
+/* Opaque type for a section.  */
+typedef struct AsmScn AsmScn_t;
+
+/* Opaque type for a section group.  */
+typedef struct AsmScnGrp AsmScnGrp_t;
+
+/* Opaque type for a symbol.  */
+typedef struct AsmSym AsmSym_t;
+
+
+/* Opaque type for the disassembler context descriptor.  */
+typedef struct DisasmCtx DisasmCtx_t;
+
+/* Type used for callback functions to retrieve symbol name.  The
+   symbol reference is in the section designated by the second parameter
+   at an offset described by the first parameter.  The value is the
+   third parameter.  */
+typedef int (*DisasmGetSymCB_t) (GElf_Addr, Elf32_Word, GElf_Addr, char **,
+				 size_t *, void *);
+
+/* Output function callback.  */
+typedef int (*DisasmOutputCB_t) (char *, size_t, void *);
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Create output file and return descriptor for assembler context.  If
+   TEXTP is true the output is an assembler format text file.
+   Otherwise an object file is created.  The MACHINE parameter
+   corresponds to an EM_ constant from <elf.h>, KLASS specifies the
+   class (32- or 64-bit), and DATA specifies the byte order (little or
+   big endian).  */
+extern AsmCtx_t *asm_begin (const char *fname, Ebl *ebl, bool textp);
+
+/* Abort the operation on the assembler context and free all resources.  */
+extern int asm_abort (AsmCtx_t *ctx);
+
+/* Finalize output file and free all resources.  */
+extern int asm_end (AsmCtx_t *ctx);
+
+
+/* Return handle for the named section.  If it was not used before
+   create it.  */
+extern AsmScn_t *asm_newscn (AsmCtx_t *ctx, const char *scnname,
+			     GElf_Word type, GElf_Xword flags);
+
+
+/* Similar to 'asm_newscn', but make it part of section group GRP.  */
+extern AsmScn_t *asm_newscn_ingrp (AsmCtx_t *ctx, const char *scnname,
+				   GElf_Word type, GElf_Xword flags,
+				   AsmScnGrp_t *grp);
+
+/* Create new subsection NR in the given section.  */
+extern AsmScn_t *asm_newsubscn (AsmScn_t *asmscn, unsigned int nr);
+
+
+/* Return handle for new section group.  The signature symbol can be
+   set later.  */
+extern AsmScnGrp_t *asm_newscngrp (AsmCtx_t *ctx, const char *grpname,
+				   AsmSym_t *signature, Elf32_Word flags);
+
+/* Set or overwrite signature symbol for group.  */
+extern int asm_scngrp_newsignature (AsmScnGrp_t *grp, AsmSym_t *signature);
+
+
+/* Add zero terminated string STR of size LEN to (sub)section ASMSCN.  */
+extern int asm_addstrz (AsmScn_t *asmscn, const char *str, size_t len);
+
+/* Add 8-bit signed integer NUM to (sub)section ASMSCN.  */
+extern int asm_addint8 (AsmScn_t *asmscn, int8_t num);
+
+/* Add 8-bit unsigned integer NUM to (sub)section ASMSCN.  */
+extern int asm_adduint8 (AsmScn_t *asmscn, uint8_t num);
+
+/* Add 16-bit signed integer NUM to (sub)section ASMSCN.  */
+extern int asm_addint16 (AsmScn_t *asmscn, int16_t num);
+
+/* Add 16-bit unsigned integer NUM to (sub)section ASMSCN.  */
+extern int asm_adduint16 (AsmScn_t *asmscn, uint16_t num);
+
+/* Add 32-bit signed integer NUM to (sub)section ASMSCN.  */
+extern int asm_addint32 (AsmScn_t *asmscn, int32_t num);
+
+/* Add 32-bit unsigned integer NUM to (sub)section ASMSCN.  */
+extern int asm_adduint32 (AsmScn_t *asmscn, uint32_t num);
+
+/* Add 64-bit signed integer NUM to (sub)section ASMSCN.  */
+extern int asm_addint64 (AsmScn_t *asmscn, int64_t num);
+
+/* Add 64-bit unsigned integer NUM to (sub)section ASMSCN.  */
+extern int asm_adduint64 (AsmScn_t *asmscn, uint64_t num);
+
+
+/* Add signed little endian base 128 integer NUM to (sub)section ASMSCN.  */
+extern int asm_addsleb128 (AsmScn_t *asmscn, int32_t num);
+
+/* Add unsigned little endian base 128 integer NUM to (sub)section ASMSCN.  */
+extern int asm_adduleb128 (AsmScn_t *asmscn, uint32_t num);
+
+
+/* Define new symbol NAME for current position in given section ASMSCN.  */
+extern AsmSym_t *asm_newsym (AsmScn_t *asmscn, const char *name,
+			     GElf_Xword size, int type, int binding);
+
+
+/* Define new common symbol NAME with given SIZE and alignment.  */
+extern AsmSym_t *asm_newcomsym (AsmCtx_t *ctx, const char *name,
+				GElf_Xword size, GElf_Addr align);
+
+/* Define new common symbol NAME with given SIZE, VALUE, TYPE, and BINDING.  */
+extern AsmSym_t *asm_newabssym (AsmCtx_t *ctx, const char *name,
+				GElf_Xword size, GElf_Addr value,
+				int type, int binding);
+
+
+/* Align (sub)section offset according to VALUE.  */
+extern int asm_align (AsmScn_t *asmscn, GElf_Word value);
+
+/* Set the byte pattern used to fill gaps created by alignment.  */
+extern int asm_fill (AsmScn_t *asmscn, void *bytes, size_t len);
+
+
+/* Return ELF descriptor created for the output file of the given context.  */
+extern Elf *asm_getelf (AsmCtx_t *ctx);
+
+
+/* Return error code of last failing function call.  This value is kept
+   separately for each thread.  */
+extern int asm_errno (void);
+
+/* Return error string for ERROR.  If ERROR is zero, return error string
+   for most recent error or NULL is none occurred.  If ERROR is -1 the
+   behaviour is similar to the last case except that not NULL but a legal
+   string is returned.  */
+extern const char *asm_errmsg (int __error);
+
+
+/* Create context descriptor for disassembler.  */
+extern DisasmCtx_t *disasm_begin (Ebl *ebl, Elf *elf, DisasmGetSymCB_t symcb);
+
+/* Release descriptor for disassembler.  */
+extern int disasm_end (DisasmCtx_t *ctx);
+
+/* Produce of disassembly output for given memory, store text in
+   provided buffer.  */
+extern int disasm_str (DisasmCtx_t *ctx, const uint8_t **startp,
+		       const uint8_t *end, GElf_Addr addr, const char *fmt,
+		       char **bufp, size_t len, void *symcbarg);
+
+/* Produce disassembly output for given memory and output it using the
+   given callback functions.  */
+extern int disasm_cb (DisasmCtx_t *ctx, const uint8_t **startp,
+		      const uint8_t *end, GElf_Addr addr, const char *fmt,
+		      DisasmOutputCB_t outcb, void *outcbarg, void *symcbarg);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* libasm.h */
diff --git a/libasm/libasm.map b/libasm/libasm.map
new file mode 100644
index 0000000..a36cdbf
--- /dev/null
+++ b/libasm/libasm.map
@@ -0,0 +1,38 @@
+ELFUTILS_1.0 {
+  global:
+    asm_abort;
+    asm_addint16;
+    asm_addint32;
+    asm_addint64;
+    asm_addint8;
+    asm_addsleb128;
+    asm_addstrz;
+    asm_adduint16;
+    asm_adduint32;
+    asm_adduint64;
+    asm_adduint8;
+    asm_adduleb128;
+    asm_align;
+    asm_begin;
+    asm_end;
+    asm_errmsg;
+    asm_errno;
+    asm_fill;
+    asm_getelf;
+    asm_newabssym;
+    asm_newcomsym;
+    asm_newscn;
+    asm_newscn_ingrp;
+    asm_newscngrp;
+    asm_newsubscn;
+    asm_newsym;
+    asm_scngrp_newsignature;
+
+    disasm_begin;
+    disasm_cb;
+    disasm_end;
+    disasm_str;
+
+  local:
+    *;
+};
diff --git a/libasm/libasmP.h b/libasm/libasmP.h
new file mode 100644
index 0000000..11f4251
--- /dev/null
+++ b/libasm/libasmP.h
@@ -0,0 +1,310 @@
+/* Internal definitions for libasm.
+   Copyright (C) 2002, 2004, 2005, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBASMP_H
+#define _LIBASMP_H 1
+
+#include <stdio.h>
+
+#include <libasm.h>
+
+#include <system.h>
+
+#include "libebl.h"
+
+#include "libdwelf.h"
+
+
+/* Known error codes.  */
+enum
+  {
+    ASM_E_NOERROR,
+    ASM_E_NOMEM,		/* No more memory.  */
+    ASM_E_CANNOT_CREATE,	/* Output file cannot be created.  */
+    ASM_E_INVALID,		/* Invalid parameters.  */
+    ASM_E_CANNOT_CHMOD,		/* Cannot change mode of output file.  */
+    ASM_E_CANNOT_RENAME,	/* Cannot rename output file.  */
+    ASM_E_DUPLSYM,		/* Duplicate symbol definition.  */
+    ASM_E_LIBELF,		/* Refer to error in libelf.  */
+    ASM_E_TYPE,			/* Invalid section type for operation.  */
+    ASM_E_IOERROR,		/* Error during output of data.  */
+    ASM_E_ENOSUP,		/* No backend support.  */
+    ASM_E_NUM			/* Keep this entry as the last.  */
+  };
+
+
+/* Special sections.  */
+#define ASM_ABS_SCN ((Elf_Scn *) 1)
+#define ASM_COM_SCN ((Elf_Scn *) 2)
+
+
+/* And the hash table for symbols.  */
+#include <symbolhash.h>
+
+
+/* Descriptor for a section.  */
+struct AsmScn
+{
+  /* The underlying assembler context.  */
+  AsmCtx_t *ctx;
+
+  /* Subsection ID.  */
+  unsigned int subsection_id;
+
+  /* Section type.  */
+  GElf_Word type;
+
+  union
+  {
+    /* Data only stored in the record for subsection zero.  */
+    struct
+    {
+      /* The ELF section.  */
+      Elf_Scn *scn;
+
+      /* Entry in the section header string table.  */
+      Dwelf_Strent *strent;
+
+      /* Next member of group.  */
+      struct AsmScn *next_in_group;
+    } main;
+
+    /* Pointer to the record for subsection zero.  */
+    AsmScn_t *up;
+  } data;
+
+  /* Current offset in the (sub)section.  */
+  GElf_Off offset;
+  /* Maximum alignment of the section so far.  */
+  GElf_Word max_align;
+
+  /* Section content.  */
+  struct AsmData
+  {
+    /* Currently used number of bytes in the block.  */
+    size_t len;
+
+    /* Number of bytes allocated.  */
+    size_t maxlen;
+
+    /* Pointer to the next block.  */
+    struct AsmData *next;
+
+    /* The actual data.  */
+    char data[flexarr_size];
+  } *content;
+
+  /* Fill pattern.  */
+  struct FillPattern
+  {
+    size_t len;
+    char bytes[flexarr_size];
+  } *pattern;
+
+  /* Next subsection.  */
+  AsmScn_t *subnext;
+
+  /* List of all allocated sections.  */
+  AsmScn_t *allnext;
+
+  /* Name of the section.  */
+  char name[flexarr_size];
+};
+
+
+/* Descriptor used for the assembling session.  */
+struct AsmCtx
+{
+  /* File descriptor of the temporary file.  */
+  int fd;
+
+  /* True if text output is wanted.  */
+  bool textp;
+
+  /* Output file handle.  */
+  union
+  {
+    /* ELF descriptor of the temporary file.  */
+    Elf *elf;
+    /* I/O stream for text output.  */
+    FILE *file;
+  } out;
+
+
+  /* List with defined sections.  */
+  AsmScn_t *section_list;
+  /* Section header string table.  */
+  Dwelf_Strtab *section_strtab;
+
+  /* Table with defined symbols.  */
+  asm_symbol_tab symbol_tab;
+  /* Number of symbols in the table.  */
+  unsigned int nsymbol_tab;
+  /* Symbol string table.  */
+  Dwelf_Strtab *symbol_strtab;
+
+  /* List of section groups.  */
+  struct AsmScnGrp *groups;
+  /* Number of section groups.  */
+  size_t ngroups;
+
+  /* Current required alignment for common symbols.  */
+  GElf_Word common_align;
+
+  /* Lock to handle multithreaded programs.  */
+  rwlock_define (,lock);
+
+  /* Counter for temporary symbols.  */
+  unsigned int tempsym_count;
+
+  /* Name of the output file.  */
+  char *fname;
+  /* The name of the temporary file.  */
+  char tmp_fname[flexarr_size];
+};
+
+
+/* Descriptor for a symbol.  */
+struct AsmSym
+{
+  /* Reference to the section which contains the symbol.  */
+  AsmScn_t *scn;
+
+  /* Type of the symbol.  */
+  int8_t type;
+  /* Binding of the symbol.  */
+  int8_t binding;
+
+  /* Size of the symbol.  */
+  GElf_Xword size;
+
+  /* Offset in the section.  */
+  GElf_Off offset;
+
+  /* Symbol table index of the symbol in the symbol table.  */
+  size_t symidx;
+
+  /* Reference to name of the symbol.  */
+  Dwelf_Strent *strent;
+};
+
+
+/* Descriptor for section group.  */
+struct AsmScnGrp
+{
+  /* Entry in the section header string table.  */
+  Dwelf_Strent *strent;
+
+  /* The ELF section.  */
+  Elf_Scn *scn;
+
+  /* The signature.  */
+  struct AsmSym *signature;
+
+  /* First member.  */
+  struct AsmScn *members;
+  /* Number of members.  */
+  size_t nmembers;
+
+  /* Flags.  */
+  Elf32_Word flags;
+
+  /* Next group.  */
+  struct AsmScnGrp *next;
+
+  /* Name of the section group.  */
+  char name[flexarr_size];
+};
+
+
+/* Descriptor for disassembler.   */
+struct DisasmCtx
+{
+  /* Handle for the backend library with the disassembler routine.  */
+  Ebl *ebl;
+
+  /* ELF file containing all the data passed to the function.  This
+     allows to look up symbols.  */
+  Elf *elf;
+
+  /* Callback function to determine symbol names.  */
+  DisasmGetSymCB_t symcb;
+};
+
+
+/* The default fill pattern: one zero byte.  */
+extern const struct FillPattern *__libasm_default_pattern
+     attribute_hidden;
+
+
+/* Ensure there are at least LEN bytes available in the output buffer
+   for ASMSCN.  */
+extern int __libasm_ensure_section_space (AsmScn_t *asmscn, size_t len)
+     internal_function;
+
+/* Free all resources associated with the assembler context.  */
+extern void __libasm_finictx (AsmCtx_t *ctx) internal_function;
+
+/* Set error code.  */
+extern void __libasm_seterrno (int err) internal_function;
+
+/* Return handle for the named section.  If it was not used before
+   create it.  */
+extern AsmScn_t *__asm_newscn_internal (AsmCtx_t *ctx, const char *scnname,
+					GElf_Word type, GElf_Xword flags)
+     attribute_hidden;
+
+
+/* Internal aliases of the asm_addintXX functions.  */
+extern int __asm_addint8_internal (AsmScn_t *asmscn, int8_t num)
+     attribute_hidden;
+extern int __asm_addint16_internal (AsmScn_t *asmscn, int16_t num)
+     attribute_hidden;
+extern int __asm_addint32_internal (AsmScn_t *asmscn, int32_t num)
+     attribute_hidden;
+extern int __asm_addint64_internal (AsmScn_t *asmscn, int64_t num)
+     attribute_hidden;
+
+
+/* Produce disassembly output for given memory and output it using the
+   given callback functions.  */
+extern int __disasm_cb_internal (DisasmCtx_t *ctx, const uint8_t **startp,
+				 const uint8_t *end, GElf_Addr addr,
+				 const char *fmt, DisasmOutputCB_t outcb,
+				 void *outcbarp, void *symcbarg)
+     attribute_hidden;
+
+
+/* Test whether given symbol is an internal symbol and if yes, whether
+   we should nevertheless emit it in the symbol table.  */
+// XXX The second part should probably be controlled by an option which
+// isn't implemented yet
+// XXX Also, the format will change with the backend.
+#define asm_emit_symbol_p(name) (!startswith (name, ".L"))
+
+#endif	/* libasmP.h */
diff --git a/libasm/symbolhash.c b/libasm/symbolhash.c
new file mode 100644
index 0000000..57c9e76
--- /dev/null
+++ b/libasm/symbolhash.c
@@ -0,0 +1,54 @@
+/* Symbol hash table implementation.
+   Copyright (C) 2001, 2002, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <libasmP.h>
+#include <libebl.h>
+
+/* Definitions for the symbol hash table.  */
+#define TYPE AsmSym_t *
+#define NAME asm_symbol_tab
+#define ITERATE 1
+#define REVERSE 1
+#define COMPARE(a, b) \
+  strcmp (dwelf_strent_str ((a)->strent), dwelf_strent_str ((b)->strent))
+
+#define next_prime __libasm_next_prime
+extern size_t next_prime (size_t) attribute_hidden;
+
+#include "../lib/dynamicsizehash.c"
+
+#undef next_prime
+#define next_prime attribute_hidden __libasm_next_prime
+#include "../lib/next_prime.c"
diff --git a/libasm/symbolhash.h b/libasm/symbolhash.h
new file mode 100644
index 0000000..d05a40a
--- /dev/null
+++ b/libasm/symbolhash.h
@@ -0,0 +1,40 @@
+/* Copyright (C) 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef SYMBOLHASH_H
+#define SYMBOLHASH_H	1
+
+/* Definitions for the symbol hash table.  */
+#define TYPE AsmSym_t *
+#define NAME asm_symbol_tab
+#define ITERATE 1
+#define COMPARE(a, b) \
+  strcmp (dwelf_strent_str ((a)->strent), dwelf_strent_str ((b)->strent))
+#include <dynamicsizehash.h>
+
+#endif	/* symbolhash.h */
diff --git a/libcpu/ChangeLog b/libcpu/ChangeLog
new file mode 100644
index 0000000..d14cd23
--- /dev/null
+++ b/libcpu/ChangeLog
@@ -0,0 +1,551 @@
+2022-12-18  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* i386_mne.h: New file, extracted from i386_disasm.c.
+	* Makefile.am (noinst_HEADERS): Add i386_mne.h.
+	(i386_parse_CFLAGS): Removed.
+	* i386_disasm.c: Include i386_mne.h.
+	* i386_parse.y: Include i386_mne.h.
+	(instrtable_out): Use MNE_COUNT instead of NMNES.
+
+2022-12-18  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* i386_disasm.c (i386_disasm): Use __asm instead of asm.
+
+2022-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* bpf_disasm.c: Include common.h and libeblP.h.
+	* i386_disasm.c: Include libeblP.h.
+	* riscv_disasm.c: Likewise.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* i386_data.h: Define FCT_mod$64r_m as FCT_mod$r_m for i386.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* i386_disasm.c: Don't include endian.h.
+	* memory-access.h: Don't include byteswap.h and endian.h.
+	Do include system.h.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* memory-access.h: Use BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN.
+	* riscv_disasm.c: Likewise.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (GENDIS_ENV): New variable, depends on
+	USE_ADDRESS_SANITIZER.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+2020-12-16  Érico Nogueira  <ericonr@disroot.org>
+
+	* Makefile.am (i386_gendis_LDADD): Add obstack_LIBS.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* i386_lex.l (invalid_char): Replace gettext(...) with _(...).
+	* i386_parse.y (yyerror): Likewise.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* bpf_disasm.c (bswap_bpf_insn): Fix spelling typo in comment.
+	* i386_disasm.c (i386_disasm): Likewise.
+
+2020-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* i386_parse.y (new_bitfield): Call free newp on error.
+
+2020-04-16  Mark Wielaard  <mark@klomp.org>
+
+	* i386_disasm.c (i386_disasm): Replace assert with goto invalid_op
+	for bad prefix.
+
+2019-12-11  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am (i386_lex_CFLAGS): Add -Wno-implicit-fallthrough.
+
+2019-10-17  Mark Wielaard  <mark@klomp.org>
+
+	* i386_data.h (FCT_sel): Check for param_start + 2 >= end instead
+	of just >.
+	* i386_disasm.c (i386_disasm): Check param_start < end. Don't
+	assert, but assign INVALID to str. Make sure we get past any
+	unrecognized opcode.
+
+2019-09-07  Mark Wielaard  <mark@klomp.org>
+
+	* riscv_disasm.c (riscv_disasm): Use UINT64_C to make calculation
+	unsigned.
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Combine libcpu_{i386,x86_64,bpf}.a into libcpu.a.
+	Make libcpu.a non-PIC by default.
+	Add libcpu_pic.a.
+
+2018-11-04  Mark Wielaard  <mark@klomp.org>
+
+	* bpf_disasm.c (bpf_disasm): Recognize BPF_JLT, BPF_JLE, BPF_JSLT
+	and BPF_JSLE.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* i386_disasm.c (i386_disasm): Use FALLTHOUGH macro instead of
+	comment.
+
+2017-08-18  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* memory-access.h: Use attribute_packed.
+
+2017-02-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Use fpic_CFLAGS.
+
+2017-07-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am: Don't check HAVE_LINUX_BPF_H, just define libcpu_bpf.
+	* bpf_disasm.c: Include bpf.h instead of linux/bpf.h. Don't define
+	BPF_PSEUDO_MAP_FD.
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* Makefile.am: Add EXEEXT to gendis.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* i386_parse.y: Eliminate comparison_fn_t.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* i386_disasm.c (i386_disasm): Add fallthrough comment.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* i386_lex.l: Remove system.h include, add libeu.h include.
+	* i386_parse.y: Remove sys/param.h include, add libeu.h include.
+	* i386_disasm.c: Remove sys/param.h.
+
+2016-09-05  Mark Wielaard  <mjw@redhat.com>
+
+	* bpf_disasm.c: Define BPF_PSEUDO_MAP_FD if undefined.
+
+2016-08-10  Richard Henderson  <rth@redhat.com>
+
+	* bpf_disasm.c (bpf_disasm): Rearrange the printing of instructions
+	to use exactly the operands required.
+
+2016-06-28  Richard Henderson  <rth@redhat.com>
+
+	* Makefile.am (noinst_LIBRARIES): Add libcpu_bpf.a.
+	(libcpu_bpf_a_SOURCES, libcpu_bpf_a_CFLAGS): New.
+	* bpf_disasm.c: New file.
+	* i386_disasm.c (i386_disasm): Add ebl parameter.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (%_defs): Add AM_V_GEN and AM_V_at silencers.
+	($(srcdir)/%_dis.h): Ditto.
+	(%.mnemonics): Add AM_V_GEN silencer.
+
+2014-10-29  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* Makefile.am (AM_CFLAGS): Use -fPIC instead of -fpic to avoid
+	relocation overflows in some platforms.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (i386_gendis_LDADD): Remove libmudflap.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2012-10-10  Roland McGrath  <roland@hack.frob.com>
+
+	* Makefile.am (%_defs, $(srcdir)/%_dis.h): Redirect to temp file,
+	mv into place with separate command.
+
+2012-06-26  Roland McGrath  <roland@hack.frob.com>
+
+	* Makefile.am [!MAINTAINER_MODE] ($(srcdir)/%_dis.h): New rule.
+
+2012-02-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (CLEANFILES): Move %_dis.h to...
+	(MAINTAINERCLEANFILES): here.
+
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+	* i386_disasm.c (ADD_NSTRING): Define.
+	(i386_disasm): Print color codes in the appropriate places.
+
+2011-10-16  Roland McGrath  <roland@hack.frob.com>
+
+	* Makefile.am (libcpu_i386_a_SOURCES): Add i386_dis.h.
+	(libcpu_x86_64_a_SOURCES): Add x86_64_dis.h.
+	(i386_disasm.o, x86_64_disasm.o): Depend on those in $(srcdir).
+	(%_dis.h): Renamed target pattern to ...
+	($(srcdir)/%_dis.h): ... this.
+	(noinst_HEADERS, noinst_PROGRAMS): Put under [MAINTAINER_MODE].
+
+2010-08-16  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (%_defs): New pattern rule.
+	(%_dis.h, %.mnemonics): Define as pattern rules using %_defs input.
+	(CLEANFILES): Include all those files.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -fdollars-in-identifiers; it is not the
+	default on every machine.
+
+2009-01-23  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (i386_parse_CFLAGS): Use quotes around command
+	substitution that can produce leading whitespace.
+
+2009-01-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_parse.y (instrtable_out): Optimize match_data table by not
+	emitting 0xff masks for leading bytes.
+	* i386_disasm.c (i386_disasm): Adjust reader of match_data.
+
+	* i386_disasm.c (i386_disasm): Reset bufcnt when not matched.  We
+	don't expect snprintf to fail.
+
+2008-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Add dppd, dpps, insertps, movntdqa, mpsadbw, packusdw,
+	pblendvb, pblendw, pcmpeqq, pcmpestri, pcmpestrm, pcmpistri, pcmpistrm,
+	pcmpgtq, phminposuw, pinsrb, pinsrd, pmaxsb, pmaxsd, pmaxud, pmaxuw,
+	pminsb, pminsd, pminud, pminuw, pmovsxbw, pmovsxbd, pmovsxbq, pmovsxwd,
+	pmovsxwq, pmovsxdq, pmovzxbw, pmovzxbd, pmovzxbq, pmovzxwd, pmovzxwq,
+	pmovzxdq, pmuldq, pmulld, popcnt, ptest, roundss, roundps, roundpd,
+	and roundsd opcodes.
+
+	* i386_disasm.c (i386_disasm): Correct resizing of buffer.
+
+	* i386_parse.y (struct argstring): Add off element.
+	(off_op_str): New global variable.
+	(print_op_str): Print strings as concatenated strings.  Keep track
+	of index and length.  Update ->off element.
+	(print_op_str_idx): New function.
+	(instrtable_out): Mark op%d_fct as const.
+	Emit two tables for the strings: the string itself (op%d_str) and the
+	index table (op%d_str_idx).
+	* i386_disasm.c (i386_disasm): Adjust for new op%d_str definition.
+
+	* i386_disasm.c [X86_64] (i386_disasm): Handle rex prefix when
+	printing only prefix.
+
+	* i386_disasm.c (i386_disasm): Minor optimizations.
+
+	* i386_parse.y (instrtable_out): No need to emit index, the reader can
+	keep track.
+	* i386_disasm.c (i386_disasm): The index is not emitted anymore, no
+	need to skip it.
+
+	* i386_disasm.c (amd3dnow): Mark as const.
+
+	* defs/i386: Add blendvpd and blendvps opcodes.
+
+2008-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Add blendpd and blendps opcodes.
+
+2008-12-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Add entry for AMD 3DNOW.
+	* i386_disasm.c: Implement AMD 3DNOW disassembly.
+
+2008-12-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_disasm.c (i386_disasm): If instruction matches prefix,
+	undoing the prefix match finishes the instruction.
+
+2008-01-21  Roland McGrath  <roland@redhat.com>
+
+	* defs/i386: Fix typo in comment.
+	* i386_disasm.c (i386_disasm): Handle cltq, cqto.
+
+	* i386_parse.y: Add sanity check for NMNES macro value.
+	* Makefile.am (i386_parse.o): Fix target in dependency rule.
+	(i386_parse.h): New target with empty commands.
+	(i386_lex.o): Depend on it in place of i386_parse.c.
+
+2008-01-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Remove defs/x86_64.
+
+2008-01-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Add fixes for opcodes with register number in opcode,
+	64-bit immediate forms, nop with rex.B.
+	* i386_data.h [X86_64] (FCT_imm64$w): New function.
+	(FCT_oreg): New function.
+	(FCT_oreg$w): New function.
+	* i386_disasm.c (i386_disasm): Reinitialize fmt always before
+	starting the loop to process the string.  Handle 0x90 special for
+	x86-64.
+	* i386_parse.y (fillin_arg): Expand synonyms before concatening to
+	form the function name.
+
+2008-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_disasm.c (struct output_buffer): Remove symcb and symcbarg.
+	(i386_disasm): Remove appropriate initializers.
+	Use symcb to lookup symbol strings.
+
+	* i386_disasm.c (struct output_buffer): Add labelbuf, labelbufsize,
+	symaddr_use, and symaddr fields.
+	(i386_disasm): Remove labelbuf and labelbufsize variables.
+	Add back %e format.  Implement %a and %l formats.
+
+	* i386_data.h (general_mod$r_m): Set symaddr_use and symaddr for %rip
+	base addressing.
+
+	* i386_disasm.c (i386_disasm): Resize output buffer if necessary.
+	Optimize output_data initialization.  Free buffers before return.
+	(struct output_data): Remove op1str field.  Adjust code.
+	(i386_disasm): Store final NUL btye at end of functions.
+
+2008-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_data.h (FCT_crdb): New function.
+	(FCT_ccc): Use FCT_crdb.
+	(FCT_ddd): Likewise.
+
+	* defs/i386: Fix a few instructions with immediate arguments.
+
+	* i386_disasm.c: Rewrite interface to callback functions for operands
+	to take a single pointer to a structure.
+	* i386_data.h: Adjust all functions.
+
+2008-01-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Enable x86-64 again.
+	* defs/i386: Lots of changes for x86-64.
+	* i386_data.h: Add support for use in x86-64 disassembler.
+	* i386_disasm.c: Likewise.
+	* i386_parse.y: Likewise.
+	* defs/x86_64: Removed.
+
+2008-01-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Cleanups, remove masks which are not needed.
+	Add remaining Intel opcodes.
+	* i386_data.h (FCT_imm8): Check for input buffer overrun.
+	* i386_disasm.c (i386_disasm): Likewise.
+	* i386_parse.y: Remove suffixes which are not needed anymore.
+
+2008-01-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Add yet more SSE instructions.
+
+2008-01-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_disasm.c (i386_disasm): Extend matcher to allow tables to
+	contain instructions with prefixes.
+	* defs/i386: Use for many SSE operations.
+	* i386_data.h (FCT_mmxreg2): Removed.
+
+2008-01-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: More 0f prefix support.
+	* i386_data.h (FCT_mmxreg): Implement.
+	(FCT_mmxreg2): Implement.
+	(FCT_mmreg): Remove.
+	* i386_disasm.c (i386_disasm): More special instructions.
+	Fix tttn suffix for cmov.
+	* i386_parse.y: Simplify test for mod/r_m mode.
+
+2007-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Fix order or arguments for mov of control/debug registers.
+	* i386_data.h (FCT_ccc): Implement
+	(FCT_ddd): Implement
+
+2007-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Fix 0f groups 6 and 7.
+	* i386_data.c (FCT_mod$16r_m): Implement.
+	* i386_disasm.c (i386_disasm): Third parameter can also have string.
+
+2007-12-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Add lots of floating point ops.
+	* i386_data.h (FCT_fmod$fr_m): Removed.
+	(FCT_freg): Implement.
+	* i386_disasm.c (i386_disasm): Implement suffix_D.
+	* i386_parse.y: Emit suffix_D.
+
+	* defs/i386: Use rel instead of dispA.
+	Fix lcall, dec, div, idiv, imul, inc, jmp, ljmp, mul, neg, not, push,
+	test.
+
+	* i386_data.h (FCT_dispA): Removed.
+	(FCT_ds_xx): Add test for end of input buffer.
+	* i386_disasm.c (ABORT_ENTRY): Removed.
+	(i386_disasm): Fix handling of SIB.  Pass correct address value to
+	operand callbacks.
+
+	* Makefile.am (*.mnemonics): Filter out INVALID entry.
+	* defs/i386: Define imms8 and use in appropriate places.
+	Add INVALID entries for special opcodes with special mnemonics.
+	Fix int3.  Fix typo in shl.  Correct xlat.
+	* i386_data.h (FCT_ds_xx): New function.
+	(FCT_ds_si): Use it.
+	(FCT_ds_bx): New function.
+	(FCT_imms8): New function.
+	* i386_disasm.c (MNE_INVALID): Define.
+	(i386_disasm): Handle invalid opcodes in mnemonics printing, not
+	separately.  Fix address value passed to operand handlers.
+	* i386_parse.y (bx_reg): Define.
+	(instrtable_out): Handle INVALID entries differently, just use
+	MNE_INVALID value for .mnemonic.
+
+2007-12-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Fix shift and mov immediate instructions.
+	* i386_data.h (FCT_imm16): Implement.
+
+	* defs/i386: Use absval instead of abs of lcall and ljmp.
+	Add parameters for cmps.  Fix test and mov immediate.
+	* i386_data.h: Implement FCT_absval.
+	* i386_disasm.c: Handle data16 for suffix_w  and FCT_imm.
+
+	* defs/i386: Move entries with 0x9b prefix together.
+	* i386_disasm.c (i386_disasm): Fix recognizing insufficient bytes in
+	input.  Handle data16 with suffix_W.
+
+	* i386_data.h (FCT_*): Add end parameter to all functions.  Check
+	before using more bytes.
+	(FCT_sel): Implement.
+	* i386_disasm.c (i386_disasm): Better handle end of input buffer.
+	Specal opcode 0x99.
+
+	* Makefile.am: Use m4 to preprocess defs/* files.
+	* defs/i386: Adjust appropriately.
+	* i386_data.c (FCT_ax): Implement.
+	(FCT_ax$w): Use FCT_ax.
+	* i386_disasm.c (ADD_STRING): Use _len instead of len.
+	(i386_disasm): If no instruction can be matched because of lack of
+	input and prefixes have been matched, print prefixes.
+	Recognize abort entries.
+	Handle special cases.
+	* i386_gendis.c: Recognize - input file name.
+	* i386_lex.c: Recognize INVALID token.
+	* i386_parse.y: Handle INVALID token input.
+
+	* defs/i386: Fix mov, pop.
+	* i386_data.h (FCT_sreg3): Implement.
+
+2007-12-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Fix adc, add, cmp, or, sbb, sub, xchg, xor.
+	* i386_data.h (FCT_imms): New function.
+	(FCT_imm$s): Use FCT_imms for handling of signed values.
+	(FCT_imm8): Sign extend values.
+	* i386_disasm.c (i386_disasm): Implement suffix_w0.
+	* i386_parse.y: Emit suffix w0.
+
+	* i386_data.h (FCT_disp8): Add 0x prefix.
+	(FCT_ds_si): Implement.
+	* i386_disasm.c (i386_disasm): Increment addr for invalid prefixes.
+	Implement tttn suffix.
+	* i386_parse.y: Emit tttn suffix definition.
+
+2007-12-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_data.h (struct instr_enc): Use suffix field.
+	(FCT_dx): Fill in body.
+	(FCT_es_di): Likewise.
+	(FCT_imm$s): Sign-extended byte values.
+	* i386_disasm.c: Protect ADD_CHAR and ADD_STRING macros.  Adjust uses.
+	(i386_disasm): Handle suffix.
+	* i386_parse.y: Emit suffix information.
+	* defs/i386: Remove unnecessary suffixes.
+
+	* Makefile.am: Disable building x86-64 version for now.
+
+	* defs/i386: Fix and, bound, cmp, or, pop, sbb, sub, xor.
+	* i386_data.h: Pass pointer to prefix to functions.  If not prefixes
+	are consumed this means invalid input.
+	* i386_disasm.c: Fix prefix printing.  Adjust function calls for
+	parameter change.
+	* i386_parse.y: Recognize moda prefix.
+
+2007-12-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_data.h: Fix SIB handling.
+	* i386_disasm.c: Likewise.
+
+2007-12-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* defs/i386: Fix up 'and' opcode.
+
+2007-10-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add dependencies of the generated files on the source
+	files.
+	(i386_lex_CFLAGS): Add -Wno-sign-compare.
+
+	* defs/i386: A lot more data.
+	* defs/x86_64: Likewise.
+	* i386_data.h (struct instr_enc): Add off1_3, off2_3, and off3_3
+	fields.
+	(opfct_t): Add parameter for third operand.
+	(FCT_*): Likewise.
+	(data_prefix): New function.
+	(FCT_abs): Implement.
+	(FCT_ax): Renamed to FCT_ax$w amd implement.
+	(FCT_disp8): Implement.
+	(FCT_dispA): Implement.
+	(FCT_imm): Implement.
+	(FCT_imm$w): Implement.
+	(FCT_imm$s): Don't zero-pad numbers.
+	(FCT_imm8): Likewise.
+	(FCT_rel): Likewise.
+	(general_mod$r_m): New function.
+	(FCT_mod$r_m): Use it.
+	(FCT_mod$r_m$w): New function.
+	(FCT_mod$8r_m): New function.
+	(FCT_reg): Correctly handle 16-bit registers.
+	(FCT_reg$w): New function.
+	* i386_disasm.c (i386_disasm): Handle prefixes better.
+	Pass third parameter to operand functions.
+	* i386_parse.y (struct instruction): Add off3 field.
+	Handle third operand throughout.
+
+2007-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_disasm.c: New file.
+	* i386_data.h: New file.
+	* i386_gendis.c: New file.
+	* i386_lex.l: New file.
+	* i386_parse.y: New file.
+	* memory-access.h: New file.
+	* x86_64_disasm.c: New file.
+	* defs/i386: New file.
+	* defs/i386.doc: New file.
+	* defs/x86_64: New file.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Define, instead of adding things to DEFS.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/libcpu/Makefile.am b/libcpu/Makefile.am
new file mode 100644
index 0000000..4ba1be5
--- /dev/null
+++ b/libcpu/Makefile.am
@@ -0,0 +1,106 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2002-2012 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+	    -I$(srcdir)/../libdw -I$(srcdir)/../libasm
+if BUILD_STATIC
+AM_CFLAGS += $(fpic_CFLAGS)
+endif
+AM_CFLAGS += -fdollars-in-identifiers
+LEXCOMPILE = $(LEX) $(LFLAGS) $(AM_LFLAGS) -P$(<F:lex.l=)
+LEX_OUTPUT_ROOT = lex.$(<F:lex.l=)
+AM_YFLAGS = -p$(<F:parse.y=)
+
+noinst_LIBRARIES = libcpu.a libcpu_pic.a
+
+noinst_HEADERS = i386_dis.h i386_mne.h x86_64_dis.h
+
+libcpu_a_SOURCES = i386_disasm.c x86_64_disasm.c bpf_disasm.c riscv_disasm.c
+
+libcpu_pic_a_SOURCES =
+am_libcpu_pic_a_OBJECTS = $(libcpu_a_SOURCES:.c=.os)
+
+i386_gendis_SOURCES = i386_gendis.c i386_lex.l i386_parse.y
+
+i386_disasm.o: i386.mnemonics $(srcdir)/i386_dis.h
+x86_64_disasm.o: x86_64.mnemonics $(srcdir)/x86_64_dis.h
+
+%_defs: $(srcdir)/defs/i386
+	$(AM_V_GEN)m4 -D$* -DDISASSEMBLER $< > $@T
+	$(AM_V_at)mv -f $@T $@
+
+if MAINTAINER_MODE
+noinst_HEADERS += memory-access.h i386_parse.h i386_data.h
+
+noinst_PROGRAMS = i386_gendis$(EXEEXT)
+
+# i386_gendis doesn't clean up, ignore leaks.
+# It is just a build tool to generate source in maintainer mode.
+if USE_ADDRESS_SANITIZER
+GENDIS_ENV=env ASAN_OPTIONS=detect_leaks=0
+else
+GENDIS_ENV=
+endif
+
+$(srcdir)/%_dis.h: %_defs i386_gendis$(EXEEXT)
+	$(AM_V_GEN) $(GENDIS_ENV) ./i386_gendis$(EXEEXT) $< > $@T
+	$(AM_V_at)mv -f $@T $@
+
+else
+
+$(srcdir)/%_dis.h:
+	@echo '*** missing $@; configure with --enable-maintainer-mode'
+	@false
+
+endif
+
+%.mnemonics: %_defs
+	$(AM_V_GEN)sed '1,/^%%/d;/^#/d;/^[[:space:]]*$$/d;s/[^:]*:\([^[:space:]]*\).*/MNE(\1)/;s/{[^}]*}//g;/INVALID/d' \
+	  $< | sort -u > $@
+
+i386_lex_no_Werror = yes
+
+libeu = ../lib/libeu.a
+
+i386_lex_CFLAGS = -Wno-unused-label -Wno-unused-function -Wno-sign-compare \
+		  -Wno-implicit-fallthrough
+i386_parse.o: i386_parse.c i386.mnemonics
+i386_lex.o: i386_parse.h
+i386_gendis_LDADD = $(libeu) -lm $(obstack_LIBS)
+
+i386_parse.h: i386_parse.c ;
+
+bpf_disasm_CFLAGS = -Wno-format-nonliteral
+
+EXTRA_DIST = defs/i386
+
+MOSTLYCLEANFILES = $(am_libcpu_pic_a_OBJECTS)
+CLEANFILES += $(foreach P,i386 x86_64,$P_defs $P.mnemonics)
+MAINTAINERCLEANFILES = $(foreach P,i386 x86_64, $P_dis.h)
diff --git a/libcpu/bpf_disasm.c b/libcpu/bpf_disasm.c
new file mode 100644
index 0000000..dabd8a4
--- /dev/null
+++ b/libcpu/bpf_disasm.c
@@ -0,0 +1,504 @@
+/* Disassembler for BPF.
+   Copyright (C) 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include "bpf.h"
+
+#include "common.h"
+#include "libeblP.h"
+
+static const char class_string[8][8] = {
+  [BPF_LD]    = "ld",
+  [BPF_LDX]   = "ldx",
+  [BPF_ST]    = "st",
+  [BPF_STX]   = "stx",
+  [BPF_ALU]   = "alu",
+  [BPF_JMP]   = "jmp",
+  [BPF_RET]   = "6",		/* completely unused in ebpf */
+  [BPF_ALU64] = "alu64",
+};
+
+
+#define REG(N)		"r%" #N "$d"
+#define REGU(N)		"(u32)" REG(N)
+#define REGS(N)		"(s64)" REG(N)
+
+#define IMMS(N)		"%" #N "$d"
+#define IMMX(N)		"%" #N "$#x"
+
+#define OFF(N)		"%" #N "$+d"
+#define JMP(N)		"%" #N "$#x"
+
+#define A32(O, S)	REG(1) " = " REGU(1) " " #O " " S
+#define A64(O, S)	REG(1) " " #O "= " S
+#define J64(D, O, S)	"if " D " " #O " " S " goto " JMP(3)
+#define LOAD(T)		REG(1) " = *(" #T " *)(" REG(2) OFF(3) ")"
+#define STORE(T, S)	"*(" #T " *)(" REG(1) OFF(3) ") = " S
+#define XADD(T, S)	"lock *(" #T " *)(" REG(1) OFF(3) ") += " S
+#define LDSKB(T, S)	"r0 = *(" #T " *)skb[" S "]"
+
+static void
+bswap_bpf_insn (struct bpf_insn *p)
+{
+  /* Note that the dst_reg and src_reg fields are 4-bit bitfields.
+     That means these two nibbles are (typically) laid out in the
+     opposite order between big- and little-endian hosts.  This is
+     not required by any standard, but does happen to be true for
+     at least ppc, s390, arm and mips as big-endian hosts.  */
+  int t = p->dst_reg;
+  p->dst_reg = p->src_reg;
+  p->src_reg = t;
+
+  /* The other 2 and 4 byte fields are trivially converted.  */
+  CONVERT (p->off);
+  CONVERT (p->imm);
+}
+
+int
+bpf_disasm (Ebl *ebl, const uint8_t **startp, const uint8_t *end,
+	    GElf_Addr addr, const char *fmt __attribute__((unused)),
+	    DisasmOutputCB_t outcb,
+	    DisasmGetSymCB_t symcb __attribute__((unused)),
+	    void *outcbarg,
+	    void *symcbarg __attribute__((unused)))
+{
+  const bool need_bswap = MY_ELFDATA != ebl->data;
+  const uint8_t *start = *startp;
+  char buf[128];
+  int len, retval = 0;
+
+  while (start + sizeof(struct bpf_insn) <= end)
+    {
+      struct bpf_insn i;
+      unsigned code, class, jmp;
+      const char *code_fmt;
+
+      memcpy(&i, start, sizeof(struct bpf_insn));
+      if (need_bswap)
+	bswap_bpf_insn (&i);
+
+      start += sizeof(struct bpf_insn);
+      addr += sizeof(struct bpf_insn);
+      jmp = addr + i.off * sizeof(struct bpf_insn);
+
+      code = i.code;
+      switch (code)
+	{
+	case BPF_LD | BPF_IMM | BPF_DW:
+	  {
+	    struct bpf_insn i2;
+	    uint64_t imm64;
+
+	    if (start + sizeof(struct bpf_insn) > end)
+	      {
+		start -= sizeof(struct bpf_insn);
+		*startp = start;
+		goto done;
+	      }
+	    memcpy(&i2, start, sizeof(struct bpf_insn));
+	    if (need_bswap)
+	      bswap_bpf_insn (&i2);
+	    start += sizeof(struct bpf_insn);
+	    addr += sizeof(struct bpf_insn);
+
+	    imm64 = (uint32_t)i.imm | ((uint64_t)i2.imm << 32);
+	    switch (i.src_reg)
+	      {
+	      case 0:
+		code_fmt = REG(1) " = %2$#" PRIx64;
+		break;
+	      case BPF_PSEUDO_MAP_FD:
+		code_fmt = REG(1) " = map_fd(%2$#" PRIx64 ")";
+		break;
+	      default:
+		code_fmt = REG(1) " = ld_pseudo(%3$d, %2$#" PRIx64 ")";
+		break;
+	      }
+	    len = snprintf(buf, sizeof(buf), code_fmt,
+			   i.dst_reg, imm64, i.src_reg);
+	  }
+	  break;
+
+	case BPF_JMP | BPF_EXIT:
+	  len = snprintf(buf, sizeof(buf), "exit");
+	  break;
+	case BPF_JMP | BPF_JA:
+	  len = snprintf(buf, sizeof(buf), "goto " JMP(1), jmp);
+	  break;
+	case BPF_JMP | BPF_CALL:
+	  code_fmt = "call " IMMS(1);
+	  goto do_imm;
+
+	case BPF_ALU | BPF_END | BPF_TO_LE:
+	  /* The imm field contains {16,32,64}.  */
+	  code_fmt = REG(1) " = le" IMMS(2) "(" REG(1) ")";
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_END | BPF_TO_BE:
+	  code_fmt = REG(1) " = be" IMMS(2) "(" REG(1) ")";
+	  goto do_dst_imm;
+
+	case BPF_ALU | BPF_ADD | BPF_K:
+	  code_fmt = A32(+, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_SUB | BPF_K:
+	  code_fmt = A32(-, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_MUL | BPF_K:
+	  code_fmt = A32(*, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_DIV | BPF_K:
+	  code_fmt = A32(/, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_OR | BPF_K:
+	  code_fmt = A32(|, IMMX(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_AND | BPF_K:
+	  code_fmt = A32(&, IMMX(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_LSH | BPF_K:
+	  code_fmt = A32(<<, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_RSH | BPF_K:
+	  code_fmt = A32(>>, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_MOD | BPF_K:
+	  code_fmt = A32(%%, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_XOR | BPF_K:
+	  code_fmt = A32(^, IMMX(2));
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_MOV | BPF_K:
+	  code_fmt = REG(1) " = " IMMX(2);
+	  goto do_dst_imm;
+	case BPF_ALU | BPF_ARSH | BPF_K:
+	  code_fmt = REG(1) " = (u32)((s32)" REG(1) " >> " IMMS(2) ")";
+	  goto do_dst_imm;
+
+	case BPF_ALU | BPF_ADD | BPF_X:
+	  code_fmt = A32(+, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_SUB | BPF_X:
+	  code_fmt = A32(-, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_MUL | BPF_X:
+	  code_fmt = A32(*, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_DIV | BPF_X:
+	  code_fmt = A32(/, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_OR | BPF_X:
+	  code_fmt = A32(|, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_AND | BPF_X:
+	  code_fmt = A32(&, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_LSH | BPF_X:
+	  code_fmt = A32(<<, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_RSH | BPF_X:
+	  code_fmt = A32(>>, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_MOD | BPF_X:
+	  code_fmt = A32(%%, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_XOR | BPF_X:
+	  code_fmt = A32(^, REGU(2));
+	  goto do_dst_src;
+	case BPF_ALU | BPF_MOV | BPF_X:
+	  code_fmt = REG(1) " = " REGU(2);
+	  goto do_dst_src;
+	case BPF_ALU | BPF_ARSH | BPF_X:
+	  code_fmt = REG(1) " = (u32)((s32)" REG(1) " >> " REG(2) ")";
+	  goto do_dst_src;
+
+	case BPF_ALU64 | BPF_ADD | BPF_K:
+	  code_fmt = A64(+, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_SUB | BPF_K:
+	  code_fmt = A64(-, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_MUL | BPF_K:
+	  code_fmt = A64(*, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_DIV | BPF_K:
+	  code_fmt = A64(/, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_OR | BPF_K:
+	  code_fmt = A64(|, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_AND | BPF_K:
+	  code_fmt = A64(&, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_LSH | BPF_K:
+	  code_fmt = A64(<<, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_RSH | BPF_K:
+	  code_fmt = A64(>>, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_MOD | BPF_K:
+	  code_fmt = A64(%%, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_XOR | BPF_K:
+	  code_fmt = A64(^, IMMS(2));
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_MOV | BPF_K:
+	  code_fmt = REG(1) " = " IMMS(2);
+	  goto do_dst_imm;
+	case BPF_ALU64 | BPF_ARSH | BPF_K:
+	  code_fmt = REG(1) " = (s64)" REG(1) " >> " IMMS(2);
+	  goto do_dst_imm;
+
+	case BPF_ALU64 | BPF_ADD | BPF_X:
+	  code_fmt = A64(+, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_SUB | BPF_X:
+	  code_fmt = A64(-, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_MUL | BPF_X:
+	  code_fmt = A64(*, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_DIV | BPF_X:
+	  code_fmt = A64(/, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_OR | BPF_X:
+	  code_fmt = A64(|, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_AND | BPF_X:
+	  code_fmt = A64(&, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_LSH | BPF_X:
+	  code_fmt = A64(<<, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_RSH | BPF_X:
+	  code_fmt = A64(>>, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_MOD | BPF_X:
+	  code_fmt = A64(%%, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_XOR | BPF_X:
+	  code_fmt = A64(^, REG(2));
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_MOV | BPF_X:
+	  code_fmt = REG(1) " = " REG(2);
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_ARSH | BPF_X:
+	  code_fmt = REG(1) " = (s64)" REG(1) " >> " REG(2);
+	  goto do_dst_src;
+
+	case BPF_ALU | BPF_NEG:
+	  code_fmt = REG(1) " = (u32)-" REG(1);
+	  goto do_dst_src;
+	case BPF_ALU64 | BPF_NEG:
+	  code_fmt = REG(1) " = -" REG(1);
+	  goto do_dst_src;
+
+	case BPF_JMP | BPF_JEQ | BPF_K:
+	  code_fmt = J64(REG(1), ==, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JGT | BPF_K:
+	  code_fmt = J64(REG(1), >, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JGE | BPF_K:
+	  code_fmt = J64(REG(1), >=, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JSET | BPF_K:
+	  code_fmt = J64(REG(1), &, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JNE | BPF_K:
+	  code_fmt = J64(REG(1), !=, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JSGT | BPF_K:
+	  code_fmt = J64(REGS(1), >, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JSGE | BPF_K:
+	  code_fmt = J64(REGS(1), >=, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JLT | BPF_K:
+	  code_fmt = J64(REG(1), <, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JLE | BPF_K:
+	  code_fmt = J64(REG(1), <=, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JSLT | BPF_K:
+	  code_fmt = J64(REGS(1), <, IMMS(2));
+	  goto do_dst_imm_jmp;
+	case BPF_JMP | BPF_JSLE | BPF_K:
+	  code_fmt = J64(REGS(1), <=, IMMS(2));
+	  goto do_dst_imm_jmp;
+
+	case BPF_JMP | BPF_JEQ | BPF_X:
+	  code_fmt = J64(REG(1), ==, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JGT | BPF_X:
+	  code_fmt = J64(REG(1), >, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JGE | BPF_X:
+	  code_fmt = J64(REG(1), >=, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JSET | BPF_X:
+	  code_fmt = J64(REG(1), &, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JNE | BPF_X:
+	  code_fmt = J64(REG(1), !=, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JSGT | BPF_X:
+	  code_fmt = J64(REGS(1), >, REGS(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JSGE | BPF_X:
+	  code_fmt = J64(REGS(1), >=, REGS(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JLT | BPF_X:
+	  code_fmt = J64(REG(1), <, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JLE | BPF_X:
+	  code_fmt = J64(REG(1), <=, REG(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JSLT | BPF_X:
+	  code_fmt = J64(REGS(1), <, REGS(2));
+	  goto do_dst_src_jmp;
+	case BPF_JMP | BPF_JSLE | BPF_X:
+	  code_fmt = J64(REGS(1), <=, REGS(2));
+	  goto do_dst_src_jmp;
+
+	case BPF_LDX | BPF_MEM | BPF_B:
+	  code_fmt = LOAD(u8);
+	  goto do_dst_src_off;
+	case BPF_LDX | BPF_MEM | BPF_H:
+	  code_fmt = LOAD(u16);
+	  goto do_dst_src_off;
+	case BPF_LDX | BPF_MEM | BPF_W:
+	  code_fmt = LOAD(u32);
+	  goto do_dst_src_off;
+	case BPF_LDX | BPF_MEM | BPF_DW:
+	  code_fmt = LOAD(u64);
+	  goto do_dst_src_off;
+
+	case BPF_STX | BPF_MEM | BPF_B:
+	  code_fmt = STORE(u8, REG(2));
+	  goto do_dst_src_off;
+	case BPF_STX | BPF_MEM | BPF_H:
+	  code_fmt = STORE(u16, REG(2));
+	  goto do_dst_src_off;
+	case BPF_STX | BPF_MEM | BPF_W:
+	  code_fmt = STORE(u32, REG(2));
+	  goto do_dst_src_off;
+	case BPF_STX | BPF_MEM | BPF_DW:
+	  code_fmt = STORE(u64, REG(2));
+	  goto do_dst_src_off;
+
+	case BPF_STX | BPF_XADD | BPF_W:
+	  code_fmt = XADD(u32, REG(2));
+	  goto do_dst_src_off;
+	case BPF_STX | BPF_XADD | BPF_DW:
+	  code_fmt = XADD(u64, REG(2));
+	  goto do_dst_src_off;
+
+	case BPF_ST | BPF_MEM | BPF_B:
+	  code_fmt = STORE(u8, IMMS(2));
+	  goto do_dst_imm_off;
+	case BPF_ST | BPF_MEM | BPF_H:
+	  code_fmt = STORE(u16, IMMS(2));
+	  goto do_dst_imm_off;
+	case BPF_ST | BPF_MEM | BPF_W:
+	  code_fmt = STORE(u32, IMMS(2));
+	  goto do_dst_imm_off;
+	case BPF_ST | BPF_MEM | BPF_DW:
+	  code_fmt = STORE(u64, IMMS(2));
+	  goto do_dst_imm_off;
+
+	case BPF_LD | BPF_ABS | BPF_B:
+	  code_fmt = LDSKB(u8, IMMS(1));
+	  goto do_imm;
+	case BPF_LD | BPF_ABS | BPF_H:
+	  code_fmt = LDSKB(u16, IMMS(1));
+	  goto do_imm;
+	case BPF_LD | BPF_ABS | BPF_W:
+	  code_fmt = LDSKB(u32, IMMS(1));
+	  goto do_imm;
+
+	case BPF_LD | BPF_IND | BPF_B:
+	  code_fmt = LDSKB(u8, REG(1) "+" IMMS(2));
+	  goto do_src_imm;
+	case BPF_LD | BPF_IND | BPF_H:
+	  code_fmt = LDSKB(u16, REG(1) "+" IMMS(2));
+	  goto do_src_imm;
+	case BPF_LD | BPF_IND | BPF_W:
+	  code_fmt = LDSKB(u32, REG(1) "+" IMMS(2));
+	  goto do_src_imm;
+
+	do_imm:
+	  len = snprintf(buf, sizeof(buf), code_fmt, i.imm);
+	  break;
+	do_dst_imm:
+	  len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm);
+	  break;
+	do_src_imm:
+	  len = snprintf(buf, sizeof(buf), code_fmt, i.src_reg, i.imm);
+	  break;
+	do_dst_src:
+	  len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.src_reg);
+	  break;
+	do_dst_imm_jmp:
+	  len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm, jmp);
+	  break;
+	do_dst_src_jmp:
+	  len = snprintf(buf, sizeof(buf), code_fmt,
+			 i.dst_reg, i.src_reg, jmp);
+	  break;
+	do_dst_imm_off:
+	  len = snprintf(buf, sizeof(buf), code_fmt, i.dst_reg, i.imm, i.off);
+	  break;
+	do_dst_src_off:
+	  len = snprintf(buf, sizeof(buf), code_fmt,
+			 i.dst_reg, i.src_reg, i.off);
+	  break;
+
+	default:
+	  class = BPF_CLASS(code);
+	  len = snprintf(buf, sizeof(buf), "invalid class %s",
+			 class_string[class]);
+	  break;
+        }
+
+      *startp = start;
+      retval = outcb (buf, len, outcbarg);
+      if (retval != 0)
+	goto done;
+    }
+
+ done:
+  return retval;
+}
diff --git a/libcpu/defs/i386 b/libcpu/defs/i386
new file mode 100644
index 0000000..e0db28d
--- /dev/null
+++ b/libcpu/defs/i386
@@ -0,0 +1,970 @@
+%mask {s}	1
+%mask {w}	1
+%mask {w1}	1
+%mask {W1}	1
+%mask {W2}	1
+dnl floating point reg suffix
+%mask {D}	1
+%mask {imm8}	8
+%mask {imms8}	8
+%mask {imm16}	16
+%mask {reg}	3
+%mask {oreg}	3
+%mask {reg16}	3
+%mask {reg64}	3
+%mask {tttn}	4
+%mask {mod}	2
+%mask {moda}	2
+%mask {MOD}	2
+%mask {r_m}	3
+dnl like {r_m} but referencing byte register
+%mask {8r_m}	3
+dnl like {r_m} but referencing 16-bit register
+%mask {16r_m}	3
+dnl like {r_m} but referencing 32- or 64-bit register
+%mask {64r_m}	3
+%mask {disp8}	8
+dnl imm really is 8/16/32 bit depending on the situation.
+%mask {imm}	8
+%mask {imm64}	8
+%mask {imms}	8
+%mask {rel}	32
+%mask {abs}	32
+%mask {absval}	32
+%mask {sel}	16
+%mask {imm32}	32
+%mask {ccc}	3
+%mask {ddd}	3
+%mask {sreg3}	3
+%mask {sreg2}	2
+%mask {mmxreg}	3
+%mask {R_M}	3
+%mask {Mod}	2
+%mask {xmmreg}	3
+%mask {R_m}	3
+%mask {xmmreg1} 3
+%mask {xmmreg2} 3
+%mask {mmxreg1} 3
+%mask {mmxreg2} 3
+%mask {predps}	8
+%mask {freg}	3
+%mask {fmod}	2
+%mask {fr_m}	3
+%prefix {R}
+%prefix {RE}
+%suffix {W}
+%suffix {w0}
+%synonym {xmmreg1} {xmmreg}
+%synonym {xmmreg2} {xmmreg}
+%synonym {mmxreg1} {mmxreg}
+%synonym {mmxreg2} {mmxreg}
+ifdef(`i386',
+`%synonym {oreg} {reg}
+%synonym {imm64} {imm}
+')dnl
+
+%%
+ifdef(`i386',
+`00110111:aaa
+11010101,00001010:aad
+11010100,00001010:aam
+00111111:aas
+')dnl
+0001010{w},{imm}:adc {imm}{w},{ax}{w}
+1000000{w},{mod}010{r_m},{imm}:adc{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}010{r_m},{imms8}:adc{w} {imms8},{mod}{r_m}
+0001000{w},{mod}{reg}{r_m}:adc {reg}{w},{mod}{r_m}{w}
+0001001{w},{mod}{reg}{r_m}:adc {mod}{r_m}{w},{reg}{w}
+0000010{w},{imm}:add {imm}{w},{ax}{w}
+1000000{w},{mod}000{r_m},{imm}:add{w} {imm}{w},{mod}{r_m}{w}
+10000011,{mod}000{r_m},{imms8}:add{w} {imms8},{mod}{r_m}
+0000000{w},{mod}{reg}{r_m}:add {reg}{w},{mod}{r_m}{w}
+0000001{w},{mod}{reg}{r_m}:add {mod}{r_m}{w},{reg}{w}
+01100110,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubpd {Mod}{R_m},{xmmreg}
+11110010,00001111,11010000,{Mod}{xmmreg}{R_m}:addsubps {Mod}{R_m},{xmmreg}
+0010010{w},{imm}:and {imm}{w},{ax}{w}
+1000000{w},{mod}100{r_m},{imm}:and{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}100{r_m},{imms8}:and{w} {imms8},{mod}{r_m}
+0010000{w},{mod}{reg}{r_m}:and {reg}{w},{mod}{r_m}{w}
+0010001{w},{mod}{reg}{r_m}:and {mod}{r_m}{w},{reg}{w}
+01100110,00001111,01010100,{Mod}{xmmreg}{R_m}:andpd {Mod}{R_m},{xmmreg}
+00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010101,{Mod}{xmmreg}{R_m}:andnpd {Mod}{R_m},{xmmreg}
+00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg}
+ifdef(`i386',
+`01100011,{mod}{reg16}{r_m}:arpl {reg16},{mod}{r_m}
+01100010,{moda}{reg}{r_m}:bound {reg},{moda}{r_m}
+',
+`01100011,{mod}{reg64}{r_m}:movslq {mod}{r_m},{reg64}
+')dnl
+00001111,10111100,{mod}{reg}{r_m}:bsf {mod}{r_m},{reg}
+00001111,10111101,{mod}{reg}{r_m}:bsr {mod}{r_m},{reg}
+00001111,11001{reg}:bswap {reg}
+00001111,10100011,{mod}{reg}{r_m}:bt {reg},{mod}{r_m}
+00001111,10111010,{mod}100{r_m},{imm8}:bt{w} {imm8},{mod}{r_m}
+00001111,10111011,{mod}{reg}{r_m}:btc {reg},{mod}{r_m}
+00001111,10111010,{mod}111{r_m},{imm8}:btc{w} {imm8},{mod}{r_m}
+00001111,10110011,{mod}{reg}{r_m}:btr {reg},{mod}{r_m}
+00001111,10111010,{mod}110{r_m},{imm8}:btr{w} {imm8},{mod}{r_m}
+00001111,10101011,{mod}{reg}{r_m}:bts {reg},{mod}{r_m}
+00001111,10111010,{mod}101{r_m},{imm8}:bts{w} {imm8},{mod}{r_m}
+11101000,{rel}:call{W} {rel}
+11111111,{mod}010{64r_m}:call{W} *{mod}{64r_m}
+ifdef(`i386',
+`10011010,{absval},{sel}:lcall {sel},{absval}
+')dnl
+11111111,{mod}011{64r_m}:lcall{W} *{mod}{64r_m}
+# SPECIAL 10011000:[{rex.w}?cltq:{dpfx}?cbtw:cwtl]
+10011000:INVALID
+# SPECIAL 10011001:[{rex.w}?cqto:{dpfx}?cltd:cwtd]
+10011001:INVALID
+11111000:clc
+11111100:cld
+11111010:cli
+00001111,00000101:syscall
+00001111,00000110:clts
+00001111,00000111:sysret
+00001111,00110100:sysenter
+00001111,00110101:sysexit
+11110101:cmc
+00001111,0100{tttn},{mod}{reg}{r_m}:cmov{tttn} {mod}{r_m},{reg}
+0011110{w},{imm}:cmp {imm}{w},{ax}{w}
+1000000{w},{mod}111{r_m},{imm}:cmp{w} {imm}{w},{mod}{r_m}{w}
+10000011,{mod}111{r_m},{imms8}:cmp{w} {imms8},{mod}{r_m}
+0011100{w},{mod}{reg}{r_m}:cmp {reg}{w},{mod}{r_m}{w}
+0011101{w},{mod}{reg}{r_m}:cmp {mod}{r_m}{w},{reg}{w}
+ifdef(`ASSEMBLER',
+`11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpsd {imm8},{Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpss {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmppd {imm8},{Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:cmpps {imm8},{Mod}{R_m},{xmmreg}
+',
+`11110010,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+01100110,00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},{imm8}:INVALID {Mod}{R_m},{xmmreg}
+')dnl
+1010011{w}:{RE}cmps{w} {es_di},{ds_si}
+00001111,1011000{w},{mod}{reg}{r_m}:cmpxchg {reg}{w},{mod}{r_m}{w}
+ifdef(`i386',
+`00001111,11000111,{mod}001{r_m}:cmpxchg8b {mod}{r_m}
+',
+`# SPECIAL 00001111,11000111,{mod}001{r_m}:[{rex.w}?cmpxchg16b:cmpxchg8b] {reg},{mod}{r_m}
+00001111,11000111,{mod}001{r_m}:INVALID {mod}{r_m}
+')dnl
+00001111,10100010:cpuid
+11110011,00001111,11100110,{Mod}{xmmreg}{R_m}:cvtdq2pd {Mod}{R_m},{xmmreg}
+11110010,00001111,11100110,{Mod}{xmmreg}{R_m}:cvtpd2dq {Mod}{R_m},{xmmreg}
+01100110,00001111,11100110,{Mod}{xmmreg}{R_m}:cvttpd2dq {Mod}{R_m},{xmmreg}
+ifdef(`i386',
+`00100111:daa
+00101111:das
+')dnl
+1111111{w},{mod}001{r_m}:dec{w} {mod}{r_m}{w}
+ifdef(`i386',
+`01001{reg}:dec {reg}
+')dnl
+1111011{w},{mod}110{r_m}:div{w} {mod}{r_m}{w}
+00001111,01110111:emms
+11001000,{imm16},{imm8}:enter{W} {imm16},{imm8}
+11011001,11010000:fnop
+11011001,11100000:fchs
+11011001,11100001:fabs
+11011001,11100100:ftst
+11011001,11100101:fxam
+11011001,11101000:fld1
+11011001,11101001:fldl2t
+11011001,11101010:fldl2e
+11011001,11101011:fldpi
+11011001,11101100:fldlg2
+11011001,11101101:fldln2
+11011001,11101110:fldz
+11011001,11110000:f2xm1
+11011001,11110001:fyl2x
+11011001,11110010:fptan
+11011001,11110011:fpatan
+11011001,11110100:fxtract
+11011001,11110101:fprem1
+11011001,11110110:fdecstp
+11011001,11110111:fincstp
+11011001,11111000:fprem
+11011001,11111001:fyl2xp1
+11011001,11111010:fsqrt
+11011001,11111011:fsincos
+11011001,11111100:frndint
+11011001,11111101:fscale
+11011001,11111110:fsin
+11011001,11111111:fcos
+# ORDER
+11011000,11000{freg}:fadd {freg},%st
+11011100,11000{freg}:fadd %st,{freg}
+11011{D}00,{mod}000{r_m}:fadd{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011000,11001{freg}:fmul {freg},%st
+11011100,11001{freg}:fmul %st,{freg}
+11011{D}00,{mod}001{r_m}:fmul{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011000,11100{freg}:fsub {freg},%st
+11011100,11100{freg}:fsub %st,{freg}
+11011{D}00,{mod}100{r_m}:fsub{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011000,11101{freg}:fsubr {freg},%st
+11011100,11101{freg}:fsubr %st,{freg}
+11011{D}00,{mod}101{r_m}:fsubr{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011101,11010{freg}:fst {freg}
+11011{D}01,{mod}010{r_m}:fst{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011101,11011{freg}:fstp {freg}
+11011{D}01,{mod}011{r_m}:fstp{D} {mod}{r_m}
+# ORDER END
+11011001,{mod}100{r_m}:fldenv {mod}{r_m}
+11011001,{mod}101{r_m}:fldcw {mod}{r_m}
+11011001,{mod}110{r_m}:fnstenv {mod}{r_m}
+11011001,{mod}111{r_m}:fnstcw {mod}{r_m}
+11011001,11001{freg}:fxch {freg}
+# ORDER
+11011110,11000{freg}:faddp %st,{freg}
+ifdef(`ASSEMBLER',
+`11011110,11000001:faddp
+')dnl
+# ORDER
+11011010,11000{freg}:fcmovb {freg},%st
+11011{w1}10,{mod}000{r_m}:fiadd{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011010,11001{freg}:fcmove {freg},%st
+11011110,11001{freg}:fmulp %st,{freg}
+11011{w1}10,{mod}001{r_m}:fimul{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011110,11100{freg}:fsubp %st,{freg}
+11011{w1}10,{mod}100{r_m}:fisub{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011110,11101{freg}:fsubrp %st,{freg}
+11011{w1}10,{mod}101{r_m}:fisubr{w1} {mod}{r_m}
+# ORDER END
+# ORDER
+11011111,11100000:fnstsw %ax
+11011111,{mod}100{r_m}:fbld {mod}{r_m}
+# ORDER END
+# ORDER
+11011111,11110{freg}:fcomip {freg},%st
+11011111,{mod}110{r_m}:fbstp {mod}{r_m}
+# ORDER END
+11011001,11100000:fchs
+# ORDER
+10011011,11011011,11100010:fclex
+10011011,11011011,11100011:finit
+10011011:fwait
+# END ORDER
+11011011,11100010:fnclex
+11011010,11000{freg}:fcmovb {freg},%st
+11011010,11001{freg}:fcmove {freg},%st
+11011010,11010{freg}:fcmovbe {freg},%st
+11011010,11011{freg}:fcmovu {freg},%st
+11011011,11000{freg}:fcmovnb {freg},%st
+11011011,11001{freg}:fcmovne {freg},%st
+11011011,11010{freg}:fcmovnbe {freg},%st
+11011011,11011{freg}:fcmovnu {freg},%st
+# ORDER
+11011000,11010{freg}:fcom {freg}
+ifdef(`ASSEMBLER',
+`11011000,11010001:fcom
+')dnl
+11011{D}00,{mod}010{r_m}:fcom{D} {mod}{r_m}
+# END ORDER
+# ORDER
+11011000,11011{freg}:fcomp {freg}
+ifdef(`ASSEMBLER',
+`11011000,11011001:fcomp
+')dnl
+11011{D}00,{mod}011{r_m}:fcomp{D} {mod}{r_m}
+# END ORDER
+11011110,11011001:fcompp
+11011011,11110{freg}:fcomi {freg},%st
+11011111,11110{freg}:fcomip {freg},%st
+11011011,11101{freg}:fucomi {freg},%st
+11011111,11101{freg}:fucomip {freg},%st
+11011001,11111111:fcos
+11011001,11110110:fdecstp
+# ORDER
+11011000,11110{freg}:fdiv {freg},%st
+11011100,11110{freg}:fdiv %st,{freg}
+11011{D}00,{mod}110{r_m}:fdiv{D} {mod}{r_m}
+# END ORDER
+11011010,{mod}110{r_m}:fidivl {mod}{r_m}
+# ORDER
+11011110,11110{freg}:fdivp %st,{freg}
+11011110,{mod}110{r_m}:fidiv {mod}{r_m}
+# END ORDER
+11011110,11111{freg}:fdivrp %st,{freg}
+ifdef(`ASSEMBLER',
+`11011110,11111001:fdivp
+')dnl
+# ORDER
+11011000,11111{freg}:fdivr {freg},%st
+11011100,11111{freg}:fdivr %st,{freg}
+11011{D}00,{mod}111{r_m}:fdivr{D} {mod}{r_m}
+# END ORDER
+11011010,{mod}111{r_m}:fidivrl {mod}{r_m}
+11011110,{mod}111{r_m}:fidivr {mod}{r_m}
+11011110,11110{freg}:fdivrp %st,{freg}
+ifdef(`ASSEMBLER',
+`11011110,11110001:fdivrp
+')dnl
+11011101,11000{freg}:ffree {freg}
+11011010,11010{freg}:fcmovbe {freg}
+11011{w1}10,{mod}010{r_m}:ficom{w1} {mod}{r_m}
+11011010,11011{freg}:fcmovu {freg}
+11011{w1}10,{mod}011{r_m}:ficomp{w1} {mod}{r_m}
+11011111,{mod}000{r_m}:fild {mod}{r_m}
+11011011,{mod}000{r_m}:fildl {mod}{r_m}
+11011111,{mod}101{r_m}:fildll {mod}{r_m}
+11011001,11110111:fincstp
+11011011,11100011:fninit
+11011{w1}11,{mod}010{r_m}:fist{w1} {mod}{r_m}
+11011{w1}11,{mod}011{r_m}:fistp{w1} {mod}{r_m}
+11011111,{mod}111{r_m}:fistpll {mod}{r_m}
+11011{w1}11,{mod}001{r_m}:fisttp{w1} {mod}{r_m}
+11011101,{mod}001{r_m}:fisttpll {mod}{r_m}
+11011011,{mod}101{r_m}:fldt {mod}{r_m}
+11011011,{mod}111{r_m}:fstpt {mod}{r_m}
+# ORDER
+11011001,11000{freg}:fld {freg}
+11011{D}01,{mod}000{r_m}:fld{D} {mod}{r_m}
+# ORDER END
+# ORDER
+11011101,11100{freg}:fucom {freg}
+11011101,{mod}100{r_m}:frstor {mod}{r_m}
+# ORDER END
+11011101,11101{freg}:fucomp {freg}
+11011101,{mod}110{r_m}:fnsave {mod}{r_m}
+11011101,{mod}111{r_m}:fnstsw {mod}{r_m}
+#
+#
+#
+11110100:hlt
+1111011{w},{mod}111{r_m}:idiv{w} {mod}{r_m}{w}
+1111011{w},{mod}101{r_m}:imul{w} {mod}{r_m}{w}
+00001111,10101111,{mod}{reg}{r_m}:imul {mod}{r_m},{reg}
+011010{s}1,{mod}{reg}{r_m},{imm}:imul {imm}{s},{mod}{r_m},{reg}
+1110010{w},{imm8}:in {imm8},{ax}{w}
+1110110{w}:in {dx},{ax}{w}
+1111111{w},{mod}000{r_m}:inc{w} {mod}{r_m}{w}
+ifdef(`i386',
+`01000{reg}:inc {reg}
+')dnl
+0110110{w}:{R}ins{w} {dx},{es_di}
+11001101,{imm8}:int {imm8}
+11001100:int3
+ifdef(`i386',
+`11001110:into
+')dnl
+00001111,00001000:invd
+# ORDER
+00001111,00000001,11111000:swapgs
+00001111,00000001,{mod}111{r_m}:invlpg {mod}{r_m}
+# ORDER END
+11001111:iret{W1}
+0111{tttn},{disp8}:j{tttn} {disp8}
+00001111,1000{tttn},{rel}:j{tttn} {rel}
+00001111,1001{tttn},{mod}000{8r_m}:set{tttn} {mod}{8r_m}
+# SPECIAL 11100011,{disp8}:[{dpfx}?jcxz:jecxz] {disp8}
+11100011,{disp8}:INVALID {disp8}
+11101011,{disp8}:jmp {disp8}
+11101001,{rel}:jmp{W} {rel}
+11111111,{mod}100{64r_m}:jmp{W} *{mod}{64r_m}
+11101010,{absval},{sel}:ljmp {sel},{absval}
+11111111,{mod}101{64r_m}:ljmp{W} *{mod}{64r_m}
+10011111:lahf
+00001111,00000010,{mod}{reg}{16r_m}:lar {mod}{16r_m},{reg}
+ifdef(`i386',
+`11000101,{mod}{reg}{r_m}:lds {mod}{r_m},{reg}
+')dnl
+10001101,{mod}{reg}{r_m}:lea {mod}{r_m},{reg}
+11001001:leave{W}
+ifdef(`i386',
+`11000100,{mod}{reg}{r_m}:les {mod}{r_m},{reg}
+')dnl
+00001111,10110100,{mod}{reg}{r_m}:lfs {mod}{r_m},{reg}
+00001111,10110101,{mod}{reg}{r_m}:lgs {mod}{r_m},{reg}
+ifdef(`i386',
+`00001111,00000001,{mod}010{r_m}:lgdt{w0} {mod}{r_m}
+00001111,00000001,{mod}011{r_m}:lidt{w0} {mod}{r_m}
+',
+`00001111,00000001,{mod}010{r_m}:lgdt {mod}{r_m}
+00001111,00000001,{mod}011{r_m}:lidt {mod}{r_m}
+')dnl
+00001111,00000000,{mod}010{16r_m}:lldt {mod}{16r_m}
+00001111,00000001,{mod}110{16r_m}:lmsw {mod}{16r_m}
+11110000:lock
+1010110{w}:{R}lods {ds_si},{ax}{w}
+11100010,{disp8}:loop {disp8}
+11100001,{disp8}:loope {disp8}
+11100000,{disp8}:loopne {disp8}
+00001111,00000011,{mod}{reg}{16r_m}:lsl {mod}{16r_m},{reg}
+00001111,10110010,{mod}{reg}{r_m}:lss {mod}{r_m},{reg}
+00001111,00000000,{mod}011{16r_m}:ltr {mod}{16r_m}
+1000100{w},{mod}{reg}{r_m}:mov {reg}{w},{mod}{r_m}{w}
+1000101{w},{mod}{reg}{r_m}:mov {mod}{r_m}{w},{reg}{w}
+1100011{w},{mod}000{r_m},{imm}:mov{w} {imm}{w},{mod}{r_m}{w}
+1011{w}{oreg},{imm64}:mov {imm64}{w},{oreg}{w}
+1010000{w},{abs}:mov {abs},{ax}{w}
+1010001{w},{abs}:mov {ax}{w},{abs}
+00001111,00100000,11{ccc}{reg64}:mov {ccc},{reg64}
+00001111,00100010,11{ccc}{reg64}:mov {reg64},{ccc}
+00001111,00100001,11{ddd}{reg64}:mov {ddd},{reg64}
+00001111,00100011,11{ddd}{reg64}:mov {reg64},{ddd}
+10001100,{mod}{sreg3}{r_m}:mov {sreg3},{mod}{r_m}
+10001110,{mod}{sreg3}{r_m}:mov {mod}{r_m},{sreg3}
+1010010{w}:{R}movs{w} {ds_si},{es_di}
+00001111,10111110,{mod}{reg}{8r_m}:movsbl {mod}{8r_m},{reg}
+00001111,10111111,{mod}{reg}{16r_m}:movswl {mod}{16r_m},{reg}
+00001111,10110110,{mod}{reg}{8r_m}:movzbl {mod}{8r_m},{reg}
+00001111,10110111,{mod}{reg}{16r_m}:movzwl {mod}{16r_m},{reg}
+1111011{w},{mod}100{r_m}:mul{w} {mod}{r_m}{w}
+1111011{w},{mod}011{r_m}:neg{w} {mod}{r_m}{w}
+11110011,10010000:pause
+ifdef(`i386',
+`10010000:nop
+',
+`10010000:INVALID
+')dnl
+# ORDER before out
+11110011,00001111,10111000,{mod}{reg}{r_m}:popcnt {mod}{r_m},{reg}
+# END ORDER
+1111011{w},{mod}010{r_m}:not{w} {mod}{r_m}{w}
+0000100{w},{mod}{reg}{r_m}:or {reg}{w},{mod}{r_m}{w}
+0000101{w},{mod}{reg}{r_m}:or {mod}{r_m}{w},{reg}{w}
+1000000{w},{mod}001{r_m},{imm}:or{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}001{r_m},{imms8}:or{w} {imms8},{mod}{r_m}{w}
+0000110{w},{imm}:or {imm}{w},{ax}{w}
+1110011{w},{imm8}:out {ax}{w},{imm8}
+1110111{w}:out {ax}{w},{dx}
+0110111{w}:{R}outs{w} {ds_si},{dx}
+ifdef(`i386',
+`10001111,{mod}000{r_m}:pop{w} {mod}{r_m}
+',
+# XXX This is not the cleanest way...
+`10001111,11000{reg64}:pop {reg64}
+10001111,{mod}000{r_m}:pop{W} {mod}{r_m}
+')dnl
+00001111,10{sreg3}001:pop{W} {sreg3}
+10011101:popf{W}
+# XXX This is not the cleanest way...
+ifdef(`i386',
+`11111111,{mod}110{r_m}:push{w} {mod}{r_m}
+',
+`11111111,11110{reg64}:push {reg64}
+11111111,{mod}110{r_m}:pushq {mod}{r_m}
+')dnl
+ifdef(`i386',
+`01010{reg}:push {reg}
+01011{reg}:pop {reg}
+',
+`01010{reg64}:push {reg64}
+01011{reg64}:pop {reg64}
+')dnl
+011010{s}0,{imm}:push{W} {imm}{s}
+000{sreg2}110:push {sreg2}
+00001111,10{sreg3}000:push{W} {sreg3}
+ifdef(`i386',
+`01100000:pusha{W}
+01100001:popa{W}
+')dnl
+10011100:pushf{W}
+1101000{w},{mod}010{r_m}:rcl{w} {mod}{r_m}{w}
+1101001{w},{mod}010{r_m}:rcl{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}010{r_m},{imm8}:rcl{w} {imm8},{mod}{r_m}{w}
+1101000{w},{mod}011{r_m}:rcr{w} {mod}{r_m}{w}
+1101001{w},{mod}011{r_m}:rcr{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}011{r_m},{imm8}:rcr{w} {imm8},{mod}{r_m}{w}
+00001111,00110010:rdmsr
+00001111,00110011:rdpmc
+00001111,00110001:rdtsc
+11000011:ret{W}
+11000010,{imm16}:ret{W} {imm16}
+11001011:lret
+11001010,{imm16}:lret {imm16}
+1101000{w},{mod}000{r_m}:rol{w} {mod}{r_m}{w}
+1101001{w},{mod}000{r_m}:rol{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}000{r_m},{imm8}:rol{w} {imm8},{mod}{r_m}{w}
+1101000{w},{mod}001{r_m}:ror{w} {mod}{r_m}{w}
+1101001{w},{mod}001{r_m}:ror{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}001{r_m},{imm8}:ror{w} {imm8},{mod}{r_m}{w}
+00001111,10101010:rsm
+10011110:sahf
+1101000{w},{mod}111{r_m}:sar{w} {mod}{r_m}{w}
+1101001{w},{mod}111{r_m}:sar{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}111{r_m},{imm8}:sar{w} {imm8},{mod}{r_m}{w}
+0001100{w},{mod}{reg}{r_m}:sbb {reg}{w},{mod}{r_m}{w}
+0001101{w},{mod}{reg}{r_m}:sbb {mod}{r_m}{w},{reg}{w}
+0001110{w},{imm}:sbb {imm}{w},{ax}{w}
+1000000{w},{mod}011{r_m},{imm}:sbb{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}011{r_m},{imms8}:sbb{w} {imms8},{mod}{r_m}
+1010111{w}:{RE}scas {es_di},{ax}{w}
+00001111,1001{tttn},{mod}000{r_m}:set{tttn} {mod}{r_m}
+1101000{w},{mod}100{r_m}:shl{w} {mod}{r_m}{w}
+1101001{w},{mod}100{r_m}:shl{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}100{r_m},{imm8}:shl{w} {imm8},{mod}{r_m}{w}
+1101000{w},{mod}101{r_m}:shr{w} {mod}{r_m}{w}
+00001111,10100100,{mod}{reg}{r_m},{imm8}:shld {imm8},{reg},{mod}{r_m}
+00001111,10100101,{mod}{reg}{r_m}:shld %cl,{reg},{mod}{r_m}
+1101001{w},{mod}101{r_m}:shr{w} %cl,{mod}{r_m}{w}
+1100000{w},{mod}101{r_m},{imm8}:shr{w} {imm8},{mod}{r_m}{w}
+00001111,10101100,{mod}{reg}{r_m},{imm8}:shrd {imm8},{reg},{mod}{r_m}
+00001111,10101101,{mod}{reg}{r_m}:shrd %cl,{reg},{mod}{r_m}
+# ORDER
+00001111,00000001,11000001:vmcall
+00001111,00000001,11000010:vmlaunch
+00001111,00000001,11000011:vmresume
+00001111,00000001,11000100:vmxoff
+00001111,01111000,{mod}{reg64}{64r_m}:vmread {reg64},{mod}{64r_m}
+00001111,01111001,{mod}{reg64}{64r_m}:vmwrite {mod}{64r_m},{reg64}
+ifdef(`i386',
+`00001111,00000001,{mod}000{r_m}:sgdtl {mod}{r_m}
+',
+`00001111,00000001,{mod}000{r_m}:sgdt {mod}{r_m}
+')dnl
+# ORDER END
+# ORDER
+ifdef(`i386',
+`00001111,00000001,11001000:monitor %eax,%ecx,%edx
+00001111,00000001,11001001:mwait %eax,%ecx
+',
+`00001111,00000001,11001000:monitor %rax,%rcx,%rdx
+00001111,00000001,11001001:mwait %rax,%rcx
+')dnl
+ifdef(`i386',
+`00001111,00000001,{mod}001{r_m}:sidtl {mod}{r_m}
+',
+`00001111,00000001,{mod}001{r_m}:sidt {mod}{r_m}
+')dnl
+# ORDER END
+00001111,00000000,{mod}000{r_m}:sldt {mod}{r_m}
+00001111,00000001,{mod}100{r_m}:smsw {mod}{r_m}
+11111001:stc
+11111101:std
+11111011:sti
+1010101{w}:{R}stos {ax}{w},{es_di}
+00001111,00000000,{mod}001{r_m}:str {mod}{r_m}
+0010100{w},{mod}{reg}{r_m}:sub {reg}{w},{mod}{r_m}{w}
+0010101{w},{mod}{reg}{r_m}:sub {mod}{r_m}{w},{reg}{w}
+0010110{w},{imm}:sub {imm}{w},{ax}{w}
+1000000{w},{mod}101{r_m},{imm}:sub{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}101{r_m},{imms8}:sub{w} {imms8},{mod}{r_m}
+1000010{w},{mod}{reg}{r_m}:test {reg}{w},{mod}{r_m}{w}
+1010100{w},{imm}:test {imm}{w},{ax}{w}
+1111011{w},{mod}000{r_m},{imm}:test{w} {imm}{w},{mod}{r_m}{w}
+00001111,00001011:ud2a
+00001111,00000000,{mod}100{16r_m}:verr {mod}{16r_m}
+00001111,00000000,{mod}101{16r_m}:verw {mod}{16r_m}
+00001111,00001001:wbinvd
+00001111,00001101,{mod}000{8r_m}:prefetch {mod}{8r_m}
+00001111,00001101,{mod}001{8r_m}:prefetchw {mod}{8r_m}
+00001111,00011000,{mod}000{r_m}:prefetchnta {mod}{r_m}
+00001111,00011000,{mod}001{r_m}:prefetcht0 {mod}{r_m}
+00001111,00011000,{mod}010{r_m}:prefetcht1 {mod}{r_m}
+00001111,00011000,{mod}011{r_m}:prefetcht2 {mod}{r_m}
+00001111,00011111,{mod}{reg}{r_m}:nop{w} {mod}{r_m}
+00001111,00110000:wrmsr
+00001111,1100000{w},{mod}{reg}{r_m}:xadd {reg}{w},{mod}{r_m}{w}
+1000011{w},{mod}{reg}{r_m}:xchg {reg}{w},{mod}{r_m}{w}
+10010{oreg}:xchg {ax},{oreg}
+11010111:xlat {ds_bx}
+0011000{w},{mod}{reg}{r_m}:xor {reg}{w},{mod}{r_m}{w}
+0011001{w},{mod}{reg}{r_m}:xor {mod}{r_m}{w},{reg}{w}
+0011010{w},{imm}:xor {imm}{w},{ax}{w}
+1000000{w},{mod}110{r_m},{imm}:xor{w} {imm}{w},{mod}{r_m}{w}
+1000001{w},{mod}110{r_m},{imms8}:xor{w} {imms8},{mod}{r_m}
+00001111,01110111:emms
+01100110,00001111,11011011,{Mod}{xmmreg}{R_m}:pand {Mod}{R_m},{xmmreg}
+00001111,11011011,{MOD}{mmxreg}{R_M}:pand {MOD}{R_M},{mmxreg}
+01100110,00001111,11011111,{Mod}{xmmreg}{R_m}:pandn {Mod}{R_m},{xmmreg}
+00001111,11011111,{MOD}{mmxreg}{R_M}:pandn {MOD}{R_M},{mmxreg}
+01100110,00001111,11110101,{Mod}{xmmreg}{R_m}:pmaddwd {Mod}{R_m},{xmmreg}
+00001111,11110101,{MOD}{mmxreg}{R_M}:pmaddwd {MOD}{R_M},{mmxreg}
+01100110,00001111,11101011,{Mod}{xmmreg}{R_m}:por {Mod}{R_m},{xmmreg}
+00001111,11101011,{MOD}{mmxreg}{R_M}:por {MOD}{R_M},{mmxreg}
+01100110,00001111,11101111,{Mod}{xmmreg}{R_m}:pxor {Mod}{R_m},{xmmreg}
+00001111,11101111,{MOD}{mmxreg}{R_M}:pxor {MOD}{R_M},{mmxreg}
+00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg}
+00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000000:cmpeqps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000001:cmpltps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000010:cmpleps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000011:cmpunordps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000100:cmpneqps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000101:cmpnltps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000110:cmpnleps {Mod}{R_m},{xmmreg}
+00001111,11000010,{Mod}{xmmreg}{R_m},00000111:cmpordps {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000000:cmpeqss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000001:cmpltss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000010:cmpless {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000011:cmpunordss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000100:cmpneqss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000101:cmpnltss {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000110:cmpnless {Mod}{R_m},{xmmreg}
+11110011,00001111,11000010,{Mod}{xmmreg}{R_m},00000111:cmpordss {Mod}{R_m},{xmmreg}
+00001111,10101110,{mod}001{r_m}:fxrstor {mod}{r_m}
+00001111,10101110,{mod}000{r_m}:fxsave {mod}{r_m}
+00001111,10101110,{mod}010{r_m}:ldmxcsr {mod}{r_m}
+00001111,10101110,{mod}011{r_m}:stmxcsr {mod}{r_m}
+11110010,00001111,00010000,{Mod}{xmmreg}{R_m}:movsd {Mod}{R_m},{xmmreg}
+11110011,00001111,00010000,{Mod}{xmmreg}{R_m}:movss {Mod}{R_m},{xmmreg}
+01100110,00001111,00010000,{Mod}{xmmreg}{R_m}:movupd {Mod}{R_m},{xmmreg}
+00001111,00010000,{Mod}{xmmreg}{R_m}:movups {Mod}{R_m},{xmmreg}
+11110010,00001111,00010001,{Mod}{xmmreg}{R_m}:movsd {xmmreg},{Mod}{R_m}
+11110011,00001111,00010001,{Mod}{xmmreg}{R_m}:movss {xmmreg},{Mod}{R_m}
+01100110,00001111,00010001,{Mod}{xmmreg}{R_m}:movupd {xmmreg},{Mod}{R_m}
+00001111,00010001,{Mod}{xmmreg}{R_m}:movups {xmmreg},{Mod}{R_m}
+11110010,00001111,00010010,{Mod}{xmmreg}{R_m}:movddup {Mod}{R_m},{xmmreg}
+11110011,00001111,00010010,{Mod}{xmmreg}{R_m}:movsldup {Mod}{R_m},{xmmreg}
+01100110,00001111,00010010,{Mod}{xmmreg}{R_m}:movlpd {Mod}{R_m},{xmmreg}
+00001111,00010010,11{xmmreg1}{xmmreg2}:movhlps {xmmreg2},{xmmreg1}
+00001111,00010010,{Mod}{xmmreg}{R_m}:movlps {Mod}{R_m},{xmmreg}
+01100110,00001111,00010011,11{xmmreg1}{xmmreg2}:movhlpd {xmmreg1},{xmmreg2}
+00001111,00010011,11{xmmreg1}{xmmreg2}:movhlps {xmmreg1},{xmmreg2}
+01100110,00001111,00010011,{Mod}{xmmreg}{R_m}:movlpd {xmmreg},{Mod}{R_m}
+00001111,00010011,{Mod}{xmmreg}{R_m}:movlps {xmmreg},{Mod}{R_m}
+01100110,00001111,00010100,{Mod}{xmmreg}{R_m}:unpcklpd {Mod}{R_m},{xmmreg}
+00001111,00010100,{Mod}{xmmreg}{R_m}:unpcklps {Mod}{R_m},{xmmreg}
+01100110,00001111,00010101,{Mod}{xmmreg}{R_m}:unpckhpd {Mod}{R_m},{xmmreg}
+00001111,00010101,{Mod}{xmmreg}{R_m}:unpckhps {Mod}{R_m},{xmmreg}
+11110011,00001111,00010110,{Mod}{xmmreg}{R_m}:movshdup {Mod}{R_m},{xmmreg}
+01100110,00001111,00010110,{Mod}{xmmreg}{R_m}:movhpd {Mod}{R_m},{xmmreg}
+00001111,00010110,11{xmmreg1}{xmmreg2}:movlhps {xmmreg2},{xmmreg1}
+00001111,00010110,{Mod}{xmmreg}{R_m}:movhps {Mod}{R_m},{xmmreg}
+01100110,00001111,00010111,11{xmmreg1}{xmmreg2}:movlhpd {xmmreg1},{xmmreg2}
+00001111,00010111,11{xmmreg1}{xmmreg2}:movlhps {xmmreg1},{xmmreg2}
+01100110,00001111,00010111,{Mod}{xmmreg}{R_m}:movhpd {xmmreg},{Mod}{R_m}
+00001111,00010111,{Mod}{xmmreg}{R_m}:movhps {xmmreg},{Mod}{R_m}
+01100110,00001111,00101000,{Mod}{xmmreg}{R_m}:movapd {Mod}{R_m},{xmmreg}
+00001111,00101000,{Mod}{xmmreg}{R_m}:movaps {Mod}{R_m},{xmmreg}
+01100110,00001111,00101001,{Mod}{xmmreg}{R_m}:movapd {xmmreg},{Mod}{R_m}
+00001111,00101001,{Mod}{xmmreg}{R_m}:movaps {xmmreg},{Mod}{R_m}
+11110010,00001111,00101010,{mod}{xmmreg}{r_m}:cvtsi2sd {mod}{r_m},{xmmreg}
+11110011,00001111,00101010,{mod}{xmmreg}{r_m}:cvtsi2ss {mod}{r_m},{xmmreg}
+01100110,00001111,00101010,{MOD}{xmmreg}{R_M}:cvtpi2pd {MOD}{R_M},{xmmreg}
+00001111,00101010,{MOD}{xmmreg}{R_M}:cvtpi2ps {MOD}{R_M},{xmmreg}
+01100110,00001111,00101011,{mod}{xmmreg}{r_m}:movntpd {xmmreg},{mod}{r_m}
+00001111,00101011,{mod}{xmmreg}{r_m}:movntps {xmmreg},{mod}{r_m}
+11110010,00001111,00101100,{Mod}{reg}{R_m}:cvttsd2si {Mod}{R_m},{reg}
+11110011,00001111,00101100,{Mod}{reg}{R_m}:cvttss2si {Mod}{R_m},{reg}
+01100110,00001111,00101100,{Mod}{mmxreg}{R_m}:cvttpd2pi {Mod}{R_m},{mmxreg}
+00001111,00101100,{Mod}{mmxreg}{R_m}:cvttps2pi {Mod}{R_m},{mmxreg}
+01100110,00001111,00101101,{Mod}{mmxreg}{R_m}:cvtpd2pi {Mod}{R_m},{mmxreg}
+11110010,00001111,00101101,{Mod}{reg}{R_m}:cvtsd2si {Mod}{R_m},{reg}
+11110011,00001111,00101101,{Mod}{reg}{R_m}:cvtss2si {Mod}{R_m},{reg}
+00001111,00101101,{Mod}{mmxreg}{R_m}:cvtps2pi {Mod}{R_m},{mmxreg}
+01100110,00001111,00101110,{Mod}{xmmreg}{R_m}:ucomisd {Mod}{R_m},{xmmreg}
+00001111,00101110,{Mod}{xmmreg}{R_m}:ucomiss {Mod}{R_m},{xmmreg}
+01100110,00001111,00101111,{Mod}{xmmreg}{R_m}:comisd {Mod}{R_m},{xmmreg}
+00001111,00101111,{Mod}{xmmreg}{R_m}:comiss {Mod}{R_m},{xmmreg}
+00001111,00110111:getsec
+01100110,00001111,01010000,11{reg}{xmmreg}:movmskpd {xmmreg},{reg}
+00001111,01010000,11{reg}{xmmreg}:movmskps {xmmreg},{reg}
+01100110,00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtpd {Mod}{R_m},{xmmreg}
+11110010,00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtss {Mod}{R_m},{xmmreg}
+00001111,01010001,{Mod}{xmmreg}{R_m}:sqrtps {Mod}{R_m},{xmmreg}
+11110011,00001111,01010010,{Mod}{xmmreg}{R_m}:rsqrtss {Mod}{R_m},{xmmreg}
+00001111,01010010,{Mod}{xmmreg}{R_m}:rsqrtps {Mod}{R_m},{xmmreg}
+11110011,00001111,01010011,{Mod}{xmmreg}{R_m}:rcpss {Mod}{R_m},{xmmreg}
+00001111,01010011,{Mod}{xmmreg}{R_m}:rcpps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010100,{Mod}{xmmreg}{R_m}:andpd {Mod}{R_m},{xmmreg}
+00001111,01010100,{Mod}{xmmreg}{R_m}:andps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010101,{Mod}{xmmreg}{R_m}:andnpd {Mod}{R_m},{xmmreg}
+00001111,01010101,{Mod}{xmmreg}{R_m}:andnps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010110,{Mod}{xmmreg}{R_m}:orpd {Mod}{R_m},{xmmreg}
+00001111,01010110,{Mod}{xmmreg}{R_m}:orps {Mod}{R_m},{xmmreg}
+01100110,00001111,01010111,{Mod}{xmmreg}{R_m}:xorpd {Mod}{R_m},{xmmreg}
+00001111,01010111,{Mod}{xmmreg}{R_m}:xorps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011000,{Mod}{xmmreg}{R_m}:addsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011000,{Mod}{xmmreg}{R_m}:addss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011000,{Mod}{xmmreg}{R_m}:addpd {Mod}{R_m},{xmmreg}
+00001111,01011000,{Mod}{xmmreg}{R_m}:addps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011001,{Mod}{xmmreg}{R_m}:mulsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011001,{Mod}{xmmreg}{R_m}:mulss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011001,{Mod}{xmmreg}{R_m}:mulpd {Mod}{R_m},{xmmreg}
+00001111,01011001,{Mod}{xmmreg}{R_m}:mulps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011010,{Mod}{xmmreg}{R_m}:cvtsd2ss {Mod}{R_m},{xmmreg}
+11110011,00001111,01011010,{Mod}{xmmreg}{R_m}:cvtss2sd {Mod}{R_m},{xmmreg}
+01100110,00001111,01011010,{Mod}{xmmreg}{R_m}:cvtpd2ps {Mod}{R_m},{xmmreg}
+00001111,01011010,{Mod}{xmmreg}{R_m}:cvtps2pd {Mod}{R_m},{xmmreg}
+01100110,00001111,01011011,{Mod}{xmmreg}{R_m}:cvtps2dq {Mod}{R_m},{xmmreg}
+11110011,00001111,01011011,{Mod}{xmmreg}{R_m}:cvttps2dq {Mod}{R_m},{xmmreg}
+00001111,01011011,{Mod}{xmmreg}{R_m}:cvtdq2ps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011100,{Mod}{xmmreg}{R_m}:subsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011100,{Mod}{xmmreg}{R_m}:subss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011100,{Mod}{xmmreg}{R_m}:subpd {Mod}{R_m},{xmmreg}
+00001111,01011100,{Mod}{xmmreg}{R_m}:subps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011101,{Mod}{xmmreg}{R_m}:minsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011101,{Mod}{xmmreg}{R_m}:minss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011101,{Mod}{xmmreg}{R_m}:minpd {Mod}{R_m},{xmmreg}
+00001111,01011101,{Mod}{xmmreg}{R_m}:minps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011110,{Mod}{xmmreg}{R_m}:divsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011110,{Mod}{xmmreg}{R_m}:divss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011110,{Mod}{xmmreg}{R_m}:divpd {Mod}{R_m},{xmmreg}
+00001111,01011110,{Mod}{xmmreg}{R_m}:divps {Mod}{R_m},{xmmreg}
+11110010,00001111,01011111,{Mod}{xmmreg}{R_m}:maxsd {Mod}{R_m},{xmmreg}
+11110011,00001111,01011111,{Mod}{xmmreg}{R_m}:maxss {Mod}{R_m},{xmmreg}
+01100110,00001111,01011111,{Mod}{xmmreg}{R_m}:maxpd {Mod}{R_m},{xmmreg}
+00001111,01011111,{Mod}{xmmreg}{R_m}:maxps {Mod}{R_m},{xmmreg}
+01100110,00001111,01100000,{Mod}{xmmreg}{R_m}:punpcklbw {Mod}{R_m},{xmmreg}
+00001111,01100000,{MOD}{mmxreg}{R_M}:punpcklbw {MOD}{R_M},{mmxreg}
+01100110,00001111,01100001,{Mod}{xmmreg}{R_m}:punpcklwd {Mod}{R_m},{xmmreg}
+00001111,01100001,{MOD}{mmxreg}{R_M}:punpcklwd {MOD}{R_M},{mmxreg}
+01100110,00001111,01100010,{Mod}{xmmreg}{R_m}:punpckldq {Mod}{R_m},{xmmreg}
+00001111,01100010,{MOD}{mmxreg}{R_M}:punpckldq {MOD}{R_M},{mmxreg}
+01100110,00001111,01100011,{Mod}{xmmreg}{R_m}:packsswb {Mod}{R_m},{xmmreg}
+00001111,01100011,{MOD}{mmxreg}{R_M}:packsswb {MOD}{R_M},{mmxreg}
+01100110,00001111,01100100,{Mod}{xmmreg}{R_m}:pcmpgtb {Mod}{R_m},{xmmreg}
+00001111,01100100,{MOD}{mmxreg}{R_M}:pcmpgtb {MOD}{R_M},{mmxreg}
+01100110,00001111,01100101,{Mod}{xmmreg}{R_m}:pcmpgtw {Mod}{R_m},{xmmreg}
+00001111,01100101,{MOD}{mmxreg}{R_M}:pcmpgtw {MOD}{R_M},{mmxreg}
+01100110,00001111,01100110,{Mod}{xmmreg}{R_m}:pcmpgtd {Mod}{R_m},{xmmreg}
+00001111,01100110,{MOD}{mmxreg}{R_M}:pcmpgtd {MOD}{R_M},{mmxreg}
+01100110,00001111,01100111,{Mod}{xmmreg}{R_m}:packuswb {Mod}{R_m},{xmmreg}
+00001111,01100111,{MOD}{mmxreg}{R_M}:packuswb {MOD}{R_M},{mmxreg}
+01100110,00001111,01101000,{Mod}{xmmreg}{R_m}:punpckhbw {Mod}{R_m},{xmmreg}
+00001111,01101000,{MOD}{mmxreg}{R_M}:punpckhbw {MOD}{R_M},{mmxreg}
+01100110,00001111,01101001,{Mod}{xmmreg}{R_m}:punpckhwd {Mod}{R_m},{xmmreg}
+00001111,01101001,{MOD}{mmxreg}{R_M}:punpckhwd {MOD}{R_M},{mmxreg}
+01100110,00001111,01101010,{Mod}{xmmreg}{R_m}:punpckhdq {Mod}{R_m},{xmmreg}
+00001111,01101010,{MOD}{mmxreg}{R_M}:punpckhdq {MOD}{R_M},{mmxreg}
+01100110,00001111,01101011,{Mod}{xmmreg}{R_m}:packssdw {Mod}{R_m},{xmmreg}
+00001111,01101011,{MOD}{mmxreg}{R_M}:packssdw {MOD}{R_M},{mmxreg}
+01100110,00001111,01101100,{Mod}{xmmreg}{R_m}:punpcklqdq {Mod}{R_m},{xmmreg}
+01100110,00001111,01101101,{Mod}{xmmreg}{R_m}:punpckhqdq {Mod}{R_m},{xmmreg}
+01100110,00001111,01101110,{mod}{xmmreg}{r_m}:movd {mod}{r_m},{xmmreg}
+00001111,01101110,{mod}{mmxreg}{r_m}:movd {mod}{r_m},{mmxreg}
+01100110,00001111,01101111,{Mod}{xmmreg}{R_m}:movdqa {Mod}{R_m},{xmmreg}
+11110011,00001111,01101111,{Mod}{xmmreg}{R_m}:movdqu {Mod}{R_m},{xmmreg}
+00001111,01101111,{MOD}{mmxreg}{R_M}:movq {MOD}{R_M},{mmxreg}
+01100110,00001111,01110000,{Mod}{xmmreg}{R_m},{imm8}:pshufd {imm8},{Mod}{R_m},{xmmreg}
+11110010,00001111,01110000,{Mod}{xmmreg}{R_m},{imm8}:pshuflw {imm8},{Mod}{R_m},{xmmreg}
+11110011,00001111,01110000,{Mod}{xmmreg}{R_m},{imm8}:pshufhw {imm8},{Mod}{R_m},{xmmreg}
+00001111,01110000,{MOD}{mmxreg}{R_M},{imm8}:pshufw {imm8},{MOD}{R_M},{mmxreg}
+01100110,00001111,01110100,{Mod}{xmmreg}{R_m}:pcmpeqb {Mod}{R_m},{xmmreg}
+00001111,01110100,{MOD}{mmxreg}{R_M}:pcmpeqb {MOD}{R_M},{mmxreg}
+01100110,00001111,01110101,{Mod}{xmmreg}{R_m}:pcmpeqw {Mod}{R_m},{xmmreg}
+00001111,01110101,{MOD}{mmxreg}{R_M}:pcmpeqw {MOD}{R_M},{mmxreg}
+01100110,00001111,01110110,{Mod}{xmmreg}{R_m}:pcmpeqd {Mod}{R_m},{xmmreg}
+00001111,01110110,{MOD}{mmxreg}{R_M}:pcmpeqd {MOD}{R_M},{mmxreg}
+01100110,00001111,01111100,{Mod}{xmmreg}{R_m}:haddpd {Mod}{R_m},{xmmreg}
+11110010,00001111,01111100,{Mod}{xmmreg}{R_m}:haddps {Mod}{R_m},{xmmreg}
+01100110,00001111,01111101,{Mod}{xmmreg}{R_m}:hsubpd {Mod}{R_m},{xmmreg}
+11110010,00001111,01111101,{Mod}{xmmreg}{R_m}:hsubps {Mod}{R_m},{xmmreg}
+01100110,00001111,01111110,{mod}{xmmreg}{r_m}:movd {xmmreg},{mod}{r_m}
+11110011,00001111,01111110,{Mod}{xmmreg}{R_m}:movq {Mod}{R_m},{xmmreg}
+00001111,01111110,{mod}{mmxreg}{r_m}:movd {mmxreg},{mod}{r_m}
+01100110,00001111,01111111,{Mod}{xmmreg}{R_m}:movdqa {xmmreg},{Mod}{R_m}
+11110011,00001111,01111111,{Mod}{xmmreg}{R_m}:movdqu {xmmreg},{Mod}{R_m}
+00001111,01111111,{MOD}{mmxreg}{R_M}:movq {mmxreg},{MOD}{R_M}
+00001111,11000011,{mod}{reg}{r_m}:movnti {reg},{mod}{r_m}
+01100110,00001111,11000100,{mod}{xmmreg}{r_m},{imm8}:pinsrw {imm8},{mod}{r_m},{xmmreg}
+00001111,11000100,{mod}{mmxreg}{r_m},{imm8}:pinsrw {imm8},{mod}{r_m},{mmxreg}
+01100110,00001111,11000101,11{reg}{xmmreg},{imm8}:pextrw {imm8},{xmmreg},{reg}
+00001111,11000101,11{reg}{mmxreg},{imm8}:pextrw {imm8},{mmxreg},{reg}
+01100110,00001111,11000110,{Mod}{xmmreg}{R_m},{imm8}:shufpd {imm8},{Mod}{R_m},{xmmreg}
+00001111,11000110,{Mod}{xmmreg}{R_m},{imm8}:shufps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,11010001,{Mod}{xmmreg}{R_m}:psrlw {Mod}{R_m},{xmmreg}
+00001111,11010001,{MOD}{mmxreg}{R_M}:psrlw {MOD}{R_M},{mmxreg}
+01100110,00001111,11010010,{Mod}{xmmreg}{R_m}:psrld {Mod}{R_m},{xmmreg}
+00001111,11010010,{MOD}{mmxreg}{R_M}:psrld {MOD}{R_M},{mmxreg}
+01100110,00001111,11010011,{Mod}{xmmreg}{R_m}:psrlq {Mod}{R_m},{xmmreg}
+00001111,11010011,{MOD}{mmxreg}{R_M}:psrlq {MOD}{R_M},{mmxreg}
+01100110,00001111,11010100,{Mod}{xmmreg}{R_m}:paddq {Mod}{R_m},{xmmreg}
+00001111,11010100,{MOD}{mmxreg}{R_M}:paddq {MOD}{R_M},{mmxreg}
+01100110,00001111,11010101,{Mod}{xmmreg}{R_m}:pmullw {Mod}{R_m},{xmmreg}
+00001111,11010101,{MOD}{mmxreg}{R_M}:pmullw {MOD}{R_M},{mmxreg}
+01100110,00001111,11010110,{Mod}{xmmreg}{R_m}:movq {xmmreg},{Mod}{R_m}
+11110010,00001111,11010110,11{mmxreg}{xmmreg}:movdq2q {xmmreg},{mmxreg}
+11110011,00001111,11010110,11{xmmreg}{mmxreg}:movq2dq {mmxreg},{xmmreg}
+01100110,00001111,11010111,11{reg}{xmmreg}:pmovmskb {xmmreg},{reg}
+00001111,11010111,11{reg}{mmxreg}:pmovmskb {mmxreg},{reg}
+01100110,00001111,11011000,{Mod}{xmmreg}{R_m}:psubusb {Mod}{R_m},{xmmreg}
+00001111,11011000,{MOD}{mmxreg}{R_M}:psubusb {MOD}{R_M},{mmxreg}
+01100110,00001111,11011001,{Mod}{xmmreg}{R_m}:psubusw {Mod}{R_m},{xmmreg}
+00001111,11011001,{MOD}{mmxreg}{R_M}:psubusw {MOD}{R_M},{mmxreg}
+01100110,00001111,11011010,{Mod}{xmmreg}{R_m}:pminub {Mod}{R_m},{xmmreg}
+00001111,11011010,{MOD}{mmxreg}{R_M}:pminub {MOD}{R_M},{mmxreg}
+01100110,00001111,11011100,{Mod}{xmmreg}{R_m}:paddusb {Mod}{R_m},{xmmreg}
+00001111,11011100,{MOD}{mmxreg}{R_M}:paddusb {MOD}{R_M},{mmxreg}
+01100110,00001111,11011101,{Mod}{xmmreg}{R_m}:paddusw {Mod}{R_m},{xmmreg}
+00001111,11011101,{MOD}{mmxreg}{R_M}:paddusw {MOD}{R_M},{mmxreg}
+01100110,00001111,11011110,{Mod}{xmmreg}{R_m}:pmaxub {Mod}{R_m},{xmmreg}
+00001111,11011110,{MOD}{mmxreg}{R_M}:pmaxub {MOD}{R_M},{mmxreg}
+01100110,00001111,11100000,{Mod}{xmmreg}{R_m}:pavgb {Mod}{R_m},{xmmreg}
+00001111,11100000,{MOD}{mmxreg}{R_M}:pavgb {MOD}{R_M},{mmxreg}
+01100110,00001111,11100001,{Mod}{xmmreg}{R_m}:psraw {Mod}{R_m},{xmmreg}
+00001111,11100001,{MOD}{mmxreg}{R_M}:psraw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100010,{Mod}{xmmreg}{R_m}:psrad {Mod}{R_m},{xmmreg}
+00001111,11100010,{MOD}{mmxreg}{R_M}:psrad {MOD}{R_M},{mmxreg}
+01100110,00001111,11100011,{Mod}{xmmreg}{R_m}:pavgw {Mod}{R_m},{xmmreg}
+00001111,11100011,{MOD}{mmxreg}{R_M}:pavgw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100100,{Mod}{xmmreg}{R_m}:pmulhuw {Mod}{R_m},{xmmreg}
+00001111,11100100,{MOD}{mmxreg}{R_M}:pmulhuw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100101,{Mod}{xmmreg}{R_m}:pmulhw {Mod}{R_m},{xmmreg}
+00001111,11100101,{MOD}{mmxreg}{R_M}:pmulhw {MOD}{R_M},{mmxreg}
+01100110,00001111,11100111,{Mod}{xmmreg}{R_m}:movntdq {xmmreg},{Mod}{R_m}
+00001111,11100111,{MOD}{mmxreg}{R_M}:movntq {mmxreg},{MOD}{R_M}
+01100110,00001111,11101000,{Mod}{xmmreg}{R_m}:psubsb {Mod}{R_m},{xmmreg}
+00001111,11101000,{MOD}{mmxreg}{R_M}:psubsb {MOD}{R_M},{mmxreg}
+01100110,00001111,11101001,{Mod}{xmmreg}{R_m}:psubsw {Mod}{R_m},{xmmreg}
+00001111,11101001,{MOD}{mmxreg}{R_M}:psubsw {MOD}{R_M},{mmxreg}
+01100110,00001111,11101010,{Mod}{xmmreg}{R_m}:pminsw {Mod}{R_m},{xmmreg}
+00001111,11101010,{MOD}{mmxreg}{R_M}:pminsw {MOD}{R_M},{mmxreg}
+01100110,00001111,11101100,{Mod}{xmmreg}{R_m}:paddsb {Mod}{R_m},{xmmreg}
+00001111,11101100,{MOD}{mmxreg}{R_M}:paddsb {MOD}{R_M},{mmxreg}
+01100110,00001111,11101101,{Mod}{xmmreg}{R_m}:paddsw {Mod}{R_m},{xmmreg}
+00001111,11101101,{MOD}{mmxreg}{R_M}:paddsw {MOD}{R_M},{mmxreg}
+01100110,00001111,11101110,{Mod}{xmmreg}{R_m}:pmaxsw {Mod}{R_m},{xmmreg}
+00001111,11101110,{MOD}{mmxreg}{R_M}:pmaxsw {MOD}{R_M},{mmxreg}
+11110010,00001111,11110000,{mod}{xmmreg}{r_m}:lddqu {mod}{r_m},{xmmreg}
+01100110,00001111,11110001,{Mod}{xmmreg}{R_m}:psllw {Mod}{R_m},{xmmreg}
+00001111,11110001,{MOD}{mmxreg}{R_M}:psllw {MOD}{R_M},{mmxreg}
+01100110,00001111,11110010,{Mod}{xmmreg}{R_m}:pslld {Mod}{R_m},{xmmreg}
+00001111,11110010,{MOD}{mmxreg}{R_M}:pslld {MOD}{R_M},{mmxreg}
+01100110,00001111,11110011,{Mod}{xmmreg}{R_m}:psllq {Mod}{R_m},{xmmreg}
+00001111,11110011,{MOD}{mmxreg}{R_M}:psllq {MOD}{R_M},{mmxreg}
+01100110,00001111,11110100,{Mod}{xmmreg}{R_m}:pmuludq {Mod}{R_m},{xmmreg}
+00001111,11110100,{MOD}{mmxreg}{R_M}:pmuludq {MOD}{R_M},{mmxreg}
+01100110,00001111,11110110,{Mod}{xmmreg}{R_m}:psadbw {Mod}{R_m},{xmmreg}
+00001111,11110110,{MOD}{mmxreg}{R_M}:psadbw {MOD}{R_M},{mmxreg}
+01100110,00001111,11110111,11{xmmreg1}{xmmreg2}:maskmovdqu {xmmreg2},{xmmreg1}
+00001111,11110111,11{mmxreg1}{mmxreg2}:maskmovq {mmxreg2},{mmxreg1}
+01100110,00001111,11111000,{Mod}{xmmreg}{R_m}:psubb {Mod}{R_m},{xmmreg}
+00001111,11111000,{MOD}{mmxreg}{R_M}:psubb {MOD}{R_M},{mmxreg}
+01100110,00001111,11111001,{Mod}{xmmreg}{R_m}:psubw {Mod}{R_m},{xmmreg}
+00001111,11111001,{MOD}{mmxreg}{R_M}:psubw {MOD}{R_M},{mmxreg}
+01100110,00001111,11111010,{Mod}{xmmreg}{R_m}:psubd {Mod}{R_m},{xmmreg}
+00001111,11111010,{MOD}{mmxreg}{R_M}:psubd {MOD}{R_M},{mmxreg}
+01100110,00001111,11111011,{Mod}{xmmreg}{R_m}:psubq {Mod}{R_m},{xmmreg}
+00001111,11111011,{MOD}{mmxreg}{R_M}:psubq {MOD}{R_M},{mmxreg}
+01100110,00001111,11111100,{Mod}{xmmreg}{R_m}:paddb {Mod}{R_m},{xmmreg}
+00001111,11111100,{MOD}{mmxreg}{R_M}:paddb {MOD}{R_M},{mmxreg}
+01100110,00001111,11111101,{Mod}{xmmreg}{R_m}:paddw {Mod}{R_m},{xmmreg}
+00001111,11111101,{MOD}{mmxreg}{R_M}:paddw {MOD}{R_M},{mmxreg}
+01100110,00001111,11111110,{Mod}{xmmreg}{R_m}:paddd {Mod}{R_m},{xmmreg}
+00001111,11111110,{MOD}{mmxreg}{R_M}:paddd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000000,{Mod}{xmmreg}{R_m}:pshufb {Mod}{R_m},{xmmreg}
+00001111,00111000,00000000,{MOD}{mmxreg}{R_M}:pshufb {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000001,{Mod}{xmmreg}{R_m}:phaddw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000001,{MOD}{mmxreg}{R_M}:phaddw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000010,{Mod}{xmmreg}{R_m}:phaddd {Mod}{R_m},{xmmreg}
+00001111,00111000,00000010,{MOD}{mmxreg}{R_M}:phaddd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000011,{Mod}{xmmreg}{R_m}:phaddsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000011,{MOD}{mmxreg}{R_M}:phaddsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000100,{Mod}{xmmreg}{R_m}:pmaddubsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000100,{MOD}{mmxreg}{R_M}:pmaddubsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000101,{Mod}{xmmreg}{R_m}:phsubw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000101,{MOD}{mmxreg}{R_M}:phsubw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000110,{Mod}{xmmreg}{R_m}:phsubd {Mod}{R_m},{xmmreg}
+00001111,00111000,00000110,{MOD}{mmxreg}{R_M}:phsubd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00000111,{Mod}{xmmreg}{R_m}:phsubsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00000111,{MOD}{mmxreg}{R_M}:phsubsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001000,{Mod}{xmmreg}{R_m}:psignb {Mod}{R_m},{xmmreg}
+00001111,00111000,00001000,{MOD}{mmxreg}{R_M}:psignb {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001001,{Mod}{xmmreg}{R_m}:psignw {Mod}{R_m},{xmmreg}
+00001111,00111000,00001001,{MOD}{mmxreg}{R_M}:psignw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001010,{Mod}{xmmreg}{R_m}:psignd {Mod}{R_m},{xmmreg}
+00001111,00111000,00001010,{MOD}{mmxreg}{R_M}:psignd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00001011,{Mod}{xmmreg}{R_m}:pmulhrsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00001011,{MOD}{mmxreg}{R_M}:pmulhrsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00011100,{Mod}{xmmreg}{R_m}:pabsb {Mod}{R_m},{xmmreg}
+00001111,00111000,00011100,{MOD}{mmxreg}{R_M}:pabsb {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00011101,{Mod}{xmmreg}{R_m}:pabsw {Mod}{R_m},{xmmreg}
+00001111,00111000,00011101,{MOD}{mmxreg}{R_M}:pabsw {MOD}{R_M},{mmxreg}
+01100110,00001111,00111000,00011110,{Mod}{xmmreg}{R_m}:pabsd {Mod}{R_m},{xmmreg}
+00001111,00111000,00011110,{MOD}{mmxreg}{R_M}:pabsd {MOD}{R_M},{mmxreg}
+01100110,00001111,00111010,00001111,{Mod}{xmmreg}{R_m},{imm8}:palignr {imm8},{Mod}{R_m},{xmmreg}
+00001111,00111010,00001111,{MOD}{mmxreg}{R_M},{imm8}:palignr {imm8},{MOD}{R_M},{mmxreg}
+01100110,00001111,11000111,{mod}110{r_m}:vmclear {mod}{r_m}
+11110011,00001111,11000111,{mod}110{r_m}:vmxon {mod}{r_m}
+00001111,11000111,{mod}110{r_m}:vmptrld {mod}{r_m}
+00001111,11000111,{mod}111{r_m}:vmptrst {mod}{r_m}
+01100110,00001111,01110001,11010{xmmreg},{imm8}:psrlw {imm8},{xmmreg}
+00001111,01110001,11010{mmxreg},{imm8}:psrlw {imm8},{mmxreg}
+01100110,00001111,01110001,11100{xmmreg},{imm8}:psraw {imm8},{xmmreg}
+00001111,01110001,11100{mmxreg},{imm8}:psraw {imm8},{mmxreg}
+01100110,00001111,01110001,11110{xmmreg},{imm8}:psllw {imm8},{xmmreg}
+00001111,01110001,11110{mmxreg},{imm8}:psllw {imm8},{mmxreg}
+01100110,00001111,01110010,11010{xmmreg},{imm8}:psrld {imm8},{xmmreg}
+00001111,01110010,11010{mmxreg},{imm8}:psrld {imm8},{mmxreg}
+01100110,00001111,01110010,11100{xmmreg},{imm8}:psrad {imm8},{xmmreg}
+00001111,01110010,11100{mmxreg},{imm8}:psrad {imm8},{mmxreg}
+01100110,00001111,01110010,11110{xmmreg},{imm8}:pslld {imm8},{xmmreg}
+00001111,01110010,11110{mmxreg},{imm8}:pslld {imm8},{mmxreg}
+01100110,00001111,01110011,11010{xmmreg},{imm8}:psrlq {imm8},{xmmreg}
+00001111,01110011,11010{mmxreg},{imm8}:psrlq {imm8},{mmxreg}
+01100110,00001111,01110011,11011{xmmreg},{imm8}:psrldq {imm8},{xmmreg}
+01100110,00001111,01110011,11110{xmmreg},{imm8}:psllq {imm8},{xmmreg}
+00001111,01110011,11110{mmxreg},{imm8}:psllq {imm8},{mmxreg}
+01100110,00001111,01110011,11111{xmmreg},{imm8}:pslldq {imm8},{xmmreg}
+00001111,10101110,11101000:lfence
+00001111,10101110,11110000:mfence
+00001111,10101110,11111000:sfence
+00001111,10101110,{mod}111{r_m}:clflush {mod}{r_m}
+00001111,00001111,{MOD}{mmxreg}{R_M}:INVALID {MOD}{R_M},{mmxreg}
+01100110,00001111,00111010,00001100,{Mod}{xmmreg}{R_m},{imm8}:blendps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001101,{Mod}{xmmreg}{R_m},{imm8}:blendpd {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010100,{Mod}{xmmreg}{R_m}:blendvps %xmm0,{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010101,{Mod}{xmmreg}{R_m}:blendvpd %xmm0,{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01000000,{Mod}{xmmreg}{R_m},{imm8}:dpps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01000001,{Mod}{xmmreg}{R_m},{imm8}:dppd {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00100001,{Mod}{xmmreg}{R_m},{imm8}:insertps {imm8},{Mod}{R_m},{xmmreg}
+# Mod == 11 is not valid
+01100110,00001111,00111000,00101010,{Mod}{xmmreg}{R_m}:movntdqa {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01000010,{Mod}{xmmreg}{R_m},{imm8}:mpsadbw {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00101011,{Mod}{xmmreg}{R_m}:packusdw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010000,{Mod}{xmmreg}{R_m}:pblendvb %xmm0,{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001110,{Mod}{xmmreg}{R_m},{imm8}:pblendw {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00101001,{Mod}{xmmreg}{R_m}:pcmpeqq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100001,{Mod}{xmmreg}{R_m},{imm8}:pcmpestri {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100000,{Mod}{xmmreg}{R_m},{imm8}:pcmpestrm {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100011,{Mod}{xmmreg}{R_m},{imm8}:pcmpistri {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,01100010,{Mod}{xmmreg}{R_m},{imm8}:pcmpistrm {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110111,{Mod}{xmmreg}{R_m}:pcmpgtq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,01000001,{Mod}{xmmreg}{R_m}:phminposuw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00100000,{mod}{xmmreg}{r_m},{imm8}:pinsrb {imm8},{mod}{r_m},{xmmreg}
+01100110,00001111,00111010,00100010,{mod}{xmmreg}{r_m},{imm8}:pinsrd {imm8},{mod}{r_m},{xmmreg}
+01100110,00001111,00111000,00111100,{Mod}{xmmreg}{R_m}:pmaxsb {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111101,{Mod}{xmmreg}{R_m}:pmaxsd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111111,{Mod}{xmmreg}{R_m}:pmaxud {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111110,{Mod}{xmmreg}{R_m}:pmaxuw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111000,{Mod}{xmmreg}{R_m}:pminsb {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111001,{Mod}{xmmreg}{R_m}:pminsd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111011,{Mod}{xmmreg}{R_m}:pminud {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00111010,{Mod}{xmmreg}{R_m}:pminuw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100000,{Mod}{xmmreg}{R_m}:pmovsxbw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100001,{Mod}{xmmreg}{R_m}:pmovsxbd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100010,{Mod}{xmmreg}{R_m}:pmovsxbq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100011,{Mod}{xmmreg}{R_m}:pmovsxwd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100100,{Mod}{xmmreg}{R_m}:pmovsxwq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00100101,{Mod}{xmmreg}{R_m}:pmovsxdq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110000,{Mod}{xmmreg}{R_m}:pmovzxbw {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110001,{Mod}{xmmreg}{R_m}:pmovzxbd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110010,{Mod}{xmmreg}{R_m}:pmovzxbq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110011,{Mod}{xmmreg}{R_m}:pmovzxwd {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110100,{Mod}{xmmreg}{R_m}:pmovzxwq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00110101,{Mod}{xmmreg}{R_m}:pmovzxdq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00101000,{Mod}{xmmreg}{R_m}:pmuldq {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,01000000,{Mod}{xmmreg}{R_m}:pmulld {Mod}{R_m},{xmmreg}
+01100110,00001111,00111000,00010111,{Mod}{xmmreg}{R_m}:ptest {Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001000,{Mod}{xmmreg}{R_m},{imm8}:roundps {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001001,{Mod}{xmmreg}{R_m},{imm8}:roundpd {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001010,{Mod}{xmmreg}{R_m},{imm8}:roundss {imm8},{Mod}{R_m},{xmmreg}
+01100110,00001111,00111010,00001011,{Mod}{xmmreg}{R_m},{imm8}:roundsd {imm8},{Mod}{R_m},{xmmreg}
+# ORDER:
+dnl Many previous entries depend on this being last.
+000{sreg2}111:pop {sreg2}
+# ORDER END:
diff --git a/libcpu/defs/i386.doc b/libcpu/defs/i386.doc
new file mode 100644
index 0000000..732cd23
--- /dev/null
+++ b/libcpu/defs/i386.doc
@@ -0,0 +1,74 @@
+{imm} only parameter:
+  - is {s} in opcode: {s} == 0, unsigned (8/)16/32 bit immediate
+                      {s} == 1, signed 8 bit immediate
+
+{es:di}: segment register normally %es, can be overwritten
+         edi/di depending on apfx
+
+{ds:si}: segment register normally %ds, can be overwritten
+         esi/si depending on apfx
+
+{ax}     al/ax/eax depending of dpfx and w
+
+{dx}     (%edx) or (%dx) depending on apfx
+
+
+{w}      0 = b, 1 = { no dpfx = l, dpfx = w }
+
+{W}      no dpfx = <empty>, dpfx = w
+{WW}     no dpfx = l, dpfx = w
+
+{R} rep prefix possible
+{RE} repe or repne prefix possible
+
+{ccc} CRx registers
+{ddd} DRx registers
+
+{gg}  00 = b, 01 = w, 10 = d, 11 = <illegal>
+{0g}  00 = b, 01 = w, 10 = <illegal>, 11 = <illegal>
+{GG}  00 = <illegal>, 01 = w, 10 = d, 11 = q
+{gG}  00 = <illegal>, 01 = w, 10 = d, 11 = <illegal>
+
+{modr/m} normal registers
+{MODR/M} MMX registers
+{ModR/m} XMM registers
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Special opcodes (prefixes):
+
+
+01100111:{apfx}
+01100110:{dpfx}
+
+00101110:{cs}
+00111110:{ds}
+00100110:{es}
+01100100:{fs}
+01100101:{gs}
+
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+table format
+
+1bit RE flag
+1bit R flag
+16bit mnemonic
+3bit suffix
+
+5bit fct
+2bit string
+6bit offset1
+5bit offset2
+
+4bit fct
+1bit string
+6bit offset1
+4bit offset2
+
+2bit fct
+1bit string
+3bit offset1
+1bit offset2
+
+61bit
diff --git a/libcpu/i386_data.h b/libcpu/i386_data.h
new file mode 100644
index 0000000..fe3c4ae
--- /dev/null
+++ b/libcpu/i386_data.h
@@ -0,0 +1,1418 @@
+/* Helper routines for disassembler for x86/x86-64.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <inttypes.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <libasm.h>
+
+struct instr_enc
+{
+  /* The mnemonic.  Especially encoded for the optimized table.  */
+  unsigned int mnemonic : MNEMONIC_BITS;
+
+  /* The rep/repe prefixes.  */
+  unsigned int rep : 1;
+  unsigned int repe : 1;
+
+  /* Mnemonic suffix.  */
+  unsigned int suffix : SUFFIX_BITS;
+
+  /* Nonzero if the instruction uses modr/m.  */
+  unsigned int modrm : 1;
+
+  /* 1st parameter.  */
+  unsigned int fct1 : FCT1_BITS;
+#ifdef STR1_BITS
+  unsigned int str1 : STR1_BITS;
+#endif
+  unsigned int off1_1 : OFF1_1_BITS;
+  unsigned int off1_2 : OFF1_2_BITS;
+  unsigned int off1_3 : OFF1_3_BITS;
+
+  /* 2nd parameter.  */
+  unsigned int fct2 : FCT2_BITS;
+#ifdef STR2_BITS
+  unsigned int str2 : STR2_BITS;
+#endif
+  unsigned int off2_1 : OFF2_1_BITS;
+  unsigned int off2_2 : OFF2_2_BITS;
+  unsigned int off2_3 : OFF2_3_BITS;
+
+  /* 3rd parameter.  */
+  unsigned int fct3 : FCT3_BITS;
+#ifdef STR3_BITS
+  unsigned int str3 : STR3_BITS;
+#endif
+  unsigned int off3_1 : OFF3_1_BITS;
+#ifdef OFF3_2_BITS
+  unsigned int off3_2 : OFF3_2_BITS;
+#endif
+#ifdef OFF3_3_BITS
+  unsigned int off3_3 : OFF3_3_BITS;
+#endif
+};
+
+
+typedef int (*opfct_t) (struct output_data *);
+
+
+static int
+data_prefix (struct output_data *d)
+{
+  char ch = '\0';
+  if (*d->prefixes & has_cs)
+    {
+      ch = 'c';
+      *d->prefixes &= ~has_cs;
+    }
+  else if (*d->prefixes & has_ds)
+    {
+      ch = 'd';
+      *d->prefixes &= ~has_ds;
+    }
+  else if (*d->prefixes & has_es)
+    {
+      ch = 'e';
+      *d->prefixes &= ~has_es;
+    }
+  else if (*d->prefixes & has_fs)
+    {
+      ch = 'f';
+      *d->prefixes &= ~has_fs;
+    }
+  else if (*d->prefixes & has_gs)
+    {
+      ch = 'g';
+      *d->prefixes &= ~has_gs;
+    }
+  else if (*d->prefixes & has_ss)
+    {
+      ch = 's';
+      *d->prefixes &= ~has_ss;
+    }
+  else
+    return 0;
+
+  if (*d->bufcntp + 4 > d->bufsize)
+    return *d->bufcntp + 4 - d->bufsize;
+
+  d->bufp[(*d->bufcntp)++] = '%';
+  d->bufp[(*d->bufcntp)++] = ch;
+  d->bufp[(*d->bufcntp)++] = 's';
+  d->bufp[(*d->bufcntp)++] = ':';
+
+  return 0;
+}
+
+#ifdef X86_64
+static const char hiregs[8][4] =
+  {
+    "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+  };
+static const char aregs[8][4] =
+  {
+    "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi"
+  };
+static const char dregs[8][4] =
+  {
+    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+  };
+#else
+static const char aregs[8][4] =
+  {
+    "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"
+  };
+# define dregs aregs
+#endif
+
+static int
+general_mod$r_m (struct output_data *d)
+{
+  int r = data_prefix (d);
+  if (r != 0)
+    return r;
+
+  int prefixes = *d->prefixes;
+  const uint8_t *data = &d->data[d->opoff1 / 8];
+  char *bufp = d->bufp;
+  size_t *bufcntp = d->bufcntp;
+  size_t bufsize = d->bufsize;
+
+  uint_fast8_t modrm = data[0];
+#ifndef X86_64
+  if (unlikely ((prefixes & has_addr16) != 0))
+    {
+      int16_t disp = 0;
+      bool nodisp = false;
+
+      if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
+	/* 16 bit displacement.  */
+	disp = read_2sbyte_unaligned (&data[1]);
+      else if ((modrm & 0xc0) == 0x40)
+	/* 8 bit displacement.  */
+	disp = *(const int8_t *) &data[1];
+      else if ((modrm & 0xc0) == 0)
+	nodisp = true;
+
+      char tmpbuf[sizeof ("-0x1234(%rr,%rr)")];
+      int n;
+      if ((modrm & 0xc7) == 6)
+	n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx16, disp);
+      else
+	{
+	  n = 0;
+	  if (!nodisp)
+	    n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx16,
+			  disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+
+	  if ((modrm & 0x4) == 0)
+	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%b%c,%%%ci)",
+			   "xp"[(modrm >> 1) & 1], "sd"[modrm & 1]);
+	  else
+	    n += snprintf (tmpbuf + n, sizeof (tmpbuf) - n, "(%%%s)",
+			   ((const char [4][3]) { "si", "di", "bp", "bx" })[modrm & 3]);
+	}
+
+      if (*bufcntp + n + 1 > bufsize)
+	return *bufcntp + n + 1 - bufsize;
+
+      memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
+      *bufcntp += n;
+    }
+  else
+#endif
+    {
+      if ((modrm & 7) != 4)
+	{
+	  int32_t disp = 0;
+	  bool nodisp = false;
+
+	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80)
+	    /* 32 bit displacement.  */
+	    disp = read_4sbyte_unaligned (&data[1]);
+	  else if ((modrm & 0xc0) == 0x40)
+	    /* 8 bit displacement.  */
+	    disp = *(const int8_t *) &data[1];
+	  else if ((modrm & 0xc0) == 0)
+	    nodisp = true;
+
+	  char tmpbuf[sizeof ("-0x12345678(%rrrr)")];
+	  int n;
+	  if (nodisp)
+	    {
+	      n = snprintf (tmpbuf, sizeof (tmpbuf), "(%%%s)",
+#ifdef X86_64
+			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
+#endif
+			    aregs[modrm & 7]);
+#ifdef X86_64
+	      if (prefixes & has_addr16)
+		{
+		  if (prefixes & has_rex_b)
+		    tmpbuf[n++] = 'd';
+		  else
+		    tmpbuf[2] = 'e';
+		}
+#endif
+	    }
+	  else if ((modrm & 0xc7) != 5)
+	    {
+	      int p;
+	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%%n%s)",
+			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp, &p,
+#ifdef X86_64
+			    (prefixes & has_rex_b) ? hiregs[modrm & 7] :
+#endif
+			    aregs[modrm & 7]);
+#ifdef X86_64
+	      if (prefixes & has_addr16)
+		{
+		  if (prefixes & has_rex_b)
+		    tmpbuf[n++] = 'd';
+		  else
+		    tmpbuf[p] = 'e';
+		}
+#endif
+	    }
+	  else
+	    {
+#ifdef X86_64
+	      n = snprintf (tmpbuf, sizeof (tmpbuf), "%s0x%" PRIx32 "(%%rip)",
+			    disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+
+	      d->symaddr_use = addr_rel_always;
+	      d->symaddr = disp;
+#else
+	      n = snprintf (tmpbuf, sizeof (tmpbuf), "0x%" PRIx32, disp);
+#endif
+	    }
+
+	  if (*bufcntp + n + 1 > bufsize)
+	    return *bufcntp + n + 1 - bufsize;
+
+	  memcpy (&bufp[*bufcntp], tmpbuf, n + 1);
+	  *bufcntp += n;
+	}
+      else
+	{
+	  /* SIB */
+	  uint_fast8_t sib = data[1];
+	  int32_t disp = 0;
+	  bool nodisp = false;
+
+	  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
+	      || ((modrm & 0xc7) == 0x4 && (sib & 0x7) == 0x5))
+	    /* 32 bit displacement.  */
+	    disp = read_4sbyte_unaligned (&data[2]);
+	  else if ((modrm & 0xc0) == 0x40)
+	    /* 8 bit displacement.  */
+	    disp = *(const int8_t *) &data[2];
+	  else
+	    nodisp = true;
+
+	  char tmpbuf[sizeof ("-0x12345678(%rrrr,%rrrr,N)")];
+	  char *cp = tmpbuf;
+	  int n;
+	  if ((modrm & 0xc0) != 0 || (sib & 0x3f) != 0x25
+#ifdef X86_64
+	      || (prefixes & has_rex_x) != 0
+#endif
+	      )
+	    {
+	      if (!nodisp)
+		{
+		  n = snprintf (cp, sizeof (tmpbuf), "%s0x%" PRIx32,
+				disp < 0 ? "-" : "", disp < 0 ? -disp : disp);
+		  cp += n;
+		}
+
+	      *cp++ = '(';
+
+	      if ((modrm & 0xc7) != 0x4 || (sib & 0x7) != 0x5)
+		{
+		  *cp++ = '%';
+		  cp = stpcpy (cp,
+#ifdef X86_64
+			       (prefixes & has_rex_b) ? hiregs[sib & 7] :
+			       (prefixes & has_addr16) ? dregs[sib & 7] :
+#endif
+			       aregs[sib & 7]);
+#ifdef X86_64
+		  if ((prefixes & (has_rex_b | has_addr16))
+		      == (has_rex_b | has_addr16))
+		    *cp++ = 'd';
+#endif
+		}
+
+	      if ((sib & 0x38) != 0x20
+#ifdef X86_64
+		  || (prefixes & has_rex_x) != 0
+#endif
+		  )
+		{
+		  *cp++ = ',';
+		  *cp++ = '%';
+		  cp = stpcpy (cp,
+#ifdef X86_64
+			       (prefixes & has_rex_x)
+			       ? hiregs[(sib >> 3) & 7] :
+			       (prefixes & has_addr16)
+			       ? dregs[(sib >> 3) & 7] :
+#endif
+			       aregs[(sib >> 3) & 7]);
+#ifdef X86_64
+		  if ((prefixes & (has_rex_b | has_addr16))
+		      == (has_rex_b | has_addr16))
+		    *cp++ = 'd';
+#endif
+
+		  *cp++ = ',';
+		  *cp++ = '0' + (1 << (sib >> 6));
+		}
+
+	      *cp++ = ')';
+	    }
+	  else
+	    {
+	      assert (! nodisp);
+#ifdef X86_64
+	      if ((prefixes & has_addr16) == 0)
+		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx64,
+			      (int64_t) disp);
+	      else
+#endif
+		n = snprintf (cp, sizeof (tmpbuf), "0x%" PRIx32, disp);
+	      cp += n;
+	    }
+
+	  if (*bufcntp + (cp - tmpbuf) > bufsize)
+	    return *bufcntp + (cp - tmpbuf) - bufsize;
+
+	  memcpy (&bufp[*bufcntp], tmpbuf, cp - tmpbuf);
+	  *bufcntp += cp - tmpbuf;
+	}
+    }
+  return 0;
+}
+
+
+static int
+FCT_MOD$R_M (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      assert (d->opoff1 / 8 == d->opoff2 / 8);
+      assert (d->opoff2 % 8 == 5);
+      //uint_fast8_t byte = d->data[d->opoff2 / 8] & 7;
+      uint_fast8_t byte = modrm & 7;
+
+      size_t *bufcntp = d->bufcntp;
+      char *buf = d->bufp + *bufcntp;
+      size_t avail = d->bufsize - *bufcntp;
+      int needed;
+      if (*d->prefixes & (has_rep | has_repne))
+	needed = snprintf (buf, avail, "%%%s", dregs[byte]);
+      else
+	needed = snprintf (buf, avail, "%%mm%" PRIxFAST8, byte);
+      if ((size_t) needed > avail)
+	return needed - avail;
+      *bufcntp += needed;
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+
+
+static int
+FCT_Mod$R_m (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      assert (d->opoff1 / 8 == d->opoff2 / 8);
+      assert (d->opoff2 % 8 == 5);
+      //uint_fast8_t byte = data[opoff2 / 8] & 7;
+      uint_fast8_t byte = modrm & 7;
+
+      size_t *bufcntp = d->bufcntp;
+      size_t avail = d->bufsize - *bufcntp;
+      int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8,
+			     byte);
+      if ((size_t) needed > avail)
+	return needed - avail;
+      *d->bufcntp += needed;
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+
+static int
+generic_abs (struct output_data *d, const char *absstring
+#ifdef X86_64
+	     , int abslen
+#else
+# define abslen 4
+#endif
+	     )
+{
+  int r = data_prefix (d);
+  if (r != 0)
+    return r;
+
+  assert (d->opoff1 % 8 == 0);
+  assert (d->opoff1 / 8 == 1);
+  if (*d->param_start + abslen > d->end)
+    return -1;
+  *d->param_start += abslen;
+#ifndef X86_64
+  uint32_t absval;
+# define ABSPRIFMT PRIx32
+#else
+  uint64_t absval;
+# define ABSPRIFMT PRIx64
+  if (abslen == 8)
+    absval = read_8ubyte_unaligned (&d->data[1]);
+  else
+#endif
+    absval = read_4ubyte_unaligned (&d->data[1]);
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "%s0x%" ABSPRIFMT,
+			 absstring, absval);
+  if ((size_t) needed > avail)
+    return needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_absval (struct output_data *d)
+{
+  return generic_abs (d, "$"
+#ifdef X86_64
+		      , 4
+#endif
+		      );
+}
+
+static int
+FCT_abs (struct output_data *d)
+{
+  return generic_abs (d, ""
+#ifdef X86_64
+		      , 8
+#endif
+		      );
+}
+
+static int
+FCT_ax (struct output_data *d)
+{
+  int is_16bit = (*d->prefixes & has_data16) != 0;
+
+  size_t *bufcntp = d->bufcntp;
+  char *bufp = d->bufp;
+  size_t bufsize = d->bufsize;
+
+  if (*bufcntp + 4 - is_16bit > bufsize)
+    return *bufcntp + 4 - is_16bit - bufsize;
+
+  bufp[(*bufcntp)++] = '%';
+  if (! is_16bit)
+    bufp[(*bufcntp)++] = (
+#ifdef X86_64
+			  (*d->prefixes & has_rex_w) ? 'r' :
+#endif
+			  'e');
+  bufp[(*bufcntp)++] = 'a';
+  bufp[(*bufcntp)++] = 'x';
+
+  return 0;
+}
+
+
+static int
+FCT_ax$w (struct output_data *d)
+{
+  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
+    return FCT_ax (d);
+
+  size_t *bufcntp = d->bufcntp;
+  char *bufp = d->bufp;
+  size_t bufsize = d->bufsize;
+
+  if (*bufcntp + 3 > bufsize)
+    return *bufcntp + 3 - bufsize;
+
+  bufp[(*bufcntp)++] = '%';
+  bufp[(*bufcntp)++] = 'a';
+  bufp[(*bufcntp)++] = 'l';
+
+  return 0;
+}
+
+
+static int
+__attribute__ ((noinline))
+FCT_crdb (struct output_data *d, const char *regstr)
+{
+  if (*d->prefixes & has_data16)
+    return -1;
+
+  size_t *bufcntp = d->bufcntp;
+
+  // XXX If this assert is true, use absolute offset below
+  assert (d->opoff1 / 8 == 2);
+  assert (d->opoff1 % 8 == 2);
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%%s%" PRIx32,
+			 regstr, (uint32_t) (d->data[d->opoff1 / 8] >> 3) & 7);
+  if ((size_t) needed > avail)
+    return needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_ccc (struct output_data *d)
+{
+  return FCT_crdb (d, "cr");
+}
+
+
+static int
+FCT_ddd (struct output_data *d)
+{
+  return FCT_crdb (d, "db");
+}
+
+
+static int
+FCT_disp8 (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  if (*d->param_start >= d->end)
+    return -1;
+  int32_t offset = *(const int8_t *) (*d->param_start)++;
+
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
+			 (uint32_t) (d->addr + (*d->param_start - d->data)
+				     + offset));
+  if ((size_t) needed > avail)
+    return needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+__attribute__ ((noinline))
+FCT_ds_xx (struct output_data *d, const char *reg)
+{
+  int prefix = *d->prefixes & SEGMENT_PREFIXES;
+
+  if (prefix == 0)
+    *d->prefixes |= prefix = has_ds;
+  /* Make sure only one bit is set.  */
+  else if ((prefix - 1) & prefix)
+    return -1;
+
+  int r = data_prefix (d);
+
+  assert ((*d->prefixes & prefix) == 0);
+
+  if (r != 0)
+    return r;
+
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "(%%%s%s)",
+#ifdef X86_64
+			 *d->prefixes & idx_addr16 ? "e" : "r",
+#else
+			 *d->prefixes & idx_addr16 ? "" : "e",
+#endif
+			 reg);
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+
+  return 0;
+}
+
+
+static int
+FCT_ds_bx (struct output_data *d)
+{
+  return FCT_ds_xx (d, "bx");
+}
+
+
+static int
+FCT_ds_si (struct output_data *d)
+{
+  return FCT_ds_xx (d, "si");
+}
+
+
+static int
+FCT_dx (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+
+  if (*bufcntp + 7 > d->bufsize)
+    return *bufcntp + 7 - d->bufsize;
+
+  memcpy (&d->bufp[*bufcntp], "(%dx)", 5);
+  *bufcntp += 5;
+
+  return 0;
+}
+
+
+static int
+FCT_es_di (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%es:(%%%sdi)",
+#ifdef X86_64
+			 *d->prefixes & idx_addr16 ? "e" : "r"
+#else
+			 *d->prefixes & idx_addr16 ? "" : "e"
+#endif
+			 );
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+
+  return 0;
+}
+
+
+static int
+FCT_imm (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed;
+  if (*d->prefixes & has_data16)
+    {
+      if (*d->param_start + 2 > d->end)
+	return -1;
+      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
+      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+    }
+  else
+    {
+      if (*d->param_start + 4 > d->end)
+	return -1;
+      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
+#ifdef X86_64
+      if (*d->prefixes & has_rex_w)
+	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+			   (int64_t) word);
+      else
+#endif
+	needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+    }
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_imm$w (struct output_data *d)
+{
+  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) != 0)
+    return FCT_imm (d);
+
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  if (*d->param_start>= d->end)
+    return -1;
+  uint_fast8_t word = *(*d->param_start)++;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIxFAST8, word);
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+#ifdef X86_64
+static int
+FCT_imm64$w (struct output_data *d)
+{
+  if ((d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7)))) == 0
+      || (*d->prefixes & has_data16) != 0)
+    return FCT_imm$w (d);
+
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed;
+  if (*d->prefixes & has_rex_w)
+    {
+      if (*d->param_start + 8 > d->end)
+	return -1;
+      uint64_t word = read_8ubyte_unaligned_inc (*d->param_start);
+      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64, word);
+    }
+  else
+    {
+      if (*d->param_start + 4 > d->end)
+	return -1;
+      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
+      needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+    }
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+#endif
+
+
+static int
+FCT_imms (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  if (*d->param_start>= d->end)
+    return -1;
+  int8_t byte = *(*d->param_start)++;
+#ifdef X86_64
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+			 (int64_t) byte);
+#else
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
+			 (int32_t) byte);
+#endif
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_imm$s (struct output_data *d)
+{
+  uint_fast8_t opcode = d->data[d->opoff2 / 8];
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  if ((opcode & 2) != 0)
+    return FCT_imms (d);
+
+  if ((*d->prefixes & has_data16) == 0)
+    {
+      if (*d->param_start + 4 > d->end)
+	return -1;
+      int32_t word = read_4sbyte_unaligned_inc (*d->param_start);
+#ifdef X86_64
+      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+			     (int64_t) word);
+#else
+      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32, word);
+#endif
+      if ((size_t) needed > avail)
+	return (size_t) needed - avail;
+      *bufcntp += needed;
+    }
+  else
+    {
+      if (*d->param_start + 2 > d->end)
+	return -1;
+      uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
+      int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+      if ((size_t) needed > avail)
+	return (size_t) needed - avail;
+      *bufcntp += needed;
+    }
+  return 0;
+}
+
+
+static int
+FCT_imm16 (struct output_data *d)
+{
+  if (*d->param_start + 2 > d->end)
+    return -1;
+  uint16_t word = read_2ubyte_unaligned_inc (*d->param_start);
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, word);
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_imms8 (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  if (*d->param_start >= d->end)
+    return -1;
+  int_fast8_t byte = *(*d->param_start)++;
+  int needed;
+#ifdef X86_64
+  if (*d->prefixes & has_rex_w)
+    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx64,
+		       (int64_t) byte);
+  else
+#endif
+    needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
+		       (int32_t) byte);
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_imm8 (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  if (*d->param_start >= d->end)
+    return -1;
+  uint_fast8_t byte = *(*d->param_start)++;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx32,
+			 (uint32_t) byte);
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_rel (struct output_data *d)
+{
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  if (*d->param_start + 4 > d->end)
+    return -1;
+  int32_t rel = read_4sbyte_unaligned_inc (*d->param_start);
+#ifdef X86_64
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx64,
+			 (uint64_t) (d->addr + rel
+				     + (*d->param_start - d->data)));
+#else
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "0x%" PRIx32,
+			 (uint32_t) (d->addr + rel
+				     + (*d->param_start - d->data)));
+#endif
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_mmxreg (struct output_data *d)
+{
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
+  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
+  size_t *bufcntp =  d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%mm%" PRIxFAST8, byte);
+  if ((size_t) needed > avail)
+    return needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_mod$r_m (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      int prefixes = *d->prefixes;
+      if (prefixes & has_addr16)
+	return -1;
+
+      int is_16bit = (prefixes & has_data16) != 0;
+
+      size_t *bufcntp = d->bufcntp;
+      char *bufp = d->bufp;
+      if (*bufcntp + 5 - is_16bit > d->bufsize)
+	return *bufcntp + 5 - is_16bit - d->bufsize;
+      bufp[(*bufcntp)++] = '%';
+
+      char *cp;
+#ifdef X86_64
+      if ((prefixes & has_rex_b) != 0 && !is_16bit)
+	{
+	  cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
+	  if ((prefixes & has_rex_w) == 0)
+	    *cp++ = 'd';
+	}
+      else
+#endif
+	{
+	  cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
+#ifdef X86_64
+	  if ((prefixes & has_rex_w) != 0)
+	    bufp[*bufcntp] = 'r';
+#endif
+	}
+      *bufcntp = cp - bufp;
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+
+
+#ifndef X86_64
+static int
+FCT_moda$r_m (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      if (*d->prefixes & has_addr16)
+	return -1;
+
+      size_t *bufcntp = d->bufcntp;
+      if (*bufcntp + 3 > d->bufsize)
+	return *bufcntp + 3 - d->bufsize;
+
+      memcpy (&d->bufp[*bufcntp], "???", 3);
+      *bufcntp += 3;
+
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+#endif
+
+
+#ifdef X86_64
+static const char rex_8bit[8][3] =
+  {
+    [0] = "a", [1] = "c", [2] = "d", [3] = "b",
+    [4] = "sp", [5] = "bp", [6] = "si", [7] = "di"
+  };
+#endif
+
+
+static int
+FCT_mod$r_m$w (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  const uint8_t *data = d->data;
+  uint_fast8_t modrm = data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      int prefixes = *d->prefixes;
+
+      if (prefixes & has_addr16)
+	return -1;
+
+      size_t *bufcntp = d->bufcntp;
+      char *bufp = d->bufp;
+      if (*bufcntp + 5 > d->bufsize)
+	return *bufcntp + 5 - d->bufsize;
+
+      if ((data[d->opoff3 / 8] & (1 << (7 - (d->opoff3 & 7)))) == 0)
+	{
+	  bufp[(*bufcntp)++] = '%';
+
+#ifdef X86_64
+	  if (prefixes & has_rex)
+	    {
+	      if (prefixes & has_rex_r)
+		*bufcntp += snprintf (bufp + *bufcntp, d->bufsize - *bufcntp,
+				      "r%db", 8 + (modrm & 7));
+	      else
+		{
+		  char *cp = stpcpy (bufp + *bufcntp, hiregs[modrm & 7]);
+		  *cp++ = 'l';
+		  *bufcntp = cp - bufp;
+		}
+	    }
+	  else
+#endif
+	    {
+	      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
+	      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
+	    }
+	}
+      else
+	{
+	  int is_16bit = (prefixes & has_data16) != 0;
+
+	  bufp[(*bufcntp)++] = '%';
+
+	  char *cp;
+#ifdef X86_64
+	  if ((prefixes & has_rex_b) != 0 && !is_16bit)
+	    {
+	      cp = stpcpy (&bufp[*bufcntp], hiregs[modrm & 7]);
+	      if ((prefixes & has_rex_w) == 0)
+		*cp++ = 'd';
+	    }
+	  else
+#endif
+	    {
+	      cp = stpcpy (&bufp[*bufcntp], dregs[modrm & 7] + is_16bit);
+#ifdef X86_64
+	      if ((prefixes & has_rex_w) != 0)
+		bufp[*bufcntp] = 'r';
+#endif
+	    }
+	  *bufcntp = cp - bufp;
+	}
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+
+
+static int
+FCT_mod$8r_m (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      size_t *bufcntp = d->bufcntp;
+      char *bufp = d->bufp;
+      if (*bufcntp + 3 > d->bufsize)
+	return *bufcntp + 3 - d->bufsize;
+      bufp[(*bufcntp)++] = '%';
+      bufp[(*bufcntp)++] = "acdb"[modrm & 3];
+      bufp[(*bufcntp)++] = "lh"[(modrm & 4) >> 2];
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+
+
+static int
+FCT_mod$16r_m (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      assert (d->opoff1 / 8 == d->opoff2 / 8);
+      //uint_fast8_t byte = data[opoff2 / 8] & 7;
+      uint_fast8_t byte = modrm & 7;
+
+      size_t *bufcntp = d->bufcntp;
+      if (*bufcntp + 3 > d->bufsize)
+	return *bufcntp + 3 - d->bufsize;
+      d->bufp[(*bufcntp)++] = '%';
+      memcpy (&d->bufp[*bufcntp], dregs[byte] + 1, sizeof (dregs[0]) - 1);
+      *bufcntp += 2;
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+
+
+#ifdef X86_64
+static int
+FCT_mod$64r_m (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  uint_fast8_t modrm = d->data[d->opoff1 / 8];
+  if ((modrm & 0xc0) == 0xc0)
+    {
+      assert (d->opoff1 / 8 == d->opoff2 / 8);
+      //uint_fast8_t byte = data[opoff2 / 8] & 7;
+      uint_fast8_t byte = modrm & 7;
+
+      size_t *bufcntp = d->bufcntp;
+      if (*bufcntp + 4 > d->bufsize)
+	return *bufcntp + 4 - d->bufsize;
+      char *cp = &d->bufp[*bufcntp];
+      *cp++ = '%';
+      cp = stpcpy (cp,
+		   (*d->prefixes & has_rex_b) ? hiregs[byte] : aregs[byte]);
+      *bufcntp = cp - d->bufp;
+      return 0;
+    }
+
+  return general_mod$r_m (d);
+}
+#else
+#define FCT_mod$64r_m FCT_mod$r_m
+#endif
+
+
+static int
+FCT_reg (struct output_data *d)
+{
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 + 3 <= 8);
+  byte >>= 8 - (d->opoff1 % 8 + 3);
+  byte &= 7;
+  int is_16bit = (*d->prefixes & has_data16) != 0;
+  size_t *bufcntp = d->bufcntp;
+  if (*bufcntp + 5 > d->bufsize)
+    return *bufcntp + 5 - d->bufsize;
+  d->bufp[(*bufcntp)++] = '%';
+#ifdef X86_64
+  if ((*d->prefixes & has_rex_r) != 0 && !is_16bit)
+    {
+      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
+			    8 + byte);
+      if ((*d->prefixes & has_rex_w) == 0)
+	d->bufp[(*bufcntp)++] = 'd';
+    }
+  else
+#endif
+    {
+      memcpy (&d->bufp[*bufcntp], dregs[byte] + is_16bit, 3 - is_16bit);
+#ifdef X86_64
+      if ((*d->prefixes & has_rex_w) != 0 && !is_16bit)
+	d->bufp[*bufcntp] = 'r';
+#endif
+      *bufcntp += 3 - is_16bit;
+    }
+  return 0;
+}
+
+
+#ifdef X86_64
+static int
+FCT_oreg (struct output_data *d)
+{
+  /* Special form where register comes from opcode.  The rex.B bit is used,
+     rex.R and rex.X are ignored.  */
+  int save_prefixes = *d->prefixes;
+
+  *d->prefixes = ((save_prefixes & ~has_rex_r)
+		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
+
+  int r = FCT_reg (d);
+
+  *d->prefixes = save_prefixes;
+
+  return r;
+}
+#endif
+
+
+static int
+FCT_reg64 (struct output_data *d)
+{
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 + 3 <= 8);
+  byte >>= 8 - (d->opoff1 % 8 + 3);
+  byte &= 7;
+  if ((*d->prefixes & has_data16) != 0)
+    return -1;
+  size_t *bufcntp = d->bufcntp;
+  if (*bufcntp + 5 > d->bufsize)
+    return *bufcntp + 5 - d->bufsize;
+  d->bufp[(*bufcntp)++] = '%';
+#ifdef X86_64
+  if ((*d->prefixes & has_rex_r) != 0)
+    {
+      *bufcntp += snprintf (&d->bufp[*bufcntp], d->bufsize - *bufcntp, "r%d",
+			    8 + byte);
+      if ((*d->prefixes & has_rex_w) == 0)
+	d->bufp[(*bufcntp)++] = 'd';
+    }
+  else
+#endif
+    {
+      memcpy (&d->bufp[*bufcntp], aregs[byte], 3);
+      *bufcntp += 3;
+    }
+  return 0;
+}
+
+
+static int
+FCT_reg$w (struct output_data *d)
+{
+  if (d->data[d->opoff2 / 8] & (1 << (7 - (d->opoff2 & 7))))
+    return FCT_reg (d);
+
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 + 3 <= 8);
+  byte >>= 8 - (d->opoff1 % 8 + 3);
+  byte &= 7;
+
+  size_t *bufcntp = d->bufcntp;
+  if (*bufcntp + 4 > d->bufsize)
+    return *bufcntp + 4 - d->bufsize;
+
+  d->bufp[(*bufcntp)++] = '%';
+
+#ifdef X86_64
+  if (*d->prefixes & has_rex)
+    {
+      if (*d->prefixes & has_rex_r)
+	*bufcntp += snprintf (d->bufp + *bufcntp, d->bufsize - *bufcntp,
+			      "r%db", 8 + byte);
+      else
+	{
+	  char* cp = stpcpy (d->bufp + *bufcntp, rex_8bit[byte]);
+	  *cp++ = 'l';
+	  *bufcntp = cp - d->bufp;
+	}
+    }
+  else
+#endif
+    {
+      d->bufp[(*bufcntp)++] = "acdb"[byte & 3];
+      d->bufp[(*bufcntp)++] = "lh"[byte >> 2];
+    }
+  return 0;
+}
+
+
+#ifdef X86_64
+static int
+FCT_oreg$w (struct output_data *d)
+{
+  /* Special form where register comes from opcode.  The rex.B bit is used,
+     rex.R and rex.X are ignored.  */
+  int save_prefixes = *d->prefixes;
+
+  *d->prefixes = ((save_prefixes & ~has_rex_r)
+		  | ((save_prefixes & has_rex_b) << (idx_rex_r - idx_rex_b)));
+
+  int r = FCT_reg$w (d);
+
+  *d->prefixes = save_prefixes;
+
+  return r;
+}
+#endif
+
+
+static int
+FCT_freg (struct output_data *d)
+{
+  assert (d->opoff1 / 8 == 1);
+  assert (d->opoff1 % 8 == 5);
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%st(%" PRIx32 ")",
+			 (uint32_t) (d->data[1] & 7));
+  if ((size_t) needed > avail)
+    return (size_t) needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+#ifndef X86_64
+static int
+FCT_reg16 (struct output_data *d)
+{
+  if (*d->prefixes & has_data16)
+    return -1;
+
+  *d->prefixes |= has_data16;
+  return FCT_reg (d);
+}
+#endif
+
+
+static int
+FCT_sel (struct output_data *d)
+{
+  assert (d->opoff1 % 8 == 0);
+  assert (d->opoff1 / 8 == 5);
+  if (*d->param_start + 2 >= d->end)
+    return -1;
+  *d->param_start += 2;
+  uint16_t absval = read_2ubyte_unaligned (&d->data[5]);
+
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "$0x%" PRIx16, absval);
+  if ((size_t) needed > avail)
+    return needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
+
+
+static int
+FCT_sreg2 (struct output_data *d)
+{
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 + 3 <= 8);
+  byte >>= 8 - (d->opoff1 % 8 + 2);
+
+  size_t *bufcntp = d->bufcntp;
+  char *bufp = d->bufp;
+  if (*bufcntp + 3 > d->bufsize)
+    return *bufcntp + 3 - d->bufsize;
+
+  bufp[(*bufcntp)++] = '%';
+  bufp[(*bufcntp)++] = "ecsd"[byte & 3];
+  bufp[(*bufcntp)++] = 's';
+
+  return 0;
+}
+
+
+static int
+FCT_sreg3 (struct output_data *d)
+{
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 + 4 <= 8);
+  byte >>= 8 - (d->opoff1 % 8 + 3);
+
+  if ((byte & 7) >= 6)
+    return -1;
+
+  size_t *bufcntp = d->bufcntp;
+  char *bufp = d->bufp;
+  if (*bufcntp + 3 > d->bufsize)
+    return *bufcntp + 3 - d->bufsize;
+
+  bufp[(*bufcntp)++] = '%';
+  bufp[(*bufcntp)++] = "ecsdfg"[byte & 7];
+  bufp[(*bufcntp)++] = 's';
+
+  return 0;
+}
+
+
+static int
+FCT_string (struct output_data *d __attribute__ ((unused)))
+{
+  return 0;
+}
+
+
+static int
+FCT_xmmreg (struct output_data *d)
+{
+  uint_fast8_t byte = d->data[d->opoff1 / 8];
+  assert (d->opoff1 % 8 == 2 || d->opoff1 % 8 == 5);
+  byte = (byte >> (5 - d->opoff1 % 8)) & 7;
+
+  size_t *bufcntp = d->bufcntp;
+  size_t avail = d->bufsize - *bufcntp;
+  int needed = snprintf (&d->bufp[*bufcntp], avail, "%%xmm%" PRIxFAST8, byte);
+  if ((size_t) needed > avail)
+    return needed - avail;
+  *bufcntp += needed;
+  return 0;
+}
diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c
new file mode 100644
index 0000000..daa5b3d
--- /dev/null
+++ b/libcpu/i386_disasm.c
@@ -0,0 +1,1146 @@
+/* Disassembler for x86.
+   Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+// GOOGLE
+#include "google-dependency-inject.h"
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <config.h>
+#include <ctype.h>
+#include <errno.h>
+#include <gelf.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libeblP.h"
+
+#define MACHINE_ENCODING LITTLE_ENDIAN
+#include "memory-access.h"
+
+#include "i386_mne.h"
+
+#define MNESTRFIELD(line) MNESTRFIELD1 (line)
+#define MNESTRFIELD1(line) str##line
+static const union mnestr_t
+{
+  struct
+  {
+#define MNE(name) char MNESTRFIELD (__LINE__)[sizeof (#name)];
+#include MNEFILE
+#undef MNE
+  };
+  char str[0];
+} mnestr =
+  {
+    {
+#define MNE(name) #name,
+#include MNEFILE
+#undef MNE
+    }
+  };
+
+static const unsigned short int mneidx[] =
+  {
+#define MNE(name) \
+  [MNE_##name] = offsetof (union mnestr_t, MNESTRFIELD (__LINE__)),
+#include MNEFILE
+#undef MNE
+  };
+
+
+enum
+  {
+    idx_rex_b = 0,
+    idx_rex_x,
+    idx_rex_r,
+    idx_rex_w,
+    idx_rex,
+    idx_cs,
+    idx_ds,
+    idx_es,
+    idx_fs,
+    idx_gs,
+    idx_ss,
+    idx_data16,
+    idx_addr16,
+    idx_rep,
+    idx_repne,
+    idx_lock
+  };
+
+enum
+  {
+#define prefbit(pref) has_##pref = 1 << idx_##pref
+    prefbit (rex_b),
+    prefbit (rex_x),
+    prefbit (rex_r),
+    prefbit (rex_w),
+    prefbit (rex),
+    prefbit (cs),
+    prefbit (ds),
+    prefbit (es),
+    prefbit (fs),
+    prefbit (gs),
+    prefbit (ss),
+    prefbit (data16),
+    prefbit (addr16),
+    prefbit (rep),
+    prefbit (repne),
+    prefbit (lock)
+#undef prefbit
+  };
+#define SEGMENT_PREFIXES \
+  (has_cs | has_ds | has_es | has_fs | has_gs | has_ss)
+
+#define prefix_cs	0x2e
+#define prefix_ds	0x3e
+#define prefix_es	0x26
+#define prefix_fs	0x64
+#define prefix_gs	0x65
+#define prefix_ss	0x36
+#define prefix_data16	0x66
+#define prefix_addr16	0x67
+#define prefix_rep	0xf3
+#define prefix_repne	0xf2
+#define prefix_lock	0xf0
+
+
+static const uint8_t known_prefixes[] =
+  {
+#define newpref(pref) [idx_##pref] = prefix_##pref
+    newpref (cs),
+    newpref (ds),
+    newpref (es),
+    newpref (fs),
+    newpref (gs),
+    newpref (ss),
+    newpref (data16),
+    newpref (addr16),
+    newpref (rep),
+    newpref (repne),
+    newpref (lock)
+#undef newpref
+  };
+#define nknown_prefixes (sizeof (known_prefixes) / sizeof (known_prefixes[0]))
+
+
+#if 0
+static const char *prefix_str[] =
+  {
+#define newpref(pref) [idx_##pref] = #pref
+    newpref (cs),
+    newpref (ds),
+    newpref (es),
+    newpref (fs),
+    newpref (gs),
+    newpref (ss),
+    newpref (data16),
+    newpref (addr16),
+    newpref (rep),
+    newpref (repne),
+    newpref (lock)
+#undef newpref
+  };
+#endif
+
+
+static const char amd3dnowstr[] =
+#define MNE_3DNOW_PAVGUSB 1
+  "pavgusb\0"
+#define MNE_3DNOW_PFADD (MNE_3DNOW_PAVGUSB + 8)
+  "pfadd\0"
+#define MNE_3DNOW_PFSUB (MNE_3DNOW_PFADD + 6)
+  "pfsub\0"
+#define MNE_3DNOW_PFSUBR (MNE_3DNOW_PFSUB + 6)
+  "pfsubr\0"
+#define MNE_3DNOW_PFACC (MNE_3DNOW_PFSUBR + 7)
+  "pfacc\0"
+#define MNE_3DNOW_PFCMPGE (MNE_3DNOW_PFACC + 6)
+  "pfcmpge\0"
+#define MNE_3DNOW_PFCMPGT (MNE_3DNOW_PFCMPGE + 8)
+  "pfcmpgt\0"
+#define MNE_3DNOW_PFCMPEQ (MNE_3DNOW_PFCMPGT + 8)
+  "pfcmpeq\0"
+#define MNE_3DNOW_PFMIN (MNE_3DNOW_PFCMPEQ + 8)
+  "pfmin\0"
+#define MNE_3DNOW_PFMAX (MNE_3DNOW_PFMIN + 6)
+  "pfmax\0"
+#define MNE_3DNOW_PI2FD (MNE_3DNOW_PFMAX + 6)
+  "pi2fd\0"
+#define MNE_3DNOW_PF2ID (MNE_3DNOW_PI2FD + 6)
+  "pf2id\0"
+#define MNE_3DNOW_PFRCP (MNE_3DNOW_PF2ID + 6)
+  "pfrcp\0"
+#define MNE_3DNOW_PFRSQRT (MNE_3DNOW_PFRCP + 6)
+  "pfrsqrt\0"
+#define MNE_3DNOW_PFMUL (MNE_3DNOW_PFRSQRT + 8)
+  "pfmul\0"
+#define MNE_3DNOW_PFRCPIT1 (MNE_3DNOW_PFMUL + 6)
+  "pfrcpit1\0"
+#define MNE_3DNOW_PFRSQIT1 (MNE_3DNOW_PFRCPIT1 + 9)
+  "pfrsqit1\0"
+#define MNE_3DNOW_PFRCPIT2 (MNE_3DNOW_PFRSQIT1 + 9)
+  "pfrcpit2\0"
+#define MNE_3DNOW_PMULHRW (MNE_3DNOW_PFRCPIT2 + 9)
+  "pmulhrw";
+
+#define AMD3DNOW_LOW_IDX 0x0d
+#define AMD3DNOW_HIGH_IDX (sizeof (amd3dnow) + AMD3DNOW_LOW_IDX - 1)
+#define AMD3DNOW_IDX(val) ((val) - AMD3DNOW_LOW_IDX)
+static const unsigned char amd3dnow[] =
+  {
+    [AMD3DNOW_IDX (0xbf)] = MNE_3DNOW_PAVGUSB,
+    [AMD3DNOW_IDX (0x9e)] = MNE_3DNOW_PFADD,
+    [AMD3DNOW_IDX (0x9a)] = MNE_3DNOW_PFSUB,
+    [AMD3DNOW_IDX (0xaa)] = MNE_3DNOW_PFSUBR,
+    [AMD3DNOW_IDX (0xae)] = MNE_3DNOW_PFACC,
+    [AMD3DNOW_IDX (0x90)] = MNE_3DNOW_PFCMPGE,
+    [AMD3DNOW_IDX (0xa0)] = MNE_3DNOW_PFCMPGT,
+    [AMD3DNOW_IDX (0xb0)] = MNE_3DNOW_PFCMPEQ,
+    [AMD3DNOW_IDX (0x94)] = MNE_3DNOW_PFMIN,
+    [AMD3DNOW_IDX (0xa4)] = MNE_3DNOW_PFMAX,
+    [AMD3DNOW_IDX (0x0d)] = MNE_3DNOW_PI2FD,
+    [AMD3DNOW_IDX (0x1d)] = MNE_3DNOW_PF2ID,
+    [AMD3DNOW_IDX (0x96)] = MNE_3DNOW_PFRCP,
+    [AMD3DNOW_IDX (0x97)] = MNE_3DNOW_PFRSQRT,
+    [AMD3DNOW_IDX (0xb4)] = MNE_3DNOW_PFMUL,
+    [AMD3DNOW_IDX (0xa6)] = MNE_3DNOW_PFRCPIT1,
+    [AMD3DNOW_IDX (0xa7)] = MNE_3DNOW_PFRSQIT1,
+    [AMD3DNOW_IDX (0xb6)] = MNE_3DNOW_PFRCPIT2,
+    [AMD3DNOW_IDX (0xb7)] = MNE_3DNOW_PMULHRW
+  };
+
+
+struct output_data
+{
+  GElf_Addr addr;
+  int *prefixes;
+  size_t opoff1;
+  size_t opoff2;
+  size_t opoff3;
+  char *bufp;
+  size_t *bufcntp;
+  size_t bufsize;
+  const uint8_t *data;
+  const uint8_t **param_start;
+  const uint8_t *end;
+  char *labelbuf;
+  size_t labelbufsize;
+  enum
+    {
+      addr_none = 0,
+      addr_abs_symbolic,
+      addr_abs_always,
+      addr_rel_symbolic,
+      addr_rel_always
+    } symaddr_use;
+  GElf_Addr symaddr;
+};
+
+
+#ifndef DISFILE
+# define DISFILE "i386_dis.h"
+#endif
+#include DISFILE
+
+
+#define ADD_CHAR(ch) \
+  do {									      \
+    if (unlikely (bufcnt == bufsize))					      \
+      goto enomem;							      \
+    buf[bufcnt++] = (ch);						      \
+  } while (0)
+
+#define ADD_STRING(str) \
+  do {									      \
+    const char *_str0 = (str);						      \
+    size_t _len0 = strlen (_str0);					      \
+    ADD_NSTRING (_str0, _len0);						      \
+  } while (0)
+
+#define ADD_NSTRING(str, len) \
+  do {									      \
+    const char *_str = (str);						      \
+    size_t _len = (len);						      \
+    if (unlikely (bufcnt + _len > bufsize))				      \
+      goto enomem;							      \
+    memcpy (buf + bufcnt, _str, _len);					      \
+    bufcnt += _len;							      \
+  } while (0)
+
+
+int
+i386_disasm (Ebl *ebl __attribute__((unused)),
+	     const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
+	     const char *fmt, DisasmOutputCB_t outcb, DisasmGetSymCB_t symcb,
+	     void *outcbarg, void *symcbarg)
+{
+  const char *save_fmt = fmt;
+
+#define BUFSIZE 512
+  char initbuf[BUFSIZE];
+  int prefixes;
+  size_t bufcnt;
+  size_t bufsize = BUFSIZE;
+  char *buf = initbuf;
+  const uint8_t *param_start;
+
+  struct output_data output_data =
+    {
+      .prefixes = &prefixes,
+      .bufp = buf,
+      .bufsize = bufsize,
+      .bufcntp = &bufcnt,
+      .param_start = &param_start,
+      .end = end
+    };
+
+  int retval = 0;
+  while (1)
+    {
+      prefixes = 0;
+
+      const uint8_t *data = *startp;
+      const uint8_t *begin = data;
+
+      /* Recognize all prefixes.  */
+      int last_prefix_bit = 0;
+      while (data < end)
+	{
+	  unsigned int i;
+	  for (i = idx_cs; i < nknown_prefixes; ++i)
+	    if (known_prefixes[i] == *data)
+	      break;
+	  if (i == nknown_prefixes)
+	    break;
+
+	  prefixes |= last_prefix_bit = 1 << i;
+
+	  ++data;
+	}
+
+#ifdef X86_64
+      if (data < end && (*data & 0xf0) == 0x40)
+	prefixes |= ((*data++) & 0xf) | has_rex;
+#endif
+
+      bufcnt = 0;
+      size_t cnt = 0;
+
+      const uint8_t *curr = match_data;
+      const uint8_t *const match_end = match_data + sizeof (match_data);
+
+      assert (data <= end);
+      if (data == end)
+	{
+	  if (prefixes != 0)
+	    goto print_prefix;
+
+	  retval = -1;
+	  goto do_ret;
+	}
+
+    next_match:
+      while (curr < match_end)
+	{
+	  uint_fast8_t len = *curr++;
+	  uint_fast8_t clen = len >> 4;
+	  len &= 0xf;
+	  const uint8_t *next_curr = curr + clen + (len - clen) * 2;
+
+	  assert (len > 0);
+	  assert (curr + clen + 2 * (len - clen) <= match_end);
+
+	  const uint8_t *codep = data;
+	  int correct_prefix = 0;
+	  int opoff = 0;
+
+	  if (data > begin && codep[-1] == *curr && clen > 0)
+	    {
+	      /* We match a prefix byte.  This is exactly one byte and
+		 is matched exactly, without a mask.  */
+	      --len;
+	      --clen;
+	      opoff = 8;
+
+	      ++curr;
+
+	      if (last_prefix_bit == 0)
+		goto invalid_op;
+	      correct_prefix = last_prefix_bit;
+	    }
+
+	  size_t avail = len;
+	  while (clen > 0)
+	    {
+	      if (*codep++ != *curr++)
+		goto not;
+	      --avail;
+	      --clen;
+	      if (codep == end && avail > 0)
+		goto do_ret;
+	    }
+
+	  while (avail > 0)
+	    {
+	      uint_fast8_t masked = *codep++ & *curr++;
+	      if (masked != *curr++)
+		{
+		not:
+		  curr = next_curr;
+		  ++cnt;
+		  bufcnt = 0;
+		  goto next_match;
+		}
+
+	      --avail;
+	      if (codep == end && avail > 0)
+		goto do_ret;
+	    }
+
+	  if (len > end - data)
+	    /* There is not enough data for the entire instruction.  The
+	       caller can figure this out by looking at the pointer into
+	       the input data.  */
+	    goto do_ret;
+
+	  if (correct_prefix != 0 && (prefixes & correct_prefix) == 0)
+	    goto invalid_op;
+	  prefixes ^= correct_prefix;
+
+	  if (0)
+	    {
+	      /* Resize the buffer.  */
+	      char *oldbuf;
+	    enomem:
+	      oldbuf = buf;
+	      if (buf == initbuf)
+		buf = malloc (2 * bufsize);
+	      else
+		buf = realloc (buf, 2 * bufsize);
+	      if (buf == NULL)
+		{
+		  buf = oldbuf;
+		  retval = ENOMEM;
+		  goto do_ret;
+		}
+	      bufsize *= 2;
+
+	      output_data.bufp = buf;
+	      output_data.bufsize = bufsize;
+	      bufcnt = 0;
+
+	      if (data == end)
+		{
+		  if (prefixes == 0)
+		    goto invalid_op;
+		  goto print_prefix;
+		}
+
+	      /* gcc is not clever enough to see the following variables
+		 are not used uninitialized.  */
+	      __asm (""
+		     : "=mr" (opoff), "=mr" (correct_prefix), "=mr" (codep),
+		     "=mr" (next_curr), "=mr" (len));
+	    }
+
+	  size_t prefix_size = 0;
+
+	  // XXXonly print as prefix if valid?
+	  if ((prefixes & has_lock) != 0)
+	    {
+	      ADD_STRING ("lock ");
+	      prefix_size += 5;
+	    }
+
+	  if (instrtab[cnt].rep)
+	    {
+	      if ((prefixes & has_rep) !=  0)
+		{
+		  ADD_STRING ("rep ");
+		  prefix_size += 4;
+		}
+	    }
+	  else if (instrtab[cnt].repe
+		   && (prefixes & (has_rep | has_repne)) != 0)
+	    {
+	      if ((prefixes & has_repne) != 0)
+		{
+		  ADD_STRING ("repne ");
+		  prefix_size += 6;
+		}
+	      else if ((prefixes & has_rep) != 0)
+		{
+		  ADD_STRING ("repe ");
+		  prefix_size += 5;
+		}
+	    }
+	  else if ((prefixes & (has_rep | has_repne)) != 0)
+	    {
+	      uint_fast8_t byte;
+	    print_prefix:
+	      bufcnt = 0;
+	      byte = *begin;
+	      /* This is a prefix byte.  Print it.  */
+	      switch (byte)
+		{
+		case prefix_rep:
+		  ADD_STRING ("rep");
+		  break;
+		case prefix_repne:
+		  ADD_STRING ("repne");
+		  break;
+		case prefix_cs:
+		  ADD_STRING ("cs");
+		  break;
+		case prefix_ds:
+		  ADD_STRING ("ds");
+		  break;
+		case prefix_es:
+		  ADD_STRING ("es");
+		  break;
+		case prefix_fs:
+		  ADD_STRING ("fs");
+		  break;
+		case prefix_gs:
+		  ADD_STRING ("gs");
+		  break;
+		case prefix_ss:
+		  ADD_STRING ("ss");
+		  break;
+		case prefix_data16:
+		  ADD_STRING ("data16");
+		  break;
+		case prefix_addr16:
+		  ADD_STRING ("addr16");
+		  break;
+		case prefix_lock:
+		  ADD_STRING ("lock");
+		  break;
+#ifdef X86_64
+		case 0x40 ... 0x4f:
+		  ADD_STRING ("rex");
+		  if (byte != 0x40)
+		    {
+		      ADD_CHAR ('.');
+		      if (byte & 0x8)
+			ADD_CHAR ('w');
+		      if (byte & 0x4)
+			ADD_CHAR ('r');
+		      if (byte & 0x3)
+			ADD_CHAR ('x');
+		      if (byte & 0x1)
+			ADD_CHAR ('b');
+		    }
+		  break;
+#endif
+		default:
+		  /* Cannot happen.  */
+		  puts ("unknown prefix");
+		  abort ();
+		}
+	      data = begin + 1;
+	      ++addr;
+
+	      goto out;
+	    }
+
+	  /* We have a match.  First determine how many bytes are
+	     needed for the addressing mode.  */
+	  param_start = codep;
+	  if (instrtab[cnt].modrm)
+	    {
+	      uint_fast8_t modrm = codep[-1];
+
+#ifndef X86_64
+	      if (likely ((prefixes & has_addr16) != 0))
+		{
+		  /* Account for displacement.  */
+		  if ((modrm & 0xc7) == 6 || (modrm & 0xc0) == 0x80)
+		    param_start += 2;
+		  else if ((modrm & 0xc0) == 0x40)
+		    param_start += 1;
+		}
+	      else
+#endif
+		{
+		  /* Account for SIB.  */
+		  if ((modrm & 0xc0) != 0xc0 && (modrm & 0x7) == 0x4)
+		    param_start += 1;
+
+		  /* Account for displacement.  */
+		  if ((modrm & 0xc7) == 5 || (modrm & 0xc0) == 0x80
+		      || ((modrm & 0xc7) == 0x4
+			  && param_start < end
+			  && (codep[0] & 0x7) == 0x5))
+		    param_start += 4;
+		  else if ((modrm & 0xc0) == 0x40)
+		    param_start += 1;
+		}
+
+	      if (unlikely (param_start > end))
+		goto not;
+	    }
+
+	  output_data.addr = addr + (data - begin);
+	  output_data.data = data;
+
+	  unsigned long string_end_idx = 0;
+	  fmt = save_fmt;
+	  const char *deferred_start = NULL;
+	  size_t deferred_len = 0;
+	  // XXX Can we get this from color.c?
+	  static const char color_off[] = "\e[0m";
+	  while (*fmt != '\0')
+	    {
+	      if (*fmt != '%')
+		{
+		  char ch = *fmt++;
+		  if (ch == '\\')
+		    {
+		      switch ((ch = *fmt++))
+			{
+			case '0' ... '7':
+			  {
+			    int val = ch - '0';
+			    ch = *fmt;
+			    if (ch >= '0' && ch <= '7')
+			      {
+				val *= 8;
+				val += ch - '0';
+				ch = *++fmt;
+				if (ch >= '0' && ch <= '7' && val < 32)
+				  {
+				    val *= 8;
+				    val += ch - '0';
+				    ++fmt;
+				  }
+			      }
+			    ch = val;
+			  }
+			  break;
+
+			case 'n':
+			  ch = '\n';
+			  break;
+
+			case 't':
+			  ch = '\t';
+			  break;
+
+			default:
+			  retval = EINVAL;
+			  goto do_ret;
+			}
+		    }
+		  else if (ch == '\e' && *fmt == '[')
+		    {
+		      deferred_start = fmt - 1;
+		      do
+			++fmt;
+		      while (*fmt != 'm' && *fmt != '\0');
+
+		      if (*fmt == 'm')
+			{
+			  deferred_len = ++fmt - deferred_start;
+			  continue;
+			}
+
+		      fmt = deferred_start + 1;
+		      deferred_start = NULL;
+		    }
+		  ADD_CHAR (ch);
+		  continue;
+		}
+	      ++fmt;
+
+	      int width = 0;
+	      while (isdigit (*fmt))
+		width = width * 10 + (*fmt++ - '0');
+
+	      int prec = 0;
+	      if (*fmt == '.')
+		while (isdigit (*++fmt))
+		  prec = prec * 10 + (*fmt - '0');
+
+	      size_t start_idx = bufcnt;
+	      size_t non_printing = 0;
+	      switch (*fmt++)
+		{
+		  char mnebuf[16];
+		  const char *str;
+
+		case 'm':
+		  /* Mnemonic.  */
+
+		  if (unlikely (instrtab[cnt].mnemonic == MNE_INVALID))
+		    {
+		      switch (*data)
+			{
+#ifdef X86_64
+			case 0x90:
+			  if (prefixes & has_rex_b)
+			    goto not;
+			  str = "nop";
+			  break;
+#endif
+
+			case 0x98:
+#ifdef X86_64
+			  if (prefixes == (has_rex_w | has_rex))
+			    {
+			      str = "cltq";
+			      break;
+			    }
+#endif
+			  if (prefixes & ~has_data16)
+			    goto print_prefix;
+			  str = prefixes & has_data16 ? "cbtw" : "cwtl";
+			  break;
+
+			case 0x99:
+#ifdef X86_64
+			  if (prefixes == (has_rex_w | has_rex))
+			    {
+			      str = "cqto";
+			      break;
+			    }
+#endif
+			  if (prefixes & ~has_data16)
+			    goto print_prefix;
+			  str = prefixes & has_data16 ? "cwtd" : "cltd";
+			  break;
+
+			case 0xe3:
+			  if (prefixes & ~has_addr16)
+			    goto print_prefix;
+#ifdef X86_64
+			  str = prefixes & has_addr16 ? "jecxz" : "jrcxz";
+#else
+			  str = prefixes & has_addr16 ? "jcxz" : "jecxz";
+#endif
+			  break;
+
+			case 0x0f:
+			  if (data[1] == 0x0f)
+			    {
+			      /* AMD 3DNOW.  We need one more byte.  */
+			      if (param_start >= end)
+				goto not;
+			      if (*param_start < AMD3DNOW_LOW_IDX
+				  || *param_start > AMD3DNOW_HIGH_IDX)
+				goto not;
+			      unsigned int idx
+				= amd3dnow[AMD3DNOW_IDX (*param_start)];
+			      if (idx == 0)
+				goto not;
+			      str = amd3dnowstr + idx - 1;
+			      /* Eat the immediate byte indicating the
+				 operation.  */
+			      ++param_start;
+			      break;
+			    }
+#ifdef X86_64
+			  if (data[1] == 0xc7)
+			    {
+			      str = ((prefixes & has_rex_w)
+				     ? "cmpxchg16b" : "cmpxchg8b");
+			      break;
+			    }
+#endif
+			  if (data[1] == 0xc2)
+			    {
+			      if (param_start >= end)
+				goto not;
+			      if (*param_start > 7)
+				goto not;
+			      static const char cmpops[][9] =
+				{
+				  [0] = "cmpeq",
+				  [1] = "cmplt",
+				  [2] = "cmple",
+				  [3] = "cmpunord",
+				  [4] = "cmpneq",
+				  [5] = "cmpnlt",
+				  [6] = "cmpnle",
+				  [7] = "cmpord"
+				};
+			      char *cp = stpcpy (mnebuf, cmpops[*param_start]);
+			      if (correct_prefix & (has_rep | has_repne))
+				*cp++ = 's';
+			      else
+				*cp++ = 'p';
+			      if (correct_prefix & (has_data16 | has_repne))
+				*cp++ = 'd';
+			      else
+				*cp++ = 's';
+			      *cp = '\0';
+			      str = mnebuf;
+			      /* Eat the immediate byte indicating the
+				 operation.  */
+			      ++param_start;
+			      break;
+			    }
+			  FALLTHROUGH;
+			default:
+			  str = "INVALID not handled";
+			  break;
+			}
+		    }
+		  else
+		    str = mnestr.str + mneidx[instrtab[cnt].mnemonic];
+
+		  if (deferred_start != NULL)
+		    {
+		      ADD_NSTRING (deferred_start, deferred_len);
+		      non_printing += deferred_len;
+		    }
+
+		  ADD_STRING (str);
+
+		  switch (instrtab[cnt].suffix)
+		    {
+		    case suffix_none:
+		      break;
+
+		    case suffix_w:
+		      if ((codep[-1] & 0xc0) != 0xc0)
+			{
+			  char ch;
+
+			  if (data[0] & 1)
+			    {
+			      if (prefixes & has_data16)
+				ch = 'w';
+#ifdef X86_64
+			      else if (prefixes & has_rex_w)
+				ch = 'q';
+#endif
+			      else
+				ch = 'l';
+			    }
+			  else
+			    ch = 'b';
+
+			  ADD_CHAR (ch);
+			}
+		      break;
+
+		    case suffix_w0:
+		      if ((codep[-1] & 0xc0) != 0xc0)
+			ADD_CHAR ('l');
+		      break;
+
+		    case suffix_w1:
+		      if ((data[0] & 0x4) == 0)
+			ADD_CHAR ('l');
+		      break;
+
+		    case suffix_W:
+		      if (prefixes & has_data16)
+			{
+			  ADD_CHAR ('w');
+			  prefixes &= ~has_data16;
+			}
+#ifdef X86_64
+		      else
+			ADD_CHAR ('q');
+#endif
+		      break;
+
+		    case suffix_W1:
+		      if (prefixes & has_data16)
+			{
+			  ADD_CHAR ('w');
+			  prefixes &= ~has_data16;
+			}
+#ifdef X86_64
+		      else if (prefixes & has_rex_w)
+			ADD_CHAR ('q');
+#endif
+		      break;
+
+		    case suffix_tttn:;
+		      static const char tttn[16][3] =
+			{
+			  "o", "no", "b", "ae", "e", "ne", "be", "a",
+			  "s", "ns", "p", "np", "l", "ge", "le", "g"
+			};
+		      ADD_STRING (tttn[codep[-1 - instrtab[cnt].modrm] & 0x0f]);
+		      break;
+
+		    case suffix_D:
+		      if ((codep[-1] & 0xc0) != 0xc0)
+			ADD_CHAR ((data[0] & 0x04) == 0 ? 's' : 'l');
+		      break;
+
+		    default:
+		      printf("unknown suffix %d\n", instrtab[cnt].suffix);
+		      abort ();
+		    }
+
+		  if (deferred_start != NULL)
+		    {
+		      ADD_STRING (color_off);
+		      non_printing += strlen (color_off);
+		    }
+
+		  string_end_idx = bufcnt;
+		  break;
+
+		case 'o':
+		  if (prec == 1 && instrtab[cnt].fct1 != 0)
+		    {
+		      /* First parameter.  */
+		      if (deferred_start != NULL)
+			{
+			  ADD_NSTRING (deferred_start, deferred_len);
+			  non_printing += deferred_len;
+			}
+
+		      if (instrtab[cnt].str1 != 0)
+			ADD_STRING (op1_str
+				    + op1_str_idx[instrtab[cnt].str1 - 1]);
+
+		      output_data.opoff1 = (instrtab[cnt].off1_1
+					    + OFF1_1_BIAS - opoff);
+		      output_data.opoff2 = (instrtab[cnt].off1_2
+					    + OFF1_2_BIAS - opoff);
+		      output_data.opoff3 = (instrtab[cnt].off1_3
+					    + OFF1_3_BIAS - opoff);
+		      int r = op1_fct[instrtab[cnt].fct1] (&output_data);
+		      if (r < 0)
+			goto not;
+		      if (r > 0)
+			goto enomem;
+
+		      if (deferred_start != NULL)
+			{
+			  ADD_STRING (color_off);
+			  non_printing += strlen (color_off);
+			}
+
+		      string_end_idx = bufcnt;
+		    }
+		  else if (prec == 2 && instrtab[cnt].fct2 != 0)
+		    {
+		      /* Second parameter.  */
+		      if (deferred_start != NULL)
+			{
+			  ADD_NSTRING (deferred_start, deferred_len);
+			  non_printing += deferred_len;
+			}
+
+		      if (instrtab[cnt].str2 != 0)
+			ADD_STRING (op2_str
+				    + op2_str_idx[instrtab[cnt].str2 - 1]);
+
+		      output_data.opoff1 = (instrtab[cnt].off2_1
+					    + OFF2_1_BIAS - opoff);
+		      output_data.opoff2 = (instrtab[cnt].off2_2
+					    + OFF2_2_BIAS - opoff);
+		      output_data.opoff3 = (instrtab[cnt].off2_3
+					    + OFF2_3_BIAS - opoff);
+		      int r = op2_fct[instrtab[cnt].fct2] (&output_data);
+		      if (r < 0)
+			goto not;
+		      if (r > 0)
+			goto enomem;
+
+		      if (deferred_start != NULL)
+			{
+			  ADD_STRING (color_off);
+			  non_printing += strlen (color_off);
+			}
+
+		      string_end_idx = bufcnt;
+		    }
+		  else if (prec == 3 && instrtab[cnt].fct3 != 0)
+		    {
+		      /* Third parameter.  */
+		      if (deferred_start != NULL)
+			{
+			  ADD_NSTRING (deferred_start, deferred_len);
+			  non_printing += deferred_len;
+			}
+
+		      if (instrtab[cnt].str3 != 0)
+			ADD_STRING (op3_str
+				    + op3_str_idx[instrtab[cnt].str3 - 1]);
+
+		      output_data.opoff1 = (instrtab[cnt].off3_1
+					    + OFF3_1_BIAS - opoff);
+		      output_data.opoff2 = (instrtab[cnt].off3_2
+					    + OFF3_2_BIAS - opoff);
+#ifdef OFF3_3_BITS
+		      output_data.opoff3 = (instrtab[cnt].off3_3
+					    + OFF3_3_BIAS - opoff);
+#else
+		      output_data.opoff3 = 0;
+#endif
+		      int r = op3_fct[instrtab[cnt].fct3] (&output_data);
+		      if (r < 0)
+			goto not;
+		      if (r > 0)
+			goto enomem;
+
+		      if (deferred_start != NULL)
+			{
+			  ADD_STRING (color_off);
+			  non_printing += strlen (color_off);
+			}
+
+		      string_end_idx = bufcnt;
+		    }
+		  else
+		    start_idx = bufcnt = string_end_idx;
+		  break;
+
+		case 'e':
+		  string_end_idx = bufcnt;
+		  break;
+
+		case 'a':
+		  /* Pad to requested column.  */
+		  while (bufcnt - non_printing < (size_t) width)
+		    ADD_CHAR (' ');
+		  width = 0;
+		  break;
+
+		case 'l':
+		  if (deferred_start != NULL)
+		    {
+		      ADD_NSTRING (deferred_start, deferred_len);
+		      non_printing += deferred_len;
+		    }
+
+		  if (output_data.labelbuf != NULL
+		      && output_data.labelbuf[0] != '\0')
+		    {
+		      ADD_STRING (output_data.labelbuf);
+		      output_data.labelbuf[0] = '\0';
+		      string_end_idx = bufcnt;
+		    }
+		  else if (output_data.symaddr_use != addr_none)
+		    {
+		      GElf_Addr symaddr = output_data.symaddr;
+		      if (output_data.symaddr_use >= addr_rel_symbolic)
+			symaddr += addr + param_start - begin;
+
+		      // XXX Lookup symbol based on symaddr
+		      const char *symstr = NULL;
+		      if (symcb != NULL
+			  && symcb (0 /* XXX */, 0 /* XXX */, symaddr,
+				    &output_data.labelbuf,
+				    &output_data.labelbufsize, symcbarg) == 0)
+			symstr = output_data.labelbuf;
+
+		      size_t bufavail = bufsize - bufcnt;
+		      int r = 0;
+		      if (symstr != NULL)
+			r = snprintf (&buf[bufcnt], bufavail, "# <%s>",
+				      symstr);
+		      else if (output_data.symaddr_use == addr_abs_always
+			       || output_data.symaddr_use == addr_rel_always)
+			r = snprintf (&buf[bufcnt], bufavail, "# %#" PRIx64,
+				      (uint64_t) symaddr);
+
+		      assert (r >= 0);
+		      if ((size_t) r >= bufavail)
+			goto enomem;
+		      bufcnt += r;
+		      string_end_idx = bufcnt;
+
+		      output_data.symaddr_use = addr_none;
+		    }
+		  if (deferred_start != NULL)
+		    {
+		      ADD_STRING (color_off);
+		      non_printing += strlen (color_off);
+		    }
+		  break;
+
+		default:
+		  abort ();
+		}
+
+	      deferred_start = NULL;
+
+	      /* Pad according to the specified width.  */
+	      while (bufcnt + prefix_size - non_printing < start_idx + width)
+		ADD_CHAR (' ');
+	      prefix_size = 0;
+	    }
+
+	  if ((prefixes & SEGMENT_PREFIXES) != 0)
+	    goto print_prefix;
+
+	  assert (string_end_idx != ~0ul);
+	  bufcnt = string_end_idx;
+
+	  addr += param_start - begin;
+	  data = param_start;
+
+	  goto out;
+	}
+
+      /* Invalid (or at least unhandled) opcode.  */
+    invalid_op:
+      if (prefixes != 0)
+	goto print_prefix;
+      /* Make sure we get past the unrecognized opcode if we haven't yet.  */
+      if (*startp == data)
+	++data;
+      ADD_STRING ("(bad)");
+      addr += data - begin;
+
+    out:
+      if (bufcnt == bufsize)
+	goto enomem;
+      buf[bufcnt] = '\0';
+
+      *startp = data;
+      retval = outcb (buf, bufcnt, outcbarg);
+      if (retval != 0)
+	goto do_ret;
+    }
+
+ do_ret:
+  free (output_data.labelbuf);
+  if (buf != initbuf)
+    free (buf);
+
+  return retval;
+}
diff --git a/libcpu/i386_gendis.c b/libcpu/i386_gendis.c
new file mode 100644
index 0000000..37d2ecd
--- /dev/null
+++ b/libcpu/i386_gendis.c
@@ -0,0 +1,71 @@
+/* Generate tables for x86 disassembler.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "system.h"
+
+extern int i386_parse (void);
+
+
+extern FILE *i386_in;
+extern int i386_debug;
+char *infname;
+
+FILE *outfile;
+
+int
+main (int argc, char *argv[argc])
+{
+  outfile = stdout;
+
+  if (argc == 1)
+    error (EXIT_FAILURE, 0, "usage: %s <MNEDEFFILE>", argv[0]);
+
+  //i386_debug = 1;
+  infname = argv[1];
+  if (strcmp (infname, "-") == 0)
+    i386_in = stdin;
+  else
+    {
+      i386_in = fopen (infname, "r");
+      if (i386_in == NULL)
+	error (EXIT_FAILURE, errno, "cannot open %s", argv[1]);
+    }
+
+  i386_parse ();
+
+  return error_message_count != 0;
+}
diff --git a/libcpu/i386_lex.l b/libcpu/i386_lex.l
new file mode 100644
index 0000000..9b33ed9
--- /dev/null
+++ b/libcpu/i386_lex.l
@@ -0,0 +1,128 @@
+%{
+/* Copyright (C) 2004, 2005, 2007, 2008 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ctype.h>
+
+#include <libeu.h>
+#include "system.h"
+#include "i386_parse.h"
+
+
+static void eat_to_eol (void);
+static void invalid_char (int ch);
+%}
+
+ID              [a-zA-Z_][a-zA-Z0-9_/]*
+ID2             [a-zA-Z0-9_:/]*
+NUMBER		[0-9]+
+WHITE		[[:space:]]+
+
+%option yylineno
+%option never-interactive
+%option noyywrap
+
+
+%x MAIN
+
+%%
+
+"%mask"				{ return kMASK; }
+
+"%prefix"			{ return kPREFIX; }
+"%suffix"			{ return kSUFFIX; }
+
+"%synonym"			{ return kSYNONYM; }
+
+{NUMBER}			{ i386_lval.num = strtoul (yytext, NULL, 10);
+				  return kNUMBER; }
+
+"%%"				{ BEGIN (MAIN); return kPERCPERC; }
+
+
+<MAIN>"0"			{ return '0'; }
+<MAIN>"1"			{ return '1'; }
+
+<INITIAL,MAIN>"{"{ID2}"}"	{ i386_lval.str = xstrndup (yytext + 1,
+							    yyleng - 2);
+				  return kBITFIELD; }
+
+<MAIN>"INVALID"			{ i386_lval.str = (void *) -1l;
+				  return kID; }
+
+<MAIN>{ID}			{ i386_lval.str = xstrndup (yytext, yyleng);
+				  return kID; }
+
+<MAIN>","			{ return ','; }
+
+<MAIN>":"			{ return ':'; }
+
+<INITIAL,MAIN>^"\n"		{ /* IGNORE */ }
+
+<INITIAL,MAIN>"\n"		{ return '\n'; }
+
+<INITIAL,MAIN>^"#"		{ eat_to_eol (); }
+
+{WHITE}				{ /* IGNORE */ }
+
+<MAIN>{WHITE}			{ return kSPACE; }
+
+<MAIN>.				{ i386_lval.ch = *yytext; return kCHAR; }
+
+.				{ invalid_char (*yytext); }
+
+
+%%
+
+static void
+eat_to_eol (void)
+{
+  while (1)
+    {
+      int c = input ();
+
+      if (c == EOF || c == '\n')
+	break;
+    }
+}
+
+static void
+invalid_char (int ch)
+{
+  error (0, 0, (isascii (ch)
+		? _("invalid character '%c' at line %d; ignored")
+		: _("invalid character '\\%o' at line %d; ignored")),
+	 ch, yylineno);
+}
+
+// Local Variables:
+// mode: C
+// End:
diff --git a/libcpu/i386_mne.h b/libcpu/i386_mne.h
new file mode 100644
index 0000000..dd10a4b
--- /dev/null
+++ b/libcpu/i386_mne.h
@@ -0,0 +1,49 @@
+/* Disassembler for x86, MNE enums.
+   Copyright (C) 2007, 2008, 2009, 2011 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _I386_MNE_H
+#define _I386_MNE_H	1
+
+// GOOGLE
+#include "google-dependency-inject.h"
+
+#ifndef MNEFILE
+# define MNEFILE "i386.mnemonics"
+#endif
+
+/* The index can be stored in the instrtab.  */
+enum
+  {
+#define MNE(name) MNE_##name,
+#include MNEFILE
+#undef MNE
+    MNE_INVALID,
+    MNE_COUNT = MNE_INVALID,
+  };
+
+#endif /* i386_mne.h */
diff --git a/libcpu/i386_parse.y b/libcpu/i386_parse.y
new file mode 100644
index 0000000..459684c
--- /dev/null
+++ b/libcpu/i386_parse.y
@@ -0,0 +1,1683 @@
+%{
+/* Parser for i386 CPU description.
+   Copyright (C) 2004, 2005, 2007, 2008, 2009 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <math.h>
+#include <obstack.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libeu.h>
+#include <system.h>
+
+#include "i386_mne.h"
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+
+/* The error handler.  */
+static void yyerror (const char *s);
+
+extern int yylex (void);
+extern int i386_lineno;
+extern char *infname;
+
+
+struct known_bitfield
+{
+  char *name;
+  unsigned long int bits;
+  int tmp;
+};
+
+
+struct bitvalue
+{
+  enum bittype { zeroone, field, failure } type;
+  union
+  {
+    unsigned int value;
+    struct known_bitfield *field;
+  };
+  struct bitvalue *next;
+};
+
+
+struct argname
+{
+  enum nametype { string, nfield } type;
+  union
+  {
+    char *str;
+    struct known_bitfield *field;
+  };
+  struct argname *next;
+};
+
+
+struct argument
+{
+  struct argname *name;
+  struct argument *next;
+};
+
+
+struct instruction
+{
+  /* The byte encoding.  */
+  struct bitvalue *bytes;
+
+  /* Prefix possible.  */
+  int repe;
+  int rep;
+
+  /* Mnemonic.  */
+  char *mnemonic;
+
+  /* Suffix.  */
+  enum { suffix_none = 0, suffix_w, suffix_w0, suffix_W, suffix_tttn,
+	 suffix_w1, suffix_W1, suffix_D } suffix;
+
+  /* Flag set if modr/m is used.  */
+  int modrm;
+
+  /* Operands.  */
+  struct operand
+  {
+    char *fct;
+    char *str;
+    int off1;
+    int off2;
+    int off3;
+  } operands[3];
+
+  struct instruction *next;
+};
+
+
+struct synonym
+{
+  char *from;
+  char *to;
+};
+
+
+struct suffix
+{
+  char *name;
+  int idx;
+};
+
+
+struct argstring
+{
+  char *str;
+  int idx;
+  int off;
+};
+
+
+static struct known_bitfield ax_reg =
+  {
+    .name = "ax", .bits = 0, .tmp = 0
+  };
+
+static struct known_bitfield dx_reg =
+  {
+    .name = "dx", .bits = 0, .tmp = 0
+  };
+
+static struct known_bitfield di_reg =
+  {
+    .name = "es_di", .bits = 0, .tmp = 0
+  };
+
+static struct known_bitfield si_reg =
+  {
+    .name = "ds_si", .bits = 0, .tmp = 0
+  };
+
+static struct known_bitfield bx_reg =
+  {
+    .name = "ds_bx", .bits = 0, .tmp = 0
+  };
+
+
+static int bitfield_compare (const void *p1, const void *p2);
+static void new_bitfield (char *name, unsigned long int num);
+static void check_bits (struct bitvalue *value);
+static int check_duplicates (struct bitvalue *val);
+static int check_argsdef (struct bitvalue *bitval, struct argument *args);
+static int check_bitsused (struct bitvalue *bitval,
+			   struct known_bitfield *suffix,
+			   struct argument *args);
+static struct argname *combine (struct argname *name);
+static void fillin_arg (struct bitvalue *bytes, struct argname *name,
+			struct instruction *instr, int n);
+static void find_numbers (void);
+static int compare_syn (const void *p1, const void *p2);
+static int compare_suf (const void *p1, const void *p2);
+static void instrtable_out (void);
+#if 0
+static void create_mnemonic_table (void);
+#endif
+
+static void *bitfields;
+static struct instruction *instructions;
+static size_t ninstructions;
+static void *synonyms;
+static void *suffixes;
+static int nsuffixes;
+static void *mnemonics;
+size_t nmnemonics;
+extern FILE *outfile;
+
+/* Number of bits used mnemonics.  */
+#if 0
+static size_t best_mnemonic_bits;
+#endif
+%}
+
+%union {
+  unsigned long int num;
+  char *str;
+  char ch;
+  struct known_bitfield *field;
+  struct bitvalue *bit;
+  struct argname *name;
+  struct argument *arg;
+}
+
+%token kMASK
+%token kPREFIX
+%token kSUFFIX
+%token kSYNONYM
+%token <str> kID
+%token <num> kNUMBER
+%token kPERCPERC
+%token <str> kBITFIELD
+%token <ch> kCHAR
+%token kSPACE
+
+%type <bit> bit byte bytes
+%type <field> bitfieldopt
+%type <name> argcomp arg
+%type <arg> args optargs
+
+%defines
+
+%%
+
+spec:		  masks kPERCPERC '\n' instrs
+		    {
+		      if (error_message_count != 0)
+			error (EXIT_FAILURE, 0,
+			       "terminated due to previous error");
+
+		      instrtable_out ();
+		    }
+		;
+
+masks:		  masks '\n' mask
+		| mask
+		;
+
+mask:		  kMASK kBITFIELD kNUMBER
+		    { new_bitfield ($2, $3); }
+		| kPREFIX kBITFIELD
+		    { new_bitfield ($2, -1); }
+		| kSUFFIX kBITFIELD
+		    { new_bitfield ($2, -2); }
+		| kSYNONYM kBITFIELD kBITFIELD
+		    {
+		      struct synonym *newp = xmalloc (sizeof (*newp));
+		      newp->from = $2;
+		      newp->to = $3;
+		      if (tfind (newp, &synonyms, compare_syn) != NULL)
+			error (0, 0,
+			       "%d: duplicate definition for synonym '%s'",
+			       i386_lineno, $2);
+		      else if (tsearch ( newp, &synonyms, compare_syn) == NULL)
+			error (EXIT_FAILURE, 0, "tsearch");
+		    }
+		|
+		;
+
+instrs:		  instrs '\n' instr
+		| instr
+		;
+
+instr:		  bytes ':' bitfieldopt kID bitfieldopt optargs
+		    {
+		      if ($3 != NULL && strcmp ($3->name, "RE") != 0
+			  && strcmp ($3->name, "R") != 0)
+			{
+			  error (0, 0, "%d: only 'R' and 'RE' prefix allowed",
+				 i386_lineno - 1);
+			}
+		      if (check_duplicates ($1) == 0
+			  && check_argsdef ($1, $6) == 0
+			  && check_bitsused ($1, $5, $6) == 0)
+			{
+			  struct instruction *newp = xcalloc (sizeof (*newp),
+							      1);
+			  if ($3 != NULL)
+			    {
+			      if (strcmp ($3->name, "RE") == 0)
+				newp->repe = 1;
+			      else if (strcmp ($3->name, "R") == 0)
+				newp->rep = 1;
+			    }
+
+			  newp->bytes = $1;
+			  newp->mnemonic = $4;
+			  if (newp->mnemonic != (void *) -1l
+			      && tfind ($4, &mnemonics,
+					(int (*)(const void *, const void *)) strcmp) == NULL)
+			    {
+			      if (tsearch ($4, &mnemonics,
+					   (int (*)(const void *, const void *)) strcmp) == NULL)
+				error (EXIT_FAILURE, errno, "tsearch");
+			      ++nmnemonics;
+			    }
+
+			  if ($5 != NULL)
+			    {
+			      if (strcmp ($5->name, "w") == 0)
+				newp->suffix = suffix_w;
+			      else if (strcmp ($5->name, "w0") == 0)
+				newp->suffix = suffix_w0;
+			      else if (strcmp ($5->name, "tttn") == 0)
+				newp->suffix = suffix_tttn;
+			      else if (strcmp ($5->name, "w1") == 0)
+				newp->suffix = suffix_w1;
+			      else if (strcmp ($5->name, "W") == 0)
+				newp->suffix = suffix_W;
+			      else if (strcmp ($5->name, "W1") == 0)
+				newp->suffix = suffix_W1;
+			      else if (strcmp ($5->name, "D") == 0)
+				newp->suffix = suffix_D;
+			      else
+				error (EXIT_FAILURE, 0,
+				       "%s: %d: unknown suffix '%s'",
+				       infname, i386_lineno - 1, $5->name);
+
+			      struct suffix search = { .name = $5->name };
+			      if (tfind (&search, &suffixes, compare_suf)
+				  == NULL)
+				{
+				  struct suffix *ns = xmalloc (sizeof (*ns));
+				  ns->name = $5->name;
+				  ns->idx = ++nsuffixes;
+				  if (tsearch (ns, &suffixes, compare_suf)
+				      == NULL)
+				    error (EXIT_FAILURE, errno, "tsearch");
+				}
+			    }
+
+			  struct argument *args = $6;
+			  int n = 0;
+			  while (args != NULL)
+			    {
+			      fillin_arg ($1, args->name, newp, n);
+
+			      args = args->next;
+			      ++n;
+			    }
+
+			  newp->next = instructions;
+			  instructions = newp;
+			  ++ninstructions;
+			}
+		    }
+		|
+		;
+
+bitfieldopt:	  kBITFIELD
+		    {
+		      struct known_bitfield search;
+		      search.name = $1;
+		      struct known_bitfield **res;
+		      res = tfind (&search, &bitfields, bitfield_compare);
+		      if (res == NULL)
+			{
+			  error (0, 0, "%d: unknown bitfield '%s'",
+				 i386_lineno, search.name);
+			  $$ = NULL;
+			}
+		      else
+			$$ = *res;
+		    }
+		|
+		    { $$ = NULL; }
+		;
+
+bytes:		  bytes ',' byte
+		    {
+		      check_bits ($3);
+
+		      struct bitvalue *runp = $1;
+		      while (runp->next != NULL)
+			runp = runp->next;
+		      runp->next = $3;
+		      $$ = $1;
+		    }
+		| byte
+		    {
+		      check_bits ($1);
+		      $$ = $1;
+		    }
+		;
+
+byte:		  byte bit
+		    {
+		      struct bitvalue *runp = $1;
+		      while (runp->next != NULL)
+			runp = runp->next;
+		      runp->next = $2;
+		      $$ = $1;
+		    }
+		| bit
+		    { $$ = $1; }
+		;
+
+bit:		  '0'
+		    {
+		      $$ = xmalloc (sizeof (struct bitvalue));
+		      $$->type = zeroone;
+		      $$->value = 0;
+		      $$->next = NULL;
+		    }
+		| '1'
+		    {
+		      $$ = xmalloc (sizeof (struct bitvalue));
+		      $$->type = zeroone;
+		      $$->value = 1;
+		      $$->next = NULL;
+		    }
+		| kBITFIELD
+		    {
+		      $$ = xmalloc (sizeof (struct bitvalue));
+		      struct known_bitfield search;
+		      search.name = $1;
+		      struct known_bitfield **res;
+		      res = tfind (&search, &bitfields, bitfield_compare);
+		      if (res == NULL)
+			{
+			  error (0, 0, "%d: unknown bitfield '%s'",
+				 i386_lineno, search.name);
+			  $$->type = failure;
+			}
+		      else
+			{
+			  $$->type = field;
+			  $$->field = *res;
+			}
+		      $$->next = NULL;
+		    }
+		;
+
+optargs:	  kSPACE args
+		    { $$ = $2; }
+		|
+		    { $$ = NULL; }
+		;
+
+args:		  args ',' arg
+		    {
+		      struct argument *runp = $1;
+		      while (runp->next != NULL)
+			runp = runp->next;
+		      runp->next = xmalloc (sizeof (struct argument));
+		      runp->next->name = combine ($3);
+		      runp->next->next = NULL;
+		      $$ = $1;
+		    }
+		| arg
+		    {
+		      $$ = xmalloc (sizeof (struct argument));
+		      $$->name = combine ($1);
+		      $$->next = NULL;
+		    }
+		;
+
+arg:		  arg argcomp
+		    {
+		      struct argname *runp = $1;
+		      while (runp->next != NULL)
+			runp = runp->next;
+		      runp->next = $2;
+		      $$ = $1;
+		    }
+		| argcomp
+		    { $$ = $1; }
+		;
+argcomp:	  kBITFIELD
+		    {
+		      $$ = xmalloc (sizeof (struct argname));
+		      $$->type = nfield;
+		      $$->next = NULL;
+
+		      struct known_bitfield search;
+		      search.name = $1;
+		      struct known_bitfield **res;
+		      res = tfind (&search, &bitfields, bitfield_compare);
+		      if (res == NULL)
+			{
+			  if (strcmp ($1, "ax") == 0)
+			    $$->field = &ax_reg;
+			  else if (strcmp ($1, "dx") == 0)
+			    $$->field = &dx_reg;
+			  else if (strcmp ($1, "es_di") == 0)
+			    $$->field = &di_reg;
+			  else if (strcmp ($1, "ds_si") == 0)
+			    $$->field = &si_reg;
+			  else if (strcmp ($1, "ds_bx") == 0)
+			    $$->field = &bx_reg;
+			  else
+			    {
+			      error (0, 0, "%d: unknown bitfield '%s'",
+				     i386_lineno, search.name);
+			      $$->field = NULL;
+			    }
+			}
+		      else
+			$$->field = *res;
+		    }
+		| kCHAR
+		    {
+		      $$ = xmalloc (sizeof (struct argname));
+		      $$->type = string;
+		      $$->next = NULL;
+		      $$->str = xmalloc (2);
+		      $$->str[0] = $1;
+		      $$->str[1] = '\0';
+		    }
+		| kID
+		    {
+		      $$ = xmalloc (sizeof (struct argname));
+		      $$->type = string;
+		      $$->next = NULL;
+		      $$->str = $1;
+		    }
+		| ':'
+		    {
+		      $$ = xmalloc (sizeof (struct argname));
+		      $$->type = string;
+		      $$->next = NULL;
+		      $$->str = xmalloc (2);
+		      $$->str[0] = ':';
+		      $$->str[1] = '\0';
+		    }
+		;
+
+%%
+
+static void
+yyerror (const char *s)
+{
+  error (0, 0, _("while reading i386 CPU description: %s at line %d"),
+         _(s), i386_lineno);
+}
+
+
+static int
+bitfield_compare (const void *p1, const void *p2)
+{
+  struct known_bitfield *f1 = (struct known_bitfield *) p1;
+  struct known_bitfield *f2 = (struct known_bitfield *) p2;
+
+  return strcmp (f1->name, f2->name);
+}
+
+
+static void
+new_bitfield (char *name, unsigned long int num)
+{
+  struct known_bitfield *newp = xmalloc (sizeof (struct known_bitfield));
+  newp->name = name;
+  newp->bits = num;
+  newp->tmp = 0;
+
+  if (tfind (newp, &bitfields, bitfield_compare) != NULL)
+    {
+      error (0, 0, "%d: duplicated definition of bitfield '%s'",
+	     i386_lineno, name);
+      free (name);
+      free (newp);
+      return;
+    }
+
+  if (tsearch (newp, &bitfields, bitfield_compare) == NULL)
+    error (EXIT_FAILURE, errno, "%d: cannot insert new bitfield '%s'",
+	   i386_lineno, name);
+}
+
+
+/* Check that the number of bits is a multiple of 8.  */
+static void
+check_bits (struct bitvalue *val)
+{
+  struct bitvalue *runp = val;
+  unsigned int total = 0;
+
+  while (runp != NULL)
+    {
+      if (runp->type == zeroone)
+	++total;
+      else if (runp->field == NULL)
+	/* No sense doing anything, the field is not known.  */
+	return;
+      else
+	total += runp->field->bits;
+
+      runp = runp->next;
+    }
+
+  if (total % 8 != 0)
+    {
+      struct obstack os;
+      obstack_init (&os);
+
+      while (val != NULL)
+	{
+	  if (val->type == zeroone)
+	    obstack_printf (&os, "%u", val->value);
+	  else
+	    obstack_printf (&os, "{%s}", val->field->name);
+	  val = val->next;
+	}
+      obstack_1grow (&os, '\0');
+
+      error (0, 0, "%d: field '%s' not a multiple of 8 bits in size",
+	     i386_lineno, (char *) obstack_finish (&os));
+
+      obstack_free (&os, NULL);
+    }
+}
+
+
+static int
+check_duplicates (struct bitvalue *val)
+{
+  static int testcnt;
+  ++testcnt;
+
+  int result = 0;
+  while (val != NULL)
+    {
+      if (val->type == field && val->field != NULL)
+	{
+	  if (val->field->tmp == testcnt)
+	    {
+	      error (0, 0, "%d: bitfield '%s' used more than once",
+		     i386_lineno - 1, val->field->name);
+	      result = 1;
+	    }
+	  val->field->tmp = testcnt;
+	}
+
+      val = val->next;
+    }
+
+  return result;
+}
+
+
+static int
+check_argsdef (struct bitvalue *bitval, struct argument *args)
+{
+  int result = 0;
+
+  while (args != NULL)
+    {
+      for (struct argname *name = args->name; name != NULL; name = name->next)
+	if (name->type == nfield && name->field != NULL
+	    && name->field != &ax_reg && name->field != &dx_reg
+	    && name->field != &di_reg && name->field != &si_reg
+	    && name->field != &bx_reg)
+	  {
+	    struct bitvalue *runp = bitval;
+
+	    while (runp != NULL)
+	      if (runp->type == field && runp->field == name->field)
+		break;
+	      else
+		runp = runp->next;
+
+	    if (runp == NULL)
+	      {
+		error (0, 0, "%d: unknown bitfield '%s' used in output format",
+		       i386_lineno - 1, name->field->name);
+		result = 1;
+	      }
+	  }
+
+      args = args->next;
+    }
+
+  return result;
+}
+
+
+static int
+check_bitsused (struct bitvalue *bitval, struct known_bitfield *suffix,
+		struct argument *args)
+{
+  int result = 0;
+
+  while (bitval != NULL)
+    {
+      if (bitval->type == field && bitval->field != NULL
+	  && bitval->field != suffix
+	  /* {w} is handled special.  */
+	  && strcmp (bitval->field->name, "w") != 0)
+	{
+	  struct argument *runp;
+	  for (runp = args; runp != NULL; runp = runp->next)
+	    {
+	      struct argname *name = runp->name;
+
+	      while (name != NULL)
+		if (name->type == nfield && name->field == bitval->field)
+		  break;
+		else
+		  name = name->next;
+
+	      if (name != NULL)
+		break;
+	    }
+
+#if 0
+	  if (runp == NULL)
+	    {
+	      error (0, 0, "%d: bitfield '%s' not used",
+		     i386_lineno - 1, bitval->field->name);
+	      result = 1;
+	    }
+#endif
+	}
+
+      bitval = bitval->next;
+    }
+
+  return result;
+}
+
+
+static struct argname *
+combine (struct argname *name)
+{
+  struct argname *last_str = NULL;
+  for (struct argname *runp = name; runp != NULL; runp = runp->next)
+    {
+      if (runp->type == string)
+	{
+	  if (last_str == NULL)
+	    last_str = runp;
+	  else
+	    {
+	      last_str->str = xrealloc (last_str->str,
+					strlen (last_str->str)
+					+ strlen (runp->str) + 1);
+	      strcat (last_str->str, runp->str);
+	      last_str->next = runp->next;
+	    }
+	}
+      else
+	last_str = NULL;
+    }
+  return name;
+}
+
+
+#define obstack_grow_str(ob, str) obstack_grow (ob, str, strlen (str))
+
+
+static void
+fillin_arg (struct bitvalue *bytes, struct argname *name,
+	    struct instruction *instr, int n)
+{
+  static struct obstack ob;
+  static int initialized;
+  if (! initialized)
+    {
+      initialized = 1;
+      obstack_init (&ob);
+    }
+
+  struct argname *runp = name;
+  int cnt = 0;
+  while (runp != NULL)
+    {
+      /* We ignore strings in the function name.  */
+      if (runp->type == string)
+	{
+	  if (instr->operands[n].str != NULL)
+	    error (EXIT_FAILURE, 0,
+		   "%d: cannot have more than one string parameter",
+		   i386_lineno - 1);
+
+	  instr->operands[n].str = runp->str;
+	}
+      else
+	{
+	  assert (runp->type == nfield);
+
+	  /* Construct the function name.  */
+	  if (cnt++ > 0)
+	    obstack_1grow (&ob, '$');
+
+	  if (runp->field == NULL)
+	    /* Add some string which contains invalid characters.  */
+	    obstack_grow_str (&ob, "!!!INVALID!!!");
+	  else
+	    {
+	      char *fieldname = runp->field->name;
+
+	      struct synonym search = { .from = fieldname };
+
+	      struct synonym **res = tfind (&search, &synonyms, compare_syn);
+	      if (res != NULL)
+		fieldname = (*res)->to;
+
+	      obstack_grow_str (&ob, fieldname);
+	    }
+
+	  /* Now compute the bit offset of the field.  */
+	  struct bitvalue *b = bytes;
+	  int bitoff = 0;
+	  if (runp->field != NULL)
+	    while (b != NULL)
+	      {
+		if (b->type == field && b->field != NULL)
+		  {
+		    if (strcmp (b->field->name, runp->field->name) == 0)
+		      break;
+		    bitoff += b->field->bits;
+		  }
+		else
+		  ++bitoff;
+
+		b = b->next;
+	      }
+	  if (instr->operands[n].off1 == 0)
+	    instr->operands[n].off1 = bitoff;
+	  else if (instr->operands[n].off2 == 0)
+	    instr->operands[n].off2 = bitoff;
+	  else if (instr->operands[n].off3 == 0)
+	    instr->operands[n].off3 = bitoff;
+	  else
+	    error (EXIT_FAILURE, 0,
+		   "%d: cannot have more than three fields in parameter",
+		   i386_lineno - 1);
+
+	  if  (runp->field != NULL
+	       && strncasecmp (runp->field->name, "mod", 3) == 0)
+	    instr->modrm = 1;
+	}
+
+      runp = runp->next;
+    }
+  if (obstack_object_size (&ob) == 0)
+    obstack_grow_str (&ob, "string");
+  obstack_1grow (&ob, '\0');
+  char *fct = obstack_finish (&ob);
+
+  instr->operands[n].fct = fct;
+}
+
+
+#if 0
+static void
+nameout (const void *nodep, VISIT value, int level)
+{
+  if (value == leaf || value == postorder)
+    printf ("  %s\n", *(const char **) nodep);
+}
+#endif
+
+
+static int
+compare_argstring (const void *p1, const void *p2)
+{
+  const struct argstring *a1 = (const struct argstring *) p1;
+  const struct argstring *a2 = (const struct argstring *) p2;
+
+  return strcmp (a1->str, a2->str);
+}
+
+
+static int maxoff[3][3];
+static int minoff[3][3] = { { 1000, 1000, 1000 },
+			    { 1000, 1000, 1000 },
+			    { 1000, 1000, 1000 } };
+static int nbitoff[3][3];
+static void *fct_names[3];
+static int nbitfct[3];
+static int nbitsuf;
+static void *strs[3];
+static int nbitstr[3];
+static int total_bits = 2;	// Already counted the rep/repe bits.
+
+static void
+find_numbers (void)
+{
+  int nfct_names[3] = { 0, 0, 0 };
+  int nstrs[3] = { 0, 0, 0 };
+
+  /* We reverse the order of the instruction list while processing it.
+     Later phases need it in the order in which the input file has
+     them.  */
+  struct instruction *reversed = NULL;
+
+  struct instruction *runp = instructions;
+  while (runp != NULL)
+    {
+      for (int i = 0; i < 3; ++i)
+	if (runp->operands[i].fct != NULL)
+	  {
+	    struct argstring search = { .str = runp->operands[i].fct };
+	    if (tfind (&search, &fct_names[i], compare_argstring) == NULL)
+	      {
+		struct argstring *newp = xmalloc (sizeof (*newp));
+		newp->str = runp->operands[i].fct;
+		newp->idx = 0;
+		if (tsearch (newp, &fct_names[i], compare_argstring) == NULL)
+		  error (EXIT_FAILURE, errno, "tsearch");
+		++nfct_names[i];
+	      }
+
+	    if (runp->operands[i].str != NULL)
+	      {
+		search.str = runp->operands[i].str;
+		if (tfind (&search, &strs[i], compare_argstring) == NULL)
+		  {
+		    struct argstring *newp = xmalloc (sizeof (*newp));
+		    newp->str = runp->operands[i].str;
+		    newp->idx = 0;
+		    if (tsearch (newp, &strs[i], compare_argstring) == NULL)
+		      error (EXIT_FAILURE, errno, "tsearch");
+		    ++nstrs[i];
+		  }
+	      }
+
+	    maxoff[i][0] = MAX (maxoff[i][0], runp->operands[i].off1);
+	    maxoff[i][1] = MAX (maxoff[i][1], runp->operands[i].off2);
+	    maxoff[i][2] = MAX (maxoff[i][2], runp->operands[i].off3);
+
+	    if (runp->operands[i].off1 > 0)
+	      minoff[i][0] = MIN (minoff[i][0], runp->operands[i].off1);
+	    if (runp->operands[i].off2 > 0)
+	      minoff[i][1] = MIN (minoff[i][1], runp->operands[i].off2);
+	    if (runp->operands[i].off3 > 0)
+	      minoff[i][2] = MIN (minoff[i][2], runp->operands[i].off3);
+	  }
+
+      struct instruction *old = runp;
+      runp = runp->next;
+
+      old->next = reversed;
+      reversed = old;
+    }
+  instructions = reversed;
+
+  int d;
+  int c;
+  for (int i = 0; i < 3; ++i)
+    {
+      // printf ("min1 = %d, min2 = %d, min3 = %d\n", minoff[i][0], minoff[i][1], minoff[i][2]);
+      // printf ("max1 = %d, max2 = %d, max3 = %d\n", maxoff[i][0], maxoff[i][1], maxoff[i][2]);
+
+      if (minoff[i][0] == 1000)
+	nbitoff[i][0] = 0;
+      else
+	{
+	  nbitoff[i][0] = 1;
+	  d = maxoff[i][0] - minoff[i][0];
+	  c = 1;
+	  while (c < d)
+	    {
+	      ++nbitoff[i][0];
+	      c *= 2;
+	    }
+	  total_bits += nbitoff[i][0];
+	}
+
+      if (minoff[i][1] == 1000)
+	nbitoff[i][1] = 0;
+      else
+	{
+	  nbitoff[i][1] = 1;
+	  d = maxoff[i][1] - minoff[i][1];
+	  c = 1;
+	  while (c < d)
+	    {
+	      ++nbitoff[i][1];
+	      c *= 2;
+	    }
+	  total_bits += nbitoff[i][1];
+	}
+
+      if (minoff[i][2] == 1000)
+	nbitoff[i][2] = 0;
+      else
+	{
+	  nbitoff[i][2] = 1;
+	  d = maxoff[i][2] - minoff[i][2];
+	  c = 1;
+	  while (c < d)
+	    {
+	      ++nbitoff[i][2];
+	      c *= 2;
+	    }
+	  total_bits += nbitoff[i][2];
+	}
+      // printf ("off1 = %d, off2 = %d, off3 = %d\n", nbitoff[i][0], nbitoff[i][1], nbitoff[i][2]);
+
+      nbitfct[i] = 1;
+      d = nfct_names[i];
+      c = 1;
+      while (c < d)
+	{
+	  ++nbitfct[i];
+	  c *= 2;
+	}
+      total_bits += nbitfct[i];
+      // printf ("%d fct[%d], %d bits\n", nfct_names[i], i, nbitfct[i]);
+
+      if (nstrs[i] != 0)
+	{
+	  nbitstr[i] = 1;
+	  d = nstrs[i];
+	  c = 1;
+	  while (c < d)
+	    {
+	      ++nbitstr[i];
+	      c *= 2;
+	    }
+	  total_bits += nbitstr[i];
+	}
+
+      // twalk (fct_names[i], nameout);
+    }
+
+  nbitsuf = 0;
+  d = nsuffixes;
+  c = 1;
+  while (c < d)
+    {
+      ++nbitsuf;
+      c *= 2;
+    }
+  total_bits += nbitsuf;
+  // printf ("%d suffixes, %d bits\n", nsuffixes, nbitsuf);
+}
+
+
+static int
+compare_syn (const void *p1, const void *p2)
+{
+  const struct synonym *s1 = (const struct synonym *) p1;
+  const struct synonym *s2 = (const struct synonym *) p2;
+
+  return strcmp (s1->from, s2->from);
+}
+
+
+static int
+compare_suf (const void *p1, const void *p2)
+{
+  const struct suffix *s1 = (const struct suffix *) p1;
+  const struct suffix *s2 = (const struct suffix *) p2;
+
+  return strcmp (s1->name, s2->name);
+}
+
+
+static int count_op_str;
+static int off_op_str;
+static void
+print_op_str (const void *nodep, VISIT value,
+	      int level __attribute__ ((unused)))
+{
+  if (value == leaf || value == postorder)
+    {
+      const char *str = (*(struct argstring **) nodep)->str;
+      fprintf (outfile, "%s\n  \"%s",
+	       count_op_str == 0 ? "" : "\\0\"", str);
+      (*(struct argstring **) nodep)->idx = ++count_op_str;
+      (*(struct argstring **) nodep)->off = off_op_str;
+      off_op_str += strlen (str) + 1;
+    }
+}
+
+
+static void
+print_op_str_idx (const void *nodep, VISIT value,
+		  int level __attribute__ ((unused)))
+{
+  if (value == leaf || value == postorder)
+    printf ("  %d,\n", (*(struct argstring **) nodep)->off);
+}
+
+
+static void
+print_op_fct (const void *nodep, VISIT value,
+	      int level __attribute__ ((unused)))
+{
+  if (value == leaf || value == postorder)
+    {
+      fprintf (outfile, "  FCT_%s,\n", (*(struct argstring **) nodep)->str);
+      (*(struct argstring **) nodep)->idx = ++count_op_str;
+    }
+}
+
+static void
+instrtable_out (void)
+{
+  find_numbers ();
+
+#if 0
+  create_mnemonic_table ();
+
+  fprintf (outfile, "#define MNEMONIC_BITS %zu\n", best_mnemonic_bits);
+#else
+  fprintf (outfile, "#define MNEMONIC_BITS %ld\n",
+	   lrint (ceil (log2 (MNE_COUNT))));
+#endif
+  fprintf (outfile, "#define SUFFIX_BITS %d\n", nbitsuf);
+  for (int i = 0; i < 3; ++i)
+    {
+      fprintf (outfile, "#define FCT%d_BITS %d\n", i + 1, nbitfct[i]);
+      if (nbitstr[i] != 0)
+	fprintf (outfile, "#define STR%d_BITS %d\n", i + 1, nbitstr[i]);
+      fprintf (outfile, "#define OFF%d_1_BITS %d\n", i + 1, nbitoff[i][0]);
+      fprintf (outfile, "#define OFF%d_1_BIAS %d\n", i + 1, minoff[i][0]);
+      if (nbitoff[i][1] != 0)
+	{
+	  fprintf (outfile, "#define OFF%d_2_BITS %d\n", i + 1, nbitoff[i][1]);
+	  fprintf (outfile, "#define OFF%d_2_BIAS %d\n", i + 1, minoff[i][1]);
+	}
+      if (nbitoff[i][2] != 0)
+	{
+	  fprintf (outfile, "#define OFF%d_3_BITS %d\n", i + 1, nbitoff[i][2]);
+	  fprintf (outfile, "#define OFF%d_3_BIAS %d\n", i + 1, minoff[i][2]);
+	}
+    }
+
+  fputs ("\n#include <i386_data.h>\n\n", outfile);
+
+
+#define APPEND(a, b) APPEND_ (a, b)
+#define APPEND_(a, b) a##b
+#define EMIT_SUFFIX(suf) \
+  fprintf (outfile, "#define suffix_%s %d\n", #suf, APPEND (suffix_, suf))
+  EMIT_SUFFIX (none);
+  EMIT_SUFFIX (w);
+  EMIT_SUFFIX (w0);
+  EMIT_SUFFIX (W);
+  EMIT_SUFFIX (tttn);
+  EMIT_SUFFIX (D);
+  EMIT_SUFFIX (w1);
+  EMIT_SUFFIX (W1);
+
+  fputc_unlocked ('\n', outfile);
+
+  for (int i = 0; i < 3; ++i)
+    {
+      /* Functions.  */
+      count_op_str = 0;
+      fprintf (outfile, "static const opfct_t op%d_fct[] =\n{\n  NULL,\n",
+	       i + 1);
+      twalk (fct_names[i], print_op_fct);
+      fputs ("};\n", outfile);
+
+      /* The operand strings.  */
+      if (nbitstr[i] != 0)
+	{
+	  count_op_str = 0;
+	  off_op_str = 0;
+	  fprintf (outfile, "static const char op%d_str[] =", i + 1);
+	  twalk (strs[i], print_op_str);
+	  fputs ("\";\n", outfile);
+
+	  fprintf (outfile, "static const uint8_t op%d_str_idx[] = {\n",
+		   i + 1);
+	  twalk (strs[i], print_op_str_idx);
+	  fputs ("};\n", outfile);
+	}
+    }
+
+
+  fputs ("static const struct instr_enc instrtab[] =\n{\n", outfile);
+  struct instruction *instr;
+  for (instr = instructions; instr != NULL; instr = instr->next)
+    {
+      fputs ("  {", outfile);
+      if (instr->mnemonic == (void *) -1l)
+	fputs (" .mnemonic = MNE_INVALID,", outfile);
+      else
+	fprintf (outfile, " .mnemonic = MNE_%s,", instr->mnemonic);
+      fprintf (outfile, " .rep = %d,", instr->rep);
+      fprintf (outfile, " .repe = %d,", instr->repe);
+      fprintf (outfile, " .suffix = %d,", instr->suffix);
+      fprintf (outfile, " .modrm = %d,", instr->modrm);
+
+      for (int i = 0; i < 3; ++i)
+	{
+	  int idx = 0;
+	  if (instr->operands[i].fct != NULL)
+	    {
+	      struct argstring search = { .str = instr->operands[i].fct };
+	      struct argstring **res = tfind (&search, &fct_names[i],
+					      compare_argstring);
+	      assert (res != NULL);
+	      idx = (*res)->idx;
+	    }
+	  fprintf (outfile, " .fct%d = %d,", i + 1, idx);
+
+	  idx = 0;
+	  if (instr->operands[i].str != NULL)
+	    {
+	      struct argstring search = { .str = instr->operands[i].str };
+	      struct argstring **res = tfind (&search, &strs[i],
+					      compare_argstring);
+	      assert (res != NULL);
+	      idx = (*res)->idx;
+	    }
+	  if (nbitstr[i] != 0)
+	    fprintf (outfile, " .str%d = %d,", i + 1, idx);
+
+	  fprintf (outfile, " .off%d_1 = %d,", i + 1,
+		   MAX (0, instr->operands[i].off1 - minoff[i][0]));
+
+	  if (nbitoff[i][1] != 0)
+	    fprintf (outfile, " .off%d_2 = %d,", i + 1,
+		     MAX (0, instr->operands[i].off2 - minoff[i][1]));
+
+	  if (nbitoff[i][2] != 0)
+	    fprintf (outfile, " .off%d_3 = %d,", i + 1,
+		     MAX (0, instr->operands[i].off3 - minoff[i][2]));
+	}
+
+      fputs (" },\n", outfile);
+    }
+  fputs ("};\n", outfile);
+
+  fputs ("static const uint8_t match_data[] =\n{\n", outfile);
+  size_t cnt = 0;
+  for (instr = instructions; instr != NULL; instr = instr->next, ++cnt)
+    {
+      /* First count the number of bytes.  */
+      size_t totalbits = 0;
+      size_t zerobits = 0;
+      bool leading_p = true;
+      size_t leadingbits = 0;
+      struct bitvalue *b = instr->bytes;
+      while (b != NULL)
+	{
+	  if (b->type == zeroone)
+	    {
+	      ++totalbits;
+	      zerobits = 0;
+	      if (leading_p)
+		++leadingbits;
+	    }
+	  else
+	    {
+	      totalbits += b->field->bits;
+	      /* We must always count the mod/rm byte.  */
+	      if (strncasecmp (b->field->name, "mod", 3) == 0)
+		zerobits = 0;
+	      else
+		zerobits += b->field->bits;
+	      leading_p = false;
+	    }
+	  b = b->next;
+	}
+      size_t nbytes = (totalbits - zerobits + 7) / 8;
+      assert (nbytes > 0);
+      size_t leadingbytes = leadingbits / 8;
+
+      fprintf (outfile, "  %#zx,", nbytes | (leadingbytes << 4));
+
+      /* Now create the mask and byte values.  */
+      uint8_t byte = 0;
+      uint8_t mask = 0;
+      int nbits = 0;
+      b = instr->bytes;
+      while (b != NULL)
+	{
+	  if (b->type == zeroone)
+	    {
+	      byte = (byte << 1) | b->value;
+	      mask = (mask << 1) | 1;
+	      if (++nbits == 8)
+		{
+		  if (leadingbytes > 0)
+		    {
+		      assert (mask == 0xff);
+		      fprintf (outfile, " %#" PRIx8 ",", byte);
+		      --leadingbytes;
+		    }
+		  else
+		    fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+			     mask, byte);
+		  byte = mask = nbits = 0;
+		  if (--nbytes == 0)
+		    break;
+		}
+	    }
+	  else
+	    {
+	      assert (leadingbytes == 0);
+
+	      unsigned long int remaining = b->field->bits;
+	      while (nbits + remaining > 8)
+		{
+		  fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",",
+			   mask << (8 - nbits), byte << (8 - nbits));
+		  remaining = nbits + remaining - 8;
+		  byte = mask = nbits = 0;
+		  if (--nbytes == 0)
+		    break;
+		}
+	      byte <<= remaining;
+	      mask <<= remaining;
+	      nbits += remaining;
+	      if (nbits == 8)
+		{
+		  fprintf (outfile, " %#" PRIx8 ", %#" PRIx8 ",", mask, byte);
+		  byte = mask = nbits = 0;
+		  if (--nbytes == 0)
+		    break;
+		}
+	    }
+	  b = b->next;
+	}
+
+      fputc_unlocked ('\n', outfile);
+    }
+  fputs ("};\n", outfile);
+}
+
+
+#if 0
+static size_t mnemonic_maxlen;
+static size_t mnemonic_minlen;
+static size_t
+which_chars (const char *str[], size_t nstr)
+{
+  char used_char[256];
+  memset (used_char, '\0', sizeof (used_char));
+  mnemonic_maxlen = 0;
+  mnemonic_minlen = 10000;
+  for (size_t cnt = 0; cnt < nstr; ++cnt)
+    {
+      const unsigned char *cp = (const unsigned char *) str[cnt];
+      mnemonic_maxlen = MAX (mnemonic_maxlen, strlen ((char *) cp));
+      mnemonic_minlen = MIN (mnemonic_minlen, strlen ((char *) cp));
+      do
+        used_char[*cp++] = 1;
+      while (*cp != '\0');
+    }
+  size_t nused_char = 0;
+  for (size_t cnt = 0; cnt < 256; ++cnt)
+    if (used_char[cnt] != 0)
+      ++nused_char;
+  return nused_char;
+}
+
+
+static const char **mnemonic_strs;
+static size_t nmnemonic_strs;
+static void
+add_mnemonics (const void *nodep, VISIT value,
+	       int level __attribute__ ((unused)))
+{
+  if (value == leaf || value == postorder)
+    mnemonic_strs[nmnemonic_strs++] = *(const char **) nodep;
+}
+
+
+struct charfreq
+{
+  char ch;
+  int freq;
+};
+static struct charfreq pfxfreq[256];
+static struct charfreq sfxfreq[256];
+
+
+static int
+compare_freq (const void *p1, const void *p2)
+{
+  const struct charfreq *c1 = (const struct charfreq *) p1;
+  const struct charfreq *c2 = (const struct charfreq *) p2;
+
+  if (c1->freq > c2->freq)
+    return -1;
+  if (c1->freq < c2->freq)
+    return 1;
+  return 0;
+}
+
+
+static size_t
+compute_pfxfreq (const char *str[], size_t nstr)
+{
+  memset (pfxfreq, '\0', sizeof (pfxfreq));
+
+  for (size_t i = 0; i < nstr; ++i)
+    pfxfreq[i].ch = i;
+
+  for (size_t i = 0; i < nstr; ++i)
+    ++pfxfreq[*((const unsigned char *) str[i])].freq;
+
+  qsort (pfxfreq, 256, sizeof (struct charfreq), compare_freq);
+
+  size_t n = 0;
+  while (n < 256 && pfxfreq[n].freq != 0)
+    ++n;
+  return n;
+}
+
+
+struct strsnlen
+{
+  const char *str;
+  size_t len;
+};
+
+static size_t
+compute_sfxfreq (size_t nstr, struct strsnlen *strsnlen)
+{
+  memset (sfxfreq, '\0', sizeof (sfxfreq));
+
+  for (size_t i = 0; i < nstr; ++i)
+    sfxfreq[i].ch = i;
+
+  for (size_t i = 0; i < nstr; ++i)
+    ++sfxfreq[((const unsigned char *) strchrnul (strsnlen[i].str, '\0'))[-1]].freq;
+
+  qsort (sfxfreq, 256, sizeof (struct charfreq), compare_freq);
+
+  size_t n = 0;
+  while (n < 256 && sfxfreq[n].freq != 0)
+    ++n;
+  return n;
+}
+
+
+static void
+create_mnemonic_table (void)
+{
+  mnemonic_strs = xmalloc (nmnemonics * sizeof (char *));
+
+  twalk (mnemonics, add_mnemonics);
+
+  (void) which_chars (mnemonic_strs, nmnemonic_strs);
+
+  size_t best_so_far = 100000000;
+  char *best_prefix = NULL;
+  char *best_suffix = NULL;
+  char *best_table = NULL;
+  size_t best_table_size = 0;
+  size_t best_table_bits = 0;
+  size_t best_prefix_bits = 0;
+
+  /* We can precompute the prefix characters.  */
+  size_t npfx_char = compute_pfxfreq (mnemonic_strs, nmnemonic_strs);
+
+  /* Compute best size for string representation including explicit NUL.  */
+  for (size_t pfxbits = 0; (1u << pfxbits) < 2 * npfx_char; ++pfxbits)
+    {
+      char prefix[1 << pfxbits];
+      size_t i;
+      for (i = 0; i < (1u << pfxbits) - 1; ++i)
+	prefix[i] = pfxfreq[i].ch;
+      prefix[i] = '\0';
+
+      struct strsnlen strsnlen[nmnemonic_strs];
+
+      for (i = 0; i < nmnemonic_strs; ++i)
+	{
+	  if (strchr (prefix, *mnemonic_strs[i]) != NULL)
+	    strsnlen[i].str = mnemonic_strs[i] + 1;
+	  else
+	    strsnlen[i].str = mnemonic_strs[i];
+	  strsnlen[i].len = strlen (strsnlen[i].str);
+	}
+
+      /* With the prefixes gone, try to combine strings.  */
+      size_t nstrsnlen = 1;
+      for (i = 1; i < nmnemonic_strs; ++i)
+	{
+	  size_t j;
+	  for (j = 0; j < nstrsnlen; ++j)
+	    if (strsnlen[i].len > strsnlen[j].len
+		&& strcmp (strsnlen[j].str,
+			   strsnlen[i].str + (strsnlen[i].len
+					      - strsnlen[j].len)) == 0)
+	      {
+		strsnlen[j] = strsnlen[i];
+		break;
+	      }
+	    else if (strsnlen[i].len < strsnlen[j].len
+		     && strcmp (strsnlen[i].str,
+				strsnlen[j].str + (strsnlen[j].len
+						   - strsnlen[i].len)) == 0)
+	      break;
+;
+	  if (j == nstrsnlen)
+	      strsnlen[nstrsnlen++] = strsnlen[i];
+	}
+
+      size_t nsfx_char = compute_sfxfreq (nstrsnlen, strsnlen);
+
+      for (size_t sfxbits = 0; (1u << sfxbits) < 2 * nsfx_char; ++sfxbits)
+	{
+	  char suffix[1 << sfxbits];
+
+	  for (i = 0; i < (1u << sfxbits) - 1; ++i)
+	    suffix[i] = sfxfreq[i].ch;
+	  suffix[i] = '\0';
+
+	  size_t newlen[nstrsnlen];
+
+	  for (i = 0; i < nstrsnlen; ++i)
+	    if (strchr (suffix, strsnlen[i].str[strsnlen[i].len - 1]) != NULL)
+	      newlen[i] = strsnlen[i].len - 1;
+	    else
+	      newlen[i] = strsnlen[i].len;
+
+	  char charused[256];
+	  memset (charused, '\0', sizeof (charused));
+	  size_t ncharused = 0;
+
+	  const char *tablestr[nstrsnlen];
+	  size_t ntablestr = 1;
+	  tablestr[0] = strsnlen[0].str;
+	  size_t table = newlen[0] + 1;
+	  for (i = 1; i < nstrsnlen; ++i)
+	    {
+	      size_t j;
+	      for (j = 0; j < ntablestr; ++j)
+		if (newlen[i] > newlen[j]
+		    && memcmp (tablestr[j],
+			       strsnlen[i].str + (newlen[i] - newlen[j]),
+			       newlen[j]) == 0)
+		  {
+		    table += newlen[i] - newlen[j];
+		    tablestr[j] = strsnlen[i].str;
+		    newlen[j] = newlen[i];
+		    break;
+		  }
+		else if (newlen[i] < newlen[j]
+		     && memcmp (strsnlen[i].str,
+				tablestr[j] + (newlen[j] - newlen[i]),
+				newlen[i]) == 0)
+		  break;
+
+	      if (j == ntablestr)
+		{
+		  table += newlen[i] + 1;
+		  tablestr[ntablestr] = strsnlen[i].str;
+		  newlen[ntablestr] = newlen[i];
+
+		  ++ntablestr;
+		}
+
+	      for (size_t x = 0; x < newlen[j]; ++x)
+		if (charused[((const unsigned char *) tablestr[j])[x]]++ == 0)
+		  ++ncharused;
+	    }
+
+	  size_t ncharused_bits = 0;
+	  i = 1;
+	  while (i < ncharused)
+	    {
+	      i *= 2;
+	      ++ncharused_bits;
+	    }
+
+	  size_t table_bits = 0;
+	  i = 1;
+	  while (i < table)
+	    {
+	      i *= 2;
+	      ++table_bits;
+	    }
+
+	  size_t mnemonic_bits = table_bits + pfxbits + sfxbits;
+	  size_t new_total = (((table + 7) / 8) * ncharused_bits + ncharused
+			      + (pfxbits == 0 ? 0 : (1 << pfxbits) - 1)
+			      + (sfxbits == 0 ? 0 : (1 << sfxbits) - 1)
+			      + (((total_bits + mnemonic_bits + 7) / 8)
+				 * ninstructions));
+
+	  if (new_total < best_so_far)
+	    {
+	      best_so_far = new_total;
+	      best_mnemonic_bits = mnemonic_bits;
+
+	      free (best_suffix);
+	      best_suffix = xstrdup (suffix);
+
+	      free (best_prefix);
+	      best_prefix = xstrdup (prefix);
+	      best_prefix_bits = pfxbits;
+
+	      best_table_size = table;
+	      best_table_bits = table_bits;
+	      char *cp = best_table = xrealloc (best_table, table);
+	      for (i = 0; i < ntablestr; ++i)
+		{
+		  assert (cp + newlen[i] + 1 <= best_table + table);
+		  cp = mempcpy (cp, tablestr[i], newlen[i]);
+		  *cp++ = '\0';
+		}
+	      assert (cp == best_table + table);
+	    }
+	}
+    }
+
+  fputs ("static const char mnemonic_table[] =\n\"", outfile);
+  for (size_t i = 0; i < best_table_size; ++i)
+    {
+      if (((i + 1) % 60) == 0)
+	fputs ("\"\n\"", outfile);
+      if (!isascii (best_table[i]) || !isprint (best_table[i]))
+	fprintf (outfile, "\\%03o", best_table[i]);
+      else
+	fputc (best_table[i], outfile);
+    }
+  fputs ("\";\n", outfile);
+
+  if (best_prefix[0] != '\0')
+    fprintf (outfile,
+	     "static const char prefix[%zu] = \"%s\";\n"
+	     "#define PREFIXCHAR_BITS %zu\n",
+	     strlen (best_prefix), best_prefix, best_prefix_bits);
+  else
+    fputs ("#define NO_PREFIX\n", outfile);
+
+  if (best_suffix[0] != '\0')
+    fprintf (outfile, "static const char suffix[%zu] = \"%s\";\n",
+	     strlen (best_suffix), best_suffix);
+  else
+    fputs ("#define NO_SUFFIX\n", outfile);
+
+  for (size_t i = 0; i < nmnemonic_strs; ++i)
+    {
+      const char *mne = mnemonic_strs[i];
+
+      size_t pfxval = 0;
+      char *cp = strchr (best_prefix, *mne);
+      if (cp != NULL)
+	{
+	  pfxval = 1 + (cp - best_prefix);
+	  ++mne;
+	}
+
+      size_t l = strlen (mne);
+
+      size_t sfxval = 0;
+      cp = strchr (best_suffix, mne[l - 1]);
+      if (cp != NULL)
+	{
+	  sfxval = 1 + (cp - best_suffix);
+	  --l;
+	}
+
+      char *off = memmem (best_table, best_table_size, mne, l);
+      while (off[l] != '\0')
+	{
+	  off = memmem (off + 1, best_table_size, mne, l);
+	  assert (off != NULL);
+	}
+
+      fprintf (outfile, "#define MNE_%s %#zx\n",
+	       mnemonic_strs[i],
+	       (off - best_table)
+	       + ((pfxval + (sfxval << best_prefix_bits)) << best_table_bits));
+    }
+}
+#endif
diff --git a/libcpu/memory-access.h b/libcpu/memory-access.h
new file mode 100644
index 0000000..6e92fc5
--- /dev/null
+++ b/libcpu/memory-access.h
@@ -0,0 +1,181 @@
+/* Unaligned memory access functionality.
+   Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MEMORY_ACCESS_H
+#define _MEMORY_ACCESS_H 1
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <system.h>
+
+/* When loading this file we require the macro MACHINE_ENCODING to be
+   defined to signal the endianness of the architecture which is
+   defined.  */
+#ifndef MACHINE_ENCODING
+# error "MACHINE_ENCODING needs to be defined"
+#endif
+#if MACHINE_ENCODING != BIG_ENDIAN && MACHINE_ENCODING != LITTLE_ENDIAN
+# error "MACHINE_ENCODING must signal either big or little endian"
+#endif
+
+
+/* We use simple memory access functions in case the hardware allows it.
+   The caller has to make sure we don't have alias problems.  */
+#if ALLOW_UNALIGNED
+
+# define read_2ubyte_unaligned(Addr) \
+  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
+   ? bswap_16 (*((const uint16_t *) (Addr)))				      \
+   : *((const uint16_t *) (Addr)))
+# define read_2sbyte_unaligned(Addr) \
+  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
+   ? (int16_t) bswap_16 (*((const int16_t *) (Addr)))			      \
+   : *((const int16_t *) (Addr)))
+
+# define read_4ubyte_unaligned_noncvt(Addr) \
+   *((const uint32_t *) (Addr))
+# define read_4ubyte_unaligned(Addr) \
+  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
+   ? bswap_32 (*((const uint32_t *) (Addr)))				      \
+   : *((const uint32_t *) (Addr)))
+# define read_4sbyte_unaligned(Addr) \
+  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
+   ? (int32_t) bswap_32 (*((const int32_t *) (Addr)))			      \
+   : *((const int32_t *) (Addr)))
+
+# define read_8ubyte_unaligned(Addr) \
+  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
+   ? bswap_64 (*((const uint64_t *) (Addr)))				      \
+   : *((const uint64_t *) (Addr)))
+# define read_8sbyte_unaligned(Addr) \
+  (unlikely (MACHINE_ENCODING != BYTE_ORDER)				      \
+   ? (int64_t) bswap_64 (*((const int64_t *) (Addr)))			      \
+   : *((const int64_t *) (Addr)))
+
+#else
+
+union unaligned
+  {
+    void *p;
+    uint16_t u2;
+    uint32_t u4;
+    uint64_t u8;
+    int16_t s2;
+    int32_t s4;
+    int64_t s8;
+  } attribute_packed;
+
+static inline uint16_t
+read_2ubyte_unaligned (const void *p)
+{
+  const union unaligned *up = p;
+  if (MACHINE_ENCODING != BYTE_ORDER)
+    return bswap_16 (up->u2);
+  return up->u2;
+}
+static inline int16_t
+read_2sbyte_unaligned (const void *p)
+{
+  const union unaligned *up = p;
+  if (MACHINE_ENCODING != BYTE_ORDER)
+    return (int16_t) bswap_16 (up->u2);
+  return up->s2;
+}
+
+static inline uint32_t
+read_4ubyte_unaligned_noncvt (const void *p)
+{
+  const union unaligned *up = p;
+  return up->u4;
+}
+static inline uint32_t
+read_4ubyte_unaligned (const void *p)
+{
+  const union unaligned *up = p;
+  if (MACHINE_ENCODING != BYTE_ORDER)
+    return bswap_32 (up->u4);
+  return up->u4;
+}
+static inline int32_t
+read_4sbyte_unaligned (const void *p)
+{
+  const union unaligned *up = p;
+  if (MACHINE_ENCODING != BYTE_ORDER)
+    return (int32_t) bswap_32 (up->u4);
+  return up->s4;
+}
+
+static inline uint64_t
+read_8ubyte_unaligned (const void *p)
+{
+  const union unaligned *up = p;
+  if (MACHINE_ENCODING != BYTE_ORDER)
+    return bswap_64 (up->u8);
+  return up->u8;
+}
+static inline int64_t
+read_8sbyte_unaligned (const void *p)
+{
+  const union unaligned *up = p;
+  if (MACHINE_ENCODING != BYTE_ORDER)
+    return (int64_t) bswap_64 (up->u8);
+  return up->s8;
+}
+
+#endif	/* allow unaligned */
+
+
+#define read_2ubyte_unaligned_inc(Addr) \
+  ({ uint16_t t_ = read_2ubyte_unaligned (Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);		      \
+     t_; })
+#define read_2sbyte_unaligned_inc(Addr) \
+  ({ int16_t t_ = read_2sbyte_unaligned (Addr);				      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);		      \
+     t_; })
+
+#define read_4ubyte_unaligned_inc(Addr) \
+  ({ uint32_t t_ = read_4ubyte_unaligned (Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);		      \
+     t_; })
+#define read_4sbyte_unaligned_inc(Addr) \
+  ({ int32_t t_ = read_4sbyte_unaligned (Addr);				      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);		      \
+     t_; })
+
+#define read_8ubyte_unaligned_inc(Addr) \
+  ({ uint64_t t_ = read_8ubyte_unaligned (Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);		      \
+     t_; })
+#define read_8sbyte_unaligned_inc(Addr) \
+  ({ int64_t t_ = read_8sbyte_unaligned (Addr);				      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);		      \
+     t_; })
+
+#endif	/* memory-access.h */
diff --git a/libcpu/riscv_disasm.c b/libcpu/riscv_disasm.c
new file mode 100644
index 0000000..823fe9c
--- /dev/null
+++ b/libcpu/riscv_disasm.c
@@ -0,0 +1,1501 @@
+/* Disassembler for RISC-V.
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2019.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libeblP.h"
+
+#define MACHINE_ENCODING LITTLE_ENDIAN
+#include "memory-access.h"
+
+
+#define ADD_CHAR(ch) \
+  do {									      \
+    if (unlikely (bufcnt == bufsize))					      \
+      goto enomem;							      \
+    buf[bufcnt++] = (ch);						      \
+  } while (0)
+
+#define ADD_STRING(str) \
+  do {									      \
+    const char *_str0 = (str);						      \
+    size_t _len0 = strlen (_str0);					      \
+    ADD_NSTRING (_str0, _len0);						      \
+  } while (0)
+
+#define ADD_NSTRING(str, len) \
+  do {									      \
+    const char *_str = (str);						      \
+    size_t _len = (len);						      \
+    if (unlikely (bufcnt + _len > bufsize))				      \
+      goto enomem;							      \
+    memcpy (buf + bufcnt, _str, _len);					      \
+    bufcnt += _len;							      \
+  } while (0)
+
+
+static const char *regnames[32] =
+  {
+    "zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
+    "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
+    "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
+    "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
+  };
+#define REG(nr) ((char *) regnames[nr])
+#define REGP(nr) REG (8 + (nr))
+
+
+static const char *fregnames[32] =
+  {
+    "ft0", "ft1", "ft2", "ft3", "ft4", "ft5", "ft6", "ft7",
+    "fs0", "fs1", "fa0", "fa1", "fa2", "fa3", "fa4", "fa5",
+    "fa6", "fa7", "fs2", "fs3", "fs4", "fs5", "fs6", "fs7",
+    "fs8", "fs9", "fs10", "fs11", "ft8", "ft9", "ft10", "ft11"
+  };
+#define FREG(nr) ((char *) fregnames[nr])
+#define FREGP(nr) FREG (8 + (nr))
+
+
+struct known_csrs
+  {
+    uint16_t nr;
+    const char *name;
+  };
+
+static int compare_csr (const void *a, const void *b)
+{
+  const struct known_csrs *ka = (const struct known_csrs *) a;
+  const struct known_csrs *kb = (const struct known_csrs *) b;
+  if (ka->nr < kb->nr)
+    return -1;
+  return ka->nr == kb->nr ? 0 : 1;
+}
+
+
+int
+riscv_disasm (Ebl *ebl,
+	      const uint8_t **startp, const uint8_t *end, GElf_Addr addr,
+	      const char *fmt, DisasmOutputCB_t outcb,
+	      DisasmGetSymCB_t symcb __attribute__((unused)),
+	      void *outcbarg, void *symcbarg __attribute__((unused)))
+{
+  const char *const save_fmt = fmt;
+
+#define BUFSIZE 512
+  char initbuf[BUFSIZE];
+  size_t bufcnt;
+  size_t bufsize = BUFSIZE;
+  char *buf = initbuf;
+
+  int retval = 0;
+  while (1)
+    {
+      const uint8_t *data = *startp;
+      assert (data <= end);
+      if (data + 2 > end)
+	{
+	  if (data != end)
+	    retval = -1;
+	  break;
+	}
+      uint16_t first = read_2ubyte_unaligned (data);
+
+      // Determine length.
+      size_t length;
+      if ((first & 0x3) != 0x3)
+	length = 2;
+      else if ((first & 0x1f) != 0x1f)
+	length = 4;
+      else if ((first & 0x3f) != 0x3f)
+	length = 6;
+      else if ((first & 0x7f) != 0x7f)
+	length = 8;
+      else
+	{
+	  uint16_t nnn = (first >> 12) & 0x7;
+	  if (nnn != 0x7)
+	    length = 10 + 2 * nnn;
+	  else
+	    // This is invalid as of the RISC-V spec on 2019-06-21.
+	    // The instruction is at least 192 bits in size so use
+	    // this minimum size.
+	    length = 24;
+	}
+      if (data + length > end)
+	{
+	  retval = -1;
+	  break;
+	}
+
+      char *mne = NULL;
+      char mnebuf[32];
+      char *op[5] = { NULL, NULL, NULL, NULL, NULL };
+      char immbuf[32];
+      size_t len;
+      char *strp = NULL;
+      char addrbuf[32];
+      bufcnt = 0;
+      int64_t opaddr;
+      if (length == 2)
+	{
+	  size_t idx = (first >> 13) * 3 + (first & 0x3);
+	  switch (idx)
+	    {
+	    uint16_t rd;
+	    uint16_t rs1;
+	    uint16_t rs2;
+
+	    case 0:
+	      if ((first & 0x1fe0) != 0)
+		{
+		  mne = "addi";
+		  op[0] = REGP ((first & 0x1c) >> 2);
+		  op[1] = REG (2);
+		  opaddr = (((first >> 1) & 0x3c0)
+			    | ((first >> 7) & 0x30)
+			    | ((first >> 2) & 0x8)
+			    | ((first >> 4) & 0x4));
+		  snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64, opaddr);
+		  op[2] = addrbuf;
+		}
+	      else if (first == 0)
+		mne = "unimp";
+	      break;
+	    case 1:
+	      rs1 = (first >> 7) & 0x1f;
+	      int16_t nzimm = ((0 - ((first >> 7) & 0x20))
+			       | ((first >> 2) & 0x1f));
+	      if (rs1 == 0)
+	        mne = nzimm == 0 ? "nop" : "c.nop";
+	      else
+		{
+		  mne = nzimm == 0 ? "c.addi" : "addi";
+		  op[0] = op[1] = REG (rs1);
+		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId16, nzimm);
+		  op[2] = addrbuf;
+		}
+	      break;
+	    case 2:
+	      rs1 = (first >> 7) & 0x1f;
+	      op[0] = op[1] = REG (rs1);
+	      opaddr = ((first >> 7) & 0x20) | ((first >> 2) & 0x1f);
+	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
+	      op[2] = addrbuf;
+	      mne = rs1 == 0 ? "c.slli" : "slli";
+	      break;
+	    case 3:
+	      op[0] = FREGP ((first >> 2) & 0x7);
+	      opaddr = ((first << 1) & 0xc0) | ((first >> 7) & 0x38);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)",
+			opaddr, REGP ((first >> 7) & 0x7));
+	      op[1] = addrbuf;
+	      mne = "fld";
+	      break;
+	    case 4:
+	      if (ebl->class == ELFCLASS32)
+		{
+		  mne = "jal";
+		  opaddr = (((first << 3) & 0x20) | ((first >> 2) & 0xe)
+			    | ((first << 1) & 0x80) | ((first >> 1) | 0x40)
+			    | ((first << 2) & 0x400) | (first & 0xb00)
+			    | ((first >> 6) & 0x10));
+		  snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
+		  op[0] = addrbuf;
+		}
+	      else
+		{
+		  int32_t imm = (((UINT32_C (0) - ((first >> 12) & 0x1)) << 5)
+				 | ((first >> 2) & 0x1f));
+		  uint16_t reg = (first >> 7) & 0x1f;
+		  if (reg == 0)
+		    {
+		      // Reserved
+		      len = snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx16, first);
+		      strp = addrbuf;
+		    }
+		  else
+		    {
+		      if (imm == 0)
+			mne = "sext.w";
+		      else
+			{
+			  mne = "addiw";
+			  snprintf (addrbuf, sizeof (addrbuf), "%" PRId32, imm);
+			  op[2] = addrbuf;
+			}
+		      op[0] = op[1] = REG (reg);
+		    }
+		}
+	      break;
+	    case 5:
+	      op[0] = FREG ((first >> 7) & 0x1f);
+	      opaddr = ((first << 4) & 0x1c0) | ((first >> 7) & 0x20) | ((first >> 2) & 0x18);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)", opaddr, REG (2));
+	      op[1] = addrbuf;
+	      mne = "fld";
+	      break;
+	    case 6:
+	    case 18:
+	      mne = idx == 6 ? "lw" : "sw";
+	      op[0] = REGP ((first >> 2) & 0x7);
+	      opaddr = (((first >> 7) & 0x38) | ((first << 1) & 0x40)
+			| ((first >> 4) & 0x4));
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
+			opaddr, REGP ((first >> 7) & 0x7));
+	      op[1] = addrbuf;
+	      break;
+	    case 7:
+	      mne = (first & 0xf80) == 0 ? "c.li" : "li";
+	      op[0] = REG((first >> 7) & 0x1f);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId16,
+			(UINT16_C (0) - ((first >> 7) & 0x20)) | ((first >> 2) & 0x1f));
+	      op[1] = addrbuf;
+	      break;
+	    case 8:
+	      rd = ((first >> 7) & 0x1f);
+	      if (rd == 0)
+		{
+		  len = snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx16, first);
+		  strp = addrbuf;
+		}
+	      else
+		{
+		  uint16_t uimm = (((first << 4) & 0xc0)
+				   | ((first >> 7) & 0x20)
+				   | ((first >> 2) & 0x1c));
+		  mne = "lw";
+		  op[0] = REG (rd);
+		  snprintf (addrbuf, sizeof (addrbuf), "%" PRIu16 "(%s)", uimm, REG (2));
+		  op[1] = addrbuf;
+		}
+	      break;
+	    case 9:
+	      if (ebl->class == ELFCLASS32)
+		{
+		  mne = "flw";
+		  op[0] = FREGP ((first >> 2) & 0x7);
+		  opaddr = (((first << 1) & 0x40)
+		            | ((first >> 7) & 0x38)
+			    | ((first >> 4) & 0x4));
+		}
+	      else
+		{
+		  mne = "ld";
+		  op[0] = REGP ((first >> 2) & 0x7);
+		  opaddr = ((first >> 7) & 0x38) | ((first << 1) & 0xc0);
+		}
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
+			opaddr, REGP ((first >> 7) & 0x7));
+	      op[1] = addrbuf;
+	      break;
+	    case 10:
+	      if ((first & 0xf80) == (2 << 7))
+		{
+		  mne = "addi";
+		  op[0] = op[1] = REG (2);
+		  opaddr = (((first >> 2) & 0x10) | ((first << 3) & 0x20)
+			    | ((first << 1) & 0x40) | ((first << 4) & 0x180)
+			    | ((UINT64_C (0) - ((first >> 12) & 0x1)) << 9));
+		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId64, opaddr);
+		  op[2] = addrbuf;
+		}
+	      else
+		{
+		  mne = "lui";
+		  op[0] = REG((first & 0xf80) >> 7);
+		  opaddr = (((UINT64_C (0) - ((first >> 12) & 0x1)) & ~0x1f)
+			    | ((first >> 2) & 0x1f));
+		  snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr & 0xfffff);
+		  op[1] = addrbuf;
+		}
+	      break;
+	    case 11:
+	      if (ebl->class == ELFCLASS32)
+		{
+		  mne = "flw";
+		  op[0] = FREG ((first >> 7) & 0x1f);
+		  opaddr = (((first << 4) & 0xc0)
+			    | ((first >> 7) & 0x20)
+			    | ((first >> 2) & 0x1c));
+		}
+	      else
+		{
+		  mne = "ld";
+		  op[0] = REG ((first >> 7) & 0x1f);
+		  opaddr = (((first << 4) & 0x1c0)
+			    | ((first >> 7) & 0x20)
+			    | ((first >> 2) & 0x18));
+		}
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (2));
+	      op[1] = addrbuf;
+	      break;
+	    case 13:
+	      if ((first & 0xc00) != 0xc00)
+		{
+		  int16_t imm = ((first >> 7) & 0x20) | ((first >> 2) & 0x1f);
+		  if ((first & 0xc00) == 0x800)
+		    {
+		      imm |= 0 - (imm & 0x20);
+		      mne = "andi";
+		      snprintf (addrbuf, sizeof (addrbuf), "%" PRId16, imm);
+		    }
+		  else
+		    {
+		      if (ebl->class != ELFCLASS32 || imm < 32)
+			{
+			  mne = (first & 0x400) ? "srai" : "srli";
+			  if (imm == 0)
+			    {
+			      strcpy (stpcpy (mnebuf, "c."), mne);
+			      mne = mnebuf;
+			    }
+			}
+		      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx16, imm);
+		    }
+		  op[2] = addrbuf;
+		}
+	      else
+		{
+		  op[2] = REGP ((first >> 2) & 0x7);
+		  static const char *const arithmne[8] =
+		    {
+		      "sub", "xor", "or", "and", "subw", "addw", NULL, NULL
+		    };
+		  mne = (char *) arithmne[((first >> 10) & 0x4) | ((first >> 5) & 0x3)];
+		}
+		op[0] = op[1] = REGP ((first >> 7) & 0x7);
+	      break;
+	    case 14:
+	      rs1 = (first >> 7) & 0x1f;
+	      rs2 = (first >> 2) & 0x1f;
+	      op[0] = REG (rs1);
+	      if ((first & 0x1000) == 0)
+		{
+		  if (rs2 == 0)
+		    {
+		      op[1] = NULL;
+		      if (rs1 == 1)
+			{
+			  mne = "ret";
+			  op[0] = NULL;
+			}
+		      else
+			mne = "jr";
+		    }
+		  else
+		    {
+		      mne = rs1 != 0 ? "mv" : "c.mv";
+		      op[1] = REG (rs2);
+		    }
+		}
+	      else
+		{
+		  if (rs2 == 0)
+		    {
+		      if (rs1 == 0)
+			{
+			  mne = "ebreak";
+			  op[0] = op[1] = NULL;
+			}
+		      else
+			mne = "jalr";
+		    }
+		  else
+		    {
+		      mne = rs1 != 0 ? "add" : "c.add";
+		      op[2] = REG (rs2);
+		      op[1] = op[0];
+		    }
+		}
+	      break;
+	    case 15:
+	      op[0] = FREGP ((first >> 2) & 0x7);
+	      opaddr = ((first << 1) & 0xc0) | ((first >> 7) & 0x38);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)",
+			opaddr, REGP ((first >> 7) & 0x7));
+	      op[1] = addrbuf;
+	      mne = "fsd";
+	      break;
+	    case 16:
+	      opaddr = (((UINT64_C (0) - ((first >> 12) & 0x1)) << 11)
+			| ((first << 2) & 0x400)
+			| ((first >> 1) & 0x300)
+			| ((first << 1) & 0x80)
+			| ((first >> 1) & 0x40)
+			| ((first << 3) & 0x20)
+			| ((first >> 7) & 0x10)
+			| ((first >> 2) & 0xe));
+	      mne = "j";
+	      // TODO translate address
+	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, addr + opaddr);
+	      op[0] = addrbuf;
+	      break;
+	    case 17:
+	      op[0] = FREG ((first >> 2) & 0x1f);
+	      opaddr = ((first >> 1) & 0x1c0) | ((first >> 7) & 0x38);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRIu64 "(%s)", opaddr, REG (2));
+	      op[1] = addrbuf;
+	      mne = "fsd";
+	      break;
+	    case 19:
+	    case 22:
+	      mne = idx == 19 ? "beqz" : "bnez";
+	      op[0] = REG (8 + ((first >> 7) & 0x7));
+	      opaddr = addr + (((UINT64_C (0) - ((first >> 12) & 0x1)) & ~0xff)
+			       | ((first << 1) & 0xc0) | ((first << 3) & 0x20)
+			       | ((first >> 7) & 0x18) |  ((first >> 2) & 0x6));
+	      // TODO translate address
+	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
+	      op[1] = addrbuf;
+	      break;
+	    case 20:
+	      op[0] = REG ((first >> 2) & 0x1f);
+	      opaddr = ((first >> 1) & 0xc0) | ((first >> 7) & 0x3c);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (2));
+	      op[1] = addrbuf;
+	      mne = "sw";
+	      break;
+	    case 21:
+	      if (idx == 18 || ebl->class == ELFCLASS32)
+		{
+		  mne = "fsw";
+		  op[0] = FREGP ((first >> 2) & 0x7);
+		  opaddr = (((first >> 7) & 0x38) | ((first << 1) & 0x40)
+			    | ((first >> 4) & 0x4));
+		}
+	      else
+		{
+		  mne = "sd";
+		  op[0] = REGP ((first >> 2) & 0x7);
+		  opaddr = ((first >> 7) & 0x38) | ((first << 1) & 0xc0);
+		}
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
+			opaddr, REGP ((first >> 7) & 0x7));
+	      op[1] = addrbuf;
+	      break;
+	    case 23:
+	      if (idx == 18 || ebl->class == ELFCLASS32)
+		{
+		  mne = "fsw";
+		  op[0] = FREG ((first & 0x7c) >> 2);
+		  opaddr = ((first & 0x1e00) >> 7) | ((first & 0x180) >> 1);
+		}
+	      else
+		{
+		  mne = "sd";
+		  op[0] = REG ((first & 0x7c) >> 2);
+		  opaddr = ((first & 0x1c00) >> 7) | ((first & 0x380) >> 1);
+		}
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (2));
+	      op[1] = addrbuf;
+	      break;
+	    default:
+	      break;
+	    }
+
+	  if (strp == NULL && mne == NULL)
+	    {
+	      len = snprintf (immbuf, sizeof (immbuf), "0x%04" PRIx16, first);
+	      strp = immbuf;
+	    }
+	}
+      else if (length == 4)
+	{
+	  uint32_t word = read_4ubyte_unaligned (data);
+	  size_t idx = (word >> 2) & 0x1f;
+
+	  switch (idx)
+	    {
+	    static const char widthchar[4] = { 's', 'd', '\0', 'q' };
+	    static const char intwidthchar[4] = { 'w', 'd', '\0', 'q' };
+	    static const char *const rndmode[8] = { "rne", "rtz", "rdn", "rup", "rmm", "???", "???", "dyn" };
+	    uint32_t rd;
+	    uint32_t rs1;
+	    uint32_t rs2;
+	    uint32_t rs3;
+	    uint32_t func;
+
+	    case 0x00:
+	    case 0x01:
+	      // LOAD and LOAD-FP
+	      rd = (word >> 7) & 0x1f;
+	      op[0] = idx == 0x00 ? REG (rd) : FREG (rd);
+	      opaddr = ((int32_t) word) >> 20;
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
+			opaddr, REG ((word >> 15) & 0x1f));
+	      op[1] = addrbuf;
+	      func = (word >> 12) & 0x7;
+	      static const char *const loadmne[8] =
+	        {
+	          "lb", "lh", "lw", "ld", "lbu", "lhu", "lwu", NULL
+	        };
+	      static const char *const floadmne[8] =
+		{
+		  NULL, NULL, "flw", "fld", "flq", NULL, NULL, NULL
+		};
+	      mne = (char *) (idx == 0x00 ? loadmne[func] : floadmne[func]);
+	      break;
+	    case 0x03:
+	      // MISC-MEM
+	      rd = (word >> 7) & 0x1f;
+	      rs1 = (word >> 15) & 0x1f;
+	      func = (word >> 12) & 0x7;
+
+	      if (word == 0x8330000f)
+		mne = "fence.tso";
+	      else if (word == 0x0000100f)
+		mne = "fence.i";
+	      else if (func == 0 && rd == 0 && rs1 == 0 && (word & 0xf0000000) == 0)
+		{
+		  static const char *const order[16] =
+		    {
+		      "unknown", "w", "r", "rw", "o", "ow", "or", "orw",
+		      "i", "iw", "ir", "irw", "io", "iow", "ior", "iorw"
+		    };
+		  uint32_t pred = (word >> 20) & 0xf;
+		  uint32_t succ = (word >> 24) & 0xf;
+		  if (pred != 0xf || succ != 0xf)
+		    {
+		      op[0] = (char *) order[succ];
+		      op[1] = (char *) order[pred];
+		     }
+		   mne = "fence";
+		}
+	      break;
+	    case 0x04:
+	    case 0x06:
+	      // OP-IMM and OP-IMM32
+	      rd = (word >> 7) & 0x1f;
+	      op[0] = REG (rd);
+	      rs1 = (word >> 15) & 0x1f;
+	      op[1] = REG (rs1);
+	      opaddr = ((int32_t) word) >> 20;
+	      static const char *const opimmmne[8] =
+		{
+		  "addi", NULL, "slti", "sltiu", "xori", NULL, "ori", "andi"
+		};
+	      func = (word >> 12) & 0x7;
+	      mne = (char *) opimmmne[func];
+	      if (mne == NULL)
+		{
+		  const uint64_t shiftmask = ebl->class == ELFCLASS32 ? 0x1f : 0x3f;
+		  if (func == 0x1 && (opaddr & ~shiftmask) == 0)
+		    mne = "slli";
+		  else if (func == 0x5 && (opaddr & ~shiftmask) == 0)
+		    mne = "srli";
+		  else if (func == 0x5 && (opaddr & ~shiftmask) == 0x400)
+		    mne = "srai";
+		  snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr & shiftmask);
+		  op[2] = addrbuf;
+		}
+	      else if (func == 0x0 && (rd != 0 || idx == 0x06) && rs1 == 0 && rd != 0)
+		{
+		  mne = "li";
+		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId64, opaddr);
+		  op[1] = addrbuf;
+		}
+	      else if (func == 0x00 && opaddr == 0)
+		{
+		  if (idx == 0x06)
+		    mne ="sext.";
+		  else if (rd == 0)
+		    {
+		      mne = "nop";
+		      op[0] = op[1] = NULL;
+		    }
+		  else
+		    mne = "mv";
+		}
+	      else if (func == 0x3 && opaddr == 1)
+		mne = "seqz";
+	      else if (func == 0x4 && opaddr == -1)
+		{
+		  mne = "not";
+		  op[2] = NULL;
+		}
+	      else
+		{
+		  snprintf (addrbuf, sizeof (addrbuf), "%" PRId64, opaddr);
+		  op[2] = addrbuf;
+
+		  if (func == 0x0 && rs1 == 0 && rd != 0)
+		    {
+		      op[1] = op[2];
+		      op[2] = NULL;
+		      mne = "li";
+		    }
+		}
+	      if (mne != NULL && idx == 0x06)
+		{
+		  mne = strcpy (mnebuf, mne);
+		  strcat (mnebuf, "w");
+		}
+	      break;
+	    case 0x05:
+	    case 0x0d:
+	      // LUI and AUIPC
+	      mne = idx == 0x05 ? "auipc" : "lui";
+	      op[0] = REG ((word >> 7) & 0x1f);
+	      opaddr = word >> 12;
+	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
+	      op[1] = addrbuf;
+	      break;
+	    case 0x08:
+	    case 0x09:
+	      // STORE and STORE-FP
+	      rs2 = (word >> 20) & 0x1f;
+	      op[0] = idx == 0x08 ? REG (rs2) : FREG (rs2);
+	      opaddr = ((((int64_t) ((int32_t) word) >> 20)) & ~0x1f) | ((word >> 7) & 0x1f);
+	      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)",
+			opaddr, REG ((word >> 15) & 0x1f));
+	      op[1] = addrbuf;
+	      func = (word >> 12) & 0x7;
+	      static const char *const storemne[8] =
+		{
+		  "sb", "sh", "sw", "sd", NULL, NULL, NULL, NULL
+		};
+	      static const char *const fstoremne[8] =
+		{
+		  NULL, NULL, "fsw", "fsd", "fsq", NULL, NULL, NULL
+		};
+	      mne = (char *) (idx == 0x08 ? storemne[func] : fstoremne[func]);
+	      break;
+	    case 0x0b:
+	      // AMO
+	      op[0] = REG ((word >> 7) & 0x1f);
+	      rs1 = (word >> 15) & 0x1f;
+	      rs2 = (word >> 20) & 0x1f;
+	      snprintf (addrbuf, sizeof (addrbuf), "(%s)", REG (rs1));
+	      op[2] = addrbuf;
+	      size_t width = (word >> 12) & 0x7;
+	      func = word >> 27;
+	      static const char *const amomne[32] =
+		{
+		  "amoadd", "amoswap", "lr", "sc", "amoxor", NULL, NULL, NULL,
+		  "amoor", NULL, NULL, NULL, "amoand", NULL, NULL, NULL,
+		  "amomin", NULL, NULL, NULL, "amomax", NULL, NULL, NULL,
+		  "amominu", NULL, NULL, NULL, "amomaxu", NULL, NULL, NULL
+		};
+	      if (amomne[func] != NULL && width >= 2 && width <= 3
+		  && (func != 0x02 || rs2 == 0))
+		{
+		  if (func == 0x02)
+		    {
+		      op[1] = op[2];
+		      op[2] = NULL;
+		    }
+		  else
+		    op[1] = REG (rs2);
+
+		  char *cp = stpcpy (mnebuf, amomne[func]);
+		  *cp++ = '.';
+		  *cp++ = "  wd    "[width];
+		  assert (cp[-1] != ' ');
+		  static const char *const aqrlstr[4] =
+		    {
+		      "", ".rl", ".aq", ".aqrl"
+		    };
+		  strcpy (cp, aqrlstr[(word >> 25) & 0x3]);
+		  mne = mnebuf;
+		}
+	      break;
+	    case 0x0c:
+	    case 0x0e:
+	      // OP and OP-32
+	      if ((word & 0xbc000000) == 0)
+		{
+		  rs1 = (word >> 15) & 0x1f;
+		  rs2 = (word >> 20) & 0x1f;
+		  op[0] = REG ((word >> 7) & 0x1f);
+		  func = ((word >> 21) & 0x10) | ((word >> 27) & 0x8) | ((word >> 12) & 0x7);
+		  static const char *const arithmne2[32] =
+		    {
+		      "add", "sll", "slt", "sltu", "xor", "srl", "or", "and",
+		      "sub", NULL, NULL, NULL, NULL, "sra", NULL, NULL,
+		      "mul", "mulh", "mulhsu", "mulhu", "div", "divu", "rem", "remu",
+		      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+		    };
+		  static const char *const arithmne3[32] =
+		    {
+		      "addw", "sllw", NULL, NULL, NULL, "srlw", NULL, NULL,
+		      "subw", NULL, NULL, NULL, NULL, "sraw", NULL, NULL,
+		      "mulw", NULL, NULL, NULL, "divw", "divuw", "remw", "remuw",
+		      NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL
+		    };
+		  if (func == 8 && rs1 == 0)
+		    {
+		      mne = idx == 0x0c ? "neg" : "negw";
+		      op[1] = REG (rs2);
+		    }
+		  else if (idx == 0x0c && rs2 == 0 && func == 2)
+		    {
+		      op[1] = REG (rs1);
+		      mne = "sltz";
+		    }
+		  else if (idx == 0x0c && rs1 == 0 && (func == 2 || func == 3))
+		    {
+		      op[1] = REG (rs2);
+		      mne = func == 2 ? "sgtz" : "snez";
+		    }
+		  else
+		    {
+		      mne = (char *) (idx == 0x0c ? arithmne2[func] : arithmne3[func]);
+		      op[1] = REG (rs1);
+		      op[2] = REG (rs2);
+		    }
+		}
+	      break;
+	    case 0x10:
+	    case 0x11:
+	    case 0x12:
+	    case 0x13:
+	      // MADD, MSUB, NMSUB, NMADD
+	      if ((word & 0x06000000) != 0x04000000)
+		{
+		  rd = (word >> 7) & 0x1f;
+		  rs1 = (word >> 15) & 0x1f;
+		  rs2 = (word >> 20) & 0x1f;
+		  rs3 = (word >> 27) & 0x1f;
+		  uint32_t rm = (word >> 12) & 0x7;
+		  width = (word >> 25) & 0x3;
+
+		  static const char *const fmamne[4] =
+		    {
+		      "fmadd.", "fmsub.", "fnmsub.", "fnmadd."
+		    };
+		  char *cp = stpcpy (mnebuf, fmamne[idx & 0x3]);
+		  *cp++ = widthchar[width];
+		  *cp = '\0';
+		  mne = mnebuf;
+		  op[0] = FREG (rd);
+		  op[1] = FREG (rs1);
+		  op[2] = FREG (rs2);
+		  op[3] = FREG (rs3);
+		  if (rm != 0x7)
+		    op[4] = (char *) rndmode[rm];
+		}
+	      break;
+	    case 0x14:
+	      // OP-FP
+	      if ((word & 0x06000000) != 0x04000000)
+		{
+		  width = (word >> 25) & 0x3;
+		  rd = (word >> 7) & 0x1f;
+		  rs1 = (word >> 15) & 0x1f;
+		  rs2 = (word >> 20) & 0x1f;
+		  func = word >> 27;
+		  uint32_t rm = (word >> 12) & 0x7;
+		  if (func < 4)
+		    {
+		      static const char *const fpop[4] =
+			{
+			  "fadd", "fsub", "fmul", "fdiv"
+			};
+		      char *cp = stpcpy (mnebuf, fpop[func]);
+		      *cp++ = '.';
+		      *cp++ = widthchar[width];
+		      *cp = '\0';
+		      mne = mnebuf;
+		      op[0] = FREG (rd);
+		      op[1] = FREG (rs1);
+		      op[2] = FREG (rs2);
+		      if (rm != 0x7)
+			op[3] = (char *) rndmode[rm];
+		    }
+		  else if (func == 0x1c && width != 2 && rs2 == 0 && rm <= 1)
+		    {
+		      char *cp;
+		      if (rm == 0)
+			{
+			  cp = stpcpy (mnebuf, "fmv.x.");
+			  *cp++ = intwidthchar[width];
+			}
+		      else
+			{
+			  cp = stpcpy (mnebuf, "fclass.");
+			  *cp++ = widthchar[width];
+			}
+		      *cp = '\0';
+		      mne = mnebuf;
+		      op[0] = REG (rd);
+		      op[1] = FREG (rs1);
+		    }
+		  else if (func == 0x1e && width != 2 && rs2 == 0 && rm == 0)
+		    {
+		      char *cp = stpcpy (mnebuf, "fmv.");
+		      *cp++ = intwidthchar[width];
+		      strcpy (cp, ".x");
+		      mne = mnebuf;
+		      op[0] = FREG (rd);
+		      op[1] = REG (rs1);
+		    }
+		  else if (func == 0x14)
+		    {
+		      uint32_t cmpop = (word >> 12) & 0x7;
+		      if (cmpop < 3)
+			{
+			  static const char *const mnefpcmp[3] =
+			    {
+			      "fle", "flt", "feq"
+			    };
+			  char *cp = stpcpy (mnebuf, mnefpcmp[cmpop]);
+			  *cp++ = '.';
+			  *cp++ = widthchar[width];
+			  *cp = '\0';
+			  mne = mnebuf;
+			  op[0] = REG (rd);
+			  op[1] = FREG (rs1);
+			  op[2] = FREG (rs2);
+			}
+		    }
+		  else if (func == 0x04)
+		    {
+		      uint32_t cmpop = (word >> 12) & 0x7;
+		      if (cmpop < 3)
+			{
+			  op[0] = FREG (rd);
+			  op[1] = FREG (rs1);
+
+			  static const char *const mnefpcmp[3] =
+			    {
+			      "fsgnj.", "fsgnjn.", "fsgnjx."
+			    };
+			  static const char *const altsignmne[3] =
+			    {
+			      "fmv.", "fneg.", "fabs."
+			    };
+			  char *cp = stpcpy (mnebuf, rs1 == rs2 ? altsignmne[cmpop] : mnefpcmp[cmpop]);
+			  *cp++ = widthchar[width];
+			  *cp = '\0';
+			  mne = mnebuf;
+
+			  if (rs1 != rs2)
+			    op[2] = FREG (rs2);
+			}
+		    }
+		  else if (func == 0x08 && width != 2 && rs2 <= 3 && rs2 != 2 && rs2 != width)
+		    {
+		      op[0] = FREG (rd);
+		      op[1] = FREG (rs1);
+		      char *cp = stpcpy (mnebuf, "fcvt.");
+		      *cp++ = widthchar[width];
+		      *cp++ = '.';
+		      *cp++ = widthchar[rs2];
+		      *cp = '\0';
+		      mne = mnebuf;
+		    }
+		  else if ((func & 0x1d) == 0x18 && width != 2 && rs2 < 4)
+		    {
+		      char *cp = stpcpy (mnebuf, "fcvt.");
+		      if (func == 0x18)
+			{
+			  *cp++ = rs2 >= 2 ? 'l' : 'w';
+			  if ((rs2 & 1) == 1)
+			    *cp++ = 'u';
+			  *cp++ = '.';
+			  *cp++ = widthchar[width];
+			  *cp = '\0';
+			  op[0] = REG (rd);
+			  op[1] = FREG (rs1);
+			}
+		      else
+			{
+			  *cp++ = widthchar[width];
+			  *cp++ = '.';
+			  *cp++ = rs2 >= 2 ? 'l' : 'w';
+			  if ((rs2 & 1) == 1)
+			    *cp++ = 'u';
+			  *cp = '\0';
+			  op[0] = FREG (rd);
+			  op[1] = REG (rs1);
+			}
+		      mne = mnebuf;
+		      if (rm != 0x7 && (func == 0x18 || width == 0 || rs2 >= 2))
+			op[2] = (char *) rndmode[rm];
+		    }
+		  else if (func == 0x0b && rs2 == 0)
+		    {
+		      op[0] = FREG (rd);
+		      op[1] = FREG (rs1);
+		      char *cp = stpcpy (mnebuf, "fsqrt.");
+		      *cp++ = widthchar[width];
+		      *cp = '\0';
+		      mne = mnebuf;
+		      if (rm != 0x7)
+			op[2] = (char *) rndmode[rm];
+		    }
+		  else if (func == 0x05 && rm < 2)
+		    {
+		      op[0] = FREG (rd);
+		      op[1] = FREG (rs1);
+		      op[2] = FREG (rs2);
+		      char *cp = stpcpy (mnebuf, rm == 0 ? "fmin." : "fmax.");
+		      *cp++ = widthchar[width];
+		      *cp = '\0';
+		      mne = mnebuf;
+		    }
+		  else if (func == 0x14 && rm <= 0x2)
+		    {
+		      op[0] = REG (rd);
+		      op[1] = FREG (rs1);
+		      op[2] = FREG (rs2);
+		      static const char *const fltcmpmne[3] =
+			{
+			  "fle.", "flt.", "feq."
+			};
+		      char *cp = stpcpy (mnebuf, fltcmpmne[rm]);
+		      *cp++ = widthchar[width];
+		      *cp = '\0';
+		      mne = mnebuf;
+		    }
+		}
+	      break;
+	    case 0x18:
+	      // BRANCH
+	      rs1 = (word >> 15) & 0x1f;
+	      op[0] = REG (rs1);
+	      rs2 = (word >> 20) & 0x1f;
+	      op[1] = REG (rs2);
+	      opaddr = addr + (((UINT64_C (0) - (word >> 31)) << 12)
+			       + ((word << 4) & 0x800)
+			       + ((word >> 20) & 0x7e0)
+			       + ((word >> 7) & 0x1e));
+	      // TODO translate address
+	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
+	      op[2] = addrbuf;
+	      static const char *const branchmne[8] =
+		{
+		  "beq", "bne", NULL, NULL, "blt", "bge", "bltu", "bgeu"
+		};
+	      func = (word >> 12) & 0x7;
+	      mne = (char *) branchmne[func];
+	      if (rs1 == 0 && func == 5)
+		{
+		  op[0] = op[1];
+		  op[1] = op[2];
+		  op[2] = NULL;
+		  mne = "blez";
+		}
+	      else if (rs1 == 0 && func == 4)
+		{
+		  op[0] = op[1];
+		  op[1] = op[2];
+		  op[2] = NULL;
+		  mne = "bgtz";
+		}
+	      else if (rs2 == 0)
+		{
+		  if (func == 0 || func == 1 || func == 4 || func == 5)
+		    {
+		      op[1] = op[2];
+		      op[2] = NULL;
+		      strcpy (stpcpy (mnebuf, mne), "z");
+		      mne = mnebuf;
+		    }
+		}
+	      else if (func == 5 || func == 7)
+		{
+		  // binutils use these opcodes and the reverse parameter order
+		  char *tmp = op[0];
+		  op[0] = op[1];
+		  op[1] = tmp;
+		  mne = func == 5 ? "ble" : "bleu";
+		}
+	      break;
+	    case 0x19:
+	      // JALR
+	      if ((word & 0x7000) == 0)
+		{
+		  rd = (word >> 7) & 0x1f;
+		  rs1 = (word >> 15) & 0x1f;
+		  opaddr = (int32_t) word >> 20;
+		  size_t next = 0;
+		  if (rd > 1)
+		    op[next++] = REG (rd);
+		  if (opaddr == 0)
+		    {
+		      if (rs1 != 0 || next == 0)
+			op[next] = REG (rs1);
+		    }
+		  else
+		    {
+		      snprintf (addrbuf, sizeof (addrbuf), "%" PRId64 "(%s)", opaddr, REG (rs1));
+		      op[next] = addrbuf;
+		    }
+		  mne = rd == 0 ? "jr" : "jalr";
+		}
+	      break;
+	    case 0x1b:
+	      // JAL
+	      rd = (word >> 7) & 0x1f;
+	      if (rd != 0)
+		op[0] = REG (rd);
+	      opaddr = addr + ((UINT64_C (0) - ((word >> 11) & 0x100000))
+			       | (word & 0xff000)
+			       | ((word >> 9) & 0x800)
+			       | ((word >> 20) & 0x7fe));
+	      // TODO translate address
+	      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx64, opaddr);
+	      op[rd != 0] = addrbuf;
+	      mne = rd == 0 ? "j" : "jal";
+	      break;
+	    case 0x1c:
+	      // SYSTEM
+	      rd = (word >> 7) & 0x1f;
+	      rs1 = (word >> 15) & 0x1f;
+	      if (word == 0x00000073)
+		mne = "ecall";
+	      else if (word == 0x00100073)
+		mne = "ebreak";
+	      else if (word == 0x00200073)
+		mne = "uret";
+	      else if (word == 0x10200073)
+		mne = "sret";
+	      else if (word == 0x30200073)
+		mne = "mret";
+	      else if (word == 0x10500073)
+		mne = "wfi";
+	      else if ((word & 0x3000) == 0x2000 && rs1 == 0)
+		{
+		  uint32_t csr = word >> 20;
+		  if (/* csr >= 0x000 && */ csr <= 0x007)
+		    {
+		      static const char *const unprivrw[4] =
+			{
+			  NULL, "frflags", "frrm", "frsr",
+			};
+		      mne = (char *) unprivrw[csr - 0x000];
+		    }
+		  else if (csr >= 0xc00 && csr <= 0xc03)
+		    {
+		      static const char *const unprivrolow[3] =
+			{
+			  "rdcycle", "rdtime", "rdinstret"
+			};
+		      mne = (char *) unprivrolow[csr - 0xc00];
+		    }
+		  op[0] = REG ((word >> 7) & 0x1f);
+		}
+	      else if ((word & 0x3000) == 0x1000 && rd == 0)
+		{
+		  uint32_t csr = word >> 20;
+		  if (/* csr >= 0x000 && */ csr <= 0x003)
+		    {
+		      static const char *const unprivrs[4] =
+			{
+			  NULL, "fsflags", "fsrm", "fssr",
+			};
+		      static const char *const unprivrsi[4] =
+			{
+			  NULL, "fsflagsi", "fsrmi", NULL
+			};
+		      mne = (char *) ((word & 0x4000) == 0 ? unprivrs : unprivrsi)[csr - 0x000];
+
+		      if ((word & 0x4000) == 0)
+			op[0] = REG ((word >> 15) & 0x1f);
+		      else
+			{
+			  snprintf (immbuf, sizeof (immbuf), "%" PRIu32, (word >> 15) & 0x1f);
+			  op[0] = immbuf;
+			}
+		    }
+		}
+	      if (mne == NULL && (word & 0x3000) != 0)
+		{
+		  static const char *const mnecsr[8] =
+		    {
+		      NULL, "csrrw", "csrrs", "csrrc",
+		      NULL, "csrrwi", "csrrsi", "csrrci"
+		    };
+		  static const struct known_csrs known[] =
+		    {
+		      // This list must remain sorted by NR.
+		      { 0x000, "ustatus" },
+		      { 0x001, "fflags" },
+		      { 0x002, "fram" },
+		      { 0x003, "fcsr" },
+		      { 0x004, "uie" },
+		      { 0x005, "utvec" },
+		      { 0x040, "uscratch" },
+		      { 0x041, "uepc" },
+		      { 0x042, "ucause" },
+		      { 0x043, "utval" },
+		      { 0x044, "uip" },
+		      { 0x100, "sstatus" },
+		      { 0x102, "sedeleg" },
+		      { 0x103, "sideleg" },
+		      { 0x104, "sie" },
+		      { 0x105, "stvec" },
+		      { 0x106, "scounteren" },
+		      { 0x140, "sscratch" },
+		      { 0x141, "sepc" },
+		      { 0x142, "scause" },
+		      { 0x143, "stval" },
+		      { 0x144, "sip" },
+		      { 0x180, "satp" },
+		      { 0x200, "vsstatus" },
+		      { 0x204, "vsie" },
+		      { 0x205, "vstvec" },
+		      { 0x240, "vsscratch" },
+		      { 0x241, "vsepc" },
+		      { 0x242, "vscause" },
+		      { 0x243, "vstval" },
+		      { 0x244, "vsip" },
+		      { 0x280, "vsatp" },
+		      { 0x600, "hstatus" },
+		      { 0x602, "hedeleg" },
+		      { 0x603, "hideleg" },
+		      { 0x605, "htimedelta" },
+		      { 0x606, "hcounteren" },
+		      { 0x615, "htimedeltah" },
+		      { 0x680, "hgatp" },
+		      { 0xc00, "cycle" },
+		      { 0xc01, "time" },
+		      { 0xc02, "instret" },
+		      { 0xc03, "hpmcounter3" },
+		      { 0xc04, "hpmcounter4" },
+		      { 0xc05, "hpmcounter5" },
+		      { 0xc06, "hpmcounter6" },
+		      { 0xc07, "hpmcounter7" },
+		      { 0xc08, "hpmcounter8" },
+		      { 0xc09, "hpmcounter9" },
+		      { 0xc0a, "hpmcounter10" },
+		      { 0xc0b, "hpmcounter11" },
+		      { 0xc0c, "hpmcounter12" },
+		      { 0xc0d, "hpmcounter13" },
+		      { 0xc0e, "hpmcounter14" },
+		      { 0xc0f, "hpmcounter15" },
+		      { 0xc10, "hpmcounter16" },
+		      { 0xc11, "hpmcounter17" },
+		      { 0xc12, "hpmcounter18" },
+		      { 0xc13, "hpmcounter19" },
+		      { 0xc14, "hpmcounter20" },
+		      { 0xc15, "hpmcounter21" },
+		      { 0xc16, "hpmcounter22" },
+		      { 0xc17, "hpmcounter23" },
+		      { 0xc18, "hpmcounter24" },
+		      { 0xc19, "hpmcounter25" },
+		      { 0xc1a, "hpmcounter26" },
+		      { 0xc1b, "hpmcounter27" },
+		      { 0xc1c, "hpmcounter28" },
+		      { 0xc1d, "hpmcounter29" },
+		      { 0xc1e, "hpmcounter30" },
+		      { 0xc1f, "hpmcounter31" },
+		      { 0xc80, "cycleh" },
+		      { 0xc81, "timeh" },
+		      { 0xc82, "instreth" },
+		      { 0xc83, "hpmcounter3h" },
+		      { 0xc84, "hpmcounter4h" },
+		      { 0xc85, "hpmcounter5h" },
+		      { 0xc86, "hpmcounter6h" },
+		      { 0xc87, "hpmcounter7h" },
+		      { 0xc88, "hpmcounter8h" },
+		      { 0xc89, "hpmcounter9h" },
+		      { 0xc8a, "hpmcounter10h" },
+		      { 0xc8b, "hpmcounter11h" },
+		      { 0xc8c, "hpmcounter12h" },
+		      { 0xc8d, "hpmcounter13h" },
+		      { 0xc8e, "hpmcounter14h" },
+		      { 0xc8f, "hpmcounter15h" },
+		      { 0xc90, "hpmcounter16h" },
+		      { 0xc91, "hpmcounter17h" },
+		      { 0xc92, "hpmcounter18h" },
+		      { 0xc93, "hpmcounter19h" },
+		      { 0xc94, "hpmcounter20h" },
+		      { 0xc95, "hpmcounter21h" },
+		      { 0xc96, "hpmcounter22h" },
+		      { 0xc97, "hpmcounter23h" },
+		      { 0xc98, "hpmcounter24h" },
+		      { 0xc99, "hpmcounter25h" },
+		      { 0xc9a, "hpmcounter26h" },
+		      { 0xc9b, "hpmcounter27h" },
+		      { 0xc9c, "hpmcounter28h" },
+		      { 0xc9d, "hpmcounter29h" },
+		      { 0xc9e, "hpmcounter30h" },
+		      { 0xc9f, "hpmcounter31h" },
+		    };
+		  uint32_t csr = word >> 20;
+		  uint32_t instr = (word >> 12) & 0x7;
+		  size_t last = 0;
+		  if (rd != 0)
+		    op[last++] = REG (rd);
+		  struct known_csrs key = { csr, NULL };
+		  struct known_csrs *found = bsearch (&key, known,
+						      sizeof (known) / sizeof (known[0]),
+						      sizeof (known[0]),
+						      compare_csr);
+		  if (found)
+		    op[last] = (char *) found->name;
+		  else
+		    {
+		      snprintf (addrbuf, sizeof (addrbuf), "0x%" PRIx32, csr);
+		      op[last] = addrbuf;
+		    }
+		  ++last;
+		  if ((word & 0x4000) == 0)
+		    op[last] = REG ((word >> 15) & 0x1f);
+		  else
+		    {
+		      snprintf (immbuf, sizeof (immbuf), "%" PRIu32, (word >> 15) & UINT32_C(0x1f));
+		      op[last] = immbuf;
+		    }
+		  if (instr == 1 && rd == 0)
+		    mne = "csrw";
+		  else if (instr == 2 && rd == 0)
+		    mne = "csrs";
+		  else if (instr == 6 && rd == 0)
+		    mne = "csrsi";
+		  else if (instr == 2 && rs1 == 0)
+		    mne = "csrr";
+		  else if (instr == 3 && rd == 0)
+		    mne = "csrc";
+		  else
+		    mne = (char *) mnecsr[instr];
+		}
+	      break;
+	    default:
+	      break;
+	    }
+
+	  if (strp == NULL && mne == NULL)
+	    {
+	      len = snprintf (addrbuf, sizeof (addrbuf), "0x%08" PRIx32, word);
+	      strp = addrbuf;
+	    }
+	}
+      else
+	{
+	  // No instruction encodings defined for these sizes yet.
+	  char *cp = stpcpy (mnebuf, "0x");
+	  assert (length % 2 == 0);
+	  for (size_t i = 0; i < length; i += 2)
+	    cp += snprintf (cp, mnebuf + sizeof (mnebuf) - cp, "%04" PRIx16,
+			    read_2ubyte_unaligned (data + i));
+	  strp = mnebuf;
+	  len = cp - mnebuf;
+	}
+
+      if (strp == NULL)
+	{
+
+	  if (0)
+	    {
+	      /* Resize the buffer.  */
+	      char *oldbuf;
+	    enomem:
+	      oldbuf = buf;
+	      if (buf == initbuf)
+		buf = malloc (2 * bufsize);
+	      else
+		buf = realloc (buf, 2 * bufsize);
+	      if (buf == NULL)
+		{
+		  buf = oldbuf;
+		  retval = ENOMEM;
+		  goto do_ret;
+		}
+	      bufsize *= 2;
+
+	      bufcnt = 0;
+	    }
+
+	  unsigned long string_end_idx = 0;
+	  fmt = save_fmt;
+	  const char *deferred_start = NULL;
+	  size_t deferred_len = 0;
+	  // XXX Can we get this from color.c?
+	  static const char color_off[] = "\e[0m";
+	  while (*fmt != '\0')
+	    {
+	      if (*fmt != '%')
+		{
+		  char ch = *fmt++;
+		  if (ch == '\\')
+		    {
+		      switch ((ch = *fmt++))
+			{
+			case '0' ... '7':
+			  {
+			    int val = ch - '0';
+			    ch = *fmt;
+			    if (ch >= '0' && ch <= '7')
+			      {
+				val *= 8;
+				val += ch - '0';
+				ch = *++fmt;
+				if (ch >= '0' && ch <= '7' && val < 32)
+				  {
+				    val *= 8;
+				    val += ch - '0';
+				    ++fmt;
+				  }
+			      }
+			    ch = val;
+			  }
+			  break;
+
+			case 'n':
+			  ch = '\n';
+			  break;
+
+			case 't':
+			  ch = '\t';
+			  break;
+
+			default:
+			  retval = EINVAL;
+			  goto do_ret;
+			}
+		    }
+		  else if (ch == '\e' && *fmt == '[')
+		    {
+		      deferred_start = fmt - 1;
+		      do
+			++fmt;
+		      while (*fmt != 'm' && *fmt != '\0');
+
+		      if (*fmt == 'm')
+			{
+			  deferred_len = ++fmt - deferred_start;
+			  continue;
+			}
+
+		      fmt = deferred_start + 1;
+		      deferred_start = NULL;
+		    }
+		  ADD_CHAR (ch);
+		  continue;
+		}
+	      ++fmt;
+
+	      int width = 0;
+	      while (isdigit (*fmt))
+		width = width * 10 + (*fmt++ - '0');
+
+	      int prec = 0;
+	      if (*fmt == '.')
+		while (isdigit (*++fmt))
+		  prec = prec * 10 + (*fmt - '0');
+
+	      size_t start_idx = bufcnt;
+	      size_t non_printing = 0;
+	      switch (*fmt++)
+		{
+		case 'm':
+		  if (deferred_start != NULL)
+		    {
+		      ADD_NSTRING (deferred_start, deferred_len);
+		      non_printing += deferred_len;
+		    }
+
+		  ADD_STRING (mne);
+
+		  if (deferred_start != NULL)
+		    {
+		      ADD_STRING (color_off);
+		      non_printing += strlen (color_off);
+		    }
+
+		  string_end_idx = bufcnt;
+		  break;
+
+		case 'o':
+		  if (op[prec - 1] != NULL)
+		    {
+		      if (deferred_start != NULL)
+			{
+			  ADD_NSTRING (deferred_start, deferred_len);
+			  non_printing += deferred_len;
+			}
+
+		      ADD_STRING (op[prec - 1]);
+
+		      if (deferred_start != NULL)
+			{
+			  ADD_STRING (color_off);
+			  non_printing += strlen (color_off);
+			}
+
+		      string_end_idx = bufcnt;
+		    }
+		  else
+		    bufcnt = string_end_idx;
+		  break;
+
+		case 'e':
+		  string_end_idx = bufcnt;
+		  break;
+
+		case 'a':
+		  /* Pad to requested column.  */
+		  while (bufcnt - non_printing < (size_t) width)
+		    ADD_CHAR (' ');
+		  width = 0;
+		  break;
+
+		case 'l':
+		  // TODO
+		  break;
+
+		default:
+		  abort();
+		}
+
+	      /* Pad according to the specified width.  */
+	      while (bufcnt - non_printing < start_idx + width)
+		ADD_CHAR (' ');
+	    }
+
+	  strp = buf;
+	  len = bufcnt;
+	}
+
+      addr += length;
+      *startp = data + length;
+      retval = outcb (strp, len, outcbarg);
+      if (retval != 0)
+	break;
+    }
+
+ do_ret:
+  if (buf != initbuf)
+    free (buf);
+
+  return retval;
+}
diff --git a/libcpu/x86_64_disasm.c b/libcpu/x86_64_disasm.c
new file mode 100644
index 0000000..947bc94
--- /dev/null
+++ b/libcpu/x86_64_disasm.c
@@ -0,0 +1,34 @@
+/* Disassembler for x86-64.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define i386_disasm x86_64_disasm
+#define DISFILE "x86_64_dis.h"
+#define MNEFILE "x86_64.mnemonics"
+#define X86_64
+#include "i386_disasm.c"
diff --git a/libdw/ChangeLog b/libdw/ChangeLog
new file mode 100644
index 0000000..b19fc80
--- /dev/null
+++ b/libdw/ChangeLog
@@ -0,0 +1,3951 @@
+2023-09-27  Omar Sandoval  <osandov@fb.com>
+
+	* libdwP.h ((Dwarf): Add elfpath.
+	* dwarf_begin_elf.c (__libdw_debugdir): Replace declaration with...
+	(__libdw_elfpath): New declaration.
+	(__libdw_set_debugdir): New declaration.
+	(__libdw_debugdir): Replace with..
+	(__libdw_elfpath): New function.
+	(__libdw_set_debugdir): New function.
+	(valid_p): Call __libdw_elfpath and __libdw_set_debugdir instead of
+	__libdw_debugdir.
+	* dwarf_end.c (dwarf_end): Free dwarf->elfpath.
+
+2023-09-27  Omar Sandoval  <osandov@fb.com>
+
+	* libdw_find_split_unit.c (try_split_file): Make static.
+	* dwarf_entrypc.c (dwarf_entrypc): Call dwarf_lowpc.
+	* dwarf_ranges.c (dwarf_ranges): Use skeleton ranges section for
+	skeleton units.
+	* dwarf_macro_param2.c (dwarf_macro_param2): Change form condition to
+	switch statement and add DW_FORM_line_strp, DW_FORM_strp_sup,
+	DW_FORM_strx, and DW_FORM_strx[1-4].
+	* dwarf_getmacros.c (get_macinfo_table): Replace assignment of
+	table->is_64bit with assignments of table->address_size and
+	table->offset_size.  Assume default DW_AT_stmt_list of 0 for split
+	DWARF.  Set table->dbg.
+	(get_table_for_offset): Ditto.
+	(read_macros): Get fake CU offset_size from table->offset_size instead
+	of table->is_64bit.
+	* dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles): Get
+	address_size for __libdw_getsrclines from table->address_size instead
+	of table->is_64bit.  Get dbg for __libdw_getsrclines from table->dbg
+	instead of dbg parameter, which is now unused.
+	* libdwP.h (Dwarf_Macro_Op_Table): Replace is_64bit with address_size
+	and offset_size.  Add dbg.
+	Add IDX_debug_cu_index and IDX_debug_tu_index.
+	* dwarf_begin_elf.c (dwarf_scnnames): Add IDX_debug_cu_index and
+	IDX_debug_tu_index.
+	(scn_to_string_section_idx): Ditto.
+	(scn_dwarf_type): Check for .debug_cu_index, .debug_tu_index,
+	.zdebug_cu_index, and .zdebug_tu_index.
+	(check_section): Change .dwo suffix matching to account for
+	.debug_cu_index and .debug_tu_index.
+
+2023-02-22  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getscopes.c (origin_match): Don't free a->scopes.
+	(dwarf_getscopes): Free a->scopes on error.
+
+2023-02-20  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (check_section): Use elf_rawdata.
+
+2023-02-14  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Correct check
+	for deref_type.
+
+2023-02-10  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_GNU_uninit.
+
+2023-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* cfi.c (execute_cfi): Add cfi_asser before reading second lib128.
+	* dwarf_chld.c (__libdw_find_attr): Check readp >= endp before
+	calling get_uleb128.
+	* dwarf_frame_register.c (dwarf_frame_register): Likewise for
+	p >= end.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Add comment about check.
+	* dwarf_getlocation.c (__libdw_intern_expression): Update check to
+	account for both the number and uleb128.
+	* encoded-value.h (read_encoded_value): Check p >= end for
+	DW_EH_PE_(u|s)leb128.
+	* fde.c (intern_fde): Check len can be read as uleb128.
+	* libdw_form.c (__libdw_form_val_compute_len): Check valp >= endp
+	before get_uleb128.
+
+2023-01-22  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getscopes.c (pc_record): Return nscopes when done.
+	(dwarf_getscopes): Call __libdw_visit_scopes with
+	inlined_origin CU.
+
+2022-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (AM_CPPFLAGS): Add -I$(srcdir)/../libebl.
+	* cfi.c: Include libebl.h.
+	* encoded-value.h: Likewise.
+	* frame-cache.h: Likewise.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* memory-access.h (get_uleb128_step): Use __typeof.
+	(get_sleb128_step): Likewise.
+	(__libdw_get_sleb128) Likewise.
+	(__libdw_get_sleb128_unchecked): Likewise.
+
+2022-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_next_cfi.c (dwarf_next_cfi): Don't dereference and assign
+	bytes.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* dwarf_begin_elf.h: Don't include unistd.h and endian.h.
+	* dwarf_end.c: Don't include unistd.h.
+	* dwarf_setalt.c: Likewise.
+	* libdw_find_split_unit.c: Likewise.
+
+2022-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h (DW_LLE_GNU_view_pair): New constant.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* memory-access.h: Include system.h instead of byteswap.h and
+	endian.h.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* memory-access.h: Use BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN.
+
+2022-09-13  Aleksei Vetrov  <vvvvvv@google.com>
+
+	* libdw.map (ELFUTILS_0.188): Add dwfl_report_offline_memory.
+
+2022-08-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_next_cfi.c (dwarf_next_cfi): Don't skip processing the
+	augmentation string.  Be more stringent what to accept.
+
+2022-07-28  Di Chen  <dichen@redhat.com>
+
+	* libdw.map (ELFUTILS_0.188): Add dwfl_frame_reg.
+
+2022-07-13  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.map (ELFUTILS_0.187): Renamed to...
+	(ELFUTILS_0.188): ... this.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (store_implicit_value): Check block length.
+
+2022-04-16  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h: Remove atomics.h include.
+
+2022-04-13  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DWARF5 package file section identifiers,
+	DW_SECT_*.
+
+2021-10-20  John M Mellor-Crummey  <johnmc@rice.edu>
+
+	* dwarf_linecontext.c: New file.
+	* dwarf_linefunctionname.c: Likewise.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_linecontext.c and
+	dwarf_linefunctionname.c
+	* dwarf.h: Add DW_LNE_NVIDIA_inlined_call and
+	DW_LNE_NVIDIA_set_function_name.
+	* dwarf_getsrclines.c (struct line_state): Add context and
+	function_name fields.
+	(add_new_line): Set context and function_name.
+	(MAX_STACK_LINES): Reduce to MAX_STACK_ALLOC / 2.
+	(read_srclines): Initialize context and function_name.  Try to
+	read debug_str_offset if available.  Handle
+	DW_LNE_NVIDIA_inlined_call and DW_LNE_NVIDIA_set_function_name.
+	* libdw.h (dwarf_linecontext): New declaration.
+	(dwarf_linefunctionname): Likewise.
+	* libdw.map (ELFUTILS_0.186): New section.
+
+2021-11-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (scn_dwarf_type): New function.
+	(check_section): Check result->type.
+	(global_read): First check type.
+	(scngrp_read): Likewise.
+	* libdw/libdwP.h (enum dwarf_type): New enumeration.
+	(struct Dwarf): New field type.
+
+2021-02-14  Alexander Miller  <alex.miller@gmx.de>
+
+	* dwarf_aggregate_size.c (dwarf_aggregate_size): Move NEW_VERSION
+	before definition.  Replace INTDEF with NEW_INTDEF.
+	* dwarf_srclang.c (dwarf_srclang): Likewise.
+	* dwarf_arrayorder.c (dwarf_arrayorder): Move NEW_VERSION.
+	* dwarf_bitoffset.c (dwarf_bitoffset): Likewise.
+	* dwarf_bitsize.c (dwarf_bitsize): Likewise.
+	* dwarf_bytesize.c (dwarf_bytesize): Likewise.
+	* dwarf_decl_column.c (dwarf_decl_column): Likewise.
+
+2021-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_aggregate_size.c (get_type): Don't pass NULL to
+	dwarf_peel_type.
+
+2021-10-06  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_aggregate_size.c (array_size): Check signedness of child DIE
+	type. Use dwarf_formsdata or dwarf_formudata to get the lower and
+	upper bounds.
+
+2021-09-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (valid_p): Identify ELF class and use this to set
+	address_size of the fake CUs. Also set offset_size and DWARF version.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* dwarf_begin_elf.c (valid_p): Remove casts of malloc return values.
+	(dwarf_begin_elf): Remove cast of calloc return value.
+	* dwarf_getpubnames.c (get_offsets): Remove casts of realloc return
+	values.
+	* dwarf_getsrclines.c (read_srclines): Remove cast of malloc return
+	value.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* dwarf_begin_elf.c (check_section): Use startswith.
+
+2021-05-01  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_form.c (__libdw_form_val_compute_len): Check indirect
+	form is not DW_FORM_indirect or DW_FORM_implicit_const.
+
+2021-04-23  Omar Sandoval  <osandov@fb.com>
+
+	* dwarf_child.c (__libdw_find_attr): Handle DW_FORM_indirect.
+	* dwarf_getattrs.c (dwarf_getattrs): Handle DW_FORM_indirect.
+
+2021-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (attr_ok): For DWARF version 4 or higher
+	block forms are not expression locations.
+	(is_constant_offset): DW_FORM_implicit_const is also a constant.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* libdwP.h (_): Remove.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* dwarf.h: Fix spelling typo in comment.
+	* dwarf_begin_elf.c (dwarf_begin_elf): Likewise.
+	* dwarf_getlocation.c (attr_ok, __libdw_intern_expression): Likewise.
+	* dwarf_getsrclines.c (read_srclines): Likewise.
+	* libdw.h: Fix spelling typos in comments.
+	* libdwP.h: Likewise.
+
+2020-12-09  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (noinst_PROGRAMS): Rename to noinst_DATA.
+	(libdw_so_SOURCES): Remove.
+	(MOSTLYCLEANFILES): Add libdw.so.
+
+2020-11-30  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (libdw.so$(EXEEXT)): Drop $(EXEEXT) suffix.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* Makefile.am (libdw_so_LDLIBS): Add fts_LIBS.
+
+2020-10-28  Tom Tromey  <tom@tromey.com>
+
+	PR26773
+	* dwarf_getlocation.c (store_implicit_value): Use
+	__libdw_get_uleb128_unchecked.
+	* memory-access.h (get_sleb128_step): Assume unsigned type for
+	'var'.
+	(__libdw_get_sleb128, __libdw_get_sleb128_unchecked): Work in
+	unsigned type.  Handle final byte.
+
+2020-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_frame_register.c (dwarf_frame_register): Declare ops_mem
+	as array of (at least) 3 elements.
+	* libdw.h (dwarf_frame_register): Add extra explanation of ops_mem
+	argument.
+
+2020-10-23  Tom Tromey  <tom@tromey.com>
+
+	* memory-access.h (read_3ubyte_unaligned_inc): Call
+	read_3ubyte_unaligned.
+
+2020-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_CFA_AARCH64_negate_ra_state.
+	* cfi.h (struct Dwarf_CFI_s): Add e_machine field.
+	* cfi.c (execute_cfi): Recognize, but ignore
+	DW_CFA_AARCH64_negate_ra_state on aarch64.
+	* dwarf_getcfi.c (dwarf_getcfi): Set cfi e_machine.
+	* dwarf_getcfi_elf.c (allocate_cfi): Take ehdr as argument and set
+	cfi e_machine.
+	(getcfi_gnu_eh_frame): Pass ehdr to allocate_cfi.
+	(getcfi_scn_eh_frame): Likewise.
+
+2020-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.map (ELFUTILS_0.126): Remove local wildcard.
+	(ELFUTILS_0.127): Likewise.
+	(ELFUTILS_0.130): Likewise.
+	(ELFUTILS_0.136): Likewise.
+	(ELFUTILS_0.138): Likewise.
+
+2020-08-25  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (check_constant_offset): Rename to...
+	(is_constant_offset): .. this.
+
+2020-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* linux-kernel-modules.c (intuit_kernel_bounds): Check read_address
+	returns an increasing address when searching for end.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* cfi.c (execute_cfi): Add missing FALLTHROUGH.
+
+2020-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_visit_scopes.c (walk_children): Don't recurse into imported
+	DW_TAG_compile_units.
+
+2020-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_decl_file.c (dwarf_decl_file): Use attr CU instead of DIE
+	CU to resolve file name.
+	* dwarf_ranges.c(dwarf_ranges): Document which CU we use when.
+	* libdw.h (dwarf_attr_integrate): Extend documentation.
+
+2020-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_alloc.c (__libdw_alloc_tail): Call Dwarf oom_handler()
+	when malloc fails.
+
+2020-04-17  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (check_section): Handle .gnu.debuglto_ prefix.
+
+2019-10-28  Aaron Merey  <amerey@redhat.com>
+
+	* Makefile.am (libdw_so_LDLIBS): Add -ldl for libdebuginfod.so dlopen.
+
+2019-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (libdw_unalloc): New define.
+	(libdw_typed_unalloc): Likewise.
+	(__libdw_thread_tail): New function declaration.
+	* libdw_alloc.c (__libdw_thread_tail): New function.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Call libdw_typed_unalloc
+	when reading invalid data or when hash collission detected.
+
+2019-10-28  Jonathon Anderson  <jma14@rice.edu>
+
+	* libdw_alloc.c: Added __libdw_alloc_tail.
+	(__libdw_allocate): Switch to use the mem_tails array.
+	* libdwP.h (Dwarf): Likewise.
+	* dwarf_begin_elf.c (dwarf_begin_elf): Support for above.
+	* dwarf_end.c (dwarf_end): Likewise.
+	* atomics.h: Add support for thread_local.
+
+2019-10-28  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_sig8_hash.h: Include libdw.h. Remove COMPARE. Include
+	dynamicsizehash_concurrent.h.
+	* dwarf_sig8_hash.c: Include dynamicsizehash_concurrent.c.
+	* dwarf_formref_die.c (dwarf_formref_die): Drop NULL argument to
+	Dwarf_Sig8_Hash_find.
+
+2019-08-26  Srđan Milaković  <sm108@rice.edu@rice.edu>
+
+	* dwarf_abbrev_hash.{c,h}: Use the *_concurrent hash table.
+
+2019-11-01  Jonathon Anderson  <jma14@rice.edu>
+
+	* dwarf_begin_elf.c (valid_p): Switch calloc for malloc for fake CUs.
+	Add explicit initialization of some fields.
+	* dwarf_end.c (cu_free): Add clause to limit freeing of CU internals.
+
+2019-08-26  Jonathon Anderson  <jma14@rice.edu>
+
+	* libdw_alloc.c (__libdw_allocate): Added thread-safe stack allocator.
+	* libdwP.h (Dwarf): Likewise.
+	* dwarf_begin_elf.c (dwarf_begin_elf): Support for above.
+	* dwarf_end.c (dwarf_end): Likewise.
+	* Makefile.am: Use -pthread to provide rwlocks.
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am (libdw_so_LIBS): Replace libebl.a with libebl_pic.a.
+	Move libebl_pic.a to the beginning so that libdw symbols are resolved.
+	(libdw_so_LDLIBS): Remove -ldl.
+	(libdw.so): Remove -rpath.
+	(libdw_a_LIBADD): Add libebl, libebl_backends, and libcpu objects.
+
+2019-08-25  Jonathon Anderson  <jma14@rice.edu>
+
+	* dwarf_getcfi.c (dwarf_getcfi): Set default_same_value to false.
+
+2019-08-12  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.map (ELFUTILS_0.177): Add new version of dwelf_elf_begin.
+
+2019-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.map (ELFUTILS_0.177): New section. Add
+	dwelf_elf_e_machine_string.
+
+2019-05-16  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_AT_GNU_numerator, DW_AT_GNU_denominator and
+	DW_AT_GNU_bias.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_siblingof.c (dwarf_siblingof): Don't initialize addr.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (dwarf_getlocation_addr): Call
+	check_constant_offset with llbufs and listlens directly.
+
+2019-04-27  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (store_implicit_value): Check dbg isn't
+	NULL.
+
+2019-02-02  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_nextcu.c (__libdw_next_unit): Define bytes_end.
+	Check there are enough bytes to read extended length, version
+	and unit.
+
+2019-01-20  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getsrclines.c (read_srclines): Check terminating NUL byte
+	for dir and file lists.
+
+2018-10-23  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_child.c (__libdw_find_attr): Initialize readp to NULL.
+	* dwarf_getattrs.c (dwarf_getattrs): Initialize die_addr to NULL.
+
+2018-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.map (ELFUTILS_0.175): New section. Add dwelf_elf_begin.
+
+2018-10-29  Milian Wolff  <milian.wolff@kdab.com>
+
+	* dwarf_getcfi_elf.c (getcfi_shdr): Check sh_type != SHT_NOBITS.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (check_section): Drop ehdr argument, add and
+	use shstrndx argument.
+	(global_read): Likewise.
+	(scngrp_read): Likewise.
+	(dwarf_begin_elf): Call elf_getshdrstrndx. Pass shstrndx to
+	global_read or scngrp_read.
+
+2018-08-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getabbrev.c (__libdw_getabbrev): Continue until both name
+	and form are zero.
+	* dwarf_hasattr.c (dwarf_hasattr): Stop when both name and form
+	are zero.
+
+2018-08-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getaranges.c (dwarf_getaranges.c): Make sure there is enough
+	data to read the address and segment size.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* libdw_alloc.c: Remove error.h include.
+
+2018-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_next_cfi.c (dwarf_next_cfi): Check whether length is zero.
+
+2018-06-27  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (check_section): Allow a single .debug_frame
+	section.
+
+2018-06-26  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.h (dwarf_getscn_info): Remove.
+	* libdw.map (ELFUTILS_0.122): Remove dwarf_getscn_info.
+
+2018-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_next_lines.c.
+	* libdw.h (dwarf_next_lines): New function declaration.
+	* libdw.map (ELFUTILS_0.173): New section.
+	* dwarf_next_lines.c: New files.
+	* dwarf_begin_elf.c (check_section): Don't error out when elf
+	decompression fails.
+	(valid_p): Allow just a single .debug_line section.
+	* dwarf_getsrclines.c (read_srclines): Keep files relative if comp_dir
+	is missing.
+
+2018-06-22  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_nextcu.c (__libdw_next_unit): Set next_off to -1 when it would
+	wrap around.
+
+2018-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_aggregate_size.c (array_size): New depth argument. Use
+	aggregate_size instead of dwarf_aggregate_size and pass depth.
+	(aggregate_size): New depth argument. Check depth isn't bigger
+	than MAX_DEPTH (256). Pass depth to recursive calls.
+	(dwarf_aggregate_size): ass zero as depth to aggregate_size.
+
+2018-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_peel_type.c (dwarf_peel_type): Limit modifier chain to 64.
+
+2018-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_aggregate_size.c (aggregate_size): Check die is not NULL.
+
+2018-06-17  Luiz Angelo Daros de Luca  <luizluca@gmail.com>
+
+	* dwarf_getsrclines.c (read_srclines): Intialize filelist early.
+
+2018-06-15  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (check_constant_offset): Clarify DW_FORM_data16
+	isn't really a constant.
+	(dwarf_getlocation): Don't handle DW_FORM_data16 as block.
+	(dwarf_getlocation_addr): Likewise.
+	(dwarf_getlocations): Likewise.
+
+2018-06-12  Mark Wielaard  <mark@klomp.org>
+
+	* memory-access.h (read_3ubyte_unaligned_inc): New define.
+
+2018-06-12  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.h (__libdw_dieabbrev): Set die->abbrev to DWARF_END_ABBREV
+	on failure.
+
+2018-06-10  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_attr_integrate.c (dwarf_attr_integrate): Stop after 16 DIE
+	ref chains.
+	* dwarf_hasattr_integrate.c (dwarf_hasattr_integrate): Likewise.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getabbrev.c (dwarf_getabbrev): Check die and offset.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_get_units.c (dwarf_get_units): Handle existing error, no
+	dwarf.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (store_implicit_value): Return error when
+	seeing bad DWARF or when tsearch runs out of memory.
+	(__libdw_intern_expression): Report error when store_implicit_value
+	reported an error.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getsrclines.c (read_srclines): Sanity check ndirs and nfiles.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation_attr.c (addr_valp): Set error and return NULL
+	when there is no .debug_addr section.
+	(dwarf_getlocation_attr): If addr_valp returns NULL, then return -1.
+
+2018-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_findcu.c (__libdw_intern_next_unit): Report DWARF_E_VERSION,
+	not DWARF_E_INVALID_DWARF on unknown version. Set address_size and
+	offset_size to 8 when unknown.
+
+2018-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (__libdw_dieabbrev): Check DIE addr falls in cu.
+
+2018-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation_die.c (dwarf_getlocation_die): Check offset
+	falls inside cu data.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getsrclines.c (read_srclines): Explicitly set diridx to -1
+	in case dwarf_formudata fails.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getaranges (dwarf_getaranges): Free new_arange if
+	__libdw_findcu fails.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getsrclines.c (read_srclines): Define dirarray early and
+	check whether or not it is equal to dirstack on exit/out before
+	cleanup.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getalt.c (find_debug_altlink): id_path array should be 2
+	larger to contain MAX_BUILD_ID_BYTES.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_find_split_unit.c (try_split_file): New function extracted
+	from...
+	(__libdw_find_split_unit): ... here. Try both the relative and
+	absolute paths to find a .dwo file.
+
+2018-05-30  Mark Wielaard  <mark@klomp.org>
+
+	* libdw/dwarf_getsrclines.c (read_srclines): Change ndir and
+	ndirlist to size_t. Add check to see ndirlist doesn't overflow.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_dieoffset.c: Check die->cu != NULL. Return -1, not ~0ul
+	on failure.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_cuoffset.c (dwarf_cuoffset): Check die->cu is not NULL.
+	* dwarf_die_addr_die.c (dwarf_die_addr_die): Also search split
+	Dwarfs.
+	* libdwP.h (struct Dwarf): Add split_tree field.
+	(__libdw_find_split_dbg_addr): New internal function definition.
+	(__libdw_finddbg_cb): Likewise.
+	* libdw_find_split_unit.c (__libdw_find_split_unit): Insert split
+	Dwarf into skeleton dbg split_tree.
+	* libdw_findcu.c (__libdw_finddbg_cb): New function.
+	(__libdw_find_split_dbg_addr): Likewise.
+	* dwarf_end (dwarf_end): Destroy split_tree.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add GNU DebugFission list entry encodings
+	DW_LLE_GNU_end_of_list_entry,
+	DW_LLE_GNU_base_address_selection_entry,
+	DW_LLE_GNU_start_end_entry and DW_LLE_GNU_start_length_entry.
+	* dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Handle
+	GNU DebugFission list entries.
+
+2018-05-28  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_find_split_unit.c (__libdw_find_split_unit): End split_dwarf
+	only after we tried every unit id in it.
+
+2018-04-07  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (struct Dwarf_CU): Add locs_base.
+	(__libdw_cu_locs_base): New static inline function.
+	* libdw_findcu.c (__libdw_intern_next_unit): Initialize locs_base.
+	* dwarf_begin_elf.c (valid_p): Create fake_loclists_cu if necessary.
+	* dwarf_end.c (dwarf_end): Clean up fake_loclists_cu.
+	* dwarf_getlocation.c (initial_offset): Handle .debug_loclists.
+	(getlocations_addr): Likewise.
+	(dwarf_getlocation_addr): Likewise.
+	* dwarf_getlocation_attr.c (attr_form_cu): Use fake_loclists_cu for
+	DWARF5.
+	(initial_offset): Handle DW_FORM_loclistx.
+	* dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Handle
+	.debug_loclists.
+	* libdwP.h (struct Dwarf): Add fake_loclists_cu.
+
+2018-04-12  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DWARF5 location list entry DW_LLE encodings.
+	* begin_elf.c (dwarf_scnnames): Add IDX_debug_loclists.
+	* dwarf_error.c (errmsgs): Remove DWARF_E_NO_LOCLIST. And replace
+	with DWARF_E_NO_DEBUG_LOC, DWARF_E_NO_DEBUG_LOCLISTS and
+	DWARF_E_NO_LOC_VALUE.
+	* dwarf_formudata.c (dwarf_formudata): Handle DW_AT_loclists_base
+	and DW_FORM_loclistx.
+	* dwarf_getlocation.c (attr_ok): Use DWARF_E_NO_LOC_VALUE.
+	(initial_offset): Use DWARF_E_NO_DEBUG_LOC.
+	* libdwP.h: Add IDX_debug_rnglists. Remove DWARF_E_NO_LOCLIST.
+	Add DWARF_E_NO_DEBUG_LOC, DWARF_E_NO_DEBUG_LOCLISTS and
+	DWARF_E_NO_LOC_VALUE.
+
+2018-05-25  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_find_split_unit.c (__libdw_find_split_unit): Extract linking
+	skeleton and split compile units code into...
+	* libdwP (__libdw_link_skel_split): ...this new function.
+
+2018-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formaddr.c (__libdw_addrx): New function, extracted from...
+	(dwarf_formaddr): here. Use __libdw_addrx.
+	* dwarf_getlocation.c (getlocations_addr): Pass cu to
+	__libdw_read_begin_end_pair_inc.
+	* dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Take cu as
+	argument. Handle .debug_rnglists.
+	(initial_offset): Handle .debug_rnglists and DW_FORM_rnglistx.
+	(dwarf_ranges): Likewise. Check cu isn't NULL before use. Pass cu to
+	__libdw_read_begin_end_pair_inc.
+	* libdwP.h (__libdw_read_begin_end_pair_inc): Take cu as argument.
+	(__libdw_cu_ranges_base): Handle DW_AT_rnglists_base.
+	(__libdw_addrx): New function definition.
+
+2018-04-11  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DWARF5 range list entry DW_RLE encodings.
+	* begin_elf.c (dwarf_scnnames): Add IDX_debug_rnglists.
+	* dwarf_error.c (errmsgs): Add DWARF_E_NO_DEBUG_RNGLISTS.
+	* dwarf_formudata.c (dwarf_formudata): Handle DW_AT_rnglists_base
+	and DW_FORM_rnglistx.
+	* dwarf_getscopes.c (pc_match): Also check for
+	DWARF_E_NO_DEBUG_RNGLISTS.
+	* libdwP.h: Add IDX_debug_rnglists.
+
+2018-05-25  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation_attr.c (__libdw_cu_addr_base): Cast offset to
+	uintptr_t before returning as pointer.
+
+2018-05-22  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (__libdw_cu_base_address): Treat errors of
+	getting lowpc or entrypc the same as missing base address (zero).
+	* dwarf_highpc (dwarf_highpc): Handle any address form. Always set
+	error when attribute could not be found.
+
+2018-05-21  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (valid_p): Add a fake_addr_cu to the result.
+	* dwarf_end.c (cu_free): Disconnect the fake_addr_cu from the split
+	dwarf if shared with skeleton.
+	(dwarf_end): release fake_addr_cu.
+	* dwarf_formaddr.c (__libdw_cu_addr_base): Move to...
+	* libdwP.h (__libdw_cu_addr_base): ... here.
+	(struct Dwarf): Add fake_addr_cu field.
+	* dwarf_formudata.c (dwarf_formudata): Handle
+	DW_FORM_GNU_addr_index and DW_FORM_addrx[1234].
+	* dwarf_getlocation_attr.c (addr_valp): New static function.
+	(dwarf_getlocation_attr): Create attribute for values of
+	DW_OP_GNU_const_index, DW_OP_constx and DW_OP_GNU_addr_index and
+	DW_OP_addrx.
+	* libdw_find_split_unit.c (__libdw_find_split_unit): Connect
+	IDX_debug_addr sectiondata and fake_addr_cu between split and
+	skeleton.
+
+2018-05-20  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_cu_info.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_cu_info.c.
+	* libdw.h (dwarf_cu_info): New function declaration.
+	* libdw.map (ELFUTILS_0.171): Add dwarf_cu_info.
+
+2018-05-24  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_ranges.c (dwarf_ranges): Check for NULL cu.
+	* libdw_findcu.c (__libdw_intern_next_unit): Initialize ranges_base.
+
+2018-05-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formudata.c (__libdw_formptr): Handle the special case
+	of IDX_debug_ranges for DW_UT_split_compile with version < 5.
+	* dwarf_highpc.c (dwarf_highpc): Use dwarf_lowpc, check for
+	split compile cudie.
+	* dwarf_lowpc.c (dwarf_lowpc): Check for split compile cudie.
+	* dwarf_ranges.c (dwarf_ranges): Switch cu and sectiondata for
+	split compile units.
+	* libdwP.h (struct Dwarf_CU): Add ranges_base field.
+	(__libdw_cu_ranges_base): New static inline function.
+
+2018-05-18  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_findcu.c (__libdw_intern_next_unit): Init files to NULL.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Handle split units by
+	taking the line table from the skeleton.
+	* dwarf_getsrcfiles.c (dwarf_getsrcfiles): Handle split units by
+	only taking the files from .debug_line offset zero (if it exists),
+	otherwise fall back to the skeleton.
+
+2018-05-17  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (__libdw_debugdir): New function.
+	(valid_p): Call __libdw_debugdir.
+	* dwarf_end.c (dwarf_end.c): Free debugdir.
+	* dwarf_getalt.c (__libdw_filepath): Extract __libdw_debugdir logic.
+	take debugdir as argument instead of fd.
+	(find_debug_altlink): Call __libdw_filepath with debugdir.
+	* libdwP.h (struct Dwarf): Add debugdir field.
+	(__libdw_debugdir): New function prototype.
+	(__libdw_filepath): Adjust prototype to take a const char * instead of
+	an int.
+	* libdw_find_split_unit.c (__libdw_find_split_unit): Call
+	__libdw_filepath with debugdir.
+
+2018-05-17  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_attr_integrate.c (dwarf_attr_integrate): Handle split_compile
+	unit DIE, search skeleton_compile unit DIE.
+	* dwarf_hasattr_integrate.c (dwarf_hasattr_integrate): Likewise.
+	* libdwP.h (is_cudie): Check cu is not NULL.
+
+2018-05-19  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (__libdw_find_split_unit): Mark as internal_function.
+
+2018-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdw_a_SOURCES): Add libdw_find_split_unit.c.
+	* dwarf_end.c (cu_free): Free split Dwarf.
+	* dwarf_get_units.c (dwarf_get_units): Handle DW_UT_skeleton by
+	calling __libdw_find_split_unit.
+	* libdwP.h (struct Dwarf_CU): Add split Dwarf_CU field.
+	(__libdw_find_split_unit): New function prototype.
+	(str_offsets_base_off): Use cu Dwarf if dbg is NULL.
+	(filepath): Rename to ...
+	(__libdw_filepath): This. Which is the actual function name in
+	dwarf_getalt.c.
+	(libdw_find_split_unit.c): New file.
+	* libdw_findcu.c (__libdw_intern_next_unit): Initialize split to -1.
+
+2018-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (__libdw_first_die_from_cu_start): Adjust commented out
+	asserts.
+	* libdw_findcu.c (__libdw_intern_next_unit): For version 4 DWARF if
+	the cudie has a DW_AT_GNU_dwi_id set the unit_id8 and unit_type to
+	DW_UT_skeleton or DW_UT_split_compile based on whether the cudie has
+	child DIEs and a DW_AT_GNU_dwo_name attribute.
+
+2018-05-14  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add GNU Debug Fission extensions. DW_AT_GNU_dwo_name,
+	DW_AT_GNU_dwo_id, DW_AT_GNU_ranges_base, DW_AT_GNU_addr_base,
+	DW_AT_GNU_pubnames, DW_AT_GNU_pubtypes. DW_FORM_GNU_addr_index,
+	DW_FORM_GNU_str_index. DW_OP_GNU_addr_index, DW_OP_GNU_const_index.
+	* dwarf_formaddr.c (dwarf_formaddr): Handle DW_FORM_GNU_addr_index
+	as DW_FORM_addrx.
+	(__libdw_cu_addr_base): Check for both DW_AT_GNU_addr_base and
+	DW_AT_addr_base.
+	* dwarf_formstring.c (dwarf_formstring): Handle DW_FORM_GNU_str_index
+	as DW_FORM_strx.
+	* dwarf_formudata.c (dwarf_formudata): Recognize DW_AT_GNU_addr_base
+	as addrptr. Recognize DW_AT_GNU_ranges_base as rangelistptr.
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_GNU_addr_index as DW_OP_addrx and DW_OP_GNU_const_index as
+	DW_OP_constx.
+	* libdw_form.c (__libdw_form_val_compute_len): Handle
+	DW_FORM_GNU_addr_index and DW_FORM_GNU_str_index taking an uleb128.
+
+2018-05-12  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (check_section): Also recognize .dwo section
+	name variants.
+
+2018-05-11  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formudata.c (dwarf_formudata): Handle DW_AT_macros as macptr.
+	* dwarf_getmacros.c (get_table_for_offset): Add DW_MACRO_define_sup,
+	DW_MACRO_undef_sup, DW_MACRO_import_sup, DW_MACRO_define_strx and
+	DW_MACRO_undef_strx. Add str_offsets_base_off to fake CU. Deal with
+	DW_AT_macros. Use libdw_valid_user_form.
+
+2018-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formstring.c (__libdw_cu_str_off_base): Moved to...
+	* libdwP.h (__libdw_cu_str_off_base): ...here. Make static inline.
+	(str_offsets_base_off): New internal function that also parses
+	.debug_str_offsets header if necessary.
+
+2018-05-11  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_siblingof.c (dwarf_siblingof): Don't reference cu till it is
+	known the Dwarf_Die is came from is valid.
+	* libdwP.h (__libdw_dieabbrev): Check cu is not NULL.
+
+2018-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formref.c (__libdw_formref): Explicitly don't handle
+	DW_FORM_ref_sup4 and DW_FORM_ref_sup8.
+	* dwarf_formref_die.c (dwarf_formref_die): Handle DW_FORM_ref_sup4
+	and DW_FORM_ref_sup8.
+	* dwarf_formstring.c (dwarf_formstring): Handle DW_FORM_strp_sup
+	as DW_FORM_GNU_strp_alt.
+
+2018-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DWARF line content descriptions.
+	* libdwP.h (libdw_valid_user_form): New static function.
+	* dwarf_getsrclines.c (read_srclines): Check and parse version 5
+	DWARF header, dir and file tables separately from older versions
+	where different.
+
+2018-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (dwarf_scnnames): Add ".debug_line_str".
+	* dwarf_error.c (errmsgs): Add DWARF_E_NO_DEBUG_STR and
+	DWARF_E_NO_DEBUG_LINE_STR.
+	* dwarf_formstring.c (dwarf_formstring): Handle DW_FORM_line_strp.
+	Get data from either .debug_str or .debug_line_str.
+	* libdwP.h: Add IDX_debug_line_str, DWARF_E_NO_DEBUG_STR and
+	DWARF_E_NO_DEBUG_LINE_STR.
+
+2018-04-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formudata.c (__libdw_formptr): Take and return const
+	unsigned char pointers.
+	* dwarf_getlocation.c (attr_base_address): Rename to...
+	(__libdw_cu_base_address): this. Take Dwarf_CU, check and set
+	base_address.
+	(initial_offset_base): Renamed to...
+	(initial_offset): this. Only provide offset.
+	(getlocations_addr): Move data size check and
+	address base addition into __libdw_read_begin_end_pair_inc. Use
+	__libdw_cu_base_address and initial_offset. Drop Elf_Data NULL
+	check (already done by initial_offset, through __libdw_formptr).
+	(dwarf_getlocations): Use __libdw_cu_base_address and initial_offset.
+	Drop Elf_Data NULL check.
+	* dwarf_ranges.c (__libdw_read_begin_end_pair_inc): Change argument
+	type of readp to Add readend argument. Check data size. Include base
+	in begin and end result.
+	(initial_offset): New static function.
+	(dwarf_ranges): Don't check Elf_Data being NULL (already done by
+	initial_offset, through __libdw_formptr). Use __libdw_cu_base_address
+	and initial_offset. Remove base check and addition (already done by
+	__libdw_read_begin_end_pair_inc.
+	* libdwP.h (Dwarf_CU): Add base_address field.
+	(__libdw_read_begin_end_pair_inc): Change argument type of readp to
+	const. Add readend argument.
+	(__libdw_formptr): Take and return const unsigned char pointers.
+	* libdw_findcu.c (__libdw_intern_next_unit): Initialize Dwarf_CU
+	base_address.
+
+2018-04-04  Mark Wielaard  <mark@klomp.org>
+
+	* libdw_findcu.c (__libdw_intern_next_unit): Initialize Dwarf_CU
+	addr_base and str_off_base.
+
+2018-03-23  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (dwarf_scnnames): Add IDX_debug_str_offsets,
+	increase size.
+	* dwarf_error.c (errmsgs): Add DWARF_E_NO_STR_OFFSETS.
+	* dwarf_formstring.c (dwarf_formstring): Handle DW_FORM_strx[1234].
+	(__libdw_cu_str_off_base): New function.
+	* dwarf_formudata.c (dwarf_formudata): Handle IDX_debug_str_offsets
+	as stroffsetsptr.
+	* libdwP.h: Add IDX_debug_str_offsets and DWARF_E_NO_STR_OFFSETS.
+	(struct Dwarf_CU): Add str_off_base field.
+	(__libdw_cu_str_off_base): New function declaration.
+
+2018-03-22  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_begin_elf.c (dwarf_scnnames): Add IDX_debug_addr.
+	* dwarf_error.c (errmsgs): Add DWARF_E_NO_DEBUG_ADDR.
+	* dwarf_formaddr.c (dwarf_formaddr): Handle DW_FORM_addrx[1234].
+	(__libdw_cu_addr_base): New function.
+	* dwarf_formudata.c (dwarf_formudata): Handle DW_AT_addr_base as
+	addrptr.
+	* libdwP.h: Add IDX_debug_addr and DWARF_E_NO_DEBUG_ADDR.
+	(struct Dwarf_CU): Add addr_base field.
+	(__libdw_cu_addr_base): New function definition.
+	* memory-access.h (file_byte_order): New static function.
+	(read_3ubyte_unaligned): New inline function.
+
+2018-03-29  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.h (dwarf_decl_file): Extend documentation.
+	(dwarf_linesrc): Likewise.
+	(dwarf_filesrc): Likewise.
+
+2018-03-06  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_OP_implicit_pointer, DW_OP_addrx, DW_OP_constx,
+	DW_OP_entry_value, DW_OP_const_type, DW_OP_regval_type,
+	DW_OP_deref_type, DW_OP_xderef_type, DW_OP_convert and
+	DW_OP_reinterpret.
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_convert, DW_OP_reinterpret, DW_OP_addrx, DW_OP_constx,
+	DW_OP_regval_type, DW_OP_entry_value, DW_OP_implicit_pointer,
+	DW_OP_deref_type, DW_OP_xderef_type and DW_OP_const_type.
+	* dwarf_getlocation_attr.c (dwarf_getlocation_attr): Handle
+	DW_OP_entry_value, DW_OP_const_type and DW_OP_implicit_pointer.
+	* dwarf_getlocation_die.c (dwarf_getlocation_die): Handle
+	DW_OP_implicit_pointer, DW_OP_convert, DW_OP_reinterpret,
+	DW_OP_const_type, DW_OP_regval_type, DW_OP_deref_type and
+	DW_OP_xderef_type.
+	* dwarf_getlocation_implicit_pointer.c
+	(dwarf_getlocation_implicit_pointer): Handle DW_OP_implicit_pointer.
+
+2018-03-01  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_AT_GNU_locviews and DW_AT_GNU_entry_view.
+	* dwarf_formudata.c (dwarf_formudata): Handle DW_AT_GNU_locviews
+	as a loclistptr.
+
+2018-02-09  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_formblock.c (dwarf_formblock): Handle DW_FORM_data16 as a
+	16 byte block.
+
+2018-02-09  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_child.c (__libdw_find_attr): Handle DW_FORM_implicit_const.
+	* dwarf_formsdata.c (dwarf_formsdata): Likewise.
+	* dwarf_formudata.c (dwarf_formudata): Likewise.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Likewise.
+	* dwarf_getattrs.c (dwarf_getattrs): Likewise.
+	* dwarf_hasattr.c (dwarf_hasattr): Likewise.
+	* dwarf_getabbrevattr.c (dwarf_getabbrevattr_data): New function
+	that will also return any data associated with the abbrev. Which
+	currently is only for DW_FORM_implicit_const. Based on...
+	(dwarf_getabbrevattr): ... this function. Which now just calls
+	dwarf_getabbrevattr_data.
+	* libdw.h (dwarf_getabbrevattr_data): Declare new function.
+	* libdw.map (ELFUTILS_0.170): Add dwarf_getabbrevattr_data.
+	* libdwP.h (dwarf_getabbrevattr_data): INTDECL.
+	* memory-access.h (__libdw_get_sleb128_unchecked): New inlined
+	function based on __libdw_get_uleb128_unchecked.
+
+2018-02-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DWARF5 DW_FORMs.
+	* libdwP.h (__libdw_form_val_compute_len): Handle fix length
+	DW_FORM_implicit_const, DW_FORM_addrx[1234], DW_FORM_strx[1234],
+	DW_FORM_ref_sup[48] and DW_FORM_data16.
+	* libdw_form.c (__libdw_form_val_compute_len): DW_FORM_strp_sup
+	and DW_FORM_line_strp are offset_size. DW_FORM_addrx, DW_FORM_strx,
+	DW_FORM_loclistx and DW_FORM_rnglistx are uleb128.
+
+2018-01-30  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_get_units.c.
+	* dwarf_get_units.c: New file.
+	* libdw.h (dwarf_get_units): New function declaration.
+	* libdw.map (ELFUTILS_0.170): Add dwarf_get_units.
+
+2018-01-29  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h (DW_UT_*): Add DWARF Unit Header Types.
+	* dwarf_cu_die.c (dwarf_cu_die): Rename arguments. type_signaturep
+	is now called unit_idp. type_offsetp is now called subdie_offsetp.
+	* dwarf_formref_die.c (dwarf_formref_die): Scan both .debug_info
+	and .debug_types sections for type units when type signature ref
+	not found.
+	* dwarf_getaranges.c (dwarf_getaranges): Use __libdw_findcu and
+	__libdw_first_die_off_from_cu instead of trying by hand.
+	* dwarf_getlocation_die.c (dwarf_getlocation_die): Use ISV4TU
+	instead of checking type_offset by hand.
+	* dwarf_getlocation_implicit_pointer.c
+	(dwarf_getlocation_implicit_pointer): Likewise.
+	* dwarf_nextcu.c (dwarf_next_unit): Call __libdw_next_unit.
+	(__libdw_next_unit): New function based on dwarf_next_unit with
+	DWARF5 header support.
+	* libdwP.h (struct Dwarf_CU): Renamed type_offset to subdie_offset
+	and type_sig8 to unit_id8.
+	(ISV4TU): New macro to determine whether a CU is a version 4 type
+	unit (which comes from the .debug_types section).
+	(DIE_OFFSET_FROM_CU_OFFSET): Replaced macro by real function...
+	(__libdw_first_die_from_cu_start): ... that also handles DWARF5
+	unit headers.
+	(__libdw_first_die_off_from_cu): New function that calls the above
+	using the CU fields.
+	(CUDIE): Use __libdw_first_die_off_from_cu.
+	(SUBDIE): New macro that provides the DIE for a CU using the
+	subdie_offset.
+	(__libdw_next_unit): New internal function declaration.
+	* libdw_findcu.c (__libdw_intern_next_unit): Use __libdw_next_unit.
+	Accept DWARF version 5 headers. Setup unit_type.
+	(__libdw_findcu): Rename debug_types argument to v4_debug_types
+	argument (to indicate that we are looking in the .debug_types
+	section). Support finding the exact offset (unit header start).
+
+2018-01-25  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_die_addr_die.c.
+	* dwarf_die_addr_die.c: New file.
+	* libdw.h (dwarf_die_addr_die): New function declaration.
+	* libdw.map (ELFUTILS_0.171): New section with dwarf_die_addr_die.
+	* libdwP.h (__libdw_findcu_addr): New internal function declaration.
+	* libdw_findcu.c (__libdw_findcu_addr): New internal function.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* cfi.c (execute_cfi): Use FALLTHROUGH macro instead of comment.
+	* dwarf_frame_register.c (dwarf_frame_register): Likewise.
+
+2018-01-22  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (AM_CPPFLAGS): Add -I libdwelf.
+	* dwarf_begin_elf.c (dwarf_begin_elf): Initialize Dwarf alt_fd to -1.
+	* dwarf_end.c (dwarf_end): Call dwarf_end and close on the alt_dwarf
+	and alt_fd if we allocated them.
+	* dwarf_fromref_die.c (dwarf_formref_die): Call dwarf_getalt.
+	* dwarf_formstring.c (dwarf_formstring): Likewise.
+	* dwarf_getalt.c (__libdw_filepath): New internal function.
+	(find_debug_altlink): New static function.
+	(dwarf_getalt): Check Dwarf alt_dwarf and call find_debug_altlink.
+	Cache result.
+	* dwarf_setalt.c (dwarf_setalt): Clean up Dwarf alt_dwarf and alt_fd
+	if we allocated.
+	* libdw.h (dwarf_getalt): Extend documentation.
+	(dwarf_setalt): Likewise.
+	* libdwP.h (struct Dwarf): Add alt_fd field.
+	(filepath): Declare new internal function.
+
+2018-01-14  Petr Machata  <pmachata@gmail.com>
+
+	* dwarf_formsdata.c (dwarf_formsdata):
+	<DW_FORM_data1>: Cast to signed char.
+	<DW_FORM_data2,4,8>: Use read_*sbyte_unaligned instead of
+	read_*ubyte_unaligned.
+
+2017-12-26  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (struct Dwarf_Abbrev): Pack struct. Remove attrcnt,
+	use bitfields for has_children and code.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Don't count attrs.
+	* dwarf_getattrcnt.c (dwarf_getattrcnt): Count attrs.
+
+2017-12-26  Mark Wielaard  <mark@klomp.org>
+
+	* memory-access.h (__libdw_get_uleb128_unchecked): New function.
+	(get_uleb128_unchecked): New define.
+	* dwarf_child.c (__libdw_find_attr): Use get_uleb128_unchecked to
+	read attr name and form.
+	* dwarf_getabbrevattr.c (dwarf_getabbrevattr): Likewise.
+	* dwarf_getattrs.c (dwarf_getattrs): Likewise.
+	* dwarf_hasattr.c (dwarf_hasattr): Likewise.
+
+2017-12-28  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_offdie.c (__libdw_offdie): Check sectiondata exists.
+
+2017-05-09  Ulf Hermann  <ulf.hermann@qt.io>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (__libdw_in_section): Fix check for the upper border of
+	the range.
+	(__libdw_offset_in_section): Likewise.
+
+2017-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* libdwP.h (struct Dwarf_CU): Add sec_idx field.
+	(cu_sec_idx): Return cu->sec_idx.
+	* libdw_findcu.c (__libdw_intern_next_unit): Set cu sec_idx to
+	IDX_debug_info or IDX_debug_types.
+	* dwarf_begin_elf.c (valid_p): Set fake_loc_cu->sec_idx to
+	IDX_debug_loc.
+	* dwarf_getmacros.c (read_macros): Set fake_cu->sec_idx to
+	IDX_debug_macro or IDX_debug_macinfo.
+
+2017-12-12  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_aggregate_size.c (dwarf_aggregate_size): Don't peel the
+	given DIE. Reserve memory for a new DIE first.
+
+2017-12-11  Dima Kogan  <dima@secretsauce.net>
+
+	* dwarf_aggregate_size.c (array_size): Handle multi-dimensional
+	arrays properly.
+
+2017-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_GNU_variable_value.
+	* dwarf_getlocation_attr.c (dwarf_getlocation_attr): Likewise.
+	* dwarf_getlocation_die.c (dwarf_getlocation_die): Likewise.
+
+2017-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_getlocation.c (attr_ok): Always accept DW_FORM_exprloc.
+	Update list of acceptable attribute codes based on DWARF5.
+
+2017-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_OP_GNU_variable_value.
+
+2017-10-03  Mark Wielaard  <mark@klomp.org>
+
+	* libdw.h: Define LIBDW_CIE_ID and use it in dwarf_cfi_cie_p.
+
+2017-08-18  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* memory-access.h: Use attribute_packed.
+
+2017-02-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libdwP.h: Use attribute_hidden.
+	* libdw_alloc.c: Likewise.
+
+2017-02-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Use fpic_CFLAGS and dso_LDFLAGS.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_MACRO_* and compat defines for DW_MACRO_GNU_*.
+	* dwarf_getmacros.c (get_table_for_offset): Accept either version
+	4 or 5. Use DW_MACRO names instead of DW_MACRO_GNU names.
+	(read_macros): Use table version for fake_cu.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_peel_type.c (dwarf_peel_type): Handle DW_TAG_immutable_type,
+	DW_TAG_packed_type and DW_TAG_shared_type.
+	* libdw.h (dwarf_peel_type): Extend documentation.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_DEFAULTED_no, DW_DEFAULTED_in_class and
+	DW_DEFAULTED_out_of_class.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_CC_pass_by_reference and DW_CC_pass_by_reference.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_default_lower_bound.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_default_lower_bound.c.
+	* dwarf_aggregate_size.c (array_size): Use dwarf_default_lower_bound.
+	* dwarf_error.c (errmsgs): Add DWARF_E_UNKNOWN_LANGUAGE.
+	* libdw.h: Add dwarf_default_lower_bound.
+	* libdw.map (ELFUTILS_0.170): Add dwarf_default_lower_bound.
+	* libdwP.h: Add DWARF_E_UNKNOWN_LANGUAGE and
+	dwarf_default_lower_bound INTDECL.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_LANG_OpenCL, DW_LANG_Modula3,
+	DW_LANG_C_plus_plus_03, DW_LANG_OCaml, DW_LANG_Rust, DW_LANG_Swift,
+	DW_LANG_Julia, DW_LANG_Dylan, DW_LANG_RenderScript, DW_LANG_BLISS.
+	* dwarf_aggregate_size.c (array_size): Add lower bound for
+	DW_LANG_C_plus_plus_03, DW_LANG_Python, DW_LANG_OpenCL,
+	DW_LANG_Haskell, DW_LANG_OCaml, DW_LANG_Rust, DW_LANG_Swift,
+	DW_LANG_Dylan, DW_LANG_RenderScript, DW_LANG_Modula3,
+	DW_LANG_Julia and DW_LANG_BLISS.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_ATE_UCS and DW_ATE_ASCII.
+
+2017-07-25  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h: Add DW_TAG_coarray_type, DW_TAG_generic_subrange,
+	DW_TAG_dynamic_type, DW_TAG_call_site, DW_TAG_call_site_parameter,
+	DW_TAG_skeleton_unit, DW_TAG_immutable_type. Add reserved comments
+	for currently unused numbers.
+
+2017-07-25  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf.h (DWARF attributes enum): Remove DW_AT_subscr_data,
+	DW_AT_element_list and DW_AT_member. Add DWARF5 attribute constants.
+	(DW_AT_subscr_data, DW_AT_element_list, DW_AT_member): New defines.
+
+2017-07-21  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_line_file.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_line_file.c.
+	* libdw.h (dwarf_line_file): New function declaration.
+	* libdw.map (ELFUTILS_0.170): New. Add dwarf_line_file.
+
+2017-02-17  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Add libdw_so_LIBS to specify the archives libdw is is
+	made of, libdw_so_DEPS for libraries it depends on (including
+	libeu.a), libdw_so_LDLIBS to specify libraries libdw links against.
+	(libdw.so$(EXEEXT)): Add $(libdw_so_LDLIBS), remove enumeration of
+	library dependencies, use libdw_so_LIBS rather than relying on the
+	order of dependencies specified, add -z,relro.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libdw.h: Remove attribute macro declarations and use
+	__noreturn_attribute__ as defined in libelf.h.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* dwarf_begin_elf.c: Include endian.h.
+
+2017-03-30  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_peel_type.c (dwarf_peel_type): Call dwarf_attr_integrate on
+	result.
+
+2016-10-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Correct spelling of DW_LANG_PLI. Add compatibility define.
+	* dwarf_aggregate_size.c (array_size): Use correct spelling of
+	DW_LANG_PLI.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.c (execute_cfi): Add fallthrough comments.
+	* encoded-value.h (encoded_value_size): Add explicit return instead
+	of relying on fallthrough.
+	* dwfl_report_elf.c (__libdwfl_elf_address_range): Add fallthrough
+	comment.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* dwarf_getpubnames.c: Remove sys/param.h include, add system.h.
+	* libdw_alloc.c: Likewise.
+
+2016-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.167): New. Add dwelf_strtab_init,
+	dwelf_strtab_add, dwelf_strtab_add_len, dwelf_strtab_finalize,
+	dwelf_strent_off, dwelf_strent_str and dwelf_strtab_free.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Calculate ndirs first, then
+	assign to ndirlist.
+
+2015-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwP.h (struct Dwarf): Remove sectiondata_gzip_mask.
+	(__libdw_free_zdata): Remove.
+	* dwarf_begin_elf.c (inflate_section): Remove.
+	(check_section): Remove __libdw_free_zdata calls. Use elf_compress
+	and elf_compress_gnu to decompress if necessary.
+	(valid_p): Remove __libdw_free_zdata calls.
+	(scngrp_read): Use elf_compress if section is compressed. Remove
+	__libdw_free_zdata calls.
+	* dwarf_end.c (__libdw_free_zdata): Remove.
+	(dwarf_end): Don't call __libdw_free_zdata.
+
+2015-10-28  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.165): New. Add dwelf_scn_gnu_compressed_size.
+
+2015-12-02  Mark Wielaard  <mjw@redhat.com>
+
+	* fde.c (intern_fde): Don't leak duplicate FDEs.
+
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* fde.c (intern_fde): Don't intern an fde that doesn't cover a
+	valid code range.
+
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_end.c (dwarf_end): Call cu_free on fake_loc_cu if it exists.
+
+2015-10-14  Chih-Hung Hsieh  <chh@google.com>
+
+	* dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Move recursive
+	functions 'add_bkpt', 'entrypc_bkpt', and 'search_range' to file scope.
+
+2015-10-14  Chih-Hung Hsieh  <chh@google.com>
+
+	* libdw_visit_scopes.c (__libdw_visit_scopes): Move recursive nested
+	function 'walk_children' to file scope; inline 'recurse' at its call
+	site.
+
+2015-10-19  Mark Wielaard  <mjw@redhat.com>
+
+	* frame-cache.c (__libdw_destroy_frame_cache): Call ebl_closebackend
+	if necessary.
+
+2015-10-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* dwarf_getsrclines.c (read_srclines): Initialize state early.
+
+2015-10-13  Chih-Hung Hsieh  <chh@google.com>
+
+	* dwarf_getsrclines.c (read_srclines): Move nested functions
+	'advance_pc' and 'add_new_line' to file scope and keep many
+	local state variables within one structure.
+
+2015-10-13  Chih-Hung Hsieh  <chh@google.com>
+
+	* dwarf_getscopevar.c (dwarf_getscopevar): Move nested
+	function 'file_matches' to file scope.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdw.so): Add -lz.
+
+2015-10-14  Chih-Hung Hsieh  <chh@google.com>
+
+	* cfi.c (execute_cfi): Move nested functions 'enough_registers'
+	and 'require_cfa_offset' to file scope.
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* dwarf_begin.c (dwarf_begin): Replace stat64 and fstat64 with stat
+	and fstat.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (libdw.so): Add AM_V_CCLD and AM_V_at silencers.
+
+2015-09-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* Makefile.am (AM_CFLAGS): Use -fPIC instead of -fpic to avoid
+	relocation overflows in some platforms.
+
+2015-09-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_error.c (__libdw_seterrno): Mark as internal_function.
+	* dwarf_formref.c (__libdw_formref): Likewise.
+	* libdw_findcu.c (__libdw_findcu): Likewise.
+	* libdw_visit_scopes.c (__libdw_visit_scopes): Likewise.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* *.c: Remove old-style function definitions.
+
+2015-09-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_peel_type.c (dwarf_peel_type): Don't reassign result pointer.
+
+2015-09-09  Chih-Hung Hsieh  <chh@google.com>
+
+	* dwarf_macro_getsrcfiles.c (dwarf_macro_getsrcfiles): Remove
+	redundant NULL tests on parameters declared with __nonnull_attribute__.
+	* dwarf_siblingof.c (dwarf_siblingof): Likewise.
+	* libdw_visit_scopes.c (__libdw_visit_scopes): Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (getlocations_addr): Replace K&R function
+	definition with ansi-C definition and add const qualifier to
+	locs argument.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* libdw_findcu.c (__libdw_intern_next_unit): Replace K&R function
+	definition with ansi-C definitions.
+	(__libdw_findcu): Likewise.
+
+2015-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_LANG_Haskell.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_begin_elf.c (dwarf_begin_elf): Assert page size is big enough
+	to hold a Dwarf.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getpubnames.c (get_offsets): Always free mem on error.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getmacros.c (get_macinfo_table): Return NULL when
+	dwarf_formudata reports an error.
+	(get_table_for_offset): Likewise.
+
+2015-06-08  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Initialize dirarray early.
+
+2015-06-06  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Initialize filelist early.
+
+2015-05-27  Mark Wielaard  <mjw@redhat.com>
+
+	* encoded-value.h (read_encoded_value): Check data d_size contains
+	at least enough data to hold a pointer for DW_EH_PE_indirect.
+
+2015-05-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Limit stack usage of lines
+	with MAX_STACK_LINES, files with MAX_STACK_LINES and dirs with
+	MAX_STACK_DIRS. Calculate number of dirs needed first, then
+	create dirarray directly, without needing the next field. Free
+	not stack allocated lines and files at the end.
+
+2015-05-19  Mark Wielaard <mjw@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Create a stack
+	allocated array to hold locs. Allocate locs bigger than the array
+	with malloc and free them when done.
+
+2015-05-11  Jonathan Lebon  <jlebon@redhat.com>
+
+	* libdwP.h (DWARF_E_COMPRESSED_ERROR): New enumerator.
+	* dwarf_error.c (errmsgs): Add DWARF_E_COMPRESSED_ERROR message.
+	* dwarf_begin_elf.c (inflate_section): New static function, lifted
+	from...
+	(check_section): ... here. Call inflate_section, set libdw errno to
+	DWARF_E_COMPRESSED_ERROR if .debug_info section couldn't be inflated.
+
+2015-05-11  Jonathan Lebon  <jlebon@redhat.com>
+
+	* dwarf_begin_elf.c (check_section): Add compressed flag. Always
+	check for .zdebug sections. Only wrap decompression in #if USE_ZLIB.
+
+2015-05-06  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Use an int64_t to store and
+	check the line number.
+
+2015-05-05  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getaranges.c (dwarf_getaranges): Check there is enough data
+	left before reading values.
+
+2015-05-04  Anthony G. Basile  <blueness@gentoo.org>
+
+	* Makefile.am (libdw_so_SOURCES): Append $(argp_LDADD) to link
+	command.
+
+2015-04-22  Mark Wielaard  <mjw@redhat.com>
+
+	* memory-access.h (__libdw_max_len_leb128): Take type_len as argument.
+	(__libdw_max_len_uleb128): New function.
+	(__libdw_max_len_sleb128): Likewise.
+	(__libdw_get_uleb128): Use __libdw_max_len_uleb128.
+	(__libdw_get_sleb128): Use __libdw_max_len_sleb128.
+
+2015-04-21  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getmacros.c (read_macros): Allocate attributes dynamically
+	when there are more than 8.
+
+2015-04-01  Petr Machata  <pmachata@redhat.com>
+
+	* libdwP.h (DWARF_E_NOT_CUDIE): New enumerator.
+	(is_cudie): New function.
+	* dwarf_error.c (errmsgs): Add message for DWARF_E_NOT_CUDIE.
+	* dwarf_getsrcfiles.c (dwarf_getsrcfiles): Call is_cudie instead
+	of white-listing valid tags.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+
+2015-03-18  Petr Machata  <pmachata@redhat.com>
+
+	* Makefile.am (pkginclude_HEADERS): Add known-dwarf.h.
+	(EXTRA_DIST): Remove known-dwarf.h.
+
+2015-02-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_LANG_Fortran03 and DW_LANG_Fortran08.
+	* dwarf_aggregate_size.c (array_size): Recognize array lower bound
+	for new Fortran language codes is 1.
+
+2015-02-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_TAG_atomic_type.
+	* libdw.h (dwarf_peel_type): Document DW_TAG_atomic_type.
+	* dwarf_peel_type.c (dwarf_peel_type): Handle DW_TAG_atomic_type.
+
+2015-02-11  Josh Stone  <jistone@redhat.com>
+
+	* encoded-value.h (read_encoded_value): Initialize value.
+
+2015-02-11  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_ranges.c (dwarf_ranges): Do not bail out when neither
+	DW_AT_entry_pc nor DW_AT_low_pc are available.  Instead remember
+	the fact in *BASEP and bail out later if it hasn't been updated by
+	__libdw_read_begin_end_pair_inc.
+
+2014-12-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrc_die.c (dwarf_getsrc_die): Return the last line record
+	smaller than or equal to addr, rather than returning immediately on
+	a match.
+
+2015-01-07  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.h (struct Dwarf_CFI_s): Add search_table_len.
+	* dwarf_getcfi_elf.c (getcfi_gnu_eh_frame): Check there is enough
+	room in the search table for all entries. Store search_table_len.
+	(getcfi_scn_eh_frame): Likewise.
+	* encoded-value.h (encoded_value_size): Don't abort, return zero.
+	(__libdw_cfi_read_address_inc): Check there is enough room to read
+	values. Pass other byte order to read functions.
+	(read_encoded_value): Check encoded_value_size. Don't abort, but
+	set libdw errno and report failure. Check there is enough room to
+	read values.
+	* fde.c (binary_search_fde): Check encoded value size. Add hdr
+	data buf and size to dummy_cfi.
+
+2015-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_siblingof.c (dwarf_siblingof): Check sibling attribute
+	is after current DIE.
+
+2015-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.c (enough_registers): Check reg < INT32_MAX / sizeof
+	(dwarf_frame_register).
+
+2015-01-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getcfi_elf.c (parse_eh_frame_hdr): Add size check.
+	(getcfi_gnu_eh_frame): Remove size check. Check d_buf is not NULL.
+	(getcfi_scn_eh_frame): Check d_buf is not NULL.
+
+2015-01-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Check dbg is not
+	NULL for DW_OP_call_ref and DW_OP_GNU_implicit_pointer. For
+	DW_OP_addr if dbg is NULL then read argument directly.
+
+2015-01-14  Jason P. Leasure <jpleasu@super.org>
+
+	* dwarf_formref_die.c (dwarf_formref_die): Offset is cu->type_offset
+	plus cu->start.
+
+2014-12-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_siblingof.c (dwarf_siblingof): Check sibling attribute offset
+	still falls inside CU data.
+
+2015-01-11  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_func_inline.c (dwarf_func_inline_instances): Call
+	__libdw_visit_scopes with NULL imports.
+	* dwarf_getfuncs.c (dwarf_getfuncs): Likewise.
+	* dwarf_getscopes.c (pc_record): Likewise.
+	(dwarf_getscopes): Likewise.
+	* dwarf_getscopes_die.c (dwarf_getscopes_die): Likewise.
+	* libdwP.h (__libdw_visit_scopes): Add imports argument.
+	* libdw_visit_scopes.c (__libdw_visit_scopes): Likewise. Add new
+	function imports_contains. Push and pop imports around walk_children
+	when processing DW_TAG_imported_unit.
+
+2014-12-18  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am: Suppress output of textrel_check command.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Check diridx is valid under
+	DW_LNE_define_file.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getpubnames.c (dwarf_getpubnames): Make sure there is enough
+	space to read die offset.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Correct overflow check for
+	unit_length.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getpubnames.c (get_offsets): Make sure whole unit fall inside
+	section data. Set error to DWARF_E_NO_ENTRY if cnt is zero.
+	(dwarf_getpubnames): Make sure section data contains string zero
+	terminator.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* memory-access.h (__libdw_get_sleb128): Unroll the first step to help
+	the compiler optimize for the common single-byte case.
+
+2014-12-15  Josh Stone  <jistone@redhat.com>
+
+	* memory-access.h (__libdw_max_len_leb128): New.
+	(__libdw_get_uleb128): Use __libdw_max_len_leb128.
+	(__libdw_get_sleb128): Likewise.
+
+2014-12-14  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.c (execute_cfi): Add program bounds checks.
+	* dwarf_child.c (__libdw_find_attr): Add attrp bounds checks.
+	* dwarf_formblock.c (dwarf_formblock): Call get_uleb128 with endp.
+	* dwarf_formref.c (__libdw_formref): Add datap bounds checks.
+	* dwarf_formsdata.c (dwarf_formsdata): Likewise.
+	* dwarf_formudata.c (dwarf_formudata): Likewise.
+	* dwarf_frame_register.c (dwarf_frame_register): Call get_uleb128
+	with end of data buf.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Add abbrevp bounds checks.
+	* dwarf_getabbrevattr.c (dwarf_getabbrevattr): Assume get_uleb128
+	call gets enough data.
+	* dwarf_getattrs,c (dwarf_getattrs): Call get_uleb128 with endp.
+	* dwarf_getlocation.c (store_implicit_value): Call get_uleb128
+	with enough data.
+	(__libdw_intern_expression): Call get_uleb128/get_sleb128 with
+	end_data.
+	* dwarf_getmacros.c (get_table_for_offset): Add nforms bounds check.
+	* dwarf_getsrclines.c (read_srclines): Bounds check linep and call
+	get_uleb128 with lineendp.
+	* dwarf_hasattr.c (dwarf_hasattr): Bounds check attrp and call
+	get_uleb128 with endp.
+	* dwarf_next_cfi.c (dwarf_next_cfi): Bounds check bytes and call
+	get_uleb128/get_sleb128 with limit.
+	* encoded-value.h (read_encoded_value): Assume get_uleb128 and
+	get_sleb128 get called with enough data.
+	* fde.c (intern_fde): Call get_uleb128 with instructions_end.
+	* libdwP.h (__libdw_dieabbrev): Call get_uleb128 with die->cu->endp.
+	* libdw_form.c (__libdw_form_val_compute_len): Call get_uleb128 with
+	endp.
+	* memory-access.h (__libdw_get_uleb128): Take an extra endp.
+	Don't call get_uleb128_step if out of data.
+	(__libdw_get_sleb128): Likewise for get_sleb128_step.
+
+2014-12-12  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwP.h (struct Dwarf): Add fake_loc_cu.
+	(cu_data): Removed.
+	(DIE_OFFSET_FROM_CU_OFFSET): Don't use cu_data, use cu_sec_idx.
+	(__libdw_form_val_compute_len): Drop dbg and endp arguments.
+	(__libdw_form_val_len): Likewise.
+	* libdw_form.c (__libdw_form_val_compute_len): Likewise.
+	* libdw_findcu.c (__libdw_intern_next_unit): Don't use cu_data, use
+	the already found data buffer directly.
+	* dwarf_begin_elf.c (valid_p): Setup fake_loc_cu.
+	* dwarf_end.c (dwarf_end): Free fake_loc_cu.
+	* dwarf_child.c (__libdw_find_attr): Call __libdw_form_val_len with
+	just cu.
+	* dwarf_getattrs.c (dwarf_getattrs): Likewise.
+	* dwarf_formblock.c (dwarf_formblock): Add bounds checking.
+	* dwarf_getlocation_attr.c (attr_form_cu): New function.
+	(dwarf_getlocation_attr): Use attr_form_cu to set result->cu.
+	(getlocation): Handle empty blocks immediately.
+	* dwarf_getlocation_implicit_pointer.c (empty_cu): New static var.
+	(__libdw_empty_loc_attr): Drop cu argument, use empty_cu.
+	(dwarf_getlocation_implicit_pointer): Call __libdw_empty_loc_attr with
+	one argument.
+	* dwarf_getmacros.c (read_macros): Also setup startp and endp for
+	fake_cu. Call __libdw_form_val_len with just fake_cu.
+	* dwarf_formref_die.c (dwarf_formref_die): Don't use cu_data, get
+	datap and size directly from cu startp and endp.
+
+2014-12-11  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw_findcu.c (__libdw_intern_next_unit): Sanity check offset.
+
+2014-12-13  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getaranges.c (compare_aranges): Make sure Dwarf_Addr
+	difference doesn't wrap around before returning as int.
+
+2014-12-11  Josh Stone  <jistone@redhat.com>
+
+	* dwarf_getsrclines.c (struct linelist): Add sequence.
+	(compare_lines): Take linelists, and break ties by sequence.
+	(read_srclines): Use linelists for sorting.
+	(read_srclines::add_new_line): Set sequence.
+
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+	* libdwP.h (Dwarf_CU): Add startp and endp boundaries.
+	* libdw_findcu.c (__libdw_intern_next_unit): Set startp and endp.
+	* dwarf_child.c (dwarf_child): Use cu->endp.
+	* dwarf_cuoffset.c (dwarf_cuoffset): Use cu->startp.
+	* dwarf_dieoffset.c (dwarf_dieoffset): Use cu->startp.
+	* dwarf_siblingof.c (dwarf_siblingof): Use both.
+
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+	* dwarf_hasattr.c (dwarf_hasattr): Just walk abbrev for presence.
+
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+	* libdwP.h (__libdw_dieabbrev): New die->abbrev lookup function.
+	* dwarf_child.c (__libdw_find_attr, dwarf_child): Use it.
+	* dwarf_getattrs.c (dwarf_getattrs): Likewise.
+	* dwarf_haschildren.c (dwarf_haschildren): Likewise.
+	* dwarf_tag.c (dwarf_tag): Likewise.
+
+2014-12-04  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwP.h (__libdw_form_val_compute_len): Add endp argument.
+	(__libdw_form_val_len): Likewise and check len doesn't overflow.
+	* libdw_form.c (__libdw_form_val_compute_len): Likewise.
+	* dwarf_child.c (__libdw_find_attr): Call __libdw_form_val_len
+	with endp.
+	* dwarf_getattrs.c (dwarf_getattrs): Likewise.
+	* dwarf_getmacros.c (read_macros): Likewise and check for errors.
+
+2014-12-02  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_getmacros.c (token_from_offset, offset_from_token): New
+	helper functions.
+	(do_dwarf_getmacros_die): Merge into dwarf_getmacros.
+	* libdw.h (DWARF_GETMACROS_START): New macro.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdw.so): Use textrel_check.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getcfi_elf.c (getcfi_gnu_eh_frame): Initialize
+	search_table_entries and search_table_encoding.
+
+2014-11-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Check line_range is not zero
+	before usage.
+
+2014-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_attr.c (dwarf_attr): Check __libdw_find_attr return value.
+	* dwarf_hasattr.c (dwarf_hasattr): Likewise.
+	* dwarf_siblingof.c (dwarf_siblingof): Likewise.
+
+2014-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getabbrev.c (__libdw_getabbrev): Don't assert on bad DWARF.
+	Set libdw errno and return NULL.
+
+2014-11-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h (DW_LANG_C_plus_plus_11): Added.
+	(DW_LANG_C11): Likewise.
+	(DW_LANG_C_plus_plus_14): Likewise.
+	* dwarf_aggregate_size.c (array_size): Handle DW_LANG_C11,
+	DW_LANG_C_plus_plus_11, DW_LANG_C_plus_plus_14 and DW_LANG_Go
+	lower bound.
+	* dwarf_getfuncs.c (dwarf_getfuncs): Set c_cu to true for
+	DW_LANG_C11.
+
+2014-11-26  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h (DW_AT_noreturn): Added.
+
+2014-11-11  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (read_srclines): Do address_size comparison
+	explicitly as uint8_t.
+	(__libdw_getsrclines): Add internal_function to declaration.
+
+2014-09-10  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_macro_getparamcnt.c: New file.
+	* dwarf_macro_param.c: New file.
+	* dwarf_macro_getsrcfiles.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add the new files.
+	* libdwP.h (struct files_lines_s): New structure.
+	(DWARF_E_INVALID_OPCODE): New enumerator.
+	(struct Dwarf): New fields macro_ops, files_lines.
+	(Dwarf_Macro_Op_Proto, Dwarf_Macro_Op_Table): New structures for
+	keeping macro opcode prototypes in.
+	(Dwarf_Macro_s): Redefine from scratch.
+	(__libdw_getsrclines, __libdw_getcompdir, libdw_macro_nforms): New
+	internal interfaces.
+	* dwarf_error.c (errmsgs): Add a message for
+	DWARF_E_INVALID_OPCODE.
+	* dwarf_end.c (dwarf_end): Destroy struct Dwarf.macro_ops and
+	files_lines.
+	* libdw.h (dwarf_getmacros_off, dwarf_macro_getparamcnt)
+	(dwarf_macro_getsrcfiles, dwarf_macro_param): New public
+	interfaces.
+	* dwarf_getmacros.c (dwarf_getmacros_off): New function,
+	(get_offset_from, macro_op_compare, build_table)
+	(init_macinfo_table, get_macinfo_table, get_table_for_offset)
+	(cache_op_table, read_macros, gnu_macros_getmacros_off)
+	(macro_info_getmacros_off, do_dwarf_getmacros_die): New helper
+	functions.
+	(dwarf_getmacros): Adjust to dispatch to the new interfaces.
+	* dwarf_getsrclines.c (read_srclines): New function with guts
+	taken from dwarf_getsrclines.
+	(__libdw_getsrclines): Likewise.
+	(__libdw_getcompdir, files_lines_compare): New functions.
+	(dwarf_getsrclines): Make it dispatch to the new interfaces.
+	* dwarf_macro_param1.c (dwarf_macro_param1): Adjust to dispatch to
+	the new interfaces.
+	* dwarf_macro_param2.c (dwarf_macro_param2): Likewise.
+	* libdw.map (ELFUTILS_0.161): New. Add dwarf_getmacros_off,
+	dwarf_macro_getsrcfiles, dwarf_macro_getparamcnt, dwarf_macro_param.
+
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_peel_type.c.
+	* dwarf_aggregate_size.c (get_type): Use dwarf_peel_type.
+	(aggregate_size): Likewise. Add old and new version.
+	* dwarf_peel_type.c: New file.
+	* libdw.h (dwarf_peel_type): New function declaration.
+	* libdwP.h (dwarf_peel_type): New internal declaration.
+	* libdw.map (ELFUTILS_0.161): New section.
+
+2014-10-15  Petr Machata  <pmachata@redhat.com>
+
+	* libdwP.h (struct Dwarf_Files_s.cu): Drop field.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Don't set it.
+
+2014-10-05  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_AT_GNU_deleted.
+
+2014-10-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_aggregate_size.c (aggregate_size): Return CU address_size
+	for sizeless DW_TAG_pointer_type, DW_TAG_reference_type or
+	DW_TAG_rvalue_reference_type.
+
+2014-09-12  Petr Machata  <pmachata@redhat.com>
+
+	* memory-access.h (read_ubyte_unaligned_inc): Allow only 4- and
+	8-byte quantities.  Consequently, rename to...
+	(read_addr_unaligned_inc): ... this.
+	(read_sbyte_unaligned_inc, read_ubyte_unaligned): Drop.
+	(read_sbyte_unaligned): Drop.
+
+2014-09-10  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_getlocation.c (attr_ok): Also accept
+	DW_AT_GNU_call_site_value, DW_AT_GNU_call_site_data_value,
+	DW_AT_GNU_call_site_target, DW_AT_GNU_call_site_target_clobbered.
+
+2014-08-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_cu_die.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_cu_die.c.
+	* libdw.h (dwarf_cu_die): New function declaration.
+	* libdw.map (ELFUTILS_0.160): Add dwarf_cu_die.
+
+2014-08-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_cu_getdwarf.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_cu_getdwarf.c.
+	* libdw.h (Dwarf_CU): New typedef.
+	(dwarf_cu_getdwarf): New function declaration.
+	* libdw.map (ELFUTILS_0.160): New. Add dwarf_cu_getdwarf.
+
+2014-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Remove DW_TAG_mutable_type.
+
+2014-05-02  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwP.h (__check_build_id): Removed now unused.
+
+2014-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwP.h (struct Dwarf): Remove free_alt.
+	* dwarf_end.c (dwarf_end): Don't check free_alt, don't end alt_dwarf.
+	* dwarf_setalt.c (dwarf_setalt): Don't check or set free_alt.
+
+2014-04-30  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.159): Add dwelf_elf_gnu_build_id.
+
+2014-04-15  Florian Weimer  <fweimer@redhat.com>
+
+	* dwarf_begin_elf.c (__check_build_id, try_debugaltlink)
+	(open_debugaltlink): Move to libdwfl.
+	(check_section): Do not locate alternate debuginfo.
+
+2014-04-24  Florian Weimer  <fweimer@redhat.com>
+
+	* libdw.map (ELFUTILS_0.159): Export dwelf_dwarf_gnu_debugaltlink.
+
+2014-04-22  Florian Weimer  <fweimer@redhat.com>
+
+	* dwarf_getalt.c, dwarf_setalt.c: New files.
+	* Makefile.am (libdw_a_SOURCES): Add them.
+	* libdw.h (dwarf_getalt, dwarf_setalt): Add function declarations.
+	* libdwP.h (dwarf_getalt, dwarf_setalt): Add internal function
+	declarations.
+	* libdw.map (ELFUTILS_0.159): Export the two new functions.
+
+2014-04-15  Florian Weimer  <fweimer@redhat.com>
+
+	* libdwP.h (enum IDX_gnu_debugaltlink): New.
+	* dwarf_begin_elf.c (dwarf_scnnames): Increase string size and add
+	.gnu_debugaltlink.
+	(check_section): Obtain .gnu_debugaltlink section from the
+	setiondata array.
+
+2014-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.159): New. Add dwelf_elf_gnu_debuglink.
+	* Makefile.am (libdw.so): Depend on libdwelf_pic.a.
+	(libdwelf_objects): New variable.
+	(libdw_a_LIBADD): Add libdwelf objects.
+
+2014-04-22  Mark Wielaard  <mjw@redhat.com>
+
+	* memory-access.h (get_sleb128_step): Remove undefined behavior
+	of left shifting a signed value. Replace it with a multiplication.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove !MUDFLAP conditions.
+
+2014-04-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_begin_elf.c (check_section): Check for unsigned overflow
+	before calling malloc to uncompress data.
+
+2014-03-03  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix abort() on missing section headers.
+	* dwarf_begin_elf.c (check_section): Replace abort call by goto err.
+	New label err to return NULL.
+
+2014-02-05  Josh Stone  <jistone@redhat.com>
+
+	* dwarf_decl_file.c (dwarf_decl_file): Read the idx as unsigned.
+	* dwarf_decl_line.c (__libdw_attr_intval): Read the line/column as
+	unsigned.  Change the range assert to DWARF_E_INVALID_DWARF.
+
+2013-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.158): Add dwfl_core_file_attach and
+	dwfl_linux_proc_attach.
+
+2013-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.158): Add dwfl_getthread_frames.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.158): Remove dwfl_module_addrsym_elf and
+	dwfl_module_getsym_elf. Add dwfl_module_addrinfo and
+	dwfl_module_getsym_info.
+
+2013-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.158): Add dwfl_module_getsymtab_first_global.
+
+2013-12-10  Josh Stone  <jistone@redhat.com>
+
+	* memory-access.h (get_uleb128_rest_return): Removed.
+	(get_sleb128_rest_return): Removed.
+	(get_uleb128_step): Make this a self-contained block.
+	(get_sleb128_step): Ditto, and use a bitfield to extend signs.
+	(get_uleb128): Make this wholly implemented by __libdw_get_uleb128.
+	(get_sleb128): Make this wholly implemented by __libdw_get_sleb128.
+	(__libdw_get_uleb128): Simplify and inline for all callers.
+	(__libdw_get_sleb128): Ditto.
+	* dwarf_getlocation.c (store_implicit_value): Void the unused uleb128.
+	* memory-access.c: Delete file.
+	* Makefile.am (libdw_a_SOURCES): Remove it.
+	(DEFS): Remove the now unused -DIS_LIBDW.
+
+2013-12-09  Josh Stone  <jistone@redhat.com>
+
+	* libdw_form.c (__libdw_form_val_compute_len): Renamed function from
+	__libdw_form_val_len, now handling only non-constant form lengths.
+	* libdwP.h (__libdw_form_val_len): New inlined function.
+
+2013-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle empty
+	location expressions.
+	* dwarf_getlocation_attr.c (dwarf_getlocation_attr): When no
+	location found, return empty location expression.
+	* dwarf_getlocation_implicit_pointer.c
+	(dwarf_getlocation_implicit_pointer): Likewise.
+	(__libdw_empty_loc_attr): New internal function.
+	* libdwP.h (__libdw_empty_loc_attr): Define.
+
+2013-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.158): Add dwfl_module_addrsym_elf and
+	dwfl_module_getsym_elf.
+
+2013-11-26  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.map (ELFUTILS_0.156): Move dwfl_attach_state, dwfl_pid,
+	dwfl_thread_dwfl, dwfl_thread_tid, dwfl_frame_thread,
+	dwfl_thread_state_registers, dwfl_thread_state_register_pc,
+	dwfl_getthreads, dwfl_thread_getframes and dwfl_frame_pc to ...
+	(ELFUTILS_0.158): ... here.
+
+2013-11-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getaranges.c (dwarf_getaranges): Read segment_size and
+	check that it is zero.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* cfi.h (struct Dwarf_Frame_s): Make the comment more specific.
+	* libdw.map (ELFUTILS_0.156): Add dwfl_attach_state, dwfl_pid,
+	dwfl_thread_dwfl, dwfl_thread_tid, dwfl_frame_thread,
+	dwfl_thread_state_registers, dwfl_thread_state_register_pc,
+	dwfl_getthreads, dwfl_thread_getframes and dwfl_frame_pc.
+
+2013-11-01  Michael Forney  <mforney@mforney.org>
+
+	* Makefile.am (libdwfl_objects): New definition.
+	(libdw_a_LIBADD): Use libdwfl_objects.
+
+2013-11-01  Michael Forney  <mforney@mforney.org>
+
+	* Makefile.am: Use READELF.
+
+2013-10-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* libdw.map (ELFUTILS_0.158): New.
+
+2013-10-10  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getfuncs.c (struct visitor_info): Rename start_offset to
+	start_addr and rename last_offset to last_addr. Now both void *.
+	(tree_visitor): Use start_add and die_addr instead of start_offset
+	and die_offset.
+	(dwarf_getfuncs): Use last_addr instead of last_offset.
+
+2013-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.c (execute_cfi): Make sure DW_CFA_expression and
+	DW_CFA_val_expression are not used with abi_cfi.
+
+2013-10-03  Josh Stone  <jistone@redhat.com>
+
+	* dwarf_formref_die.c (dwarf_formref_die): Don't hash the sig8 here.
+	* libdw_findcu.c (__libdw_intern_next_unit): Since this never revisits
+	a unit, make sure to always hash the sig8 here, so none are missed.
+
+2013-09-29  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (store_implicit_value): Cast op->number2 to
+	uintptr_t before casting to char *.
+	(__libdw_intern_expression): Cast data to uintptr_t before casting
+	to Dwarf_Word.
+	* dwarf_getlocation_attr.c (dwarf_getlocation_attr): Cast
+	op->number2 to uintptr_t before casting to char *.
+
+2013-09-24  Josh Stone  <jistone@redhat.com>
+
+	* libdw_visit_scopes.c (classify_die): Removed.
+	(may_have_scopes): New function to replace classify_die.  There's no
+	need for full classification; just find tags that may contain scopes.
+	(__libdw_visit_scopes): Use a direct tag comparison for imported
+	units, and use may_have_scopes to test if recursion is needed.
+
+2013-09-20  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getfuncs.c (visitor_info): New struct.
+	(tree_visitor): New function.
+	(dwarf_getfuncs): Use __libdw_visit_scopes with tree_visitor.
+	* libdw.h (dwarf_getfuncs): Expand function documentation.
+
+2013-09-12  Mark Wielaard  <mjw@redhat.com>
+
+	* fde.c (intern_fde): Free fde and set libdw errno when start
+	or end could not be read.
+
+2013-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (store_implicit_value): Don't take data
+	as argument, get block data from op number2. Return false when
+	block data length and op number don't match up.
+	(__libdw_intern_expression): Store start of block for
+	DW_OP_implicit_value and DW_OP_GNU_entry_value instead of
+	relative data offset. Also store block start (including length)
+	for DW_OP_GNU_const_type. Don't pass data to store_implicit_value.
+	* dwarf_getlocation_attr.c: New file.
+	* dwarf_getlocation_die.c: Likewise.
+	* libdw.h (dwarf_getlocation_die): New function definition.
+	(dwarf_getlocation_attr): Likewise.
+	* libdwP.h: Declare internal dwarf_getlocation_die.
+	* libdw.map (ELFUTILS_0.157): Add dwarf_getlocation_die and
+	dwarf_getlocation_attr.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getlocation_die.c and
+	dwarf_getlocation_attr.c.
+
+2013-08-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getlocation.c (attr_ok): Also accept DW_AT_segment.
+	(attr_base_address): New function.
+	(initial_offset_base): New function.
+	(getlocations_addr): New function. Taken from...
+	(dwarf_getlocation_addr): here. Use new initial_offset_base and
+	getlocations_addr.
+	(dwarf_getlocations): New function.
+	* libdw.h (dwarf_getlocations): New function definition.
+	* libdw.map (ELFUTILS_0.157): New.
+
+2013-07-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Add new stack allocation
+	limit MAX_STACK_ALLOC.  After MAX_STACK_ALLOC lines use malloc in
+	NEW_LINE macro.  Free malloced line records if any at the end.
+
+2013-07-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getcfi_elf.c (getcfi_shdr): Check sh_type == SHT_PROGBITS.
+
+2013-06-26  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw_visit_scopes.c (__libdw_visit_scopes): Don't reject root
+	DIEs without children. Return an error whenever dwarf_child or
+	dwarf_siblingof return an error. Don't call recurse and increase
+	the depth for an imported unit. Walk the children of an imported
+	unit as if they are logical children of the parent root DIE.
+
+2013-05-03  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Only set end_sequence
+	when nlinelist > 0.
+
+2013-04-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* libdw.map (ELFUTILS_0.156): New.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2013-04-10  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_formref_die.c (dwarf_formref_die): Reference size is only
+	equal to address size when we have a DW_FORM_ref_addr for DWARF
+	version 2.
+
+2013-03-25  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Mark highest address as
+	end_sequence.
+
+2013-03-12  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getsrcfiles.c (dwarf_getsrcfiles): Allow DW_TAG_partial_unit.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+
+2013-02-15  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_formstring.c (dwarf_formstring): Check dbg_ret->sectiondata,
+	not dbg->sectiondata.
+
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* memory-access.h
+	[ALLOW_UNALIGNED] (read_8ubyte_unaligned_noncvt): New macro.
+	[!ALLOW_UNALIGNED] (read_8ubyte_unaligned_noncvt): New inline function.
+
+2012-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_begin_elf.c (valid_p): Call Dwarf_Sig8_Hash_free if invalid.
+	(check_section): Likewise on error.
+	(scngrp_read): Likewise.
+	(dwarf_begin_elf): Likewise.
+
+2012-10-09  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle
+	DW_OP_GNU_parameter_ref, DW_OP_GNU_convert, DW_OP_GNU_reinterpret,
+	DW_OP_GNU_regval_type, DW_OP_GNU_entry_value,
+	DW_OP_GNU_deref_type, DW_OP_GNU_const_type.
+
+2012-10-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* cfi.c: New include system.h.
+	(execute_cfi) (enough_registers): Clear new memory after realloc.
+
+2012-10-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* fde.c (__libdw_find_fde): Change <fde != NULL> to likely.  Return
+	DWARF_E_NO_MATCH if .eh_frame_hdr points to FDE which is too short for
+	searched PC.
+
+2012-10-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression) <cfap>: Make new
+	loclist element DW_OP_call_frame_cfa before decoding the opcodes.
+	Remove the later DW_OP_call_frame_cfa push to RESULT.
+
+2012-10-08  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Code cleanup.
+	* fde.c (binary_search_fde): Remove always true <address >= start>
+	conditional.  Move L initialization upwards.
+
+2012-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_begin_elf.c (check_section): Only probe for dwz multi files
+	when ENABLE_DWZ is defined.
+	* libdwP.h (__check_build_id): Only declare when ENABLE_DWZ is
+	defined.
+
+2012-08-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add known-dwarf.h.
+	* dwarf.h (DW_LANG_Go): Update comment.
+	(DW_LANG_Mips_Assembler): Likewise.
+
+2012-06-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_FORM_GNU_ref_alt and DW_FORM_GNU_strp_alt.
+	* dwarf_begin.c (dwarf_begin): Add INTDEF.
+	* dwarf_begin_elf.c (__check_build_id): New internal_function.
+	(try_debugaltlink): New function.
+	(open_debugaltlink): Likewise.
+	(check_section): Try open_debugaltlink for .gnu_debugaltlink.
+	* dwarf_end.c (dwarf_end): Free the alternative Dwarf descriptor if
+	necessary.
+	* dwarf_error.c (errmsgs): Add DWARF_E_NO_ALT_DEBUGLINK.
+	* dwarf_formref.c (__libdw_formref): Using DW_FORM_GNU_ref_alt
+	is an error here.
+	* dwarf_formref_die.c (dwarf_formref_die): Handle DW_FORM_GNU_ref_alt.
+	* dwarf_formstring.c (dwarf_formstring): Handle DW_FORM_GNU_strp_alt.
+	* dwarf_formudata.c (__libdw_formptr): Adjust __libdw_read_offset
+	calls.
+	* dwarf_getpubnames.c (get_offsets): Adjust __libdw_read_offset call.
+	* libdwP.h: Add DWARF_E_NO_ALT_DEBUGLINK.
+	(struct Dwarf): Add alt_dwarf and free_alt fields.
+	(__libdw_read_offset): Add dbg_ret argument, use to check with
+	__libdw_offset_in_section.
+	(__check_build_id): New function declaration.
+	(dwarf_begin): Define as INTDECL.
+	* libdw_form.c (__libdw_form_val_len): Handle DW_FORM_GNU_ref_alt
+	and DW_FORM_GNU_strp_alt.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_OP_GNU_parameter_ref.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Correct spelling of DW_LANG_ObjC.
+	* dwarf_aggregate_size.c (array_size): Use correct spelling of
+	DW_LANG_ObjC.
+
+2012-07-24  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_ATE_UTF.
+
+2012-06-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_MACRO_GNU .debug_macro type encodings.
+
+2012-06-26  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwP.h: Add IDX_debug_macro.
+	* dwarf.h: Add DW_AT_GNU_macros.
+	* dwarf_begin_elf.c (dwarf_scnnames): Add .debug_macro.
+	* dwarf_formudata.c (dwarf_formudata): Recognize DW_AT_GNU_macros.
+
+2012-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw/dwarf_highpc.c (dwarf_highpc): Handle DW_AT_high_pc being
+	a constant offset from DW_AT_low_pc.
+
+2012-03-19  Tom Tromey  <tromey@redhat.com>
+
+	* libdw_findcu.c (findcu_cb): Move earlier.
+	(__libdw_intern_next_unit): Add new CU to search tree here...
+	(__libdw_findcu): ... not here.
+
+2012-01-31  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_formudata.c (dwarf_formudata): Handle DW_FORM_sec_offset.
+
+2011-11-31  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (known-dwarf.h): Run gawk on config/known-dwarf.awk.
+
+2011-07-14  Mark Wielaard  <mjw@redhat.com>
+
+	* libdw.h (dwarf_offdie): Fix documentation to mention .debug_info.
+
+2011-05-16  Jakub Jelinek  <jakub@redhat.com>
+
+	* dwarf.h (DW_OP_GNU_const_type, DW_OP_GNU_regval_type,
+	DW_OP_GNU_deref_type, DW_OP_GNU_convert, DW_OP_GNU_reinterpret):
+	New.
+
+2011-04-26  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_child (dwarf_child): Sanity check end of section against
+	cu_data () of die->cu.
+
+2011-03-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Add DW_TAG_GNU_call_site,
+	DW_TAG_GNU_call_site_parameter,
+	DW_AT_GNU_call_site_value,
+	DW_AT_GNU_call_site_data_value,
+	DW_AT_GNU_call_site_target,
+	DW_AT_GNU_call_site_target_clobbered,
+	DW_AT_GNU_tail_call,
+	DW_AT_GNU_all_tail_call_sites,
+	DW_AT_GNU_all_call_sites,
+	DW_AT_GNU_all_source_call_sites,
+	and DW_OP_GNU_entry_value.
+
+2011-03-10  Petr Machata  <pmachata@redhat.com>
+
+	* libdw/dwarf_tag.c (__libdw_findabbrev): Reject requests for
+	abbreviation with code 0.
+
+2011-03-09  Petr Machata  <pmachata@redhat.com>
+
+	* libdw/dwarf_child.c (dwarf_child): Check for section overrun.
+
+2011-02-23  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (struct Dwarf) [USE_ZLIB]: New member sectiondata_gzip_mask.
+	Declare __libdw_free_zdata.
+	* dwarf_end.c [USE_ZLIB] (__libdw_free_zdata): New function.
+	(dwarf_end): Call it.
+
+	* dwarf_begin_elf.c (valid_p): Likewise.
+	(check_section, scngrp_read): Likewise.
+	(check_section) [USE_ZLIB]: Grok .z* flavors of sections.
+
+2010-10-13  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Add DW_LANG_Go.
+
+2010-10-05  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getaranges.c: Use malloc rather than alloca,
+	since the total number of elements can be quite huge.
+
+2010-07-26  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation_implicit_pointer.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.map (ELFUTILS_0.149): New set.
+	Add dwarf_getlocation_implicit_pointer.
+	* libdw.h: Declare it.
+
+	* dwarf_offdie.c (do_offdie): Renamed to __libdw_offdie, made global.
+	(dwarf_offdie, dwarf_offdie_types): Update callers.
+	* libdwP.h: Declare it.
+
+	* dwarf.h: Add DW_OP_GNU_implicit_pointer.
+	* dwarf_getlocation.c (__libdw_intern_expression): Handle it.
+
+2010-08-24  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.149): New set.  Add dwfl_dwarf_line.
+
+2010-07-27  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_formref_die.c: Fix sig8 hash insertion.
+
+2010-06-23  Roland McGrath  <roland@redhat.com>
+
+	* cfi.c (dwarf_cfi_validate_fde): Function removed.
+	* libdw.h: Remove it.
+	* libdw.map: Likewise.
+
+2010-06-22  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (check_constant_offset): data[48] are constant.
+
+	* dwarf_getsrclines.c: Fix signed comparison warning in extended
+	opcode parsing.
+
+2010-06-21  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Add DW_TAG_GNU_* constants.
+
+	* memory-access.h (get_sleb128_rest_return): Fix sign extension for
+	10-byte case.
+
+2010-06-20  Roland McGrath  <roland@redhat.com>
+
+	* libdw_findcu.c (__libdw_findcu): Take new flag argument,
+	to search TUs instead of CUs.
+	* libdwP.h: Update decl.
+	(struct Dwarf): New member tu_tree.
+	* dwarf_end.c (dwarf_end): Clean up tu_tree.
+	* dwarf_offdie.c (do_offdie): New function, broken out of ...
+	(dwarf_offdie): ... here.
+	(dwarf_offdie_types): New function.
+	* libdw.h: Declare it.
+	* libdw.map (ELFUTILS_0.148): Add it.
+
+	* libdwP.h (CUDIE): Use cu_data.
+	* dwarf_formblock.c: Likewise.
+	* dwarf_formref_die.c: Likewise.
+	* dwarf_diecu.c: Use CUDIE macro.
+	* dwarf_formaddr.c: Use cu_sec_idx.
+
+2010-06-16  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_formref_die.c: Use dwarf_offdie only for DW_FORM_ref_addr, so
+	we don't repeat a CU lookup we've already done.  Handle
+	DW_FORM_ref_sig8 using sig8_hash table and __libdw_intern_next_unit.
+
+	* libdw_findcu.c (__libdw_intern_next_unit): New function,
+	broken out of ...
+	(__libdw_findcu): ... here.  Call it.
+	* libdwP.h: Declare it.
+	(struct Dwarf): New member next_tu_offset.
+
+	* dwarf_sig8_hash.c: New file.
+	* dwarf_sig8_hash.h: New file.
+	* Makefile.am (libdw_a_SOURCES, noinst_HEADERS): Add them.
+	* dwarf_abbrev_hash.c: Include dwarf_sig8_hash.h before
+	defining NO_UNDEF.
+	* libdwP.h (struct Dwarf): New member sig8_hash.
+	* dwarf_begin_elf.c: Call Dwarf_Sig8_Hash_init on it.
+	* dwarf_end.c: Call Dwarf_Sig8_Hash_free on it.
+
+	* dwarf_nextcu.c (dwarf_next_unit): New function, broken out of ...
+	(dwarf_nextcu): ... here.  Call it.
+	* libdw.h: Declare it.
+	* libdwP.h: Add INTDECL.
+	* libdw_findcu.c (__libdw_findcu): Use it instead of dwarf_nextcu.
+	* libdw.map (ELFUTILS_0.148): New set, add dwarf_next_unit.
+
+	* libdwP.h (cu_sec_idx, cu_data): New functions.
+	Use .debug_types when CU is a TU.
+	* dwarf_cuoffset.c: Use that instead of assuming IDX_debug_info.
+	* dwarf_siblingof.c: Likewise.
+	* dwarf_formstring.c: Likewise.
+	* dwarf_formudata.c (__libdw_formptr, dwarf_formudata): Likewise.
+	* dwarf_getlocation.c (dwarf_getlocation): Likewise.
+	(dwarf_getlocation_addr): Likewise.
+
+	* libdwP.h (struct Dwarf_CU): Add new members type_offset, type_sig8.
+	(DIE_OFFSET_FROM_CU_OFFSET): Take flag argument; if true, compute
+	.debug_types header size instead of .debug_info header size.
+	(CUDIE): Use it.
+	* dwarf_diecu.c: Update caller.
+	* dwarf_getaranges.c: Likewise.
+	* dwarf_nextcu.c: Likewise.
+	* libdw_findcu.c (__libdw_findcu): Initialize new members.
+
+	* fde.c (fde_by_offset): Renamed to ...
+	(__libdw_fde_by_offset): ... this, made global and internal_function.
+	Don't take ADDRESS argument.
+	(__libdw_find_fde): Update caller.  Do address sanity check here.
+	* cfi.h: Declare __libdw_fde_by_offset.
+	* cfi.c (dwarf_cfi_validate_fde): New function.
+	* libdw.h: Declare it.
+	* libdw.map (ELFUTILS_0.148): Add it.
+
+	* cie.c (intern_new_cie): Canonicalize DW_EH_PE_absptr FDE encoding to
+	either DW_EH_PE_udata8 or DW_EH_PE_udata4.
+
+	* encoded-value.h (read_encoded_value): Handle DW_EH_PE_indirect.
+	Don't assume DW_EH_PE_aligned refers to native address size.
+
+	* cfi.c (execute_cfi): Barf on CIE initial instructions changing the
+	address.
+
+2010-06-17  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (struct Dwarf_Line_s): Add members isa, discriminator, and
+	op_index.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Move NEW_FILE macro guts
+	into an inner inline function.  Set new fields.  Check all fields for
+	overflow when setting.
+	* dwarf_lineisa.c: New file.
+	* dwarf_linediscriminator.c: New file.
+	* dwarf_lineop_index.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add them.
+	* libdw.map (ELFUTILS_0.148): Add them.
+	* libdw.h: Declare them.
+
+2010-06-16  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_next_cfi.c: Fix version 4 return_address_register decoding.
+
+	* fde.c (fde_by_offset): Renamed to ...
+	(__libdw_fde_by_offset): ... this, made global and internal_function.
+	Don't take ADDRESS argument.
+	(__libdw_find_fde): Update caller.  Do address sanity check here.
+	* cfi.h: Declare __libdw_fde_by_offset.
+	* cfi.c (dwarf_cfi_validate_fde): New function.
+	* libdw.h: Declare it.
+	* libdw.map (ELFUTILS_0.148): Add it.
+
+	* cie.c (intern_new_cie): Canonicalize DW_EH_PE_absptr FDE encoding to
+	either DW_EH_PE_udata8 or DW_EH_PE_udata4.
+
+	* encoded-value.h (read_encoded_value): Handle DW_EH_PE_indirect.
+	Don't assume DW_EH_PE_aligned refers to native address size.
+
+	* cfi.c (execute_cfi): Barf on CIE initial instructions changing the
+	address.
+
+2010-06-15  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_formref.c (__libdw_formref): Diagnose DW_FORM_ref_sig8 like
+	DW_FORM_ref_addr.
+	* dwarf_formref_die.c (dwarf_formref_die): Diagnose it the same way
+	here, since we don't support it yet.
+
+	* dwarf_next_cfi.c: Handle version 4 format.
+
+	* dwarf_getsrclines.c: Handle version 4 format.
+
+2010-06-01  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h: Remove unused IDX_debug_*names, add IDX_debug_types.
+	* dwarf_begin_elf.c (dwarf_scnnames): Likewise.
+
+	* libdwP.h (CIE_VERSION): Remove unused macro.
+
+	* dwarf_getsrclines.c: Fix version field test.
+	* libdwP.h (DWARF_VERSION): Remove useless macro.
+
+	* dwarf_formudata.c (__libdw_formptr): Fix DW_FORM_sec_offset handling.
+
+	* dwarf_formblock.c (dwarf_formblock): Handle DW_FORM_exprloc.
+
+	* libdw_findcu.c (__libdw_findcu): Accept version 4.
+
+2010-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* cfi.h (dwarf_cfi_cie_p): Move definition from here, to ..
+	* libdw.h (dwarf_cfi_cie_p): ... here.
+
+2010-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf.h: Fix DW_LANG_Python constant.
+
+2010-05-28  Eduardo Santiago  <santiago@redhat.com>
+
+	* dwarf_getlocation.c (dwarf_getlocation): Do attr_ok check first
+	thing.
+
+2010-05-27  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Add DW_AT_enum_class, DW_AT_linkage_name,
+	DW_TAG_template_alias, DW_LANG_Python, DW_LNE_set_discriminator.
+
+2010-05-08  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Take new argument
+	REF_SIZE.  Use that to handle DW_OP_call_ref correctly.
+	(getlocation): Update caller.
+	* dwarf_frame_cfa.c (dwarf_frame_cfa): Likewise.
+	* dwarf_frame_register.c (dwarf_frame_register): Likewise.
+	* libdwP.h: Update decl.
+
+2010-04-26  Roland McGrath  <roland@redhat.com>
+
+	* cfi.h (struct Dwarf_Frame_s): Add cfa_invalid alternative in cfa_rule.
+	* cfi.c (execute_cfi): Set that instead of doing cfi_assert for
+	DW_CFA_def_cfa_{offset*,register} when a non-offset rule is in force.
+	* dwarf_frame_cfa.c (dwarf_frame_cfa): Handle cfa_invalid.
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Take new arg CFAP.
+	Prepend DW_OP_call_frame_cfa if true.
+	(getlocation): Update caller.
+	* dwarf_frame_cfa.c (dwarf_frame_cfa): Likewise.
+	* dwarf_frame_register.c (dwarf_frame_register): Likewise.
+	* libdwP.h: Update decl.
+
+2010-04-22  Roland McGrath  <roland@redhat.com>
+
+	* cfi.c (execute_cfi): Never return without cleanup.
+	Free FS on failure.
+	(cie_cache_initial_state): Adjust caller to expect that free.
+	(__libdw_frame_at_address): Likewise.
+
+2010-03-10  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.146): New set.  Add dwfl_core_file_report.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2010-02-02  Mark Wielaard  <mjw@redhat.com>
+
+	* fde.c (intern_fde): Fix length check for sized_augmentation_data.
+
+2010-01-07  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getcfi_elf.c (getcfi_phdr): Use elf_getphdrnum.
+
+2010-01-05  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_aggregate_size.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare it.
+	* libdwP.h: Add INTDECL.
+	* libdw.map (ELFUTILS_0.144): New set.  Add dwarf_aggregate_size.
+
+	* dwarf_srclang.c: Add INTDEF.
+	* libdwP.h: Add INTDECL.
+
+	* dwarf.h: Add some more DW_AT_GNU_* types from gcc.
+
+	* dwarf.h: Add DW_AT_GNU_vector, DW_AT_GNU_template_name.
+
+2009-11-21  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (check_constant_offset): Return 1 for all
+	non-constant forms.
+
+2009-10-15  Roland McGrath  <roland@redhat.com>
+
+	* libdw_form.c (__libdw_form_val_len): Grok DW_FORM_sec_offset,
+	DW_FORM_exprloc, DW_FORM_flag_present, and DW_FORM_ref_sig8.
+
+2009-09-17  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (dwarf_getlocation_implicit_value): Make OP
+	argument a pointer to const.
+	* libdw.h: Update decl.
+
+2009-09-10  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (store_implicit_value): New function.
+	(__libdw_intern_expression): Use it, handle DW_OP_implicit_value.
+	(dwarf_getlocation_implicit_value): New function.
+	* libdw.h: Declare it.
+	* libdw.map (ELFUTILS_0.143): Add it.
+
+2009-09-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_getcfi.c (dwarf_getcfi): Clear cfi->ebl.
+
+2009-08-21  Josh Stone  <jistone@redhat.com>
+
+	* dwarf_hasattr_integrate.c: Integrate DW_AT_specification too.
+
+2009-08-10  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getscopevar.c: Use dwarf_diename.
+
+2009-08-09  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.143): New version set,
+	inherits from ELFUTILS_0.142.
+	* dwarf_arrayorder.c: Use OLD_VERSION and NEW_VERSION to define an
+	alias in the ELFUTILS_0.122 version set and the default in the new set.
+	* dwarf_srclang.c: Likewise.
+	* dwarf_decl_file.c: Likewise.
+	* dwarf_decl_line.c: Likewise.
+	* dwarf_decl_column.c: Likewise.
+	* dwarf_bytesize.c: Likewise.
+	* dwarf_bitsize.c: Likewise.
+	* dwarf_bitoffset.c: Likewise.
+
+2009-08-07  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_arrayorder.c: Use dwarf_attr_integrate.
+	* dwarf_srclang.c: Likewise.
+	* dwarf_decl_file.c: Likewise.
+	* dwarf_decl_line.c (__libdw_attr_intval): Likewise.
+	* dwarf_bytesize.c: Likewise.
+	* dwarf_bitsize.c: Likewise.
+	* dwarf_bitoffset.c: Likewise.
+
+2009-07-22  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_frame_cfa.c: Change calling convention.
+	* libdw.h: Update decl.
+
+	* dwarf_frame_register.c: Change calling/return-value convention for
+	value-only results and undefined/same_value.
+	* libdw.h: Update decl.
+
+	* dwarf_getlocation.c (__libdw_intern_expression): Take new bool
+	argument, append DW_OP_stack_value if set.  Don't take NOPS argument,
+	return that value instead.
+	(getlocation): Update caller.
+	* dwarf_frame_cfa.c: Likewise.
+	* libdwP.h: Update decl.
+
+2009-07-21  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getsrc_file.c: Ignore a CU that just has no DW_AT_stmt_list.
+	Fix loop iteration after skipping a bogus or useless CU.
+
+	* dwarf_entry_breakpoints.c: Handle 0 dwarf_errno () as harmless
+	absence, not DWARF_E_NO_DEBUG_LINE.
+
+2009-07-20  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (__libdw_intern_expression):
+	Handle DW_OP_stack_value.
+
+2009-07-16  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_formudata.c (__libdw_formptr): Handle DW_FORM_sec_offset,
+	reject others when CU's version > 3.
+
+	* dwarf_formflag.c: Handle DW_FORM_flag_present.
+
+	* dwarf.h: Add DW_OP_{implicit,stack}_value from DWARF 4 draft.
+	Also DW_TAG_type_unit and DW_TAG_rvalue_reference_type.
+	Also DW_AT_signature, DW_AT_main_subprogram, DW_AT_data_bit_offset,
+	and DW_AT_const_expr.
+	Also DW_FORM_sec_offset, DW_FORM_exprloc, DW_FORM_flag_present,
+	and DW_FORM_ref_sig8.
+
+2009-07-15  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c: Grok DW_OP_form_tls_address,
+	DW_OP_GNU_push_tls_address, and DW_OP_bit_piece.
+
+2009-07-13  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c: Grok DW_OP_call_frame_cfa.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.142): Add dwfl_module_dwarf_cfi,
+	dwfl_module_eh_cfi.
+
+	* libdwP.h (struct Dwarf): Add member `cfi'.
+	* dwarf_end.c (dwarf_end): Call __libdw_destroy_frame_cache on it.
+	* dwarf_getcfi.c: New file.
+	* dwarf_getcfi_elf.c: New file.
+	* dwarf_cfi_end.c: New file.
+	* dwarf_cfi_addrframe.c: New file.
+	* dwarf_frame_cfa.c: New file.
+	* dwarf_frame_register.c: New file.
+	* dwarf_frame_return_address_register.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add them.
+	* unwind.h: Declare those functions.
+	* libdw.map (ELFUTILS_0.142): Export them.
+
+	* dwarf_getlocation.c (__libdw_intern_expression): New function,
+	broken out of ...
+	(getlocation): ... here, call it.
+	* libdwP.h: Declare it.
+
+	* cie.c: New file.
+	* fde.c: New file.
+	* frame-cache.c: New file.
+	* cfi.c: New file.
+	* cfi.h: New file.
+	* encoded-value.h: New file.
+	* Makefile.am (libdw_a_SOURCES, noinst_HEADERS): Add them.
+	* libdwP.h: Add DWARF_E_INVALID_CFI to errors enum.
+	* dwarf_error.c (errmsgs): Add element for it.
+
+	* dwarf_next_cfi.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h (Dwarf_CIE, Dwarf_FDE, Dwarf_CIE_Entry): New types.
+	Declare dwarf_next_cfi.
+	* libdw.map (ELFUTILS_0.142): New set, inherits from ELFUTILS_0.136.
+	Add dwarf_next_cfi.
+
+	* memory-access.h [! ALLOW_UNALIGNED]
+	(read_2ubyte_unaligned): Renamed to ...
+	(read_2ubyte_unaligned_1): ... this.  Take bool rather than Dwarf *.
+	(read_2ubyte_unaligned): Define as macro passing dbg->other_byte_order.
+	(read_2sbyte_unaligned): Likewise.
+	(read_4ubyte_unaligned): Likewise.
+	(read_4sbyte_unaligned): Likewise.
+	(read_8ubyte_unaligned): Likewise.
+	(read_8sbyte_unaligned): Likewise.
+
+	* libdwP.h (IDX_eh_frame): Remove it.
+	* dwarf_begin_elf.c (dwarf_scnnames): Remove its element.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (struct Dwarf_Line_s): Reorder members to pack better.
+
+	* dwarf_getlocation.c (check_constant_offset): New function.
+	(dwarf_getlocation, dwarf_getlocation_addr): Call it to
+	handle DW_AT_data_member_location of data[48] as constant offset.
+
+2009-06-18  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (__libdw_read_address_inc): Constify.
+	(__libdw_read_offset_inc): Likewise.
+	* dwarf_getaranges.c: Likewise.
+	* dwarf_getlocation.c: Likewise.
+	* dwarf_getsrclines.c: Likewise.
+	* dwarf_nextcu.c: Likewise.
+
+2009-05-05  Petr Machata  <pmachata@redhat.com>
+
+	* libdwP.h (__libdw_formptr): Declare new function.
+	* dwarf_formudata.c: Implement it here.
+	* dwarf_getlocation.c (dwarf_getlocation_addr):
+	Call it instead of hand-rolled offset handling code.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+	* dwarf_ranges.c (dwarf_ranges): Likewise.
+
+2009-05-04  Petr Machata  <pmachata@redhat.com>
+
+	* libdwP.h (__libdw_read_begin_end_pair_inc): Declare new function.
+	* dwarf_ranges.c: Implement it here.
+	(dwarf_ranges): Call it.
+	* dwarf_getlocation.c (dwarf_getlocation_addr): Call it also here.
+
+2009-04-23  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_formaddr.c (dwarf_formaddr): Call __libdw_read_* instead
+	of read_*ubyte_unaligned.
+	* dwarf_formref_die.c (dwarf_formref_die): Likewise.
+	* dwarf_formstring.c (dwarf_formstring): Likewise.
+	* dwarf_formudate.c (dwarf_formudata): Likewise.
+	* dwarf_getaranges.c (dwarf_getaranges): Likewise.
+	* dwarf_getlocation.c (dwarf_getlocation_addr): Likewise.
+	* dwarf_getpubnames.c (get_offsets): Likewise.
+	* dwarf_nextcu.c (dwarf_nextcu): Likewise.
+
+2009-04-23  Petr Machata  <pmachata@redhat.com>
+
+	* libdwP.h (__libdw_read_addr_inc, __libdw_read_off_inc,
+	__libdw_read_addr, __libdw_read_off): Add four new internal
+	functions.
+
+2009-05-07  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getmacros.c (dwarf_getmacros): Use absolute section offset in
+	return value and OFFSET argument, not CU-relative.  Only fetch the
+	attribute data when called with OFFSET of 0.
+
+2009-05-07  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf_getmacros.c (dwarf_getmacros): Take into account offset in
+	DW_AT_macro_info attribute of CU DIE.
+
+2009-04-15  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h (DW_CIE_ID): Removed.
+	(DW_CIE_ID_32, DW_CIE_ID_64): New constants replace it.
+
+2009-04-01  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Add DW_CFA_GNU_negative_offset_extended.
+
+2009-01-28  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (struct Dwarf_Line_s): Move out of struct Dwarf_Lines_s
+	defn so C++ doesn't scope the name to not match the Dwarf_Line typedef.
+
+	* libdwP.h (struct Dwarf_Files_s): Replace dbg field with cu field.
+
+2009-01-26  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_ranges.c: Return 0 when no ranges or *_pc attrs at all.
+
+2009-01-25  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getattrs.c: Correctly skip attribute values when restarting.
+
+2009-01-23  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am ($(srcdir)/known-dwarf.h): Target renamed back.
+	Put these rules under if MAINTAINER_MODE.
+
+2009-01-22  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Add DW_OP_GNU_encoded_addr.
+
+2009-01-21  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (CLEANFILES): Renamed to ...
+	(MOSTLYCLEANFILES): ... here.
+	(CLEANFILES): New variable, add known-dwarf.h.
+
+2009-01-17  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (known-dwarf.h): Target renamed, not in $(srcdir).
+	Make it unconditional.
+	(BUILT_SOURCES): Updated.
+
+	* dwarf.h: Add description comments for DW_LANG_* values.
+
+	* Makefile.am [MAINTAINER_MODE]
+	($(srcdir)/known-dwarf.h): New target.
+	(BUILT_SOURCES): Add it.
+
+	* dwarf.h: Add DW_OP_GNU_push_tls_address, DW_OP_GNU_uninit.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_error.c: Always use __thread.  Remove all !USE_TLS code.
+
+2009-01-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libdw.so): Don't depend on $(zip_LIBS), just link it in.
+
+2008-01-06  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (struct Dwarf_Abbrev): Change type of 'has_children' to bool.
+	Reorder members.
+	* dwarf_haschildren.c: Return -1 for error case, not 0.
+
+	* Makefile.am (libdw.so): Link in $(zip_LIBS).
+
+2009-01-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf.h: Add definition for unwind and call frame information.
+
+	* memory-access.h: Define read_ubyte_unaligned, read_sbyte_unaligned,
+	read_ubyte_unaligned_inc, and read_sbyte_unaligned_inc.
+
+2008-08-15  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.136): New version set, inherits from
+	ELFUTILS_0.130.  Add dwfl_addrsegment, dwfl_report_segment.
+
+2008-01-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_child.c: Minor optimizations.
+	* dwarf_getattrs.c: Likewise.
+	* dwarf_getpubnames.c: Likewise.
+	* dwarf_siblingof.c: Likewise.
+	* dwarf_tag.c: Likewise.
+
+2008-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Don't require exact match
+	of DWARF_VERSION comparison, just fail if the file's version is newer.
+
+2008-01-17  Nick Clifton  <nickc@redhat.com>
+
+	* dwarf.h (DWARF3_LENGTH_MIN_ESCAPE_CODE): New define.
+	(DWARF3_LENGTH_MAX_ESCAPE_CODE): New define.
+	(DWARF3_LENGTH_64_BIT): New define.
+	* dwarf_getaranges (dwarf_getaranges): Use the new definitions.
+	* dwarf_getpubnames: Include dwarf.h.
+	(get_offsets): Use the new definitions.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Use the new defintions.
+	* dwarf_nextcu.c: Include dwarf.h.  Correct comment.
+	(dwarf_nextcu): Use the new definitions.
+
+	* libdwP.h (DIE_OFFSET_FROM_CU_OFFSET): New macro.
+	* dwarf_diecu.c (dwarf_diecu): Use the new macro.
+	* dwarf_getaranges (dwarf_getaranges): Use the new macro.
+	* dwarf_nextcu.c (dwarf_nextcu): Use the new macro.
+
+	* dwarf_getpubnames (get_offsets): Replace assertion with test and
+	error return.
+
+	* dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Use CUDIE.
+
+	* dwarf_siblingof (dwarf_siblingof): Detect a NULL return pointer.
+	Set the address in the return structure to the address of the next
+	non-sibling die, if there is no sibling and the return pointer is
+	not the same as the die pointer.
+	* libdw.h: Expand the description of the dwarf_siblingof prototype.
+
+	* dwarf_child.c: Fix typo in comment.
+
+	* libdwP.h (DWARF_VERSION): Change to 3.
+
+	* dwarf_formref.c (__libdw_formref.c): Handle attributes which do
+	not have a initialised valp pointer.
+
+	* dwarf_getattrs.c (dwarf_getattrs): Return 1 rather than 0 when
+	the end of the attributes is reached.  When the callback fails,
+	return the address of the failing attribute, not the address of
+	its successor.
+	* libdw.h: Expand the description of the dwarf_getattrs prototype.
+
+	* dwarf_child.c (__libdw_find_attr): Use the new definition.
+	(dwarf_child): Likewise.
+	* dwarf_tag.c (__libdw_findabbrev): Likewise.
+	(dwarf_tag): Likewise.
+
+2008-01-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (euinclude): Variable removed.
+	(pkginclude_HEADERS): Set this instead of euinclude_HEADERS.
+	(libdw.so): Pass -Wl,--enable-new-dtags,-rpath,$(pkglibdir).
+
+2007-10-17  Roland McGrath  <roland@redhat.com>
+
+	* libdw.h (__deprecated_attribute__): New macro.
+	(dwarf_formref): Mark it deprecated.
+	* dwarf_formref.c (__libdw_formref): New function, broken out of ...
+	(dwarf_formref): ... here.  Call it.  Remove INTDEF.
+	* libdwP.h: Remove INTDECL.
+	Declare __libdw_formref.
+	* dwarf_siblingof.c (dwarf_siblingof): Call __libdw_formref instead.
+	* dwarf_formref_die.c: Likewise.  Handle DW_FORM_ref_addr here.
+
+	* libdw_form.c (__libdw_form_val_len): Fix DW_FORM_ref_addr result,
+	needs to check CU->version.
+
+	* libdwP.h (struct Dwarf_CU): New member `version'.
+	* libdw_findcu.c (__libdw_findcu): Initialize it.
+
+	* dwarf_child.c: Return 1 for null entry as first child.
+
+2007-10-05  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_begin_elf.c (check_section): Punt on SHT_NOBITS sections.
+
+	* libdw.h (__extern_inline): Rename to __libdw_extern_inline.
+	[__OPTIMIZE__] (dwarf_whatattr, dwarf_whatform): Update uses.
+
+2007-10-03  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.130: Add dwfl_build_id_find_elf
+	and dwfl_build_id_find_debuginfo.
+
+	* libdw.map (ELFUTILS_0.130): New version set, inherits from
+	ELFUTILS_0.127.  Add dwfl_module_build_id, dwfl_module_report_build_id.
+
+2007-10-02  Roland McGrath  <roland@redhat.com>
+
+	* libdw_visit_scopes.c (classify_die): Return walk for class_type and
+	structure_type.
+
+2007-08-07  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getscopes.c (pc_match): Swallow dwarf_haspc error return when
+	error code is DWARF_E_NOERROR (0).
+
+	* dwarf_getscopes.c (pc_record): Always bail early if DIE->prune.
+	Fix typo in __libdw_visit_scopes argument.
+
+	* dwarf_getscopes.c (pc_match): Check dwarf_haspc error return,
+	swallow DWARF_E_NO_DEBUG_RANGES but not other errors.
+
+2007-07-03  Roland McGrath  <roland@redhat.com>
+
+	* libdw.h (__extern_inline): New macro.
+	[__OPTIMIZE__] (dwarf_whatattr, dwarf_whatform): Use it.
+
+2007-04-16  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.127): Add dwfl_module_address_section.
+
+2007-04-05  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getsrcdirs.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_getsrcdirs.
+	* libdw.map (ELFUTILS_0.127): Add it.
+
+	* libdwP.h (struct Dwarf_Files_s): New member ndirs.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Don't clobber NDIRLIST to
+	zero before we use it to check for DWARF_E_INVALID_DIR_IDX.
+	Save DIRARRAY in the Dwarf_Files.
+
+	* dwarf_ranges.c (dwarf_ranges): Don't sign-extend 32-bit BEGIN
+	address to check for all-ones base address entry.  Check directly.
+	Reported by Sébastien Dugué <sebastien.dugue@bull.net>.
+
+2007-03-25  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_begin_elf.c (check_section): Return Dwarf * instead of void.
+	Return NULL when freeing RESULT on error.
+	(global_read, scngrp_read): Check return value from check_section,
+	break out of loop after it has freed RESULT.
+	(valid_p): Handle null argument.
+
+2007-03-12  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.127): Add dwfl_report_begin_add.
+
+2007-03-04  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map (ELFUTILS_0.127): New version set, inherits from
+	ELFUTILS_0.126.  Add dwfl_module_addrsym.
+
+2007-02-10  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h (DW_OP_fbreg): Comment fix.
+
+2007-02-03  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getelf.c (dwarf_getelf): Renamed from dwarf_get_elf.
+	* libdw.map (ELFUTILS_0.126): New version set, inherits from
+	ELFUTILS_0.122.  Move dwarf_getelf there; it was never truly
+	exported in the past.
+
+2006-12-17  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (dwarf_getlocation_addr): Use zero as base
+	address when the CU is missing attributes due to buggy GCC.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (CLEANFILES): Add libdw.so.$(VERSION).
+
+	* libdw.h (dwarf_diecu): Add __nonnull_attribute__.
+	(dwarf_child): Don't list arg 1 in __nonnull_attribute__.
+
+	* libdw_alloc.c (__libdw_allocate): Take new ALIGN argument, make sure
+	result is aligned.  Adjust NEWP->remaining here for this allocation.
+	* libdwP.h: Update decl.
+	(libdw_alloc): Update caller.
+
+2006-07-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_child.c: Adjust for internal_function_def removal.
+	* dwarf_getabbrev.c: Likewise.
+	* dwarf_tag.c: Likewise.
+	* libdw_form.c: Likewise.
+	* memory-access.c: Likewise.
+
+2006-06-28  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Export dwfl_linecu, dwfl_line_comp_dir.
+
+	* libdw.map: Bump to 0.122; export dwfl_module_getsymtab and
+	dwfl_module_getsym.
+
+2006-05-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Add extern "C".
+
+2006-05-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getaranges.c (dwarf_getaranges): Handle files without
+	aranges information.
+
+2006-05-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Add nonnull attributes to dwarf_tag, dwarf_getattrs,
+	dwarf_haschildren.
+
+2006-02-28  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Add missing DW_ATE_*, DW_TAG_*, DW_LANG_*, DW_CFA_*,
+	DW_OP_* values, to match DWARF 3.0.  Add new DW_DS_*, DW_END_*
+	values from DWARF 3.0.
+
+2006-02-22  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Bump to 0.120; export dwfl_version.
+
+2005-12-22  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Bump to 0.119; export dwfl_linux_proc_maps_report.
+
+2005-12-12  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_ranges.c: Copy CU base address-finding code from
+	dwarf_getlocation.
+
+2005-12-09  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getlocation.c (dwarf_getlocation_addr): Add some unlikelys.
+	Delay CU base lookup until it's needed.
+	If CU base lookup fails with no error, flag invalid DWARF.
+
+2005-11-25  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Bump to 0.118; export dwfl_module_register_names.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am [BUILD_STATIC] (AM_CFLAGS): Add -fpic.
+
+2005-11-13  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Bump to 0.117; export dwfl_module_return_value_location.
+
+2005-10-27  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_entry_breakpoints.c (search_range): Fix binary search code;
+	don't match end_sequence markers.
+
+	* dwarf_getsrclines.c (compare_lines): Sort end_sequence markers
+	before normal records at the same address.
+	* dwarf_getsrc_die.c (dwarf_getsrc_die): Don't match an end_sequence
+	marker.
+
+2005-10-26  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getfuncs.c (dwarf_getfuncs): Use Dwarf_Die, not Dwarf_Func.
+	* dwarf_func_file.c: Renamed to ...
+	* dwarf_decl_file.c: ... here.
+	* dwarf_func_col.c: Renamed to ...
+	* dwarf_decl_column.c: ... here.
+	* dwarf_func_line.c: Renamed to ...
+	* dwarf_decl_line.c: ... here.
+	(dwarf_func_line): Renamed to ...
+	(dwarf_decl_line): ... this.  Take a Dwarf_Die * argument.
+	(__libdw_func_intval): Renamed __libdw_attr_intval.
+	* dwarf_func_name.c: File removed.
+	* dwarf_func_lowpc.c: File removed.
+	* dwarf_func_highpc.c: File removed.
+	* dwarf_func_entrypc.c: File removed.
+	* dwarf_func_die.c: File removed.
+	* Makefile.am (libdw_a_SOURCES): Updated.
+	* libdw.h: Update decls.
+	(Dwarf_Func): Type removed.
+	* libdwP.h: Update decls.
+	(struct Dwarf_Func_s): Type removed.
+	* libdw.map: Updated.
+
+	* libdwP.h (CUDIE): New macro.
+	* dwarf_getlocation.c (dwarf_getlocation_addr): Use it.
+	* dwarf_getscopes_die.c (dwarf_getscopes_die): Likewise.
+	* dwarf_ranges.c (dwarf_ranges): Likewise.
+
+	* dwarf_getloclist.c: Renamed to ...
+	* dwarf_getlocation.c: ... here.
+	(getloclist): Renamed to getlocation.
+	(dwarf_getloclist): Renamed to dwarf_getlocation.
+	(dwarf_addrloclists): Renamed to dwarf_getlocation_addr.
+	* Makefile.am (libdw_a_SOURCES): Updated.
+	* libdw.h (dwarf_getloclist): Renamed to dwarf_getlocation.
+	(dwarf_addrloclists): Renamed dwarf_getlocation_addr.
+	(Dwarf_Loc): Renamed Dwarf_Op.
+	* libdwP.h (struct loc_s): Update use.
+	* libdw.map: Update map.
+
+	* dwarf_entry_breakpoints.c: Use the second line record within the
+	function, regardless of its source location data.
+
+2005-10-25  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_entry_breakpoints.c: Fall back to entrypc for contiguous too.
+
+	* libdw.map: Add dwarf_entrypc, dwarf_entry_breakpoints.
+
+2005-10-14  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_diecu.c (dwarf_diecu): New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_diecu.
+	* libdw.map: Export it.
+
+	* libdw.map: Bump to 0.116; export dwarf_ranges.
+
+2005-09-20  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_haspc.c: Use dwarf_ranges.
+	* dwarf_entry_breakpoints.c: Likewise.
+
+	* dwarf_ranges.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_ranges.
+	* libdwP.h: Add INTDECL.
+
+2005-09-14  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_entry_breakpoints.c (dwarf_entry_breakpoints): Fix braino in
+	prologue_end marker scanning loop.
+
+2005-09-11  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h: Comment typo fix.
+
+2005-09-07  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_entry_breakpoints.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_entry_breakpoints.
+
+	* dwarf_entrypc.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_entrypc.
+	* libdwP.h: Add INTDECL.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Use $(LINK) not $(CC) when creating DSO.
+	(%.os): Use COMPILE.os.
+	(COMPILE.os): Filter out gconv options.
+
+2005-08-27  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getscopes.c (dwarf_getscopes): Rewritten using
+	__libdw_visit_scopes.
+
+	* dwarf_getscopes_die.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_getscopes_die.
+	* libdw.map: Bump to 0.115 and add it.
+
+	* libdw_visit_scopes.c (__libdw_visit_scopes): Pass a struct
+	containing a DIE and its parent pointer, instead of just Dwarf_Die.
+	Take two functions for both preorder and postorder visitors.
+	* libdwP.h: Update decl.
+	(struct Dwarf_Die_Chain): New type.
+	* dwarf_func_inline.c: Update uses.
+
+	* dwarf_diename.c (dwarf_diename): Use dwarf_attr_integrate.
+	Add INTDEF.
+	* libdwP.h: Add INTDECL.
+	* dwarf_func_name.c (dwarf_func_name): Use dwarf_diename.
+
+2005-08-23  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_attr_integrate.c (dwarf_attr_integrate): Treat
+	DW_AT_specification the same as DW_AT_abstract_origin.
+
+2005-08-20  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Add dwfl_cumodule, remove dwfl_linecu.
+	Add dwfl_linux_kernel_report_offline, dwfl_offline_section_address,
+	and dwfl_report_offline.
+
+2005-08-19  Roland McGrath  <roland@redhat.com>
+
+	* libdw.map: Bump version to ELFUTILS_0.114 for libdwfl changes.
+	Add dwfl_module_relocate_address, dwfl_module_relocations,
+	dwfl_module_relocation_info.
+
+2005-08-18  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getscopes.c (dwarf_getscopes): Include the CU itself as
+	outermost scope in the results.
+
+2005-08-15  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_func_inline.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_func_inline, dwarf_func_inline_instances.
+	* libdw.map: Add them.
+
+	* dwarf_func_die.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_func_die.
+	* libdw.map: Add it.  Bump version to ELFUTILS_0.114.
+
+2005-08-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Correct fallout of renaming
+	of DW_LNS_set_epilog_begin.
+
+2005-08-09  Roland McGrath  <roland@redhat.com>
+
+	* dwarf.h (DW_LNS_set_epilog_begin): Renamed DW_LNS_set_epilogue_begin.
+
+	* dwarf_end.c: Add INTDEF.
+	* dwarf_error.c (dwarf_errmsg): Likewise.
+	* libdwP.h (dwarf_end, dwarf_errmsg): Add INTDECLs.
+
+2005-08-01  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getaranges.c (dwarf_getaranges): Check for bogus offset.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Likewise.
+
+2005-07-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libdw.so): No need to link with libeu.a anymore.
+	(libdw_a_LIBADD): Add all files from libdwfl.a.
+
+2005-07-27  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libdw.so): Link ../libdwfl/libdwfl_pic.a in,
+	along with ../libebl/libebl.a and ../lib/libeu.a;
+	depend on ../libelf/libelf.so.
+	(libdw_so_LDADD): New variable.
+	* libdw.map: Add dwfl_* symbols formerly in ../libdwfl/libdwfl.map.
+
+	* libdw.map: Define an empty base version and move all symbols to
+	version ELFUTILS_0.111; don't define ELFUTILS_1.0 at all yet.
+
+2005-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_error.c: Add internal alias for dwarf_errno.
+	* libdwP.h: Declare __dwarf_errno_internal.
+	* dwarf_getloclist.c: Use INTDEF for dwarf_errno.
+
+	* dwarf_error.c [USE_TLS]: Actually use __thread in definition of
+	global_error.
+
+2005-06-01  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getaranges.c (dwarf_getaranges): Sort result array.
+	* dwarf_getarange_addr.c (dwarf_getarange_addr): Use binary search.
+
+2005-06-08  Roland McGrath  <roland@redhat.com>
+
+	* memory-access.h (get_uleb128_step, get_uleb128): Remove casts.
+	(get_sleb128_step, get_sleb128): Likewise.
+	* dwarf_getattrs.c (dwarf_getattrs): Add consts.
+	* dwarf_getloclist.c (getloclist): Likewise.
+	* dwarf_formblock.c (dwarf_formblock): Likewise.
+	* dwarf_getsrclines.c (dwarf_getsrclines): Likewise.
+	* dwarf_getabbrevattr.c (dwarf_getabbrevattr): Likewise.
+	* dwarf_formref.c (dwarf_formref): Likewise.
+	* dwarf_formsdata.c (dwarf_formsdata): Likewise.
+	* dwarf_formudata.c (dwarf_formudata): Likewise.
+	* dwarf_haschildren.c (dwarf_haschildren): Likewise.
+	* dwarf_child.c (__libdw_find_attr, __libdw_find_attr): Likewise.
+	* dwarf_tag.c (dwarf_tag): Likewise.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Likewise.
+	* memory-access.c (__libdw_get_uleb128, __libdw_get_sleb128): Likewise.
+	* libdw_form.c (__libdw_form_val_len): Likewise.
+	* libdwP.h: Update decl.
+
+2005-06-04  Roland McGrath  <roland@redhat.com>
+
+	* memory-access.h (get_uleb128_rest_return): New macro.
+	[! IS_LIBDW] (__libdw_get_uleb128): New static, defined using it.
+	(get_sleb128_rest_return): New macro.
+	[! IS_LIBDW] (__libdw_get_sleb128): New static, defined using it.
+	* memory-access.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	(DEFS): Add -DIS_LIBDW.
+
+2005-05-31  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_formref_die.c (dwarf_formref_die): Add CU header offset to
+	formref offset.
+
+2005-05-30  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getloclist.c (dwarf_addrloclists): Use DW_AT_entry_pc for base
+	address if DW_AT_low_pc is missing.  Not to spec, but GCC generates it.
+
+	* dwarf_getloclist.c (dwarf_addrloclists): Don't sign-extend 4-byte
+	BEGIN value.  Instead, match base address entries separately for
+	32/64 size cases.
+
+2005-05-28  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getloclist.c (dwarf_addrloclists): Fix decoding to advance
+	past location expression contents.
+
+2005-05-23  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getsrclines.c: Comment typo fix.
+
+	* dwarf_haspc.c (dwarf_haspc): Fix CU DIE address calculation.
+	* dwarf_getloclist.c (dwarf_addrloclists): Likewise.
+
+2005-05-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdwP.h: Only use INTDECL for alias prototypes.
+
+2005-05-19  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getloclist.c (attr_ok): Permit DW_AT_static_link too.
+
+	* dwarf_getscopevar.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_getscopevar.
+
+	* dwarf_getsrcfiles.c: Add INTDEF.
+	* dwarf_haschildren.c: Likewise.
+	* libdwP.h (dwarf_getsrcfiles, dwarf_haschildren): Add INTDECL.
+
+	* dwarf_getscopes.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h: Declare dwarf_getscopes.
+	* libdw.map: Add it.
+
+2005-05-18  Roland McGrath  <roland@redhat.com>
+
+	* libdwP.h (IDX_debug_ranges): New enum constant.
+	* dwarf_begin_elf.c (dwarf_scnnames): Add it for ".debug_ranges".
+	* libdwP.h (DWARF_E_NO_DEBUG_RANGES): New enum constant.
+	* dwarf_error.c (errmsgs): Add it.
+	* dwarf_haspc.c: New file.
+	* libdw.h: Declare dwarf_haspc.
+	* libdw.map: Add it.
+	* libdwP.h: Add INTDECL.
+
+	* dwarf_attr_integrate.c: New file.
+	* dwarf_hasattr_integrate.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add them.
+	* libdw.h: Declare dwarf_attr_integrate, dwarf_hasattr_integrate.
+	* libdw.map: Add them.
+
+	* dwarf_hasattr.c: Add INTDEF.
+	* libdwP.h: Add INTDECL for it.
+
+	* dwarf_formref_die.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add it.
+	* libdw.h (dwarf_formref_die): Declare it.
+	* libdwP.h (dwarf_formref_die): Add INTDECL.
+	* libdw.map: Add it.
+
+	* dwarf_getloclist.c (attr_ok, getloclist): New functions, broken out
+	of ...
+	(dwarf_getloclist): ... here.  Call them.
+	(dwarf_addrloclists): New function.
+	* libdw.h: Declare it.
+	* libdw.map: Add it.
+
+	* dwarf_getmacros.c (dwarf_getmacros): Don't bail at
+	DW_MACINFO_end_file.  Recognize type 0 as terminator.
+
+2005-05-05  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getsrc_die.c (dwarf_getsrc_die): Use binary search.
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Sort result array, since
+	the line program does not produce all entries in ascending order.
+
+2005-04-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrc_file.c (dwarf_getsrc_file): Handle multiple
+	occurences (e.g., inlines) better.
+
+2005-04-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h (DWARF_END_ABBREV): Define.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Return DWARF_END_ABBREV if
+	end is reached.
+	* dwarf_offabbrev.c (dwarf_offabbrev): Return -1 on error, 1 if end
+	of records reached.
+	* dwarf_tag.c (__libdw_findabbrev): Also recognize DWARF_END_ABBREV
+	as error of __libdw_getabbrev.
+
+2005-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrc_file.c (dwarf_getsrc_file): Minor optimization.
+
+	* dwarf_getsrc_file.c (dwarf_getsrc_file): Always pass number of
+	results back to caller.
+
+2005-04-04  Roland McGrath  <roland@redhat.com>
+
+	* dwarf_getsrc_file.c (dwarf_getsrc_file): Use size_t for CUHL.
+
+	* dwarf_func_line.c (__libdw_func_intval): Use internal_function in
+	defn.
+
+2005-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrc_file.c (dwarf_getsrc_file): Use INTUSE.
+
+	* dwarf_getsrc_file.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getsrc_file.c.
+	* libdw.h: Declare dwarf_getsrc_file.
+	* libdw.map: Add dwarf_getsrc_file.
+
+2005-04-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_func_entrypc.c: New file.
+	* dwarf_func_col.c: New file.
+	* dwarf_func_line.c: New file.
+	* dwarf_func_file.c: New file.
+	* libdw.h: Add prototypes for new functions.
+	* libdw.map: Add dwarf_func_entrypc, dwarf_func_col, dwarf_func_line,
+	dwarf_func_file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_func_entrypc.c,
+	dwarf_func_col.c, dwarf_func_line.c, dwarf_func_file.c.
+	* libdwP.h (struct Dwarf_Func_s): Add cudie element.
+	Declare __libdw_func_intval and __dwarf_formsdata_internal.
+	* dwarf_getfuncs.c: Also fill in cudie in Dwarf_Func object.
+	* dwarf_formsdata.c: Use INTUSE and INTDEF to avoid PLTs.
+
+	* dwarf.h: Add some DWARF3 definitions.
+
+2005-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getfuncs.c: New file.
+	* dwarf_func_highpc.c: New file.
+	* dwarf_func_lowpc.c: New file.
+	* dwarf_func_name.c: New file.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getfuncs.c,
+	dwarf_func_highpc.c, dwarf_func_lowpc.c, and dwarf_func_name.c.
+	* libdw.map: Add dwarf_getfuncs, dwarf_func_highpc, dwarf_func_lowpc,
+	and dwarf_func_name.
+	* libdw.h: Add prototypes for new functions.
+	* dwarf_child.c: Use INTUSE and INTDEF to avoid PLTs.
+	* dwarf_siblingof.c: Likewise.
+	* dwarf_dieoffset.c: Likewise.
+	* dwarf_highpc.c: Likewise.
+	* dwarf_lowpc.c: Likewise.
+	* libdwP.h: Add prototypes for internal functions.
+	Define Dwarf_Func_s structure.
+
+2005-03-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Add padding in Dwarf_die.
+
+	* dwarf_arrayorder.c: Use INTUSE and INTDEF to avoid PLTs.
+	* dwarf_attr.c: Likewise.
+	* dwarf_begin.c: Likewise.
+	* dwarf_begin_elf.c: Likewise.
+	* dwarf_bitoffset.c: Likewise.
+	* dwarf_bitsize.c: Likewise.
+	* dwarf_bytesize.c: Likewise.
+	* dwarf_diename.c: Likewise.
+	* dwarf_formaddr.c: Likewise.
+	* dwarf_formblock.c: Likewise.
+	* dwarf_formref.c: Likewise.
+	* dwarf_formstring.c: Likewise.
+	* dwarf_formudata.c: Likewise.
+	* dwarf_getarange_addr.c: Likewise.
+	* dwarf_getarangeinfo.c: Likewise.
+	* dwarf_getaranges.c: Likewise.
+	* dwarf_getloclist.c: Likewise.
+	* dwarf_getmacros.c: Likewise.
+	* dwarf_getsrc_die.c: Likewise.
+	* dwarf_getsrcfiles.c: Likewise.
+	* dwarf_getsrclines.c: Likewise.
+	* dwarf_highpc.c: Likewise.
+	* dwarf_lowpc.c: Likewise.
+	* dwarf_nextcu.c: Likewise.
+	* dwarf_offdie.c: Likewise.
+	* dwarf_siblingof.c: Likewise.
+	* dwarf_srclang.c: Likewise.
+	* dwarf_tag.c: Likewise.
+	* libdw_findcu.c: Likewise.
+	* libdwP.h: Add prototypes for internal functions.
+
+	* dwarf_addrdie.c: New file.
+	* dwarf_macro_opcode.c: New file.
+	* dwarf_macro_param1.c: New file.
+	* dwarf_macro_param2.c: New file.
+	* libdw.h: Add declarations.  Move Dwarf_Macro definition to libdwP.h.
+	* libdwP.h: Remove Dwarf_Macro definition.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_addrdie.c,
+	dwarf_macro_opcode.c, dwarf_macro_param1.c, and dwarf_macro_param2.c.
+	* libdw.map: Add entries for new functions.
+
+2005-03-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Handle broken gcc < 4.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (AM_CFLAGS): Add -Wunused -Wextra -Wformat=2.
+
+	* dwarf_begin_elf.c: Fix warnings.
+	* dwarf_dieoffset.c: Likewise.
+	* dwarf_end.c: Likewise.
+	* dwarf_error.c: Likewise.
+	* dwarf_getpubnames.c: Likewise.
+
+	* libdwP.h: Add new error values.
+	* dwarf_error.c: Support new error values.
+	* dwarf_getpubnames.c: Check parameter value.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Check for text relocations in constructed DSO.
+
+	* Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fmudflap.
+
+2005-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_siblingof.c (dwarf_siblingof): Add some buffer boundary
+	checks to not read over buffer boundaries for ill-formed DWARF data.
+
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_child.c: Make compile with gcc 4.0.
+	* dwarf_error.c: Likewise.
+	* dwarf_formblock.c: Likewise.
+	* dwarf_getabbrev.c: Likewise.
+	* dwarf_getattrs.c: Likewise.
+	* dwarf_getsrclines.c: Likewise.
+	* dwarf_tag.c: Likewise.
+	* libdw_form.c: Likewise.
+
+2004-01-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+	* dwarf_getloclist.c: Fix warnings gcc 3.4 spits out.
+	* dwarf_getsrclines.c: Likewise.
+	* dwarf_memory-access.h: Likewise.
+
+2004-01-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrcfiles.c: Third parameter can be NULL.
+
+	* libdw.h: Define Dwarf_macro.  Declare dwarf_getmacros.
+	Third parameter of dwarf_getsrcfiles can be NULL.
+
+	* libdw.map: Add dwarf_getmacros.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getmacros.
+	* dwarf_getmacros.c: New file.
+
+2004-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Second parameter of dwarf_getaranges can be NULL.
+
+	* dwarf_nextcu.c: Return -1 if dwarf parameter is NULL.
+
+	* dwarf_getsrclines.c:
+	Use read_2ubyte_unaligned_inc instead of _inc-less variant.
+
+	* dwarf_getaranges.c: Allow naranges parameter to be NULL.
+
+	* libdwP.h (_): Use elfutils domain.
+
+	* dwarf_getsrclines.c (dwarf_getsrclines): Add more branch prediction.
+
+	* dwarf_getsrclines.c: Fix typo in comment.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+2004-01-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* memory-access.h: Add lots of const in case a pointer passed is const.
+
+	* dwarf_formflag.c: New file.
+	* dwarf_getattrs.c: New file.
+	* dwarf_error.c: Add new error value.
+	* libdw.h: Add prototypes for new functions.  Adjust prototype for
+	dwarf_getpubnames.
+	* libdw.map: Add new functions.
+	* dwarf_getpubnames.c: Change type of return value and fourth parameter
+	to ptrdiff_t.
+	* libdwP.h: Add new error value.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getattrs.c and
+	dwarf_formflag.c.
+
+	* dwarf_getpubnames.c (dwarf_getpubnames): Just fail if dbg is NULL.
+
+2004-01-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getarange_addr.c: New file
+	* dwarf_getarangeinfo.c: New file.
+	* dwarf_getaranges.c: New file.
+	* dwarf_onerange.c: New file.
+	* libdw.h: Declare new functions.  Define Dwarf_Arange and
+	Dwarf_Aranges.
+	* libdw.map: Add new functions.
+	* libdwP.h: Add new errors.  Add aranges member to struct Dwarf.
+	Define Dwarf_Aranges_s and Dwarf_Arange_s.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getaranges.c,
+	dwarf_onearange.c, dwarf_getarangeinfo.c, dwarf_getarange_addr.c.
+	* dwarf_error.c: Add new message.
+
+2004-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_lineaddr.c, dwarf_linecol.c,
+	dwarf_linebeginstatement.c, dwarf_lineendsequence.c, dwarf_lineblock.c,
+	dwarf_lineprologueend.c, dwarf_lineepiloguebegin.c, dwarf_onesrcline.c.
+	* dwarf_error.c: Add another message.
+	* dwarf_getsrc_die.c: Adjust for Dwarf_Files and Dwarf_Lines
+	introduction.
+	* dwarf_filesrc.c: Likewise.
+	* dwarf_getsrcfiles.c: Likewise.
+	* dwarf_getsrclines.c: Likewise.
+	* dwarf_lineaddr.c: New file.
+	* dwarf_linebeginstatement.c: New file.
+	* dwarf_lineblock.c: New file.
+	* dwarf_linecol.c: New file.
+	* dwarf_lineendsequence.c: New file.
+	* dwarf_lineepiloguebegin.c: New file.
+	* dwarf_lineno.c: New file.
+	* dwarf_lineprologueend.c: New file.
+	* dwarf_onesrcline.c: New file.
+	* dwarf_lineno.c: Change interface to store result in object pointed
+	to by second parameter.
+	* libdw.h: Add prototypes for new functions.  Change dwarf_lineno
+	prototype.  Define Dwarf_Files and Dwarf_Lines.
+	* libdw.map: Add new functions.
+	* libdwP.h: Define Dwarf_Files_s and Dwarf_Lines_s.
+	* libdw_findcu.c: Don't initialize nlines field.
+
+	* dwarf_siblingof: Little optimization.
+
+	* dwarf_begin.c: Remember that the ELF descriptor must be closed.
+	* dwarf_end.c: Close ELF descriptor if free_elf is set.
+	* libdwP.h (struct Dwarf): Add free_elf field.
+
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getstring.c and
+	dwarf_offabbrev.c.
+	* dwarf_getstring.c: New file.
+	* dwarf_offabbrev.c: New file.
+	* libdw.map: Add dwarf_getstring and dwarf_offabbrev.
+	* dwarf_getabbrev.c (__libdw_getabbrev): Add new dbg and result
+	parameters.  Don't allocate memory if not necessary and don't lookup
+	previous results if no CU given.
+	(dwarf_getabbrev): Adjust call to __libdw_getabbrev.
+	* dwarf_tag.c: Adjust call to __libdw_getabbrev.
+	* libdw.h: Declare dwarf_offabbrev and dwarf_getstring.
+	* libdwP.h: Change prototype for __libdw_getabbrev.
+
+	* dwarf_getabbrevattr.c: Add offsetp parameter.  Fill in before
+	returning if this is wanted.
+
+2004-01-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_nextcu.c: Add new parameter offset_sizep.  Initialize it
+	with offset_size value.
+	* libdw.h: Adjust dwarf_nextcu prototype.
+	* libdwP.h (struct Dwarf_CU): Add offset_size member.
+	* libdw_findcu.c: Adjust dwarf_nextcu call.  Initialize offset_size
+	member of new CU struct.
+	* dwarf_formstring.c: Depend on offset_size not address_size for
+	DW_FORM_strp handling.
+	* dwarf_form.c: Likewise for DW_FORM_strp and DW_FORM_ref_addr.
+
+	* dwarf_tag.c (__libdw_findabbrev): Return correct value for
+	failing lookup.
+	(dwarf_tag): Correctly recognize failed lookup.
+
+	* dwarf_end.c (cu_free):  Call tdestroy for locs member.  Use new
+	function noop_free.
+	* dwarf_error.c: Add message for DWARF_E_NO_BLOCK.
+	* dwarf_formblock.c: New file.
+	* dwarf_getloclist.c: Rewrite to handle a single block.
+	* libdw.h: Define Dwarf_Block.  Rename Dwarf_Loc members.  Remove
+	Dwarf_Locdesc definition.  Declare dwarf_formblock.  Remove
+	dwarf_getloclistent declaration.
+	* libdw.map: Add dwarf_formblock, remove dwarf_getloclistent.
+	* libdwP.h: Define struct loc_s and DWARF_E_NO_BLOCK.
+	Add locs member to struct Dwarf_CU.
+	* libdw_fundcu.c: Initialize locs member of new CU.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_formblock.c.
+	Remove dwarf_getloclistent.c.
+
+2004-01-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Use __nonnull__ attribute only for gcc >= 3.3.
+	* libdwP.h: Likewise.
+
+	* dwarf_getloclist.c: New file.
+	* dwarf_getloclistent.c: New file.
+	* libdw.h: Define Dwarf_Loc and Dwarf_Locdesc.
+	Declare dwarf_getloclistent and dwarf_getloclist.
+	* libdw.map: Add dwarf_getloclistent and dwarf_getloclist.
+	* libdwP.h: Define DWARF_E_NO_LOCLIST.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getloclistent.c and
+	dwarf_getloclist.c.
+
+	* dwarf_error.c: More error messages.
+
+2004-01-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwarf_getsrclines.c: Remove debugging support.
+
+	* dwarf_getsrcfiles.c: New file.
+	* dwarf_filesrc.c: New file.
+	* libdw.h: Declare these functions.  Define Dwarf_File.
+	* libdwP.c: Adjust Dwarf_File_s definition.
+	* libdw.map: Add these functions.
+	* Makefile.am (libdw_a_SOURCES): Add dwarf_getsrcfiles.c and
+	dwarf_filesrc.c.
+	* dwarf_getsrclines.c: Initialize cu->files.
+
+2004-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdw.h: Add more nonnull function attributes.
+
+	* dwarf_begin_elf.c (dwarf_begin_elf): Don't initialize mem_tail->next.
+	* dwarf_end.c (cu_free): New function.
+	(dwarf_end): Also free CU tree.  Correct freeing of memory blocks.
+	* dwarf_error.c (errmsgs): Add new messages.
+	* dwarf_getsrc_die.c: New file.
+	* dwarf_getsrclines.c: New file.
+	* dwarf_lineno.c: New file.
+	* dwarf_linesrc.c: New file.
+	* dwarf_nextcu.c (dwarf_nextcu): Use read_*byte_unaligned_inc
+	instead of the *_inc-less variants.
+	* libdw.h: Define Dwarf_Line.  Add some function attributes.  Declare
+	dwarf_getsrclines, dwarf_getsrc_die, dwarf_lineno, and dwarf_linesrc.
+	* libdw.map: Add dwarf_getsrclines, dwarf_getsrc_die, dwarf_lineno,
+	and dwarf_linesrc.
+	* libdwP.h: Add more error codes.
+	(struct Dwarf): Remove mem_tail.next member.
+	(Dwarf_File): Define type.
+	(struct Dwarf_Line_s): Define type.
+	(struct Dwarf_CU): Add lines and nlines members.
+	(libdw_alloc): Define local variable _tail and use it.
+	Add some function attributes.
+	* libdw_alloc.c (__libdw_allocate): Don't initialize next member.
+	* libdw_findcu.c (__libdw_findcu): Initialize lines and nlines members.
+	* memory-access.h: Add unlikely for the endian conversion paths.
+	* Makefile.am (AM_CFLAGS): Add -std parameter.
+	(libdw_a_SOURCES): Add dwarf_getsrclines, dwarf_getsrc_die,
+	dwarf_lineno, and dwarf_linesrc.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/libdw/Makefile.am b/libdw/Makefile.am
new file mode 100644
index 0000000..5363c02
--- /dev/null
+++ b/libdw/Makefile.am
@@ -0,0 +1,156 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2002-2010, 2012, 2014, 2016, 2018 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+if BUILD_STATIC
+AM_CFLAGS += $(fpic_CFLAGS)
+endif
+AM_CPPFLAGS += -I$(srcdir)/../libebl -I$(srcdir)/../libelf -I$(srcdir)/../libdwelf -pthread
+VERSION = 1
+
+lib_LIBRARIES = libdw.a
+noinst_LIBRARIES = libdw_pic.a
+noinst_DATA = $(noinst_LIBRARIES:_pic.a=.so)
+
+include_HEADERS = dwarf.h
+pkginclude_HEADERS = libdw.h known-dwarf.h
+
+libdw_a_SOURCES = dwarf_begin.c dwarf_begin_elf.c dwarf_end.c dwarf_getelf.c \
+		  dwarf_getpubnames.c dwarf_getabbrev.c dwarf_tag.c \
+		  dwarf_error.c dwarf_nextcu.c dwarf_diename.c dwarf_offdie.c \
+		  dwarf_attr.c dwarf_formstring.c \
+		  dwarf_abbrev_hash.c dwarf_sig8_hash.c \
+		  dwarf_attr_integrate.c dwarf_hasattr_integrate.c \
+		  dwarf_child.c dwarf_haschildren.c dwarf_formaddr.c \
+		  dwarf_formudata.c dwarf_formsdata.c dwarf_lowpc.c \
+		  dwarf_entrypc.c dwarf_haspc.c dwarf_highpc.c dwarf_ranges.c \
+		  dwarf_formref.c dwarf_formref_die.c dwarf_siblingof.c \
+		  dwarf_dieoffset.c dwarf_cuoffset.c dwarf_diecu.c \
+		  dwarf_hasattr.c dwarf_hasform.c \
+		  dwarf_whatform.c dwarf_whatattr.c \
+		  dwarf_bytesize.c dwarf_arrayorder.c dwarf_bitsize.c \
+		  dwarf_bitoffset.c dwarf_srclang.c dwarf_getabbrevtag.c \
+		  dwarf_getabbrevcode.c dwarf_abbrevhaschildren.c \
+		  dwarf_getattrcnt.c dwarf_getabbrevattr.c \
+		  dwarf_getsrclines.c dwarf_getsrc_die.c \
+		  dwarf_getscopes.c dwarf_getscopes_die.c dwarf_getscopevar.c \
+		  dwarf_linesrc.c dwarf_lineno.c dwarf_lineaddr.c \
+		  dwarf_linecol.c dwarf_linebeginstatement.c \
+		  dwarf_lineendsequence.c dwarf_lineblock.c \
+		  dwarf_linecontext.c dwarf_linefunctionname.c \
+		  dwarf_lineprologueend.c dwarf_lineepiloguebegin.c \
+		  dwarf_lineisa.c dwarf_linediscriminator.c \
+		  dwarf_lineop_index.c dwarf_line_file.c \
+		  dwarf_onesrcline.c dwarf_formblock.c \
+		  dwarf_getsrcfiles.c dwarf_filesrc.c dwarf_getsrcdirs.c \
+		  dwarf_getlocation.c dwarf_getstring.c dwarf_offabbrev.c \
+		  dwarf_getaranges.c dwarf_onearange.c dwarf_getarangeinfo.c \
+		  dwarf_getarange_addr.c dwarf_getattrs.c dwarf_formflag.c \
+		  dwarf_getmacros.c dwarf_macro_getparamcnt.c	\
+		  dwarf_macro_opcode.c dwarf_macro_param.c	\
+		  dwarf_macro_param1.c dwarf_macro_param2.c	\
+		  dwarf_macro_getsrcfiles.c			\
+		  dwarf_addrdie.c dwarf_getfuncs.c \
+		  dwarf_decl_file.c dwarf_decl_line.c dwarf_decl_column.c \
+		  dwarf_func_inline.c dwarf_getsrc_file.c \
+		  libdw_findcu.c libdw_form.c libdw_alloc.c \
+		  libdw_visit_scopes.c \
+		  dwarf_entry_breakpoints.c \
+		  dwarf_next_cfi.c \
+		  cie.c fde.c cfi.c frame-cache.c \
+		  dwarf_frame_info.c dwarf_frame_cfa.c dwarf_frame_register.c \
+		  dwarf_cfi_addrframe.c \
+		  dwarf_getcfi.c dwarf_getcfi_elf.c dwarf_cfi_end.c \
+		  dwarf_aggregate_size.c dwarf_getlocation_implicit_pointer.c \
+		  dwarf_getlocation_die.c dwarf_getlocation_attr.c \
+		  dwarf_getalt.c dwarf_setalt.c dwarf_cu_getdwarf.c \
+		  dwarf_cu_die.c dwarf_peel_type.c dwarf_default_lower_bound.c \
+		  dwarf_die_addr_die.c dwarf_get_units.c \
+		  libdw_find_split_unit.c dwarf_cu_info.c \
+		  dwarf_next_lines.c dwarf_cu_dwp_section_info.c
+
+if MAINTAINER_MODE
+BUILT_SOURCES = $(srcdir)/known-dwarf.h
+MAINTAINERCLEANFILES = $(srcdir)/known-dwarf.h
+$(srcdir)/known-dwarf.h: $(top_srcdir)/config/known-dwarf.awk $(srcdir)/dwarf.h
+	gawk -f $^ > $@.new
+	mv -f $@.new $@
+endif
+
+libdw_pic_a_SOURCES =
+am_libdw_pic_a_OBJECTS = $(libdw_a_SOURCES:.c=.os)
+
+libdw_so_LIBS = ../libebl/libebl_pic.a ../backends/libebl_backends_pic.a \
+		../libcpu/libcpu_pic.a libdw_pic.a ../libdwelf/libdwelf_pic.a \
+		../libdwfl/libdwfl_pic.a
+libdw_so_DEPS = ../lib/libeu.a ../libelf/libelf.so
+libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(fts_LIBS) $(obstack_LIBS) $(zip_LIBS) -pthread
+libdw.so: $(srcdir)/libdw.map $(libdw_so_LIBS) $(libdw_so_DEPS)
+	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
+		-Wl,--soname,$@.$(VERSION),--enable-new-dtags \
+		-Wl,--version-script,$< \
+		$(NO_UNDEFINED) \
+		-Wl,--whole-archive $(libdw_so_LIBS) -Wl,--no-whole-archive \
+		$(libdw_so_LDLIBS)
+	@$(textrel_check)
+	$(AM_V_at)ln -fs $@ $@.$(VERSION)
+
+install: install-am libdw.so
+	$(mkinstalldirs) $(DESTDIR)$(libdir)
+	$(INSTALL_PROGRAM) libdw.so $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so
+	ln -fs libdw-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libdw.so.$(VERSION)
+	ln -fs libdw.so.$(VERSION) $(DESTDIR)$(libdir)/libdw.so
+
+uninstall: uninstall-am
+	rm -f $(DESTDIR)$(libdir)/libdw-$(PACKAGE_VERSION).so
+	rm -f $(DESTDIR)$(libdir)/libdw.so.$(VERSION)
+	rm -f $(DESTDIR)$(libdir)/libdw.so
+	rmdir --ignore-fail-on-non-empty $(DESTDIR)$(includedir)/elfutils
+
+libdwfl_objects = $(shell $(AR) t ../libdwfl/libdwfl.a)
+libdw_a_LIBADD = $(addprefix ../libdwfl/,$(libdwfl_objects))
+
+libdwelf_objects = $(shell $(AR) t ../libdwelf/libdwelf.a)
+libdw_a_LIBADD += $(addprefix ../libdwelf/,$(libdwelf_objects))
+
+libebl_objects = $(shell $(AR) t ../libebl/libebl.a)
+libdw_a_LIBADD += $(addprefix ../libebl/,$(libebl_objects))
+
+backends_objects = $(shell $(AR) t ../backends/libebl_backends.a)
+libdw_a_LIBADD += $(addprefix ../backends/,$(backends_objects))
+
+libcpu_objects = $(shell $(AR) t ../libcpu/libcpu.a)
+libdw_a_LIBADD += $(addprefix ../libcpu/,$(libcpu_objects))
+
+noinst_HEADERS = libdwP.h memory-access.h dwarf_abbrev_hash.h \
+		 dwarf_sig8_hash.h cfi.h encoded-value.h
+
+EXTRA_DIST = libdw.map
+
+MOSTLYCLEANFILES = $(am_libdw_pic_a_OBJECTS) libdw.so libdw.so.$(VERSION)
diff --git a/libdw/cfi.c b/libdw/cfi.c
new file mode 100644
index 0000000..a717440
--- /dev/null
+++ b/libdw/cfi.c
@@ -0,0 +1,532 @@
+/* CFI program execution.
+   Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libebl.h"
+#include "cfi.h"
+#include "memory-access.h"
+#include "encoded-value.h"
+#include "system.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CFI_PRIMARY_MAX	0x3f
+
+static Dwarf_Frame *
+duplicate_frame_state (const Dwarf_Frame *original,
+		       Dwarf_Frame *prev)
+{
+  size_t size = offsetof (Dwarf_Frame, regs[original->nregs]);
+  Dwarf_Frame *copy = malloc (size);
+  if (likely (copy != NULL))
+    {
+      memcpy (copy, original, size);
+      copy->prev = prev;
+    }
+  return copy;
+}
+
+static inline bool
+enough_registers (Dwarf_Word reg, Dwarf_Frame **pfs, int *result)
+{
+  /* Don't allow insanely large register numbers.  268435456 registers
+     should be enough for anybody.  And very large values might overflow
+     the array size and offsetof calculations below.  */
+  if (unlikely (reg >= INT32_MAX / sizeof ((*pfs)->regs[0])))
+    {
+      *result = DWARF_E_INVALID_CFI;
+      return false;
+    }
+
+  if ((*pfs)->nregs <= reg)
+    {
+       size_t size = offsetof (Dwarf_Frame, regs[reg + 1]);
+       Dwarf_Frame *bigger = realloc (*pfs, size);
+       if (unlikely (bigger == NULL))
+         {
+           *result = DWARF_E_NOMEM;
+           return false;
+         }
+       else
+         {
+           eu_static_assert (reg_unspecified == 0);
+           memset (bigger->regs + bigger->nregs, 0,
+                   (reg + 1 - bigger->nregs) * sizeof bigger->regs[0]);
+           bigger->nregs = reg + 1;
+           *pfs = bigger;
+         }
+     }
+  return true;
+}
+
+static inline void
+require_cfa_offset (Dwarf_Frame *fs)
+{
+  if (unlikely (fs->cfa_rule != cfa_offset))
+    fs->cfa_rule = cfa_invalid;
+}
+
+/* Returns a DWARF_E_* error code, usually NOERROR or INVALID_CFI.
+   Frees *STATE on failure.  */
+static int
+execute_cfi (Dwarf_CFI *cache,
+	     const struct dwarf_cie *cie,
+	     Dwarf_Frame **state,
+	     const uint8_t *program, const uint8_t *const end, bool abi_cfi,
+	     Dwarf_Addr loc, Dwarf_Addr find_pc)
+{
+  /* The caller should not give us anything out of range.  */
+  assert (loc <= find_pc);
+
+  int result = DWARF_E_NOERROR;
+
+#define cfi_assert(ok) do {						      \
+    if (likely (ok)) break;						      \
+    result = DWARF_E_INVALID_CFI;					      \
+    goto out;								      \
+  } while (0)
+
+  Dwarf_Frame *fs = *state;
+
+#define register_rule(regno, r_rule, r_value) do {	\
+    if (unlikely (! enough_registers (regno, &fs, &result)))	\
+      goto out;						\
+    fs->regs[regno].rule = reg_##r_rule;		\
+    fs->regs[regno].value = (r_value);			\
+  } while (0)
+
+  while (program < end)
+    {
+      uint8_t opcode = *program++;
+      Dwarf_Word regno;
+      Dwarf_Word offset;
+      Dwarf_Word sf_offset;
+      Dwarf_Word operand = opcode & CFI_PRIMARY_MAX;
+      switch (opcode)
+	{
+	  /* These cases move LOC, i.e. "create a new table row".  */
+
+	case DW_CFA_advance_loc1:
+	  operand = *program++;
+	  FALLTHROUGH;
+	case DW_CFA_advance_loc + 0 ... DW_CFA_advance_loc + CFI_PRIMARY_MAX:
+	advance_loc:
+	  loc += operand * cie->code_alignment_factor;
+	  break;
+
+	case DW_CFA_advance_loc2:
+	  cfi_assert (program + 2 <= end);
+	  operand = read_2ubyte_unaligned_inc (cache, program);
+	  goto advance_loc;
+	case DW_CFA_advance_loc4:
+	  cfi_assert (program + 4 <= end);
+	  operand = read_4ubyte_unaligned_inc (cache, program);
+	  goto advance_loc;
+	case DW_CFA_MIPS_advance_loc8:
+	  cfi_assert (program + 8 <= end);
+	  operand = read_8ubyte_unaligned_inc (cache, program);
+	  goto advance_loc;
+
+	case DW_CFA_set_loc:
+	  if (likely (!read_encoded_value (cache, cie->fde_encoding,
+					   &program, &loc)))
+	    break;
+	  result = INTUSE(dwarf_errno) ();
+	  goto out;
+
+	  /* Now all following cases affect this row, but do not touch LOC.
+	     These cases end with 'continue'.  We only get out of the
+	     switch block for the row-copying (LOC-moving) cases above.  */
+
+	case DW_CFA_def_cfa:
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (offset, program, end);
+	def_cfa:
+	  fs->cfa_rule = cfa_offset;
+	  fs->cfa_val_reg = operand;
+	  fs->cfa_val_offset = offset;
+	  /* Prime the rest of the Dwarf_Op so dwarf_frame_cfa can use it.  */
+	  fs->cfa_data.offset.atom = DW_OP_bregx;
+	  fs->cfa_data.offset.offset = 0;
+	  continue;
+
+	case DW_CFA_def_cfa_register:
+	  get_uleb128 (regno, program, end);
+	  require_cfa_offset (fs);
+	  fs->cfa_val_reg = regno;
+	  continue;
+
+	case DW_CFA_def_cfa_sf:
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_sleb128 (sf_offset, program, end);
+	  offset = sf_offset * cie->data_alignment_factor;
+	  goto def_cfa;
+
+	case DW_CFA_def_cfa_offset:
+	  get_uleb128 (offset, program, end);
+	def_cfa_offset:
+	  require_cfa_offset (fs);
+	  fs->cfa_val_offset = offset;
+	  continue;
+
+	case DW_CFA_def_cfa_offset_sf:
+	  get_sleb128 (sf_offset, program, end);
+	  offset = sf_offset * cie->data_alignment_factor;
+	  goto def_cfa_offset;
+
+	case DW_CFA_def_cfa_expression:
+	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (operand <= (Dwarf_Word) (end - program));
+	  fs->cfa_rule = cfa_expr;
+	  fs->cfa_data.expr.data = (unsigned char *) program;
+	  fs->cfa_data.expr.length = operand;
+	  program += operand;
+	  continue;
+
+	case DW_CFA_undefined:
+	  get_uleb128 (regno, program, end);
+	  register_rule (regno, undefined, 0);
+	  continue;
+
+	case DW_CFA_same_value:
+	  get_uleb128 (regno, program, end);
+	  register_rule (regno, same_value, 0);
+	  continue;
+
+	case DW_CFA_offset_extended:
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  FALLTHROUGH;
+	case DW_CFA_offset + 0 ... DW_CFA_offset + CFI_PRIMARY_MAX:
+	  get_uleb128 (offset, program, end);
+	  offset *= cie->data_alignment_factor;
+	offset_extended:
+	  register_rule (operand, offset, offset);
+	  continue;
+
+	case DW_CFA_offset_extended_sf:
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_sleb128 (sf_offset, program, end);
+	offset_extended_sf:
+	  offset = sf_offset * cie->data_alignment_factor;
+	  goto offset_extended;
+
+	case DW_CFA_GNU_negative_offset_extended:
+	  /* GNU extension obsoleted by DW_CFA_offset_extended_sf.  */
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (offset, program, end);
+	  sf_offset = -offset;
+	  goto offset_extended_sf;
+
+	case DW_CFA_val_offset:
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (offset, program, end);
+	  offset *= cie->data_alignment_factor;
+	val_offset:
+	  register_rule (operand, val_offset, offset);
+	  continue;
+
+	case DW_CFA_val_offset_sf:
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (program < end);
+	  get_sleb128 (sf_offset, program, end);
+	  offset = sf_offset * cie->data_alignment_factor;
+	  goto val_offset;
+
+	case DW_CFA_register:
+	  get_uleb128 (regno, program, end);
+	  cfi_assert (program < end);
+	  get_uleb128 (operand, program, end);
+	  register_rule (regno, register, operand);
+	  continue;
+
+	case DW_CFA_expression:
+	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
+	  assert (! abi_cfi);
+	  get_uleb128 (regno, program, end);
+	  offset = program - (const uint8_t *) cache->data->d.d_buf;
+	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
+	  cfi_assert (program < end);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (operand <= (Dwarf_Word) (end - program));
+	  program += operand;
+	  register_rule (regno, expression, offset);
+	  continue;
+
+	case DW_CFA_val_expression:
+	  /* Expression rule relies on section data, abi_cfi cannot use it.  */
+	  assert (! abi_cfi);
+	  get_uleb128 (regno, program, end);
+	  /* DW_FORM_block is a ULEB128 length followed by that many bytes.  */
+	  offset = program - (const uint8_t *) cache->data->d.d_buf;
+	  cfi_assert (program < end);
+	  get_uleb128 (operand, program, end);
+	  cfi_assert (operand <= (Dwarf_Word) (end - program));
+	  program += operand;
+	  register_rule (regno, val_expression, offset);
+	  continue;
+
+	case DW_CFA_restore_extended:
+	  get_uleb128 (operand, program, end);
+	  FALLTHROUGH;
+	case DW_CFA_restore + 0 ... DW_CFA_restore + CFI_PRIMARY_MAX:
+
+	  if (unlikely (abi_cfi) && likely (opcode == DW_CFA_restore))
+	    {
+	      /* Special case hack to give backend abi_cfi a shorthand.  */
+	      cache->default_same_value = true;
+	      continue;
+	    }
+
+	  /* This can't be used in the CIE's own initial instructions.  */
+	  cfi_assert (cie->initial_state != NULL);
+
+	  /* Restore the CIE's initial rule for this register.  */
+	  if (unlikely (! enough_registers (operand, &fs, &result)))
+	    goto out;
+	  if (cie->initial_state->nregs > operand)
+	    fs->regs[operand] = cie->initial_state->regs[operand];
+	  else
+	    fs->regs[operand].rule = reg_unspecified;
+	  continue;
+
+	case DW_CFA_remember_state:
+	  {
+	    /* Duplicate the state and chain the copy on.  */
+	    Dwarf_Frame *copy = duplicate_frame_state (fs, fs);
+	    if (unlikely (copy == NULL))
+	      {
+		result = DWARF_E_NOMEM;
+		goto out;
+	      }
+	    fs = copy;
+	    continue;
+	  }
+
+	case DW_CFA_restore_state:
+	  {
+	    /* Pop the current state off and use the old one instead.  */
+	    Dwarf_Frame *prev = fs->prev;
+	    cfi_assert (prev != NULL);
+	    free (fs);
+	    fs = prev;
+	    continue;
+	  }
+
+	case DW_CFA_nop:
+	  continue;
+
+	case DW_CFA_GNU_window_save: /* DW_CFA_AARCH64_negate_ra_state */
+	  if (cache->e_machine == EM_AARCH64)
+	    {
+	      /* Toggles the return address state, indicating whether
+		 the return address is encrypted or not on
+		 aarch64. XXX not handled yet.  */
+	    }
+	  else
+	    {
+	      /* This is magic shorthand used only by SPARC.  It's
+		 equivalent to a bunch of DW_CFA_register and
+		 DW_CFA_offset operations.  */
+	      if (unlikely (! enough_registers (31, &fs, &result)))
+		goto out;
+	      for (regno = 8; regno < 16; ++regno)
+		{
+		  /* Find each %oN in %iN.  */
+		  fs->regs[regno].rule = reg_register;
+		  fs->regs[regno].value = regno + 16;
+		}
+	      unsigned int address_size;
+	      address_size = (cache->e_ident[EI_CLASS] == ELFCLASS32
+			      ? 4 : 8);
+	      for (; regno < 32; ++regno)
+		{
+		  /* Find %l0..%l7 and %i0..%i7 in a block at the CFA.  */
+		  fs->regs[regno].rule = reg_offset;
+		  fs->regs[regno].value = (regno - 16) * address_size;
+		}
+	    }
+	  continue;
+
+	case DW_CFA_GNU_args_size:
+	  /* XXX is this useful for anything? */
+	  get_uleb128 (operand, program, end);
+	  continue;
+
+	default:
+	  cfi_assert (false);
+	  continue;
+	}
+
+      /* We get here only for the cases that have just moved LOC.  */
+      cfi_assert (cie->initial_state != NULL);
+      if (find_pc >= loc)
+	/* This advance has not yet reached FIND_PC.  */
+	fs->start = loc;
+      else
+	{
+	  /* We have just advanced past the address we're looking for.
+	     The state currently described is what we want to see.  */
+	  fs->end = loc;
+	  break;
+	}
+    }
+
+  /* "The end of the instruction stream can be thought of as a
+     DW_CFA_set_loc (initial_location + address_range) instruction."
+     (DWARF 3.0 Section 6.4.3)
+
+     When we fall off the end of the program without an advance_loc/set_loc
+     that put us past FIND_PC, the final state left by the FDE program
+     applies to this address (the caller ensured it was inside the FDE).
+     This address (FDE->end) is already in FS->end as set by the caller.  */
+
+#undef register_rule
+#undef cfi_assert
+
+ out:
+
+  /* Pop any remembered states left on the stack.  */
+  while (fs->prev != NULL)
+    {
+      Dwarf_Frame *prev = fs->prev;
+      fs->prev = prev->prev;
+      free (prev);
+    }
+
+  if (likely (result == DWARF_E_NOERROR))
+    *state = fs;
+  else
+    free (fs);
+
+  return result;
+}
+
+static int
+cie_cache_initial_state (Dwarf_CFI *cache, struct dwarf_cie *cie)
+{
+  int result = DWARF_E_NOERROR;
+
+  if (likely (cie->initial_state != NULL))
+    return result;
+
+  /* This CIE has not been used before.  Play out its initial
+     instructions and cache the initial state that results.
+     First we'll let the backend fill in the default initial
+     state for this machine's ABI.  */
+
+  Dwarf_CIE abi_info = { DW_CIE_ID_64, NULL, NULL, 1, 1, -1, "", NULL, 0, 0 };
+
+  /* Make sure we have a backend handle cached.  */
+  if (unlikely (cache->ebl == NULL))
+    {
+      cache->ebl = ebl_openbackend (cache->data->s->elf);
+      if (unlikely (cache->ebl == NULL))
+	cache->ebl = (void *) -1l;
+    }
+
+  /* Fetch the ABI's default CFI program.  */
+  if (likely (cache->ebl != (void *) -1l)
+      && unlikely (ebl_abi_cfi (cache->ebl, &abi_info) < 0))
+    return DWARF_E_UNKNOWN_ERROR;
+
+  Dwarf_Frame *cie_fs = calloc (1, sizeof (Dwarf_Frame));
+  if (unlikely (cie_fs == NULL))
+    return DWARF_E_NOMEM;
+
+  /* If the default state of any register is not "undefined"
+     (i.e. call-clobbered), then the backend supplies instructions
+     for the standard initial state.  */
+  if (abi_info.initial_instructions_end > abi_info.initial_instructions)
+    {
+      /* Dummy CIE for backend's instructions.  */
+      struct dwarf_cie abi_cie =
+	{
+	  .code_alignment_factor = abi_info.code_alignment_factor,
+	  .data_alignment_factor = abi_info.data_alignment_factor,
+	};
+      result = execute_cfi (cache, &abi_cie, &cie_fs,
+			    abi_info.initial_instructions,
+			    abi_info.initial_instructions_end, true,
+			    0, (Dwarf_Addr) -1l);
+    }
+
+  /* Now run the CIE's initial instructions.  */
+  if (cie->initial_instructions_end > cie->initial_instructions
+      && likely (result == DWARF_E_NOERROR))
+    result = execute_cfi (cache, cie, &cie_fs,
+			  cie->initial_instructions,
+			  cie->initial_instructions_end, false,
+			  0, (Dwarf_Addr) -1l);
+
+  if (likely (result == DWARF_E_NOERROR))
+    {
+      /* Now we have the initial state of things that all
+	 FDEs using this CIE will start from.  */
+      cie_fs->cache = cache;
+      cie->initial_state = cie_fs;
+    }
+
+  return result;
+}
+
+int
+internal_function
+__libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
+			  Dwarf_Addr address, Dwarf_Frame **frame)
+{
+  int result = cie_cache_initial_state (cache, fde->cie);
+  if (likely (result == DWARF_E_NOERROR))
+    {
+      Dwarf_Frame *fs = duplicate_frame_state (fde->cie->initial_state, NULL);
+      if (unlikely (fs == NULL))
+	return DWARF_E_NOMEM;
+
+      fs->fde = fde;
+      fs->start = fde->start;
+      fs->end = fde->end;
+
+      result = execute_cfi (cache, fde->cie, &fs,
+			    fde->instructions, fde->instructions_end, false,
+			    fde->start, address);
+      if (likely (result == DWARF_E_NOERROR))
+	*frame = fs;
+    }
+  return result;
+}
diff --git a/libdw/cfi.h b/libdw/cfi.h
new file mode 100644
index 0000000..1b0d712
--- /dev/null
+++ b/libdw/cfi.h
@@ -0,0 +1,238 @@
+/* Internal definitions for libdw CFI interpreter.
+   Copyright (C) 2009-2010, 2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _UNWINDP_H
+#define _UNWINDP_H 1
+
+#include "libdwP.h"
+#include "libelfP.h"
+struct ebl;
+
+/* Cached CIE representation.  */
+struct dwarf_cie
+{
+  Dwarf_Off offset;	 /* Our position, as seen in FDEs' CIE_pointer.  */
+
+  Dwarf_Word code_alignment_factor;
+  Dwarf_Sword data_alignment_factor;
+  Dwarf_Word return_address_register;
+
+  size_t fde_augmentation_data_size;
+
+  // play out to initial state
+  const uint8_t *initial_instructions;
+  const uint8_t *initial_instructions_end;
+
+  const Dwarf_Frame *initial_state;
+
+  uint8_t fde_encoding;		/* DW_EH_PE_* for addresses in FDEs.  */
+  uint8_t lsda_encoding;    /* DW_EH_PE_* for LSDA in FDE augmentation.  */
+
+  bool sized_augmentation_data;	/* Saw 'z': FDEs have self-sized data.  */
+  bool signal_frame;		/* Saw 'S': FDE is for a signal frame.  */
+};
+
+/* Cached FDE representation.  */
+struct dwarf_fde
+{
+  struct dwarf_cie *cie;
+
+  /* This FDE describes PC values in [start, end).  */
+  Dwarf_Addr start;
+  Dwarf_Addr end;
+
+  const uint8_t *instructions;
+  const uint8_t *instructions_end;
+};
+
+/* This holds everything we cache about the CFI from each ELF file's
+   .debug_frame or .eh_frame section.  */
+struct Dwarf_CFI_s
+{
+  /* Dwarf handle we came from.  If null, this is .eh_frame data.  */
+  Dwarf *dbg;
+#define CFI_IS_EH(cfi)	((cfi)->dbg == NULL)
+
+  /* Data of the .debug_frame or .eh_frame section.  */
+  Elf_Data_Scn *data;
+  const unsigned char *e_ident;	/* For EI_DATA and EI_CLASS.  */
+
+  Dwarf_Addr frame_vaddr;  /* DW_EH_PE_pcrel, address of frame section.  */
+  Dwarf_Addr textrel;		/* DW_EH_PE_textrel base address.  */
+  Dwarf_Addr datarel;		/* DW_EH_PE_datarel base address.  */
+
+  /* Location of next unread entry in the section.  */
+  Dwarf_Off next_offset;
+
+  /* Search tree for the CIEs, indexed by CIE_pointer (section offset).  */
+  void *cie_tree;
+
+  /* Search tree for the FDEs, indexed by PC address.  */
+  void *fde_tree;
+
+  /* Search tree for parsed DWARF expressions, indexed by raw pointer.  */
+  void *expr_tree;
+
+  /* Backend hook.  */
+  struct ebl *ebl;
+
+  /* Binary search table in .eh_frame_hdr section.  */
+  const uint8_t *search_table;
+  size_t search_table_len;
+  Dwarf_Addr search_table_vaddr;
+  size_t search_table_entries;
+  uint8_t search_table_encoding;
+
+  uint16_t e_machine;
+
+  /* True if the file has a byte order different from the host.  */
+  bool other_byte_order;
+
+  /* Default rule for registers not previously mentioned
+     is same_value, not undefined.  */
+  bool default_same_value;
+};
+
+
+enum dwarf_frame_rule
+  {
+    reg_unspecified,		/* Uninitialized state.  */
+    reg_undefined,		/* DW_CFA_undefined */
+    reg_same_value,		/* DW_CFA_same_value */
+    reg_offset,			/* DW_CFA_offset_extended et al */
+    reg_val_offset,		/* DW_CFA_val_offset et al */
+    reg_register,		/* DW_CFA_register */
+    reg_expression,		/* DW_CFA_expression */
+    reg_val_expression,		/* DW_CFA_val_expression */
+  };
+
+/* This describes what we know about an individual register.  */
+struct dwarf_frame_register
+{
+  enum dwarf_frame_rule rule:3;
+
+  /* The meaning of the value bits depends on the rule:
+
+	Rule			Value
+	----			-----
+	undefined		unused
+	same_value		unused
+	offset(N)		N	(register saved at CFA + value)
+	val_offset(N)		N	(register = CFA + value)
+	register(R)		R	(register = register #value)
+	expression(E)		section offset of DW_FORM_block containing E
+					(register saved at address E computes)
+	val_expression(E)	section offset of DW_FORM_block containing E
+					(register = value E computes)
+  */
+  Dwarf_Sword value:(sizeof (Dwarf_Sword) * 8 - 3);
+};
+
+/* This holds instructions for unwinding frame at a particular PC location
+   described by an FDE.  */
+struct Dwarf_Frame_s
+{
+  /* This frame description covers PC values in [start, end).  */
+  Dwarf_Addr start;
+  Dwarf_Addr end;
+
+  Dwarf_CFI *cache;
+
+  /* Previous state saved by DW_CFA_remember_state, or .cie->initial_state,
+     or NULL in an initial_state pseudo-frame.  */
+  Dwarf_Frame *prev;
+
+  /* The FDE that generated this frame state.  This points to its CIE,
+     which has the return_address_register and signal_frame flag.  */
+  struct dwarf_fde *fde;
+
+  /* The CFA is unknown, is R+N, or is computed by a DWARF expression.
+     A bogon in the CFI can indicate an invalid/incalculable rule.
+     We store that as cfa_invalid rather than barfing when processing it,
+     so callers can ignore the bogon unless they really need that CFA.  */
+  enum { cfa_undefined, cfa_offset, cfa_expr, cfa_invalid } cfa_rule;
+  union
+  {
+    Dwarf_Op offset;
+    Dwarf_Block expr;
+  } cfa_data;
+  /* We store an offset rule as a DW_OP_bregx operation.  */
+#define cfa_val_reg	cfa_data.offset.number
+#define cfa_val_offset	cfa_data.offset.number2
+
+  size_t nregs;
+  struct dwarf_frame_register regs[];
+};
+
+
+/* Clean up the data structure and all it points to.  */
+extern void __libdw_destroy_frame_cache (Dwarf_CFI *cache)
+  __nonnull_attribute__ (1) internal_function;
+
+/* Enter a CIE encountered while reading through for FDEs.  */
+extern void __libdw_intern_cie (Dwarf_CFI *cache, Dwarf_Off offset,
+				const Dwarf_CIE *info)
+  __nonnull_attribute__ (1, 3) internal_function;
+
+/* Look up a CIE_pointer for random access.  */
+extern struct dwarf_cie *__libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset)
+  __nonnull_attribute__ (1) internal_function;
+
+
+/* Look for an FDE covering the given PC address.  */
+extern struct dwarf_fde *__libdw_find_fde (Dwarf_CFI *cache,
+					   Dwarf_Addr address)
+  __nonnull_attribute__ (1) internal_function;
+
+/* Look for an FDE by its offset in the section.  */
+extern struct dwarf_fde *__libdw_fde_by_offset (Dwarf_CFI *cache,
+						Dwarf_Off offset)
+  __nonnull_attribute__ (1) internal_function;
+
+/* Process the FDE that contains the given PC address,
+   to yield the frame state when stopped there.
+   The return value is a DWARF_E_* error code.  */
+extern int __libdw_frame_at_address (Dwarf_CFI *cache, struct dwarf_fde *fde,
+				     Dwarf_Addr address, Dwarf_Frame **frame)
+  __nonnull_attribute__ (1, 2, 4) internal_function;
+
+
+/* Dummy struct for memory-access.h macros.  */
+#define BYTE_ORDER_DUMMY(var, e_ident)					      \
+  const struct { bool other_byte_order; } var =				      \
+    { ((BYTE_ORDER == LITTLE_ENDIAN && e_ident[EI_DATA] == ELFDATA2MSB)       \
+       || (BYTE_ORDER == BIG_ENDIAN && e_ident[EI_DATA] == ELFDATA2LSB)) }
+
+
+INTDECL (dwarf_next_cfi)
+INTDECL (dwarf_getcfi)
+INTDECL (dwarf_getcfi_elf)
+INTDECL (dwarf_cfi_end)
+INTDECL (dwarf_cfi_addrframe)
+
+#endif	/* unwindP.h */
diff --git a/libdw/cie.c b/libdw/cie.c
new file mode 100644
index 0000000..1b0aae7
--- /dev/null
+++ b/libdw/cie.c
@@ -0,0 +1,196 @@
+/* CIE reading.
+   Copyright (C) 2009-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+#include "encoded-value.h"
+#include <assert.h>
+#include <search.h>
+#include <stdlib.h>
+
+
+static int
+compare_cie (const void *a, const void *b)
+{
+  const struct dwarf_cie *cie1 = a;
+  const struct dwarf_cie *cie2 = b;
+  if (cie1->offset < cie2->offset)
+    return -1;
+  if (cie1->offset > cie2->offset)
+    return 1;
+  return 0;
+}
+
+/* There is no CIE at OFFSET in the tree.  Add it.  */
+static struct dwarf_cie *
+intern_new_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
+{
+  struct dwarf_cie *cie = malloc (sizeof (struct dwarf_cie));
+  if (cie == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  cie->offset = offset;
+  cie->code_alignment_factor = info->code_alignment_factor;
+  cie->data_alignment_factor = info->data_alignment_factor;
+  cie->return_address_register = info->return_address_register;
+
+  cie->fde_augmentation_data_size = 0;
+  cie->sized_augmentation_data = false;
+  cie->signal_frame = false;
+
+  cie->fde_encoding = DW_EH_PE_absptr;
+  cie->lsda_encoding = DW_EH_PE_omit;
+
+  /* Grok the augmentation string and its data.  */
+  const uint8_t *data = info->augmentation_data;
+  for (const char *ap = info->augmentation; *ap != '\0'; ++ap)
+    {
+      uint8_t encoding;
+      switch (*ap)
+	{
+	case 'z':
+	  cie->sized_augmentation_data = true;
+	  continue;
+
+	case 'S':
+	  cie->signal_frame = true;
+	  continue;
+
+	case 'L':		/* LSDA pointer encoding byte.  */
+	  cie->lsda_encoding = *data++;
+	  if (!cie->sized_augmentation_data)
+	    cie->fde_augmentation_data_size
+	      += encoded_value_size (&cache->data->d, cache->e_ident,
+				     cie->lsda_encoding, NULL);
+	  continue;
+
+	case 'R':		/* FDE address encoding byte.  */
+	  cie->fde_encoding = *data++;
+	  continue;
+
+	case 'P':		/* Skip personality routine.  */
+	  encoding = *data++;
+	  data += encoded_value_size (&cache->data->d, cache->e_ident,
+				      encoding, data);
+	  continue;
+
+	default:
+	  /* Unknown augmentation string.  If we have 'z' we can ignore it,
+	     otherwise we must bail out.  */
+	  if (cie->sized_augmentation_data)
+	    continue;
+	}
+      /* We only get here when we need to bail out.  */
+      break;
+    }
+
+  if ((cie->fde_encoding & 0x0f) == DW_EH_PE_absptr)
+    {
+      /* Canonicalize encoding to a specific size.  */
+      assert (DW_EH_PE_absptr == 0);
+
+      /* XXX should get from dwarf_next_cfi with v4 header.  */
+      uint_fast8_t address_size
+	= cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+      switch (address_size)
+	{
+	case 8:
+	  cie->fde_encoding |= DW_EH_PE_udata8;
+	  break;
+	case 4:
+	  cie->fde_encoding |= DW_EH_PE_udata4;
+	  break;
+	default:
+	  free (cie);
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return NULL;
+	}
+    }
+
+  /* Save the initial instructions to be played out into initial state.  */
+  cie->initial_instructions = info->initial_instructions;
+  cie->initial_instructions_end = info->initial_instructions_end;
+  cie->initial_state = NULL;
+
+  /* Add the new entry to the search tree.  */
+  if (tsearch (cie, &cache->cie_tree, &compare_cie) == NULL)
+    {
+      free (cie);
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  return cie;
+}
+
+/* Look up a CIE_pointer for random access.  */
+struct dwarf_cie *
+internal_function
+__libdw_find_cie (Dwarf_CFI *cache, Dwarf_Off offset)
+{
+  const struct dwarf_cie cie_key = { .offset = offset };
+  struct dwarf_cie **found = tfind (&cie_key, &cache->cie_tree, &compare_cie);
+  if (found != NULL)
+    return *found;
+
+  /* We have not read this CIE yet.  Go find it.  */
+  Dwarf_Off next_offset = offset;
+  Dwarf_CFI_Entry entry;
+  int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
+				       &cache->data->d, CFI_IS_EH (cache),
+				       offset, &next_offset, &entry);
+  if (result != 0 || entry.cie.CIE_id != DW_CIE_ID_64)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  /* If this happened to be what we would have read next, notice it.  */
+  if (cache->next_offset == offset)
+    cache->next_offset = next_offset;
+
+  return intern_new_cie (cache, offset, &entry.cie);
+}
+
+/* Enter a CIE encountered while reading through for FDEs.  */
+void
+internal_function
+__libdw_intern_cie (Dwarf_CFI *cache, Dwarf_Off offset, const Dwarf_CIE *info)
+{
+  const struct dwarf_cie cie_key = { .offset = offset };
+  struct dwarf_cie **found = tfind (&cie_key, &cache->cie_tree, &compare_cie);
+  if (found == NULL)
+    /* We have not read this CIE yet.  Enter it.  */
+    (void) intern_new_cie (cache, offset, info);
+}
diff --git a/libdw/dwarf.h b/libdw/dwarf.h
new file mode 100644
index 0000000..4be32de
--- /dev/null
+++ b/libdw/dwarf.h
@@ -0,0 +1,1050 @@
+/* This file defines standard DWARF types, structures, and macros.
+   Copyright (C) 2000-2011, 2014, 2016, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DWARF_H
+#define	_DWARF_H 1
+
+/* DWARF Unit Header Types.  */
+enum
+  {
+    DW_UT_compile = 0x01,
+    DW_UT_type = 0x02,
+    DW_UT_partial = 0x03,
+    DW_UT_skeleton = 0x04,
+    DW_UT_split_compile = 0x05,
+    DW_UT_split_type = 0x06,
+
+    DW_UT_lo_user = 0x80,
+    DW_UT_hi_user = 0xff
+  };
+
+/* DWARF tags.  */
+enum
+  {
+    DW_TAG_array_type = 0x01,
+    DW_TAG_class_type = 0x02,
+    DW_TAG_entry_point = 0x03,
+    DW_TAG_enumeration_type = 0x04,
+    DW_TAG_formal_parameter = 0x05,
+    /* 0x06 reserved.  */
+    /* 0x07 reserved.  */
+    DW_TAG_imported_declaration = 0x08,
+    /* 0x09 reserved.  */
+    DW_TAG_label = 0x0a,
+    DW_TAG_lexical_block = 0x0b,
+    /* 0x0c reserved.  */
+    DW_TAG_member = 0x0d,
+    /* 0x0e reserved.  */
+    DW_TAG_pointer_type = 0x0f,
+    DW_TAG_reference_type = 0x10,
+    DW_TAG_compile_unit = 0x11,
+    DW_TAG_string_type = 0x12,
+    DW_TAG_structure_type = 0x13,
+    /* 0x14 reserved.  */
+    DW_TAG_subroutine_type = 0x15,
+    DW_TAG_typedef = 0x16,
+    DW_TAG_union_type = 0x17,
+    DW_TAG_unspecified_parameters = 0x18,
+    DW_TAG_variant = 0x19,
+    DW_TAG_common_block = 0x1a,
+    DW_TAG_common_inclusion = 0x1b,
+    DW_TAG_inheritance = 0x1c,
+    DW_TAG_inlined_subroutine = 0x1d,
+    DW_TAG_module = 0x1e,
+    DW_TAG_ptr_to_member_type = 0x1f,
+    DW_TAG_set_type = 0x20,
+    DW_TAG_subrange_type = 0x21,
+    DW_TAG_with_stmt = 0x22,
+    DW_TAG_access_declaration = 0x23,
+    DW_TAG_base_type = 0x24,
+    DW_TAG_catch_block = 0x25,
+    DW_TAG_const_type = 0x26,
+    DW_TAG_constant = 0x27,
+    DW_TAG_enumerator = 0x28,
+    DW_TAG_file_type = 0x29,
+    DW_TAG_friend = 0x2a,
+    DW_TAG_namelist = 0x2b,
+    DW_TAG_namelist_item = 0x2c,
+    DW_TAG_packed_type = 0x2d,
+    DW_TAG_subprogram = 0x2e,
+    DW_TAG_template_type_parameter = 0x2f,
+    DW_TAG_template_value_parameter = 0x30,
+    DW_TAG_thrown_type = 0x31,
+    DW_TAG_try_block = 0x32,
+    DW_TAG_variant_part = 0x33,
+    DW_TAG_variable = 0x34,
+    DW_TAG_volatile_type = 0x35,
+    DW_TAG_dwarf_procedure = 0x36,
+    DW_TAG_restrict_type = 0x37,
+    DW_TAG_interface_type = 0x38,
+    DW_TAG_namespace = 0x39,
+    DW_TAG_imported_module = 0x3a,
+    DW_TAG_unspecified_type = 0x3b,
+    DW_TAG_partial_unit = 0x3c,
+    DW_TAG_imported_unit = 0x3d,
+    /* 0x3e reserved.  Was DW_TAG_mutable_type.  */
+    DW_TAG_condition = 0x3f,
+    DW_TAG_shared_type = 0x40,
+    DW_TAG_type_unit = 0x41,
+    DW_TAG_rvalue_reference_type = 0x42,
+    DW_TAG_template_alias = 0x43,
+    DW_TAG_coarray_type = 0x44,
+    DW_TAG_generic_subrange = 0x45,
+    DW_TAG_dynamic_type = 0x46,
+    DW_TAG_atomic_type = 0x47,
+    DW_TAG_call_site = 0x48,
+    DW_TAG_call_site_parameter = 0x49,
+    DW_TAG_skeleton_unit = 0x4a,
+    DW_TAG_immutable_type = 0x4b,
+
+    DW_TAG_lo_user = 0x4080,
+
+    DW_TAG_MIPS_loop = 0x4081,
+    DW_TAG_format_label = 0x4101,
+    DW_TAG_function_template = 0x4102,
+    DW_TAG_class_template = 0x4103,
+
+    DW_TAG_GNU_BINCL = 0x4104,
+    DW_TAG_GNU_EINCL = 0x4105,
+
+    DW_TAG_GNU_template_template_param = 0x4106,
+    DW_TAG_GNU_template_parameter_pack = 0x4107,
+    DW_TAG_GNU_formal_parameter_pack = 0x4108,
+    DW_TAG_GNU_call_site = 0x4109,
+    DW_TAG_GNU_call_site_parameter = 0x410a,
+
+    DW_TAG_hi_user = 0xffff
+  };
+
+
+/* Children determination encodings.  */
+enum
+  {
+    DW_CHILDREN_no = 0,
+    DW_CHILDREN_yes = 1
+  };
+
+
+/* DWARF attributes encodings.  */
+enum
+  {
+    DW_AT_sibling = 0x01,
+    DW_AT_location = 0x02,
+    DW_AT_name = 0x03,
+    /* 0x04 reserved.  */
+    /* 0x05 reserved.  */
+    /* 0x06 reserved.  */
+    /* 0x07 reserved.  */
+    /* 0x08 reserved.  */
+    DW_AT_ordering = 0x09,
+    /* 0x0a reserved.  */
+    DW_AT_byte_size = 0x0b,
+    DW_AT_bit_offset = 0x0c,  /* Deprecated in DWARF4.  */
+    DW_AT_bit_size = 0x0d,
+    /* 0x0e reserved.  */
+    /* 0x0f reserved.  */
+    DW_AT_stmt_list = 0x10,
+    DW_AT_low_pc = 0x11,
+    DW_AT_high_pc = 0x12,
+    DW_AT_language = 0x13,
+    /* 0x14 reserved.  */
+    DW_AT_discr = 0x15,
+    DW_AT_discr_value = 0x16,
+    DW_AT_visibility = 0x17,
+    DW_AT_import = 0x18,
+    DW_AT_string_length = 0x19,
+    DW_AT_common_reference = 0x1a,
+    DW_AT_comp_dir = 0x1b,
+    DW_AT_const_value = 0x1c,
+    DW_AT_containing_type = 0x1d,
+    DW_AT_default_value = 0x1e,
+    /* 0x1f reserved.  */
+    DW_AT_inline = 0x20,
+    DW_AT_is_optional = 0x21,
+    DW_AT_lower_bound = 0x22,
+    /* 0x23 reserved.  */
+    /* 0x24 reserved.  */
+    DW_AT_producer = 0x25,
+    /* 0x26 reserved.  */
+    DW_AT_prototyped = 0x27,
+    /* 0x28 reserved.  */
+    /* 0x29 reserved.  */
+    DW_AT_return_addr = 0x2a,
+    /* 0x2b reserved.  */
+    DW_AT_start_scope = 0x2c,
+    /* 0x2d reserved.  */
+    DW_AT_bit_stride = 0x2e,
+    DW_AT_upper_bound = 0x2f,
+    /* 0x30 reserved.  */
+    DW_AT_abstract_origin = 0x31,
+    DW_AT_accessibility = 0x32,
+    DW_AT_address_class = 0x33,
+    DW_AT_artificial = 0x34,
+    DW_AT_base_types = 0x35,
+    DW_AT_calling_convention = 0x36,
+    DW_AT_count = 0x37,
+    DW_AT_data_member_location = 0x38,
+    DW_AT_decl_column = 0x39,
+    DW_AT_decl_file = 0x3a,
+    DW_AT_decl_line = 0x3b,
+    DW_AT_declaration = 0x3c,
+    DW_AT_discr_list = 0x3d,
+    DW_AT_encoding = 0x3e,
+    DW_AT_external = 0x3f,
+    DW_AT_frame_base = 0x40,
+    DW_AT_friend = 0x41,
+    DW_AT_identifier_case = 0x42,
+    DW_AT_macro_info = 0x43, /* Deprecated in DWARF5.  */
+    DW_AT_namelist_item = 0x44,
+    DW_AT_priority = 0x45,
+    DW_AT_segment = 0x46,
+    DW_AT_specification = 0x47,
+    DW_AT_static_link = 0x48,
+    DW_AT_type = 0x49,
+    DW_AT_use_location = 0x4a,
+    DW_AT_variable_parameter = 0x4b,
+    DW_AT_virtuality = 0x4c,
+    DW_AT_vtable_elem_location = 0x4d,
+    DW_AT_allocated = 0x4e,
+    DW_AT_associated = 0x4f,
+    DW_AT_data_location = 0x50,
+    DW_AT_byte_stride = 0x51,
+    DW_AT_entry_pc = 0x52,
+    DW_AT_use_UTF8 = 0x53,
+    DW_AT_extension = 0x54,
+    DW_AT_ranges = 0x55,
+    DW_AT_trampoline = 0x56,
+    DW_AT_call_column = 0x57,
+    DW_AT_call_file = 0x58,
+    DW_AT_call_line = 0x59,
+    DW_AT_description = 0x5a,
+    DW_AT_binary_scale = 0x5b,
+    DW_AT_decimal_scale = 0x5c,
+    DW_AT_small = 0x5d,
+    DW_AT_decimal_sign = 0x5e,
+    DW_AT_digit_count = 0x5f,
+    DW_AT_picture_string = 0x60,
+    DW_AT_mutable = 0x61,
+    DW_AT_threads_scaled = 0x62,
+    DW_AT_explicit = 0x63,
+    DW_AT_object_pointer = 0x64,
+    DW_AT_endianity = 0x65,
+    DW_AT_elemental = 0x66,
+    DW_AT_pure = 0x67,
+    DW_AT_recursive = 0x68,
+    DW_AT_signature = 0x69,
+    DW_AT_main_subprogram = 0x6a,
+    DW_AT_data_bit_offset = 0x6b,
+    DW_AT_const_expr = 0x6c,
+    DW_AT_enum_class = 0x6d,
+    DW_AT_linkage_name = 0x6e,
+    DW_AT_string_length_bit_size = 0x6f,
+    DW_AT_string_length_byte_size = 0x70,
+    DW_AT_rank = 0x71,
+    DW_AT_str_offsets_base = 0x72,
+    DW_AT_addr_base = 0x73,
+    DW_AT_rnglists_base = 0x74,
+    /* 0x75 reserved.  */
+    DW_AT_dwo_name = 0x76,
+    DW_AT_reference = 0x77,
+    DW_AT_rvalue_reference = 0x78,
+    DW_AT_macros = 0x79,
+    DW_AT_call_all_calls = 0x7a,
+    DW_AT_call_all_source_calls = 0x7b,
+    DW_AT_call_all_tail_calls = 0x7c,
+    DW_AT_call_return_pc = 0x7d,
+    DW_AT_call_value = 0x7e,
+    DW_AT_call_origin = 0x7f,
+    DW_AT_call_parameter = 0x80,
+    DW_AT_call_pc = 0x81,
+    DW_AT_call_tail_call = 0x82,
+    DW_AT_call_target = 0x83,
+    DW_AT_call_target_clobbered = 0x84,
+    DW_AT_call_data_location = 0x85,
+    DW_AT_call_data_value = 0x86,
+    DW_AT_noreturn = 0x87,
+    DW_AT_alignment = 0x88,
+    DW_AT_export_symbols = 0x89,
+    DW_AT_deleted = 0x8a,
+    DW_AT_defaulted = 0x8b,
+    DW_AT_loclists_base = 0x8c,
+
+    DW_AT_lo_user = 0x2000,
+
+    DW_AT_MIPS_fde = 0x2001,
+    DW_AT_MIPS_loop_begin = 0x2002,
+    DW_AT_MIPS_tail_loop_begin = 0x2003,
+    DW_AT_MIPS_epilog_begin = 0x2004,
+    DW_AT_MIPS_loop_unroll_factor = 0x2005,
+    DW_AT_MIPS_software_pipeline_depth = 0x2006,
+    DW_AT_MIPS_linkage_name = 0x2007,
+    DW_AT_MIPS_stride = 0x2008,
+    DW_AT_MIPS_abstract_name = 0x2009,
+    DW_AT_MIPS_clone_origin = 0x200a,
+    DW_AT_MIPS_has_inlines = 0x200b,
+    DW_AT_MIPS_stride_byte = 0x200c,
+    DW_AT_MIPS_stride_elem = 0x200d,
+    DW_AT_MIPS_ptr_dopetype = 0x200e,
+    DW_AT_MIPS_allocatable_dopetype = 0x200f,
+    DW_AT_MIPS_assumed_shape_dopetype = 0x2010,
+    DW_AT_MIPS_assumed_size = 0x2011,
+
+    /* GNU extensions.  */
+    DW_AT_sf_names = 0x2101,
+    DW_AT_src_info = 0x2102,
+    DW_AT_mac_info = 0x2103,
+    DW_AT_src_coords = 0x2104,
+    DW_AT_body_begin = 0x2105,
+    DW_AT_body_end = 0x2106,
+    DW_AT_GNU_vector = 0x2107,
+    DW_AT_GNU_guarded_by = 0x2108,
+    DW_AT_GNU_pt_guarded_by = 0x2109,
+    DW_AT_GNU_guarded = 0x210a,
+    DW_AT_GNU_pt_guarded = 0x210b,
+    DW_AT_GNU_locks_excluded = 0x210c,
+    DW_AT_GNU_exclusive_locks_required = 0x210d,
+    DW_AT_GNU_shared_locks_required = 0x210e,
+    DW_AT_GNU_odr_signature = 0x210f,
+    DW_AT_GNU_template_name = 0x2110,
+    DW_AT_GNU_call_site_value = 0x2111,
+    DW_AT_GNU_call_site_data_value = 0x2112,
+    DW_AT_GNU_call_site_target = 0x2113,
+    DW_AT_GNU_call_site_target_clobbered = 0x2114,
+    DW_AT_GNU_tail_call = 0x2115,
+    DW_AT_GNU_all_tail_call_sites = 0x2116,
+    DW_AT_GNU_all_call_sites = 0x2117,
+    DW_AT_GNU_all_source_call_sites = 0x2118,
+    DW_AT_GNU_locviews = 0x2137,
+    DW_AT_GNU_entry_view = 0x2138,
+    DW_AT_GNU_macros = 0x2119,
+    DW_AT_GNU_deleted = 0x211a,
+    /* GNU Debug Fission extensions.  */
+    DW_AT_GNU_dwo_name = 0x2130,
+    DW_AT_GNU_dwo_id = 0x2131,
+    DW_AT_GNU_ranges_base = 0x2132,
+    DW_AT_GNU_addr_base = 0x2133,
+    DW_AT_GNU_pubnames = 0x2134,
+    DW_AT_GNU_pubtypes = 0x2135,
+
+    /* https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator  */
+    DW_AT_GNU_numerator = 0x2303,
+    DW_AT_GNU_denominator = 0x2304,
+    /* https://gcc.gnu.org/wiki/DW_AT_GNU_bias  */
+    DW_AT_GNU_bias = 0x2305,
+
+    DW_AT_hi_user = 0x3fff
+  };
+
+/* Old unofficially attribute names.  Should not be used.
+   Will not appear in known-dwarf.h  */
+
+/* DWARF1 array subscripts and element data types.  */
+#define DW_AT_subscr_data	0x0a
+/* DWARF1 enumeration literals.  */
+#define DW_AT_element_list	0x0f
+/* DWARF1 reference for variable to member structure, class or union.  */
+#define DW_AT_member		0x14
+
+/* DWARF form encodings.  */
+enum
+  {
+    DW_FORM_addr = 0x01,
+    DW_FORM_block2 = 0x03,
+    DW_FORM_block4 = 0x04,
+    DW_FORM_data2 = 0x05,
+    DW_FORM_data4 = 0x06,
+    DW_FORM_data8 = 0x07,
+    DW_FORM_string = 0x08,
+    DW_FORM_block = 0x09,
+    DW_FORM_block1 = 0x0a,
+    DW_FORM_data1 = 0x0b,
+    DW_FORM_flag = 0x0c,
+    DW_FORM_sdata = 0x0d,
+    DW_FORM_strp = 0x0e,
+    DW_FORM_udata = 0x0f,
+    DW_FORM_ref_addr = 0x10,
+    DW_FORM_ref1 = 0x11,
+    DW_FORM_ref2 = 0x12,
+    DW_FORM_ref4 = 0x13,
+    DW_FORM_ref8 = 0x14,
+    DW_FORM_ref_udata = 0x15,
+    DW_FORM_indirect = 0x16,
+    DW_FORM_sec_offset = 0x17,
+    DW_FORM_exprloc = 0x18,
+    DW_FORM_flag_present = 0x19,
+    DW_FORM_strx = 0x1a,
+    DW_FORM_addrx = 0x1b,
+    DW_FORM_ref_sup4 = 0x1c,
+    DW_FORM_strp_sup = 0x1d,
+    DW_FORM_data16 = 0x1e,
+    DW_FORM_line_strp = 0x1f,
+    DW_FORM_ref_sig8 = 0x20,
+    DW_FORM_implicit_const = 0x21,
+    DW_FORM_loclistx = 0x22,
+    DW_FORM_rnglistx = 0x23,
+    DW_FORM_ref_sup8 = 0x24,
+    DW_FORM_strx1 = 0x25,
+    DW_FORM_strx2 = 0x26,
+    DW_FORM_strx3 = 0x27,
+    DW_FORM_strx4 = 0x28,
+    DW_FORM_addrx1 = 0x29,
+    DW_FORM_addrx2 = 0x2a,
+    DW_FORM_addrx3 = 0x2b,
+    DW_FORM_addrx4 = 0x2c,
+
+    /* GNU Debug Fission extensions.  */
+    DW_FORM_GNU_addr_index = 0x1f01,
+    DW_FORM_GNU_str_index = 0x1f02,
+
+    DW_FORM_GNU_ref_alt = 0x1f20, /* offset in alternate .debuginfo.  */
+    DW_FORM_GNU_strp_alt = 0x1f21 /* offset in alternate .debug_str. */
+  };
+
+
+/* DWARF location operation encodings.  */
+enum
+  {
+    DW_OP_addr = 0x03,		/* Constant address.  */
+    DW_OP_deref = 0x06,
+    DW_OP_const1u = 0x08,	/* Unsigned 1-byte constant.  */
+    DW_OP_const1s = 0x09,	/* Signed 1-byte constant.  */
+    DW_OP_const2u = 0x0a,	/* Unsigned 2-byte constant.  */
+    DW_OP_const2s = 0x0b,	/* Signed 2-byte constant.  */
+    DW_OP_const4u = 0x0c,	/* Unsigned 4-byte constant.  */
+    DW_OP_const4s = 0x0d,	/* Signed 4-byte constant.  */
+    DW_OP_const8u = 0x0e,	/* Unsigned 8-byte constant.  */
+    DW_OP_const8s = 0x0f,	/* Signed 8-byte constant.  */
+    DW_OP_constu = 0x10,	/* Unsigned LEB128 constant.  */
+    DW_OP_consts = 0x11,	/* Signed LEB128 constant.  */
+    DW_OP_dup = 0x12,
+    DW_OP_drop = 0x13,
+    DW_OP_over = 0x14,
+    DW_OP_pick = 0x15,		/* 1-byte stack index.  */
+    DW_OP_swap = 0x16,
+    DW_OP_rot = 0x17,
+    DW_OP_xderef = 0x18,
+    DW_OP_abs = 0x19,
+    DW_OP_and = 0x1a,
+    DW_OP_div = 0x1b,
+    DW_OP_minus = 0x1c,
+    DW_OP_mod = 0x1d,
+    DW_OP_mul = 0x1e,
+    DW_OP_neg = 0x1f,
+    DW_OP_not = 0x20,
+    DW_OP_or = 0x21,
+    DW_OP_plus = 0x22,
+    DW_OP_plus_uconst = 0x23,	/* Unsigned LEB128 addend.  */
+    DW_OP_shl = 0x24,
+    DW_OP_shr = 0x25,
+    DW_OP_shra = 0x26,
+    DW_OP_xor = 0x27,
+    DW_OP_bra = 0x28,		/* Signed 2-byte constant.  */
+    DW_OP_eq = 0x29,
+    DW_OP_ge = 0x2a,
+    DW_OP_gt = 0x2b,
+    DW_OP_le = 0x2c,
+    DW_OP_lt = 0x2d,
+    DW_OP_ne = 0x2e,
+    DW_OP_skip = 0x2f,		/* Signed 2-byte constant.  */
+    DW_OP_lit0 = 0x30,		/* Literal 0.  */
+    DW_OP_lit1 = 0x31,		/* Literal 1.  */
+    DW_OP_lit2 = 0x32,		/* Literal 2.  */
+    DW_OP_lit3 = 0x33,		/* Literal 3.  */
+    DW_OP_lit4 = 0x34,		/* Literal 4.  */
+    DW_OP_lit5 = 0x35,		/* Literal 5.  */
+    DW_OP_lit6 = 0x36,		/* Literal 6.  */
+    DW_OP_lit7 = 0x37,		/* Literal 7.  */
+    DW_OP_lit8 = 0x38,		/* Literal 8.  */
+    DW_OP_lit9 = 0x39,		/* Literal 9.  */
+    DW_OP_lit10 = 0x3a,		/* Literal 10.  */
+    DW_OP_lit11 = 0x3b,		/* Literal 11.  */
+    DW_OP_lit12 = 0x3c,		/* Literal 12.  */
+    DW_OP_lit13 = 0x3d,		/* Literal 13.  */
+    DW_OP_lit14 = 0x3e,		/* Literal 14.  */
+    DW_OP_lit15 = 0x3f,		/* Literal 15.  */
+    DW_OP_lit16 = 0x40,		/* Literal 16.  */
+    DW_OP_lit17 = 0x41,		/* Literal 17.  */
+    DW_OP_lit18 = 0x42,		/* Literal 18.  */
+    DW_OP_lit19 = 0x43,		/* Literal 19.  */
+    DW_OP_lit20 = 0x44,		/* Literal 20.  */
+    DW_OP_lit21 = 0x45,		/* Literal 21.  */
+    DW_OP_lit22 = 0x46,		/* Literal 22.  */
+    DW_OP_lit23 = 0x47,		/* Literal 23.  */
+    DW_OP_lit24 = 0x48,		/* Literal 24.  */
+    DW_OP_lit25 = 0x49,		/* Literal 25.  */
+    DW_OP_lit26 = 0x4a,		/* Literal 26.  */
+    DW_OP_lit27 = 0x4b,		/* Literal 27.  */
+    DW_OP_lit28 = 0x4c,		/* Literal 28.  */
+    DW_OP_lit29 = 0x4d,		/* Literal 29.  */
+    DW_OP_lit30 = 0x4e,		/* Literal 30.  */
+    DW_OP_lit31 = 0x4f,		/* Literal 31.  */
+    DW_OP_reg0 = 0x50,		/* Register 0.  */
+    DW_OP_reg1 = 0x51,		/* Register 1.  */
+    DW_OP_reg2 = 0x52,		/* Register 2.  */
+    DW_OP_reg3 = 0x53,		/* Register 3.  */
+    DW_OP_reg4 = 0x54,		/* Register 4.  */
+    DW_OP_reg5 = 0x55,		/* Register 5.  */
+    DW_OP_reg6 = 0x56,		/* Register 6.  */
+    DW_OP_reg7 = 0x57,		/* Register 7.  */
+    DW_OP_reg8 = 0x58,		/* Register 8.  */
+    DW_OP_reg9 = 0x59,		/* Register 9.  */
+    DW_OP_reg10 = 0x5a,		/* Register 10.  */
+    DW_OP_reg11 = 0x5b,		/* Register 11.  */
+    DW_OP_reg12 = 0x5c,		/* Register 12.  */
+    DW_OP_reg13 = 0x5d,		/* Register 13.  */
+    DW_OP_reg14 = 0x5e,		/* Register 14.  */
+    DW_OP_reg15 = 0x5f,		/* Register 15.  */
+    DW_OP_reg16 = 0x60,		/* Register 16.  */
+    DW_OP_reg17 = 0x61,		/* Register 17.  */
+    DW_OP_reg18 = 0x62,		/* Register 18.  */
+    DW_OP_reg19 = 0x63,		/* Register 19.  */
+    DW_OP_reg20 = 0x64,		/* Register 20.  */
+    DW_OP_reg21 = 0x65,		/* Register 21.  */
+    DW_OP_reg22 = 0x66,		/* Register 22.  */
+    DW_OP_reg23 = 0x67,		/* Register 24.  */
+    DW_OP_reg24 = 0x68,		/* Register 24.  */
+    DW_OP_reg25 = 0x69,		/* Register 25.  */
+    DW_OP_reg26 = 0x6a,		/* Register 26.  */
+    DW_OP_reg27 = 0x6b,		/* Register 27.  */
+    DW_OP_reg28 = 0x6c,		/* Register 28.  */
+    DW_OP_reg29 = 0x6d,		/* Register 29.  */
+    DW_OP_reg30 = 0x6e,		/* Register 30.  */
+    DW_OP_reg31 = 0x6f,		/* Register 31.  */
+    DW_OP_breg0 = 0x70,		/* Base register 0.  */
+    DW_OP_breg1 = 0x71,		/* Base register 1.  */
+    DW_OP_breg2 = 0x72,		/* Base register 2.  */
+    DW_OP_breg3 = 0x73,		/* Base register 3.  */
+    DW_OP_breg4 = 0x74,		/* Base register 4.  */
+    DW_OP_breg5 = 0x75,		/* Base register 5.  */
+    DW_OP_breg6 = 0x76,		/* Base register 6.  */
+    DW_OP_breg7 = 0x77,		/* Base register 7.  */
+    DW_OP_breg8 = 0x78,		/* Base register 8.  */
+    DW_OP_breg9 = 0x79,		/* Base register 9.  */
+    DW_OP_breg10 = 0x7a,	/* Base register 10.  */
+    DW_OP_breg11 = 0x7b,	/* Base register 11.  */
+    DW_OP_breg12 = 0x7c,	/* Base register 12.  */
+    DW_OP_breg13 = 0x7d,	/* Base register 13.  */
+    DW_OP_breg14 = 0x7e,	/* Base register 14.  */
+    DW_OP_breg15 = 0x7f,	/* Base register 15.  */
+    DW_OP_breg16 = 0x80,	/* Base register 16.  */
+    DW_OP_breg17 = 0x81,	/* Base register 17.  */
+    DW_OP_breg18 = 0x82,	/* Base register 18.  */
+    DW_OP_breg19 = 0x83,	/* Base register 19.  */
+    DW_OP_breg20 = 0x84,	/* Base register 20.  */
+    DW_OP_breg21 = 0x85,	/* Base register 21.  */
+    DW_OP_breg22 = 0x86,	/* Base register 22.  */
+    DW_OP_breg23 = 0x87,	/* Base register 23.  */
+    DW_OP_breg24 = 0x88,	/* Base register 24.  */
+    DW_OP_breg25 = 0x89,	/* Base register 25.  */
+    DW_OP_breg26 = 0x8a,	/* Base register 26.  */
+    DW_OP_breg27 = 0x8b,	/* Base register 27.  */
+    DW_OP_breg28 = 0x8c,	/* Base register 28.  */
+    DW_OP_breg29 = 0x8d,	/* Base register 29.  */
+    DW_OP_breg30 = 0x8e,	/* Base register 30.  */
+    DW_OP_breg31 = 0x8f,	/* Base register 31.  */
+    DW_OP_regx = 0x90,		/* Unsigned LEB128 register.  */
+    DW_OP_fbreg = 0x91,		/* Signed LEB128 offset.  */
+    DW_OP_bregx = 0x92,		/* ULEB128 register followed by SLEB128 off. */
+    DW_OP_piece = 0x93,		/* ULEB128 size of piece addressed. */
+    DW_OP_deref_size = 0x94,	/* 1-byte size of data retrieved.  */
+    DW_OP_xderef_size = 0x95,	/* 1-byte size of data retrieved.  */
+    DW_OP_nop = 0x96,
+    DW_OP_push_object_address = 0x97,
+    DW_OP_call2 = 0x98,
+    DW_OP_call4 = 0x99,
+    DW_OP_call_ref = 0x9a,
+    DW_OP_form_tls_address = 0x9b,/* TLS offset to address in current thread */
+    DW_OP_call_frame_cfa = 0x9c,/* CFA as determined by CFI.  */
+    DW_OP_bit_piece = 0x9d,	/* ULEB128 size and ULEB128 offset in bits.  */
+    DW_OP_implicit_value = 0x9e, /* DW_FORM_block follows opcode.  */
+    DW_OP_stack_value = 0x9f,	 /* No operands, special like DW_OP_piece.  */
+
+    DW_OP_implicit_pointer = 0xa0,
+    DW_OP_addrx = 0xa1,
+    DW_OP_constx = 0xa2,
+    DW_OP_entry_value = 0xa3,
+    DW_OP_const_type = 0xa4,
+    DW_OP_regval_type = 0xa5,
+    DW_OP_deref_type = 0xa6,
+    DW_OP_xderef_type = 0xa7,
+    DW_OP_convert = 0xa8,
+    DW_OP_reinterpret = 0xa9,
+
+    /* GNU extensions.  */
+    DW_OP_GNU_push_tls_address = 0xe0,
+    DW_OP_GNU_uninit = 0xf0,
+    DW_OP_GNU_encoded_addr = 0xf1,
+    DW_OP_GNU_implicit_pointer = 0xf2,
+    DW_OP_GNU_entry_value = 0xf3,
+    DW_OP_GNU_const_type = 0xf4,
+    DW_OP_GNU_regval_type = 0xf5,
+    DW_OP_GNU_deref_type = 0xf6,
+    DW_OP_GNU_convert = 0xf7,
+    DW_OP_GNU_reinterpret = 0xf9,
+    DW_OP_GNU_parameter_ref = 0xfa,
+
+    /* GNU Debug Fission extensions.  */
+    DW_OP_GNU_addr_index = 0xfb,
+    DW_OP_GNU_const_index = 0xfc,
+
+    DW_OP_GNU_variable_value = 0xfd,
+
+    DW_OP_lo_user = 0xe0,	/* Implementation-defined range start.  */
+    DW_OP_hi_user = 0xff	/* Implementation-defined range end.  */
+  };
+
+
+/* DWARF base type encodings.  */
+enum
+  {
+    DW_ATE_void = 0x0,
+    DW_ATE_address = 0x1,
+    DW_ATE_boolean = 0x2,
+    DW_ATE_complex_float = 0x3,
+    DW_ATE_float = 0x4,
+    DW_ATE_signed = 0x5,
+    DW_ATE_signed_char = 0x6,
+    DW_ATE_unsigned = 0x7,
+    DW_ATE_unsigned_char = 0x8,
+    DW_ATE_imaginary_float = 0x9,
+    DW_ATE_packed_decimal = 0xa,
+    DW_ATE_numeric_string = 0xb,
+    DW_ATE_edited = 0xc,
+    DW_ATE_signed_fixed = 0xd,
+    DW_ATE_unsigned_fixed = 0xe,
+    DW_ATE_decimal_float = 0xf,
+    DW_ATE_UTF = 0x10,
+    DW_ATE_UCS = 0x11,
+    DW_ATE_ASCII = 0x12,
+
+    DW_ATE_lo_user = 0x80,
+    DW_ATE_hi_user = 0xff
+  };
+
+
+/* DWARF decimal sign encodings.  */
+enum
+  {
+    DW_DS_unsigned = 1,
+    DW_DS_leading_overpunch = 2,
+    DW_DS_trailing_overpunch = 3,
+    DW_DS_leading_separate = 4,
+    DW_DS_trailing_separate = 5,
+  };
+
+
+/* DWARF endianity encodings.  */
+enum
+  {
+    DW_END_default = 0,
+    DW_END_big = 1,
+    DW_END_little = 2,
+
+    DW_END_lo_user = 0x40,
+    DW_END_hi_user = 0xff
+  };
+
+
+/* DWARF accessibility encodings.  */
+enum
+  {
+    DW_ACCESS_public = 1,
+    DW_ACCESS_protected = 2,
+    DW_ACCESS_private = 3
+  };
+
+
+/* DWARF visibility encodings.  */
+enum
+  {
+    DW_VIS_local = 1,
+    DW_VIS_exported = 2,
+    DW_VIS_qualified = 3
+  };
+
+
+/* DWARF virtuality encodings.  */
+enum
+  {
+    DW_VIRTUALITY_none = 0,
+    DW_VIRTUALITY_virtual = 1,
+    DW_VIRTUALITY_pure_virtual = 2
+  };
+
+
+/* DWARF language encodings.  */
+enum
+  {
+    DW_LANG_C89 = 0x0001,	     /* ISO C:1989 */
+    DW_LANG_C = 0x0002,		     /* C */
+    DW_LANG_Ada83 = 0x0003,	     /* ISO Ada:1983 */
+    DW_LANG_C_plus_plus	= 0x0004,    /* ISO C++:1998 */
+    DW_LANG_Cobol74 = 0x0005,	     /* ISO Cobol:1974 */
+    DW_LANG_Cobol85 = 0x0006,	     /* ISO Cobol:1985 */
+    DW_LANG_Fortran77 = 0x0007,	     /* ISO FORTRAN 77 */
+    DW_LANG_Fortran90 = 0x0008,	     /* ISO Fortran 90 */
+    DW_LANG_Pascal83 = 0x0009,	     /* ISO Pascal:1983 */
+    DW_LANG_Modula2 = 0x000a,	     /* ISO Modula-2:1996 */
+    DW_LANG_Java = 0x000b,	     /* Java */
+    DW_LANG_C99 = 0x000c,	     /* ISO C:1999 */
+    DW_LANG_Ada95 = 0x000d,	     /* ISO Ada:1995 */
+    DW_LANG_Fortran95 = 0x000e,	     /* ISO Fortran 95 */
+    DW_LANG_PLI = 0x000f,	     /* ISO PL/1:1976 */
+    DW_LANG_ObjC = 0x0010,	     /* Objective-C */
+    DW_LANG_ObjC_plus_plus = 0x0011, /* Objective-C++ */
+    DW_LANG_UPC = 0x0012,	     /* Unified Parallel C */
+    DW_LANG_D = 0x0013,		     /* D */
+    DW_LANG_Python = 0x0014,	     /* Python */
+    DW_LANG_OpenCL = 0x0015,	     /* OpenCL */
+    DW_LANG_Go = 0x0016,	     /* Go */
+    DW_LANG_Modula3 = 0x0017,	     /* Modula-3 */
+    DW_LANG_Haskell = 0x0018,	     /* Haskell */
+    DW_LANG_C_plus_plus_03 = 0x0019, /* ISO C++:2003 */
+    DW_LANG_C_plus_plus_11 = 0x001a, /* ISO C++:2011 */
+    DW_LANG_OCaml = 0x001b,	     /* OCaml */
+    DW_LANG_Rust = 0x001c,	     /* Rust */
+    DW_LANG_C11 = 0x001d,	     /* ISO C:2011 */
+    DW_LANG_Swift = 0x001e,	     /* Swift */
+    DW_LANG_Julia = 0x001f,	     /* Julia */
+    DW_LANG_Dylan = 0x0020,	     /* Dylan */
+    DW_LANG_C_plus_plus_14 = 0x0021, /* ISO C++:2014 */
+    DW_LANG_Fortran03 = 0x0022,	     /* ISO/IEC 1539-1:2004 */
+    DW_LANG_Fortran08 = 0x0023,	     /* ISO/IEC 1539-1:2010 */
+    DW_LANG_RenderScript = 0x0024,   /* RenderScript Kernal Language */
+    DW_LANG_BLISS = 0x0025,	     /* BLISS */
+
+    DW_LANG_lo_user = 0x8000,
+    DW_LANG_Mips_Assembler = 0x8001, /* Assembler */
+    DW_LANG_hi_user = 0xffff
+  };
+
+/* Old (typo) '1' != 'I'.  */
+#define DW_LANG_PL1 DW_LANG_PLI
+
+/* DWARF identifier case encodings.  */
+enum
+  {
+    DW_ID_case_sensitive = 0,
+    DW_ID_up_case = 1,
+    DW_ID_down_case = 2,
+    DW_ID_case_insensitive = 3
+  };
+
+
+/* DWARF calling conventions encodings.
+   Used as values of DW_AT_calling_convention for subroutines
+   (normal, program or nocall) or structures, unions and class types
+   (normal, reference or value).  */
+enum
+  {
+    DW_CC_normal = 0x1,
+    DW_CC_program = 0x2,
+    DW_CC_nocall = 0x3,
+    DW_CC_pass_by_reference = 0x4,
+    DW_CC_pass_by_value = 0x5,
+    DW_CC_lo_user = 0x40,
+    DW_CC_hi_user = 0xff
+  };
+
+
+/* DWARF inline encodings.  */
+enum
+  {
+    DW_INL_not_inlined = 0,
+    DW_INL_inlined = 1,
+    DW_INL_declared_not_inlined = 2,
+    DW_INL_declared_inlined = 3
+  };
+
+
+/* DWARF ordering encodings.  */
+enum
+  {
+    DW_ORD_row_major = 0,
+    DW_ORD_col_major = 1
+  };
+
+
+/* DWARF discriminant descriptor encodings.  */
+enum
+  {
+    DW_DSC_label = 0,
+    DW_DSC_range = 1
+  };
+
+/* DWARF defaulted member function encodings.  */
+enum
+  {
+    DW_DEFAULTED_no = 0,
+    DW_DEFAULTED_in_class = 1,
+    DW_DEFAULTED_out_of_class = 2
+  };
+
+/* DWARF line content descriptions.  */
+enum
+  {
+    DW_LNCT_path = 0x1,
+    DW_LNCT_directory_index = 0x2,
+    DW_LNCT_timestamp = 0x3,
+    DW_LNCT_size = 0x4,
+    DW_LNCT_MD5 = 0x5,
+    DW_LNCT_lo_user = 0x2000,
+    DW_LNCT_hi_user = 0x3fff
+  };
+
+/* DWARF standard opcode encodings.  */
+enum
+  {
+    DW_LNS_copy = 1,
+    DW_LNS_advance_pc = 2,
+    DW_LNS_advance_line = 3,
+    DW_LNS_set_file = 4,
+    DW_LNS_set_column = 5,
+    DW_LNS_negate_stmt = 6,
+    DW_LNS_set_basic_block = 7,
+    DW_LNS_const_add_pc = 8,
+    DW_LNS_fixed_advance_pc = 9,
+    DW_LNS_set_prologue_end = 10,
+    DW_LNS_set_epilogue_begin = 11,
+    DW_LNS_set_isa = 12
+  };
+
+
+/* DWARF extended opcode encodings.  */
+enum
+  {
+    DW_LNE_end_sequence = 1,
+    DW_LNE_set_address = 2,
+    DW_LNE_define_file = 3,
+    DW_LNE_set_discriminator = 4,
+
+    DW_LNE_lo_user = 128,
+
+    DW_LNE_NVIDIA_inlined_call = 144,
+    DW_LNE_NVIDIA_set_function_name = 145,
+
+    DW_LNE_hi_user = 255
+  };
+
+
+/* DWARF macinfo type encodings.  */
+enum
+  {
+    DW_MACINFO_define = 1,
+    DW_MACINFO_undef = 2,
+    DW_MACINFO_start_file = 3,
+    DW_MACINFO_end_file = 4,
+    DW_MACINFO_vendor_ext = 255
+  };
+
+
+/* DWARF debug_macro type encodings.  */
+enum
+  {
+    DW_MACRO_define = 0x01,
+    DW_MACRO_undef = 0x02,
+    DW_MACRO_start_file = 0x03,
+    DW_MACRO_end_file = 0x04,
+    DW_MACRO_define_strp = 0x05,
+    DW_MACRO_undef_strp = 0x06,
+    DW_MACRO_import = 0x07,
+    DW_MACRO_define_sup = 0x08,
+    DW_MACRO_undef_sup = 0x09,
+    DW_MACRO_import_sup = 0x0a,
+    DW_MACRO_define_strx = 0x0b,
+    DW_MACRO_undef_strx = 0x0c,
+    DW_MACRO_lo_user = 0xe0,
+    DW_MACRO_hi_user = 0xff
+  };
+
+/* Old GNU extension names for DWARF5 debug_macro type encodings.
+   There are no equivalents for the supplementary object file (sup)
+   and indirect string references (strx).  */
+#define DW_MACRO_GNU_define		 DW_MACRO_define
+#define DW_MACRO_GNU_undef		 DW_MACRO_undef
+#define DW_MACRO_GNU_start_file		 DW_MACRO_start_file
+#define DW_MACRO_GNU_end_file		 DW_MACRO_end_file
+#define DW_MACRO_GNU_define_indirect	 DW_MACRO_define_strp
+#define DW_MACRO_GNU_undef_indirect	 DW_MACRO_undef_strp
+#define DW_MACRO_GNU_transparent_include DW_MACRO_import
+#define DW_MACRO_GNU_lo_user		 DW_MACRO_lo_user
+#define DW_MACRO_GNU_hi_user		 DW_MACRO_hi_user
+
+
+/* Range list entry encoding.  */
+enum
+  {
+    DW_RLE_end_of_list = 0x0,
+    DW_RLE_base_addressx = 0x1,
+    DW_RLE_startx_endx = 0x2,
+    DW_RLE_startx_length = 0x3,
+    DW_RLE_offset_pair = 0x4,
+    DW_RLE_base_address = 0x5,
+    DW_RLE_start_end = 0x6,
+    DW_RLE_start_length = 0x7
+  };
+
+
+/* Location list entry encoding.  */
+enum
+  {
+    DW_LLE_end_of_list = 0x0,
+    DW_LLE_base_addressx = 0x1,
+    DW_LLE_startx_endx = 0x2,
+    DW_LLE_startx_length = 0x3,
+    DW_LLE_offset_pair = 0x4,
+    DW_LLE_default_location = 0x5,
+    DW_LLE_base_address = 0x6,
+    DW_LLE_start_end = 0x7,
+    DW_LLE_start_length = 0x8
+  };
+
+
+/* GNU DebugFission list entry encodings (.debug_loc.dwo).  */
+enum
+  {
+    DW_LLE_GNU_end_of_list_entry = 0x0,
+    DW_LLE_GNU_base_address_selection_entry = 0x1,
+    DW_LLE_GNU_start_end_entry = 0x2,
+    DW_LLE_GNU_start_length_entry = 0x3,
+
+    // http://www.fsfla.org/~lxoliva/papers/sfn/dwarf6-sfn-lvu.txt
+    // https://dwarfstd.org/ShowIssue.php?issue=170427.1
+    DW_LLE_GNU_view_pair = 0x9
+  };
+
+/* DWARF5 package file section identifiers.  */
+enum
+  {
+    DW_SECT_INFO = 1,
+    DW_SECT_TYPES = 2, /* Only DWARF4 GNU DebugFission. Reserved in DWARF5.  */
+    DW_SECT_ABBREV = 3,
+    DW_SECT_LINE = 4,
+    DW_SECT_LOCLISTS = 5,
+    DW_SECT_STR_OFFSETS = 6,
+    DW_SECT_MACRO = 7,
+    DW_SECT_RNGLISTS = 8,
+  };
+
+
+/* DWARF call frame instruction encodings.  */
+enum
+  {
+    DW_CFA_advance_loc = 0x40,
+    DW_CFA_offset = 0x80,
+    DW_CFA_restore = 0xc0,
+    DW_CFA_extended = 0,
+
+    DW_CFA_nop = 0x00,
+    DW_CFA_set_loc = 0x01,
+    DW_CFA_advance_loc1 = 0x02,
+    DW_CFA_advance_loc2 = 0x03,
+    DW_CFA_advance_loc4 = 0x04,
+    DW_CFA_offset_extended = 0x05,
+    DW_CFA_restore_extended = 0x06,
+    DW_CFA_undefined = 0x07,
+    DW_CFA_same_value = 0x08,
+    DW_CFA_register = 0x09,
+    DW_CFA_remember_state = 0x0a,
+    DW_CFA_restore_state = 0x0b,
+    DW_CFA_def_cfa = 0x0c,
+    DW_CFA_def_cfa_register = 0x0d,
+    DW_CFA_def_cfa_offset = 0x0e,
+    DW_CFA_def_cfa_expression = 0x0f,
+    DW_CFA_expression = 0x10,
+    DW_CFA_offset_extended_sf = 0x11,
+    DW_CFA_def_cfa_sf = 0x12,
+    DW_CFA_def_cfa_offset_sf = 0x13,
+    DW_CFA_val_offset = 0x14,
+    DW_CFA_val_offset_sf = 0x15,
+    DW_CFA_val_expression = 0x16,
+
+    DW_CFA_low_user = 0x1c,
+    DW_CFA_MIPS_advance_loc8 = 0x1d,
+    DW_CFA_GNU_window_save = 0x2d,
+    DW_CFA_AARCH64_negate_ra_state = 0x2d,
+    DW_CFA_GNU_args_size = 0x2e,
+    DW_CFA_GNU_negative_offset_extended = 0x2f,
+    DW_CFA_high_user = 0x3f
+  };
+
+/* ID indicating CIE as opposed to FDE in .debug_frame.  */
+enum
+  {
+    DW_CIE_ID_32 = 0xffffffffU,		 /* In 32-bit format CIE header.  */
+    DW_CIE_ID_64 = 0xffffffffffffffffULL /* In 64-bit format CIE header.  */
+  };
+
+
+/* Information for GNU unwind information.  */
+enum
+  {
+    DW_EH_PE_absptr = 0x00,
+    DW_EH_PE_omit = 0xff,
+
+    /* FDE data encoding.  */
+    DW_EH_PE_uleb128 = 0x01,
+    DW_EH_PE_udata2 = 0x02,
+    DW_EH_PE_udata4 = 0x03,
+    DW_EH_PE_udata8 = 0x04,
+    DW_EH_PE_sleb128 = 0x09,
+    DW_EH_PE_sdata2 = 0x0a,
+    DW_EH_PE_sdata4 = 0x0b,
+    DW_EH_PE_sdata8 = 0x0c,
+    DW_EH_PE_signed = 0x08,
+
+    /* FDE flags.  */
+    DW_EH_PE_pcrel = 0x10,
+    DW_EH_PE_textrel = 0x20,
+    DW_EH_PE_datarel = 0x30,
+    DW_EH_PE_funcrel = 0x40,
+    DW_EH_PE_aligned = 0x50,
+
+    DW_EH_PE_indirect = 0x80
+  };
+
+
+/* DWARF XXX.  */
+#define DW_ADDR_none	0
+
+/* Section 7.2.2 of the DWARF3 specification defines a range of escape
+   codes that can appear in the length field of certain DWARF structures.
+
+   These defines enumerate the minimum and maximum values of this range.
+   Currently only the maximum value is used (to indicate that 64-bit
+   values are going to be used in the dwarf data that accompanies the
+   structure).  The other values are reserved.
+
+   Note: There is a typo in DWARF3 spec (published Dec 20, 2005).  In
+   sections 7.4, 7.5.1, 7.19, 7.20 the minimum escape code is referred to
+   as 0xffffff00 whereas in fact it should be 0xfffffff0.  */
+#define DWARF3_LENGTH_MIN_ESCAPE_CODE 0xfffffff0u
+#define DWARF3_LENGTH_MAX_ESCAPE_CODE 0xffffffffu
+#define DWARF3_LENGTH_64_BIT          DWARF3_LENGTH_MAX_ESCAPE_CODE
+
+#endif	/* dwarf.h */
diff --git a/libdw/dwarf_abbrev_hash.c b/libdw/dwarf_abbrev_hash.c
new file mode 100644
index 0000000..c254814
--- /dev/null
+++ b/libdw/dwarf_abbrev_hash.c
@@ -0,0 +1,45 @@
+/* Implementation of hash table for DWARF .debug_abbrev section content.
+   Copyright (C) 2000-2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "dwarf_sig8_hash.h"
+#define NO_UNDEF
+#include "libdwP.h"
+
+#define next_prime __libdwarf_next_prime
+extern size_t next_prime (size_t) attribute_hidden;
+
+#include <dynamicsizehash_concurrent.c>
+
+#undef next_prime
+#define next_prime attribute_hidden __libdwarf_next_prime
+#include "../lib/next_prime.c"
diff --git a/libdw/dwarf_abbrev_hash.h b/libdw/dwarf_abbrev_hash.h
new file mode 100644
index 0000000..a368c59
--- /dev/null
+++ b/libdw/dwarf_abbrev_hash.h
@@ -0,0 +1,38 @@
+/* Hash table for DWARF .debug_abbrev section content.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DWARF_ABBREV_HASH_H
+#define _DWARF_ABBREV_HASH_H	1
+
+#define NAME Dwarf_Abbrev_Hash
+#define TYPE Dwarf_Abbrev *
+
+#include <dynamicsizehash_concurrent.h>
+
+#endif	/* dwarf_abbrev_hash.h */
diff --git a/libdw/dwarf_abbrevhaschildren.c b/libdw/dwarf_abbrevhaschildren.c
new file mode 100644
index 0000000..0f17c7e
--- /dev/null
+++ b/libdw/dwarf_abbrevhaschildren.c
@@ -0,0 +1,43 @@
+/* Return true if abbreviation is children flag set.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_abbrevhaschildren (Dwarf_Abbrev *abbrev)
+{
+  return abbrev == NULL ? -1 : abbrev->has_children;
+}
diff --git a/libdw/dwarf_addrdie.c b/libdw/dwarf_addrdie.c
new file mode 100644
index 0000000..48a1aae
--- /dev/null
+++ b/libdw/dwarf_addrdie.c
@@ -0,0 +1,51 @@
+/* Return CU DIE containing given address.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr, Dwarf_Die *result)
+{
+  Dwarf_Aranges *aranges;
+  size_t naranges;
+  Dwarf_Off off;
+
+  if (__libdw_getdieranges (dbg, &aranges, &naranges) != 0
+      || INTUSE(dwarf_getarangeinfo) (INTUSE(dwarf_getarange_addr) (aranges,
+								    addr),
+				      NULL, NULL, &off) != 0)
+    return NULL;
+
+  return INTUSE(dwarf_offdie) (dbg, off, result);
+}
diff --git a/libdw/dwarf_aggregate_size.c b/libdw/dwarf_aggregate_size.c
new file mode 100644
index 0000000..8216ae4
--- /dev/null
+++ b/libdw/dwarf_aggregate_size.c
@@ -0,0 +1,256 @@
+/* Compute size of an aggregate type from DWARF.
+   Copyright (C) 2010, 2014, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+static Dwarf_Die *
+get_type (Dwarf_Die *die, Dwarf_Attribute *attr_mem, Dwarf_Die *type_mem)
+{
+  Dwarf_Die *type = INTUSE(dwarf_formref_die)
+    (INTUSE(dwarf_attr_integrate) (die, DW_AT_type, attr_mem), type_mem);
+
+  if (type == NULL || INTUSE(dwarf_peel_type) (type, type) != 0)
+    return NULL;
+
+  return type;
+}
+
+static int aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
+			   Dwarf_Die *type_mem, int depth);
+
+static int
+array_size (Dwarf_Die *die, Dwarf_Word *size,
+	    Dwarf_Attribute *attr_mem, int depth)
+{
+  Dwarf_Word eltsize;
+  Dwarf_Die type_mem, aggregate_type_mem;
+  if (aggregate_size (get_type (die, attr_mem, &type_mem), &eltsize,
+		      &aggregate_type_mem, depth) != 0)
+      return -1;
+
+  /* An array can have DW_TAG_subrange_type or DW_TAG_enumeration_type
+     children instead that give the size of each dimension.  */
+
+  Dwarf_Die child;
+  if (INTUSE(dwarf_child) (die, &child) != 0)
+    return -1;
+
+  bool any = false;
+  Dwarf_Word count_total = 1;
+  do
+    {
+      Dwarf_Word count;
+      switch (INTUSE(dwarf_tag) (&child))
+	{
+	case DW_TAG_subrange_type:
+	  /* This has either DW_AT_count or DW_AT_upper_bound.  */
+	  if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_count,
+					    attr_mem) != NULL)
+	    {
+	      if (INTUSE(dwarf_formudata) (attr_mem, &count) != 0)
+		return -1;
+	    }
+	  else
+	    {
+	      bool is_signed = true;
+	      if (INTUSE(dwarf_attr) (get_type (&child, attr_mem, &type_mem),
+				      DW_AT_encoding, attr_mem) != NULL)
+		{
+		  Dwarf_Word encoding;
+		  if (INTUSE(dwarf_formudata) (attr_mem, &encoding) == 0)
+		    is_signed = (encoding == DW_ATE_signed
+				 || encoding == DW_ATE_signed_char);
+		}
+
+	      Dwarf_Sword upper;
+	      Dwarf_Sword lower;
+	      if (is_signed)
+		{
+		  if (INTUSE(dwarf_formsdata) (INTUSE(dwarf_attr_integrate)
+					       (&child, DW_AT_upper_bound,
+						attr_mem), &upper) != 0)
+		    return -1;
+		}
+	      else
+		{
+		  Dwarf_Word unsigned_upper;
+		  if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+					       (&child, DW_AT_upper_bound,
+						attr_mem), &unsigned_upper) != 0)
+		    return -1;
+		  upper = unsigned_upper;
+		}
+
+	      /* Having DW_AT_lower_bound is optional.  */
+	      if (INTUSE(dwarf_attr_integrate) (&child, DW_AT_lower_bound,
+						attr_mem) != NULL)
+		{
+		  if (is_signed)
+		    {
+		      if (INTUSE(dwarf_formsdata) (attr_mem, &lower) != 0)
+			return -1;
+		    }
+		  else
+		    {
+		      Dwarf_Word unsigned_lower;
+		      if (INTUSE(dwarf_formudata) (attr_mem, &unsigned_lower) != 0)
+			return -1;
+		      lower = unsigned_lower;
+		    }
+		}
+	      else
+		{
+		  Dwarf_Die cu = CUDIE (die->cu);
+		  int lang = INTUSE(dwarf_srclang) (&cu);
+		  if (lang == -1
+		      || INTUSE(dwarf_default_lower_bound) (lang, &lower) != 0)
+		    return -1;
+		}
+	      if (unlikely (lower > upper))
+		return -1;
+	      count = upper - lower + 1;
+	    }
+	  break;
+
+	case DW_TAG_enumeration_type:
+	  /* We have to find the DW_TAG_enumerator child with the
+	     highest value to know the array's element count.  */
+	  count = 0;
+	  Dwarf_Die enum_child;
+	  int has_children = INTUSE(dwarf_child) (die, &enum_child);
+	  if (has_children < 0)
+	    return -1;
+	  if (has_children > 0)
+	    do
+	      if (INTUSE(dwarf_tag) (&enum_child) == DW_TAG_enumerator)
+		{
+		  Dwarf_Word value;
+		  if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+					       (&enum_child, DW_AT_const_value,
+						attr_mem), &value) != 0)
+		    return -1;
+		  if (value >= count)
+		    count = value + 1;
+		}
+	    while (INTUSE(dwarf_siblingof) (&enum_child, &enum_child) > 0);
+	  break;
+
+	default:
+	  continue;
+	}
+
+      count_total *= count;
+
+      any = true;
+    }
+  while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
+
+  if (!any)
+    return -1;
+
+  /* This is a subrange_type or enumeration_type and we've set COUNT.
+     Now determine the stride for this array.  */
+  Dwarf_Word stride = eltsize;
+  if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_stride,
+                                    attr_mem) != NULL)
+    {
+      if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
+        return -1;
+    }
+  else if (INTUSE(dwarf_attr_integrate) (die, DW_AT_bit_stride,
+                                         attr_mem) != NULL)
+    {
+      if (INTUSE(dwarf_formudata) (attr_mem, &stride) != 0)
+        return -1;
+      if (stride % 8) 	/* XXX maybe compute in bits? */
+        return -1;
+      stride /= 8;
+    }
+
+  *size = count_total * stride;
+  return 0;
+}
+
+static int
+aggregate_size (Dwarf_Die *die, Dwarf_Word *size,
+		Dwarf_Die *type_mem, int depth)
+{
+  Dwarf_Attribute attr_mem;
+
+/* Arrays of arrays of subrange types of arrays... Don't recurse too deep.  */
+#define MAX_DEPTH 256
+  if (die == NULL || depth++ >= MAX_DEPTH)
+    return -1;
+
+  if (INTUSE(dwarf_attr_integrate) (die, DW_AT_byte_size, &attr_mem) != NULL)
+    return INTUSE(dwarf_formudata) (&attr_mem, size);
+
+  switch (INTUSE(dwarf_tag) (die))
+    {
+    case DW_TAG_subrange_type:
+      {
+	Dwarf_Die aggregate_type_mem;
+	return aggregate_size (get_type (die, &attr_mem, type_mem),
+			       size, &aggregate_type_mem, depth);
+      }
+
+    case DW_TAG_array_type:
+      return array_size (die, size, &attr_mem, depth);
+
+    /* Assume references and pointers have pointer size if not given an
+       explicit DW_AT_byte_size.  */
+    case DW_TAG_pointer_type:
+    case DW_TAG_reference_type:
+    case DW_TAG_rvalue_reference_type:
+      *size = die->cu->address_size;
+      return 0;
+    }
+
+  /* Most types must give their size directly.  */
+  return -1;
+}
+
+NEW_VERSION (dwarf_aggregate_size, ELFUTILS_0.161)
+int
+dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size)
+{
+  Dwarf_Die die_mem, type_mem;
+
+  if (INTUSE (dwarf_peel_type) (die, &die_mem) != 0)
+    return -1;
+
+  return aggregate_size (&die_mem, size, &type_mem, 0);
+}
+NEW_INTDEF (dwarf_aggregate_size)
+OLD_VERSION (dwarf_aggregate_size, ELFUTILS_0.144)
diff --git a/libdw/dwarf_arrayorder.c b/libdw/dwarf_arrayorder.c
new file mode 100644
index 0000000..782e075
--- /dev/null
+++ b/libdw/dwarf_arrayorder.c
@@ -0,0 +1,49 @@
+/* Return array order attribute of DIE.
+   Copyright (C) 2003, 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_arrayorder, ELFUTILS_0.143)
+int
+dwarf_arrayorder (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word value;
+
+  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+				  (die, DW_AT_ordering, &attr_mem),
+				  &value) == 0 ? (int) value : -1;
+}
+OLD_VERSION (dwarf_arrayorder, ELFUTILS_0.122)
diff --git a/libdw/dwarf_attr.c b/libdw/dwarf_attr.c
new file mode 100644
index 0000000..db8acfe
--- /dev/null
+++ b/libdw/dwarf_attr.c
@@ -0,0 +1,52 @@
+/* Return specific DWARF attribute of a DIE.
+   Copyright (C) 2003, 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Attribute *
+dwarf_attr (Dwarf_Die *die, unsigned int search_name, Dwarf_Attribute *result)
+{
+  if (die == NULL)
+    return NULL;
+
+  /* Search for the attribute with the given name.  */
+  result->valp = __libdw_find_attr (die, search_name, &result->code,
+				    &result->form);
+  /* Always fill in the CU information.  */
+  result->cu = die->cu;
+
+  return result->valp != NULL && result->code == search_name ? result : NULL;
+}
+INTDEF(dwarf_attr)
diff --git a/libdw/dwarf_attr_integrate.c b/libdw/dwarf_attr_integrate.c
new file mode 100644
index 0000000..fc06863
--- /dev/null
+++ b/libdw/dwarf_attr_integrate.c
@@ -0,0 +1,73 @@
+/* Return specific DWARF attribute of a DIE, integrating indirections.
+   Copyright (C) 2005, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+Dwarf_Attribute *
+dwarf_attr_integrate (Dwarf_Die *die, unsigned int search_name,
+		      Dwarf_Attribute *result)
+{
+  Dwarf_Die die_mem;
+  int chain = 16; /* Largest DIE ref chain we will follow.  */
+  do
+    {
+      Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, search_name, result);
+      if (attr != NULL)
+	return attr;
+
+      attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin, result);
+      if (attr == NULL)
+	attr = INTUSE(dwarf_attr) (die, DW_AT_specification, result);
+      if (attr == NULL)
+	break;
+
+      die = INTUSE(dwarf_formref_die) (attr, &die_mem);
+    }
+  while (die != NULL && chain-- != 0);
+
+  /* Not NULL if it didn't have abstract_origin and specification
+     attributes.  If it is a split CU then see if the skeleton
+     has it.  */
+  if (die != NULL && is_cudie (die)
+      && die->cu->unit_type == DW_UT_split_compile)
+    {
+      Dwarf_CU *skel_cu = __libdw_find_split_unit (die->cu);
+      if (skel_cu != NULL)
+	{
+	  Dwarf_Die skel_die = CUDIE (skel_cu);
+	  return INTUSE(dwarf_attr) (&skel_die, search_name, result);
+	}
+    }
+  return NULL;
+}
+INTDEF (dwarf_attr_integrate)
diff --git a/libdw/dwarf_begin.c b/libdw/dwarf_begin.c
new file mode 100644
index 0000000..19d16e5
--- /dev/null
+++ b/libdw/dwarf_begin.c
@@ -0,0 +1,99 @@
+/* Create descriptor from file descriptor for processing file.
+   Copyright (C) 2002, 2003, 2004, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <sys/stat.h>
+
+#include <libdwP.h>
+
+
+Dwarf *
+dwarf_begin (int fd, Dwarf_Cmd cmd)
+{
+  Elf *elf;
+  Elf_Cmd elfcmd;
+  Dwarf *result = NULL;
+
+  switch (cmd)
+    {
+    case DWARF_C_READ:
+      elfcmd = ELF_C_READ_MMAP;
+      break;
+    case DWARF_C_WRITE:
+      elfcmd = ELF_C_WRITE;
+      break;
+    case DWARF_C_RDWR:
+      elfcmd = ELF_C_RDWR;
+      break;
+    default:
+      /* No valid mode.  */
+      __libdw_seterrno (DWARF_E_INVALID_CMD);
+      return NULL;
+    }
+
+  /* We have to call `elf_version' here since the user might have not
+     done it or initialized libelf with a different version.  This
+     would break libdwarf since we are using the ELF data structures
+     in a certain way.  */
+  elf_version (EV_CURRENT);
+
+  /* Get an ELF descriptor.  */
+  elf = elf_begin (fd, elfcmd, NULL);
+  if (elf == NULL)
+    {
+      /* Test why the `elf_begin" call failed.  */
+      struct stat st;
+
+      if (fstat (fd, &st) == 0 && ! S_ISREG (st.st_mode))
+	__libdw_seterrno (DWARF_E_NO_REGFILE);
+      else if (errno == EBADF)
+	__libdw_seterrno (DWARF_E_INVALID_FILE);
+      else
+	__libdw_seterrno (DWARF_E_IO_ERROR);
+    }
+  else
+    {
+      /* Do the real work now that we have an ELF descriptor.  */
+      result = INTUSE(dwarf_begin_elf) (elf, cmd, NULL);
+
+      /* If this failed, free the resources.  */
+      if (result == NULL)
+	elf_end (elf);
+      else
+	result->free_elf = true;
+    }
+
+  return result;
+}
+INTDEF(dwarf_begin)
diff --git a/libdw/dwarf_begin_elf.c b/libdw/dwarf_begin_elf.c
new file mode 100644
index 0000000..ca2b7e2
--- /dev/null
+++ b/libdw/dwarf_begin_elf.c
@@ -0,0 +1,621 @@
+/* Create descriptor from ELF descriptor for processing file.
+   Copyright (C) 2002-2011, 2014, 2015, 2017, 2018 Red Hat, Inc.
+   Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "libelfP.h"
+#include "libdwP.h"
+
+
+/* Section names.  (Note .debug_str_offsets is the largest 19 chars.)  */
+static const char dwarf_scnnames[IDX_last][19] =
+{
+  [IDX_debug_info] = ".debug_info",
+  [IDX_debug_types] = ".debug_types",
+  [IDX_debug_abbrev] = ".debug_abbrev",
+  [IDX_debug_addr] = ".debug_addr",
+  [IDX_debug_aranges] = ".debug_aranges",
+  [IDX_debug_line] = ".debug_line",
+  [IDX_debug_line_str] = ".debug_line_str",
+  [IDX_debug_frame] = ".debug_frame",
+  [IDX_debug_loc] = ".debug_loc",
+  [IDX_debug_loclists] = ".debug_loclists",
+  [IDX_debug_pubnames] = ".debug_pubnames",
+  [IDX_debug_str] = ".debug_str",
+  [IDX_debug_str_offsets] = ".debug_str_offsets",
+  [IDX_debug_macinfo] = ".debug_macinfo",
+  [IDX_debug_macro] = ".debug_macro",
+  [IDX_debug_ranges] = ".debug_ranges",
+  [IDX_debug_rnglists] = ".debug_rnglists",
+  [IDX_debug_cu_index] = ".debug_cu_index",
+  [IDX_debug_tu_index] = ".debug_tu_index",
+  [IDX_gnu_debugaltlink] = ".gnu_debugaltlink"
+};
+#define ndwarf_scnnames (sizeof (dwarf_scnnames) / sizeof (dwarf_scnnames[0]))
+
+/* Map from section index to string section index.
+   Non-string sections should have STR_SCN_IDX_last.  */
+static const enum string_section_index scn_to_string_section_idx[IDX_last] =
+{
+  [IDX_debug_info] = STR_SCN_IDX_last,
+  [IDX_debug_types] = STR_SCN_IDX_last,
+  [IDX_debug_abbrev] = STR_SCN_IDX_last,
+  [IDX_debug_addr] = STR_SCN_IDX_last,
+  [IDX_debug_aranges] = STR_SCN_IDX_last,
+  [IDX_debug_line] = STR_SCN_IDX_last,
+  [IDX_debug_line_str] = STR_SCN_IDX_debug_line_str,
+  [IDX_debug_frame] = STR_SCN_IDX_last,
+  [IDX_debug_loc] = STR_SCN_IDX_last,
+  [IDX_debug_loclists] = STR_SCN_IDX_last,
+  [IDX_debug_pubnames] = STR_SCN_IDX_last,
+  [IDX_debug_str] = STR_SCN_IDX_debug_str,
+  [IDX_debug_str_offsets] = STR_SCN_IDX_last,
+  [IDX_debug_macinfo] = STR_SCN_IDX_last,
+  [IDX_debug_macro] = STR_SCN_IDX_last,
+  [IDX_debug_ranges] = STR_SCN_IDX_last,
+  [IDX_debug_rnglists] = STR_SCN_IDX_last,
+  [IDX_debug_cu_index] = STR_SCN_IDX_last,
+  [IDX_debug_tu_index] = STR_SCN_IDX_last,
+  [IDX_gnu_debugaltlink] = STR_SCN_IDX_last
+};
+
+static enum dwarf_type
+scn_dwarf_type (Dwarf *result, size_t shstrndx, Elf_Scn *scn)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    return TYPE_UNKNOWN;
+
+  const char *scnname = elf_strptr (result->elf, shstrndx,
+				    shdr->sh_name);
+  if (scnname != NULL)
+    {
+      if (startswith (scnname, ".gnu.debuglto_.debug"))
+	return TYPE_GNU_LTO;
+      else if (strcmp (scnname, ".debug_cu_index") == 0
+	       || strcmp (scnname, ".debug_tu_index") == 0
+	       || strcmp (scnname, ".zdebug_cu_index") == 0
+	       || strcmp (scnname, ".zdebug_tu_index") == 0)
+	return TYPE_DWO;
+      else if (startswith (scnname, ".debug_") || startswith (scnname, ".zdebug_"))
+	{
+	  size_t len = strlen (scnname);
+	  if (strcmp (scnname + len - 4, ".dwo") == 0)
+	    return TYPE_DWO;
+	  else
+	    return TYPE_PLAIN;
+	}
+    }
+  return TYPE_UNKNOWN;
+}
+static Dwarf *
+check_section (Dwarf *result, size_t shstrndx, Elf_Scn *scn, bool inscngrp)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr;
+
+  /* Get the section header data.  */
+  shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    /* We may read /proc/PID/mem with only program headers mapped and section
+       headers out of the mapped pages.  */
+    goto err;
+
+  /* Ignore any SHT_NOBITS sections.  Debugging sections should not
+     have been stripped, but in case of a corrupt file we won't try
+     to look at the missing data.  */
+  if (unlikely (shdr->sh_type == SHT_NOBITS))
+    return result;
+
+  /* Make sure the section is part of a section group only iff we
+     really need it.  If we are looking for the global (= non-section
+     group debug info) we have to ignore all the info in section
+     groups.  If we are looking into a section group we cannot look at
+     a section which isn't part of the section group.  */
+  if (! inscngrp && (shdr->sh_flags & SHF_GROUP) != 0)
+    /* Ignore the section.  */
+    return result;
+
+
+  /* We recognize the DWARF section by their names.  This is not very
+     safe and stable but the best we can do.  */
+  const char *scnname = elf_strptr (result->elf, shstrndx,
+				    shdr->sh_name);
+  if (scnname == NULL)
+    {
+      /* The section name must be valid.  Otherwise is the ELF file
+	 invalid.  */
+    err:
+      Dwarf_Sig8_Hash_free (&result->sig8_hash);
+      __libdw_seterrno (DWARF_E_INVALID_ELF);
+      free (result);
+      return NULL;
+    }
+
+  /* Recognize the various sections.  Most names start with .debug_.
+     They might be compressed (and start with .z).  Or end with .dwo
+     for split dwarf sections.  Or start with .gnu.debuglto_ for
+     LTO debug sections.  We should only use one consistent set at
+     a time.  We prefer PLAIN over DWO over LTO.  */
+  size_t cnt;
+  bool gnu_compressed = false;
+  for (cnt = 0; cnt < ndwarf_scnnames; ++cnt)
+    {
+      /* .debug_cu_index and .debug_tu_index don't have a .dwo suffix,
+	 but they are for DWO.  */
+      if (result->type != TYPE_DWO
+	  && (cnt == IDX_debug_cu_index || cnt == IDX_debug_tu_index))
+	continue;
+      bool need_dot_dwo =
+	(result->type == TYPE_DWO
+	 && cnt != IDX_debug_cu_index
+	 && cnt != IDX_debug_tu_index);
+      size_t dbglen = strlen (dwarf_scnnames[cnt]);
+      size_t scnlen = strlen (scnname);
+      if (strncmp (scnname, dwarf_scnnames[cnt], dbglen) == 0
+	  && ((!need_dot_dwo && dbglen == scnlen)
+	      || (need_dot_dwo
+		  && scnlen == dbglen + 4
+		  && strstr (scnname, ".dwo") == scnname + dbglen)))
+	break;
+      else if (scnname[0] == '.' && scnname[1] == 'z'
+	       && (strncmp (&scnname[2], &dwarf_scnnames[cnt][1],
+			    dbglen - 1) == 0
+		   && ((!need_dot_dwo && scnlen == dbglen + 1)
+		       || (need_dot_dwo
+			   && scnlen == dbglen + 5
+			   && strstr (scnname,
+				      ".dwo") == scnname + dbglen + 1))))
+	{
+	  gnu_compressed = true;
+	  break;
+	}
+      else if (scnlen > 14 /* .gnu.debuglto_ prefix. */
+	       && startswith (scnname, ".gnu.debuglto_")
+	       && strcmp (&scnname[14], dwarf_scnnames[cnt]) == 0)
+	{
+	  if (result->type == TYPE_GNU_LTO)
+	    break;
+	}
+    }
+
+  if (cnt >= ndwarf_scnnames)
+    /* Not a debug section; ignore it. */
+    return result;
+
+  if (unlikely (result->sectiondata[cnt] != NULL))
+    /* A section appears twice.  That's bad.  We ignore the section.  */
+    return result;
+
+  /* We cannot know whether or not a GNU compressed section has already
+     been uncompressed or not, so ignore any errors.  */
+  if (gnu_compressed)
+    elf_compress_gnu (scn, 0, 0);
+
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+    {
+      if (elf_compress (scn, 0, 0) < 0)
+	{
+	  /* It would be nice if we could fail with a specific error.
+	     But we don't know if this was an essential section or not.
+	     So just continue for now. See also valid_p().  */
+	  return result;
+	}
+    }
+
+  /* Get the section data.  Should be raw bytes, no conversion needed.  */
+  Elf_Data *data = elf_rawdata (scn, NULL);
+  if (data == NULL)
+    goto err;
+
+  if (data->d_buf == NULL || data->d_size == 0)
+    /* No data actually available, ignore it. */
+    return result;
+
+  /* We can now read the section data into results. */
+  result->sectiondata[cnt] = data;
+
+  /* If the section contains string data, we want to know a size of a prefix
+     where any string will be null-terminated. */
+  enum string_section_index string_section_idx = scn_to_string_section_idx[cnt];
+  if (string_section_idx < STR_SCN_IDX_last)
+    {
+      size_t size = data->d_size;
+      /* Reduce the size by the number of non-zero bytes at the end of the
+	 section.  */
+      while (size > 0 && *((const char *) data->d_buf + size - 1) != '\0')
+	--size;
+      result->string_section_size[string_section_idx] = size;
+    }
+
+  return result;
+}
+
+char *
+__libdw_elfpath (int fd)
+{
+  /* strlen ("/proc/self/fd/") = 14 + strlen (<MAXINT>) = 10 + 1 = 25.  */
+  char devfdpath[25];
+  sprintf (devfdpath, "/proc/self/fd/%u", fd);
+  return realpath (devfdpath, NULL);
+}
+
+
+void
+__libdw_set_debugdir (Dwarf *dbg)
+{
+  if (dbg->elfpath == NULL || dbg->elfpath[0] != '/')
+    return;
+  size_t dirlen = strrchr (dbg->elfpath, '/') - dbg->elfpath + 1;
+  dbg->debugdir = malloc (dirlen + 1);
+  if (dbg->debugdir == NULL)
+    return;
+  memcpy (dbg->debugdir, dbg->elfpath, dirlen);
+  dbg->debugdir[dirlen] = '\0';
+}
+
+
+/* Check whether all the necessary DWARF information is available.  */
+static Dwarf *
+valid_p (Dwarf *result)
+{
+  /* We looked at all the sections.  Now determine whether all the
+     sections with debugging information we need are there.
+
+     Require at least one section that can be read "standalone".  */
+  if (likely (result != NULL)
+      && unlikely (result->sectiondata[IDX_debug_info] == NULL
+		   && result->sectiondata[IDX_debug_line] == NULL
+		   && result->sectiondata[IDX_debug_frame] == NULL))
+    {
+      Dwarf_Sig8_Hash_free (&result->sig8_hash);
+      __libdw_seterrno (DWARF_E_NO_DWARF);
+      free (result);
+      result = NULL;
+    }
+
+  /* We are setting up some "fake" CUs, which need an address size.
+     Check the ELF class to come up with something reasonable.  */
+  int elf_addr_size = 8;
+  if (result != NULL)
+    {
+      GElf_Ehdr ehdr;
+      if (gelf_getehdr (result->elf, &ehdr) == NULL)
+	{
+	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+	  __libdw_seterrno (DWARF_E_INVALID_ELF);
+	  free (result);
+	  result = NULL;
+	}
+      else if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
+	elf_addr_size = 4;
+    }
+
+  /* For dwarf_location_attr () we need a "fake" CU to indicate
+     where the "fake" attribute data comes from.  This is a block
+     inside the .debug_loc or .debug_loclists section.  */
+  if (result != NULL && result->sectiondata[IDX_debug_loc] != NULL)
+    {
+      result->fake_loc_cu = malloc (sizeof (Dwarf_CU));
+      if (unlikely (result->fake_loc_cu == NULL))
+	{
+	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  free (result);
+	  result = NULL;
+	}
+      else
+	{
+	  result->fake_loc_cu->sec_idx = IDX_debug_loc;
+	  result->fake_loc_cu->dbg = result;
+	  result->fake_loc_cu->startp
+	    = result->sectiondata[IDX_debug_loc]->d_buf;
+	  result->fake_loc_cu->endp
+	    = (result->sectiondata[IDX_debug_loc]->d_buf
+	       + result->sectiondata[IDX_debug_loc]->d_size);
+	  result->fake_loc_cu->locs = NULL;
+	  result->fake_loc_cu->address_size = elf_addr_size;
+	  result->fake_loc_cu->offset_size = 4;
+	  result->fake_loc_cu->version = 4;
+	  result->fake_loc_cu->split = NULL;
+	}
+    }
+
+  if (result != NULL && result->sectiondata[IDX_debug_loclists] != NULL)
+    {
+      result->fake_loclists_cu = malloc (sizeof (Dwarf_CU));
+      if (unlikely (result->fake_loclists_cu == NULL))
+	{
+	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  free (result->fake_loc_cu);
+	  free (result);
+	  result = NULL;
+	}
+      else
+	{
+	  result->fake_loclists_cu->sec_idx = IDX_debug_loclists;
+	  result->fake_loclists_cu->dbg = result;
+	  result->fake_loclists_cu->startp
+	    = result->sectiondata[IDX_debug_loclists]->d_buf;
+	  result->fake_loclists_cu->endp
+	    = (result->sectiondata[IDX_debug_loclists]->d_buf
+	       + result->sectiondata[IDX_debug_loclists]->d_size);
+	  result->fake_loclists_cu->locs = NULL;
+	  result->fake_loclists_cu->address_size = elf_addr_size;
+	  result->fake_loclists_cu->offset_size = 4;
+	  result->fake_loclists_cu->version = 5;
+	  result->fake_loclists_cu->split = NULL;
+	}
+    }
+
+  /* For DW_OP_constx/GNU_const_index and DW_OP_addrx/GNU_addr_index
+     the dwarf_location_attr () will need a "fake" address CU to
+     indicate where the attribute data comes from.  This is a just
+     inside the .debug_addr section, if it exists.  */
+  if (result != NULL && result->sectiondata[IDX_debug_addr] != NULL)
+    {
+      result->fake_addr_cu = malloc (sizeof (Dwarf_CU));
+      if (unlikely (result->fake_addr_cu == NULL))
+	{
+	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  free (result->fake_loc_cu);
+	  free (result->fake_loclists_cu);
+	  free (result);
+	  result = NULL;
+	}
+      else
+	{
+	  result->fake_addr_cu->sec_idx = IDX_debug_addr;
+	  result->fake_addr_cu->dbg = result;
+	  result->fake_addr_cu->startp
+	    = result->sectiondata[IDX_debug_addr]->d_buf;
+	  result->fake_addr_cu->endp
+	    = (result->sectiondata[IDX_debug_addr]->d_buf
+	       + result->sectiondata[IDX_debug_addr]->d_size);
+	  result->fake_addr_cu->locs = NULL;
+	  result->fake_addr_cu->address_size = elf_addr_size;
+	  result->fake_addr_cu->offset_size = 4;
+	  result->fake_addr_cu->version = 5;
+	  result->fake_addr_cu->split = NULL;
+	}
+    }
+
+  if (result != NULL)
+    {
+      result->elfpath = __libdw_elfpath (result->elf->fildes);
+      __libdw_set_debugdir(result);
+    }
+
+  return result;
+}
+
+
+static Dwarf *
+global_read (Dwarf *result, Elf *elf, size_t shstrndx)
+{
+  Elf_Scn *scn = NULL;
+
+  /* First check the type (PLAIN, DWO, LTO) we are looking for.  We
+     prefer PLAIN if available over DWO, over LTO.  */
+  while ((scn = elf_nextscn (elf, scn)) != NULL && result->type != TYPE_PLAIN)
+    {
+      enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
+      if (type > result->type)
+	result->type = type;
+    }
+
+  scn = NULL;
+  while (result != NULL && (scn = elf_nextscn (elf, scn)) != NULL)
+    result = check_section (result, shstrndx, scn, false);
+
+  return valid_p (result);
+}
+
+
+static Dwarf *
+scngrp_read (Dwarf *result, Elf *elf, size_t shstrndx, Elf_Scn *scngrp)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scngrp, &shdr_mem);
+  if (shdr == NULL)
+    {
+      Dwarf_Sig8_Hash_free (&result->sig8_hash);
+      __libdw_seterrno (DWARF_E_INVALID_ELF);
+      free (result);
+      return NULL;
+    }
+
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0
+      && elf_compress (scngrp, 0, 0) < 0)
+    {
+      Dwarf_Sig8_Hash_free (&result->sig8_hash);
+      __libdw_seterrno (DWARF_E_COMPRESSED_ERROR);
+      free (result);
+      return NULL;
+    }
+
+  /* SCNGRP is the section descriptor for a section group which might
+     contain debug sections.  */
+  Elf_Data *data = elf_getdata (scngrp, NULL);
+  if (data == NULL)
+    {
+      /* We cannot read the section content.  Fail!  */
+      Dwarf_Sig8_Hash_free (&result->sig8_hash);
+      free (result);
+      return NULL;
+    }
+
+  /* The content of the section is a number of 32-bit words which
+     represent section indices.  The first word is a flag word.  */
+  Elf32_Word *scnidx = (Elf32_Word *) data->d_buf;
+  size_t cnt;
+
+  /* First check the type (PLAIN, DWO, LTO) we are looking for.  We
+     prefer PLAIN if available over DWO, over LTO.  */
+  for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size; ++cnt)
+    {
+      Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
+      if (scn == NULL)
+	{
+	  /* A section group refers to a non-existing section.  Should
+	     never happen.  */
+	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+	  __libdw_seterrno (DWARF_E_INVALID_ELF);
+	  free (result);
+	  return NULL;
+	}
+
+      enum dwarf_type type = scn_dwarf_type (result, shstrndx, scn);
+      if (type > result->type)
+	result->type = type;
+    }
+
+  for (cnt = 1; cnt * sizeof (Elf32_Word) <= data->d_size && result != NULL; ++cnt)
+    {
+      Elf_Scn *scn = elf_getscn (elf, scnidx[cnt]);
+      assert (scn != NULL); // checked above
+      result = check_section (result, shstrndx, scn, true);
+      if (result == NULL)
+	break;
+    }
+
+  return valid_p (result);
+}
+
+
+Dwarf *
+dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp)
+{
+  GElf_Ehdr *ehdr;
+  GElf_Ehdr ehdr_mem;
+
+  /* Get the ELF header of the file.  We need various pieces of
+     information from it.  */
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      if (elf_kind (elf) != ELF_K_ELF)
+	__libdw_seterrno (DWARF_E_NOELF);
+      else
+	__libdw_seterrno (DWARF_E_GETEHDR_ERROR);
+
+      return NULL;
+    }
+
+
+  /* Default memory allocation size.  */
+  size_t mem_default_size = sysconf (_SC_PAGESIZE) - 4 * sizeof (void *);
+  assert (sizeof (struct Dwarf) < mem_default_size);
+
+  /* Allocate the data structure.  */
+  Dwarf *result = calloc (1, sizeof (Dwarf));
+  if (unlikely (result == NULL)
+      || unlikely (Dwarf_Sig8_Hash_init (&result->sig8_hash, 11) < 0))
+    {
+      free (result);
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  /* Fill in some values.  */
+  if ((BYTE_ORDER == LITTLE_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2MSB)
+      || (BYTE_ORDER == BIG_ENDIAN && ehdr->e_ident[EI_DATA] == ELFDATA2LSB))
+    result->other_byte_order = true;
+
+  result->elf = elf;
+  result->alt_fd = -1;
+  result->dwp_fd = -1;
+
+  /* Initialize the memory handling.  Initial blocks are allocated on first
+     actual allocation.  */
+  result->mem_default_size = mem_default_size;
+  result->oom_handler = __libdw_oom;
+  if (pthread_rwlock_init(&result->mem_rwl, NULL) != 0)
+    {
+      free (result);
+      __libdw_seterrno (DWARF_E_NOMEM); /* no memory.  */
+      return NULL;
+    }
+  result->mem_stacks = 0;
+  result->mem_tails = NULL;
+
+  if (cmd == DWARF_C_READ || cmd == DWARF_C_RDWR)
+    {
+      /* All sections are recognized by name, so pass the section header
+	 string index along to easily get the section names.  */
+      size_t shstrndx;
+      if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+	{
+	  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+	  __libdw_seterrno (DWARF_E_INVALID_ELF);
+	  free (result);
+	  return NULL;
+	}
+
+      /* If the caller provides a section group we get the DWARF
+	 sections only from this section group.  Otherwise we search
+	 for the first section with the required name.  Further
+	 sections with the name are ignored.  The DWARF specification
+	 does not really say this is allowed.  */
+      if (scngrp == NULL)
+	return global_read (result, elf, shstrndx);
+      else
+	return scngrp_read (result, elf, shstrndx, scngrp);
+    }
+  else if (cmd == DWARF_C_WRITE)
+    {
+      Dwarf_Sig8_Hash_free (&result->sig8_hash);
+      __libdw_seterrno (DWARF_E_UNIMPL);
+      free (result);
+      return NULL;
+    }
+
+  Dwarf_Sig8_Hash_free (&result->sig8_hash);
+  __libdw_seterrno (DWARF_E_INVALID_CMD);
+  free (result);
+  return NULL;
+}
+INTDEF(dwarf_begin_elf)
diff --git a/libdw/dwarf_bitoffset.c b/libdw/dwarf_bitoffset.c
new file mode 100644
index 0000000..61a0d59
--- /dev/null
+++ b/libdw/dwarf_bitoffset.c
@@ -0,0 +1,49 @@
+/* Return bit offset attribute of DIE.
+   Copyright (C) 2003, 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_bitoffset, ELFUTILS_0.143)
+int
+dwarf_bitoffset (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word value;
+
+  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+				  (die, DW_AT_bit_offset, &attr_mem),
+				  &value) == 0 ? (int) value : -1;
+}
+OLD_VERSION (dwarf_bitoffset, ELFUTILS_0.122)
diff --git a/libdw/dwarf_bitsize.c b/libdw/dwarf_bitsize.c
new file mode 100644
index 0000000..35e8744
--- /dev/null
+++ b/libdw/dwarf_bitsize.c
@@ -0,0 +1,49 @@
+/* Return bit size attribute of DIE.
+   Copyright (C) 2003, 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_bitsize, ELFUTILS_0.143)
+int
+dwarf_bitsize (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word value;
+
+  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+				  (die, DW_AT_bit_size, &attr_mem),
+				  &value) == 0 ? (int) value : -1;
+}
+OLD_VERSION (dwarf_bitsize, ELFUTILS_0.122)
diff --git a/libdw/dwarf_bytesize.c b/libdw/dwarf_bytesize.c
new file mode 100644
index 0000000..6d1ff9a
--- /dev/null
+++ b/libdw/dwarf_bytesize.c
@@ -0,0 +1,49 @@
+/* Return byte size attribute of DIE.
+   Copyright (C) 2003, 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_bytesize, ELFUTILS_0.143)
+int
+dwarf_bytesize (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word value;
+
+  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+				  (die, DW_AT_byte_size, &attr_mem),
+				  &value) == 0 ? (int) value : -1;
+}
+OLD_VERSION (dwarf_bytesize, ELFUTILS_0.122)
diff --git a/libdw/dwarf_cfi_addrframe.c b/libdw/dwarf_cfi_addrframe.c
new file mode 100644
index 0000000..4424027
--- /dev/null
+++ b/libdw/dwarf_cfi_addrframe.c
@@ -0,0 +1,54 @@
+/* Compute frame state at PC.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+
+int
+dwarf_cfi_addrframe (Dwarf_CFI *cache, Dwarf_Addr address, Dwarf_Frame **frame)
+{
+  /* Maybe there was a previous error.  */
+  if (cache == NULL)
+    return -1;
+
+  struct dwarf_fde *fde = __libdw_find_fde (cache, address);
+  if (fde == NULL)
+    return -1;
+
+  int error = __libdw_frame_at_address (cache, fde, address, frame);
+  if (error != DWARF_E_NOERROR)
+    {
+      __libdw_seterrno (error);
+      return -1;
+    }
+  return 0;
+}
+INTDEF (dwarf_cfi_addrframe)
diff --git a/libdw/dwarf_cfi_end.c b/libdw/dwarf_cfi_end.c
new file mode 100644
index 0000000..d68e2db
--- /dev/null
+++ b/libdw/dwarf_cfi_end.c
@@ -0,0 +1,48 @@
+/* Clean up Dwarf_CFI structure.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include "cfi.h"
+#include <stdlib.h>
+
+int
+dwarf_cfi_end (Dwarf_CFI *cache)
+{
+  if (cache != NULL)
+    {
+      __libdw_destroy_frame_cache (cache);
+      free (cache);
+    }
+
+  return 0;
+}
+INTDEF (dwarf_cfi_end)
diff --git a/libdw/dwarf_child.c b/libdw/dwarf_child.c
new file mode 100644
index 0000000..96a0d60
--- /dev/null
+++ b/libdw/dwarf_child.c
@@ -0,0 +1,193 @@
+/* Return child of current DIE.
+   Copyright (C) 2003-2011, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <string.h>
+
+/* Some arbitrary value not conflicting with any existing code.  */
+#define INVALID 0xffffe444
+
+
+unsigned char *
+internal_function
+__libdw_find_attr (Dwarf_Die *die, unsigned int search_name,
+		   unsigned int *codep, unsigned int *formp)
+{
+  const unsigned char *readp = NULL;
+
+  /* Find the abbreviation entry.  */
+  Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &readp);
+  if (unlikely (abbrevp == DWARF_END_ABBREV))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  const unsigned char *endp = die->cu->endp;
+
+  /* Search the name attribute.  Attribute has been checked when
+     Dwarf_Abbrev was created, we can read unchecked.  */
+  const unsigned char *attrp = abbrevp->attrp;
+  while (1)
+    {
+      /* Get attribute name and form.  */
+      unsigned int attr_name;
+      get_uleb128_unchecked (attr_name, attrp);
+
+      unsigned int attr_form;
+      get_uleb128_unchecked (attr_form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr_name == 0 && attr_form == 0)
+	break;
+
+      if (attr_form == DW_FORM_indirect)
+	{
+	  if (readp >= endp)
+	    goto invalid;
+	  get_uleb128 (attr_form, readp, endp);
+	  if (attr_form == DW_FORM_indirect ||
+	      attr_form == DW_FORM_implicit_const)
+	    {
+	    invalid:
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return NULL;
+	    }
+	}
+
+      /* Is this the name attribute?  */
+      if (attr_name == search_name && search_name != INVALID)
+	{
+	  if (codep != NULL)
+	    *codep = attr_name;
+	  if (formp != NULL)
+	    *formp = attr_form;
+
+	  /* Normally the attribute data comes from the DIE/info,
+	     except for implicit_form, where it comes from the abbrev.  */
+	  if (attr_form == DW_FORM_implicit_const)
+	    return (unsigned char *) attrp;
+	  else
+	    return (unsigned char *) readp;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr_form != 0)
+	{
+	  size_t len = __libdw_form_val_len (die->cu, attr_form, readp);
+	  if (unlikely (len == (size_t) -1l))
+	    {
+	      readp = NULL;
+	      break;
+	    }
+
+	  // __libdw_form_val_len will have done a bounds check.
+	  readp += len;
+
+	  // If the value is in the abbrev data, skip it.
+	  if (attr_form == DW_FORM_implicit_const)
+	    {
+	      int64_t attr_value __attribute__((__unused__));
+	      get_sleb128_unchecked (attr_value, attrp);
+	    }
+	}
+    }
+
+  // XXX Do we need other values?
+  if (codep != NULL)
+    *codep = INVALID;
+  if (formp != NULL)
+    *formp = INVALID;
+
+  return (unsigned char *) readp;
+}
+
+
+int
+dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
+{
+  /* Ignore previous errors.  */
+  if (die == NULL)
+    return -1;
+
+  /* Find the abbreviation entry.  */
+  Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+  if (unlikely (abbrevp == DWARF_END_ABBREV))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  /* If there are no children, do not search.  */
+  if (! abbrevp->has_children)
+    return 1;
+
+  /* Skip past the last attribute.  */
+  void *addr = __libdw_find_attr (die, INVALID, NULL, NULL);
+
+  if (addr == NULL)
+    return -1;
+
+  /* RESULT can be the same as DIE.  So preserve what we need.  */
+  struct Dwarf_CU *cu = die->cu;
+
+  /* It's kosher (just suboptimal) to have a null entry first thing (7.5.3).
+     So if this starts with ULEB128 of 0 (even with silly encoding of 0),
+     it is a kosher null entry and we do not really have any children.  */
+  const unsigned char *code = addr;
+  const unsigned char *endp = cu->endp;
+  while (1)
+    {
+      if (unlikely (code >= endp)) /* Truncated section.  */
+	return 1;
+      if (unlikely (*code == 0x80))
+	++code;
+      else
+	break;
+    }
+  if (unlikely (*code == '\0'))
+    return 1;
+
+  /* Clear the entire DIE structure.  This signals we have not yet
+     determined any of the information.  */
+  memset (result, '\0', sizeof (Dwarf_Die));
+
+  /* We have the address.  */
+  result->addr = addr;
+
+  /* Same CU as the parent.  */
+  result->cu = cu;
+
+  return 0;
+}
+INTDEF(dwarf_child)
diff --git a/libdw/dwarf_cu_die.c b/libdw/dwarf_cu_die.c
new file mode 100644
index 0000000..7594e7d
--- /dev/null
+++ b/libdw/dwarf_cu_die.c
@@ -0,0 +1,62 @@
+/* Internal definitions for libdwarf.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_cu_die (Dwarf_CU *cu, Dwarf_Die *result, Dwarf_Half *versionp,
+	      Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
+	      uint8_t *offset_sizep, uint64_t *unit_idp,
+	      Dwarf_Off *subdie_offsetp)
+{
+  if (cu == NULL)
+    return NULL;
+
+  *result = CUDIE (cu);
+
+  if (versionp != NULL)
+    *versionp = cu->version;
+  if (abbrev_offsetp != NULL)
+    *abbrev_offsetp = cu->orig_abbrev_offset;
+  if (address_sizep != NULL)
+    *address_sizep = cu->address_size;
+  if (offset_sizep != NULL)
+    *offset_sizep = cu->offset_size;
+  if (unit_idp != NULL)
+    *unit_idp = cu->unit_id8;
+  if (subdie_offsetp != NULL)
+    *subdie_offsetp = cu->subdie_offset;
+
+  return result;
+}
diff --git a/libdw/dwarf_cu_dwp_section_info.c b/libdw/dwarf_cu_dwp_section_info.c
new file mode 100644
index 0000000..5a081f5
--- /dev/null
+++ b/libdw/dwarf_cu_dwp_section_info.c
@@ -0,0 +1,532 @@
+/* Read DWARF package file index sections.
+   Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+
+#include "libdwP.h"
+
+static Dwarf_Package_Index *
+__libdw_read_package_index (Dwarf *dbg, bool tu)
+{
+  Elf_Data *data;
+  if (tu)
+    data = dbg->sectiondata[IDX_debug_tu_index];
+  else
+    data = dbg->sectiondata[IDX_debug_cu_index];
+
+  /* We need at least 16 bytes for the header.  */
+  if (data == NULL || data->d_size < 16)
+    {
+    invalid:
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  const unsigned char *datap = data->d_buf;
+  const unsigned char *endp = datap + data->d_size;
+  uint16_t version;
+  /* In GNU DebugFission for DWARF 4, the version is 2 as a uword.  In the
+     standardized DWARF 5 format, it is a uhalf followed by a padding uhalf.
+     Check for both.  */
+  if (read_4ubyte_unaligned (dbg, datap) == 2)
+    version = 2;
+  else
+    {
+      version = read_2ubyte_unaligned (dbg, datap);
+      if (version != 5)
+	{
+	  __libdw_seterrno (DWARF_E_VERSION);
+	  return NULL;
+	}
+    }
+  datap += 4;
+  uint32_t section_count = read_4ubyte_unaligned_inc (dbg, datap);
+  uint32_t unit_count = read_4ubyte_unaligned_inc (dbg, datap);
+  uint32_t slot_count = read_4ubyte_unaligned_inc (dbg, datap);
+
+  /* The specification has a stricter requirement that
+     slot_count > 3 * unit_count / 2, but this is enough for us.  */
+  if (slot_count < unit_count)
+    goto invalid;
+
+  /* After the header, the section must contain:
+
+       8 byte signature per hash table slot
+     + 4 byte index per hash table slot
+     + Section offset table with 1 header row, 1 row per unit, 1 column per
+       section, 4 bytes per field
+     + Section size table with 1 row per unit, 1 column per section, 4 bytes
+       per field
+
+     We have to be careful about overflow when checking this.  */
+  const unsigned char *hash_table = datap;
+  if ((size_t) (endp - hash_table) < (uint64_t) slot_count * 12)
+    goto invalid;
+  const unsigned char *indices = hash_table + (size_t) slot_count * 8;
+  const unsigned char *sections = indices + (size_t) slot_count * 4;
+  if ((size_t) (endp - sections) < (uint64_t) section_count * 4)
+    goto invalid;
+  const unsigned char *section_offsets = sections + (size_t) section_count * 4;
+  if ((uint64_t) unit_count * section_count > UINT64_MAX / 8
+      || ((size_t) (endp - section_offsets)
+	  < (uint64_t) unit_count * section_count * 8))
+    goto invalid;
+  const unsigned char *section_sizes
+    = section_offsets + (uint64_t) unit_count * section_count * 4;
+
+  Dwarf_Package_Index *index = malloc (sizeof (*index));
+  if (index == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  index->dbg = dbg;
+  /* Set absent sections to UINT32_MAX.  */
+  for (size_t i = 0;
+       i < sizeof (index->sections) / sizeof (index->sections[0]); i++)
+    index->sections[i] = UINT32_MAX;
+  for (size_t i = 0; i < section_count; i++)
+    {
+      uint32_t section = read_4ubyte_unaligned (dbg, sections + i * 4);
+      /* 2 is DW_SECT_TYPES in version 2 and reserved in version 5.  We ignore
+         it for version 5.
+	 5 is DW_SECT_LOC in version 2 and DW_SECT_LOCLISTS in version 5.  We
+	 use the same index for both.
+	 7 is DW_SECT_MACINFO in version 2 and DW_SECT_MACRO in version 5.  We
+	 use the same index for both.
+	 8 is DW_SECT_MACRO in version 2 and DW_SECT_RNGLISTS in version 5.  We
+	 use the same index for version 2's DW_SECT_MACRO as version 2's
+	 DW_SECT_MACINFO/version 5's DW_SECT_MACRO.
+	 We ignore unknown sections.  */
+      if (section == 0)
+	continue;
+      if (version == 2)
+	{
+	  if (section > 8)
+	    continue;
+	  else if (section == 8)
+	    section = DW_SECT_MACRO;
+	}
+      else if (section == 2
+	       || (section
+		   > sizeof (index->sections) / sizeof (index->sections[0])))
+	continue;
+      index->sections[section - 1] = i;
+    }
+
+  /* DW_SECT_INFO (or DW_SECT_TYPES for DWARF 4 type units) and DW_SECT_ABBREV
+     are required.  */
+  if (((!tu || dbg->sectiondata[IDX_debug_types] == NULL)
+       && index->sections[DW_SECT_INFO - 1] == UINT32_MAX)
+      || (tu && dbg->sectiondata[IDX_debug_types] != NULL
+	  && index->sections[DW_SECT_TYPES - 1] == UINT32_MAX)
+      || index->sections[DW_SECT_ABBREV - 1] == UINT32_MAX)
+    {
+      free (index);
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  index->section_count = section_count;
+  index->unit_count = unit_count;
+  index->slot_count = slot_count;
+  index->last_unit_found = 0;
+  index->hash_table = hash_table;
+  index->indices = indices;
+  index->section_offsets = section_offsets;
+  index->section_sizes = section_sizes;
+  index->debug_info_offsets = NULL;
+
+  return index;
+}
+
+static Dwarf_Package_Index *
+__libdw_package_index (Dwarf *dbg, bool tu)
+{
+  if (tu && dbg->tu_index != NULL)
+    return dbg->tu_index;
+  else if (!tu && dbg->cu_index != NULL)
+    return dbg->cu_index;
+
+  Dwarf_Package_Index *index = __libdw_read_package_index (dbg, tu);
+  if (index == NULL)
+    return NULL;
+
+  /* Offsets in the section offset table are 32-bit unsigned integers.  In
+     practice, the .debug_info.dwo section for very large executables can be
+     larger than 4GB.  GNU dwp as of binutils 2.41 and llvm-dwp before LLVM 15
+     both accidentally truncate offsets larger than 4GB.
+
+     LLVM 15 detects the overflow and errors out instead; see LLVM commit
+     f8df8114715b ("[DWP][DWARF] Detect and error on debug info offset
+     overflow").  However, lldb in LLVM 16 supports using dwp files with
+     truncated offsets by recovering them directly from the unit headers in the
+     .debug_info.dwo section; see LLVM commit c0db06227721 ("[DWARFLibrary] Add
+     support to re-construct cu-index").  Since LLVM 17, the overflow error can
+     be turned into a warning instead; see LLVM commit 53a483cee801 ("[DWP] add
+     overflow check for llvm-dwp tools if offset overflow").
+
+     LLVM's support for > 4GB offsets is effectively an extension to the DWARF
+     package file format, which we implement here.  The strategy is to walk the
+     unit headers in .debug_info.dwo in lockstep with the DW_SECT_INFO columns
+     in the section offset tables.  As long as they are in the same order
+     (which they are in practice for both GNU dwp and llvm-dwp), we can
+     correlate the truncated offset and produce a corrected array of offsets.
+
+     Note that this will be fixed properly in DWARF 6:
+     https://dwarfstd.org/issues/220708.2.html.  */
+  if (index->sections[DW_SECT_INFO - 1] != UINT32_MAX
+      && dbg->sectiondata[IDX_debug_info]->d_size > UINT32_MAX)
+    {
+      Dwarf_Package_Index *cu_index, *tu_index = NULL;
+      if (tu)
+	{
+	  tu_index = index;
+	  assert (dbg->cu_index == NULL);
+	  cu_index = __libdw_read_package_index (dbg, false);
+	  if (cu_index == NULL)
+	    {
+	      free(index);
+	      return NULL;
+	    }
+	}
+      else
+	{
+	  cu_index = index;
+	  if (dbg->sectiondata[IDX_debug_tu_index] != NULL
+	      && dbg->sectiondata[IDX_debug_types] == NULL)
+	    {
+	      assert (dbg->tu_index == NULL);
+	      tu_index = __libdw_read_package_index (dbg, true);
+	      if (tu_index == NULL)
+		{
+		  free(index);
+		  return NULL;
+		}
+	    }
+	}
+
+      cu_index->debug_info_offsets = malloc (cu_index->unit_count
+					     * sizeof (Dwarf_Off));
+      if (cu_index->debug_info_offsets == NULL)
+	{
+	  free (tu_index);
+	  free (cu_index);
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  return NULL;
+	}
+      if (tu_index != NULL)
+	{
+	  tu_index->debug_info_offsets = malloc (tu_index->unit_count
+						 * sizeof (Dwarf_Off));
+	  if (tu_index->debug_info_offsets == NULL)
+	    {
+	      free (tu_index);
+	      free (cu_index->debug_info_offsets);
+	      free (cu_index);
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      return NULL;
+	    }
+	}
+
+      Dwarf_Off off = 0;
+      uint32_t cui = 0, tui = 0;
+      uint32_t cu_count = cu_index->unit_count;
+      const unsigned char *cu_offset
+	= cu_index->section_offsets + cu_index->sections[DW_SECT_INFO - 1] * 4;
+      uint32_t tu_count = 0;
+      const unsigned char *tu_offset = NULL;
+      if (tu_index != NULL)
+	{
+	  tu_count = tu_index->unit_count;
+	  tu_offset = tu_index->section_offsets
+		      + tu_index->sections[DW_SECT_INFO - 1] * 4;
+	}
+      while (cui < cu_count || tui < tu_count)
+	{
+	  Dwarf_Off next_off;
+	  uint8_t unit_type;
+	  if (__libdw_next_unit (dbg, false, off, &next_off, NULL, NULL,
+				 &unit_type, NULL, NULL, NULL, NULL, NULL)
+	      != 0)
+	    {
+	    not_sorted:
+	      free (cu_index->debug_info_offsets);
+	      cu_index->debug_info_offsets = NULL;
+	      if (tu_index != NULL)
+		{
+		  free (tu_index->debug_info_offsets);
+		  tu_index->debug_info_offsets = NULL;
+		}
+	      break;
+	    }
+	  if (unit_type != DW_UT_split_type && cui < cu_count)
+	    {
+	      if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, cu_offset))
+		goto not_sorted;
+	      cu_index->debug_info_offsets[cui++] = off;
+	      cu_offset += cu_index->section_count * 4;
+	    }
+	  else if (unit_type == DW_UT_split_type && tu_index != NULL
+		   && tui < tu_count)
+	    {
+	      if ((off & UINT32_MAX) != read_4ubyte_unaligned (dbg, tu_offset))
+		goto not_sorted;
+	      tu_index->debug_info_offsets[tui++] = off;
+	      tu_offset += tu_index->section_count * 4;
+	    }
+	  off = next_off;
+	}
+
+      if (tu)
+	dbg->cu_index = cu_index;
+      else if (tu_index != NULL)
+	dbg->tu_index = tu_index;
+    }
+
+  if (tu)
+    dbg->tu_index = index;
+  else
+    dbg->cu_index = index;
+  return index;
+}
+
+static int
+__libdw_dwp_unit_row (Dwarf_Package_Index *index, uint64_t unit_id,
+		      uint32_t *unit_rowp)
+{
+  if (index == NULL)
+    return -1;
+
+  uint32_t hash = unit_id;
+  uint32_t hash2 = (unit_id >> 32) | 1;
+  /* Only check each slot once.  */
+  for (uint32_t n = index->slot_count; n-- > 0; )
+    {
+      size_t slot = hash & (index->slot_count - 1);
+      uint64_t sig = read_8ubyte_unaligned (index->dbg,
+					    index->hash_table + slot * 8);
+      if (sig == unit_id)
+	{
+	  uint32_t row = read_4ubyte_unaligned (index->dbg,
+						index->indices + slot * 4);
+	  if (row > index->unit_count)
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return -1;
+	    }
+	  *unit_rowp = row;
+	  return 0;
+	}
+      else if (sig == 0
+	       && read_4ubyte_unaligned (index->dbg,
+					 index->indices + slot * 4) == 0)
+	break;
+      hash += hash2;
+    }
+  *unit_rowp = 0;
+  return 0;
+}
+
+static int
+__libdw_dwp_section_info (Dwarf_Package_Index *index, uint32_t unit_row,
+			  unsigned int section, Dwarf_Off *offsetp,
+			  Dwarf_Off *sizep)
+{
+  if (index == NULL)
+    return -1;
+  if (unit_row == 0)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+  if (index->sections[section - 1] == UINT32_MAX)
+    {
+      if (offsetp != NULL)
+	*offsetp = 0;
+      if (sizep != NULL)
+	*sizep = 0;
+      return 0;
+    }
+  size_t i = (size_t)(unit_row - 1) * index->section_count
+	     + index->sections[section - 1];
+  if (offsetp != NULL)
+    {
+      if (section == DW_SECT_INFO && index->debug_info_offsets != NULL)
+	*offsetp = index->debug_info_offsets[unit_row - 1];
+      else
+	*offsetp = read_4ubyte_unaligned (index->dbg,
+					  index->section_offsets + i * 4);
+    }
+  if (sizep != NULL)
+    *sizep = read_4ubyte_unaligned (index->dbg,
+				    index->section_sizes + i * 4);
+  return 0;
+}
+
+int
+internal_function
+__libdw_dwp_find_unit (Dwarf *dbg, bool debug_types, Dwarf_Off off,
+		       uint16_t version, uint8_t unit_type, uint64_t unit_id8,
+		       uint32_t *unit_rowp, Dwarf_Off *abbrev_offsetp)
+{
+  if (version >= 5
+      && unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
+    {
+    not_dwp:
+      *unit_rowp = 0;
+      *abbrev_offsetp = 0;
+      return 0;
+    }
+  bool tu = unit_type == DW_UT_split_type || debug_types;
+  if (dbg->sectiondata[tu ? IDX_debug_tu_index : IDX_debug_cu_index] == NULL)
+    goto not_dwp;
+  Dwarf_Package_Index *index = __libdw_package_index (dbg, tu);
+  if (index == NULL)
+    return -1;
+
+  /* This is always called for ascending offsets.  The most obvious way for a
+     producer to generate the section offset table is sorted by offset; both
+     GNU dwp and llvm-dwp do this.  In this common case, we can avoid the full
+     lookup.  */
+  if (index->last_unit_found < index->unit_count)
+    {
+      Dwarf_Off offset, size;
+      if (__libdw_dwp_section_info (index, index->last_unit_found + 1,
+				    debug_types ? DW_SECT_TYPES : DW_SECT_INFO,
+				    &offset, &size) != 0)
+	return -1;
+      if (offset <= off && off - offset < size)
+	{
+	  *unit_rowp = ++index->last_unit_found;
+	  goto done;
+	}
+      else
+	/* The units are not sorted. Don't try again.  */
+	index->last_unit_found = index->unit_count;
+    }
+
+  if (version >= 5 || debug_types)
+    {
+      /* In DWARF 5 and in type units, the unit signature is available in the
+         unit header.  */
+      if (__libdw_dwp_unit_row (index, unit_id8, unit_rowp) != 0)
+	return -1;
+    }
+  else
+    {
+      /* In DWARF 4 compilation units, the unit signature is an attribute.  We
+	 can't parse attributes in the split unit until we get the abbreviation
+	 table offset from the package index, which is a chicken-and-egg
+	 problem.  We could get the signature from the skeleton unit, but that
+	 may not be available.
+
+	 Instead, we resort to a linear scan through the section offset table.
+	 Finding all units is therefore quadratic in the number of units.
+	 However, this will likely never be needed in practice because of the
+	 sorted fast path above.  If this ceases to be the case, we can try to
+	 plumb through the skeleton unit's signature when it is available, or
+	 build a sorted lookup table for binary search.  */
+      if (index->sections[DW_SECT_INFO - 1] == UINT32_MAX)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      for (uint32_t i = 0; i < index->unit_count; i++)
+	{
+	  Dwarf_Off offset, size;
+	  __libdw_dwp_section_info (index, i + 1, DW_SECT_INFO, &offset,
+				    &size);
+	  if (offset <= off && off - offset < size)
+	    {
+	      *unit_rowp = i + 1;
+	      goto done;
+	    }
+	}
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+ done:
+  return __libdw_dwp_section_info (index, *unit_rowp, DW_SECT_ABBREV,
+				   abbrev_offsetp, NULL);
+}
+
+Dwarf_CU *
+internal_function
+__libdw_dwp_findcu_id (Dwarf *dbg, uint64_t unit_id8)
+{
+  Dwarf_Package_Index *index = __libdw_package_index (dbg, false);
+  uint32_t unit_row;
+  Dwarf_Off offset;
+  Dwarf_CU *cu;
+  if (__libdw_dwp_unit_row (index, unit_id8, &unit_row) == 0
+      && __libdw_dwp_section_info (index, unit_row, DW_SECT_INFO, &offset,
+				   NULL) == 0
+      && (cu = __libdw_findcu (dbg, offset, false)) != NULL
+      && cu->unit_type == DW_UT_split_compile
+      && cu->unit_id8 == unit_id8)
+    return cu;
+  else
+    return NULL;
+}
+
+int
+dwarf_cu_dwp_section_info (Dwarf_CU *cu, unsigned int section,
+			   Dwarf_Off *offsetp, Dwarf_Off *sizep)
+{
+  if (cu == NULL)
+    return -1;
+  if (section < DW_SECT_INFO || section > DW_SECT_RNGLISTS)
+    {
+      __libdw_seterrno (DWARF_E_UNKNOWN_SECTION);
+      return -1;
+    }
+  if (cu->dwp_row == 0)
+    {
+      if (offsetp != NULL)
+	*offsetp = 0;
+      if (sizep != NULL)
+	*sizep = 0;
+      return 0;
+    }
+  else
+    {
+      Dwarf_Package_Index *index
+	= cu->unit_type == DW_UT_split_compile
+	? cu->dbg->cu_index : cu->dbg->tu_index;
+      return __libdw_dwp_section_info (index, cu->dwp_row, section, offsetp,
+				       sizep);
+    }
+}
+INTDEF(dwarf_cu_dwp_section_info)
diff --git a/libdw/dwarf_cu_getdwarf.c b/libdw/dwarf_cu_getdwarf.c
new file mode 100644
index 0000000..562460f
--- /dev/null
+++ b/libdw/dwarf_cu_getdwarf.c
@@ -0,0 +1,46 @@
+/* Retrieve Dwarf descriptor underlying a Dwarf_CU.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include "libdwP.h"
+
+
+Dwarf *
+dwarf_cu_getdwarf (Dwarf_CU *cu)
+{
+  if (cu == NULL)
+    /* Some error occurred before.  */
+    return NULL;
+
+  return cu->dbg;
+}
diff --git a/libdw/dwarf_cu_info.c b/libdw/dwarf_cu_info.c
new file mode 100644
index 0000000..30aee6c
--- /dev/null
+++ b/libdw/dwarf_cu_info.c
@@ -0,0 +1,103 @@
+/* Provides information and DIEs associated with the Dwarf_CU unit.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+int
+dwarf_cu_info (Dwarf_CU *cu,
+	       Dwarf_Half *version, uint8_t *unit_type,
+	       Dwarf_Die *cudie, Dwarf_Die *subdie,
+	       uint64_t *unit_id,
+	       uint8_t *address_size, uint8_t *offset_size)
+{
+  if (cu == NULL)
+    return -1;
+
+  if (version != NULL)
+    *version = cu->version;
+
+  if (unit_type != NULL)
+    *unit_type = cu->unit_type;
+
+  if (cudie != NULL)
+    {
+      if (cu->version >= 2 && cu->version <= 5
+	  && cu->unit_type >= DW_UT_compile
+	  && cu->unit_type <= DW_UT_split_type)
+	*cudie = CUDIE (cu);
+      else
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+    }
+
+  if (subdie != NULL)
+    {
+      if (cu->version >= 2 && cu->version <= 5)
+	{
+	  /* For types, return the actual type DIE.  For skeletons,
+	     find the associated split compile unit and return its
+	     DIE.  */
+	  if (cu->unit_type == DW_UT_type
+	      || cu->unit_type == DW_UT_split_type)
+	    *subdie = SUBDIE(cu);
+	  else if (cu->unit_type == DW_UT_skeleton)
+	    {
+	      Dwarf_CU *split_cu = __libdw_find_split_unit (cu);
+	      if (split_cu != NULL)
+		*subdie = CUDIE(split_cu);
+	      else
+		memset (subdie, '\0', sizeof (Dwarf_Die));
+	    }
+	  else
+	    memset (subdie, '\0', sizeof (Dwarf_Die));
+	}
+      else
+	goto invalid;
+    }
+
+  if (unit_id != NULL)
+    *unit_id = cu->unit_id8;
+
+  if (address_size != NULL)
+    *address_size = cu->address_size;
+
+  if (offset_size != NULL)
+    *offset_size = cu->offset_size;
+
+  return 0;
+}
diff --git a/libdw/dwarf_cuoffset.c b/libdw/dwarf_cuoffset.c
new file mode 100644
index 0000000..f13b02f
--- /dev/null
+++ b/libdw/dwarf_cuoffset.c
@@ -0,0 +1,44 @@
+/* Return offset of DIE in CU.
+   Copyright (C) 2003-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Off
+dwarf_cuoffset (Dwarf_Die *die)
+{
+  return ((die == NULL || die->cu == NULL)
+	  ? (Dwarf_Off) -1l
+	  : (Dwarf_Off) (die->addr - die->cu->startp));
+}
diff --git a/libdw/dwarf_decl_column.c b/libdw/dwarf_decl_column.c
new file mode 100644
index 0000000..3225fd1
--- /dev/null
+++ b/libdw/dwarf_decl_column.c
@@ -0,0 +1,44 @@
+/* Get column number of beginning of given declaration.
+   Copyright (C) 2005-2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_decl_column, ELFUTILS_0.143)
+int
+dwarf_decl_column (Dwarf_Die *decl, int *colp)
+{
+  return __libdw_attr_intval (decl, colp, DW_AT_decl_column);
+}
+OLD_VERSION (dwarf_decl_column, ELFUTILS_0.122)
diff --git a/libdw/dwarf_decl_file.c b/libdw/dwarf_decl_file.c
new file mode 100644
index 0000000..1b91a4e
--- /dev/null
+++ b/libdw/dwarf_decl_file.c
@@ -0,0 +1,64 @@
+/* Return file name containing definition of the given function.
+   Copyright (C) 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_decl_file, ELFUTILS_0.143)
+const char *
+dwarf_decl_file (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word idx = 0;
+
+  if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+			       (die, DW_AT_decl_file, &attr_mem),
+			       &idx) != 0)
+    return NULL;
+
+  Dwarf_Files *files;
+  size_t nfiles;
+  if (INTUSE(dwarf_getsrcfiles) (&CUDIE (attr_mem.cu), &files, &nfiles) != 0)
+    return NULL;
+
+  if (idx >= nfiles)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  return files->info[idx].name;
+}
+OLD_VERSION (dwarf_decl_file, ELFUTILS_0.122)
diff --git a/libdw/dwarf_decl_line.c b/libdw/dwarf_decl_line.c
new file mode 100644
index 0000000..6b31eeb
--- /dev/null
+++ b/libdw/dwarf_decl_line.c
@@ -0,0 +1,70 @@
+/* Get line number of beginning of given function.
+   Copyright (C) 2005, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <limits.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_decl_line, ELFUTILS_0.143)
+int
+dwarf_decl_line (Dwarf_Die *func, int *linep)
+{
+  return __libdw_attr_intval (func, linep, DW_AT_decl_line);
+}
+OLD_VERSION (dwarf_decl_line, ELFUTILS_0.122)
+
+
+int internal_function
+__libdw_attr_intval (Dwarf_Die *die, int *linep, int attval)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word line;
+
+  int res = INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+				     (die, attval, &attr_mem),
+				     &line);
+  if (res == 0)
+    {
+      if (line > INT_MAX)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  res = -1;
+	}
+      else
+	*linep = line;
+    }
+
+  return res;
+}
diff --git a/libdw/dwarf_default_lower_bound.c b/libdw/dwarf_default_lower_bound.c
new file mode 100644
index 0000000..a33a343
--- /dev/null
+++ b/libdw/dwarf_default_lower_bound.c
@@ -0,0 +1,91 @@
+/* Get the default subrange lower bound for a given language.
+   Copyright (C) 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+/* Determine default lower bound from language, as per the DWARF5
+   "Subrange Type Entries" table.  */
+int
+dwarf_default_lower_bound (int lang, Dwarf_Sword *result)
+{
+  switch (lang)
+    {
+    case DW_LANG_C:
+    case DW_LANG_C89:
+    case DW_LANG_C99:
+    case DW_LANG_C11:
+    case DW_LANG_C_plus_plus:
+    case DW_LANG_C_plus_plus_03:
+    case DW_LANG_C_plus_plus_11:
+    case DW_LANG_C_plus_plus_14:
+    case DW_LANG_ObjC:
+    case DW_LANG_ObjC_plus_plus:
+    case DW_LANG_Java:
+    case DW_LANG_D:
+    case DW_LANG_Python:
+    case DW_LANG_UPC:
+    case DW_LANG_OpenCL:
+    case DW_LANG_Go:
+    case DW_LANG_Haskell:
+    case DW_LANG_OCaml:
+    case DW_LANG_Rust:
+    case DW_LANG_Swift:
+    case DW_LANG_Dylan:
+    case DW_LANG_RenderScript:
+    case DW_LANG_BLISS:
+      *result = 0;
+      return 0;
+
+    case DW_LANG_Ada83:
+    case DW_LANG_Ada95:
+    case DW_LANG_Cobol74:
+    case DW_LANG_Cobol85:
+    case DW_LANG_Fortran77:
+    case DW_LANG_Fortran90:
+    case DW_LANG_Fortran95:
+    case DW_LANG_Fortran03:
+    case DW_LANG_Fortran08:
+    case DW_LANG_Pascal83:
+    case DW_LANG_Modula2:
+    case DW_LANG_Modula3:
+    case DW_LANG_PLI:
+    case DW_LANG_Julia:
+      *result = 1;
+      return 0;
+
+    default:
+      __libdw_seterrno (DWARF_E_UNKNOWN_LANGUAGE);
+      return -1;
+    }
+}
+INTDEF (dwarf_default_lower_bound)
diff --git a/libdw/dwarf_die_addr_die.c b/libdw/dwarf_die_addr_die.c
new file mode 100644
index 0000000..6572916
--- /dev/null
+++ b/libdw/dwarf_die_addr_die.c
@@ -0,0 +1,70 @@
+/* Return offset of DIE.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_die_addr_die (Dwarf *dbg, void *addr, Dwarf_Die *result)
+{
+  if (dbg == NULL)
+    return NULL;
+
+  Dwarf_CU *cu = __libdw_findcu_addr (dbg, addr);
+
+  if (cu == NULL)
+    {
+      Dwarf *alt = INTUSE (dwarf_getalt) (dbg);
+      if (alt != NULL)
+	cu = __libdw_findcu_addr (alt, addr);
+    }
+
+  if (cu == NULL)
+    {
+      Dwarf *split = __libdw_find_split_dbg_addr (dbg, addr);
+      if (split != NULL)
+	cu = __libdw_findcu_addr (split, addr);
+    }
+
+  if (cu == NULL)
+    {
+      memset (result, '\0', sizeof (Dwarf_Die));
+      return NULL;
+    }
+
+  *result = (Dwarf_Die) { .addr = addr, .cu = cu };
+
+  return result;
+}
diff --git a/libdw/dwarf_diecu.c b/libdw/dwarf_diecu.c
new file mode 100644
index 0000000..5281c35
--- /dev/null
+++ b/libdw/dwarf_diecu.c
@@ -0,0 +1,52 @@
+/* Return CU DIE containing given DIE.
+   Copyright (C) 2005-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_diecu (Dwarf_Die *die, Dwarf_Die *result, uint8_t *address_sizep,
+	     uint8_t *offset_sizep)
+{
+  if (die == NULL)
+    return NULL;
+
+  *result = CUDIE (die->cu);
+
+  if (address_sizep != NULL)
+    *address_sizep = die->cu->address_size;
+  if (offset_sizep != NULL)
+    *offset_sizep = die->cu->offset_size;
+
+  return result;
+}
diff --git a/libdw/dwarf_diename.c b/libdw/dwarf_diename.c
new file mode 100644
index 0000000..96450c1
--- /dev/null
+++ b/libdw/dwarf_diename.c
@@ -0,0 +1,47 @@
+/* Return string in name attribute of DIE.
+   Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_diename (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+
+  return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr_integrate) (die,
+								 DW_AT_name,
+								 &attr_mem));
+}
+INTDEF (dwarf_diename)
diff --git a/libdw/dwarf_dieoffset.c b/libdw/dwarf_dieoffset.c
new file mode 100644
index 0000000..3a8e2cb
--- /dev/null
+++ b/libdw/dwarf_dieoffset.c
@@ -0,0 +1,45 @@
+/* Return offset of DIE.
+   Copyright (C) 2003-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Off
+dwarf_dieoffset (Dwarf_Die *die)
+{
+  return ((die == NULL || die->cu == NULL)
+	  ? (Dwarf_Off) -1
+	  : (Dwarf_Off) (die->addr - die->cu->startp + die->cu->start));
+}
+INTDEF(dwarf_dieoffset)
diff --git a/libdw/dwarf_end.c b/libdw/dwarf_end.c
new file mode 100644
index 0000000..ed8d27b
--- /dev/null
+++ b/libdw/dwarf_end.c
@@ -0,0 +1,179 @@
+/* Release debugging handling context.
+   Copyright (C) 2002-2011, 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <search.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+
+#include "libdwP.h"
+#include "cfi.h"
+
+
+static void
+dwarf_package_index_free (Dwarf_Package_Index *index)
+{
+  if (index != NULL)
+    {
+      free (index->debug_info_offsets);
+      free (index);
+    }
+}
+
+
+static void
+noop_free (void *arg __attribute__ ((unused)))
+{
+}
+
+
+static void
+cu_free (void *arg)
+{
+  struct Dwarf_CU *p = (struct Dwarf_CU *) arg;
+
+  tdestroy (p->locs, noop_free);
+
+  /* Only free the CU internals if its not a fake CU.  */
+  if(p != p->dbg->fake_loc_cu && p != p->dbg->fake_loclists_cu
+     && p != p->dbg->fake_addr_cu)
+    {
+      Dwarf_Abbrev_Hash_free (&p->abbrev_hash);
+
+      /* Free split dwarf one way (from skeleton to split).  */
+      if (p->unit_type == DW_UT_skeleton
+	  && p->split != NULL && p->split != (void *)-1)
+	{
+	  /* The fake_addr_cu might be shared, only release one.  */
+	  if (p->dbg->fake_addr_cu == p->split->dbg->fake_addr_cu)
+	    p->split->dbg->fake_addr_cu = NULL;
+	  /* There is only one DWP file. We free it later.  */
+	  if (p->split->dbg != p->dbg->dwp_dwarf)
+	    INTUSE(dwarf_end) (p->split->dbg);
+	}
+    }
+}
+
+
+int
+dwarf_end (Dwarf *dwarf)
+{
+  if (dwarf != NULL)
+    {
+      dwarf_package_index_free (dwarf->tu_index);
+      dwarf_package_index_free (dwarf->cu_index);
+
+      if (dwarf->cfi != NULL)
+	/* Clean up the CFI cache.  */
+	__libdw_destroy_frame_cache (dwarf->cfi);
+
+      Dwarf_Sig8_Hash_free (&dwarf->sig8_hash);
+
+      /* The search tree for the CUs.  NB: the CU data itself is
+	 allocated separately, but the abbreviation hash tables need
+	 to be handled.  */
+      tdestroy (dwarf->cu_tree, cu_free);
+      tdestroy (dwarf->tu_tree, cu_free);
+
+      /* Search tree for macro opcode tables.  */
+      tdestroy (dwarf->macro_ops, noop_free);
+
+      /* Search tree for decoded .debug_lines units.  */
+      tdestroy (dwarf->files_lines, noop_free);
+
+      /* And the split Dwarf.  */
+      tdestroy (dwarf->split_tree, noop_free);
+
+      /* Free the internally allocated memory.  */
+      for (size_t i = 0; i < dwarf->mem_stacks; i++)
+        {
+          struct libdw_memblock *memp = dwarf->mem_tails[i];
+          while (memp != NULL)
+	    {
+	      struct libdw_memblock *prevp = memp->prev;
+	      free (memp);
+	      memp = prevp;
+	    }
+        }
+      if (dwarf->mem_tails != NULL)
+        free (dwarf->mem_tails);
+      pthread_rwlock_destroy (&dwarf->mem_rwl);
+
+      /* Free the pubnames helper structure.  */
+      free (dwarf->pubnames_sets);
+
+      /* Free the ELF descriptor if necessary.  */
+      if (dwarf->free_elf)
+	elf_end (dwarf->elf);
+
+      /* Free the fake location list CU.  */
+      if (dwarf->fake_loc_cu != NULL)
+	{
+	  cu_free (dwarf->fake_loc_cu);
+	  free (dwarf->fake_loc_cu);
+	}
+      if (dwarf->fake_loclists_cu != NULL)
+	{
+	  cu_free (dwarf->fake_loclists_cu);
+	  free (dwarf->fake_loclists_cu);
+	}
+      if (dwarf->fake_addr_cu != NULL)
+	{
+	  cu_free (dwarf->fake_addr_cu);
+	  free (dwarf->fake_addr_cu);
+	}
+
+      /* Did we find and allocate the alt Dwarf ourselves?  */
+      if (dwarf->alt_fd != -1)
+	{
+	  INTUSE(dwarf_end) (dwarf->alt_dwarf);
+	  close (dwarf->alt_fd);
+	}
+
+      if (dwarf->dwp_fd != -1)
+	{
+	  INTUSE(dwarf_end) (dwarf->dwp_dwarf);
+	  close (dwarf->dwp_fd);
+	}
+
+      /* The cached path and dir we found the Dwarf ELF file in.  */
+      free (dwarf->elfpath);
+      free (dwarf->debugdir);
+
+      /* Free the context descriptor.  */
+      free (dwarf);
+    }
+
+  return 0;
+}
+INTDEF(dwarf_end)
diff --git a/libdw/dwarf_entry_breakpoints.c b/libdw/dwarf_entry_breakpoints.c
new file mode 100644
index 0000000..c3c0f39
--- /dev/null
+++ b/libdw/dwarf_entry_breakpoints.c
@@ -0,0 +1,163 @@
+/* Find entry breakpoint locations for a function.
+   Copyright (C) 2005-2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "libdwP.h"
+#include <dwarf.h>
+#include <stdlib.h>
+
+
+/* Add one breakpoint location to the result vector.  */
+static inline int
+add_bkpt (Dwarf_Addr pc, Dwarf_Addr **bkpts, int *pnbkpts)
+{
+  Dwarf_Addr *newlist = realloc (*bkpts, ++(*pnbkpts) * sizeof newlist[0]);
+  if (newlist == NULL)
+    {
+      free (*bkpts);
+      *bkpts = NULL;
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return -1;
+    }
+  newlist[*pnbkpts - 1] = pc;
+  *bkpts = newlist;
+  return *pnbkpts;
+}
+
+/* Fallback result, break at the entrypc/lowpc value.  */
+static inline int
+entrypc_bkpt (Dwarf_Die *die, Dwarf_Addr **bkpts, int *pnbkpts)
+{
+  Dwarf_Addr pc;
+  return INTUSE(dwarf_entrypc) (die, &pc) < 0 ? -1 : add_bkpt (pc, bkpts, pnbkpts);
+}
+
+/* Search a contiguous PC range for prologue-end markers.
+   If DWARF, look for proper markers.
+   Failing that, if ADHOC, look for the ad hoc convention.  */
+static inline int
+search_range (Dwarf_Addr low, Dwarf_Addr high,
+	      bool dwarf, bool adhoc,
+              Dwarf_Lines *lines, size_t nlines,
+              Dwarf_Addr **bkpts, int *pnbkpts)
+{
+      size_t l = 0, u = nlines;
+      while (l < u)
+	{
+	  size_t idx = (l + u) / 2;
+	  if (lines->info[idx].addr < low)
+	    l = idx + 1;
+	  else if (lines->info[idx].addr > low)
+	    u = idx;
+	  else if (lines->info[idx].end_sequence)
+	    l = idx + 1;
+	  else
+	    {
+	      l = idx;
+	      break;
+	    }
+	}
+      if (l < u)
+	{
+	  if (dwarf)
+	    for (size_t i = l; i < u && lines->info[i].addr < high; ++i)
+	      if (lines->info[i].prologue_end
+		  && add_bkpt (lines->info[i].addr, bkpts, pnbkpts) < 0)
+		return -1;
+	  if (adhoc && *pnbkpts == 0)
+	    while (++l < nlines && lines->info[l].addr < high)
+	      if (!lines->info[l].end_sequence)
+		return add_bkpt (lines->info[l].addr, bkpts, pnbkpts);
+	  return *pnbkpts;
+	}
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+}
+
+int
+dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts)
+{
+  int nbkpts = 0;
+  *bkpts = NULL;
+
+  /* Fetch the CU's line records to look for this DIE's addresses.  */
+  Dwarf_Die cudie = CUDIE (die->cu);
+  Dwarf_Lines *lines;
+  size_t nlines;
+  if (INTUSE(dwarf_getsrclines) (&cudie, &lines, &nlines) < 0)
+    {
+      int error = INTUSE (dwarf_errno) ();
+      if (error == 0)		/* CU has no DW_AT_stmt_list.  */
+	return entrypc_bkpt (die, bkpts, &nbkpts);
+      __libdw_seterrno (error);
+      return -1;
+    }
+
+  /* Search each contiguous address range for DWARF prologue_end markers.  */
+
+  Dwarf_Addr base;
+  Dwarf_Addr begin;
+  Dwarf_Addr end;
+  ptrdiff_t offset = INTUSE(dwarf_ranges) (die, 0, &base, &begin, &end);
+  if (offset < 0)
+    return -1;
+
+  /* Most often there is a single contiguous PC range for the DIE.  */
+  if (offset == 1)
+    return search_range (begin, end, true, true, lines, nlines, bkpts, &nbkpts)
+        ?: entrypc_bkpt (die, bkpts, &nbkpts);
+
+  Dwarf_Addr lowpc = (Dwarf_Addr) -1l;
+  Dwarf_Addr highpc = (Dwarf_Addr) -1l;
+  while (offset > 0)
+    {
+      /* We have an address range entry.  */
+      if (search_range (begin, end, true, false,
+                        lines, nlines, bkpts, &nbkpts) < 0)
+	return -1;
+
+      if (begin < lowpc)
+	{
+	  lowpc = begin;
+	  highpc = end;
+	}
+
+      offset = INTUSE(dwarf_ranges) (die, offset, &base, &begin, &end);
+    }
+
+  /* If we didn't find any proper DWARF markers, then look in the
+     lowest-addressed range for an ad hoc marker.  Failing that,
+     fall back to just using the entrypc value.  */
+  return (nbkpts
+	  ?: (lowpc == (Dwarf_Addr) -1l ? 0
+	      : search_range (lowpc, highpc, false, true,
+	                      lines, nlines, bkpts, &nbkpts))
+	  ?: entrypc_bkpt (die, bkpts, &nbkpts));
+}
diff --git a/libdw/dwarf_entrypc.c b/libdw/dwarf_entrypc.c
new file mode 100644
index 0000000..543567d
--- /dev/null
+++ b/libdw/dwarf_entrypc.c
@@ -0,0 +1,46 @@
+/* Return entry PC attribute of DIE.
+   Copyright (C) 2003, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_entrypc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+{
+  Dwarf_Attribute attr_mem, *attr;
+  if ((attr = INTUSE(dwarf_attr) (die, DW_AT_entry_pc, &attr_mem)) != NULL)
+    return INTUSE(dwarf_formaddr) (attr, return_addr);
+  else
+    return INTUSE(dwarf_lowpc) (die, return_addr);
+}
+INTDEF(dwarf_entrypc)
diff --git a/libdw/dwarf_error.c b/libdw/dwarf_error.c
new file mode 100644
index 0000000..0123cfa
--- /dev/null
+++ b/libdw/dwarf_error.c
@@ -0,0 +1,131 @@
+/* Retrieve ELF descriptor used for DWARF access.
+   Copyright (C) 2002-2005, 2009, 2014, 2015, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+
+#include "libdwP.h"
+
+
+/* The error number.  */
+static __thread int global_error;
+
+
+int
+dwarf_errno (void)
+{
+  int result = global_error;
+  global_error = DWARF_E_NOERROR;
+  return result;
+}
+INTDEF(dwarf_errno)
+
+
+/* XXX For now we use string pointers.  Once the table stablelizes
+   make it more DSO-friendly.  */
+static const char *errmsgs[] =
+  {
+    [DWARF_E_NOERROR] = N_("no error"),
+    [DWARF_E_UNKNOWN_ERROR] = N_("unknown error"),
+    [DWARF_E_INVALID_ACCESS] = N_("invalid access"),
+    [DWARF_E_NO_REGFILE] = N_("no regular file"),
+    [DWARF_E_IO_ERROR] = N_("I/O error"),
+    [DWARF_E_INVALID_ELF] = N_("invalid ELF file"),
+    [DWARF_E_NO_DWARF] = N_("no DWARF information"),
+    [DWARF_E_COMPRESSED_ERROR] = N_("cannot decompress DWARF"),
+    [DWARF_E_NOELF] = N_("no ELF file"),
+    [DWARF_E_GETEHDR_ERROR] = N_("cannot get ELF header"),
+    [DWARF_E_NOMEM] = N_("out of memory"),
+    [DWARF_E_UNIMPL] = N_("not implemented"),
+    [DWARF_E_INVALID_CMD] = N_("invalid command"),
+    [DWARF_E_INVALID_VERSION] = N_("invalid version"),
+    [DWARF_E_INVALID_FILE] = N_("invalid file"),
+    [DWARF_E_NO_ENTRY] = N_("no entries found"),
+    [DWARF_E_INVALID_DWARF] = N_("invalid DWARF"),
+    [DWARF_E_NO_STRING] = N_("no string data"),
+    [DWARF_E_NO_DEBUG_STR] = N_(".debug_str section missing"),
+    [DWARF_E_NO_DEBUG_LINE_STR] = N_(".debug_line_str section missing"),
+    [DWARF_E_NO_STR_OFFSETS] = N_(".debug_str_offsets section missing"),
+    [DWARF_E_NO_ADDR] = N_("no address value"),
+    [DWARF_E_NO_CONSTANT] = N_("no constant value"),
+    [DWARF_E_NO_REFERENCE] = N_("no reference value"),
+    [DWARF_E_INVALID_REFERENCE] = N_("invalid reference value"),
+    [DWARF_E_NO_DEBUG_LINE] = N_(".debug_line section missing"),
+    [DWARF_E_INVALID_DEBUG_LINE] = N_("invalid .debug_line section"),
+    [DWARF_E_TOO_BIG] = N_("debug information too big"),
+    [DWARF_E_VERSION] = N_("invalid DWARF version"),
+    [DWARF_E_INVALID_DIR_IDX] = N_("invalid directory index"),
+    [DWARF_E_ADDR_OUTOFRANGE] = N_("address out of range"),
+    [DWARF_E_NO_DEBUG_LOC] = N_(".debug_loc section missing"),
+    [DWARF_E_NO_DEBUG_LOCLISTS] = N_(".debug_loclists section missing"),
+    [DWARF_E_NO_LOC_VALUE] = N_("not a location list value"),
+    [DWARF_E_NO_BLOCK] = N_("no block data"),
+    [DWARF_E_INVALID_LINE_IDX] = N_("invalid line index"),
+    [DWARF_E_INVALID_ARANGE_IDX] = N_("invalid address range index"),
+    [DWARF_E_NO_MATCH] = N_("no matching address range"),
+    [DWARF_E_NO_FLAG] = N_("no flag value"),
+    [DWARF_E_INVALID_OFFSET] = N_("invalid offset"),
+    [DWARF_E_NO_DEBUG_RANGES] = N_(".debug_ranges section missing"),
+    [DWARF_E_NO_DEBUG_RNGLISTS] = N_(".debug_rnglists section missing"),
+    [DWARF_E_INVALID_CFI] = N_("invalid CFI section"),
+    [DWARF_E_NO_ALT_DEBUGLINK] = N_("no alternative debug link found"),
+    [DWARF_E_INVALID_OPCODE] = N_("invalid opcode"),
+    [DWARF_E_NOT_CUDIE] = N_("not a CU (unit) DIE"),
+    [DWARF_E_UNKNOWN_LANGUAGE] = N_("unknown language code"),
+    [DWARF_E_NO_DEBUG_ADDR] = N_(".debug_addr section missing"),
+    [DWARF_E_UNKNOWN_SECTION] = N_("unknown section"),
+  };
+#define nerrmsgs (sizeof (errmsgs) / sizeof (errmsgs[0]))
+
+
+void
+internal_function
+__libdw_seterrno (int value)
+{
+  global_error = (value >= 0 && value < (int) nerrmsgs
+		  ? value : DWARF_E_UNKNOWN_ERROR);
+}
+
+
+const char *
+dwarf_errmsg (int error)
+{
+  int last_error = global_error;
+
+  if (error == 0)
+    return last_error != 0 ? _(errmsgs[last_error]) : NULL;
+  else if (error < -1 || error >= (int) nerrmsgs)
+    return _(errmsgs[DWARF_E_UNKNOWN_ERROR]);
+
+  return _(errmsgs[error == -1 ? last_error : error]);
+}
+INTDEF(dwarf_errmsg)
diff --git a/libdw/dwarf_filesrc.c b/libdw/dwarf_filesrc.c
new file mode 100644
index 0000000..d866ce7
--- /dev/null
+++ b/libdw/dwarf_filesrc.c
@@ -0,0 +1,51 @@
+/* Find source file information.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+const char *
+dwarf_filesrc (Dwarf_Files *file, size_t idx, Dwarf_Word *mtime,
+	       Dwarf_Word *length)
+{
+  if (file == NULL || idx >= file->nfiles)
+    return NULL;
+
+  if (mtime != NULL)
+    *mtime = file->info[idx].mtime;
+
+  if (length != NULL)
+    *length = file->info[idx].length;
+
+  return file->info[idx].name;
+}
diff --git a/libdw/dwarf_formaddr.c b/libdw/dwarf_formaddr.c
new file mode 100644
index 0000000..9cd3d20
--- /dev/null
+++ b/libdw/dwarf_formaddr.c
@@ -0,0 +1,148 @@
+/* Return address represented by attribute.
+   Copyright (C) 2003-2010, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+__libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
+{
+  Dwarf_Off addr_off = __libdw_cu_addr_base (cu);
+  if (addr_off == (Dwarf_Off) -1)
+    return -1;
+
+  Dwarf *dbg = cu->dbg;
+  if (dbg->sectiondata[IDX_debug_addr] == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
+      return -1;
+    }
+
+  /* The section should at least contain room for one address.  */
+  int address_size = cu->address_size;
+  if (cu->address_size > dbg->sectiondata[IDX_debug_addr]->d_size)
+    {
+    invalid_offset:
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1;
+    }
+
+  if (addr_off > (dbg->sectiondata[IDX_debug_addr]->d_size
+		  - address_size))
+    goto invalid_offset;
+
+  idx *= address_size;
+  if (idx > (dbg->sectiondata[IDX_debug_addr]->d_size
+	     - address_size - addr_off))
+    goto invalid_offset;
+
+  const unsigned char *datap;
+  datap = dbg->sectiondata[IDX_debug_addr]->d_buf + addr_off + idx;
+  if (address_size == 4)
+    *addr = read_4ubyte_unaligned (dbg, datap);
+  else
+    *addr = read_8ubyte_unaligned (dbg, datap);
+
+  return 0;
+}
+
+int
+dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
+{
+  if (attr == NULL)
+    return -1;
+
+  Dwarf_Word idx;
+  Dwarf_CU *cu = attr->cu;
+  Dwarf *dbg = cu->dbg;
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
+  switch (attr->form)
+    {
+      /* There is one form that just encodes the whole address.  */
+      case DW_FORM_addr:
+	if (__libdw_read_address (dbg, cu_sec_idx (cu), datap,
+				  cu->address_size, return_addr))
+	  return -1;
+	return 0;
+
+      /* All others encode an index into the .debug_addr section where
+	 the address can be found.  */
+      case DW_FORM_GNU_addr_index:
+      case DW_FORM_addrx:
+	if (datap >= endp)
+	  {
+	  invalid:
+	    __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	    return -1;
+	  }
+	get_uleb128 (idx, datap, endp);
+	break;
+
+      case DW_FORM_addrx1:
+	if (datap >= endp - 1)
+	  goto invalid;
+	idx = *datap;
+	break;
+
+      case DW_FORM_addrx2:
+	if (datap >= endp - 2)
+	  goto invalid;
+	idx = read_2ubyte_unaligned (dbg, datap);
+	break;
+
+      case DW_FORM_addrx3:
+	if (datap >= endp - 3)
+	  goto invalid;
+	idx = read_3ubyte_unaligned (dbg, datap);
+	break;
+
+      case DW_FORM_addrx4:
+	if (datap >= endp - 4)
+	  goto invalid;
+	idx = read_4ubyte_unaligned (dbg, datap);
+	break;
+
+      default:
+	__libdw_seterrno (DWARF_E_NO_ADDR);
+	return -1;
+    }
+
+  /* So we got an index.  Lets see if it is valid and we can get the actual
+     address.  */
+  if (__libdw_addrx (cu, idx, return_addr) != 0)
+    return -1;
+
+  return 0;
+}
+INTDEF(dwarf_formaddr)
diff --git a/libdw/dwarf_formblock.c b/libdw/dwarf_formblock.c
new file mode 100644
index 0000000..924baf4
--- /dev/null
+++ b/libdw/dwarf_formblock.c
@@ -0,0 +1,103 @@
+/* Return block represented by attribute.
+   Copyright (C) 2004-2010, 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formblock (Dwarf_Attribute *attr, Dwarf_Block *return_block)
+{
+  if (attr == NULL)
+    return -1;
+
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
+
+  switch (attr->form)
+    {
+    case DW_FORM_block1:
+      if (unlikely (endp - datap < 1))
+	goto invalid;
+      return_block->length = *(uint8_t *) attr->valp;
+      return_block->data = attr->valp + 1;
+      break;
+
+    case DW_FORM_block2:
+      if (unlikely (endp - datap < 2))
+	goto invalid;
+      return_block->length = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+      return_block->data = attr->valp + 2;
+      break;
+
+    case DW_FORM_block4:
+      if (unlikely (endp - datap < 4))
+	goto invalid;
+      return_block->length = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      return_block->data = attr->valp + 4;
+      break;
+
+    case DW_FORM_block:
+    case DW_FORM_exprloc:
+      if (unlikely (endp - datap < 1))
+	goto invalid;
+      get_uleb128 (return_block->length, datap, endp);
+      return_block->data = (unsigned char *) datap;
+      break;
+
+    case DW_FORM_data16:
+      /* The DWARFv5 spec calls this constant class, but we interpret
+	 it as a block that the user will need to interpret when
+	 converting to a value.  */
+      if (unlikely (endp - datap < 16))
+	goto invalid;
+      return_block->length = 16;
+      return_block->data = (unsigned char *) datap;
+      break;
+
+    default:
+      __libdw_seterrno (DWARF_E_NO_BLOCK);
+      return -1;
+    }
+
+  if (unlikely (return_block->length > (size_t) (endp - return_block->data)))
+    {
+      /* Block does not fit.  */
+    invalid:
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  return 0;
+}
+INTDEF(dwarf_formblock)
diff --git a/libdw/dwarf_formflag.c b/libdw/dwarf_formflag.c
new file mode 100644
index 0000000..b48ede4
--- /dev/null
+++ b/libdw/dwarf_formflag.c
@@ -0,0 +1,59 @@
+/* Return flag represented by attribute.
+   Copyright (C) 2004-2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formflag (Dwarf_Attribute *attr, bool *return_bool)
+{
+  if (attr == NULL)
+    return -1;
+
+  if (attr->form == DW_FORM_flag_present)
+    {
+      *return_bool = true;
+      return 0;
+    }
+
+  if (unlikely (attr->form != DW_FORM_flag))
+    {
+      __libdw_seterrno (DWARF_E_NO_FLAG);
+      return -1;
+    }
+
+  *return_bool = *attr->valp != 0;
+
+  return 0;
+}
diff --git a/libdw/dwarf_formref.c b/libdw/dwarf_formref.c
new file mode 100644
index 0000000..2bae2a4
--- /dev/null
+++ b/libdw/dwarf_formref.c
@@ -0,0 +1,112 @@
+/* Return reference offset represented by attribute.
+   Copyright (C) 2003-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+int
+internal_function
+__libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
+{
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
+
+  if (attr->valp == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_REFERENCE);
+      return -1;
+    }
+
+  switch (attr->form)
+    {
+    case DW_FORM_ref1:
+      if (datap + 1 > endp)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      *return_offset = *attr->valp;
+      break;
+
+    case DW_FORM_ref2:
+      if (datap + 2 > endp)
+	goto invalid;
+      *return_offset = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_ref4:
+      if (datap + 4 > endp)
+	goto invalid;
+      *return_offset = read_4ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_ref8:
+      if (datap + 8 > endp)
+	goto invalid;
+      *return_offset = read_8ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_ref_udata:
+      if (datap + 1 > endp)
+	goto invalid;
+      get_uleb128 (*return_offset, datap, endp);
+      break;
+
+    case DW_FORM_ref_addr:
+    case DW_FORM_ref_sig8:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_ref_sup4:
+    case DW_FORM_ref_sup8:
+      /* These aren't handled by dwarf_formref, only by dwarf_formref_die.  */
+      __libdw_seterrno (DWARF_E_INVALID_REFERENCE);
+      return -1;
+
+    default:
+      __libdw_seterrno (DWARF_E_NO_REFERENCE);
+      return -1;
+    }
+
+  return 0;
+}
+
+/* This is the old public entry point.
+   It is now deprecated in favor of dwarf_formref_die.  */
+int
+dwarf_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
+{
+  if (attr == NULL)
+    return -1;
+
+  return __libdw_formref (attr, return_offset);
+}
diff --git a/libdw/dwarf_formref_die.c b/libdw/dwarf_formref_die.c
new file mode 100644
index 0000000..48ba819
--- /dev/null
+++ b/libdw/dwarf_formref_die.c
@@ -0,0 +1,137 @@
+/* Look up the DIE in a reference-form attribute.
+   Copyright (C) 2005-2010, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+Dwarf_Die *
+dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *result)
+{
+  if (attr == NULL)
+    return NULL;
+
+  struct Dwarf_CU *cu = attr->cu;
+
+  Dwarf_Off offset;
+  if (attr->form == DW_FORM_ref_addr || attr->form == DW_FORM_GNU_ref_alt
+      || attr->form == DW_FORM_ref_sup4 || attr->form == DW_FORM_ref_sup8)
+    {
+      /* This has an absolute offset.  */
+
+      uint8_t ref_size;
+      if (cu->version == 2 && attr->form == DW_FORM_ref_addr)
+	ref_size = cu->address_size;
+      else if (attr->form == DW_FORM_ref_sup4)
+	ref_size = 4;
+      else if (attr->form == DW_FORM_ref_sup8)
+	ref_size = 8;
+      else
+	ref_size = cu->offset_size;
+
+      Dwarf *dbg_ret = (attr->form == DW_FORM_GNU_ref_alt
+			? INTUSE(dwarf_getalt) (cu->dbg) : cu->dbg);
+
+      if (dbg_ret == NULL)
+	{
+	  __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
+	  return NULL;
+	}
+
+      if (__libdw_read_offset (cu->dbg, dbg_ret, IDX_debug_info, attr->valp,
+			       ref_size, &offset, IDX_debug_info, 0))
+	return NULL;
+
+      return INTUSE(dwarf_offdie) (dbg_ret, offset, result);
+    }
+
+  const unsigned char *datap;
+  size_t size;
+  if (attr->form == DW_FORM_ref_sig8)
+    {
+      /* This doesn't have an offset, but instead a value we
+	 have to match in the type unit headers.  */
+
+      uint64_t sig = read_8ubyte_unaligned (cu->dbg, attr->valp);
+      cu = Dwarf_Sig8_Hash_find (&cu->dbg->sig8_hash, sig);
+      if (cu == NULL)
+	{
+	  /* Not seen before.  We have to scan through the type units.
+	     Since DWARFv5 these can (also) be found in .debug_info,
+	     so scan that first.  */
+	  bool scan_debug_types = false;
+	  do
+	    {
+	      cu = __libdw_intern_next_unit (attr->cu->dbg, scan_debug_types);
+	      if (cu == NULL)
+		{
+		  if (scan_debug_types == false)
+		    scan_debug_types = true;
+		  else
+		    {
+		      __libdw_seterrno (INTUSE(dwarf_errno) ()
+					?: DWARF_E_INVALID_REFERENCE);
+		      return NULL;
+		    }
+		}
+	    }
+	  while (cu == NULL || cu->unit_id8 != sig);
+	}
+
+      int secid = cu_sec_idx (cu);
+      datap = cu->dbg->sectiondata[secid]->d_buf;
+      size = cu->dbg->sectiondata[secid]->d_size;
+      offset = cu->start + cu->subdie_offset;
+    }
+  else
+    {
+      /* Other forms produce an offset from the CU.  */
+      if (unlikely (__libdw_formref (attr, &offset) != 0))
+	return NULL;
+
+      datap = cu->startp;
+      size = cu->endp - cu->startp;
+    }
+
+  if (unlikely (offset >= size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  memset (result, '\0', sizeof (Dwarf_Die));
+  result->addr = (char *) datap + offset;
+  result->cu = cu;
+  return result;
+}
+INTDEF (dwarf_formref_die)
diff --git a/libdw/dwarf_formsdata.c b/libdw/dwarf_formsdata.c
new file mode 100644
index 0000000..def32c9
--- /dev/null
+++ b/libdw/dwarf_formsdata.c
@@ -0,0 +1,101 @@
+/* Return signed constant represented by attribute.
+   Copyright (C) 2003, 2005, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_sval)
+{
+  if (attr == NULL)
+    return -1;
+
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
+
+  switch (attr->form)
+    {
+    case DW_FORM_data1:
+      if (datap + 1 > endp)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      *return_sval = (signed char) *attr->valp;
+      break;
+
+    case DW_FORM_data2:
+      if (datap + 2 > endp)
+	goto invalid;
+      *return_sval = read_2sbyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data4:
+      if (datap + 4 > endp)
+	goto invalid;
+      *return_sval = read_4sbyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data8:
+      if (datap + 8 > endp)
+	goto invalid;
+      *return_sval = read_8sbyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_sdata:
+      if (datap + 1 > endp)
+	goto invalid;
+      get_sleb128 (*return_sval, datap, endp);
+      break;
+
+    case DW_FORM_udata:
+      if (datap + 1 > endp)
+	goto invalid;
+      get_uleb128 (*return_sval, datap, endp);
+      break;
+
+    case DW_FORM_implicit_const:
+      // The data comes from the abbrev, which has been bounds checked.
+      get_sleb128_unchecked (*return_sval, datap);
+      break;
+
+    default:
+      __libdw_seterrno (DWARF_E_NO_CONSTANT);
+      return -1;
+    }
+
+  return 0;
+}
+INTDEF(dwarf_formsdata)
diff --git a/libdw/dwarf_formstring.c b/libdw/dwarf_formstring.c
new file mode 100644
index 0000000..65f03a5
--- /dev/null
+++ b/libdw/dwarf_formstring.c
@@ -0,0 +1,183 @@
+/* Return string associated with given attribute.
+   Copyright (C) 2003-2010, 2013, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_formstring (Dwarf_Attribute *attrp)
+{
+  /* Ignore earlier errors.  */
+  if (attrp == NULL)
+    return NULL;
+
+  /* We found it.  Now determine where the string is stored.  */
+  if (attrp->form == DW_FORM_string)
+    /* A simple inlined string.  */
+    return (const char *) attrp->valp;
+
+  Dwarf_CU *cu = attrp->cu;
+  Dwarf *dbg = cu->dbg;
+  Dwarf *dbg_ret = ((attrp->form == DW_FORM_GNU_strp_alt
+		     || attrp->form == DW_FORM_strp_sup)
+		    ? INTUSE(dwarf_getalt) (dbg) : dbg);
+
+  if (unlikely (dbg_ret == NULL))
+    {
+      __libdw_seterrno (DWARF_E_NO_ALT_DEBUGLINK);
+      return NULL;
+    }
+
+  Elf_Data *data = ((attrp->form == DW_FORM_line_strp)
+		    ? dbg_ret->sectiondata[IDX_debug_line_str]
+		    : dbg_ret->sectiondata[IDX_debug_str]);
+  size_t data_size = ((attrp->form == DW_FORM_line_strp)
+		      ? dbg_ret->string_section_size[STR_SCN_IDX_debug_line_str]
+		      : dbg_ret->string_section_size[STR_SCN_IDX_debug_str]);
+  if (data == NULL)
+    {
+      __libdw_seterrno ((attrp->form == DW_FORM_line_strp)
+			? DWARF_E_NO_DEBUG_LINE_STR
+			: DWARF_E_NO_DEBUG_STR);
+      return NULL;
+    }
+
+  uint64_t off;
+  if (attrp->form == DW_FORM_strp
+      || attrp->form == DW_FORM_GNU_strp_alt
+      || attrp->form == DW_FORM_strp_sup)
+    {
+      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
+			       attrp->valp, cu->offset_size, &off,
+			       IDX_debug_str, 1))
+	return NULL;
+    }
+  else if (attrp->form == DW_FORM_line_strp)
+    {
+      if (__libdw_read_offset (dbg, dbg_ret, cu_sec_idx (cu),
+			       attrp->valp, cu->offset_size, &off,
+			       IDX_debug_line_str, 1))
+	return NULL;
+    }
+  else
+    {
+      Dwarf_Word idx;
+      const unsigned char *datap = attrp->valp;
+      const unsigned char *endp = cu->endp;
+      switch (attrp->form)
+	{
+	case DW_FORM_strx:
+	case DW_FORM_GNU_str_index:
+	  if (datap >= endp)
+	    {
+	    invalid:
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return NULL;
+	    }
+	  get_uleb128 (idx, datap, endp);
+	  break;
+
+	case DW_FORM_strx1:
+	  if (datap >= endp - 1)
+	    goto invalid;
+	  idx = *datap;
+	  break;
+
+	case DW_FORM_strx2:
+	  if (datap >= endp - 2)
+	    goto invalid;
+	  idx = read_2ubyte_unaligned (dbg, datap);
+	  break;
+
+	case DW_FORM_strx3:
+	  if (datap >= endp - 3)
+	    goto invalid;
+	  idx = read_3ubyte_unaligned (dbg, datap);
+	  break;
+
+	case DW_FORM_strx4:
+	  if (datap >= endp - 4)
+	    goto invalid;
+	  idx = read_4ubyte_unaligned (dbg, datap);
+	  break;
+
+	default:
+	  __libdw_seterrno (DWARF_E_NO_STRING);
+	  return NULL;
+	}
+
+      /* So we got an index in the .debug_str_offsets.  Lets see if it
+	 is valid and we can get the actual .debug_str offset.  */
+      Dwarf_Off str_off = __libdw_cu_str_off_base (cu);
+      if (str_off == (Dwarf_Off) -1)
+	return NULL;
+
+      if (dbg->sectiondata[IDX_debug_str_offsets] == NULL)
+	{
+	  __libdw_seterrno (DWARF_E_NO_STR_OFFSETS);
+	  return NULL;
+	}
+
+      /* The section should at least contain room for one offset.  */
+      int offset_size = cu->offset_size;
+      if (cu->offset_size > dbg->sectiondata[IDX_debug_str_offsets]->d_size)
+	{
+	invalid_offset:
+	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+	  return NULL;
+	}
+
+      /* And the base offset should be at least inside the section.  */
+      if (str_off > (dbg->sectiondata[IDX_debug_str_offsets]->d_size
+		     - offset_size))
+	goto invalid_offset;
+
+      size_t max_idx = (dbg->sectiondata[IDX_debug_str_offsets]->d_size
+			- offset_size - str_off) / offset_size;
+      if (idx > max_idx)
+	goto invalid_offset;
+
+      datap = (dbg->sectiondata[IDX_debug_str_offsets]->d_buf
+	       + str_off + (idx * offset_size));
+      if (offset_size == 4)
+	off = read_4ubyte_unaligned (dbg, datap);
+      else
+	off = read_8ubyte_unaligned (dbg, datap);
+    }
+
+  if (off >= data_size)
+    goto invalid_offset;
+
+  return (const char *) data->d_buf + off;
+}
+INTDEF(dwarf_formstring)
diff --git a/libdw/dwarf_formudata.c b/libdw/dwarf_formudata.c
new file mode 100644
index 0000000..26f86f1
--- /dev/null
+++ b/libdw/dwarf_formudata.c
@@ -0,0 +1,357 @@
+/* Return unsigned constant represented by attribute.
+   Copyright (C) 2003-2012, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+internal_function const unsigned char *
+__libdw_formptr (Dwarf_Attribute *attr, int sec_index,
+		 int err_nodata, const unsigned char **endpp,
+		 Dwarf_Off *offsetp)
+{
+  if (attr == NULL)
+    return NULL;
+
+  const Elf_Data *d = attr->cu->dbg->sectiondata[sec_index];
+  Dwarf_CU *skel = NULL; /* See below, needed for GNU DebugFission.  */
+  if (unlikely (d == NULL
+		&& sec_index == IDX_debug_ranges
+		&& attr->cu->version < 5
+		&& attr->cu->unit_type == DW_UT_split_compile))
+    {
+      skel = __libdw_find_split_unit (attr->cu);
+      if (skel != NULL)
+	d = skel->dbg->sectiondata[IDX_debug_ranges];
+    }
+
+  if (unlikely (d == NULL))
+    {
+      __libdw_seterrno (err_nodata);
+      return NULL;
+    }
+
+  Dwarf_Word offset;
+  if (attr->form == DW_FORM_sec_offset)
+    {
+      /* GNU DebugFission is slightly odd.  It uses DW_FORM_sec_offset
+	 in split units, but they are really (unrelocated) offsets
+	 from the skeleton DW_AT_GNU_ranges_base (which is only used
+	 for the split unit, not the skeleton ranges itself, see also
+	 DW_AT_rnglists_base, which is used in DWARF5 for both, but
+	 points to the offsets index).  So it isn't really a formptr,
+	 but an offset + base calculation.  */
+      if (unlikely (skel != NULL))
+	{
+	  Elf_Data *data = attr->cu->dbg->sectiondata[cu_sec_idx (attr->cu)];
+	  const unsigned char *datap = attr->valp;
+	  size_t size = attr->cu->offset_size;
+	  if (unlikely (data == NULL
+			|| datap < (const unsigned char *) data->d_buf
+			|| data->d_size < size
+			|| ((size_t) (datap
+				      - (const unsigned char *) data->d_buf)
+			    > data->d_size - size)))
+	    goto invalid;
+
+	  if (size == 4)
+	    offset = read_4ubyte_unaligned (attr->cu->dbg, datap);
+	  else
+	    offset = read_8ubyte_unaligned (attr->cu->dbg, datap);
+
+	  offset += __libdw_cu_ranges_base (skel);
+	}
+      else
+	{
+	  if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
+				   cu_sec_idx (attr->cu), attr->valp,
+				   attr->cu->offset_size, &offset,
+				   sec_index, 0))
+	    return NULL;
+	}
+    }
+  else if (attr->cu->version > 3)
+    goto invalid;
+  else
+    switch (attr->form)
+      {
+      case DW_FORM_data4:
+      case DW_FORM_data8:
+	if (__libdw_read_offset (attr->cu->dbg, attr->cu->dbg,
+				 cu_sec_idx (attr->cu),
+				 attr->valp,
+				 attr->form == DW_FORM_data4 ? 4 : 8,
+				 &offset, sec_index, 0))
+	  return NULL;
+	break;
+
+      default:
+	if (INTUSE(dwarf_formudata) (attr, &offset))
+	  return NULL;
+      };
+
+  unsigned char *readp = d->d_buf + offset;
+  unsigned char *endp = d->d_buf + d->d_size;
+  if (unlikely (readp >= endp))
+    {
+    invalid:
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  if (endpp != NULL)
+    *endpp = endp;
+  if (offsetp != NULL)
+    *offsetp = offset;
+  return readp;
+}
+
+int
+dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
+{
+  if (attr == NULL)
+    return -1;
+
+  const unsigned char *datap = attr->valp;
+  const unsigned char *endp = attr->cu->endp;
+
+  switch (attr->form)
+    {
+    case DW_FORM_data1:
+      if (datap + 1 > endp)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      *return_uval = *attr->valp;
+      break;
+
+    case DW_FORM_data2:
+      if (datap + 2 > endp)
+	goto invalid;
+      *return_uval = read_2ubyte_unaligned (attr->cu->dbg, attr->valp);
+      break;
+
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+    case DW_FORM_sec_offset:
+      /* Before DWARF4 data4 and data8 are pure constants unless the
+	 attribute also allows offsets (*ptr classes), since DWARF4
+	 they are always just constants (start_scope is special though,
+	 since it only could express a rangelist since DWARF4).  */
+      if (attr->form == DW_FORM_sec_offset
+	  || (attr->cu->version < 4 && attr->code != DW_AT_start_scope))
+	{
+	  switch (attr->code)
+	    {
+	    case DW_AT_data_member_location:
+	    case DW_AT_frame_base:
+	    case DW_AT_location:
+	    case DW_AT_return_addr:
+	    case DW_AT_segment:
+	    case DW_AT_static_link:
+	    case DW_AT_string_length:
+	    case DW_AT_use_location:
+	    case DW_AT_vtable_elem_location:
+	    case DW_AT_GNU_locviews:
+	    case DW_AT_loclists_base:
+	      if (attr->cu->version < 5)
+		{
+		  /* loclistptr */
+		  if (__libdw_formptr (attr, IDX_debug_loc,
+				       DWARF_E_NO_DEBUG_LOC, NULL,
+				       return_uval) == NULL)
+		    return -1;
+		}
+	      else
+		{
+		  /* loclist, loclistsptr */
+		  if (__libdw_formptr (attr, IDX_debug_loclists,
+				       DWARF_E_NO_DEBUG_LOCLISTS, NULL,
+				       return_uval) == NULL)
+		    return -1;
+		}
+	      break;
+
+	    case DW_AT_macro_info:
+	      /* macptr into .debug_macinfo */
+	      if (__libdw_formptr (attr, IDX_debug_macinfo,
+				   DWARF_E_NO_ENTRY, NULL,
+				   return_uval) == NULL)
+		return -1;
+	      break;
+
+	    case DW_AT_GNU_macros:
+	    case DW_AT_macros:
+	      /* macptr into .debug_macro */
+	      if (__libdw_formptr (attr, IDX_debug_macro,
+				   DWARF_E_NO_ENTRY, NULL,
+				   return_uval) == NULL)
+		return -1;
+	      break;
+
+	    case DW_AT_ranges:
+	    case DW_AT_start_scope:
+	    case DW_AT_GNU_ranges_base:
+	    case DW_AT_rnglists_base:
+	      if (attr->cu->version < 5)
+		{
+		  /* rangelistptr */
+		  if (__libdw_formptr (attr, IDX_debug_ranges,
+				       DWARF_E_NO_DEBUG_RANGES, NULL,
+				       return_uval) == NULL)
+		    return -1;
+		}
+	      else
+		{
+		  /* rnglistsptr */
+		  if (__libdw_formptr (attr, IDX_debug_rnglists,
+				       DWARF_E_NO_DEBUG_RNGLISTS, NULL,
+				       return_uval) == NULL)
+		    return -1;
+		}
+	      break;
+
+	    case DW_AT_stmt_list:
+	      /* lineptr */
+	      if (__libdw_formptr (attr, IDX_debug_line,
+				   DWARF_E_NO_DEBUG_LINE, NULL,
+				   return_uval) == NULL)
+		return -1;
+	      break;
+
+	    case DW_AT_addr_base:
+	    case DW_AT_GNU_addr_base:
+	      /* addrptr */
+	      if (__libdw_formptr (attr, IDX_debug_addr,
+				   DWARF_E_NO_DEBUG_ADDR, NULL,
+				   return_uval) == NULL)
+		return -1;
+	      break;
+
+	    case DW_AT_str_offsets_base:
+	      /* stroffsetsptr */
+	      if (__libdw_formptr (attr, IDX_debug_str_offsets,
+				   DWARF_E_NO_STR_OFFSETS, NULL,
+				   return_uval) == NULL)
+		return -1;
+	      break;
+
+	    default:
+	      /* sec_offset can only be used by one of the above attrs.  */
+	      if (attr->form == DW_FORM_sec_offset)
+		{
+		  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+		  return -1;
+		}
+
+	      /* Not one of the special attributes, just a constant.  */
+	      if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
+					attr->valp,
+					attr->form == DW_FORM_data4 ? 4 : 8,
+					return_uval))
+		return -1;
+	      break;
+	    }
+	}
+      else
+	{
+	  /* We are dealing with a constant data4 or data8.  */
+	  if (__libdw_read_address (attr->cu->dbg, cu_sec_idx (attr->cu),
+				    attr->valp,
+				    attr->form == DW_FORM_data4 ? 4 : 8,
+				    return_uval))
+	    return -1;
+	}
+      break;
+
+    case DW_FORM_sdata:
+      if (datap + 1 > endp)
+	goto invalid;
+      get_sleb128 (*return_uval, datap, endp);
+      break;
+
+    case DW_FORM_udata:
+    case DW_FORM_rnglistx:
+    case DW_FORM_loclistx:
+      if (datap + 1 > endp)
+	goto invalid;
+      get_uleb128 (*return_uval, datap, endp);
+      break;
+
+    case DW_FORM_implicit_const:
+      // The data comes from the abbrev, which has been bounds checked.
+      get_sleb128_unchecked (*return_uval, datap);
+      break;
+
+    /* These are indexes into the .debug_addr section, normally resolved
+       with dwarf_formaddr.  Here treat as constants.  */
+    case DW_FORM_GNU_addr_index:
+    case DW_FORM_addrx:
+      if (datap >= endp)
+	goto invalid;
+      get_uleb128 (*return_uval, datap, endp);
+      break;
+
+    case DW_FORM_addrx1:
+      if (datap >= endp - 1)
+	goto invalid;
+      *return_uval = *datap;
+      break;
+
+    case DW_FORM_addrx2:
+      if (datap >= endp - 2)
+	goto invalid;
+      *return_uval = read_2ubyte_unaligned (attr->cu->dbg, datap);
+      break;
+
+    case DW_FORM_addrx3:
+      if (datap >= endp - 3)
+	goto invalid;
+      *return_uval = read_3ubyte_unaligned (attr->cu->dbg, datap);
+      break;
+
+    case DW_FORM_addrx4:
+      if (datap >= endp - 4)
+	goto invalid;
+      *return_uval = read_4ubyte_unaligned (attr->cu->dbg, datap);
+      break;
+
+    default:
+      __libdw_seterrno (DWARF_E_NO_CONSTANT);
+      return -1;
+    }
+
+  return 0;
+}
+INTDEF(dwarf_formudata)
diff --git a/libdw/dwarf_frame_cfa.c b/libdw/dwarf_frame_cfa.c
new file mode 100644
index 0000000..07f998c
--- /dev/null
+++ b/libdw/dwarf_frame_cfa.c
@@ -0,0 +1,77 @@
+/* Get CFA expression for frame.
+   Copyright (C) 2009-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+#include <dwarf.h>
+#include <stdlib.h>
+
+int
+dwarf_frame_cfa (Dwarf_Frame *fs, Dwarf_Op **ops, size_t *nops)
+{
+  /* Maybe there was a previous error.  */
+  if (fs == NULL)
+    return -1;
+
+  int result = 0;
+  switch (fs->cfa_rule)
+    {
+    case cfa_undefined:
+      *ops = NULL;
+      *nops = 0;
+      break;
+
+    case cfa_offset:
+      /* The Dwarf_Op was already fully initialized by execute_cfi.  */
+      *ops = &fs->cfa_data.offset;
+      *nops = 1;
+      break;
+
+    case cfa_expr:
+      /* Parse the expression into internal form.  */
+      result = __libdw_intern_expression
+	(NULL, fs->cache->other_byte_order,
+	 fs->cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8, 4,
+	 &fs->cache->expr_tree, &fs->cfa_data.expr, false, false,
+	 ops, nops, IDX_debug_frame);
+      break;
+
+    case cfa_invalid:
+      __libdw_seterrno (DWARF_E_INVALID_CFI);
+      result = -1;
+      break;
+
+    default:
+      abort ();
+    }
+
+  return result;
+}
diff --git a/libdw/dwarf_frame_info.c b/libdw/dwarf_frame_info.c
new file mode 100644
index 0000000..9ba560f
--- /dev/null
+++ b/libdw/dwarf_frame_info.c
@@ -0,0 +1,50 @@
+/* Get return address register for frame.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+
+int
+dwarf_frame_info (Dwarf_Frame *fs, Dwarf_Addr *start, Dwarf_Addr *end,
+		  bool *signalp)
+{
+  /* Maybe there was a previous error.  */
+  if (fs == NULL)
+    return -1;
+
+  if (start != NULL)
+    *start = fs->start;
+  if (end != NULL)
+    *end = fs->end;
+  if (signalp != NULL)
+    *signalp = fs->fde->cie->signal_frame;
+  return fs->fde->cie->return_address_register;
+}
diff --git a/libdw/dwarf_frame_register.c b/libdw/dwarf_frame_register.c
new file mode 100644
index 0000000..a6b7c4c
--- /dev/null
+++ b/libdw/dwarf_frame_register.c
@@ -0,0 +1,124 @@
+/* Get register location expression for frame.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+#include <dwarf.h>
+
+int
+dwarf_frame_register (Dwarf_Frame *fs, int regno, Dwarf_Op ops_mem[3],
+		      Dwarf_Op **ops, size_t *nops)
+{
+  /* Maybe there was a previous error.  */
+  if (fs == NULL)
+    return -1;
+
+  if (unlikely (regno < 0))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ACCESS);
+      return -1;
+    }
+
+  *ops = ops_mem;
+  *nops = 0;
+
+  if (unlikely ((size_t) regno >= fs->nregs))
+    goto default_rule;
+
+  const struct dwarf_frame_register *reg = &fs->regs[regno];
+
+  switch (reg->rule)
+    {
+    case reg_unspecified:
+    default_rule:
+      /* Use the default rule for registers not yet mentioned in CFI.  */
+      if (fs->cache->default_same_value)
+	goto same_value;
+      FALLTHROUGH;
+    case reg_undefined:
+      /* The value is known to be unavailable.  */
+      break;
+
+    case reg_same_value:
+    same_value:
+      /* The location is not known here, but the caller might know it.  */
+      *ops = NULL;
+      break;
+
+    case reg_offset:
+    case reg_val_offset:
+      ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_call_frame_cfa };
+      if (reg->value != 0)
+	ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_plus_uconst,
+					  .number = reg->value };
+      if (reg->rule == reg_val_offset)
+	/* A value, not a location.  */
+	ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_stack_value };
+      *ops = ops_mem;
+      break;
+
+    case reg_register:
+      ops_mem[(*nops)++] = (Dwarf_Op) { .atom = DW_OP_regx,
+					.number = reg->value };
+      break;
+
+    case reg_val_expression:
+    case reg_expression:
+      {
+	unsigned int address_size = (fs->cache->e_ident[EI_CLASS] == ELFCLASS32
+				     ? 4 : 8);
+
+	Dwarf_Block block;
+	const uint8_t *p = fs->cache->data->d.d_buf + reg->value;
+	const uint8_t *end = (fs->cache->data->d.d_buf
+			      + fs->cache->data->d.d_size);
+	if (p >= end)
+	  {
+	    __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	    return -1;
+	  }
+	get_uleb128 (block.length, p, end);
+	block.data = (void *) p;
+
+	/* Parse the expression into internal form.  */
+	if (__libdw_intern_expression (NULL,
+				       fs->cache->other_byte_order,
+				       address_size, 4,
+				       &fs->cache->expr_tree, &block,
+				       true, reg->rule == reg_val_expression,
+				       ops, nops, IDX_debug_frame) < 0)
+	  return -1;
+	break;
+      }
+    }
+
+  return 0;
+}
diff --git a/libdw/dwarf_func_inline.c b/libdw/dwarf_func_inline.c
new file mode 100644
index 0000000..1f04adf
--- /dev/null
+++ b/libdw/dwarf_func_inline.c
@@ -0,0 +1,101 @@
+/* Convenience functions for handling DWARF descriptions of inline functions.
+   Copyright (C) 2005,2006,2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+struct visitor_info
+{
+  void *die_addr;
+  int (*callback) (Dwarf_Die *, void *);
+  void *arg;
+};
+
+static int
+scope_visitor (unsigned int depth __attribute__ ((unused)),
+	       struct Dwarf_Die_Chain *die, void *arg)
+{
+  struct visitor_info *const v = arg;
+
+  if (INTUSE(dwarf_tag) (&die->die) != DW_TAG_inlined_subroutine)
+    return DWARF_CB_OK;
+
+  Dwarf_Attribute attr_mem;
+  Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&die->die, DW_AT_abstract_origin,
+					      &attr_mem);
+  if (attr == NULL)
+    return DWARF_CB_OK;
+
+  Dwarf_Die origin_mem;
+  Dwarf_Die *origin = INTUSE(dwarf_formref_die) (attr, &origin_mem);
+  if (origin == NULL)
+    return DWARF_CB_ABORT;
+
+  if (origin->addr != v->die_addr)
+    return DWARF_CB_OK;
+
+  return (*v->callback) (&die->die, v->arg);
+}
+
+int
+dwarf_func_inline (Dwarf_Die *func)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word val;
+  if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (func, DW_AT_inline,
+						   &attr_mem),
+			       &val) == 0)
+  switch (val)
+    {
+    case DW_INL_not_inlined:
+      return 0;
+
+    case DW_INL_declared_not_inlined:
+      return -1;
+
+    case DW_INL_inlined:
+    case DW_INL_declared_inlined:
+      return 1;
+    }
+
+  return 0;
+}
+
+int
+dwarf_func_inline_instances (Dwarf_Die *func,
+			     int (*callback) (Dwarf_Die *, void *),
+			     void *arg)
+{
+  struct visitor_info v = { func->addr, callback, arg };
+  struct Dwarf_Die_Chain cu = { .die = CUDIE (func->cu), .parent = NULL };
+  return __libdw_visit_scopes (0, &cu, NULL, &scope_visitor, NULL, &v);
+}
diff --git a/libdw/dwarf_get_units.c b/libdw/dwarf_get_units.c
new file mode 100644
index 0000000..407ed2b
--- /dev/null
+++ b/libdw/dwarf_get_units.c
@@ -0,0 +1,132 @@
+/* Iterate through the CU units for a given Dwarf.
+   Copyright (C) 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+
+#include "libdwP.h"
+
+int
+dwarf_get_units (Dwarf *dwarf, Dwarf_CU *cu, Dwarf_CU **next_cu,
+		 Dwarf_Half *version, uint8_t *unit_type,
+		 Dwarf_Die *cudie, Dwarf_Die *subdie)
+{
+  /* Handle existing error.  */
+  if (dwarf == NULL)
+    return -1;
+
+  Dwarf_Off off;
+  bool v4type;
+  if (cu == NULL)
+    {
+      off = 0;
+      v4type = false;
+    }
+  else
+    {
+      off = cu->end;
+      v4type = cu->sec_idx != IDX_debug_info;
+
+      /* Make sure we got a real (not fake) CU.  */
+      if (cu->sec_idx != IDX_debug_info && cu->sec_idx != IDX_debug_types)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+	  return -1;
+	}
+
+      /* Do we have to switch to the other section, or are we at the end?  */
+      if (! v4type)
+	{
+	  if (off >= cu->dbg->sectiondata[IDX_debug_info]->d_size)
+	    {
+	      if (cu->dbg->sectiondata[IDX_debug_types] == NULL)
+		return 1;
+
+	      off = 0;
+	      v4type = true;
+	    }
+	}
+      else
+	if (off >= cu->dbg->sectiondata[IDX_debug_types]->d_size)
+	  return 1;
+    }
+
+  *next_cu = __libdw_findcu (dwarf, off, v4type);
+  if (*next_cu == NULL)
+    return -1;
+
+  Dwarf_CU *next = (*next_cu);
+
+  if (version != NULL)
+    *version = next->version;
+
+  if (unit_type != NULL)
+    *unit_type = next->unit_type;
+
+  if (cudie != NULL)
+    {
+      if (next->version >= 2 && next->version <= 5
+	  && next->unit_type >= DW_UT_compile
+	  && next->unit_type <= DW_UT_split_type)
+	*cudie = CUDIE (next);
+      else
+	memset (cudie, '\0', sizeof (Dwarf_Die));
+    }
+
+  if (subdie != NULL)
+    {
+      if (next->version >= 2 && next->version <= 5)
+	{
+	  /* For types, return the actual type DIE.  For skeletons,
+	     find the associated split compile unit and return its
+	     DIE.  */
+	  if (next->unit_type == DW_UT_type
+	      || next->unit_type == DW_UT_split_type)
+	    *subdie = SUBDIE(next);
+	  else if (next->unit_type == DW_UT_skeleton)
+	    {
+	      Dwarf_CU *split_cu = __libdw_find_split_unit (next);
+	      if (split_cu != NULL)
+		*subdie = CUDIE(split_cu);
+	      else
+		memset (subdie, '\0', sizeof (Dwarf_Die));
+	    }
+	  else
+	    memset (subdie, '\0', sizeof (Dwarf_Die));
+	}
+      else
+	memset (subdie, '\0', sizeof (Dwarf_Die));
+    }
+
+  return 0;
+}
+INTDEF(dwarf_get_units)
diff --git a/libdw/dwarf_getabbrev.c b/libdw/dwarf_getabbrev.c
new file mode 100644
index 0000000..5b02333
--- /dev/null
+++ b/libdw/dwarf_getabbrev.c
@@ -0,0 +1,187 @@
+/* Get abbreviation at given offset.
+   Copyright (C) 2003, 2004, 2005, 2006, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Abbrev *
+internal_function
+__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu, Dwarf_Off offset,
+		   size_t *lengthp, Dwarf_Abbrev *result)
+{
+  /* Don't fail if there is not .debug_abbrev section.  */
+  if (dbg->sectiondata[IDX_debug_abbrev] == NULL)
+    return NULL;
+
+  if (offset >= dbg->sectiondata[IDX_debug_abbrev]->d_size)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return NULL;
+    }
+
+  const unsigned char *abbrevp
+    = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset;
+
+  if (*abbrevp == '\0')
+    /* We are past the last entry.  */
+    return DWARF_END_ABBREV;
+
+  /* 7.5.3 Abbreviations Tables
+
+     [...] Each declaration begins with an unsigned LEB128 number
+     representing the abbreviation code itself.  [...]  The
+     abbreviation code is followed by another unsigned LEB128
+     number that encodes the entry's tag.  [...]
+
+     [...] Following the tag encoding is a 1-byte value that
+     determines whether a debugging information entry using this
+     abbreviation has child entries or not. [...]
+
+     [...] Finally, the child encoding is followed by a series of
+     attribute specifications. Each attribute specification
+     consists of two parts. The first part is an unsigned LEB128
+     number representing the attribute's name. The second part is
+     an unsigned LEB128 number representing the attribute's form.  */
+  const unsigned char *end = (dbg->sectiondata[IDX_debug_abbrev]->d_buf
+			      + dbg->sectiondata[IDX_debug_abbrev]->d_size);
+  const unsigned char *start_abbrevp = abbrevp;
+  unsigned int code;
+  // We start off with abbrevp at offset, which is checked above.
+  get_uleb128 (code, abbrevp, end);
+
+  /* Check whether this code is already in the hash table.  */
+  bool foundit = false;
+  Dwarf_Abbrev *abb = NULL;
+  if (cu == NULL
+      || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code)) == NULL)
+    {
+      if (result == NULL)
+	abb = libdw_typed_alloc (dbg, Dwarf_Abbrev);
+      else
+	abb = result;
+    }
+  else
+    {
+      foundit = true;
+
+      if (unlikely (abb->offset != offset))
+	{
+	  /* A duplicate abbrev code at a different offset,
+	     that should never happen.  */
+	invalid:
+	  if (! foundit)
+	    libdw_typed_unalloc (dbg, Dwarf_Abbrev);
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return NULL;
+	}
+
+      /* If the caller doesn't need the length we are done.  */
+      if (lengthp == NULL)
+	goto out;
+    }
+
+  /* If there is already a value in the hash table we are going to
+     overwrite its content.  This must not be a problem, since the
+     content better be the same.  */
+  abb->code = code;
+  if (abbrevp >= end)
+    goto invalid;
+  get_uleb128 (abb->tag, abbrevp, end);
+  if (abbrevp + 1 >= end)
+    goto invalid;
+  abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
+  abb->attrp = (unsigned char *) abbrevp;
+  abb->offset = offset;
+
+  /* Skip over all the attributes and check rest of the abbrev is valid.  */
+  unsigned int attrname;
+  unsigned int attrform;
+  do
+    {
+      if (abbrevp >= end)
+	goto invalid;
+      get_uleb128 (attrname, abbrevp, end);
+      if (abbrevp >= end)
+	goto invalid;
+      get_uleb128 (attrform, abbrevp, end);
+      if (attrform == DW_FORM_implicit_const)
+	{
+	  int64_t formval __attribute__((__unused__));
+	  if (abbrevp >= end)
+	    goto invalid;
+	  get_sleb128 (formval, abbrevp, end);
+	}
+    }
+  while (attrname != 0 || attrform != 0);
+
+  /* Return the length to the caller if she asked for it.  */
+  if (lengthp != NULL)
+    *lengthp = abbrevp - start_abbrevp;
+
+  /* Add the entry to the hash table.  */
+  if (cu != NULL && ! foundit)
+    if (Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb) == -1)
+      {
+	/* The entry was already in the table, remove the one we just
+	   created and get the one already inserted.  */
+	libdw_typed_unalloc (dbg, Dwarf_Abbrev);
+	abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code);
+      }
+
+ out:
+  return abb;
+}
+
+
+Dwarf_Abbrev *
+dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset, size_t *lengthp)
+{
+  if (die == NULL || die->cu == NULL)
+    return NULL;
+
+  Dwarf_CU *cu = die->cu;
+  Dwarf *dbg = cu->dbg;
+  Dwarf_Off abbrev_offset = cu->orig_abbrev_offset;
+  Elf_Data *data = dbg->sectiondata[IDX_debug_abbrev];
+  if (data == NULL)
+    return NULL;
+
+  if (offset >= data->d_size - abbrev_offset)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return NULL;
+    }
+
+  return __libdw_getabbrev (dbg, cu, abbrev_offset + offset, lengthp, NULL);
+}
diff --git a/libdw/dwarf_getabbrevattr.c b/libdw/dwarf_getabbrevattr.c
new file mode 100644
index 0000000..54ff604
--- /dev/null
+++ b/libdw/dwarf_getabbrevattr.c
@@ -0,0 +1,94 @@
+/* Get specific attribute of abbreviation.
+   Copyright (C) 2003, 2004, 2005, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_getabbrevattr_data (Dwarf_Abbrev *abbrev, size_t idx,
+			  unsigned int *namep, unsigned int *formp,
+			  Dwarf_Sword *datap, Dwarf_Off *offsetp)
+{
+  if (abbrev == NULL)
+    return -1;
+
+  size_t cnt = 0;
+  const unsigned char *attrp = abbrev->attrp;
+  const unsigned char *start_attrp;
+  unsigned int name;
+  unsigned int form;
+  Dwarf_Word data;
+
+  do
+    {
+      start_attrp = attrp;
+
+      /* Attribute code and form are encoded as ULEB128 values.
+         Already checked when Dwarf_Abbrev was created, read unchecked.  */
+      get_uleb128_unchecked (name, attrp);
+      get_uleb128_unchecked (form, attrp);
+
+      if (form == DW_FORM_implicit_const)
+	get_sleb128_unchecked (data, attrp);
+      else
+	data = 0;
+
+      /* If both values are zero the index is out of range.  */
+      if (name == 0 && form == 0)
+	return -1;
+    }
+  while (cnt++ < idx);
+
+  /* Store the result if requested.  */
+  if (namep != NULL)
+    *namep = name;
+  if (formp != NULL)
+    *formp = form;
+  if (datap != NULL)
+    *datap = data;
+  if (offsetp != NULL)
+    *offsetp = (start_attrp - abbrev->attrp) + abbrev->offset;
+
+  return 0;
+}
+INTDEF(dwarf_getabbrevattr_data)
+
+int
+dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx, unsigned int *namep,
+		     unsigned int *formp, Dwarf_Off *offsetp)
+{
+  return INTUSE(dwarf_getabbrevattr_data) (abbrev, idx, namep, formp,
+					   NULL, offsetp);
+}
diff --git a/libdw/dwarf_getabbrevcode.c b/libdw/dwarf_getabbrevcode.c
new file mode 100644
index 0000000..8691708
--- /dev/null
+++ b/libdw/dwarf_getabbrevcode.c
@@ -0,0 +1,43 @@
+/* Get abbreviation code.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_getabbrevcode (Dwarf_Abbrev *abbrev)
+{
+  return abbrev == NULL ? 0 : abbrev->code;
+}
diff --git a/libdw/dwarf_getabbrevtag.c b/libdw/dwarf_getabbrevtag.c
new file mode 100644
index 0000000..52aaa3f
--- /dev/null
+++ b/libdw/dwarf_getabbrevtag.c
@@ -0,0 +1,43 @@
+/* Get abbreviation tag.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_getabbrevtag (Dwarf_Abbrev *abbrev)
+{
+  return abbrev == NULL ? 0 : abbrev->tag;
+}
diff --git a/libdw/dwarf_getalt.c b/libdw/dwarf_getalt.c
new file mode 100644
index 0000000..0a12dfa
--- /dev/null
+++ b/libdw/dwarf_getalt.c
@@ -0,0 +1,184 @@
+/* Retrieves the DWARF descriptor for debugaltlink data.
+   Copyright (C) 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include "libelfP.h"
+#include "libdwelfP.h"
+#include "system.h"
+
+#include <inttypes.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+
+char *
+internal_function
+__libdw_filepath (const char *debugdir, const char *dir, const char *file)
+{
+  if (file == NULL)
+    return NULL;
+
+  if (file[0] == '/')
+    return strdup (file);
+
+  if (dir != NULL && dir[0] == '/')
+    {
+      size_t dirlen = strlen (dir);
+      size_t filelen = strlen (file);
+      size_t len = dirlen + 1 + filelen + 1;
+      char *path = malloc (len);
+      if (path != NULL)
+	{
+	  char *c = mempcpy (path, dir, dirlen);
+	  if (dir[dirlen - 1] != '/')
+	    *c++ = '/';
+	  mempcpy (c, file, filelen + 1);
+	}
+      return path;
+    }
+
+  if (debugdir != NULL)
+    {
+      size_t debugdirlen = strlen (debugdir);
+      size_t dirlen = dir != NULL ? strlen (dir) : 0;
+      size_t filelen = strlen (file);
+      size_t len = debugdirlen + 1 + dirlen + 1 + filelen + 1;
+      char *path = malloc (len);
+      if (path != NULL)
+	{
+	  char *c = mempcpy (path, debugdir, debugdirlen);
+	  if (dirlen > 0)
+	    {
+	      c = mempcpy (c, dir, dirlen);
+	      if (dir[dirlen - 1] != '/')
+		*c++ = '/';
+	    }
+	  mempcpy (c, file, filelen + 1);
+	  return path;
+	}
+    }
+
+  return NULL;
+}
+
+static void
+find_debug_altlink (Dwarf *dbg)
+{
+  const char *altname;
+  const void *build_id;
+  ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (dbg,
+							       &altname,
+							       &build_id);
+
+  /* Couldn't even get the debugaltlink.  It probably doesn't exist.  */
+  if (build_id_len <= 0)
+    return;
+
+  const uint8_t *id = (const uint8_t *) build_id;
+  size_t id_len = build_id_len;
+  int fd = -1;
+
+  /* We only look in the standard path.  And relative to the dbg file.  */
+#define DEBUGINFO_PATH "/usr/lib/debug"
+
+  /* We don't handle very short or really large build-ids.  We need at
+     at least 3 and allow for up to 64 (normally ids are 20 long).  */
+#define MIN_BUILD_ID_BYTES 3
+#define MAX_BUILD_ID_BYTES 64
+  if (id_len >= MIN_BUILD_ID_BYTES && id_len <= MAX_BUILD_ID_BYTES)
+    {
+      /* Note sizeof a string literal includes the trailing zero.  */
+      char id_path[sizeof DEBUGINFO_PATH - 1 + sizeof "/.build-id/" - 1
+		   + 2 + 1 + (MAX_BUILD_ID_BYTES - 1) * 2 + sizeof ".debug"];
+      sprintf (&id_path[0], "%s%s", DEBUGINFO_PATH, "/.build-id/");
+      sprintf (&id_path[sizeof DEBUGINFO_PATH - 1 + sizeof "/.build-id/" - 1],
+	       "%02" PRIx8 "/", (uint8_t) id[0]);
+      for (size_t i = 1; i < id_len; ++i)
+	sprintf (&id_path[sizeof DEBUGINFO_PATH - 1 + sizeof "/.build-id/" - 1
+			  + 3 + (i - 1) * 2], "%02" PRIx8, (uint8_t) id[i]);
+      strcpy (&id_path[sizeof DEBUGINFO_PATH - 1 + sizeof "/.build-id/" - 1
+		       + 3 + (id_len - 1) * 2], ".debug");
+
+      fd = TEMP_FAILURE_RETRY (open (id_path, O_RDONLY));
+    }
+
+  /* Fall back on (possible relative) alt file path.  */
+  if (fd < 0)
+    {
+      char *altpath = __libdw_filepath (dbg->debugdir, NULL, altname);
+      if (altpath != NULL)
+	{
+	  fd = TEMP_FAILURE_RETRY (open (altpath, O_RDONLY));
+	  free (altpath);
+	}
+    }
+
+  if (fd >= 0)
+    {
+      Dwarf *alt = dwarf_begin (fd, O_RDONLY);
+      if (alt != NULL)
+	{
+	  dbg->alt_dwarf = alt;
+	  dbg->alt_fd = fd;
+	}
+      else
+	close (fd);
+    }
+}
+
+Dwarf *
+dwarf_getalt (Dwarf *main)
+{
+  /* Only try once.  */
+  if (main == NULL || main->alt_dwarf == (void *) -1)
+    return NULL;
+
+  if (main->alt_dwarf != NULL)
+    return main->alt_dwarf;
+
+  find_debug_altlink (main);
+
+  /* If we found nothing, make sure we don't try again.  */
+  if (main->alt_dwarf == NULL)
+    {
+      main->alt_dwarf = (void *) -1;
+      return NULL;
+    }
+
+  return main->alt_dwarf;
+}
+INTDEF (dwarf_getalt)
diff --git a/libdw/dwarf_getarange_addr.c b/libdw/dwarf_getarange_addr.c
new file mode 100644
index 0000000..d383e22
--- /dev/null
+++ b/libdw/dwarf_getarange_addr.c
@@ -0,0 +1,60 @@
+/* Get address range which includes given address.
+   Copyright (C) 2004, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+Dwarf_Arange *
+dwarf_getarange_addr (Dwarf_Aranges *aranges, Dwarf_Addr addr)
+{
+  if (aranges == NULL)
+    return NULL;
+
+  /* The ranges are sorted by address, so we can use binary search.  */
+  size_t l = 0, u = aranges->naranges;
+  while (l < u)
+    {
+      size_t idx = (l + u) / 2;
+      if (addr < aranges->info[idx].addr)
+	u = idx;
+      else if (addr > aranges->info[idx].addr
+	       && addr - aranges->info[idx].addr >= aranges->info[idx].length)
+	l = idx + 1;
+      else
+	return &aranges->info[idx];
+    }
+
+  __libdw_seterrno (DWARF_E_NO_MATCH);
+  return NULL;
+}
+INTDEF(dwarf_getarange_addr)
diff --git a/libdw/dwarf_getarangeinfo.c b/libdw/dwarf_getarangeinfo.c
new file mode 100644
index 0000000..67b6e67
--- /dev/null
+++ b/libdw/dwarf_getarangeinfo.c
@@ -0,0 +1,53 @@
+/* Return list address ranges.
+   Copyright (C) 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+int
+dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp,
+		     Dwarf_Word *lengthp, Dwarf_Off *offsetp)
+{
+  if (arange == NULL)
+    return -1;
+
+  if (addrp != NULL)
+    *addrp = arange->addr;
+  if (lengthp != NULL)
+    *lengthp = arange->length;
+  if (offsetp != NULL)
+    *offsetp = arange->offset;
+
+  return 0;
+}
+INTDEF(dwarf_getarangeinfo)
diff --git a/libdw/dwarf_getaranges.c b/libdw/dwarf_getaranges.c
new file mode 100644
index 0000000..7a3cd36
--- /dev/null
+++ b/libdw/dwarf_getaranges.c
@@ -0,0 +1,390 @@
+/* Return list address ranges.
+   Copyright (C) 2000-2010, 2016, 2017 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include "libdwP.h"
+#include <dwarf.h>
+
+struct arangelist
+{
+  Dwarf_Arange arange;
+  struct arangelist *next;
+};
+
+/* Compare by Dwarf_Arange.addr, given pointers into an array of pointeers.  */
+static int
+compare_aranges (const void *a, const void *b)
+{
+  struct arangelist *const *p1 = a, *const *p2 = b;
+  struct arangelist *l1 = *p1, *l2 = *p2;
+  if (l1->arange.addr != l2->arange.addr)
+    return (l1->arange.addr < l2->arange.addr) ? -1 : 1;
+  return 0;
+}
+
+/* Convert ARANGELIST into Dwarf_Aranges and store at ARANGES.  */
+static bool
+finalize_aranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges,
+		  struct arangelist *arangelist, unsigned int narangelist)
+{
+  /* Allocate the array for the result.  */
+  void *buf = libdw_alloc (dbg, Dwarf_Aranges,
+			   sizeof (Dwarf_Aranges)
+			   + narangelist * sizeof (Dwarf_Arange), 1);
+
+  /* First use the buffer for the pointers, and sort the entries.
+     We'll write the pointers in the end of the buffer, and then
+     copy into the buffer from the beginning so the overlap works.  */
+  eu_static_assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
+  struct arangelist **sortaranges
+    = (buf + sizeof (Dwarf_Aranges)
+       + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
+
+  /* The list is in LIFO order and usually they come in clumps with
+     ascending addresses.  So fill from the back to probably start with
+     runs already in order before we sort.  */
+  unsigned int i = narangelist;
+  while (i-- > 0)
+    {
+      sortaranges[i] = arangelist;
+      arangelist = arangelist->next;
+    }
+
+  /* Something went wrong if narangelist is less then the actual length
+     of arangelist. */
+  if (arangelist != NULL)
+    {
+      __libdw_seterrno (DWARF_E_UNKNOWN_ERROR);
+      return false;
+    }
+
+  /* Sort by ascending address.  */
+  qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
+
+  /* Now that they are sorted, put them in the final array.
+     The buffers overlap, so we've clobbered the early elements
+     of SORTARANGES by the time we're reading the later ones.  */
+  *aranges = buf;
+  (*aranges)->dbg = dbg;
+  (*aranges)->naranges = narangelist;
+  if (naranges != NULL)
+    *naranges = narangelist;
+  for (i = 0; i < narangelist; ++i)
+    {
+      struct arangelist *elt = sortaranges[i];
+      (*aranges)->info[i] = elt->arange;
+      free (elt);
+    }
+
+  return true;
+}
+
+int
+__libdw_getdieranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
+{
+  if (dbg == NULL)
+    return -1;
+
+  if (dbg->dieranges != NULL)
+    {
+      *aranges = dbg->dieranges;
+      if (naranges != NULL)
+	*naranges = dbg->dieranges->naranges;
+      return 0;
+    }
+
+  struct arangelist *arangelist = NULL;
+  unsigned int narangelist = 0;
+
+  Dwarf_CU *cu = NULL;
+  while (INTUSE(dwarf_get_units) (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
+    {
+      Dwarf_Addr base;
+      Dwarf_Addr low;
+      Dwarf_Addr high;
+
+      Dwarf_Die cudie = CUDIE (cu);
+
+      /* Skip CUs that only contain type information.  */
+      if (!INTUSE(dwarf_hasattr) (&cudie, DW_AT_low_pc)
+	  && !INTUSE(dwarf_hasattr) (&cudie, DW_AT_ranges))
+	continue;
+
+      ptrdiff_t offset = 0;
+
+      /* Add arange for each range list entry or high_pc and low_pc.  */
+      while ((offset = INTUSE(dwarf_ranges) (&cudie, offset,
+					     &base, &low, &high)) > 0)
+	{
+	  if (offset == -1)
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      goto fail;
+	    }
+
+	  struct arangelist *new_arange = malloc (sizeof *new_arange);
+	  if (unlikely (new_arange == NULL))
+	    {
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      goto fail;
+	    }
+
+	  new_arange->arange.addr = low;
+	  new_arange->arange.length = (Dwarf_Word) (high - low);
+	  new_arange->arange.offset = __libdw_first_die_off_from_cu (cu);
+
+	  new_arange->next = arangelist;
+	  arangelist = new_arange;
+	  ++narangelist;
+	}
+    }
+
+  if (narangelist == 0)
+    {
+      if (naranges != NULL)
+	*naranges = 0;
+      *aranges = NULL;
+      return 0;
+    }
+
+  if (!finalize_aranges (dbg, aranges, naranges, arangelist, narangelist))
+    goto fail;
+
+  dbg->dieranges = *aranges;
+  return 0;
+
+fail:
+  while (arangelist != NULL)
+    {
+      struct arangelist *next = arangelist->next;
+      free (arangelist);
+      arangelist = next;
+    }
+  return -1;
+}
+
+int
+dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
+{
+  if (dbg == NULL)
+    return -1;
+
+  if (dbg->aranges != NULL)
+    {
+      *aranges = dbg->aranges;
+      if (naranges != NULL)
+	*naranges = dbg->aranges->naranges;
+      return 0;
+    }
+
+  if (dbg->sectiondata[IDX_debug_aranges] == NULL)
+    {
+      /* No such section.  */
+      *aranges = NULL;
+      if (naranges != NULL)
+	*naranges = 0;
+      return 0;
+    }
+
+  if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
+    return -1;
+
+  struct arangelist *arangelist = NULL;
+  unsigned int narangelist = 0;
+
+  const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf;
+  const unsigned char *readendp
+    = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
+
+  while (readp < readendp)
+    {
+      const unsigned char *hdrstart = readp;
+
+      /* Each entry starts with a header:
+
+	 1. A 4-byte or 12-byte length containing the length of the
+	 set of entries for this compilation unit, not including the
+	 length field itself. [...]
+
+	 2. A 2-byte version identifier containing the value 2 for
+	 DWARF Version 2.1.
+
+	 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
+
+	 4. A 1-byte unsigned integer containing the size in bytes of
+	 an address (or the offset portion of an address for segmented
+	 addressing) on the target system.
+
+	 5. A 1-byte unsigned integer containing the size in bytes of
+	 a segment descriptor on the target system.  */
+      if (unlikely (readp + 4 > readendp))
+	goto invalid;
+
+      Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
+      unsigned int length_bytes = 4;
+      if (length == DWARF3_LENGTH_64_BIT)
+	{
+	  if (unlikely (readp + 8 > readendp))
+	    goto invalid;
+
+	  length = read_8ubyte_unaligned_inc (dbg, readp);
+	  length_bytes = 8;
+	}
+      else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
+			 && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
+	goto invalid;
+
+      const unsigned char *endp = readp + length;
+      if (unlikely (endp > readendp))
+	goto invalid;
+
+      if (unlikely (readp + 2 > readendp))
+	goto invalid;
+
+      unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
+      if (version != 2)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	fail:
+	  while (arangelist != NULL)
+	    {
+	      struct arangelist *next = arangelist->next;
+	      free (arangelist);
+	      arangelist = next;
+	    }
+	  return -1;
+	}
+
+      Dwarf_Word offset = 0;
+      if (__libdw_read_offset_inc (dbg,
+				   IDX_debug_aranges, &readp,
+				   length_bytes, &offset, IDX_debug_info, 4))
+	goto fail;
+
+      /* Next up two bytes for address and segment size.  */
+      if (readp + 2 > readendp)
+	goto invalid;
+
+      unsigned int address_size = *readp++;
+      if (unlikely (address_size != 4 && address_size != 8))
+	goto invalid;
+
+      /* We don't actually support segment selectors.  */
+      unsigned int segment_size = *readp++;
+      if (segment_size != 0)
+	goto invalid;
+
+      /* Round the address to the next multiple of 2*address_size.  */
+      readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
+		% (2 * address_size));
+
+      while (1)
+	{
+	  Dwarf_Word range_address;
+	  Dwarf_Word range_length;
+
+	  if (__libdw_read_address_inc (dbg, IDX_debug_aranges, &readp,
+					address_size, &range_address))
+	    goto fail;
+
+	  if (readp + address_size > readendp)
+	    goto invalid;
+
+	  if (address_size == 4)
+	    range_length = read_4ubyte_unaligned_inc (dbg, readp);
+	  else
+	    range_length = read_8ubyte_unaligned_inc (dbg, readp);
+
+	  /* Two zero values mark the end.  But in some cases (bugs)
+	     there might be such entries in the middle of the table.
+	     Ignore and continue, we'll check the actual length of
+	     the table to see if we are really at the end.  */
+	  if (range_address == 0 && range_length == 0)
+	    {
+	      if (readp >= endp)
+		break;
+	      else
+		continue;
+	    }
+
+	  /* We don't use alloca for these temporary structures because
+	     the total number of them can be quite large.  */
+	  struct arangelist *new_arange = malloc (sizeof *new_arange);
+	  if (unlikely (new_arange == NULL))
+	    {
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      goto fail;
+	    }
+
+	  new_arange->arange.addr = range_address;
+	  new_arange->arange.length = range_length;
+
+	  /* We store the actual CU DIE offset, not the CU header offset.  */
+	  Dwarf_CU *cu = __libdw_findcu (dbg, offset, false);
+	  if (unlikely (cu == NULL))
+	    {
+	      /* We haven't gotten a chance to link in the new_arange
+		 into the arangelist, don't leak it.  */
+	      free (new_arange);
+	      goto fail;
+	    }
+	  new_arange->arange.offset = __libdw_first_die_off_from_cu (cu);
+
+	  new_arange->next = arangelist;
+	  arangelist = new_arange;
+	  ++narangelist;
+
+	  /* Sanity-check the data.  */
+	  if (unlikely (new_arange->arange.offset
+			>= dbg->sectiondata[IDX_debug_info]->d_size))
+	    goto invalid;
+	}
+    }
+
+  if (narangelist == 0)
+    {
+      if (naranges != NULL)
+	*naranges = 0;
+      *aranges = NULL;
+      return 0;
+    }
+
+  if (!finalize_aranges (dbg, aranges, naranges, arangelist, narangelist))
+    goto fail;
+
+  dbg->aranges = *aranges;
+  return 0;
+}
+INTDEF(dwarf_getaranges)
diff --git a/libdw/dwarf_getattrcnt.c b/libdw/dwarf_getattrcnt.c
new file mode 100644
index 0000000..a05976d
--- /dev/null
+++ b/libdw/dwarf_getattrcnt.c
@@ -0,0 +1,61 @@
+/* Get number of attributes of abbreviation.
+   Copyright (C) 2003, 2004, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_getattrcnt (Dwarf_Abbrev *abbrev, size_t *attrcntp)
+{
+  if (abbrev == NULL)
+    return -1;
+
+  const unsigned char *abbrevp = abbrev->attrp;
+
+  /* Skip over all the attributes and count them while doing so.  */
+  int attrcnt = 0;
+  unsigned int attrname;
+  unsigned int attrform;
+  do
+    {
+      /* We can use unchecked since they were checked when the Dwrf_Abbrev
+	 was created.  */
+      get_uleb128_unchecked (attrname, abbrevp);
+      get_uleb128_unchecked (attrform, abbrevp);
+    }
+  while (attrname != 0 && attrform != 0 && ++attrcnt);
+
+  *attrcntp = attrcnt;
+
+  return 0;
+}
diff --git a/libdw/dwarf_getattrs.c b/libdw/dwarf_getattrs.c
new file mode 100644
index 0000000..770c32c
--- /dev/null
+++ b/libdw/dwarf_getattrs.c
@@ -0,0 +1,132 @@
+/* Get attributes of the DIE.
+   Copyright (C) 2004, 2005, 2008, 2009, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+ptrdiff_t
+dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
+		void *arg, ptrdiff_t offset)
+{
+  if (die == NULL)
+    return -1l;
+
+  if (unlikely (offset == 1))
+    return 1;
+
+  const unsigned char *die_addr = NULL;
+
+  /* Find the abbreviation entry.  */
+  Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &die_addr);
+
+  if (unlikely (abbrevp == DWARF_END_ABBREV))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1l;
+    }
+
+  const unsigned char *endp = die->cu->endp;
+
+  /* This is where the attributes start.  */
+  const unsigned char *attrp = abbrevp->attrp;
+  const unsigned char *const offset_attrp = abbrevp->attrp + offset;
+
+  /* Go over the list of attributes.  */
+  while (1)
+    {
+      /* Get attribute name and form.  Dwarf_Abbrev was checked when
+	 created, so we can read unchecked.  */
+      Dwarf_Attribute attr;
+      const unsigned char *remembered_attrp = attrp;
+
+      get_uleb128_unchecked (attr.code, attrp);
+      get_uleb128_unchecked (attr.form, attrp);
+
+      /* We can stop if we found the attribute with value zero.  */
+      if (attr.code == 0 && attr.form == 0)
+	/* Do not return 0 here - there would be no way to
+	   distinguish this value from the attribute at offset 0.
+	   Instead we return +1 which would never be a valid
+	   offset of an attribute.  */
+        return 1l;
+
+      if (attr.form == DW_FORM_indirect)
+	{
+	  get_uleb128 (attr.form, die_addr, endp);
+	  if (attr.form == DW_FORM_indirect ||
+	      attr.form == DW_FORM_implicit_const)
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return -1l;
+	    }
+	}
+
+      /* If we are not to OFFSET_ATTRP yet, we just have to skip
+	 the values of the intervening attributes.  */
+      if (remembered_attrp >= offset_attrp)
+	{
+	  /* Fill in the rest.  */
+	  if (attr.form == DW_FORM_implicit_const)
+	    attr.valp = (unsigned char *) attrp;
+	  else
+	    attr.valp = (unsigned char *) die_addr;
+	  attr.cu = die->cu;
+
+	  /* Now call the callback function.  */
+	  if (callback (&attr, arg) != DWARF_CB_OK)
+	    /* Return the offset of the start of the attribute, so that
+	       dwarf_getattrs() can be restarted from this point if the
+	       caller so desires.  */
+	    return remembered_attrp - abbrevp->attrp;
+	}
+
+      /* Skip over the rest of this attribute (if there is any).  */
+      if (attr.form != 0)
+	{
+	  size_t len = __libdw_form_val_len (die->cu, attr.form, die_addr);
+	  if (unlikely (len == (size_t) -1l))
+	    /* Something wrong with the file.  */
+	    return -1l;
+
+	  // __libdw_form_val_len will have done a bounds check.
+	  die_addr += len;
+
+	  if (attr.form == DW_FORM_implicit_const)
+	    {
+	      int64_t attr_value __attribute__((__unused__));
+	      get_sleb128_unchecked (attr_value, attrp);
+	    }
+	}
+    }
+  /* NOTREACHED */
+}
diff --git a/libdw/dwarf_getcfi.c b/libdw/dwarf_getcfi.c
new file mode 100644
index 0000000..afa8a46
--- /dev/null
+++ b/libdw/dwarf_getcfi.c
@@ -0,0 +1,78 @@
+/* Get CFI from DWARF file.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include "cfi.h"
+#include <dwarf.h>
+
+Dwarf_CFI *
+dwarf_getcfi (Dwarf *dbg)
+{
+  if (dbg == NULL)
+    return NULL;
+
+  if (dbg->cfi == NULL && dbg->sectiondata[IDX_debug_frame] != NULL)
+    {
+      Dwarf_CFI *cfi = libdw_typed_alloc (dbg, Dwarf_CFI);
+
+      cfi->dbg = dbg;
+      cfi->data = (Elf_Data_Scn *) dbg->sectiondata[IDX_debug_frame];
+
+      cfi->search_table = NULL;
+      cfi->search_table_vaddr = 0;
+      cfi->search_table_entries = 0;
+      cfi->search_table_encoding = DW_EH_PE_omit;
+
+      cfi->frame_vaddr = 0;
+      cfi->textrel = 0;
+      cfi->datarel = 0;
+
+      cfi->e_ident = (unsigned char *) elf_getident (dbg->elf, NULL);
+
+      GElf_Ehdr ehdr;
+      gelf_getehdr (dbg->elf, &ehdr);
+      cfi->e_machine = ehdr.e_machine;
+
+      cfi->other_byte_order = dbg->other_byte_order;
+      cfi->default_same_value = false;
+
+      cfi->next_offset = 0;
+      cfi->cie_tree = cfi->fde_tree = cfi->expr_tree = NULL;
+
+      cfi->ebl = NULL;
+
+      dbg->cfi = cfi;
+    }
+
+  return dbg->cfi;
+}
+INTDEF (dwarf_getcfi)
diff --git a/libdw/dwarf_getcfi_elf.c b/libdw/dwarf_getcfi_elf.c
new file mode 100644
index 0000000..c0e3cad
--- /dev/null
+++ b/libdw/dwarf_getcfi_elf.c
@@ -0,0 +1,338 @@
+/* Get CFI from ELF file's exception-handling info.
+   Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "libdwP.h"
+#include "cfi.h"
+#include "encoded-value.h"
+#include <dwarf.h>
+
+
+static Dwarf_CFI *
+allocate_cfi (Elf *elf, const GElf_Ehdr *ehdr, GElf_Addr vaddr)
+{
+  Dwarf_CFI *cfi = calloc (1, sizeof *cfi);
+  if (cfi == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  cfi->e_ident = (unsigned char *) elf_getident (elf, NULL);
+  if (cfi->e_ident == NULL)
+    {
+      free (cfi);
+      __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
+      return NULL;
+    }
+
+  cfi->e_machine = ehdr->e_machine;
+
+  if ((BYTE_ORDER == LITTLE_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2MSB)
+      || (BYTE_ORDER == BIG_ENDIAN && cfi->e_ident[EI_DATA] == ELFDATA2LSB))
+    cfi->other_byte_order = true;
+
+  cfi->frame_vaddr = vaddr;
+  cfi->textrel = 0;		/* XXX ? */
+  cfi->datarel = 0;		/* XXX ? */
+
+  return cfi;
+}
+
+static const uint8_t *
+parse_eh_frame_hdr (const uint8_t *hdr, size_t hdr_size, GElf_Addr hdr_vaddr,
+		    const GElf_Ehdr *ehdr, GElf_Addr *eh_frame_vaddr,
+		    size_t *table_entries, uint8_t *table_encoding)
+{
+  const uint8_t *h = hdr;
+
+  if (hdr_size < 4 || *h++ != 1)		/* version */
+    return (void *) -1l;
+
+  uint8_t eh_frame_ptr_encoding = *h++;
+  uint8_t fde_count_encoding = *h++;
+  uint8_t fde_table_encoding = *h++;
+
+  if (eh_frame_ptr_encoding == DW_EH_PE_omit)
+    return (void *) -1l;
+
+  /* Dummy used by read_encoded_value.  */
+  Elf_Data_Scn dummy_cfi_hdr_data =
+    {
+      .d = { .d_buf = (void *) hdr, .d_size = hdr_size }
+    };
+  Dwarf_CFI dummy_cfi =
+    {
+      .e_ident = ehdr->e_ident,
+      .datarel = hdr_vaddr,
+      .frame_vaddr = hdr_vaddr,
+      .data = &dummy_cfi_hdr_data,
+    };
+
+  if (unlikely (read_encoded_value (&dummy_cfi, eh_frame_ptr_encoding, &h,
+				    eh_frame_vaddr)))
+    return (void *) -1l;
+
+  if (fde_count_encoding != DW_EH_PE_omit)
+    {
+      Dwarf_Word fde_count;
+      if (unlikely (read_encoded_value (&dummy_cfi, fde_count_encoding, &h,
+					&fde_count)))
+	return (void *) -1l;
+      if (fde_count != 0 && (size_t) fde_count == fde_count
+	  && fde_table_encoding != DW_EH_PE_omit
+	  && (fde_table_encoding &~ DW_EH_PE_signed) != DW_EH_PE_uleb128)
+	{
+	  *table_entries = fde_count;
+	  *table_encoding = fde_table_encoding;
+	  return h;
+	}
+    }
+
+  return NULL;
+}
+
+static Dwarf_CFI *
+getcfi_gnu_eh_frame (Elf *elf, const GElf_Ehdr *ehdr, const GElf_Phdr *phdr)
+{
+  Elf_Data *data = elf_getdata_rawchunk (elf, phdr->p_offset, phdr->p_filesz,
+					 ELF_T_BYTE);
+  if (data == NULL || data->d_buf == NULL)
+    {
+    invalid_hdr:
+      /* XXX might be read error or corrupt phdr */
+      __libdw_seterrno (DWARF_E_INVALID_CFI);
+      return NULL;
+    }
+
+  size_t vsize, dmax;
+  Dwarf_Addr eh_frame_ptr;
+  size_t search_table_entries = 0;
+  uint8_t search_table_encoding = 0;
+  const uint8_t *search_table = parse_eh_frame_hdr (data->d_buf, phdr->p_filesz,
+						    phdr->p_vaddr, ehdr,
+						    &eh_frame_ptr,
+						    &search_table_entries,
+						    &search_table_encoding);
+
+  /* Make sure there is enough room for the entries in the table,
+     each entry consists of 2 encoded values.  */
+  vsize = encoded_value_size (data, ehdr->e_ident, search_table_encoding,
+			      NULL);
+  dmax = phdr->p_filesz - (search_table - (const uint8_t *) data->d_buf);
+  if (unlikely (search_table == (void *) -1l
+		|| vsize == 0
+		|| search_table_entries > (dmax / vsize) / 2))
+    goto invalid_hdr;
+
+  Dwarf_Off eh_frame_offset = eh_frame_ptr - phdr->p_vaddr + phdr->p_offset;
+  Dwarf_Word eh_frame_size = 0;
+
+  /* XXX we have no way without section headers to know the size
+     of the .eh_frame data.  Calculate the largest it might possibly be.
+     This won't be wasteful if the file is already mmap'd, but if it isn't
+     it might be quite excessive.  */
+  size_t filesize;
+  if (elf_rawfile (elf, &filesize) != NULL)
+    eh_frame_size = filesize - eh_frame_offset;
+
+  data = elf_getdata_rawchunk (elf, eh_frame_offset, eh_frame_size, ELF_T_BYTE);
+  if (data == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ELF); /* XXX might be read error */
+      return NULL;
+    }
+  Dwarf_CFI *cfi = allocate_cfi (elf, ehdr, eh_frame_ptr);
+  if (cfi != NULL)
+    {
+      cfi->data = (Elf_Data_Scn *) data;
+
+      if (search_table != NULL)
+	{
+	  cfi->search_table = search_table;
+	  cfi->search_table_len = phdr->p_filesz;
+	  cfi->search_table_vaddr = phdr->p_vaddr;
+	  cfi->search_table_encoding = search_table_encoding;
+	  cfi->search_table_entries = search_table_entries;
+	}
+    }
+  return cfi;
+}
+
+/* Search the phdrs for PT_GNU_EH_FRAME.  */
+static Dwarf_CFI *
+getcfi_phdr (Elf *elf, const GElf_Ehdr *ehdr)
+{
+  size_t phnum;
+  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+    return NULL;
+
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (unlikely (phdr == NULL))
+	return NULL;
+      if (phdr->p_type == PT_GNU_EH_FRAME)
+	return getcfi_gnu_eh_frame (elf, ehdr, phdr);
+    }
+
+  __libdw_seterrno (DWARF_E_NO_DWARF);
+  return NULL;
+}
+
+static Dwarf_CFI *
+getcfi_scn_eh_frame (Elf *elf, const GElf_Ehdr *ehdr,
+		     Elf_Scn *scn, GElf_Shdr *shdr,
+		     Elf_Scn *hdr_scn, GElf_Addr hdr_vaddr)
+{
+  Elf_Data *data = elf_rawdata (scn, NULL);
+  if (data == NULL || data->d_buf == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ELF);
+      return NULL;
+    }
+  Dwarf_CFI *cfi = allocate_cfi (elf, ehdr, shdr->sh_addr);
+  if (cfi != NULL)
+    {
+      cfi->data = (Elf_Data_Scn *) data;
+      if (hdr_scn != NULL)
+	{
+	  Elf_Data *hdr_data = elf_rawdata (hdr_scn, NULL);
+	  if (hdr_data != NULL && hdr_data->d_buf != NULL)
+	    {
+	      size_t vsize, dmax;
+	      GElf_Addr eh_frame_vaddr;
+	      cfi->search_table_vaddr = hdr_vaddr;
+	      cfi->search_table
+		= parse_eh_frame_hdr (hdr_data->d_buf, hdr_data->d_size,
+				      hdr_vaddr, ehdr, &eh_frame_vaddr,
+				      &cfi->search_table_entries,
+				      &cfi->search_table_encoding);
+	      cfi->search_table_len = hdr_data->d_size;
+
+	      /* Make sure there is enough room for the entries in the table,
+		 each entry consists of 2 encoded values.  */
+	      vsize = encoded_value_size (hdr_data, ehdr->e_ident,
+					  cfi->search_table_encoding, NULL);
+	      dmax = hdr_data->d_size - (cfi->search_table
+					 - (const uint8_t *) hdr_data->d_buf);
+	      if (unlikely (cfi->search_table == (void *) -1l
+			    || vsize == 0
+			    || cfi->search_table_entries > (dmax / vsize) / 2))
+		{
+		  free (cfi);
+		  /* XXX might be read error or corrupt phdr */
+		  __libdw_seterrno (DWARF_E_INVALID_CFI);
+		  return NULL;
+		}
+
+	      /* Sanity check.  */
+	      if (unlikely (eh_frame_vaddr != shdr->sh_addr))
+		cfi->search_table = NULL;
+	    }
+	}
+    }
+  return cfi;
+}
+
+/* Search for the sections named ".eh_frame" and ".eh_frame_hdr".  */
+static Dwarf_CFI *
+getcfi_shdr (Elf *elf, const GElf_Ehdr *ehdr)
+{
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) != 0)
+    {
+      __libdw_seterrno (DWARF_E_GETEHDR_ERROR);
+      return NULL;
+    }
+
+  if (shstrndx != 0)
+    {
+      Elf_Scn *hdr_scn = NULL;
+      GElf_Addr hdr_vaddr = 0;
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    continue;
+	  const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
+	  if (name == NULL)
+	    continue;
+	  if (!strcmp (name, ".eh_frame_hdr"))
+	    {
+	      hdr_scn = scn;
+	      hdr_vaddr = shdr->sh_addr;
+	    }
+	  else if (!strcmp (name, ".eh_frame"))
+	    {
+	      if (shdr->sh_type != SHT_NOBITS)
+		return getcfi_scn_eh_frame (elf, ehdr, scn, shdr,
+					    hdr_scn, hdr_vaddr);
+	      else
+		return NULL;
+	    }
+	}
+    }
+
+  return (void *) -1l;
+}
+
+Dwarf_CFI *
+dwarf_getcfi_elf (Elf *elf)
+{
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      __libdw_seterrno (DWARF_E_NOELF);
+      return NULL;
+    }
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (unlikely (ehdr == NULL))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ELF);
+      return NULL;
+    }
+
+  Dwarf_CFI *result = getcfi_shdr (elf, ehdr);
+  if (result == (void *) -1l)
+    result = getcfi_phdr (elf, ehdr);
+
+  return result;
+}
+INTDEF (dwarf_getcfi_elf)
diff --git a/libdw/dwarf_getelf.c b/libdw/dwarf_getelf.c
new file mode 100644
index 0000000..2d6268e
--- /dev/null
+++ b/libdw/dwarf_getelf.c
@@ -0,0 +1,47 @@
+/* Retrieve ELF descriptor used for DWARF access.
+   Copyright (C) 2002, 2004, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include "libdwP.h"
+
+
+Elf *
+dwarf_getelf (Dwarf *dwarf)
+{
+  if (dwarf == NULL)
+    /* Some error occurred before.  */
+    return NULL;
+
+  return dwarf->elf;
+}
diff --git a/libdw/dwarf_getfuncs.c b/libdw/dwarf_getfuncs.c
new file mode 100644
index 0000000..b95f06f
--- /dev/null
+++ b/libdw/dwarf_getfuncs.c
@@ -0,0 +1,118 @@
+/* Get function information.
+   Copyright (C) 2005, 2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+struct visitor_info
+{
+  /* The user callback of dwarf_getfuncs.  */
+  int (*callback) (Dwarf_Die *, void *);
+
+  /* The user arg value to dwarf_getfuncs.  */
+  void *arg;
+
+  /* Addr of the DIE offset where to (re)start the search.  Zero for all.  */
+  void *start_addr;
+
+  /* Last subprogram DIE addr seen.  */
+  void *last_addr;
+
+  /* The CU only contains C functions.  Allows pruning of most subtrees.  */
+  bool c_cu;
+};
+
+static int
+tree_visitor (unsigned int depth __attribute__ ((unused)),
+	      struct Dwarf_Die_Chain *chain, void *arg)
+{
+  struct visitor_info *const v = arg;
+  Dwarf_Die *die = &chain->die;
+  void *start_addr = v->start_addr;
+  void *die_addr = die->addr;
+
+  /* Pure C CUs can only contain defining subprogram DIEs as direct
+     children of the CU DIE or as nested function inside a normal C
+     code constructs.  */
+  int tag = INTUSE(dwarf_tag) (die);
+  if (v->c_cu
+      && tag != DW_TAG_subprogram
+      && tag != DW_TAG_lexical_block
+      && tag != DW_TAG_inlined_subroutine)
+    {
+      chain->prune = true;
+      return DWARF_CB_OK;
+    }
+
+  /* Skip all DIEs till we found the (re)start addr.  */
+  if (start_addr != NULL)
+    {
+      if (die_addr == start_addr)
+	v->start_addr = NULL;
+      return DWARF_CB_OK;
+    }
+
+  /* If this isn't a (defining) subprogram entity, skip DIE.  */
+  if (tag != DW_TAG_subprogram
+      || INTUSE(dwarf_hasattr) (die, DW_AT_declaration))
+    return DWARF_CB_OK;
+
+  v->last_addr = die_addr;
+  return (*v->callback) (die, v->arg);
+}
+
+ptrdiff_t
+dwarf_getfuncs (Dwarf_Die *cudie, int (*callback) (Dwarf_Die *, void *),
+		void *arg, ptrdiff_t offset)
+{
+  if (unlikely (cudie == NULL
+		|| INTUSE(dwarf_tag) (cudie) != DW_TAG_compile_unit))
+    return -1;
+
+  int lang = INTUSE(dwarf_srclang) (cudie);
+  bool c_cu = (lang == DW_LANG_C89
+	       || lang == DW_LANG_C
+	       || lang == DW_LANG_C99
+	       || lang == DW_LANG_C11);
+
+  struct visitor_info v = { callback, arg, (void *) offset, NULL, c_cu };
+  struct Dwarf_Die_Chain chain = { .die = CUDIE (cudie->cu),
+				   .parent = NULL };
+  int res = __libdw_visit_scopes (0, &chain, NULL, &tree_visitor, NULL, &v);
+
+  if (res == DWARF_CB_ABORT)
+    return (ptrdiff_t) v.last_addr;
+  else
+    return res;
+}
diff --git a/libdw/dwarf_getlocation.c b/libdw/dwarf_getlocation.c
new file mode 100644
index 0000000..37b32fc
--- /dev/null
+++ b/libdw/dwarf_getlocation.c
@@ -0,0 +1,1040 @@
+/* Return location expression list.
+   Copyright (C) 2000-2010, 2013-2015, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <search.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include <libdwP.h>
+
+
+static bool
+attr_ok (Dwarf_Attribute *attr)
+{
+  if (attr == NULL)
+    return false;
+
+  /* If it is an exprloc, it is obviously OK.  */
+  if (dwarf_whatform (attr) == DW_FORM_exprloc)
+    return true;
+
+  if (attr->cu->version >= 4)
+    {
+      /* Must be an exprloc (or constant), just not any block form.  */
+      switch (dwarf_whatform (attr))
+	{
+	case DW_FORM_block:
+	case DW_FORM_block1:
+	case DW_FORM_block2:
+	case DW_FORM_block4:
+	  __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
+	  return false;
+	default:
+	  break;
+	}
+    }
+
+  /* Otherwise must be one of the attributes listed below.  Older
+     DWARF versions might have encoded the exprloc as block, and we
+     cannot easily distinguish attributes in the loclist class because
+     the same forms are used for different classes.  */
+  switch (attr->code)
+    {
+    case DW_AT_location:
+    case DW_AT_byte_size:
+    case DW_AT_bit_offset:
+    case DW_AT_bit_size:
+    case DW_AT_lower_bound:
+    case DW_AT_bit_stride:
+    case DW_AT_upper_bound:
+    case DW_AT_count:
+    case DW_AT_allocated:
+    case DW_AT_associated:
+    case DW_AT_data_location:
+    case DW_AT_byte_stride:
+    case DW_AT_rank:
+    case DW_AT_call_value:
+    case DW_AT_call_target:
+    case DW_AT_call_target_clobbered:
+    case DW_AT_call_data_location:
+    case DW_AT_call_data_value:
+    case DW_AT_data_member_location:
+    case DW_AT_vtable_elem_location:
+    case DW_AT_string_length:
+    case DW_AT_use_location:
+    case DW_AT_frame_base:
+    case DW_AT_return_addr:
+    case DW_AT_static_link:
+    case DW_AT_segment:
+    case DW_AT_GNU_call_site_value:
+    case DW_AT_GNU_call_site_data_value:
+    case DW_AT_GNU_call_site_target:
+    case DW_AT_GNU_call_site_target_clobbered:
+      break;
+
+    default:
+      __libdw_seterrno (DWARF_E_NO_LOC_VALUE);
+      return false;
+    }
+
+  return true;
+}
+
+
+struct loclist
+{
+  uint8_t atom;
+  Dwarf_Word number;
+  Dwarf_Word number2;
+  Dwarf_Word offset;
+  struct loclist *next;
+};
+
+
+static int
+loc_compare (const void *p1, const void *p2)
+{
+  const struct loc_s *l1 = (const struct loc_s *) p1;
+  const struct loc_s *l2 = (const struct loc_s *) p2;
+
+  if ((uintptr_t) l1->addr < (uintptr_t) l2->addr)
+    return -1;
+  if ((uintptr_t) l1->addr > (uintptr_t) l2->addr)
+    return 1;
+
+  return 0;
+}
+
+/* For each DW_OP_implicit_value, we store a special entry in the cache.
+   This points us directly to the block data for later fetching.
+   Returns zero on success, -1 on bad DWARF or 1 if tsearch failed.  */
+static int
+store_implicit_value (Dwarf *dbg, void **cache, Dwarf_Op *op)
+{
+  if (dbg == NULL)
+    return -1;
+  struct loc_block_s *block = libdw_alloc (dbg, struct loc_block_s,
+					   sizeof (struct loc_block_s), 1);
+  const unsigned char *data = (const unsigned char *) (uintptr_t) op->number2;
+  /* Skip the block length.  */
+  Dwarf_Word length;
+  get_uleb128_unchecked (length, data);
+  if (length != op->number)
+    return -1;
+  block->addr = op;
+  block->data = (unsigned char *) data;
+  block->length = op->number;
+  if (unlikely (tsearch (block, cache, loc_compare) == NULL))
+    return 1;
+  return 0;
+}
+
+int
+dwarf_getlocation_implicit_value (Dwarf_Attribute *attr, const Dwarf_Op *op,
+				  Dwarf_Block *return_block)
+{
+  if (attr == NULL)
+    return -1;
+
+  struct loc_block_s fake = { .addr = (void *) op };
+  struct loc_block_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
+  if (unlikely (found == NULL))
+    {
+      __libdw_seterrno (DWARF_E_NO_BLOCK);
+      return -1;
+    }
+
+  return_block->length = (*found)->length;
+  return_block->data = (*found)->data;
+  return 0;
+}
+
+/* If the given attribute is DW_AT_data_member_location and it has constant
+   form then create a fake location using DW_OP_plus_uconst and the offset
+   value.  On success returns zero and fills in llbuf (when not NULL) and
+   sets listlen to 1.  Returns 1 when this isn't a DW_AT_data_member_location
+   offset.  Returns -1 and sets dwarf_errno on failure (bad DWARF data).  */
+static int
+is_constant_offset (Dwarf_Attribute *attr,
+		    Dwarf_Op **llbuf, size_t *listlen)
+{
+  if (attr->code != DW_AT_data_member_location)
+    return 1;
+
+  switch (attr->form)
+    {
+      /* Punt for any non-constant form.  */
+    default:
+      return 1;
+
+      /* Note, we don't regard DW_FORM_data16 as a constant form,
+	 even though technically it is according to the standard.  */
+    case DW_FORM_data1:
+    case DW_FORM_data2:
+    case DW_FORM_data4:
+    case DW_FORM_data8:
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_implicit_const:
+      break;
+    }
+
+  /* Check whether we already cached this location.  */
+  struct loc_s fake = { .addr = attr->valp };
+  struct loc_s **found = tfind (&fake, &attr->cu->locs, loc_compare);
+
+  if (found == NULL)
+    {
+      Dwarf_Word offset;
+      if (INTUSE(dwarf_formudata) (attr, &offset) != 0)
+	return -1;
+
+      Dwarf_Op *result = libdw_alloc (attr->cu->dbg,
+				      Dwarf_Op, sizeof (Dwarf_Op), 1);
+
+      result->atom = DW_OP_plus_uconst;
+      result->number = offset;
+      result->number2 = 0;
+      result->offset = 0;
+
+      /* Insert a record in the search tree so we can find it again later.  */
+      struct loc_s *newp = libdw_alloc (attr->cu->dbg,
+					struct loc_s, sizeof (struct loc_s),
+					1);
+      newp->addr = attr->valp;
+      newp->loc = result;
+      newp->nloc = 1;
+
+      found = tsearch (newp, &attr->cu->locs, loc_compare);
+    }
+
+  assert ((*found)->nloc == 1);
+
+  if (llbuf != NULL)
+    {
+      *llbuf = (*found)->loc;
+      *listlen = 1;
+    }
+
+  return 0;
+}
+
+int
+internal_function
+__libdw_intern_expression (Dwarf *dbg, bool other_byte_order,
+			   unsigned int address_size, unsigned int ref_size,
+			   void **cache, const Dwarf_Block *block,
+			   bool cfap, bool valuep,
+			   Dwarf_Op **llbuf, size_t *listlen, int sec_index)
+{
+  /* Empty location expressions don't have any ops to intern.  */
+  if (block->length == 0)
+    {
+      *listlen = 0;
+      return 0;
+    }
+
+  /* Check whether we already looked at this list.  */
+  struct loc_s fake = { .addr = block->data };
+  struct loc_s **found = tfind (&fake, cache, loc_compare);
+  if (found != NULL)
+    {
+      /* We already saw it.  */
+      *llbuf = (*found)->loc;
+      *listlen = (*found)->nloc;
+
+      if (valuep)
+	{
+	  assert (*listlen > 1);
+	  assert ((*llbuf)[*listlen - 1].atom == DW_OP_stack_value);
+	}
+
+      return 0;
+    }
+
+  const unsigned char *data = block->data;
+  const unsigned char *const end_data = data + block->length;
+
+  const struct { bool other_byte_order; } bo = { other_byte_order };
+
+  struct loclist *loclist = NULL;
+  unsigned int n = 0;
+
+  /* Stack allocate at most this many locs.  */
+#define MAX_STACK_LOCS 256
+  struct loclist stack_locs[MAX_STACK_LOCS];
+#define NEW_LOC() ({ struct loclist *ll;			\
+		     ll = (likely (n < MAX_STACK_LOCS)		\
+			   ? &stack_locs[n]			\
+			   : malloc (sizeof (struct loclist)));	\
+		     if (unlikely (ll == NULL))			\
+		       goto nomem;				\
+		     n++;					\
+		     ll->next = loclist;			\
+		     loclist = ll;				\
+		     ll; })
+
+  if (cfap)
+    {
+      /* Synthesize the operation to push the CFA before the expression.  */
+      struct loclist *newloc = NEW_LOC ();
+      newloc->atom = DW_OP_call_frame_cfa;
+      newloc->number = 0;
+      newloc->number2 = 0;
+      newloc->offset = -1;
+    }
+
+  /* Decode the opcodes.  It is possible in some situations to have a
+     block of size zero.  */
+  while (data < end_data)
+    {
+      struct loclist *newloc;
+      newloc = NEW_LOC ();
+      newloc->number = 0;
+      newloc->number2 = 0;
+      newloc->offset = data - block->data;
+
+      switch ((newloc->atom = *data++))
+	{
+	case DW_OP_addr:
+	  /* Address, depends on address size of CU.  */
+	  if (dbg == NULL)
+	    {
+	      // XXX relocation?
+	      if (address_size == 4)
+		{
+		  if (unlikely (data + 4 > end_data))
+		    goto invalid;
+		  else
+		    newloc->number = read_4ubyte_unaligned_inc (&bo, data);
+		}
+	      else
+		{
+		  if (unlikely (data + 8 > end_data))
+		    goto invalid;
+		  else
+		    newloc->number = read_8ubyte_unaligned_inc (&bo, data);
+		}
+	    }
+	  else if (__libdw_read_address_inc (dbg, sec_index, &data,
+					     address_size, &newloc->number))
+	    goto invalid;
+	  break;
+
+	case DW_OP_call_ref:
+	case DW_OP_GNU_variable_value:
+	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
+	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
+						      ref_size,
+						      &newloc->number,
+						      IDX_debug_info, 0))
+	    goto invalid;
+	  break;
+
+	case DW_OP_deref:
+	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_lit0 ... DW_OP_lit31:
+	case DW_OP_reg0 ... DW_OP_reg31:
+	case DW_OP_nop:
+	case DW_OP_push_object_address:
+	case DW_OP_call_frame_cfa:
+	case DW_OP_form_tls_address:
+	case DW_OP_GNU_push_tls_address:
+	case DW_OP_stack_value:
+	case DW_OP_GNU_uninit:
+	  /* No operand.  */
+	  break;
+
+	case DW_OP_const1u:
+	case DW_OP_pick:
+	case DW_OP_deref_size:
+	case DW_OP_xderef_size:
+	  if (unlikely (data >= end_data))
+	    {
+	    invalid:
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	    returnmem:
+	      /* Free any dynamically allocated loclists, if any.  */
+	      while (n > MAX_STACK_LOCS)
+		{
+		  struct loclist *loc = loclist;
+		  loclist = loc->next;
+		  free (loc);
+		  n--;
+		}
+	      return -1;
+	    }
+
+	  newloc->number = *data++;
+	  break;
+
+	case DW_OP_const1s:
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+
+	  newloc->number = *((int8_t *) data);
+	  ++data;
+	  break;
+
+	case DW_OP_const2u:
+	  if (unlikely (data + 2 > end_data))
+	    goto invalid;
+
+	  newloc->number = read_2ubyte_unaligned_inc (&bo, data);
+	  break;
+
+	case DW_OP_const2s:
+	case DW_OP_skip:
+	case DW_OP_bra:
+	case DW_OP_call2:
+	  if (unlikely (data + 2 > end_data))
+	    goto invalid;
+
+	  newloc->number = read_2sbyte_unaligned_inc (&bo, data);
+	  break;
+
+	case DW_OP_const4u:
+	  if (unlikely (data + 4 > end_data))
+	    goto invalid;
+
+	  newloc->number = read_4ubyte_unaligned_inc (&bo, data);
+	  break;
+
+	case DW_OP_const4s:
+	case DW_OP_call4:
+	case DW_OP_GNU_parameter_ref:
+	  if (unlikely (data + 4 > end_data))
+	    goto invalid;
+
+	  newloc->number = read_4sbyte_unaligned_inc (&bo, data);
+	  break;
+
+	case DW_OP_const8u:
+	  if (unlikely (data + 8 > end_data))
+	    goto invalid;
+
+	  newloc->number = read_8ubyte_unaligned_inc (&bo, data);
+	  break;
+
+	case DW_OP_const8s:
+	  if (unlikely (data + 8 > end_data))
+	    goto invalid;
+
+	  newloc->number = read_8sbyte_unaligned_inc (&bo, data);
+	  break;
+
+	case DW_OP_constu:
+	case DW_OP_plus_uconst:
+	case DW_OP_regx:
+	case DW_OP_piece:
+	case DW_OP_convert:
+	case DW_OP_GNU_convert:
+	case DW_OP_reinterpret:
+	case DW_OP_GNU_reinterpret:
+	case DW_OP_addrx:
+	case DW_OP_GNU_addr_index:
+	case DW_OP_constx:
+	case DW_OP_GNU_const_index:
+	  get_uleb128 (newloc->number, data, end_data);
+	  break;
+
+	case DW_OP_consts:
+	case DW_OP_breg0 ... DW_OP_breg31:
+	case DW_OP_fbreg:
+	  get_sleb128 (newloc->number, data, end_data);
+	  break;
+
+	case DW_OP_bregx:
+	  get_uleb128 (newloc->number, data, end_data);
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  get_sleb128 (newloc->number2, data, end_data);
+	  break;
+
+	case DW_OP_bit_piece:
+	case DW_OP_regval_type:
+	case DW_OP_GNU_regval_type:
+	  get_uleb128 (newloc->number, data, end_data);
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  get_uleb128 (newloc->number2, data, end_data);
+	  break;
+
+	case DW_OP_implicit_value:
+	case DW_OP_entry_value:
+	case DW_OP_GNU_entry_value:
+	  /* This cannot be used in a CFI expression.  */
+	  if (unlikely (dbg == NULL))
+	    goto invalid;
+
+	  /* start of block inc. len.  */
+	  newloc->number2 = (Dwarf_Word) (uintptr_t) data;
+	  get_uleb128 (newloc->number, data, end_data); /* Block length.  */
+	  if (unlikely ((Dwarf_Word) (end_data - data) < newloc->number))
+	    goto invalid;
+	  data += newloc->number;		/* Skip the block.  */
+	  break;
+
+	case DW_OP_implicit_pointer:
+	case DW_OP_GNU_implicit_pointer:
+	  /* DW_FORM_ref_addr, depends on offset size of CU.  */
+	  if (dbg == NULL || __libdw_read_offset_inc (dbg, sec_index, &data,
+						      ref_size,
+						      &newloc->number,
+						      IDX_debug_info, 0))
+	    goto invalid;
+	  if (unlikely (data >= end_data))
+	    goto invalid;
+	  get_uleb128 (newloc->number2, data, end_data); /* Byte offset.  */
+	  break;
+
+	case DW_OP_deref_type:
+	case DW_OP_GNU_deref_type:
+	case DW_OP_xderef_type:
+	  if (unlikely (data + 1 >= end_data))
+	    goto invalid;
+	  newloc->number = *data++;
+	  get_uleb128 (newloc->number2, data, end_data);
+	  break;
+
+	case DW_OP_const_type:
+	case DW_OP_GNU_const_type:
+	  {
+	    size_t size;
+	    get_uleb128 (newloc->number, data, end_data);
+	    if (unlikely (data >= end_data))
+	      goto invalid;
+
+	    /* start of block inc. len.  */
+	    newloc->number2 = (Dwarf_Word) (uintptr_t) data;
+	    size = *data++;
+	    if (unlikely ((Dwarf_Word) (end_data - data) < size))
+	      goto invalid;
+	    data += size;		/* Skip the block.  */
+	  }
+	  break;
+
+	default:
+	  goto invalid;
+	}
+    }
+
+  if (unlikely (n == 0))
+    {
+      /* This is not allowed.
+	 It would mean an empty location expression, which we handled
+	 already as a special case above.  */
+      goto invalid;
+    }
+
+  if (valuep)
+    {
+      struct loclist *newloc = NEW_LOC ();
+      newloc->atom = DW_OP_stack_value;
+      newloc->number = 0;
+      newloc->number2 = 0;
+      newloc->offset = data - block->data;
+    }
+
+  /* Allocate the array.  */
+  Dwarf_Op *result;
+  if (dbg != NULL)
+    result = libdw_alloc (dbg, Dwarf_Op, sizeof (Dwarf_Op), n);
+  else
+    {
+      result = malloc (sizeof *result * n);
+      if (result == NULL)
+	{
+	nomem:
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  goto returnmem;
+	}
+    }
+
+  /* Store the result.  */
+  *llbuf = result;
+  *listlen = n;
+
+  do
+    {
+      /* We populate the array from the back since the list is backwards.  */
+      --n;
+      result[n].atom = loclist->atom;
+      result[n].number = loclist->number;
+      result[n].number2 = loclist->number2;
+      result[n].offset = loclist->offset;
+
+      if (result[n].atom == DW_OP_implicit_value)
+	{
+	  int store = store_implicit_value (dbg, cache, &result[n]);
+	  if (unlikely (store != 0))
+	    {
+	      if (store < 0)
+	        goto invalid;
+	      else
+		goto nomem;
+	    }
+	}
+
+      struct loclist *loc = loclist;
+      loclist = loclist->next;
+      if (unlikely (n + 1 > MAX_STACK_LOCS))
+	free (loc);
+    }
+  while (n > 0);
+
+  /* Insert a record in the search tree so that we can find it again later.  */
+  struct loc_s *newp;
+  if (dbg != NULL)
+    newp = libdw_alloc (dbg, struct loc_s, sizeof (struct loc_s), 1);
+  else
+    {
+      newp = malloc (sizeof *newp);
+      if (newp == NULL)
+	{
+	  free (result);
+	  goto nomem;
+	}
+    }
+
+  newp->addr = block->data;
+  newp->loc = result;
+  newp->nloc = *listlen;
+  (void) tsearch (newp, cache, loc_compare);
+
+  /* We did it.  */
+  return 0;
+}
+
+static int
+getlocation (struct Dwarf_CU *cu, const Dwarf_Block *block,
+	     Dwarf_Op **llbuf, size_t *listlen, int sec_index)
+{
+  /* Empty location expressions don't have any ops to intern.
+     Note that synthetic empty_cu doesn't have an associated DWARF dbg.  */
+  if (block->length == 0)
+    {
+      *listlen = 0;
+      return 0;
+    }
+
+  return __libdw_intern_expression (cu->dbg, cu->dbg->other_byte_order,
+				    cu->address_size, (cu->version == 2
+						       ? cu->address_size
+						       : cu->offset_size),
+				    &cu->locs, block,
+				    false, false,
+				    llbuf, listlen, sec_index);
+}
+
+int
+dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **llbuf, size_t *listlen)
+{
+  if (! attr_ok (attr))
+    return -1;
+
+  int result = is_constant_offset (attr, llbuf, listlen);
+  if (result != 1)
+    return result; /* Either success 0, or -1 to indicate error.  */
+
+  /* If it has a block form, it's a single location expression.
+     Except for DW_FORM_data16, which is a 128bit constant.  */
+  if (attr->form == DW_FORM_data16)
+    {
+      __libdw_seterrno (DWARF_E_NO_BLOCK);
+      return -1;
+    }
+  Dwarf_Block block;
+  if (INTUSE(dwarf_formblock) (attr, &block) != 0)
+    return -1;
+
+  return getlocation (attr->cu, &block, llbuf, listlen, cu_sec_idx (attr->cu));
+}
+
+Dwarf_Addr
+__libdw_cu_base_address (Dwarf_CU *cu)
+{
+  if (cu->base_address == (Dwarf_Addr) -1)
+    {
+      Dwarf_Addr base;
+
+      /* Fetch the CU's base address.  */
+      Dwarf_Die cudie = CUDIE (cu);
+
+      /* Find the base address of the compilation unit.  It will
+	 normally be specified by DW_AT_low_pc.  In DWARF-3 draft 4,
+	 the base address could be overridden by DW_AT_entry_pc.  It's
+	 been removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc
+	 for compilation units with discontinuous ranges.  */
+      Dwarf_Attribute attr_mem;
+      if (INTUSE(dwarf_lowpc) (&cudie, &base) != 0
+	  && INTUSE(dwarf_formaddr) (INTUSE(dwarf_attr) (&cudie,
+							 DW_AT_entry_pc,
+							 &attr_mem),
+				     &base) != 0)
+	{
+	  /* The compiler provided no base address when it should
+	     have.  Buggy GCC does this when it used absolute
+	     addresses in the location list and no DW_AT_ranges.  */
+	   base = 0;
+	}
+      cu->base_address = base;
+    }
+
+  return cu->base_address;
+}
+
+static int
+initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
+{
+  size_t secidx = (attr->cu->version < 5
+		   ? IDX_debug_loc : IDX_debug_loclists);
+
+  Dwarf_Word start_offset;
+  if (attr->form == DW_FORM_loclistx)
+    {
+      Dwarf_Word idx;
+      Dwarf_CU *cu = attr->cu;
+      const unsigned char *datap = attr->valp;
+      const unsigned char *endp = cu->endp;
+      if (datap >= endp)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      get_uleb128 (idx, datap, endp);
+
+      Elf_Data *data = cu->dbg->sectiondata[secidx];
+      if (data == NULL && cu->unit_type == DW_UT_split_compile)
+	{
+	  cu = __libdw_find_split_unit (cu);
+	  if (cu != NULL)
+	    data = cu->dbg->sectiondata[secidx];
+	}
+
+      if (data == NULL)
+	{
+	  __libdw_seterrno (secidx == IDX_debug_loc
+                            ? DWARF_E_NO_DEBUG_LOC
+                            : DWARF_E_NO_DEBUG_LOCLISTS);
+	  return -1;
+	}
+
+      Dwarf_Off loc_base_off = __libdw_cu_locs_base (cu);
+
+      /* The section should at least contain room for one offset.  */
+      size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
+      size_t offset_size = cu->offset_size;
+      if (offset_size > sec_size)
+	{
+	invalid_offset:
+	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+	  return -1;
+	}
+
+      /* And the base offset should be at least inside the section.  */
+      if (loc_base_off > (sec_size - offset_size))
+	goto invalid_offset;
+
+      size_t max_idx = (sec_size - offset_size - loc_base_off) / offset_size;
+      if (idx > max_idx)
+	goto invalid_offset;
+
+      datap = (cu->dbg->sectiondata[secidx]->d_buf
+	       + loc_base_off + (idx * offset_size));
+      if (offset_size == 4)
+	start_offset = read_4ubyte_unaligned (cu->dbg, datap);
+      else
+	start_offset = read_8ubyte_unaligned (cu->dbg, datap);
+
+      start_offset += loc_base_off;
+    }
+  else
+    {
+      if (__libdw_formptr (attr, secidx,
+			   (secidx == IDX_debug_loc
+			    ? DWARF_E_NO_DEBUG_LOC
+			    : DWARF_E_NO_DEBUG_LOCLISTS),
+			    NULL, &start_offset) == NULL)
+	return -1;
+
+      Dwarf_Off loc_off;
+      if (INTUSE(dwarf_cu_dwp_section_info) (attr->cu, DW_SECT_LOCLISTS,
+					     &loc_off, NULL) != 0)
+	return -1;
+      start_offset += loc_off;
+    }
+
+  *offset = start_offset;
+  return 0;
+}
+
+static ptrdiff_t
+getlocations_addr (Dwarf_Attribute *attr, ptrdiff_t offset,
+		   Dwarf_Addr *basep, Dwarf_Addr *startp, Dwarf_Addr *endp,
+		   Dwarf_Addr address, const Elf_Data *locs, Dwarf_Op **expr,
+		   size_t *exprlen)
+{
+  Dwarf_CU *cu = attr->cu;
+  Dwarf *dbg = cu->dbg;
+  size_t secidx = cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
+  const unsigned char *readp = locs->d_buf + offset;
+  const unsigned char *readendp = locs->d_buf + locs->d_size;
+
+  Dwarf_Addr begin;
+  Dwarf_Addr end;
+
+ next:
+  switch (__libdw_read_begin_end_pair_inc (cu, secidx,
+					   &readp, readendp,
+					   cu->address_size,
+					   &begin, &end, basep))
+    {
+    case 0: /* got location range. */
+      break;
+    case 1: /* base address setup. */
+      goto next;
+    case 2: /* end of loclist */
+      return 0;
+    default: /* error */
+      return -1;
+    }
+
+  /* We have a location expression.  */
+  Dwarf_Block block;
+  if (secidx == IDX_debug_loc)
+    {
+      if (readendp - readp < 2)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      block.length = read_2ubyte_unaligned_inc (dbg, readp);
+    }
+  else
+    {
+      if (readendp - readp < 1)
+	goto invalid;
+      get_uleb128 (block.length, readp, readendp);
+    }
+  block.data = (unsigned char *) readp;
+  if (readendp - readp < (ptrdiff_t) block.length)
+    goto invalid;
+  readp += block.length;
+
+  /* Note these addresses include any base (if necessary) already.  */
+  *startp = begin;
+  *endp = end;
+
+  /* If address is minus one we want them all, otherwise only matching.  */
+  if (address != (Dwarf_Word) -1 && (address < *startp || address >= *endp))
+    goto next;
+
+  if (getlocation (cu, &block, expr, exprlen, secidx) != 0)
+    return -1;
+
+  return readp - (unsigned char *) locs->d_buf;
+}
+
+int
+dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
+			Dwarf_Op **llbufs, size_t *listlens, size_t maxlocs)
+{
+  if (! attr_ok (attr))
+    return -1;
+
+  if (llbufs == NULL)
+    maxlocs = SIZE_MAX;
+
+  /* If it has a block form, it's a single location expression.
+     Except for DW_FORM_data16, which is a 128bit constant.  */
+  Dwarf_Block block;
+  if (attr->form != DW_FORM_data16
+      && INTUSE(dwarf_formblock) (attr, &block) == 0)
+    {
+      if (maxlocs == 0)
+	return 0;
+      if (llbufs != NULL &&
+	  getlocation (attr->cu, &block, &llbufs[0], &listlens[0],
+		       cu_sec_idx (attr->cu)) != 0)
+	return -1;
+      return listlens[0] == 0 ? 0 : 1;
+    }
+
+  if (attr->form != DW_FORM_data16)
+    {
+      int error = INTUSE(dwarf_errno) ();
+      if (unlikely (error != DWARF_E_NO_BLOCK))
+	{
+	  __libdw_seterrno (error);
+	  return -1;
+	}
+    }
+
+  /* If is_constant_offset is successful, we are done with 1 result.  */
+  int result = is_constant_offset (attr, llbufs, listlens);
+  if (result != 1)
+    return result ?: 1;
+
+  Dwarf_Addr base, start, end;
+  Dwarf_Op *expr;
+  size_t expr_len;
+  ptrdiff_t off = 0;
+  size_t got = 0;
+
+  /* This is a true loclistptr, fetch the initial base address and offset.  */
+  base = __libdw_cu_base_address (attr->cu);
+  if (base == (Dwarf_Addr) -1)
+    return -1;
+
+  if (initial_offset (attr, &off) != 0)
+    return -1;
+
+  size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
+  const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
+
+  while (got < maxlocs
+         && (off = getlocations_addr (attr, off, &base, &start, &end,
+				      address, d, &expr, &expr_len)) > 0)
+    {
+      /* This one matches the address.  */
+      if (llbufs != NULL)
+	{
+	  llbufs[got] = expr;
+	  listlens[got] = expr_len;
+	}
+      ++got;
+    }
+
+  /* We might stop early, so off can be zero or positive on success.  */
+  if (off < 0)
+    return -1;
+
+  return got;
+}
+
+ptrdiff_t
+dwarf_getlocations (Dwarf_Attribute *attr, ptrdiff_t offset, Dwarf_Addr *basep,
+		    Dwarf_Addr *startp, Dwarf_Addr *endp, Dwarf_Op **expr,
+		    size_t *exprlen)
+{
+  if (! attr_ok (attr))
+    return -1;
+
+  /* 1 is an invalid offset, meaning no more locations. */
+  if (offset == 1)
+    return 0;
+
+  if (offset == 0)
+    {
+      /* If it has a block form, it's a single location expression.
+	 Except for DW_FORM_data16, which is a 128bit constant.  */
+      Dwarf_Block block;
+      if (attr->form != DW_FORM_data16
+	  && INTUSE(dwarf_formblock) (attr, &block) == 0)
+	{
+	  if (getlocation (attr->cu, &block, expr, exprlen,
+			   cu_sec_idx (attr->cu)) != 0)
+	    return -1;
+
+	  /* This is the one and only location covering everything. */
+	  *startp = 0;
+	  *endp = -1;
+	  return 1;
+	}
+
+      if (attr->form != DW_FORM_data16)
+	{
+	  int error = INTUSE(dwarf_errno) ();
+	  if (unlikely (error != DWARF_E_NO_BLOCK))
+	    {
+	      __libdw_seterrno (error);
+	      return -1;
+	    }
+	}
+
+      int result = is_constant_offset (attr, expr, exprlen);
+      if (result != 1)
+	{
+	  if (result == 0)
+	    {
+	      /* This is the one and only location covering everything. */
+	      *startp = 0;
+	      *endp = -1;
+	      return 1;
+	    }
+	  return result; /* Something bad, dwarf_errno has been set.  */
+	}
+
+      /* We must be looking at a true loclistptr, fetch the initial
+	 base address and offset.  */
+      *basep = __libdw_cu_base_address (attr->cu);
+      if (*basep == (Dwarf_Addr) -1)
+	return -1;
+
+      if (initial_offset (attr, &offset) != 0)
+	return -1;
+    }
+
+  size_t secidx = attr->cu->version < 5 ? IDX_debug_loc : IDX_debug_loclists;
+  const Elf_Data *d = attr->cu->dbg->sectiondata[secidx];
+
+  return getlocations_addr (attr, offset, basep, startp, endp,
+			    (Dwarf_Word) -1, d, expr, exprlen);
+}
diff --git a/libdw/dwarf_getlocation_attr.c b/libdw/dwarf_getlocation_attr.c
new file mode 100644
index 0000000..99bcc82
--- /dev/null
+++ b/libdw/dwarf_getlocation_attr.c
@@ -0,0 +1,162 @@
+/* Return DWARF attribute associated with a location expression op.
+   Copyright (C) 2013, 2014, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <libdwP.h>
+
+static Dwarf_CU *
+attr_form_cu (Dwarf_Attribute *attr)
+{
+  /* If the attribute has block/expr form the data comes from the
+     .debug_info from the same cu as the attr.  Otherwise it comes from
+     the .debug_loc or .debug_loclists data section.  */
+  switch (attr->form)
+    {
+    case DW_FORM_block1:
+    case DW_FORM_block2:
+    case DW_FORM_block4:
+    case DW_FORM_block:
+    case DW_FORM_exprloc:
+      return attr->cu;
+    default:
+      return (attr->cu->version < 5
+	      ? attr->cu->dbg->fake_loc_cu
+	      : attr->cu->dbg->fake_loclists_cu);
+    }
+}
+
+static unsigned char *
+addr_valp (Dwarf_CU *cu, Dwarf_Word index)
+{
+  Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
+  if (debug_addr == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DEBUG_ADDR);
+      return NULL;
+    }
+
+  Dwarf_Word offset = __libdw_cu_addr_base (cu) + (index * cu->address_size);
+  return (unsigned char *) debug_addr->d_buf + offset;
+}
+
+int
+dwarf_getlocation_attr (Dwarf_Attribute *attr, const Dwarf_Op *op, Dwarf_Attribute *result)
+{
+  if (attr == NULL)
+    return -1;
+
+  switch (op->atom)
+    {
+      case DW_OP_implicit_value:
+	result->code = DW_AT_const_value;
+	result->form = DW_FORM_block;
+	result->valp = (unsigned char *) (uintptr_t) op->number2;
+	result->cu = attr_form_cu (attr);
+	break;
+
+      case DW_OP_entry_value:
+      case DW_OP_GNU_entry_value:
+	result->code = DW_AT_location;
+	result->form = DW_FORM_exprloc;
+	result->valp = (unsigned char *) (uintptr_t) op->number2;
+	result->cu = attr_form_cu (attr);
+	break;
+
+      case DW_OP_const_type:
+      case DW_OP_GNU_const_type:
+	result->code = DW_AT_const_value;
+	result->form = DW_FORM_block1;
+	result->valp = (unsigned char *) (uintptr_t) op->number2;
+	result->cu = attr_form_cu (attr);
+	break;
+
+      case DW_OP_GNU_const_index:
+      case DW_OP_constx:
+	result->code = DW_AT_const_value;
+	if (attr->cu->address_size == 4)
+	  result->form = DW_FORM_data4;
+	else
+	  result->form = DW_FORM_data8;
+	result->valp = addr_valp (attr->cu, op->number);
+	if (result->valp == NULL)
+	  return -1;
+	result->cu = attr->cu->dbg->fake_addr_cu;
+	break;
+
+      case DW_OP_GNU_addr_index:
+      case DW_OP_addrx:
+	result->code = DW_AT_low_pc;
+	result->form = DW_FORM_addr;
+	result->valp = addr_valp (attr->cu, op->number);
+	if (result->valp == NULL)
+	  return -1;
+	result->cu = attr->cu->dbg->fake_addr_cu;
+	break;
+
+      case DW_OP_call2:
+      case DW_OP_call4:
+      case DW_OP_call_ref:
+	{
+	  Dwarf_Die die;
+	  if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
+	    return -1;
+	  if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL)
+	    {
+	      __libdw_empty_loc_attr (result);
+	      return 0;
+	    }
+	}
+	break;
+
+      case DW_OP_implicit_pointer:
+      case DW_OP_GNU_implicit_pointer:
+      case DW_OP_GNU_variable_value:
+	{
+	  Dwarf_Die die;
+	  if (INTUSE(dwarf_getlocation_die) (attr, op, &die) != 0)
+	    return -1;
+	  if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
+	      && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
+	    {
+	      __libdw_empty_loc_attr (result);
+	      return 0;
+	    }
+	}
+	break;
+
+      default:
+	__libdw_seterrno (DWARF_E_INVALID_ACCESS);
+	return -1;
+    }
+
+  return 0;
+}
diff --git a/libdw/dwarf_getlocation_die.c b/libdw/dwarf_getlocation_die.c
new file mode 100644
index 0000000..673c61c
--- /dev/null
+++ b/libdw/dwarf_getlocation_die.c
@@ -0,0 +1,95 @@
+/* Return DIE associated with a location expression op.
+   Copyright (C) 2013, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <libdwP.h>
+
+int
+dwarf_getlocation_die (Dwarf_Attribute *attr, const Dwarf_Op *op,
+		       Dwarf_Die *result)
+{
+  if (attr == NULL)
+    return -1;
+
+  Dwarf_Off dieoff;
+  switch (op->atom)
+    {
+    case DW_OP_implicit_pointer:
+    case DW_OP_GNU_implicit_pointer:
+    case DW_OP_call_ref:
+    case DW_OP_GNU_variable_value:
+      dieoff = op->number;
+      break;
+
+    case DW_OP_GNU_parameter_ref:
+    case DW_OP_convert:
+    case DW_OP_GNU_convert:
+    case DW_OP_reinterpret:
+    case DW_OP_GNU_reinterpret:
+    case DW_OP_const_type:
+    case DW_OP_GNU_const_type:
+    case DW_OP_call2:
+    case DW_OP_call4:
+      if (op->number > (attr->cu->end - attr->cu->start))
+	{
+	invalid_offset:
+	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+	  return -1;
+	}
+      dieoff = attr->cu->start + op->number;
+      break;
+
+    case DW_OP_regval_type:
+    case DW_OP_GNU_regval_type:
+    case DW_OP_deref_type:
+    case DW_OP_GNU_deref_type:
+      if (op->number2 > (attr->cu->end - attr->cu->start))
+	goto invalid_offset;
+      dieoff = attr->cu->start + op->number2;
+      break;
+
+    case DW_OP_xderef_type:
+      dieoff = op->number2;
+      break;
+
+    default:
+      __libdw_seterrno (DWARF_E_INVALID_ACCESS);
+      return -1;
+    }
+
+  if (__libdw_offdie (attr->cu->dbg, dieoff, result,
+		      ISV4TU(attr->cu)) == NULL)
+    return -1;
+
+  return 0;
+}
+INTDEF(dwarf_getlocation_die);
diff --git a/libdw/dwarf_getlocation_implicit_pointer.c b/libdw/dwarf_getlocation_implicit_pointer.c
new file mode 100644
index 0000000..0c1cd00
--- /dev/null
+++ b/libdw/dwarf_getlocation_implicit_pointer.c
@@ -0,0 +1,78 @@
+/* Return associated attribute for DW_OP_GNU_implicit_pointer.
+   Copyright (C) 2010, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+static unsigned char empty_exprloc = 0;
+static Dwarf_CU empty_cu = { .startp = &empty_exprloc,
+			     .endp = &empty_exprloc + 1 };
+
+void
+internal_function
+__libdw_empty_loc_attr (Dwarf_Attribute *attr)
+{
+  attr->code = DW_AT_location;
+  attr->form = DW_FORM_exprloc;
+  attr->valp = &empty_exprloc;
+  attr->cu = &empty_cu;
+}
+
+int
+dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr, const Dwarf_Op *op,
+				    Dwarf_Attribute *result)
+{
+  if (attr == NULL)
+    return -1;
+
+  if (unlikely (op->atom != DW_OP_implicit_pointer
+		&& op->atom != DW_OP_GNU_implicit_pointer))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ACCESS);
+      return -1;
+    }
+
+  Dwarf_Die die;
+  if (__libdw_offdie (attr->cu->dbg, op->number, &die,
+		      ISV4TU(attr->cu)) == NULL)
+    return -1;
+
+  if (INTUSE(dwarf_attr) (&die, DW_AT_location, result) == NULL
+      && INTUSE(dwarf_attr) (&die, DW_AT_const_value, result) == NULL)
+    {
+      __libdw_empty_loc_attr (result);
+      return 0;
+    }
+
+  return 0;
+}
diff --git a/libdw/dwarf_getmacros.c b/libdw/dwarf_getmacros.c
new file mode 100644
index 0000000..2667eb4
--- /dev/null
+++ b/libdw/dwarf_getmacros.c
@@ -0,0 +1,635 @@
+/* Get macro information.
+   Copyright (C) 2002-2009, 2014, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwP.h>
+
+static int
+get_offset_from (Dwarf_Die *die, int name, Dwarf_Word *retp)
+{
+  /* Get the appropriate attribute.  */
+  Dwarf_Attribute attr;
+  if (INTUSE(dwarf_attr) (die, name, &attr) == NULL)
+    return -1;
+
+  /* Offset into the corresponding section.  */
+  if (INTUSE(dwarf_formudata) (&attr, retp) != 0)
+    return -1;
+
+  Dwarf_Off offset;
+  if (INTUSE(dwarf_cu_dwp_section_info) (die->cu, DW_SECT_MACRO, &offset, NULL)
+      != 0)
+    return -1;
+  *retp += offset;
+  return 0;
+}
+
+static int
+macro_op_compare (const void *p1, const void *p2)
+{
+  const Dwarf_Macro_Op_Table *t1 = (const Dwarf_Macro_Op_Table *) p1;
+  const Dwarf_Macro_Op_Table *t2 = (const Dwarf_Macro_Op_Table *) p2;
+
+  if (t1->offset < t2->offset)
+    return -1;
+  if (t1->offset > t2->offset)
+    return 1;
+
+  if (t1->sec_index < t2->sec_index)
+    return -1;
+  if (t1->sec_index > t2->sec_index)
+    return 1;
+
+  return 0;
+}
+
+static void
+build_table (Dwarf_Macro_Op_Table *table,
+	     Dwarf_Macro_Op_Proto op_protos[static 255])
+{
+  unsigned ct = 0;
+  for (unsigned i = 1; i < 256; ++i)
+    if (op_protos[i - 1].forms != NULL)
+      table->table[table->opcodes[i - 1] = ct++] = op_protos[i - 1];
+    else
+      table->opcodes[i - 1] = 0xff;
+}
+
+#define MACRO_PROTO(NAME, ...)					\
+  Dwarf_Macro_Op_Proto NAME = ({				\
+      static const uint8_t proto[] = {__VA_ARGS__};		\
+      (Dwarf_Macro_Op_Proto) {sizeof proto, proto};		\
+    })
+
+enum { macinfo_data_size = offsetof (Dwarf_Macro_Op_Table, table[5]) };
+static unsigned char macinfo_data[macinfo_data_size]
+	__attribute__ ((aligned (__alignof (Dwarf_Macro_Op_Table))));
+
+static __attribute__ ((constructor)) void
+init_macinfo_table (void)
+{
+  MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
+  MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
+  MACRO_PROTO (p_none);
+
+  Dwarf_Macro_Op_Proto op_protos[255] =
+    {
+      [DW_MACINFO_define - 1] = p_udata_str,
+      [DW_MACINFO_undef - 1] = p_udata_str,
+      [DW_MACINFO_vendor_ext - 1] = p_udata_str,
+      [DW_MACINFO_start_file - 1] = p_udata_udata,
+      [DW_MACINFO_end_file - 1] = p_none,
+      /* If you are adding more elements to this array, increase
+	 MACINFO_DATA_SIZE above.  */
+    };
+
+  Dwarf_Macro_Op_Table *macinfo_table = (void *) macinfo_data;
+  memset (macinfo_table, 0, sizeof macinfo_data);
+  build_table (macinfo_table, op_protos);
+  macinfo_table->sec_index = IDX_debug_macinfo;
+}
+
+static Dwarf_Macro_Op_Table *
+get_macinfo_table (Dwarf *dbg, Dwarf_Word macoff, Dwarf_Die *cudie)
+{
+  assert (cudie != NULL);
+
+  Dwarf_Attribute attr_mem, *attr
+    = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
+  Dwarf_Off line_offset = (Dwarf_Off) -1;
+  if (attr != NULL)
+    {
+      if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
+	return NULL;
+    }
+  else if (cudie->cu->unit_type == DW_UT_split_compile
+	   && dbg->sectiondata[IDX_debug_line] != NULL)
+    line_offset = 0;
+  if (line_offset != (Dwarf_Off) -1)
+    {
+      Dwarf_Off dwp_offset;
+      if (INTUSE(dwarf_cu_dwp_section_info) (cudie->cu, DW_SECT_LINE,
+					     &dwp_offset, NULL) != 0)
+	return NULL;
+      line_offset += dwp_offset;
+    }
+
+  Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
+					     macinfo_data_size, 1);
+  memcpy (table, macinfo_data, macinfo_data_size);
+
+  table->dbg = dbg;
+  table->offset = macoff;
+  table->sec_index = IDX_debug_macinfo;
+  table->line_offset = line_offset;
+  table->address_size = cudie->cu->address_size;
+  table->offset_size = cudie->cu->offset_size;
+  table->comp_dir = __libdw_getcompdir (cudie);
+
+  return table;
+}
+
+static Dwarf_Macro_Op_Table *
+get_table_for_offset (Dwarf *dbg, Dwarf_Word macoff,
+		      const unsigned char *readp,
+		      const unsigned char *const endp,
+		      Dwarf_Die *cudie)
+{
+  const unsigned char *startp = readp;
+
+  /* Request at least 3 bytes for header.  */
+  if (readp + 3 > endp)
+    {
+    invalid_dwarf:
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+  if (version != 4 && version != 5)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_VERSION);
+      return NULL;
+    }
+
+  uint8_t flags = *readp++;
+  bool is_64bit = (flags & 0x1) != 0;
+
+  Dwarf_Off line_offset = (Dwarf_Off) -1;
+  if ((flags & 0x2) != 0)
+    {
+      line_offset = read_addr_unaligned_inc (is_64bit ? 8 : 4, dbg, readp);
+      if (readp > endp)
+	goto invalid_dwarf;
+    }
+  else if (cudie != NULL)
+    {
+      Dwarf_Attribute attr_mem, *attr
+	= INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list, &attr_mem);
+      if (attr != NULL)
+	if (unlikely (INTUSE(dwarf_formudata) (attr, &line_offset) != 0))
+	  return NULL;
+    }
+  if (line_offset != (Dwarf_Off) -1 && cudie != NULL)
+    {
+      Dwarf_Off dwp_offset;
+      if (INTUSE(dwarf_cu_dwp_section_info) (cudie->cu, DW_SECT_LINE,
+					     &dwp_offset, NULL) != 0)
+	return NULL;
+      line_offset += dwp_offset;
+    }
+
+  uint8_t address_size;
+  if (cudie != NULL)
+    address_size = cudie->cu->address_size;
+  else
+    {
+      char *ident = elf_getident (dbg->elf, NULL);
+      address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+    }
+
+  /* """The macinfo entry types defined in this standard may, but
+     might not, be described in the table""".
+
+     I.e. these may be present.  It's tempting to simply skip them,
+     but it's probably more correct to tolerate that a producer tweaks
+     the way certain opcodes are encoded, for whatever reasons.  */
+
+  MACRO_PROTO (p_udata_str, DW_FORM_udata, DW_FORM_string);
+  MACRO_PROTO (p_udata_strp, DW_FORM_udata, DW_FORM_strp);
+  MACRO_PROTO (p_udata_strsup, DW_FORM_udata, DW_FORM_strp_sup);
+  MACRO_PROTO (p_udata_strx, DW_FORM_udata, DW_FORM_strx);
+  MACRO_PROTO (p_udata_udata, DW_FORM_udata, DW_FORM_udata);
+  MACRO_PROTO (p_secoffset, DW_FORM_sec_offset);
+  MACRO_PROTO (p_none);
+
+  Dwarf_Macro_Op_Proto op_protos[255] =
+    {
+      [DW_MACRO_define - 1] = p_udata_str,
+      [DW_MACRO_undef - 1] = p_udata_str,
+      [DW_MACRO_define_strp - 1] = p_udata_strp,
+      [DW_MACRO_undef_strp - 1] = p_udata_strp,
+      [DW_MACRO_start_file - 1] = p_udata_udata,
+      [DW_MACRO_end_file - 1] = p_none,
+      [DW_MACRO_import - 1] = p_secoffset,
+      [DW_MACRO_define_sup - 1] = p_udata_strsup,
+      [DW_MACRO_undef_sup - 1] = p_udata_strsup,
+      [DW_MACRO_import_sup - 1] = p_secoffset, /* XXX - but in sup!. */
+      [DW_MACRO_define_strx - 1] = p_udata_strx,
+      [DW_MACRO_undef_strx - 1] = p_udata_strx,
+    };
+
+  if ((flags & 0x4) != 0)
+    {
+      unsigned count = *readp++;
+      for (unsigned i = 0; i < count; ++i)
+	{
+	  unsigned opcode = *readp++;
+
+	  Dwarf_Macro_Op_Proto e;
+	  if (readp >= endp)
+	    goto invalid;
+	  get_uleb128 (e.nforms, readp, endp);
+	  e.forms = readp;
+	  op_protos[opcode - 1] = e;
+
+	  readp += e.nforms;
+	  if (readp > endp)
+	    {
+	    invalid:
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return NULL;
+	    }
+	}
+    }
+
+  size_t ct = 0;
+  for (unsigned i = 1; i < 256; ++i)
+    if (op_protos[i - 1].forms != NULL)
+      ++ct;
+
+  /* We support at most 0xfe opcodes defined in the table, as 0xff is
+     a value that means that given opcode is not stored at all.  But
+     that should be fine, as opcode 0 is not allocated.  */
+  assert (ct < 0xff);
+
+  size_t macop_table_size = offsetof (Dwarf_Macro_Op_Table, table[ct]);
+
+  Dwarf_Macro_Op_Table *table = libdw_alloc (dbg, Dwarf_Macro_Op_Table,
+					     macop_table_size, 1);
+
+  *table = (Dwarf_Macro_Op_Table) {
+    .dbg = dbg,
+    .offset = macoff,
+    .sec_index = IDX_debug_macro,
+    .line_offset = line_offset,
+    .header_len = readp - startp,
+    .version = version,
+    .address_size = address_size,
+    .offset_size = is_64bit ? 8 : 4,
+
+    /* NULL if CUDIE is NULL or DW_AT_comp_dir is absent.  */
+    .comp_dir = __libdw_getcompdir (cudie),
+  };
+  build_table (table, op_protos);
+
+  return table;
+}
+
+static Dwarf_Macro_Op_Table *
+cache_op_table (Dwarf *dbg, int sec_index, Dwarf_Off macoff,
+		const unsigned char *startp,
+		const unsigned char *const endp,
+		Dwarf_Die *cudie)
+{
+  Dwarf_Macro_Op_Table fake = { .offset = macoff, .sec_index = sec_index };
+  Dwarf_Macro_Op_Table **found = tfind (&fake, &dbg->macro_ops,
+					macro_op_compare);
+  if (found != NULL)
+    return *found;
+
+  Dwarf_Macro_Op_Table *table = sec_index == IDX_debug_macro
+    ? get_table_for_offset (dbg, macoff, startp, endp, cudie)
+    : get_macinfo_table (dbg, macoff, cudie);
+
+  if (table == NULL)
+    return NULL;
+
+  Dwarf_Macro_Op_Table **ret = tsearch (table, &dbg->macro_ops,
+					macro_op_compare);
+  if (unlikely (ret == NULL))
+    {
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  return *ret;
+}
+
+static ptrdiff_t
+read_macros (Dwarf *dbg, int sec_index,
+	     Dwarf_Off macoff, int (*callback) (Dwarf_Macro *, void *),
+	     void *arg, ptrdiff_t offset, bool accept_0xff,
+	     Dwarf_Die *cudie)
+{
+  Elf_Data *d = dbg->sectiondata[sec_index];
+  if (unlikely (d == NULL || d->d_buf == NULL))
+    {
+      __libdw_seterrno (DWARF_E_NO_ENTRY);
+      return -1;
+    }
+
+  if (unlikely (macoff >= d->d_size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  const unsigned char *const startp = d->d_buf + macoff;
+  const unsigned char *const endp = d->d_buf + d->d_size;
+
+  Dwarf_Macro_Op_Table *table = cache_op_table (dbg, sec_index, macoff,
+						startp, endp, cudie);
+  if (table == NULL)
+    return -1;
+
+  if (offset == 0)
+    offset = table->header_len;
+
+  assert (offset >= 0);
+  assert (offset < endp - startp);
+  const unsigned char *readp = startp + offset;
+
+  while (readp < endp)
+    {
+      unsigned int opcode = *readp++;
+      if (opcode == 0)
+	/* Nothing more to do.  */
+	return 0;
+
+      if (unlikely (opcode == 0xff && ! accept_0xff))
+	{
+	  /* See comment below at dwarf_getmacros for explanation of
+	     why we are doing this.  */
+	  __libdw_seterrno (DWARF_E_INVALID_OPCODE);
+	  return -1;
+	}
+
+      unsigned int idx = table->opcodes[opcode - 1];
+      if (idx == 0xff)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_OPCODE);
+	  return -1;
+	}
+
+      Dwarf_Macro_Op_Proto *proto = &table->table[idx];
+
+      /* A fake CU with bare minimum data to fool dwarf_formX into
+	 doing the right thing with the attributes that we put out.
+	 We pretend it is the same version as the actual table.
+	 Version 4 for the old GNU extension, version 5 for DWARF5.
+	 To handle DW_FORM_strx[1234] we set the .str_offsets_base
+	 from the given CU.
+	 XXX We will need to deal with DW_MACRO_import_sup and change
+	 out the dbg somehow for the DW_FORM_sec_offset to make sense.  */
+      Dwarf_CU fake_cu = {
+	.dbg = dbg,
+	.sec_idx = sec_index,
+	.version = table->version,
+	.offset_size = table->offset_size,
+	.str_off_base = str_offsets_base_off (dbg, (cudie != NULL
+						    ? cudie->cu: NULL)),
+	.startp = (void *) startp + offset,
+	.endp = (void *) endp,
+      };
+
+      Dwarf_Attribute *attributes;
+      Dwarf_Attribute *attributesp = NULL;
+      Dwarf_Attribute nattributes[8];
+      if (unlikely (proto->nforms > 8))
+	{
+	  attributesp = malloc (sizeof (Dwarf_Attribute) * proto->nforms);
+	  if (attributesp == NULL)
+	    {
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      return -1;
+	    }
+	  attributes = attributesp;
+	}
+      else
+	attributes = &nattributes[0];
+
+      for (Dwarf_Word i = 0; i < proto->nforms; ++i)
+	{
+	  /* We pretend this is a DW_AT[_GNU]_macros attribute so that
+	     DW_FORM_sec_offset forms get correctly interpreted as
+	     offset into .debug_macro.  XXX Deal with DW_MACRO_import_sup
+	     (swap .dbg) for DW_FORM_sec_offset? */
+	  attributes[i].code = (fake_cu.version == 4 ? DW_AT_GNU_macros
+						     : DW_AT_macros);
+	  attributes[i].form = proto->forms[i];
+	  attributes[i].valp = (void *) readp;
+	  attributes[i].cu = &fake_cu;
+
+	  /* We don't want forms that aren't allowed because they could
+	     read from the "abbrev" like DW_FORM_implicit_const.  */
+	  if (! libdw_valid_user_form (attributes[i].form))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      free (attributesp);
+	      return -1;
+	    }
+
+	  size_t len = __libdw_form_val_len (&fake_cu, proto->forms[i], readp);
+	  if (unlikely (len == (size_t) -1))
+	    {
+	      free (attributesp);
+	      return -1;
+	    }
+
+	  readp += len;
+	}
+
+      Dwarf_Macro macro = {
+	.table = table,
+	.opcode = opcode,
+	.attributes = attributes,
+      };
+
+      int res = callback (&macro, arg);
+      if (unlikely (attributesp != NULL))
+	free (attributesp);
+
+      if (res != DWARF_CB_OK)
+	return readp - startp;
+    }
+
+  return 0;
+}
+
+/* Token layout:
+
+   - The highest bit is used for distinguishing between callers that
+     know that opcode 0xff may have one of two incompatible meanings.
+     The mask that we use for selecting this bit is
+     DWARF_GETMACROS_START.
+
+   - The rest of the token (31 or 63 bits) encodes address inside the
+     macro unit.
+
+   Besides, token value of 0 signals end of iteration and -1 is
+   reserved for signaling errors.  That means it's impossible to
+   represent maximum offset of a .debug_macro unit to new-style
+   callers (which in practice decreases the permissible macro unit
+   size by another 1 byte).  */
+
+static ptrdiff_t
+token_from_offset (ptrdiff_t offset, bool accept_0xff)
+{
+  if (offset == -1 || offset == 0)
+    return offset;
+
+  /* Make sure the offset didn't overflow into the flag bit.  */
+  if ((offset & DWARF_GETMACROS_START) != 0)
+    {
+      __libdw_seterrno (DWARF_E_TOO_BIG);
+      return -1;
+    }
+
+  if (accept_0xff)
+    offset |= DWARF_GETMACROS_START;
+
+  return offset;
+}
+
+static ptrdiff_t
+offset_from_token (ptrdiff_t token, bool *accept_0xffp)
+{
+  *accept_0xffp = (token & DWARF_GETMACROS_START) != 0;
+  token &= ~DWARF_GETMACROS_START;
+
+  return token;
+}
+
+static ptrdiff_t
+gnu_macros_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
+			  int (*callback) (Dwarf_Macro *, void *),
+			  void *arg, ptrdiff_t offset, bool accept_0xff,
+			  Dwarf_Die *cudie)
+{
+  assert (offset >= 0);
+
+  if (macoff >= dbg->sectiondata[IDX_debug_macro]->d_size)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1;
+    }
+
+  return read_macros (dbg, IDX_debug_macro, macoff,
+		      callback, arg, offset, accept_0xff, cudie);
+}
+
+static ptrdiff_t
+macro_info_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
+			  int (*callback) (Dwarf_Macro *, void *),
+			  void *arg, ptrdiff_t offset, Dwarf_Die *cudie)
+{
+  assert (offset >= 0);
+
+  return read_macros (dbg, IDX_debug_macinfo, macoff,
+		      callback, arg, offset, true, cudie);
+}
+
+ptrdiff_t
+dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
+		     int (*callback) (Dwarf_Macro *, void *),
+		     void *arg, ptrdiff_t token)
+{
+  if (dbg == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DWARF);
+      return -1;
+    }
+
+  bool accept_0xff;
+  ptrdiff_t offset = offset_from_token (token, &accept_0xff);
+  assert (accept_0xff);
+
+  offset = gnu_macros_getmacros_off (dbg, macoff, callback, arg, offset,
+				     accept_0xff, NULL);
+
+  return token_from_offset (offset, accept_0xff);
+}
+
+ptrdiff_t
+dwarf_getmacros (Dwarf_Die *cudie, int (*callback) (Dwarf_Macro *, void *),
+		 void *arg, ptrdiff_t token)
+{
+  if (cudie == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DWARF);
+      return -1;
+    }
+
+  /* This function might be called from a code that expects to see
+     DW_MACINFO_* opcodes, not DW_MACRO_{GNU_,}* ones.  It is fine to
+     serve most DW_MACRO_{GNU_,}* opcodes to such code, because those
+     whose values are the same as DW_MACINFO_* ones also have the same
+     behavior.  It is not very likely that a .debug_macro section
+     would only use the part of opcode space that it shares with
+     .debug_macinfo, but it is possible.  Serving the opcodes that are
+     only valid in DW_MACRO_{GNU_,}* domain is OK as well, because
+     clients in general need to be ready that newer standards define
+     more opcodes, and have coping mechanisms for unfamiliar opcodes.
+
+     The one exception to the above rule is opcode 0xff, which has
+     concrete semantics in .debug_macinfo, but falls into vendor block
+     in .debug_macro, and can be assigned to do whatever.  There is
+     some small probability that the two opcodes would look
+     superficially similar enough that a client would be confused and
+     misbehave as a result.  For this reason, we refuse to serve
+     through this interface 0xff's originating from .debug_macro
+     unless the TOKEN that we obtained indicates the call originates
+     from a new-style caller.  See above for details on what
+     information is encoded into tokens.  */
+
+  bool accept_0xff;
+  ptrdiff_t offset = offset_from_token (token, &accept_0xff);
+
+  /* DW_AT_macro_info */
+  if (dwarf_hasattr (cudie, DW_AT_macro_info))
+    {
+      Dwarf_Word macoff;
+      if (get_offset_from (cudie, DW_AT_macro_info, &macoff) != 0)
+	return -1;
+      offset = macro_info_getmacros_off (cudie->cu->dbg, macoff,
+					 callback, arg, offset, cudie);
+    }
+  else
+    {
+      /* DW_AT_GNU_macros, DW_AT_macros */
+      Dwarf_Word macoff;
+      if (get_offset_from (cudie, DW_AT_GNU_macros, &macoff) != 0
+	  && get_offset_from (cudie, DW_AT_macros, &macoff) != 0)
+	return -1;
+      offset = gnu_macros_getmacros_off (cudie->cu->dbg, macoff,
+					 callback, arg, offset, accept_0xff,
+					 cudie);
+    }
+
+  return token_from_offset (offset, accept_0xff);
+}
diff --git a/libdw/dwarf_getpubnames.c b/libdw/dwarf_getpubnames.c
new file mode 100644
index 0000000..de72640
--- /dev/null
+++ b/libdw/dwarf_getpubnames.c
@@ -0,0 +1,243 @@
+/* Get public symbol information.
+   Copyright (C) 2002, 2003, 2004, 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libdwP.h>
+#include <dwarf.h>
+#include <system.h>
+
+
+static int
+get_offsets (Dwarf *dbg)
+{
+  size_t allocated = 0;
+  size_t cnt = 0;
+  struct pubnames_s *mem = NULL;
+  const size_t entsize = sizeof (struct pubnames_s);
+  unsigned char *const startp = dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+  unsigned char *readp = startp;
+  unsigned char *endp = readp + dbg->sectiondata[IDX_debug_pubnames]->d_size;
+
+  while (readp + 14 < endp)
+    {
+      /* If necessary, allocate more entries.  */
+      if (cnt >= allocated)
+	{
+	  allocated = MAX (10, 2 * allocated);
+	  struct pubnames_s *newmem = realloc (mem, allocated * entsize);
+	  if (newmem == NULL)
+	    {
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	    err_return:
+	      free (mem);
+	      return -1;
+	    }
+
+	  mem = newmem;
+	}
+
+      /* Read the set header.  */
+      int len_bytes = 4;
+      Dwarf_Off len = read_4ubyte_unaligned_inc (dbg, readp);
+      if (len == DWARF3_LENGTH_64_BIT)
+	{
+	  len = read_8ubyte_unaligned_inc (dbg, readp);
+	  len_bytes = 8;
+	}
+      else if (unlikely (len >= DWARF3_LENGTH_MIN_ESCAPE_CODE
+			 && len <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  goto err_return;
+	}
+
+      /* Now we know the offset of the first offset/name pair.  */
+      mem[cnt].set_start = readp + 2 + 2 * len_bytes - startp;
+      mem[cnt].address_len = len_bytes;
+      size_t max_size = dbg->sectiondata[IDX_debug_pubnames]->d_size;
+      if (mem[cnt].set_start >= max_size
+	  || len - (2 + 2 * len_bytes) > max_size - mem[cnt].set_start)
+	/* Something wrong, the first entry is beyond the end of
+	   the section.  Or the length of the whole unit is too big.  */
+	break;
+
+      /* Read the version.  It better be two for now.  */
+      uint16_t version = read_2ubyte_unaligned (dbg, readp);
+      if (unlikely (version != 2))
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_VERSION);
+	  goto err_return;
+	}
+
+      /* Get the CU offset.  */
+      if (__libdw_read_offset (dbg, dbg, IDX_debug_pubnames,
+			       readp + 2, len_bytes,
+			       &mem[cnt].cu_offset, IDX_debug_info, 3))
+	/* Error has been already set in reader.  */
+	goto err_return;
+
+      /* Determine the size of the CU header.  */
+      unsigned char *infop
+	= ((unsigned char *) dbg->sectiondata[IDX_debug_info]->d_buf
+	   + mem[cnt].cu_offset);
+      if (read_4ubyte_unaligned_noncvt (infop) == DWARF3_LENGTH_64_BIT)
+	mem[cnt].cu_header_size = 23;
+      else
+	mem[cnt].cu_header_size = 11;
+
+      ++cnt;
+
+      /* Advance to the next set.  */
+      readp += len;
+    }
+
+  if (mem == NULL || cnt == 0)
+    {
+      free (mem);
+      __libdw_seterrno (DWARF_E_NO_ENTRY);
+      return -1;
+    }
+
+  dbg->pubnames_sets = realloc (mem, cnt * entsize);
+  dbg->pubnames_nsets = cnt;
+
+  return 0;
+}
+
+
+ptrdiff_t
+dwarf_getpubnames (Dwarf *dbg,
+		   int (*callback) (Dwarf *, Dwarf_Global *, void *),
+		   void *arg, ptrdiff_t offset)
+{
+  if (dbg == NULL)
+    return -1l;
+
+  if (unlikely (offset < 0))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1l;
+    }
+
+  /* Make sure it is a valid offset.  */
+  if (unlikely (dbg->sectiondata[IDX_debug_pubnames] == NULL
+		|| ((size_t) offset
+		    >= dbg->sectiondata[IDX_debug_pubnames]->d_size)))
+    /* No (more) entry.  */
+    return 0;
+
+  /* If necessary read the set information.  */
+  if (dbg->pubnames_nsets == 0 && unlikely (get_offsets (dbg) != 0))
+    return -1l;
+
+  /* Find the place where to start.  */
+  size_t cnt;
+  if (offset == 0)
+    {
+      cnt = 0;
+      offset = dbg->pubnames_sets[0].set_start;
+    }
+  else
+    {
+      for (cnt = 0; cnt + 1 < dbg->pubnames_nsets; ++cnt)
+	if ((Dwarf_Off) offset >= dbg->pubnames_sets[cnt].set_start)
+	  {
+	    assert ((Dwarf_Off) offset
+		    < dbg->pubnames_sets[cnt + 1].set_start);
+	    break;
+	  }
+      assert (cnt + 1 < dbg->pubnames_nsets);
+    }
+
+  unsigned char *startp
+    = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+  unsigned char *endp
+    = startp + dbg->sectiondata[IDX_debug_pubnames]->d_size;
+  unsigned char *readp = startp + offset;
+  while (1)
+    {
+      Dwarf_Global gl;
+
+      gl.cu_offset = (dbg->pubnames_sets[cnt].cu_offset
+		      + dbg->pubnames_sets[cnt].cu_header_size);
+
+      while (1)
+	{
+	  /* READP points to the next offset/name pair.  */
+	  if (readp + dbg->pubnames_sets[cnt].address_len > endp)
+	    goto invalid_dwarf;
+	  if (dbg->pubnames_sets[cnt].address_len == 4)
+	    gl.die_offset = read_4ubyte_unaligned_inc (dbg, readp);
+	  else
+	    gl.die_offset = read_8ubyte_unaligned_inc (dbg, readp);
+
+	  /* If the offset is zero we reached the end of the set.  */
+	  if (gl.die_offset == 0)
+	    break;
+
+	  /* Add the CU offset.  */
+	  gl.die_offset += dbg->pubnames_sets[cnt].cu_offset;
+
+	  gl.name = (char *) readp;
+	  readp = (unsigned char *) memchr (gl.name, '\0', endp - readp);
+	  if (unlikely (readp == NULL))
+	    {
+	    invalid_dwarf:
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return -1l;
+	    }
+	  readp++;
+
+	  /* We found name and DIE offset.  Report it.  */
+	  if (callback (dbg, &gl, arg) != DWARF_CB_OK)
+	    {
+	      /* The user wants us to stop.  Return the offset of the
+		 next entry.  */
+	      return readp - startp;
+	    }
+	}
+
+      if (++cnt == dbg->pubnames_nsets)
+	/* This was the last set.  */
+	break;
+
+      startp = (unsigned char *) dbg->sectiondata[IDX_debug_pubnames]->d_buf;
+      readp = startp + dbg->pubnames_sets[cnt].set_start;
+    }
+
+  /* We are done.  No more entries.  */
+  return 0;
+}
diff --git a/libdw/dwarf_getscopes.c b/libdw/dwarf_getscopes.c
new file mode 100644
index 0000000..ce073b1
--- /dev/null
+++ b/libdw/dwarf_getscopes.c
@@ -0,0 +1,207 @@
+/* Return scope DIEs containing PC address.
+   Copyright (C) 2005, 2007, 2015 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+struct args
+{
+  Dwarf_Addr pc;
+  Dwarf_Die *scopes;
+  unsigned int inlined, nscopes;
+  Dwarf_Die inlined_origin;
+};
+
+/* Preorder visitor: prune the traversal if this DIE does not contain PC.  */
+static int
+pc_match (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg)
+{
+  struct args *a = arg;
+
+  if (a->scopes != NULL)
+    die->prune = true;
+  else
+    {
+      /* dwarf_haspc returns an error if there are no appropriate attributes.
+	 But we use it indiscriminantly instead of presuming which tags can
+	 have PC attributes.  So when it fails for that reason, treat it just
+	 as a nonmatching return.  */
+      int result = INTUSE(dwarf_haspc) (&die->die, a->pc);
+      if (result < 0)
+	{
+	  int error = INTUSE(dwarf_errno) ();
+	  if (error != DWARF_E_NOERROR
+	      && error != DWARF_E_NO_DEBUG_RANGES
+	      && error != DWARF_E_NO_DEBUG_RNGLISTS)
+	    {
+	      __libdw_seterrno (error);
+	      return -1;
+	    }
+	  result = 0;
+	}
+      if (result == 0)
+    	die->prune = true;
+
+      if (!die->prune
+	  && INTUSE (dwarf_tag) (&die->die) == DW_TAG_inlined_subroutine)
+	a->inlined = depth;
+    }
+
+  return 0;
+}
+
+/* Preorder visitor for second partial traversal after finding a
+   concrete inlined instance.  */
+static int
+origin_match (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg)
+{
+  struct args *a = arg;
+
+  if (die->die.addr != a->inlined_origin.addr)
+    return 0;
+
+  /* We have a winner!  This is the abstract definition of the inline
+     function of which A->scopes[A->nscopes - 1] is a concrete instance.
+  */
+
+  unsigned int nscopes = a->nscopes + depth;
+  Dwarf_Die *scopes = realloc (a->scopes, nscopes * sizeof scopes[0]);
+  if (scopes == NULL)
+    {
+      /* a->scopes will be freed by dwarf_getscopes on error.  */
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return -1;
+    }
+
+  a->scopes = scopes;
+  do
+    {
+      die = die->parent;
+      scopes[a->nscopes++] = die->die;
+    }
+  while (a->nscopes < nscopes);
+  assert (die->parent == NULL);
+  return a->nscopes;
+}
+
+/* Postorder visitor: first (innermost) call wins.  */
+static int
+pc_record (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg)
+{
+  struct args *a = arg;
+
+  if (die->prune)
+    return 0;
+
+  if (a->scopes == NULL)
+    {
+      /* We have hit the innermost DIE that contains the target PC.  */
+
+      a->nscopes = depth + 1 - a->inlined;
+      a->scopes = malloc (a->nscopes * sizeof a->scopes[0]);
+      if (a->scopes == NULL)
+	{
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  return -1;
+	}
+
+      for (unsigned int i = 0; i < a->nscopes; ++i)
+	{
+	  a->scopes[i] = die->die;
+	  die = die->parent;
+	}
+
+      if (a->inlined == 0)
+	{
+	  assert (die == NULL);
+	  return a->nscopes;
+	}
+
+      /* This is the concrete inlined instance itself.
+	 Record its abstract_origin pointer.  */
+      Dwarf_Die *const inlinedie = &a->scopes[depth - a->inlined];
+
+      assert (INTUSE (dwarf_tag) (inlinedie) == DW_TAG_inlined_subroutine);
+      Dwarf_Attribute attr_mem;
+      Dwarf_Attribute *attr = INTUSE (dwarf_attr) (inlinedie,
+						   DW_AT_abstract_origin,
+						   &attr_mem);
+      if (INTUSE (dwarf_formref_die) (attr, &a->inlined_origin) == NULL)
+	return -1;
+      return 0;
+    }
+
+
+  /* We've recorded the scopes back to one that is a concrete inlined
+     instance.  Now return out of the traversal back to the scope
+     containing that instance.  */
+
+  assert (a->inlined);
+  if (depth >= a->inlined)
+    /* Not there yet.  */
+    return 0;
+
+  /* This is the innermost inline scope, we are done here.  */
+  return a->nscopes;
+}
+
+
+int
+dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc, Dwarf_Die **scopes)
+{
+  if (cudie == NULL)
+    return -1;
+
+  struct Dwarf_Die_Chain cu = { .parent = NULL, .die = *cudie };
+  struct args a = { .pc = pc };
+
+  int result = __libdw_visit_scopes (0, &cu, NULL, &pc_match, &pc_record, &a);
+
+  if (result >= 0 && a.scopes != NULL && a.inlined > 0)
+    {
+      /* We like the find the inline function's abstract definition
+         scope, but that might be in a different CU.  */
+      cu.die = CUDIE (a.inlined_origin.cu);
+      result = __libdw_visit_scopes (0, &cu, NULL, &origin_match, NULL, &a);
+    }
+
+  if (result > 0)
+    *scopes = a.scopes;
+  else if (result < 0)
+    free (a.scopes);
+
+  return result;
+}
diff --git a/libdw/dwarf_getscopes_die.c b/libdw/dwarf_getscopes_die.c
new file mode 100644
index 0000000..8e2e41d
--- /dev/null
+++ b/libdw/dwarf_getscopes_die.c
@@ -0,0 +1,74 @@
+/* Return scope DIEs containing given DIE.
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include "libdwP.h"
+#include <assert.h>
+#include <stdlib.h>
+
+static int
+scope_visitor (unsigned int depth, struct Dwarf_Die_Chain *die, void *arg)
+{
+  if (die->die.addr != *(void **) arg)
+    return 0;
+
+  Dwarf_Die *scopes = malloc (depth * sizeof scopes[0]);
+  if (scopes == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return -1;
+    }
+
+  unsigned int i = 0;
+  do
+    {
+      scopes[i++] = die->die;
+      die = die->parent;
+    }
+  while (die != NULL);
+  assert (i == depth);
+
+  *(void **) arg = scopes;
+  return depth;
+}
+
+int
+dwarf_getscopes_die (Dwarf_Die *die, Dwarf_Die **scopes)
+{
+  if (die == NULL)
+    return -1;
+
+  struct Dwarf_Die_Chain cu = { .die = CUDIE (die->cu), .parent = NULL };
+  void *info = die->addr;
+  int result = __libdw_visit_scopes (1, &cu, NULL, &scope_visitor, NULL, &info);
+  if (result > 0)
+    *scopes = info;
+  return result;
+}
diff --git a/libdw/dwarf_getscopevar.c b/libdw/dwarf_getscopevar.c
new file mode 100644
index 0000000..7b1416f
--- /dev/null
+++ b/libdw/dwarf_getscopevar.c
@@ -0,0 +1,159 @@
+/* Find a named variable or parameter within given scopes.
+   Copyright (C) 2005-2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdbool.h>
+#include <string.h>
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+/* Find the containing CU's files.  */
+static int
+getfiles (Dwarf_Die *die, Dwarf_Files **files)
+{
+  return INTUSE(dwarf_getsrcfiles) (&CUDIE (die->cu), files, NULL);
+}
+
+/* Fetch an attribute that should have a constant integer form.  */
+static int
+getattr (Dwarf_Die *die, int search_name, Dwarf_Word *value)
+{
+  Dwarf_Attribute attr_mem;
+  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (die, search_name,
+						      &attr_mem), value);
+}
+
+static inline int
+file_matches (const char *lastfile,
+              size_t match_file_len, const char *match_file,
+              Dwarf_Files *files, size_t idx,
+              bool *lastfile_matches)
+{
+  if (idx >= files->nfiles)
+    return false;
+  const char *file = files->info[idx].name;
+  if (file != lastfile)
+    {
+      size_t len = strlen (file);
+      *lastfile_matches = (len >= match_file_len
+                          && !memcmp (match_file, file, match_file_len)
+                          && (len == match_file_len
+                              || file[len - match_file_len - 1] == '/'));
+    }
+  return *lastfile_matches;
+}
+
+/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
+   Ignore the first SKIP_SHADOWS scopes that match the name.
+   If MATCH_FILE is not null, accept only declaration in that source file;
+   if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration
+   at that line and column.
+
+   If successful, fill in *RESULT with the DIE of the variable found,
+   and return N where SCOPES[N] is the scope defining the variable.
+   Return -1 for errors or -2 for no matching variable found.  */
+
+int
+dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
+		   const char *name, int skip_shadows,
+		   const char *match_file, int match_lineno, int match_linecol,
+		   Dwarf_Die *result)
+{
+  /* Match against the given file name.  */
+  size_t match_file_len = match_file == NULL ? 0 : strlen (match_file);
+  bool lastfile_matches = false;
+  const char *lastfile = NULL;
+
+  /* Start with the innermost scope and move out.  */
+  for (int out = 0; out < nscopes; ++out)
+    if (INTUSE(dwarf_haschildren) (&scopes[out]))
+      {
+	if (INTUSE(dwarf_child) (&scopes[out], result) != 0)
+	  return -1;
+	do
+	  {
+	    switch (INTUSE(dwarf_tag) (result))
+	      {
+	      case DW_TAG_variable:
+	      case DW_TAG_formal_parameter:
+		break;
+
+	      default:
+		continue;
+	      }
+
+	    /* Only get here for a variable or parameter.  Check the name.  */
+	    const char *diename = INTUSE(dwarf_diename) (result);
+	    if (diename != NULL && !strcmp (name, diename))
+	      {
+		/* We have a matching name.  */
+
+		if (skip_shadows > 0)
+		  {
+		    /* Punt this scope for the one it shadows.  */
+		    --skip_shadows;
+		    break;
+		  }
+
+		if (match_file != NULL)
+		  {
+		    /* Check its decl_file.  */
+
+		    Dwarf_Word i;
+		    Dwarf_Files *files;
+		    if (getattr (result, DW_AT_decl_file, &i) != 0
+			|| getfiles (&scopes[out], &files) != 0)
+		      break;
+
+		    if (!file_matches (lastfile, match_file_len, match_file,
+		                       files, i, &lastfile_matches))
+		      break;
+
+		    if (match_lineno > 0
+			&& (getattr (result, DW_AT_decl_line, &i) != 0
+			    || (int) i != match_lineno))
+		      break;
+		    if (match_linecol > 0
+			&& (getattr (result, DW_AT_decl_column, &i) != 0
+			    || (int) i != match_linecol))
+		      break;
+		  }
+
+		/* We have a winner!  */
+		return out;
+	      }
+	  }
+	while (INTUSE(dwarf_siblingof) (result, result) == 0);
+      }
+
+  return -2;
+}
diff --git a/libdw/dwarf_getsrc_die.c b/libdw/dwarf_getsrc_die.c
new file mode 100644
index 0000000..a95179f
--- /dev/null
+++ b/libdw/dwarf_getsrc_die.c
@@ -0,0 +1,74 @@
+/* Find line information for address.
+   Copyright (C) 2004, 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <assert.h>
+
+
+Dwarf_Line *
+dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr)
+{
+  Dwarf_Lines *lines;
+  size_t nlines;
+
+  if (INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines) != 0)
+    return NULL;
+
+  /* The lines are sorted by address, so we can use binary search.  */
+  if (nlines > 0)
+    {
+      size_t l = 0, u = nlines - 1;
+      while (l < u)
+	{
+	  size_t idx = u - (u - l) / 2;
+	  Dwarf_Line *line = &lines->info[idx];
+	  if (addr < line->addr)
+	    u = idx - 1;
+	  else
+	    l = idx;
+	}
+
+      /* This is guaranteed for us by libdw read_srclines.  */
+      assert (lines->info[nlines - 1].end_sequence);
+
+      /* The last line which is less than or equal to addr is what we
+	 want, unless it is the end_sequence which is after the
+	 current line sequence.  */
+      Dwarf_Line *line = &lines->info[l];
+      if (! line->end_sequence && line->addr <= addr)
+	return &lines->info[l];
+    }
+
+  __libdw_seterrno (DWARF_E_ADDR_OUTOFRANGE);
+  return NULL;
+}
diff --git a/libdw/dwarf_getsrc_file.c b/libdw/dwarf_getsrc_file.c
new file mode 100644
index 0000000..03da431
--- /dev/null
+++ b/libdw/dwarf_getsrc_file.c
@@ -0,0 +1,178 @@
+/* Find line information for given file/line/column triple.
+   Copyright (C) 2005-2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdwP.h"
+
+
+int
+dwarf_getsrc_file (Dwarf *dbg, const char *fname, int lineno, int column,
+		   Dwarf_Line ***srcsp, size_t *nsrcs)
+{
+  if (dbg == NULL)
+    return -1;
+
+  bool is_basename = strchr (fname, '/') == NULL;
+
+  size_t max_match = *nsrcs ?: ~0u;
+  size_t act_match = *nsrcs;
+  size_t cur_match = 0;
+  Dwarf_Line **match = *nsrcs == 0 ? NULL : *srcsp;
+
+  size_t cuhl;
+  Dwarf_Off noff;
+  for (Dwarf_Off off = 0;
+       INTUSE(dwarf_nextcu) (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0;
+       off = noff)
+    {
+      Dwarf_Die cudie_mem;
+      Dwarf_Die *cudie = INTUSE(dwarf_offdie) (dbg, off + cuhl, &cudie_mem);
+      if (cudie == NULL)
+	continue;
+
+      /* Get the line number information for this file.  */
+      Dwarf_Lines *lines;
+      size_t nlines;
+      if (INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines) != 0)
+	{
+	  /* Ignore a CU that just has no DW_AT_stmt_list at all.  */
+	  int error = INTUSE(dwarf_errno) ();
+	  if (error == 0)
+	    continue;
+	  __libdw_seterrno (error);
+	  return -1;
+	}
+
+      /* Search through all the line number records for a matching
+	 file and line/column number.  If any of the numbers is zero,
+	 no match is performed.  */
+      unsigned int lastfile = UINT_MAX;
+      bool lastmatch = false;
+      for (size_t cnt = 0; cnt < nlines; ++cnt)
+	{
+	  Dwarf_Line *line = &lines->info[cnt];
+
+	  if (lastfile != line->file)
+	    {
+	      lastfile = line->file;
+	      if (lastfile >= line->files->nfiles)
+		{
+		  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+		  return -1;
+		}
+
+	      /* Match the name with the name the user provided.  */
+	      const char *fname2 = line->files->info[lastfile].name;
+	      if (is_basename)
+		lastmatch = strcmp (xbasename (fname2), fname) == 0;
+	      else
+		lastmatch = strcmp (fname2, fname) == 0;
+	    }
+	  if (!lastmatch)
+	    continue;
+
+	  /* See whether line and possibly column match.  */
+	  if (lineno != 0
+	      && (lineno > line->line
+		  || (column != 0 && column > line->column)))
+	    /* Cannot match.  */
+	    continue;
+
+	  /* Determine whether this is the best match so far.  */
+	  size_t inner;
+	  for (inner = 0; inner < cur_match; ++inner)
+	    if (match[inner]->files == line->files
+		&& match[inner]->file == line->file)
+	      break;
+	  if (inner < cur_match
+	      && (match[inner]->line != line->line
+		  || match[inner]->line != lineno
+		  || (column != 0
+		      && (match[inner]->column != line->column
+			  || match[inner]->column != column))))
+	    {
+	      /* We know about this file already.  If this is a better
+		 match for the line number, use it.  */
+	      if (match[inner]->line >= line->line
+		  && (match[inner]->line != line->line
+		      || match[inner]->column >= line->column))
+		/*  Use the new line.  Otherwise the old one.  */
+		match[inner] = line;
+	      continue;
+	    }
+
+	  if (cur_match < max_match)
+	    {
+	      if (cur_match == act_match)
+		{
+		  /* Enlarge the array for the results.  */
+		  act_match += 10;
+		  Dwarf_Line **newp = realloc (match,
+					       act_match
+					       * sizeof (Dwarf_Line *));
+		  if (newp == NULL)
+		    {
+		      free (match);
+		      __libdw_seterrno (DWARF_E_NOMEM);
+		      return -1;
+		    }
+		  match = newp;
+		}
+
+	      match[cur_match++] = line;
+	    }
+	}
+
+      /* If we managed to find as many matches as the user requested
+	 already, there is no need to go on to the next CU.  */
+      if (cur_match == max_match)
+	break;
+    }
+
+  if (cur_match > 0)
+    {
+      assert (*nsrcs == 0 || *srcsp == match);
+
+      *nsrcs = cur_match;
+      *srcsp = match;
+
+      return 0;
+    }
+
+  __libdw_seterrno (DWARF_E_NO_MATCH);
+  return -1;
+}
diff --git a/libdw/dwarf_getsrcdirs.c b/libdw/dwarf_getsrcdirs.c
new file mode 100644
index 0000000..8160ed3
--- /dev/null
+++ b/libdw/dwarf_getsrcdirs.c
@@ -0,0 +1,45 @@
+/* Find include directories in source file information.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_getsrcdirs (Dwarf_Files *files, const char *const **result, size_t *ndirs)
+{
+  if (files == NULL)
+    return -1;
+
+  *result = (void *) &files->info[files->nfiles];
+  *ndirs = files->ndirs;
+  return 0;
+}
diff --git a/libdw/dwarf_getsrcfiles.c b/libdw/dwarf_getsrcfiles.c
new file mode 100644
index 0000000..cd2e5b5
--- /dev/null
+++ b/libdw/dwarf_getsrcfiles.c
@@ -0,0 +1,116 @@
+/* Return source file information of CU.
+   Copyright (C) 2004, 2005, 2013, 2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files, size_t *nfiles)
+{
+  if (cudie == NULL)
+    return -1;
+  if (! is_cudie (cudie))
+    {
+      __libdw_seterrno (DWARF_E_NOT_CUDIE);
+      return -1;
+    }
+
+  int res = -1;
+
+  /* Get the information if it is not already known.  */
+  struct Dwarf_CU *const cu = cudie->cu;
+  if (cu->files == NULL)
+    {
+      /* For split units there might be a simple file table (without lines).
+	 If not, use the one from the skeleton.  */
+      if (cu->unit_type == DW_UT_split_compile
+	  || cu->unit_type == DW_UT_split_type)
+	{
+	  /* We tried, assume we fail...  */
+	  cu->files = (void *) -1;
+
+	  /* See if there is a .debug_line section, for split CUs
+	     the table is at offset zero.  */
+	  if (cu->dbg->sectiondata[IDX_debug_line] != NULL)
+	    {
+	      Dwarf_Off dwp_off;
+	      if (INTUSE(dwarf_cu_dwp_section_info) (cu, DW_SECT_LINE,
+						     &dwp_off, NULL) == 0)
+		{
+		  /* We are only interested in the files, the lines will
+		     always come from the skeleton.  */
+		  res = __libdw_getsrclines (cu->dbg, dwp_off,
+					     __libdw_getcompdir (cudie),
+					     cu->address_size, NULL,
+					     &cu->files);
+		}
+	    }
+	  else
+	    {
+	      Dwarf_CU *skel = __libdw_find_split_unit (cu);
+	      if (skel != NULL)
+		{
+		  Dwarf_Die skeldie = CUDIE (skel);
+		  res = INTUSE(dwarf_getsrcfiles) (&skeldie, files, nfiles);
+		  cu->files = skel->files;
+		}
+	    }
+	}
+      else
+	{
+	  Dwarf_Lines *lines;
+	  size_t nlines;
+
+	  /* Let the more generic function do the work.  It'll create more
+	     data but that will be needed in an real program anyway.  */
+	  res = INTUSE(dwarf_getsrclines) (cudie, &lines, &nlines);
+	}
+    }
+  else if (cu->files != (void *) -1l)
+    /* We already have the information.  */
+    res = 0;
+
+  if (likely (res == 0))
+    {
+      assert (cu->files != NULL && cu->files != (void *) -1l);
+      *files = cu->files;
+      if (nfiles != NULL)
+	*nfiles = cu->files->nfiles;
+    }
+
+  // XXX Eventually: unlocking here.
+
+  return res;
+}
+INTDEF (dwarf_getsrcfiles)
diff --git a/libdw/dwarf_getsrclines.c b/libdw/dwarf_getsrclines.c
new file mode 100644
index 0000000..69e10c7
--- /dev/null
+++ b/libdw/dwarf_getsrclines.c
@@ -0,0 +1,1268 @@
+/* Return line number information of CU.
+   Copyright (C) 2004-2010, 2013, 2014, 2015, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+#include <search.h>
+
+#include "dwarf.h"
+#include "libdwP.h"
+
+
+struct filelist
+{
+  Dwarf_Fileinfo info;
+  struct filelist *next;
+};
+
+struct linelist
+{
+  Dwarf_Line line;
+  struct linelist *next;
+  size_t sequence;
+};
+
+
+/* Compare by Dwarf_Line.addr, given pointers into an array of pointers.  */
+static int
+compare_lines (const void *a, const void *b)
+{
+  struct linelist *const *p1 = a;
+  struct linelist *const *p2 = b;
+  struct linelist *list1 = *p1;
+  struct linelist *list2 = *p2;
+  Dwarf_Line *line1 = &list1->line;
+  Dwarf_Line *line2 = &list2->line;
+
+  if (line1->addr != line2->addr)
+    return (line1->addr < line2->addr) ? -1 : 1;
+
+  /* An end_sequence marker precedes a normal record at the same address.  */
+  if (line1->end_sequence != line2->end_sequence)
+    return line2->end_sequence - line1->end_sequence;
+
+  /* Otherwise, the linelist sequence maintains a stable sort.  */
+  return (list1->sequence < list2->sequence) ? -1
+    : (list1->sequence > list2->sequence) ? 1
+    : 0;
+}
+
+struct line_state
+{
+  Dwarf_Word addr;
+  unsigned int op_index;
+  unsigned int file;
+  int64_t line;
+  unsigned int column;
+  uint_fast8_t is_stmt;
+  bool basic_block;
+  bool prologue_end;
+  bool epilogue_begin;
+  unsigned int isa;
+  unsigned int discriminator;
+  struct linelist *linelist;
+  size_t nlinelist;
+  unsigned int end_sequence;
+  unsigned int context;
+  unsigned int function_name;
+};
+
+static inline void
+run_advance_pc (struct line_state *state, unsigned int op_advance,
+                uint_fast8_t minimum_instr_len, uint_fast8_t max_ops_per_instr)
+{
+  state->addr += minimum_instr_len * ((state->op_index + op_advance)
+				      / max_ops_per_instr);
+  state->op_index = (state->op_index + op_advance) % max_ops_per_instr;
+}
+
+static inline bool
+add_new_line (struct line_state *state, struct linelist *new_line)
+{
+  /* Set the line information.  For some fields we use bitfields,
+     so we would lose information if the encoded values are too large.
+     Check just for paranoia, and call the data "invalid" if it
+     violates our assumptions on reasonable limits for the values.  */
+  new_line->next = state->linelist;
+  new_line->sequence = state->nlinelist;
+  state->linelist = new_line;
+  ++(state->nlinelist);
+
+  /* Set the line information.  For some fields we use bitfields,
+     so we would lose information if the encoded values are too large.
+     Check just for paranoia, and call the data "invalid" if it
+     violates our assumptions on reasonable limits for the values.  */
+#define SET(field)						      \
+  do {								      \
+     new_line->line.field = state->field;			      \
+     if (unlikely (new_line->line.field != state->field))	      \
+       return true;						      \
+   } while (0)
+
+  /* Same as above, but don't flag as "invalid" just use truncated
+     value.  Used for discriminator for which llvm might use a value
+     that won't fit 24 bits.  */
+#define SETX(field)						      \
+     new_line->line.field = state->field;			      \
+
+  SET (addr);
+  SET (op_index);
+  SET (file);
+  SET (line);
+  SET (column);
+  SET (is_stmt);
+  SET (basic_block);
+  SET (end_sequence);
+  SET (prologue_end);
+  SET (epilogue_begin);
+  SET (isa);
+  SETX (discriminator);
+  SET (context);
+  SET (function_name);
+
+#undef SET
+
+  return false;
+}
+
+static int
+read_srclines (Dwarf *dbg,
+	       const unsigned char *linep, const unsigned char *lineendp,
+	       const char *comp_dir, unsigned address_size,
+	       Dwarf_Lines **linesp, Dwarf_Files **filesp)
+{
+  int res = -1;
+
+  struct filelist *filelist = NULL;
+  size_t nfilelist = 0;
+  size_t ndirlist = 0;
+
+  /* If there are a large number of lines, files or dirs don't blow up
+     the stack.  Stack allocate some entries, only dynamically malloc
+     when more than MAX.  */
+#define MAX_STACK_ALLOC 4096
+#define MAX_STACK_LINES (MAX_STACK_ALLOC / 2)
+#define MAX_STACK_FILES (MAX_STACK_ALLOC / 4)
+#define MAX_STACK_DIRS  (MAX_STACK_ALLOC / 16)
+
+  /* Initial statement program state (except for stmt_list, see below).  */
+  struct line_state state =
+    {
+      .linelist = NULL,
+      .nlinelist = 0,
+      .addr = 0,
+      .op_index = 0,
+      .file = 1,
+      /* We only store int but want to check for overflow (see SET above).  */
+      .line = 1,
+      .column = 0,
+      .basic_block = false,
+      .prologue_end = false,
+      .epilogue_begin = false,
+      .isa = 0,
+      .discriminator = 0,
+      .context = 0,
+      .function_name = 0
+    };
+
+  /* The dirs normally go on the stack, but if there are too many
+     we alloc them all.  Set up stack storage early, so we can check on
+     error if we need to free them or not.  */
+  struct dirlist
+  {
+    const char *dir;
+    size_t len;
+  };
+  struct dirlist dirstack[MAX_STACK_DIRS];
+  struct dirlist *dirarray = dirstack;
+
+  if (unlikely (linep + 4 > lineendp))
+    {
+    invalid_data:
+      __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
+      goto out;
+    }
+
+  Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
+  unsigned int length = 4;
+  if (unlikely (unit_length == DWARF3_LENGTH_64_BIT))
+    {
+      if (unlikely (linep + 8 > lineendp))
+	goto invalid_data;
+      unit_length = read_8ubyte_unaligned_inc (dbg, linep);
+      length = 8;
+    }
+
+  /* Check whether we have enough room in the section.  */
+  if (unlikely (unit_length > (size_t) (lineendp - linep)))
+    goto invalid_data;
+  lineendp = linep + unit_length;
+
+  /* The next element of the header is the version identifier.  */
+  if ((size_t) (lineendp - linep) < 2)
+    goto invalid_data;
+  uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
+  if (unlikely (version < 2) || unlikely (version > 5))
+    {
+      __libdw_seterrno (DWARF_E_VERSION);
+      goto out;
+    }
+
+  /* DWARF5 explicitly lists address and segment_selector sizes.  */
+  if (version >= 5)
+    {
+      if ((size_t) (lineendp - linep) < 2)
+	goto invalid_data;
+      size_t line_address_size = *linep++;
+      size_t segment_selector_size = *linep++;
+      if (line_address_size != address_size || segment_selector_size != 0)
+	goto invalid_data;
+    }
+
+  /* Next comes the header length.  */
+  Dwarf_Word header_length;
+  if (length == 4)
+    {
+      if ((size_t) (lineendp - linep) < 4)
+	goto invalid_data;
+      header_length = read_4ubyte_unaligned_inc (dbg, linep);
+    }
+  else
+    {
+      if ((size_t) (lineendp - linep) < 8)
+	goto invalid_data;
+      header_length = read_8ubyte_unaligned_inc (dbg, linep);
+    }
+  const unsigned char *header_start = linep;
+
+  /* Next the minimum instruction length.  */
+  uint_fast8_t minimum_instr_len = *linep++;
+
+  /* Next the maximum operations per instruction, in version 4 format.  */
+  uint_fast8_t max_ops_per_instr = 1;
+  if (version >= 4)
+    {
+      if (unlikely ((size_t) (lineendp - linep) < 1))
+	goto invalid_data;
+      max_ops_per_instr = *linep++;
+      if (unlikely (max_ops_per_instr == 0))
+	goto invalid_data;
+    }
+
+  /* 4 more bytes, is_stmt, line_base, line_range and opcode_base.  */
+  if ((size_t) (lineendp - linep) < 4)
+    goto invalid_data;
+
+  /* Then the flag determining the default value of the is_stmt
+     register.  */
+  uint_fast8_t default_is_stmt = *linep++;
+
+  /* Now the line base.  */
+  int_fast8_t line_base = (int8_t) *linep++;
+
+  /* And the line range.  */
+  uint_fast8_t line_range = *linep++;
+
+  /* The opcode base.  */
+  uint_fast8_t opcode_base = *linep++;
+
+  /* Remember array with the standard opcode length (-1 to account for
+     the opcode with value zero not being mentioned).  */
+  const uint8_t *standard_opcode_lengths = linep - 1;
+  if (unlikely (lineendp - linep < opcode_base - 1))
+    goto invalid_data;
+  linep += opcode_base - 1;
+
+  /* To read DWARF5 dir and file lists we need to know the forms.  For
+     now we skip everything, except the DW_LNCT_path and
+     DW_LNCT_directory_index.  */
+  uint16_t forms[256];
+  unsigned char nforms = 0;
+  unsigned char form_path = -1; /* Which forms is DW_LNCT_path.  */
+  unsigned char form_idx = -1;  /* And which is DW_LNCT_directory_index.  */
+
+  /* To read/skip form data.  */
+  Dwarf_CU fake_cu = {
+    .dbg = dbg,
+    .sec_idx = IDX_debug_line,
+    .version = 5,
+    .offset_size = length,
+    .address_size = address_size,
+    .startp = (void *) linep,
+    .endp = (void *) lineendp,
+  };
+
+  /* First count the entries.  */
+  size_t ndirs = 0;
+  if (version < 5)
+    {
+      const unsigned char *dirp = linep;
+      while (dirp < lineendp && *dirp != 0)
+	{
+	  uint8_t *endp = memchr (dirp, '\0', lineendp - dirp);
+	  if (endp == NULL)
+	    goto invalid_data;
+	  ++ndirs;
+	  dirp = endp + 1;
+	}
+      if (dirp >= lineendp || *dirp != '\0')
+	goto invalid_data;
+      ndirs = ndirs + 1; /* There is always the "unknown" dir.  */
+    }
+  else
+    {
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      nforms = *linep++;
+      for (int i = 0; i < nforms; i++)
+	{
+	  uint16_t desc, form;
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (desc, linep, lineendp);
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (form, linep, lineendp);
+
+	  if (! libdw_valid_user_form (form))
+	    goto invalid_data;
+
+	  forms[i] = form;
+	  if (desc == DW_LNCT_path)
+	    form_path = i;
+	}
+
+      if (nforms > 0 && form_path == (unsigned char) -1)
+	goto invalid_data;
+
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      get_uleb128 (ndirs, linep, lineendp);
+
+      if (nforms == 0 && ndirs != 0)
+	goto invalid_data;
+
+      /* Assume there is at least 1 byte needed per form to describe
+	 the directory.  Filters out insanely large ndirs.  */
+      if (nforms != 0 && ndirs > (size_t) (lineendp - linep) / nforms)
+	goto invalid_data;
+    }
+
+  /* Arrange the list in array form.  */
+  ndirlist = ndirs;
+  if (ndirlist >= MAX_STACK_DIRS)
+    {
+      if (ndirlist > SIZE_MAX / sizeof (*dirarray))
+	goto no_mem;
+      dirarray = malloc (ndirlist * sizeof (*dirarray));
+      if (unlikely (dirarray == NULL))
+	{
+	no_mem:
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  goto out;
+	}
+    }
+
+  /* Entry zero is implicit for older versions, but explicit for 5+.  */
+  struct dirlist comp_dir_elem;
+  if (version < 5)
+    {
+      /* First comes the list of directories.  Add the compilation
+	 directory first since the index zero is used for it.  */
+      comp_dir_elem.dir = comp_dir;
+      comp_dir_elem.len = comp_dir ? strlen (comp_dir) : 0,
+      dirarray[0] = comp_dir_elem;
+      for (unsigned int n = 1; n < ndirlist; n++)
+	{
+	  dirarray[n].dir = (char *) linep;
+	  uint8_t *endp = memchr (linep, '\0', lineendp - linep);
+	  assert (endp != NULL); // Checked above when calculating ndirlist.
+	  dirarray[n].len = endp - linep;
+	  linep = endp + 1;
+	}
+      /* Skip the final NUL byte.  */
+      assert (*linep == '\0'); // Checked above when calculating ndirlist.
+      ++linep;
+    }
+  else
+    {
+      Dwarf_Attribute attr;
+      attr.code = DW_AT_name;
+      attr.cu = &fake_cu;
+      for (unsigned int n = 0; n < ndirlist; n++)
+	{
+	  const char *dir = NULL;
+	  for (unsigned char m = 0; m < nforms; m++)
+	    {
+	      if (m == form_path)
+		{
+		  attr.form = forms[m];
+		  attr.valp = (void *) linep;
+		  dir = dwarf_formstring (&attr);
+		}
+
+	      size_t len = __libdw_form_val_len (&fake_cu, forms[m], linep);
+	      if ((size_t) (lineendp - linep) < len)
+		goto invalid_data;
+
+	      linep += len;
+	    }
+
+	  if (dir == NULL)
+	    goto invalid_data;
+
+	  dirarray[n].dir = dir;
+	  dirarray[n].len = strlen (dir);
+	}
+    }
+
+  /* File index zero doesn't exist for DWARF < 5.  Files are indexed
+     starting from 1.  But for DWARF5 they are indexed starting from
+     zero, but the default index is still 1.  In both cases the
+     "first" file is special and refers to the main compile unit file,
+     equal to the DW_AT_name of the DW_TAG_compile_unit.  */
+  struct filelist null_file =
+    {
+      .info =
+      {
+	.name = "???",
+	.mtime = 0,
+	.length = 0
+      },
+      .next = NULL
+    };
+  filelist = &null_file;
+  nfilelist = 1;
+
+  /* Allocate memory for a new file.  For the first MAX_STACK_FILES
+     entries just return a slot in the preallocated stack array.
+     This is slightly complicated because in DWARF < 5 new files could
+     be defined with DW_LNE_define_file after the normal file list was
+     read.  */
+  struct filelist flstack[MAX_STACK_FILES];
+#define NEW_FILE() ({							\
+  struct filelist *fl = (nfilelist < MAX_STACK_FILES			\
+			   ? &flstack[nfilelist]			\
+			   : malloc (sizeof (struct filelist)));	\
+  if (unlikely (fl == NULL))						\
+    goto no_mem;							\
+  ++nfilelist;								\
+  fl->next = filelist;							\
+  filelist = fl;							\
+  fl; })
+
+  /* Now read the files.  */
+  if (version < 5)
+    {
+      if (unlikely (linep >= lineendp))
+	goto invalid_data;
+      while (linep < lineendp && *linep != '\0')
+	{
+	  struct filelist *new_file = NEW_FILE ();
+
+	  /* First comes the file name.  */
+	  char *fname = (char *) linep;
+	  uint8_t *endp = memchr (fname, '\0', lineendp - linep);
+	  if (endp == NULL)
+	    goto invalid_data;
+	  size_t fnamelen = endp - (uint8_t *) fname;
+	  linep = endp + 1;
+
+	  /* Then the index.  */
+	  Dwarf_Word diridx;
+	  if (unlikely (linep >= lineendp))
+	    goto invalid_data;
+	  get_uleb128 (diridx, linep, lineendp);
+	  if (unlikely (diridx >= ndirlist))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
+	      goto out;
+	    }
+
+	  if (*fname == '/')
+	    /* It's an absolute path.  */
+	    new_file->info.name = fname;
+	  else
+	    {
+	      new_file->info.name = libdw_alloc (dbg, char, 1,
+						 dirarray[diridx].len + 1
+						 + fnamelen + 1);
+	      char *cp = new_file->info.name;
+
+	      if (dirarray[diridx].dir != NULL)
+		{
+		  /* This value could be NULL in case the DW_AT_comp_dir
+		     was not present.  We cannot do much in this case.
+		     Just keep the file relative.  */
+		  cp = stpcpy (cp, dirarray[diridx].dir);
+		  *cp++ = '/';
+		}
+	      strcpy (cp, fname);
+	      assert (strlen (new_file->info.name)
+		      < dirarray[diridx].len + 1 + fnamelen + 1);
+	    }
+
+	  /* Next comes the modification time.  */
+	  if (unlikely (linep >= lineendp))
+	    goto invalid_data;
+	  get_uleb128 (new_file->info.mtime, linep, lineendp);
+
+	  /* Finally the length of the file.  */
+	  if (unlikely (linep >= lineendp))
+	    goto invalid_data;
+	  get_uleb128 (new_file->info.length, linep, lineendp);
+	}
+      if (linep >= lineendp || *linep != '\0')
+	goto invalid_data;
+      /* Skip the final NUL byte.  */
+      ++linep;
+    }
+  else
+    {
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      nforms = *linep++;
+      form_path = form_idx = -1;
+      for (int i = 0; i < nforms; i++)
+	{
+	  uint16_t desc, form;
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (desc, linep, lineendp);
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  get_uleb128 (form, linep, lineendp);
+
+	  if (! libdw_valid_user_form (form))
+	    goto invalid_data;
+
+	  forms[i] = form;
+	  if (desc == DW_LNCT_path)
+	    form_path = i;
+	  else if (desc == DW_LNCT_directory_index)
+	    form_idx = i;
+	}
+
+      if (nforms > 0 && (form_path == (unsigned char) -1
+			 || form_idx == (unsigned char) -1))
+	goto invalid_data;
+
+      size_t nfiles;
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      get_uleb128 (nfiles, linep, lineendp);
+
+      if (nforms == 0 && nfiles != 0)
+	goto invalid_data;
+
+      /* Assume there is at least 1 byte needed per form to describe
+	 the file.  Filters out insanely large nfiles.  */
+      if (nforms != 0 && nfiles > (size_t) (lineendp - linep) / nforms)
+	goto invalid_data;
+
+      Dwarf_Attribute attr;
+      attr.cu = &fake_cu;
+      for (unsigned int n = 0; n < nfiles; n++)
+	{
+	  const char *fname = NULL;
+	  Dwarf_Word diridx = (Dwarf_Word) -1;
+	  for (unsigned char m = 0; m < nforms; m++)
+	    {
+	      if (m == form_path)
+		{
+		  attr.code = DW_AT_name;
+		  attr.form = forms[m];
+		  attr.valp = (void *) linep;
+		  fname = dwarf_formstring (&attr);
+		}
+	      else if (m == form_idx)
+		{
+		  attr.code = DW_AT_decl_file; /* Close enough.  */
+		  attr.form = forms[m];
+		  attr.valp = (void *) linep;
+		  if (dwarf_formudata (&attr, &diridx) != 0)
+		    diridx = (Dwarf_Word) -1;
+		}
+
+	      size_t len = __libdw_form_val_len (&fake_cu, forms[m], linep);
+	      if ((size_t) (lineendp - linep) < len)
+		goto invalid_data;
+
+	      linep += len;
+	    }
+
+	  if (fname == NULL || diridx == (Dwarf_Word) -1)
+	    goto invalid_data;
+
+	  size_t fnamelen = strlen (fname);
+
+	  if (unlikely (diridx >= ndirlist))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
+	      goto out;
+	    }
+
+	  /* Yes, weird.  Looks like an off-by-one in the spec.  */
+	  struct filelist *new_file = n == 0 ? &null_file : NEW_FILE ();
+
+	  /* We follow the same rules as above for DWARF < 5, even
+	     though the standard doesn't explicitly mention absolute
+	     paths and ignoring the dir index.  */
+	  if (*fname == '/')
+	    /* It's an absolute path.  */
+	    new_file->info.name = (char *) fname;
+	  else
+	    {
+	      new_file->info.name = libdw_alloc (dbg, char, 1,
+						 dirarray[diridx].len + 1
+						 + fnamelen + 1);
+	      char *cp = new_file->info.name;
+
+	      /* In the DWARF >= 5 case, dir can never be NULL.  */
+	      cp = stpcpy (cp, dirarray[diridx].dir);
+	      *cp++ = '/';
+	      strcpy (cp, fname);
+	      assert (strlen (new_file->info.name)
+		      < dirarray[diridx].len + 1 + fnamelen + 1);
+	    }
+
+	  /* For now we just ignore the modification time and file length.  */
+	  new_file->info.mtime = 0;
+	  new_file->info.length = 0;
+	}
+    }
+
+  unsigned int debug_str_offset = 0;
+  if (unlikely (linep == header_start + header_length - 4))
+    {
+      /* CUBINs contain an unsigned 4-byte offset */
+      debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep);
+    }
+
+  /* Consistency check.  */
+  if (unlikely (linep != header_start + header_length))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      goto out;
+    }
+
+  /* We are about to process the statement program.  Most state machine
+     registers have already been initialize above.  Just add the is_stmt
+     default. See 6.2.2 in the v2.1 specification.  */
+  state.is_stmt = default_is_stmt;
+
+  /* Apply the "operation advance" from a special opcode or
+     DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
+#define advance_pc(op_advance) \
+  run_advance_pc (&state, op_advance, minimum_instr_len, max_ops_per_instr)
+
+  /* Process the instructions.  */
+
+  /* Adds a new line to the matrix.  For the first MAX_STACK_LINES
+     entries just return a slot in the preallocated stack array.  */
+  struct linelist llstack[MAX_STACK_LINES];
+#define NEW_LINE(end_seq)						\
+  do {								\
+    struct linelist *ll = (state.nlinelist < MAX_STACK_LINES	\
+			   ? &llstack[state.nlinelist]		\
+			   : malloc (sizeof (struct linelist)));	\
+    if (unlikely (ll == NULL))					\
+      goto no_mem;						\
+    state.end_sequence = end_seq;				\
+    if (unlikely (add_new_line (&state, ll)))			\
+      goto invalid_data;						\
+  } while (0)
+
+  while (linep < lineendp)
+    {
+      unsigned int opcode;
+      unsigned int u128;
+      int s128;
+
+      /* Read the opcode.  */
+      opcode = *linep++;
+
+      /* Is this a special opcode?  */
+      if (likely (opcode >= opcode_base))
+	{
+	  if (unlikely (line_range == 0))
+	    goto invalid_data;
+
+	  /* Yes.  Handling this is quite easy since the opcode value
+	     is computed with
+
+	     opcode = (desired line increment - line_base)
+		       + (line_range * address advance) + opcode_base
+	  */
+	  int line_increment = (line_base
+				+ (opcode - opcode_base) % line_range);
+
+	  /* Perform the increments.  */
+	  state.line += line_increment;
+	  advance_pc ((opcode - opcode_base) / line_range);
+
+	  /* Add a new line with the current state machine values.  */
+	  NEW_LINE (0);
+
+	  /* Reset the flags.  */
+	  state.basic_block = false;
+	  state.prologue_end = false;
+	  state.epilogue_begin = false;
+	  state.discriminator = 0;
+	}
+      else if (opcode == 0)
+	{
+	  /* This an extended opcode.  */
+	  if (unlikely (lineendp - linep < 2))
+	    goto invalid_data;
+
+	  /* The length.  */
+	  uint_fast8_t len = *linep++;
+
+	  if (unlikely ((size_t) (lineendp - linep) < len))
+	    goto invalid_data;
+
+	  /* The sub-opcode.  */
+	  opcode = *linep++;
+
+	  switch (opcode)
+	    {
+	    case DW_LNE_end_sequence:
+	      /* Add a new line with the current state machine values.
+		 The is the end of the sequence.  */
+	      NEW_LINE (1);
+
+	      /* Reset the registers.  */
+	      state.addr = 0;
+	      state.op_index = 0;
+	      state.file = 1;
+	      state.line = 1;
+	      state.column = 0;
+	      state.is_stmt = default_is_stmt;
+	      state.basic_block = false;
+	      state.prologue_end = false;
+	      state.epilogue_begin = false;
+	      state.isa = 0;
+	      state.discriminator = 0;
+	      state.context = 0;
+	      state.function_name = 0;
+	      break;
+
+	    case DW_LNE_set_address:
+	      /* The value is an address.  The size is defined as
+		 appropriate for the target machine.  We use the
+		 address size field from the CU header.  */
+	      state.op_index = 0;
+	      if (unlikely (lineendp - linep < (uint8_t) address_size))
+		goto invalid_data;
+	      if (__libdw_read_address_inc (dbg, IDX_debug_line, &linep,
+					    address_size, &state.addr))
+		goto out;
+	      break;
+
+	    case DW_LNE_define_file:
+	      {
+		char *fname = (char *) linep;
+		uint8_t *endp = memchr (linep, '\0', lineendp - linep);
+		if (endp == NULL)
+		  goto invalid_data;
+		size_t fnamelen = endp - linep;
+		linep = endp + 1;
+
+		unsigned int diridx;
+		if (unlikely (linep >= lineendp))
+		  goto invalid_data;
+		get_uleb128 (diridx, linep, lineendp);
+		if (unlikely (diridx >= ndirlist))
+		  {
+		    __libdw_seterrno (DWARF_E_INVALID_DIR_IDX);
+		    goto invalid_data;
+		  }
+		Dwarf_Word mtime;
+		if (unlikely (linep >= lineendp))
+		  goto invalid_data;
+		get_uleb128 (mtime, linep, lineendp);
+		Dwarf_Word filelength;
+		if (unlikely (linep >= lineendp))
+		  goto invalid_data;
+		get_uleb128 (filelength, linep, lineendp);
+
+		struct filelist *new_file = NEW_FILE ();
+		if (fname[0] == '/')
+		  new_file->info.name = fname;
+		else
+		  {
+		    new_file->info.name =
+		      libdw_alloc (dbg, char, 1, (dirarray[diridx].len + 1
+						  + fnamelen + 1));
+		    char *cp = new_file->info.name;
+
+		    if (dirarray[diridx].dir != NULL)
+		      /* This value could be NULL in case the
+			 DW_AT_comp_dir was not present.  We
+			 cannot do much in this case.  Just
+			 keep the file relative.  */
+		      {
+			cp = stpcpy (cp, dirarray[diridx].dir);
+			*cp++ = '/';
+		      }
+		    strcpy (cp, fname);
+		  }
+
+		new_file->info.mtime = mtime;
+		new_file->info.length = filelength;
+	      }
+	      break;
+
+	    case DW_LNE_set_discriminator:
+	      /* Takes one ULEB128 parameter, the discriminator.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		goto invalid_data;
+
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (state.discriminator, linep, lineendp);
+	      break;
+
+	    case DW_LNE_NVIDIA_inlined_call:
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (state.context, linep, lineendp);
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (state.function_name, linep, lineendp);
+	      state.function_name += debug_str_offset;
+	      break;
+
+	    case DW_LNE_NVIDIA_set_function_name:
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (state.function_name, linep, lineendp);
+	      state.function_name += debug_str_offset;
+	      break;
+
+	    default:
+	      /* Unknown, ignore it.  */
+	      if (unlikely ((size_t) (lineendp - (linep - 1)) < len))
+		goto invalid_data;
+	      linep += len - 1;
+	      break;
+	    }
+	}
+      else if (opcode <= DW_LNS_set_isa)
+	{
+	  /* This is a known standard opcode.  */
+	  switch (opcode)
+	    {
+	    case DW_LNS_copy:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		goto invalid_data;
+
+	      /* Add a new line with the current state machine values.  */
+	      NEW_LINE (0);
+
+	      /* Reset the flags.  */
+	      state.basic_block = false;
+	      state.prologue_end = false;
+	      state.epilogue_begin = false;
+	      state.discriminator = 0;
+	      break;
+
+	    case DW_LNS_advance_pc:
+	      /* Takes one uleb128 parameter which is added to the
+		 address.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		goto invalid_data;
+
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
+	      advance_pc (u128);
+	      break;
+
+	    case DW_LNS_advance_line:
+	      /* Takes one sleb128 parameter which is added to the
+		 line.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		goto invalid_data;
+
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_sleb128 (s128, linep, lineendp);
+	      state.line += s128;
+	      break;
+
+	    case DW_LNS_set_file:
+	      /* Takes one uleb128 parameter which is stored in file.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		goto invalid_data;
+
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
+	      state.file = u128;
+	      break;
+
+	    case DW_LNS_set_column:
+	      /* Takes one uleb128 parameter which is stored in column.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		goto invalid_data;
+
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
+	      state.column = u128;
+	      break;
+
+	    case DW_LNS_negate_stmt:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		goto invalid_data;
+
+	      state.is_stmt = 1 - state.is_stmt;
+	      break;
+
+	    case DW_LNS_set_basic_block:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		goto invalid_data;
+
+	      state.basic_block = true;
+	      break;
+
+	    case DW_LNS_const_add_pc:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		goto invalid_data;
+
+	      if (unlikely (line_range == 0))
+		goto invalid_data;
+
+	      advance_pc ((255 - opcode_base) / line_range);
+	      break;
+
+	    case DW_LNS_fixed_advance_pc:
+	      /* Takes one 16 bit parameter which is added to the
+		 address.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1)
+		  || unlikely (lineendp - linep < 2))
+		goto invalid_data;
+
+	      state.addr += read_2ubyte_unaligned_inc (dbg, linep);
+	      state.op_index = 0;
+	      break;
+
+	    case DW_LNS_set_prologue_end:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		goto invalid_data;
+
+	      state.prologue_end = true;
+	      break;
+
+	    case DW_LNS_set_epilogue_begin:
+	      /* Takes no argument.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 0))
+		goto invalid_data;
+
+	      state.epilogue_begin = true;
+	      break;
+
+	    case DW_LNS_set_isa:
+	      /* Takes one uleb128 parameter which is stored in isa.  */
+	      if (unlikely (standard_opcode_lengths[opcode] != 1))
+		goto invalid_data;
+
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (state.isa, linep, lineendp);
+	      break;
+	    }
+	}
+      else
+	{
+	  /* This is a new opcode the generator but not we know about.
+	     Read the parameters associated with it but then discard
+	     everything.  Read all the parameters for this opcode.  */
+	  for (int n = standard_opcode_lengths[opcode]; n > 0; --n)
+	    {
+	      if (unlikely (linep >= lineendp))
+		goto invalid_data;
+	      get_uleb128 (u128, linep, lineendp);
+	    }
+
+	  /* Next round, ignore this opcode.  */
+	  continue;
+	}
+    }
+
+  /* Put all the files in an array.  */
+  Dwarf_Files *files = libdw_alloc (dbg, Dwarf_Files,
+				    sizeof (Dwarf_Files)
+				    + nfilelist * sizeof (Dwarf_Fileinfo)
+				    + (ndirlist + 1) * sizeof (char *),
+				    1);
+  const char **dirs = (void *) &files->info[nfilelist];
+
+  struct filelist *fileslist = filelist;
+  files->nfiles = nfilelist;
+  for (size_t n = nfilelist; n > 0; n--)
+    {
+      files->info[n - 1] = fileslist->info;
+      fileslist = fileslist->next;
+    }
+  assert (fileslist == NULL);
+
+  /* Put all the directory strings in an array.  */
+  files->ndirs = ndirlist;
+  for (unsigned int i = 0; i < ndirlist; ++i)
+    dirs[i] = dirarray[i].dir;
+  dirs[ndirlist] = NULL;
+
+  /* Pass the file data structure to the caller.  */
+  if (filesp != NULL)
+    *filesp = files;
+
+  size_t buf_size = (sizeof (Dwarf_Lines)
+		     + (sizeof (Dwarf_Line) * state.nlinelist));
+  void *buf = libdw_alloc (dbg, Dwarf_Lines, buf_size, 1);
+
+  /* First use the buffer for the pointers, and sort the entries.
+     We'll write the pointers in the end of the buffer, and then
+     copy into the buffer from the beginning so the overlap works.  */
+  assert (sizeof (Dwarf_Line) >= sizeof (struct linelist *));
+  struct linelist **sortlines = (buf + buf_size
+				 - sizeof (struct linelist **) * state.nlinelist);
+
+  /* The list is in LIFO order and usually they come in clumps with
+     ascending addresses.  So fill from the back to probably start with
+     runs already in order before we sort.  */
+  struct linelist *lineslist = state.linelist;
+  for (size_t i = state.nlinelist; i-- > 0; )
+    {
+      sortlines[i] = lineslist;
+      lineslist = lineslist->next;
+    }
+  assert (lineslist == NULL);
+
+  /* Sort by ascending address.  */
+  qsort (sortlines, state.nlinelist, sizeof sortlines[0], &compare_lines);
+
+  /* Now that they are sorted, put them in the final array.
+     The buffers overlap, so we've clobbered the early elements
+     of SORTLINES by the time we're reading the later ones.  */
+  Dwarf_Lines *lines = buf;
+  lines->nlines = state.nlinelist;
+  for (size_t i = 0; i < state.nlinelist; ++i)
+    {
+      lines->info[i] = sortlines[i]->line;
+      lines->info[i].files = files;
+    }
+
+  /* Make sure the highest address for the CU is marked as end_sequence.
+     This is required by the DWARF spec, but some compilers forget and
+     dwfl_module_getsrc depends on it.  */
+  if (state.nlinelist > 0)
+    lines->info[state.nlinelist - 1].end_sequence = 1;
+
+  /* Pass the line structure back to the caller.  */
+  if (linesp != NULL)
+    *linesp = lines;
+
+  /* Success.  */
+  res = 0;
+
+ out:
+  /* Free malloced line records, if any.  */
+  for (size_t i = MAX_STACK_LINES; i < state.nlinelist; i++)
+    {
+      struct linelist *ll = state.linelist->next;
+      free (state.linelist);
+      state.linelist = ll;
+    }
+  if (dirarray != dirstack)
+    free (dirarray);
+  for (size_t i = MAX_STACK_FILES; i < nfilelist; i++)
+    {
+      struct filelist *fl = filelist->next;
+      free (filelist);
+      filelist = fl;
+    }
+
+  return res;
+}
+
+static int
+files_lines_compare (const void *p1, const void *p2)
+{
+  const struct files_lines_s *t1 = p1;
+  const struct files_lines_s *t2 = p2;
+
+  if (t1->debug_line_offset < t2->debug_line_offset)
+    return -1;
+  if (t1->debug_line_offset > t2->debug_line_offset)
+    return 1;
+
+  return 0;
+}
+
+int
+internal_function
+__libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
+		     const char *comp_dir, unsigned address_size,
+		     Dwarf_Lines **linesp, Dwarf_Files **filesp)
+{
+  struct files_lines_s fake = { .debug_line_offset = debug_line_offset };
+  struct files_lines_s **found = tfind (&fake, &dbg->files_lines,
+					files_lines_compare);
+  if (found == NULL)
+    {
+      Elf_Data *data = __libdw_checked_get_data (dbg, IDX_debug_line);
+      if (data == NULL
+	  || __libdw_offset_in_section (dbg, IDX_debug_line,
+					debug_line_offset, 1) != 0)
+	return -1;
+
+      const unsigned char *linep = data->d_buf + debug_line_offset;
+      const unsigned char *lineendp = data->d_buf + data->d_size;
+
+      struct files_lines_s *node = libdw_alloc (dbg, struct files_lines_s,
+						sizeof *node, 1);
+
+      if (read_srclines (dbg, linep, lineendp, comp_dir, address_size,
+			 &node->lines, &node->files) != 0)
+	return -1;
+
+      node->debug_line_offset = debug_line_offset;
+
+      found = tsearch (node, &dbg->files_lines, files_lines_compare);
+      if (found == NULL)
+	{
+	  __libdw_seterrno (DWARF_E_NOMEM);
+	  return -1;
+	}
+    }
+
+  if (linesp != NULL)
+    *linesp = (*found)->lines;
+
+  if (filesp != NULL)
+    *filesp = (*found)->files;
+
+  return 0;
+}
+
+/* Get the compilation directory, if any is set.  */
+const char *
+__libdw_getcompdir (Dwarf_Die *cudie)
+{
+  Dwarf_Attribute compdir_attr_mem;
+  Dwarf_Attribute *compdir_attr = INTUSE(dwarf_attr) (cudie,
+						      DW_AT_comp_dir,
+						      &compdir_attr_mem);
+  return INTUSE(dwarf_formstring) (compdir_attr);
+}
+
+int
+dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines, size_t *nlines)
+{
+  if (cudie == NULL)
+    return -1;
+  if (! is_cudie (cudie))
+    {
+      __libdw_seterrno (DWARF_E_NOT_CUDIE);
+      return -1;
+    }
+
+  /* Get the information if it is not already known.  */
+  struct Dwarf_CU *const cu = cudie->cu;
+  if (cu->lines == NULL)
+    {
+      /* For split units always pick the lines from the skeleton.  */
+      if (cu->unit_type == DW_UT_split_compile
+	  || cu->unit_type == DW_UT_split_type)
+	{
+	  /* We tries, assume we fail...  */
+	  cu->lines = (void *) -1l;
+
+	  Dwarf_CU *skel = __libdw_find_split_unit (cu);
+	  if (skel != NULL)
+	    {
+	      Dwarf_Die skeldie = CUDIE (skel);
+	      int res = INTUSE(dwarf_getsrclines) (&skeldie, lines, nlines);
+	      if (res == 0)
+		{
+		  cu->lines = skel->lines;
+		  *lines = cu->lines;
+		  *nlines = cu->lines->nlines;
+		}
+	      return res;
+	    }
+
+	  __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
+	  return -1;
+	}
+
+      /* Failsafe mode: no data found.  */
+      cu->lines = (void *) -1l;
+      cu->files = (void *) -1l;
+
+      /* The die must have a statement list associated.  */
+      Dwarf_Attribute stmt_list_mem;
+      Dwarf_Attribute *stmt_list = INTUSE(dwarf_attr) (cudie, DW_AT_stmt_list,
+						       &stmt_list_mem);
+
+      /* Get the offset into the .debug_line section.  NB: this call
+	 also checks whether the previous dwarf_attr call failed.  */
+      Dwarf_Off debug_line_offset;
+      if (__libdw_formptr (stmt_list, IDX_debug_line, DWARF_E_NO_DEBUG_LINE,
+			   NULL, &debug_line_offset) == NULL)
+	return -1;
+
+      if (__libdw_getsrclines (cu->dbg, debug_line_offset,
+			       __libdw_getcompdir (cudie),
+			       cu->address_size, &cu->lines, &cu->files) < 0)
+	return -1;
+    }
+  else if (cu->lines == (void *) -1l)
+    return -1;
+
+  *lines = cu->lines;
+  *nlines = cu->lines->nlines;
+
+  // XXX Eventually: unlocking here.
+
+  return 0;
+}
+INTDEF(dwarf_getsrclines)
diff --git a/libdw/dwarf_getstring.c b/libdw/dwarf_getstring.c
new file mode 100644
index 0000000..5620cb0
--- /dev/null
+++ b/libdw/dwarf_getstring.c
@@ -0,0 +1,63 @@
+/* Get string.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_getstring (Dwarf *dbg, Dwarf_Off offset, size_t *lenp)
+{
+  if (dbg == NULL)
+    return NULL;
+
+  if (dbg->sectiondata[IDX_debug_str] == NULL
+      || offset >= dbg->sectiondata[IDX_debug_str]->d_size)
+    {
+    no_string:
+      __libdw_seterrno (DWARF_E_NO_STRING);
+      return NULL;
+    }
+
+  const char *result = ((const char *) dbg->sectiondata[IDX_debug_str]->d_buf
+			+ offset);
+  const char *endp = memchr (result, '\0',
+			     dbg->sectiondata[IDX_debug_str]->d_size - offset);
+  if (endp == NULL)
+    goto no_string;
+
+  if (lenp != NULL)
+    *lenp = endp - result;
+
+  return result;
+}
diff --git a/libdw/dwarf_hasattr.c b/libdw/dwarf_hasattr.c
new file mode 100644
index 0000000..eca0839
--- /dev/null
+++ b/libdw/dwarf_hasattr.c
@@ -0,0 +1,77 @@
+/* Check whether given DIE has specific attribute.
+   Copyright (C) 2003, 2005, 2014, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_hasattr (Dwarf_Die *die, unsigned int search_name)
+{
+  if (die == NULL)
+    return 0;
+
+  /* Find the abbreviation entry.  */
+  Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+  if (unlikely (abbrevp == DWARF_END_ABBREV))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return 0;
+    }
+
+  /* Search the name attribute.  Dwarf_Abbrev was checked when created,
+     so we can read unchecked here.  */
+  const unsigned char *attrp = abbrevp->attrp;
+  while (1)
+    {
+      /* Get attribute name and form.  */
+      unsigned int attr_name;
+      get_uleb128_unchecked (attr_name, attrp);
+      unsigned int attr_form;
+      get_uleb128_unchecked (attr_form, attrp);
+
+      /* We can stop if we found the end of the attribute list.  */
+      if (attr_name == 0 && attr_form == 0)
+	return 0;
+
+      if (attr_name == search_name)
+	return 1;
+
+      if (attr_form == DW_FORM_implicit_const)
+	{
+	  int64_t attr_value __attribute__ ((unused));
+	  get_sleb128_unchecked (attr_value, attrp);
+	}
+    }
+}
+INTDEF (dwarf_hasattr)
diff --git a/libdw/dwarf_hasattr_integrate.c b/libdw/dwarf_hasattr_integrate.c
new file mode 100644
index 0000000..1d94628
--- /dev/null
+++ b/libdw/dwarf_hasattr_integrate.c
@@ -0,0 +1,73 @@
+/* Check whether DIE has specific attribute, integrating DW_AT_abstract_origin.
+   Copyright (C) 2005, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+int
+dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name)
+{
+  Dwarf_Die die_mem;
+  int chain = 16; /* Largest DIE ref chain we will follow.  */
+  do
+    {
+      if (INTUSE(dwarf_hasattr) (die, search_name))
+	return 1;
+
+      Dwarf_Attribute attr_mem;
+      Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin,
+						  &attr_mem);
+      if (attr == NULL)
+	attr = INTUSE(dwarf_attr) (die, DW_AT_specification, &attr_mem);
+      if (attr == NULL)
+	break;
+
+      die = INTUSE(dwarf_formref_die) (attr, &die_mem);
+    }
+  while (die != NULL && chain-- != 0);
+
+  /* Not NULL if it didn't have abstract_origin and specification
+     attributes.  If it is a split CU then see if the skeleton
+     has it.  */
+  if (die != NULL && is_cudie (die)
+      && die->cu->unit_type == DW_UT_split_compile)
+    {
+      Dwarf_CU *skel_cu = __libdw_find_split_unit (die->cu);
+      if (skel_cu != NULL)
+	{
+	  Dwarf_Die skel_die = CUDIE (skel_cu);
+	  return INTUSE(dwarf_hasattr) (&skel_die, search_name);
+	}
+    }
+
+  return 0;
+}
diff --git a/libdw/dwarf_haschildren.c b/libdw/dwarf_haschildren.c
new file mode 100644
index 0000000..03a8173
--- /dev/null
+++ b/libdw/dwarf_haschildren.c
@@ -0,0 +1,51 @@
+/* Return string associated with given attribute.
+   Copyright (C) 2003, 2005, 2008, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <string.h>
+
+
+int
+dwarf_haschildren (Dwarf_Die *die)
+{
+  /* Find the abbreviation entry.  */
+  Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+  if (unlikely (abbrevp == DWARF_END_ABBREV))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  return abbrevp->has_children;
+}
+INTDEF (dwarf_haschildren)
diff --git a/libdw/dwarf_hasform.c b/libdw/dwarf_hasform.c
new file mode 100644
index 0000000..a0c3229
--- /dev/null
+++ b/libdw/dwarf_hasform.c
@@ -0,0 +1,45 @@
+/* Check whether given attribute has specific form.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_hasform (Dwarf_Attribute *attr, unsigned int search_form)
+{
+  if (attr == NULL)
+    return 0;
+
+  return attr->form == search_form;
+}
diff --git a/libdw/dwarf_haspc.c b/libdw/dwarf_haspc.c
new file mode 100644
index 0000000..47e2b05
--- /dev/null
+++ b/libdw/dwarf_haspc.c
@@ -0,0 +1,54 @@
+/* Determine whether a DIE covers a PC address.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+int
+dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc)
+{
+  if (die == NULL)
+    return -1;
+
+  Dwarf_Addr base;
+  Dwarf_Addr begin;
+  Dwarf_Addr end;
+  ptrdiff_t offset = 0;
+  while ((offset = INTUSE(dwarf_ranges) (die, offset, &base,
+					 &begin, &end)) > 0)
+    if (pc >= begin && pc < end)
+      return 1;
+
+  return offset;
+}
+INTDEF (dwarf_haspc)
diff --git a/libdw/dwarf_highpc.c b/libdw/dwarf_highpc.c
new file mode 100644
index 0000000..5b2f0fd
--- /dev/null
+++ b/libdw/dwarf_highpc.c
@@ -0,0 +1,70 @@
+/* Return high PC attribute of DIE.
+   Copyright (C) 2003, 2005, 2012, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+{
+  Dwarf_Attribute attr_high_mem;
+  Dwarf_Attribute *attr_high;
+  /* Split compile DIEs inherit high_pc from their skeleton DIE.  */
+  if (is_cudie (die) && die->cu->unit_type == DW_UT_split_compile)
+    attr_high = INTUSE(dwarf_attr_integrate) (die, DW_AT_high_pc,
+					      &attr_high_mem);
+  else
+    attr_high = INTUSE(dwarf_attr) (die, DW_AT_high_pc, &attr_high_mem);
+
+  if (attr_high == NULL)
+    goto no_addr;
+
+  if (INTUSE(dwarf_formaddr) (attr_high, return_addr) == 0)
+    return 0;
+
+  /* DWARF 4 allows high_pc to be a constant offset from low_pc. */
+  if (INTUSE(dwarf_lowpc) (die, return_addr) == 0)
+    {
+      Dwarf_Word uval;
+      if (INTUSE(dwarf_formudata) (attr_high, &uval) == 0)
+	{
+	  *return_addr += uval;
+	  return 0;
+	}
+    }
+
+no_addr:
+  __libdw_seterrno (DWARF_E_NO_ADDR);
+  return -1;
+}
+INTDEF(dwarf_highpc)
diff --git a/libdw/dwarf_line_file.c b/libdw/dwarf_line_file.c
new file mode 100644
index 0000000..e2df642
--- /dev/null
+++ b/libdw/dwarf_line_file.c
@@ -0,0 +1,52 @@
+/* Find line information for address.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_line_file (Dwarf_Line *line, Dwarf_Files **files, size_t *idx)
+{
+  if (line == NULL)
+    return -1;
+
+  if (line->file >= line->files->nfiles)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  *files = line->files;
+  *idx = line->file;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineaddr.c b/libdw/dwarf_lineaddr.c
new file mode 100644
index 0000000..4e1952d
--- /dev/null
+++ b/libdw/dwarf_lineaddr.c
@@ -0,0 +1,46 @@
+/* Return line address.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp)
+{
+  if (line == NULL)
+    return -1;
+
+  *addrp =  line->addr;
+
+  return 0;
+}
diff --git a/libdw/dwarf_linebeginstatement.c b/libdw/dwarf_linebeginstatement.c
new file mode 100644
index 0000000..4854c56
--- /dev/null
+++ b/libdw/dwarf_linebeginstatement.c
@@ -0,0 +1,46 @@
+/* Return true if record is for beginning of a statement.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp)
+{
+  if (line == NULL)
+    return -1;
+
+  *flagp =  line->is_stmt;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineblock.c b/libdw/dwarf_lineblock.c
new file mode 100644
index 0000000..e3c7f41
--- /dev/null
+++ b/libdw/dwarf_lineblock.c
@@ -0,0 +1,46 @@
+/* Return true if record is for beginning of a basic block.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineblock (Dwarf_Line *line, bool *flagp)
+{
+  if (line == NULL)
+    return -1;
+
+  *flagp =  line->basic_block;
+
+  return 0;
+}
diff --git a/libdw/dwarf_linecol.c b/libdw/dwarf_linecol.c
new file mode 100644
index 0000000..c667b1b
--- /dev/null
+++ b/libdw/dwarf_linecol.c
@@ -0,0 +1,46 @@
+/* Return column in line.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_linecol (Dwarf_Line *line, int *colp)
+{
+  if (line == NULL)
+    return -1;
+
+  *colp =  line->column;
+
+  return 0;
+}
diff --git a/libdw/dwarf_linecontext.c b/libdw/dwarf_linecontext.c
new file mode 100644
index 0000000..84572e2
--- /dev/null
+++ b/libdw/dwarf_linecontext.c
@@ -0,0 +1,45 @@
+/* Return context in line.
+   This file is part of elfutils.
+   Written by John Mellor-Crummey <johnmc@rice.edu>, 2021.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Line*
+dwarf_linecontext (Dwarf_Lines* lines, Dwarf_Line *line)
+{
+  if (lines == NULL || line == NULL)
+    return NULL;
+  if (line->context == 0 || line->context >= lines->nlines)
+    return NULL;
+
+  return lines->info + (line->context - 1);
+}
diff --git a/libdw/dwarf_linediscriminator.c b/libdw/dwarf_linediscriminator.c
new file mode 100644
index 0000000..552205a
--- /dev/null
+++ b/libdw/dwarf_linediscriminator.c
@@ -0,0 +1,45 @@
+/* Return code path discriminator in line record.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_linediscriminator (Dwarf_Line *line, unsigned int *discp)
+{
+  if (line == NULL)
+    return -1;
+
+  *discp = line->discriminator;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineendsequence.c b/libdw/dwarf_lineendsequence.c
new file mode 100644
index 0000000..61bde93
--- /dev/null
+++ b/libdw/dwarf_lineendsequence.c
@@ -0,0 +1,46 @@
+/* Return true if record is for end of sequence.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineendsequence (Dwarf_Line *line, bool *flagp)
+{
+  if (line == NULL)
+    return -1;
+
+  *flagp =  line->end_sequence;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineepiloguebegin.c b/libdw/dwarf_lineepiloguebegin.c
new file mode 100644
index 0000000..b914787
--- /dev/null
+++ b/libdw/dwarf_lineepiloguebegin.c
@@ -0,0 +1,46 @@
+/* Return true if record is for beginning of epilogue.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp)
+{
+  if (line == NULL)
+    return -1;
+
+  *flagp =  line->epilogue_begin;
+
+  return 0;
+}
diff --git a/libdw/dwarf_linefunctionname.c b/libdw/dwarf_linefunctionname.c
new file mode 100644
index 0000000..e194d21
--- /dev/null
+++ b/libdw/dwarf_linefunctionname.c
@@ -0,0 +1,52 @@
+/* Return function name in line.
+   This file is part of elfutils.
+   Written by John Mellor-Crummey <johnmc@rice.edu>, 2021.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+const char *
+dwarf_linefunctionname (Dwarf *dbg, Dwarf_Line *line)
+{
+  if (dbg == NULL || line == NULL)
+    return NULL;
+  if (line->context == 0)
+    return NULL;
+
+  Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
+  if (str_data == NULL || line->function_name >= str_data->d_size
+      || memchr (str_data->d_buf + line->function_name, '\0',
+		 str_data->d_size - line->function_name) == NULL)
+    return NULL;
+
+  return (char *) str_data->d_buf + line->function_name;
+}
diff --git a/libdw/dwarf_lineisa.c b/libdw/dwarf_lineisa.c
new file mode 100644
index 0000000..30181fc
--- /dev/null
+++ b/libdw/dwarf_lineisa.c
@@ -0,0 +1,45 @@
+/* Return ISA in line.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineisa (Dwarf_Line *line, unsigned int *isap)
+{
+  if (line == NULL)
+    return -1;
+
+  *isap = line->isa;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineno.c b/libdw/dwarf_lineno.c
new file mode 100644
index 0000000..009999c
--- /dev/null
+++ b/libdw/dwarf_lineno.c
@@ -0,0 +1,46 @@
+/* Return line number.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineno (Dwarf_Line *line, int *linep)
+{
+  if (line == NULL)
+    return -1;
+
+  *linep =  line->line;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineop_index.c b/libdw/dwarf_lineop_index.c
new file mode 100644
index 0000000..9ea4ef4
--- /dev/null
+++ b/libdw/dwarf_lineop_index.c
@@ -0,0 +1,45 @@
+/* Return line VLIW operation index.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineop_index (Dwarf_Line *line, unsigned int *idxp)
+{
+  if (line == NULL)
+    return -1;
+
+  *idxp = line->op_index;
+
+  return 0;
+}
diff --git a/libdw/dwarf_lineprologueend.c b/libdw/dwarf_lineprologueend.c
new file mode 100644
index 0000000..6ba8be2
--- /dev/null
+++ b/libdw/dwarf_lineprologueend.c
@@ -0,0 +1,46 @@
+/* Return true if record is for end of prologue.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_lineprologueend (Dwarf_Line *line, bool *flagp)
+{
+  if (line == NULL)
+    return -1;
+
+  *flagp =  line->prologue_end;
+
+  return 0;
+}
diff --git a/libdw/dwarf_linesrc.c b/libdw/dwarf_linesrc.c
new file mode 100644
index 0000000..27b5990
--- /dev/null
+++ b/libdw/dwarf_linesrc.c
@@ -0,0 +1,56 @@
+/* Find line information for address.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+const char *
+dwarf_linesrc (Dwarf_Line *line, Dwarf_Word *mtime, Dwarf_Word *length)
+{
+  if (line == NULL)
+    return NULL;
+
+  if (line->file >= line->files->nfiles)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  if (mtime != NULL)
+    *mtime = line->files->info[line->file].mtime;
+
+  if (length != NULL)
+    *length = line->files->info[line->file].length;
+
+  return line->files->info[line->file].name;
+}
diff --git a/libdw/dwarf_lowpc.c b/libdw/dwarf_lowpc.c
new file mode 100644
index 0000000..4d743a7
--- /dev/null
+++ b/libdw/dwarf_lowpc.c
@@ -0,0 +1,48 @@
+/* Return low PC attribute of DIE.
+   Copyright (C) 2003, 2005, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+int
+dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+{
+  Dwarf_Attribute attr_mem, *attr;
+  /* Split compile DIEs inherit low_pc from their skeleton DIE.  */
+  if (is_cudie (die) && die->cu->unit_type == DW_UT_split_compile)
+    attr = INTUSE(dwarf_attr_integrate) (die, DW_AT_low_pc, &attr_mem);
+  else
+    attr = INTUSE(dwarf_attr) (die, DW_AT_low_pc, &attr_mem);
+  return INTUSE(dwarf_formaddr) (attr, return_addr);
+}
+INTDEF(dwarf_lowpc)
diff --git a/libdw/dwarf_macro_getparamcnt.c b/libdw/dwarf_macro_getparamcnt.c
new file mode 100644
index 0000000..e218eb1
--- /dev/null
+++ b/libdw/dwarf_macro_getparamcnt.c
@@ -0,0 +1,43 @@
+/* Return number of parameters of a macro.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+int
+dwarf_macro_getparamcnt (Dwarf_Macro *macro, size_t *paramcntp)
+{
+  if (macro == NULL)
+    return -1;
+
+  *paramcntp = libdw_macro_nforms (macro);
+  return 0;
+}
diff --git a/libdw/dwarf_macro_getsrcfiles.c b/libdw/dwarf_macro_getsrcfiles.c
new file mode 100644
index 0000000..11c587a
--- /dev/null
+++ b/libdw/dwarf_macro_getsrcfiles.c
@@ -0,0 +1,88 @@
+/* Find line information for a given macro.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+int
+dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro,
+			 Dwarf_Files **files, size_t *nfiles)
+{
+  /* This was needed before Dwarf_Macro_Op_Table stored the Dwarf handle.  */
+  (void)dbg;
+
+  /* macro is declared NN */
+  Dwarf_Macro_Op_Table *const table = macro->table;
+  if (table->files == NULL)
+    {
+      Dwarf_Off line_offset = table->line_offset;
+      if (line_offset == (Dwarf_Off) -1)
+	{
+	  *files = NULL;
+	  *nfiles = 0;
+	  return 0;
+	}
+
+      /* If TABLE->comp_dir is NULL that could mean any of the
+	 following:
+
+	 - The macro unit is not bound to a CU.  It's an auxiliary
+           unit used purely for import from other units.  In that case
+           there's actually no COMP_DIR value that we could use.
+
+	 - The macro unit is bound to a CU, but there's no
+           DW_AT_comp_dir attribute at the CU DIE.
+
+	 - The macro unit is bound to a CU, but we don't know that,
+           likely because its iteration was requested through
+           dwarf_getmacros_off interface.  This might be legitimate if
+           one macro unit imports another CU's macro unit, but that is
+           unlikely to happen in practice.  Most probably this is not
+           legitimate use of the interfaces.
+
+	 So when the interfaces are used correctly, COMP_DIR value is
+	 always right.  That means that we can cache the parsed
+	 .debug_line unit without fear that later on someone requests
+	 the same unit through dwarf_getsrcfiles, and the file names
+	 will be broken.  */
+
+      if (__libdw_getsrclines (table->dbg, line_offset, table->comp_dir,
+			       table->address_size, NULL, &table->files) < 0)
+	table->files = (void *) -1;
+    }
+
+  if (table->files == (void *) -1)
+    return -1;
+
+  *files = table->files;
+  *nfiles = table->files->nfiles;
+  return 0;
+}
diff --git a/libdw/dwarf_macro_opcode.c b/libdw/dwarf_macro_opcode.c
new file mode 100644
index 0000000..8607777
--- /dev/null
+++ b/libdw/dwarf_macro_opcode.c
@@ -0,0 +1,46 @@
+/* Return macro opcode.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep)
+{
+  if (macro == NULL)
+    return -1;
+
+  *opcodep = macro->opcode;
+
+  return 0;
+}
diff --git a/libdw/dwarf_macro_param.c b/libdw/dwarf_macro_param.c
new file mode 100644
index 0000000..bd846a7
--- /dev/null
+++ b/libdw/dwarf_macro_param.c
@@ -0,0 +1,46 @@
+/* Return a given parameter of a macro.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+int
+dwarf_macro_param (Dwarf_Macro *macro, size_t idx, Dwarf_Attribute *ret)
+{
+  if (macro == NULL)
+    return -1;
+
+  if (idx >= libdw_macro_nforms (macro))
+    return -1;
+
+  *ret = macro->attributes[idx];
+  return 0;
+}
diff --git a/libdw/dwarf_macro_param1.c b/libdw/dwarf_macro_param1.c
new file mode 100644
index 0000000..87ce003
--- /dev/null
+++ b/libdw/dwarf_macro_param1.c
@@ -0,0 +1,48 @@
+/* Return first macro parameter.
+   Copyright (C) 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp)
+{
+  if (macro == NULL)
+    return -1;
+
+  Dwarf_Attribute param;
+  if (dwarf_macro_param (macro, 0, &param) != 0)
+    return -1;
+
+  return dwarf_formudata (&param, paramp);
+}
diff --git a/libdw/dwarf_macro_param2.c b/libdw/dwarf_macro_param2.c
new file mode 100644
index 0000000..f12e6f9
--- /dev/null
+++ b/libdw/dwarf_macro_param2.c
@@ -0,0 +1,64 @@
+/* Return second macro parameter.
+   Copyright (C) 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp, const char **strp)
+{
+  if (macro == NULL)
+    return -1;
+
+  Dwarf_Attribute param;
+  if (dwarf_macro_param (macro, 1, &param) != 0)
+    return -1;
+
+  switch (param.form)
+    {
+      /* String forms allowed by libdw_valid_user_form.  */
+      case DW_FORM_line_strp:
+      case DW_FORM_string:
+      case DW_FORM_strp:
+      case DW_FORM_strp_sup:
+      case DW_FORM_strx:
+      case DW_FORM_strx1:
+      case DW_FORM_strx2:
+      case DW_FORM_strx3:
+      case DW_FORM_strx4:
+	*strp = dwarf_formstring (&param);
+	return 0;
+      default:
+	return dwarf_formudata (&param, paramp);
+    }
+}
diff --git a/libdw/dwarf_next_cfi.c b/libdw/dwarf_next_cfi.c
new file mode 100644
index 0000000..be08984
--- /dev/null
+++ b/libdw/dwarf_next_cfi.c
@@ -0,0 +1,274 @@
+/* Advance to next CFI entry.
+   Copyright (C) 2009-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+#include "encoded-value.h"
+
+#include <string.h>
+
+
+int
+dwarf_next_cfi (const unsigned char e_ident[],
+		Elf_Data *data,
+		bool eh_frame_p,
+		Dwarf_Off off,
+		Dwarf_Off *next_off,
+		Dwarf_CFI_Entry *entry)
+{
+  /* Dummy struct for memory-access.h macros.  */
+  BYTE_ORDER_DUMMY (dw, e_ident);
+
+  /* If we reached the end before don't do anything.  */
+  if (off == (Dwarf_Off) -1l
+      /* Make sure there is enough space in the .debug_frame section
+	 for at least the initial word.  We cannot test the rest since
+	 we don't know yet whether this is a 64-bit object or not.  */
+      || unlikely (off + 4 >= data->d_size))
+    {
+    done:
+      *next_off = (Dwarf_Off) -1l;
+      return 1;
+    }
+
+  /* This points into the .debug_frame section at the start of the entry.  */
+  const uint8_t *bytes = data->d_buf + off;
+  const uint8_t *limit = data->d_buf + data->d_size;
+
+  /* The format of a CFI entry is described in DWARF3 6.4.1:
+   */
+
+  uint64_t length = read_4ubyte_unaligned_inc (&dw, bytes);
+  size_t offset_size = 4;
+  if (length == DWARF3_LENGTH_64_BIT)
+    {
+      /* This is the 64-bit DWARF format.  */
+      offset_size = 8;
+      if (unlikely (limit - bytes < 8))
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      length = read_8ubyte_unaligned_inc (&dw, bytes);
+    }
+
+  /* Not explicitly in the DWARF spec, but mentioned in the LSB exception
+     frames (.eh_frame) spec. If Length contains the value 0, then this
+     CIE shall be considered a terminator and processing shall end.  */
+  if (length == 0)
+    goto done;
+
+  if (unlikely ((uint64_t) (limit - bytes) < length)
+      || unlikely (length < offset_size + 1))
+    goto invalid;
+
+  /* Now we know how large the entry is.  Note the trick in the
+     computation.  If the offset_size is 4 the '- 4' term undoes the
+     '2 *'.  If offset_size is 8 this term computes the size of the
+     escape value plus the 8 byte offset.  */
+  *next_off = off + (2 * offset_size - 4) + length;
+
+  limit = bytes + length;
+
+  const uint8_t *const cie_pointer_start = bytes;
+  if (offset_size == 8)
+    entry->cie.CIE_id = read_8ubyte_unaligned_inc (&dw, bytes);
+  else
+    {
+      entry->cie.CIE_id = read_4ubyte_unaligned_inc (&dw, bytes);
+      /* Canonicalize the 32-bit CIE_ID value to 64 bits.  */
+      if (!eh_frame_p && entry->cie.CIE_id == DW_CIE_ID_32)
+	entry->cie.CIE_id = DW_CIE_ID_64;
+    }
+  if (eh_frame_p)
+    {
+      /* Canonicalize the .eh_frame CIE pointer to .debug_frame format.  */
+      if (entry->cie.CIE_id == 0)
+	entry->cie.CIE_id = DW_CIE_ID_64;
+      else
+	{
+	  /* In .eh_frame format, a CIE pointer is the distance from where
+	     it appears back to the beginning of the CIE.  */
+	  ptrdiff_t pos = cie_pointer_start - (const uint8_t *) data->d_buf;
+	  if (unlikely (entry->cie.CIE_id > (Dwarf_Off) pos)
+	      || unlikely (pos <= (ptrdiff_t) offset_size))
+	    goto invalid;
+	  entry->cie.CIE_id = pos - entry->cie.CIE_id;
+	}
+    }
+
+  if (entry->cie.CIE_id == DW_CIE_ID_64)
+    {
+      /* Read the version stamp.  Always an 8-bit value.  */
+      uint8_t version = *bytes++;
+
+      if (version != 1 && (unlikely (version < 3) || unlikely (version > 4)))
+	goto invalid;
+
+      entry->cie.augmentation = (const char *) bytes;
+
+      bytes = memchr (bytes, '\0', limit - bytes);
+      if (unlikely (bytes == NULL))
+	goto invalid;
+      ++bytes;
+
+      /* The address size for CFI is implicit in the ELF class.  */
+      uint_fast8_t address_size = e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+      uint_fast8_t segment_size = 0;
+      if (version >= 4)
+	{
+	  if (unlikely (limit - bytes < 5))
+	    goto invalid;
+	  /* XXX We don't actually support address_size not matching the class.
+	     To do so, we'd have to return it here so that intern_new_cie
+	     could use it choose a specific fde_encoding.  */
+	  if (unlikely (*bytes != address_size))
+	    {
+	      __libdw_seterrno (DWARF_E_VERSION);
+	      return -1;
+	    }
+	  address_size = *bytes++;
+	  segment_size = *bytes++;
+	  /* We don't actually support segment selectors.  We'd have to
+	     roll this into the fde_encoding bits or something.  */
+	  if (unlikely (segment_size != 0))
+	    {
+	      __libdw_seterrno (DWARF_E_VERSION);
+	      return -1;
+	    }
+	}
+
+      const char *ap = entry->cie.augmentation;
+
+      /* g++ v2 "eh" has pointer immediately following augmentation string,
+	 so it must be handled first.  */
+      if (unlikely (ap[0] == 'e' && ap[1] == 'h'))
+	{
+	  ap += 2;
+	  bytes += address_size;
+	}
+
+      if (bytes >= limit)
+	goto invalid;
+      get_uleb128 (entry->cie.code_alignment_factor, bytes, limit);
+
+      if (bytes >= limit)
+	goto invalid;
+      get_sleb128 (entry->cie.data_alignment_factor, bytes, limit);
+
+      if (bytes >= limit)
+	goto invalid;
+
+      if (version >= 3)		/* DWARF 3+ */
+	get_uleb128 (entry->cie.return_address_register, bytes, limit);
+      else			/* DWARF 2 */
+	entry->cie.return_address_register = *bytes++;
+
+      entry->cie.fde_augmentation_data_size = 0;
+      entry->cie.augmentation_data = bytes;
+      bool sized_augmentation = *ap == 'z';
+      if (sized_augmentation)
+	{
+	  ++ap;
+	  if (bytes >= limit)
+	    goto invalid;
+	  get_uleb128 (entry->cie.augmentation_data_size, bytes, limit);
+	  if ((Dwarf_Word) (limit - bytes) < entry->cie.augmentation_data_size)
+	    goto invalid;
+	  entry->cie.augmentation_data = bytes;
+	}
+
+      for (; *ap != '\0'; ++ap)
+	{
+	  uint8_t encoding;
+	  switch (*ap)
+	    {
+	    case 'L':
+	      if (sized_augmentation)
+		{
+		  /* Skip LSDA pointer encoding byte.  */
+		  encoding = *bytes++;
+		  entry->cie.fde_augmentation_data_size
+		    += encoded_value_size (data, e_ident, encoding, NULL);
+		  continue;
+		}
+	      break;
+	    case 'R':
+	      if (sized_augmentation)
+		{
+		  /* Skip FDE address encoding byte.  */
+		  bytes++;
+		  continue;
+		}
+	      break;
+	    case 'P':
+	      if (sized_augmentation)
+		{
+		  /* Skip encoded personality routine pointer. */
+		  encoding = *bytes++;
+		  bytes += encoded_value_size (data, e_ident, encoding, bytes);
+		  continue;
+		}
+	      break;
+	    case 'S':
+	      if (sized_augmentation)
+		/* Skip signal-frame flag.  */
+		continue;
+	      break;
+	    default:
+	      /* Unknown augmentation string.  initial_instructions might
+		 actually start with some augmentation data.  */
+	      break;
+	    }
+	  break;
+	}
+      if (! sized_augmentation)
+	entry->cie.augmentation_data_size = bytes - entry->cie.augmentation_data;
+      else
+	{
+	  if (bytes > entry->cie.augmentation_data + entry->cie.augmentation_data_size)
+	    goto invalid;
+	  bytes = entry->cie.augmentation_data + entry->cie.augmentation_data_size;
+	}
+
+      entry->cie.initial_instructions = bytes;
+      entry->cie.initial_instructions_end = limit;
+    }
+  else
+    {
+      entry->fde.start = bytes;
+      entry->fde.end = limit;
+    }
+
+  return 0;
+}
+INTDEF (dwarf_next_cfi)
diff --git a/libdw/dwarf_next_lines.c b/libdw/dwarf_next_lines.c
new file mode 100644
index 0000000..a96bd73
--- /dev/null
+++ b/libdw/dwarf_next_lines.c
@@ -0,0 +1,189 @@
+/* Iterate through the debug line table.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+
+
+int
+dwarf_next_lines (Dwarf *dbg, Dwarf_Off off,
+		  Dwarf_Off *next_off, Dwarf_CU **cu,
+		  Dwarf_Files **srcfiles, size_t *nfiles,
+		  Dwarf_Lines **srclines, size_t *nlines)
+{
+  /* Ignore existing errors.  */
+  if (dbg == NULL)
+    return -1;
+
+  Elf_Data *lines = dbg->sectiondata[IDX_debug_line];
+  if (lines == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NO_DEBUG_LINE);
+      return -1;
+    }
+
+  if (off == (Dwarf_Off) -1
+      || lines->d_size < 4
+      || off >= lines->d_size)
+    {
+      *next_off = (Dwarf_Off) -1;
+      return 1;
+    }
+
+  /* Read enough of the header to know where the next table is and
+     whether we need to lookup the CU (version < 5).  */
+  const unsigned char *linep = lines->d_buf + off;
+  const unsigned char *lineendp = lines->d_buf + lines->d_size;
+
+  if ((size_t) (lineendp - linep) < 4)
+    {
+    invalid_data:
+      __libdw_seterrno (DWARF_E_INVALID_DEBUG_LINE);
+      return -1;
+    }
+
+  *next_off = off + 4;
+  Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
+  if (unit_length == DWARF3_LENGTH_64_BIT)
+    {
+      if ((size_t) (lineendp - linep) < 8)
+	goto invalid_data;
+      unit_length = read_8ubyte_unaligned_inc (dbg, linep);
+      *next_off += 8;
+    }
+
+  if (unit_length > (size_t) (lineendp - linep))
+    goto invalid_data;
+
+  *next_off += unit_length;
+  lineendp = linep + unit_length;
+
+  if ((size_t) (lineendp - linep) < 2)
+    goto invalid_data;
+  uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
+
+  Dwarf_Die cudie;
+  if (version < 5)
+    {
+      /* We need to find the matching CU to get the comp_dir.  Use the
+	 given CU as hint where to start searching.  Normally it will
+	 be the next CU that has a statement list.  If the CUs are in a
+	 different order from the line tables, then we do a linear
+	 search.  */
+      Dwarf_CU *given_cu = *cu;
+      Dwarf_CU *next_cu = given_cu;
+      bool restarted = false;
+      while (1)
+	{
+	  if (restarted && next_cu == given_cu)
+	    {
+	      /* We checked all of the CUs and there was no match.  */
+	      *cu = NULL;
+	      break;
+	    }
+	  if (INTUSE(dwarf_get_units) (dbg, next_cu, &next_cu, NULL, NULL,
+				       &cudie, NULL) != 0)
+	    {
+	      /* We didn't find the matching CU after the starting point.
+	         Check the CUs up to the starting point.  */
+	      next_cu = NULL;
+	      restarted = true;
+	      continue;
+	    }
+
+	  Dwarf_Word stmt_off = 0;
+	  if (dwarf_hasattr (&cudie, DW_AT_stmt_list))
+	    {
+	      Dwarf_Attribute attr;
+	      if (dwarf_formudata (dwarf_attr (&cudie, DW_AT_stmt_list, &attr),
+				   &stmt_off) != 0)
+		continue;
+	    }
+	  /* Split units have an implicit offset of 0.  */
+	  else if (next_cu->unit_type != DW_UT_split_compile
+		   && next_cu->unit_type != DW_UT_split_type)
+	    continue;
+
+	  Dwarf_Off dwp_off;
+	  if (INTUSE(dwarf_cu_dwp_section_info) (next_cu, DW_SECT_LINE,
+						 &dwp_off, NULL) == 0)
+	    stmt_off += dwp_off;
+
+	  if (stmt_off == off)
+	    {
+	      *cu = next_cu;
+	      break;
+	    }
+	}
+    }
+  else
+    *cu = NULL;
+
+  const char *comp_dir;
+  unsigned address_size;
+  if (*cu != NULL)
+    {
+      comp_dir = __libdw_getcompdir (&cudie);
+      address_size = (*cu)->address_size;
+    }
+  else
+    {
+      comp_dir = NULL;
+
+      size_t esize;
+      char *ident = elf_getident (dbg->elf, &esize);
+      if (ident == NULL || esize < EI_NIDENT)
+	goto invalid_data;
+      address_size = ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+    }
+
+  if (__libdw_getsrclines (dbg, off, comp_dir, address_size,
+			   srclines, srcfiles) != 0)
+    return -1;
+
+  if (nlines != NULL)
+    {
+      if (srclines != NULL && *srclines != NULL)
+	*nlines = (*srclines)->nlines;
+      else
+	*nlines = 0;
+    }
+
+  if (nfiles != NULL)
+    {
+      if (srcfiles != NULL && *srcfiles != NULL)
+	*nfiles = (*srcfiles)->nfiles;
+      else
+	*nfiles = 0;
+    }
+
+  return 0;
+}
diff --git a/libdw/dwarf_nextcu.c b/libdw/dwarf_nextcu.c
new file mode 100644
index 0000000..67cec44
--- /dev/null
+++ b/libdw/dwarf_nextcu.c
@@ -0,0 +1,309 @@
+/* Advance to next CU header.
+   Copyright (C) 2002-2010, 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libdwP.h>
+#include <dwarf.h>
+
+
+int
+dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
+		 size_t *header_sizep, Dwarf_Half *versionp,
+		 Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
+		 uint8_t *offset_sizep, uint64_t *v4_type_signaturep,
+		 Dwarf_Off *v4_type_offsetp)
+{
+  const bool v4_debug_types = v4_type_signaturep != NULL;
+  return __libdw_next_unit (dwarf, v4_debug_types, off, next_off,
+			     header_sizep, versionp, NULL,
+			     abbrev_offsetp, address_sizep, offset_sizep,
+			     v4_type_signaturep, v4_type_offsetp);
+}
+INTDEF(dwarf_next_unit)
+
+int
+internal_function
+__libdw_next_unit (Dwarf *dwarf, bool v4_debug_types, Dwarf_Off off,
+		   Dwarf_Off *next_off, size_t *header_sizep,
+		   Dwarf_Half *versionp, uint8_t *unit_typep,
+		   Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
+		   uint8_t *offset_sizep, uint64_t *unit_id8p,
+		   Dwarf_Off *subdie_offsetp)
+{
+  /* Note that debug_type units come from .debug_types in DWARF < 5 and
+     from .debug_info in DWARF >= 5.  If the user requested the
+     v4_type_signature we return from .debug_types always.  If no signature
+     is requested we return units (any type) from .debug_info.  */
+  const size_t sec_idx = v4_debug_types ? IDX_debug_types : IDX_debug_info;
+
+  /* Maybe there has been an error before.  */
+  if (dwarf == NULL)
+    return -1;
+
+  /* If we reached the end before don't do anything.  */
+  if (off == (Dwarf_Off) -1l
+      || unlikely (dwarf->sectiondata[sec_idx] == NULL)
+      /* Make sure there is enough space in the .debug_info section
+	 for at least the initial word.  We cannot test the rest since
+	 we don't know yet whether this is a 64-bit object or not.  */
+      || unlikely (off + 4 >= dwarf->sectiondata[sec_idx]->d_size))
+    {
+      *next_off = (Dwarf_Off) -1l;
+      return 1;
+    }
+
+  /* This points into the .debug_info or .debug_types section to the
+     beginning of the CU entry.  */
+  const unsigned char *data = dwarf->sectiondata[sec_idx]->d_buf;
+  const unsigned char *bytes = data + off;
+  const unsigned char *bytes_end = data + dwarf->sectiondata[sec_idx]->d_size;
+
+  /* The format of the CU header is described in dwarf2p1 7.5.1 and
+     changed in DWARFv5 (to include unit type, switch location of some
+     fields and add some optional fields).
+
+     1.  A 4-byte or 12-byte unsigned integer representing the length
+	 of the .debug_info contribution for that compilation unit, not
+	 including the length field itself. In the 32-bit DWARF format,
+	 this is a 4-byte unsigned integer (which must be less than
+	 0xfffffff0); in the 64-bit DWARF format, this consists of the
+	 4-byte value 0xffffffff followed by an 8-byte unsigned integer
+	 that gives the actual length (see Section 7.2.2). This field
+	 indicates whether this unit is 32-bit of 64-bit DWARF, which
+	 affects all other offset fields in this header.
+
+      2. A 2-byte unsigned integer representing the version of the
+	 DWARF information for that compilation unit. For DWARF Version
+	 2.1, the value in this field is 2 (3 for v3, 4 for v4, 5 for v5).
+	 This fields determines the order of the next fields and whether
+	 there are any optional fields in this header.
+
+      3. For DWARF 2, 3 and 4 (including v4 type units):
+         A 4-byte or 8-byte unsigned offset into the .debug_abbrev
+	 section. This offset associates the compilation unit with a
+	 particular set of debugging information entry abbreviations. In
+	 the 32-bit DWARF format, this is a 4-byte unsigned length; in
+	 the 64-bit DWARF format, this is an 8-byte unsigned length (see
+	 Section 7.4).
+
+	 For DWARF 5:
+	 A 1-byte unsigned integer representing the unit (header) type.
+	 This field determines what the optional fields in the header
+	 represent.  If this is an unknown unit type then we cannot
+	 assume anything about the rest of the unit (header).
+
+      4. For all DWARF versions (including v4 type units):
+         A 1-byte unsigned integer representing the size in bytes of
+	 an address on the target architecture. If the system uses
+	 segmented addressing, this value represents the size of the
+	 offset portion of an address. This is the last field in the header
+	 for DWARF versions 2, 3 and 4 (except for v4 type units).
+
+      5. For DWARF 5 only (this is field 3 for DWARF 2, 3, 4 and v4 types):
+         A 4-byte or 8-byte unsigned offset into the .debug_abbrev
+	 section. This offset associates the compilation unit with a
+	 particular set of debugging information entry abbreviations. In
+	 the 32-bit DWARF format, this is a 4-byte unsigned length; in
+	 the 64-bit DWARF format, this is an 8-byte unsigned length.
+
+      6. For v4 type units (this is really field 5 for v4 types) and
+         DWARF 5 optional (skeleton, split_compile, type and
+         split_type): An 8 byte (opaque) integer constant value. For
+         v4 and v5 type units this is the type signature. For skeleton
+         and split compile units this is the compilation ID.
+
+      7. For v4 type units (this is really field 6 for v4 types) and
+         DWARF 5 optional (type and split_type) and v4 type units:
+         A 4-byte or 8-byte unsigned offset. In the 32-bit DWARF format,
+         this is a 4-byte unsigned length; in the 64-bit DWARF format,
+         this is an 8-byte unsigned length. This is the type DIE offset
+	 (which is not necessarily the first DIE in the unit).
+  */
+
+  uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
+  size_t offset_size = 4;
+  /* Lengths of 0xfffffff0 - 0xffffffff are escape codes.  Oxffffffff is
+     used to indicate that 64-bit dwarf information is being used, the
+     other values are currently reserved.  */
+  if (length == DWARF3_LENGTH_64_BIT)
+    offset_size = 8;
+  else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
+		     && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
+    {
+    invalid:
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  if (length == DWARF3_LENGTH_64_BIT)
+    {
+      /* This is a 64-bit DWARF format.  */
+      if (bytes_end - bytes < 8)
+	goto invalid;
+      length = read_8ubyte_unaligned_inc (dwarf, bytes);
+    }
+
+  /* Read the version stamp.  Always a 16-bit value.  */
+  if (bytes_end - bytes < 2)
+    goto invalid;
+  uint_fast16_t version = read_2ubyte_unaligned_inc (dwarf, bytes);
+
+  /* We keep unit_type at zero for older DWARF since we cannot
+     easily guess whether it is a compile or partial unit.  */
+  uint8_t unit_type = 0;
+  if (version >= 5)
+    {
+      if (bytes_end - bytes < 1)
+	goto invalid;
+      unit_type = *bytes++;
+    }
+
+  /* All these are optional.  */
+  Dwarf_Off subdie_off = 0;
+  uint64_t sig_id = 0;
+  Dwarf_Off abbrev_offset = 0;
+  uint8_t address_size = 0;
+
+  if (version < 2 || version > 5
+      || (version == 5 && ! (unit_type == DW_UT_compile
+			     || unit_type == DW_UT_partial
+			     || unit_type == DW_UT_skeleton
+			     || unit_type == DW_UT_split_compile
+			     || unit_type == DW_UT_type
+			     || unit_type == DW_UT_split_type)))
+    {
+      /* We cannot really know more about the header.  Just report
+	 the length of the unit, version and unit type.  */
+      goto done;
+    }
+
+  /* We have to guess the unit_type. But we don't have a real CUDIE.  */
+  if (version < 5)
+    unit_type = v4_debug_types ? DW_UT_type : DW_UT_compile;
+
+  /* Now we know how large the header is (should be).  */
+  if (unlikely (__libdw_first_die_from_cu_start (off, offset_size, version,
+						 unit_type)
+		>= dwarf->sectiondata[sec_idx]->d_size))
+    {
+      *next_off = -1;
+      return 1;
+    }
+
+  /* The address size.  Always an 8-bit value.
+     Comes after abbrev_offset for version < 5, otherwise unit type
+     and address size (if a known unit type) comes before abbrev_offset.  */
+  if (version >= 5)
+    address_size = *bytes++;
+
+  /* Get offset in .debug_abbrev.  Note that the size of the entry
+     depends on whether this is a 32-bit or 64-bit DWARF definition.  */
+  if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
+			       &abbrev_offset, IDX_debug_abbrev, 0))
+    return -1;
+
+  if (version < 5)
+    address_size = *bytes++;
+
+  /* Extra fields, signature/id and type offset/padding.  */
+  if (v4_debug_types
+      || (version >= 5
+	  && (unit_type == DW_UT_skeleton || unit_type == DW_UT_split_compile
+	      || unit_type == DW_UT_type || unit_type == DW_UT_split_type)))
+    {
+      sig_id = read_8ubyte_unaligned_inc (dwarf, bytes);
+
+      if ((v4_debug_types
+	   || unit_type == DW_UT_type || unit_type == DW_UT_split_type))
+	{
+	  if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
+				       &subdie_off, sec_idx, 0))
+	    return -1;
+
+	  /* Validate that the TYPE_OFFSET points past the header.  */
+	  if (unlikely (subdie_off < (size_t) (bytes - (data + off))))
+	    goto invalid;
+	}
+    }
+
+ done:
+  if (unit_id8p != NULL)
+    *unit_id8p = sig_id;
+
+  if (subdie_offsetp != NULL)
+    *subdie_offsetp = subdie_off;
+
+  /* Store the header length.  This is really how much we have read
+     from the header.  If we didn't recognize the unit type the
+     header might actually be bigger.  */
+  if (header_sizep != NULL)
+    *header_sizep = bytes - (data + off);
+
+  if (versionp != NULL)
+    *versionp = version;
+
+  if (unit_typep != NULL)
+    *unit_typep = unit_type;
+
+  if (abbrev_offsetp != NULL)
+    *abbrev_offsetp = abbrev_offset;
+
+  if (address_sizep != NULL)
+    *address_sizep = address_size;
+
+  /* Store the offset size.  */
+  if (offset_sizep != NULL)
+    *offset_sizep = offset_size;
+
+  /* The length of the unit doesn't include the length field itself.
+     The length field is either, with offset == 4: 2 * 4 - 4 == 4,
+     or with offset == 8: 2 * 8 - 4 == 12.  */
+  *next_off = off + 2 * offset_size - 4 + length;
+
+  /* This means that the length field is bogus, but return the CU anyway.
+     We just won't return anything after this.  */
+  if (*next_off <= off)
+    *next_off = (Dwarf_Off) -1;
+
+  return 0;
+}
+
+int
+dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
+	      size_t *header_sizep, Dwarf_Off *abbrev_offsetp,
+	      uint8_t *address_sizep, uint8_t *offset_sizep)
+{
+  return INTUSE(dwarf_next_unit) (dwarf, off, next_off, header_sizep, NULL,
+				  abbrev_offsetp, address_sizep, offset_sizep,
+				  NULL, NULL);
+}
+INTDEF(dwarf_nextcu)
diff --git a/libdw/dwarf_offabbrev.c b/libdw/dwarf_offabbrev.c
new file mode 100644
index 0000000..27cdad6
--- /dev/null
+++ b/libdw/dwarf_offabbrev.c
@@ -0,0 +1,51 @@
+/* Get abbreviation at given offset.
+   Copyright (C) 2004, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+int
+dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp,
+		 Dwarf_Abbrev *abbrevp)
+{
+  if (dbg == NULL)
+    return -1;
+
+  Dwarf_Abbrev *abbrev = __libdw_getabbrev (dbg, NULL, offset, lengthp,
+					    abbrevp);
+
+  if (abbrev == NULL)
+    return -1;
+
+  return abbrev == DWARF_END_ABBREV ? 1 : 0;
+}
diff --git a/libdw/dwarf_offdie.c b/libdw/dwarf_offdie.c
new file mode 100644
index 0000000..883720d
--- /dev/null
+++ b/libdw/dwarf_offdie.c
@@ -0,0 +1,84 @@
+/* Return DIE at given offset.
+   Copyright (C) 2002-2010, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+internal_function
+__libdw_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result,
+		bool debug_types)
+{
+  if (dbg == NULL)
+    return NULL;
+
+  Elf_Data *const data = dbg->sectiondata[debug_types ? IDX_debug_types
+					  : IDX_debug_info];
+  if (data == NULL || offset >= data->d_size)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  /* Clear the entire DIE structure.  This signals we have not yet
+     determined any of the information.  */
+  memset (result, '\0', sizeof (Dwarf_Die));
+
+  result->addr = (char *) data->d_buf + offset;
+
+  /* Get the CU.  */
+  result->cu = __libdw_findcu (dbg, offset, debug_types);
+  if (result->cu == NULL)
+    {
+      /* This should never happen.  The input file is malformed.  */
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      result = NULL;
+    }
+
+  return result;
+}
+
+
+Dwarf_Die *
+dwarf_offdie (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result)
+{
+  return __libdw_offdie (dbg, offset, result, false);
+}
+INTDEF(dwarf_offdie)
+
+Dwarf_Die *
+dwarf_offdie_types (Dwarf *dbg, Dwarf_Off offset, Dwarf_Die *result)
+{
+  return __libdw_offdie (dbg, offset, result, true);
+}
diff --git a/libdw/dwarf_onearange.c b/libdw/dwarf_onearange.c
new file mode 100644
index 0000000..de49f6c
--- /dev/null
+++ b/libdw/dwarf_onearange.c
@@ -0,0 +1,50 @@
+/* Return one of the address range entries.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Arange *
+dwarf_onearange (Dwarf_Aranges *aranges, size_t idx)
+{
+  if (aranges == NULL)
+    return NULL;
+
+  if (idx >= aranges->naranges)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ARANGE_IDX);
+      return NULL;
+    }
+
+  return &aranges->info[idx];
+}
diff --git a/libdw/dwarf_onesrcline.c b/libdw/dwarf_onesrcline.c
new file mode 100644
index 0000000..5d3c3de
--- /dev/null
+++ b/libdw/dwarf_onesrcline.c
@@ -0,0 +1,50 @@
+/* Return one of the sources lines of a CU.
+   Copyright (C) 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Line *
+dwarf_onesrcline (Dwarf_Lines *lines, size_t idx)
+{
+  if (lines == NULL)
+    return NULL;
+
+  if (idx >= lines->nlines)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_LINE_IDX);
+      return NULL;
+    }
+
+  return &lines->info[idx];
+}
diff --git a/libdw/dwarf_peel_type.c b/libdw/dwarf_peel_type.c
new file mode 100644
index 0000000..59fc6f1
--- /dev/null
+++ b/libdw/dwarf_peel_type.c
@@ -0,0 +1,80 @@
+/* Peel type aliases and qualifier tags from a type DIE.
+   Copyright (C) 2014, 2015, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+#include <string.h>
+
+
+int
+dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result)
+{
+  int tag;
+
+  /* Ignore previous errors.  */
+  if (die == NULL)
+    return -1;
+
+  *result = *die;
+  tag = INTUSE (dwarf_tag) (result);
+
+/* Stack 8 of all these modifiers, after that it gets silly.  */
+#define MAX_DEPTH (8 * 8)
+  int max_depth = MAX_DEPTH;
+  while ((tag == DW_TAG_typedef
+	  || tag == DW_TAG_const_type
+	  || tag == DW_TAG_volatile_type
+	  || tag == DW_TAG_restrict_type
+	  || tag == DW_TAG_atomic_type
+	  || tag == DW_TAG_immutable_type
+	  || tag == DW_TAG_packed_type
+	  || tag == DW_TAG_shared_type)
+	&& max_depth-- > 0)
+    {
+      Dwarf_Attribute attr_mem;
+      Dwarf_Attribute *attr = INTUSE (dwarf_attr_integrate) (result, DW_AT_type,
+							     &attr_mem);
+      if (attr == NULL)
+	return 1;
+
+      if (INTUSE (dwarf_formref_die) (attr, result) == NULL)
+	return -1;
+
+      tag = INTUSE (dwarf_tag) (result);
+    }
+
+  if (tag == DW_TAG_invalid || max_depth <= 0)
+    return -1;
+
+  return 0;
+}
+INTDEF(dwarf_peel_type)
diff --git a/libdw/dwarf_ranges.c b/libdw/dwarf_ranges.c
new file mode 100644
index 0000000..b853e4b
--- /dev/null
+++ b/libdw/dwarf_ranges.c
@@ -0,0 +1,562 @@
+/* Enumerate the PC ranges covered by a DIE.
+   Copyright (C) 2005, 2007, 2009, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+#include <assert.h>
+
+/* Read up begin/end pair and increment read pointer.
+    - If it's normal range record, set up `*beginp' and `*endp' and return 0.
+    - If it's a default location, set `*beginp' (0), `*endp' (-1) and return 0.
+    - If it's base address selection record, set up `*basep' and return 1.
+    - If it's end of rangelist, don't set anything and return 2
+    - If an error occurs, don't set anything and return -1.  */
+internal_function int
+__libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
+				 const unsigned char **addrp,
+				 const unsigned char *addrend,
+				 int width,
+				 Dwarf_Addr *beginp, Dwarf_Addr *endp,
+				 Dwarf_Addr *basep)
+{
+  Dwarf *dbg = cu->dbg;
+  if (sec_index == IDX_debug_loc
+      && cu->version < 5
+      && cu->unit_type == DW_UT_split_compile)
+    {
+      /* GNU DebugFission.  */
+      const unsigned char *addr = *addrp;
+      if (addrend - addr < 1)
+	goto invalid;
+
+      const char code = *addr++;
+      uint64_t begin = 0, end = 0, base = *basep, addr_idx;
+      switch (code)
+	{
+	case DW_LLE_GNU_end_of_list_entry:
+	  *addrp = addr;
+	  return 2;
+
+	case DW_LLE_GNU_base_address_selection_entry:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
+	    return -1;
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_LLE_GNU_start_end_entry:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
+	    return -1;
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_LLE_GNU_start_length_entry:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 4)
+	    goto invalid;
+	  end = read_4ubyte_unaligned_inc (dbg, addr);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	default:
+	  goto invalid;
+	}
+    }
+  else if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc)
+    {
+      Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
+			   : (Elf64_Addr) (Elf32_Addr) -1);
+      Dwarf_Addr begin;
+      Dwarf_Addr end;
+
+      const unsigned char *addr = *addrp;
+      if (addrend - addr < width * 2)
+	{
+	invalid:
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+
+      bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
+						begin);
+      bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
+					      end);
+      *addrp = addr;
+
+      /* Unrelocated escape for begin means base address selection.  */
+      if (begin == escape && !begin_relocated)
+	{
+	  if (unlikely (end == escape))
+	    goto invalid;
+
+	  *basep = end;
+	  return 1;
+	}
+
+      /* Unrelocated pair of zeroes means end of range list.  */
+      if (begin == 0 && end == 0 && !begin_relocated && !end_relocated)
+	return 2;
+
+      /* Don't check for begin_relocated == end_relocated.  Serve the data
+	 to the client even though it may be buggy.  */
+      *beginp = begin + *basep;
+      *endp = end + *basep;
+
+      return 0;
+    }
+  else if (sec_index == IDX_debug_rnglists)
+    {
+      const unsigned char *addr = *addrp;
+      if (addrend - addr < 1)
+	goto invalid;
+
+      const char code = *addr++;
+      uint64_t begin = 0, end = 0, base = *basep, addr_idx;
+      switch (code)
+	{
+	case DW_RLE_end_of_list:
+	  *addrp = addr;
+	  return 2;
+
+	case DW_RLE_base_addressx:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
+	    return -1;
+
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_RLE_startx_endx:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
+	    return -1;
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_startx_length:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_offset_pair:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (begin, addr, addrend);
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin + base;
+	  *endp = end + base;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_base_address:
+	  if (addrend - addr < width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
+
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_RLE_start_end:
+	  if (addrend - addr < 2 * width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_RLE_start_length:
+	  if (addrend - addr < width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	default:
+	  goto invalid;
+	}
+    }
+  else if (sec_index == IDX_debug_loclists)
+    {
+      const unsigned char *addr = *addrp;
+      if (addrend - addr < 1)
+	goto invalid;
+
+      const char code = *addr++;
+      uint64_t begin = 0, end = 0, base = *basep, addr_idx;
+      switch (code)
+	{
+	case DW_LLE_end_of_list:
+	  *addrp = addr;
+	  return 2;
+
+	case DW_LLE_base_addressx:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
+	    return -1;
+
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_LLE_startx_endx:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
+	    return -1;
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_LLE_startx_length:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (addr_idx, addr, addrend);
+	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
+	    return -1;
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_LLE_offset_pair:
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (begin, addr, addrend);
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin + base;
+	  *endp = end + base;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_LLE_default_location:
+	  *beginp = 0;
+	  *endp = (Dwarf_Addr) -1;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_LLE_base_address:
+	  if (addrend - addr < width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
+
+	  *basep = base;
+	  *addrp = addr;
+	  return 1;
+
+	case DW_LLE_start_end:
+	  if (addrend - addr < 2 * width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
+
+	  *beginp = begin;
+	  *endp = end;
+	  *addrp = addr;
+	  return 0;
+
+	case DW_LLE_start_length:
+	  if (addrend - addr < width)
+	    goto invalid;
+	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
+	  if (addrend - addr < 1)
+	    goto invalid;
+	  get_uleb128 (end, addr, addrend);
+
+	  *beginp = begin;
+	  *endp = begin + end;
+	  *addrp = addr;
+	  return 0;
+
+	default:
+	  goto invalid;
+	}
+    }
+  else
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+}
+
+static int
+initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
+{
+  size_t secidx = (attr->cu->version < 5
+		   ? IDX_debug_ranges : IDX_debug_rnglists);
+
+  Dwarf_Word start_offset;
+  if (attr->form == DW_FORM_rnglistx)
+    {
+      Dwarf_Word idx;
+      Dwarf_CU *cu = attr->cu;
+      const unsigned char *datap = attr->valp;
+      const unsigned char *endp = cu->endp;
+      if (datap >= endp)
+	{
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return -1;
+	}
+      get_uleb128 (idx, datap, endp);
+
+      Elf_Data *data = cu->dbg->sectiondata[secidx];
+      if (data == NULL && cu->unit_type == DW_UT_split_compile)
+	{
+	  cu = __libdw_find_split_unit (cu);
+	  if (cu != NULL)
+	    data = cu->dbg->sectiondata[secidx];
+	}
+
+      if (data == NULL)
+	{
+	  __libdw_seterrno (secidx == IDX_debug_ranges
+                            ? DWARF_E_NO_DEBUG_RANGES
+                            : DWARF_E_NO_DEBUG_RNGLISTS);
+	  return -1;
+	}
+
+      Dwarf_Off range_base_off = __libdw_cu_ranges_base (cu);
+
+      /* The section should at least contain room for one offset.  */
+      size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
+      size_t offset_size = cu->offset_size;
+      if (offset_size > sec_size)
+	{
+	invalid_offset:
+	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+	  return -1;
+	}
+
+      /* And the base offset should be at least inside the section.  */
+      if (range_base_off > (sec_size - offset_size))
+	goto invalid_offset;
+
+      size_t max_idx = (sec_size - offset_size - range_base_off) / offset_size;
+      if (idx > max_idx)
+	goto invalid_offset;
+
+      datap = (cu->dbg->sectiondata[secidx]->d_buf
+	       + range_base_off + (idx * offset_size));
+      if (offset_size == 4)
+	start_offset = read_4ubyte_unaligned (cu->dbg, datap);
+      else
+	start_offset = read_8ubyte_unaligned (cu->dbg, datap);
+
+      start_offset += range_base_off;
+    }
+  else
+    {
+      if (__libdw_formptr (attr, secidx,
+			   (secidx == IDX_debug_ranges
+			    ? DWARF_E_NO_DEBUG_RANGES
+			    : DWARF_E_NO_DEBUG_RNGLISTS),
+			   NULL, &start_offset) == NULL)
+	return -1;
+    }
+
+  *offset = start_offset;
+  return 0;
+}
+
+ptrdiff_t
+dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
+	      Dwarf_Addr *startp, Dwarf_Addr *endp)
+{
+  if (die == NULL)
+    return -1;
+
+  if (offset == 0
+      /* Usually there is a single contiguous range.  */
+      && INTUSE(dwarf_highpc) (die, endp) == 0
+      && INTUSE(dwarf_lowpc) (die, startp) == 0)
+    /* A offset into .debug_ranges will never be 1, it must be at least a
+       multiple of 4.  So we can return 1 as a special case value to mark
+       there are no ranges to look for on the next call.  */
+    return 1;
+
+  if (offset == 1)
+    return 0;
+
+  /* We have to look for a noncontiguous range.  */
+  Dwarf_CU *cu = die->cu;
+  if (cu == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return -1;
+    }
+
+  size_t secidx = (cu->version < 5 ? IDX_debug_ranges : IDX_debug_rnglists);
+  const Elf_Data *d = cu->dbg->sectiondata[secidx];
+  if (cu->unit_type == DW_UT_split_compile && (d == NULL || is_cudie (die)))
+    {
+      Dwarf_CU *skel = __libdw_find_split_unit (cu);
+      if (skel != NULL && skel->dbg->sectiondata[secidx] != NULL)
+	{
+	  cu = skel;
+	  d = cu->dbg->sectiondata[secidx];
+	}
+    }
+
+  const unsigned char *readp;
+  const unsigned char *readendp;
+  if (offset == 0)
+    {
+      Dwarf_Attribute attr_mem;
+      Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges,
+						  &attr_mem);
+      /* Note that above we use dwarf_attr, not dwarf_attr_integrate.
+	 The only case where the ranges can come from another DIE
+	 attribute are the split CU case. In that case we also have a
+	 different CU to check against. But that is already set up
+	 above using __libdw_find_split_unit.  */
+      if (attr == NULL
+	  && is_cudie (die)
+	  && die->cu->unit_type == DW_UT_split_compile)
+	attr = INTUSE(dwarf_attr_integrate) (die, DW_AT_ranges, &attr_mem);
+      if (attr == NULL)
+	/* No PC attributes in this DIE at all, so an empty range list.  */
+	return 0;
+
+      *basep = __libdw_cu_base_address (attr->cu);
+      if (*basep == (Dwarf_Addr) -1)
+	return -1;
+
+      if (initial_offset (attr, &offset) != 0)
+	return -1;
+    }
+  else
+    {
+      if (__libdw_offset_in_section (cu->dbg,
+				     secidx, offset, 1))
+	return -1;
+    }
+
+  readp = d->d_buf + offset;
+  readendp = d->d_buf + d->d_size;
+
+  Dwarf_Addr begin;
+  Dwarf_Addr end;
+
+ next:
+  switch (__libdw_read_begin_end_pair_inc (cu, secidx,
+					   &readp, readendp,
+					   cu->address_size,
+					   &begin, &end, basep))
+    {
+    case 0:
+      break;
+    case 1:
+      goto next;
+    case 2:
+      return 0;
+    default:
+      return -1;
+    }
+
+  *startp = begin;
+  *endp = end;
+  return readp - (unsigned char *) d->d_buf;
+}
+INTDEF (dwarf_ranges)
diff --git a/libdw/dwarf_setalt.c b/libdw/dwarf_setalt.c
new file mode 100644
index 0000000..dc9b61c
--- /dev/null
+++ b/libdw/dwarf_setalt.c
@@ -0,0 +1,47 @@
+/* Provides the data referenced by the .gnu_debugaltlink section.
+   Copyright (C) 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+void
+dwarf_setalt (Dwarf *main, Dwarf *alt)
+{
+  if (main->alt_fd != -1)
+    {
+      INTUSE(dwarf_end) (main->alt_dwarf);
+      close (main->alt_fd);
+      main->alt_fd = -1;
+    }
+
+  main->alt_dwarf = alt;
+}
+INTDEF (dwarf_setalt)
diff --git a/libdw/dwarf_siblingof.c b/libdw/dwarf_siblingof.c
new file mode 100644
index 0000000..dbed9fa
--- /dev/null
+++ b/libdw/dwarf_siblingof.c
@@ -0,0 +1,144 @@
+/* Return sibling of given DIE.
+   Copyright (C) 2003-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+#include <string.h>
+
+
+int
+dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result)
+{
+  /* Ignore previous errors.  */
+  if (die == NULL)
+    return -1;
+
+  /* result is declared NN */
+
+  if (result != die)
+    result->addr = NULL;
+
+  unsigned int level = 0;
+
+  /* Copy of the current DIE.  */
+  Dwarf_Die this_die = *die;
+  /* Temporary attributes we create.  */
+  Dwarf_Attribute sibattr;
+  /* Copy of the CU in the request.  */
+  sibattr.cu = this_die.cu;
+  /* That's the address we start looking.  */
+  unsigned char *addr;
+
+  /* Search for the beginning of the next die on this level.  We
+     must not return the dies for children of the given die.  */
+  do
+    {
+      /* Find the end of the DIE or the sibling attribute.  */
+      addr = __libdw_find_attr (&this_die, DW_AT_sibling, &sibattr.code,
+				&sibattr.form);
+      if (addr != NULL && sibattr.code == DW_AT_sibling)
+	{
+	  Dwarf_Off offset;
+	  sibattr.valp = addr;
+	  if (unlikely (__libdw_formref (&sibattr, &offset) != 0))
+	    /* Something went wrong.  */
+	    return -1;
+
+	  /* The sibling attribute should point after this DIE in the CU.
+	     But not after the end of the CU.  */
+	  size_t size = sibattr.cu->endp - sibattr.cu->startp;
+	  size_t die_off = this_die.addr - this_die.cu->startp;
+	  if (unlikely (offset >= size || offset <= die_off))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return -1;
+	    }
+
+	  /* Compute the next address.  */
+	  addr = sibattr.cu->startp + offset;
+	}
+      else if (unlikely (addr == NULL)
+	       || unlikely (this_die.abbrev == DWARF_END_ABBREV))
+	return -1;
+      else if (this_die.abbrev->has_children)
+	/* This abbreviation has children.  */
+	++level;
+
+      /* End of the buffer.  */
+      unsigned char *endp = sibattr.cu->endp;
+
+      while (1)
+	{
+	  /* Make sure we are still in range.  Some producers might skip
+	     the trailing NUL bytes.  */
+	  if (addr >= endp)
+	    return 1;
+
+	  if (*addr != '\0')
+	    break;
+
+	  if (level-- == 0)
+	    {
+	      if (result != die)
+		result->addr = addr;
+	      /* No more sibling at all.  */
+	      return 1;
+	    }
+
+	  ++addr;
+	}
+
+      /* Initialize the 'current DIE'.  */
+      this_die.addr = addr;
+      this_die.abbrev = NULL;
+    }
+  while (level > 0);
+
+  /* Maybe we reached the end of the CU.  */
+  unsigned char *endp = sibattr.cu->endp;
+  if (addr >= endp)
+    return 1;
+
+  /* Clear the entire DIE structure.  This signals we have not yet
+     determined any of the information.  */
+  memset (result, '\0', sizeof (Dwarf_Die));
+
+  /* We have the address.  */
+  result->addr = addr;
+
+  /* Same CU as the parent.  */
+  result->cu = sibattr.cu;
+
+  return 0;
+}
+INTDEF(dwarf_siblingof)
diff --git a/libdw/dwarf_sig8_hash.c b/libdw/dwarf_sig8_hash.c
new file mode 100644
index 0000000..777f9eb
--- /dev/null
+++ b/libdw/dwarf_sig8_hash.c
@@ -0,0 +1,41 @@
+/* Implementation of hash table for DWARF .debug_types section content.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define NO_UNDEF
+#include "dwarf_sig8_hash.h"
+#undef NO_UNDEF
+
+/* This is defined in dwarf_abbrev_hash.c, we can just use it here.  */
+#define next_prime __libdwarf_next_prime
+extern size_t next_prime (size_t) attribute_hidden;
+
+#include <dynamicsizehash_concurrent.c>
diff --git a/libdw/dwarf_sig8_hash.h b/libdw/dwarf_sig8_hash.h
new file mode 100644
index 0000000..c399919
--- /dev/null
+++ b/libdw/dwarf_sig8_hash.h
@@ -0,0 +1,43 @@
+/* Hash table for DWARF .debug_types section content.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DWARF_SIG8_HASH_H
+#define _DWARF_SIG8_HASH_H	1
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdw.h"
+
+#define NAME Dwarf_Sig8_Hash
+#define TYPE struct Dwarf_CU *
+
+#include <dynamicsizehash_concurrent.h>
+
+#endif	/* dwarf_sig8_hash.h */
diff --git a/libdw/dwarf_srclang.c b/libdw/dwarf_srclang.c
new file mode 100644
index 0000000..77bd58c
--- /dev/null
+++ b/libdw/dwarf_srclang.c
@@ -0,0 +1,50 @@
+/* Return source language attribute of DIE.
+   Copyright (C) 2003-2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+NEW_VERSION (dwarf_srclang, ELFUTILS_0.143)
+int
+dwarf_srclang (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Word value;
+
+  return INTUSE(dwarf_formudata) (INTUSE(dwarf_attr_integrate)
+				  (die, DW_AT_language, &attr_mem),
+				  &value) == 0 ? (int) value : -1;
+}
+NEW_INTDEF (dwarf_srclang)
+OLD_VERSION (dwarf_srclang, ELFUTILS_0.122)
diff --git a/libdw/dwarf_tag.c b/libdw/dwarf_tag.c
new file mode 100644
index 0000000..d784970
--- /dev/null
+++ b/libdw/dwarf_tag.c
@@ -0,0 +1,94 @@
+/* Return tag of given DIE.
+   Copyright (C) 2003-2011, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+
+
+Dwarf_Abbrev *
+internal_function
+__libdw_findabbrev (struct Dwarf_CU *cu, unsigned int code)
+{
+  Dwarf_Abbrev *abb;
+
+  /* Abbreviation code can never have a value of 0.  */
+  if (unlikely (code == 0))
+    return DWARF_END_ABBREV;
+
+  /* See whether the entry is already in the hash table.  */
+  abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code);
+  if (abb == NULL)
+    while (cu->last_abbrev_offset != (size_t) -1l)
+      {
+	size_t length;
+
+	/* Find the next entry.  It gets automatically added to the
+	   hash table.  */
+	abb = __libdw_getabbrev (cu->dbg, cu, cu->last_abbrev_offset, &length,
+				 NULL);
+	if (abb == NULL || abb == DWARF_END_ABBREV)
+	  {
+	    /* Make sure we do not try to search for it again.  */
+	    cu->last_abbrev_offset = (size_t) -1l;
+	    return DWARF_END_ABBREV;
+	  }
+
+	cu->last_abbrev_offset += length;
+
+	/* Is this the code we are looking for?  */
+	if (abb->code == code)
+	  break;
+      }
+
+  /* This is our second (or third, etc.) call to __libdw_findabbrev
+     and the code is invalid.  */
+  if (unlikely (abb == NULL))
+    abb = DWARF_END_ABBREV;
+
+  return abb;
+}
+
+
+int
+dwarf_tag (Dwarf_Die *die)
+{
+  /* Find the abbreviation entry.  */
+  Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, NULL);
+  if (unlikely (abbrevp == DWARF_END_ABBREV))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return DW_TAG_invalid;
+    }
+
+  return abbrevp->tag;
+}
+INTDEF(dwarf_tag)
diff --git a/libdw/dwarf_whatattr.c b/libdw/dwarf_whatattr.c
new file mode 100644
index 0000000..d664b02
--- /dev/null
+++ b/libdw/dwarf_whatattr.c
@@ -0,0 +1,42 @@
+/* Return attribute code of given attribute.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_whatattr (Dwarf_Attribute *attr)
+{
+  return attr == NULL ? 0 : attr->code;
+}
diff --git a/libdw/dwarf_whatform.c b/libdw/dwarf_whatform.c
new file mode 100644
index 0000000..dee29a9
--- /dev/null
+++ b/libdw/dwarf_whatform.c
@@ -0,0 +1,42 @@
+/* Return form code of given attribute.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+unsigned int
+dwarf_whatform (Dwarf_Attribute *attr)
+{
+  return attr == NULL ? 0 : attr->form;
+}
diff --git a/libdw/encoded-value.h b/libdw/encoded-value.h
new file mode 100644
index 0000000..4566ef9
--- /dev/null
+++ b/libdw/encoded-value.h
@@ -0,0 +1,236 @@
+/* DW_EH_PE_* support for libdw unwinder.
+   Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ENCODED_VALUE_H
+#define _ENCODED_VALUE_H 1
+
+#include <dwarf.h>
+#include <stdlib.h>
+#include "libdwP.h"
+#include "common.h"
+
+
+/* Returns zero if the value is omitted, the encoding is unknown or
+   the (leb128) size cannot be determined.  */
+static size_t __attribute__ ((unused))
+encoded_value_size (const Elf_Data *data, const unsigned char e_ident[],
+		    uint8_t encoding, const uint8_t *p)
+{
+  if (encoding == DW_EH_PE_omit)
+    return 0;
+
+  switch (encoding & 0x07)
+    {
+    case DW_EH_PE_udata2:
+      return 2;
+    case DW_EH_PE_udata4:
+      return 4;
+    case DW_EH_PE_udata8:
+      return 8;
+
+    case DW_EH_PE_absptr:
+      return e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+    case DW_EH_PE_uleb128:
+      if (p != NULL)
+	{
+	  const uint8_t *end = p;
+	  while (end < (uint8_t *) data->d_buf + data->d_size)
+	    if (*end++ & 0x80u)
+	      return end - p;
+	}
+      return 0;
+
+    default:
+      return 0;
+    }
+}
+
+/* Returns zero when value was read successfully, minus one otherwise.  */
+static inline int __attribute__ ((unused))
+__libdw_cfi_read_address_inc (const Dwarf_CFI *cache,
+			      const unsigned char **addrp,
+			      int width, Dwarf_Addr *ret)
+{
+  width = width ?: cache->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+  if (cache->dbg != NULL)
+    return __libdw_read_address_inc (cache->dbg, IDX_debug_frame,
+				     addrp, width, ret);
+
+  /* Only .debug_frame might have relocation to consider.
+     Read plain values from .eh_frame data.  */
+
+  const unsigned char *endp = cache->data->d.d_buf + cache->data->d.d_size;
+  Dwarf eh_dbg = { .other_byte_order = MY_ELFDATA != cache->e_ident[EI_DATA] };
+
+  if (width == 4)
+    {
+      if (unlikely (*addrp + 4 > endp))
+	{
+	invalid_data:
+	  __libdw_seterrno (DWARF_E_INVALID_CFI);
+	  return -1;
+	}
+      *ret = read_4ubyte_unaligned_inc (&eh_dbg, *addrp);
+    }
+  else
+    {
+      if (unlikely (*addrp + 8 > endp))
+	goto invalid_data;
+      *ret = read_8ubyte_unaligned_inc (&eh_dbg, *addrp);
+    }
+  return 0;
+}
+
+/* Returns true on error, false otherwise. */
+static bool __attribute__ ((unused))
+read_encoded_value (const Dwarf_CFI *cache, uint8_t encoding,
+		    const uint8_t **p, Dwarf_Addr *result)
+{
+  *result = 0;
+  switch (encoding & 0x70)
+    {
+    case DW_EH_PE_absptr:
+      break;
+    case DW_EH_PE_pcrel:
+      *result = (cache->frame_vaddr
+		 + (*p - (const uint8_t *) cache->data->d.d_buf));
+      break;
+    case DW_EH_PE_textrel:
+      // ia64: segrel
+      *result = cache->textrel;
+      break;
+    case DW_EH_PE_datarel:
+      // i386: GOTOFF
+      // ia64: gprel
+      *result = cache->datarel;
+      break;
+    case DW_EH_PE_funcrel:	/* XXX */
+      break;
+    case DW_EH_PE_aligned:
+      {
+	const size_t size = encoded_value_size (&cache->data->d,
+						cache->e_ident,
+						encoding, *p);
+	if (unlikely (size == 0))
+	  return true;
+	size_t align = ((cache->frame_vaddr
+			 + (*p - (const uint8_t *) cache->data->d.d_buf))
+			& (size - 1));
+	if (align != 0)
+	  *p += size - align;
+	break;
+      }
+
+    default:
+      __libdw_seterrno (DWARF_E_INVALID_CFI);
+      return true;
+    }
+
+  Dwarf_Addr value = 0;
+  const unsigned char *endp = cache->data->d.d_buf + cache->data->d.d_size;
+  switch (encoding & 0x0f)
+    {
+    case DW_EH_PE_udata2:
+      if (unlikely (*p + 2 > endp))
+	{
+	invalid_data:
+	  __libdw_seterrno (DWARF_E_INVALID_CFI);
+	  return true;
+	}
+      value = read_2ubyte_unaligned_inc (cache, *p);
+      break;
+
+    case DW_EH_PE_sdata2:
+      if (unlikely (*p + 2 > endp))
+	goto invalid_data;
+      value = read_2sbyte_unaligned_inc (cache, *p);
+      break;
+
+    case DW_EH_PE_udata4:
+      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 4, &value) != 0))
+	return true;
+      break;
+
+    case DW_EH_PE_sdata4:
+      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 4, &value) != 0))
+	return true;
+      value = (Dwarf_Sword) (Elf32_Sword) value; /* Sign-extend.  */
+      break;
+
+    case DW_EH_PE_udata8:
+    case DW_EH_PE_sdata8:
+      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 8, &value) != 0))
+	return true;
+      break;
+
+    case DW_EH_PE_absptr:
+      if (unlikely (__libdw_cfi_read_address_inc (cache, p, 0, &value) != 0))
+	return true;
+      break;
+
+    case DW_EH_PE_uleb128:
+      if (*p >= endp)
+	goto invalid_data;
+      get_uleb128 (value, *p, endp);
+      break;
+
+    case DW_EH_PE_sleb128:
+      if (*p >= endp)
+	goto invalid_data;
+      get_sleb128 (value, *p, endp);
+      break;
+
+    default:
+      __libdw_seterrno (DWARF_E_INVALID_CFI);
+      return true;
+    }
+
+  *result += value;
+
+  if (encoding & DW_EH_PE_indirect)
+    {
+      if (unlikely (*result < cache->frame_vaddr))
+	return true;
+      *result -= cache->frame_vaddr;
+      size_t ptrsize = encoded_value_size (NULL, cache->e_ident,
+					   DW_EH_PE_absptr, NULL);
+      if (unlikely (cache->data->d.d_size < ptrsize
+		    || *result > (cache->data->d.d_size - ptrsize)))
+	return true;
+      const uint8_t *ptr = cache->data->d.d_buf + *result;
+      if (unlikely (__libdw_cfi_read_address_inc (cache, &ptr, 0, result)
+		    != 0))
+	return true;
+    }
+
+  return false;
+}
+
+#endif	/* encoded-value.h */
diff --git a/libdw/fde.c b/libdw/fde.c
new file mode 100644
index 0000000..73d551b
--- /dev/null
+++ b/libdw/fde.c
@@ -0,0 +1,327 @@
+/* FDE reading.
+   Copyright (C) 2009-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+#include <search.h>
+#include <stdlib.h>
+
+#include "encoded-value.h"
+
+static int
+compare_fde (const void *a, const void *b)
+{
+  const struct dwarf_fde *fde1 = a;
+  const struct dwarf_fde *fde2 = b;
+
+  /* Find out which of the two arguments is the search value.
+     It has end offset 0.  */
+  if (fde1->end == 0)
+    {
+      if (fde1->start < fde2->start)
+	return -1;
+      if (fde1->start >= fde2->end)
+	return 1;
+    }
+  else
+    {
+      if (fde2->start < fde1->start)
+	return 1;
+      if (fde2->start >= fde1->end)
+	return -1;
+    }
+
+  return 0;
+}
+
+static struct dwarf_fde *
+intern_fde (Dwarf_CFI *cache, const Dwarf_FDE *entry)
+{
+  /* Look up the new entry's CIE.  */
+  struct dwarf_cie *cie = __libdw_find_cie (cache, entry->CIE_pointer);
+  if (cie == NULL)
+    return (void *) -1l;
+
+  struct dwarf_fde *fde = malloc (sizeof (struct dwarf_fde));
+  if (fde == NULL)
+    {
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  fde->instructions = entry->start;
+  fde->instructions_end = entry->end;
+  if (unlikely (read_encoded_value (cache, cie->fde_encoding,
+				    &fde->instructions, &fde->start))
+      || unlikely (read_encoded_value (cache, cie->fde_encoding & 0x0f,
+				       &fde->instructions, &fde->end)))
+    {
+      free (fde);
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+  fde->end += fde->start;
+
+  /* Make sure the fde actually covers a real code range.  */
+  if (fde->start >= fde->end)
+    {
+      free (fde);
+      return (void *) -1;
+    }
+
+  fde->cie = cie;
+
+  if (cie->sized_augmentation_data)
+    {
+      /* The CIE augmentation says the FDE has a DW_FORM_block
+	 before its actual instruction stream.  */
+      Dwarf_Word len;
+      if (fde->instructions >= fde->instructions_end)
+	goto invalid;
+      get_uleb128 (len, fde->instructions, fde->instructions_end);
+      if ((Dwarf_Word) (fde->instructions_end - fde->instructions) < len)
+	{
+	invalid:
+	  free (fde);
+	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	  return NULL;
+	}
+      fde->instructions += len;
+    }
+  else
+    /* We had to understand all of the CIE augmentation string.
+       We've recorded the number of data bytes in FDEs.  */
+    fde->instructions += cie->fde_augmentation_data_size;
+
+  /* Add the new entry to the search tree.  */
+  struct dwarf_fde **tres = tsearch (fde, &cache->fde_tree, &compare_fde);
+  if (tres == NULL)
+    {
+      free (fde);
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+  else if (*tres != fde)
+    {
+      /* There is already an FDE in the cache that covers the same
+	 address range.  That is odd.  Ignore this FDE.  And just use
+	 the one in the cache for consistency.  */
+      free (fde);
+      return *tres;
+    }
+
+  return fde;
+}
+
+struct dwarf_fde *
+internal_function
+__libdw_fde_by_offset (Dwarf_CFI *cache, Dwarf_Off offset)
+{
+  Dwarf_CFI_Entry entry;
+  Dwarf_Off next_offset;
+  int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
+				       &cache->data->d, CFI_IS_EH (cache),
+				       offset, &next_offset, &entry);
+  if (result != 0)
+    {
+      if (result > 0)
+      invalid:
+	__libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  if (unlikely (dwarf_cfi_cie_p (&entry)))
+    goto invalid;
+
+  /* We have a new FDE to consider.  */
+  struct dwarf_fde *fde = intern_fde (cache, &entry.fde);
+  if (fde == (void *) -1l || fde == NULL)
+    return NULL;
+
+  /* If this happened to be what we would have read next, notice it.  */
+  if (cache->next_offset == offset)
+    cache->next_offset = next_offset;
+
+  return fde;
+}
+
+/* Use a binary search table in .eh_frame_hdr format, yield an FDE offset.  */
+static Dwarf_Off
+binary_search_fde (Dwarf_CFI *cache, Dwarf_Addr address)
+{
+  const size_t size = 2 * encoded_value_size (&cache->data->d, cache->e_ident,
+					      cache->search_table_encoding,
+					      NULL);
+  if (unlikely (size == 0))
+    return (Dwarf_Off) -1l;
+
+  /* Dummy used by read_encoded_value.  */
+  Elf_Data_Scn dummy_cfi_hdr_data =
+    {
+      .d = { .d_buf = (void *) cache->search_table,
+	     .d_size = cache->search_table_len }
+    };
+
+  Dwarf_CFI dummy_cfi =
+    {
+      .e_ident = cache->e_ident,
+      .datarel = cache->search_table_vaddr,
+      .frame_vaddr = cache->search_table_vaddr,
+      .data = &dummy_cfi_hdr_data
+    };
+
+  size_t l = 0, u = cache->search_table_entries;
+  while (l < u)
+    {
+      size_t idx = (l + u) / 2;
+
+      /* Max idx * size is checked against search_table len when
+	 loading eh_frame_hdr.  */
+      const uint8_t *p = &cache->search_table[idx * size];
+      Dwarf_Addr start;
+      if (unlikely (read_encoded_value (&dummy_cfi,
+					cache->search_table_encoding, &p,
+					&start)))
+	break;
+      if (address < start)
+	u = idx;
+      else
+	{
+	  l = idx + 1;
+
+	  Dwarf_Addr fde;
+	  if (unlikely (read_encoded_value (&dummy_cfi,
+					    cache->search_table_encoding, &p,
+					    &fde)))
+	    break;
+
+	  /* If this is the last entry, its upper bound is assumed to be
+	     the end of the module.
+	     XXX really should be end of containing PT_LOAD segment */
+	  if (l < cache->search_table_entries)
+	    {
+	      /* Look at the start address in the following entry.  */
+	      Dwarf_Addr end;
+	      if (unlikely (read_encoded_value
+			    (&dummy_cfi, cache->search_table_encoding, &p,
+			     &end)))
+		break;
+	      if (address >= end)
+		continue;
+	    }
+
+	  return fde - cache->frame_vaddr;
+	}
+    }
+
+  return (Dwarf_Off) -1l;
+}
+
+struct dwarf_fde *
+internal_function
+__libdw_find_fde (Dwarf_CFI *cache, Dwarf_Addr address)
+{
+  /* Look for a cached FDE covering this address.  */
+
+  const struct dwarf_fde fde_key = { .start = address, .end = 0 };
+  struct dwarf_fde **found = tfind (&fde_key, &cache->fde_tree, &compare_fde);
+  if (found != NULL)
+    return *found;
+
+  /* Use .eh_frame_hdr binary search table if possible.  */
+  if (cache->search_table != NULL)
+    {
+      Dwarf_Off offset = binary_search_fde (cache, address);
+      if (offset == (Dwarf_Off) -1l)
+	goto no_match;
+      struct dwarf_fde *fde = __libdw_fde_by_offset (cache, offset);
+      if (likely (fde != NULL))
+	{
+	  /* Sanity check the address range.  */
+	  if (unlikely (address < fde->start))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return NULL;
+	    }
+	  /* .eh_frame_hdr does not indicate length covered by FDE.  */
+	  if (unlikely (address >= fde->end))
+	    goto no_match;
+	}
+      return fde;
+    }
+
+  /* It's not there.  Read more CFI entries until we find it.  */
+  while (1)
+    {
+      Dwarf_Off last_offset = cache->next_offset;
+      Dwarf_CFI_Entry entry;
+      int result = INTUSE(dwarf_next_cfi) (cache->e_ident,
+					   &cache->data->d, CFI_IS_EH (cache),
+					   last_offset, &cache->next_offset,
+					   &entry);
+      if (result > 0)
+	break;
+      if (result < 0)
+	{
+	  if (cache->next_offset == last_offset)
+	    /* We couldn't progress past the bogus FDE.  */
+	    break;
+	  /* Skip the loser and look at the next entry.  */
+	  continue;
+	}
+
+      if (dwarf_cfi_cie_p (&entry))
+	{
+	  /* This is a CIE, not an FDE.  We eagerly intern these
+	     because the next FDE will usually refer to this CIE.  */
+	  __libdw_intern_cie (cache, last_offset, &entry.cie);
+	  continue;
+	}
+
+      /* We have a new FDE to consider.  */
+      struct dwarf_fde *fde = intern_fde (cache, &entry.fde);
+
+      if (fde == (void *) -1l)	/* Bad FDE, but we can keep looking.  */
+	continue;
+
+      if (fde == NULL)		/* Bad data.  */
+	return NULL;
+
+      /* Is this the one we're looking for?  */
+      if (fde->start <= address && fde->end > address)
+	return fde;
+    }
+
+ no_match:
+  /* We found no FDE covering this address.  */
+  __libdw_seterrno (DWARF_E_NO_MATCH);
+  return NULL;
+}
diff --git a/libdw/frame-cache.c b/libdw/frame-cache.c
new file mode 100644
index 0000000..683f7f1
--- /dev/null
+++ b/libdw/frame-cache.c
@@ -0,0 +1,70 @@
+/* Frame cache handling.
+   Copyright (C) 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libebl.h"
+#include "cfi.h"
+#include <search.h>
+#include <stdlib.h>
+
+
+static void
+free_cie (void *arg)
+{
+  struct dwarf_cie *cie = arg;
+
+  free ((Dwarf_Frame *) cie->initial_state);
+  free (cie);
+}
+
+#define free_fde	free
+
+static void
+free_expr (void *arg)
+{
+  struct loc_s *loc = arg;
+
+  free (loc->loc);
+  free (loc);
+}
+
+void
+internal_function
+__libdw_destroy_frame_cache (Dwarf_CFI *cache)
+{
+  /* Most of the data is in our two search trees.  */
+  tdestroy (cache->fde_tree, free_fde);
+  tdestroy (cache->cie_tree, free_cie);
+  tdestroy (cache->expr_tree, free_expr);
+
+  if (cache->ebl != NULL && cache->ebl != (void *) -1l)
+    ebl_closebackend (cache->ebl);
+}
diff --git a/libdw/libdw.h b/libdw/libdw.h
new file mode 100644
index 0000000..d53dc78
--- /dev/null
+++ b/libdw/libdw.h
@@ -0,0 +1,1147 @@
+/* Interfaces for libdw.
+   Copyright (C) 2002-2010, 2013, 2014, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBDW_H
+#define _LIBDW_H	1
+
+#include <gelf.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+/* Mode for the session.  */
+typedef enum
+  {
+    DWARF_C_READ,		/* Read .. */
+    DWARF_C_RDWR,		/* Read and write .. */
+    DWARF_C_WRITE,		/* Write .. */
+  }
+Dwarf_Cmd;
+
+
+/* Callback results.  */
+enum
+{
+  DWARF_CB_OK = 0,
+  DWARF_CB_ABORT
+};
+
+
+/* Error values.  */
+enum
+  {
+    DW_TAG_invalid = 0
+#define DW_TAG_invalid	DW_TAG_invalid
+  };
+
+
+/* Type for offset in DWARF file.  */
+typedef GElf_Off Dwarf_Off;
+
+/* Type for address in DWARF file.  */
+typedef GElf_Addr Dwarf_Addr;
+
+/* Integer types.  Big enough to hold any numeric value.  */
+typedef GElf_Xword Dwarf_Word;
+typedef GElf_Sxword Dwarf_Sword;
+/* For the times we know we do not need that much.  */
+typedef GElf_Half Dwarf_Half;
+
+
+/* DWARF abbreviation record.  */
+typedef struct Dwarf_Abbrev Dwarf_Abbrev;
+
+/* Returned to show the last DIE has be returned.  */
+#define DWARF_END_ABBREV ((Dwarf_Abbrev *) -1l)
+
+/* Source code line information for CU.  */
+typedef struct Dwarf_Lines_s Dwarf_Lines;
+
+/* One source code line information.  */
+typedef struct Dwarf_Line_s Dwarf_Line;
+
+/* Source file information.  */
+typedef struct Dwarf_Files_s Dwarf_Files;
+
+/* One address range record.  */
+typedef struct Dwarf_Arange_s Dwarf_Arange;
+
+/* Address ranges of a file.  */
+typedef struct Dwarf_Aranges_s Dwarf_Aranges;
+
+/* CU representation.  */
+struct Dwarf_CU;
+typedef struct Dwarf_CU Dwarf_CU;
+
+/* Macro information.  */
+typedef struct Dwarf_Macro_s Dwarf_Macro;
+
+/* Attribute representation.  */
+typedef struct
+{
+  unsigned int code;
+  unsigned int form;
+  unsigned char *valp;
+  struct Dwarf_CU *cu;
+} Dwarf_Attribute;
+
+
+/* Data block representation.  */
+typedef struct
+{
+  Dwarf_Word length;
+  unsigned char *data;
+} Dwarf_Block;
+
+
+/* DIE information.  */
+typedef struct
+{
+  /* The offset can be computed from the address.  */
+  void *addr;
+  struct Dwarf_CU *cu;
+  Dwarf_Abbrev *abbrev;
+  // XXX We'll see what other information will be needed.
+  long int padding__;
+} Dwarf_Die;
+
+/* Returned to show the last DIE has be returned.  */
+#define DWARF_END_DIE ((Dwarf_Die *) -1l)
+
+
+/* Global symbol information.  */
+typedef struct
+{
+  Dwarf_Off cu_offset;
+  Dwarf_Off die_offset;
+  const char *name;
+} Dwarf_Global;
+
+
+/* One operation in a DWARF location expression.
+   A location expression is an array of these.  */
+typedef struct
+{
+  uint8_t atom;			/* Operation */
+  Dwarf_Word number;		/* Operand */
+  Dwarf_Word number2;		/* Possible second operand */
+  Dwarf_Word offset;		/* Offset in location expression */
+} Dwarf_Op;
+
+
+/* This describes one Common Information Entry read from a CFI section.
+   Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi.  */
+typedef struct
+{
+  Dwarf_Off CIE_id;	 /* Always DW_CIE_ID_64 in Dwarf_CIE structures.  */
+
+  /* Instruction stream describing initial state used by FDEs.  If
+     we did not understand the whole augmentation string and it did
+     not use 'z', then there might be more augmentation data here
+     (and in FDEs) before the actual instructions.  */
+  const uint8_t *initial_instructions;
+  const uint8_t *initial_instructions_end;
+
+  Dwarf_Word code_alignment_factor;
+  Dwarf_Sword data_alignment_factor;
+  Dwarf_Word return_address_register;
+
+  const char *augmentation;	/* Augmentation string.  */
+
+  /* Augmentation data, might be NULL.  The size is correct only if
+     we understood the augmentation string sufficiently.  */
+  const uint8_t *augmentation_data;
+  size_t augmentation_data_size;
+  size_t fde_augmentation_data_size;
+} Dwarf_CIE;
+
+/* This describes one Frame Description Entry read from a CFI section.
+   Pointers here point into the DATA->d_buf block passed to dwarf_next_cfi.  */
+typedef struct
+{
+  /* Section offset of CIE this FDE refers to.  This will never be
+     DW_CIE_ID_64 in an FDE.  If this value is DW_CIE_ID_64, this is
+     actually a Dwarf_CIE structure.  */
+  Dwarf_Off CIE_pointer;
+
+  /* We can't really decode anything further without looking up the CIE
+     and checking its augmentation string.  Here follows the encoded
+     initial_location and address_range, then any augmentation data,
+     then the instruction stream.  This FDE describes PC locations in
+     the byte range [initial_location, initial_location+address_range).
+     When the CIE augmentation string uses 'z', the augmentation data is
+     a DW_FORM_block (self-sized).  Otherwise, when we understand the
+     augmentation string completely, fde_augmentation_data_size gives
+     the number of bytes of augmentation data before the instructions.  */
+  const uint8_t *start;
+  const uint8_t *end;
+} Dwarf_FDE;
+
+/* Each entry in a CFI section is either a CIE described by Dwarf_CIE or
+   an FDE described by Dward_FDE.  Check CIE_id to see which you have.  */
+typedef union
+{
+  Dwarf_Off CIE_id;	 /* Always DW_CIE_ID_64 in Dwarf_CIE structures.  */
+  Dwarf_CIE cie;
+  Dwarf_FDE fde;
+} Dwarf_CFI_Entry;
+
+/* Same as DW_CIE_ID_64 from dwarf.h to keep libdw.h independent.  */
+#define LIBDW_CIE_ID 0xffffffffffffffffULL
+#define dwarf_cfi_cie_p(entry)	((entry)->cie.CIE_id == LIBDW_CIE_ID)
+
+/* Opaque type representing a frame state described by CFI.  */
+typedef struct Dwarf_Frame_s Dwarf_Frame;
+
+/* Opaque type representing a CFI section found in a DWARF or ELF file.  */
+typedef struct Dwarf_CFI_s Dwarf_CFI;
+
+
+/* Handle for debug sessions.  */
+typedef struct Dwarf Dwarf;
+
+
+/* Out-Of-Memory handler.  */
+typedef void (*__noreturn_attribute__ Dwarf_OOM) (void);
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Create a handle for a new debug session.  */
+extern Dwarf *dwarf_begin (int fildes, Dwarf_Cmd cmd);
+
+/* Create a handle for a new debug session for an ELF file.  */
+extern Dwarf *dwarf_begin_elf (Elf *elf, Dwarf_Cmd cmd, Elf_Scn *scngrp);
+
+/* Retrieve ELF descriptor used for DWARF access.  */
+extern Elf *dwarf_getelf (Dwarf *dwarf);
+
+/* Retrieve DWARF descriptor used for a Dwarf_Die or Dwarf_Attribute.
+   A Dwarf_Die or a Dwarf_Attribute is associated with a particular
+   Dwarf_CU handle.  This function returns the DWARF descriptor for
+   that Dwarf_CU.  */
+extern Dwarf *dwarf_cu_getdwarf (Dwarf_CU *cu);
+
+/* Retrieves the DWARF descriptor for debugaltlink data.  Returns NULL
+   if no alternate debug data has been supplied yet.  libdw will try
+   to set the alt file on first use of an alt FORM if not yet explicitly
+   provided by dwarf_setalt.  */
+extern Dwarf *dwarf_getalt (Dwarf *main);
+
+/* Provides the data referenced by the .gnu_debugaltlink section.  The
+   caller should check that MAIN and ALT match (i.e., they have the
+   same build ID).  It is the responsibility of the caller to ensure
+   that the data referenced by ALT stays valid while it is used by
+   MAIN, until dwarf_setalt is called on MAIN with a different
+   descriptor, or dwarf_end.  Must be called before inspecting DIEs
+   that might have alt FORMs.  Otherwise libdw will try to set the
+   alt file itself on first use.  */
+extern void dwarf_setalt (Dwarf *main, Dwarf *alt);
+
+/* Release debugging handling context.  */
+extern int dwarf_end (Dwarf *dwarf);
+
+
+/* Read the header for the DWARF CU.  */
+extern int dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
+			 size_t *header_sizep, Dwarf_Off *abbrev_offsetp,
+			 uint8_t *address_sizep, uint8_t *offset_sizep)
+     __nonnull_attribute__ (3);
+
+/* Read the header of a DWARF CU or type unit.  If TYPE_SIGNATUREP is not
+   null, this reads a type unit from the .debug_types section; otherwise
+   this reads a CU from the .debug_info section.  */
+extern int dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
+			    size_t *header_sizep, Dwarf_Half *versionp,
+			    Dwarf_Off *abbrev_offsetp,
+			    uint8_t *address_sizep, uint8_t *offset_sizep,
+			    uint64_t *type_signaturep, Dwarf_Off *type_offsetp)
+     __nonnull_attribute__ (3);
+
+
+/* Gets the next Dwarf_CU (unit), version, unit type and if available
+   the CU DIE and sub (type) DIE of the unit.  Returns 0 on success,
+   -1 on error or 1 if there are no more units.  To start iterating
+   provide NULL for CU.  If version < 5 the unit type is set from the
+   CU DIE if available (DW_UT_compile for DW_TAG_compile_unit,
+   DW_UT_type for DW_TAG_type_unit or DW_UT_partial for
+   DW_TAG_partial_unit), otherwise it is set to zero.  If unavailable
+   (the version or unit type is unknown) the CU DIE is cleared.
+   Likewise if the sub DIE isn't isn't available (the unit type is not
+   DW_UT_type or DW_UT_split_type) the sub DIE tag is cleared.  */
+extern int dwarf_get_units (Dwarf *dwarf, Dwarf_CU *cu, Dwarf_CU **next_cu,
+			    Dwarf_Half *version, uint8_t *unit_type,
+			    Dwarf_Die *cudie, Dwarf_Die *subdie)
+     __nonnull_attribute__ (3);
+
+/* Provides information and DIEs associated with the given Dwarf_CU
+   unit.  Returns -1 on error, zero on success. Arguments not needed
+   may be NULL.  If they are NULL and aren't known yet, they won't be
+   looked up.  If the subdie doesn't exist for this unit_type it will
+   be cleared.  If there is no unit_id for this unit type it will be
+   set to zero.  */
+extern int dwarf_cu_info (Dwarf_CU *cu,
+			  Dwarf_Half *version, uint8_t *unit_type,
+			  Dwarf_Die *cudie, Dwarf_Die *subdie,
+			  uint64_t *unit_id,
+			  uint8_t *address_size, uint8_t *offset_size);
+
+/* Decode one DWARF CFI entry (CIE or FDE) from the raw section data.
+   The E_IDENT from the originating ELF file indicates the address
+   size and byte order used in the CFI section contained in DATA;
+   EH_FRAME_P should be true for .eh_frame format and false for
+   .debug_frame format.  OFFSET is the byte position in the section
+   to start at; on return *NEXT_OFFSET is filled in with the byte
+   position immediately after this entry.
+
+   On success, returns 0 and fills in *ENTRY; use dwarf_cfi_cie_p to
+   see whether ENTRY->cie or ENTRY->fde is valid.
+
+   On errors, returns -1.  Some format errors will permit safely
+   skipping to the next CFI entry though the current one is unusable.
+   In that case, *NEXT_OFF will be updated before a -1 return.
+
+   If there are no more CFI entries left in the section,
+   returns 1 and sets *NEXT_OFFSET to (Dwarf_Off) -1.  */
+extern int dwarf_next_cfi (const unsigned char e_ident[],
+			   Elf_Data *data, bool eh_frame_p,
+			   Dwarf_Off offset, Dwarf_Off *next_offset,
+			   Dwarf_CFI_Entry *entry)
+  __nonnull_attribute__ (1, 2, 5, 6);
+
+/* Use the CFI in the DWARF .debug_frame section.
+   Returns NULL if there is no such section (not an error).
+   The pointer returned can be used until dwarf_end is called on DWARF,
+   and must not be passed to dwarf_cfi_end.
+   Calling this more than once returns the same pointer.  */
+extern Dwarf_CFI *dwarf_getcfi (Dwarf *dwarf);
+
+/* Use the CFI in the ELF file's exception-handling data.
+   Returns NULL if there is no such data.
+   The pointer returned can be used until elf_end is called on ELF,
+   and must be passed to dwarf_cfi_end before then.
+   Calling this more than once allocates independent data structures.  */
+extern Dwarf_CFI *dwarf_getcfi_elf (Elf *elf);
+
+/* Release resources allocated by dwarf_getcfi_elf.  */
+extern int dwarf_cfi_end (Dwarf_CFI *cache);
+
+
+/* Return DIE at given offset in .debug_info section.  */
+extern Dwarf_Die *dwarf_offdie (Dwarf *dbg, Dwarf_Off offset,
+				Dwarf_Die *result) __nonnull_attribute__ (3);
+
+/* Return DIE at given offset in .debug_types section.  */
+extern Dwarf_Die *dwarf_offdie_types (Dwarf *dbg, Dwarf_Off offset,
+				      Dwarf_Die *result)
+     __nonnull_attribute__ (3);
+
+/* Return offset of DIE.  */
+extern Dwarf_Off dwarf_dieoffset (Dwarf_Die *die);
+
+/* Return offset of DIE in CU.  */
+extern Dwarf_Off dwarf_cuoffset (Dwarf_Die *die);
+
+/* Return CU DIE containing given DIE.  */
+extern Dwarf_Die *dwarf_diecu (Dwarf_Die *die, Dwarf_Die *result,
+			       uint8_t *address_sizep, uint8_t *offset_sizep)
+     __nonnull_attribute__ (2);
+
+/* Given a Dwarf_Die addr returns a (reconstructed) Dwarf_Die, or NULL
+   if the given addr didn't come from a valid Dwarf_Die.  In particular
+   it will make sure that the correct Dwarf_CU pointer is set for the
+   Dwarf_Die, the Dwarf_Abbrev pointer will not be set up yet (it will
+   only be once the Dwarf_Die is used to read attributes, children or
+   siblings).  This functions can be used to keep a reference to a
+   Dwarf_Die which you want to refer to later.  The addr, and the result
+   of this function, is only valid while the associated Dwarf is valid.  */
+extern Dwarf_Die *dwarf_die_addr_die (Dwarf *dbg, void *addr,
+				      Dwarf_Die *result)
+     __nonnull_attribute__ (3);
+
+/* Return the CU DIE and the header info associated with a Dwarf_Die
+   or Dwarf_Attribute.  A Dwarf_Die or a Dwarf_Attribute is associated
+   with a particular Dwarf_CU handle.  This function returns the CU or
+   type unit DIE and header information for that Dwarf_CU.  The
+   returned DIE is either a compile_unit, partial_unit or type_unit.
+   If it is a type_unit, then the type signature and type offset are
+   also provided, otherwise type_offset will be set to zero.  See also
+   dwarf_diecu and dwarf_next_unit.  */
+extern Dwarf_Die *dwarf_cu_die (Dwarf_CU *cu, Dwarf_Die *result,
+				Dwarf_Half *versionp,
+				Dwarf_Off *abbrev_offsetp,
+				uint8_t *address_sizep,
+				uint8_t *offset_sizep,
+				uint64_t *type_signaturep,
+				Dwarf_Off *type_offsetp)
+     __nonnull_attribute__ (2);
+
+/* Return CU DIE containing given address.  */
+extern Dwarf_Die *dwarf_addrdie (Dwarf *dbg, Dwarf_Addr addr,
+				 Dwarf_Die *result) __nonnull_attribute__ (3);
+
+/* Return child of current DIE.  */
+extern int dwarf_child (Dwarf_Die *die, Dwarf_Die *result)
+     __nonnull_attribute__ (2);
+
+/* Locates the first sibling of DIE and places it in RESULT.
+   Returns 0 if a sibling was found, -1 if something went wrong.
+   Returns 1 if no sibling could be found and, if RESULT is not
+   the same as DIE, it sets RESULT->addr to the address of the
+   (non-sibling) DIE that follows this one, or NULL if this DIE
+   was the last one in the compilation unit.  */
+extern int dwarf_siblingof (Dwarf_Die *die, Dwarf_Die *result)
+     __nonnull_attribute__ (2);
+
+/* For type aliases and qualifier type DIEs, which don't modify or
+   change the structural layout of the underlying type, follow the
+   DW_AT_type attribute (recursively) and return the underlying type
+   Dwarf_Die.
+
+   Returns 0 when RESULT contains a Dwarf_Die (possibly equal to the
+   given DIE) that isn't a type alias or qualifier type.  Returns 1
+   when RESULT contains a type alias or qualifier Dwarf_Die that
+   couldn't be peeled further (it doesn't have a DW_TAG_type
+   attribute).  Returns -1 when an error occurred.
+
+   The current DWARF specification defines one type alias tag
+   (DW_TAG_typedef) and seven modifier/qualifier type tags
+   (DW_TAG_const_type, DW_TAG_volatile_type, DW_TAG_restrict_type,
+   DW_TAG_atomic_type, DW_TAG_immutable_type, DW_TAG_packed_type and
+   DW_TAG_shared_type).  This function won't peel modifier type
+   tags that change the way the underlying type is accessed such
+   as the pointer or reference type tags (DW_TAG_pointer_type,
+   DW_TAG_reference_type or DW_TAG_rvalue_reference_type).
+
+   A future version of this function might peel other alias or
+   qualifier type tags if a future DWARF version or GNU extension
+   defines other type aliases or qualifier type tags that don't modify,
+   change the structural layout or the way to access the underlying type.  */
+extern int dwarf_peel_type (Dwarf_Die *die, Dwarf_Die *result)
+    __nonnull_attribute__ (2);
+
+/* Check whether the DIE has children.  */
+extern int dwarf_haschildren (Dwarf_Die *die) __nonnull_attribute__ (1);
+
+/* Walks the attributes of DIE, starting at the one OFFSET bytes in,
+   calling the CALLBACK function for each one.  Stops if the callback
+   function ever returns a value other than DWARF_CB_OK and returns the
+   offset of the offending attribute.  If the end of the attributes
+   is reached 1 is returned.  If something goes wrong -1 is returned and
+   the dwarf error number is set.  */
+extern ptrdiff_t dwarf_getattrs (Dwarf_Die *die,
+				 int (*callback) (Dwarf_Attribute *, void *),
+				 void *arg, ptrdiff_t offset)
+     __nonnull_attribute__ (2);
+
+/* Return tag of given DIE.  */
+extern int dwarf_tag (Dwarf_Die *die) __nonnull_attribute__ (1);
+
+
+/* Return specific attribute of DIE.  */
+extern Dwarf_Attribute *dwarf_attr (Dwarf_Die *die, unsigned int search_name,
+				    Dwarf_Attribute *result)
+     __nonnull_attribute__ (3);
+
+/* Check whether given DIE has specific attribute.  */
+extern int dwarf_hasattr (Dwarf_Die *die, unsigned int search_name);
+
+/* These are the same as dwarf_attr and dwarf_hasattr, respectively,
+   but they resolve an indirect attribute through
+   DW_AT_abstract_origin, DW_AT_specification or, if the DIE is a
+   top-level split CU, the skeleton DIE.  Note that the attribute
+   might come from a DIE in a different CU (possibly from a different
+   Dwarf file).  In that case all attribute information needs to be
+   resolved through the CU associated with the returned
+   Dwarf_Attribute.  The dwarf_form functions already do this
+   automatically.  */
+extern Dwarf_Attribute *dwarf_attr_integrate (Dwarf_Die *die,
+					      unsigned int search_name,
+					      Dwarf_Attribute *result)
+     __nonnull_attribute__ (3);
+extern int dwarf_hasattr_integrate (Dwarf_Die *die, unsigned int search_name);
+
+
+
+
+/* Check whether given attribute has specific form.  */
+extern int dwarf_hasform (Dwarf_Attribute *attr, unsigned int search_form);
+
+/* Return attribute code of given attribute.  */
+extern unsigned int dwarf_whatattr (Dwarf_Attribute *attr);
+
+/* Return form code of given attribute.  */
+extern unsigned int dwarf_whatform (Dwarf_Attribute *attr);
+
+
+/* Return string associated with given attribute.  */
+extern const char *dwarf_formstring (Dwarf_Attribute *attrp);
+
+/* Return unsigned constant represented by attribute.  */
+extern int dwarf_formudata (Dwarf_Attribute *attr, Dwarf_Word *return_uval)
+     __nonnull_attribute__ (2);
+
+/* Return signed constant represented by attribute.  */
+extern int dwarf_formsdata (Dwarf_Attribute *attr, Dwarf_Sword *return_uval)
+     __nonnull_attribute__ (2);
+
+/* Return address represented by attribute.  */
+extern int dwarf_formaddr (Dwarf_Attribute *attr, Dwarf_Addr *return_addr)
+     __nonnull_attribute__ (2);
+
+/* This function is deprecated.  Always use dwarf_formref_die instead.
+   Return reference offset represented by attribute.  */
+extern int dwarf_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
+     __nonnull_attribute__ (2) __deprecated_attribute__;
+
+/* Look up the DIE in a reference-form attribute.  */
+extern Dwarf_Die *dwarf_formref_die (Dwarf_Attribute *attr, Dwarf_Die *die_mem)
+     __nonnull_attribute__ (2);
+
+/* Return block represented by attribute.  */
+extern int dwarf_formblock (Dwarf_Attribute *attr, Dwarf_Block *return_block)
+     __nonnull_attribute__ (2);
+
+/* Return flag represented by attribute.  */
+extern int dwarf_formflag (Dwarf_Attribute *attr, bool *return_bool)
+     __nonnull_attribute__ (2);
+
+
+/* Simplified attribute value access functions.  */
+
+/* Return string in name attribute of DIE.  */
+extern const char *dwarf_diename (Dwarf_Die *die);
+
+/* Return high PC attribute of DIE.  */
+extern int dwarf_highpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+     __nonnull_attribute__ (2);
+
+/* Return low PC attribute of DIE.  */
+extern int dwarf_lowpc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+     __nonnull_attribute__ (2);
+
+/* Return entry_pc or low_pc attribute of DIE.  */
+extern int dwarf_entrypc (Dwarf_Die *die, Dwarf_Addr *return_addr)
+     __nonnull_attribute__ (2);
+
+/* Return 1 if DIE's lowpc/highpc or ranges attributes match the PC address,
+   0 if not, or -1 for errors.  */
+extern int dwarf_haspc (Dwarf_Die *die, Dwarf_Addr pc);
+
+/* Enumerate the PC address ranges covered by this DIE, covering all
+   addresses where dwarf_haspc returns true.  In the first call OFFSET
+   should be zero and *BASEP need not be initialized.  Returns -1 for
+   errors, zero when there are no more address ranges to report, or a
+   nonzero OFFSET value to pass to the next call.  Each subsequent call
+   must preserve *BASEP from the prior call.  Successful calls fill in
+   *STARTP and *ENDP with a contiguous address range.  */
+extern ptrdiff_t dwarf_ranges (Dwarf_Die *die,
+			       ptrdiff_t offset, Dwarf_Addr *basep,
+			       Dwarf_Addr *startp, Dwarf_Addr *endp);
+
+
+/* Return byte size attribute of DIE.  */
+extern int dwarf_bytesize (Dwarf_Die *die);
+
+/* Return bit size attribute of DIE.  */
+extern int dwarf_bitsize (Dwarf_Die *die);
+
+/* Return bit offset attribute of DIE.  */
+extern int dwarf_bitoffset (Dwarf_Die *die);
+
+/* Return array order attribute of DIE.  */
+extern int dwarf_arrayorder (Dwarf_Die *die);
+
+/* Return source language attribute of DIE.  */
+extern int dwarf_srclang (Dwarf_Die *die);
+
+
+/* Get abbreviation at given offset for given DIE.  */
+extern Dwarf_Abbrev *dwarf_getabbrev (Dwarf_Die *die, Dwarf_Off offset,
+				      size_t *lengthp);
+
+/* Get abbreviation at given offset in .debug_abbrev section.  */
+extern int dwarf_offabbrev (Dwarf *dbg, Dwarf_Off offset, size_t *lengthp,
+			    Dwarf_Abbrev *abbrevp)
+     __nonnull_attribute__ (4);
+
+/* Get abbreviation code.  */
+extern unsigned int dwarf_getabbrevcode (Dwarf_Abbrev *abbrev);
+
+/* Get abbreviation tag.  */
+extern unsigned int dwarf_getabbrevtag (Dwarf_Abbrev *abbrev);
+
+/* Return true if abbreviation is children flag set.  */
+extern int dwarf_abbrevhaschildren (Dwarf_Abbrev *abbrev);
+
+/* Get number of attributes of abbreviation.  */
+extern int dwarf_getattrcnt (Dwarf_Abbrev *abbrev, size_t *attrcntp)
+     __nonnull_attribute__ (2);
+
+/* Get specific attribute of abbreviation.  */
+extern int dwarf_getabbrevattr (Dwarf_Abbrev *abbrev, size_t idx,
+				unsigned int *namep, unsigned int *formp,
+				Dwarf_Off *offset);
+
+/* Get specific attribute of abbreviation and any data encoded with it.
+   Specifically for DW_FORM_implicit_const data will be set to the
+   constant value associated.  */
+extern int dwarf_getabbrevattr_data (Dwarf_Abbrev *abbrev, size_t idx,
+				     unsigned int *namep, unsigned int *formp,
+				     Dwarf_Sword *datap, Dwarf_Off *offset);
+
+/* Get string from-debug_str section.  */
+extern const char *dwarf_getstring (Dwarf *dbg, Dwarf_Off offset,
+				    size_t *lenp);
+
+
+/* Get public symbol information.  */
+extern ptrdiff_t dwarf_getpubnames (Dwarf *dbg,
+				    int (*callback) (Dwarf *, Dwarf_Global *,
+						     void *),
+				    void *arg, ptrdiff_t offset)
+     __nonnull_attribute__ (2);
+
+
+/* Get source file information for CU.  */
+extern int dwarf_getsrclines (Dwarf_Die *cudie, Dwarf_Lines **lines,
+			      size_t *nlines) __nonnull_attribute__ (2, 3);
+
+/* Return one of the source lines of the CU.  */
+extern Dwarf_Line *dwarf_onesrcline (Dwarf_Lines *lines, size_t idx);
+
+/* Get the file source files used in the CU.  */
+extern int dwarf_getsrcfiles (Dwarf_Die *cudie, Dwarf_Files **files,
+			      size_t *nfiles)
+     __nonnull_attribute__ (2);
+
+
+/* Get source for address in CU.  */
+extern Dwarf_Line *dwarf_getsrc_die (Dwarf_Die *cudie, Dwarf_Addr addr);
+
+/* Get source for file and line number.  */
+extern int dwarf_getsrc_file (Dwarf *dbg, const char *fname, int line, int col,
+			      Dwarf_Line ***srcsp, size_t *nsrcs)
+     __nonnull_attribute__ (2, 5, 6);
+
+
+/* Return line address.  */
+extern int dwarf_lineaddr (Dwarf_Line *line, Dwarf_Addr *addrp);
+
+/* Return line VLIW operation index.  */
+extern int dwarf_lineop_index (Dwarf_Line *line, unsigned int *op_indexp);
+
+/* Return line number.  */
+extern int dwarf_lineno (Dwarf_Line *line, int *linep)
+     __nonnull_attribute__ (2);
+
+/* Return column in line.  */
+extern int dwarf_linecol (Dwarf_Line *line, int *colp)
+     __nonnull_attribute__ (2);
+
+/* Return true if record is for beginning of a statement.  */
+extern int dwarf_linebeginstatement (Dwarf_Line *line, bool *flagp)
+     __nonnull_attribute__ (2);
+
+/* Return true if record is for end of sequence.  */
+extern int dwarf_lineendsequence (Dwarf_Line *line, bool *flagp)
+     __nonnull_attribute__ (2);
+
+/* Return true if record is for beginning of a basic block.  */
+extern int dwarf_lineblock (Dwarf_Line *line, bool *flagp)
+     __nonnull_attribute__ (2);
+
+/* Return true if record is for end of prologue.  */
+extern int dwarf_lineprologueend (Dwarf_Line *line, bool *flagp)
+     __nonnull_attribute__ (2);
+
+/* Return true if record is for beginning of epilogue.  */
+extern int dwarf_lineepiloguebegin (Dwarf_Line *line, bool *flagp)
+     __nonnull_attribute__ (2);
+
+/* Return instruction-set architecture in this record.  */
+extern int dwarf_lineisa (Dwarf_Line *line, unsigned int *isap)
+     __nonnull_attribute__ (2);
+
+/* Return code path discriminator in this record.  */
+extern int dwarf_linediscriminator (Dwarf_Line *line, unsigned int *discp)
+     __nonnull_attribute__ (2);
+
+
+/* Find line information for address.  The returned string is NULL when
+   an error occurred, or the file path.  The file path is either absolute
+   or relative to the compilation directory.  See dwarf_decl_file.  */
+extern const char *dwarf_linesrc (Dwarf_Line *line,
+				  Dwarf_Word *mtime, Dwarf_Word *length);
+
+/* Return the caller of this line if inlined.  If not inlined,
+   return NULL.  */
+extern Dwarf_Line *dwarf_linecontext (Dwarf_Lines *lines, Dwarf_Line *line);
+
+/* Return the function name in this line record. If this line is
+   inlined, this is the name of the function that was inlined. If this line
+   is not inlined, return NULL.  */
+extern const char *dwarf_linefunctionname (Dwarf *dbg, Dwarf_Line *line);
+
+/* Return file information.  The returned string is NULL when
+   an error occurred, or the file path.  The file path is either absolute
+   or relative to the compilation directory.  See dwarf_decl_file.  */
+extern const char *dwarf_filesrc (Dwarf_Files *file, size_t idx,
+				  Dwarf_Word *mtime, Dwarf_Word *length);
+
+/* Return the Dwarf_Files and index associated with the given Dwarf_Line.  */
+extern int dwarf_line_file (Dwarf_Line *line,
+			    Dwarf_Files **files, size_t *idx)
+    __nonnull_attribute__ (2, 3);
+
+/* Return the directory list used in the file information extracted.
+   (*RESULT)[0] is the CU's DW_AT_comp_dir value, and may be null.
+   (*RESULT)[0..*NDIRS-1] are the compile-time include directory path
+   encoded by the compiler.  */
+extern int dwarf_getsrcdirs (Dwarf_Files *files,
+			     const char *const **result, size_t *ndirs)
+  __nonnull_attribute__ (2, 3);
+
+/* Iterates through the debug line units.  Returns 0 on success, -1 on
+   error or 1 if there are no more units.  To start iterating use zero
+   for OFF and set *CU to NULL.  On success NEXT_OFF will be set to
+   the next offset to use.  The *CU will be set if this line table
+   needed a specific CU and needs to be given when calling
+   dwarf_next_lines again (to help dwarf_next_lines quickly find the
+   next CU).  *CU might be set to NULL when it couldn't be found (the
+   compilation directory entry will be the empty string in that case)
+   or for DWARF 5 or later tables, which are self contained.  SRCFILES
+   and SRCLINES may be NULL if the caller is not interested in the
+   actual line or file table.  On success and when not NULL, NFILES
+   and NLINES will be set to the number of files in the file table and
+   number of lines in the line table.  */
+extern int dwarf_next_lines (Dwarf *dwarf, Dwarf_Off off,
+			     Dwarf_Off *next_off, Dwarf_CU **cu,
+			     Dwarf_Files **srcfiles, size_t *nfiles,
+			     Dwarf_Lines **srclines, size_t *nlines)
+  __nonnull_attribute__ (3,4);
+
+/* Return location expression, decoded as a list of operations.  */
+extern int dwarf_getlocation (Dwarf_Attribute *attr, Dwarf_Op **expr,
+			      size_t *exprlen) __nonnull_attribute__ (2, 3);
+
+/* Return location expressions.  If the attribute uses a location list,
+   ADDRESS selects the relevant location expressions from the list.
+   There can be multiple matches, resulting in multiple expressions to
+   return.  EXPRS and EXPRLENS are parallel arrays of NLOCS slots to
+   fill in.  Returns the number of locations filled in, or -1 for
+   errors.  If EXPRS is a null pointer, stores nothing and returns the
+   total number of locations.  A return value of zero means that the
+   location list indicated no value is accessible.  */
+extern int dwarf_getlocation_addr (Dwarf_Attribute *attr, Dwarf_Addr address,
+				   Dwarf_Op **exprs, size_t *exprlens,
+				   size_t nlocs);
+
+/* Enumerate the locations ranges and descriptions covered by the
+   given attribute.  In the first call OFFSET should be zero and
+   *BASEP need not be initialized.  Returns -1 for errors, zero when
+   there are no more locations to report, or a nonzero OFFSET
+   value to pass to the next call.  Each subsequent call must preserve
+   *BASEP from the prior call.  Successful calls fill in *STARTP and
+   *ENDP with a contiguous address range and *EXPR with a pointer to
+   an array of operations with length *EXPRLEN.  If the attribute
+   describes a single location description and not a location list the
+   first call (with OFFSET zero) will return the location description
+   in *EXPR with *STARTP set to zero and *ENDP set to minus one.  */
+extern ptrdiff_t dwarf_getlocations (Dwarf_Attribute *attr,
+				     ptrdiff_t offset, Dwarf_Addr *basep,
+				     Dwarf_Addr *startp, Dwarf_Addr *endp,
+				     Dwarf_Op **expr, size_t *exprlen);
+
+/* Return the block associated with a DW_OP_implicit_value operation.
+   The OP pointer must point into an expression that dwarf_getlocation
+   or dwarf_getlocation_addr has returned given the same ATTR.  */
+extern int dwarf_getlocation_implicit_value (Dwarf_Attribute *attr,
+					     const Dwarf_Op *op,
+					     Dwarf_Block *return_block)
+  __nonnull_attribute__ (2, 3);
+
+/* Return the attribute indicated by a DW_OP_GNU_implicit_pointer operation.
+   The OP pointer must point into an expression that dwarf_getlocation
+   or dwarf_getlocation_addr has returned given the same ATTR.
+   The result is the DW_AT_location or DW_AT_const_value attribute
+   of the OP->number DIE.  */
+extern int dwarf_getlocation_implicit_pointer (Dwarf_Attribute *attr,
+					       const Dwarf_Op *op,
+					       Dwarf_Attribute *result)
+  __nonnull_attribute__ (2, 3);
+
+/* Return the DIE associated with an operation such as
+   DW_OP_GNU_implicit_pointer, DW_OP_GNU_parameter_ref, DW_OP_GNU_convert,
+   DW_OP_GNU_reinterpret, DW_OP_GNU_const_type, DW_OP_GNU_regval_type or
+   DW_OP_GNU_deref_type.  The OP pointer must point into an expression that
+   dwarf_getlocation or dwarf_getlocation_addr has returned given the same
+   ATTR.  The RESULT is a DIE that expresses a type or value needed by the
+   given OP.  */
+extern int dwarf_getlocation_die (Dwarf_Attribute *attr,
+				  const Dwarf_Op *op,
+				  Dwarf_Die *result)
+  __nonnull_attribute__ (2, 3);
+
+/* Return the attribute expressing a value associated with an operation such
+   as DW_OP_implicit_value, DW_OP_GNU_entry_value or DW_OP_GNU_const_type.
+   The OP pointer must point into an expression that dwarf_getlocation
+   or dwarf_getlocation_addr has returned given the same ATTR.
+   The RESULT is a value expressed by an attribute such as DW_AT_location
+   or DW_AT_const_value.  */
+extern int dwarf_getlocation_attr (Dwarf_Attribute *attr,
+				   const Dwarf_Op *op,
+				   Dwarf_Attribute *result)
+  __nonnull_attribute__ (2, 3);
+
+
+/* Compute the byte-size of a type DIE according to DWARF rules.
+   For most types, this is just DW_AT_byte_size.
+   For DW_TAG_array_type it can apply much more complex rules.  */
+extern int dwarf_aggregate_size (Dwarf_Die *die, Dwarf_Word *size);
+
+/* Given a language code, as returned by dwarf_srclan, get the default
+   lower bound for a subrange type without a lower bound attribute.
+   Returns zero on success or -1 on failure when the given language
+   wasn't recognized.  */
+extern int dwarf_default_lower_bound (int lang, Dwarf_Sword *result)
+  __nonnull_attribute__ (2);
+
+/* Return scope DIEs containing PC address.
+   Sets *SCOPES to a malloc'd array of Dwarf_Die structures,
+   and returns the number of elements in the array.
+   (*SCOPES)[0] is the DIE for the innermost scope containing PC,
+   (*SCOPES)[1] is the DIE for the scope containing that scope, and so on.
+   Returns -1 for errors or 0 if no scopes match PC.  */
+extern int dwarf_getscopes (Dwarf_Die *cudie, Dwarf_Addr pc,
+			    Dwarf_Die **scopes);
+
+/* Return scope DIEs containing the given DIE.
+   Sets *SCOPES to a malloc'd array of Dwarf_Die structures,
+   and returns the number of elements in the array.
+   (*SCOPES)[0] is a copy of DIE.
+   (*SCOPES)[1] is the DIE for the scope containing that scope, and so on.
+   Returns -1 for errors or 0 if DIE is not found in any scope entry.  */
+extern int dwarf_getscopes_die (Dwarf_Die *die, Dwarf_Die **scopes);
+
+
+/* Search SCOPES[0..NSCOPES-1] for a variable called NAME.
+   Ignore the first SKIP_SHADOWS scopes that match the name.
+   If MATCH_FILE is not null, accept only declaration in that source file;
+   if MATCH_LINENO or MATCH_LINECOL are also nonzero, accept only declaration
+   at that line and column.
+
+   If successful, fill in *RESULT with the DIE of the variable found,
+   and return N where SCOPES[N] is the scope defining the variable.
+   Return -1 for errors or -2 for no matching variable found.  */
+extern int dwarf_getscopevar (Dwarf_Die *scopes, int nscopes,
+			      const char *name, int skip_shadows,
+			      const char *match_file,
+			      int match_lineno, int match_linecol,
+			      Dwarf_Die *result);
+
+
+
+/* Return list address ranges.  */
+extern int dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges,
+			     size_t *naranges)
+     __nonnull_attribute__ (2);
+
+/* Return one of the address range entries.  */
+extern Dwarf_Arange *dwarf_onearange (Dwarf_Aranges *aranges, size_t idx);
+
+/* Return information in address range record.  */
+extern int dwarf_getarangeinfo (Dwarf_Arange *arange, Dwarf_Addr *addrp,
+				Dwarf_Word *lengthp, Dwarf_Off *offsetp);
+
+/* Get address range which includes given address.  */
+extern Dwarf_Arange *dwarf_getarange_addr (Dwarf_Aranges *aranges,
+					   Dwarf_Addr addr);
+
+
+
+/* Get functions in CUDIE.  The given callback will be called for all
+   defining DW_TAG_subprograms in the CU DIE tree.  If the callback
+   returns DWARF_CB_ABORT the return value can be used as offset argument
+   to resume the function to find all remaining functions (this is not
+   really recommended, since it needs to rewalk the CU DIE tree first till
+   that offset is found again).  If the callback returns DWARF_CB_OK
+   dwarf_getfuncs will not return but keep calling the callback for each
+   function DIE it finds.  Pass zero for offset on the first call to walk
+   the full CU DIE tree.  If no more functions can be found and the callback
+   returned DWARF_CB_OK then the function returns zero.  */
+extern ptrdiff_t dwarf_getfuncs (Dwarf_Die *cudie,
+				 int (*callback) (Dwarf_Die *, void *),
+				 void *arg, ptrdiff_t offset);
+
+
+/* Return file name containing definition of the given declaration.
+   Of the DECL has an (indirect, see dwarf_attr_integrate) decl_file
+   attribute.  The returned file path is either absolute, or relative
+   to the compilation directory.  Given the decl DIE, the compilation
+   directory can be retrieved through:
+   dwarf_formstring (dwarf_attr (dwarf_diecu (decl, &cudie, NULL, NULL),
+                                 DW_AT_comp_dir, &attr));
+   Returns NULL if no decl_file could be found or an error occurred.  */
+extern const char *dwarf_decl_file (Dwarf_Die *decl);
+
+/* Get line number of beginning of given declaration.  */
+extern int dwarf_decl_line (Dwarf_Die *decl, int *linep)
+     __nonnull_attribute__ (2);
+
+/* Get column number of beginning of given declaration.  */
+extern int dwarf_decl_column (Dwarf_Die *decl, int *colp)
+     __nonnull_attribute__ (2);
+
+
+/* Return nonzero if given function is an abstract inline definition.  */
+extern int dwarf_func_inline (Dwarf_Die *func);
+
+/* Find each concrete inlined instance of the abstract inline definition.  */
+extern int dwarf_func_inline_instances (Dwarf_Die *func,
+					int (*callback) (Dwarf_Die *, void *),
+					void *arg);
+
+
+/* Find the appropriate PC location or locations for function entry
+   breakpoints for the given DW_TAG_subprogram DIE.  Returns -1 for errors.
+   On success, returns the number of breakpoint locations (never zero)
+   and sets *BKPTS to a malloc'd vector of addresses.  */
+extern int dwarf_entry_breakpoints (Dwarf_Die *die, Dwarf_Addr **bkpts);
+
+
+/* Iterate through the macro unit referenced by CUDIE and call
+   CALLBACK for each macro information entry.  To start the iteration,
+   one would pass DWARF_GETMACROS_START for TOKEN.
+
+   The iteration continues while CALLBACK returns DWARF_CB_OK.  If the
+   callback returns DWARF_CB_ABORT, the iteration stops and a
+   continuation token is returned, which can be used to restart the
+   iteration at the point where it ended.  Returns -1 for errors or 0
+   if there are no more macro entries.
+
+   Note that the Dwarf_Macro pointer passed to the callback is only
+   valid for the duration of the callback invocation.
+
+   For backward compatibility, a token of 0 is accepted for starting
+   the iteration as well, but in that case this interface will refuse
+   to serve opcode 0xff from .debug_macro sections.  Such opcode would
+   be considered invalid and would cause dwarf_getmacros to return
+   with error.  */
+#define DWARF_GETMACROS_START PTRDIFF_MIN
+extern ptrdiff_t dwarf_getmacros (Dwarf_Die *cudie,
+				  int (*callback) (Dwarf_Macro *, void *),
+				  void *arg, ptrdiff_t token)
+     __nonnull_attribute__ (2);
+
+/* This is similar in operation to dwarf_getmacros, but selects the
+   unit to iterate through by offset instead of by CU, and always
+   iterates .debug_macro.  This can be used for handling
+   DW_MACRO_GNU_transparent_include's or similar opcodes.
+
+   TOKEN value of DWARF_GETMACROS_START can be used to start the
+   iteration.
+
+   It is not appropriate to obtain macro unit offset by hand from a CU
+   DIE and then request iteration through this interface.  The reason
+   for this is that if a dwarf_macro_getsrcfiles is later called,
+   there would be no way to figure out what DW_AT_comp_dir was present
+   on the CU DIE, and file names referenced in either the macro unit
+   itself, or the .debug_line unit that it references, might be wrong.
+   Use dwarf_getmacros.  */
+extern ptrdiff_t dwarf_getmacros_off (Dwarf *dbg, Dwarf_Off macoff,
+				      int (*callback) (Dwarf_Macro *, void *),
+				      void *arg, ptrdiff_t token)
+  __nonnull_attribute__ (3);
+
+/* Get the source files used by the macro entry.  You shouldn't assume
+   that Dwarf_Files references will remain valid after MACRO becomes
+   invalid.  (Which is to say it's only valid within the
+   dwarf_getmacros* callback.)  Returns 0 for success or a negative
+   value in case of an error.  */
+extern int dwarf_macro_getsrcfiles (Dwarf *dbg, Dwarf_Macro *macro,
+				    Dwarf_Files **files, size_t *nfiles)
+  __nonnull_attribute__ (2, 3, 4);
+
+/* Return macro opcode.  That's a constant that can be either from
+   DW_MACINFO_* domain or DW_MACRO_GNU_* domain.  The two domains have
+   compatible values, so it's OK to use either of them for
+   comparisons.  The only differences is 0xff, which could be either
+   DW_MACINFO_vendor_ext or a vendor-defined DW_MACRO_* constant.  One
+   would need to look if the CU DIE which the iteration was requested
+   for has attribute DW_AT_macro_info, or either of DW_AT_GNU_macros
+   or DW_AT_macros to differentiate the two interpretations.  */
+extern int dwarf_macro_opcode (Dwarf_Macro *macro, unsigned int *opcodep)
+     __nonnull_attribute__ (2);
+
+/* Get number of parameters of MACRO and store it to *PARAMCNTP.  */
+extern int dwarf_macro_getparamcnt (Dwarf_Macro *macro, size_t *paramcntp);
+
+/* Get IDX-th parameter of MACRO (numbered from zero), and stores it
+   to *ATTRIBUTE.  Returns 0 on success or -1 for errors.
+
+   After a successful call, you can query ATTRIBUTE by dwarf_whatform
+   to determine which of the dwarf_formX calls to make to get actual
+   value out of ATTRIBUTE.  Note that calling dwarf_whatattr is not
+   meaningful for pseudo-attributes formed this way.  */
+extern int dwarf_macro_param (Dwarf_Macro *macro, size_t idx,
+			      Dwarf_Attribute *attribute);
+
+/* Return macro parameter with index 0.  This will return -1 if the
+   parameter is not an integral value.  Use dwarf_macro_param for more
+   general access.  */
+extern int dwarf_macro_param1 (Dwarf_Macro *macro, Dwarf_Word *paramp)
+     __nonnull_attribute__ (2);
+
+/* Return macro parameter with index 1.  This will return -1 if the
+   parameter is not an integral or string value.  Use
+   dwarf_macro_param for more general access.  */
+extern int dwarf_macro_param2 (Dwarf_Macro *macro, Dwarf_Word *paramp,
+			       const char **strp);
+
+/* Compute what's known about a call frame when the PC is at ADDRESS.
+   Returns 0 for success or -1 for errors.
+   On success, *FRAME is a malloc'd pointer.  */
+extern int dwarf_cfi_addrframe (Dwarf_CFI *cache,
+				Dwarf_Addr address, Dwarf_Frame **frame)
+  __nonnull_attribute__ (3);
+
+/* Return the DWARF register number used in FRAME to denote
+   the return address in FRAME's caller frame.  The remaining
+   arguments can be non-null to fill in more information.
+
+   Fill [*START, *END) with the PC range to which FRAME's information applies.
+   Fill in *SIGNALP to indicate whether this is a signal-handling frame.
+   If true, this is the implicit call frame that calls a signal handler.
+   This frame's "caller" is actually the interrupted state, not a call;
+   its return address is an exact PC, not a PC after a call instruction.  */
+extern int dwarf_frame_info (Dwarf_Frame *frame,
+			     Dwarf_Addr *start, Dwarf_Addr *end, bool *signalp);
+
+/* Return a DWARF expression that yields the Canonical Frame Address at
+   this frame state.  Returns -1 for errors, or zero for success, with
+   *NOPS set to the number of operations stored at *OPS.  That pointer
+   can be used only as long as FRAME is alive and unchanged.  *NOPS is
+   zero if the CFA cannot be determined here.  Note that if nonempty,
+   *OPS is a DWARF expression, not a location description--append
+   DW_OP_stack_value to a get a location description for the CFA.  */
+extern int dwarf_frame_cfa (Dwarf_Frame *frame, Dwarf_Op **ops, size_t *nops)
+  __nonnull_attribute__ (2);
+
+/* Deliver a DWARF location description that yields the location or
+   value of DWARF register number REGNO in the state described by FRAME.
+
+   Returns -1 for errors or zero for success, setting *NOPS to the
+   number of operations in the array stored at *OPS.  Note the last
+   operation is DW_OP_stack_value if there is no mutable location but
+   only a computable value.
+
+   *NOPS zero with *OPS set to OPS_MEM means CFI says the caller's
+   REGNO is "undefined", i.e. it's call-clobbered and cannot be recovered.
+
+   *NOPS zero with *OPS set to a null pointer means CFI says the
+   caller's REGNO is "same_value", i.e. this frame did not change it;
+   ask the caller frame where to find it.
+
+   For common simple expressions *OPS is OPS_MEM (which is a caller
+   owned array for at least 3 Dwarf_Ops).  For arbitrary DWARF
+   expressions in the CFI, *OPS is an internal pointer that can be
+   used as long as the Dwarf_CFI used to create FRAME remains
+   alive.  */
+extern int dwarf_frame_register (Dwarf_Frame *frame, int regno,
+				 Dwarf_Op ops_mem[3],
+				 Dwarf_Op **ops, size_t *nops)
+  __nonnull_attribute__ (3, 4, 5);
+
+
+/* Return offset and/or size of CU's contribution to SECTION in a
+   DWARF package file.
+
+   If CU is not from a DWARF package file, the file does not have
+   SECTION, or CU does not contribute to SECTION, then *OFFSETP and
+   *SIZEP are set to 0 (this is not an error and the function will
+   return 0 in that case).
+
+   SECTION is a DW_SECT section identifier.  Note that the original
+   GNU DWARF package file extension for DWARF 4 used slightly
+   different section identifiers.  This function uses the standardized
+   section identifiers and maps the GNU DWARF 4 identifiers to their
+   standard DWARF 5 analogues: DW_SECT_LOCLISTS (5) refers to
+   .debug_locs.dwo for DWARF 4.  DW_SECT_MACRO (7) refers to
+   .debug_macinfo.dwo for DWARF 4 or .debug_macro.dwo for the GNU
+   .debug_macro extension for DWARF 4 (section identifier 8 is
+   DW_SECT_RNGLISTS in DWARF 5, NOT DW_SECT_MACRO like in the GNU
+   extension.)  .debug_types.dwo does not have a DWARF 5 equivalent,
+   so this function accepts the original DW_SECT_TYPES (2).
+
+   Returns 0 for success or -1 for errors reading the DWARF package
+   file data or if an unknown SECTION constant is given.  OFFSETP and
+   SIZEP may be NULL.  */
+extern int dwarf_cu_dwp_section_info (Dwarf_CU *cu, unsigned int section,
+				      Dwarf_Off *offsetp, Dwarf_Off *sizep);
+
+
+/* Return error code of last failing function call.  This value is kept
+   separately for each thread.  */
+extern int dwarf_errno (void);
+
+/* Return error string for ERROR.  If ERROR is zero, return error string
+   for most recent error or NULL is none occurred.  If ERROR is -1 the
+   behaviour is similar to the last case except that not NULL but a legal
+   string is returned.  */
+extern const char *dwarf_errmsg (int err);
+
+
+/* Register new Out-Of-Memory handler.  The old handler is returned.  */
+extern Dwarf_OOM dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler);
+
+
+/* Inline optimizations.  */
+#ifdef __OPTIMIZE__
+/* Return attribute code of given attribute.  */
+__libdw_extern_inline unsigned int
+dwarf_whatattr (Dwarf_Attribute *attr)
+{
+  return attr == NULL ? 0 : attr->code;
+}
+
+/* Return attribute code of given attribute.  */
+__libdw_extern_inline unsigned int
+dwarf_whatform (Dwarf_Attribute *attr)
+{
+  return attr == NULL ? 0 : attr->form;
+}
+#endif	/* Optimize.  */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* libdw.h */
diff --git a/libdw/libdw.map b/libdw/libdw.map
new file mode 100644
index 0000000..3c5ce8d
--- /dev/null
+++ b/libdw/libdw.map
@@ -0,0 +1,380 @@
+ELFUTILS_0 { };
+ELFUTILS_0.122 {
+  global:
+    dwarf_abbrevhaschildren;
+    dwarf_addrdie;
+    dwarf_arrayorder;
+    dwarf_attr;
+    dwarf_attr_integrate;
+    dwarf_begin;
+    dwarf_begin_elf;
+    dwarf_bitoffset;
+    dwarf_bitsize;
+    dwarf_bytesize;
+    dwarf_child;
+    dwarf_cuoffset;
+    dwarf_decl_column;
+    dwarf_decl_file;
+    dwarf_decl_line;
+    dwarf_diecu;
+    dwarf_diename;
+    dwarf_dieoffset;
+    dwarf_end;
+    dwarf_entry_breakpoints;
+    dwarf_entrypc;
+    dwarf_errmsg;
+    dwarf_errno;
+    dwarf_filesrc;
+    dwarf_formaddr;
+    dwarf_formblock;
+    dwarf_formflag;
+    dwarf_formref;
+    dwarf_formref_die;
+    dwarf_formsdata;
+    dwarf_formstring;
+    dwarf_formudata;
+    dwarf_func_inline;
+    dwarf_func_inline_instances;
+    dwarf_getabbrev;
+    dwarf_getabbrevattr;
+    dwarf_getabbrevcode;
+    dwarf_getabbrevtag;
+    dwarf_getarange_addr;
+    dwarf_getarangeinfo;
+    dwarf_getaranges;
+    dwarf_getattrcnt;
+    dwarf_getattrs;
+    dwarf_getfuncs;
+    dwarf_getlocation;
+    dwarf_getlocation_addr;
+    dwarf_getmacros;
+    dwarf_getpubnames;
+    dwarf_getscopes;
+    dwarf_getscopes_die;
+    dwarf_getscopevar;
+    dwarf_getsrc_die;
+    dwarf_getsrc_file;
+    dwarf_getsrcfiles;
+    dwarf_getsrclines;
+    dwarf_getstring;
+    dwarf_hasattr;
+    dwarf_hasattr_integrate;
+    dwarf_haschildren;
+    dwarf_hasform;
+    dwarf_haspc;
+    dwarf_highpc;
+    dwarf_lineaddr;
+    dwarf_linebeginstatement;
+    dwarf_lineblock;
+    dwarf_linecol;
+    dwarf_lineendsequence;
+    dwarf_lineepiloguebegin;
+    dwarf_lineno;
+    dwarf_lineprologueend;
+    dwarf_linesrc;
+    dwarf_lowpc;
+    dwarf_macro_opcode;
+    dwarf_macro_param1;
+    dwarf_macro_param2;
+    dwarf_new_oom_handler;
+    dwarf_nextcu;
+    dwarf_offabbrev;
+    dwarf_offdie;
+    dwarf_onearange;
+    dwarf_onesrcline;
+    dwarf_ranges;
+    dwarf_siblingof;
+    dwarf_srclang;
+    dwarf_tag;
+    dwarf_whatattr;
+    dwarf_whatform;
+
+    # libdwfl_pic.a contributes these symbols.
+    dwfl_addrdie;
+    dwfl_addrdwarf;
+    dwfl_addrmodule;
+    dwfl_begin;
+    dwfl_cumodule;
+    dwfl_end;
+    dwfl_errmsg;
+    dwfl_errno;
+    dwfl_getdwarf;
+    dwfl_getmodules;
+    dwfl_getsrc;
+    dwfl_getsrclines;
+    dwfl_line_comp_dir;
+    dwfl_linecu;
+    dwfl_lineinfo;
+    dwfl_linemodule;
+    dwfl_linux_kernel_find_elf;
+    dwfl_linux_kernel_module_section_address;
+    dwfl_linux_kernel_report_kernel;
+    dwfl_linux_kernel_report_modules;
+    dwfl_linux_kernel_report_offline;
+    dwfl_linux_proc_find_elf;
+    dwfl_linux_proc_maps_report;
+    dwfl_linux_proc_report;
+    dwfl_module_addrdie;
+    dwfl_module_addrname;
+    dwfl_module_getdwarf;
+    dwfl_module_getelf;
+    dwfl_module_getsrc;
+    dwfl_module_getsrc_file;
+    dwfl_module_getsym;
+    dwfl_module_getsymtab;
+    dwfl_module_info;
+    dwfl_module_nextcu;
+    dwfl_module_register_names;
+    dwfl_module_relocate_address;
+    dwfl_module_relocation_info;
+    dwfl_module_relocations;
+    dwfl_module_return_value_location;
+    dwfl_nextcu;
+    dwfl_offline_section_address;
+    dwfl_onesrcline;
+    dwfl_report_begin;
+    dwfl_report_elf;
+    dwfl_report_end;
+    dwfl_report_module;
+    dwfl_report_offline;
+    dwfl_standard_argp;
+    dwfl_standard_find_debuginfo;
+    dwfl_version;
+
+  local:
+    *;
+} ELFUTILS_0;
+
+ELFUTILS_0.126 {
+  global:
+    dwarf_getelf;
+
+} ELFUTILS_0.122;
+
+ELFUTILS_0.127 {
+  global:
+    dwarf_getsrcdirs;
+
+    dwfl_module_addrsym;
+    dwfl_report_begin_add;
+    dwfl_module_address_section;
+
+} ELFUTILS_0.126;
+
+ELFUTILS_0.130 {
+  global:
+    dwfl_build_id_find_elf;
+    dwfl_build_id_find_debuginfo;
+    dwfl_module_build_id;
+    dwfl_module_report_build_id;
+
+} ELFUTILS_0.127;
+
+ELFUTILS_0.136 {
+  global:
+    dwfl_addrsegment;
+    dwfl_report_segment;
+
+} ELFUTILS_0.130;
+
+ELFUTILS_0.138 {
+  global:
+    # Replaced ELFUTILS_0.130 version, which has bug-compatibility wrapper.
+    dwfl_module_build_id;
+
+} ELFUTILS_0.136;
+
+ELFUTILS_0.142 {
+  global:
+    dwarf_next_cfi;
+    dwarf_getcfi;
+    dwarf_getcfi_elf;
+    dwarf_cfi_addrframe;
+    dwarf_cfi_end;
+    dwarf_frame_cfa;
+    dwarf_frame_register;
+    dwarf_frame_info;
+
+    dwfl_module_dwarf_cfi;
+    dwfl_module_eh_cfi;
+} ELFUTILS_0.138;
+
+ELFUTILS_0.143 {
+  global:
+    dwarf_getlocation_implicit_value;
+
+    # Replaced ELFUTILS_0.122 versions.  Both versions point to the
+    # same implementation, but users of the new symbol version can
+    # presume that they use dwarf_attr_integrate properly.
+    dwarf_arrayorder;
+    dwarf_bitoffset;
+    dwarf_bitsize;
+    dwarf_bytesize;
+    dwarf_decl_column;
+    dwarf_decl_file;
+    dwarf_decl_line;
+    dwarf_srclang;
+
+} ELFUTILS_0.142;
+
+ELFUTILS_0.144 {
+  global:
+    dwarf_aggregate_size;
+} ELFUTILS_0.143;
+
+ELFUTILS_0.146 {
+  global:
+    dwfl_core_file_report;
+} ELFUTILS_0.144;
+
+ELFUTILS_0.148 {
+  global:
+    dwarf_lineisa;
+    dwarf_linediscriminator;
+    dwarf_lineop_index;
+
+    dwarf_next_unit;
+    dwarf_offdie_types;
+} ELFUTILS_0.146;
+
+ELFUTILS_0.149 {
+  global:
+    dwarf_getlocation_implicit_pointer;
+
+    dwfl_dwarf_line;
+} ELFUTILS_0.148;
+
+ELFUTILS_0.156 {
+  global:
+    # Replaced ELFUTILS_0.122 version, which has a wrapper without add_p_vaddr.
+    dwfl_report_elf;
+} ELFUTILS_0.149;
+
+ELFUTILS_0.157 {
+  global:
+    dwarf_getlocations;
+    dwarf_getlocation_die;
+    dwarf_getlocation_attr;
+} ELFUTILS_0.156;
+
+ELFUTILS_0.158 {
+  global:
+    # Replaced ELFUTILS_0.146 version, which has a wrapper without executable.
+    dwfl_core_file_report;
+
+    dwfl_attach_state;
+    dwfl_pid;
+    dwfl_thread_dwfl;
+    dwfl_thread_tid;
+    dwfl_frame_thread;
+    dwfl_thread_state_registers;
+    dwfl_thread_state_register_pc;
+    dwfl_getthread_frames;
+    dwfl_getthreads;
+    dwfl_thread_getframes;
+    dwfl_frame_pc;
+
+    dwfl_module_getsymtab_first_global;
+    dwfl_module_addrinfo;
+    dwfl_module_getsym_info;
+
+    dwfl_core_file_attach;
+    dwfl_linux_proc_attach;
+} ELFUTILS_0.157;
+
+ELFUTILS_0.159 {
+  global:
+    dwarf_getalt;
+    dwarf_setalt;
+    dwelf_dwarf_gnu_debugaltlink;
+    dwelf_elf_gnu_debuglink;
+    dwelf_elf_gnu_build_id;
+} ELFUTILS_0.158;
+
+ELFUTILS_0.160 {
+  global:
+    dwarf_cu_getdwarf;
+    dwarf_cu_die;
+} ELFUTILS_0.159;
+
+ELFUTILS_0.161 {
+  global:
+    dwarf_peel_type;
+
+    # Replaced ELFUTILS_0.144 version.  Both versions point to the
+    # same implementation, but users of the new symbol version can
+    # presume that it uses dwarf_peel_type.
+    dwarf_aggregate_size;
+
+    dwarf_getmacros_off;
+    dwarf_macro_getsrcfiles;
+    dwarf_macro_getparamcnt;
+    dwarf_macro_param;
+} ELFUTILS_0.160;
+
+ELFUTILS_0.165 {
+  global:
+    dwelf_scn_gnu_compressed_size;
+} ELFUTILS_0.161;
+
+ELFUTILS_0.167 {
+  global:
+    dwelf_strtab_init;
+    dwelf_strtab_add;
+    dwelf_strtab_add_len;
+    dwelf_strtab_finalize;
+    dwelf_strent_off;
+    dwelf_strent_str;
+    dwelf_strtab_free;
+} ELFUTILS_0.165;
+
+ELFUTILS_0.170 {
+  global:
+    dwarf_default_lower_bound;
+    dwarf_line_file;
+} ELFUTILS_0.167;
+
+ELFUTILS_0.171 {
+  global:
+    dwarf_die_addr_die;
+    dwarf_get_units;
+    dwarf_getabbrevattr_data;
+    dwarf_cu_info;
+} ELFUTILS_0.170;
+
+ELFUTILS_0.173 {
+  global:
+    dwarf_next_lines;
+} ELFUTILS_0.171;
+
+ELFUTILS_0.175 {
+  global:
+    dwelf_elf_begin;
+} ELFUTILS_0.173;
+
+ELFUTILS_0.177 {
+  global:
+    dwelf_elf_e_machine_string;
+    # Replaced ELFUTILS_0.175 versions.  Both versions point to the
+    # same implementation, but users of the new symbol version can
+    # presume that NULL is only returned on error (otherwise ELF_K_NONE).
+    dwelf_elf_begin;
+} ELFUTILS_0.175;
+
+ELFUTILS_0.186 {
+  global:
+    dwarf_linecontext;
+    dwarf_linefunctionname;
+} ELFUTILS_0.177;
+
+ELFUTILS_0.188 {
+  global:
+    dwfl_get_debuginfod_client;
+    dwfl_frame_reg;
+    dwfl_report_offline_memory;
+} ELFUTILS_0.186;
+
+ELFUTILS_0.191 {
+  global:
+    dwarf_cu_dwp_section_info;
+} ELFUTILS_0.188;
diff --git a/libdw/libdwP.h b/libdw/libdwP.h
new file mode 100644
index 0000000..8b2f06f
--- /dev/null
+++ b/libdw/libdwP.h
@@ -0,0 +1,1503 @@
+/* Internal definitions for libdw.
+   Copyright (C) 2002-2011, 2013-2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBDWP_H
+#define _LIBDWP_H 1
+
+#include <stdbool.h>
+#include <pthread.h>
+
+#include <libdw.h>
+#include <dwarf.h>
+
+
+/* Known location expressions already decoded.  */
+struct loc_s
+{
+  void *addr;
+  Dwarf_Op *loc;
+  size_t nloc;
+};
+
+/* Known DW_OP_implicit_value blocks already decoded.
+   This overlaps struct loc_s exactly, but only the
+   first member really has to match.  */
+struct loc_block_s
+{
+  void *addr;
+  unsigned char *data;
+  size_t length;
+};
+
+/* Already decoded .debug_line units.  */
+struct files_lines_s
+{
+  Dwarf_Off debug_line_offset;
+  Dwarf_Files *files;
+  Dwarf_Lines *lines;
+};
+
+/* Valid indices for the section data.  */
+enum
+  {
+    IDX_debug_info = 0,
+    IDX_debug_types,
+    IDX_debug_abbrev,
+    IDX_debug_aranges,
+    IDX_debug_addr,
+    IDX_debug_line,
+    IDX_debug_line_str,
+    IDX_debug_frame,
+    IDX_debug_loc,
+    IDX_debug_loclists,
+    IDX_debug_pubnames,
+    IDX_debug_str,
+    IDX_debug_str_offsets,
+    IDX_debug_macinfo,
+    IDX_debug_macro,
+    IDX_debug_ranges,
+    IDX_debug_rnglists,
+    IDX_debug_cu_index,
+    IDX_debug_tu_index,
+    IDX_gnu_debugaltlink,
+    IDX_last
+  };
+
+/* Valid indices for the string section's information.  */
+enum string_section_index
+  {
+    STR_SCN_IDX_debug_line_str,
+    STR_SCN_IDX_debug_str,
+    STR_SCN_IDX_last
+  };
+
+/* Error values.  */
+enum
+{
+  DWARF_E_NOERROR = 0,
+  DWARF_E_UNKNOWN_ERROR,
+  DWARF_E_INVALID_ACCESS,
+  DWARF_E_NO_REGFILE,
+  DWARF_E_IO_ERROR,
+  DWARF_E_INVALID_ELF,
+  DWARF_E_NO_DWARF,
+  DWARF_E_COMPRESSED_ERROR,
+  DWARF_E_NOELF,
+  DWARF_E_GETEHDR_ERROR,
+  DWARF_E_NOMEM,
+  DWARF_E_UNIMPL,
+  DWARF_E_INVALID_CMD,
+  DWARF_E_INVALID_VERSION,
+  DWARF_E_INVALID_FILE,
+  DWARF_E_NO_ENTRY,
+  DWARF_E_INVALID_DWARF,
+  DWARF_E_NO_STRING,
+  DWARF_E_NO_DEBUG_STR,
+  DWARF_E_NO_DEBUG_LINE_STR,
+  DWARF_E_NO_STR_OFFSETS,
+  DWARF_E_NO_ADDR,
+  DWARF_E_NO_CONSTANT,
+  DWARF_E_NO_REFERENCE,
+  DWARF_E_INVALID_REFERENCE,
+  DWARF_E_NO_DEBUG_LINE,
+  DWARF_E_INVALID_DEBUG_LINE,
+  DWARF_E_TOO_BIG,
+  DWARF_E_VERSION,
+  DWARF_E_INVALID_DIR_IDX,
+  DWARF_E_ADDR_OUTOFRANGE,
+  DWARF_E_NO_DEBUG_LOC,
+  DWARF_E_NO_DEBUG_LOCLISTS,
+  DWARF_E_NO_LOC_VALUE,
+  DWARF_E_NO_BLOCK,
+  DWARF_E_INVALID_LINE_IDX,
+  DWARF_E_INVALID_ARANGE_IDX,
+  DWARF_E_NO_MATCH,
+  DWARF_E_NO_FLAG,
+  DWARF_E_INVALID_OFFSET,
+  DWARF_E_NO_DEBUG_RANGES,
+  DWARF_E_NO_DEBUG_RNGLISTS,
+  DWARF_E_INVALID_CFI,
+  DWARF_E_NO_ALT_DEBUGLINK,
+  DWARF_E_INVALID_OPCODE,
+  DWARF_E_NOT_CUDIE,
+  DWARF_E_UNKNOWN_LANGUAGE,
+  DWARF_E_NO_DEBUG_ADDR,
+  DWARF_E_UNKNOWN_SECTION,
+};
+
+
+#include "dwarf_sig8_hash.h"
+
+/* The type of Dwarf object, sorted by preference
+   (if there is a higher order type, we pick that one over the others).  */
+enum dwarf_type
+  {
+    TYPE_UNKNOWN = 0,
+    TYPE_GNU_LTO = 16,
+    TYPE_DWO = 32,
+    TYPE_PLAIN = 64,
+  };
+
+/* This is the structure representing the debugging state.  */
+struct Dwarf
+{
+  /* The underlying ELF file.  */
+  Elf *elf;
+
+  /* The (absolute) path to the ELF file, if known.  To help locating
+     dwp files.  */
+  char *elfpath;
+
+  /* The (absolute) path to the ELF dir, if known.  To help locating
+     alt and dwo files.  */
+  char *debugdir;
+
+  /* dwz alternate DWARF file.  */
+  Dwarf *alt_dwarf;
+
+  /* DWARF package file.  */
+  Dwarf *dwp_dwarf;
+
+  /* The section data.  */
+  Elf_Data *sectiondata[IDX_last];
+
+  /* Size of a prefix of string sections, where any string will be
+     null-terminated. */
+  size_t string_section_size[STR_SCN_IDX_last];
+
+  /* True if the file has a byte order different from the host.  */
+  bool other_byte_order;
+
+  /* If true, we allocated the ELF descriptor ourselves.  */
+  bool free_elf;
+
+  /* If >= 0, we allocated the alt_dwarf ourselves and must end it and
+     close this file descriptor.  */
+  int alt_fd;
+
+  /* File descriptor of DWARF package file.  */
+  int dwp_fd;
+
+  /* Information for traversing the .debug_pubnames section.  This is
+     an array and separately allocated with malloc.  */
+  struct pubnames_s
+  {
+    Dwarf_Off cu_offset;
+    Dwarf_Off set_start;
+    unsigned int cu_header_size;
+    int address_len;
+  } *pubnames_sets;
+  size_t pubnames_nsets;
+
+  /* Search tree for the CUs.  */
+  void *cu_tree;
+  Dwarf_Off next_cu_offset;
+
+  /* Search tree and sig8 hash table for .debug_types type units.  */
+  void *tu_tree;
+  Dwarf_Off next_tu_offset;
+  Dwarf_Sig8_Hash sig8_hash;
+
+  /* Search tree for split Dwarf associated with CUs in this debug.  */
+  void *split_tree;
+
+  /* Search tree for .debug_macro operator tables.  */
+  void *macro_ops;
+
+  /* Search tree for decoded .debug_line units.  */
+  void *files_lines;
+
+  /* Address ranges read from .debug_aranges.  */
+  Dwarf_Aranges *aranges;
+
+  /* Address ranges inferred from CUs.  */
+  Dwarf_Aranges *dieranges;
+
+  /* Cached info from the CFI section.  */
+  struct Dwarf_CFI_s *cfi;
+
+  /* DWARF package file CU index section.  */
+  struct Dwarf_Package_Index_s *cu_index;
+  /* DWARF package file TU index section.  */
+  struct Dwarf_Package_Index_s *tu_index;
+
+  /* Fake loc CU.  Used when synthesizing attributes for Dwarf_Ops that
+     came from a location list entry in dwarf_getlocation_attr.
+     Depending on version this is the .debug_loc or .debug_loclists
+     section (could be both if mixing CUs with different DWARF versions).  */
+  struct Dwarf_CU *fake_loc_cu;
+  struct Dwarf_CU *fake_loclists_cu;
+
+  /* Similar for addrx/constx, which will come from .debug_addr section.  */
+  struct Dwarf_CU *fake_addr_cu;
+
+  enum dwarf_type type;
+
+  /* Supporting lock for internal memory handling.  Ensures threads that have
+     an entry in the mem_tails array are not disturbed by new threads doing
+     allocations for this Dwarf.  */
+  pthread_rwlock_t mem_rwl;
+
+  /* Internal memory handling.  This is basically a simplified thread-local
+     reimplementation of obstacks.  Unfortunately the standard obstack
+     implementation is not usable in libraries.  */
+  size_t mem_stacks;
+  struct libdw_memblock
+  {
+    size_t size;
+    size_t remaining;
+    struct libdw_memblock *prev;
+    char mem[0];
+  } **mem_tails;
+
+  /* Default size of allocated memory blocks.  */
+  size_t mem_default_size;
+
+  /* Registered OOM handler.  */
+  Dwarf_OOM oom_handler;
+};
+
+
+/* Abbreviation representation.  */
+struct Dwarf_Abbrev
+{
+  Dwarf_Off offset;	  /* Offset to start of abbrev into .debug_abbrev.  */
+  unsigned char *attrp;   /* Pointer to start of attribute name/form pairs. */
+  bool has_children : 1;  /* Whether or not the DIE has children. */
+  unsigned int code : 31; /* The (unique) abbrev code.  */
+  unsigned int tag;	  /* The tag of the DIE. */
+} attribute_packed;
+
+#include "dwarf_abbrev_hash.h"
+
+
+/* Files in line information records.  */
+struct Dwarf_Files_s
+  {
+    unsigned int ndirs;
+    unsigned int nfiles;
+    struct Dwarf_Fileinfo_s
+    {
+      char *name;
+      Dwarf_Word mtime;
+      Dwarf_Word length;
+    } info[0];
+    /* nfiles of those, followed by char *[ndirs].  */
+  };
+typedef struct Dwarf_Fileinfo_s Dwarf_Fileinfo;
+
+
+/* Representation of a row in the line table.  */
+
+struct Dwarf_Line_s
+{
+  Dwarf_Files *files;
+
+  Dwarf_Addr addr;
+  unsigned int file;
+  int line;
+  unsigned short int column;
+  unsigned int is_stmt:1;
+  unsigned int basic_block:1;
+  unsigned int end_sequence:1;
+  unsigned int prologue_end:1;
+  unsigned int epilogue_begin:1;
+  /* The remaining bit fields are not flags, but hold values presumed to be
+     small.  All the flags and other bit fields should add up to 48 bits
+     to give the whole struct a nice round size.  */
+  unsigned int op_index:8;
+  unsigned int isa:8;
+  unsigned int discriminator:24;
+  /* These are currently only used for the NVIDIA extensions.  */
+  unsigned int context;
+  unsigned int function_name;
+};
+
+struct Dwarf_Lines_s
+{
+  size_t nlines;
+  struct Dwarf_Line_s info[0];
+};
+
+/* Representation of address ranges.  */
+struct Dwarf_Aranges_s
+{
+  Dwarf *dbg;
+  size_t naranges;
+
+  struct Dwarf_Arange_s
+  {
+    Dwarf_Addr addr;
+    Dwarf_Word length;
+    Dwarf_Off offset;
+  } info[0];
+};
+
+/* DWARF package file unit index.  */
+typedef struct Dwarf_Package_Index_s
+{
+  Dwarf *dbg;
+  uint32_t section_count;
+  uint32_t unit_count;
+  uint32_t slot_count;
+  /* Mapping from DW_SECT_* - 1 to column number in the section tables, or
+     UINT32_MAX if not present.  */
+  uint32_t sections[DW_SECT_RNGLISTS];
+  /* Row number of last unit found in the index.  */
+  uint32_t last_unit_found;
+  const unsigned char *hash_table;
+  const unsigned char *indices;
+  const unsigned char *section_offsets;
+  const unsigned char *section_sizes;
+  /* If DW_SECT_INFO section offsets were truncated to 32 bits, recovered
+     64-bit offsets.  */
+  Dwarf_Off *debug_info_offsets;
+} Dwarf_Package_Index;
+
+/* CU representation.  */
+struct Dwarf_CU
+{
+  Dwarf *dbg;
+  Dwarf_Off start;
+  Dwarf_Off end;
+  /* Row number of this unit in DWARF package file index.  */
+  uint32_t dwp_row;
+  uint8_t address_size;
+  uint8_t offset_size;
+  uint16_t version;
+
+  size_t sec_idx; /* Normally .debug_info, could be .debug_type or "fake". */
+
+  /* The unit type if version >= 5.  Otherwise 0 for normal CUs (from
+     .debug_info) or 1 for v4 type units (from .debug_types).  */
+  uint8_t unit_type;
+
+  /* Zero if the unit type doesn't support a die/type offset and/or id/sig.
+     Nonzero if it is a v4 type unit or for DWARFv5 units depending on
+     unit_type.  */
+  size_t subdie_offset;
+  uint64_t unit_id8;
+
+  /* If this is a skeleton unit this points to the split compile unit.
+     Or the other way around if this is a split compile unit.  Set to -1
+     if not yet searched.  Always use __libdw_find_split_unit to access
+     this field.  */
+  struct Dwarf_CU *split;
+
+  /* Hash table for the abbreviations.  */
+  Dwarf_Abbrev_Hash abbrev_hash;
+  /* Offset of the first abbreviation.  */
+  size_t orig_abbrev_offset;
+  /* Offset past last read abbreviation.  */
+  size_t last_abbrev_offset;
+
+  /* The srcline information.  */
+  Dwarf_Lines *lines;
+
+  /* The source file information.  */
+  Dwarf_Files *files;
+
+  /* Known location lists.  */
+  void *locs;
+
+  /* Base address for use with ranges and locs.
+     Don't access directly, call __libdw_cu_base_address.  */
+  Dwarf_Addr base_address;
+
+  /* The offset into the .debug_addr section where index zero begins.
+     Don't access directly, call __libdw_cu_addr_base.  */
+  Dwarf_Off addr_base;
+
+  /* The offset into the .debug_str_offsets section where index zero begins.
+     Don't access directly, call __libdw_cu_str_off_base.  */
+  Dwarf_Off str_off_base;
+
+  /* The offset into the .debug_ranges section to use for GNU
+     DebugFission split units.  Don't access directly, call
+     __libdw_cu_ranges_base.  */
+  Dwarf_Off ranges_base;
+
+  /* The start of the offset table in .debug_loclists.
+     Don't access directly, call __libdw_cu_locs_base.  */
+  Dwarf_Off locs_base;
+
+  /* Memory boundaries of this CU.  */
+  void *startp;
+  void *endp;
+};
+
+/* Aliases to avoid PLTs.  */
+INTDECL (dwarf_aggregate_size)
+INTDECL (dwarf_attr)
+INTDECL (dwarf_attr_integrate)
+INTDECL (dwarf_begin)
+INTDECL (dwarf_begin_elf)
+INTDECL (dwarf_child)
+INTDECL (dwarf_cu_dwp_section_info)
+INTDECL (dwarf_default_lower_bound)
+INTDECL (dwarf_dieoffset)
+INTDECL (dwarf_diename)
+INTDECL (dwarf_end)
+INTDECL (dwarf_entrypc)
+INTDECL (dwarf_errmsg)
+INTDECL (dwarf_formaddr)
+INTDECL (dwarf_formblock)
+INTDECL (dwarf_formref_die)
+INTDECL (dwarf_formsdata)
+INTDECL (dwarf_formstring)
+INTDECL (dwarf_formudata)
+INTDECL (dwarf_getabbrevattr_data)
+INTDECL (dwarf_getalt)
+INTDECL (dwarf_getarange_addr)
+INTDECL (dwarf_getarangeinfo)
+INTDECL (dwarf_getaranges)
+INTDECL (dwarf_getlocation_die)
+INTDECL (dwarf_getsrcfiles)
+INTDECL (dwarf_getsrclines)
+INTDECL (dwarf_get_units)
+INTDECL (dwarf_hasattr)
+INTDECL (dwarf_haschildren)
+INTDECL (dwarf_haspc)
+INTDECL (dwarf_highpc)
+INTDECL (dwarf_lowpc)
+INTDECL (dwarf_nextcu)
+INTDECL (dwarf_next_unit)
+INTDECL (dwarf_offdie)
+INTDECL (dwarf_peel_type)
+INTDECL (dwarf_ranges)
+INTDECL (dwarf_setalt)
+INTDECL (dwarf_siblingof)
+INTDECL (dwarf_srclang)
+INTDECL (dwarf_tag)
+
+#define ISV4TU(cu) ((cu)->version == 4 && (cu)->sec_idx == IDX_debug_types)
+
+/* Compute the offset of a CU's first DIE from the CU offset.
+   CU must be a valid/known version/unit_type.  */
+static inline Dwarf_Off
+__libdw_first_die_from_cu_start (Dwarf_Off cu_start,
+				 uint8_t offset_size,
+				 uint16_t version,
+				 uint8_t unit_type)
+{
+/*
+  assert (offset_size == 4 || offset_size == 8);
+  assert (version >= 2 && version <= 5);
+  assert (unit_type == DW_UT_compile
+	  || unit_type == DW_UT_partial
+	  || unit_type == DW_UT_skeleton
+	  || unit_type == DW_UT_split_compile
+	  || unit_type == DW_UT_type
+	  || unit_type == DW_UT_split_type);
+*/
+
+  Dwarf_Off off = cu_start;
+  if (version < 5)
+    {
+   /*
+        LEN       VER     OFFSET    ADDR
+      4-bytes + 2-bytes + 4-bytes + 1-byte  for 32-bit dwarf
+     12-bytes + 2-bytes + 8-bytes + 1-byte  for 64-bit dwarf
+   or in .debug_types, 			     SIGNATURE TYPE-OFFSET
+      4-bytes + 2-bytes + 4-bytes + 1-byte + 8-bytes + 4-bytes  for 32-bit
+     12-bytes + 2-bytes + 8-bytes + 1-byte + 8-bytes + 8-bytes  for 64-bit
+
+   Note the trick in the computation.  If the offset_size is 4
+   the '- 4' term changes the '3 *' (or '4 *') into a '2 *' (or '3 *).
+   If the offset_size is 8 it accounts for the 4-byte escape value
+   used at the start of the length.  */
+      if (unit_type != DW_UT_type)
+	off += 3 * offset_size - 4 + 3;
+      else
+	off += 4 * offset_size - 4 + 3 + 8;
+    }
+  else
+    {
+     /*
+        LEN       VER      TYPE     ADDR     OFFSET   SIGNATURE  TYPE-OFFSET
+      4-bytes + 2-bytes + 1-byte + 1-byte + 4-bytes + 8-bytes + 4-bytes 32-bit
+     12-bytes + 2-bytes + 1-byte + 1-byte + 8-bytes + 8-bytes + 8-bytes 64-bit
+        Both signature and type offset are optional.
+
+        Note same 4/8 offset size trick as above.
+        We explicitly ignore unknown unit types (see asserts above).  */
+      off += 3 * offset_size - 4 + 4;
+      if (unit_type == DW_UT_skeleton || unit_type == DW_UT_split_compile
+	  || unit_type == DW_UT_type || unit_type == DW_UT_split_type)
+	{
+	  off += 8;
+	  if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)
+	    off += offset_size;
+	}
+    }
+
+  return off;
+}
+
+static inline Dwarf_Off
+__libdw_first_die_off_from_cu (struct Dwarf_CU *cu)
+{
+  return __libdw_first_die_from_cu_start (cu->start,
+					  cu->offset_size,
+					  cu->version,
+					  cu->unit_type);
+}
+
+#define CUDIE(fromcu)							      \
+  ((Dwarf_Die)								      \
+   {									      \
+     .cu = (fromcu),							      \
+     .addr = ((char *) (fromcu)->dbg->sectiondata[cu_sec_idx (fromcu)]->d_buf \
+	      + __libdw_first_die_off_from_cu (fromcu))			      \
+   })
+
+#define SUBDIE(fromcu)							      \
+  ((Dwarf_Die)								      \
+   {									      \
+     .cu = (fromcu),							      \
+     .addr = ((char *) (fromcu)->dbg->sectiondata[cu_sec_idx (fromcu)]->d_buf \
+	      + (fromcu)->start + (fromcu)->subdie_offset)		      \
+   })
+
+
+/* Prototype of a single .debug_macro operator.  */
+typedef struct
+{
+  Dwarf_Word nforms;
+  unsigned char const *forms;
+} Dwarf_Macro_Op_Proto;
+
+/* Prototype table.  */
+typedef struct
+{
+  Dwarf *dbg;
+
+  /* Offset of .debug_macro section.  */
+  Dwarf_Off offset;
+
+  /* Offset of associated .debug_line section.  */
+  Dwarf_Off line_offset;
+
+  /* The source file information.  */
+  Dwarf_Files *files;
+
+  /* If this macro unit was opened through dwarf_getmacros or
+     dwarf_getmacros_die, this caches value of DW_AT_comp_dir, if
+     present.  */
+  const char *comp_dir;
+
+  /* Header length.  */
+  Dwarf_Half header_len;
+
+  uint16_t version;
+  uint8_t address_size;
+  uint8_t offset_size;
+  uint8_t sec_index;	/* IDX_debug_macro or IDX_debug_macinfo.  */
+
+  /* Shows where in TABLE each opcode is defined.  Since opcode 0 is
+     never used, it stores index of opcode X in X-1'th element.  The
+     value of 0xff means not stored at all.  */
+  unsigned char opcodes[255];
+
+  /* Individual opcode prototypes.  */
+  Dwarf_Macro_Op_Proto table[];
+} Dwarf_Macro_Op_Table;
+
+struct Dwarf_Macro_s
+{
+  Dwarf_Macro_Op_Table *table;
+  Dwarf_Attribute *attributes;
+  uint8_t opcode;
+};
+
+static inline Dwarf_Word
+libdw_macro_nforms (Dwarf_Macro *macro)
+{
+  return macro->table->table[macro->table->opcodes[macro->opcode - 1]].nforms;
+}
+
+/* Returns true for any allowed FORM in the opcode_operands_table as
+   mentioned in the DWARF5 spec (6.3.1 Macro Information Header).
+   Or those mentioned in DWARF5 spec (6.2.4.2 Vendor-defined Content
+   Descriptions) for the directory/file table (plus DW_FORM_strp_sup).  */
+static inline bool
+libdw_valid_user_form (int form)
+{
+  switch (form)
+    {
+      case DW_FORM_block:
+      case DW_FORM_block1:
+      case DW_FORM_block2:
+      case DW_FORM_block4:
+      case DW_FORM_data1:
+      case DW_FORM_data2:
+      case DW_FORM_data4:
+      case DW_FORM_data8:
+      case DW_FORM_data16:
+      case DW_FORM_flag:
+      case DW_FORM_line_strp:
+      case DW_FORM_sdata:
+      case DW_FORM_sec_offset:
+      case DW_FORM_string:
+      case DW_FORM_strp:
+      case DW_FORM_strp_sup:
+      case DW_FORM_strx:
+      case DW_FORM_strx1:
+      case DW_FORM_strx2:
+      case DW_FORM_strx3:
+      case DW_FORM_strx4:
+      case DW_FORM_udata:
+	return true;
+      default:
+	return false;
+    }
+}
+
+
+/* We have to include the file at this point because the inline
+   functions access internals of the Dwarf structure.  */
+#include "memory-access.h"
+
+
+/* Set error value.  */
+extern void __libdw_seterrno (int value) internal_function;
+
+
+/* Memory handling, the easy parts.  */
+#define libdw_alloc(dbg, type, tsize, cnt) \
+  ({ struct libdw_memblock *_tail = __libdw_alloc_tail(dbg);		      \
+     size_t _required = (tsize) * (cnt);				      \
+     type *_result = (type *) (_tail->mem + (_tail->size - _tail->remaining));\
+     size_t _padding = ((__alignof (type)				      \
+			 - ((uintptr_t) _result & (__alignof (type) - 1)))    \
+			& (__alignof (type) - 1));			      \
+     if (unlikely (_tail->remaining < _required + _padding))		      \
+       _result = (type *) __libdw_allocate (dbg, _required, __alignof (type));\
+     else								      \
+       {								      \
+	 _required += _padding;						      \
+	 _result = (type *) ((char *) _result + _padding);		      \
+	 _tail->remaining -= _required;					      \
+       }								      \
+     _result; })
+
+#define libdw_typed_alloc(dbg, type) \
+  libdw_alloc (dbg, type, sizeof (type), 1)
+
+/* Can only be used to undo the last libdw_alloc.  */
+#define libdw_unalloc(dbg, type, tsize, cnt) \
+  ({ struct libdw_memblock *_tail = __libdw_thread_tail (dbg);		      \
+     size_t _required = (tsize) * (cnt);				      \
+     /* We cannot know the padding, it is lost.  */			      \
+     _tail->remaining += _required; })					      \
+
+#define libdw_typed_unalloc(dbg, type) \
+  libdw_unalloc (dbg, type, sizeof (type), 1)
+
+/* Callback to choose a thread-local memory allocation stack.  */
+extern struct libdw_memblock *__libdw_alloc_tail (Dwarf* dbg)
+     __nonnull_attribute__ (1);
+
+extern struct libdw_memblock *__libdw_thread_tail (Dwarf* dbg)
+     __nonnull_attribute__ (1);
+
+/* Callback to allocate more.  */
+extern void *__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
+     __attribute__ ((__malloc__)) __nonnull_attribute__ (1);
+
+/* Default OOM handler.  */
+extern void __libdw_oom (void) __attribute ((noreturn)) attribute_hidden;
+
+/* Read next unit (or v4 debug type) and return next offset.  Doesn't
+   create an actual Dwarf_CU just provides necessary header fields.  */
+extern int
+internal_function
+__libdw_next_unit (Dwarf *dbg, bool v4_debug_types, Dwarf_Off off,
+		   Dwarf_Off *next_off, size_t *header_sizep,
+		   Dwarf_Half *versionp, uint8_t *unit_typep,
+		   Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
+		   uint8_t *offset_sizep, uint64_t *unit_id8p,
+		   Dwarf_Off *subdie_offsetp)
+     __nonnull_attribute__ (4) internal_function;
+
+/* Allocate the internal data for a unit not seen before.  */
+extern struct Dwarf_CU *__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Find CU for given offset.  */
+extern struct Dwarf_CU *__libdw_findcu (Dwarf *dbg, Dwarf_Off offset, bool tu)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Find CU for given DIE address.  */
+extern struct Dwarf_CU *__libdw_findcu_addr (Dwarf *dbg, void *addr)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Find split Dwarf for given DIE address.  */
+extern struct Dwarf *__libdw_find_split_dbg_addr (Dwarf *dbg, void *addr)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Find the split (or skeleton) unit.  */
+extern struct Dwarf_CU *__libdw_find_split_unit (Dwarf_CU *cu)
+     internal_function;
+
+/* Find a unit in a DWARF package file for __libdw_intern_next_unit.  */
+extern int __libdw_dwp_find_unit (Dwarf *dbg, bool debug_types, Dwarf_Off off,
+				  uint16_t version, uint8_t unit_type,
+				  uint64_t unit_id8, uint32_t *unit_rowp,
+				  Dwarf_Off *abbrev_offsetp)
+     __nonnull_attribute__ (1, 7, 8) internal_function;
+
+/* Find the compilation unit in a DWARF package file with the given id.  */
+extern Dwarf_CU *__libdw_dwp_findcu_id (Dwarf *dbg, uint64_t unit_id8)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Get abbreviation with given code.  */
+extern Dwarf_Abbrev *__libdw_findabbrev (struct Dwarf_CU *cu,
+					 unsigned int code)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Get abbreviation at given offset.  */
+extern Dwarf_Abbrev *__libdw_getabbrev (Dwarf *dbg, struct Dwarf_CU *cu,
+					Dwarf_Off offset, size_t *lengthp,
+					Dwarf_Abbrev *result)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Get abbreviation of given DIE, and optionally set *READP to the DIE memory
+   just past the abbreviation code.  */
+static inline Dwarf_Abbrev *
+__nonnull_attribute__ (1)
+__libdw_dieabbrev (Dwarf_Die *die, const unsigned char **readp)
+{
+  /* Do we need to get the abbreviation, or need to read after the code?  */
+  if (die->abbrev == NULL || readp != NULL)
+    {
+      /* Get the abbreviation code.  */
+      unsigned int code;
+      const unsigned char *addr = die->addr;
+      if (unlikely (die->cu == NULL
+		    || addr >= (const unsigned char *) die->cu->endp))
+	return die->abbrev = DWARF_END_ABBREV;
+      get_uleb128 (code, addr, die->cu->endp);
+      if (readp != NULL)
+	*readp = addr;
+
+      /* Find the abbreviation.  */
+      if (die->abbrev == NULL)
+	die->abbrev = __libdw_findabbrev (die->cu, code);
+    }
+  return die->abbrev;
+}
+
+/* Helper functions for form handling.  */
+extern size_t __libdw_form_val_compute_len (struct Dwarf_CU *cu,
+					    unsigned int form,
+					    const unsigned char *valp)
+     __nonnull_attribute__ (1, 3) internal_function;
+
+/* Find the length of a form attribute in DIE/info data.  */
+static inline size_t
+__nonnull_attribute__ (1, 3)
+__libdw_form_val_len (struct Dwarf_CU *cu, unsigned int form,
+		      const unsigned char *valp)
+{
+  /* Small lookup table of forms with fixed lengths.  Absent indexes are
+     initialized 0, so any truly desired 0 is set to 0x80 and masked.  */
+  static const uint8_t form_lengths[] =
+    {
+      [DW_FORM_flag_present] = 0x80,
+      [DW_FORM_implicit_const] = 0x80, /* Value is in abbrev, not in info.  */
+
+      [DW_FORM_flag] = 1,
+      [DW_FORM_data1] = 1, [DW_FORM_ref1] = 1,
+      [DW_FORM_addrx1] = 1, [DW_FORM_strx1] = 1,
+
+      [DW_FORM_data2] = 2, [DW_FORM_ref2] = 2,
+      [DW_FORM_addrx2] = 2, [DW_FORM_strx2] = 2,
+
+      [DW_FORM_addrx3] = 3, [DW_FORM_strx3] = 3,
+
+      [DW_FORM_data4] = 4, [DW_FORM_ref4] = 4, [DW_FORM_ref_sup4] = 4,
+      [DW_FORM_addrx4] = 4, [DW_FORM_strx4] = 4,
+
+      [DW_FORM_ref_sig8] = 8,
+      [DW_FORM_data8] = 8, [DW_FORM_ref8] = 8, [DW_FORM_ref_sup8] = 8,
+
+      [DW_FORM_data16] = 16,
+    };
+
+  /* Return immediately for forms with fixed lengths.  */
+  if (form < sizeof form_lengths / sizeof form_lengths[0])
+    {
+      uint8_t len = form_lengths[form];
+      if (len != 0)
+	{
+	  const unsigned char *endp = cu->endp;
+	  len &= 0x7f; /* Mask to allow 0x80 -> 0.  */
+	  if (unlikely (len > (size_t) (endp - valp)))
+	    {
+	      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+	      return -1;
+	    }
+	  return len;
+	}
+    }
+
+  /* Other forms require some computation.  */
+  return __libdw_form_val_compute_len (cu, form, valp);
+}
+
+/* Helper function for DW_FORM_ref* handling.  */
+extern int __libdw_formref (Dwarf_Attribute *attr, Dwarf_Off *return_offset)
+     __nonnull_attribute__ (1, 2) internal_function;
+
+
+/* Helper function to locate attribute.  */
+extern unsigned char *__libdw_find_attr (Dwarf_Die *die,
+					 unsigned int search_name,
+					 unsigned int *codep,
+					 unsigned int *formp)
+     __nonnull_attribute__ (1) internal_function;
+
+/* Helper function to access integer attribute.  */
+extern int __libdw_attr_intval (Dwarf_Die *die, int *valp, int attval)
+     __nonnull_attribute__ (1, 2) internal_function;
+
+/* Helper function to walk scopes.  */
+struct Dwarf_Die_Chain
+{
+  Dwarf_Die die;
+  struct Dwarf_Die_Chain *parent;
+  bool prune;			/* The PREVISIT function can set this.  */
+};
+extern int __libdw_visit_scopes (unsigned int depth,
+				 struct Dwarf_Die_Chain *root,
+				 struct Dwarf_Die_Chain *imports,
+				 int (*previsit) (unsigned int depth,
+						  struct Dwarf_Die_Chain *,
+						  void *arg),
+				 int (*postvisit) (unsigned int depth,
+						   struct Dwarf_Die_Chain *,
+						   void *arg),
+				 void *arg)
+  __nonnull_attribute__ (2, 4) internal_function;
+
+/* Parse a DWARF Dwarf_Block into an array of Dwarf_Op's,
+   and cache the result (via tsearch).  */
+extern int __libdw_intern_expression (Dwarf *dbg,
+				      bool other_byte_order,
+				      unsigned int address_size,
+				      unsigned int ref_size,
+				      void **cache, const Dwarf_Block *block,
+				      bool cfap, bool valuep,
+				      Dwarf_Op **llbuf, size_t *listlen,
+				      int sec_index)
+  __nonnull_attribute__ (5, 6, 9, 10) internal_function;
+
+extern Dwarf_Die *__libdw_offdie (Dwarf *dbg, Dwarf_Off offset,
+				  Dwarf_Die *result, bool debug_types)
+  internal_function;
+
+
+/* Return error code of last failing function call.  This value is kept
+   separately for each thread.  */
+extern int __dwarf_errno_internal (void);
+
+
+/* Reader hooks.  */
+
+/* Relocation hooks return -1 on error (in that case the error code
+   must already have been set), 0 if there is no relocation and 1 if a
+   relocation was present.*/
+
+static inline int
+__libdw_relocate_address (Dwarf *dbg __attribute__ ((unused)),
+			  int sec_index __attribute__ ((unused)),
+			  const void *addr __attribute__ ((unused)),
+			  int width __attribute__ ((unused)),
+			  Dwarf_Addr *val __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static inline int
+__libdw_relocate_offset (Dwarf *dbg __attribute__ ((unused)),
+			 int sec_index __attribute__ ((unused)),
+			 const void *addr __attribute__ ((unused)),
+			 int width __attribute__ ((unused)),
+			 Dwarf_Off *val __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static inline Elf_Data *
+__libdw_checked_get_data (Dwarf *dbg, int sec_index)
+{
+  Elf_Data *data = dbg->sectiondata[sec_index];
+  if (unlikely (data == NULL)
+      || unlikely (data->d_buf == NULL))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+  return data;
+}
+
+static inline int
+__libdw_offset_in_section (Dwarf *dbg, int sec_index,
+			   Dwarf_Off offset, size_t size)
+{
+  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+  if (data == NULL)
+    return -1;
+  if (unlikely (offset > data->d_size)
+      || unlikely (data->d_size < size)
+      || unlikely (offset > data->d_size - size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return -1;
+    }
+
+  return 0;
+}
+
+static inline bool
+__libdw_in_section (Dwarf *dbg, int sec_index,
+		    const void *addr, size_t size)
+{
+  Elf_Data *data = __libdw_checked_get_data (dbg, sec_index);
+  if (data == NULL)
+    return false;
+  if (unlikely (addr < data->d_buf)
+      || unlikely (data->d_size < size)
+      || unlikely ((size_t)(addr - data->d_buf) > data->d_size - size))
+    {
+      __libdw_seterrno (DWARF_E_INVALID_OFFSET);
+      return false;
+    }
+
+  return true;
+}
+
+#define READ_AND_RELOCATE(RELOC_HOOK, VAL)				\
+  ({									\
+    if (!__libdw_in_section (dbg, sec_index, addr, width))		\
+      return -1;							\
+									\
+    const unsigned char *orig_addr = addr;				\
+    if (width == 4)							\
+      VAL = read_4ubyte_unaligned_inc (dbg, addr);			\
+    else								\
+      VAL = read_8ubyte_unaligned_inc (dbg, addr);			\
+									\
+    int status = RELOC_HOOK (dbg, sec_index, orig_addr, width, &VAL);	\
+    if (status < 0)							\
+      return status;							\
+    status > 0;								\
+   })
+
+static inline int
+__libdw_read_address_inc (Dwarf *dbg,
+			  int sec_index, const unsigned char **addrp,
+			  int width, Dwarf_Addr *ret)
+{
+  const unsigned char *addr = *addrp;
+  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+  *addrp = addr;
+  return 0;
+}
+
+static inline int
+__libdw_read_address (Dwarf *dbg,
+		      int sec_index, const unsigned char *addr,
+		      int width, Dwarf_Addr *ret)
+{
+  READ_AND_RELOCATE (__libdw_relocate_address, (*ret));
+  return 0;
+}
+
+static inline int
+__libdw_read_offset_inc (Dwarf *dbg,
+			 int sec_index, const unsigned char **addrp,
+			 int width, Dwarf_Off *ret, int sec_ret,
+			 size_t size)
+{
+  const unsigned char *addr = *addrp;
+  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+  *addrp = addr;
+  return __libdw_offset_in_section (dbg, sec_ret, *ret, size);
+}
+
+static inline int
+__libdw_read_offset (Dwarf *dbg, Dwarf *dbg_ret,
+		     int sec_index, const unsigned char *addr,
+		     int width, Dwarf_Off *ret, int sec_ret,
+		     size_t size)
+{
+  READ_AND_RELOCATE (__libdw_relocate_offset, (*ret));
+  return __libdw_offset_in_section (dbg_ret, sec_ret, *ret, size);
+}
+
+static inline size_t
+cu_sec_idx (struct Dwarf_CU *cu)
+{
+  return cu->sec_idx;
+}
+
+static inline bool
+is_cudie (Dwarf_Die *cudie)
+{
+  return cudie->cu != NULL && CUDIE (cudie->cu).addr == cudie->addr;
+}
+
+/* Read up begin/end pair and increment read pointer.
+    - If it's normal range record, set up *BEGINP and *ENDP and return 0.
+    - If it's base address selection record, set up *BASEP and return 1.
+    - If it's end of rangelist, don't set anything and return 2
+    - If an error occurs, don't set anything and return <0.  */
+int __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
+				     const unsigned char **readp,
+				     const unsigned char *readend,
+				     int width,
+				     Dwarf_Addr *beginp, Dwarf_Addr *endp,
+				     Dwarf_Addr *basep)
+  internal_function;
+
+const unsigned char * __libdw_formptr (Dwarf_Attribute *attr, int sec_index,
+				       int err_nodata,
+				       const unsigned char **endpp,
+				       Dwarf_Off *offsetp)
+  internal_function;
+
+/* Fills in the given attribute to point at an empty location expression.  */
+void __libdw_empty_loc_attr (Dwarf_Attribute *attr)
+  internal_function;
+
+/* Load .debug_line unit at DEBUG_LINE_OFFSET.  COMP_DIR is a value of
+   DW_AT_comp_dir or NULL if that attribute is not available.  Caches
+   the loaded unit and optionally set *LINESP and/or *FILESP (if not
+   NULL) with loaded information.  Returns 0 for success or a negative
+   value for failure.  */
+int __libdw_getsrclines (Dwarf *dbg, Dwarf_Off debug_line_offset,
+			 const char *comp_dir, unsigned address_size,
+			 Dwarf_Lines **linesp, Dwarf_Files **filesp)
+  internal_function
+  __nonnull_attribute__ (1);
+
+/* Load and return value of DW_AT_comp_dir from CUDIE.  */
+const char *__libdw_getcompdir (Dwarf_Die *cudie);
+
+/* Get the base address for the CU, fetches it when not yet set.
+   This is used as initial base address for ranges and loclists.  */
+Dwarf_Addr __libdw_cu_base_address (Dwarf_CU *cu);
+
+/* Get the address base for the CU, fetches it when not yet set.  */
+static inline Dwarf_Off
+__libdw_cu_addr_base (Dwarf_CU *cu)
+{
+  if (cu->addr_base == (Dwarf_Off) -1)
+    {
+      Dwarf_Die cu_die = CUDIE(cu);
+      Dwarf_Attribute attr;
+      Dwarf_Off offset = 0;
+      if (dwarf_attr (&cu_die, DW_AT_GNU_addr_base, &attr) != NULL
+	  || dwarf_attr (&cu_die, DW_AT_addr_base, &attr) != NULL)
+	{
+	  Dwarf_Word off;
+	  if (dwarf_formudata (&attr, &off) == 0)
+	    offset = off;
+	}
+      cu->addr_base = offset;
+    }
+
+  return cu->addr_base;
+}
+
+/* Gets the .debug_str_offsets base offset to use.  static inline to
+   be shared between libdw and eu-readelf.  */
+static inline Dwarf_Off
+str_offsets_base_off (Dwarf *dbg, Dwarf_CU *cu)
+{
+  /* If we don't have a CU, then find and use the first one in the
+     debug file (when we support .dwp files, we must actually find the
+     one matching our "caller" - aka macro or line).  If we (now) have
+     a cu and str_offsets_base attribute, just use that.  Otherwise
+     use the first offset.  But we might have to parse the header
+     first, but only if this is version 5.  Assume if all else fails,
+     this is version 4, without header.  */
+
+  if (cu == NULL && dbg != NULL)
+    {
+      Dwarf_CU *first_cu;
+      if (INTUSE(dwarf_get_units) (dbg, NULL, &first_cu,
+				   NULL, NULL, NULL, NULL) == 0)
+	cu = first_cu;
+    }
+
+  Dwarf_Off off = 0;
+  if (cu != NULL)
+    {
+      if (cu->str_off_base == (Dwarf_Off) -1)
+	{
+	  Dwarf_Off dwp_offset;
+	  if (dwarf_cu_dwp_section_info (cu, DW_SECT_STR_OFFSETS, &dwp_offset,
+					 NULL) == 0)
+	    off = dwp_offset;
+	  Dwarf_Die cu_die = CUDIE(cu);
+	  Dwarf_Attribute attr;
+	  if (dwarf_attr (&cu_die, DW_AT_str_offsets_base, &attr) != NULL)
+	    {
+	      Dwarf_Word base;
+	      if (dwarf_formudata (&attr, &base) == 0)
+		{
+		  cu->str_off_base = off + base;
+		  return cu->str_off_base;
+		}
+	    }
+	  /* For older DWARF simply assume zero (no header).  */
+	  if (cu->version < 5)
+	    {
+	      cu->str_off_base = off;
+	      return cu->str_off_base;
+	    }
+
+	  if (dbg == NULL)
+	    dbg = cu->dbg;
+	}
+      else
+	return cu->str_off_base;
+    }
+
+  /* No str_offsets_base attribute, we have to assume "zero".
+     But there could be a header first.  */
+  if (dbg == NULL)
+    goto no_header;
+
+  Elf_Data *data =  dbg->sectiondata[IDX_debug_str_offsets];
+  if (data == NULL)
+    goto no_header;
+
+  const unsigned char *start;
+  const unsigned char *readp;
+  const unsigned char *readendp;
+  start = readp = (const unsigned char *) data->d_buf;
+  readendp = (const unsigned char *) data->d_buf + data->d_size;
+
+  uint64_t unit_length;
+  uint16_t version;
+
+  unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+  if (unlikely (unit_length == 0xffffffff))
+    {
+      if (unlikely (readendp - readp < 8))
+	goto no_header;
+      unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+      /* In theory the offset size could be different
+	 between CU and str_offsets unit.  But we just
+	 ignore that here. */
+    }
+
+  /* We need at least 2-bytes (version) + 2-bytes (padding) =
+     4 bytes to complete the header.  And this unit cannot go
+     beyond the section data.  */
+  if (readendp - readp < 4
+      || unit_length < 4
+      || (uint64_t) (readendp - readp) < unit_length)
+    goto no_header;
+
+  version = read_2ubyte_unaligned_inc (dbg, readp);
+  if (version != 5)
+    goto no_header;
+  /* padding */
+  read_2ubyte_unaligned_inc (dbg, readp);
+
+  off += (Dwarf_Off) (readp - start);
+
+ no_header:
+  if (cu != NULL)
+    cu->str_off_base = off;
+
+  return off;
+}
+
+
+/* Get the string offsets base for the CU, fetches it when not yet set.  */
+static inline Dwarf_Off __libdw_cu_str_off_base (Dwarf_CU *cu)
+{
+  return str_offsets_base_off (NULL, cu);
+}
+
+
+/* Either a direct offset into .debug_ranges for version < 5, or the
+   start of the offset table in .debug_rnglists for version > 5.  */
+static inline Dwarf_Off
+__libdw_cu_ranges_base (Dwarf_CU *cu)
+{
+  if (cu->ranges_base == (Dwarf_Off) -1)
+    {
+      Dwarf_Off offset = 0;
+      Dwarf_Die cu_die = CUDIE(cu);
+      Dwarf_Attribute attr;
+      if (cu->version < 5)
+	{
+	  if (dwarf_attr (&cu_die, DW_AT_GNU_ranges_base, &attr) != NULL)
+	    {
+	      Dwarf_Word off;
+	      if (dwarf_formudata (&attr, &off) == 0)
+		offset = off;
+	    }
+	}
+      else
+	{
+	  Dwarf_Off dwp_offset;
+	  if (dwarf_cu_dwp_section_info (cu, DW_SECT_RNGLISTS, &dwp_offset,
+					 NULL) == 0)
+	    offset = dwp_offset;
+
+	  if (dwarf_attr (&cu_die, DW_AT_rnglists_base, &attr) != NULL)
+	    {
+	      Dwarf_Word off;
+	      if (dwarf_formudata (&attr, &off) == 0)
+		offset += off;
+	    }
+
+	  /* There wasn't an rnglists_base, if the Dwarf does have a
+	     .debug_rnglists section, then it might be we need the
+	     base after the first header. */
+	  Elf_Data *data = cu->dbg->sectiondata[IDX_debug_rnglists];
+	  if (offset == dwp_offset && data != NULL)
+	    {
+	      Dwarf *dbg = cu->dbg;
+	      const unsigned char *readp = data->d_buf;
+	      const unsigned char *const dataend
+		= (unsigned char *) data->d_buf + data->d_size;
+
+	      uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+	      unsigned int offset_size = 4;
+	      if (unlikely (unit_length == 0xffffffff))
+		{
+		  if (unlikely (readp > dataend - 8))
+		    goto no_header;
+
+		  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+		  offset_size = 8;
+		}
+
+	      if (readp > dataend - 8
+		  || unit_length < 8
+		  || unit_length > (uint64_t) (dataend - readp))
+		goto no_header;
+
+	      uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+	      if (version != 5)
+		goto no_header;
+
+	      uint8_t address_size = *readp++;
+	      if (address_size != 4 && address_size != 8)
+		goto no_header;
+
+	      uint8_t segment_size = *readp++;
+	      if (segment_size != 0)
+		goto no_header;
+
+	      uint32_t offset_entry_count;
+	      offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
+
+	      const unsigned char *offset_array_start = readp;
+	      if (offset_entry_count <= 0)
+		goto no_header;
+
+	      uint64_t needed = offset_entry_count * offset_size;
+	      if (unit_length - 8 < needed)
+		goto no_header;
+
+	      offset += (Dwarf_Off) (offset_array_start
+				     - (unsigned char *) data->d_buf);
+	    }
+	}
+    no_header:
+      cu->ranges_base = offset;
+    }
+
+  return cu->ranges_base;
+}
+
+
+/* The start of the offset table in .debug_loclists for DWARF5.  */
+static inline Dwarf_Off
+__libdw_cu_locs_base (Dwarf_CU *cu)
+{
+  if (cu->locs_base == (Dwarf_Off) -1)
+    {
+      Dwarf_Off offset = 0;
+      Dwarf_Off dwp_offset;
+      if (dwarf_cu_dwp_section_info (cu, DW_SECT_LOCLISTS, &dwp_offset, NULL)
+	  == 0)
+	offset = dwp_offset;
+
+      Dwarf_Die cu_die = CUDIE(cu);
+      Dwarf_Attribute attr;
+      if (dwarf_attr (&cu_die, DW_AT_loclists_base, &attr) != NULL)
+	{
+	  Dwarf_Word off;
+	  if (dwarf_formudata (&attr, &off) == 0)
+	    offset += off;
+	}
+
+      /* There wasn't an loclists_base, if the Dwarf does have a
+	 .debug_loclists section, then it might be we need the
+	 base after the first header. */
+      Elf_Data *data = cu->dbg->sectiondata[IDX_debug_loclists];
+      if (offset == dwp_offset && data != NULL)
+	{
+	  Dwarf *dbg = cu->dbg;
+	  const unsigned char *readp = data->d_buf;
+	  const unsigned char *const dataend
+	    = (unsigned char *) data->d_buf + data->d_size;
+
+	  uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+	  unsigned int offset_size = 4;
+	  if (unlikely (unit_length == 0xffffffff))
+	    {
+	      if (unlikely (readp > dataend - 8))
+		goto no_header;
+
+	      unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+	      offset_size = 8;
+	    }
+
+	  if (readp > dataend - 8
+	      || unit_length < 8
+	      || unit_length > (uint64_t) (dataend - readp))
+	    goto no_header;
+
+	  uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+	  if (version != 5)
+	    goto no_header;
+
+	  uint8_t address_size = *readp++;
+	  if (address_size != 4 && address_size != 8)
+	    goto no_header;
+
+	  uint8_t segment_size = *readp++;
+	  if (segment_size != 0)
+	    goto no_header;
+
+	  uint32_t offset_entry_count;
+	  offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
+
+	  const unsigned char *offset_array_start = readp;
+	  if (offset_entry_count <= 0)
+	    goto no_header;
+
+	  uint64_t needed = offset_entry_count * offset_size;
+	  if (unit_length - 8 < needed)
+	    goto no_header;
+
+	  offset += (Dwarf_Off) (offset_array_start
+				 - (unsigned char *) data->d_buf);
+	}
+
+    no_header:
+      cu->locs_base = offset;
+    }
+
+  return cu->locs_base;
+}
+
+/* Helper function for tsearch/tfind split_tree Dwarf.  */
+int __libdw_finddbg_cb (const void *arg1, const void *arg2);
+
+/* Link skeleton and split compile units.  */
+static inline void
+__libdw_link_skel_split (Dwarf_CU *skel, Dwarf_CU *split)
+{
+  skel->split = split;
+  split->split = skel;
+
+  /* Get .debug_addr and addr_base greedy.
+     We also need it for the fake addr cu.
+     This needs to be done for each split unit (one per .dwo file, or multiple
+     per .dwp file).  */
+  Dwarf *dbg = skel->dbg;
+  Dwarf *sdbg = split->dbg;
+  if (dbg->sectiondata[IDX_debug_addr] != NULL
+      /* If this split file hasn't been linked yet...  */
+      && (sdbg->sectiondata[IDX_debug_addr] == NULL
+	  /* ... or it was linked to the same skeleton file for another
+	     unit...  */
+	  || (sdbg->sectiondata[IDX_debug_addr]
+	      == dbg->sectiondata[IDX_debug_addr])))
+    {
+      /* ... then link the address information for this file and unit.  */
+      sdbg->sectiondata[IDX_debug_addr]
+	= dbg->sectiondata[IDX_debug_addr];
+      split->addr_base = __libdw_cu_addr_base (skel);
+      sdbg->fake_addr_cu = dbg->fake_addr_cu;
+    }
+}
+
+
+/* Given an address index for a CU return the address.
+   Returns -1 and sets libdw_errno if an error occurs.  */
+int __libdw_addrx (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr);
+
+
+/* Helper function to set elfpath field in Dwarf, used from dwarf_begin_elf
+   and libdwfl process_file.  */
+char * __libdw_elfpath (int fd);
+
+/* Helper function to set debugdir field in Dwarf after elfpath field has been
+   set.  */
+void __libdw_set_debugdir (Dwarf *dbg);
+
+
+/* Given the directory of a debug file, an absolute or relative dir
+   to look in, and file returns a full path.
+
+   If the file is absolute (starts with a /) a copy of file is returned.
+   the file isn't absolute, but dir is absolute, then a path that is
+   the concatenation of dir and file is returned.  If neither file,
+   nor dir is absolute, the path will be constructed using dir (if not
+   NULL) and file relative to the debugdir (if valid).
+
+   The debugdir and the dir may be NULL (in which case they aren't used).
+   If file is NULL, or no full path can be constructed NULL is returned.
+
+   The caller is responsible for freeing the result if not NULL.  */
+char * __libdw_filepath (const char *debugdir, const char *dir,
+			 const char *file)
+  internal_function;
+
+/* Like dwarf_getaranges but aranges are generated from CU address
+   ranges instead of being read from .debug_aranges.
+
+   Returns 0 if successful and updates ARANGES and NARANGES.  Otherwise
+   returns -1 and sets libdw_errno.
+*/
+int __libdw_getdieranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges);
+#endif	/* libdwP.h */
diff --git a/libdw/libdw_alloc.c b/libdw/libdw_alloc.c
new file mode 100644
index 0000000..b3e5334
--- /dev/null
+++ b/libdw/libdw_alloc.c
@@ -0,0 +1,156 @@
+/* Memory handling for libdw.
+   Copyright (C) 2003, 2004, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include "libdwP.h"
+#include "system.h"
+#include "atomics.h"
+#if USE_VG_ANNOTATIONS == 1
+#include <helgrind.h>
+#else
+#define ANNOTATE_HAPPENS_BEFORE(X)
+#define ANNOTATE_HAPPENS_AFTER(X)
+#endif
+
+#define THREAD_ID_UNSET ((size_t) -1)
+static __thread size_t thread_id = THREAD_ID_UNSET;
+static atomic_size_t next_id = ATOMIC_VAR_INIT(0);
+
+struct libdw_memblock *
+__libdw_alloc_tail (Dwarf *dbg)
+{
+  if (thread_id == THREAD_ID_UNSET)
+    thread_id = atomic_fetch_add (&next_id, 1);
+
+  pthread_rwlock_rdlock (&dbg->mem_rwl);
+  if (thread_id >= dbg->mem_stacks)
+    {
+      pthread_rwlock_unlock (&dbg->mem_rwl);
+      pthread_rwlock_wrlock (&dbg->mem_rwl);
+
+      /* Another thread may have already reallocated. In theory using an
+         atomic would be faster, but given that this only happens once per
+         thread per Dwarf, some minor slowdown should be fine.  */
+      if (thread_id >= dbg->mem_stacks)
+        {
+          dbg->mem_tails = realloc (dbg->mem_tails, (thread_id+1)
+                                    * sizeof (struct libdw_memblock *));
+          if (dbg->mem_tails == NULL)
+            {
+              pthread_rwlock_unlock (&dbg->mem_rwl);
+              dbg->oom_handler();
+            }
+          for (size_t i = dbg->mem_stacks; i <= thread_id; i++)
+            dbg->mem_tails[i] = NULL;
+          dbg->mem_stacks = thread_id + 1;
+          ANNOTATE_HAPPENS_BEFORE (&dbg->mem_tails);
+        }
+
+      pthread_rwlock_unlock (&dbg->mem_rwl);
+      pthread_rwlock_rdlock (&dbg->mem_rwl);
+    }
+
+  /* At this point, we have an entry in the tail array.  */
+  ANNOTATE_HAPPENS_AFTER (&dbg->mem_tails);
+  struct libdw_memblock *result = dbg->mem_tails[thread_id];
+  if (result == NULL)
+    {
+      result = malloc (dbg->mem_default_size);
+      if (result == NULL)
+	{
+	  pthread_rwlock_unlock (&dbg->mem_rwl);
+	  dbg->oom_handler();
+	}
+      result->size = dbg->mem_default_size
+                     - offsetof (struct libdw_memblock, mem);
+      result->remaining = result->size;
+      result->prev = NULL;
+      dbg->mem_tails[thread_id] = result;
+    }
+  pthread_rwlock_unlock (&dbg->mem_rwl);
+  return result;
+}
+
+/* Can only be called after a allocation for this thread has already
+   been done, to possibly undo it.  */
+struct libdw_memblock *
+__libdw_thread_tail (Dwarf *dbg)
+{
+  struct libdw_memblock *result;
+  pthread_rwlock_rdlock (&dbg->mem_rwl);
+  result = dbg->mem_tails[thread_id];
+  pthread_rwlock_unlock (&dbg->mem_rwl);
+  return result;
+}
+
+void *
+__libdw_allocate (Dwarf *dbg, size_t minsize, size_t align)
+{
+  size_t size = MAX (dbg->mem_default_size,
+		     (align - 1 +
+		      2 * minsize + offsetof (struct libdw_memblock, mem)));
+  struct libdw_memblock *newp = malloc (size);
+  if (newp == NULL)
+    dbg->oom_handler ();
+
+  uintptr_t result = ((uintptr_t) newp->mem + align - 1) & ~(align - 1);
+
+  newp->size = size - offsetof (struct libdw_memblock, mem);
+  newp->remaining = (uintptr_t) newp + size - (result + minsize);
+
+  pthread_rwlock_rdlock (&dbg->mem_rwl);
+  newp->prev = dbg->mem_tails[thread_id];
+  dbg->mem_tails[thread_id] = newp;
+  pthread_rwlock_unlock (&dbg->mem_rwl);
+
+  return (void *) result;
+}
+
+
+Dwarf_OOM
+dwarf_new_oom_handler (Dwarf *dbg, Dwarf_OOM handler)
+{
+  Dwarf_OOM old = dbg->oom_handler;
+  dbg->oom_handler = handler;
+  return old;
+}
+
+
+void
+__attribute ((noreturn)) attribute_hidden
+__libdw_oom (void)
+{
+  while (1)
+    error (EXIT_FAILURE, ENOMEM, "libdw");
+}
diff --git a/libdw/libdw_find_split_unit.c b/libdw/libdw_find_split_unit.c
new file mode 100644
index 0000000..8426a92
--- /dev/null
+++ b/libdw/libdw_find_split_unit.c
@@ -0,0 +1,211 @@
+/* Find the split (or skeleton) unit for a given unit.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include "libelfP.h"
+
+#include <limits.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+static void
+try_split_file (Dwarf_CU *cu, const char *dwo_path)
+{
+  int split_fd = open (dwo_path, O_RDONLY);
+  if (split_fd != -1)
+    {
+      Dwarf *split_dwarf = dwarf_begin (split_fd, DWARF_C_READ);
+      if (split_dwarf != NULL)
+	{
+	  Dwarf_CU *split = NULL;
+	  while (INTUSE(dwarf_get_units) (split_dwarf, split, &split,
+					  NULL, NULL, NULL, NULL) == 0)
+	    {
+	      if (split->unit_type == DW_UT_split_compile
+		  && cu->unit_id8 == split->unit_id8)
+		{
+		  if (tsearch (split->dbg, &cu->dbg->split_tree,
+			       __libdw_finddbg_cb) == NULL)
+		    {
+		      /* Something went wrong.  Don't link.  */
+		      __libdw_seterrno (DWARF_E_NOMEM);
+		      break;
+		    }
+
+		  /* Link skeleton and split compile units.  */
+		  __libdw_link_skel_split (cu, split);
+
+		  /* We have everything we need from this ELF
+		     file.  And we are going to close the fd to
+		     not run out of file descriptors.  */
+		  elf_cntl (split_dwarf->elf, ELF_C_FDDONE);
+		  break;
+		}
+	    }
+	  if (cu->split == (Dwarf_CU *) -1)
+	    dwarf_end (split_dwarf);
+	}
+      /* Always close, because we don't want to run out of file
+	 descriptors.  See also the elf_fcntl ELF_C_FDDONE call
+	 above.  */
+      close (split_fd);
+    }
+}
+
+static void
+try_dwp_file (Dwarf_CU *cu)
+{
+  if (cu->dbg->dwp_dwarf == NULL)
+    {
+      if (cu->dbg->elfpath != NULL)
+	{
+	  /* The DWARF 5 standard says "the package file is typically placed in
+	     the same directory as the application, and is given the same name
+	     with a '.dwp' extension".  */
+	  size_t elfpath_len = strlen (cu->dbg->elfpath);
+	  char *dwp_path = malloc (elfpath_len + 5);
+	  if (dwp_path == NULL)
+	    {
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      return;
+	    }
+	  memcpy (dwp_path, cu->dbg->elfpath, elfpath_len);
+	  strcpy (dwp_path + elfpath_len, ".dwp");
+	  int dwp_fd = open (dwp_path, O_RDONLY);
+	  free (dwp_path);
+	  if (dwp_fd != -1)
+	    {
+	      Dwarf *dwp_dwarf = dwarf_begin (dwp_fd, DWARF_C_READ);
+	      /* There's no way to know whether we got the correct file until
+		 we look up the unit, but it should at least be a dwp file.  */
+	      if (dwp_dwarf != NULL
+		  && (dwp_dwarf->sectiondata[IDX_debug_cu_index] != NULL
+		      || dwp_dwarf->sectiondata[IDX_debug_tu_index] != NULL))
+		{
+		  cu->dbg->dwp_dwarf = dwp_dwarf;
+		  cu->dbg->dwp_fd = dwp_fd;
+		}
+	      else
+		close (dwp_fd);
+	    }
+	}
+      if (cu->dbg->dwp_dwarf == NULL)
+	cu->dbg->dwp_dwarf = (Dwarf *) -1;
+    }
+
+  if (cu->dbg->dwp_dwarf != (Dwarf *) -1)
+    {
+      Dwarf_CU *split = __libdw_dwp_findcu_id (cu->dbg->dwp_dwarf,
+					       cu->unit_id8);
+      if (split != NULL)
+	{
+	  if (tsearch (split->dbg, &cu->dbg->split_tree,
+		       __libdw_finddbg_cb) == NULL)
+	    {
+	      /* Something went wrong.  Don't link.  */
+	      __libdw_seterrno (DWARF_E_NOMEM);
+	      return;
+	    }
+
+	  /* Link skeleton and split compile units.  */
+	  __libdw_link_skel_split (cu, split);
+	}
+    }
+}
+
+Dwarf_CU *
+internal_function
+__libdw_find_split_unit (Dwarf_CU *cu)
+{
+  /* Only try once.  */
+  if (cu->split != (Dwarf_CU *) -1)
+    return cu->split;
+
+  /* We need a skeleton unit with a comp_dir and [GNU_]dwo_name attributes.
+     The split unit will be the first in the dwo file and should have the
+     same id as the skeleton.  */
+  if (cu->unit_type == DW_UT_skeleton)
+    {
+      /* First, try the dwp file.  */
+      try_dwp_file (cu);
+
+      Dwarf_Die cudie = CUDIE (cu);
+      Dwarf_Attribute dwo_name;
+      /* Try a dwo file.  It is fine if dwo_dir doesn't exist, but then
+	 dwo_name needs to be an absolute path.  */
+      if (cu->split == (Dwarf_CU *) -1
+	  && (dwarf_attr (&cudie, DW_AT_dwo_name, &dwo_name) != NULL
+	      || dwarf_attr (&cudie, DW_AT_GNU_dwo_name, &dwo_name) != NULL))
+	{
+	  /* Try the dwo file name in the same directory
+	     as we found the skeleton file.  */
+	  const char *dwo_file = dwarf_formstring (&dwo_name);
+	  const char *debugdir = cu->dbg->debugdir;
+	  char *dwo_path = __libdw_filepath (debugdir, NULL, dwo_file);
+	  if (dwo_path != NULL)
+	    {
+	      try_split_file (cu, dwo_path);
+	      free (dwo_path);
+	    }
+
+	  if (cu->split == (Dwarf_CU *) -1)
+	    {
+	      /* Try compdir plus dwo_name.  */
+	      Dwarf_Attribute compdir;
+	      dwarf_attr (&cudie, DW_AT_comp_dir, &compdir);
+	      const char *dwo_dir = dwarf_formstring (&compdir);
+	      if (dwo_dir != NULL)
+		{
+		  dwo_path = __libdw_filepath (debugdir, dwo_dir, dwo_file);
+		  if (dwo_path != NULL)
+		    {
+		      try_split_file (cu, dwo_path);
+		      free (dwo_path);
+		    }
+		}
+	    }
+	  /* XXX If still not found we could try stripping dirs from the
+	     comp_dir and adding them from the comp_dir, assuming
+	     someone moved a whole build tree around.  */
+	}
+    }
+
+  /* If we found nothing, make sure we don't try again.  */
+  if (cu->split == (Dwarf_CU *) -1)
+    cu->split = NULL;
+
+  return cu->split;
+}
diff --git a/libdw/libdw_findcu.c b/libdw/libdw_findcu.c
new file mode 100644
index 0000000..6c7dcfb
--- /dev/null
+++ b/libdw/libdw_findcu.c
@@ -0,0 +1,315 @@
+/* Find CU for given offset.
+   Copyright (C) 2003-2010, 2014, 2016, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <search.h>
+#include "libdwP.h"
+
+static int
+findcu_cb (const void *arg1, const void *arg2)
+{
+  struct Dwarf_CU *cu1 = (struct Dwarf_CU *) arg1;
+  struct Dwarf_CU *cu2 = (struct Dwarf_CU *) arg2;
+
+  /* Find out which of the two arguments is the search value.  It has
+     end offset 0.  */
+  if (cu1->end == 0)
+    {
+      if (cu1->start < cu2->start)
+	return -1;
+      if (cu1->start >= cu2->end)
+	return 1;
+    }
+  else
+    {
+      if (cu2->start < cu1->start)
+	return 1;
+      if (cu2->start >= cu1->end)
+	return -1;
+    }
+
+  return 0;
+}
+
+int
+__libdw_finddbg_cb (const void *arg1, const void *arg2)
+{
+  Dwarf *dbg1 = (Dwarf *) arg1;
+  Dwarf *dbg2 = (Dwarf *) arg2;
+
+  Elf_Data *dbg1_data = dbg1->sectiondata[IDX_debug_info];
+  unsigned char *dbg1_start = dbg1_data->d_buf;
+  size_t dbg1_size = dbg1_data->d_size;
+
+  Elf_Data *dbg2_data = dbg2->sectiondata[IDX_debug_info];
+  unsigned char *dbg2_start = dbg2_data->d_buf;
+  size_t dbg2_size = dbg2_data->d_size;
+
+  /* Find out which of the two arguments is the search value.  It has
+     a size of 0.  */
+  if (dbg1_size == 0)
+    {
+      if (dbg1_start < dbg2_start)
+	return -1;
+      if (dbg1_start >= dbg2_start + dbg2_size)
+	return 1;
+    }
+  else
+    {
+      if (dbg2_start < dbg1_start)
+	return 1;
+      if (dbg2_start >= dbg1_start + dbg1_size)
+	return -1;
+    }
+
+  return 0;
+}
+
+struct Dwarf_CU *
+internal_function
+__libdw_intern_next_unit (Dwarf *dbg, bool debug_types)
+{
+  Dwarf_Off *const offsetp
+    = debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
+  void **tree = debug_types ? &dbg->tu_tree : &dbg->cu_tree;
+
+  Dwarf_Off oldoff = *offsetp;
+  uint16_t version;
+  uint8_t unit_type;
+  uint8_t address_size;
+  uint8_t offset_size;
+  Dwarf_Off abbrev_offset;
+  uint64_t unit_id8;
+  Dwarf_Off subdie_offset;
+
+  if (__libdw_next_unit (dbg, debug_types, oldoff, offsetp, NULL,
+			 &version, &unit_type, &abbrev_offset,
+			 &address_size, &offset_size,
+			 &unit_id8, &subdie_offset) != 0)
+    /* No more entries.  */
+    return NULL;
+
+  /* We only know how to handle the DWARF version 2 through 5 formats.
+     For v4 debug types we only handle version 4.  */
+  if (unlikely (version < 2) || unlikely (version > 5)
+      || (debug_types && unlikely (version != 4)))
+    {
+      __libdw_seterrno (DWARF_E_VERSION);
+      return NULL;
+    }
+
+  /* We only handle 32 or 64 bit (4 or 8 byte) addresses and offsets.
+     Just assume we are dealing with 64bit in case the size is "unknown".
+     Too much code assumes if it isn't 4 then it is 8 (or the other way
+     around).  */
+  if (unlikely (address_size != 4 && address_size != 8))
+    address_size = 8;
+  if (unlikely (offset_size != 4 && offset_size != 8))
+    offset_size = 8;
+
+  /* Invalid or truncated debug section data?  */
+  size_t sec_idx = debug_types ? IDX_debug_types : IDX_debug_info;
+  Elf_Data *data = dbg->sectiondata[sec_idx];
+  if (unlikely (*offsetp > data->d_size))
+    *offsetp = data->d_size;
+
+  uint32_t dwp_row;
+  Dwarf_Off dwp_abbrev_offset;
+  if (__libdw_dwp_find_unit (dbg, debug_types, oldoff, version, unit_type,
+			     unit_id8, &dwp_row, &dwp_abbrev_offset) != 0)
+    return NULL;
+  abbrev_offset += dwp_abbrev_offset;
+
+  /* Create an entry for this CU.  */
+  struct Dwarf_CU *newp = libdw_typed_alloc (dbg, struct Dwarf_CU);
+
+  newp->dbg = dbg;
+  newp->sec_idx = sec_idx;
+  newp->start = oldoff;
+  newp->end = *offsetp;
+  newp->dwp_row = dwp_row;
+  newp->address_size = address_size;
+  newp->offset_size = offset_size;
+  newp->version = version;
+  newp->unit_id8 = unit_id8;
+  newp->subdie_offset = subdie_offset;
+  Dwarf_Abbrev_Hash_init (&newp->abbrev_hash, 41);
+  newp->orig_abbrev_offset = newp->last_abbrev_offset = abbrev_offset;
+  newp->files = NULL;
+  newp->lines = NULL;
+  newp->locs = NULL;
+  newp->split = (Dwarf_CU *) -1;
+  newp->base_address = (Dwarf_Addr) -1;
+  newp->addr_base = (Dwarf_Off) -1;
+  newp->str_off_base = (Dwarf_Off) -1;
+  newp->ranges_base = (Dwarf_Off) -1;
+  newp->locs_base = (Dwarf_Off) -1;
+
+  newp->startp = data->d_buf + newp->start;
+  newp->endp = data->d_buf + newp->end;
+
+  /* v4 debug type units have version == 4 and unit_type == DW_UT_type.  */
+  if (debug_types)
+    newp->unit_type = DW_UT_type;
+  else if (version < 5)
+    {
+      /* This is a reasonable guess (and needed to get the CUDIE).  */
+      newp->unit_type = DW_UT_compile;
+
+      /* But set it correctly from the actual CUDIE tag.  */
+      Dwarf_Die cudie = CUDIE (newp);
+      int tag = INTUSE(dwarf_tag) (&cudie);
+      if (tag == DW_TAG_compile_unit)
+	{
+	  Dwarf_Attribute dwo_id;
+	  if (INTUSE(dwarf_attr) (&cudie, DW_AT_GNU_dwo_id, &dwo_id) != NULL)
+	    {
+	      Dwarf_Word id8;
+	      if (INTUSE(dwarf_formudata) (&dwo_id, &id8) == 0)
+		{
+		  if (INTUSE(dwarf_haschildren) (&cudie) == 0
+		      && INTUSE(dwarf_hasattr) (&cudie,
+						DW_AT_GNU_dwo_name) == 1)
+		    newp->unit_type = DW_UT_skeleton;
+		  else
+		    newp->unit_type = DW_UT_split_compile;
+
+		  newp->unit_id8 = id8;
+		}
+	    }
+	}
+      else if (tag == DW_TAG_partial_unit)
+	newp->unit_type = DW_UT_partial;
+      else if (tag == DW_TAG_type_unit)
+	newp->unit_type = DW_UT_type;
+    }
+  else
+    newp->unit_type = unit_type;
+
+  /* Store a reference to any type unit ids in the hash for quick lookup.  */
+  if (unit_type == DW_UT_type || unit_type == DW_UT_split_type)
+    Dwarf_Sig8_Hash_insert (&dbg->sig8_hash, unit_id8, newp);
+
+  /* Add the new entry to the search tree.  */
+  if (tsearch (newp, tree, findcu_cb) == NULL)
+    {
+      /* Something went wrong.  Undo the operation.  */
+      *offsetp = oldoff;
+      __libdw_seterrno (DWARF_E_NOMEM);
+      return NULL;
+    }
+
+  return newp;
+}
+
+struct Dwarf_CU *
+internal_function
+__libdw_findcu (Dwarf *dbg, Dwarf_Off start, bool v4_debug_types)
+{
+  void **tree = v4_debug_types ? &dbg->tu_tree : &dbg->cu_tree;
+  Dwarf_Off *next_offset
+    = v4_debug_types ? &dbg->next_tu_offset : &dbg->next_cu_offset;
+
+  /* Maybe we already know that CU.  */
+  struct Dwarf_CU fake = { .start = start, .end = 0 };
+  struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb);
+  if (found != NULL)
+    return *found;
+
+  if (start < *next_offset)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      return NULL;
+    }
+
+  /* No.  Then read more CUs.  */
+  while (1)
+    {
+      struct Dwarf_CU *newp = __libdw_intern_next_unit (dbg, v4_debug_types);
+      if (newp == NULL)
+	return NULL;
+
+      /* Is this the one we are looking for?  */
+      if (start < *next_offset || start == newp->start)
+	return newp;
+    }
+  /* NOTREACHED */
+}
+
+struct Dwarf_CU *
+internal_function
+__libdw_findcu_addr (Dwarf *dbg, void *addr)
+{
+  void **tree;
+  Dwarf_Off start;
+  if (addr >= dbg->sectiondata[IDX_debug_info]->d_buf
+      && addr < (dbg->sectiondata[IDX_debug_info]->d_buf
+		 + dbg->sectiondata[IDX_debug_info]->d_size))
+    {
+      tree = &dbg->cu_tree;
+      start = addr - dbg->sectiondata[IDX_debug_info]->d_buf;
+    }
+  else if (dbg->sectiondata[IDX_debug_types] != NULL
+	   && addr >= dbg->sectiondata[IDX_debug_types]->d_buf
+	   && addr < (dbg->sectiondata[IDX_debug_types]->d_buf
+		      + dbg->sectiondata[IDX_debug_types]->d_size))
+    {
+      tree = &dbg->tu_tree;
+      start = addr - dbg->sectiondata[IDX_debug_types]->d_buf;
+    }
+  else
+    return NULL;
+
+  struct Dwarf_CU fake = { .start = start, .end = 0 };
+  struct Dwarf_CU **found = tfind (&fake, tree, findcu_cb);
+
+  if (found != NULL)
+    return *found;
+
+  return NULL;
+}
+
+Dwarf *
+internal_function
+__libdw_find_split_dbg_addr (Dwarf *dbg, void *addr)
+{
+  /* XXX Assumes split DWARF only has CUs in main IDX_debug_info.  */
+  Elf_Data fake_data = { .d_buf = addr, .d_size = 0 };
+  Dwarf fake = { .sectiondata[IDX_debug_info] = &fake_data };
+  Dwarf **found = tfind (&fake, &dbg->split_tree, __libdw_finddbg_cb);
+
+  if (found != NULL)
+    return *found;
+
+  return NULL;
+}
diff --git a/libdw/libdw_form.c b/libdw/libdw_form.c
new file mode 100644
index 0000000..4004544
--- /dev/null
+++ b/libdw/libdw_form.c
@@ -0,0 +1,150 @@
+/* Helper functions for form handling.
+   Copyright (C) 2003-2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include <string.h>
+
+#include "libdwP.h"
+
+
+size_t
+internal_function
+__libdw_form_val_compute_len (struct Dwarf_CU *cu, unsigned int form,
+			      const unsigned char *valp)
+{
+  const unsigned char *startp = valp;
+  const unsigned char *endp = cu->endp;
+  Dwarf_Word u128;
+  size_t result;
+
+  /* NB: This doesn't cover constant form lengths, which are
+     already handled by the inlined __libdw_form_val_len.  */
+  switch (form)
+    {
+    case DW_FORM_addr:
+      result = cu->address_size;
+      break;
+
+    case DW_FORM_ref_addr:
+      result = cu->version == 2 ? cu->address_size : cu->offset_size;
+      break;
+
+    case DW_FORM_strp:
+    case DW_FORM_strp_sup:
+    case DW_FORM_line_strp:
+    case DW_FORM_sec_offset:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_GNU_strp_alt:
+      result = cu->offset_size;
+      break;
+
+    case DW_FORM_block1:
+      if (unlikely ((size_t) (endp - startp) < 1))
+	goto invalid;
+      result = *valp + 1;
+      break;
+
+    case DW_FORM_block2:
+      if (unlikely ((size_t) (endp - startp) < 2))
+	goto invalid;
+      result = read_2ubyte_unaligned (cu->dbg, valp) + 2;
+      break;
+
+    case DW_FORM_block4:
+      if (unlikely ((size_t) (endp - startp) < 4))
+	goto invalid;
+      result = read_4ubyte_unaligned (cu->dbg, valp) + 4;
+      break;
+
+    case DW_FORM_block:
+    case DW_FORM_exprloc:
+      if (valp >= endp)
+       goto invalid;
+      get_uleb128 (u128, valp, endp);
+      result = u128 + (valp - startp);
+      break;
+
+    case DW_FORM_string:
+      {
+	const unsigned char *endstrp = memchr (valp, '\0',
+					       (size_t) (endp - startp));
+	if (unlikely (endstrp == NULL))
+	  goto invalid;
+	result = (size_t) (endstrp - startp) + 1;
+	break;
+      }
+
+    case DW_FORM_sdata:
+    case DW_FORM_udata:
+    case DW_FORM_ref_udata:
+    case DW_FORM_addrx:
+    case DW_FORM_loclistx:
+    case DW_FORM_rnglistx:
+    case DW_FORM_strx:
+    case DW_FORM_GNU_addr_index:
+    case DW_FORM_GNU_str_index:
+      if (valp >= endp)
+       goto invalid;
+      get_uleb128 (u128, valp, endp);
+      result = valp - startp;
+      break;
+
+    case DW_FORM_indirect:
+      /* The amount of data to skip in the DIE is the size of the actual
+	 FORM data (which is __libdw_form_val_len) plus the size of the
+	 uleb128 encoding that FORM (which is valp - startp).  */
+      if (valp >= endp)
+	goto invalid;
+      get_uleb128 (u128, valp, endp);
+      if (*valp == DW_FORM_indirect || *valp == DW_FORM_implicit_const)
+	return (size_t) -1;
+      result = __libdw_form_val_len (cu, u128, valp);
+      if (result != (size_t) -1)
+	result += valp - startp;
+      else
+        return (size_t) -1;
+      break;
+
+    default:
+      goto invalid;
+    }
+
+  if (unlikely (result > (size_t) (endp - startp)))
+    {
+    invalid:
+      __libdw_seterrno (DWARF_E_INVALID_DWARF);
+      result = (size_t) -1;
+    }
+
+  return result;
+}
diff --git a/libdw/libdw_visit_scopes.c b/libdw/libdw_visit_scopes.c
new file mode 100644
index 0000000..7dfa5f6
--- /dev/null
+++ b/libdw/libdw_visit_scopes.c
@@ -0,0 +1,192 @@
+/* Helper functions to descend DWARF scope trees.
+   Copyright (C) 2005,2006,2007,2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+
+static bool
+may_have_scopes (Dwarf_Die *die)
+{
+  switch (INTUSE(dwarf_tag) (die))
+    {
+      /* DIEs with addresses we can try to match.  */
+    case DW_TAG_compile_unit:
+    case DW_TAG_module:
+    case DW_TAG_lexical_block:
+    case DW_TAG_with_stmt:
+    case DW_TAG_catch_block:
+    case DW_TAG_try_block:
+    case DW_TAG_entry_point:
+    case DW_TAG_inlined_subroutine:
+    case DW_TAG_subprogram:
+      return true;
+
+      /* DIEs without addresses that can own DIEs with addresses.  */
+    case DW_TAG_namespace:
+    case DW_TAG_class_type:
+    case DW_TAG_structure_type:
+      return true;
+
+      /* Other DIEs we have no reason to descend.  */
+    default:
+      break;
+    }
+  return false;
+}
+
+struct walk_children_state
+{
+  /* Parameters of __libdw_visit_scopes. */
+  unsigned int depth;
+  struct Dwarf_Die_Chain *imports;
+  int (*previsit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
+  int (*postvisit) (unsigned int depth, struct Dwarf_Die_Chain *, void *);
+  void *arg;
+  /* Extra local variables for the walker. */
+  struct Dwarf_Die_Chain child;
+};
+
+static inline int
+walk_children (struct walk_children_state *state);
+
+int
+internal_function
+__libdw_visit_scopes (unsigned int depth, struct Dwarf_Die_Chain *root,
+		      struct Dwarf_Die_Chain *imports,
+		      int (*previsit) (unsigned int,
+				       struct Dwarf_Die_Chain *,
+				       void *),
+		      int (*postvisit) (unsigned int,
+					struct Dwarf_Die_Chain *,
+					void *),
+		      void *arg)
+{
+  struct walk_children_state state =
+    {
+      .depth = depth,
+      .imports = imports,
+      .previsit = previsit,
+      .postvisit = postvisit,
+      .arg = arg
+    };
+
+  state.child.parent = root;
+  int ret;
+  if ((ret = INTUSE(dwarf_child) (&root->die, &state.child.die)) != 0)
+    return ret < 0 ? -1 : 0; // Having zero children is legal.
+
+  return walk_children (&state);
+}
+
+static inline int
+walk_children (struct walk_children_state *state)
+{
+  int ret;
+  do
+    {
+      /* For an imported unit, it is logically as if the children of
+	 that unit are siblings of the other children.  So don't do
+	 a full recursion into the imported unit, but just walk the
+	 children in place before moving to the next real child.  */
+      while (INTUSE(dwarf_tag) (&state->child.die) == DW_TAG_imported_unit)
+	{
+	  Dwarf_Die orig_child_die = state->child.die;
+	  Dwarf_Attribute attr_mem;
+	  Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&state->child.die,
+						      DW_AT_import,
+						      &attr_mem);
+	  /* Some gcc -flto versions imported other top-level compile units,
+	     skip those.  */
+	  if (INTUSE(dwarf_formref_die) (attr, &state->child.die) != NULL
+	      && INTUSE(dwarf_tag) (&state->child.die) != DW_TAG_compile_unit
+	      && (INTUSE(dwarf_child) (&state->child.die, &state->child.die)
+		  == 0))
+	    {
+	      /* Checks the given DIE hasn't been imported yet
+	         to prevent cycles.  */
+	      bool imported = false;
+	      for (struct Dwarf_Die_Chain *import = state->imports; import != NULL;
+	        import = import->parent)
+	        if (import->die.addr == orig_child_die.addr)
+	          {
+	            imported = true;
+	            break;
+	          }
+	      if (imported)
+		{
+		  __libdw_seterrno (DWARF_E_INVALID_DWARF);
+		  return -1;
+		}
+	      struct Dwarf_Die_Chain *orig_imports = state->imports;
+	      struct Dwarf_Die_Chain import = { .die = orig_child_die,
+					        .parent = orig_imports };
+	      state->imports = &import;
+	      int result = walk_children (state);
+	      state->imports = orig_imports;
+	      if (result != DWARF_CB_OK)
+		return result;
+	    }
+
+	  /* Any "real" children left?  */
+	  if ((ret = INTUSE(dwarf_siblingof) (&orig_child_die,
+					      &state->child.die)) != 0)
+	    return ret < 0 ? -1 : 0;
+	};
+
+	state->child.prune = false;
+
+	/* previsit is declared NN */
+	int result = (*state->previsit) (state->depth + 1, &state->child, state->arg);
+	if (result != DWARF_CB_OK)
+	  return result;
+
+	if (!state->child.prune && may_have_scopes (&state->child.die)
+	    && INTUSE(dwarf_haschildren) (&state->child.die))
+	  {
+	    result = __libdw_visit_scopes (state->depth + 1, &state->child, state->imports,
+				           state->previsit, state->postvisit, state->arg);
+	    if (result != DWARF_CB_OK)
+	      return result;
+	  }
+
+	if (state->postvisit != NULL)
+	  {
+	    result = (*state->postvisit) (state->depth + 1, &state->child, state->arg);
+	    if (result != DWARF_CB_OK)
+	      return result;
+	  }
+    }
+  while ((ret = INTUSE(dwarf_siblingof) (&state->child.die, &state->child.die)) == 0);
+
+  return ret < 0 ? -1 : 0;
+}
diff --git a/libdw/memory-access.h b/libdw/memory-access.h
new file mode 100644
index 0000000..6d79343
--- /dev/null
+++ b/libdw/memory-access.h
@@ -0,0 +1,412 @@
+/* Unaligned memory access functionality.
+   Copyright (C) 2000-2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _MEMORY_ACCESS_H
+#define _MEMORY_ACCESS_H 1
+
+#include <limits.h>
+#include <stdint.h>
+
+#include <system.h>
+
+/* Number decoding macros.  See 7.6 Variable Length Data.  */
+
+#define len_leb128(var) ((8 * sizeof (var) + 6) / 7)
+
+static inline size_t
+__libdw_max_len_leb128 (const size_t type_len,
+			const unsigned char *addr, const unsigned char *end)
+{
+  const size_t pointer_len = likely (addr < end) ? end - addr : 0;
+  return likely (type_len <= pointer_len) ? type_len : pointer_len;
+}
+
+static inline size_t
+__libdw_max_len_uleb128 (const unsigned char *addr, const unsigned char *end)
+{
+  const size_t type_len = len_leb128 (uint64_t);
+  return __libdw_max_len_leb128 (type_len, addr, end);
+}
+
+static inline size_t
+__libdw_max_len_sleb128 (const unsigned char *addr, const unsigned char *end)
+{
+  /* Subtract one step, so we don't shift into sign bit.  */
+  const size_t type_len = len_leb128 (int64_t) - 1;
+  return __libdw_max_len_leb128 (type_len, addr, end);
+}
+
+#define get_uleb128_step(var, addr, nth)				      \
+  do {									      \
+    unsigned char __b = *(addr)++;					      \
+    (var) |= (__typeof (var)) (__b & 0x7f) << ((nth) * 7);		      \
+    if (likely ((__b & 0x80) == 0))					      \
+      return (var);							      \
+  } while (0)
+
+static inline uint64_t
+__libdw_get_uleb128 (const unsigned char **addrp, const unsigned char *end)
+{
+  const size_t max = __libdw_max_len_uleb128 (*addrp, end);
+  if (unlikely (max == 0))
+    return UINT64_MAX;
+
+  uint64_t acc = 0;
+
+  /* Unroll the first step to help the compiler optimize
+     for the common single-byte case.  */
+  get_uleb128_step (acc, *addrp, 0);
+
+  for (size_t i = 1; i < max; ++i)
+    get_uleb128_step (acc, *addrp, i);
+  /* Other implementations set VALUE to UINT_MAX in this
+     case.  So we better do this as well.  */
+  return UINT64_MAX;
+}
+
+static inline uint64_t
+__libdw_get_uleb128_unchecked (const unsigned char **addrp)
+{
+  uint64_t acc = 0;
+
+  /* Unroll the first step to help the compiler optimize
+     for the common single-byte case.  */
+  get_uleb128_step (acc, *addrp, 0);
+
+  const size_t max = len_leb128 (uint64_t);
+  for (size_t i = 1; i < max; ++i)
+    get_uleb128_step (acc, *addrp, i);
+  /* Other implementations set VALUE to UINT_MAX in this
+     case.  So we better do this as well.  */
+  return UINT64_MAX;
+}
+
+/* Note, addr needs to me smaller than end. */
+#define get_uleb128(var, addr, end) ((var) = __libdw_get_uleb128 (&(addr), end))
+#define get_uleb128_unchecked(var, addr) ((var) = __libdw_get_uleb128_unchecked (&(addr)))
+
+/* The signed case is similar, but we sign-extend the result.  */
+
+#define get_sleb128_step(var, addr, nth)				      \
+  do {									      \
+    unsigned char __b = *(addr)++;					      \
+    (var) |= (__typeof (var)) (__b & 0x7f) << ((nth) * 7);		      \
+    if (likely ((__b & 0x80) == 0))					      \
+      {									      \
+	if ((__b & 0x40) != 0)						      \
+	  (var) |= - ((__typeof (var)) 1 << (((nth) + 1) * 7));		      \
+	return (var);							      \
+      }									      \
+  } while (0)
+
+static inline int64_t
+__libdw_get_sleb128 (const unsigned char **addrp, const unsigned char *end)
+{
+  const size_t max = __libdw_max_len_sleb128 (*addrp, end);
+  if (unlikely (max == 0))
+    return INT64_MAX;
+
+  /* Do the work in an unsigned type, but use implementation-defined
+     behavior to cast to signed on return.  This avoids some undefined
+     behavior when shifting.  */
+  uint64_t acc = 0;
+
+  /* Unroll the first step to help the compiler optimize
+     for the common single-byte case.  */
+  get_sleb128_step (acc, *addrp, 0);
+
+  for (size_t i = 1; i < max; ++i)
+    get_sleb128_step (acc, *addrp, i);
+  if (*addrp == end)
+    return INT64_MAX;
+
+  /* There might be one extra byte.  */
+  unsigned char b = **addrp;
+  ++*addrp;
+  if (likely ((b & 0x80) == 0))
+    {
+      /* We only need the low bit of the final byte, and as it is the
+	 sign bit, we don't need to do anything else here.  */
+      acc |= ((__typeof (acc)) b) << 7 * max;
+      return acc;
+    }
+
+  /* Other implementations set VALUE to INT_MAX in this
+     case.  So we better do this as well.  */
+  return INT64_MAX;
+}
+
+static inline int64_t
+__libdw_get_sleb128_unchecked (const unsigned char **addrp)
+{
+  /* Do the work in an unsigned type, but use implementation-defined
+     behavior to cast to signed on return.  This avoids some undefined
+     behavior when shifting.  */
+  uint64_t acc = 0;
+
+  /* Unroll the first step to help the compiler optimize
+     for the common single-byte case.  */
+  get_sleb128_step (acc, *addrp, 0);
+
+  /* Subtract one step, so we don't shift into sign bit.  */
+  const size_t max = len_leb128 (int64_t) - 1;
+  for (size_t i = 1; i < max; ++i)
+    get_sleb128_step (acc, *addrp, i);
+
+  /* There might be one extra byte.  */
+  unsigned char b = **addrp;
+  ++*addrp;
+  if (likely ((b & 0x80) == 0))
+    {
+      /* We only need the low bit of the final byte, and as it is the
+	 sign bit, we don't need to do anything else here.  */
+      acc |= ((__typeof (acc)) b) << 7 * max;
+      return acc;
+    }
+
+  /* Other implementations set VALUE to INT_MAX in this
+     case.  So we better do this as well.  */
+  return INT64_MAX;
+}
+
+#define get_sleb128(var, addr, end) ((var) = __libdw_get_sleb128 (&(addr), end))
+#define get_sleb128_unchecked(var, addr) ((var) = __libdw_get_sleb128_unchecked (&(addr)))
+
+
+/* We use simple memory access functions in case the hardware allows it.
+   The caller has to make sure we don't have alias problems.  */
+#if ALLOW_UNALIGNED
+
+# define read_2ubyte_unaligned(Dbg, Addr) \
+  (unlikely ((Dbg)->other_byte_order)					      \
+   ? bswap_16 (*((const uint16_t *) (Addr)))				      \
+   : *((const uint16_t *) (Addr)))
+# define read_2sbyte_unaligned(Dbg, Addr) \
+  (unlikely ((Dbg)->other_byte_order)					      \
+   ? (int16_t) bswap_16 (*((const int16_t *) (Addr)))			      \
+   : *((const int16_t *) (Addr)))
+
+# define read_4ubyte_unaligned_noncvt(Addr) \
+   *((const uint32_t *) (Addr))
+# define read_4ubyte_unaligned(Dbg, Addr) \
+  (unlikely ((Dbg)->other_byte_order)					      \
+   ? bswap_32 (*((const uint32_t *) (Addr)))				      \
+   : *((const uint32_t *) (Addr)))
+# define read_4sbyte_unaligned(Dbg, Addr) \
+  (unlikely ((Dbg)->other_byte_order)					      \
+   ? (int32_t) bswap_32 (*((const int32_t *) (Addr)))			      \
+   : *((const int32_t *) (Addr)))
+
+# define read_8ubyte_unaligned_noncvt(Addr) \
+   *((const uint64_t *) (Addr))
+# define read_8ubyte_unaligned(Dbg, Addr) \
+  (unlikely ((Dbg)->other_byte_order)					      \
+   ? bswap_64 (*((const uint64_t *) (Addr)))				      \
+   : *((const uint64_t *) (Addr)))
+# define read_8sbyte_unaligned(Dbg, Addr) \
+  (unlikely ((Dbg)->other_byte_order)					      \
+   ? (int64_t) bswap_64 (*((const int64_t *) (Addr)))			      \
+   : *((const int64_t *) (Addr)))
+
+#else
+
+union unaligned
+  {
+    void *p;
+    uint16_t u2;
+    uint32_t u4;
+    uint64_t u8;
+    int16_t s2;
+    int32_t s4;
+    int64_t s8;
+  } attribute_packed;
+
+# define read_2ubyte_unaligned(Dbg, Addr) \
+  read_2ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
+# define read_2sbyte_unaligned(Dbg, Addr) \
+  read_2sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
+# define read_4ubyte_unaligned(Dbg, Addr) \
+  read_4ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
+# define read_4sbyte_unaligned(Dbg, Addr) \
+  read_4sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
+# define read_8ubyte_unaligned(Dbg, Addr) \
+  read_8ubyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
+# define read_8sbyte_unaligned(Dbg, Addr) \
+  read_8sbyte_unaligned_1 ((Dbg)->other_byte_order, (Addr))
+
+static inline uint16_t
+read_2ubyte_unaligned_1 (bool other_byte_order, const void *p)
+{
+  const union unaligned *up = p;
+  if (unlikely (other_byte_order))
+    return bswap_16 (up->u2);
+  return up->u2;
+}
+static inline int16_t
+read_2sbyte_unaligned_1 (bool other_byte_order, const void *p)
+{
+  const union unaligned *up = p;
+  if (unlikely (other_byte_order))
+    return (int16_t) bswap_16 (up->u2);
+  return up->s2;
+}
+
+static inline uint32_t
+read_4ubyte_unaligned_noncvt (const void *p)
+{
+  const union unaligned *up = p;
+  return up->u4;
+}
+static inline uint32_t
+read_4ubyte_unaligned_1 (bool other_byte_order, const void *p)
+{
+  const union unaligned *up = p;
+  if (unlikely (other_byte_order))
+    return bswap_32 (up->u4);
+  return up->u4;
+}
+static inline int32_t
+read_4sbyte_unaligned_1 (bool other_byte_order, const void *p)
+{
+  const union unaligned *up = p;
+  if (unlikely (other_byte_order))
+    return (int32_t) bswap_32 (up->u4);
+  return up->s4;
+}
+
+static inline uint64_t
+read_8ubyte_unaligned_noncvt (const void *p)
+{
+  const union unaligned *up = p;
+  return up->u8;
+}
+static inline uint64_t
+read_8ubyte_unaligned_1 (bool other_byte_order, const void *p)
+{
+  const union unaligned *up = p;
+  if (unlikely (other_byte_order))
+    return bswap_64 (up->u8);
+  return up->u8;
+}
+static inline int64_t
+read_8sbyte_unaligned_1 (bool other_byte_order, const void *p)
+{
+  const union unaligned *up = p;
+  if (unlikely (other_byte_order))
+    return (int64_t) bswap_64 (up->u8);
+  return up->s8;
+}
+
+#endif	/* allow unaligned */
+
+
+#define read_2ubyte_unaligned_inc(Dbg, Addr) \
+  ({ uint16_t t_ = read_2ubyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);		      \
+     t_; })
+#define read_2sbyte_unaligned_inc(Dbg, Addr) \
+  ({ int16_t t_ = read_2sbyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 2);		      \
+     t_; })
+
+#define read_4ubyte_unaligned_inc(Dbg, Addr) \
+  ({ uint32_t t_ = read_4ubyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);		      \
+     t_; })
+#define read_4sbyte_unaligned_inc(Dbg, Addr) \
+  ({ int32_t t_ = read_4sbyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 4);		      \
+     t_; })
+
+#define read_8ubyte_unaligned_inc(Dbg, Addr) \
+  ({ uint64_t t_ = read_8ubyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);		      \
+     t_; })
+#define read_8sbyte_unaligned_inc(Dbg, Addr) \
+  ({ int64_t t_ = read_8sbyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 8);		      \
+     t_; })
+
+/* 3ubyte reads are only used for DW_FORM_addrx3 and DW_FORM_strx3.
+   And are probably very rare.  They are not optimized.  They are
+   handled as if reading a 4byte value with the first (for big endian)
+   or last (for little endian) byte zero.  */
+
+static inline int
+file_byte_order (bool other_byte_order)
+{
+#if BYTE_ORDER == LITTLE_ENDIAN
+  return other_byte_order ? BIG_ENDIAN : LITTLE_ENDIAN;
+#else
+  return other_byte_order ? LITTLE_ENDIAN : BIG_ENDIAN;
+#endif
+}
+
+static inline uint32_t
+read_3ubyte_unaligned (Dwarf *dbg, const unsigned char *p)
+{
+  union
+  {
+    uint32_t u4;
+    unsigned char c[4];
+  } d;
+  bool other_byte_order = dbg->other_byte_order;
+
+  if (file_byte_order (other_byte_order) == BIG_ENDIAN)
+    {
+      d.c[0] = 0x00;
+      d.c[1] = p[0];
+      d.c[2] = p[1];
+      d.c[3] = p[2];
+    }
+  else
+    {
+      d.c[0] = p[0];
+      d.c[1] = p[1];
+      d.c[2] = p[2];
+      d.c[3] = 0x00;
+    }
+
+  if (other_byte_order)
+    return bswap_32 (d.u4);
+  else
+    return d.u4;
+}
+
+
+#define read_3ubyte_unaligned_inc(Dbg, Addr) \
+  ({ uint32_t t_ = read_3ubyte_unaligned (Dbg, Addr);			      \
+     Addr = (__typeof (Addr)) (((uintptr_t) (Addr)) + 3);		      \
+     t_; })
+
+#define read_addr_unaligned_inc(Nbytes, Dbg, Addr)			\
+  (assert ((Nbytes) == 4 || (Nbytes) == 8),				\
+    ((Nbytes) == 4 ? read_4ubyte_unaligned_inc (Dbg, Addr)		\
+     : read_8ubyte_unaligned_inc (Dbg, Addr)))
+
+#endif	/* memory-access.h */
diff --git a/libdwelf/ChangeLog b/libdwelf/ChangeLog
new file mode 100644
index 0000000..1940629
--- /dev/null
+++ b/libdwelf/ChangeLog
@@ -0,0 +1,125 @@
+2022-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* libdwelfP.h: Include libdwP.h.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* dwelf_elf_begin.c: Don't include unistd.h.
+	* dwelf_strtab.c: Likewise.
+
+2022-08-08  Andreas Schwab  <schwab@suse.de>
+
+	* dwelf_elf_e_machine_string.c (dwelf_elf_e_machine_string): Add
+	EM_LOONGARCH LoongArch.
+
+2022-03-24  Mark Wielaard  <mark@klomp.org>
+
+	* dwelf_elf_e_machine_string.c (dwelf_elf_e_machine_string): Add
+	EM_INTELGT Intel Graphics Technology.
+
+2021-02-14  Alexander Miller  <alex.miller@gmx.de>
+
+	* dwelf_elf_begin.c (dwelf_elf_begin): Move NEW_VERSION before
+	definition.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* dwelf_strtab.c (dwelf_strtab_init): Remove cast of calloc return
+	value.
+	(morememory): Remove cast of malloc return value.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* libdwelf.h: Fix spelling typos in comments.
+	* dwelf_strtab.c (newstring): Likewise.
+
+	* dwelf_elf_e_machine_string.c (dwelf_elf_e_machine_string): Fix
+	spelling typos in returned strings.
+
+2020-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* dwelf_elf_e_machine_string.c (dwelf_elf_e_machine_string):
+	Rename EM_ARC_COMPACT2 to EM_ARCV2.
+
+2019-08-12  Mark Wielaard  <mark@klomp.org>
+
+	* libdwelf.h (dwelf_elf_begin): Update documentation.
+	* dwelf_elf_begin.c (dwelf_elf_begin): Don't suppress ELF_K_NONE.
+	Mark old and new version.
+
+2019-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libdwelf_a_SOURCES): Add dwelf_elf_e_machine_string.c.
+	* libdwelf.h (dwelf_elf_e_machine_string): Define new function.
+	* dwelf_elf_e_machine_string.c: New file.
+
+2018-10-21  Mark Wielaard  <mark@klomp.org>
+
+	* libdwelf.h (dwelf_elf_begin): Add function declaration.
+	* dwelf_elf_begin.c: New file.
+	* Makefile.am (libdwelf_a_SOURCES): Add dwelf_elf_begin.c.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwelf_elf_gnu_build_id.c (find_elf_build_id): Check p_align to
+	set ELF type.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* dwelf_strtab.c: Remove sys/param.h include.
+	(MIN): Remove definition.
+
+2016-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdwelf_a_SOURCES): Add dwelf_strtab.c.
+	* dwelf_strtab.c: New file.
+	* libdwelf.h (Dwelf_Strtab): New typedef.
+	(Dwelf_Strent): Likewise.
+	(dwelf_strtab_init): New function.
+	(dwelf_strtab_add): Likewise.
+	(dwelf_strtab_add_len): Likewise.
+	(dwelf_strtab_finalize): Likewise.
+	(dwelf_strent_off): Likewise.
+	(dwelf_strent_str): Likewise.
+	(dwelf_strtab_free): Likewise.
+
+2015-10-28  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdwelf_a_SOURCES): Add
+	dwelf_scn_gnu_compressed_size.c.
+	* dwelf_scn_gnu_compressed_size.c: Likewise.
+	* libdwelf.h (dwelf_scn_gnu_compressed_size): New declaration.
+
+2015-10-14  Chih-Hung Hsieh  <chh@google.com>
+
+	* dwelf_elf_gnu_build_id.c (find_elf_build_id): Move nested function
+	'check_notes' to file scope.
+
+2014-11-14  Mark Wielaard  <mjw@redhat.com>
+
+	* dwelf_elf_gnu_debuglink.c (dwelf_elf_gnu_debuglink): Check d_buf
+	is not NULL.
+
+2014-04-30  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (AM_CPPFLAGS): Add libdwfl and libebl include dirs.
+	(libdwelf_a_SOURCES): Add dwelf_elf_gnu_build_id.c
+	* dwelf_elf_gnu_build_id.c: New file. Moved libdwfl function
+	__libdwfl_find_elf_build_id here.
+	* libdwelf.h (dwelf_elf_gnu_build_id): Declare new function.
+	* libdwelfP.h (dwelf_elf_gnu_build_id): Add internal declaration.
+
+2014-04-24  Florian Weimer  <fweimer@redhat.com>
+
+	* dwelf_dwarf_gnu_debugaltlink.c: New file.
+	* Makefile.am (libdwelf_a_SOURCES): Add it.
+	* libdwelf.h (dwelf_dwarf_gnu_debugaltlink): Declare new function.
+	* libdwelfP.h (dwelf_dwarf_gnu_debugaltlink): Add internal
+	declaration.
+
+2014-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: New file.
+	* libdwelf.h: Likewise.
+	* libdwelfP.h: Likewise.
+	* dwelf_elf_gnu_debuglink.c: Likewise.
diff --git a/libdwelf/Makefile.am b/libdwelf/Makefile.am
new file mode 100644
index 0000000..a35a287
--- /dev/null
+++ b/libdwelf/Makefile.am
@@ -0,0 +1,57 @@
+## Makefile.am for libdwelf library subdirectory in elfutils.
+##
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2014, 2015 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libdw \
+	       -I$(srcdir)/../libdwfl -I$(srcdir)/../libebl
+VERSION = 1
+
+noinst_LIBRARIES = libdwelf.a libdwelf_pic.a
+
+pkginclude_HEADERS = libdwelf.h
+noinst_HEADERS = libdwelfP.h
+
+libdwelf_a_SOURCES = dwelf_elf_gnu_debuglink.c dwelf_dwarf_gnu_debugaltlink.c \
+		     dwelf_elf_gnu_build_id.c dwelf_scn_gnu_compressed_size.c \
+		     dwelf_strtab.c dwelf_elf_begin.c \
+		     dwelf_elf_e_machine_string.c
+
+libdwelf = $(libdw)
+
+libdw = ../libdw/libdw.so
+libelf = ../libelf/libelf.so
+libebl = ../libebl/libebl.a
+libeu = ../lib/libeu.a
+
+libdwelf_pic_a_SOURCES =
+am_libdwelf_pic_a_OBJECTS = $(libdwelf_a_SOURCES:.c=.os)
+
+CLEANFILES += $(am_libdwelf_pic_a_OBJECTS)
diff --git a/libdwelf/dwelf_dwarf_gnu_debugaltlink.c b/libdwelf/dwelf_dwarf_gnu_debugaltlink.c
new file mode 100644
index 0000000..b8285d0
--- /dev/null
+++ b/libdwelf/dwelf_dwarf_gnu_debugaltlink.c
@@ -0,0 +1,62 @@
+/* Returns the file name and build ID stored in the .gnu_altdebuglink if found.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+
+ssize_t
+dwelf_dwarf_gnu_debugaltlink (Dwarf *dwarf,
+			      const char **name_p,
+			      const void **build_idp)
+{
+  Elf_Data *data = dwarf->sectiondata[IDX_gnu_debugaltlink];
+  if (data == NULL)
+    {
+      return 0;
+    }
+
+  const void *ptr = memchr (data->d_buf, '\0', data->d_size);
+  if (ptr == NULL)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ELF);
+      return -1;
+    }
+  size_t build_id_len = data->d_size - (ptr - data->d_buf + 1);
+  if (build_id_len == 0 || (size_t) (ssize_t) build_id_len != build_id_len)
+    {
+      __libdw_seterrno (DWARF_E_INVALID_ELF);
+      return -1;
+    }
+  *name_p = data->d_buf;
+  *build_idp = ptr + 1;
+  return build_id_len;
+}
+INTDEF(dwelf_dwarf_gnu_debugaltlink)
diff --git a/libdwelf/dwelf_elf_begin.c b/libdwelf/dwelf_elf_begin.c
new file mode 100644
index 0000000..17a90fc
--- /dev/null
+++ b/libdwelf/dwelf_elf_begin.c
@@ -0,0 +1,62 @@
+/* Creates an ELF handle from a possibly compressed file descriptor.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+#include "libdwflP.h"
+#include "libelfP.h"
+
+NEW_VERSION (dwelf_elf_begin, ELFUTILS_0.177)
+Elf *
+dwelf_elf_begin (int fd)
+{
+  Elf *elf = NULL;
+  Dwfl_Error e = __libdw_open_elf (fd, &elf);
+  if (e == DWFL_E_NOERROR)
+    return elf;
+
+  /* Elf wasn't usable.  Make sure there is a proper elf error
+     message.  This is probably not the real error, because there is
+     no good way to propagate errnos or decompression errors, but
+     better than nothing.  */
+
+  if (e != DWFL_E_LIBELF)
+    {
+      /* Force a bad ELF error.  */
+      char badelf[EI_NIDENT] = { };
+      Elf *belf = elf_memory (badelf, EI_NIDENT);
+      elf32_getehdr (belf);
+      elf_end (belf);
+    }
+
+  return NULL;
+}
+OLD_VERSION (dwelf_elf_begin, ELFUTILS_0.175)
diff --git a/libdwelf/dwelf_elf_e_machine_string.c b/libdwelf/dwelf_elf_e_machine_string.c
new file mode 100644
index 0000000..6d588ea
--- /dev/null
+++ b/libdwelf/dwelf_elf_e_machine_string.c
@@ -0,0 +1,410 @@
+/* Returns a human readable description of an ELF header e_machine value.
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelf.h"
+
+
+const char *
+dwelf_elf_e_machine_string (int machine)
+{
+  switch (machine)
+    {
+    case EM_NONE:
+      return "None";
+    case EM_M32:
+      return "WE32100";
+    case EM_SPARC:
+      return "SPARC";
+    case EM_386:
+      return "Intel 80386";
+    case EM_68K:
+      return "M68K";
+    case EM_88K:
+      return "M88K";
+    case EM_IAMCU:
+      return "Intel MCU";
+    case EM_860:
+      return "Intel 80860";
+    case EM_MIPS:
+      return "MIPS R3000";
+    case EM_S370:
+      return "IBM System/370";
+    case EM_MIPS_RS3_LE:
+      return "MIPS R3000";
+    case EM_PARISC:
+      return "HPPA";
+    case EM_VPP500:
+      return "Fujitsu VPP500";
+    case EM_SPARC32PLUS:
+      return "SPARC v8+";
+    case EM_960:
+      return "Intel 80960";
+    case EM_PPC:
+      return "PowerPC";
+    case EM_PPC64:
+      return "PowerPC64";
+    case EM_S390:
+      return "IBM S/390";
+    case EM_SPU:
+      return "IBM SPU/SPC";
+    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_FAKE_ALPHA:
+      return "Digital Alpha";
+    case EM_SH:
+      return "SH";
+    case EM_SPARCV9:
+      return "SPARC v9";
+    case EM_TRICORE:
+      return "Siemens Tricore";
+    case EM_ARC:
+      return "ARC";
+    case EM_H8_300:
+      return "H8/300";
+    case EM_H8_300H:
+      return "H8/300H";
+    case EM_H8S:
+      return "H8S";
+    case EM_H8_500:
+      return "H8/500";
+    case EM_IA_64:
+      return "Intel IA-64";
+    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 Multimedia Accelerator";
+    case EM_PCP:
+      return "Siemens PCP";
+    case EM_NCPU:
+      return "Sony nCPU embedded RISC";
+    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 "STMicroelectronic ST100";
+    case EM_TINYJ:
+      return "Advanced Logic Corporation Tinyj";
+    case EM_X86_64:
+      return "AMD x86-64";
+    case EM_PDSP:
+      return "Sony DSP Processor";
+    case EM_PDP10:
+      return "Digital PDP-10";
+    case EM_PDP11:
+      return "Digital PDP-11";
+    case EM_FX66:
+      return "Siemens FX66 microcontroller";
+    case EM_ST9PLUS:
+      return "STMicroelectronics ST9+";
+    case EM_ST7:
+      return "STMicroelectronics ST7";
+    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";
+    case EM_VAX:
+      return "Digital VAX";
+    case EM_CRIS:
+      return "Axis Communications 32-bit embedded processor";
+    case EM_JAVELIN:
+      return "Infineon Technologies 32-bit 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 processor";
+    case EM_HUANY:
+      return "Harvard University machine-independent object";
+    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";
+    case EM_ARC_COMPACT:
+      return "ARC International ARCompact";
+    case EM_XTENSA:
+      return "Tensilica Xtensa Architecture";
+    case EM_VIDEOCORE:
+      return "Alphamosaic VideoCore";
+    case EM_TMM_GPP:
+      return "Thompson Multimedia General Purpose Processor";
+    case EM_NS32K:
+      return "National Semiconductor 32000";
+    case EM_TPC:
+      return "Tenor Network TPC";
+    case EM_SNP1K:
+      return "Trebia SNP 1000";
+    case EM_ST200:
+      return "STMicroelectronics ST200";
+    case EM_IP2K:
+      return "Ubicom IP2xxx";
+    case EM_MAX:
+      return "MAX processor";
+    case EM_CR:
+      return "National Semiconductor CompactRISC";
+    case EM_F2MC16:
+      return "Fujitsu F2MC16";
+    case EM_MSP430:
+      return "Texas Instruments msp430";
+    case EM_BLACKFIN:
+      return "Analog Devices Blackfin DSP";
+    case EM_SE_C33:
+      return "Seiko Epson S1C33";
+    case EM_SEP:
+      return "Sharp embedded microprocessor";
+    case EM_ARCA:
+      return "Arca RISC";
+    case EM_UNICORE:
+      return "Unicore";
+    case EM_EXCESS:
+      return "eXcess configurable CPU";
+    case EM_DXP:
+      return "Icera Semiconductor Deep Execution Processor";
+    case EM_ALTERA_NIOS2:
+      return "Altera Nios II";
+    case EM_CRX:
+      return "National Semiconductor CompactRISC CRX";
+    case EM_XGATE:
+      return "Motorola XGATE";
+    case EM_C166:
+      return "Infineon C16x/XC16x";
+    case EM_M16C:
+      return "Renesas M16C";
+    case EM_DSPIC30F:
+      return "Microchip Technology dsPIC30F";
+    case EM_CE:
+      return "Freescale Communication Engine RISC";
+    case EM_M32C:
+      return "Renesas M32C";
+    case EM_TSK3000:
+      return "Altium TSK3000";
+    case EM_RS08:
+      return "Freescale RS08";
+    case EM_SHARC:
+      return "Analog Devices SHARC";
+    case EM_ECOG2:
+      return "Cyan Technology eCOG2";
+    case EM_SCORE7:
+      return "Sunplus S+core7 RISC";
+    case EM_DSP24:
+      return "New Japan Radio (NJR) 24-bit DSP";
+    case EM_VIDEOCORE3:
+      return "Broadcom VideoCore III";
+    case EM_LATTICEMICO32:
+      return "RISC for Lattice FPGA";
+    case EM_SE_C17:
+      return "Seiko Epson C17";
+    case EM_TI_C6000:
+      return "Texas Instruments TMS320C6000 DSP";
+    case EM_TI_C2000:
+      return "Texas Instruments TMS320C2000 DSP";
+    case EM_TI_C5500:
+      return "Texas Instruments TMS320C55x DSP";
+    case EM_TI_ARP32:
+      return "Texas Instruments Application Specific RISC";
+    case EM_TI_PRU:
+      return "Texas Instruments Programmable Realtime Unit";
+    case EM_MMDSP_PLUS:
+      return "STMicroelectronics 64bit VLIW DSP";
+    case EM_CYPRESS_M8C:
+      return "Cypress M8C";
+    case EM_R32C:
+      return "Renesas R32C";
+    case EM_TRIMEDIA:
+      return "NXP Semiconductors TriMedia";
+    case EM_QDSP6:
+      return "QUALCOMM DSP6";
+    case EM_8051:
+      return "Intel 8051 and variants";
+    case EM_STXP7X:
+      return "STMicroelectronics STxP7x";
+    case EM_NDS32:
+      return "Andes Technology compact code size embedded RISC";
+    case EM_ECOG1X:
+      return "Cyan Technology eCOG1X";
+    case EM_MAXQ30:
+      return "Dallas Semiconductor MAXQ30";
+    case EM_XIMO16:
+      return "New Japan Radio (NJR) 16-bit DSP";
+    case EM_MANIK:
+      return "M2000 Reconfigurable RISC";
+    case EM_CRAYNV2:
+      return "Cray NV2 vector architecture";
+    case EM_RX:
+      return "Renesas RX";
+    case EM_METAG:
+      return "Imagination Technologies META";
+    case EM_MCST_ELBRUS:
+      return "MCST Elbrus";
+    case EM_ECOG16:
+      return "Cyan Technology eCOG16";
+    case EM_CR16:
+      return "National Semiconductor CompactRISC";
+    case EM_ETPU:
+      return "Freescale Extended Time Processing Unit";
+    case EM_SLE9X:
+      return "Infineon Technologies SLE9X";
+    case EM_L10M:
+      return "Intel L10M";
+    case EM_K10M:
+      return "Intel K10M";
+    case EM_AARCH64:
+      return "AARCH64";
+    case EM_AVR32:
+      return "Amtel AVR32";
+    case EM_STM8:
+      return "STMicroelectronics STM8";
+    case EM_TILE64:
+      return "Tilera TILE64";
+    case EM_TILEPRO:
+      return "Tilera TILEPro";
+    case EM_MICROBLAZE:
+      return "Xilinx MicroBlaze";
+    case EM_CUDA:
+      return "NVIDIA CUDA";
+    case EM_TILEGX:
+      return "Tilera TILE-Gx";
+    case EM_CLOUDSHIELD:
+      return "CloudShield";
+    case EM_COREA_1ST:
+      return "KIPO-KAIST Core-A 1st gen";
+    case EM_COREA_2ND:
+      return "KIPO-KAIST Core-A 2nd gen";
+    case EM_ARCV2:
+      return "Synopsys ARCv2 ISA";
+    case EM_OPEN8:
+      return "Open8 RISC";
+    case EM_RL78:
+      return "Renesas RL78";
+    case EM_VIDEOCORE5:
+      return "Broadcom VideoCore V";
+    case EM_78KOR:
+      return "Renesas 78KOR";
+    case EM_56800EX:
+      return "Freescale 56800EX DSC";
+    case EM_BA1:
+      return "Beyond BA1";
+    case EM_BA2:
+      return "Beyond BA2";
+    case EM_XCORE:
+      return "XMOS xCORE";
+    case EM_MCHP_PIC:
+      return "Microchip 8-bit PIC";
+    case EM_INTELGT:
+      return "Intel Graphics Technology";
+    case EM_KM32:
+      return "KM211 KM32";
+    case EM_KMX32:
+      return "KM211 KMX32";
+    case EM_EMX16:
+      return "KM211 KMX16";
+    case EM_EMX8:
+      return "KM211 KMX8";
+    case EM_KVARC:
+      return "KM211 KVARC";
+    case EM_CDP:
+      return "Paneve CDP";
+    case EM_COGE:
+      return "Cognitive Smart Memory Processor";
+    case EM_COOL:
+      return "Bluechip CoolEngine";
+    case EM_NORC:
+      return "Nanoradio Optimized RISC";
+    case EM_CSR_KALIMBA:
+      return "CSR Kalimba";
+    case EM_Z80:
+      return "Zilog Z80";
+    case EM_VISIUM:
+      return "CDS VISIUMcore";
+    case EM_FT32:
+      return "FTDI Chip FT32";
+    case EM_MOXIE:
+      return "Moxie";
+    case EM_AMDGPU:
+      return "AMD GPU";
+    case EM_RISCV:
+      return "RISC-V";
+    case EM_BPF:
+      return "BPF";
+    case EM_CSKY:
+      return "C-SKY";
+    case EM_LOONGARCH:
+      return "LoongArch";
+
+    case EM_ALPHA:
+      return "Alpha";
+
+    default:
+      return NULL;
+    }
+}
diff --git a/libdwelf/dwelf_elf_gnu_build_id.c b/libdwelf/dwelf_elf_gnu_build_id.c
new file mode 100644
index 0000000..dbcfc82
--- /dev/null
+++ b/libdwelf/dwelf_elf_gnu_build_id.c
@@ -0,0 +1,158 @@
+/* Returns the build id if found in a NT_GNU_BUILD_ID note.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+#include "libdwflP.h"
+
+#define NO_VADDR	((GElf_Addr) -1l)
+
+static int
+check_notes (Elf_Data *data, GElf_Addr data_elfaddr,
+             const void **build_id_bits, GElf_Addr *build_id_elfaddr,
+             int *build_id_len)
+{
+  size_t pos = 0;
+  GElf_Nhdr nhdr;
+  size_t name_pos;
+  size_t desc_pos;
+  while ((pos = gelf_getnote (data, pos, &nhdr, &name_pos, &desc_pos)) > 0)
+    if (nhdr.n_type == NT_GNU_BUILD_ID
+	&& nhdr.n_namesz == sizeof "GNU"
+	&& !memcmp (data->d_buf + name_pos, "GNU", sizeof "GNU"))
+	{
+	  *build_id_bits = data->d_buf + desc_pos;
+	  *build_id_elfaddr = (data_elfaddr == NO_VADDR
+	                      ? 0 : data_elfaddr + desc_pos);
+	  *build_id_len = nhdr.n_descsz;
+	  return 1;
+	}
+  return 0;
+}
+
+/* Defined here for reuse. The dwelf interface doesn't care about the
+   address of the note, but libdwfl does.  */
+static int
+find_elf_build_id (Dwfl_Module *mod, int e_type, Elf *elf,
+		   const void **build_id_bits, GElf_Addr *build_id_elfaddr,
+		   int *build_id_len)
+{
+  size_t shstrndx = SHN_UNDEF;
+  int result = 0;
+
+  Elf_Scn *scn = elf_nextscn (elf, NULL);
+
+  if (scn == NULL)
+    {
+      /* No sections, have to look for phdrs.  */
+      size_t phnum;
+      if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+	{
+	  if (mod != NULL)
+	    __libdwfl_seterrno (DWFL_E_LIBELF);
+	  return -1;
+	}
+      for (size_t i = 0; result == 0 && i < phnum; ++i)
+	{
+	  GElf_Phdr phdr_mem;
+	  GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+	  if (likely (phdr != NULL) && phdr->p_type == PT_NOTE)
+	    result = check_notes (elf_getdata_rawchunk (elf,
+							phdr->p_offset,
+							phdr->p_filesz,
+							(phdr->p_align == 8
+							 ? ELF_T_NHDR8
+							 : ELF_T_NHDR)),
+				  phdr->p_vaddr,
+				  build_id_bits,
+				  build_id_elfaddr,
+				  build_id_len);
+	}
+    }
+  else
+    do
+      {
+	GElf_Shdr shdr_mem;
+	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	if (likely (shdr != NULL) && shdr->sh_type == SHT_NOTE)
+	  {
+	    /* Determine the right sh_addr in this module.  */
+	    GElf_Addr vaddr = 0;
+	    if (!(shdr->sh_flags & SHF_ALLOC))
+	      vaddr = NO_VADDR;
+	    else if (mod == NULL || e_type != ET_REL)
+	      vaddr = shdr->sh_addr;
+	    else if (__libdwfl_relocate_value (mod, elf, &shstrndx,
+					       elf_ndxscn (scn), &vaddr))
+	      vaddr = NO_VADDR;
+	    result = check_notes (elf_getdata (scn, NULL), vaddr,
+	                          build_id_bits,
+	                          build_id_elfaddr,
+	                          build_id_len);
+	  }
+      }
+    while (result == 0 && (scn = elf_nextscn (elf, scn)) != NULL);
+
+  return result;
+}
+
+int
+internal_function
+__libdwfl_find_elf_build_id (Dwfl_Module *mod, Elf *elf,
+			     const void **build_id_bits,
+			     GElf_Addr *build_id_elfaddr, int *build_id_len)
+{
+  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (unlikely (ehdr == NULL))
+    {
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      return -1;
+    }
+  // MOD->E_TYPE is zero here.
+  assert (ehdr->e_type != ET_REL || mod != NULL);
+
+  return find_elf_build_id (mod, ehdr->e_type, elf,
+			    build_id_bits, build_id_elfaddr, build_id_len);
+}
+
+ssize_t
+dwelf_elf_gnu_build_id (Elf *elf, const void **build_idp)
+{
+  GElf_Addr build_id_elfaddr;
+  int build_id_len;
+  int result = find_elf_build_id (NULL, ET_NONE, elf, build_idp,
+				  &build_id_elfaddr, &build_id_len);
+  if (result > 0)
+    return build_id_len;
+
+  return result;
+}
+INTDEF(dwelf_elf_gnu_build_id)
diff --git a/libdwelf/dwelf_elf_gnu_debuglink.c b/libdwelf/dwelf_elf_gnu_debuglink.c
new file mode 100644
index 0000000..6e22cf6
--- /dev/null
+++ b/libdwelf/dwelf_elf_gnu_debuglink.c
@@ -0,0 +1,99 @@
+/* Returns the file name and crc stored in the .gnu_debuglink if found.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+
+const char *
+dwelf_elf_gnu_debuglink (Elf *elf, GElf_Word *crc)
+{
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+    return NULL;
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+        return NULL;
+
+      const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
+      if (name == NULL)
+        return NULL;
+
+      if (!strcmp (name, ".gnu_debuglink"))
+        break;
+    }
+
+  if (scn == NULL)
+    return NULL;
+
+  /* Found the .gnu_debuglink section.  Extract its contents.  */
+  Elf_Data *rawdata = elf_rawdata (scn, NULL);
+  if (rawdata == NULL || rawdata->d_buf == NULL)
+    return NULL;
+
+  /* The CRC comes after the zero-terminated file name,
+     (aligned up to 4 bytes) at the end of the section data.  */
+  if (rawdata->d_size <= sizeof *crc
+      || memchr (rawdata->d_buf, '\0', rawdata->d_size - sizeof *crc) == NULL)
+    return NULL;
+
+  Elf_Data crcdata =
+    {
+      .d_type = ELF_T_WORD,
+      .d_buf = crc,
+      .d_size = sizeof *crc,
+      .d_version = EV_CURRENT,
+    };
+  Elf_Data conv =
+    {
+      .d_type = ELF_T_WORD,
+      .d_buf = rawdata->d_buf + rawdata->d_size - sizeof *crc,
+      .d_size = sizeof *crc,
+      .d_version = EV_CURRENT,
+    };
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    return NULL;
+
+  Elf_Data *d = gelf_xlatetom (elf, &crcdata, &conv, ehdr->e_ident[EI_DATA]);
+  if (d == NULL)
+    return NULL;
+  assert (d == &crcdata);
+
+  return rawdata->d_buf;
+}
+INTDEF(dwelf_elf_gnu_debuglink)
diff --git a/libdwelf/dwelf_scn_gnu_compressed_size.c b/libdwelf/dwelf_scn_gnu_compressed_size.c
new file mode 100644
index 0000000..d39b702
--- /dev/null
+++ b/libdwelf/dwelf_scn_gnu_compressed_size.c
@@ -0,0 +1,77 @@
+/* Return size of GNU compressed section.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwelfP.h"
+#include "libelfP.h"
+
+ssize_t
+dwelf_scn_gnu_compressed_size (Elf_Scn *scn)
+{
+  if (scn == NULL)
+    return -1;
+
+  GElf_Shdr shdr;
+  if (gelf_getshdr (scn, &shdr) == NULL)
+    return -1;
+
+  /* Allocated or no bits sections can never be compressed.  */
+  if ((shdr.sh_flags & SHF_ALLOC) != 0
+      || shdr.sh_type == SHT_NULL
+      || shdr.sh_type == SHT_NOBITS)
+    return -1;
+
+  Elf_Data *d = elf_rawdata (scn, NULL);
+  if (d == NULL)
+    return -1;
+
+  if (d->d_size >= 4 + 8
+      && memcmp (d->d_buf, "ZLIB", 4) == 0)
+    {
+      /* There is a 12-byte header of "ZLIB" followed by
+	 an 8-byte big-endian size.  There is only one type and
+	 alignment isn't preserved separately.  */
+      uint64_t size;
+      memcpy (&size, d->d_buf + 4, sizeof size);
+      size = be64toh (size);
+
+      /* One more sanity check, size should be bigger than original
+	 data size plus some overhead (4 chars ZLIB + 8 bytes size + 6
+	 bytes zlib stream overhead + 5 bytes overhead max for one 16K
+	 block) and should fit into a size_t.  */
+      if (size + 4 + 8 + 6 + 5 < d->d_size || size > SIZE_MAX)
+	return -1;
+
+      return size;
+    }
+
+  return -1;
+}
diff --git a/libdwelf/dwelf_strtab.c b/libdwelf/dwelf_strtab.c
new file mode 100644
index 0000000..c95f946
--- /dev/null
+++ b/libdwelf/dwelf_strtab.c
@@ -0,0 +1,358 @@
+/* ELF/DWARF string table handling.
+   Copyright (C) 2000, 2001, 2002, 2005, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdwelfP.h"
+#include <system.h>
+
+
+struct Dwelf_Strent
+{
+  const char *string;
+  size_t len;
+  struct Dwelf_Strent *next;
+  struct Dwelf_Strent *left;
+  struct Dwelf_Strent *right;
+  size_t offset;
+  char reverse[0];
+};
+
+
+struct memoryblock
+{
+  struct memoryblock *next;
+  char memory[0];
+};
+
+
+struct Dwelf_Strtab
+{
+  struct Dwelf_Strent *root;
+  struct memoryblock *memory;
+  char *backp;
+  size_t left;
+  size_t total;
+  bool nullstr;
+
+  struct Dwelf_Strent null;
+};
+
+
+/* Cache for the pagesize.  */
+static size_t ps;
+/* We correct this value a bit so that `malloc' is not allocating more
+   than a page. */
+#define MALLOC_OVERHEAD (2 * sizeof (void *))
+
+
+Dwelf_Strtab *
+dwelf_strtab_init (bool nullstr)
+{
+  if (ps == 0)
+    {
+      ps = sysconf (_SC_PAGESIZE);
+      assert (sizeof (struct memoryblock) < ps - MALLOC_OVERHEAD);
+    }
+
+  Dwelf_Strtab *ret = calloc (1, sizeof (struct Dwelf_Strtab));
+  if (ret != NULL)
+    {
+      ret->nullstr = nullstr;
+
+      if (nullstr)
+	{
+	  ret->null.len = 1;
+	  ret->null.string = "";
+	}
+    }
+
+  return ret;
+}
+
+
+static int
+morememory (Dwelf_Strtab *st, size_t len)
+{
+  size_t overhead = offsetof (struct memoryblock, memory);
+  len += overhead + MALLOC_OVERHEAD;
+
+  /* Allocate nearest multiple of pagesize >= len.  */
+  len = ((len / ps) + (len % ps != 0)) * ps - MALLOC_OVERHEAD;
+
+  struct memoryblock *newmem = malloc (len);
+  if (newmem == NULL)
+    return 1;
+
+  newmem->next = st->memory;
+  st->memory = newmem;
+  st->backp = newmem->memory;
+  st->left = len - overhead;
+
+  return 0;
+}
+
+
+void
+dwelf_strtab_free (Dwelf_Strtab *st)
+{
+  struct memoryblock *mb = st->memory;
+
+  while (mb != NULL)
+    {
+      void *old = mb;
+      mb = mb->next;
+      free (old);
+    }
+
+  free (st);
+}
+
+
+static Dwelf_Strent *
+newstring (Dwelf_Strtab *st, const char *str, size_t len)
+{
+  /* Compute the amount of padding needed to make the structure aligned.  */
+  size_t align = ((__alignof__ (struct Dwelf_Strent)
+		   - (((uintptr_t) st->backp)
+		      & (__alignof__ (struct Dwelf_Strent) - 1)))
+		  & (__alignof__ (struct Dwelf_Strent) - 1));
+
+  /* Make sure there is enough room in the memory block.  */
+  if (st->left < align + sizeof (struct Dwelf_Strent) + len)
+    {
+      if (morememory (st, sizeof (struct Dwelf_Strent) + len))
+	return NULL;
+
+      align = 0;
+    }
+
+  /* Create the reserved string.  */
+  Dwelf_Strent *newstr = (Dwelf_Strent *) (st->backp + align);
+  newstr->string = str;
+  newstr->len = len;
+  newstr->next = NULL;
+  newstr->left = NULL;
+  newstr->right = NULL;
+  newstr->offset = 0;
+  for (int i = len - 2; i >= 0; --i)
+    newstr->reverse[i] = str[len - 2 - i];
+  newstr->reverse[len - 1] = '\0';
+  st->backp += align + sizeof (struct Dwelf_Strent) + len;
+  st->left -= align + sizeof (struct Dwelf_Strent) + len;
+
+  return newstr;
+}
+
+
+/* XXX This function should definitely be rewritten to use a balancing
+   tree algorithm (AVL, red-black trees).  For now a simple, correct
+   implementation is enough.  */
+static Dwelf_Strent **
+searchstring (Dwelf_Strent **sep, Dwelf_Strent *newstr)
+{
+  /* More strings?  */
+  if (*sep == NULL)
+    {
+      *sep = newstr;
+      return sep;
+    }
+
+  /* Compare the strings.  */
+  int cmpres = memcmp ((*sep)->reverse, newstr->reverse,
+		       MIN ((*sep)->len, newstr->len) - 1);
+  if (cmpres == 0)
+    /* We found a matching string.  */
+    return sep;
+  else if (cmpres > 0)
+    return searchstring (&(*sep)->left, newstr);
+  else
+    return searchstring (&(*sep)->right, newstr);
+}
+
+
+/* Add new string.  The actual string is assumed to be permanent.  */
+static Dwelf_Strent *
+strtab_add (Dwelf_Strtab *st, const char *str, size_t len)
+{
+  /* Make sure all "" strings get offset 0 but only if the table was
+     created with a special null entry in mind.  */
+  if (len == 1 && st->null.string != NULL)
+    return &st->null;
+
+  /* Allocate memory for the new string and its associated information.  */
+  Dwelf_Strent *newstr = newstring (st, str, len);
+  if (newstr == NULL)
+    return NULL;
+
+  /* Search in the array for the place to insert the string.  If there
+     is no string with matching prefix and no string with matching
+     leading substring, create a new entry.  */
+  Dwelf_Strent **sep = searchstring (&st->root, newstr);
+  if (*sep != newstr)
+    {
+      /* This is not the same entry.  This means we have a prefix match.  */
+      if ((*sep)->len > newstr->len)
+	{
+	  /* Check whether we already know this string.  */
+	  for (Dwelf_Strent *subs = (*sep)->next; subs != NULL;
+	       subs = subs->next)
+	    if (subs->len == newstr->len)
+	      {
+		/* We have an exact match with a substring.  Free the memory
+		   we allocated.  */
+		st->left += st->backp - (char *) newstr;
+		st->backp = (char *) newstr;
+
+		return subs;
+	      }
+
+	  /* We have a new substring.  This means we don't need the reverse
+	     string of this entry anymore.  */
+	  st->backp -= newstr->len;
+	  st->left += newstr->len;
+
+	  newstr->next = (*sep)->next;
+	  (*sep)->next = newstr;
+	}
+      else if ((*sep)->len != newstr->len)
+	{
+	  /* When we get here it means that the string we are about to
+	     add has a common prefix with a string we already have but
+	     it is longer.  In this case we have to put it first.  */
+	  st->total += newstr->len - (*sep)->len;
+	  newstr->next = *sep;
+	  newstr->left = (*sep)->left;
+	  newstr->right = (*sep)->right;
+	  *sep = newstr;
+	}
+      else
+	{
+	  /* We have an exact match.  Free the memory we allocated.  */
+	  st->left += st->backp - (char *) newstr;
+	  st->backp = (char *) newstr;
+
+	  newstr = *sep;
+	}
+    }
+  else
+    st->total += newstr->len;
+
+  return newstr;
+}
+
+Dwelf_Strent *
+dwelf_strtab_add (Dwelf_Strtab *st, const char *str)
+{
+  return strtab_add (st, str, strlen (str) + 1);
+}
+
+Dwelf_Strent *
+dwelf_strtab_add_len (Dwelf_Strtab *st, const char *str, size_t len)
+{
+  return strtab_add (st, str, len);
+}
+
+static void
+copystrings (Dwelf_Strent *nodep, char **freep, size_t *offsetp)
+{
+  if (nodep->left != NULL)
+    copystrings (nodep->left, freep, offsetp);
+
+  /* Process the current node.  */
+  nodep->offset = *offsetp;
+  *freep = (char *) mempcpy (*freep, nodep->string, nodep->len);
+  *offsetp += nodep->len;
+
+  for (Dwelf_Strent *subs = nodep->next; subs != NULL; subs = subs->next)
+    {
+      assert (subs->len < nodep->len);
+      subs->offset = nodep->offset + nodep->len - subs->len;
+      assert (subs->offset != 0 || subs->string[0] == '\0');
+    }
+
+  if (nodep->right != NULL)
+    copystrings (nodep->right, freep, offsetp);
+}
+
+
+Elf_Data *
+dwelf_strtab_finalize (Dwelf_Strtab *st, Elf_Data *data)
+{
+  size_t nulllen = st->nullstr ? 1 : 0;
+
+  /* Fill in the information.  */
+  data->d_buf = malloc (st->total + nulllen);
+  if (data->d_buf == NULL)
+    return NULL;
+
+  /* The first byte must always be zero if we created the table with a
+     null string.  */
+  if (st->nullstr)
+    *((char *) data->d_buf) = '\0';
+
+  data->d_type = ELF_T_BYTE;
+  data->d_size = st->total + nulllen;
+  data->d_off = 0;
+  data->d_align = 1;
+  data->d_version = EV_CURRENT;
+
+  /* Now run through the tree and add all the string while also updating
+     the offset members of the elfstrent records.  */
+  char *endp = (char *) data->d_buf + nulllen;
+  size_t copylen = nulllen;
+  if (st->root)
+    copystrings (st->root, &endp, &copylen);
+  assert (copylen == st->total + nulllen);
+
+  return data;
+}
+
+
+size_t
+dwelf_strent_off (Dwelf_Strent *se)
+{
+  return se->offset;
+}
+
+
+const char *
+dwelf_strent_str (Dwelf_Strent *se)
+{
+  return se->string;
+}
diff --git a/libdwelf/libdwelf.h b/libdwelf/libdwelf.h
new file mode 100644
index 0000000..263ca60
--- /dev/null
+++ b/libdwelf/libdwelf.h
@@ -0,0 +1,147 @@
+/* Interfaces for libdwelf. DWARF ELF Low-level Functions.
+   Copyright (C) 2014, 2015, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBDWELF_H
+#define _LIBDWELF_H	1
+
+#include "libdw.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* DWARF ELF Low-level Functions (dwelf).
+   Functions starting with dwelf_elf will take a (libelf) Elf object as
+   first argument and might set elf_errno on error.  Functions starting
+   with dwelf_dwarf will take a (libdw) Dwarf object as first argument
+   and might set dwarf_errno on error.  */
+
+/* Returns the name and the CRC32 of the separate debug file from the
+   .gnu_debuglink section if found in the ELF.  Return NULL if the ELF
+   file didn't have a .gnu_debuglink section, had malformed data in the
+   section or some other error occurred.  */
+extern const char *dwelf_elf_gnu_debuglink (Elf *elf, GElf_Word *crc);
+
+/* Returns the name and build ID from the .gnu_debugaltlink section if
+   found in the ELF.  On success, pointers to the name and build ID
+   are written to *NAMEP and *BUILDID_P, and the positive length of
+   the build ID is returned.  Returns 0 if the ELF lacks a
+   .gnu_debugaltlink section.  Returns -1 in case of malformed data or
+   other errors.  */
+extern ssize_t dwelf_dwarf_gnu_debugaltlink (Dwarf *dwarf,
+					     const char **namep,
+					     const void **build_idp);
+
+/* Returns the build ID as found in a NT_GNU_BUILD_ID note from either
+   a SHT_NOTE section or from a PT_NOTE segment if the ELF file
+   doesn't contain any section headers.  On success a pointer to the
+   build ID is written to *BUILDID_P, and the positive length of the
+   build ID is returned.  Returns 0 if the ELF lacks a NT_GNU_BUILD_ID
+   note.  Returns -1 in case of malformed data or other errors.  */
+extern ssize_t dwelf_elf_gnu_build_id (Elf *elf, const void **build_idp);
+
+/* Returns the size of the uncompressed data of a GNU compressed
+   section.  The section name should start with .zdebug (but this
+   isn't checked by this function).  If the section isn't compressed
+   (the section data doesn't start with ZLIB) -1 is returned. If an
+   error occurred -1 is returned and elf_errno is set.  */
+extern ssize_t dwelf_scn_gnu_compressed_size (Elf_Scn *scn);
+
+/* ELF/DWARF string table handling.  */
+typedef struct Dwelf_Strtab Dwelf_Strtab;
+typedef struct Dwelf_Strent Dwelf_Strent;
+
+/* Create a new ELF/DWARF string table object in memory.  ELF string
+   tables have a required zero length null string at offset zero.
+   DWARF string tables don't require such a null entry (unless they
+   are shared with an ELF string table).  If NULLSTR is true then a
+   null entry is always created (even if the string table is empty
+   otherwise).  */
+extern Dwelf_Strtab *dwelf_strtab_init (bool nullstr);
+
+/* Add string STR to string table ST.  Returns NULL if no memory could
+   be allocated.  The given STR is owned by the called and must be
+   valid till dwelf_strtab_free is called.  dwelf_strtab_finalize
+   might copy the string into the final table and dwelf_strent_str
+   might return it, or a reference to an identical copy/substring
+   added to the string table.  */
+extern Dwelf_Strent *dwelf_strtab_add (Dwelf_Strtab *st, const char *str)
+  __nonnull_attribute__ (1, 2);
+
+/* This is an optimized version of dwelf_strtab_add if the length of
+   the string is already known.  LEN is the length of STR including
+   zero terminator.  Calling dwelf_strtab_add (st, str) is similar to
+   calling dwelf_strtab_len (st, str, strlen (str) + 1).  */
+extern Dwelf_Strent *dwelf_strtab_add_len (Dwelf_Strtab *st,
+					   const char *str, size_t len)
+  __nonnull_attribute__ (1, 2);
+
+/* Finalize string table ST and store size and memory location
+   information in DATA d_size and d_buf.  DATA d_type will be set to
+   ELF_T_BYTE, d_off will be zero, d_align will be 1 and d_version
+   will be set to EV_CURRENT.  If no memory could be allocated NULL is
+   returned and DATA->d_buf will be set to NULL.  Otherwise DATA will
+   be returned.  */
+extern Elf_Data *dwelf_strtab_finalize (Dwelf_Strtab *st,
+					Elf_Data *data)
+  __nonnull_attribute__ (1, 2);
+
+/* Get offset in string table for string associated with entry.  Only
+   valid after dwelf_strtab_finalize has been called.  */
+extern size_t dwelf_strent_off (Dwelf_Strent *se)
+  __nonnull_attribute__ (1);
+
+/* Return the string associated with the entry.  */
+extern const char *dwelf_strent_str (Dwelf_Strent *se)
+  __nonnull_attribute__ (1);
+
+/* Free resources allocated for the string table.  This invalidates
+   any Dwelf_Strent references returned earlier. */
+extern void dwelf_strtab_free (Dwelf_Strtab *st)
+  __nonnull_attribute__ (1);
+
+/* Creates a read-only Elf handle from the given file handle.  The
+   file may be compressed and/or contain a linux kernel image header,
+   in which case it is eagerly decompressed in full and the Elf handle
+   is created as if created with elf_memory ().  On decompression or
+   file errors NULL is returned (and elf_errno will be set).  If there
+   was no error, but the file is not an ELF file, then an ELF_K_NONE
+   Elf handle is returned (just like with elf_begin).  The Elf handle
+   should be closed with elf_end ().  The file handle will not be
+   closed.  */
+extern Elf *dwelf_elf_begin (int fd);
+
+/* Returns a human readable string for the given ELF header e_machine
+   value, or NULL if the given number isn't currently known.  */
+extern const char *dwelf_elf_e_machine_string (int machine);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* libdwelf.h */
diff --git a/libdwelf/libdwelfP.h b/libdwelf/libdwelfP.h
new file mode 100644
index 0000000..faaf1a2
--- /dev/null
+++ b/libdwelf/libdwelfP.h
@@ -0,0 +1,42 @@
+/* Internal definitions for libdwelf. DWARF ELF Low-level Functions.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBDWELFP_H
+#define _LIBDWELFP_H	1
+
+#include <libdwelf.h>
+#include "libdwP.h"	/* We need its INTDECLs.  */
+#include <assert.h>
+#include <string.h>
+
+/* Avoid PLT entries.  */
+INTDECL (dwelf_elf_gnu_debuglink)
+INTDECL (dwelf_dwarf_gnu_debugaltlink)
+INTDECL (dwelf_elf_gnu_build_id)
+
+#endif	/* libdwelfP.h */
diff --git a/libdwfl/ChangeLog b/libdwfl/ChangeLog
new file mode 100644
index 0000000..abbf0df
--- /dev/null
+++ b/libdwfl/ChangeLog
@@ -0,0 +1,3628 @@
+2023-09-27  Omar Sandoval  <osandov@fb.com>
+	* dwfl_module.c (__libdwfl_module_free): Free mod->elfpath instead of
+	mod->elfdir.
+	* dwfl_module_getdwarf.c (load_dw): Set mod->dw->elfpath and call
+	__libdw_set_debugdir instead of setting mod->dw->debugdir.
+	* libdwflP.h (Dwfl_Module): Replace elfdir with elfpath.
+	* offline.c (process_elf): Call __libdw_elfpath and set mod->elfpath
+	instead of mod->elfdir.
+
+2023-04-24  John Gallagher  <john@gllghr.com>
+
+	* gzip.c: Fix memory leak in unzip()
+
+2023-02-06  Mark Wielaard  <mark@klomp.org>
+
+	* libdwfl.h: Guard debuginfod_client typedef with
+	_ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF.
+
+2022-12-21  Mark Wielaard  <mark@klomp.org>
+
+	* core-file.c: Don't undef _.
+	* dwfl_segment_report_module.c: Likewise.
+	* elf-from-memory.c: Likewise.
+	* open.c: Likewise.
+
+2022-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (AM_CPPFLAGS): debuginfod.h is in builddir.
+	* core-file.c: Include libelfP.h.
+	* cu.c: Include libdwP.h and memory-access.h.
+	* debuginfod-client.c: Include debuginfod.h.
+	* dwfl_dwarf_line.c: Include libdwP.h.
+	* dwfl_lineinfo.c: Include libdwP.h.
+	* dwfl_module.c: Include cfi.h.
+	* dwfl_module_dwarf_cfi.c: Include cfi.h.
+	* dwfl_module_eh_cfi.c: Include cfi.h.
+	* dwfl_module_getdwarf.c: Include libdwP.h and libelfP.h.
+	* dwfl_module_getsrc.c: Include libdwP.h.
+	* dwfl_module_getsrc_file.c: Include libdwP.h.
+	* dwfl_segment_report_module.c: Include libelfP.h.
+	* elf-from-memory.c: Include libelfP.h.
+	* frame_unwind.c: Include dwarf.h.
+	* libdwflP.h: Include libdwP.h and libdwelfP.h. Don't include
+	debuginfod.h.
+	* lines.c: Include libdwP.h.
+	* link_map.c: Include memory-access.h.
+	* linux-core-attach.c: Include memory-access.h.
+	* open.c: Include libelfP.h.
+
+2022-11-28  Gavin Li  <gavin@matician.com>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Remove
+	data size check after read_portion memory_callback.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* argp-std.c: Don't include unistd.h.
+	* core-file.c: Don't include unistd.h, endian.h, byteswap.h and
+	system.h.
+	* dwfl_build_id_find_debuginfo.c: Don't include unistd.h.
+	* dwfl_build_id_find_elf.c: Likewise.
+	* dwfl_end.c: Likewise.
+	* dwfl_frame.c: Likewise.
+	* dwfl_module.c: Likewise.
+	* dwfl_module_getdwarf.c: Likewise.
+	* dwfl_report_elf.c: Likewise.
+	* dwfl_segment_report_module.c: Don't include endian.h and unistd.h.
+	* find-debuginfo.c: Don't include unistd.h.
+	* gzip.c: Likewise.
+	* image-header.c: Don't include system.h, unistd.h and endian.h.
+	* link_map.c: Don't include byteswap.h and endian.h.
+	* linux-pid-attach.c: Don't include unistd.h.
+	* offline.c: Likewise.
+	* open.c: Likewise.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* libdwfl_crc32.c: Remove LIB_SYSTEM_H define.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* dwfl_segment_report_module.c: Use BYTE_ORDER, LITTLE_ENDIAN and
+	BIG_ENDIAN.
+
+2022-09-13  Aleksei Vetrov  <vvvvvv@google.com>
+
+	* libdwfl.h (dwfl_report_offline_memory): New function.
+	* libdwflP.h (__libdw_open_elf_memory): New internal function.
+	(dwfl_report_offline_memory): INTDECL.
+	* offline.c (dwfl_report_offline_memory): New function.
+	* open.c (decompress): Return DWFL_E_BADELF when fd is -1.
+	(libdw_open_elf): New argument use_elfp. Adding *elfp to elf if
+	true.
+	(__libdw_open_file): Pass false to libdw_open_elf.
+	(__libdw_open_elf_memory): New function.
+	(__libdw_open_elf): Pass false for libdw_open_elf.
+
+2022-07-28  Di Chen  <dichen@redhat.com>
+
+	* libdwfl.h (dwfl_frame_reg): New function.
+	* libdwflP.h (DWFL_E_REGISTER_VAL_UNKNOWN): New error code.
+	(__libdwfl_frame_reg_get): Return an int.
+	(dwfl_frame_reg): INTDECL.
+	* dwfl_frame_regs.c (dwfl_frame_reg): New function.
+	* frame_unwind.c (__libdwfl_frame_reg_get): Return an int.
+	(state_get_reg): Removed.
+	(expr_eval): Use INTUSE (dwfl_frame_reg) instead of state_get_reg.
+	(handle_cfi): Likewise.
+	(getfunc): Likewise.
+	* linux-core-attach.c (core_set_initial_registers): Check
+	__libdwfl_frame_reg_get returns zero.
+
+2022-07-28  Mark Wielaard  <mark@klomp.org>
+
+	* core-file.c (elf_begin_rand): Replace struct ar_hdr h with
+	a char ar_size[AR_SIZE_CHARS + 1] array to read size.
+
+2022-07-18  Shahab Vahedi  <shahab@synopsys.com>
+
+	* debuginfod-client.c (dwfl_get_debuginfod_client stub):
+	Add a name to the sole parameter.
+
+2022-07-13  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (dwfl_get_debuginfod_client): Add INTDEF.
+	(__libdwfl_debuginfod_find_executable): Use
+	INTUSE (dwfl_get_debuginfod_client).
+	(__libdwfl_debuginfod_find_debuginfo): Likewise.
+
+2022-06-22  Milian Wolff <mail@milianw.de>
+
+	* libdwfl.h, debuginfod-client.c (dwfl_get_debuginfod_client):
+	Rename get_client to dwfl_get_debuginfod_client and make it public.
+
+2022-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* libdwfl.h (dwfl_module_addrinfo): Update docs and nonnull
+	attribute to make clear offset and sym cannot be NULL.
+
+2022-04-22  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-client.c (init_control): New static pthread_once_t.
+	(get_client): Use pthread_once to call __libdwfl_debuginfod_init.
+	(__libdwfl_debuginfod_init): Make static, remove attribute
+	constructor.
+
+2022-02-18  Mark Wielaard  <mark@klomp.org>
+
+	* image-header.c (__libdw_image_header): Assign header values for
+	magic1, magic2, version, offset, length and sects using memcpy.
+
+2022-02-18  Mark Wielaard  <mark@klomp.org>
+
+	* offline.c (process_archive_member): Close member if process_file
+	failed.
+
+2022-01-03  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Only declare d32 and d64 before
+	actual use.
+
+2022-01-03  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Copy
+	dyn_data and set xlatefrom.d_buf to dyns when dyns is not aligned.
+
+2022-01-03  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (read_addrs): Fix buffer_available nb overflow.
+
+2021-12-23  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (read_addrs): Calculate addr to read by hand.
+
+2021-12-23  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Call memcpy and set in.d_buf to
+	out.d_buf before calling xlatetom for unaligned buffers.
+
+2021-12-23  Mark Wielaard  <mark@klomp.org>
+
+	* core-file.c (dwfl_elf_phdr_memory_callback): Check start <
+	elf->maximum_size and end - start < minread.
+
+2021-12-20  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Move
+	and initialize struct elf_build_id build_id early. Only free memory
+	early when no longer needed. Free memory if not NULL at out.
+
+2021-12-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Copy
+	data and set xlatefrom.d_buf to notes when data is not aligned.
+
+2021-12-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Copy
+	ph_buffer and set xlatefrom.d_buf to phdrsp when ph_buffer is not
+	aligned.
+
+2021-12-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Copy
+	buffer and set xlatefrom.d_buf to ehdr when buffer is not aligned.
+
+2021-12-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Check
+	notes filesz. Rewrite reading of GElf_Nhdr.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Make sure
+	that dyn_filesz can contain at least one Elf_Dyn and isn't larger than
+	possible.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Make sure
+	that ph_buffer_size has room for at least one phdr.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Make
+	sure the note len increases each iteration.
+
+2021-12-17  Mark Wielaard  <mark@klomp.org>
+
+	* libdwflP.h (dwfl_segment_report_module): Add maxread argument.
+	* core-file.c (dwfl_core_file_report): Pass elf->maximum_size to
+	dwfl_segment_report_module.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Add
+	maxread argument. Check file_trimmed_end against maxread.
+
+2021-12-16  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Check
+	note data is properly aligned.
+
+2021-12-16  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Make sure phnum is non-zero.
+
+2021-12-16  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Make sure dyn_filesz / entsize is
+	non-zero.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Add
+	len overflow check while iterating notes.
+
+2021-12-15  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Make sure phent is either sizeof
+	Elf32_Phdr or sizeof Elf64_Phdr. Check in.d_size can hold at least one
+	Phdr.
+
+2021-12-12  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Don't
+	allocate more than SIZE_MAX.
+
+2021-12-09  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Limit dyn_filesz malloc size
+	to max possible. When converting make sure we don't exceed the number
+	of bytes available in either in.d_buf or out.d_buf.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Check
+	Dwfl_Module isn't associated with an Elf before installing it.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Don't
+	trust e_shentsize.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Make sure phent != 0.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (dwfl_link_map_report): Limit malloc size to max
+	possible. When converting make sure we don't exceed the number
+	of bytes available in either in.d_buf nor out.d_buf.
+
+2021-12-08  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Don't
+	read beyond of (actual) end of (memory) file.
+
+2021-11-18  Matthias Maennich  <maennich@google.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_modules):
+	Add one to modname array size.
+
+2021-02-14  Alexander Miller  <alex.miller@gmx.de>
+
+	* core-file.c (dwfl_core_file_report): Move NEW_VERSION before
+	definition.  Replace INTDEF with NEW_INTDEF.
+	* dwfl_module_build_id.c (dwfl_module_build_id): Likewise.
+	* dwfl_report_elf.c (dwfl_report_elf): Likewise.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* linux-pid-attach.c (read_cached_memory): Remove cast of malloc
+	return value.
+
+2021-06-09  Omar Sandoval  <osandov@fb.com>
+
+	* link_map.c (read_addrs): Fix potential NULL pointer dereference.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* dwfl_frame.c (dwfl_attach_state): Use startswith.
+	* dwfl_module_getdwarf.c (find_symtab): Likewise.
+	* linux-kernel-modules.c: Likewise.
+	* linux-pid-attach.c (linux_proc_pid_is_stopped): Likewise.
+	(dwfl_linux_proc_attach): Likewise.
+	* relocate.c (resolve_symbol): Likewise.
+	(relocate_section): Likewise.
+
+2021-02-01  Érico Nogueira  <ericonr@disroot.org>
+
+	* dwfl_error.c (strerror_r): Only use the GNU version when available.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Add for loop over
+	switch. inline handle_segment call, set vaddr, offset and filesz
+	directly based on class.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Use if instead of
+	switch on class. Set new vaddr, memsz, offset and filesz
+	variables. Inline handle_segment function check and set loadbase,
+	found_base, segments_end and segments_end_mem directly.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* argp-std.c (_): Remove.
+	* libdwflP.h (_): Likewise.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* libdwfl.h: Fix spelling typos in comments.
+	* dwfl_module_getdwarf.c (open_elf, find_symtab): Likewise.
+	* dwfl_report_elf.c (__libdwfl_elf_address_range): Likewise.
+	* linux-pid-attach.c (read_cached_memory): Likewise.
+
+2020-12-07  Timm Bäder  <tbaeder@redhat.com>
+
+	* link_map.c (report_r_debug): Pull read_addrs() function into
+	file scope.
+
+2020-12-07  Timm Bäder  <tbaeder@redhat.com>
+
+	* link_map.c (report_r_debug): Pull release_buffer() function into
+	file scope. Add memory_closure struct.
+
+2020-12-08  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* debuginfod-client.c (__libdwfl_debuginfod_init): Replace
+	"libdebuginfod-" VERSION ".so" with DEBUGINFOD_SONAME in dlopen call.
+	Do not fall back to dlopen of "libdebuginfod.so".
+
+2020-12-01  Timm Bäder  <tbaeder@redhat.com>
+
+	* link_map.c (dwfl_link_map_report): Removed consider_phdr function
+	and inline code.
+
+2020-11-28  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Use GElf_Addr to calculate note_vaddr instead of size_t.
+
+2020-11-26  Timm Bäder  <tbaeder@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Remove consider_notes function. Inline code for type == PT_NOTE.
+
+2020-11-26  Timm Bäder  <tbaeder@redhat.com>
+
+	* dwfl_segment_report_module.c (read_portion): New static function.
+	(dwfl_segment_report_module): Remove read_portion function.
+	Call static function with read_state, start and segment.
+
+2020-11-26  Timm Bäder  <tbaeder@redhat.com>
+
+	* dwfl_segment_report_module.c (struct read_state): New.
+	(finish_portion): New static function.
+	(dwfl_segment_report_module): Introduce read_state. Remove
+	finish_portion function. Call static function with read_state.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Remove
+	consider_phdr, do checks inline.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Remove
+	consider_dyn, do checks inline.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Do one
+	loop check for d32/d64 arrays.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Remove
+	read_phdr, do check and call memory_callback directly.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Do one
+	loop check for p32/p64 arrays.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Remove
+	final_read, call memory_callback directly.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (struct elf_build_id): New.
+	(dwfl_segment_report_module): Pass build_id as struct.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Remove
+	release_buffer, call memory_callback directly.
+
+2020-11-23  Timm Bäder  <tbaeder@redhat.com>
+
+	* segment_report_module.c (dwfl_segment_report_module): Remove
+	segment_read, call memory_callback directly.
+
+2020-11-19  Andreas Krebbel  <krebbel@linux.ibm.com>
+
+	* linux-pid-attach.c (pid_memory_read): Shift the upper 4 bytes
+	down on big endian 64 bit targets.
+
+2020-11-12  Timm Bäder <tbaeder@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Remove
+	finish function, replace with goto out.
+
+2020-11-12  Timm Bäder <tbaeder@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Declare
+	p32 and p64 as pointers instead of arrays.
+
+2020-09-18  Mark Wielaard  <mark@klomp.org>
+
+	* zstd.c: New file.
+	* libdwflP.h: Add DWFL_E_ZSTD and __libdw_unzstd.
+	* Makefile.am (libdwfl_a_SOURCES): add zstd.c if ZSTD.
+	* gzip.c: Add defines and includes for ZSTD.
+	(zlib_fail): Don't define for ZSTD.
+	(unzip): Change pread_retry failure from zlib_fail to fail.
+	Add ZSTD support.
+	* open.c (decompress): Also try __libdw_unzstd.
+	* linux-kernel-modules.c (check_suffix): Also TRY ".ko.zst".
+
+2020-08-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (libdwfl_a_SOURCES): Conditionalize
+	debuginfod-client.c on LIBDEBUGINFOD.
+	* dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Conditionalize
+	__libdwfl_debuginfod_find_executable invocation on
+	ENABLE_LIBDEBUGINFOD.
+	* dwfl_end.c (dwfl_end): Conditionalize __libdwfl_debuginfod_end
+	invocation on ENABLE_LIBDEBUGINFOD.
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Conditionalize
+	__libdwfl_debuginfod_find_debuginfo invocation on
+	ENABLE_LIBDEBUGINFOD.
+	* libdwflP.h: Guard debuginfod.h include with ENABLE_LIBDEBUGINFOD.
+	(struct Dwfl): Guard debuginfod field with ENABLE_LIBDEBUGINFOD.
+	(__libdwfl_debuginfod_find_executable,
+	__libdwfl_debuginfod_find_debuginfo, __libdwfl_debuginfod_end):
+	Guard declarations with ENABLE_LIBDEBUGINFOD.
+
+2020-07-05  Mark Wielaard  <mark@klomp.org>
+
+	* argp-std.c (parse_opt): Don't assert, but call fail when
+	dwfl_report_end fails.
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Don't
+	assert, but goto bad_id when snprintf fails.
+	* frame_unwind.c (__libdwfl_frame_unwind): Don't assert, but
+	return when dwfl_frame_pc fails.
+	* linux-core-attach.c (core_set_initial_registers): Don't assert,
+	but return false when gelf_getnote fails or the core note is not
+	as expected.
+	* linux-pid-attach.c (dwfl_linux_proc_attach): Don't assert, but
+	goto fail when snprintf fails.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* frame_unwind.c (handle_cfi): Flag an error if
+	return_address_register is invalid.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* linux-kernel-modules.c (try_kernel_name): Don't try other
+	compressed kernels if we already found an compressed image.
+
+2020-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Return failure
+	when mod is NULL.
+
+2020-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* libdwfl/core-file.c (dwfl_core_file_report): Keep track of
+	new bool cleanup_user_core and cleanup dwfl->user_core in error
+	case.
+
+2020-04-30  Mark Wielaard  <mark@klomp.org>
+
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): When mod->dw
+	is already set then try fetching debugaltlink.
+
+2020-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* gzip.c (open_stream): Return DWFL_E_NOMEM instead of calling
+	zlib_fail.
+
+2020-04-16  Mark Wielaard  <mark@klomp.org>
+
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Initialize bits
+	to NULL.
+
+2020-01-24  Mark Wielaard  <mark@klomp.org>
+
+	* linux-kernel-modules.c (find_kernel_elf): Check release isn't NULL.
+	(report_kernel): Check release and *release aren't NULL.
+	(report_kernel_archive): Likewise.
+
+2019-12-11  Omar Sandoval  <osandov@fb.com>
+
+	* libdwflP.h (Dwfl_Module): Remove coalescing state.
+	Rename lookup_tail_ndx to next_segndx.
+	* segment.c (dwfl_report_segment): Remove coalescing logic.
+	* libdwfl.h (dwfl_report_segment): Document that IDENT is ignored.
+
+2019-12-05  Mark Wielaard  <mark@klomp.org>
+
+	* linux-kernel-modules.c (find_kernel_elf): Also try to find
+	vmlinux image.
+
+2019-10-28  Aaron Merey  <amerey@redhat.com>
+
+	* dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Call debuginfod
+	client functions via dlopen to look for elf/dwarf files as fallback.
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Ditto.
+
+2019-10-07  Omar Sandoval  <osandov@fb.com>
+
+	* dwfl_frame.c (dwfl_getthreads): Get rid of unnecessary
+	thread_free_all_states calls.
+	(getthread): Ditto.
+	(state_free): Remove function.
+	(thread_free_all_states): Remove function.
+	(free_states): Add function.
+	(dwfl_thread_getframes): Don't update thread->unwound while unwinding.
+	* libdwflP.h (struct Dwfl_Thread): Update comment for unwound member.
+
+2019-08-12  Mark Wielaard  <mark@klomp.org>
+
+	* gzip.c (open_stream): Return DWFL_E_ERRNO on bad file operation.
+	* open.c (libdw_open_elf): New argument bad_elf_ok. Check it and
+	return DWFL_E_NOERROR in case it is set and error was DWFL_E_BADELF.
+	(__libdw_open_file): Call libdw_open_elf with bad_elf_ok false.
+	(__libdw_open_elf): Call libdw_open_elf with bad_elf_ok true.
+
+2019-08-05  Omar Sandoval  <osandov@fb.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Assign
+	mod->main.fd.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* frame_unwind.c (expr_eval): Make sure we left shift a unsigned
+	64bit value.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* cu.c (addrarange): Only call realloc when naranges is not zero.
+
+2019-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Check
+	ph_buffer_size vs xlatefrom.d_size after read_portion call.
+
+2019-02-24  Mark Wielaard  <mark@klomp.org>
+
+	* linux-kernel-modules.c (intuit_kernel_bounds): Init *notes before
+	fopen.
+	(dwfl_linux_kernel_report_kernel): Remove fake note init empty asm.
+
+2019-01-25  Yonghong Song  <yhs@fb.com>
+
+	* linux-proc-maps.c (proc_maps_report): Use PRIu64, not PRIi64, to
+	read the inode number.
+
+2019-01-20  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Check
+	dyn_filesz vs dyn_data_size after read_portion call.
+
+2019-01-16  Mark Wielaard  <mark@klomp.org>
+
+	* linux-core-attach.c (core_next_thread): Pass desc to ebl_core_note.
+	(core_set_initial_registers): Likewise.
+
+2018-10-23  Mark Wielaard  <mark@klomp.org>
+
+	* relocate.c (relocate_section): Only sanity check mmapped Elf files
+	for overlap. Don't error when section data was malloced, not mmapped.
+
+2018-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* libdwflP.h (__libdw_open_elf): New internal function declaration.
+	* open.c (what_kind): Rename close_fd to may_close_fd.
+	(__libdw_open_file): Replaced (and renamed) by a call to ...
+	(libdw_open_elf): this. And add never_close_fd argument.
+	(__libdw_open_elf): New function that calls libdw_open_elf.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (consider_note): Take align as new
+	argument.  Use align to set d_type and calculate padding.
+	(dwfl_segment_report_module): Pass align to consider_notes.
+	* core-file.c (dwfl_core_file_report): Check p_align to set ELF
+	type.
+	* linux-kernel-modules.c (check_notes): Check name and type of note
+	to determine padding.
+
+2018-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_module_getdwarf.c (find_aux_sym): Check sh_entsize is not zero.
+
+2018-10-14  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (read_portion): Check requested
+	filesz isn't larger than buffer_available.
+	(dwfl_segment_report_module): Check data_size vs filesz after
+	read_portion call.
+
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+	* relocate.c (relocate): Handle ADD/SUB relocations.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Document why we use e_shnum directly.
+	* elf-from-memory.c (elf_from_remote_memory): Likewise.
+
+2018-07-17  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* linux-pid-attach.c: Include sys/uio.h only on linux.
+
+2018-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* libdwflP.h (__libdwfl_addrsym): Remove function declaration.
+	* dwfl_module_addrsym.c (__libdwfl_addrsym): Make a static function.
+
+2018-05-27  Mark Wielaard  <mark@klomp.org>
+
+	* relocate.c (__libdwfl_relocate): Always call relocate_section with
+	partial true.
+
+2018-05-17  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_module (__libdwfl_module_free): Free elfdir.
+	* dwfl_module_getdwarf.c (load_dw): Close file descriptors after
+	dwarf_begin_elf call. Set Dwarf debugdir if it is NULL, this is the
+	main module file and we recorded the elfdir.
+	* libdwflP.h (struct Dwfl_Module): Add elfdir field.
+	* offline.c (process_elf): Record the elfdir before we close the
+	main ELF file descriptor.
+
+2018-04-10  Mark Wielaard  <mark@klomp.org>
+
+	* frame_unwind.c (unwind): If __libdwfl_frame_reg_get fails for
+	the return address either set an error or mark the pc undefined.
+
+2018-03-17  Mark Wielaard  <mark@klomp.org>
+
+	* libdwflP.h (struct __libdwfl_remote_mem_cache): New.
+	(struct __libdwfl_pid_arg): Add mem_cache field.
+	* linux-pid-attach.c (read_cached_memory): New function.
+	(clear_cached_memory): Likewise.
+	(pid_memory_read): Call read_cached_memory.
+	(pid_detach): Free mem_cache.
+	(pid_thread_detach): Call clear_cached_memory.
+	(dwfl_linux_proc_attach): Initialize mem_cache to NULL.
+
+2018-03-05  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Use
+	realpath (name, NULL) instead of canonicalize_file_name (name).
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Likewise.
+
+2018-01-29  Mark Wielaard  <mark@klomp.org>
+
+	* cu.c (cudie_offset): Use __libdw_first_die_off_from_cu instead of
+	DIE_OFFSET_FROM_CU_OFFSET.
+	(intern_cu): Simply use a copy of the given die CU as key instead of
+	trying to construct a dummy one by hand.
+
+2018-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* linux-pid-attach.c: Include sys/wait.h after sys/ptrace.h.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* dwfl_report_elf.c (__libdwfl_elf_address_range): Use FALLTHROUGH
+	macro instead of comment.
+	* frame_unwind.c (expr_eval): Likewise.
+
+2017-11-20  Mark Wielaard  <mark@klomp.org>
+
+	* link_map.c (do_check64): Take a char * and calculate type and val
+	offsets before reading, possibly unaligned, values.
+	(do_check32): Likewise.
+	(check64): Remove define.
+	(check32): Likewise.
+	(auxv_format_probe): Call do_check32 and do_check64 directly with
+	a, possibly unaligned, auxv entry pointer.
+	(dwfl_link_map_report): Redefine AUXV_SCAN to not dereference a
+	possibly unaligned auxv entry pointer.
+
+2017-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* argp-std.c (parse_opt): For -k call argp_failure not failure to
+	keep dwfl around.
+
+2017-07-26  Yunlian Jiang  <yunlian@google.com>
+
+	* argp-std.c (failure): Move to file scope.
+	(fail): Likewise.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* derelocate.c (compare_secrefs): Compare by end address and then by
+	section number if addresses are equal.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* linux-kernel-modules.c: Always return NULL from kernel_release() on
+	non-linux systems and set errno to ENOTSUP.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libdwflP.h: Don't include config.h.
+	* argp-std.c: Include config.h.
+	* cu.c: Likewise.
+	* derelocate.c: Likewise.
+	* dwfl_addrdie.c: Likewise.
+	* dwfl_addrdwarf.c: Likewise.
+	* dwfl_addrmodule.c: Likewise.
+	* dwfl_begin.c: Likewise.
+	* dwfl_build_id_find_debuginfo.c: Likewise.
+	* dwfl_build_id_find_elf.c: Likewise.
+	* dwfl_cumodule.c: Likewise.
+	* dwfl_dwarf_line.c: Likewise.
+	* dwfl_end.c: Likewise.
+	* dwfl_frame.c: Likewise.
+	* dwfl_frame_regs.c: Likewise.
+	* dwfl_getdwarf.c: Likewise.
+	* dwfl_getmodules.c: Likewise.
+	* dwfl_getsrc.c: Likewise.
+	* dwfl_getsrclines.c: Likewise.
+	* dwfl_line_comp_dir.c: Likewise.
+	* dwfl_linecu.c: Likewise.
+	* dwfl_lineinfo.c: Likewise.
+	* dwfl_linemodule.c: Likewise.
+	* dwfl_module.c: Likewise.
+	* dwfl_module_addrdie.c: Likewise.
+	* dwfl_module_addrname.c: Likewise.
+	* dwfl_module_addrsym.c: Likewise.
+	* dwfl_module_build_id.c: Likewise.
+	* dwfl_module_dwarf_cfi.c: Likewise.
+	* dwfl_module_eh_cfi.c: Likewise.
+	* dwfl_module_getdarf.c: Likewise.
+	* dwfl_module_getelf.c: Likewise.
+	* dwfl_module_getsrc.c: Likewise.
+	* dwfl_module_getsrc_file.c: Likewise.
+	* dwfl_module_getsym.c: Likewise.
+	* dwfl_module_info.c: Likewise.
+	* dwfl_module_nextcu.c: Likewise.
+	* dwfl_module_register_names.c: Likewise.
+	* dwfl_module_report_build_id.c: Likewise.
+	* dwfl_module_return_value_location.c: Likewise.
+	* dwfl_nextcu.c: Likewise.
+	* dwfl_onesrcline.c: Likewise.
+	* dwfl_report_elf.c: Likewise.
+	* dwfl_validate_address.c: Likewise.
+	* dwfl_version.c: Likewise.
+	* find-debuginfo.c: Likewise.
+	* gzip.c: Likewise.
+	* image-header.c: Likewise.
+	* lines.c: Likewise.
+	* linux-core-attach.c: Likewise.
+	* linux-pid-attach.c: Likewise.
+	* offline.c: Likewise.
+	* open.c: Likewise.
+	* relocate.c: Likewise.
+	* segment.c: Likewise.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libdwfl.h: Use __const_attribute__.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* elf-from-memory.c: Explicitly cast phnum to size_t.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* dwfl_module_getdwarf.c: Check shnum for 0 before subtracting from
+	it.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* dwfl_frame.c: Drop unused sys/ptrace.h include.
+	* frame_unwind.c: Likewise.
+	* linux-pid-attach.c: Include sys/ptrace.h and sys/syscall.h only on
+	linux.
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* linux-kernel-modules.c: Include sys/types.h before fts.h
+
+2017-03-24  Mark Wielaard  <mark@klomp.org>
+
+	* linux-core-attach.c (core_next_thread): If n_namesz == 0 then
+	the note name data is the empty string.
+	(dwfl_core_file_attach): Likewise.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* linux-kernel-modules.c: Include system.h.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* linux-kernel-modules.c: Use sysconf(_SC_PAGESIZE) to get page size.
+	* linux-proc-maps.c: Likewise.
+
+2016-12-29  Luiz Angelo Daros de Luca  <luizluca@gmail.com>
+
+	* dwfl_build_id_find_elf.c: Include system.h.
+	* dwfl_module_getdwarf.c: Likewise.
+	* libdwfl_crc32_file.c: Don't define LIB_SYSTEM_H.
+
+2016-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c: Only include fts.h early if BAD_FTS is
+	defined.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* core-file.c: Remove sys/param.h.
+	* dwfl_segment_report_module.c: Likewise. Add system.h include.
+	(MAX): Remove definition.
+	* frame_unwind.c: Add system.h include.
+	(MAX): Remove definition.
+	* linux-core-attach.c (MIN): Remove definition.
+	* linux-pid-attach.c (MAX): Likewise.
+
+2016-08-12  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (dwfl_link_map_report): Fix assert, set in.d_size.
+
+2016-04-14  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getsrc_file.c (dwfl_module_getsrc_file): Free match
+	on invalid DWARF if we allocated it.
+
+2016-04-14  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (proc_maps_report): Free last_file on bad file
+	mapping.
+
+2016-03-01  Steven Chamberlain  <steven@pyro.eu.org>
+
+	* linux-pid-attach.c: Removed unused pid_thread_callbacks,
+	pid_thread_detach, pid_detach, pid_set_initial_registers,
+	pid_memory_read, pid_getthread, pid_next_thread in #ifndef
+	__linux__ code.
+
+2016-02-22  Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* find-debuginfo.c (find_debuginfo_in_path): Remember whether
+	debuglink_file is NULL. Try file basename (without .debug) ofr
+	absolute and relative path if debug_file was NULL.
+	* linux-kernel-modules.c (try_kernel_name): If try_debug is true call
+	dwfl_standard_find_debuginfo with NULL debuglink_file, otherwise with
+	basename of fname.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (proc_maps_report): Free last_file when ENOEXEC.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* frame_unwind.c (new_unwound): Check and return unwound.
+	(handle_cfi): Check new_unwound was able to allocate new memory
+	before use. Return DWFL_E_NOMEM otherwise.
+
+2016-02-11  Mark Wielaard  <mjw@redhat.com>
+
+	* relocate.c (relocate_section): Check result of all gelf_get* calls.
+	(__libdwfl_relocate): Likewise.
+	(__libdwfl_relocate_section): Likewise.
+
+2016-02-11  Mark Wielaard  <mjw@redhat.com>
+
+	* relocate.c (relocate_section): Check result of gelf_update_* calls.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwfl_a_SOURCES: Unconditionally add gzip.c.
+	* linux-kernel-modules.c (vmlinux_suffixes): We always have at least
+	.gz support.
+	(try_kernel_name): Likewise.
+	(check_suffix): Likewise.
+	* open.c (decompress): Likewise.
+
+2015-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Uncompress symstr, xndx, sym
+	sections and aux_str, aux_xndx and aux_sym sections if necessary.
+	* relocate.c (relocate_getsym): Uncompress symtab and symtab_shndx
+	if necessary.
+	(resolve_symbol): Uncompress strtab section if necessary.
+	(relocate_section): Uncompress the section the relocations apply to
+	if necessary.
+
+2015-11-18  Chih-Hung Hsieh <chh@google.com>
+
+	* linux-proc-maps.c (proc_maps_report): Move nested function
+	'report' to file scope.
+
+2015-11-18  Chih-Hung Hsieh <chh@google.com>
+
+	* core-file.c (elf_begin_rand): Move nested function 'fail' to file
+	scope.
+	* core-file.c (dwfl_elf_phdr_memory_callback): Move nested functions
+	'update_end' and 'more' to file scope.
+
+2015-11-17  Chih-Hung Hsieh <chh@google.com>
+
+	* link_map.c (auxv_format_probe): Move nested functions
+	check64 and check32 to file scope.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* dwfl_frame.c (state_fetch_pc): Add a backend-defined offset to
+	the value of the return address register as defined by the CFI
+	abi.
+	* frame_unwind.c (handle_cfi): Likewise.
+
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (dwfl_link_map_report): Track whether in.d_buf comes
+	from exec or memory_callback, free as appropriate.
+
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct Dwfl_User_Core): New.
+	(struct DWfl): Replace executable_for_core with user_core.
+	* argp-std.c (parse_opt): Store core and fd in Dwfl user_core.
+	* core-file.c (dwfl_core_file_report): Check and store
+	executable_for_core in Dwfl user_core.
+	* dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Check and use
+	executable_for_core in Dwfl user_core.
+	* dwfl_end.c (dwfl_end): Release resources held in Dwfl user_core.
+	* link-map.c (report_r_debug): Check executable_for_core in Dwfl
+	user_core.
+	(dwfl_link_map_report): Likewise.
+
+2015-11-16  Chih-Hung Hsieh <chh@google.com>
+
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Move nested
+	function 'consider_shdr' to file scope.
+	* dwfl_module_getdwarf.c (find_dynsym): Move nested function
+	'translate_offs' to file scope.
+
+2015-11-16  Chih-Hung Hsieh <chh@google.com>
+
+	* dwfl_module_addrsym.c (__libdwfl_addrsym): Move nested functions
+	'same_section', 'binding_value', 'try_sym_value', and 'search_table'
+	to file scope.
+
+2015-11-19  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module.c (__libdwfl_module_free): Remove Dwfl_Module Ebl from
+	eh_cfi and dwarf_cfi cache if necessary before calling dwarf_end and
+	dwarf_cfi_end.
+
+2015-11-13  Chih-Hung Hsieh <chh@google.com>
+
+	* gzip.c (unzip): Move nested functions to file scope.
+
+2015-10-21  Chih-Hung Hsieh <chh@google.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getsrc_file.c (dwfl_module_getsrc_file): Move nested
+	functions 'dwarf_line_file', 'dwfl_line', and 'dwfl_line_file' to
+	file scope. Rename dwarf_line_file to dwfl_dwarf_line_file. Don't
+	use INTUSE.
+
+2015-10-21  Chih-Hung Hsieh <chh@google.com>
+
+	* frame_unwind.c (expr_eval): Move nested function 'push' and 'pop'
+	to file scope. Pass used local variables in struct eval_stack.
+
+2015-10-21  Chih-Hung Hsieh <chh@google.com>
+
+	* dwfl_module.c (dwfl_report_module): Move nested function 'use' to
+	file scope.
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* core-file.c (elf_begin_rand): Replace loff_t with off_t.
+	* open.c (decompress): Replace off64_t with off_t.
+	* gzip.c (unzip): Likewise.
+	* image-header.c (__libdw_image_header): Likewise.
+	* libdwflP.h: Likewise in function declarations.
+	* argp-std.c (parse_opt): Replace open64 with open.
+	* dwfl_build_id_find_elf.c (__libdwfl_open_mod_by_build_id,
+	dwfl_build_id_find_elf): Likewise.
+	* dwfl_module_getdwarf.c (open_elf_file): Likewise.
+	* dwfl_report_elf.c (dwfl_report_elf): Likewise.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Likewise.
+	* link_map.c (report_r_debug): Likewise.
+	* offline.c (dwfl_report_offline): Likewise.
+	* linux-proc-maps.c (grovel_auxv, get_pid_class,
+	dwfl_linux_proc_find_elf): Likewise.
+	(read_proc_memory): Replace off64_t with off_t.
+	* find-debuginfo.c (find_debuginfo_in_path): Replace stat64 and
+	fstat64 with stat and fstat.
+	(try_open): Likewise, and replace open64 with open.
+	* linux-kernel-modules.c: Manually define open and fopen to open64 and
+	fopen64 when needed, since the early fts.h include breaks that.
+	(try_kernel_name): Replace open64 with open.
+	(check_notes): Likewise.
+
+2015-10-09  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* linux-proc-maps.c (read_proc_memory): Use seek+read instead of
+	pread, as the later doesn't accept negative offsets.
+
+2015-10-07  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (MAX): Removed.
+	(find_prelink_address_sync): Allocate exact amount of bytes for
+	phdrs and shdrs.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Likewise for phdrs.
+	* elf-from-memory.c (MAX): Removed.
+	(elf_from_remote_memory): Allocate exact amount of bytes for phdrs.
+
+2015-10-05  Chih-Hung Hsieh <chh@google.com>
+
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Do not use
+	union of variable length arrays.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Likewise.
+	* elf-from-memory.c (elf_from_remote_memory): Likewise.
+	* link_map.c (auxv_format_probe): Likewise.
+	* link_map.c (report_r_debug): Likewise.
+	* link_map.c (dwfl_link_map_report): Likewise.
+
+2015-09-18  Chih-Hung Hsieh  <chh@google.com>
+
+	* relocate.c (relocate_section): Move nested function "relocate"
+	to file scope, pass all used local variables as constants.
+	Move nested "check_badreltype" to file scope, pass addresses of
+	updated used local variables.
+	* linux-kernel-modules.c (intuit_kernel_bounds): Move nested function
+	"read_address" to file scope, pass all updated local variables in
+	a state structure.
+	* linux-kernel-modules.c (dwfl_linux_kernel_find_elf): Move nested
+	function "subst_name" to file scope, pass all used local variables
+	as constants.
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_kernel): Replace
+	simple nested function "report" with a macro. Work around gcc static
+	analysis error -Werror=maybe-uninitialized.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* core-file.c: Remove old-style function definitions.
+	* dwfl_error.c: Likewise.
+	* dwfl_module_dwarf_cfi.c: Likewise.
+	* dwfl_module_eh_cfi.c: Likewise.
+	* dwfl_module_register_names.c: Likewise.
+	* dwfl_module_return_value_location.c: Likewise.
+	* dwfl_version.c: Likewise.
+
+2015-09-09  Chih-Hung Hsieh  <chh@google.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_frame.c (dwfl_attach_state): Remove redundant NULL tests
+	on parameters declared with __nonnull_attribute__.
+	* libdwfl.h (dwfl_module_getelf): Don't mark first argument as
+	nonnull.
+
+2015-09-08  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct __libdwfl_pid_arg): Add elf and elf_fd.
+	* linux-pid-attach.c (pid_detach): Call elf_end and close.
+	(dwfl_linux_proc_attach): Open and save /proc/PID/exe.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com
+
+	* frame_unwind.c (expr_eval): Use llabs instead of abs.
+
+2015-08-14  Dodji Seketeli  <dodji@seketeli.org>
+
+	* find-debuginfo.c (find_debuginfo_in_path): Try to locate the
+	debug info file named debuglink_file under
+	mod->dwfl->callbacks->debuginfo_path, by looking at
+	the set of sub-trees under mod->dwfl->callbacks->debuginfo_path
+	which is common to the set of non-absolute parent trees of
+	file_name.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* find-debuginfo.c (try_open): Free fname on all failure paths.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Check shdr is not NULL and
+	sh_entsize is not zero.
+
+2015-06-06  Mark Wielaard  <mjw@redhat.com>
+
+	* find-debuginfo.c (find_debuginfo_in_path): Always free localpath,
+	localname and file_dirname.
+
+2015-06-06  Mark Wielaard  <mjw@redhat.com>
+
+	* derelocate.c (cache_sections): Free sortrefs.
+
+2015-06-05  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	If the note_file exists, but the build_id doesn't match discard
+	the file and continue reporting.
+
+2015-06-01  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Copy path
+	pointer before passing to strsep.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (check32): Use read_4ubyte_unaligned_noncvt to read
+	type and value.
+	(read_addrs): Use read_(4|8)ubyte_unaligned_noncvt or to read
+	addresses.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Check file_name is
+	not NULL before calling canonicalize_file_name.
+
+2015-05-24  Mark Wielaard  <mjw@redhat.com>
+
+	* derelocate.c (check_module): Check mod is not NULL.
+
+2015-05-22  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (dwfl_link_map_report): Allocate phdrs and dyn with
+	malloc instead of stack allocating. Call free when done with data.
+
+2015-05-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Allocate phdrs with malloc, not on stack. free in finish.
+	Allocate dyn with malloc, not on stack, free after use.
+
+2015-05-22  Mark Wielaard  <mjw@redhat.com>
+
+	* find-debuginfo.c (find_debuginfo_in_path): malloc or strdup,
+	instead of alloca or strdupa, local strings of unknown size.
+	Call free before return.
+
+2015-05-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Return
+	error when id_len too small or too large. strdup, not strdupa,
+	and free path when done.
+
+2015-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Don't allocate all
+	phdrs on the stack. Allocate with malloc and free when done.
+
+2015-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_find_elf): malloc and
+	free alternate_name.
+
+2015-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Don't
+	stack allocate name. Only change chars up to suffix.
+
+2015-05-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Allocate
+	phdrs and shdrs unions with malloc, not alloca. Free after use.
+
+2015-05-18  Mark Wielaard  <mjw@redhat.com>
+
+	* derelocate.c (cache_sections): Allocate temporary newrefs and
+	sortrefs with malloc, not alloca. Always free them on return.
+
+2015-05-07  Mark Wielaard  <mjw@redhat.com>
+
+	* cu.c (intern_cu): Check for EOF and check cuoff points to a real
+	Dwarf_Die before interning. Explicitly check EOF is expected.
+
+2015-05-05  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_lineinfo.c (dwfl_lineinfo): Check info->file is valid.
+
+2015-05-06  Roland McGrath  <roland@hack.frob.com>
+
+	* dwfl_error.c (struct msgtable): Break type definition out of
+	the 'msgtable' initializer.
+	(msgtable): Make it a union of struct msgtable and a char array.
+	(msgstr): Use the full-table char array rather than the msg_0 entry.
+
+2015-04-23  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* core-file.c (_compat_without_executable_dwfl_core_file_report):
+	Guard with SYMBOL_VERSIONING.
+	* dwfl_module_build_id.c (_compat_vaddr_at_end_dwfl_module_build_id):
+	Likewise.
+	* dwfl_report_elf.c (_compat_without_add_p_vaddr_dwfl_report_elf):
+	Likewise.
+
+2015-04-02  Mark Wielaard  <mjw@redhat.com>
+
+	* segment.c (insert): Check correct number of lookup_elts.
+
+2015-03-31  Mark Wielaard  <mjw@redhat.com>
+
+	* core-file.c (core_file_read_eagerly): Special case small images.
+
+2015-01-26  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Explicitly clear symdata,
+	syments and first_global on elferr before calling find_dynsym.
+
+2014-12-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getsrc.c (dwfl_module_getsrc): Never match a line that
+	has end_sequence set.
+
+2015-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* cu.c (intern_cu): Store result and return directly when finding
+	EOF marker.
+	(__libdwfl_nextcu): Check *nextp as returned by intern_cu isn't -1.
+
+2014-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Always try find_dynsym last.
+
+2014-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-from-memory.c (handle_segment): Remove palign sanity check.
+
+2014-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* relocate.c (resolve_symbol): Make sure symstrdata->d_buf != NULL.
+
+2014-12-13  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_dynsym): elf_getdata_rawchunk takes
+	a size_t, make sure it doesn't overflow.
+
+2014-12-13  Mark Wielaard  <mjw@redhat.com>
+
+	* cu.c (cudie_offset): Make sure Dwarf_Off difference doesn't
+	wrap around before returning as int.
+
+2014-12-11  Josh Stone  <jistone@redhat.com>
+
+	* dwfl_module_getsrc.c (dwfl_module_getsrc): Return the *last* line
+	record <= addr, rather than returning immediately on matches.
+
+2014-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_segment_report_module.c (handle_file_note): Check count doesn't
+	overflow.
+
+2014-12-07  Mark Wielaard  <mjw@redhat.com>
+
+	* relocate.c (relocate_section): Sanity check section overlap against
+	actually used ehsize, shentsize and phentsize.
+
+2014-12-07  Mark Wielaard  <mjw@redhat.com>
+
+	* offline.c (dwfl_offline_section_address): Assert shndx is not zero.
+	* relocate.c (__libdwfl_relocate_value): Don't relocate against
+	section zero.
+
+2014-11-29  Mark Wielaard  <mjw@redhat.com>
+
+	* relocate.c (relocate_section): Check relocation section and target
+	section data don't overlap any of the ELF headers.
+	(relocate): Check for offset + size overflow.
+
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (consider_executable): Use elf_getphdrnum.
+	(dwfl_link_map_report): Likewise.
+
+2014-11-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Sanity check the data buffer,
+	number of symbols and first_global before use.
+
+2014-11-14  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (load_symtab): Don't use tables which have
+	a zero sh_entsize.
+
+2014-11-10  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_dynsym): New inner function
+	translate_offs that takes an adjust argument. Try finding
+	the symbol table with and without adjusting to main_bias.
+
+2014-09-26  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Support NT_FILE for locating files.
+	* core-file.c (dwfl_core_file_report): New variables note_file and
+	note_file_size, set them and pass them to dwfl_segment_report_module.
+	* dwfl_segment_report_module.c: Include common.h and fcntl.h.
+	(buf_has_data, buf_read_ulong, handle_file_note): New functions.
+	(invalid_elf): New function from code of dwfl_segment_report_module.
+	(dwfl_segment_report_module): Add parameters note_file and
+	note_file_size.  New variables elf and fd, clean them up in finish.
+	Move some code to invalid_elf.  Call handle_file_note, if it found
+	a name verify the file by invalid_elf.  Protect elf and fd against
+	cleanup by finish if we found the file for new Dwfl_Module.
+	* libdwflP.h (dwfl_segment_report_module): Add parameters note_file and
+	note_file_size.
+
+2014-09-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Extract ei_class, ei_data and e_type early and use the result.
+
+2014-09-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Use IS_EXECUTABLE.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Set
+	IS_EXECUTABLE.
+	* libdwflP.h (struct Dwfl_Module): New field is_executable.
+
+2014-08-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_offsets): Add parameter main_bias, use
+	it.
+	(find_dynsym): Pass the new parameter main_bias.
+
+2014-08-14  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (check-suffix): Also TRY .ko.xz.
+
+2014-07-24  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix report_r_debug for prelinked libraries.
+	* link_map.c (report_r_debug): Comment out variable l_addr.
+	Use instead new variable base recalculated from l_ld.
+
+2014-06-24  Kurt Roeckx  <kurt@roeckx.be>
+
+	* linux-pid-attach.c: Make it build on non linux hosts.
+
+2014-06-17  Mark Wielaard  <mjw@redhat.com>
+
+	* frame_unwind.c (handle_cfi): Use ebl_func_addr_mask.
+	* dwfl_module_getsym.c (__libdwfl_getsym): Likewise.
+
+2014-06-15  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-core-attach.c (core_memory_read): Use libdw/memory-access.h
+	macros read_4ubyte_unaligned_noncvt and read_8ubyte_unaligned_noncvt
+	to read possibly unaligned data.
+	(core_next_thread): Likewise.
+	(core_set_initial_registers): Likewise.
+	(dwfl_core_file_attach): Likewise.
+
+2014-06-11  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_frame.c (__libdwfl_process_free): Reset dwfl->attacherr.
+	(dwfl_attach_state): Set dwfl->attacherr.
+	(dwfl_pid): Check and return dwfl->attacherr if set.
+	(dwfl_getthreads): Likewise.
+	(getthread): Likewise.
+	* libdwflP.h: Add DWFL_E_NO_CORE_FILE.
+	(struct Dwfl): Add attacherr field.
+	* linux-core-attach.c (dwfl_core_file_attach): Set dwfl->attacherr.
+	Don't assert if ELF file is not ET_CORE, just return error.
+	* linux-pid-attach.c (dwfl_linux_proc_attach): Set dwfl->attacherr.
+
+2014-06-10  Mark Wielaard  <mjw@redhat.com>
+
+	* argp-std.c (parse_opt): Ignore errors from dwfl_core_file_attach
+	or dwfl_linux_proc_attach.
+
+2014-05-15  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (grovel_auxv): Close fd on error.
+
+2014-05-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf: Remove ENABLE_DWZ ifdefs so find_debug_altlink
+	is always called.
+
+2014-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct Dwfl_Module): Add alt, alt_fd and alt_elf fields.
+	(__libdwfl_open_mod_by_build_id): Renamed __libdwfl_open_by_build_id.
+	(__libdwfl_open_by_build_id): New declaration that takes an explicit
+	build-id.
+	* dwfl_build_id_find_debuginfo.c (dwfl_build_id_find_debuginfo): If
+	we already have the Dwarf then look for the alt dwz multi file by
+	build-id.
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Add the
+	build-id we are looking for as argument.
+	(__libdwfl_open_mod_by_build_id): New function, calls
+	__libdwfl_open_by_build_id.
+	(dwfl_build_id_find_elf): Call __libdwfl_open_mod_by_build_id.
+	* dwfl_module.c (__libdwfl_module_free): Release alt, alt_elf and
+	close alt_fd if necessary.
+	* dwfl_module_getdwarf.c (__check_build_id): Removed.
+	(try_debugaltlink): Removed.
+	(open_debugaltlink): Removed.
+	(open_elf_file): First half of open_elf that just opens the elf
+	file but doesn't setup the load address.
+	(open_elf): Call open_elf_file.
+	(find_debug_altlink): New function.
+	(load_dw): Remove loading of dwz multifile.
+	(find_dw): Call find_debug_altlink.
+	* find-debuginfo.c (validate): Handle alt debug case using
+	dwelf_dwarf_gnu_debugaltlink and mod->alt_elf.
+	(find_debuginfo_in_path): Handle alt debug files possibly in .dwz
+	subdirs.
+	* linux-kernel-modules.c (try_kernel_name): Use fakemod.debug.name
+	to store name to find by dwfl_standard_find_debuginfo instead of
+	allocating an extra variable on stack.
+
+2014-04-30  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_build_id.c (__libdwfl_find_elf_build_id): Moved to
+	dwelf_elf_gnu_build_id.c.
+	(__libdwfl_find_build_id): Add assert to make sure mod is never NULL.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Call
+	dwelf_elf_gnu_build_id directly instead of __libdwfl_find_build_id.
+	* dwfl_module_getdwarf.c (__check_build_id): Implement using
+	dwelf_elf_gnu_build_id.
+
+2014-04-15  Florian Weimer  <fweimer@redhat.com>
+
+	* dwfl_module_getdwarf.c (__check_build_id): Moved from libdw.
+	(try_debugaltlink): Likewise.
+	(open_debugaltlink): Likewise.
+	(load_dw): Locate alternate debug information using
+	dwelf_dwarf_gnu_debugaltlink and call open_debugaltlink.
+
+2014-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (AM_CPPFLAGS): Add libdwelf.
+	* libdwflP.h: Include libdwelfP.h.
+	* dwfl_module_getdwarf.c (find_debuglink): Moved to libdwelf.
+	(find_debuginfo): Use dwelf_elf_gnu_debuglink.
+
+2014-04-22  Mark Wielaard  <mjw@redhat.com>
+
+	* frame_unwind.c (__libdwfl_frame_reg_get): Use uint64_t when
+	checking bits.
+	(__libdwfl_frame_reg_set): Likewise.
+
+2014-04-22  Kurt Roeckx  <kurt@roeckx.be>
+
+	* linux-pid-attach.c: Make linux only.
+
+2014-03-14  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove !MUDFLAP and MUDFLAP conditions.
+	Remove libelf and libdw definitions when MUDFLAP is defined.
+	* argp-std.c (__libdwfl_argp_mudflap_options): Removed.
+
+2014-03-03  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Keep track of
+	segments_end_mem. Pass memsz to first handle_segment pass. Only
+	extend contents_size and use shdrs if only file bits are in
+	segment.
+
+2014-03-11  Josh Stone  <jistone@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Only explicitly set
+	mod->e_type when processing the main ELF file.
+
+2014-03-04  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct __libdwfl_pid_arg): Moved here and renamed from
+	linux-pid-attach.c (struct pid_arg).
+	(__libdwfl_get_pid_arg): New internal function declaration.
+	(__libdwfl_ptrace_attach): Likewise.
+	(__libdwfl_ptrace_detach): Likewise.
+	* dwfl_frame.c (dwfl_attach_state): Add "(deleted)" files to the
+	special exception modules that cannot be checked at this point.
+	* linux-pid-attach.c (struct pid_arg): Moved to libdwflP.h
+	(ptrace_attach): Renamed to...
+	(__libdwfl_ptrace_attach): New internal function.
+	(__libdwfl_ptrace_detach): Likewise. Extracted from ...
+	(pid_thread_detach): Call __libdwfl_ptrace_detach now.
+	(__libdwfl_get_pid_arg): New internal function.
+	* linux-proc-maps.c (dwfl_linux_proc_find_elf): Check if special
+	module name contains "(deleted)" and dwfl_pid gives an attached
+	pid. If pid is set and try to (re)use ptrace attach state of
+	process before reading memory.
+
+2014-03-03  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Take pagesize as
+	argument. Free buffer when detecting bad elf. Check PT_LOAD
+	alignment requirements on first handle_segment pass. Calculate
+	loadbase, start and end of segment using pagesize, not p_align.
+	* linux-proc-maps.c (dwfl_linux_proc_find_elf): Provide pagesize
+	to elf_from_remote_memory.
+
+2014-02-26  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (proc_maps_report): Don't assert on bad input.
+
+2014-02-26  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Check against p64
+	p_type in case ELFCLASS64, not against p32 p_type.
+
+2014-01-17  Petr Machata  <pmachata@redhat.com>
+
+	* relocate.c (relocate_section): Use gelf_fsize instead of relying
+	on shdr->sh_entsize.
+
+2014-01-05  Mark Wielaard  <mjw@redhat.com>
+
+	* frame_unwind.c (handle_cfi): Only skip resetting return register
+	if the regno is not the actual CIE return address register.
+
+2014-01-02  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-pid-attach.c (dwfl_linux_proc_attach): Use strtol, not atoi.
+
+2013-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* argp-std.c (parse_opt): Call dwfl_linux_proc_attach and
+	dwfl_core_file_attach explicitly.
+	* core-file.c (dwfl_core_file_report): Don't call
+	__libdwfl_attach_state_for_core implicitly.
+	* dwfl_begin.c (dwfl_begin): Remove setting of process_attach_error.
+	* dwfl_frame.c (dwfl_pid): Set errno to DWFL_E_NO_ATTACH_STATE, not
+	process_attach_error.
+	(dwfl_getthreads): Likewise.
+	(getthread): Likewise.
+	* libdwfl.h (dwfl_core_file_report): Update documentation.
+	(dwfl_linux_proc_report): Likewise.
+	(dwfl_core_file_attach): New function declaration.
+	(dwfl_linux_proc_attach): Likewise.
+	* libdwflP.h (struct Dwfl): Remove process_attach_error.
+	(__libdwfl_attach_state_for_pid): Removed declaration.
+	(__libdwfl_attach_state_for_core): Likewise.
+	(dwfl_core_file_attach): New internal declaration.
+	(dwfl_linux_proc_attach): Likewise.
+	(attach_state_for_core): Renamed to...
+	(dwfl_core_file_attach): ...this. Change return type.
+	(__libdwfl_attach_state_for_core): Removed.
+	* linux-pid-attach.c (struct pid_arg): Add assume_ptrace_stopped.
+	(pid_set_initial_registers): Check assume_ptrace_stopped before
+	calling ptrace.
+	(pid_thread_detach): Likewise.
+	(__libdwfl_attach_state_for_pid): Renamed to...
+	(dwfl_linux_proc_attach): ...this. Adjust return type.
+	* linux-proc-maps.c (dwfl_linux_proc_report): Don't call
+	__libdwfl_attach_state_for_pid implicitly.
+
+2013-12-28  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (dwfl_linux_proc_find_elf): Don't return special
+	character device files, only regular files.
+
+2013-12-24  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-core-attach.c (core_next_thread): Check whether thread_argp
+	is NULL. Reset core_arg->thread_note_offset and malloc a thread_arg
+	in that case. Free thread_arg if there are no more threads.
+
+2013-12-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Free
+	build_id before returning early.
+
+2013-12-23  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-pid-attach.c (__libdwfl_attach_state_for_pid): Report actual
+	pid (thread group leader) to dwfl_attach_state.
+
+2013-12-21  Mark Wielaard  <mjw@redhat.com>
+
+	* frame_unwind.c (handle_cfi): Track whether the return register
+	has been set and only allow it to be set once.
+
+2013-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_frame.c (one_arg): New struct.
+	(get_one_thread_cb): New function.
+	(dwfl_getthread): Likewise.
+	(one_thread): New struct.
+	(get_one_thread_frames_cb): New function.
+	(dwfl_getthread_frames): Likewise.
+	* libdwfl.h (Dwfl_Thread_Callbacks): Add get_thread function.
+	(dwfl_getthread_frames): Likewise.
+	* libdwflP.h (dwfl_getthread_frames): New internal function declaration.
+	* linux-core-attach.c (core_thread_callbacks): Initialize get_thread
+	to NULL.
+	* linux-pid-attach.c (pid_getthread): New function.
+	(pid_thread_callbacks): Initialize get_thread to pid_getthread.
+
+2013-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel_archive): Correct nested
+	asprintf result check for debug.a.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* derelocate.c (__libdwfl_find_section_ndx): New internal function.
+	* dwfl_module_addrname.c (dwfl_module_addrname): Use
+	dwfl_module_addrinfo.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Replace with...
+	(__libdwfl_addrsym): ...this. Use __libdwfl_getsym, use value
+	for comparisons, not st_value. Fill in off. Search for both value
+	and the (adjusted) sym.st_value when different.
+	(dwfl_module_addrsym): Implement using __libdwfl_addrsym.
+	(dwfl_module_addrinfo): New function.
+	* dwfl_module_getsym.c (dwfl_module_getsym_elf): Replace with...
+	(__libdwfl_getsym): ...this. Use ebl_resolve_sym_value if requested
+	and possible. Adjust sym->st_value only when requested. Fill in addr
+	if available.
+	(dwfl_module_getsym_info): New function.
+	(dwfl_module_getsym): Use __libdwfl_getsym.
+	* libdwfl.h (dwfl_module_getsym_elf): Removed.
+	(dwfl_module_getsym_info): New function declaration.
+	(dwfl_module_addrinfo): Likewise.
+	(dwfl_module_addrsym): Add documentation describing differences
+	with addrinfo variants.
+	(dwfl_module_addrsym_elf): Removed.
+	* libdwflP.h (__libdwfl_getsym): New internal function declaration.
+	(__libdwfl_addrsym): Likewise.
+	(__libdwfl_find_section_ndx): Likewise.
+	(dwfl_module_addrinfo): New internal declaration.
+	(dwfl_module_getsym_info): Likewise.
+	(dwfl_module_addrsym_elf): Removed.
+	(dwfl_module_getsym_elf): Likewise.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* argp-std.c (offline_find_elf): Remove.
+	(offline_callbacks): Use dwfl_build_id_find_elf instead.
+	* dwfl_build_id_find_elf.c (dwfl_build_id_find_elf): Move here the code
+	removed above.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: s390 and s390x
+	* dwfl_frame_pc.c (dwfl_frame_pc): Call ebl_normalize_pc.
+	* frame_unwind.c (new_unwound): New function from ...
+	(handle_cfi): ... here.  Call it.
+	(setfunc, getfunc, readfunc): New functions.
+	(__libdwfl_frame_unwind): Call ebl_unwind with those functions.
+	* linux-core-attach.c (core_set_initial_registers): Always iterate
+	through the Ebl_Register_Location loop.  Call
+	dwfl_thread_state_register_pc there.
+
+2013-12-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* frame_unwind.c (handle_cfi): Call ebl_dwarf_to_regno for RA.
+
+2013-12-17  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-pid-attach.c (pid_next_thread): Call rewinddir on first
+	traversal.
+
+2013-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwfl.h (dwfl_module_getsymtab_first_global): New function
+	definition.
+	* dwfl_module_getdwarf.c (dwfl_module_getsymtab_first_global): New
+	function.
+	* libdwflP.h (dwfl_module_getsymtab_first_global): New internal
+	function definition.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym_elf): Use new function.
+
+2013-12-14  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module.c (__libdwfl_module_free): Free mod->reloc_info if
+	allocated. Call dwarf_cfi_end on mod->eh_cfi if necessary.
+	* frame_unwind.c (handle_cfi): Free frame result from
+	dwarf_cfi_addrframe when done.
+
+2013-12-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: ppc and ppc64
+	* frame_unwind.c (__libdwfl_frame_reg_get, __libdwfl_frame_reg_set):
+	Call ebl_dwarf_to_regno.
+	* linux-core-attach.c (core_set_initial_registers): Implement
+	pc_register support.
+	* linux-pid-attach.c (pid_thread_state_registers_cb): Implement
+	FIRSTREG -1.
+
+2013-11-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Introduce process_attach_error.
+	* dwfl_begin.c (dwfl_begin): Initialize process_attach_error.
+	* dwfl_frame.c (dwfl_pid, dwfl_getthreads): Use PROCESS_ATTACH_ERROR if
+	PROCESS is NULL.
+	* libdwflP.h (struct Dwfl): New field process_attach_error.
+	* linux-core-attach.c (__libdwfl_attach_state_for_core): Rename to ...
+	(attach_state_for_core): ... here, make it static, change return type,
+	no longer use __libdwfl_seterrno.
+	(__libdwfl_attach_state_for_core): New wrapper for it.
+
+2013-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Rename to and call...
+	(dwfl_module_addrsym_elf): this. Add elfp and biasp arguments,
+	keep track of symelf, addr_symelf, closest_elf and sizeless_elf
+	instead of tracking dwfl_files.
+	* dwfl_module_getsym.c (__libdwfl_module_getsym): Renamed to...
+	(dwfl_module_getsym_elf): ...this. Remove dwfl_file argument, add
+	new elfp and biasp arguments. Track elf instead of file.
+	(dwfl_module_getsym): Call dwfl_module_getsym_elf.
+	dwfl_module_info.c (dwfl_module_info): Pass elf to
+	dwfl_adjusted_st_value.
+	* libdwfl.h (dwfl_module_getsym): Document limitations of shndx.
+	(dwfl_module_getsym_elf): New function declaration.
+	(dwfl_module_addrsym_elf): Likewise.
+	* libdwflP.h (dwfl_module_addrsym_elf): INTDECL.
+	(dwfl_module_getsym_elf): Likewise.
+	(dwfl_adjusted_st_value): Take and check elf not dwfl_file.
+	(dwfl_deadjust_st_value): Likewise.
+	(__libdwfl_module_getsym): Removed.
+	* relocate.c (resolve_symbol): Pass elf to dwfl_adjusted_st_value.
+
+2013-11-21  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix non-build-id core files on build-id system.
+	* link_map.c (report_r_debug): Remove valid clearing if build-id cannot
+	be read from memory.
+
+2013-11-21  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): New
+	variable close_elf.  Call __libdwfl_find_elf_build_id and compare the
+	content, if possible.
+
+2013-11-21  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	link_map: Use proper bias, not l_addr.
+	* core-file.c (dynamic_vaddr_get): Rename to ...
+	(__libdwfl_dynamic_vaddr_get): ... here, make it global,
+	internal_function.
+	(dwfl_core_file_report): Update name in the caller.
+	* libdwflP.h (__libdwfl_dynamic_vaddr_get): New declaration.
+	* link_map.c (report_r_debug): New variable elf_dynamic_vaddr.  Call
+	__libdwfl_dynamic_vaddr_get for it.  Remove L_ADDR FIXME comment.
+	Use ELF_DYNAMIC_VADDR instead of L_ADDR.
+
+2013-11-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Compatibility with older kernels such as RHEL-6.
+	* linux-pid-attach.c (struct pid_arg): New field tid_was_stopped.
+	(ptrace_attach): New parameter tid_was_stoppedp.  Set it.
+	(pid_set_initial_registers): Pass tid_was_stopped.
+	(pid_thread_detach): Use tid_was_stopped.
+
+2013-11-18  Josh Stone  <jistone@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_aux_address_sync): New function.
+	(find_aux_sym): Use it.
+
+2013-11-14  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Code cleanup: Remove const in prototype
+	* dwfl_frame_regs.c (dwfl_thread_state_registers): Remove const from
+	firstreg.
+	* libdwfl.h (dwfl_thread_state_registers): Likewise.
+	* linux-pid-attach.c (pid_thread_state_registers_cb): Likewise.
+
+2013-11-14  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix dwfl_attach_state machine->elf.
+	* dwfl_frame.c (dwfl_attach_state): Change parameter machine to elf.
+	Call ebl_openbackend instead of ebl_openbackend_machine.
+	* libdwfl.h (dwfl_attach_state): Change parameter machine to elf.
+	Update the function description.
+	* linux-core-attach.c (__libdwfl_attach_state_for_core): Pass CORE to
+	dwfl_attach_state.
+	* linux-pid-attach.c (__libdwfl_attach_state_for_pid): Pass NULL to
+	dwfl_attach_state.
+
+2013-11-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Provide __libdwfl_module_getsym to get dwfl_file *.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym) (i_to_symfile): Remove.
+	(dwfl_module_addrsym) (search_table): New variable file.  Use
+	__libdwfl_module_getsym.  Use file.
+	* dwfl_module_getsym.c (dwfl_module_getsym): Rename to ...
+	(__libdwfl_module_getsym): ... here.  Add parameter filep.  Set it.
+	(dwfl_module_getsym): New wrapper.
+	* libdwflP.h (__libdwfl_module_getsym): New declaration.
+
+2013-11-13  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix dwfl_module_addrsym for minidebuginfo.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): New variable
+	addr_symfile.
+	(dwfl_module_addrsym) (same_section): Use it.
+	(dwfl_module_addrsym) (i_to_symfile): New function.
+	(dwfl_module_addrsym) (search_table): Use it.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libdwfl_a_SOURCES): Add dwfl_frame.c, frame_unwind.c,
+	dwfl_frame_pc.c, linux-pid-attach.c, linux-core-attach.c and
+	dwfl_frame_regs.c.
+	* core-file.c (dwfl_core_file_report): Call
+	__libdwfl_attach_state_for_core.
+	* dwfl_end.c (dwfl_end): Call __libdwfl_process_free.
+	* dwfl_frame.c: New file.
+	* frame_unwind.c: New file.
+	* dwfl_frame_pc.c: New file.
+	* linux-pid-attach.c: New file.
+	* linux-core-attach.c: New file.
+	* dwfl_frame_regs.c: New file.
+	* libdwfl.h (Dwfl_Thread, Dwfl_Frame): New typedefs.
+	(dwfl_core_file_report, dwfl_linux_proc_report): Extend comments.
+	(Dwfl_Thread_Callbacks): New definition.
+	(struct ebl, dwfl_attach_state, dwfl_pid, dwfl_thread_dwfl)
+	(dwfl_thread_tid, dwfl_frame_thread, dwfl_thread_state_registers)
+	(dwfl_thread_state_register_pc, dwfl_getthreads, dwfl_thread_getframes)
+	(dwfl_frame_pc): New declarations.
+	* libdwflP.h (Dwfl_Process): New typedef.
+	(LIBEBL_BAD, CORE_MISSING, INVALID_REGISTER, PROCESS_MEMORY_READ)
+	(PROCESS_NO_ARCH, PARSE_PROC, INVALID_DWARF, UNSUPPORTED_DWARF)
+	(NEXT_THREAD_FAIL, ATTACH_STATE_CONFLICT, NO_ATTACH_STATE, NO_UNWIND)
+	(INVALID_ARGUMENT): New DWFL_ERROR entries.
+	(struct Dwfl): New entry process.
+	(struct Dwfl_Process, struct Dwfl_Thread, struct Dwfl_Frame)
+	(__libdwfl_frame_reg_get, __libdwfl_frame_reg_set)
+	(__libdwfl_process_free, __libdwfl_frame_unwind)
+	(__libdwfl_attach_state_for_pid, __libdwfl_attach_state_for_core)
+	(__libdwfl_segment_start, __libdwfl_segment_end): New declarations.
+	(dwfl_attach_state, dwfl_pid, dwfl_thread_dwfl, dwfl_thread_tid)
+	(dwfl_frame_thread, dwfl_thread_state_registers)
+	(dwfl_thread_state_register_pc, dwfl_getthreads, dwfl_thread_getframes)
+	(dwfl_frame_pc): New INTDECL entries.
+	* linux-proc-maps.c (dwfl_linux_proc_report): Call
+	__libdwfl_attach_state_for_pid.
+	* segment.c (segment_start): Rename to ...
+	(__libdwfl_segment_start): ... here and make it internal_function.
+	(segment_end): Rename to ...
+	(__libdwfl_segment_end): ... here and make it internal_function.
+	(reify_segments, dwfl_report_segment): Rename them at the callers.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* core-file.c (dwfl_core_file_report): Remove the use of MAX.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* core-file.c (dwfl_core_file_report): Replaced variable sniffed by
+	retval.  Fix one forgotten LISTED increase.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix core files for re-prelink-ed files.
+	* core-file.c (dynamic_vaddr_get): New function.
+	(dwfl_core_file_report): New variable file_dynamic_vaddr.  Call
+	dynamic_vaddr_get instead of using L_ADDR.
+	* libdwflP.h (struct r_debug_info_module): Remove field l_addr.
+	* link_map.c (report_r_debug): Do not initialize l_addr.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Code cleanup.
+	* core-file.c (dwfl_core_file_report): Reindent block of code by
+	continue keyword.
+
+2013-10-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* argp-std.c (parse_opt): Use executable parameter of
+	dwfl_core_file_report.
+	* core-file.c (dwfl_core_file_report): Add parameter executable.  Set
+	it to DWFL.  Add NEW_VERSION for it.
+	(_compat_without_executable_dwfl_core_file_report): New.  Twice.
+	* libdwfl.h (dwfl_core_file_report): Add parameter executable, update
+	the function comment.
+
+2013-10-15  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (proc_maps_report): Ignore non-absolute file
+	mappings.
+	(dwfl_linux_proc_find_elf): Don't abort, just return failure.
+
+2013-09-12  Mark Wielaard  <mjw@redhat.com>
+
+	* cu.c (intern_cu): If dwarf_offdie fails free cu.
+
+2013-09-12  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-proc-maps.c (proc_maps_report): Don't fclose FILE in
+	bad_report.
+
+2013-09-12  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_symtab): Call elf_getdata with
+	aux_xndxscn, not xndxscn, for aux_symxndxdata.
+
+2013-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel): Pass add_p_vaddr as true
+	to dwfl_report_elf.
+
+2013-07-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Check for
+	conflicts all the modules, not just the first one.  Compare L_LD if it
+	is equal, not if it is in a module address range.
+
+2013-07-23  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* libdwflP.h (__libdwfl_elf_address_range): Add internal_function.
+
+2013-07-23  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* core-file.c (clear_r_debug_info): Close also ELF and FD.
+	(dwfl_core_file_report): Call __libdwfl_report_elf for
+	R_DEBUG_INFO.MODULE.
+	* dwfl_report_elf.c (__libdwfl_elf_address_range): New function from
+	code of ...
+	(__libdwfl_report_elf): ... this function.  Call it.
+	* dwfl_segment_report_module.c: Include unistd.h.
+	(dwfl_segment_report_module): Use basename for MODULE->NAME.
+	Clear MODULE if it has no build-id and we have segment with build-id.
+	Ignore this segment only if MODULE still contains valid ELF.
+	* libdwflP.h (__libdwfl_elf_address_range): New declaration.
+	(struct r_debug_info_module): New fields fd, elf, l_addr, start, end
+	and disk_file_has_build_id.
+	(dwfl_link_map_report): Extend the comment.
+	* link_map.c (report_r_debug): Extend the comment.  Always fill in new
+	r_debug_info_module.  Initialize also the new r_debug_info_module
+	fields.  Remove one FIXME comment.  Call __libdwfl_elf_address_range
+	instead of __libdwfl_report_elf when R_DEBUG_INFO is not NULL.
+
+2013-07-19  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* libdwflP.h (__libdwfl_find_elf_build_id): Add internal_function.
+
+2013-07-02  Mark Wielaard  <mjw@redhat.com>
+
+	* relocate.c (__libdwfl_relocate_value): Remove mod->e_type assert.
+
+2013-06-05  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c (report_r_debug): Always call release_buffer after
+	memory_callback succeeded reading build_id.
+
+2013-05-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* argp-std.c (parse_opt) <ARGP_KEY_SUCCESS> <opt->core> <opt->e>: Set
+	executable_for_core before calling dwfl_core_file_report.
+	* core-file.c (clear_r_debug_info): New function.
+	(dwfl_core_file_report): Move raw segments reporting lower.  New
+	variable r_debug_info, pass it to dwfl_segment_report_module.  Call
+	clear_r_debug_info in the end.  Return sum of LISTED and SNIFFED.
+	* dwfl_module_build_id.c (check_notes): Move into
+	__libdwfl_find_elf_build_id.
+	(__libdwfl_find_build_id): Rename to ...
+	(__libdwfl_find_elf_build_id): ... here.  Add parameters build_id_bits,
+	build_id_elfaddr and build_id_len.  Verify MOD vs. ELF.
+	(__libdwfl_find_elf_build_id) (check_notes): Remove parameters mod and
+	set, rename data_vaddr to data_elfaddr.  Do not call found_build_id.
+	(__libdwfl_find_elf_build_id): Update the check_notes caller, do not
+	adjust its data_elfaddr parameter.
+	(__libdwfl_find_build_id): New wrapper of __libdwfl_find_elf_build_id.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): New
+	parameter r_debug_info.  New variable name_is_final.  Adjust addresses
+	according to R_DEBUG_INFO->MODULE.  Check conflicts against DWFL.
+	Do not overwrite NAME by SONAME if NAME_IS_FINAL.
+	* libdwflP.h (__libdwfl_find_elf_build_id): New declaration.
+	(struct r_debug_info_module, struct r_debug_info): New definitions.
+	(dwfl_segment_report_module, dwfl_link_map_report): Add parameter
+	r_debug_info.
+	* link_map.c: Include fcntl.h.
+	(report_r_debug): Add parameter r_debug_info, describe it in the
+	function comment.  Delete dwfl_addrmodule call and its dependent code.
+	Verify build-id before calling dwfl_report_elf, also supply
+	executable_for_core to it.  Store r_debug_info->module info when
+	appropriate.
+	(dwfl_link_map_report): Add parameter r_debug_info.  New variable
+	in_ok.  Try to read IN from EXECUTABLE_FOR_CORE.  Update report_r_debug
+	caller parameters.
+
+2013-04-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Add parameter add_p_vaddr.
+	Set it to true for ET_EXEC and ET_CORE.  Provide alternative
+	setup of START and BIAS if !ADD_P_VADDR.  Set END from BIAS, not BASE.
+	(dwfl_report_elf): Add parameter add_p_vaddr.  Pass it down.  Add
+	NEW_VERSION.
+	(_compat_without_add_p_vaddr_dwfl_report_elf) <SHARED>: New, with
+	COMPAT_VERSION.
+	* libdwfl.h (dwfl_report_elf): Add parameter add_p_vaddr.  Describe it.
+	* libdwflP.h (__libdwfl_report_elf): Add parameter add_p_vaddr.
+	* link_map.c (report_r_debug): Use true add_p_vaddr for dwfl_report_elf.
+	* linux-kernel-modules.c (report_kernel): Use false add_p_vaddr for
+	dwfl_report_elf.
+	* offline.c (process_elf): Use true add_p_vaddr for dwfl_report_elf.
+
+2013-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* link_map.c: #include system.h.
+
+2013-04-26  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* link_map.c (BE32, BE64, LE32, LE64): Delete the definitions, move
+	them to lib/system.h.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2013-03-20  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Remove BASE aligning.
+
+2013-03-12  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_getsrclines.c (dwfl_getsrclines): Return 0 on success.
+
+2013-02-22  Mark Wielaard  <mjw@redhat.com>
+
+	* open.c (__libdw_gunzip,__libdw_bunzip2,__libdw_unlzma): Define
+	as DWFL_E_BADELF when not used.
+
+2013-02-10  Mark Wielaard  <mjw@redhat.com>
+
+	* argp-std.c (parse_opt): Use opt->core and opt->e explicitly in
+	failure messages When handling ARGP_KEY_SUCCESS because arg will
+	not have been set.
+
+2013-01-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* linux-proc-maps.c: Include system.h.
+	(PROCEXEFMT, get_pid_class): New.
+	(grovel_auxv): Detect 32-bit vs. 64-bit auxv, possibly call
+	get_pid_class.
+
+2013-01-23  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_aux_sym): Don't subtract one
+	from aux_syments by default.
+	(find_symtab): Also succeed when only aux_symdata is found.
+	When no symtab is found always try to load auxiliary table.
+	(dwfl_module_getsymtab): Substract one from result when both
+	tables have symbols.
+	* dwfl_module_getsym.c (dwfl_module_getsym): Only skip auxiliary
+	zero entry when both tables have symbols.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Only subtract
+	one from first_global when both tables have symbols.
+
+2013-01-16  Mark Wielaard  <mjw@redhat.com>
+
+	* libdwflP.h (struct Dwfl_Module): Add aux_sym, aux_symdata,
+	aux_syments, aux_symstrdata, aux_symxndxdata and aux_first_global.
+	(dwfl_adjusted_aux_sym_addr): New function.
+	(dwfl_deadjust_aux_sym_addr): Likewise.
+	(dwfl_adjusted_st_value): Take and check symfile argument.
+	(dwfl_deadjust_st_value): Likewise.
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Take and
+	use dwfl_file as argument to set address_sync.
+	(find_debuginfo): Call find_prelink_address_sync with debug file.
+	(find_aux_sym): New function.
+	(find_symtab): Use find_aux_sym if all we have is the dynsym table
+	and fill in aux DwflModule fields.
+	(dwfl_module_getsymtab): Return syments plus aux_syments.
+	(load_symtab): Always set first_global.
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Check symfile
+	when using same_section. Calculate first_global based on both
+	mod->first_global and mod->aux_first_global.
+	* dwfl_module.c (__libdwfl_module_free): Free aux_sym.
+	* dwfl_module_getsym.c (dwfl_module_getsym): Use auxsym table
+	to retrieve symbol and name if necessary, making sure all locals
+	from any table come before any globals.
+	* dwfl_module_info.c (dwfl_module_info): Call dwfl_adjusted_st_value
+	with symfile.
+	* relocate.c (resolve_symbol): Likewise.
+
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* link_map.c (auxv_format_probe): Handle unaligned 64-bit data, but
+	still assume the data is at least 32-bit aligned anyway.
+	(dwfl_link_map_report): Handle unaligned auxv data.
+
+2012-12-11  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel): Only free fname if
+	find_kernel_elf succeeds and allocates it.
+	(report_kernel_archive): Fix brackets around unlikely expression.
+
+2012-11-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* argp-std.c: Update Copyright year.
+	(offline_find_elf): New function.
+	(offline_callbacks): Use it for find_elf.
+	(struct parse_opt): New.
+	(parse_opt): New key ARGP_KEY_INIT.  In other make hook struct
+	parse_opt pointer from former Dwfl pointer.  Delay 'e and OPT_COREFILE
+	processing till ARGP_KEY_SUCCESS.  Initialize state->input already from
+	ARGP_KEY_SUCCESS.  Modify the cleanup in ARGP_KEY_ERROR.  Make the
+	final state->input initialization optional.
+	* dwfl_end.c: Update Copyright year.
+	(dwfl_end): Free executable_for_core.
+	* libdwflP.h: Update Copyright year.
+	(struct Dwfl): New field executable_for_core.
+
+2012-11-20  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Simplify START and BIAS
+	calculation.
+
+2012-10-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_module_getdwarf.c (mod_verify_build_id): New function with code
+	from ...
+	(__libdwfl_getelf): ... here.  Call it.
+
+2012-10-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* libdwfl.h (dwfl_module_getelf): Add __nonnull_attribute__.
+
+2012-10-10  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_segment_report_module.c (dwfl_segment_report_module):
+	Initialize mod->MAIN_BIAS.
+
+2012-10-10  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): New function
+	binding_value.  Use it for both zero and non-zero size symbols
+	comparisons.
+
+2012-10-01  Mark Wielaard  <mjw@redhat.com>
+
+	* cu.c (cudie_offset): Don't use type_sig8, it might not be
+	initialized and these are always real CUs, never TUs.
+
+2012-10-01  Mark Wielaard  <mjw@redhat.com>
+
+	* derelocate.c (find_section): Check next section exists before
+	accessing it.
+
+2012-08-01  Petr Machata  <pmachata@redhat.com>
+
+	* offline.c (process_archive_member): Ignore entry "/SYM64/".
+
+2012-03-28  Roland McGrath  <roland@hack.frob.com>
+
+	* dwfl_segment_report_module.c
+	(dwfl_segment_report_module: read_portion): Don't use existing buffer
+	when FILESZ is zero (string mode) and available portion doesn't hold
+	a terminated string.
+
+2011-12-02  Roland McGrath  <roland@hack.frob.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Fix ELFCLASS64 case
+	to use elf64_xlatetom and PHDRS.p64.
+	Reported by Serge Pavlov <serge.pavlov.at.gnu@gmail.com>.
+
+2011-11-31  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): First search all
+	global symbols. Then only when that doesn't provide a match search
+	all local symbols too.
+	* dwfl_module_getdwarf.c (load_symtab): Take first_global int arg
+	and fill it in.
+	(find_symtab): Initialize mod->first_global and pass it to load_symtab.
+	* libdwfl/libdwflP.h (Dwfl_Module): Add first_global field.
+
+2011-11-31  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Only update
+	sizeless_sym if needed and closer to desired addr.
+
+2011-10-20  Mark Wielaard  <mjw@redhat.com>
+
+	* derelocate.c (cache_sections): Intern mod->reloc_info check.
+	(dwfl_module_relocations): Don't check mod->reloc_info.
+	(dwfl_module_relocation_info): Likewise.
+	(find_section): Likewise.
+
+2011-07-09  Roland McGrath  <roland@hack.frob.com>
+
+	* image-header.c (LE32): Macro removed (now in lib/system.h).
+
+2011-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* linux-kernel-modules.c (vmlinux_suffixes): Guard definition
+	by check for zlib, bzlib or lzma defines to check it isn't empty.
+	(try_kernel_name): Use same guard for use of vmlinux_suffixes.
+
+2011-03-08  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Clear errno before CBFAIL.
+	Reported by Kurt Roeckx <kurt@roeckx.be>.
+
+2011-02-11  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (try_kernel_name): Try .gz, .bz2, .xz
+	suffixes if corresponding decompression support is enabled.
+
+2011-02-01  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Use the
+	section-end address as the synchronization point, rather than sh_addr.
+
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Discover
+	PT_INTERP p_vaddr separately from main phdrs and undo phdrs.
+
+	* dwfl_module_getdwarf.c (find_prelink_address_sync): Fix pasto in
+	last change, so we recognize PT_INTERP in ELFCLASS64 correctly.
+
+2011-01-11  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Remove section-based
+	address_sync fixup from here.
+	(find_prelink_address_sync): New function.
+	(find_debuginfo): Call it.
+	* libdwflP.h (DWFL_ERRORS): Add BAD_PRELINK error.
+
+2011-01-04  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Enhance address_sync calculation
+	logic to consider section addresses, the better to survive all the
+	possible prelink machinations.
+	* libdwflP.h (struct dwfl_file): Comment change.
+
+2010-11-30  Roland McGrath  <roland@redhat.com>
+
+	* derelocate.c (dwfl_module_relocations): Remove over-eager assert.
+
+2010-11-12  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h (struct Dwfl_Module): New member main_bias.
+	(dwfl_adjusted_address, dwfl_deadjust_address): Use it.
+	* dwfl_module_getdwarf.c (__libdwfl_getelf): Initialize it.
+
+	* libdwflP.h (dwfl_deadjust_address): New function.
+	(dwfl_deadjust_dwarf_addr, dwfl_deadjust_st_value): New functions.
+	* cu.c (addrarange): Use dwfl_deadjust_dwarf_addr.
+	* dwfl_module_addrsym.c: Use dwfl_deadjust_st_value.
+
+2010-11-11  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h (struct dwfl_file): Remove bias member.
+	Add vaddr and address_sync members instead.
+	(dwfl_adjusted_address): Calculate using vaddr.
+	(dwfl_adjusted_dwarf_addr): Calculate using address_sync and call that.
+	(dwfl_adjusted_st_value): Use one of those calls.
+	* dwfl_module_getdwarf.c (open_elf): Initialize vaddr and address_sync.
+	* dwfl_segment_report_module.c (dwfl_segment_report_module): Likewise.
+	* derelocate.c (dwfl_module_relocations): Update ET_EXEC assertions.
+	* link_map.c (consider_executable): Adjust only MOD->low_addr for
+	detected PIE bias change.
+
+	* libdwflP.h (dwfl_adjusted_dwarf_addr): New function.
+	* dwfl_module_info.c: Use it.
+	* cu.c (addrarange): Likewise.
+	* dwfl_dwarf_line.c: Likewise.
+	* dwfl_module_dwarf_cfi.c: Likewise.
+	* dwfl_lineinfo.c: Likewise.
+	* dwfl_nextcu.c: Likewise.
+	* dwfl_module_getdwarf.c (dwfl_module_getdwarf): Likewise.
+
+	* libdwflP.h (dwfl_adjusted_st_value): New function.
+	* relocate.c (resolve_symbol): Use it.
+	* dwfl_module_getsym.c: Likewise.
+	* dwfl_module_addrsym.c: Likewise.
+	* dwfl_module_info.c: Likewise.
+
+	* libdwflP.h (dwfl_adjusted_address): New function.
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Use it.
+	* relocate.c (__libdwfl_relocate_value): Likewise.
+	* derelocate.c (cache_sections): Likewise.
+	(dwfl_module_address_section): Likewise.
+	* dwfl_module_getelf.c: Likewise.
+	* dwfl_module_eh_cfi.c: Likewise.
+	* link_map.c (consider_executable): Likewise.
+
+2010-08-24  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_dwarf_line.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+
+2010-08-18  Roland McGrath  <roland@redhat.com>
+
+	* link_map.c (report_r_debug): Use found name if we have no name,
+	even if we already have an Elf handle.
+
+2010-06-30  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_find_elf): Don't be
+	confused by -1 return from dwfl_build_id_find_elf after it opened
+	the Elf handle.
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Likewise for
+	dwfl_build_id_find_debuginfo.
+
+2010-06-16  Roland McGrath  <roland@redhat.com>
+
+	* cu.c (cudie_offset): Use DIE_OFFSET_FROM_CU_OFFSET macro.
+
+2010-06-14  Roland McGrath  <roland@redhat.com>
+
+	* find-debuginfo.c (try_open): Take new arg MAIN_STAT.  Compare
+	candidate file to that st_dev/st_ino and pretend it didn't exist
+	if they match.
+	(find_debuginfo_in_path): Update caller, pass main file's info.
+
+2010-05-20  Roland McGrath  <roland@redhat.com>
+
+	* linux-proc-maps.c (find_sysinfo_ehdr): Renamed to ...
+	(grovel_auxv): ... this.  Take DWFL argument.
+	(dwfl_linux_proc_report): Update caller.
+
+	* dwfl_module_getdwarf.c (open_elf): Calculate alignment for bias
+	based on dwfl->segment_align or manifest alignment of MOD->low_addr.
+
+2010-05-19  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (intuit_kernel_bounds): Rewritten.
+
+2010-05-06  Roland McGrath  <roland@redhat.com>
+
+	* segment.c (insert): Clear inserted elements of DWFL->lookup_module.
+
+	* libdwflP.h (DWFL_ERRORS): Add WRONG_ID_ELF.
+	* dwfl_build_id_find_elf.c: Set MOD->main.valid when there is a build
+	ID but we didn't find a file.
+	* dwfl_module_getdwarf.c (__libdwfl_getelf): When that's set, check
+	and refuse any fallback file-by-name if it lacks the matching ID.
+
+	* dwfl_error.c (dwfl_errno): Add INTDEF.
+	* libdwflP.h: Add INTDECL.
+
+	* dwfl_module_getdwarf.c (open_elf): Do elf_end and clear FILE->elf in
+	failure cases.
+
+2010-05-04  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_segment_report_module.c: Use "[pie]" rather than "[dso]" for an
+	ET_DYN that has a DT_DEBUG.
+
+	* dwfl_segment_report_module.c: Fix jump-start of NDX-finding loop.
+
+	* segment.c (insert): Fix moving of values following insertion.
+	(reify_segments): Fix up MOD->segment backpointer indices after
+	later insertions in the main loop invalidate them.
+
+	* link_map.c (dwfl_link_map_report): Detect bias of embedded phdrs and
+	apply it to PT_DYNAMIC p_vaddr so we handle a PIE correctly.
+
+	* core-file.c (dwfl_core_file_report): Return any nonzero count of
+	modules reported, even if link_map grovelling failed and only sniffing
+	found anything.
+
+2010-04-26  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (relocate_section): Treat R_*_NONE reloc as no reloc.
+	Works around probably-wrong ld -r behavior for case of a DWARF address
+	constant that refers to a discarded SHF_ALLOC section.
+
+2010-04-14  Roland McGrath  <roland@redhat.com>
+
+	* link_map.c (report_r_debug): Limit iterations on the l_next chain to
+	an upper bound on sane possible number of elements.
+
+2010-03-11  Roland McGrath  <roland@redhat.com>
+
+	* link_map.c (auxv_format_probe): Fix scanning loop, so we really scan
+	the second half for 32-bit matches.
+
+2010-03-10  Roland McGrath  <roland@redhat.com>
+
+	* core-file.c (dwfl_core_file_report): Punt EHDR argument.
+	* argp-std.c (parse_opt): Update caller.
+	* libdwfl.h: Declare dwfl_core_file_report.
+	* libdwflP.h: Don't.
+
+2010-02-17  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_segment_report_module.c (addr_segndx): Take new flag argument.
+	If set, find the first index not below ADDR.
+	(dwfl_segment_report_module): Update callers.
+	Pass true when calculating return value.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+	* find-debuginfo.c (find_debuginfo_in_path): Fix uninitialized
+	variable in failure path.
+
+2010-02-02  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_module_dwarf_cfi.c (dwfl_module_dwarf_cfi): Always set bias.
+	* dwfl_module_eh_cfi.c (dwfl_module_eh_cfi): Likewise
+
+2010-01-07  Roland McGrath  <roland@redhat.com>
+
+	* core-file.c (dwfl_core_file_report): Use elf_getphdrnum.
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Likewise.
+	* dwfl_module_getdwarf.c (open_elf, find_dynsym): Likewise.
+	* dwfl_report_elf.c (__libdwfl_report_elf): Likewise.
+
+2010-01-06  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (relocate_getsym): For SHN_COMMON, zero st_value.
+	(relocate_section): Let unresolved SHN_COMMON symbol stay 0.
+
+2009-11-16  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (relocate_section): Skip SHT_NOBITS or empty target scn.
+
+2009-11-12  Petr Machata  <pmachata@redhat.com>
+
+	* core-file.c (dwfl_elf_phdr_memory_callback): Only load ahead if
+	the chunk is both offset-contiguous and vaddr-contiguous.
+
+2009-11-05  Roland McGrath  <roland@redhat.com>
+
+	* link_map.c (report_r_debug): Skip entries with l_ld==0.
+	Use dwfl_addrmodule for l_ld lookup, don't bail on lookup failure.
+
+2009-09-04  Roland McGrath  <roland@redhat.com>
+
+	* image-header.c (__libdw_image_header): Fix tranposed comparison.
+
+2009-08-27  Roland McGrath  <roland@redhat.com>
+
+	* image-header.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwflP.h: Declare __libdw_image_header.
+	* open.c (decompress): Don't consume ELF on failure.
+	(what_kind): New function, broken out of ...
+	(__libdw_open_file): ... here.  Call it.
+	If it fails, try __libdw_image_header and then try what_kind again.
+
+	* gzip.c (unzip): Reuse *WHOLE as first INPUT_BUFFER,
+	leave it behind for next decompressor.
+	* open.c (decompress): Free BUFFER on failure.
+
+2009-08-26  Roland McGrath  <roland@redhat.com>
+
+	* gzip.c (find_zImage_payload): New function, broken out of ...
+	(mapped_zImage): ... here.  Call it.
+	(find_zImage_payload) [LZMA]: Match LZMA-compressed kernels with
+	stupid method of just trying the decoder.
+
+	* open.c [USE_LZMA]: Try __libdw_unlzma.
+	* libdwflP.h: Declare it.
+	(DWFL_ERRORS): Add DWFL_E_LZMA.
+	* gzip.c [LZMA]: Implement liblzma version for XZ file format.
+	* lzma.c: New file.
+	* Makefile.am [LZMA] (libdwfl_a_SOURCES): Add it.
+
+	* gzip.c (mapped_zImage): Limit scan to 32kb.
+	Make this unconditional, support bzip2 kernel images too.
+	(unzip): Use direct inflate method for non-mmap case too.
+	Only zlib uses the stream method.
+
+2009-08-09  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_build_id.c: Use new macros for versioned definitions.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_dwarf_cfi.c: New file.
+	* dwfl_module_eh_cfi.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add them.
+	* libdwflP.h (struct Dwfl_Module): New members `dwarf_cfi', `eh_cfi.
+	Add INTDECL for dwfl_module_eh_cfi, dwfl_module_dwarf_cfi.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h (struct Dwfl_Module): Reorder members to pack better.
+
+2009-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Return NULL on overlap.
+
+2009-06-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* derelocate.c: Don't use deprecated libelf functions.
+	* dwfl_module_getdwarf.c: Likewise.
+	* relocate.c: Likewise.
+
+2009-04-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwfl_module_build_id.c: Define versioned symbols only if SHARED is
+	defined.  Otherwise just define the latest version.
+
+2009-04-22  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (resolve_symbol): Apply correct bias to st_value found in
+	a non-ET_REL module.
+
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Fix last change to
+	adjust properly for non-ET_REL.
+
+2009-04-21  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getsym.c: Apply non-ET_REL bias only if SHF_ALLOC.
+
+	* relocate.c (__libdwfl_relocate_value): Assert that MOD is ET_REL.
+	* derelocate.c (cache_sections): Call __libdwfl_relocate_value only
+	for ET_REL.
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Likewise.
+
+2009-04-20  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (__libdwfl_getelf): Add internal_function.
+
+2009-04-19  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_file): Renamed to ...
+	(__libdwfl_getelf): ... this.  Make it global.
+	(find_symtab, find_dw): Update callers.
+	(dwfl_module_getelf): Functions moved ...
+	* dwfl_module_getelf.c: ... here, new file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwflP.h: Declare __libdwfl_getelf.
+
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_segment_report_module.c: Handle DT_STRTAB value being either
+	absolute (already adjusted in place) or needing load bias adjustment.
+
+	* core-file.c (dwfl_elf_phdr_memory_callback): Fix return value for
+	gelf_getphdr failure.  Fix file size limit checks.
+
+	* dwfl_segment_report_module.c: Fix underflow in DYNSTRSZ check.
+
+2009-04-08  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getsym.c: Don't adjust for bias again after
+	__libdwfl_relocate_value.
+
+	* relocate.c (__libdwfl_relocate_value): Don't adjust a value from
+	a non-SHF_ALLOC section.
+	(relocate_getsym): Test st_shndx for SHN_* values, not *SHNDX.
+	* dwfl_module_getsym.c (dwfl_module_getsym): Likewise.
+
+2009-03-09  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Move SHSTRNDX
+	variable to outer scope, so we cache it for the loop.
+
+	* relocate.c (__libdwfl_relocate_value): Add MOD->main.bias to sh_addr.
+
+2009-02-12  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Use
+	__libdwfl_relocate_value to find correct sh_addr value.
+
+2009-02-10  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Take new arg SANITY.
+	If false, don't fail for NO_PHDR.
+	(dwfl_report_elf): Update caller.
+	* libdwflP.h: Update decl.
+	* offline.c (process_elf): Call it with false, so we don't refuse
+	dubiously-formed objects here.
+
+	* link_map.c (consider_executable): Don't assert dwfl_addrsegment
+	finds our module.  We shouldn't crash when we confuse some guesses.
+
+2009-02-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* open.c (decompress): Avoid crash with empty input file.
+
+2009-01-27  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Ignore trailing PT_LOAD
+	with zero vaddr and memsz.
+
+2009-01-22  Roland McGrath  <roland@redhat.com>
+
+	* open.c (decompress): Move BUFFER, SIZE decls outside #if.
+
+	* dwfl_segment_report_module.c (addr_segndx): Remove bogus adjustments
+	after address-matching loop.
+
+	* segment.c (lookup): Fix fencepost in checking for HINT match.
+
+2009-01-14  Roland McGrath  <roland@redhat.com>
+
+	* gzip.c [!BZLIB] (mapped_zImage): New function.
+	(unzip) [!BZLIB]: Grok Linux kernel zImage format.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwfl_error.c: Always use __thread.  Remove all !USE_TLS code.
+
+2009-01-08  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_offline):
+	Skip subdirectory named "source".
+	(dwfl_linux_kernel_find_elf): Likewise.
+
+2009-01-06  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (check_suffix): New function.
+	Match ".ko", ".ko.gz", and ".ko.bz2" suffixes.
+	(dwfl_linux_kernel_report_offline): Use it.
+	(dwfl_linux_kernel_find_elf): Likewise.
+
+2009-01-05  Roland McGrath  <roland@redhat.com>
+
+	* argp-std.c (parse_opt): Use __libdw_open_file for core file.
+	* dwfl_build_id_find_debuginfo.c: Use it to open the file.
+	* dwfl_build_id_find_elf.c: Likewise.
+	* dwfl_module_getdwarf.c (open_elf): Likewise.
+	* dwfl_report_elf.c: Likewise.
+	* find-debuginfo.c (validate): Likewise.
+	* offline.c (__libdwfl_report_offline): Likewise.
+
+	* libdwflP.h: Declare __libdw_open_file.
+	* open.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+
+	* gzip.c: New file.
+	* Makefile.am [ZLIB] (libdwfl_a_SOURCES): Add it.
+	* bzip2.c: New file.
+	* Makefile.am [BZLIB] (libdwfl_a_SOURCES): Add it.
+	* libdwflP.h: Declare __libdw_gunzip, __libdw_bunzip2.
+
+2008-12-16  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_build_id.c (dwfl_module_build_id): Define with alias and
+	symver magic to bind to ELFUTILS_0.138.
+	(_BUG_COMPAT_dwfl_module_build_id): New function, bug compatible
+	wrapper for ELFUTILS_0.130 version set.
+
+2008-12-18  Roland McGrath  <roland@redhat.com>
+
+	* derelocate.c (dwfl_module_relocate_address): Fix last fix: ET_DYN
+	addresses are taken as relative to MOD->low_addr.
+
+2008-12-15  Roland McGrath  <roland@redhat.com>
+
+	* derelocate.c (dwfl_module_relocate_address): Apply main.bias, not
+	debug.bias.
+
+2008-12-11  Roland McGrath  <roland@redhat.com>
+
+	* offline.c (process_archive): Don't call elf_end and close if
+	returning NULL.  Check first elf_begin call and set error code
+	specially for empty archive.
+	Fixes RHBZ#465878.
+
+2008-12-02  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_getmodules.c (dwfl_getmodules): Typo fix in last change.
+
+2008-11-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_getmodules.c (dwfl_getmodules): Encode iteration style in
+	return value, and interpret encoded OFFSET argument.
+
+2008-10-07  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_build_id.c (check_notes): Fix typo in vaddr calculation.
+
+2008-09-29  Roland McGrath  <roland@redhat.com>
+
+	* segment.c (insert): Must realloc DWFL->lookup_module here too.
+	(dwfl_report_segment): Clear DWFL->lookup_module before insert calls.
+
+2008-08-28  Roland McGrath  <roland@redhat.com>
+
+	* segment.c (reify_segments): Fix last change.
+
+2008-08-27  Roland McGrath  <roland@redhat.com>
+
+	* linux-proc-maps.c (read_proc_memory): Return 0 for EINVAL or EPERM
+	failure from pread64.
+
+2008-08-26  Roland McGrath  <roland@redhat.com>
+
+	* segment.c (reify_segments): Insert a trailing segment for a module
+	end that is above the highest current segment.
+
+2008-08-25  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Extract elf_errno () for
+	coded return value, not plain DWFL_E_LIBELF.  Return DWFL_E_BADELF
+	if FILE->elf is not ELF_K_ELF.
+
+	* dwfl_segment_report_module.c: Add a cast.
+
+2008-08-21  Denys Vlasenko  <dvlasenk@redhat.com>
+
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Improve logic
+	which decides which symbol is "closest" to a given address.
+
+2008-08-15  Roland McGrath  <roland@redhat.com>
+
+	* argp-std.c (offline_callbacks): Use dwfl_build_id_find_elf.
+	(options, parse_opt): Handle --core.
+
+	* core-file.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwflP.h (dwfl_core_file_report): Declare it.
+
+	* link_map.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwflP.h (dwfl_link_map_report): Declare it.
+
+	* libdwflP.h (MIN, MAX): New macros.
+	(Dwfl_Memory_Callback): New typedef.
+	(Dwfl_Module_Callback): New typedef.
+	(dwfl_segment_report_module): Declare it.
+	* dwfl_segment_report_module.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+
+	* derelocate.c (dwfl_module_address_section): Add INTDEF.
+	* libdwflP.h: Add INTDECL.
+
+	* segment.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_addrsegment, dwfl_report_segment.
+	* libdwflP.h (struct Dwfl): New members lookup_elts, lookup_alloc,
+	lookup_addr, lookup_module, lookup_segndx, replace removed members
+	modules, nmodules.
+	(struct Dwfl_Module): New member segment.
+	* dwfl_end.c (dwfl_end): Free the new ones.  Iterate via modulelist
+	to each free module.
+	* dwfl_module.c (dwfl_report_begin_add): Do nothing.
+	(dwfl_report_begin): Don't call it.  Truncate the segment table instead.
+	(dwfl_report_module): Don't touch DWFL->nmodules.
+	(dwfl_report_end): Don't touch DWFL->modules and DWFL->nmodules.
+	(compare_modules): Function removed.
+	* dwfl_getmodules.c: Rewritten.
+	Add INTDEF.
+	* libdwflP.h: Add INTDECLs.
+	* dwfl_getdwarf.c: Rewritten to call dwfl_getmodules.
+	* dwfl_addrmodule.c: Rewritten to just call dwfl_addrsegment.
+
+2008-08-03  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c: Include <fts.h> before <config.h>.
+
+2008-07-17  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Set errno to
+	zero if the failure was only ENOENT.
+
+2008-06-03  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_addrsym.c (dwfl_module_addrsym): Exclude undefined
+	symbols.
+
+2008-05-22  Petr Machata  <pmachata@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Bias of ET_EXEC files is always 0.
+
+2008-05-06  Roland McGrath  <roland@frob.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Use
+	FTS_LOGICAL here too.
+	(dwfl_linux_kernel_find_elf): Likewise.
+
+2008-04-29  Roland McGrath  <roland@redhat.com>
+
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Try path search
+	based on canonicalize_file_name if it differs from the supplied name.
+
+	* linux-kernel-modules.c (check_module_notes): Use FTS_LOGICAL so
+	we accept symlinks.
+
+2008-04-27  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel): Fix crash when
+	dwfl_report_elf fails.
+
+2008-04-05  Roland McGrath  <roland@redhat.com>
+
+	* linux-proc-maps.c (proc_maps_report): Don't leak LAST_FILE.
+
+	* dwfl_module_getdwarf.c (find_file): Always free build_id_bits.
+	Clear it after freeing.
+	* dwfl_module_report_build_id.c (dwfl_module_report_build_id): Likewise.
+
+2008-03-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (load_symtab): Don't return success for
+	SHT_DYNSYM, just set *SYMSCN like the comment says.
+
+	* dwfl_end.c (dwfl_end): Iterate on modulelist chain, not modules array.
+
+	* argp-std.c (parse_opt): On failure, call dwfl_end before argp_failure.
+
+2008-03-19  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getsrc.c: Adjust address for module bias before search.
+
+2008-03-01  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h (__libdwfl_seterrno): Remove parameter name from
+	prototype to avoid older compiler's complaint about reuse of the name.
+	(__libdwfl_canon_error): Likewise.
+
+2008-02-19  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (relocate_section): Check for an unhandled relocation
+	type before resolving a reloc's symbol.  Lift DWFL_E_BADRELTYPE ->
+	DWFL_E_UNKNOWN_MACHINE check out of loops.
+
+	* dwfl_module_getdwarf.c (load_dw): Skip relocation if
+	DEBUGFILE->relocated is already set.
+
+2008-01-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (open_elf): Open FILE->name if it's non-null.
+
+	* dwfl_build_id_find_elf.c (__libdwfl_open_by_build_id): Don't clear
+	incoming *FILE_NAME at the start.
+
+2008-01-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (euinclude): Variable removed.
+	(pkginclude_HEADERS): Set this instead of euinclude_HEADERS.
+
+2007-10-23  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel_archive): Reorder the kernel
+	module to appear first.
+
+2007-10-20  Roland McGrath  <roland@redhat.com>
+
+	* offline.c (process_archive_member): Take FD argument, pass it down
+	to process_file.  Return Elf_Cmd, not bool.
+	Call elf_next here, always before elf_end.
+	(process_archive): Update caller.  Don't close FD here unless there
+	are no member refs.
+
+	* dwfl_module.c (free_file): Close fd only when elf_end returns zero.
+
+	* libdwflP.h (struct dwfl_file): New bool member `relocated'.
+	* dwfl_module_getdwarf.c (dwfl_module_getelf): For ET_REL, apply
+	partial relocation to one or both files.
+	(dwfl_module_getdwarf): For ET_REL, make sure extra sections'
+	relocations have been applied to the debug file if dwfl_module_getelf
+	has been used before.
+
+	* relocate.c (resolve_symbol): New function.
+	(relocate_section): Call it.
+
+	* relocate.c (relocate_getsym): Handle null MOD->symfile.
+	(relocate_section): Take new bool arg, PARTIAL.  If true,
+	no error for BADRELTYPE/RELUNDEF, instead just skip them
+	and leave only those skipped relocs behind the reloc section.
+	(__libdwfl_relocate_section): Take new arg, pass it down.
+	(__libdwfl_relocate): Take new bool arg, DEBUG.  If false,
+	do partial relocation on all sections.
+	* dwfl_module_getdwarf.c (load_dw): Update caller.
+	* libdwflP.h: Update decls.
+	* derelocate.c (dwfl_module_address_section): Pass new argument
+	to __libdwfl_relocate_section, true.
+
+	* derelocate.c (cache_sections): Don't cache reloc sections when
+	section_address callback is null.
+
+2007-10-19  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (relocate_section): Fix fencepost error in r_offset check.
+
+	* derelocate.c (struct dwfl_relocation): Add member `relocs'.
+	(struct secref): Likewise.
+	(cache_sections): Cache the relocation section referring to each
+	section we cache, if any.
+	(dwfl_module_address_section): Use __libdwfl_relocate_section as
+	necessary.
+
+	* relocate.c (struct reloc_symtab_cache): New type.
+	(relocate_getsym): Use it instead of four arguments.
+	(__libdwfl_relocate): Update caller.
+	(relocate_section): New function, broken out of ...
+	(__libdwfl_relocate): ... here.
+	(__libdwfl_relocate_section): New function.
+	* libdwflP.h: Declare it.
+
+2007-10-17  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getsym.c (dwfl_module_getsym): Apply MOD->symfile->bias
+	to relocated st_value.
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Align initial BASE for
+	ET_REL to 0x100.
+
+2007-10-16  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Readjust BASE when a later
+	section has larger alignment requirements not met by the original BASE,
+	rather than padding more between sections.
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Fix bias calculation.
+
+	* dwfl_module_build_id.c (__libdwfl_find_build_id): Apply module bias
+	to sh_addr value.
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Don't be confused by BASE
+	at zero in ET_REL case.  Adjust BASE to necessary alignment.
+
+	* dwfl_module_build_id.c (check_notes): Take -1, not 0, as stub value
+	for DATA_VADDR.
+	(__libdwfl_find_build_id): Update caller.
+
+	* relocate.c (__libdwfl_relocate_value): Don't use sh_offset.
+	* dwfl_report_elf.c (__libdwfl_report_elf): Likewise.
+	* offline.c (dwfl_offline_section_address): Bail early if there is
+	separate debug file.
+
+	* relocate.c (__libdwfl_relocate): Don't return DWFL_E_NO_DWARF.
+
+2007-10-09  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): Clear SHDR->sh_offset when
+	caching SHDR->sh_addr = 0.
+	* offline.c (dwfl_offline_section_address): Never called for sh_addr
+	really at 0, don't check for it.  Use MOD->debug directly, not symfile.
+
+	* dwfl_module_getdwarf.c (load_symtab): Return success properly when
+	we've found SHT_SYMTAB.
+
+	* relocate.c (relocate_getsym): New function.
+	(__libdwfl_relocate): Use it.
+	(__libdwfl_relocate_value): Take new Elf * argument.  Make SYMSHSTRNDX
+	be a pointer instead of value; cache getshstrndx result there.
+	* libdwflP.h: Update decl.
+	* derelocate.c (cache_sections): Update caller.
+	Always work on the main file, not the symfile.
+	(dwfl_module_address_section): Likewise.
+	* dwfl_module_getsym.c (dwfl_module_getsym): Update caller.
+
+2007-10-07  Roland McGrath  <roland@redhat.com>
+
+	* offline.c (process_archive): Initialize MOD.
+
+	* linux-kernel-modules.c (get_release): New function, broken out of ...
+	(report_kernel): ... here.  Call it.
+	(try_kernel_name): Take new arg TRY_DEBUG, only try ".debug" if set.
+	(find_kernel_elf): Update caller.
+	(report_kernel_archive): New function.
+	(dwfl_linux_kernel_report_offline): Call it.
+
+	* offline.c (process_file): Take new arg PREDICATE, pass it down.
+	(process_archive): Likewise.
+	(process_archive_member): Likewise.  When nonnull, let the predicate
+	decide whether to use this member.
+	(__libdwfl_report_offline): New function, broken out of ...
+	(dwfl_report_offline): ... here.  Call it.
+	* libdwflP.h: Declare it.
+
+	* offline.c (process_archive, process_archive_member): New functions.
+	(process_elf, process_file): New functions, broken out of ...
+	(dwfl_report_offline): ... here.  Call process_file, which recurses on
+	ELF_K_AR files.
+
+	* dwfl_report_elf.c (__libdwfl_report_elf): New, broken out of ...
+	(dwfl_report_elf): ... here.  Call it.
+	* libdwflP.h: Declare it.
+
+2007-10-06  Roland McGrath  <roland@redhat.com>
+
+	* derelocate.c (dwfl_module_relocations): Don't call
+	dwfl_module_getdwarf.
+
+	* derelocate.c (find_section): Use __libdwfl_seterrno, not
+	__libdw_seterrno.
+
+	* relocate.c (__libdwfl_relocate_value): Abuse sh_offset, not
+	SHF_ALLOC, to cache sh_addr resolved to 0.
+
+	* dwfl_report_elf.c (dwfl_report_elf): When an ET_REL file has sh_addr
+	values nonzero already, just use its existing layout.
+
+	* relocate.c (__libdwfl_relocate): Clear size of reloc section in its
+	in-core shdr after applying it.
+
+2007-10-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_kernel): Fake
+	initialization of notes variable.
+
+2007-10-04  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (intuit_kernel_bounds): Take new arg NOTES,
+	fill in with vaddr of "__start_notes" symbol if found.
+	(check_notes): New function.
+	(check_kernel_notes): New function.
+	(dwfl_linux_kernel_report_kernel): Call it.
+	(check_module_notes): New function.
+	(dwfl_linux_kernel_report_modules): Call it.
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_find_elf):
+	Try dwfl_build_id_find_elf first.
+
+	* linux-kernel-modules.c (report_kernel): Don't leak FD if !REPORT.
+	Set kernel module e_type to ET_DYN.
+
+2007-10-03  Roland McGrath  <roland@redhat.com>
+
+	* find-debuginfo.c (validate): New function, broken out of ...
+	(find_debuginfo_in_path): ... here.  New function, broken out of ...
+	(dwfl_standard_find_debuginfo): ... here.  Call it, after trying
+	dwfl_build_id_find_debuginfo first.
+
+	* dwfl_build_id_find_elf.c: New file.
+	* dwfl_build_id_find_debuginfo.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add them.
+	* libdwfl.h: Declare them.
+	* libdwflP.h: Add INTDECLs.
+
+	* dwfl_module_build_id.c: New file.
+	* dwfl_module_report_build_id.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add them.
+	* libdwfl.h: Declare them.
+	* libdwflP.h (struct Dwfl_Module): New members build_id_bits,
+	build_id_len, build_id_vaddr.  Declare __libdwfl_find_build_id.
+	* dwfl_module.c (__libdwfl_module_free): Free MOD->build_id_bits.
+
+	* dwfl_module_getdwarf.c (find_offsets): New function.
+	(find_dynsym): New function, calls that.
+	(find_symtab): Call it.
+
+2007-09-11  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_addrsym.c: Prefer a later global symbol at the same
+	address if its st_size is smaller.
+
+2007-08-13  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_addrsym.c: Add dead initializer for stupid compiler.
+
+2007-08-12  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Don't use
+	FTS_LOGICAL.
+
+	* elf-from-memory.c (elf_from_remote_memory): Don't reset LOADBASE on
+	a second phdr if it happens to match EHDR_VMA exactly.
+
+2007-08-08  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_addrsym.c: Don't use STT_SECTION, STT_FILE symbols and
+	those with no names.  Rewrite best symbol algorithm not to assume a
+	sorted table and to be smarter handling sizeless symbols.
+
+2007-07-16  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (dwfl_report_module): Increment DWFL->nmodules when
+	reviving an existing module.
+
+2007-06-08  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h: Fix #ifndef for config.h to use PACKAGE_NAME.
+
+2007-05-17  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_offline): Look at
+	whole /lib/modules/VERSION tree, not just /lib/modules/VERSION/kernel.
+	(dwfl_linux_kernel_find_elf): Likewise.
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_modules): Use
+	getline and sscanf instead of fscanf.
+
+2007-05-08  Roland McGrath  <roland@redhat.com>
+
+	* offline.c (dwfl_offline_section_address): Don't assume section
+	numbers match between stripped and debuginfo files.  Instead, assume
+	only that the ordering among SHF_ALLOC sections matches.
+
+	* linux-kernel-modules.c (report_kernel): Change RELEASE argument to
+	pointer to string.
+	(dwfl_linux_kernel_report_offline): Update caller.
+	(dwfl_linux_kernel_report_kernel): Likewise.
+
+2007-04-23  Roland McGrath  <roland@redhat.com>
+
+	* argp-std.c (options): Fix group title string.
+
+	* argp-std.c (parse_opt): Handle ARGP_KEY_ERROR, free the Dwfl.
+	Update via STATE->input every time we set STATE->hook, not only at
+	ARGP_KEY_SUCCESS.
+
+	* dwfl_module.c (free_file): Free FILE->name.
+
+2007-04-16  Roland McGrath  <roland@redhat.com>
+
+	* derelocate.c (cache_sections): Apply bias to sh_addr.
+	(compare_secrefs): Fix address comparison to avoid signed overflow.
+	(find_section): New function, broken out of ...
+	(dwfl_module_relocate_address): ... here, call it.
+	(check_module): New function, broken out of ...
+	(dwfl_module_relocate_address): ... here, call it.
+	(dwfl_module_address_section): New function.
+	* libdwfl.h: Declare it.
+
+2007-03-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (__libdwfl_module_free): Free MOD itself.
+
+2007-03-18  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (find_debuglink): New function, broken out of
+	(find_debuginfo): ... here.  Call it.
+	Don't return error for libelf errors finding .gnu_debuglink section.
+
+2007-03-12  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (dwfl_report_begin_add): New function broken out of ...
+	(dwfl_report_begin): ... here.  Call it.
+	* libdwfl.h: Declare it.
+	* libdwflP.h: Add INTDECL.
+
+	* elf-from-memory.c (elf_from_remote_memory): Fix 32/64 typo.
+
+	* offline.c: Comment typo fix.
+
+2007-03-04  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (KERNEL_MODNAME): New macro for "kernel".
+	(find_kernel_elf): New function, broken out of ...
+	(report_kernel): ... here.  Call it.
+	(dwfl_linux_kernel_find_elf): Use it for module named KERNEL_MODNAME.
+	(intuit_kernel_bounds): New function, grovel /proc/kallsyms to guess
+	virtual address bounds of kernel from symbols rounded to page size.
+	(dwfl_linux_kernel_report_kernel): Use that if it works, before
+	resorting to report_kernel.
+
+	* dwfl_module_getdwarf.c (open_elf): Set MOD->e_type to ET_DYN for an
+	ET_EXEC file with nonzero bias.
+
+	* dwfl_module_addrname.c (dwfl_module_addrname): Just call
+	dwfl_module_addrsym.  Guts moved to ...
+	* dwfl_module_addrsym.c: ... here; new file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_module_addrsym.
+	* libdwflP.h: Add INTDECL.
+
+2007-03-03  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (free_file): New function, broken out of ...
+	(__libdwfl_module_free): ... here.  In it, close fd after elf_end.
+
+	* dwfl_module_getdwarf.c (open_elf): Close fd and reset to -1
+	on libelf failure.
+
+2007-03-02  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c: Fix bogus error test for asprintf call.
+
+2007-02-02  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_addrmodule.c (dwfl_addrmodule): Match a module's high boundary
+	address exactly if it's no other module's low boundary.
+
+	* dwfl_module_addrname.c (dwfl_module_addrname): If no symbol's value
+	and size cover the address, select the closest symbol with st_size==0
+	that lies in the same section.
+
+2007-01-29  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_version.c (dwfl_version): Return PACKAGE_VERSION,
+	not PACKAGE_STRING.
+
+2007-01-20  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (__libdwfl_relocate_value): Treat section_address of -1
+	as omitted, not 0.
+	* libdwfl.h (Dwfl_Callbacks): Update comment.
+	* derelocate.c (cache_sections): Don't ignore sh_addr == 0 sections.
+	* linux-kernel-modules.c (dwfl_linux_kernel_module_section_address):
+	For ignored missing section, use -1 instead of 0.
+	* offline.c (dwfl_offline_section_address): Expect a call for 0.
+
+2007-01-19  Roland McGrath  <roland@redhat.com>
+
+	* argp-std.c (parse_opt): For -e, reset DWFL->offline_next_address to
+	zero so a lone -e foo.so is shown without address bias.
+
+2007-01-10  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel): Check asprintf return value
+	directly instead of via side effect, to silence warn_unused_result.
+	(dwfl_linux_kernel_report_offline): Likewise.
+	(dwfl_linux_kernel_find_elf): Likewise.
+	(dwfl_linux_kernel_module_section_address): Likewise.
+	* find-debuginfo.c (try_open): Likewise.
+	* linux-proc-maps.c (find_sysinfo_ehdr): Likewise.
+	(dwfl_linux_proc_report): Likewise.
+
+	* libdwfl.h (dwfl_begin): Require nonnull argument.
+
+2006-12-27  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (compare_modules): Fix address comparison to avoid
+	signed overflow.  Patch by Frank Ch. Eigler <fche@redhat.com>.
+
+2006-10-30  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (dwfl_report_module): Comment typo fix.
+
+2006-09-05  Roland McGrath  <roland@redhat.com>
+
+	* derelocate.c (cache_sections): Use alloca instead of variable-sized
+	auto array, in function already using alloca.
+
+2006-08-14  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (try_kernel_name): If the call to
+	dwfl_standard_find_debuginfo produces no results, try it again
+	with NULL as DEBUGLINK_FILE to try *FNAME with .debug suffix.
+
+	* find-debuginfo.c (DEFAULT_DEBUGINFO_PATH): Macro moved ...
+	* libdwflP.h: ... to here.
+	* linux-kernel-modules.c (try_kernel_name): Skip manual open if it
+	repeats the first thing dwfl_standard_find_debuginfo will try.
+
+	* linux-kernel-modules.c (MODULE_SECT_NAME_LEN): New macro.
+	(dwfl_linux_kernel_module_section_address): If a /sys file is missing
+	and the section name is >= MODULE_SECT_NAME_LEN, try truncating the
+	section name.
+
+2006-07-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* cu.c: Adjust for internal_function_def removal.
+	* dwfl_error.c: Likewise.
+	* dwfl_module.c: Likewise.
+	* dwfl_module_getdwarf.c: Likewise.
+	* lines.c: Likewise.
+	* relocate.c: Likewise.
+
+2006-07-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwfl_module.c (compare_modules): Don't return GElf_Sxword value,
+	it can overflow the return value type.
+	Patch by Tim Moore <timoore@redhat.com>.
+
+2006-06-28  Roland McGrath  <roland@redhat.com>
+
+	* libdwfl.h: Cosmetic changes.
+
+	* dwfl_line_comp_dir.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_line_comp_dir.
+
+	* dwfl_lineinfo.c (dwfl_lineinfo): Remove stray extern in defn.
+
+	* dwfl_linecu.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_linecu.
+
+	* libdwflP.h (dwfl_linecu_inline): Function renamed from dwfl_linecu.
+	(dwfl_linecu): Define as macro.
+
+	* relocate.c (__libdwfl_relocate): Use dwfl_module_getsym.
+
+	* dwfl_module_getdwarf.c (dwfl_module_getsymtab): New function.
+	(dwfl_module_addrname): Function moved ...
+	* dwfl_module_addrname.c: ... here, new file.
+	* dwfl_module_getsym.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add them.
+	* libdwfl.h: Declare dwfl_module_getsymtab, dwfl_module_getsym.
+	* libdwflP.h: Add INTDECLs.
+
+2006-06-27  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module.c (dwfl_report_end): Whitespace fix.
+
+2006-06-13  Roland McGrath  <roland@redhat.com>
+
+	* elf-from-memory.c (elf_from_remote_memory): Fix 32/64 typo.
+	Use __libdwfl_seterrno for elf_memory failure.
+
+2006-05-22  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_return_value_location.c
+	(dwfl_module_return_value_location): Use __libdwfl_module_getebl.
+
+2006-05-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdwfl.h: Add extern "C".
+
+2006-05-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* cu.c (addrarange): Handle files without aranges information.
+
+2006-05-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* dwfl_addrmodule.c (dwfl_addrmodule): Also return NULL of
+	->modules is NULL.
+
+2006-02-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_version.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_version.
+
+	* offline.c (dwfl_report_offline): Account for dwfl_report_elf having
+	aligned up from DWFL->offline_next_address when checking for overlap.
+
+2005-12-22  Roland McGrath  <roland@redhat.com>
+
+	* argp-std.c (parse_opt): Call dwfl_end in failure cases.
+
+	* linux-proc-maps.c (proc_maps_report): New function, broken out of ...
+	(dwfl_linux_proc_report): ... here.  Call it.
+	(dwfl_linux_proc_maps_report): New function.
+	* libdwfl.h: Declare it.
+	* libdwflP.h: Add INTDECL.
+	* argp-std.c (options, parse_opt): Grok -M/--linux-process-map.
+
+	* dwfl_nextcu.c (dwfl_nextcu): Don't fail when dwfl_module_getdwarf
+	failed with DWFL_E_NO_DWARF.
+
+2005-11-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_end.c (dwfl_end): Free the DWFL itself.
+
+2005-11-25  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getdwarf.c (__libdwfl_module_getebl): New function.
+	(load_dw): Use it.
+	* dwfl_module_register_names.c (dwfl_module_register_names): Likewise.
+	* libdwflP.h: Declare it.
+
+	* dwfl_module_register_names.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_module_register_names.
+
+2005-11-21  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_module_section_address):
+	Don't leak malloc'd file name.
+	If a /sys/.../sections file is missing and starts with ".init",
+	try the variant with "_init" too; catches PPC64 kernel braindamage.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* libdwfl.h: Comment fixes.
+
+	* dwfl_module_return_value_location.c: Add unlikely for error case.
+
+2005-11-13  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_return_value_location.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_module_return_value_location.
+	* libdwflP.h (DWFL_ERRORS): Add DWFL_E_WEIRD_TYPE.
+
+2005-10-20  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h (DWFL_ERRORS): New error UNKNOWN_MACHINE.
+	* relocate.c (__libdwfl_relocate): Return DWFL_E_UNKNOWN_MACHINE
+	instead of DWFL_E_BADRELTYPE if ebl_get_elfmachine yields EM_NONE.
+
+2005-10-01  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel): Return ENOENT if we fail
+	with errno 0.
+
+2005-09-19  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_report_modules): Use
+	PRIx64 instead of PRIi64, lest addresses with high bits set overflow
+	the signed integer reading; they will just have to be in hexadecimal.
+	(dwfl_linux_kernel_module_section_address): Likewise.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (%.os): Use COMPILE.os.
+	(COMPILE.os): Filter out gconv options.
+
+2005-08-25  Roland McGrath  <roland@redhat.com>
+
+	* cu.c (__libdwfl_nextcu): Return success when dwarf_nextcu hits end.
+	* dwfl_nextcu.c (dwfl_nextcu): Skip modules with no dwarf info.
+
+2005-08-24  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_lineinfo.c (dwfl_lineinfo): Add bias, don't subtract it.
+
+	* argp-std.c [_MUDFLAP] (__libdwfl_argp_mudflap_options): New function,
+	magic initializer to set -heur-stack-bound option.
+
+2005-08-22  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_validate_address.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_validate_address.
+
+	* derelocate.c (dwfl_module_relocate_address): Add INTDEF.
+	* libdwflP.h: Add INTDECL.
+
+	* dwfl_module_getdwarf.c (find_symtab): Use elf_getdata instead of
+	elf_rawdata for symbol-related sections.
+
+	* offline.c (dwfl_report_offline): Move offline_next_address outside
+	module's range, in case it's an ET_EXEC using fixed segment locations.
+	* libdwfl.h: Update comment.
+
+	* dwfl_report_elf.c (dwfl_report_elf): Align BASE to first segment's
+	required alignment.
+
+2005-08-20  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (report_kernel): Take new argument PREDICATE,
+	function to choose whether to report.
+	(dwfl_linux_kernel_report_offline): Likewise.
+	* libdwfl.h: Update decl.
+	* argp-std.c (parse_opt): Update caller.
+
+	* dwfl_getsrclines.c: New file.
+	* dwfl_onesrcline.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add them.
+	* libdwfl.h: Declare dwfl_getsrclines, dwfl_onesrcline.
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_find_elf): Don't leak
+	MODULESDIR[0].  Call fts_close on failure.
+
+	* dwfl_module_getdwarf.c (load_dw): Take dwfl_file * instead of Elf *.
+	Close ET_REL file descriptors after relocation.
+	(find_dw): Update caller.
+	* offline.c (dwfl_report_offline): Get the file into memory and close
+	the file descriptor.
+
+	* dwfl_module_getdwarf.c (find_debuginfo): Do nothing when
+	MOD->debug.elf is already set.
+
+	* find-debuginfo.c (try_open): Use TEMP_FAILURE_RETRY.
+	(dwfl_standard_find_debuginfo): Fail on errors not ENOENT or ENOTDIR.
+
+	* argp-std.c (options, parse_opt): Grok -K/--offline-kernel, use
+	dwfl_linux_kernel_report_offline with offline_callbacks.
+
+	* linux-kernel-modules.c (report_kernel): New function, broken out of
+	...
+	(dwfl_linux_kernel_report_kernel): ... here.  Use it.
+	(dwfl_linux_kernel_report_offline): New function.
+	* libdwfl.h: Declare it.
+	* libdwflP.h: Add INTDECL.
+
+2005-08-19  Roland McGrath  <roland@redhat.com>
+
+	Use standard debuginfo search path to look for vmlinux.
+	* find-debuginfo.c (dwfl_standard_find_debuginfo): Don't check CRC if
+	passed zero.
+	* linux-kernel-modules.c (try_kernel_name): New function, broken out
+	of ...
+	(dwfl_linux_kernel_report_kernel): ... here.  Use it.
+
+	* argp-std.c (offline_callbacks): New variable.
+	(parse_opt): Use it for -e.  Allow multiple -e options.
+
+	* offline.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+	* libdwfl.h: Declare dwfl_offline_section_address, dwfl_report_offline.
+	* libdwflP.h: Add INTDECLs.
+	(OFFLINE_REDZONE): New macro.
+	(struct Dwfl): New member `offline_next_address'.
+	* dwfl_begin.c (dwfl_begin): Initialize it.
+	* dwfl_module.c (dwfl_report_begin): Likewise.
+
+	* dwfl_report_elf.c (dwfl_report_elf): Accept all types.  When ET_REL,
+	do a nominal absolute section layout starting at BASE.
+	* libdwfl.h: Update comment.
+
+2005-08-18  Roland McGrath  <roland@redhat.com>
+
+	* dwfl_module_getsrc_file.c (dwfl_module_getsrc_file): Do
+	dwfl_module_getdwarf if necessary.
+
+	* dwfl_report_elf.c (dwfl_report_elf): Permit ET_REL with BASE==0.
+	* libdwfl.h: Update comment.
+
+	* derelocate.c: New file.
+	* Makefile.am (libdwfl_a_SOURCES): Add it.
+
+	* libdwflP.h (struct Dwfl_Module): isrel -> e_type.
+	* dwfl_report_elf.c (dwfl_report_elf): Initialize it.
+	* dwfl_module_getdwarf.c (open_elf): Update initialization.
+	(load_dw, dwfl_module_addrname): Update uses.
+	* relocate.c (__libdwfl_relocate): Likewise.
+
+2005-08-04  Roland McGrath  <roland@redhat.com>
+
+	* libdwfl.h (Dwfl_Callbacks.section_address): Take additional
+	arguments SHNDX, SHDR.
+	(dwfl_linux_kernel_module_section_address): Update prototype.
+	* relocate.c (__libdwfl_relocate_value): Update caller.
+	* linux-kernel-modules.c (dwfl_linux_kernel_module_section_address):
+	Take the new arguments.
+
+2005-08-10  Roland McGrath  <roland@redhat.com>
+
+	* relocate.c (__libdwfl_relocate): Take argument DEBUGFILE,
+	use it instead of MOD->debug.file.
+	* libdwflP.h: Update decl.
+	* dwfl_module_getdwarf.c (load_dw): Update caller.
+	Fixes bug #165598.
+
+2005-08-09  Roland McGrath  <roland@redhat.com>
+
+	* libdwflP.h: Include ../libdw/libdwP.h for its INTDECLs.
+	* cu.c: Use INTUSE on dwarf_* calls.
+	* dwfl_error.c: Likewise.
+	* dwfl_module.c: Likewise.
+	* dwfl_module_getdwarf.c: Likewise.
+	* dwfl_module_getsrc_file.c: Likewise.
+	* lines.c: Likewise.
+
+2005-08-07  Roland McGrath  <roland@redhat.com>
+
+	* linux-kernel-modules.c (dwfl_linux_kernel_find_elf): When module
+	names contain '_' or '-', look for files named either "foo-bar.ko"
+	or "foo_bar.ko".
+
+2005-07-29  Roland McGrath  <roland@redhat.com>
+
+	* loc2c.c: File removed.
+	* loc2c.h: File removed.
+	* loc2c-runtime.h: File removed.
+	* test2.c: File removed.
+	* Makefile.am (EXTRA_DIST): Variable removed.
+	(noinst_HEADERS): Remove loc2c.h from here.
+
+2005-07-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* libdwfl.h: Add a few missing extern for function prototypes.
+
+	* libdwfl_crc32.c: New file.
+	* libdwfl_crc32_file.c: New file.
+	* libdwflP.h: Declare the new functions.
+	* Makefile.am (libdwfl_a_SOURCES): Add libdwfl_crc32.c and
+	libdwfl_crc32_file.c.
+	* libdwfl/find-debuginfo.c (check_crc): Use __libdwfl_crc32_file
+	instead of crc32_file.
+
+2005-07-28  Roland McGrath  <roland@redhat.com>
+
+	* ptest.c: Moved to ../tests/dwflmodtest.c.
+
+	* Makefile.am (noinst_PROGRAMS): Variable removed.
+	(libdwfl_so_SOURCES, libdwfl_LIBS, libdwfl_so_LDADD): Likewise.
+	(EXTRA_DIST, ptest_LDADD, test2_LDADD): Likewise.
+	(libdwfl): Don't use libdwfl.so any more.
+	(libdwfl.so, install, uninstall): Targets removed.
+	(test2_SOURCES): Define EXTRA_DIST instead of this.
+	* libdwfl.map: File removed.
+
+	* libdwfl.h: Use "" for libdw.h #include.
+
+2005-07-27  Roland McGrath  <roland@redhat.com>
+
+	* libdwfl.map: Add dwfl_getmodules.
+
+2005-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Fix rules to allow building with mudflap.
+
+2005-07-21  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (noinst_HEADERS): Add loc2c.c.
+
+	* test2.c (main): Check sscanf result to quiet warning.
+
+2005-07-20  Roland McGrath  <roland@redhat.com>
+
+	* libdwfl-branch merged, creating this direcotry.
diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am
new file mode 100644
index 0000000..6b26cd5
--- /dev/null
+++ b/libdwfl/Makefile.am
@@ -0,0 +1,96 @@
+## Makefile.am for libdwfl library subdirectory in elfutils.
+##
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2005-2010, 2013 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+AM_CPPFLAGS += -I$(srcdir) -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+	   -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf -I$(builddir)/../debuginfod
+VERSION = 1
+
+noinst_LIBRARIES = libdwfl.a
+noinst_LIBRARIES += libdwfl_pic.a
+
+pkginclude_HEADERS = libdwfl.h
+
+
+libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \
+		    dwfl_module.c dwfl_report_elf.c relocate.c \
+		    dwfl_module_build_id.c dwfl_module_report_build_id.c \
+		    derelocate.c offline.c segment.c \
+		    dwfl_module_info.c dwfl_getmodules.c dwfl_getdwarf.c \
+		    dwfl_module_getdwarf.c dwfl_module_getelf.c \
+		    dwfl_validate_address.c \
+		    argp-std.c find-debuginfo.c \
+		    dwfl_build_id_find_elf.c \
+		    dwfl_build_id_find_debuginfo.c \
+		    linux-kernel-modules.c linux-proc-maps.c \
+		    dwfl_addrmodule.c dwfl_addrdwarf.c \
+		    cu.c dwfl_module_nextcu.c dwfl_nextcu.c dwfl_cumodule.c \
+		    dwfl_module_addrdie.c dwfl_addrdie.c \
+		    lines.c dwfl_lineinfo.c dwfl_line_comp_dir.c \
+		    dwfl_linemodule.c dwfl_linecu.c dwfl_dwarf_line.c \
+		    dwfl_getsrclines.c dwfl_onesrcline.c \
+		    dwfl_module_getsrc.c dwfl_getsrc.c \
+		    dwfl_module_getsrc_file.c \
+		    libdwfl_crc32.c libdwfl_crc32_file.c \
+		    elf-from-memory.c \
+		    dwfl_module_dwarf_cfi.c dwfl_module_eh_cfi.c \
+		    dwfl_module_getsym.c \
+		    dwfl_module_addrname.c dwfl_module_addrsym.c \
+		    dwfl_module_return_value_location.c \
+		    dwfl_module_register_names.c \
+		    dwfl_segment_report_module.c \
+		    link_map.c core-file.c open.c image-header.c \
+		    dwfl_frame.c frame_unwind.c dwfl_frame_pc.c \
+		    linux-pid-attach.c linux-core-attach.c dwfl_frame_regs.c \
+		    gzip.c debuginfod-client.c
+
+if BZLIB
+libdwfl_a_SOURCES += bzip2.c
+endif
+if LZMA
+libdwfl_a_SOURCES += lzma.c
+endif
+if ZSTD
+libdwfl_a_SOURCES += zstd.c
+endif
+
+libdwfl = $(libdw)
+libdw = ../libdw/libdw.so
+libelf = ../libelf/libelf.so
+libebl = ../libebl/libebl.a
+libeu = ../lib/libeu.a
+
+libdwfl_pic_a_SOURCES =
+am_libdwfl_pic_a_OBJECTS = $(libdwfl_a_SOURCES:.c=.os)
+
+noinst_HEADERS = libdwflP.h
+
+CLEANFILES += $(am_libdwfl_pic_a_OBJECTS)
diff --git a/libdwfl/argp-std.c b/libdwfl/argp-std.c
new file mode 100644
index 0000000..1605fbf
--- /dev/null
+++ b/libdwfl/argp-std.c
@@ -0,0 +1,379 @@
+/* Standard argp argument parsers for tools using libdwfl.
+   Copyright (C) 2005-2010, 2012, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <argp.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <fcntl.h>
+
+
+#define OPT_DEBUGINFO	0x100
+#define OPT_COREFILE	0x101
+
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
+  { "executable", 'e', "FILE", 0, N_("Find addresses in FILE"), 0 },
+  { "core", OPT_COREFILE, "COREFILE", 0,
+    N_("Find addresses from signatures found in COREFILE"), 0 },
+  { "pid", 'p', "PID", 0,
+    N_("Find addresses in files mapped into process PID"), 0 },
+  { "linux-process-map", 'M', "FILE", 0,
+    N_("Find addresses in files mapped as read from FILE"
+       " in Linux /proc/PID/maps format"), 0 },
+  { "kernel", 'k', NULL, 0, N_("Find addresses in the running kernel"), 0 },
+  { "offline-kernel", 'K', "RELEASE", OPTION_ARG_OPTIONAL,
+    N_("Kernel with all modules"), 0 },
+  { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
+    N_("Search path for separate debuginfo files"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+static char *debuginfo_path;
+
+static const Dwfl_Callbacks offline_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .debuginfo_path = &debuginfo_path,
+
+    .section_address = INTUSE(dwfl_offline_section_address),
+
+    /* We use this table for core files too.  */
+    .find_elf = INTUSE(dwfl_build_id_find_elf),
+  };
+
+static const Dwfl_Callbacks proc_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .debuginfo_path = &debuginfo_path,
+
+    .find_elf = INTUSE(dwfl_linux_proc_find_elf),
+  };
+
+static const Dwfl_Callbacks kernel_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .debuginfo_path = &debuginfo_path,
+
+    .find_elf = INTUSE(dwfl_linux_kernel_find_elf),
+    .section_address = INTUSE(dwfl_linux_kernel_module_section_address),
+  };
+
+/* Structure held at state->HOOK.  */
+struct parse_opt
+{
+  Dwfl *dwfl;
+  /* The -e|--executable parameter.  */
+  const char *e;
+  /* The --core parameter.  */
+  const char *core;
+};
+
+static inline void
+failure (Dwfl *dwfl, int errnum, const char *msg, struct argp_state *state)
+{
+  if (dwfl != NULL)
+    dwfl_end (dwfl);
+  if (errnum == -1)
+    argp_failure (state, EXIT_FAILURE, 0, "%s: %s",
+                  msg, INTUSE(dwfl_errmsg) (-1));
+  else
+    argp_failure (state, EXIT_FAILURE, errnum, "%s", msg);
+}
+
+static inline error_t
+fail (Dwfl *dwfl, int errnum, const char *msg, struct argp_state *state)
+{
+  failure (dwfl, errnum, msg, state);
+  return errnum == -1 ? EIO : errnum;
+}
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case ARGP_KEY_INIT:
+      {
+	assert (state->hook == NULL);
+	struct parse_opt *opt = calloc (1, sizeof (*opt));
+	if (opt == NULL)
+	  failure (NULL, DWFL_E_ERRNO, "calloc", state);
+	state->hook = opt;
+      }
+      break;
+
+    case OPT_DEBUGINFO:
+      debuginfo_path = arg;
+      break;
+
+    case 'e':
+      {
+	struct parse_opt *opt = state->hook;
+	Dwfl *dwfl = opt->dwfl;
+	if (dwfl == NULL)
+	  {
+	    dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
+	    if (dwfl == NULL)
+	      return fail (dwfl, -1, arg, state);
+	    opt->dwfl = dwfl;
+
+	    /* Start at zero so if there is just one -e foo.so,
+	       the DSO is shown without address bias.  */
+	    dwfl->offline_next_address = 0;
+	  }
+	if (dwfl->callbacks != &offline_callbacks)
+	  {
+	  toomany:
+	    argp_error (state, "%s",
+			_("only one of -e, -p, -k, -K, or --core allowed"));
+	    return EINVAL;
+	  }
+	opt->e = arg;
+      }
+      break;
+
+    case 'p':
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
+	    int result = INTUSE(dwfl_linux_proc_report) (dwfl, atoi (arg));
+	    if (result != 0)
+	      return fail (dwfl, result, arg, state);
+
+	    /* Non-fatal to not be able to attach to process, ignore error.  */
+	    INTUSE(dwfl_linux_proc_attach) (dwfl, atoi (arg), false);
+
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
+      break;
+
+    case 'M':
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    FILE *f = fopen (arg, "r");
+	    if (f == NULL)
+	      {
+		int code = errno;
+		argp_failure (state, EXIT_FAILURE, code,
+			      "cannot open '%s'", arg);
+		return code;
+	      }
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&proc_callbacks);
+	    int result = INTUSE(dwfl_linux_proc_maps_report) (dwfl, f);
+	    fclose (f);
+	    if (result != 0)
+	      return fail (dwfl, result, arg, state);
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
+      break;
+
+    case OPT_COREFILE:
+      {
+	struct parse_opt *opt = state->hook;
+	Dwfl *dwfl = opt->dwfl;
+	if (dwfl == NULL)
+	  opt->dwfl = dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
+	/* Permit -e and --core together.  */
+	else if (dwfl->callbacks != &offline_callbacks)
+	  goto toomany;
+	opt->core = arg;
+      }
+      break;
+
+    case 'k':
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&kernel_callbacks);
+	    int result = INTUSE(dwfl_linux_kernel_report_kernel) (dwfl);
+	    if (result != 0)
+	      return fail (dwfl, result, _("cannot load kernel symbols"), state);
+	    result = INTUSE(dwfl_linux_kernel_report_modules) (dwfl);
+	    if (result != 0)
+	      /* Non-fatal to have no modules since we do have the kernel.  */
+	      argp_failure (state, 0, result, _("cannot find kernel modules"));
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
+      break;
+
+    case 'K':
+      {
+	struct parse_opt *opt = state->hook;
+	if (opt->dwfl == NULL)
+	  {
+	    Dwfl *dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
+	    int result = INTUSE(dwfl_linux_kernel_report_offline) (dwfl, arg,
+								   NULL);
+	    if (result != 0)
+	      return fail (dwfl, result, _("cannot find kernel or modules"), state);
+	    opt->dwfl = dwfl;
+	  }
+	else
+	  goto toomany;
+      }
+      break;
+
+    case ARGP_KEY_SUCCESS:
+      {
+	struct parse_opt *opt = state->hook;
+	Dwfl *dwfl = opt->dwfl;
+
+	if (dwfl == NULL)
+	  {
+	    /* Default if no -e, -p, or -k, is "-e a.out".  */
+	    arg = "a.out";
+	    dwfl = INTUSE(dwfl_begin) (&offline_callbacks);
+	    if (INTUSE(dwfl_report_offline) (dwfl, "", arg, -1) == NULL)
+	      return fail (dwfl, -1, arg, state);
+	    opt->dwfl = dwfl;
+	  }
+
+	if (opt->core)
+	  {
+	    int fd = open (opt->core, O_RDONLY);
+	    if (fd < 0)
+	      {
+		int code = errno;
+		argp_failure (state, EXIT_FAILURE, code,
+			      "cannot open '%s'", opt->core);
+		return code;
+	      }
+
+	    Elf *core;
+	    Dwfl_Error error = __libdw_open_file (&fd, &core, true, false);
+	    if (error != DWFL_E_NOERROR)
+	      {
+		argp_failure (state, EXIT_FAILURE, 0,
+			      _("cannot read ELF core file: %s"),
+			      INTUSE(dwfl_errmsg) (error));
+		return error == DWFL_E_ERRNO ? errno : EIO;
+	      }
+
+	    int result = INTUSE(dwfl_core_file_report) (dwfl, core, opt->e);
+	    if (result < 0)
+	      {
+		elf_end (core);
+		close (fd);
+		return fail (dwfl, result, opt->core, state);
+	      }
+
+	    /* Non-fatal to not be able to attach to core, ignore error.  */
+	    INTUSE(dwfl_core_file_attach) (dwfl, core);
+
+	    /* Store core Elf and fd in Dwfl to expose with dwfl_end.  */
+	    if (dwfl->user_core == NULL)
+	      {
+		dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
+		if (dwfl->user_core == NULL)
+		  {
+		    argp_failure (state, EXIT_FAILURE, 0,
+				  _("Not enough memory"));
+		    return ENOMEM;
+		  }
+	      }
+	    dwfl->user_core->core = core;
+	    dwfl->user_core->fd = fd;
+
+	    if (result == 0)
+	      {
+		argp_failure (state, EXIT_FAILURE, 0,
+			      _("No modules recognized in core file"));
+		return ENOENT;
+	      }
+	  }
+	else if (opt->e)
+	  {
+	    if (INTUSE(dwfl_report_offline) (dwfl, "", opt->e, -1) == NULL)
+	      return fail (dwfl, -1, opt->e, state);
+	  }
+
+	/* One of the three flavors has done dwfl_begin and some reporting
+	   if we got here.  Tie up the Dwfl and return it to the caller of
+	   argp_parse.  */
+
+	int result = INTUSE(dwfl_report_end) (dwfl, NULL, NULL);
+	if (result != 0)
+	  return fail (dwfl, -1, arg, state);
+
+	/* Update the input all along, so a parent parser can see it.
+	   As we free OPT the update below will be no longer active.  */
+	*(Dwfl **) state->input = dwfl;
+	free (opt);
+	state->hook = NULL;
+      }
+      break;
+
+    case ARGP_KEY_ERROR:
+      {
+	struct parse_opt *opt = state->hook;
+	dwfl_end (opt->dwfl);
+	free (opt);
+	state->hook = NULL;
+      }
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+
+  /* Update the input all along, so a parent parser can see it.  */
+  struct parse_opt *opt = state->hook;
+  if (opt)
+    *(Dwfl **) state->input = opt->dwfl;
+
+  return 0;
+}
+
+static const struct argp libdwfl_argp =
+  { .options = options, .parser = parse_opt };
+
+const struct argp *
+dwfl_standard_argp (void)
+{
+  return &libdwfl_argp;
+}
diff --git a/libdwfl/bzip2.c b/libdwfl/bzip2.c
new file mode 100644
index 0000000..8ad4ee5
--- /dev/null
+++ b/libdwfl/bzip2.c
@@ -0,0 +1,4 @@
+/* bzlib is almost just like zlib.  */
+
+#define BZLIB
+#include "gzip.c"
diff --git a/libdwfl/core-file.c b/libdwfl/core-file.c
new file mode 100644
index 0000000..89527d2
--- /dev/null
+++ b/libdwfl/core-file.c
@@ -0,0 +1,645 @@
+/* Core file handling.
+   Copyright (C) 2008-2010, 2013, 2015 Red Hat, Inc.
+   Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include "libelfP.h"	/* For NOTE_ALIGN.  */
+#include "libdwflP.h"
+#include <gelf.h>
+
+/* On failure return, we update *NEXT to point back at OFFSET.  */
+static inline Elf *
+do_fail (int error, off_t *next, off_t offset)
+{
+    if (next != NULL)
+      *next = offset;
+    //__libelf_seterrno (error);
+    __libdwfl_seterrno (DWFL_E (LIBELF, error));
+    return NULL;
+}
+
+#define fail(error) do_fail (error, next, offset)
+
+/* This is a prototype of what a new libelf interface might be.
+   This implementation is pessimal for non-mmap cases and should
+   be replaced by more diddling inside libelf internals.  */
+static Elf *
+elf_begin_rand (Elf *parent, off_t offset, off_t size, off_t *next)
+{
+  if (parent == NULL)
+    return NULL;
+
+  off_t min = (parent->kind == ELF_K_ELF ?
+		(parent->class == ELFCLASS32
+		 ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr))
+		: parent->kind == ELF_K_AR ? SARMAG
+		: 0);
+
+  if (unlikely (offset < min)
+      || unlikely (offset >= (off_t) parent->maximum_size))
+    return fail (ELF_E_RANGE);
+
+  /* For an archive, fetch just the size field
+     from the archive header to override SIZE.  */
+  if (parent->kind == ELF_K_AR)
+    {
+      /* File size, in ASCII decimal, right-padded with ASCII spaces.
+         Max 10 characters. Not zero terminated. So make this ar_size
+         array one larger and explicitly zero terminate it.  As needed
+         for strtoll.  */
+      #define AR_SIZE_CHARS 10
+      char ar_size[AR_SIZE_CHARS + 1];
+      ar_size[AR_SIZE_CHARS] = '\0';
+
+      if (unlikely (parent->maximum_size - offset < sizeof (struct ar_hdr)))
+	return fail (ELF_E_RANGE);
+
+      if (parent->map_address != NULL)
+	memcpy (ar_size, parent->map_address + parent->start_offset + offset,
+		AR_SIZE_CHARS);
+      else if (unlikely (pread_retry (parent->fildes,
+				      ar_size, AR_SIZE_CHARS,
+				      parent->start_offset + offset
+				      + offsetof (struct ar_hdr, ar_size))
+			 != AR_SIZE_CHARS))
+	return fail (ELF_E_READ_ERROR);
+
+      offset += sizeof (struct ar_hdr);
+
+      char *endp;
+      size = strtoll (ar_size, &endp, 10);
+      if (unlikely (endp == ar_size)
+	  || unlikely ((off_t) parent->maximum_size - offset < size))
+	return fail (ELF_E_INVALID_ARCHIVE);
+    }
+
+  if (unlikely ((off_t) parent->maximum_size - offset < size))
+    return fail (ELF_E_RANGE);
+
+  /* Even if we fail at this point, update *NEXT to point past the file.  */
+  if (next != NULL)
+    *next = offset + size;
+
+  if (unlikely (offset == 0)
+      && unlikely (size == (off_t) parent->maximum_size))
+    return elf_clone (parent, parent->cmd);
+
+  /* Note the image is guaranteed live only as long as PARENT
+     lives.  Using elf_memory is quite suboptimal if the whole
+     file is not mmap'd.  We really should have something like
+     a generalization of the archive support.  */
+  Elf_Data *data = elf_getdata_rawchunk (parent, offset, size, ELF_T_BYTE);
+  if (data == NULL)
+    return NULL;
+  assert ((off_t) data->d_size == size);
+  return elf_memory (data->d_buf, size);
+}
+
+
+int
+dwfl_report_core_segments (Dwfl *dwfl, Elf *elf, size_t phnum, GElf_Phdr *notes)
+{
+  if (unlikely (dwfl == NULL))
+    return -1;
+
+  int result = 0;
+
+  if (notes != NULL)
+    notes->p_type = PT_NULL;
+
+  for (size_t ndx = 0; result >= 0 && ndx < phnum; ++ndx)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, ndx, &phdr_mem);
+      if (unlikely (phdr == NULL))
+	{
+	  __libdwfl_seterrno (DWFL_E_LIBELF);
+	  return -1;
+	}
+      switch (phdr->p_type)
+	{
+	case PT_LOAD:
+	  result = dwfl_report_segment (dwfl, ndx, phdr, 0, NULL);
+	  break;
+
+	case PT_NOTE:
+	  if (notes != NULL)
+	    {
+	      *notes = *phdr;
+	      notes = NULL;
+	    }
+	  break;
+	}
+    }
+
+  return result;
+}
+
+/* Never read more than this much without mmap.  */
+#define MAX_EAGER_COST	8192
+
+/* Dwfl_Module_Callback passed to and called by dwfl_segment_report_module
+   to read in a segment as ELF image directly if possible or indicate an
+   attempt must be made to read in the while segment right now.  */
+static bool
+core_file_read_eagerly (Dwfl_Module *mod,
+			void **userdata __attribute__ ((unused)),
+			const char *name __attribute__ ((unused)),
+			Dwarf_Addr start __attribute__ ((unused)),
+			void **buffer, size_t *buffer_available,
+			GElf_Off cost, GElf_Off worthwhile,
+			GElf_Off whole,
+			GElf_Off contiguous __attribute__ ((unused)),
+			void *arg, Elf **elfp)
+{
+  Elf *core = arg;
+
+  /* The available buffer is often the whole segment when the core file
+     was mmap'd if used together with the dwfl_elf_phdr_memory_callback.
+     Which means that if it is complete we can just construct the whole
+     ELF image right now without having to read in anything more.  */
+  if (whole <= *buffer_available)
+    {
+      /* All there ever was, we already have on hand.  */
+
+      if (core->map_address == NULL)
+	{
+	  /* We already malloc'd the buffer.  */
+	  *elfp = elf_memory (*buffer, whole);
+	  if (unlikely (*elfp == NULL))
+	    return false;
+
+	  (*elfp)->flags |= ELF_F_MALLOCED;
+	  *buffer = NULL;
+	  *buffer_available = 0;
+	  return true;
+	}
+
+      /* We can use the image inside the core file directly.  */
+      *elfp = elf_begin_rand (core, *buffer - core->map_address, whole, NULL);
+      *buffer = NULL;
+      *buffer_available = 0;
+      return *elfp != NULL;
+    }
+
+  /* We don't have the whole file.  Which either means the core file
+     wasn't mmap'd, but needs to still be read in, or that the segment
+     is truncated.  Figure out if this is better than nothing.  */
+
+  if (worthwhile == 0)
+    /* Caller doesn't think so.  */
+    return false;
+
+  /*
+    XXX would like to fall back to partial file via memory
+    when build id find_elf fails
+    also, link_map name may give file name from disk better than partial here
+    requires find_elf hook re-doing the magic to fall back if no file found
+  */
+
+  if (whole > MAX_EAGER_COST && mod->build_id_len > 0)
+    /* We can't cheaply read the whole file here, so we'd
+       be using a partial file.  But there is a build ID that could
+       help us find the whole file, which might be more useful than
+       what we have.  We'll just rely on that.  */
+    return false;
+
+  /* The file is either small (most likely the vdso) or big and incomplete,
+     but we don't have a build-id.  */
+
+  if (core->map_address != NULL)
+    /* It's cheap to get, so get it.  */
+    return true;
+
+  /* Only use it if there isn't too much to be read.  */
+  return cost <= MAX_EAGER_COST;
+}
+
+static inline void
+update_end (GElf_Phdr *pphdr, const GElf_Off align,
+            GElf_Off *pend, GElf_Addr *pend_vaddr)
+{
+  *pend = (pphdr->p_offset + pphdr->p_filesz + align - 1) & -align;
+  *pend_vaddr = (pphdr->p_vaddr + pphdr->p_memsz + align - 1) & -align;
+}
+
+/* Use following contiguous segments to get towards SIZE.  */
+static inline bool
+do_more (size_t size, GElf_Phdr *pphdr, const GElf_Off align,
+         Elf *elf, GElf_Off start, int *pndx,
+         GElf_Off *pend, GElf_Addr *pend_vaddr)
+{
+  while (*pend <= start || *pend - start < size)
+    {
+      if (pphdr->p_filesz < pphdr->p_memsz)
+	/* This segment is truncated, so no following one helps us.  */
+	return false;
+
+      if (unlikely (gelf_getphdr (elf, (*pndx)++, pphdr) == NULL))
+	return false;
+
+      if (pphdr->p_type == PT_LOAD)
+	{
+	  if (pphdr->p_offset > *pend
+	      || pphdr->p_vaddr > *pend_vaddr)
+	    /* It's discontiguous!  */
+	    return false;
+
+	  update_end (pphdr, align, pend, pend_vaddr);
+	}
+    }
+  return true;
+}
+
+#define more(size) do_more (size, &phdr, align, elf, start, &ndx, &end, &end_vaddr)
+
+bool
+dwfl_elf_phdr_memory_callback (Dwfl *dwfl, int ndx,
+			       void **buffer, size_t *buffer_available,
+			       GElf_Addr vaddr,
+			       size_t minread,
+			       void *arg)
+{
+  Elf *elf = arg;
+
+  if (ndx == -1)
+    {
+      /* Called for cleanup.  */
+      if (elf->map_address == NULL)
+	free (*buffer);
+      *buffer = NULL;
+      *buffer_available = 0;
+      return false;
+    }
+
+  const GElf_Off align = dwfl->segment_align ?: 1;
+  GElf_Phdr phdr;
+
+  do
+    if (unlikely (gelf_getphdr (elf, ndx++, &phdr) == NULL))
+      return false;
+  while (phdr.p_type != PT_LOAD
+	 || ((phdr.p_vaddr + phdr.p_memsz + align - 1) & -align) <= vaddr);
+
+  GElf_Off start = vaddr - phdr.p_vaddr + phdr.p_offset;
+  GElf_Off end;
+  GElf_Addr end_vaddr;
+
+  update_end (&phdr, align, &end, &end_vaddr);
+
+  /* We need at least this much.  */
+  if (! more (minread))
+    return false;
+
+  /* See how much more we can get of what the caller wants.  */
+  (void) more (*buffer_available);
+
+  /* If it's already on hand anyway, use as much as there is.  */
+  if (elf->map_address != NULL && start < elf->maximum_size)
+    (void) more (elf->maximum_size - start);
+
+  /* Make sure we don't look past the end of the actual file,
+     even if the headers tell us to.  */
+  if (unlikely (end > elf->maximum_size))
+    end = elf->maximum_size;
+
+  /* If the file is too small, there is nothing at all to get.  */
+  if (unlikely (start >= end))
+    return false;
+
+  if (end - start < minread)
+    return false;
+
+  if (elf->map_address != NULL)
+    {
+      void *contents = elf->map_address + elf->start_offset + start;
+      size_t size = end - start;
+
+      if (minread == 0)		/* String mode.  */
+	{
+	  const void *eos = memchr (contents, '\0', size);
+	  if (unlikely (eos == NULL) || unlikely (eos == contents))
+	    return false;
+	  size = eos + 1 - contents;
+	}
+
+      if (*buffer == NULL)
+	{
+	  *buffer = contents;
+	  *buffer_available = size;
+	}
+      else
+	{
+	  *buffer_available = MIN (size, *buffer_available);
+	  memcpy (*buffer, contents, *buffer_available);
+	}
+    }
+  else
+    {
+      void *into = *buffer;
+      if (*buffer == NULL)
+	{
+	  *buffer_available = MIN (minread ?: 512,
+				   MAX (4096, MIN (end - start,
+						   *buffer_available)));
+	  into = malloc (*buffer_available);
+	  if (unlikely (into == NULL))
+	    {
+	      __libdwfl_seterrno (DWFL_E_NOMEM);
+	      return false;
+	    }
+	}
+
+      ssize_t nread = pread_retry (elf->fildes, into, *buffer_available, start);
+      if (nread < (ssize_t) minread)
+	{
+	  if (into != *buffer)
+	    free (into);
+	  if (nread < 0)
+	    __libdwfl_seterrno (DWFL_E_ERRNO);
+	  return false;
+	}
+
+      if (minread == 0)		/* String mode.  */
+	{
+	  const void *eos = memchr (into, '\0', nread);
+	  if (unlikely (eos == NULL) || unlikely (eos == into))
+	    {
+	      if (*buffer == NULL)
+		free (into);
+	      return false;
+	    }
+	  nread = eos + 1 - into;
+	}
+
+      if (*buffer == NULL)
+	*buffer = into;
+      *buffer_available = nread;
+    }
+
+  return true;
+}
+
+/* Free the contents of R_DEBUG_INFO without the R_DEBUG_INFO memory itself.  */
+
+static void
+clear_r_debug_info (struct r_debug_info *r_debug_info)
+{
+  while (r_debug_info->module != NULL)
+    {
+      struct r_debug_info_module *module = r_debug_info->module;
+      r_debug_info->module = module->next;
+      elf_end (module->elf);
+      if (module->fd != -1)
+	close (module->fd);
+      free (module);
+    }
+}
+
+bool
+internal_function
+__libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
+{
+  size_t phnum;
+  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+    return false;
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (unlikely (phdr == NULL))
+	return false;
+      if (phdr->p_type == PT_DYNAMIC)
+	{
+	  *vaddrp = phdr->p_vaddr;
+	  return true;
+	}
+    }
+  return false;
+}
+
+NEW_VERSION (dwfl_core_file_report, ELFUTILS_0.158)
+int
+dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable)
+{
+  size_t phnum;
+  if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+    {
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      return -1;
+    }
+
+  bool cleanup_user_core = false;
+  if (dwfl->user_core != NULL)
+    free (dwfl->user_core->executable_for_core);
+  if (executable == NULL)
+    {
+      if (dwfl->user_core != NULL)
+	dwfl->user_core->executable_for_core = NULL;
+    }
+  else
+    {
+      if (dwfl->user_core == NULL)
+	{
+	  cleanup_user_core = true;
+	  dwfl->user_core = calloc (1, sizeof (struct Dwfl_User_Core));
+	  if (dwfl->user_core == NULL)
+	    {
+	      __libdwfl_seterrno (DWFL_E_NOMEM);
+	      return -1;
+	    }
+	  dwfl->user_core->fd = -1;
+	}
+      dwfl->user_core->executable_for_core = strdup (executable);
+      if (dwfl->user_core->executable_for_core == NULL)
+	{
+	  if (cleanup_user_core)
+	    {
+	      free (dwfl->user_core);
+	      dwfl->user_core = NULL;
+	    }
+	  __libdwfl_seterrno (DWFL_E_NOMEM);
+	  return -1;
+	}
+    }
+
+  /* First report each PT_LOAD segment.  */
+  GElf_Phdr notes_phdr;
+  int ndx = dwfl_report_core_segments (dwfl, elf, phnum, &notes_phdr);
+  if (unlikely (ndx <= 0))
+    {
+      if (cleanup_user_core)
+	{
+	  free (dwfl->user_core->executable_for_core);
+	  free (dwfl->user_core);
+	  dwfl->user_core = NULL;
+	}
+      return ndx;
+    }
+
+  /* Next, we should follow the chain from DT_DEBUG.  */
+
+  const void *auxv = NULL;
+  const void *note_file = NULL;
+  size_t auxv_size = 0;
+  size_t note_file_size = 0;
+  if (likely (notes_phdr.p_type == PT_NOTE))
+    {
+      /* PT_NOTE -> NT_AUXV -> AT_PHDR -> PT_DYNAMIC -> DT_DEBUG */
+
+      Elf_Data *notes = elf_getdata_rawchunk (elf,
+					      notes_phdr.p_offset,
+					      notes_phdr.p_filesz,
+					      (notes_phdr.p_align == 8
+					       ? ELF_T_NHDR8
+					       : ELF_T_NHDR));
+      if (likely (notes != NULL))
+	{
+	  size_t pos = 0;
+	  GElf_Nhdr nhdr;
+	  size_t name_pos;
+	  size_t desc_pos;
+	  while ((pos = gelf_getnote (notes, pos, &nhdr,
+				      &name_pos, &desc_pos)) > 0)
+	    if (nhdr.n_namesz == sizeof "CORE"
+		&& !memcmp (notes->d_buf + name_pos, "CORE", sizeof "CORE"))
+	      {
+		if (nhdr.n_type == NT_AUXV)
+		  {
+		    auxv = notes->d_buf + desc_pos;
+		    auxv_size = nhdr.n_descsz;
+		  }
+		if (nhdr.n_type == NT_FILE)
+		  {
+		    note_file = notes->d_buf + desc_pos;
+		    note_file_size = nhdr.n_descsz;
+		  }
+	      }
+	}
+    }
+
+  /* Now we have NT_AUXV contents.  From here on this processing could be
+     used for a live process with auxv read from /proc.  */
+
+  struct r_debug_info r_debug_info;
+  memset (&r_debug_info, 0, sizeof r_debug_info);
+  int retval = dwfl_link_map_report (dwfl, auxv, auxv_size,
+				     dwfl_elf_phdr_memory_callback, elf,
+				     &r_debug_info);
+  int listed = retval > 0 ? retval : 0;
+
+  /* Now sniff segment contents for modules hinted by information gathered
+     from DT_DEBUG.  */
+
+  ndx = 0;
+  do
+    {
+      int seg = dwfl_segment_report_module (dwfl, ndx, NULL,
+					    &dwfl_elf_phdr_memory_callback, elf,
+					    core_file_read_eagerly, elf,
+					    elf->maximum_size,
+					    note_file, note_file_size,
+					    &r_debug_info);
+      if (unlikely (seg < 0))
+	{
+	  clear_r_debug_info (&r_debug_info);
+	  return seg;
+	}
+      if (seg > ndx)
+	{
+	  ndx = seg;
+	  ++listed;
+	}
+      else
+	++ndx;
+    }
+  while (ndx < (int) phnum);
+
+  /* Now report the modules from dwfl_link_map_report which were not filtered
+     out by dwfl_segment_report_module.  */
+
+  Dwfl_Module **lastmodp = &dwfl->modulelist;
+  while (*lastmodp != NULL)
+    lastmodp = &(*lastmodp)->next;
+  for (struct r_debug_info_module *module = r_debug_info.module;
+       module != NULL; module = module->next)
+    {
+      if (module->elf == NULL)
+	continue;
+      GElf_Addr file_dynamic_vaddr;
+      if (! __libdwfl_dynamic_vaddr_get (module->elf, &file_dynamic_vaddr))
+	continue;
+      Dwfl_Module *mod;
+      mod = __libdwfl_report_elf (dwfl, xbasename (module->name), module->name,
+				  module->fd, module->elf,
+				  module->l_ld - file_dynamic_vaddr,
+				  true, true);
+      if (mod == NULL)
+	continue;
+      ++listed;
+      module->elf = NULL;
+      module->fd = -1;
+      /* Move this module to the end of the list, so that we end
+	 up with a list in the same order as the link_map chain.  */
+      if (mod->next != NULL)
+	{
+	  if (*lastmodp != mod)
+	    {
+	      lastmodp = &dwfl->modulelist;
+	      while (*lastmodp != mod)
+		lastmodp = &(*lastmodp)->next;
+	    }
+	  *lastmodp = mod->next;
+	  mod->next = NULL;
+	  while (*lastmodp != NULL)
+	    lastmodp = &(*lastmodp)->next;
+	  *lastmodp = mod;
+	}
+      lastmodp = &mod->next;
+    }
+
+  clear_r_debug_info (&r_debug_info);
+
+  /* We return the number of modules we found if we found any.
+     If we found none, we return -1 instead of 0 if there was an
+     error rather than just nothing found.  */
+  return listed > 0 ? listed : retval;
+}
+NEW_INTDEF (dwfl_core_file_report)
+
+#ifdef SYMBOL_VERSIONING
+int _compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf);
+COMPAT_VERSION_NEWPROTO (dwfl_core_file_report, ELFUTILS_0.146,
+			 without_executable)
+
+int
+_compat_without_executable_dwfl_core_file_report (Dwfl *dwfl, Elf *elf)
+{
+  return dwfl_core_file_report (dwfl, elf, NULL);
+}
+#endif
diff --git a/libdwfl/cu.c b/libdwfl/cu.c
new file mode 100644
index 0000000..0668435
--- /dev/null
+++ b/libdwfl/cu.c
@@ -0,0 +1,317 @@
+/* Keeping track of DWARF compilation units in libdwfl.
+   Copyright (C) 2005-2010, 2015, 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "libdwP.h"
+#include "memory-access.h"
+#include <search.h>
+
+
+static inline Dwarf_Arange *
+dwar (Dwfl_Module *mod, unsigned int idx)
+{
+  return &mod->dw->dieranges->info[mod->aranges[idx].arange];
+}
+
+
+static Dwfl_Error
+addrarange (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_arange **arange)
+{
+  if (mod->aranges == NULL)
+    {
+      struct dwfl_arange *aranges = NULL;
+      Dwarf_Aranges *dwaranges = NULL;
+      size_t naranges;
+      if (__libdw_getdieranges (mod->dw, &dwaranges, &naranges) != 0)
+	return DWFL_E_LIBDW;
+
+      /* If the module has no aranges (when no code is included) we
+	 allocate nothing.  */
+      if (naranges != 0)
+	{
+	  aranges = malloc (naranges * sizeof *aranges);
+	  if (unlikely (aranges == NULL))
+	    return DWFL_E_NOMEM;
+
+	  /* libdw has sorted its list by address, which is how we want it.
+	     But the sorted list is full of not-quite-contiguous runs pointing
+	     to the same CU.  We don't care about the little gaps inside the
+	     module, we'll consider them part of the surrounding CU anyway.
+	     Collect our own array with just one record for each run of ranges
+	     pointing to one CU.  */
+
+	  naranges = 0;
+	  Dwarf_Off lastcu = 0;
+	  for (size_t i = 0; i < dwaranges->naranges; ++i)
+	    if (i == 0 || dwaranges->info[i].offset != lastcu)
+	      {
+		aranges[naranges].arange = i;
+		aranges[naranges].cu = NULL;
+		++naranges;
+		lastcu = dwaranges->info[i].offset;
+	      }
+	}
+
+      /* Store the final array, which is probably much smaller than before.  */
+      mod->naranges = naranges;
+      if (naranges > 0)
+        mod->aranges = (realloc (aranges, naranges * sizeof aranges[0])
+			?: aranges);
+      else if (aranges != NULL)
+	free (aranges);
+      mod->lazycu += naranges;
+    }
+
+  /* The address must be inside the module to begin with.  */
+  addr = dwfl_deadjust_dwarf_addr (mod, addr);
+
+  /* The ranges are sorted by address, so we can use binary search.  */
+  size_t l = 0, u = mod->naranges;
+  while (l < u)
+    {
+      size_t idx = (l + u) / 2;
+      Dwarf_Addr start = dwar (mod, idx)->addr;
+      if (addr < start)
+	{
+	  u = idx;
+	  continue;
+	}
+      else if (addr > start)
+	{
+	  if (idx + 1 < mod->naranges)
+	    {
+	      if (addr >= dwar (mod, idx + 1)->addr)
+		{
+		  l = idx + 1;
+		  continue;
+		}
+	    }
+	  else
+	    {
+	      /* It might be in the last range.  */
+	      const Dwarf_Arange *last
+		= &mod->dw->dieranges->info[mod->dw->dieranges->naranges - 1];
+	      if (addr > last->addr + last->length)
+		break;
+	    }
+	}
+
+      *arange = &mod->aranges[idx];
+      return DWFL_E_NOERROR;
+    }
+
+  return DWFL_E_ADDR_OUTOFRANGE;
+}
+
+
+static void
+nofree (void *arg)
+{
+  struct dwfl_cu *cu = arg;
+  if (cu == (void *) -1l)
+    return;
+
+  assert (cu->mod->lazycu == 0);
+}
+
+/* One reason fewer to keep the lazy lookup table for CUs.  */
+static inline void
+less_lazy (Dwfl_Module *mod)
+{
+  if (--mod->lazycu > 0)
+    return;
+
+  /* We know about all the CUs now, we don't need this table.  */
+  tdestroy (mod->lazy_cu_root, nofree);
+  mod->lazy_cu_root = NULL;
+}
+
+static inline Dwarf_Off
+cudie_offset (const struct dwfl_cu *cu)
+{
+  return __libdw_first_die_off_from_cu (cu->die.cu);
+}
+
+static int
+compare_cukey (const void *a, const void *b)
+{
+  Dwarf_Off a_off = cudie_offset (a);
+  Dwarf_Off b_off = cudie_offset (b);
+  return (a_off < b_off) ? -1 : ((a_off > b_off) ? 1 : 0);
+}
+
+/* Intern the CU if necessary.  */
+static Dwfl_Error
+intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
+{
+  if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size))
+    {
+      if (likely (mod->lazycu == 1))
+	{
+	  /* This is the EOF marker.  Now we have interned all the CUs.
+	     One increment in MOD->lazycu counts not having hit EOF yet.  */
+	  *result = (void *) -1;
+	  less_lazy (mod);
+	  return DWFL_E_NOERROR;
+	}
+      else
+	{
+	  /* Unexpected EOF, most likely a bogus aranges.  */
+	  return (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
+	}
+    }
+
+  /* Make sure the cuoff points to a real DIE.  */
+  Dwarf_Die cudie;
+  Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cudie);
+  if (die == NULL)
+    return DWFL_E_LIBDW;
+
+  struct dwfl_cu key;
+  key.die.cu = die->cu;
+  struct dwfl_cu **found = tsearch (&key, &mod->lazy_cu_root, &compare_cukey);
+  if (unlikely (found == NULL))
+    return DWFL_E_NOMEM;
+
+  if (*found == &key || *found == NULL)
+    {
+      /* This is a new entry, meaning we haven't looked at this CU.  */
+
+      *found = NULL;
+
+      struct dwfl_cu *cu = malloc (sizeof *cu);
+      if (unlikely (cu == NULL))
+	return DWFL_E_NOMEM;
+
+      cu->mod = mod;
+      cu->next = NULL;
+      cu->lines = NULL;
+      cu->die = cudie;
+
+      struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1)
+						   * sizeof (mod->cu[0])));
+      if (newvec == NULL)
+	{
+	  free (cu);
+	  return DWFL_E_NOMEM;
+	}
+      mod->cu = newvec;
+
+      mod->cu[mod->ncu++] = cu;
+      if (cu->die.cu->start == 0)
+	mod->first_cu = cu;
+
+      *found = cu;
+    }
+
+  *result = *found;
+  return DWFL_E_NOERROR;
+}
+
+
+/* Traverse all the CUs in the module.  */
+
+Dwfl_Error
+internal_function
+__libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
+		  struct dwfl_cu **cu)
+{
+  Dwarf_Off cuoff;
+  struct dwfl_cu **nextp;
+
+  if (lastcu == NULL)
+    {
+      /* Start the traversal.  */
+      cuoff = 0;
+      nextp = &mod->first_cu;
+    }
+  else
+    {
+      /* Continue following LASTCU.  */
+      cuoff = lastcu->die.cu->end;
+      nextp = &lastcu->next;
+    }
+
+  if (*nextp == NULL)
+    {
+      size_t cuhdrsz;
+      Dwarf_Off nextoff;
+      int end = INTUSE(dwarf_nextcu) (mod->dw, cuoff, &nextoff, &cuhdrsz,
+				      NULL, NULL, NULL);
+      if (end < 0)
+	return DWFL_E_LIBDW;
+      if (end > 0)
+	{
+	  *cu = NULL;
+	  return DWFL_E_NOERROR;
+	}
+
+      Dwfl_Error result = intern_cu (mod, cuoff + cuhdrsz, nextp);
+      if (result != DWFL_E_NOERROR)
+	return result;
+
+      if (*nextp != (void *) -1
+	  && (*nextp)->next == NULL && nextoff == (Dwarf_Off) -1l)
+	(*nextp)->next = (void *) -1l;
+    }
+
+  *cu = *nextp == (void *) -1l ? NULL : *nextp;
+  return DWFL_E_NOERROR;
+}
+
+
+/* Intern the CU arange points to, if necessary.  */
+
+static Dwfl_Error
+arangecu (Dwfl_Module *mod, struct dwfl_arange *arange, struct dwfl_cu **cu)
+{
+  if (arange->cu == NULL)
+    {
+      const Dwarf_Arange *dwarange = &mod->dw->dieranges->info[arange->arange];
+      Dwfl_Error result = intern_cu (mod, dwarange->offset, &arange->cu);
+      if (result != DWFL_E_NOERROR)
+	return result;
+      assert (arange->cu != NULL && arange->cu != (void *) -1l);
+      less_lazy (mod);		/* Each arange with null ->cu counts once.  */
+    }
+
+  *cu = arange->cu;
+  return DWFL_E_NOERROR;
+}
+
+Dwfl_Error
+internal_function
+__libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_cu **cu)
+{
+  struct dwfl_arange *arange;
+  return addrarange (mod, addr, &arange) ?: arangecu (mod, arange, cu);
+}
diff --git a/libdwfl/debuginfod-client.c b/libdwfl/debuginfod-client.c
new file mode 100644
index 0000000..882a5ef
--- /dev/null
+++ b/libdwfl/debuginfod-client.c
@@ -0,0 +1,152 @@
+/* Try to get an ELF or debug file through the debuginfod.
+   Copyright (C) 2019 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+#ifdef ENABLE_LIBDEBUGINFOD
+
+#include "debuginfod.h"
+
+#include <pthread.h>
+#include <dlfcn.h>
+
+static __typeof__ (debuginfod_begin) *fp_debuginfod_begin;
+static __typeof__ (debuginfod_find_executable) *fp_debuginfod_find_executable;
+static __typeof__ (debuginfod_find_debuginfo) *fp_debuginfod_find_debuginfo;
+static __typeof__ (debuginfod_end) *fp_debuginfod_end;
+
+static void __libdwfl_debuginfod_init (void);
+
+static pthread_once_t init_control = PTHREAD_ONCE_INIT;
+
+/* NB: this is slightly thread-unsafe */
+
+debuginfod_client *
+dwfl_get_debuginfod_client (Dwfl *dwfl)
+{
+  if (dwfl->debuginfod != NULL)
+    return dwfl->debuginfod;
+
+  pthread_once (&init_control, __libdwfl_debuginfod_init);
+
+  if (fp_debuginfod_begin != NULL)
+    {
+      dwfl->debuginfod = (*fp_debuginfod_begin) ();
+      return dwfl->debuginfod;
+    }
+
+  return NULL;
+}
+INTDEF(dwfl_get_debuginfod_client)
+
+int
+__libdwfl_debuginfod_find_executable (Dwfl *dwfl,
+				      const unsigned char *build_id_bits,
+				      size_t build_id_len)
+{
+  int fd = -1;
+  if (build_id_len > 0)
+    {
+      debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
+      if (c != NULL)
+	fd = (*fp_debuginfod_find_executable) (c, build_id_bits,
+					       build_id_len, NULL);
+    }
+
+  return fd;
+}
+
+int
+__libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
+				     const unsigned char *build_id_bits,
+				     size_t build_id_len)
+{
+  int fd = -1;
+  if (build_id_len > 0)
+    {
+      debuginfod_client *c = INTUSE (dwfl_get_debuginfod_client) (dwfl);
+      if (c != NULL)
+	fd = (*fp_debuginfod_find_debuginfo) (c, build_id_bits,
+					      build_id_len, NULL);
+    }
+
+  return fd;
+}
+
+void
+__libdwfl_debuginfod_end (debuginfod_client *c)
+{
+  if (c != NULL)
+    (*fp_debuginfod_end) (c);
+}
+
+/* Try to get the libdebuginfod library functions.
+   Only needs to be called once from dwfl_get_debuginfod_client.  */
+static void
+__libdwfl_debuginfod_init (void)
+{
+  void *debuginfod_so = dlopen(DEBUGINFOD_SONAME, RTLD_LAZY);
+
+  if (debuginfod_so != NULL)
+    {
+      fp_debuginfod_begin = dlsym (debuginfod_so, "debuginfod_begin");
+      fp_debuginfod_find_executable = dlsym (debuginfod_so,
+					     "debuginfod_find_executable");
+      fp_debuginfod_find_debuginfo = dlsym (debuginfod_so,
+					    "debuginfod_find_debuginfo");
+      fp_debuginfod_end = dlsym (debuginfod_so, "debuginfod_end");
+
+      /* We either get them all, or we get none.  */
+      if (fp_debuginfod_begin == NULL
+	  || fp_debuginfod_find_executable == NULL
+	  || fp_debuginfod_find_debuginfo == NULL
+	  || fp_debuginfod_end == NULL)
+	{
+	  fp_debuginfod_begin = NULL;
+	  fp_debuginfod_find_executable = NULL;
+	  fp_debuginfod_find_debuginfo = NULL;
+	  fp_debuginfod_end = NULL;
+	  dlclose (debuginfod_so);
+	}
+    }
+}
+
+#else // ENABLE_LIBDEBUGINFOD
+
+debuginfod_client *
+dwfl_get_debuginfod_client (Dwfl *dummy __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+#endif // ENABLE_LIBDEBUGINFOD
diff --git a/libdwfl/derelocate.c b/libdwfl/derelocate.c
new file mode 100644
index 0000000..2f80b20
--- /dev/null
+++ b/libdwfl/derelocate.c
@@ -0,0 +1,434 @@
+/* Recover relocatibility for addresses computed from debug information.
+   Copyright (C) 2005-2010, 2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+struct dwfl_relocation
+{
+  size_t count;
+  struct
+  {
+    Elf_Scn *scn;
+    Elf_Scn *relocs;
+    const char *name;
+    GElf_Addr start, end;
+  } refs[0];
+};
+
+
+struct secref
+{
+  struct secref *next;
+  Elf_Scn *scn;
+  Elf_Scn *relocs;
+  const char *name;
+  GElf_Addr start, end;
+};
+
+static int
+compare_secrefs (const void *a, const void *b)
+{
+  struct secref *const *p1 = a;
+  struct secref *const *p2 = b;
+
+  /* No signed difference calculation is correct here, since the
+     terms are unsigned and could be more than INT64_MAX apart.  */
+  if ((*p1)->start < (*p2)->start)
+    return -1;
+  if ((*p1)->start > (*p2)->start)
+    return 1;
+
+  if ((*p1)->end < (*p2)->end)
+    return -1;
+  if ((*p1)->end > (*p2)->end)
+    return 1;
+
+  /* Same start/end, then just compare which section came first.  */
+  return elf_ndxscn ((*p1)->scn) - elf_ndxscn ((*p2)->scn);
+}
+
+static int
+cache_sections (Dwfl_Module *mod)
+{
+  if (likely (mod->reloc_info != NULL))
+    return mod->reloc_info->count;
+
+  struct secref *refs = NULL;
+  size_t nrefs = 0;
+
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0))
+    {
+    elf_error:
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      nrefs = -1;
+      goto free_refs;
+    }
+
+  bool check_reloc_sections = false;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	goto elf_error;
+
+      if ((shdr->sh_flags & SHF_ALLOC) && shdr->sh_addr == 0
+	  && mod->e_type == ET_REL)
+	{
+	  /* This section might not yet have been looked at.  */
+	  if (__libdwfl_relocate_value (mod, mod->main.elf, &shstrndx,
+					elf_ndxscn (scn),
+					&shdr->sh_addr) != DWFL_E_NOERROR)
+	    continue;
+	  shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (unlikely (shdr == NULL))
+	    goto elf_error;
+	}
+
+      if (shdr->sh_flags & SHF_ALLOC)
+	{
+	  const char *name = elf_strptr (mod->main.elf, shstrndx,
+					 shdr->sh_name);
+	  if (unlikely (name == NULL))
+	    goto elf_error;
+
+	  struct secref *newref = malloc (sizeof *newref);
+	  if (unlikely (newref == NULL))
+	    {
+	    nomem:
+	      __libdwfl_seterrno (DWFL_E_NOMEM);
+	      nrefs = -1;
+	      goto free_refs;
+	    }
+
+	  newref->scn = scn;
+	  newref->relocs = NULL;
+	  newref->name = name;
+	  newref->start = dwfl_adjusted_address (mod, shdr->sh_addr);
+	  newref->end = newref->start + shdr->sh_size;
+	  newref->next = refs;
+	  refs = newref;
+	  ++nrefs;
+	}
+
+      if (mod->e_type == ET_REL
+	  && shdr->sh_size != 0
+	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+	  && mod->dwfl->callbacks->section_address != NULL)
+	{
+	  if (shdr->sh_info < elf_ndxscn (scn))
+	    {
+	      /* We've already looked at the section these relocs apply to.  */
+	      Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info);
+	      if (likely (tscn != NULL))
+		for (struct secref *sec = refs; sec != NULL; sec = sec->next)
+		  if (sec->scn == tscn)
+		    {
+		      sec->relocs = scn;
+		      break;
+		    }
+	    }
+	  else
+	    /* We'll have to do a second pass.  */
+	    check_reloc_sections = true;
+	}
+    }
+
+  mod->reloc_info = malloc (offsetof (struct dwfl_relocation, refs[nrefs]));
+  if (unlikely (mod->reloc_info == NULL))
+    goto nomem;
+
+  struct secref **sortrefs = malloc (nrefs * sizeof sortrefs[0]);
+  if (unlikely (sortrefs == NULL))
+    goto nomem;
+
+  for (size_t i = nrefs; i-- > 0; refs = refs->next)
+    sortrefs[i] = refs;
+  assert (refs == NULL);
+
+  qsort (sortrefs, nrefs, sizeof sortrefs[0], &compare_secrefs);
+
+  mod->reloc_info->count = nrefs;
+  for (size_t i = 0; i < nrefs; ++i)
+    {
+      mod->reloc_info->refs[i].name = sortrefs[i]->name;
+      mod->reloc_info->refs[i].scn = sortrefs[i]->scn;
+      mod->reloc_info->refs[i].relocs = sortrefs[i]->relocs;
+      mod->reloc_info->refs[i].start = sortrefs[i]->start;
+      mod->reloc_info->refs[i].end = sortrefs[i]->end;
+      free (sortrefs[i]);
+    }
+
+  free (sortrefs);
+
+  if (unlikely (check_reloc_sections))
+    {
+      /* There was a reloc section that preceded its target section.
+	 So we have to scan again now that we have cached all the
+	 possible target sections we care about.  */
+
+      scn = NULL;
+      while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    goto elf_error;
+
+      	  if (shdr->sh_size != 0
+	      && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
+	    {
+	      Elf_Scn *tscn = elf_getscn (mod->main.elf, shdr->sh_info);
+	      if (likely (tscn != NULL))
+		for (size_t i = 0; i < nrefs; ++i)
+		  if (mod->reloc_info->refs[i].scn == tscn)
+		    {
+		      mod->reloc_info->refs[i].relocs = scn;
+		      break;
+		    }
+	    }
+	}
+    }
+
+free_refs:
+  while (refs != NULL)
+    {
+      struct secref *ref = refs;
+      refs = ref->next;
+      free (ref);
+    }
+
+  return nrefs;
+}
+
+
+int
+dwfl_module_relocations (Dwfl_Module *mod)
+{
+  if (mod == NULL)
+    return -1;
+
+  switch (mod->e_type)
+    {
+    case ET_REL:
+      return cache_sections (mod);
+
+    case ET_DYN:
+      return 1;
+
+    case ET_EXEC:
+      assert (mod->main.vaddr == mod->low_addr);
+      break;
+    }
+
+  return 0;
+}
+
+const char *
+dwfl_module_relocation_info (Dwfl_Module *mod, unsigned int idx,
+			     Elf32_Word *shndxp)
+{
+  if (mod == NULL)
+    return NULL;
+
+  switch (mod->e_type)
+    {
+    case ET_REL:
+      break;
+
+    case ET_DYN:
+      if (idx != 0)
+	return NULL;
+      if (shndxp)
+	*shndxp = SHN_ABS;
+      return "";
+
+    default:
+      return NULL;
+    }
+
+  if (cache_sections (mod) < 0)
+    return NULL;
+
+  struct dwfl_relocation *sections = mod->reloc_info;
+
+  if (idx >= sections->count)
+    return NULL;
+
+  if (shndxp)
+    *shndxp = elf_ndxscn (sections->refs[idx].scn);
+
+  return sections->refs[idx].name;
+}
+
+/* Check that MOD is valid and make sure its relocation has been done.  */
+static bool
+check_module (Dwfl_Module *mod)
+{
+  if (mod == NULL)
+    return true;
+
+  if (INTUSE(dwfl_module_getsymtab) (mod) < 0)
+    {
+      Dwfl_Error error = dwfl_errno ();
+      if (error != DWFL_E_NO_SYMTAB)
+	{
+	  __libdwfl_seterrno (error);
+	  return true;
+	}
+    }
+
+  if (mod->dw == NULL)
+    {
+      Dwarf_Addr bias;
+      if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL)
+	{
+	  Dwfl_Error error = dwfl_errno ();
+	  if (error != DWFL_E_NO_DWARF)
+	    {
+	      __libdwfl_seterrno (error);
+	      return true;
+	    }
+	}
+    }
+
+  return false;
+}
+
+/* Find the index in MOD->reloc_info.refs containing *ADDR.  */
+static int
+find_section (Dwfl_Module *mod, Dwarf_Addr *addr)
+{
+  if (cache_sections (mod) < 0)
+    return -1;
+
+  struct dwfl_relocation *sections = mod->reloc_info;
+
+  /* The sections are sorted by address, so we can use binary search.  */
+  size_t l = 0, u = sections->count;
+  while (l < u)
+    {
+      size_t idx = (l + u) / 2;
+      if (*addr < sections->refs[idx].start)
+	u = idx;
+      else if (*addr > sections->refs[idx].end)
+	l = idx + 1;
+      else
+	{
+	  /* Consider the limit of a section to be inside it, unless it's
+	     inside the next one.  A section limit address can appear in
+	     line records.  */
+	  if (*addr == sections->refs[idx].end
+	      && idx + 1 < sections->count
+	      && *addr == sections->refs[idx + 1].start)
+	    ++idx;
+
+	  *addr -= sections->refs[idx].start;
+	  return idx;
+	}
+    }
+
+  __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_NO_MATCH));
+  return -1;
+}
+
+size_t
+internal_function
+__libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr)
+{
+  int idx = find_section (mod, addr);
+  if (unlikely (idx == -1))
+    return SHN_UNDEF;
+
+  return elf_ndxscn (mod->reloc_info->refs[idx].scn);
+}
+
+int
+dwfl_module_relocate_address (Dwfl_Module *mod, Dwarf_Addr *addr)
+{
+  if (unlikely (check_module (mod)))
+    return -1;
+
+  switch (mod->e_type)
+    {
+    case ET_REL:
+      return find_section (mod, addr);
+
+    case ET_DYN:
+      /* All relative to first and only relocation base: module start.  */
+      *addr -= mod->low_addr;
+      break;
+
+    default:
+      /* Already absolute, dwfl_module_relocations returned zero.  We
+	 shouldn't really have been called, but it's a harmless no-op.  */
+      break;
+    }
+
+  return 0;
+}
+INTDEF (dwfl_module_relocate_address)
+
+Elf_Scn *
+dwfl_module_address_section (Dwfl_Module *mod, Dwarf_Addr *address,
+			     Dwarf_Addr *bias)
+{
+  if (check_module (mod))
+    return NULL;
+
+  int idx = find_section (mod, address);
+  if (idx < 0)
+    return NULL;
+
+  if (mod->reloc_info->refs[idx].relocs != NULL)
+    {
+      assert (mod->e_type == ET_REL);
+
+      Elf_Scn *tscn = mod->reloc_info->refs[idx].scn;
+      Elf_Scn *relocscn = mod->reloc_info->refs[idx].relocs;
+      Dwfl_Error result = __libdwfl_relocate_section (mod, mod->main.elf,
+						      relocscn, tscn, true);
+      if (likely (result == DWFL_E_NOERROR))
+	mod->reloc_info->refs[idx].relocs = NULL;
+      else
+	{
+	  __libdwfl_seterrno (result);
+	  return NULL;
+	}
+    }
+
+  *bias = dwfl_adjusted_address (mod, 0);
+  return mod->reloc_info->refs[idx].scn;
+}
+INTDEF (dwfl_module_address_section)
diff --git a/libdwfl/dwfl_addrdie.c b/libdwfl/dwfl_addrdie.c
new file mode 100644
index 0000000..c5b1d68
--- /dev/null
+++ b/libdwfl/dwfl_addrdie.c
@@ -0,0 +1,40 @@
+/* Fetch CU DIE from address.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwarf_Die *
+dwfl_addrdie (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias)
+{
+  return INTUSE(dwfl_module_addrdie) (INTUSE(dwfl_addrmodule) (dwfl, addr),
+				      addr, bias);
+}
diff --git a/libdwfl/dwfl_addrdwarf.c b/libdwfl/dwfl_addrdwarf.c
new file mode 100644
index 0000000..4f9efab
--- /dev/null
+++ b/libdwfl/dwfl_addrdwarf.c
@@ -0,0 +1,41 @@
+/* Fetch libdw handle from address.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwarf *
+dwfl_addrdwarf (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Addr *bias)
+{
+  return INTUSE(dwfl_module_getdwarf) (INTUSE(dwfl_addrmodule) (dwfl, address),
+				       bias);
+}
+INTDEF (dwfl_addrdwarf)
diff --git a/libdwfl/dwfl_addrmodule.c b/libdwfl/dwfl_addrmodule.c
new file mode 100644
index 0000000..abf1ff4
--- /dev/null
+++ b/libdwfl/dwfl_addrmodule.c
@@ -0,0 +1,42 @@
+/* Find module containing address.
+   Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwfl_Module *
+dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address)
+{
+  Dwfl_Module *mod;
+  (void) INTUSE(dwfl_addrsegment) (dwfl, address, &mod);
+  return mod;
+}
+INTDEF (dwfl_addrmodule)
diff --git a/libdwfl/dwfl_begin.c b/libdwfl/dwfl_begin.c
new file mode 100644
index 0000000..b03f5cf
--- /dev/null
+++ b/libdwfl/dwfl_begin.c
@@ -0,0 +1,55 @@
+/* Set up a session using libdwfl.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwfl *
+dwfl_begin (const Dwfl_Callbacks *callbacks)
+{
+  if (elf_version (EV_CURRENT) == EV_NONE)
+    {
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      return NULL;
+    }
+
+  Dwfl *dwfl = calloc (1, sizeof *dwfl);
+  if (dwfl == NULL)
+    __libdwfl_seterrno (DWFL_E_NOMEM);
+  else
+    {
+      dwfl->callbacks = callbacks;
+      dwfl->offline_next_address = OFFLINE_REDZONE;
+    }
+
+  return dwfl;
+}
+INTDEF (dwfl_begin)
diff --git a/libdwfl/dwfl_build_id_find_debuginfo.c b/libdwfl/dwfl_build_id_find_debuginfo.c
new file mode 100644
index 0000000..856f231
--- /dev/null
+++ b/libdwfl/dwfl_build_id_find_debuginfo.c
@@ -0,0 +1,130 @@
+/* Find the debuginfo file for a module from its build ID.
+   Copyright (C) 2007, 2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+int
+dwfl_build_id_find_debuginfo (Dwfl_Module *mod,
+			      void **userdata __attribute__ ((unused)),
+			      const char *modname __attribute__ ((unused)),
+			      Dwarf_Addr base __attribute__ ((unused)),
+			      const char *file __attribute__ ((unused)),
+			      const char *debuglink __attribute__ ((unused)),
+			      GElf_Word crc __attribute__ ((unused)),
+			      char **debuginfo_file_name)
+{
+  int fd = -1;
+
+  /* Are we looking for a separate debug file for the main file or for
+     an alternate (dwz multi) debug file?  Alternatively we could check
+     whether the dwbias == -1.  */
+  if (mod->dw != NULL)
+    {
+      const void *build_id;
+      const char *altname;
+      ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
+								   &altname,
+								   &build_id);
+      if (build_id_len > 0)
+	fd = __libdwfl_open_by_build_id (mod, true, debuginfo_file_name,
+					 build_id_len, build_id);
+
+      if (fd >= 0)
+	{
+	  /* We need to open an Elf handle on the file so we can check its
+	     build ID note for validation.  Backdoor the handle into the
+	     module data structure since we had to open it early anyway.  */
+	  Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf,
+						true, false);
+	  if (error != DWFL_E_NOERROR)
+	    __libdwfl_seterrno (error);
+	  else
+	    {
+	      const void *alt_build_id;
+	      ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf,
+								&alt_build_id);
+	      if (alt_len > 0 && alt_len == build_id_len
+		  && memcmp (build_id, alt_build_id, alt_len) == 0)
+		return fd;
+	      else
+		{
+		  /* A mismatch!  */
+		  elf_end (mod->alt_elf);
+		  mod->alt_elf = NULL;
+		  close (fd);
+		  fd = -1;
+		}
+	      free (*debuginfo_file_name);
+	      *debuginfo_file_name = NULL;
+	      errno = 0;
+	    }
+	}
+      return fd;
+    }
+
+  /* We don't even have the Dwarf yet and it isn't in the main file.
+     Try to find separate debug file now using the module build id.  */
+  const unsigned char *bits;
+  GElf_Addr vaddr;
+
+  if (INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr) > 0)
+    fd = __libdwfl_open_mod_by_build_id (mod, true, debuginfo_file_name);
+  if (fd >= 0)
+    {
+      /* We need to open an Elf handle on the file so we can check its
+	 build ID note for validation.  Backdoor the handle into the
+	 module data structure since we had to open it early anyway.  */
+      Dwfl_Error error = __libdw_open_file (&fd, &mod->debug.elf, true, false);
+      if (error != DWFL_E_NOERROR)
+	__libdwfl_seterrno (error);
+      else if (likely (__libdwfl_find_build_id (mod, false,
+						mod->debug.elf) == 2))
+	{
+	  /* Also backdoor the gratuitous flag.  */
+	  mod->debug.valid = true;
+	  return fd;
+	}
+      else
+	{
+	  /* A mismatch!  */
+	  elf_end (mod->debug.elf);
+	  mod->debug.elf = NULL;
+	  close (fd);
+	  fd = -1;
+	}
+      free (*debuginfo_file_name);
+      *debuginfo_file_name = NULL;
+      errno = 0;
+    }
+  return fd;
+}
+INTDEF (dwfl_build_id_find_debuginfo)
diff --git a/libdwfl/dwfl_build_id_find_elf.c b/libdwfl/dwfl_build_id_find_elf.c
new file mode 100644
index 0000000..35bc8c9
--- /dev/null
+++ b/libdwfl/dwfl_build_id_find_elf.c
@@ -0,0 +1,212 @@
+/* Find an ELF file for a module from its build ID.
+   Copyright (C) 2007-2010, 2014, 2015, 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <inttypes.h>
+#include <fcntl.h>
+#include "system.h"
+
+
+int
+internal_function
+__libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug, char **file_name,
+			    const size_t id_len, const uint8_t *id)
+{
+  /* We don't handle very short or really large build-ids.  We need at
+     at least 3 and allow for up to 64 (normally ids are 20 long).  */
+#define MIN_BUILD_ID_BYTES 3
+#define MAX_BUILD_ID_BYTES 64
+  if (id_len < MIN_BUILD_ID_BYTES || id_len > MAX_BUILD_ID_BYTES)
+    {
+    bad_id:
+      __libdwfl_seterrno (DWFL_E_WRONG_ID_ELF);
+      return -1;
+    }
+
+  /* Search debuginfo_path directories' .build-id/ subdirectories.  */
+
+  char id_name[sizeof "/.build-id/" + 1 + MAX_BUILD_ID_BYTES * 2
+	       + sizeof ".debug" - 1];
+  strcpy (id_name, "/.build-id/");
+  int n = snprintf (&id_name[sizeof "/.build-id/" - 1],
+		    4, "%02" PRIx8 "/", (uint8_t) id[0]);
+  if (n != 3)
+    goto bad_id;;
+  for (size_t i = 1; i < id_len; ++i)
+    {
+      n = snprintf (&id_name[sizeof "/.build-id/" - 1 + 3 + (i - 1) * 2],
+		    3, "%02" PRIx8, (uint8_t) id[i]);
+      if (n != 2)
+	goto bad_id;
+    }
+  if (debug)
+    strcpy (&id_name[sizeof "/.build-id/" - 1 + 3 + (id_len - 1) * 2],
+	    ".debug");
+
+  const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
+  char *path = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
+		       ?: DEFAULT_DEBUGINFO_PATH);
+  if (path == NULL)
+    return -1;
+
+  int fd = -1;
+  char *dir;
+  char *paths = path;
+  while (fd < 0 && (dir = strsep (&paths, ":")) != NULL)
+    {
+      if (dir[0] == '+' || dir[0] == '-')
+	++dir;
+
+      /* Only absolute directory names are useful to us.  */
+      if (dir[0] != '/')
+	continue;
+
+      size_t dirlen = strlen (dir);
+      char *name = malloc (dirlen + sizeof id_name);
+      if (unlikely (name == NULL))
+	break;
+      memcpy (mempcpy (name, dir, dirlen), id_name, sizeof id_name);
+
+      fd = TEMP_FAILURE_RETRY (open (name, O_RDONLY));
+      if (fd >= 0)
+	{
+	  if (*file_name != NULL)
+	    free (*file_name);
+	  *file_name = realpath (name, NULL);
+	  if (*file_name == NULL)
+	    {
+	      *file_name = name;
+	      name = NULL;
+	    }
+	}
+      free (name);
+    }
+
+  free (path);
+
+  /* If we simply found nothing, clear errno.  If we had some other error
+     with the file, report that.  Possibly this should treat other errors
+     like ENOENT too.  But ignoring all errors could mask some that should
+     be reported.  */
+  if (fd < 0 && errno == ENOENT)
+    errno = 0;
+
+  return fd;
+}
+
+int
+internal_function
+__libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug, char **file_name)
+{
+  /* If *FILE_NAME was primed into the module, leave it there
+     as the fallback when we have nothing to offer.  */
+  errno = 0;
+  if (mod->build_id_len <= 0)
+    return -1;
+
+  const size_t id_len = mod->build_id_len;
+  const uint8_t *id = mod->build_id_bits;
+
+  return __libdwfl_open_by_build_id (mod, debug, file_name, id_len, id);
+}
+
+int
+dwfl_build_id_find_elf (Dwfl_Module *mod,
+			void **userdata __attribute__ ((unused)),
+			const char *modname __attribute__ ((unused)),
+			Dwarf_Addr base __attribute__ ((unused)),
+			char **file_name, Elf **elfp)
+{
+  *elfp = NULL;
+  if (mod->is_executable
+      && mod->dwfl->user_core != NULL
+      && mod->dwfl->user_core->executable_for_core != NULL)
+    {
+      /* When dwfl_core_file_report was called with a non-NULL executable file
+	 name this callback will replace the Dwfl_Module main.name with the
+	 recorded executable file when MOD was identified as main executable
+	 (which then triggers opening and reporting of the executable).  */
+      const char *executable = mod->dwfl->user_core->executable_for_core;
+      int fd = open (executable, O_RDONLY);
+      if (fd >= 0)
+	{
+	  *file_name = strdup (executable);
+	  if (*file_name != NULL)
+	    return fd;
+	  else
+	    close (fd);
+	}
+    }
+  int fd = __libdwfl_open_mod_by_build_id (mod, false, file_name);
+  if (fd >= 0)
+    {
+      Dwfl_Error error = __libdw_open_file (&fd, elfp, true, false);
+      if (error != DWFL_E_NOERROR)
+	__libdwfl_seterrno (error);
+      else if (__libdwfl_find_build_id (mod, false, *elfp) == 2)
+	{
+	  /* This is a backdoor signal to short-circuit the ID refresh.  */
+	  mod->main.valid = true;
+	  return fd;
+	}
+      else
+	{
+	  /* This file does not contain the ID it should!  */
+	  elf_end (*elfp);
+	  *elfp = NULL;
+	  close (fd);
+	  fd = -1;
+	}
+      free (*file_name);
+      *file_name = NULL;
+    }
+  else
+    {
+#ifdef ENABLE_LIBDEBUGINFOD
+      /* If all else fails and a build-id is available, query the
+	 debuginfo-server if enabled.  */
+      if (fd < 0 && mod->build_id_len > 0)
+	fd = __libdwfl_debuginfod_find_executable (mod->dwfl,
+						   mod->build_id_bits,
+						   mod->build_id_len);
+#endif
+    }
+
+  if (fd < 0 && errno == 0 && mod->build_id_len > 0)
+    /* Setting this with no file yet loaded is a marker that
+       the build ID is authoritative even if we also know a
+       putative *FILE_NAME.  */
+    mod->main.valid = true;
+
+  return fd;
+}
+INTDEF (dwfl_build_id_find_elf)
diff --git a/libdwfl/dwfl_cumodule.c b/libdwfl/dwfl_cumodule.c
new file mode 100644
index 0000000..2b593f2
--- /dev/null
+++ b/libdwfl/dwfl_cumodule.c
@@ -0,0 +1,40 @@
+/* Find the module for a CU DIE previously returned by libdwfl.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwfl_Module *
+dwfl_cumodule (Dwarf_Die *cudie)
+{
+  struct dwfl_cu *cu = (struct dwfl_cu *) cudie;
+  return cu->mod;
+}
diff --git a/libdwfl/dwfl_dwarf_line.c b/libdwfl/dwfl_dwarf_line.c
new file mode 100644
index 0000000..5084c65
--- /dev/null
+++ b/libdwfl/dwfl_dwarf_line.c
@@ -0,0 +1,47 @@
+/* Get information from a source line record returned by libdwfl.
+   Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "libdwP.h"
+
+Dwarf_Line *
+dwfl_dwarf_line (Dwfl_Line *line, Dwarf_Addr *bias)
+{
+  if (line == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu = dwfl_linecu (line);
+  const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx];
+
+  *bias = dwfl_adjusted_dwarf_addr (cu->mod, 0);
+  return (Dwarf_Line *) info;
+}
diff --git a/libdwfl/dwfl_end.c b/libdwfl/dwfl_end.c
new file mode 100644
index 0000000..a181240
--- /dev/null
+++ b/libdwfl/dwfl_end.c
@@ -0,0 +1,69 @@
+/* Finish a session using libdwfl.
+   Copyright (C) 2005, 2008, 2012-2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+void
+dwfl_end (Dwfl *dwfl)
+{
+  if (dwfl == NULL)
+    return;
+
+#ifdef ENABLE_LIBDEBUGINFOD
+  __libdwfl_debuginfod_end (dwfl->debuginfod);
+#endif
+
+  if (dwfl->process)
+    __libdwfl_process_free (dwfl->process);
+
+  free (dwfl->lookup_addr);
+  free (dwfl->lookup_module);
+  free (dwfl->lookup_segndx);
+
+  Dwfl_Module *next = dwfl->modulelist;
+  while (next != NULL)
+    {
+      Dwfl_Module *dead = next;
+      next = dead->next;
+      __libdwfl_module_free (dead);
+    }
+
+  if (dwfl->user_core != NULL)
+    {
+      free (dwfl->user_core->executable_for_core);
+      elf_end (dwfl->user_core->core);
+      if (dwfl->user_core->fd != -1)
+	close (dwfl->user_core->fd);
+      free (dwfl->user_core);
+    }
+  free (dwfl);
+}
diff --git a/libdwfl/dwfl_error.c b/libdwfl/dwfl_error.c
new file mode 100644
index 0000000..43fa1dc
--- /dev/null
+++ b/libdwfl/dwfl_error.c
@@ -0,0 +1,185 @@
+/* Error handling in libdwfl.
+   Copyright (C) 2005-2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "libdwflP.h"
+
+
+/* The error number.  */
+static __thread int global_error;
+
+
+int
+dwfl_errno (void)
+{
+  int result = global_error;
+  global_error = DWFL_E_NOERROR;
+  return result;
+}
+INTDEF (dwfl_errno)
+
+
+struct msgtable
+{
+#define DWFL_ERROR(name, text) char msg_##name[sizeof text];
+  DWFL_ERRORS
+#undef	DWFL_ERROR
+};
+
+static const union
+{
+  struct msgtable table;
+  char strings[
+#define DWFL_ERROR(name, text)	+ sizeof text
+	       DWFL_ERRORS
+#undef	DWFL_ERROR
+	       ];
+} msgtable =
+  {
+    .table =
+    {
+#define DWFL_ERROR(name, text) text,
+      DWFL_ERRORS
+#undef	DWFL_ERROR
+    }
+  };
+#define msgstr (msgtable.strings)
+
+static const uint_fast16_t msgidx[] =
+{
+#define DWFL_ERROR(name, text) \
+  [DWFL_E_##name] = offsetof (struct msgtable, msg_##name),
+  DWFL_ERRORS
+#undef	DWFL_ERROR
+};
+#define nmsgidx (sizeof msgidx / sizeof msgidx[0])
+
+
+static inline int
+canonicalize (Dwfl_Error error)
+{
+  unsigned int value;
+
+  switch (error)
+    {
+    default:
+      value = error;
+      if ((value &~ 0xffff) != 0)
+	break;
+      assert (value < nmsgidx);
+      break;
+    case DWFL_E_ERRNO:
+      value = DWFL_E (ERRNO, errno);
+      break;
+    case DWFL_E_LIBELF:
+      value = DWFL_E (LIBELF, elf_errno ());
+      break;
+    case DWFL_E_LIBDW:
+      value = DWFL_E (LIBDW, INTUSE(dwarf_errno) ());
+      break;
+#if 0
+    DWFL_E_LIBEBL:
+      value = DWFL_E (LIBEBL, ebl_errno ());
+      break;
+#endif
+    }
+
+  return value;
+}
+
+int
+internal_function
+__libdwfl_canon_error (Dwfl_Error error)
+{
+  return canonicalize (error);
+}
+
+void
+internal_function
+__libdwfl_seterrno (Dwfl_Error error)
+{
+  global_error = canonicalize (error);
+}
+
+
+static const char *
+errnomsg(int error)
+{
+  /* Won't be changed by strerror_r, but not const so compiler doesn't throw warning */
+  static char unknown[] = "unknown error";
+
+#ifdef STRERROR_R_CHAR_P
+  return strerror_r (error, unknown, 0);
+#else
+  /* To store the error message from strerror_r in a thread-safe manner */
+  static __thread char msg[128];
+  return strerror_r (error, msg, sizeof (msg)) ? unknown : msg;
+#endif
+}
+
+const char *
+dwfl_errmsg (int error)
+{
+  if (error == 0 || error == -1)
+    {
+      int last_error = global_error;
+
+      if (error == 0 && last_error == 0)
+	return NULL;
+
+      error = last_error;
+      global_error = DWFL_E_NOERROR;
+    }
+
+  switch (error &~ 0xffff)
+    {
+    case OTHER_ERROR (ERRNO):
+      return errnomsg (error & 0xffff);
+    case OTHER_ERROR (LIBELF):
+      return elf_errmsg (error & 0xffff);
+    case OTHER_ERROR (LIBDW):
+      return INTUSE(dwarf_errmsg) (error & 0xffff);
+#if 0
+    case OTHER_ERROR (LIBEBL):
+      return ebl_errmsg (error & 0xffff);
+#endif
+    }
+
+  return _(&msgstr[msgidx[(unsigned int) error < nmsgidx
+			  ? error : DWFL_E_UNKNOWN_ERROR]]);
+}
+INTDEF (dwfl_errmsg)
diff --git a/libdwfl/dwfl_frame.c b/libdwfl/dwfl_frame.c
new file mode 100644
index 0000000..5ee71dd
--- /dev/null
+++ b/libdwfl/dwfl_frame.c
@@ -0,0 +1,457 @@
+/* Get Dwarf Frame state for target PID or core file.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include "libdwflP.h"
+
+/* Set STATE->pc_set from STATE->regs according to the backend.  Return true on
+   success, false on error.  */
+static bool
+state_fetch_pc (Dwfl_Frame *state)
+{
+  switch (state->pc_state)
+    {
+    case DWFL_FRAME_STATE_PC_SET:
+      return true;
+    case DWFL_FRAME_STATE_PC_UNDEFINED:
+      abort ();
+    case DWFL_FRAME_STATE_ERROR:
+      {
+	Ebl *ebl = state->thread->process->ebl;
+	Dwarf_CIE abi_info;
+	if (ebl_abi_cfi (ebl, &abi_info) != 0)
+	  {
+	    __libdwfl_seterrno (DWFL_E_LIBEBL);
+	    return false;
+	  }
+	unsigned ra = abi_info.return_address_register;
+	/* dwarf_frame_state_reg_is_set is not applied here.  */
+	if (ra >= ebl_frame_nregs (ebl))
+	  {
+	    __libdwfl_seterrno (DWFL_E_LIBEBL_BAD);
+	    return false;
+	  }
+	state->pc = state->regs[ra] + ebl_ra_offset (ebl);
+	state->pc_state = DWFL_FRAME_STATE_PC_SET;
+      }
+      return true;
+    }
+  abort ();
+}
+
+/* Do not call it on your own, to be used by thread_* functions only.  */
+
+static void
+free_states (Dwfl_Frame *state)
+{
+  while (state)
+    {
+      Dwfl_Frame *next = state->unwound;
+      free(state);
+      state = next;
+    }
+}
+
+static Dwfl_Frame *
+state_alloc (Dwfl_Thread *thread)
+{
+  assert (thread->unwound == NULL);
+  Ebl *ebl = thread->process->ebl;
+  size_t nregs = ebl_frame_nregs (ebl);
+  if (nregs == 0)
+    return NULL;
+  assert (nregs < sizeof (((Dwfl_Frame *) NULL)->regs_set) * 8);
+  Dwfl_Frame *state = malloc (sizeof (*state) + sizeof (*state->regs) * nregs);
+  if (state == NULL)
+    return NULL;
+  state->thread = thread;
+  state->signal_frame = false;
+  state->initial_frame = true;
+  state->pc_state = DWFL_FRAME_STATE_ERROR;
+  memset (state->regs_set, 0, sizeof (state->regs_set));
+  thread->unwound = state;
+  state->unwound = NULL;
+  return state;
+}
+
+void
+internal_function
+__libdwfl_process_free (Dwfl_Process *process)
+{
+  Dwfl *dwfl = process->dwfl;
+  if (process->callbacks->detach != NULL)
+    process->callbacks->detach (dwfl, process->callbacks_arg);
+  assert (dwfl->process == process);
+  dwfl->process = NULL;
+  if (process->ebl_close)
+    ebl_closebackend (process->ebl);
+  free (process);
+  dwfl->attacherr = DWFL_E_NOERROR;
+}
+
+/* Allocate new Dwfl_Process for DWFL.  */
+static void
+process_alloc (Dwfl *dwfl)
+{
+  Dwfl_Process *process = malloc (sizeof (*process));
+  if (process == NULL)
+    return;
+  process->dwfl = dwfl;
+  dwfl->process = process;
+}
+
+bool
+dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
+		   const Dwfl_Thread_Callbacks *thread_callbacks, void *arg)
+{
+  if (dwfl->process != NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_ATTACH_STATE_CONFLICT);
+      return false;
+    }
+
+  /* Reset any previous error, we are just going to try again.  */
+  dwfl->attacherr = DWFL_E_NOERROR;
+  /* thread_callbacks is declared NN */
+  if (thread_callbacks->next_thread == NULL
+      || thread_callbacks->set_initial_registers == NULL)
+    {
+      dwfl->attacherr = DWFL_E_INVALID_ARGUMENT;
+    fail:
+      dwfl->attacherr = __libdwfl_canon_error (dwfl->attacherr);
+      __libdwfl_seterrno (dwfl->attacherr);
+      return false;
+    }
+
+  Ebl *ebl;
+  bool ebl_close;
+  if (elf != NULL)
+    {
+      ebl = ebl_openbackend (elf);
+      ebl_close = true;
+    }
+  else
+    {
+      ebl = NULL;
+      for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
+	{
+	  /* Reading of the vDSO or (deleted) modules may fail as
+	     /proc/PID/mem is unreadable without PTRACE_ATTACH and
+	     we may not be PTRACE_ATTACH-ed now.  MOD would not be
+	     re-read later to unwind it when we are already
+	     PTRACE_ATTACH-ed to PID.  This happens when this function
+	     is called from dwfl_linux_proc_attach with elf == NULL.
+	     __libdwfl_module_getebl will call __libdwfl_getelf which
+	     will call the find_elf callback.  */
+	  if (startswith (mod->name, "[vdso: ")
+	      || strcmp (strrchr (mod->name, ' ') ?: "",
+			 " (deleted)") == 0)
+	    continue;
+	  Dwfl_Error error = __libdwfl_module_getebl (mod);
+	  if (error != DWFL_E_NOERROR)
+	    continue;
+	  ebl = mod->ebl;
+	  break;
+	}
+      ebl_close = false;
+    }
+  if (ebl == NULL)
+    {
+      /* Not identified EBL from any of the modules.  */
+      dwfl->attacherr = DWFL_E_PROCESS_NO_ARCH;
+      goto fail;
+    }
+  process_alloc (dwfl);
+  Dwfl_Process *process = dwfl->process;
+  if (process == NULL)
+    {
+      if (ebl_close)
+	ebl_closebackend (ebl);
+      dwfl->attacherr = DWFL_E_NOMEM;
+      goto fail;
+    }
+  process->ebl = ebl;
+  process->ebl_close = ebl_close;
+  process->pid = pid;
+  process->callbacks = thread_callbacks;
+  process->callbacks_arg = arg;
+  return true;
+}
+INTDEF(dwfl_attach_state)
+
+pid_t
+dwfl_pid (Dwfl *dwfl)
+{
+  if (dwfl->attacherr != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (dwfl->attacherr);
+      return -1;
+    }
+
+  if (dwfl->process == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
+      return -1;
+    }
+  return dwfl->process->pid;
+}
+INTDEF(dwfl_pid)
+
+Dwfl *
+dwfl_thread_dwfl (Dwfl_Thread *thread)
+{
+  return thread->process->dwfl;
+}
+INTDEF(dwfl_thread_dwfl)
+
+pid_t
+dwfl_thread_tid (Dwfl_Thread *thread)
+{
+  return thread->tid;
+}
+INTDEF(dwfl_thread_tid)
+
+Dwfl_Thread *
+dwfl_frame_thread (Dwfl_Frame *state)
+{
+  return state->thread;
+}
+INTDEF(dwfl_frame_thread)
+
+int
+dwfl_getthreads (Dwfl *dwfl, int (*callback) (Dwfl_Thread *thread, void *arg),
+		 void *arg)
+{
+  if (dwfl->attacherr != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (dwfl->attacherr);
+      return -1;
+    }
+
+  Dwfl_Process *process = dwfl->process;
+  if (process == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
+      return -1;
+    }
+
+  Dwfl_Thread thread;
+  thread.process = process;
+  thread.unwound = NULL;
+  thread.callbacks_arg = NULL;
+  for (;;)
+    {
+      thread.tid = process->callbacks->next_thread (dwfl,
+						    process->callbacks_arg,
+						    &thread.callbacks_arg);
+      if (thread.tid < 0)
+	return -1;
+      if (thread.tid == 0)
+	{
+	  __libdwfl_seterrno (DWFL_E_NOERROR);
+	  return 0;
+	}
+      int err = callback (&thread, arg);
+      if (err != DWARF_CB_OK)
+	return err;
+      assert (thread.unwound == NULL);
+    }
+  /* NOTREACHED */
+}
+INTDEF(dwfl_getthreads)
+
+struct one_arg
+{
+  pid_t tid;
+  bool seen;
+  int (*callback) (Dwfl_Thread *thread, void *arg);
+  void *arg;
+  int ret;
+};
+
+static int
+get_one_thread_cb (Dwfl_Thread *thread, void *arg)
+{
+  struct one_arg *oa = (struct one_arg *) arg;
+  if (! oa->seen && INTUSE(dwfl_thread_tid) (thread) == oa->tid)
+    {
+      oa->seen = true;
+      oa->ret = oa->callback (thread, oa->arg);
+      return DWARF_CB_ABORT;
+    }
+
+  return DWARF_CB_OK;
+}
+
+/* Note not currently exported, will be when there are more Dwfl_Thread
+   properties to query.  Use dwfl_getthread_frames for now directly.  */
+static int
+getthread (Dwfl *dwfl, pid_t tid,
+	   int (*callback) (Dwfl_Thread *thread, void *arg),
+	   void *arg)
+{
+  if (dwfl->attacherr != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (dwfl->attacherr);
+      return -1;
+    }
+
+  Dwfl_Process *process = dwfl->process;
+  if (process == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NO_ATTACH_STATE);
+      return -1;
+    }
+
+  if (process->callbacks->get_thread != NULL)
+    {
+      Dwfl_Thread thread;
+      thread.process = process;
+      thread.unwound = NULL;
+      thread.callbacks_arg = NULL;
+
+      if (process->callbacks->get_thread (dwfl, tid, process->callbacks_arg,
+					  &thread.callbacks_arg))
+	{
+	  thread.tid = tid;
+	  return callback (&thread, arg);
+	}
+
+      return -1;
+    }
+
+   struct one_arg oa = { .tid = tid, .callback = callback,
+			 .arg = arg, .seen = false };
+   int err = INTUSE(dwfl_getthreads) (dwfl, get_one_thread_cb, &oa);
+
+   if (err == DWARF_CB_ABORT && oa.seen)
+     return oa.ret;
+
+   if (err == DWARF_CB_OK && ! oa.seen)
+     {
+	errno = ESRCH;
+	__libdwfl_seterrno (DWFL_E_ERRNO);
+	return -1;
+     }
+
+   return err;
+}
+
+struct one_thread
+{
+  int (*callback) (Dwfl_Frame *frame, void *arg);
+  void *arg;
+};
+
+static int
+get_one_thread_frames_cb (Dwfl_Thread *thread, void *arg)
+{
+  struct one_thread *ot = (struct one_thread *) arg;
+  return INTUSE(dwfl_thread_getframes) (thread, ot->callback, ot->arg);
+}
+
+int
+dwfl_getthread_frames (Dwfl *dwfl, pid_t tid,
+		       int (*callback) (Dwfl_Frame *frame, void *arg),
+		       void *arg)
+{
+  struct one_thread ot = { .callback = callback, .arg = arg };
+  return getthread (dwfl, tid, get_one_thread_frames_cb, &ot);
+}
+INTDEF(dwfl_getthread_frames)
+
+int
+dwfl_thread_getframes (Dwfl_Thread *thread,
+		       int (*callback) (Dwfl_Frame *state, void *arg),
+		       void *arg)
+{
+  Ebl *ebl = thread->process->ebl;
+  if (ebl_frame_nregs (ebl) == 0)
+    {
+      __libdwfl_seterrno (DWFL_E_NO_UNWIND);
+      return -1;
+    }
+  if (state_alloc (thread) == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return -1;
+    }
+  Dwfl_Process *process = thread->process;
+  if (! process->callbacks->set_initial_registers (thread,
+						   thread->callbacks_arg))
+    {
+      free_states (thread->unwound);
+      thread->unwound = NULL;
+      return -1;
+    }
+  Dwfl_Frame *state = thread->unwound;
+  thread->unwound = NULL;
+  if (! state_fetch_pc (state))
+    {
+      if (process->callbacks->thread_detach)
+	process->callbacks->thread_detach (thread, thread->callbacks_arg);
+      free_states (state);
+      return -1;
+    }
+  do
+    {
+      int err = callback (state, arg);
+      if (err != DWARF_CB_OK)
+	{
+	  if (process->callbacks->thread_detach)
+	    process->callbacks->thread_detach (thread, thread->callbacks_arg);
+	  free_states (state);
+	  return err;
+	}
+      __libdwfl_frame_unwind (state);
+      Dwfl_Frame *next = state->unwound;
+      /* The old frame is no longer needed.  */
+      free (state);
+      state = next;
+    }
+  while (state && state->pc_state == DWFL_FRAME_STATE_PC_SET);
+
+  Dwfl_Error err = dwfl_errno ();
+  if (process->callbacks->thread_detach)
+    process->callbacks->thread_detach (thread, thread->callbacks_arg);
+  if (state == NULL || state->pc_state == DWFL_FRAME_STATE_ERROR)
+    {
+      free_states (state);
+      __libdwfl_seterrno (err);
+      return -1;
+    }
+  assert (state->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
+  free_states (state);
+  return 0;
+}
+INTDEF(dwfl_thread_getframes)
diff --git a/libdwfl/dwfl_frame_pc.c b/libdwfl/dwfl_frame_pc.c
new file mode 100644
index 0000000..296c815
--- /dev/null
+++ b/libdwfl/dwfl_frame_pc.c
@@ -0,0 +1,64 @@
+/* Get return address register value for frame.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+bool
+dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
+{
+  assert (state->pc_state == DWFL_FRAME_STATE_PC_SET);
+  *pc = state->pc;
+  ebl_normalize_pc (state->thread->process->ebl, pc);
+  if (isactivation)
+    {
+      /* Bottom frame?  */
+      if (state->initial_frame)
+	*isactivation = true;
+      /* *ISACTIVATION is logical union of whether current or previous frame
+	 state is SIGNAL_FRAME.  */
+      else if (state->signal_frame)
+	*isactivation = true;
+      else
+	{
+	  /* If the previous frame has unwound unsuccessfully just silently do
+	     not consider it could be a SIGNAL_FRAME.  */
+	  __libdwfl_frame_unwind (state);
+	  if (state->unwound == NULL
+	      || state->unwound->pc_state != DWFL_FRAME_STATE_PC_SET)
+	    *isactivation = false;
+	  else
+	    *isactivation = state->unwound->signal_frame;
+	}
+    }
+  return true;
+}
+INTDEF (dwfl_frame_pc)
diff --git a/libdwfl/dwfl_frame_regs.c b/libdwfl/dwfl_frame_regs.c
new file mode 100644
index 0000000..a4bd388
--- /dev/null
+++ b/libdwfl/dwfl_frame_regs.c
@@ -0,0 +1,73 @@
+/* Get Dwarf Frame state from modules present in DWFL.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+bool
+dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg,
+			     unsigned nregs, const Dwarf_Word *regs)
+{
+  Dwfl_Frame *state = thread->unwound;
+  assert (state && state->unwound == NULL);
+  assert (state->initial_frame);
+  for (unsigned regno = firstreg; regno < firstreg + nregs; regno++)
+    if (! __libdwfl_frame_reg_set (state, regno, regs[regno - firstreg]))
+      {
+	__libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+	return false;
+      }
+  return true;
+}
+INTDEF(dwfl_thread_state_registers)
+
+void
+dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc)
+{
+  Dwfl_Frame *state = thread->unwound;
+  assert (state && state->unwound == NULL);
+  assert (state->initial_frame);
+  state->pc = pc;
+  state->pc_state = DWFL_FRAME_STATE_PC_SET;
+}
+INTDEF(dwfl_thread_state_register_pc)
+
+int
+dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val)
+{
+  int res = __libdwfl_frame_reg_get (state, regno, val);
+  if (res == -1)
+      __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+  else if (res == 1)
+      __libdwfl_seterrno (DWFL_E_REGISTER_VAL_UNKNOWN);
+  return res;
+}
+INTDEF(dwfl_frame_reg)
diff --git a/libdwfl/dwfl_getdwarf.c b/libdwfl/dwfl_getdwarf.c
new file mode 100644
index 0000000..edd088e
--- /dev/null
+++ b/libdwfl/dwfl_getdwarf.c
@@ -0,0 +1,63 @@
+/* Iterate through modules to fetch Dwarf information.
+   Copyright (C) 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+struct module_callback_info
+{
+  int (*callback) (Dwfl_Module *, void **,
+		   const char *, Dwarf_Addr,
+		   Dwarf *, Dwarf_Addr, void *);
+  void *arg;
+};
+
+static int
+module_callback (Dwfl_Module *mod, void **userdata,
+		 const char *name, Dwarf_Addr start, void *arg)
+{
+  const struct module_callback_info *info = arg;
+  Dwarf_Addr bias = 0;
+  Dwarf *dw = INTUSE(dwfl_module_getdwarf) (mod, &bias);
+  return (*info->callback) (mod, userdata, name, start, dw, bias, info->arg);
+}
+
+ptrdiff_t
+dwfl_getdwarf (Dwfl *dwfl,
+	       int (*callback) (Dwfl_Module *, void **,
+				const char *, Dwarf_Addr,
+				Dwarf *, Dwarf_Addr, void *),
+	       void *arg,
+	       ptrdiff_t offset)
+{
+  struct module_callback_info info = { callback, arg };
+  return INTUSE(dwfl_getmodules) (dwfl, &module_callback, &info, offset);
+}
diff --git a/libdwfl/dwfl_getmodules.c b/libdwfl/dwfl_getmodules.c
new file mode 100644
index 0000000..243cb04
--- /dev/null
+++ b/libdwfl/dwfl_getmodules.c
@@ -0,0 +1,96 @@
+/* Iterate through modules.
+   Copyright (C) 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+ptrdiff_t
+dwfl_getmodules (Dwfl *dwfl,
+		 int (*callback) (Dwfl_Module *, void **,
+				  const char *, Dwarf_Addr, void *),
+		 void *arg,
+		 ptrdiff_t offset)
+{
+  if (dwfl == NULL)
+    return -1;
+
+  /* We iterate through the linked list when it's all we have.
+     But continuing from an offset is slow that way.  So when
+     DWFL->lookup_module is populated, we can instead keep our
+     place by jumping directly into the array.  Since the actions
+     of a callback could cause it to get populated, we must
+     choose the style of place-holder when we return an offset,
+     and we encode the choice in the low bits of that value.  */
+
+  Dwfl_Module *m = dwfl->modulelist;
+
+  if ((offset & 3) == 1)
+    {
+      offset >>= 2;
+      for (ptrdiff_t pos = 0; pos < offset; ++pos)
+	if (m == NULL)
+	  return -1;
+	else
+	  m = m->next;
+    }
+  else if (((offset & 3) == 2) && likely (dwfl->lookup_module != NULL))
+    {
+      offset >>= 2;
+
+      if ((size_t) offset - 1 == dwfl->lookup_elts)
+	return 0;
+
+      if (unlikely ((size_t) offset - 1 > dwfl->lookup_elts))
+	return -1;
+
+      m = dwfl->lookup_module[offset - 1];
+      if (unlikely (m == NULL))
+	return -1;
+    }
+  else if (offset != 0)
+    {
+      __libdwfl_seterrno (DWFL_E_BADSTROFF);
+      return -1;
+    }
+
+  while (m != NULL)
+    {
+      int ok = (*callback) (MODCB_ARGS (m), arg);
+      ++offset;
+      m = m->next;
+      if (ok != DWARF_CB_OK)
+	return ((dwfl->lookup_module == NULL) ? ((offset << 2) | 1)
+		: (((m == NULL ? (ptrdiff_t) dwfl->lookup_elts + 1
+		     : m->segment + 1) << 2) | 2));
+    }
+  return 0;
+}
+INTDEF (dwfl_getmodules)
diff --git a/libdwfl/dwfl_getsrc.c b/libdwfl/dwfl_getsrc.c
new file mode 100644
index 0000000..d853aed
--- /dev/null
+++ b/libdwfl/dwfl_getsrc.c
@@ -0,0 +1,40 @@
+/* Find source location for PC address.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwfl_Line *
+dwfl_getsrc (Dwfl *dwfl, Dwarf_Addr addr)
+{
+  return INTUSE(dwfl_module_getsrc) (INTUSE(dwfl_addrmodule) (dwfl, addr),
+				     addr);
+}
diff --git a/libdwfl/dwfl_getsrclines.c b/libdwfl/dwfl_getsrclines.c
new file mode 100644
index 0000000..1ce78fc
--- /dev/null
+++ b/libdwfl/dwfl_getsrclines.c
@@ -0,0 +1,52 @@
+/* Fetch source line information for CU.
+   Copyright (C) 2005, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+int
+dwfl_getsrclines (Dwarf_Die *cudie, size_t *nlines)
+{
+  struct dwfl_cu *cu = (struct dwfl_cu *) cudie;
+
+  if (cu->lines == NULL)
+    {
+      Dwfl_Error error = __libdwfl_cu_getsrclines (cu);
+      if (error != DWFL_E_NOERROR)
+	{
+	  __libdwfl_seterrno (error);
+	  return -1;
+	}
+    }
+
+  *nlines = cu->die.cu->lines->nlines;
+  return 0;
+}
diff --git a/libdwfl/dwfl_line_comp_dir.c b/libdwfl/dwfl_line_comp_dir.c
new file mode 100644
index 0000000..77c3fdf
--- /dev/null
+++ b/libdwfl/dwfl_line_comp_dir.c
@@ -0,0 +1,47 @@
+/* Get information from a source line record returned by libdwfl.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <dwarf.h>
+
+const char *
+dwfl_line_comp_dir (Dwfl_Line *line)
+{
+  if (line == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu = dwfl_linecu (line);
+  Dwarf_Attribute attr_mem;
+  return INTUSE(dwarf_formstring) (INTUSE(dwarf_attr) (&cu->die,
+						       DW_AT_comp_dir,
+						       &attr_mem));
+}
diff --git a/libdwfl/dwfl_linecu.c b/libdwfl/dwfl_linecu.c
new file mode 100644
index 0000000..2043b17
--- /dev/null
+++ b/libdwfl/dwfl_linecu.c
@@ -0,0 +1,45 @@
+/* Fetch the module containing a source line record returned by libdwfl.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+#undef dwfl_linecu
+
+Dwarf_Die *
+dwfl_linecu (Dwfl_Line *line)
+{
+  if (line == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu = dwfl_linecu_inline (line);
+  return &cu->die;
+}
diff --git a/libdwfl/dwfl_lineinfo.c b/libdwfl/dwfl_lineinfo.c
new file mode 100644
index 0000000..85c4b31
--- /dev/null
+++ b/libdwfl/dwfl_lineinfo.c
@@ -0,0 +1,65 @@
+/* Get information from a source line record returned by libdwfl.
+   Copyright (C) 2005-2010, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "libdwP.h"
+
+const char *
+dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr, int *linep, int *colp,
+	       Dwarf_Word *mtime, Dwarf_Word *length)
+{
+  if (line == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu = dwfl_linecu (line);
+  const Dwarf_Line *info = &cu->die.cu->lines->info[line->idx];
+
+  if (addr != NULL)
+    *addr = dwfl_adjusted_dwarf_addr (cu->mod, info->addr);
+  if (linep != NULL)
+    *linep = info->line;
+  if (colp != NULL)
+    *colp = info->column;
+
+  if (unlikely (info->file >= info->files->nfiles))
+    {
+      __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
+      return NULL;
+    }
+
+  struct Dwarf_Fileinfo_s *file = &info->files->info[info->file];
+  if (mtime != NULL)
+    *mtime = file->mtime;
+  if (length != NULL)
+    *length = file->length;
+  return file->name;
+}
diff --git a/libdwfl/dwfl_linemodule.c b/libdwfl/dwfl_linemodule.c
new file mode 100644
index 0000000..d243f0d
--- /dev/null
+++ b/libdwfl/dwfl_linemodule.c
@@ -0,0 +1,42 @@
+/* Fetch the module containing a source line record returned by libdwfl.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwfl_Module *
+dwfl_linemodule (Dwfl_Line *line)
+{
+  if (line == NULL)
+    return NULL;
+
+  return dwfl_linecu (line)->mod;
+}
diff --git a/libdwfl/dwfl_module.c b/libdwfl/dwfl_module.c
new file mode 100644
index 0000000..c4d872d
--- /dev/null
+++ b/libdwfl/dwfl_module.c
@@ -0,0 +1,242 @@
+/* Maintenance of module list in libdwfl.
+   Copyright (C) 2005, 2006, 2007, 2008, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "cfi.h"
+#include <search.h>
+
+static void
+free_cu (struct dwfl_cu *cu)
+{
+  if (cu->lines != NULL)
+    free (cu->lines);
+  free (cu);
+}
+
+static void
+nofree (void *arg __attribute__ ((unused)))
+{
+}
+
+static void
+free_file (struct dwfl_file *file)
+{
+  free (file->name);
+
+  /* Close the fd only on the last reference.  */
+  if (file->elf != NULL && elf_end (file->elf) == 0 && file->fd != -1)
+    close (file->fd);
+}
+
+void
+internal_function
+__libdwfl_module_free (Dwfl_Module *mod)
+{
+  if (mod->lazy_cu_root != NULL)
+    tdestroy (mod->lazy_cu_root, nofree);
+
+  if (mod->aranges != NULL)
+    free (mod->aranges);
+
+  if (mod->cu != NULL)
+    {
+      for (size_t i = 0; i < mod->ncu; ++i)
+	free_cu (mod->cu[i]);
+      free (mod->cu);
+    }
+
+  /* We might have primed the Dwarf_CFI ebl cache with our own ebl
+     in __libdwfl_set_cfi. Make sure we don't free it twice.  */
+  if (mod->eh_cfi != NULL)
+    {
+      if (mod->eh_cfi->ebl != NULL && mod->eh_cfi->ebl == mod->ebl)
+	mod->eh_cfi->ebl = NULL;
+      dwarf_cfi_end (mod->eh_cfi);
+    }
+
+  if (mod->dwarf_cfi != NULL)
+    {
+      if (mod->dwarf_cfi->ebl != NULL && mod->dwarf_cfi->ebl == mod->ebl)
+	mod->dwarf_cfi->ebl = NULL;
+      /* We don't need to explicitly destroy the dwarf_cfi.
+	 That will be done by dwarf_end.  */
+    }
+
+  if (mod->dw != NULL)
+    {
+      INTUSE(dwarf_end) (mod->dw);
+      if (mod->alt != NULL)
+	{
+	  INTUSE(dwarf_end) (mod->alt);
+	  if (mod->alt_elf != NULL)
+	    elf_end (mod->alt_elf);
+	  if (mod->alt_fd != -1)
+	    close (mod->alt_fd);
+	}
+    }
+
+  if (mod->ebl != NULL)
+    ebl_closebackend (mod->ebl);
+
+  if (mod->debug.elf != mod->main.elf)
+    free_file (&mod->debug);
+  free_file (&mod->main);
+  free_file (&mod->aux_sym);
+
+  if (mod->build_id_bits != NULL)
+    free (mod->build_id_bits);
+
+  if (mod->reloc_info != NULL)
+    free (mod->reloc_info);
+
+  free (mod->name);
+  free (mod->elfpath);
+  free (mod);
+}
+
+void
+dwfl_report_begin_add (Dwfl *dwfl __attribute__ ((unused)))
+{
+  /* The lookup table will be cleared on demand, there is nothing we need
+     to do here.  */
+}
+INTDEF (dwfl_report_begin_add)
+
+void
+dwfl_report_begin (Dwfl *dwfl)
+{
+  /* Clear the segment lookup table.  */
+  dwfl->lookup_elts = 0;
+
+  for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
+    m->gc = true;
+
+  dwfl->offline_next_address = OFFLINE_REDZONE;
+}
+INTDEF (dwfl_report_begin)
+
+static inline Dwfl_Module *
+use (Dwfl_Module *mod, Dwfl_Module **tailp, Dwfl *dwfl)
+{
+  mod->next = *tailp;
+  *tailp = mod;
+
+  if (unlikely (dwfl->lookup_module != NULL))
+    {
+      free (dwfl->lookup_module);
+      dwfl->lookup_module = NULL;
+    }
+
+  return mod;
+}
+
+/* Report that a module called NAME spans addresses [START, END).
+   Returns the module handle, either existing or newly allocated,
+   or returns a null pointer for an allocation error.  */
+Dwfl_Module *
+dwfl_report_module (Dwfl *dwfl, const char *name,
+		    GElf_Addr start, GElf_Addr end)
+{
+  Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
+
+  for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
+    {
+      if (m->low_addr == start && m->high_addr == end
+	  && !strcmp (m->name, name))
+	{
+	  /* This module is still here.  Move it to the place in the list
+	     after the last module already reported.  */
+	  *prevp = m->next;
+	  m->gc = false;
+	  return use (m, tailp, dwfl);
+	}
+
+      if (! m->gc)
+	tailp = &m->next;
+    }
+
+  Dwfl_Module *mod = calloc (1, sizeof *mod);
+  if (mod == NULL)
+    goto nomem;
+
+  mod->name = strdup (name);
+  if (mod->name == NULL)
+    {
+      free (mod);
+    nomem:
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return NULL;
+    }
+
+  mod->low_addr = start;
+  mod->high_addr = end;
+  mod->dwfl = dwfl;
+
+  return use (mod, tailp, dwfl);
+}
+INTDEF (dwfl_report_module)
+
+
+/* Finish reporting the current set of modules to the library.
+   If REMOVED is not null, it's called for each module that
+   existed before but was not included in the current report.
+   Returns a nonzero return value from the callback.
+   DWFL cannot be used until this function has returned zero.  */
+int
+dwfl_report_end (Dwfl *dwfl,
+		 int (*removed) (Dwfl_Module *, void *,
+				 const char *, Dwarf_Addr,
+				 void *arg),
+		 void *arg)
+{
+  Dwfl_Module **tailp = &dwfl->modulelist;
+  while (*tailp != NULL)
+    {
+      Dwfl_Module *m = *tailp;
+      if (m->gc && removed != NULL)
+	{
+	  int result = (*removed) (MODCB_ARGS (m), arg);
+	  if (result != 0)
+	    return result;
+	}
+      if (m->gc)
+	{
+	  *tailp = m->next;
+	  __libdwfl_module_free (m);
+	}
+      else
+	tailp = &m->next;
+    }
+
+  return 0;
+}
+INTDEF (dwfl_report_end)
diff --git a/libdwfl/dwfl_module_addrdie.c b/libdwfl/dwfl_module_addrdie.c
new file mode 100644
index 0000000..b44ec13
--- /dev/null
+++ b/libdwfl/dwfl_module_addrdie.c
@@ -0,0 +1,49 @@
+/* Fetch the CU DIE for a PC address in a given module.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwarf_Die *
+dwfl_module_addrdie (Dwfl_Module *mod, Dwarf_Addr addr, Dwarf_Addr *bias)
+{
+  if (INTUSE(dwfl_module_getdwarf) (mod, bias) == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu;
+  Dwfl_Error error = __libdwfl_addrcu (mod, addr, &cu);
+  if (likely (error == DWFL_E_NOERROR))
+    return &cu->die;
+
+  __libdwfl_seterrno (error);
+  return NULL;
+}
+INTDEF (dwfl_module_addrdie)
diff --git a/libdwfl/dwfl_module_addrname.c b/libdwfl/dwfl_module_addrname.c
new file mode 100644
index 0000000..3142b3e
--- /dev/null
+++ b/libdwfl/dwfl_module_addrname.c
@@ -0,0 +1,42 @@
+/* Find debugging and symbol information for a module in libdwfl.
+   Copyright (C) 2005, 2006, 2007, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+const char *
+dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr addr)
+{
+  GElf_Off off;
+  GElf_Sym sym;
+  return INTUSE(dwfl_module_addrinfo) (mod, addr, &off, &sym,
+				       NULL, NULL, NULL);
+}
diff --git a/libdwfl/dwfl_module_addrsym.c b/libdwfl/dwfl_module_addrsym.c
new file mode 100644
index 0000000..2336b60
--- /dev/null
+++ b/libdwfl/dwfl_module_addrsym.c
@@ -0,0 +1,335 @@
+/* Find debugging and symbol information for a module in libdwfl.
+   Copyright (C) 2005-2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+struct search_state
+{
+  Dwfl_Module *mod;
+  GElf_Addr addr;
+
+  GElf_Sym *closest_sym;
+  bool adjust_st_value;
+  GElf_Word addr_shndx;
+  Elf *addr_symelf;
+
+  /* Keep track of the closest symbol we have seen so far.
+     Here we store only symbols with nonzero st_size.  */
+  const char *closest_name;
+  GElf_Addr closest_value;
+  GElf_Word closest_shndx;
+  Elf *closest_elf;
+
+  /* Keep track of an eligible symbol with st_size == 0 as a fallback.  */
+  const char *sizeless_name;
+  GElf_Sym sizeless_sym;
+  GElf_Addr sizeless_value;
+  GElf_Word sizeless_shndx;
+  Elf *sizeless_elf;
+
+  /* Keep track of the lowest address a relevant sizeless symbol could have.  */
+  GElf_Addr min_label;
+};
+
+/* Return true iff we consider ADDR to lie in the same section as SYM.  */
+static inline bool
+same_section (struct search_state *state,
+	      GElf_Addr value, Elf *symelf, GElf_Word shndx)
+{
+  /* For absolute symbols and the like, only match exactly.  */
+  if (shndx >= SHN_LORESERVE)
+    return value == state->addr;
+
+  /* If value might not be st_value, the shndx of the symbol might
+      not match the section of the value. Explicitly look both up.  */
+  if (! state->adjust_st_value)
+    {
+      Dwarf_Addr v;
+      if (state->addr_shndx == SHN_UNDEF)
+        {
+          v = state->addr;
+          state->addr_shndx = __libdwfl_find_section_ndx (state->mod, &v);
+        }
+
+      v = value;
+      return state->addr_shndx == __libdwfl_find_section_ndx (state->mod, &v);
+    }
+
+  /* Figure out what section ADDR lies in.  */
+  if (state->addr_shndx == SHN_UNDEF || state->addr_symelf != symelf)
+    {
+      GElf_Addr mod_addr = dwfl_deadjust_st_value (state->mod, symelf,
+						   state->addr);
+      Elf_Scn *scn = NULL;
+      state->addr_shndx = SHN_ABS;
+      state->addr_symelf = symelf;
+      while ((scn = elf_nextscn (symelf, scn)) != NULL)
+        {
+          GElf_Shdr shdr_mem;
+          GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+          if (likely (shdr != NULL)
+              && mod_addr >= shdr->sh_addr
+              && mod_addr < shdr->sh_addr + shdr->sh_size)
+            {
+              state->addr_shndx = elf_ndxscn (scn);
+              break;
+            }
+        }
+    }
+
+  return shndx == state->addr_shndx && state->addr_symelf == symelf;
+}
+
+/* Return GELF_ST_BIND as higher-is-better integer.  */
+static inline int
+binding_value (const GElf_Sym *symp)
+{
+  switch (GELF_ST_BIND (symp->st_info))
+    {
+    case STB_GLOBAL:
+      return 3;
+    case STB_WEAK:
+      return 2;
+    case STB_LOCAL:
+      return 1;
+    default:
+      return 0;
+    }
+}
+
+/* Try one symbol and associated value from the search table.  */
+static inline void
+try_sym_value (struct search_state *state,
+               GElf_Addr value, GElf_Sym *sym,
+               const char *name, GElf_Word shndx,
+               Elf *elf, bool resolved)
+{
+    /* Even if we don't choose this symbol, its existence excludes
+       any sizeless symbol (assembly label) that is below its upper
+       bound.  */
+    if (value + sym->st_size > state->min_label)
+      state->min_label = value + sym->st_size;
+
+    if (sym->st_size == 0 || state->addr - value < sym->st_size)
+      {
+	/* This symbol is a better candidate than the current one
+	   if it's closer to ADDR or is global when it was local.  */
+	if (state->closest_name == NULL
+	    || state->closest_value < value
+	    || binding_value (state->closest_sym) < binding_value (sym))
+	  {
+	    if (sym->st_size != 0)
+	      {
+		*state->closest_sym = *sym;
+		state->closest_value = value;
+		state->closest_shndx = shndx;
+		state->closest_elf = elf;
+		state->closest_name = name;
+	      }
+	    else if (state->closest_name == NULL
+		     && value >= state->min_label
+		     && same_section (state, value,
+				      resolved ? state->mod->main.elf : elf,
+				      shndx))
+	      {
+		/* Handwritten assembly symbols sometimes have no
+		   st_size.  If no symbol with proper size includes
+		   the address, we'll use the closest one that is in
+		   the same section as ADDR.  */
+		state->sizeless_sym = *sym;
+		state->sizeless_value = value;
+		state->sizeless_shndx = shndx;
+		state->sizeless_elf = elf;
+		state->sizeless_name = name;
+	      }
+	  }
+	/* When the beginning of its range is no closer,
+	   the end of its range might be.  Otherwise follow
+	   GELF_ST_BIND preference.  If all are equal prefer
+	   the first symbol found.  */
+	else if (sym->st_size != 0
+		 && state->closest_value == value
+		 && ((state->closest_sym->st_size > sym->st_size
+		      && (binding_value (state->closest_sym)
+			  <= binding_value (sym)))
+		     || (state->closest_sym->st_size >= sym->st_size
+			 && (binding_value (state->closest_sym)
+			     < binding_value (sym)))))
+	  {
+	    *state->closest_sym = *sym;
+	    state->closest_value = value;
+	    state->closest_shndx = shndx;
+	    state->closest_elf = elf;
+	    state->closest_name = name;
+	  }
+      }
+}
+
+/* Look through the symbol table for a matching symbol.  */
+static inline void
+search_table (struct search_state *state, int start, int end)
+{
+      for (int i = start; i < end; ++i)
+	{
+	  GElf_Sym sym;
+	  GElf_Addr value;
+	  GElf_Word shndx;
+	  Elf *elf;
+	  bool resolved;
+	  const char *name = __libdwfl_getsym (state->mod, i, &sym, &value,
+					       &shndx, &elf, NULL,
+					       &resolved,
+					       state->adjust_st_value);
+	  if (name != NULL && name[0] != '\0'
+	      && sym.st_shndx != SHN_UNDEF
+	      && value <= state->addr
+	      && GELF_ST_TYPE (sym.st_info) != STT_SECTION
+	      && GELF_ST_TYPE (sym.st_info) != STT_FILE
+	      && GELF_ST_TYPE (sym.st_info) != STT_TLS)
+	    {
+	      try_sym_value (state, value, &sym, name, shndx, elf, resolved);
+
+	      /* If this is an addrinfo variant and the value could be
+		 resolved then also try matching the (adjusted) st_value.  */
+	      if (resolved && state->mod->e_type != ET_REL)
+		{
+		  GElf_Addr adjusted_st_value;
+		  adjusted_st_value = dwfl_adjusted_st_value (state->mod, elf,
+							      sym.st_value);
+		  if (value != adjusted_st_value
+		      && adjusted_st_value <= state->addr)
+		    try_sym_value (state, adjusted_st_value, &sym, name, shndx,
+				   elf, false);
+		}
+	    }
+	}
+}
+
+/* Returns the name of the symbol "closest" to ADDR.
+   Never returns symbols at addresses above ADDR.
+
+   Wrapper for old dwfl_module_addrsym and new dwfl_module_addrinfo.
+   adjust_st_value set to true returns adjusted SYM st_value, set to false
+   it will not adjust SYM at all, but does match against resolved values.   */
+static const char *
+__libdwfl_addrsym (Dwfl_Module *_mod, GElf_Addr _addr, GElf_Off *off,
+		   GElf_Sym *_closest_sym, GElf_Word *shndxp,
+		   Elf **elfp, Dwarf_Addr *biasp, bool _adjust_st_value)
+{
+  int syments = INTUSE(dwfl_module_getsymtab) (_mod);
+  if (syments < 0)
+    return NULL;
+
+  struct search_state state =
+    {
+      .addr = _addr,
+      .mod = _mod,
+      .closest_sym = _closest_sym,
+      .adjust_st_value = _adjust_st_value,
+      .addr_shndx = SHN_UNDEF,
+      .addr_symelf = NULL,
+      .closest_name = NULL,
+      .closest_value = 0,
+      .closest_shndx = SHN_UNDEF,
+      .closest_elf = NULL,
+      .sizeless_name = NULL,
+      .sizeless_sym = { 0, 0, 0, 0, 0, SHN_UNDEF },
+      .sizeless_value = 0,
+      .sizeless_shndx = SHN_UNDEF,
+      .sizeless_elf = NULL,
+      .min_label = 0
+    };
+
+  /* First go through global symbols.  mod->first_global and
+     mod->aux_first_global are setup by dwfl_module_getsymtab to the
+     index of the first global symbol in those symbol tables.  Both
+     are non-zero when the table exist, except when there is only a
+     dynsym table loaded through phdrs, then first_global is zero and
+     there will be no auxiliary table.  All symbols with local binding
+     come first in the symbol table, then all globals.  The zeroth,
+     null entry, in the auxiliary table is skipped if there is a main
+     table.  */
+  int first_global = INTUSE (dwfl_module_getsymtab_first_global) (state.mod);
+  if (first_global < 0)
+    return NULL;
+  search_table (&state, first_global == 0 ? 1 : first_global, syments);
+
+  /* If we found nothing searching the global symbols, then try the locals.
+     Unless we have a global sizeless symbol that matches exactly.  */
+  if (state.closest_name == NULL && first_global > 1
+      && (state.sizeless_name == NULL || state.sizeless_value != state.addr))
+    search_table (&state, 1, first_global);
+
+  /* If we found no proper sized symbol to use, fall back to the best
+     candidate sizeless symbol we found, if any.  */
+  if (state.closest_name == NULL
+      && state.sizeless_name != NULL
+      && state.sizeless_value >= state.min_label)
+    {
+      *state.closest_sym = state.sizeless_sym;
+      state.closest_value = state.sizeless_value;
+      state.closest_shndx = state.sizeless_shndx;
+      state.closest_elf = state.sizeless_elf;
+      state.closest_name = state.sizeless_name;
+    }
+
+  *off = state.addr - state.closest_value;
+
+  if (shndxp != NULL)
+    *shndxp = state.closest_shndx;
+  if (elfp != NULL)
+    *elfp = state.closest_elf;
+  if (biasp != NULL)
+    *biasp = dwfl_adjusted_st_value (state.mod, state.closest_elf, 0);
+  return state.closest_name;
+}
+
+
+const char *
+dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr addr,
+		     GElf_Sym *closest_sym, GElf_Word *shndxp)
+{
+  GElf_Off off;
+  return __libdwfl_addrsym (mod, addr, &off, closest_sym, shndxp,
+			    NULL, NULL, true);
+}
+INTDEF (dwfl_module_addrsym)
+
+const char
+*dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address,
+		       GElf_Off *offset, GElf_Sym *sym,
+		       GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *bias)
+{
+  return __libdwfl_addrsym (mod, address, offset, sym, shndxp, elfp, bias,
+			    false);
+}
+INTDEF (dwfl_module_addrinfo)
diff --git a/libdwfl/dwfl_module_build_id.c b/libdwfl/dwfl_module_build_id.c
new file mode 100644
index 0000000..0c198f2
--- /dev/null
+++ b/libdwfl/dwfl_module_build_id.c
@@ -0,0 +1,121 @@
+/* Return build ID information for a module.
+   Copyright (C) 2007-2010, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+static int
+found_build_id (Dwfl_Module *mod, bool set,
+		const void *bits, int len, GElf_Addr vaddr)
+{
+  if (!set)
+    /* When checking bits, we do not compare VADDR because the
+       address found in a debuginfo file may not match the main
+       file as modified by prelink.  */
+    return 1 + (mod->build_id_len == len
+		&& !memcmp (bits, mod->build_id_bits, len));
+
+  void *copy = malloc (len);
+  if (unlikely (copy == NULL))
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return -1;
+    }
+
+  mod->build_id_bits = memcpy (copy, bits, len);
+  mod->build_id_vaddr = vaddr;
+  mod->build_id_len = len;
+  return len;
+}
+
+int
+internal_function
+__libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
+{
+  const void *build_id_bits;
+  GElf_Addr build_id_elfaddr;
+  int build_id_len;
+
+  /* For mod == NULL use dwelf_elf_gnu_build_id directly.  */
+  assert (mod != NULL);
+
+  int result = __libdwfl_find_elf_build_id (mod, elf, &build_id_bits,
+					    &build_id_elfaddr, &build_id_len);
+  if (result <= 0)
+    return result;
+
+  GElf_Addr build_id_vaddr = build_id_elfaddr + (build_id_elfaddr != 0
+						 ? mod->main_bias : 0);
+  return found_build_id (mod, set, build_id_bits, build_id_len, build_id_vaddr);
+}
+
+NEW_VERSION (dwfl_module_build_id, ELFUTILS_0.138)
+int
+dwfl_module_build_id (Dwfl_Module *mod,
+		      const unsigned char **bits, GElf_Addr *vaddr)
+{
+  if (mod == NULL)
+    return -1;
+
+  if (mod->build_id_len == 0 && mod->main.elf != NULL)
+    {
+      /* We have the file, but have not examined it yet.  */
+      int result = __libdwfl_find_build_id (mod, true, mod->main.elf);
+      if (result <= 0)
+	{
+	  mod->build_id_len = -1;	/* Cache negative result.  */
+	  return result;
+	}
+    }
+
+  if (mod->build_id_len <= 0)
+    return 0;
+
+  *bits = mod->build_id_bits;
+  *vaddr = mod->build_id_vaddr;
+  return mod->build_id_len;
+}
+NEW_INTDEF (dwfl_module_build_id)
+
+#ifdef SYMBOL_VERSIONING
+COMPAT_VERSION (dwfl_module_build_id, ELFUTILS_0.130, vaddr_at_end)
+
+int
+_compat_vaddr_at_end_dwfl_module_build_id (Dwfl_Module *mod,
+					   const unsigned char **bits,
+					   GElf_Addr *vaddr)
+{
+  int result = INTUSE(dwfl_module_build_id) (mod, bits, vaddr);
+  if (result > 0)
+    *vaddr += (result + 3) & -4;
+  return result;
+}
+#endif
diff --git a/libdwfl/dwfl_module_dwarf_cfi.c b/libdwfl/dwfl_module_dwarf_cfi.c
new file mode 100644
index 0000000..05a14f7
--- /dev/null
+++ b/libdwfl/dwfl_module_dwarf_cfi.c
@@ -0,0 +1,73 @@
+/* Find DWARF CFI for a module in libdwfl.
+   Copyright (C) 2009-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "cfi.h"
+
+Dwarf_CFI *
+internal_function
+__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot, Dwarf_CFI *cfi)
+{
+  if (cfi != NULL && cfi->ebl == NULL)
+    {
+      Dwfl_Error error = __libdwfl_module_getebl (mod);
+      if (error == DWFL_E_NOERROR)
+	cfi->ebl = mod->ebl;
+      else
+	{
+	  if (slot == &mod->eh_cfi)
+	    INTUSE(dwarf_cfi_end) (cfi);
+	  __libdwfl_seterrno (error);
+	  return NULL;
+	}
+    }
+
+  return *slot = cfi;
+}
+
+Dwarf_CFI *
+dwfl_module_dwarf_cfi (Dwfl_Module *mod, Dwarf_Addr *bias)
+{
+  if (mod == NULL)
+    return NULL;
+
+  if (mod->dwarf_cfi != NULL)
+    {
+      *bias = dwfl_adjusted_dwarf_addr (mod, 0);
+      return mod->dwarf_cfi;
+    }
+
+  return __libdwfl_set_cfi (mod, &mod->dwarf_cfi,
+			    INTUSE(dwarf_getcfi)
+			    (INTUSE(dwfl_module_getdwarf) (mod, bias)));
+}
+INTDEF (dwfl_module_dwarf_cfi)
diff --git a/libdwfl/dwfl_module_eh_cfi.c b/libdwfl/dwfl_module_eh_cfi.c
new file mode 100644
index 0000000..aac6657
--- /dev/null
+++ b/libdwfl/dwfl_module_eh_cfi.c
@@ -0,0 +1,59 @@
+/* Find EH CFI for a module in libdwfl.
+   Copyright (C) 2009-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "cfi.h"
+
+Dwarf_CFI *
+dwfl_module_eh_cfi (Dwfl_Module *mod, Dwarf_Addr *bias)
+{
+  if (mod == NULL)
+    return NULL;
+
+  if (mod->eh_cfi != NULL)
+    {
+      *bias = dwfl_adjusted_address (mod, 0);
+      return mod->eh_cfi;
+    }
+
+  __libdwfl_getelf (mod);
+  if (mod->elferr != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (mod->elferr);
+      return NULL;
+    }
+
+  *bias = dwfl_adjusted_address (mod, 0);
+  return __libdwfl_set_cfi (mod, &mod->eh_cfi,
+			    INTUSE(dwarf_getcfi_elf) (mod->main.elf));
+}
+INTDEF (dwfl_module_eh_cfi)
diff --git a/libdwfl/dwfl_module_getdwarf.c b/libdwfl/dwfl_module_getdwarf.c
new file mode 100644
index 0000000..6f98c02
--- /dev/null
+++ b/libdwfl/dwfl_module_getdwarf.c
@@ -0,0 +1,1509 @@
+/* Find debugging and symbol information for a module in libdwfl.
+   Copyright (C) 2005-2012, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <inttypes.h>
+#include <fcntl.h>
+#include <string.h>
+#include "libdwP.h"	/* DWARF_E_* values are here.  */
+#include "libelfP.h"
+#include "system.h"
+
+static inline Dwfl_Error
+open_elf_file (Elf **elf, int *fd, char **name)
+{
+  if (*elf == NULL)
+    {
+      /* CBFAIL uses errno if it's set, so clear it first in case we don't
+	 set it with an open failure below.  */
+      errno = 0;
+
+      /* If there was a pre-primed file name left that the callback left
+	 behind, try to open that file name.  */
+      if (*fd < 0 && *name != NULL)
+	*fd = TEMP_FAILURE_RETRY (open (*name, O_RDONLY));
+
+      if (*fd < 0)
+	return CBFAIL;
+
+      return __libdw_open_file (fd, elf, true, false);
+    }
+  else if (unlikely (elf_kind (*elf) != ELF_K_ELF))
+    {
+      elf_end (*elf);
+      *elf = NULL;
+      close (*fd);
+      *fd = -1;
+      return DWFL_E_BADELF;
+    }
+
+  /* Elf file already open and looks fine.  */
+  return DWFL_E_NOERROR;
+}
+
+/* Open libelf FILE->fd and compute the load base of ELF as loaded in MOD.
+   When we return success, FILE->elf and FILE->vaddr are set up.  */
+static inline Dwfl_Error
+open_elf (Dwfl_Module *mod, struct dwfl_file *file)
+{
+  Dwfl_Error error = open_elf_file (&file->elf, &file->fd, &file->name);
+  if (error != DWFL_E_NOERROR)
+    return error;
+
+  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (file->elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+    elf_error:
+      elf_end (file->elf);
+      file->elf = NULL;
+      close (file->fd);
+      file->fd = -1;
+      return DWFL_E (LIBELF, elf_errno ());
+    }
+
+  if (ehdr->e_type != ET_REL)
+    {
+      /* In any non-ET_REL file, we compute the "synchronization address".
+
+	 We start with the address at the end of the first PT_LOAD
+	 segment.  When prelink converts REL to RELA in an ET_DYN
+	 file, it expands the space between the beginning of the
+	 segment and the actual code/data addresses.  Since that
+	 change wasn't made in the debug file, the distance from
+	 p_vaddr to an address of interest (in an st_value or DWARF
+	 data) now differs between the main and debug files.  The
+	 distance from address_sync to an address of interest remains
+	 consistent.
+
+	 If there are no section headers at all (full stripping), then
+	 the end of the first segment is a valid synchronization address.
+	 This cannot happen in a prelinked file, since prelink itself
+	 relies on section headers for prelinking and for undoing it.
+	 (If you do full stripping on a prelinked file, then you get what
+	 you deserve--you can neither undo the prelinking, nor expect to
+	 line it up with a debug file separated before prelinking.)
+
+	 However, when prelink processes an ET_EXEC file, it can do
+	 something different.  There it juggles the "special" sections
+	 (SHT_DYNSYM et al) to make space for the additional prelink
+	 special sections.  Sometimes it will do this by moving a special
+	 section like .dynstr after the real program sections in the first
+	 PT_LOAD segment--i.e. to the end.  That changes the end address of
+	 the segment, so it no longer lines up correctly and is not a valid
+	 synchronization address to use.  Because of this, we need to apply
+	 a different prelink-savvy means to discover the synchronization
+	 address when there is a separate debug file and a prelinked main
+	 file.  That is done in find_debuginfo, below.  */
+
+      size_t phnum;
+      if (unlikely (elf_getphdrnum (file->elf, &phnum) != 0))
+	goto elf_error;
+
+      file->vaddr = file->address_sync = 0;
+      for (size_t i = 0; i < phnum; ++i)
+	{
+	  GElf_Phdr ph_mem;
+	  GElf_Phdr *ph = gelf_getphdr (file->elf, i, &ph_mem);
+	  if (unlikely (ph == NULL))
+	    goto elf_error;
+	  if (ph->p_type == PT_LOAD)
+	    {
+	      file->vaddr = ph->p_vaddr & -ph->p_align;
+	      file->address_sync = ph->p_vaddr + ph->p_memsz;
+	      break;
+	    }
+	}
+    }
+
+  /* We only want to set the module e_type explicitly once, derived from
+     the main ELF file.  (It might be changed for the kernel, because
+     that is special - see below.)  open_elf is always called first for
+     the main ELF file, because both find_dw and find_symtab call
+     __libdwfl_getelf first to open the main file.  So don't let debug
+     or aux files override the module e_type.  The kernel heuristic
+     below could otherwise trigger for non-kernel/non-main files, since
+     their phdrs might not match the actual load addresses.  */
+  if (file == &mod->main)
+    {
+      mod->e_type = ehdr->e_type;
+
+      /* Relocatable Linux kernels are ET_EXEC but act like ET_DYN.  */
+      if (mod->e_type == ET_EXEC && file->vaddr != mod->low_addr)
+	mod->e_type = ET_DYN;
+    }
+  else
+    assert (mod->main.elf != NULL);
+
+  return DWFL_E_NOERROR;
+}
+
+/* We have an authoritative build ID for this module MOD, so don't use
+   a file by name that doesn't match that ID.  */
+static void
+mod_verify_build_id (Dwfl_Module *mod)
+{
+  assert (mod->build_id_len > 0);
+
+  switch (__builtin_expect (__libdwfl_find_build_id (mod, false,
+						     mod->main.elf), 2))
+    {
+    case 2:
+      /* Build ID matches as it should. */
+      return;
+
+    case -1:			/* ELF error.  */
+      mod->elferr = INTUSE(dwfl_errno) ();
+      break;
+
+    case 0:			/* File has no build ID note.  */
+    case 1:			/* FIle has a build ID that does not match.  */
+      mod->elferr = DWFL_E_WRONG_ID_ELF;
+      break;
+
+    default:
+      abort ();
+    }
+
+  /* We get here when it was the right ELF file.  Clear it out.  */
+  elf_end (mod->main.elf);
+  mod->main.elf = NULL;
+  if (mod->main.fd >= 0)
+    {
+      close (mod->main.fd);
+      mod->main.fd = -1;
+    }
+}
+
+/* Find the main ELF file for this module and open libelf on it.
+   When we return success, MOD->main.elf and MOD->main.bias are set up.  */
+void
+internal_function
+__libdwfl_getelf (Dwfl_Module *mod)
+{
+  if (mod->main.elf != NULL	/* Already done.  */
+      || mod->elferr != DWFL_E_NOERROR)	/* Cached failure.  */
+    return;
+
+  mod->main.fd = (*mod->dwfl->callbacks->find_elf) (MODCB_ARGS (mod),
+						    &mod->main.name,
+						    &mod->main.elf);
+  const bool fallback = mod->main.elf == NULL && mod->main.fd < 0;
+  mod->elferr = open_elf (mod, &mod->main);
+  if (mod->elferr != DWFL_E_NOERROR)
+    return;
+
+  if (!mod->main.valid)
+    {
+      /* Clear any explicitly reported build ID, just in case it was wrong.
+	 We'll fetch it from the file when asked.  */
+      free (mod->build_id_bits);
+      mod->build_id_bits = NULL;
+      mod->build_id_len = 0;
+    }
+  else if (fallback)
+    mod_verify_build_id (mod);
+
+  mod->main_bias = mod->e_type == ET_REL ? 0 : mod->low_addr - mod->main.vaddr;
+}
+
+static inline void
+consider_shdr (GElf_Addr interp,
+               GElf_Word sh_type,
+               GElf_Xword sh_flags,
+               GElf_Addr sh_addr,
+               GElf_Xword sh_size,
+               GElf_Addr *phighest)
+{
+  if ((sh_flags & SHF_ALLOC)
+      && ((sh_type == SHT_PROGBITS && sh_addr != interp)
+          || sh_type == SHT_NOBITS))
+    {
+      const GElf_Addr sh_end = sh_addr + sh_size;
+      if (sh_end > *phighest)
+        *phighest = sh_end;
+    }
+}
+
+/* If the main file might have been prelinked, then we need to
+   discover the correct synchronization address between the main and
+   debug files.  Because of prelink's section juggling, we cannot rely
+   on the address_sync computed from PT_LOAD segments (see open_elf).
+
+   We will attempt to discover a synchronization address based on the
+   section headers instead.  But finding a section address that is
+   safe to use requires identifying which sections are SHT_PROGBITS.
+   We can do that in the main file, but in the debug file all the
+   allocated sections have been transformed into SHT_NOBITS so we have
+   lost the means to match them up correctly.
+
+   The only method left to us is to decode the .gnu.prelink_undo
+   section in the prelinked main file.  This shows what the sections
+   looked like before prelink juggled them--when they still had a
+   direct correspondence to the debug file.  */
+static Dwfl_Error
+find_prelink_address_sync (Dwfl_Module *mod, struct dwfl_file *file)
+{
+  /* The magic section is only identified by name.  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (mod->main.elf, &shstrndx) < 0)
+    return DWFL_E_LIBELF;
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (shdr == NULL))
+	return DWFL_E_LIBELF;
+      if (shdr->sh_type == SHT_PROGBITS
+	  && !(shdr->sh_flags & SHF_ALLOC)
+	  && shdr->sh_name != 0)
+	{
+	  const char *secname = elf_strptr (mod->main.elf, shstrndx,
+					    shdr->sh_name);
+	  if (unlikely (secname == NULL))
+	    return DWFL_E_LIBELF;
+	  if (!strcmp (secname, ".gnu.prelink_undo"))
+	    break;
+	}
+    }
+
+  if (scn == NULL)
+    /* There was no .gnu.prelink_undo section.  */
+    return DWFL_E_NOERROR;
+
+  Elf_Data *undodata = elf_rawdata (scn, NULL);
+  if (unlikely (undodata == NULL))
+    return DWFL_E_LIBELF;
+
+  /* Decode the section.  It consists of the original ehdr, phdrs,
+     and shdrs (but omits section 0).  */
+
+  union
+  {
+    Elf32_Ehdr e32;
+    Elf64_Ehdr e64;
+  } ehdr;
+  Elf_Data dst =
+    {
+      .d_buf = &ehdr,
+      .d_size = sizeof ehdr,
+      .d_type = ELF_T_EHDR,
+      .d_version = EV_CURRENT
+    };
+  Elf_Data src = *undodata;
+  src.d_size = gelf_fsize (mod->main.elf, ELF_T_EHDR, 1, EV_CURRENT);
+  src.d_type = ELF_T_EHDR;
+  if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
+			       elf_getident (mod->main.elf, NULL)[EI_DATA])
+		== NULL))
+    return DWFL_E_LIBELF;
+
+  size_t shentsize = gelf_fsize (mod->main.elf, ELF_T_SHDR, 1, EV_CURRENT);
+  size_t phentsize = gelf_fsize (mod->main.elf, ELF_T_PHDR, 1, EV_CURRENT);
+
+  uint_fast16_t phnum;
+  uint_fast16_t shnum;
+  if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
+    {
+      if (ehdr.e32.e_shentsize != shentsize
+	  || ehdr.e32.e_phentsize != phentsize)
+	return DWFL_E_BAD_PRELINK;
+      phnum = ehdr.e32.e_phnum;
+      shnum = ehdr.e32.e_shnum;
+    }
+  else
+    {
+      if (ehdr.e64.e_shentsize != shentsize
+	  || ehdr.e64.e_phentsize != phentsize)
+	return DWFL_E_BAD_PRELINK;
+      phnum = ehdr.e64.e_phnum;
+      shnum = ehdr.e64.e_shnum;
+    }
+
+  /* Since prelink does not store the zeroth section header in the undo
+     section, it cannot support SHN_XINDEX encoding.  */
+  if (unlikely (shnum >= SHN_LORESERVE) || unlikely(shnum == 0)
+      || unlikely (undodata->d_size != (src.d_size
+					+ phnum * phentsize
+					+ (shnum - 1) * shentsize)))
+    return DWFL_E_BAD_PRELINK;
+
+  --shnum;
+
+  /* We look at the allocated SHT_PROGBITS (or SHT_NOBITS) sections.  (Most
+     every file will have some SHT_PROGBITS sections, but it's possible to
+     have one with nothing but .bss, i.e. SHT_NOBITS.)  The special sections
+     that can be moved around have different sh_type values--except for
+     .interp, the section that became the PT_INTERP segment.  So we exclude
+     the SHT_PROGBITS section whose address matches the PT_INTERP p_vaddr.
+     For this reason, we must examine the phdrs first to find PT_INTERP.  */
+
+  GElf_Addr main_interp = 0;
+  {
+    size_t main_phnum;
+    if (unlikely (elf_getphdrnum (mod->main.elf, &main_phnum)))
+      return DWFL_E_LIBELF;
+    for (size_t i = 0; i < main_phnum; ++i)
+      {
+	GElf_Phdr phdr;
+	if (unlikely (gelf_getphdr (mod->main.elf, i, &phdr) == NULL))
+	  return DWFL_E_LIBELF;
+	if (phdr.p_type == PT_INTERP)
+	  {
+	    main_interp = phdr.p_vaddr;
+	    break;
+	  }
+      }
+  }
+
+  src.d_buf += src.d_size;
+  src.d_type = ELF_T_PHDR;
+  src.d_size = phnum * phentsize;
+
+  GElf_Addr undo_interp = 0;
+  bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
+  {
+    size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
+    if (unlikely (phnum > SIZE_MAX / phdr_size))
+      return DWFL_E_NOMEM;
+    const size_t phdrs_bytes = phnum * phdr_size;
+    void *phdrs = malloc (phdrs_bytes);
+    if (unlikely (phdrs == NULL))
+      return DWFL_E_NOMEM;
+    dst.d_buf = phdrs;
+    dst.d_size = phdrs_bytes;
+    if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
+				 ehdr.e32.e_ident[EI_DATA]) == NULL))
+      {
+	free (phdrs);
+	return DWFL_E_LIBELF;
+      }
+    if (class32)
+      {
+	Elf32_Phdr (*p32)[phnum] = phdrs;
+	for (uint_fast16_t i = 0; i < phnum; ++i)
+	  if ((*p32)[i].p_type == PT_INTERP)
+	    {
+	      undo_interp = (*p32)[i].p_vaddr;
+	      break;
+	    }
+      }
+    else
+      {
+	Elf64_Phdr (*p64)[phnum] = phdrs;
+	for (uint_fast16_t i = 0; i < phnum; ++i)
+	  if ((*p64)[i].p_type == PT_INTERP)
+	    {
+	      undo_interp = (*p64)[i].p_vaddr;
+	      break;
+	    }
+      }
+    free (phdrs);
+  }
+
+  if (unlikely ((main_interp == 0) != (undo_interp == 0)))
+    return DWFL_E_BAD_PRELINK;
+
+  src.d_buf += src.d_size;
+  src.d_type = ELF_T_SHDR;
+  src.d_size = gelf_fsize (mod->main.elf, ELF_T_SHDR, shnum, EV_CURRENT);
+
+  size_t shdr_size = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr);
+  if (unlikely (shnum > SIZE_MAX / shdr_size))
+    return DWFL_E_NOMEM;
+  const size_t shdrs_bytes = shnum * shdr_size;
+  void *shdrs = malloc (shdrs_bytes);
+  if (unlikely (shdrs == NULL))
+    return DWFL_E_NOMEM;
+  dst.d_buf = shdrs;
+  dst.d_size = shdrs_bytes;
+  if (unlikely (gelf_xlatetom (mod->main.elf, &dst, &src,
+			       ehdr.e32.e_ident[EI_DATA]) == NULL))
+    {
+      free (shdrs);
+      return DWFL_E_LIBELF;
+    }
+
+  /* Now we can look at the original section headers of the main file
+     before it was prelinked.  First we'll apply our method to the main
+     file sections as they are after prelinking, to calculate the
+     synchronization address of the main file.  Then we'll apply that
+     same method to the saved section headers, to calculate the matching
+     synchronization address of the debug file.
+
+     The method is to consider SHF_ALLOC sections that are either
+     SHT_PROGBITS or SHT_NOBITS, excluding the section whose sh_addr
+     matches the PT_INTERP p_vaddr.  The special sections that can be
+     moved by prelink have other types, except for .interp (which
+     becomes PT_INTERP).  The "real" sections cannot move as such, but
+     .bss can be split into .dynbss and .bss, with the total memory
+     image remaining the same but being spread across the two sections.
+     So we consider the highest section end, which still matches up.  */
+
+  GElf_Addr highest;
+
+  highest = 0;
+  scn = NULL;
+  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
+    {
+      GElf_Shdr sh_mem;
+      GElf_Shdr *sh = gelf_getshdr (scn, &sh_mem);
+      if (unlikely (sh == NULL))
+	{
+	  free (shdrs);
+	  return DWFL_E_LIBELF;
+	}
+      consider_shdr (main_interp, sh->sh_type, sh->sh_flags,
+		     sh->sh_addr, sh->sh_size, &highest);
+    }
+  if (highest > mod->main.vaddr)
+    {
+      mod->main.address_sync = highest;
+
+      highest = 0;
+      if (class32)
+	{
+	  Elf32_Shdr (*s32)[shnum] = shdrs;
+	  for (size_t i = 0; i < shnum; ++i)
+	    consider_shdr (undo_interp, (*s32)[i].sh_type,
+			   (*s32)[i].sh_flags, (*s32)[i].sh_addr,
+			   (*s32)[i].sh_size, &highest);
+	}
+      else
+	{
+	  Elf64_Shdr (*s64)[shnum] = shdrs;
+	  for (size_t i = 0; i < shnum; ++i)
+	    consider_shdr (undo_interp, (*s64)[i].sh_type,
+			   (*s64)[i].sh_flags, (*s64)[i].sh_addr,
+			   (*s64)[i].sh_size, &highest);
+	}
+
+      if (highest > file->vaddr)
+	file->address_sync = highest;
+      else
+	{
+	  free (shdrs);
+	  return DWFL_E_BAD_PRELINK;
+	}
+    }
+
+  free (shdrs);
+
+  return DWFL_E_NOERROR;
+}
+
+/* Find the separate debuginfo file for this module and open libelf on it.
+   When we return success, MOD->debug is set up.  */
+static Dwfl_Error
+find_debuginfo (Dwfl_Module *mod)
+{
+  if (mod->debug.elf != NULL)
+    return DWFL_E_NOERROR;
+
+  GElf_Word debuglink_crc = 0;
+  const char *debuglink_file;
+  debuglink_file = INTUSE(dwelf_elf_gnu_debuglink) (mod->main.elf,
+						    &debuglink_crc);
+
+  mod->debug.fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
+							   mod->main.name,
+							   debuglink_file,
+							   debuglink_crc,
+							   &mod->debug.name);
+  Dwfl_Error result = open_elf (mod, &mod->debug);
+  if (result == DWFL_E_NOERROR && mod->debug.address_sync != 0)
+    result = find_prelink_address_sync (mod, &mod->debug);
+  return result;
+}
+
+/* Try to find the alternative debug link for the given DWARF and set
+   it if found.  Only called when mod->dw is already setup but still
+   might need an alternative (dwz multi) debug file.  filename is either
+   the main or debug name from which the Dwarf was created. */
+static void
+find_debug_altlink (Dwfl_Module *mod, const char *filename)
+{
+  assert (mod->dw != NULL);
+
+  const char *altname;
+  const void *build_id;
+  ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
+							       &altname,
+							       &build_id);
+
+  if (build_id_len > 0)
+    {
+      /* We could store altfile in the module, but don't really need it.  */
+      char *altfile = NULL;
+      mod->alt_fd = (*mod->dwfl->callbacks->find_debuginfo) (MODCB_ARGS (mod),
+							     filename,
+							     altname,
+							     0,
+							     &altfile);
+
+      /* The (internal) callbacks might just set mod->alt_elf directly
+	 because they open the Elf anyway for sanity checking.
+	 Otherwise open either the given file name or use the fd
+	 returned.  */
+      Dwfl_Error error = open_elf_file (&mod->alt_elf, &mod->alt_fd,
+					&altfile);
+      if (error == DWFL_E_NOERROR)
+	{
+	  mod->alt = INTUSE(dwarf_begin_elf) (mod->alt_elf,
+					      DWARF_C_READ, NULL);
+	  if (mod->alt == NULL)
+	    {
+	      elf_end (mod->alt_elf);
+	      mod->alt_elf = NULL;
+	      close (mod->alt_fd);
+	      mod->alt_fd = -1;
+	    }
+	  else
+	    dwarf_setalt (mod->dw, mod->alt);
+	}
+
+      free (altfile); /* See above, we don't really need it.  */
+    }
+}
+
+/* Try to find a symbol table in FILE.
+   Returns DWFL_E_NOERROR if a proper one is found.
+   Returns DWFL_E_NO_SYMTAB if not, but still sets results for SHT_DYNSYM.  */
+static Dwfl_Error
+load_symtab (struct dwfl_file *file, struct dwfl_file **symfile,
+	     Elf_Scn **symscn, Elf_Scn **xndxscn,
+	     size_t *syments, int *first_global, GElf_Word *strshndx)
+{
+  bool symtab = false;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (file->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr != NULL)
+	switch (shdr->sh_type)
+	  {
+	  case SHT_SYMTAB:
+	    if (shdr->sh_entsize == 0)
+	      break;
+	    symtab = true;
+	    *symscn = scn;
+	    *symfile = file;
+	    *strshndx = shdr->sh_link;
+	    *syments = shdr->sh_size / shdr->sh_entsize;
+	    *first_global = shdr->sh_info;
+	    if (*xndxscn != NULL)
+	      return DWFL_E_NOERROR;
+	    break;
+
+	  case SHT_DYNSYM:
+	    if (symtab)
+	      break;
+	    /* Use this if need be, but keep looking for SHT_SYMTAB.  */
+	    if (shdr->sh_entsize == 0)
+	      break;
+	    *symscn = scn;
+	    *symfile = file;
+	    *strshndx = shdr->sh_link;
+	    *syments = shdr->sh_size / shdr->sh_entsize;
+	    *first_global = shdr->sh_info;
+	    break;
+
+	  case SHT_SYMTAB_SHNDX:
+	    *xndxscn = scn;
+	    if (symtab)
+	      return DWFL_E_NOERROR;
+	    break;
+
+	  default:
+	    break;
+	  }
+    }
+
+  if (symtab)
+    /* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
+    return DWFL_E_NOERROR;
+
+  /* We found no SHT_SYMTAB, so any SHT_SYMTAB_SHNDX was bogus.
+     We might have found an SHT_DYNSYM and set *SYMSCN et al though.  */
+  *xndxscn = NULL;
+  return DWFL_E_NO_SYMTAB;
+}
+
+
+/* Translate addresses into file offsets.
+   OFFS[*] start out zero and remain zero if unresolved.  */
+static void
+find_offsets (Elf *elf, GElf_Addr main_bias, size_t phnum, size_t n,
+	      GElf_Addr addrs[n], GElf_Off offs[n])
+{
+  size_t unsolved = n;
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
+	for (size_t j = 0; j < n; ++j)
+	  if (offs[j] == 0
+	      && addrs[j] >= phdr->p_vaddr + main_bias
+	      && addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz)
+	    {
+	      offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset;
+	      if (--unsolved == 0)
+		break;
+	    }
+    }
+}
+
+/* Various addresses we might want to pull from the dynamic segment.  */
+enum
+{
+  i_symtab,
+  i_strtab,
+  i_hash,
+  i_gnu_hash,
+  i_max
+};
+
+/* Translate pointers into file offsets.  ADJUST is either zero
+   in case the dynamic segment wasn't adjusted or mod->main_bias.
+   Will set mod->symfile if the translated offsets can be used as
+   symbol table.  */
+static void
+translate_offs (GElf_Addr adjust,
+                Dwfl_Module *mod, size_t phnum,
+                GElf_Addr addrs[i_max], GElf_Xword strsz,
+                GElf_Ehdr *ehdr)
+{
+  GElf_Off offs[i_max] = { 0, };
+  find_offsets (mod->main.elf, adjust, phnum, i_max, addrs, offs);
+
+  /* Figure out the size of the symbol table.  */
+  if (offs[i_hash] != 0)
+    {
+      /* In the original format, .hash says the size of .dynsym.  */
+
+      size_t entsz = SH_ENTSIZE_HASH (ehdr);
+      Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
+					     offs[i_hash] + entsz, entsz,
+					     (entsz == 4
+					      ? ELF_T_WORD : ELF_T_XWORD));
+      if (data != NULL)
+	mod->syments = (entsz == 4
+			? *(const GElf_Word *) data->d_buf
+			: *(const GElf_Xword *) data->d_buf);
+    }
+  if (offs[i_gnu_hash] != 0 && mod->syments == 0)
+    {
+      /* In the new format, we can derive it with some work.  */
+
+      const struct
+      {
+        Elf32_Word nbuckets;
+        Elf32_Word symndx;
+        Elf32_Word maskwords;
+        Elf32_Word shift2;
+      } *header;
+
+      Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, offs[i_gnu_hash],
+					     sizeof *header, ELF_T_WORD);
+      if (data != NULL)
+        {
+          header = data->d_buf;
+          Elf32_Word nbuckets = header->nbuckets;
+          Elf32_Word symndx = header->symndx;
+          GElf_Off buckets_at = (offs[i_gnu_hash] + sizeof *header
+				 + (gelf_getclass (mod->main.elf)
+				    * sizeof (Elf32_Word)
+				    * header->maskwords));
+
+          // elf_getdata_rawchunk takes a size_t, make sure it
+          // doesn't overflow.
+#if SIZE_MAX <= UINT32_MAX
+          if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
+            data = NULL;
+          else
+#endif
+            data = elf_getdata_rawchunk (mod->main.elf, buckets_at,
+					   nbuckets * sizeof (Elf32_Word),
+					   ELF_T_WORD);
+	  if (data != NULL && symndx < nbuckets)
+	    {
+	      const Elf32_Word *const buckets = data->d_buf;
+	      Elf32_Word maxndx = symndx;
+	      for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
+		if (buckets[bucket] > maxndx)
+		  maxndx = buckets[bucket];
+
+	      GElf_Off hasharr_at = (buckets_at
+				     + nbuckets * sizeof (Elf32_Word));
+	      hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
+	      do
+		{
+		  data = elf_getdata_rawchunk (mod->main.elf,
+					       hasharr_at,
+					       sizeof (Elf32_Word),
+					       ELF_T_WORD);
+		  if (data != NULL
+		      && (*(const Elf32_Word *) data->d_buf & 1u))
+		    {
+		      mod->syments = maxndx + 1;
+		      break;
+		    }
+		  ++maxndx;
+		  hasharr_at += sizeof (Elf32_Word);
+		}
+	      while (data != NULL);
+	    }
+	}
+    }
+  if (offs[i_strtab] > offs[i_symtab] && mod->syments == 0)
+    mod->syments = ((offs[i_strtab] - offs[i_symtab])
+		    / gelf_fsize (mod->main.elf,
+				  ELF_T_SYM, 1, EV_CURRENT));
+
+  if (mod->syments > 0)
+    {
+      mod->symdata = elf_getdata_rawchunk (mod->main.elf,
+					   offs[i_symtab],
+					   gelf_fsize (mod->main.elf,
+						       ELF_T_SYM,
+						       mod->syments,
+						       EV_CURRENT),
+						       ELF_T_SYM);
+      if (mod->symdata != NULL)
+	{
+	  mod->symstrdata = elf_getdata_rawchunk (mod->main.elf,
+						  offs[i_strtab],
+						  strsz,
+						  ELF_T_BYTE);
+	  if (mod->symstrdata == NULL)
+	    mod->symdata = NULL;
+	}
+      if (mod->symdata == NULL)
+	mod->symerr = DWFL_E (LIBELF, elf_errno ());
+      else
+	{
+	  mod->symfile = &mod->main;
+	  mod->symerr = DWFL_E_NOERROR;
+	}
+    }
+}
+
+/* Try to find a dynamic symbol table via phdrs.  */
+static void
+find_dynsym (Dwfl_Module *mod)
+{
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (mod->main.elf, &ehdr_mem);
+
+  size_t phnum;
+  if (unlikely (elf_getphdrnum (mod->main.elf, &phnum) != 0))
+    return;
+
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
+      if (phdr == NULL)
+	break;
+
+      if (phdr->p_type == PT_DYNAMIC)
+	{
+	  /* Examine the dynamic section for the pointers we need.  */
+
+	  Elf_Data *data = elf_getdata_rawchunk (mod->main.elf,
+						 phdr->p_offset, phdr->p_filesz,
+						 ELF_T_DYN);
+	  if (data == NULL)
+	    continue;
+
+	  GElf_Addr addrs[i_max] = { 0, };
+	  GElf_Xword strsz = 0;
+	  size_t n = data->d_size / gelf_fsize (mod->main.elf,
+						ELF_T_DYN, 1, EV_CURRENT);
+	  for (size_t j = 0; j < n; ++j)
+	    {
+	      GElf_Dyn dyn_mem;
+	      GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
+	      if (dyn != NULL)
+		switch (dyn->d_tag)
+		  {
+		  case DT_SYMTAB:
+		    addrs[i_symtab] = dyn->d_un.d_ptr;
+		    continue;
+
+		  case DT_HASH:
+		    addrs[i_hash] = dyn->d_un.d_ptr;
+		    continue;
+
+		  case DT_GNU_HASH:
+		    addrs[i_gnu_hash] = dyn->d_un.d_ptr;
+		    continue;
+
+		  case DT_STRTAB:
+		    addrs[i_strtab] = dyn->d_un.d_ptr;
+		    continue;
+
+		  case DT_STRSZ:
+		    strsz = dyn->d_un.d_val;
+		    continue;
+
+		  default:
+		    continue;
+
+		  case DT_NULL:
+		    break;
+		  }
+	      break;
+	    }
+
+	  /* First try unadjusted, like ELF files from disk, vdso.
+	     Then try for already adjusted dynamic section, like ELF
+	     from remote memory.  */
+	  translate_offs (0, mod, phnum, addrs, strsz, ehdr);
+	  if (mod->symfile == NULL)
+	    translate_offs (mod->main_bias, mod, phnum, addrs, strsz, ehdr);
+
+	  return;
+	}
+    }
+}
+
+
+#if USE_LZMA
+/* Try to find the offset between the main file and .gnu_debugdata.  */
+static bool
+find_aux_address_sync (Dwfl_Module *mod)
+{
+  /* Don't trust the phdrs in the minisymtab elf file to be setup correctly.
+     The address_sync is equal to the main file it is embedded in at first.  */
+  mod->aux_sym.address_sync = mod->main.address_sync;
+
+  /* Adjust address_sync for the difference in entry addresses, attempting to
+     account for ELF relocation changes after aux was split.  */
+  GElf_Ehdr ehdr_main, ehdr_aux;
+  if (unlikely (gelf_getehdr (mod->main.elf, &ehdr_main) == NULL)
+      || unlikely (gelf_getehdr (mod->aux_sym.elf, &ehdr_aux) == NULL))
+    return false;
+  mod->aux_sym.address_sync += ehdr_aux.e_entry - ehdr_main.e_entry;
+
+  /* The shdrs are setup OK to make find_prelink_address_sync () do the right
+     thing, which is possibly more reliable, but it needs .gnu.prelink_undo.  */
+  if (mod->aux_sym.address_sync != 0)
+    return find_prelink_address_sync (mod, &mod->aux_sym) == DWFL_E_NOERROR;
+
+  return true;
+}
+#endif
+
+/* Try to find the auxiliary symbol table embedded in the main elf file
+   section .gnu_debugdata.  Only matters if the symbol information comes
+   from the main file dynsym.  No harm done if not found.  */
+static void
+find_aux_sym (Dwfl_Module *mod __attribute__ ((unused)),
+	      Elf_Scn **aux_symscn __attribute__ ((unused)),
+	      Elf_Scn **aux_xndxscn __attribute__ ((unused)),
+	      GElf_Word *aux_strshndx __attribute__ ((unused)))
+{
+  /* Since a .gnu_debugdata section is compressed using lzma don't do
+     anything unless we have support for that.  */
+#if USE_LZMA
+  Elf *elf = mod->main.elf;
+
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+    return;
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	return;
+
+      const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
+      if (name == NULL)
+	return;
+
+      if (!strcmp (name, ".gnu_debugdata"))
+	break;
+    }
+
+  if (scn == NULL)
+    return;
+
+  /* Found the .gnu_debugdata section.  Uncompress the lzma image and
+     turn it into an ELF image.  */
+  Elf_Data *rawdata = elf_rawdata (scn, NULL);
+  if (rawdata == NULL)
+    return;
+
+  Dwfl_Error error;
+  void *buffer = NULL;
+  size_t size = 0;
+  error = __libdw_unlzma (-1, 0, rawdata->d_buf, rawdata->d_size,
+			  &buffer, &size);
+  if (error == DWFL_E_NOERROR)
+    {
+      if (unlikely (size == 0))
+	free (buffer);
+      else
+	{
+	  mod->aux_sym.elf = elf_memory (buffer, size);
+	  if (mod->aux_sym.elf == NULL)
+	    free (buffer);
+	  else
+	    {
+	      mod->aux_sym.fd = -1;
+	      mod->aux_sym.elf->flags |= ELF_F_MALLOCED;
+	      if (open_elf (mod, &mod->aux_sym) != DWFL_E_NOERROR)
+		return;
+	      if (! find_aux_address_sync (mod))
+		{
+		  elf_end (mod->aux_sym.elf);
+		  mod->aux_sym.elf = NULL;
+		  return;
+		}
+
+	      /* So far, so good. Get minisymtab table data and cache it. */
+	      bool minisymtab = false;
+	      scn = NULL;
+	      while ((scn = elf_nextscn (mod->aux_sym.elf, scn)) != NULL)
+		{
+		  GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
+		  if (shdr != NULL)
+		    switch (shdr->sh_type)
+		      {
+		      case SHT_SYMTAB:
+			if (shdr->sh_entsize == 0)
+			  return;
+			minisymtab = true;
+			*aux_symscn = scn;
+			*aux_strshndx = shdr->sh_link;
+			mod->aux_syments = shdr->sh_size / shdr->sh_entsize;
+			mod->aux_first_global = shdr->sh_info;
+			if (*aux_xndxscn != NULL)
+			  return;
+			break;
+
+		      case SHT_SYMTAB_SHNDX:
+			*aux_xndxscn = scn;
+			if (minisymtab)
+			  return;
+			break;
+
+		      default:
+			break;
+		      }
+		}
+
+	      if (minisymtab)
+		/* We found one, though no SHT_SYMTAB_SHNDX to go with it.  */
+		return;
+
+	      /* We found no SHT_SYMTAB, so everything else is bogus.  */
+	      *aux_xndxscn = NULL;
+	      *aux_strshndx = 0;
+	      mod->aux_syments = 0;
+	      elf_end (mod->aux_sym.elf);
+	      mod->aux_sym.elf = NULL;
+	      return;
+	    }
+	}
+    }
+  else
+    free (buffer);
+#endif
+}
+
+/* Try to find a symbol table in either MOD->main.elf or MOD->debug.elf.  */
+static void
+find_symtab (Dwfl_Module *mod)
+{
+  if (mod->symdata != NULL || mod->aux_symdata != NULL	/* Already done.  */
+      || mod->symerr != DWFL_E_NOERROR) /* Cached previous failure.  */
+    return;
+
+  __libdwfl_getelf (mod);
+  mod->symerr = mod->elferr;
+  if (mod->symerr != DWFL_E_NOERROR)
+    return;
+
+  /* First see if the main ELF file has the debugging information.  */
+  Elf_Scn *symscn = NULL, *xndxscn = NULL;
+  Elf_Scn *aux_symscn = NULL, *aux_xndxscn = NULL;
+  GElf_Word strshndx, aux_strshndx = 0;
+  mod->symerr = load_symtab (&mod->main, &mod->symfile, &symscn,
+			     &xndxscn, &mod->syments, &mod->first_global,
+			     &strshndx);
+  switch (mod->symerr)
+    {
+    default:
+      return;
+
+    case DWFL_E_NOERROR:
+      break;
+
+    case DWFL_E_NO_SYMTAB:
+      /* Now we have to look for a separate debuginfo file.  */
+      mod->symerr = find_debuginfo (mod);
+      switch (mod->symerr)
+	{
+	default:
+	  return;
+
+	case DWFL_E_NOERROR:
+	  mod->symerr = load_symtab (&mod->debug, &mod->symfile, &symscn,
+				     &xndxscn, &mod->syments,
+				     &mod->first_global, &strshndx);
+	  break;
+
+	case DWFL_E_CB:		/* The find_debuginfo hook failed.  */
+	  mod->symerr = DWFL_E_NO_SYMTAB;
+	  break;
+	}
+
+      switch (mod->symerr)
+	{
+	default:
+	  return;
+
+	case DWFL_E_NOERROR:
+	  break;
+
+	case DWFL_E_NO_SYMTAB:
+	  /* There might be an auxiliary table.  */
+	  find_aux_sym (mod, &aux_symscn, &aux_xndxscn, &aux_strshndx);
+
+	  if (symscn != NULL)
+	    {
+	      /* We still have the dynamic symbol table.  */
+	      mod->symerr = DWFL_E_NOERROR;
+	      break;
+	    }
+
+	  if (aux_symscn != NULL)
+	    {
+	      /* We still have the auxiliary symbol table.  */
+	      mod->symerr = DWFL_E_NOERROR;
+	      goto aux_cache;
+	    }
+
+	  /* Last ditch, look for dynamic symbols without section headers.  */
+	  find_dynsym (mod);
+	  return;
+	}
+      break;
+    }
+
+  /* This does some sanity checks on the string table section.  */
+  if (elf_strptr (mod->symfile->elf, strshndx, 0) == NULL)
+    {
+    elferr:
+      mod->symdata = NULL;
+      mod->syments = 0;
+      mod->first_global = 0;
+      mod->symerr = DWFL_E (LIBELF, elf_errno ());
+      goto aux_cleanup; /* This cleans up some more and tries find_dynsym.  */
+    }
+
+  /* Cache the data; MOD->syments and MOD->first_global were set
+     above.  If any of the sections is compressed, uncompress it
+     first.  Only the string data section could theoretically be
+     compressed GNU style (as .zdebug_str).  Everything else only ELF
+     gabi style (SHF_COMPRESSED).  */
+
+  Elf_Scn *symstrscn = elf_getscn (mod->symfile->elf, strshndx);
+  if (symstrscn == NULL)
+    goto elferr;
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (symstrscn, &shdr_mem);
+  if (shdr == NULL)
+    goto elferr;
+
+  size_t shstrndx;
+  if (elf_getshdrstrndx (mod->symfile->elf, &shstrndx) < 0)
+    goto elferr;
+
+  const char *sname = elf_strptr (mod->symfile->elf, shstrndx, shdr->sh_name);
+  if (sname == NULL)
+    goto elferr;
+
+  if (startswith (sname, ".zdebug"))
+    /* Try to uncompress, but it might already have been, an error
+       might just indicate, already uncompressed.  */
+    elf_compress_gnu (symstrscn, 0, 0);
+
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+    if (elf_compress (symstrscn, 0, 0) < 0)
+      goto elferr;
+
+  mod->symstrdata = elf_getdata (symstrscn, NULL);
+  if (mod->symstrdata == NULL || mod->symstrdata->d_buf == NULL)
+    goto elferr;
+
+  if (xndxscn == NULL)
+    mod->symxndxdata = NULL;
+  else
+    {
+      shdr = gelf_getshdr (xndxscn, &shdr_mem);
+      if (shdr == NULL)
+	goto elferr;
+
+      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	if (elf_compress (xndxscn, 0, 0) < 0)
+	  goto elferr;
+
+      mod->symxndxdata = elf_getdata (xndxscn, NULL);
+      if (mod->symxndxdata == NULL || mod->symxndxdata->d_buf == NULL)
+	goto elferr;
+    }
+
+  shdr = gelf_getshdr (symscn, &shdr_mem);
+  if (shdr == NULL)
+    goto elferr;
+
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+    if (elf_compress (symscn, 0, 0) < 0)
+      goto elferr;
+
+  mod->symdata = elf_getdata (symscn, NULL);
+  if (mod->symdata == NULL || mod->symdata->d_buf == NULL)
+    goto elferr;
+
+  // Sanity check number of symbols.
+  shdr = gelf_getshdr (symscn, &shdr_mem);
+  if (shdr == NULL || shdr->sh_entsize == 0
+      || mod->syments > mod->symdata->d_size / shdr->sh_entsize
+      || (size_t) mod->first_global > mod->syments)
+    goto elferr;
+
+  /* Cache any auxiliary symbol info, when it fails, just ignore aux_sym.  */
+  if (aux_symscn != NULL)
+    {
+  aux_cache:
+      /* This does some sanity checks on the string table section.  */
+      if (elf_strptr (mod->aux_sym.elf, aux_strshndx, 0) == NULL)
+	{
+	aux_cleanup:
+	  mod->aux_syments = 0;
+	  elf_end (mod->aux_sym.elf);
+	  mod->aux_sym.elf = NULL;
+	  /* We thought we had something through shdrs, but it failed...
+	     Last ditch, look for dynamic symbols without section headers.  */
+	  find_dynsym (mod);
+	  return;
+	}
+
+      Elf_Scn *aux_strscn = elf_getscn (mod->aux_sym.elf, aux_strshndx);
+      if (aux_strscn == NULL)
+	goto elferr;
+
+      shdr = gelf_getshdr (aux_strscn, &shdr_mem);
+      if (shdr == NULL)
+	goto elferr;
+
+      size_t aux_shstrndx;
+      if (elf_getshdrstrndx (mod->aux_sym.elf, &aux_shstrndx) < 0)
+	goto elferr;
+
+      sname = elf_strptr (mod->aux_sym.elf, aux_shstrndx,
+				      shdr->sh_name);
+      if (sname == NULL)
+	goto elferr;
+
+      if (startswith (sname, ".zdebug"))
+	/* Try to uncompress, but it might already have been, an error
+	   might just indicate, already uncompressed.  */
+	elf_compress_gnu (aux_strscn, 0, 0);
+
+      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	if (elf_compress (aux_strscn, 0, 0) < 0)
+	  goto elferr;
+
+      mod->aux_symstrdata = elf_getdata (aux_strscn, NULL);
+      if (mod->aux_symstrdata == NULL || mod->aux_symstrdata->d_buf == NULL)
+	goto aux_cleanup;
+
+      if (aux_xndxscn == NULL)
+	mod->aux_symxndxdata = NULL;
+      else
+	{
+	  shdr = gelf_getshdr (aux_xndxscn, &shdr_mem);
+	  if (shdr == NULL)
+	    goto elferr;
+
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    if (elf_compress (aux_xndxscn, 0, 0) < 0)
+	      goto elferr;
+
+	  mod->aux_symxndxdata = elf_getdata (aux_xndxscn, NULL);
+	  if (mod->aux_symxndxdata == NULL
+	      || mod->aux_symxndxdata->d_buf == NULL)
+	    goto aux_cleanup;
+	}
+
+      shdr = gelf_getshdr (aux_symscn, &shdr_mem);
+      if (shdr == NULL)
+	goto elferr;
+
+      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	if (elf_compress (aux_symscn, 0, 0) < 0)
+	  goto elferr;
+
+      mod->aux_symdata = elf_getdata (aux_symscn, NULL);
+      if (mod->aux_symdata == NULL || mod->aux_symdata->d_buf == NULL)
+	goto aux_cleanup;
+
+      // Sanity check number of aux symbols.
+      shdr = gelf_getshdr (aux_symscn, &shdr_mem);
+      if (mod->aux_syments > mod->aux_symdata->d_size / shdr->sh_entsize
+	  || (size_t) mod->aux_first_global > mod->aux_syments)
+	goto aux_cleanup;
+    }
+}
+
+
+/* Try to open a libebl backend for MOD.  */
+Dwfl_Error
+internal_function
+__libdwfl_module_getebl (Dwfl_Module *mod)
+{
+  if (mod->ebl == NULL)
+    {
+      __libdwfl_getelf (mod);
+      if (mod->elferr != DWFL_E_NOERROR)
+	return mod->elferr;
+
+      mod->ebl = ebl_openbackend (mod->main.elf);
+      if (mod->ebl == NULL)
+	return DWFL_E_LIBEBL;
+    }
+  return DWFL_E_NOERROR;
+}
+
+/* Try to start up libdw on DEBUGFILE.  */
+static Dwfl_Error
+load_dw (Dwfl_Module *mod, struct dwfl_file *debugfile)
+{
+  if (mod->e_type == ET_REL && !debugfile->relocated)
+    {
+      const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
+
+      /* The debugging sections have to be relocated.  */
+      if (cb->section_address == NULL)
+	return DWFL_E_NOREL;
+
+      Dwfl_Error error = __libdwfl_module_getebl (mod);
+      if (error != DWFL_E_NOERROR)
+	return error;
+
+      find_symtab (mod);
+      Dwfl_Error result = mod->symerr;
+      if (result == DWFL_E_NOERROR)
+	result = __libdwfl_relocate (mod, debugfile->elf, true);
+      if (result != DWFL_E_NOERROR)
+	return result;
+    }
+
+  mod->dw = INTUSE(dwarf_begin_elf) (debugfile->elf, DWARF_C_READ, NULL);
+  if (mod->dw == NULL)
+    {
+      int err = INTUSE(dwarf_errno) ();
+      return err == DWARF_E_NO_DWARF ? DWFL_E_NO_DWARF : DWFL_E (LIBDW, err);
+    }
+
+  /* Do this after dwarf_begin_elf has a chance to process the fd.  */
+  if (mod->e_type == ET_REL && !debugfile->relocated)
+    {
+      /* Don't keep the file descriptors around.  */
+      if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
+	{
+	  close (mod->main.fd);
+	  mod->main.fd = -1;
+	}
+      if (debugfile->fd != -1 && elf_cntl (debugfile->elf, ELF_C_FDREAD) == 0)
+	{
+	  close (debugfile->fd);
+	  debugfile->fd = -1;
+	}
+    }
+
+  /* We might have already closed the fd when we asked dwarf_begin_elf to
+     create an Dwarf.  Help out a little in case we need to find an alt,
+     dwo, or dwp file later.  */
+  if (mod->dw->elfpath == NULL && mod->elfpath != NULL
+      && debugfile == &mod->main)
+    {
+      mod->dw->elfpath = strdup (mod->elfpath);
+      __libdw_set_debugdir (mod->dw);
+    }
+
+  /* Until we have iterated through all CU's, we might do lazy lookups.  */
+  mod->lazycu = 1;
+
+  return DWFL_E_NOERROR;
+}
+
+/* Try to start up libdw on either the main file or the debuginfo file.  */
+static void
+find_dw (Dwfl_Module *mod)
+{
+  if (mod->dw != NULL		/* Already done.  */
+      || mod->dwerr != DWFL_E_NOERROR) /* Cached previous failure.  */
+    return;
+
+  __libdwfl_getelf (mod);
+  mod->dwerr = mod->elferr;
+  if (mod->dwerr != DWFL_E_NOERROR)
+    return;
+
+  /* First see if the main ELF file has the debugging information.  */
+  mod->dwerr = load_dw (mod, &mod->main);
+  switch (mod->dwerr)
+    {
+    case DWFL_E_NOERROR:
+      mod->debug.elf = mod->main.elf;
+      mod->debug.address_sync = mod->main.address_sync;
+
+      /* The Dwarf might need an alt debug file, find that now after
+	 everything about the debug file has been setup (the
+	 find_debuginfo callback might need it).  */
+      find_debug_altlink (mod, mod->main.name);
+      return;
+
+    case DWFL_E_NO_DWARF:
+      break;
+
+    default:
+      goto canonicalize;
+    }
+
+  /* Now we have to look for a separate debuginfo file.  */
+  mod->dwerr = find_debuginfo (mod);
+  switch (mod->dwerr)
+    {
+    case DWFL_E_NOERROR:
+      mod->dwerr = load_dw (mod, &mod->debug);
+      if (mod->dwerr == DWFL_E_NOERROR)
+	{
+	  /* The Dwarf might need an alt debug file, find that now after
+	     everything about the debug file has been setup (the
+	     find_debuginfo callback might need it).  */
+	  find_debug_altlink (mod, mod->debug.name);
+	  return;
+	}
+
+      break;
+
+    case DWFL_E_CB:		/* The find_debuginfo hook failed.  */
+      mod->dwerr = DWFL_E_NO_DWARF;
+      return;
+
+    default:
+      break;
+    }
+
+ canonicalize:
+  mod->dwerr = __libdwfl_canon_error (mod->dwerr);
+}
+
+Dwarf *
+dwfl_module_getdwarf (Dwfl_Module *mod, Dwarf_Addr *bias)
+{
+  if (mod == NULL)
+    return NULL;
+
+  find_dw (mod);
+  if (mod->dwerr == DWFL_E_NOERROR)
+    {
+      /* If dwfl_module_getelf was used previously, then partial apply
+	 relocation to miscellaneous sections in the debug file too.  */
+      if (mod->e_type == ET_REL
+	  && mod->main.relocated && ! mod->debug.relocated)
+	{
+	  mod->debug.relocated = true;
+	  if (mod->debug.elf != mod->main.elf)
+	    (void) __libdwfl_relocate (mod, mod->debug.elf, false);
+	}
+
+      *bias = dwfl_adjusted_dwarf_addr (mod, 0);
+      return mod->dw;
+    }
+
+  __libdwfl_seterrno (mod->dwerr);
+  return NULL;
+}
+INTDEF (dwfl_module_getdwarf)
+
+int
+dwfl_module_getsymtab (Dwfl_Module *mod)
+{
+  if (mod == NULL)
+    return -1;
+
+  find_symtab (mod);
+  if (mod->symerr == DWFL_E_NOERROR)
+    /* We will skip the auxiliary zero entry if there is another one.  */
+    return (mod->syments + mod->aux_syments
+	    - (mod->syments > 0 && mod->aux_syments > 0 ? 1 : 0));
+
+  __libdwfl_seterrno (mod->symerr);
+  return -1;
+}
+INTDEF (dwfl_module_getsymtab)
+
+int
+dwfl_module_getsymtab_first_global (Dwfl_Module *mod)
+{
+  if (mod == NULL)
+    return -1;
+
+  find_symtab (mod);
+  if (mod->symerr == DWFL_E_NOERROR)
+    {
+      /* All local symbols should come before all global symbols.  If
+	 we have an auxiliary table make sure all the main locals come
+	 first, then all aux locals, then all main globals and finally all
+	 aux globals.  And skip the auxiliary table zero undefined
+	 entry.  */
+      int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
+      return mod->first_global + mod->aux_first_global - skip_aux_zero;
+    }
+
+  __libdwfl_seterrno (mod->symerr);
+  return -1;
+}
+INTDEF (dwfl_module_getsymtab_first_global)
diff --git a/libdwfl/dwfl_module_getelf.c b/libdwfl/dwfl_module_getelf.c
new file mode 100644
index 0000000..6358de4
--- /dev/null
+++ b/libdwfl/dwfl_module_getelf.c
@@ -0,0 +1,71 @@
+/* Find debugging and symbol information for a module in libdwfl.
+   Copyright (C) 2009-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Elf *
+dwfl_module_getelf (Dwfl_Module *mod, GElf_Addr *loadbase)
+{
+  if (mod == NULL)
+    return NULL;
+
+  __libdwfl_getelf (mod);
+  if (mod->elferr == DWFL_E_NOERROR)
+    {
+      if (mod->e_type == ET_REL && ! mod->main.relocated)
+	{
+	  /* Before letting them get at the Elf handle,
+	     apply all the relocations we know how to.  */
+
+	  mod->main.relocated = true;
+	  if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR))
+	    {
+	      (void) __libdwfl_relocate (mod, mod->main.elf, false);
+
+	      if (mod->debug.elf == mod->main.elf)
+		mod->debug.relocated = true;
+	      else if (mod->debug.elf != NULL && ! mod->debug.relocated)
+		{
+		  mod->debug.relocated = true;
+		  (void) __libdwfl_relocate (mod, mod->debug.elf, false);
+		}
+	    }
+	}
+
+      *loadbase = dwfl_adjusted_address (mod, 0);
+      return mod->main.elf;
+    }
+
+  __libdwfl_seterrno (mod->elferr);
+  return NULL;
+}
+INTDEF (dwfl_module_getelf)
diff --git a/libdwfl/dwfl_module_getsrc.c b/libdwfl/dwfl_module_getsrc.c
new file mode 100644
index 0000000..73dbf43
--- /dev/null
+++ b/libdwfl/dwfl_module_getsrc.c
@@ -0,0 +1,85 @@
+/* Find source location for PC address in module.
+   Copyright (C) 2005, 2008, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "libdwP.h"
+
+Dwfl_Line *
+dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  Dwarf_Addr bias;
+  if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu;
+  Dwfl_Error error = __libdwfl_addrcu (mod, addr, &cu);
+  if (likely (error == DWFL_E_NOERROR))
+    error = __libdwfl_cu_getsrclines (cu);
+  if (likely (error == DWFL_E_NOERROR))
+    {
+      Dwarf_Lines *lines = cu->die.cu->lines;
+      size_t nlines = lines->nlines;
+      if (nlines > 0)
+	{
+	  /* This is guaranteed for us by libdw read_srclines.  */
+	  assert(lines->info[nlines - 1].end_sequence);
+
+	  /* Now we look at the module-relative address.  */
+	  addr -= bias;
+
+	  /* The lines are sorted by address, so we can use binary search.  */
+	  size_t l = 0, u = nlines - 1;
+	  while (l < u)
+	    {
+	      size_t idx = u - (u - l) / 2;
+	      Dwarf_Line *line = &lines->info[idx];
+	      if (addr < line->addr)
+		u = idx - 1;
+	      else
+		l = idx;
+	    }
+
+	  /* The last line which is less than or equal to addr is what
+	     we want, unless it is the end_sequence which is after the
+	     current line sequence.  */
+	  Dwarf_Line *line = &lines->info[l];
+	  if (! line->end_sequence && line->addr <= addr)
+	    return &cu->lines->idx[l];
+	}
+
+      error = DWFL_E_ADDR_OUTOFRANGE;
+    }
+
+  __libdwfl_seterrno (error);
+  return NULL;
+}
+INTDEF (dwfl_module_getsrc)
diff --git a/libdwfl/dwfl_module_getsrc_file.c b/libdwfl/dwfl_module_getsrc_file.c
new file mode 100644
index 0000000..fc14422
--- /dev/null
+++ b/libdwfl/dwfl_module_getsrc_file.c
@@ -0,0 +1,178 @@
+/* Find matching source locations in a module.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "libdwP.h"
+
+
+static inline const char *
+dwfl_dwarf_line_file (const Dwarf_Line *line)
+{
+  return line->files->info[line->file].name;
+}
+
+static inline Dwarf_Line *
+dwfl_line (const Dwfl_Line *line)
+{
+  return &dwfl_linecu (line)->die.cu->lines->info[line->idx];
+}
+
+static inline const char *
+dwfl_line_file (const Dwfl_Line *line)
+{
+  return dwfl_dwarf_line_file (dwfl_line (line));
+}
+
+int
+dwfl_module_getsrc_file (Dwfl_Module *mod,
+			 const char *fname, int lineno, int column,
+			 Dwfl_Line ***srcsp, size_t *nsrcs)
+{
+  if (mod == NULL)
+    return -1;
+
+  if (mod->dw == NULL)
+    {
+      Dwarf_Addr bias;
+      if (INTUSE(dwfl_module_getdwarf) (mod, &bias) == NULL)
+	return -1;
+    }
+
+  bool is_basename = strchr (fname, '/') == NULL;
+
+  size_t max_match = *nsrcs ?: ~0u;
+  size_t act_match = *nsrcs;
+  size_t cur_match = 0;
+  Dwfl_Line **match = *nsrcs == 0 ? NULL : *srcsp;
+
+  struct dwfl_cu *cu = NULL;
+  Dwfl_Error error;
+  while ((error = __libdwfl_nextcu (mod, cu, &cu)) == DWFL_E_NOERROR
+	 && cu != NULL
+	 && (error = __libdwfl_cu_getsrclines (cu)) == DWFL_E_NOERROR)
+    {
+      /* Search through all the line number records for a matching
+	 file and line/column number.  If any of the numbers is zero,
+	 no match is performed.  */
+      const char *lastfile = NULL;
+      bool lastmatch = false;
+      for (size_t cnt = 0; cnt < cu->die.cu->lines->nlines; ++cnt)
+	{
+	  Dwarf_Line *line = &cu->die.cu->lines->info[cnt];
+
+	  if (unlikely (line->file >= line->files->nfiles))
+	    {
+	      if (*nsrcs == 0)
+		free (match);
+	      __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
+	      return -1;
+	    }
+	  else
+	    {
+	      const char *file = dwfl_dwarf_line_file (line);
+	      if (file != lastfile)
+		{
+		  /* Match the name with the name the user provided.  */
+		  lastfile = file;
+		  lastmatch = !strcmp (is_basename ? xbasename (file) : file,
+				       fname);
+		}
+	    }
+	  if (!lastmatch)
+	    continue;
+
+	  /* See whether line and possibly column match.  */
+	  if (lineno != 0
+	      && (lineno > line->line
+		  || (column != 0 && column > line->column)))
+	    /* Cannot match.  */
+	    continue;
+
+	  /* Determine whether this is the best match so far.  */
+	  size_t inner;
+	  for (inner = 0; inner < cur_match; ++inner)
+	    if (dwfl_line_file (match[inner])
+		== dwfl_dwarf_line_file (line))
+	      break;
+	  if (inner < cur_match
+	      && (dwfl_line (match[inner])->line != line->line
+		  || dwfl_line (match[inner])->line != lineno
+		  || (column != 0
+		      && (dwfl_line (match[inner])->column != line->column
+			  || dwfl_line (match[inner])->column != column))))
+	    {
+	      /* We know about this file already.  If this is a better
+		 match for the line number, use it.  */
+	      if (dwfl_line (match[inner])->line >= line->line
+		  && (dwfl_line (match[inner])->line != line->line
+		      || dwfl_line (match[inner])->column >= line->column))
+		/* Use the new line.  Otherwise the old one.  */
+		match[inner] = &cu->lines->idx[cnt];
+	      continue;
+	    }
+
+	  if (cur_match < max_match)
+	    {
+	      if (cur_match == act_match)
+		{
+		  /* Enlarge the array for the results.  */
+		  act_match += 10;
+		  Dwfl_Line **newp = realloc (match,
+					      act_match
+					      * sizeof (Dwfl_Line *));
+		  if (newp == NULL)
+		    {
+		      free (match);
+		      __libdwfl_seterrno (DWFL_E_NOMEM);
+		      return -1;
+		    }
+		  match = newp;
+		}
+
+	      match[cur_match++] = &cu->lines->idx[cnt];
+	    }
+	}
+    }
+
+  if (cur_match > 0)
+    {
+      assert (*nsrcs == 0 || *srcsp == match);
+
+      *nsrcs = cur_match;
+      *srcsp = match;
+
+      return 0;
+    }
+
+  __libdwfl_seterrno (DWFL_E_NO_MATCH);
+  return -1;
+}
diff --git a/libdwfl/dwfl_module_getsym.c b/libdwfl/dwfl_module_getsym.c
new file mode 100644
index 0000000..8de9a3e
--- /dev/null
+++ b/libdwfl/dwfl_module_getsym.c
@@ -0,0 +1,220 @@
+/* Find debugging and symbol information for a module in libdwfl.
+   Copyright (C) 2006-2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+const char *
+internal_function
+__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym, GElf_Addr *addr,
+		  GElf_Word *shndxp, Elf **elfp, Dwarf_Addr *biasp,
+		  bool *resolved, bool adjust_st_value)
+{
+  if (unlikely (mod == NULL))
+    return NULL;
+
+  if (unlikely (mod->symdata == NULL))
+    {
+      int result = INTUSE(dwfl_module_getsymtab) (mod);
+      if (result < 0)
+	return NULL;
+    }
+
+  /* All local symbols should come before all global symbols.  If we
+     have an auxiliary table make sure all the main locals come first,
+     then all aux locals, then all main globals and finally all aux globals.
+     And skip the auxiliary table zero undefined entry.  */
+  GElf_Word shndx;
+  int tndx = ndx;
+  int skip_aux_zero = (mod->syments > 0 && mod->aux_syments > 0) ? 1 : 0;
+  Elf *elf;
+  Elf_Data *symdata;
+  Elf_Data *symxndxdata;
+  Elf_Data *symstrdata;
+  if (mod->aux_symdata == NULL
+      || ndx < mod->first_global)
+    {
+      /* main symbol table (locals).  */
+      tndx = ndx;
+      elf = mod->symfile->elf;
+      symdata = mod->symdata;
+      symxndxdata = mod->symxndxdata;
+      symstrdata = mod->symstrdata;
+    }
+  else if (ndx < mod->first_global + mod->aux_first_global - skip_aux_zero)
+    {
+      /* aux symbol table (locals).  */
+      tndx = ndx - mod->first_global + skip_aux_zero;
+      elf = mod->aux_sym.elf;
+      symdata = mod->aux_symdata;
+      symxndxdata = mod->aux_symxndxdata;
+      symstrdata = mod->aux_symstrdata;
+    }
+  else if ((size_t) ndx < mod->syments + mod->aux_first_global - skip_aux_zero)
+    {
+      /* main symbol table (globals).  */
+      tndx = ndx - mod->aux_first_global + skip_aux_zero;
+      elf = mod->symfile->elf;
+      symdata = mod->symdata;
+      symxndxdata = mod->symxndxdata;
+      symstrdata = mod->symstrdata;
+    }
+  else
+    {
+      /* aux symbol table (globals).  */
+      tndx = ndx - mod->syments + skip_aux_zero;
+      elf = mod->aux_sym.elf;
+      symdata = mod->aux_symdata;
+      symxndxdata = mod->aux_symxndxdata;
+      symstrdata = mod->aux_symstrdata;
+    }
+  sym = gelf_getsymshndx (symdata, symxndxdata, tndx, sym, &shndx);
+
+  if (unlikely (sym == NULL))
+    {
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      return NULL;
+    }
+
+  if (sym->st_shndx != SHN_XINDEX)
+    shndx = sym->st_shndx;
+
+  /* Figure out whether this symbol points into an SHF_ALLOC section.  */
+  bool alloc = true;
+  if ((shndxp != NULL || mod->e_type != ET_REL)
+      && (sym->st_shndx == SHN_XINDEX
+	  || (sym->st_shndx < SHN_LORESERVE && sym->st_shndx != SHN_UNDEF)))
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, shndx), &shdr_mem);
+      alloc = unlikely (shdr == NULL) || (shdr->sh_flags & SHF_ALLOC);
+    }
+
+  /* In case of an value in an allocated section the main Elf Ebl
+     might know where the real value is (e.g. for function
+     descriptors).  */
+
+  char *ident;
+  GElf_Addr st_value = sym->st_value & ebl_func_addr_mask (mod->ebl);
+  *resolved = false;
+  if (! adjust_st_value && mod->e_type != ET_REL && alloc
+      && (GELF_ST_TYPE (sym->st_info) == STT_FUNC
+	  || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC
+	      && (ident = elf_getident (elf, NULL)) != NULL
+	      && ident[EI_OSABI] == ELFOSABI_LINUX)))
+    {
+      if (likely (__libdwfl_module_getebl (mod) == DWFL_E_NOERROR))
+	{
+	  if (elf != mod->main.elf)
+	    {
+	      st_value = dwfl_adjusted_st_value (mod, elf, st_value);
+	      st_value = dwfl_deadjust_st_value (mod, mod->main.elf, st_value);
+	    }
+
+	  *resolved = ebl_resolve_sym_value (mod->ebl, &st_value);
+	  if (! *resolved)
+	    st_value = sym->st_value;
+	}
+    }
+
+  if (shndxp != NULL)
+    /* Yield -1 in case of a non-SHF_ALLOC section.  */
+    *shndxp = alloc ? shndx : (GElf_Word) -1;
+
+  switch (sym->st_shndx)
+    {
+    case SHN_ABS:		/* XXX sometimes should use bias?? */
+    case SHN_UNDEF:
+    case SHN_COMMON:
+      break;
+
+    default:
+      if (mod->e_type == ET_REL)
+	{
+	  /* In an ET_REL file, the symbol table values are relative
+	     to the section, not to the module's load base.  */
+	  size_t symshstrndx = SHN_UNDEF;
+	  Dwfl_Error result = __libdwfl_relocate_value (mod, elf,
+							&symshstrndx,
+							shndx, &st_value);
+	  if (unlikely (result != DWFL_E_NOERROR))
+	    {
+	      __libdwfl_seterrno (result);
+	      return NULL;
+	    }
+	}
+      else if (alloc)
+	/* Apply the bias to the symbol value.  */
+	st_value = dwfl_adjusted_st_value (mod,
+					   *resolved ? mod->main.elf : elf,
+					   st_value);
+      break;
+    }
+
+  if (adjust_st_value)
+    sym->st_value = st_value;
+
+  if (addr != NULL)
+    *addr = st_value;
+
+  if (unlikely (sym->st_name >= symstrdata->d_size))
+    {
+      __libdwfl_seterrno (DWFL_E_BADSTROFF);
+      return NULL;
+    }
+  if (elfp)
+    *elfp = elf;
+  if (biasp)
+    *biasp = dwfl_adjusted_st_value (mod, elf, 0);
+  return (const char *) symstrdata->d_buf + sym->st_name;
+}
+
+const char *
+dwfl_module_getsym_info (Dwfl_Module *mod, int ndx,
+			 GElf_Sym *sym, GElf_Addr *addr,
+			 GElf_Word *shndxp,
+			 Elf **elfp, Dwarf_Addr *bias)
+{
+  bool resolved;
+  return __libdwfl_getsym (mod, ndx, sym, addr, shndxp, elfp, bias,
+			   &resolved, false);
+}
+INTDEF (dwfl_module_getsym_info)
+
+const char *
+dwfl_module_getsym (Dwfl_Module *mod, int ndx,
+		    GElf_Sym *sym, GElf_Word *shndxp)
+{
+  bool resolved;
+  return __libdwfl_getsym (mod, ndx, sym, NULL, shndxp, NULL, NULL,
+			   &resolved, true);
+}
+INTDEF (dwfl_module_getsym)
diff --git a/libdwfl/dwfl_module_info.c b/libdwfl/dwfl_module_info.c
new file mode 100644
index 0000000..af1faab
--- /dev/null
+++ b/libdwfl/dwfl_module_info.c
@@ -0,0 +1,65 @@
+/* Return information about a module.
+   Copyright (C) 2005-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+const char *
+dwfl_module_info (Dwfl_Module *mod, void ***userdata,
+		  Dwarf_Addr *start, Dwarf_Addr *end,
+		  Dwarf_Addr *dwbias, Dwarf_Addr *symbias,
+		  const char **mainfile, const char **debugfile)
+{
+  if (mod == NULL)
+    return NULL;
+
+  if (userdata)
+    *userdata = &mod->userdata;
+  if (start)
+    *start = mod->low_addr;
+  if (end)
+    *end = mod->high_addr;
+
+  if (dwbias)
+    *dwbias = (mod->debug.elf == NULL ? (Dwarf_Addr) -1
+	       : dwfl_adjusted_dwarf_addr (mod, 0));
+  if (symbias)
+    *symbias = (mod->symfile == NULL ? (Dwarf_Addr) -1
+		: dwfl_adjusted_st_value (mod, mod->symfile->elf, 0));
+
+  if (mainfile)
+    *mainfile = mod->main.name;
+
+  if (debugfile)
+    *debugfile = mod->debug.name;
+
+  return mod->name;
+}
diff --git a/libdwfl/dwfl_module_nextcu.c b/libdwfl/dwfl_module_nextcu.c
new file mode 100644
index 0000000..32ee6bc
--- /dev/null
+++ b/libdwfl/dwfl_module_nextcu.c
@@ -0,0 +1,48 @@
+/* Iterate through DWARF compilation units in a module.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwarf_Die *
+dwfl_module_nextcu (Dwfl_Module *mod, Dwarf_Die *lastcu, Dwarf_Addr *bias)
+{
+  if (INTUSE(dwfl_module_getdwarf) (mod, bias) == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu;
+  Dwfl_Error error = __libdwfl_nextcu (mod, (struct dwfl_cu *) lastcu, &cu);
+  if (likely (error == DWFL_E_NOERROR))
+    return &cu->die;		/* Same as a cast, so ok for null too.  */
+
+  __libdwfl_seterrno (error);
+  return NULL;
+}
diff --git a/libdwfl/dwfl_module_register_names.c b/libdwfl/dwfl_module_register_names.c
new file mode 100644
index 0000000..9ea0937
--- /dev/null
+++ b/libdwfl/dwfl_module_register_names.c
@@ -0,0 +1,82 @@
+/* Enumerate DWARF register numbers and their names.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+
+int
+dwfl_module_register_names (Dwfl_Module *mod,
+			    int (*func) (void *, int, const char *,
+					 const char *, const char *,
+					 int, int),
+			    void *arg)
+{
+  if (unlikely (mod == NULL))
+    return -1;
+
+  if (unlikely (mod->ebl == NULL))
+    {
+      Dwfl_Error error = __libdwfl_module_getebl (mod);
+      if (error != DWFL_E_NOERROR)
+	{
+	  __libdwfl_seterrno (error);
+	  return -1;
+	}
+    }
+
+  int nregs = ebl_register_info (mod->ebl, -1, NULL, 0,
+				 NULL, NULL, NULL, NULL);
+  int result = 0;
+  for (int regno = 0; regno < nregs && likely (result == 0); ++regno)
+    {
+      char name[32];
+      const char *setname = NULL;
+      const char *prefix = NULL;
+      int bits = -1;
+      int type = -1;
+      ssize_t len = ebl_register_info (mod->ebl, regno, name, sizeof name,
+				       &prefix, &setname, &bits, &type);
+      if (unlikely (len < 0))
+	{
+	  __libdwfl_seterrno (DWFL_E_LIBEBL);
+	  result = -1;
+	  break;
+	}
+      if (likely (len > 0))
+	{
+	  assert (len > 1);	/* Backend should never yield "".  */
+	  result = (*func) (arg, regno, setname, prefix, name, bits, type);
+	}
+    }
+
+  return result;
+}
diff --git a/libdwfl/dwfl_module_report_build_id.c b/libdwfl/dwfl_module_report_build_id.c
new file mode 100644
index 0000000..31e17c8
--- /dev/null
+++ b/libdwfl/dwfl_module_report_build_id.c
@@ -0,0 +1,84 @@
+/* Report build ID information for a module.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+// XXX vs report changed module: punting old file
+int
+dwfl_module_report_build_id (Dwfl_Module *mod,
+			     const unsigned char *bits, size_t len,
+			     GElf_Addr vaddr)
+{
+  if (mod == NULL)
+    return -1;
+
+  if (mod->main.elf != NULL)
+    {
+      /* Once we know about a file, we won't take any lies about
+	 its contents.  The only permissible call is a no-op.  */
+
+      if ((size_t) mod->build_id_len == len
+	  && (mod->build_id_vaddr == vaddr || vaddr == 0)
+	  && !memcmp (bits, mod->build_id_bits, len))
+	return 0;
+
+      __libdwfl_seterrno (DWFL_E_ALREADY_ELF);
+      return -1;
+    }
+
+  if (vaddr != 0 && (vaddr < mod->low_addr || vaddr + len > mod->high_addr))
+    {
+      __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE);
+      return -1;
+    }
+
+  void *copy = NULL;
+  if (len > 0)
+    {
+      copy = malloc (len);
+      if (unlikely (copy == NULL))
+	{
+	  __libdwfl_seterrno (DWFL_E_NOMEM);
+	  return -1;
+	}
+      memcpy (copy, bits, len);
+    }
+
+  free (mod->build_id_bits);
+
+  mod->build_id_bits = copy;
+  mod->build_id_len = len;
+  mod->build_id_vaddr = vaddr;
+
+  return 0;
+}
+INTDEF (dwfl_module_report_build_id)
diff --git a/libdwfl/dwfl_module_return_value_location.c b/libdwfl/dwfl_module_return_value_location.c
new file mode 100644
index 0000000..ff6f56f
--- /dev/null
+++ b/libdwfl/dwfl_module_return_value_location.c
@@ -0,0 +1,66 @@
+/* Return location expression to find return value given a function type DIE.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+
+int
+dwfl_module_return_value_location (Dwfl_Module *mod, Dwarf_Die *functypedie,
+				   const Dwarf_Op **locops)
+{
+  if (mod == NULL)
+    return -1;
+
+  if (mod->ebl == NULL)
+    {
+      Dwfl_Error error = __libdwfl_module_getebl (mod);
+      if (error != DWFL_E_NOERROR)
+	{
+	  __libdwfl_seterrno (error);
+	  return -1;
+	}
+    }
+
+  int nops = ebl_return_value_location (mod->ebl, functypedie, locops);
+  if (unlikely (nops < 0))
+    {
+      if (nops == -1)
+	__libdwfl_seterrno (DWFL_E_LIBDW);
+      else if (nops == -2)
+	__libdwfl_seterrno (DWFL_E_WEIRD_TYPE);
+      else
+	__libdwfl_seterrno (DWFL_E_LIBEBL);
+      nops = -1;
+    }
+
+  return nops;
+}
diff --git a/libdwfl/dwfl_nextcu.c b/libdwfl/dwfl_nextcu.c
new file mode 100644
index 0000000..64bd521
--- /dev/null
+++ b/libdwfl/dwfl_nextcu.c
@@ -0,0 +1,86 @@
+/* Iterate through DWARF compilation units across all modules.
+   Copyright (C) 2005-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwarf_Die *
+dwfl_nextcu (Dwfl *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias)
+{
+  if (dwfl == NULL)
+    return NULL;
+
+  struct dwfl_cu *cu = (struct dwfl_cu *) lastcu;
+  Dwfl_Module *mod;
+
+  if (cu == NULL)
+    {
+      mod = dwfl->modulelist;
+      goto nextmod;
+    }
+  else
+    mod = cu->mod;
+
+  Dwfl_Error error;
+  do
+    {
+      error = __libdwfl_nextcu (mod, cu, &cu);
+      if (error != DWFL_E_NOERROR)
+	break;
+
+      if (cu != NULL)
+	{
+	  *bias = dwfl_adjusted_dwarf_addr (mod, 0);
+	  return &cu->die;
+	}
+
+      do
+	{
+	  mod = mod->next;
+
+	nextmod:
+	  if (mod == NULL)
+	    return NULL;
+
+	  if (mod->dwerr == DWFL_E_NOERROR
+	      && (mod->dw != NULL
+		  || INTUSE(dwfl_module_getdwarf) (mod, bias) != NULL))
+	    break;
+	}
+      while (mod->dwerr == DWFL_E_NO_DWARF);
+      error = mod->dwerr;
+    }
+  while (error == DWFL_E_NOERROR);
+
+  __libdwfl_seterrno (error);
+  return NULL;
+}
+INTDEF (dwfl_nextcu)
diff --git a/libdwfl/dwfl_onesrcline.c b/libdwfl/dwfl_onesrcline.c
new file mode 100644
index 0000000..b1e7055
--- /dev/null
+++ b/libdwfl/dwfl_onesrcline.c
@@ -0,0 +1,60 @@
+/* Return one of the sources lines of a CU.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+Dwfl_Line *
+dwfl_onesrcline (Dwarf_Die *cudie, size_t idx)
+{
+  struct dwfl_cu *cu = (struct dwfl_cu *) cudie;
+
+  if (cudie == NULL)
+    return NULL;
+
+  if (cu->lines == NULL)
+    {
+      Dwfl_Error error = __libdwfl_cu_getsrclines (cu);
+      if (error != DWFL_E_NOERROR)
+	{
+	  __libdwfl_seterrno (error);
+	  return NULL;
+	}
+    }
+
+  if (idx >= cu->die.cu->lines->nlines)
+    {
+      __libdwfl_seterrno (DWFL_E (LIBDW, DWARF_E_INVALID_LINE_IDX));
+      return NULL;
+    }
+
+  return &cu->lines->idx[idx];
+}
diff --git a/libdwfl/dwfl_report_elf.c b/libdwfl/dwfl_report_elf.c
new file mode 100644
index 0000000..a76d368
--- /dev/null
+++ b/libdwfl/dwfl_report_elf.c
@@ -0,0 +1,341 @@
+/* Report a module to libdwfl based on ELF program headers.
+   Copyright (C) 2005-2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <fcntl.h>
+
+/* We start every ET_REL module at a moderately aligned boundary.
+   This keeps the low addresses easy to read compared to a layout
+   starting at 0 (as when using -e).  It also makes it unlikely
+   that a middle section will have a larger alignment and require
+   rejiggering (see below).  */
+#define REL_MIN_ALIGN	((GElf_Xword) 0x100)
+
+bool
+internal_function
+__libdwfl_elf_address_range (Elf *elf, GElf_Addr base, bool add_p_vaddr,
+			     bool sanity, GElf_Addr *vaddrp,
+			     GElf_Addr *address_syncp, GElf_Addr *startp,
+			     GElf_Addr *endp, GElf_Addr *biasp,
+			     GElf_Half *e_typep)
+{
+  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+    elf_error:
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      return false;
+    }
+
+  GElf_Addr vaddr = 0;
+  GElf_Addr address_sync = 0;
+  GElf_Addr start = 0, end = 0, bias = 0;
+  switch (ehdr->e_type)
+    {
+    case ET_REL:
+      /* For a relocatable object, we do an arbitrary section layout.
+	 By updating the section header in place, we leave the layout
+	 information to be found by relocation.  */
+
+      start = end = base = (base + REL_MIN_ALIGN - 1) & -REL_MIN_ALIGN;
+
+      bool first = true;
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (unlikely (shdr == NULL))
+	    goto elf_error;
+
+	  if (shdr->sh_flags & SHF_ALLOC)
+	    {
+	      const GElf_Xword align = shdr->sh_addralign ?: 1;
+	      const GElf_Addr next = (end + align - 1) & -align;
+	      if (shdr->sh_addr == 0
+		  /* Once we've started doing layout we have to do it all,
+		     unless we just laid out the first section at 0 when
+		     it already was at 0.  */
+		  || (bias == 0 && end > start && end != next))
+		{
+		  shdr->sh_addr = next;
+		  if (end == base)
+		    /* This is the first section assigned a location.
+		       Use its aligned address as the module's base.  */
+		    start = base = shdr->sh_addr;
+		  else if (unlikely (base & (align - 1)))
+		    {
+		      /* If BASE has less than the maximum alignment of
+			 any section, we eat more than the optimal amount
+			 of padding and so make the module's apparent
+			 size come out larger than it would when placed
+			 at zero.  So reset the layout with a better base.  */
+
+		      start = end = base = (base + align - 1) & -align;
+		      Elf_Scn *prev_scn = NULL;
+		      do
+			{
+			  prev_scn = elf_nextscn (elf, prev_scn);
+			  GElf_Shdr prev_shdr_mem;
+			  GElf_Shdr *prev_shdr = gelf_getshdr (prev_scn,
+							       &prev_shdr_mem);
+			  if (unlikely (prev_shdr == NULL))
+			    goto elf_error;
+			  if (prev_shdr->sh_flags & SHF_ALLOC)
+			    {
+			      const GElf_Xword prev_align
+				= prev_shdr->sh_addralign ?: 1;
+
+			      prev_shdr->sh_addr
+				= (end + prev_align - 1) & -prev_align;
+			      end = prev_shdr->sh_addr + prev_shdr->sh_size;
+
+			      if (unlikely (! gelf_update_shdr (prev_scn,
+								prev_shdr)))
+				goto elf_error;
+			    }
+			}
+		      while (prev_scn != scn);
+		      continue;
+		    }
+
+		  end = shdr->sh_addr + shdr->sh_size;
+		  if (likely (shdr->sh_addr != 0)
+		      && unlikely (! gelf_update_shdr (scn, shdr)))
+		    goto elf_error;
+		}
+	      else
+		{
+		  /* The address is already assigned.  Just track it.  */
+		  if (first || end < shdr->sh_addr + shdr->sh_size)
+		    end = shdr->sh_addr + shdr->sh_size;
+		  if (first || bias > shdr->sh_addr)
+		    /* This is the lowest address in the module.  */
+		    bias = shdr->sh_addr;
+
+		  if ((shdr->sh_addr - bias + base) & (align - 1))
+		    /* This section winds up misaligned using BASE.
+		       Adjust BASE upwards to make it congruent to
+		       the lowest section address in the file modulo ALIGN.  */
+		    base = (((base + align - 1) & -align)
+			    + (bias & (align - 1)));
+		}
+
+	      first = false;
+	    }
+	}
+
+      if (bias != 0)
+	{
+	  /* The section headers had nonzero sh_addr values.  The layout
+	     was already done.  We've just collected the total span.
+	     Now just compute the bias from the requested base.  */
+	  start = base;
+	  end = end - bias + start;
+	  bias = start - bias;
+	}
+      break;
+
+      /* Everything else has to have program headers.  */
+
+    case ET_EXEC:
+    case ET_CORE:
+      /* An assigned base address is meaningless for these.  */
+      base = 0;
+      add_p_vaddr = true;
+      FALLTHROUGH;
+    case ET_DYN:
+    default:;
+      size_t phnum;
+      if (unlikely (elf_getphdrnum (elf, &phnum) != 0))
+	goto elf_error;
+      for (size_t i = 0; i < phnum; ++i)
+	{
+	  GElf_Phdr phdr_mem, *ph = gelf_getphdr (elf, i, &phdr_mem);
+	  if (unlikely (ph == NULL))
+	    goto elf_error;
+	  if (ph->p_type == PT_LOAD)
+	    {
+	      vaddr = ph->p_vaddr & -ph->p_align;
+	      address_sync = ph->p_vaddr + ph->p_memsz;
+	      break;
+	    }
+	}
+      if (add_p_vaddr)
+	{
+	  start = base + vaddr;
+	  bias = base;
+	}
+      else
+	{
+	  start = base;
+	  bias = base - vaddr;
+	}
+
+      for (size_t i = phnum; i-- > 0;)
+	{
+	  GElf_Phdr phdr_mem, *ph = gelf_getphdr (elf, i, &phdr_mem);
+	  if (unlikely (ph == NULL))
+	    goto elf_error;
+	  if (ph->p_type == PT_LOAD
+	      && ph->p_vaddr + ph->p_memsz > 0)
+	    {
+	      end = bias + (ph->p_vaddr + ph->p_memsz);
+	      break;
+	    }
+	}
+
+      if (end == 0 && sanity)
+	{
+	  __libdwfl_seterrno (DWFL_E_NO_PHDR);
+	  return false;
+	}
+      break;
+    }
+  if (vaddrp)
+    *vaddrp = vaddr;
+  if (address_syncp)
+    *address_syncp = address_sync;
+  if (startp)
+    *startp = start;
+  if (endp)
+    *endp = end;
+  if (biasp)
+    *biasp = bias;
+  if (e_typep)
+    *e_typep = ehdr->e_type;
+  return true;
+}
+
+Dwfl_Module *
+internal_function
+__libdwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name,
+		      int fd, Elf *elf, GElf_Addr base, bool add_p_vaddr,
+		      bool sanity)
+{
+  GElf_Addr vaddr, address_sync, start, end, bias;
+  GElf_Half e_type;
+  if (! __libdwfl_elf_address_range (elf, base, add_p_vaddr, sanity, &vaddr,
+				     &address_sync, &start, &end, &bias,
+				     &e_type))
+    return NULL;
+  Dwfl_Module *m = INTUSE(dwfl_report_module) (dwfl, name, start, end);
+  if (m != NULL)
+    {
+      if (m->main.name == NULL)
+	{
+	  m->main.name = strdup (file_name);
+	  m->main.fd = fd;
+	}
+      else if ((fd >= 0 && m->main.fd != fd)
+	       || strcmp (m->main.name, file_name))
+	{
+	overlap:
+	  m->gc = true;
+	  __libdwfl_seterrno (DWFL_E_OVERLAP);
+	  return NULL;
+	}
+
+      /* Preinstall the open ELF handle for the module.  */
+      if (m->main.elf == NULL)
+	{
+	  m->main.elf = elf;
+	  m->main.vaddr = vaddr;
+	  m->main.address_sync = address_sync;
+	  m->main_bias = bias;
+	  m->e_type = e_type;
+	}
+      else
+	{
+	  if (m->main_bias != bias
+	      || m->main.vaddr != vaddr || m->main.address_sync != address_sync)
+	    goto overlap;
+	  elf_end (m->main.elf);
+	  m->main.elf = elf;
+	}
+    }
+  return m;
+}
+
+NEW_VERSION (dwfl_report_elf, ELFUTILS_0.156)
+Dwfl_Module *
+dwfl_report_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
+		 GElf_Addr base, bool add_p_vaddr)
+{
+  bool closefd = false;
+  if (fd < 0)
+    {
+      closefd = true;
+      fd = open (file_name, O_RDONLY);
+      if (fd < 0)
+	{
+	  __libdwfl_seterrno (DWFL_E_ERRNO);
+	  return NULL;
+	}
+    }
+
+  Elf *elf;
+  Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, false);
+  if (error != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (error);
+      return NULL;
+    }
+
+  Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name,
+					   fd, elf, base, add_p_vaddr, true);
+  if (mod == NULL)
+    {
+      elf_end (elf);
+      if (closefd)
+	close (fd);
+    }
+
+  return mod;
+}
+NEW_INTDEF (dwfl_report_elf)
+
+#ifdef SYMBOL_VERSIONING
+Dwfl_Module *
+  _compat_without_add_p_vaddr_dwfl_report_elf (Dwfl *dwfl, const char *name,
+					       const char *file_name, int fd,
+					       GElf_Addr base);
+COMPAT_VERSION_NEWPROTO (dwfl_report_elf, ELFUTILS_0.122, without_add_p_vaddr)
+
+Dwfl_Module *
+_compat_without_add_p_vaddr_dwfl_report_elf (Dwfl *dwfl, const char *name,
+					     const char *file_name, int fd,
+					     GElf_Addr base)
+{
+  return dwfl_report_elf (dwfl, name, file_name, fd, base, true);
+}
+#endif
diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c
new file mode 100644
index 0000000..dc34e0a
--- /dev/null
+++ b/libdwfl/dwfl_segment_report_module.c
@@ -0,0 +1,1054 @@
+/* Sniff out modules from ELF headers visible in memory segments.
+   Copyright (C) 2008-2012, 2014, 2015, 2018 Red Hat, Inc.
+   Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include "libelfP.h"	/* For NOTE_ALIGN4 and NOTE_ALIGN8.  */
+#include "libdwflP.h"
+#include "common.h"
+
+#include <elf.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <fcntl.h>
+
+#include <system.h>
+
+
+/* A good size for the initial read from memory, if it's not too costly.
+   This more than covers the phdrs and note segment in the average 64-bit
+   binary.  */
+
+#define INITIAL_READ	1024
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define MY_ELFDATA	ELFDATA2LSB
+#else
+# define MY_ELFDATA	ELFDATA2MSB
+#endif
+
+struct elf_build_id
+{
+  void *memory;
+  size_t len;
+  GElf_Addr vaddr;
+};
+
+struct read_state
+{
+  Dwfl *dwfl;
+  Dwfl_Memory_Callback *memory_callback;
+  void *memory_callback_arg;
+  void **buffer;
+  size_t *buffer_available;
+};
+
+/* Return user segment index closest to ADDR but not above it.
+   If NEXT, return the closest to ADDR but not below it.  */
+static int
+addr_segndx (Dwfl *dwfl, size_t segment, GElf_Addr addr, bool next)
+{
+  int ndx = -1;
+  do
+    {
+      if (dwfl->lookup_segndx[segment] >= 0)
+	ndx = dwfl->lookup_segndx[segment];
+      if (++segment >= dwfl->lookup_elts - 1)
+	return next ? ndx + 1 : ndx;
+    }
+  while (dwfl->lookup_addr[segment] < addr);
+
+  if (next)
+    {
+      while (dwfl->lookup_segndx[segment] < 0)
+	if (++segment >= dwfl->lookup_elts - 1)
+	  return ndx + 1;
+      ndx = dwfl->lookup_segndx[segment];
+    }
+
+  return ndx;
+}
+
+/* Return whether there is SZ bytes available at PTR till END.  */
+
+static bool
+buf_has_data (const void *ptr, const void *end, size_t sz)
+{
+  return ptr < end && (size_t) (end - ptr) >= sz;
+}
+
+/* Read SZ bytes into *RETP from *PTRP (limited by END) in format EI_DATA.
+   Function comes from src/readelf.c .  */
+
+static bool
+buf_read_ulong (unsigned char ei_data, size_t sz,
+		const void **ptrp, const void *end, uint64_t *retp)
+{
+  if (! buf_has_data (*ptrp, end, sz))
+    return false;
+
+  union
+  {
+    uint64_t u64;
+    uint32_t u32;
+  } u;
+
+  memcpy (&u, *ptrp, sz);
+  (*ptrp) += sz;
+
+  if (retp == NULL)
+    return true;
+
+  if (MY_ELFDATA != ei_data)
+    {
+      if (sz == 4)
+	CONVERT (u.u32);
+      else
+	CONVERT (u.u64);
+    }
+  if (sz == 4)
+    *retp = u.u32;
+  else
+    *retp = u.u64;
+  return true;
+}
+
+/* Try to find matching entry for module from address MODULE_START to
+   MODULE_END in NT_FILE note located at NOTE_FILE of NOTE_FILE_SIZE
+   bytes in format EI_CLASS and EI_DATA.  */
+
+static const char *
+handle_file_note (GElf_Addr module_start, GElf_Addr module_end,
+		  unsigned char ei_class, unsigned char ei_data,
+		  const void *note_file, size_t note_file_size)
+{
+  if (note_file == NULL)
+    return NULL;
+
+  size_t sz;
+  switch (ei_class)
+    {
+    case ELFCLASS32:
+      sz = 4;
+      break;
+    case ELFCLASS64:
+      sz = 8;
+      break;
+    default:
+      return NULL;
+    }
+
+  const void *ptr = note_file;
+  const void *end = note_file + note_file_size;
+  uint64_t count;
+  if (! buf_read_ulong (ei_data, sz, &ptr, end, &count))
+    return NULL;
+  if (! buf_read_ulong (ei_data, sz, &ptr, end, NULL)) // page_size
+    return NULL;
+
+  uint64_t maxcount = (size_t) (end - ptr) / (3 * sz);
+  if (count > maxcount)
+    return NULL;
+
+  /* Where file names are stored.  */
+  const char *fptr = ptr + 3 * count * sz;
+
+  ssize_t firstix = -1;
+  ssize_t lastix = -1;
+  for (size_t mix = 0; mix < count; mix++)
+    {
+      uint64_t mstart, mend, moffset;
+      if (! buf_read_ulong (ei_data, sz, &ptr, fptr, &mstart)
+	  || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &mend)
+	  || ! buf_read_ulong (ei_data, sz, &ptr, fptr, &moffset))
+	return NULL;
+      if (mstart == module_start && moffset == 0)
+	firstix = lastix = mix;
+      if (firstix != -1 && mstart < module_end)
+	lastix = mix;
+      if (mend >= module_end)
+	break;
+    }
+  if (firstix == -1)
+    return NULL;
+
+  const char *retval = NULL;
+  for (ssize_t mix = 0; mix <= lastix; mix++)
+    {
+      const char *fnext = memchr (fptr, 0, (const char *) end - fptr);
+      if (fnext == NULL)
+	return NULL;
+      if (mix == firstix)
+	retval = fptr;
+      if (firstix < mix && mix <= lastix && strcmp (fptr, retval) != 0)
+	return NULL;
+      fptr = fnext + 1;
+    }
+  return retval;
+}
+
+/* Return true iff we are certain ELF cannot match BUILD_ID of
+   BUILD_ID_LEN bytes.  Pass DISK_FILE_HAS_BUILD_ID as false if it is
+   certain ELF does not contain build-id (it is only a performance hit
+   to pass it always as true).  */
+
+static bool
+invalid_elf (Elf *elf, bool disk_file_has_build_id,
+             struct elf_build_id *build_id)
+{
+  if (! disk_file_has_build_id && build_id->len > 0)
+    {
+      /* Module found in segments with build-id is more reliable
+	 than a module found via DT_DEBUG on disk without any
+	 build-id.   */
+      return true;
+    }
+  if (disk_file_has_build_id && build_id->len > 0)
+    {
+      const void *elf_build_id;
+      ssize_t elf_build_id_len;
+
+      /* If there is a build id in the elf file, check it.  */
+      elf_build_id_len = INTUSE(dwelf_elf_gnu_build_id) (elf, &elf_build_id);
+      if (elf_build_id_len > 0)
+	{
+	  if (build_id->len != (size_t) elf_build_id_len
+	      || memcmp (build_id->memory, elf_build_id, build_id->len) != 0)
+	    return true;
+	}
+    }
+  return false;
+}
+
+static void
+finish_portion (struct read_state *read_state,
+		void **data, size_t *data_size)
+{
+  if (*data_size != 0 && *data != NULL)
+    (*read_state->memory_callback) (read_state->dwfl, -1, data, data_size,
+				    0, 0, read_state->memory_callback_arg);
+}
+
+static inline bool
+read_portion (struct read_state *read_state,
+	      void **data, size_t *data_size,
+	      GElf_Addr start, size_t segment,
+	      GElf_Addr vaddr, size_t filesz)
+{
+  /* Check whether we will have to read the segment data, or if it
+     can be returned from the existing buffer.  */
+  if (filesz > *read_state->buffer_available
+      || vaddr - start > *read_state->buffer_available - filesz
+      /* If we're in string mode, then don't consider the buffer we have
+	 sufficient unless it contains the terminator of the string.  */
+      || (filesz == 0 && memchr (vaddr - start + *read_state->buffer, '\0',
+				 (*read_state->buffer_available
+				  - (vaddr - start))) == NULL))
+    {
+      *data = NULL;
+      *data_size = filesz;
+      return !(*read_state->memory_callback) (read_state->dwfl,
+					      addr_segndx (read_state->dwfl,
+							   segment, vaddr,
+							   false),
+					      data, data_size, vaddr, filesz,
+					      read_state->memory_callback_arg);
+    }
+
+  /* We already have this whole note segment from our initial read.  */
+  *data = vaddr - start + (*read_state->buffer);
+  *data_size = 0;
+  return false;
+}
+
+int
+dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
+			    Dwfl_Memory_Callback *memory_callback,
+			    void *memory_callback_arg,
+			    Dwfl_Module_Callback *read_eagerly,
+			    void *read_eagerly_arg,
+			    size_t maxread,
+			    const void *note_file, size_t note_file_size,
+			    const struct r_debug_info *r_debug_info)
+{
+  size_t segment = ndx;
+  struct read_state read_state;
+
+  if (segment >= dwfl->lookup_elts)
+    segment = dwfl->lookup_elts - 1;
+
+  while (segment > 0
+	 && (dwfl->lookup_segndx[segment] > ndx
+	     || dwfl->lookup_segndx[segment] == -1))
+    --segment;
+
+  while (dwfl->lookup_segndx[segment] < ndx)
+    if (++segment == dwfl->lookup_elts)
+      return 0;
+
+  GElf_Addr start = dwfl->lookup_addr[segment];
+
+  /* First read in the file header and check its sanity.  */
+
+  void *buffer = NULL;
+  size_t buffer_available = INITIAL_READ;
+  Elf *elf = NULL;
+  int fd = -1;
+
+  read_state.dwfl = dwfl;
+  read_state.memory_callback = memory_callback;
+  read_state.memory_callback_arg = memory_callback_arg;
+  read_state.buffer = &buffer;
+  read_state.buffer_available = &buffer_available;
+
+  /* We might have to reserve some memory for the phdrs.  Set to NULL
+     here so we can always safely free it.  */
+  void *phdrsp = NULL;
+
+  /* Collect the build ID bits here.  */
+  struct elf_build_id build_id;
+  build_id.memory = NULL;
+  build_id.len = 0;
+  build_id.vaddr = 0;
+
+  if (! (*memory_callback) (dwfl, ndx, &buffer, &buffer_available,
+			    start, sizeof (Elf64_Ehdr), memory_callback_arg)
+      || memcmp (buffer, ELFMAG, SELFMAG) != 0)
+    goto out;
+
+  /* Extract the information we need from the file header.  */
+  const unsigned char *e_ident;
+  unsigned char ei_class;
+  unsigned char ei_data;
+  uint16_t e_type;
+  union
+  {
+    Elf32_Ehdr e32;
+    Elf64_Ehdr e64;
+  } ehdr;
+  GElf_Off phoff;
+  uint_fast16_t phnum;
+  uint_fast16_t phentsize;
+  GElf_Off shdrs_end;
+  Elf_Data xlatefrom =
+    {
+      .d_type = ELF_T_EHDR,
+      .d_buf = (void *) buffer,
+      .d_version = EV_CURRENT,
+    };
+  Elf_Data xlateto =
+    {
+      .d_type = ELF_T_EHDR,
+      .d_buf = &ehdr,
+      .d_size = sizeof ehdr,
+      .d_version = EV_CURRENT,
+    };
+  e_ident = ((const unsigned char *) buffer);
+  ei_class = e_ident[EI_CLASS];
+  ei_data = e_ident[EI_DATA];
+  /* buffer may be unaligned, in which case xlatetom would not work.
+     xlatetom does work when the in and out d_buf are equal (but not
+     for any other overlap).  */
+  size_t ehdr_align = (ei_class == ELFCLASS32
+		       ? __alignof__ (Elf32_Ehdr)
+		       : __alignof__ (Elf64_Ehdr));
+  if (((uintptr_t) buffer & (ehdr_align - 1)) != 0)
+    {
+      memcpy (&ehdr, buffer,
+	      (ei_class == ELFCLASS32
+	       ? sizeof (Elf32_Ehdr)
+	       : sizeof (Elf64_Ehdr)));
+      xlatefrom.d_buf = &ehdr;
+    }
+  switch (ei_class)
+    {
+    case ELFCLASS32:
+      xlatefrom.d_size = sizeof (Elf32_Ehdr);
+      if (elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
+	goto out;
+      e_type = ehdr.e32.e_type;
+      phoff = ehdr.e32.e_phoff;
+      phnum = ehdr.e32.e_phnum;
+      phentsize = ehdr.e32.e_phentsize;
+      if (phentsize != sizeof (Elf32_Phdr))
+	goto out;
+      /* NOTE if the number of sections is > 0xff00 then e_shnum
+	 is zero and the actual number would come from the section
+	 zero sh_size field. We ignore this here because getting shdrs
+	 is just a nice bonus (see below in the type == PT_LOAD case
+	 where we trim the last segment).  */
+      shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * sizeof (Elf32_Shdr);
+      break;
+
+    case ELFCLASS64:
+      xlatefrom.d_size = sizeof (Elf64_Ehdr);
+      if (elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
+	goto out;
+      e_type = ehdr.e64.e_type;
+      phoff = ehdr.e64.e_phoff;
+      phnum = ehdr.e64.e_phnum;
+      phentsize = ehdr.e64.e_phentsize;
+      if (phentsize != sizeof (Elf64_Phdr))
+	goto out;
+      /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
+      shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * sizeof (Elf64_Shdr);
+      break;
+
+    default:
+      goto out;
+    }
+
+  /* The file header tells where to find the program headers.
+     These are what we need to find the boundaries of the module.
+     Without them, we don't have a module to report.  */
+
+  if (phnum == 0)
+    goto out;
+
+  xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
+  xlatefrom.d_size = phnum * phentsize;
+
+  void *ph_buffer = NULL;
+  size_t ph_buffer_size = 0;
+  if (read_portion (&read_state, &ph_buffer, &ph_buffer_size,
+		    start, segment,
+		    start + phoff, xlatefrom.d_size))
+    goto out;
+
+  xlatefrom.d_buf = ph_buffer;
+
+  bool class32 = ei_class == ELFCLASS32;
+  size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
+  if (unlikely (phnum > SIZE_MAX / phdr_size))
+    goto out;
+  const size_t phdrsp_bytes = phnum * phdr_size;
+  phdrsp = malloc (phdrsp_bytes);
+  if (unlikely (phdrsp == NULL))
+    goto out;
+
+  xlateto.d_buf = phdrsp;
+  xlateto.d_size = phdrsp_bytes;
+
+  /* ph_ buffer may be unaligned, in which case xlatetom would not work.
+     xlatetom does work when the in and out d_buf are equal (but not
+     for any other overlap).  */
+  size_t phdr_align = (class32
+		       ? __alignof__ (Elf32_Phdr)
+		       : __alignof__ (Elf64_Phdr));
+  if (((uintptr_t) ph_buffer & (phdr_align - 1)) != 0)
+    {
+      memcpy (phdrsp, ph_buffer, phdrsp_bytes);
+      xlatefrom.d_buf = phdrsp;
+    }
+
+  /* Track the bounds of the file visible in memory.  */
+  GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end.  */
+  GElf_Off file_end = 0;	 /* Rounded up to effective page size.  */
+  GElf_Off contiguous = 0;	 /* Visible as contiguous file from START.  */
+  GElf_Off total_filesz = 0;	 /* Total size of data to read.  */
+
+  /* Collect the bias between START and the containing PT_LOAD's p_vaddr.  */
+  GElf_Addr bias = 0;
+  bool found_bias = false;
+
+  /* Collect the unbiased bounds of the module here.  */
+  GElf_Addr module_start = -1l;
+  GElf_Addr module_end = 0;
+  GElf_Addr module_address_sync = 0;
+
+  /* If we see PT_DYNAMIC, record it here.  */
+  GElf_Addr dyn_vaddr = 0;
+  GElf_Xword dyn_filesz = 0;
+
+  Elf32_Phdr *p32 = phdrsp;
+  Elf64_Phdr *p64 = phdrsp;
+  if ((ei_class == ELFCLASS32
+       && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL)
+      || (ei_class == ELFCLASS64
+          && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) == NULL))
+    {
+      found_bias = false; /* Trigger error check */
+    }
+  else
+    {
+      /* Consider each of the program headers we've read from the image.  */
+      for (uint_fast16_t i = 0; i < phnum; ++i)
+        {
+          bool is32 = (ei_class == ELFCLASS32);
+          GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
+          GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
+          GElf_Xword memsz = is32 ? p32[i].p_memsz : p64[i].p_memsz;
+          GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
+          GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
+          GElf_Xword align = is32 ? p32[i].p_align : p64[i].p_align;
+
+          if (type == PT_DYNAMIC)
+            {
+              dyn_vaddr = vaddr;
+              dyn_filesz = filesz;
+            }
+          else if (type == PT_NOTE)
+            {
+              /* If we have already seen a build ID, we don't care any more.  */
+              if (build_id.memory != NULL || filesz == 0)
+                continue; /* Next header */
+
+              /* We calculate from the p_offset of the note segment,
+               because we don't yet know the bias for its p_vaddr.  */
+              const GElf_Addr note_vaddr = start + offset;
+              void *data = NULL;
+              size_t data_size = 0;
+              if (read_portion (&read_state, &data, &data_size,
+				start, segment, note_vaddr, filesz))
+                continue; /* Next header */
+
+	      if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
+		continue;
+
+              assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
+
+              void *notes;
+              if (ei_data == MY_ELFDATA
+		  && (uintptr_t) data == (align == 8
+					  ? NOTE_ALIGN8 ((uintptr_t) data)
+					  : NOTE_ALIGN4 ((uintptr_t) data)))
+                notes = data;
+              else
+                {
+                  const unsigned int xencoding = ehdr.e32.e_ident[EI_DATA];
+
+		  if (filesz > SIZE_MAX / sizeof (Elf32_Nhdr))
+		    continue;
+                  notes = malloc (filesz);
+                  if (unlikely (notes == NULL))
+                    continue; /* Next header */
+                  xlatefrom.d_type = xlateto.d_type = (align == 8
+                                                       ? ELF_T_NHDR8
+						       : ELF_T_NHDR);
+                  xlatefrom.d_buf = (void *) data;
+                  xlatefrom.d_size = filesz;
+                  xlateto.d_buf = notes;
+                  xlateto.d_size = filesz;
+
+		  /* data may be unaligned, in which case xlatetom would not work.
+		     xlatetom does work when the in and out d_buf are equal (but not
+		     for any other overlap).  */
+		  if ((uintptr_t) data != (align == 8
+					   ? NOTE_ALIGN8 ((uintptr_t) data)
+					   : NOTE_ALIGN4 ((uintptr_t) data)))
+		    {
+		      memcpy (notes, data, filesz);
+		      xlatefrom.d_buf = notes;
+		    }
+
+                  if (elf32_xlatetom (&xlateto, &xlatefrom, xencoding) == NULL)
+                    {
+                      free (notes);
+                      finish_portion (&read_state, &data, &data_size);
+                      continue;
+                    }
+                }
+
+              const GElf_Nhdr *nh = notes;
+              size_t len = 0;
+              while (filesz - len > sizeof (*nh))
+                {
+		  len += sizeof (*nh);
+
+		  size_t namesz = nh->n_namesz;
+		  namesz = align == 8 ? NOTE_ALIGN8 (namesz) : NOTE_ALIGN4 (namesz);
+		  if (namesz > filesz - len || len + namesz < namesz)
+		    break;
+
+		  void *note_name = notes + len;
+		  len += namesz;
+
+		  size_t descsz = nh->n_descsz;
+		  descsz = align == 8 ? NOTE_ALIGN8 (descsz) : NOTE_ALIGN4 (descsz);
+		  if (descsz > filesz - len || len + descsz < descsz)
+		    break;
+
+		  void *note_desc = notes + len;
+		  len += descsz;
+
+		  /* We don't handle very short or really large build-ids.  We need at
+		     at least 3 and allow for up to 64 (normally ids are 20 long).  */
+#define MIN_BUILD_ID_BYTES 3
+#define MAX_BUILD_ID_BYTES 64
+		  if (nh->n_type == NT_GNU_BUILD_ID
+		      && nh->n_descsz >= MIN_BUILD_ID_BYTES
+		      && nh->n_descsz <= MAX_BUILD_ID_BYTES
+		      && nh->n_namesz == sizeof "GNU"
+		      && !memcmp (note_name, "GNU", sizeof "GNU"))
+		    {
+		      build_id.vaddr = (note_desc
+					- (const void *) notes
+					+ note_vaddr);
+		      build_id.len = nh->n_descsz;
+		      build_id.memory = malloc (build_id.len);
+		      if (likely (build_id.memory != NULL))
+			memcpy (build_id.memory, note_desc, build_id.len);
+		      break;
+		    }
+
+		  nh = (void *) notes + len;
+		}
+
+              if (notes != data)
+                free (notes);
+              finish_portion (&read_state, &data, &data_size);
+            }
+          else if (type == PT_LOAD)
+            {
+              align = (dwfl->segment_align > 1
+                       ? dwfl->segment_align : (align ?: 1));
+
+              GElf_Addr vaddr_end = (vaddr + memsz + align - 1) & -align;
+              GElf_Addr filesz_vaddr = (filesz < memsz
+                                        ? vaddr + filesz : vaddr_end);
+              GElf_Off filesz_offset = filesz_vaddr - vaddr + offset;
+
+              if (file_trimmed_end < offset + filesz)
+                {
+                  file_trimmed_end = offset + filesz;
+
+                  /* Trim the last segment so we don't bother with zeros
+                     in the last page that are off the end of the file.
+                     However, if the extra bit in that page includes the
+                     section headers, keep them.  */
+                  if (shdrs_end <= filesz_offset
+                      && shdrs_end > file_trimmed_end)
+                    {
+                      filesz += shdrs_end - file_trimmed_end;
+                      file_trimmed_end = shdrs_end;
+                    }
+                }
+
+              total_filesz += filesz;
+
+              if (file_end < filesz_offset)
+                {
+                  file_end = filesz_offset;
+                  if (filesz_vaddr - start == filesz_offset)
+                    contiguous = file_end;
+                }
+
+              if (!found_bias && (offset & -align) == 0
+                  && likely (filesz_offset >= phoff + phnum * phentsize))
+                {
+                  bias = start - vaddr;
+                  found_bias = true;
+                }
+
+              if ((vaddr & -align) < module_start)
+                {
+                  module_start = vaddr & -align;
+                  module_address_sync = vaddr + memsz;
+                }
+
+              if (module_end < vaddr_end)
+                module_end = vaddr_end;
+            }
+        }
+    }
+
+  finish_portion (&read_state, &ph_buffer, &ph_buffer_size);
+
+  /* We must have seen the segment covering offset 0, or else the ELF
+     header we read at START was not produced by these program headers.  */
+  if (unlikely (!found_bias))
+    goto out;
+
+  /* Now we know enough to report a module for sure: its bounds.  */
+  module_start += bias;
+  module_end += bias;
+
+  dyn_vaddr += bias;
+
+  /* NAME found from link map has precedence over DT_SONAME possibly read
+     below.  */
+  bool name_is_final = false;
+
+  /* Try to match up DYN_VADDR against L_LD as found in link map.
+     Segments sniffing may guess invalid address as the first read-only memory
+     mapping may not be dumped to the core file (if ELF headers are not dumped)
+     and the ELF header is dumped first with the read/write mapping of the same
+     file at higher addresses.  */
+  if (r_debug_info != NULL)
+    for (const struct r_debug_info_module *module = r_debug_info->module;
+	 module != NULL; module = module->next)
+      if (module_start <= module->l_ld && module->l_ld < module_end)
+	{
+	  /* L_LD read from link map must be right while DYN_VADDR is unsafe.
+	     Therefore subtract DYN_VADDR and add L_LD to get a possibly
+	     corrective displacement for all addresses computed so far.  */
+	  GElf_Addr fixup = module->l_ld - dyn_vaddr;
+	  if ((fixup & (dwfl->segment_align - 1)) == 0
+	      && module_start + fixup <= module->l_ld
+	      && module->l_ld < module_end + fixup)
+	    {
+	      module_start += fixup;
+	      module_end += fixup;
+	      dyn_vaddr += fixup;
+	      bias += fixup;
+	      if (module->name[0] != '\0')
+		{
+		  name = xbasename (module->name);
+		  name_is_final = true;
+		}
+	      break;
+	    }
+	}
+
+  if (r_debug_info != NULL)
+    {
+      bool skip_this_module = false;
+      for (struct r_debug_info_module *module = r_debug_info->module;
+	   module != NULL; module = module->next)
+	if ((module_end > module->start && module_start < module->end)
+	    || dyn_vaddr == module->l_ld)
+	  {
+	    if (module->elf != NULL
+	        && invalid_elf (module->elf, module->disk_file_has_build_id,
+				&build_id))
+	      {
+		/* If MODULE's build-id doesn't match the disk file's
+		   build-id, close ELF only if MODULE and ELF refer to
+		   different builds of files with the same name.  This
+		   prevents premature closure of the correct ELF in cases
+		   where segments of a module are non-contiguous in memory.  */
+		if (name != NULL && module->name[0] != '\0'
+		    && strcmp (xbasename (module->name), xbasename (name)) == 0)
+		  {
+		    elf_end (module->elf);
+		    close (module->fd);
+		    module->elf = NULL;
+		    module->fd = -1;
+		  }
+	      }
+	    else if (module->elf != NULL)
+	      {
+		/* This module has already been reported.  */
+		skip_this_module = true;
+	      }
+	    else
+	      {
+		/* Only report this module if we haven't already done so.  */
+		for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL;
+		     mod = mod->next)
+		  if (mod->low_addr == module_start
+		      && mod->high_addr == module_end)
+		    skip_this_module = true;
+	      }
+	  }
+      if (skip_this_module)
+	goto out;
+    }
+
+  const char *file_note_name = handle_file_note (module_start, module_end,
+						 ei_class, ei_data,
+						 note_file, note_file_size);
+  if (file_note_name)
+    {
+      name = file_note_name;
+      name_is_final = true;
+      bool invalid = false;
+      fd = open (name, O_RDONLY);
+      if (fd >= 0)
+	{
+	  Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
+	  if (error == DWFL_E_NOERROR)
+	    invalid = invalid_elf (elf, true /* disk_file_has_build_id */,
+                                   &build_id);
+	}
+      if (invalid)
+	{
+	  /* The file was there, but the build_id didn't match.  We
+	     still want to report the module, but need to get the ELF
+	     some other way if possible.  */
+	  close (fd);
+	  fd = -1;
+	  elf_end (elf);
+	  elf = NULL;
+	}
+    }
+
+  /* Examine its .dynamic section to get more interesting details.
+     If it has DT_SONAME, we'll use that as the module name.
+     If it has a DT_DEBUG, then it's actually a PIE rather than a DSO.
+     We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME,
+     and they also tell us the essential portion of the file
+     for fetching symbols.  */
+  GElf_Addr soname_stroff = 0;
+  GElf_Addr dynstr_vaddr = 0;
+  GElf_Xword dynstrsz = 0;
+  bool execlike = false;
+  const size_t dyn_entsize = (ei_class == ELFCLASS32
+			      ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
+  void *dyn_data = NULL;
+  size_t dyn_data_size = 0;
+  if (dyn_filesz != 0 && dyn_filesz % dyn_entsize == 0
+      && ! read_portion (&read_state, &dyn_data, &dyn_data_size,
+			 start, segment, dyn_vaddr, dyn_filesz))
+    {
+      if ((dyn_filesz / dyn_entsize) == 0
+	  || dyn_filesz > (SIZE_MAX / dyn_entsize))
+	goto out;
+      void *dyns = malloc (dyn_filesz);
+      Elf32_Dyn *d32 = dyns;
+      Elf64_Dyn *d64 = dyns;
+      if (unlikely (dyns == NULL))
+	goto out;
+
+      xlatefrom.d_type = xlateto.d_type = ELF_T_DYN;
+      xlatefrom.d_buf = (void *) dyn_data;
+      xlatefrom.d_size = dyn_filesz;
+      xlateto.d_buf = dyns;
+      xlateto.d_size = dyn_filesz;
+
+      /* dyn_data may be unaligned, in which case xlatetom would not work.
+	 xlatetom does work when the in and out d_buf are equal (but not
+	 for any other overlap).  */
+      bool is32 = (ei_class == ELFCLASS32);
+      size_t dyn_align = (is32
+			  ? __alignof__ (Elf32_Dyn)
+			  : __alignof__ (Elf64_Dyn));
+      if (((uintptr_t) dyn_data & (dyn_align - 1)) != 0)
+	{
+	  memcpy (dyns, dyn_data, dyn_filesz);
+	  xlatefrom.d_buf = dyns;
+	}
+
+      if ((is32 && elf32_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL)
+          || (!is32 && elf64_xlatetom (&xlateto, &xlatefrom, ei_data) != NULL))
+        {
+          size_t n = (is32
+		      ? (dyn_filesz / sizeof (Elf32_Dyn))
+		      : (dyn_filesz / sizeof (Elf64_Dyn)));
+          for (size_t i = 0; i < n; ++i)
+            {
+              GElf_Sxword tag = is32 ? d32[i].d_tag : d64[i].d_tag;
+              GElf_Xword val = is32 ? d32[i].d_un.d_val : d64[i].d_un.d_val;
+
+              if (tag == DT_DEBUG)
+                execlike = true;
+              else if (tag == DT_SONAME)
+                soname_stroff = val;
+              else if (tag == DT_STRTAB)
+                dynstr_vaddr = val;
+              else if (tag == DT_STRSZ)
+                dynstrsz = val;
+              else
+                continue;
+
+              if (soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0)
+                break;
+            }
+        }
+      free (dyns);
+    }
+  finish_portion (&read_state, &dyn_data, &dyn_data_size);
+
+  /* We'll use the name passed in or a stupid default if not DT_SONAME.  */
+  if (name == NULL)
+    name = e_type == ET_EXEC ? "[exe]" : execlike ? "[pie]" : "[dso]";
+
+  void *soname = NULL;
+  size_t soname_size = 0;
+  if (! name_is_final && dynstrsz != 0 && dynstr_vaddr != 0)
+    {
+      /* We know the bounds of the .dynstr section.
+
+	 The DYNSTR_VADDR pointer comes from the .dynamic section
+	 (DT_STRTAB, detected above).  Ordinarily the dynamic linker
+	 will have adjusted this pointer in place so it's now an
+	 absolute address.  But sometimes .dynamic is read-only (in
+	 vDSOs and odd architectures), and sometimes the adjustment
+	 just hasn't happened yet in the memory image we looked at.
+	 So treat DYNSTR_VADDR as an absolute address if it falls
+	 within the module bounds, or try applying the phdr bias
+	 when that adjusts it to fall within the module bounds.  */
+
+      if ((dynstr_vaddr < module_start || dynstr_vaddr >= module_end)
+	  && dynstr_vaddr + bias >= module_start
+	  && dynstr_vaddr + bias < module_end)
+	dynstr_vaddr += bias;
+
+      if (unlikely (dynstr_vaddr + dynstrsz > module_end))
+	dynstrsz = 0;
+
+      /* Try to get the DT_SONAME string.  */
+      if (soname_stroff != 0 && soname_stroff + 1 < dynstrsz
+	  && ! read_portion (&read_state, &soname, &soname_size,
+			     start, segment,
+			     dynstr_vaddr + soname_stroff, 0))
+	name = soname;
+    }
+
+  /* Now that we have chosen the module's name and bounds, report it.
+     If we found a build ID, report that too.  */
+
+  Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, name,
+						 module_start, module_end);
+
+  // !execlike && ET_EXEC is PIE.
+  // execlike && !ET_EXEC is a static executable.
+  if (mod != NULL && (execlike || ehdr.e32.e_type == ET_EXEC))
+    mod->is_executable = true;
+
+  if (likely (mod != NULL) && build_id.memory != NULL
+      && unlikely (INTUSE(dwfl_module_report_build_id) (mod,
+							build_id.memory,
+							build_id.len,
+							build_id.vaddr)))
+    {
+      mod->gc = true;
+      mod = NULL;
+    }
+
+  /* At this point we do not need BUILD_ID or NAME any more.
+     They have been copied.  */
+  free (build_id.memory);
+  build_id.memory = NULL;
+  finish_portion (&read_state, &soname, &soname_size);
+
+  if (unlikely (mod == NULL))
+    {
+      ndx = -1;
+      goto out;
+    }
+  else
+    ndx++;
+
+  /* We have reported the module.  Now let the caller decide whether we
+     should read the whole thing in right now.  */
+
+  const GElf_Off cost = (contiguous < file_trimmed_end ? total_filesz
+			 : buffer_available >= contiguous ? 0
+			 : contiguous - buffer_available);
+  const GElf_Off worthwhile = ((dynstr_vaddr == 0 || dynstrsz == 0) ? 0
+			       : dynstr_vaddr + dynstrsz - start);
+  const GElf_Off whole = MAX (file_trimmed_end, shdrs_end);
+
+  if (elf == NULL
+      && (*read_eagerly) (MODCB_ARGS (mod), &buffer, &buffer_available,
+			  cost, worthwhile, whole, contiguous,
+			  read_eagerly_arg, &elf)
+      && elf == NULL)
+    {
+      /* The caller wants to read the whole file in right now, but hasn't
+	 done it for us.  Fill in a local image of the virtual file.  */
+
+      if (file_trimmed_end > maxread)
+	file_trimmed_end = maxread;
+
+      void *contents = calloc (1, file_trimmed_end);
+      if (unlikely (contents == NULL))
+	goto out;
+
+      if (contiguous < file_trimmed_end)
+	{
+	  /* We can't use the memory image verbatim as the file image.
+	     So we'll be reading into a local image of the virtual file.  */
+          for (uint_fast16_t i = 0; i < phnum; ++i)
+            {
+              bool is32 = (ei_class == ELFCLASS32);
+              GElf_Word type = is32 ? p32[i].p_type : p64[i].p_type;
+
+              if (type != PT_LOAD)
+                continue;
+
+              GElf_Addr vaddr = is32 ? p32[i].p_vaddr : p64[i].p_vaddr;
+              GElf_Off offset = is32 ? p32[i].p_offset : p64[i].p_offset;
+              GElf_Xword filesz = is32 ? p32[i].p_filesz : p64[i].p_filesz;
+
+              /* Don't try to read beyond the actual end of file.  */
+              if (offset >= file_trimmed_end)
+                continue;
+
+              void *into = contents + offset;
+              size_t read_size = MIN (filesz, file_trimmed_end - offset);
+              (*memory_callback) (dwfl, addr_segndx (dwfl, segment,
+                                                     vaddr + bias, false),
+                                  &into, &read_size, vaddr + bias, read_size,
+                                  memory_callback_arg);
+            }
+	}
+      else
+	{
+	  /* The whole file sits contiguous in memory,
+	     but the caller didn't want to just do it.  */
+
+	  const size_t have = MIN (buffer_available, file_trimmed_end);
+	  memcpy (contents, buffer, have);
+
+	  if (have < file_trimmed_end)
+            {
+	      void *into = contents + have;
+	      size_t read_size = file_trimmed_end - have;
+	      (*memory_callback) (dwfl,
+				  addr_segndx (dwfl, segment,
+					       start + have, false),
+				  &into, &read_size, start + have,
+				  read_size, memory_callback_arg);
+            }
+	}
+
+      elf = elf_memory (contents, file_trimmed_end);
+      if (unlikely (elf == NULL))
+	free (contents);
+      else
+	elf->flags |= ELF_F_MALLOCED;
+    }
+
+  if (elf != NULL && mod->main.elf == NULL)
+    {
+      /* Install the file in the module.  */
+      mod->main.elf = elf;
+      mod->main.fd = fd;
+      elf = NULL;
+      fd = -1;
+      mod->main.vaddr = module_start - bias;
+      mod->main.address_sync = module_address_sync;
+      mod->main_bias = bias;
+    }
+
+out:
+  if (build_id.memory != NULL)
+    free (build_id.memory);
+  free (phdrsp);
+  if (buffer != NULL)
+    (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0,
+                        memory_callback_arg);
+
+  if (elf != NULL)
+    elf_end (elf);
+  if (fd != -1)
+    close (fd);
+  return ndx;
+}
diff --git a/libdwfl/dwfl_validate_address.c b/libdwfl/dwfl_validate_address.c
new file mode 100644
index 0000000..15e2602
--- /dev/null
+++ b/libdwfl/dwfl_validate_address.c
@@ -0,0 +1,65 @@
+/* Validate an address and the relocatability of an offset from it.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+int
+dwfl_validate_address (Dwfl *dwfl, Dwarf_Addr address, Dwarf_Sword offset)
+{
+  Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (dwfl, address);
+  if (mod == NULL)
+    return -1;
+
+  Dwarf_Addr relative = address;
+  int idx = INTUSE(dwfl_module_relocate_address) (mod, &relative);
+  if (idx < 0)
+    return -1;
+
+  if (offset != 0)
+    {
+      int offset_idx = -1;
+      relative = address + offset;
+      if (relative >= mod->low_addr && relative <= mod->high_addr)
+	{
+	  offset_idx = INTUSE(dwfl_module_relocate_address) (mod, &relative);
+	  if (offset_idx < 0)
+	    return -1;
+	}
+      if (offset_idx != idx)
+	{
+	  __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE);
+	  return -1;
+	}
+    }
+
+  return 0;
+}
diff --git a/libdwfl/dwfl_version.c b/libdwfl/dwfl_version.c
new file mode 100644
index 0000000..c27d4f6
--- /dev/null
+++ b/libdwfl/dwfl_version.c
@@ -0,0 +1,39 @@
+/* Return implementation's version string suitable for printing.
+   Copyright (C) 2006, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+const char *
+dwfl_version (Dwfl *dwfl __attribute__ ((unused)))
+{
+  return PACKAGE_VERSION;
+}
diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c
new file mode 100644
index 0000000..e9b330f
--- /dev/null
+++ b/libdwfl/elf-from-memory.c
@@ -0,0 +1,371 @@
+/* Reconstruct an ELF file by reading the segments out of remote memory.
+   Copyright (C) 2005-2011, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include "libelfP.h"
+
+#include "libdwflP.h"
+
+#include <gelf.h>
+#include <sys/types.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Reconstruct an ELF file by reading the segments out of remote memory
+   based on the ELF file header at EHDR_VMA and the ELF program headers it
+   points to.  If not null, *LOADBASEP is filled in with the difference
+   between the addresses from which the segments were read, and the
+   addresses the file headers put them at.
+
+   The function READ_MEMORY is called to copy at least MINREAD and at most
+   MAXREAD bytes from the remote memory at target address ADDRESS into the
+   local buffer at DATA; it should return -1 for errors (with code in
+   `errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
+   the number of bytes read if >= MINREAD.  ARG is passed through.
+
+   PAGESIZE is the minimum page size and alignment used for the PT_LOAD
+   segments.  */
+
+Elf *
+elf_from_remote_memory (GElf_Addr ehdr_vma,
+			GElf_Xword pagesize,
+			GElf_Addr *loadbasep,
+			ssize_t (*read_memory) (void *arg, void *data,
+						GElf_Addr address,
+						size_t minread,
+						size_t maxread),
+			void *arg)
+{
+  /* We might have to reserve some memory for the phdrs.  Set to NULL
+     here so we can always safely free it.  */
+  void *phdrsp = NULL;
+
+  /* First read in the file header and check its sanity.  */
+
+  const size_t initial_bufsize = 256;
+  unsigned char *buffer = malloc (initial_bufsize);
+  if (unlikely (buffer == NULL))
+    {
+    no_memory:
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return NULL;
+    }
+
+  ssize_t nread = (*read_memory) (arg, buffer, ehdr_vma,
+				  sizeof (Elf32_Ehdr), initial_bufsize);
+  if (nread <= 0)
+    {
+    read_error:
+      free (buffer);
+      free (phdrsp);
+      __libdwfl_seterrno (nread < 0 ? DWFL_E_ERRNO : DWFL_E_TRUNCATED);
+      return NULL;
+    }
+
+  if (memcmp (buffer, ELFMAG, SELFMAG) != 0)
+    {
+    bad_elf:
+      free (buffer);
+      free (phdrsp);
+      __libdwfl_seterrno (DWFL_E_BADELF);
+      return NULL;
+    }
+
+  /* Extract the information we need from the file header.  */
+
+  union
+  {
+    Elf32_Ehdr e32;
+    Elf64_Ehdr e64;
+  } ehdr;
+  Elf_Data xlatefrom =
+    {
+      .d_type = ELF_T_EHDR,
+      .d_buf = buffer,
+      .d_version = EV_CURRENT,
+    };
+  Elf_Data xlateto =
+    {
+      .d_type = ELF_T_EHDR,
+      .d_buf = &ehdr,
+      .d_size = sizeof ehdr,
+      .d_version = EV_CURRENT,
+    };
+
+  GElf_Off phoff;
+  uint_fast16_t phnum;
+  uint_fast16_t phentsize;
+  GElf_Off shdrs_end;
+
+  switch (buffer[EI_CLASS])
+    {
+    case ELFCLASS32:
+      xlatefrom.d_size = sizeof (Elf32_Ehdr);
+      if (elf32_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
+	{
+	libelf_error:
+	  __libdwfl_seterrno (DWFL_E_LIBELF);
+	  return NULL;
+	}
+      phoff = ehdr.e32.e_phoff;
+      phnum = ehdr.e32.e_phnum;
+      phentsize = ehdr.e32.e_phentsize;
+      if (phentsize != sizeof (Elf32_Phdr) || phnum == 0)
+	goto bad_elf;
+      /* NOTE if the number of sections is > 0xff00 then e_shnum
+	 is zero and the actual number would come from the section
+	 zero sh_size field. We ignore this here because getting shdrs
+	 is just a nice bonus (see below where we trim the last phdrs
+	 PT_LOAD segment).  */
+      shdrs_end = ehdr.e32.e_shoff + ehdr.e32.e_shnum * ehdr.e32.e_shentsize;
+      break;
+
+    case ELFCLASS64:
+      xlatefrom.d_size = sizeof (Elf64_Ehdr);
+      if (elf64_xlatetom (&xlateto, &xlatefrom, buffer[EI_DATA]) == NULL)
+	goto libelf_error;
+      phoff = ehdr.e64.e_phoff;
+      phnum = ehdr.e64.e_phnum;
+      phentsize = ehdr.e64.e_phentsize;
+      if (phentsize != sizeof (Elf64_Phdr) || phnum == 0)
+	goto bad_elf;
+      /* See the NOTE above for shdrs_end and ehdr.e32.e_shnum.  */
+      shdrs_end = ehdr.e64.e_shoff + ehdr.e64.e_shnum * ehdr.e64.e_shentsize;
+      break;
+
+    default:
+      goto bad_elf;
+    }
+
+
+  /* The file header tells where to find the program headers.
+     These are what we use to actually choose what to read.  */
+
+  xlatefrom.d_type = xlateto.d_type = ELF_T_PHDR;
+  xlatefrom.d_size = phnum * phentsize;
+
+  if ((size_t) nread >= phoff + phnum * phentsize)
+    /* We already have all the phdrs from the initial read.  */
+    xlatefrom.d_buf = buffer + phoff;
+  else
+    {
+      /* Read in the program headers.  */
+
+      if (initial_bufsize < (size_t)phnum * phentsize)
+	{
+	  unsigned char *newbuf = realloc (buffer, phnum * phentsize);
+	  if (newbuf == NULL)
+	    {
+	      free (buffer);
+	      free (phdrsp);
+	      goto no_memory;
+	    }
+	  buffer = newbuf;
+	}
+      nread = (*read_memory) (arg, buffer, ehdr_vma + phoff,
+			      phnum * phentsize, phnum * phentsize);
+      if (nread <= 0)
+	goto read_error;
+
+      xlatefrom.d_buf = buffer;
+    }
+
+  bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
+  size_t phdr_size = class32 ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr);
+  if (unlikely (phnum > SIZE_MAX / phdr_size))
+    {
+      free (buffer);
+      goto no_memory;
+    }
+  const size_t phdrsp_bytes = phnum * phdr_size;
+  phdrsp = malloc (phdrsp_bytes);
+  if (unlikely (phdrsp == NULL))
+    {
+      free (buffer);
+      goto no_memory;
+    }
+
+  xlateto.d_buf = phdrsp;
+  xlateto.d_size = phdrsp_bytes;
+
+  /* Scan for PT_LOAD segments to find the total size of the file image.  */
+  size_t contents_size = 0;
+  GElf_Off segments_end = 0;
+  GElf_Off segments_end_mem = 0;
+  GElf_Addr loadbase = ehdr_vma;
+  bool found_base = false;
+  Elf32_Phdr (*p32)[phnum] = phdrsp;
+  Elf64_Phdr (*p64)[phnum] = phdrsp;
+
+  if (class32)
+    {
+      if (! elf32_xlatetom (&xlateto, &xlatefrom, ehdr.e32.e_ident[EI_DATA]))
+        goto libelf_error;
+    }
+  else
+    {
+      if (! elf64_xlatetom (&xlateto, &xlatefrom, ehdr.e64.e_ident[EI_DATA]))
+        goto libelf_error;
+    }
+
+  for (uint_fast16_t i = 0; i < phnum; ++i)
+    {
+      GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
+
+      if (type != PT_LOAD)
+        continue;
+
+      GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
+      GElf_Xword memsz = class32 ? (*p32)[i].p_memsz : (*p64)[i].p_memsz;
+      GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
+      GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
+
+      /* Sanity check the segment load aligns with the pagesize.  */
+      if (((vaddr - offset) & (pagesize - 1)) != 0)
+        goto bad_elf;
+
+      GElf_Off segment_end = ((offset + filesz + pagesize - 1)
+                              & -pagesize);
+
+      if (segment_end > (GElf_Off) contents_size)
+        contents_size = segment_end;
+
+      if (!found_base && (offset & -pagesize) == 0)
+        {
+          loadbase = ehdr_vma - (vaddr & -pagesize);
+          found_base = true;
+        }
+
+      segments_end = offset + filesz;
+      segments_end_mem = offset + memsz;
+    }
+
+  /* Trim the last segment so we don't bother with zeros in the last page
+     that are off the end of the file.  However, if the extra bit in that
+     page includes the section headers and the memory isn't extended (which
+     might indicate it will have been reused otherwise), keep them.  */
+  if ((GElf_Off) contents_size > segments_end
+      && (GElf_Off) contents_size >= shdrs_end
+      && segments_end == segments_end_mem)
+    {
+      contents_size = segments_end;
+      if ((GElf_Off) contents_size < shdrs_end)
+	contents_size = shdrs_end;
+    }
+  else
+    contents_size = segments_end;
+
+  free (buffer);
+
+  /* Now we know the size of the whole image we want read in.  */
+  buffer = calloc (1, contents_size);
+  if (buffer == NULL)
+    {
+      free (phdrsp);
+      goto no_memory;
+    }
+
+  for (uint_fast16_t i = 0; i < phnum; ++i)
+    {
+      GElf_Word type = class32 ? (*p32)[i].p_type : (*p64)[i].p_type;
+
+      if (type != PT_LOAD)
+        continue;
+
+      GElf_Addr vaddr = class32 ? (*p32)[i].p_vaddr : (*p64)[i].p_vaddr;
+      GElf_Off offset = class32 ? (*p32)[i].p_offset : (*p64)[i].p_offset;
+      GElf_Xword filesz = class32 ? (*p32)[i].p_filesz : (*p64)[i].p_filesz;
+
+      GElf_Off start = offset & -pagesize;
+      GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize;
+      if (end > (GElf_Off) contents_size)
+        end = contents_size;
+      nread = (*read_memory) (arg, buffer + start,
+                              (loadbase + vaddr) & -pagesize,
+                              end - start, end - start);
+      if (nread <= 0)
+        goto read_error;
+    }
+
+  /* If the segments visible in memory didn't include the section
+     headers, then clear them from the file header.  */
+  if (contents_size < shdrs_end)
+    {
+      if (class32)
+        {
+          ehdr.e32.e_shoff = 0;
+          ehdr.e32.e_shnum = 0;
+          ehdr.e32.e_shstrndx = 0;
+        }
+      else
+        {
+          ehdr.e64.e_shoff = 0;
+          ehdr.e64.e_shnum = 0;
+          ehdr.e64.e_shstrndx = 0;
+        }
+    }
+
+  /* This will normally have been in the first PT_LOAD segment.  But it
+     conceivably could be missing, and we might have just changed it.  */
+  xlatefrom.d_type = xlateto.d_type = ELF_T_EHDR;
+  xlateto.d_buf = buffer;
+  if (class32)
+    {
+      xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e32;
+      xlatefrom.d_buf = &ehdr.e32;
+      if (elf32_xlatetof (&xlateto, &xlatefrom,
+                          ehdr.e32.e_ident[EI_DATA]) == NULL)
+        goto libelf_error;
+    }
+  else
+    {
+      xlatefrom.d_size = xlateto.d_size = sizeof ehdr.e64;
+      xlatefrom.d_buf = &ehdr.e64;
+      if (elf64_xlatetof (&xlateto, &xlatefrom,
+                          ehdr.e64.e_ident[EI_DATA]) == NULL)
+        goto libelf_error;
+    }
+
+  free (phdrsp);
+  phdrsp = NULL;
+
+  /* Now we have the image.  Open libelf on it.  */
+
+  Elf *elf = elf_memory ((char *) buffer, contents_size);
+  if (elf == NULL)
+    {
+      free (buffer);
+      goto libelf_error;
+    }
+
+  elf->flags |= ELF_F_MALLOCED;
+  if (loadbasep != NULL)
+    *loadbasep = loadbase;
+  return elf;
+}
diff --git a/libdwfl/find-debuginfo.c b/libdwfl/find-debuginfo.c
new file mode 100644
index 0000000..b358c77
--- /dev/null
+++ b/libdwfl/find-debuginfo.c
@@ -0,0 +1,429 @@
+/* Standard find_debuginfo callback for libdwfl.
+   Copyright (C) 2005-2010, 2014, 2015, 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "system.h"
+
+
+/* Try to open [DIR/][SUBDIR/]DEBUGLINK, return file descriptor or -1.
+   On success, *DEBUGINFO_FILE_NAME has the malloc'd name of the open file.  */
+static int
+try_open (const struct stat *main_stat,
+	  const char *dir, const char *subdir, const char *debuglink,
+	  char **debuginfo_file_name)
+{
+  char *fname;
+  if (dir == NULL && subdir == NULL)
+    {
+      fname = strdup (debuglink);
+      if (unlikely (fname == NULL))
+	return -1;
+    }
+  else if ((subdir == NULL ? asprintf (&fname, "%s/%s", dir, debuglink)
+	    : dir == NULL ? asprintf (&fname, "%s/%s", subdir, debuglink)
+	    : asprintf (&fname, "%s/%s/%s", dir, subdir, debuglink)) < 0)
+    return -1;
+
+  struct stat st;
+  int fd = TEMP_FAILURE_RETRY (open (fname, O_RDONLY));
+  if (fd < 0)
+    free (fname);
+  else if (fstat (fd, &st) == 0
+	   && st.st_ino == main_stat->st_ino
+	   && st.st_dev == main_stat->st_dev)
+    {
+      /* This is the main file by another name.  Don't look at it again.  */
+      free (fname);
+      close (fd);
+      errno = ENOENT;
+      fd = -1;
+    }
+  else
+    *debuginfo_file_name = fname;
+
+  return fd;
+}
+
+/* Return true iff the FD's contents CRC matches DEBUGLINK_CRC.  */
+static inline bool
+check_crc (int fd, GElf_Word debuglink_crc)
+{
+  uint32_t file_crc;
+  return (__libdwfl_crc32_file (fd, &file_crc) == 0
+	  && file_crc == debuglink_crc);
+}
+
+static bool
+validate (Dwfl_Module *mod, int fd, bool check, GElf_Word debuglink_crc)
+{
+  /* For alt debug files always check the build-id from the Dwarf and alt.  */
+  if (mod->dw != NULL)
+    {
+      bool valid = false;
+      const void *build_id;
+      const char *altname;
+      ssize_t build_id_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw,
+								   &altname,
+								   &build_id);
+      if (build_id_len > 0)
+	{
+	  /* We need to open an Elf handle on the file so we can check its
+	     build ID note for validation.  Backdoor the handle into the
+	     module data structure since we had to open it early anyway.  */
+	  Dwfl_Error error = __libdw_open_file (&fd, &mod->alt_elf,
+						false, false);
+	  if (error != DWFL_E_NOERROR)
+	    __libdwfl_seterrno (error);
+	  else
+	    {
+	      const void *alt_build_id;
+	      ssize_t alt_len = INTUSE(dwelf_elf_gnu_build_id) (mod->alt_elf,
+								&alt_build_id);
+	      if (alt_len > 0 && alt_len == build_id_len
+		  && memcmp (build_id, alt_build_id, alt_len) == 0)
+		valid = true;
+	      else
+		{
+		  /* A mismatch!  */
+		  elf_end (mod->alt_elf);
+		  mod->alt_elf = NULL;
+		  close (fd);
+		  fd = -1;
+		}
+	    }
+	}
+      return valid;
+    }
+
+  /* If we have a build ID, check only that.  */
+  if (mod->build_id_len > 0)
+    {
+      /* We need to open an Elf handle on the file so we can check its
+	 build ID note for validation.  Backdoor the handle into the
+	 module data structure since we had to open it early anyway.  */
+
+      mod->debug.valid = false;
+      Dwfl_Error error = __libdw_open_file (&fd, &mod->debug.elf, false, false);
+      if (error != DWFL_E_NOERROR)
+	__libdwfl_seterrno (error);
+      else if (likely (__libdwfl_find_build_id (mod, false,
+						mod->debug.elf) == 2))
+	/* Also backdoor the gratuitous flag.  */
+	mod->debug.valid = true;
+      else
+	{
+	  /* A mismatch!  */
+	  elf_end (mod->debug.elf);
+	  mod->debug.elf = NULL;
+	  close (fd);
+	  fd = -1;
+	}
+
+      return mod->debug.valid;
+    }
+
+  return !check || check_crc (fd, debuglink_crc);
+}
+
+static int
+find_debuginfo_in_path (Dwfl_Module *mod, const char *file_name,
+			const char *debuglink_file, GElf_Word debuglink_crc,
+			char **debuginfo_file_name)
+{
+  bool cancheck = debuglink_crc != (GElf_Word) 0;
+
+  const char *file_basename = file_name == NULL ? NULL : xbasename (file_name);
+  char *localname = NULL;
+
+  /* We invent a debuglink .debug name if NULL, but then want to try the
+     basename too.  */
+  bool debuglink_null = debuglink_file == NULL;
+  if (debuglink_null)
+    {
+      /* For a alt debug multi file we need a name, for a separate debug
+	 name we may be able to fall back on file_basename.debug.  */
+      if (file_basename == NULL || mod->dw != NULL)
+	{
+	  errno = 0;
+	  return -1;
+	}
+
+      size_t len = strlen (file_basename);
+      localname = malloc (len + sizeof ".debug");
+      if (unlikely (localname == NULL))
+	return -1;
+      memcpy (localname, file_basename, len);
+      memcpy (&localname[len], ".debug", sizeof ".debug");
+      debuglink_file = localname;
+      cancheck = false;
+    }
+
+  /* Look for a file named DEBUGLINK_FILE in the directories
+     indicated by the debug directory path setting.  */
+
+  const Dwfl_Callbacks *const cb = mod->dwfl->callbacks;
+  char *localpath = strdup ((cb->debuginfo_path ? *cb->debuginfo_path : NULL)
+			    ?: DEFAULT_DEBUGINFO_PATH);
+  if (unlikely (localpath == NULL))
+    {
+      free (localname);
+      return -1;
+    }
+
+  /* A leading - or + in the whole path sets whether to check file CRCs.  */
+  bool defcheck = true;
+  char *path = localpath;
+  if (path[0] == '-' || path[0] == '+')
+    {
+      defcheck = path[0] == '+';
+      ++path;
+    }
+
+  /* XXX dev/ino should be cached in struct dwfl_file.  */
+  struct stat main_stat;
+  if (unlikely ((mod->main.fd != -1 ? fstat (mod->main.fd, &main_stat)
+		 : file_name != NULL ? stat (file_name, &main_stat)
+		 : -1) < 0))
+    {
+      main_stat.st_dev = 0;
+      main_stat.st_ino = 0;
+    }
+
+  char *file_dirname = (file_basename == file_name ? NULL
+			: strndup (file_name, file_basename - 1 - file_name));
+  if (file_basename != file_name && file_dirname == NULL)
+    {
+      free (localpath);
+      free (localname);
+      return -1;
+    }
+  char *p;
+  while ((p = strsep (&path, ":")) != NULL)
+    {
+      /* A leading - or + says whether to check file CRCs for this element.  */
+      bool check = defcheck;
+      if (*p == '+' || *p == '-')
+	check = *p++ == '+';
+      check = check && cancheck;
+
+      /* Try the basename too, if we made up the debuglink name and this
+	 is not the main directory.  */
+      bool try_file_basename;
+
+      const char *dir, *subdir, *file;
+      switch (p[0])
+	{
+	case '\0':
+	  /* An empty entry says to try the main file's directory.  */
+	  dir = file_dirname;
+	  subdir = NULL;
+	  file = debuglink_file;
+	  try_file_basename = false;
+	  break;
+	case '/':
+	  /* An absolute path says to look there for a subdirectory
+	     named by the main file's absolute directory.  This cannot
+	     be applied to a relative file name.  For alt debug files
+	     it means to look for the basename file in that dir or the
+	     .dwz subdir (see below).  */
+	  if (mod->dw == NULL
+	      && (file_dirname == NULL || file_dirname[0] != '/'))
+	    continue;
+	  dir = p;
+	  if (mod->dw == NULL)
+	    {
+	      subdir = file_dirname;
+	      /* We want to explore all sub-subdirs.  Chop off one slash
+		 at a time.  */
+	    explore_dir:
+	      subdir = strchr (subdir, '/');
+	      if (subdir != NULL)
+		subdir = subdir + 1;
+	      if (subdir && *subdir == 0)
+		continue;
+	      file = debuglink_file;
+	    }
+	  else
+	    {
+	      subdir = NULL;
+	      file = xbasename (debuglink_file);
+	    }
+	  try_file_basename = debuglink_null;
+	  break;
+	default:
+	  /* A relative path says to try a subdirectory of that name
+	     in the main file's directory.  */
+	  dir = file_dirname;
+	  subdir = p;
+	  file = debuglink_file;
+	  try_file_basename = debuglink_null;
+	  break;
+	}
+
+      char *fname = NULL;
+      int fd = try_open (&main_stat, dir, subdir, file, &fname);
+      if (fd < 0 && try_file_basename)
+	fd = try_open (&main_stat, dir, subdir, file_basename, &fname);
+      if (fd < 0)
+	switch (errno)
+	  {
+	  case ENOENT:
+	  case ENOTDIR:
+	    /* If we are looking for the alt file also try the .dwz subdir.
+	       But only if this is the empty or absolute path.  */
+	    if (mod->dw != NULL && (p[0] == '\0' || p[0] == '/'))
+	      {
+		fd = try_open (&main_stat, dir, ".dwz",
+			       xbasename (file), &fname);
+		if (fd < 0)
+		  {
+		    if (errno != ENOENT && errno != ENOTDIR)
+		      goto fail_free;
+		    else
+		      continue;
+		  }
+		break;
+	      }
+	    /* If possible try again with a sub-subdir.  */
+	    if (mod->dw == NULL && subdir)
+	      goto explore_dir;
+	    continue;
+	  default:
+	    goto fail_free;
+	  }
+      if (validate (mod, fd, check, debuglink_crc))
+	{
+	  free (localpath);
+	  free (localname);
+	  free (file_dirname);
+	  *debuginfo_file_name = fname;
+	  return fd;
+	}
+      free (fname);
+      close (fd);
+    }
+
+  /* No dice.  */
+  errno = 0;
+fail_free:
+  free (localpath);
+  free (localname);
+  free (file_dirname);
+  return -1;
+}
+
+int
+dwfl_standard_find_debuginfo (Dwfl_Module *mod,
+			      void **userdata __attribute__ ((unused)),
+			      const char *modname __attribute__ ((unused)),
+			      GElf_Addr base __attribute__ ((unused)),
+			      const char *file_name,
+			      const char *debuglink_file,
+			      GElf_Word debuglink_crc,
+			      char **debuginfo_file_name)
+{
+  if (mod == NULL)
+    return -1;
+
+  /* First try by build ID if we have one.  If that succeeds or fails
+     other than just by finding nothing, that's all we do.  */
+  const unsigned char *bits = NULL;
+  GElf_Addr vaddr;
+  int bits_len;
+  if ((bits_len = INTUSE(dwfl_module_build_id) (mod, &bits, &vaddr)) > 0)
+    {
+      /* Dropping most arguments means we cannot rely on them in
+	 dwfl_build_id_find_debuginfo.  But leave it that way since
+	 some user code out there also does this, so we'll have to
+	 handle it anyway.  */
+      int fd = INTUSE(dwfl_build_id_find_debuginfo) (mod,
+						     NULL, NULL, 0,
+						     NULL, NULL, 0,
+						     debuginfo_file_name);
+
+      /* Did the build_id callback find something or report an error?
+         Then we are done.  Otherwise fallback on path based search.  */
+      if (fd >= 0
+	  || (mod->dw == NULL && mod->debug.elf != NULL)
+	  || (mod->dw != NULL && mod->alt_elf != NULL)
+	  || errno != 0)
+	return fd;
+    }
+
+  /* Failing that, search the path by name.  */
+  int fd = find_debuginfo_in_path (mod, file_name,
+				   debuglink_file, debuglink_crc,
+				   debuginfo_file_name);
+
+  if (fd < 0 && errno == 0 && file_name != NULL)
+    {
+      /* If FILE_NAME is a symlink, the debug file might be associated
+	 with the symlink target name instead.  */
+
+      char *canon = realpath (file_name, NULL);
+      if (canon != NULL && strcmp (file_name, canon))
+	fd = find_debuginfo_in_path (mod, canon,
+				     debuglink_file, debuglink_crc,
+				     debuginfo_file_name);
+      free (canon);
+    }
+
+#ifdef ENABLE_LIBDEBUGINFOD
+  /* Still nothing? Try if we can use the debuginfod client.
+     But note that we might be looking for the alt file.
+     We use the same trick as dwfl_build_id_find_debuginfo.
+     If the debug file (dw) is already set, then we must be
+     looking for the altfile. But we cannot use the actual
+     file/path name given as hint. We'll have to lookup the
+     alt file "build-id". Because the debuginfod client only
+     handles build-ids.  */
+  if (fd < 0)
+    {
+      if (mod->dw != NULL)
+	{
+	  const char *altname;
+	  bits_len = INTUSE(dwelf_dwarf_gnu_debugaltlink) (mod->dw, &altname,
+							   (const void **)
+							   &bits);
+	}
+
+      if (bits_len > 0)
+	fd = __libdwfl_debuginfod_find_debuginfo (mod->dwfl, bits, bits_len);
+    }
+#endif
+
+  return fd;
+}
+INTDEF (dwfl_standard_find_debuginfo)
diff --git a/libdwfl/frame_unwind.c b/libdwfl/frame_unwind.c
new file mode 100644
index 0000000..1e2f025
--- /dev/null
+++ b/libdwfl/frame_unwind.c
@@ -0,0 +1,767 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2013, 2014, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "cfi.h"
+#include <stdlib.h>
+#include "libdwflP.h"
+#include "dwarf.h"
+#include <system.h>
+
+/* Maximum number of DWARF expression stack slots before returning an error.  */
+#define DWARF_EXPR_STACK_MAX 0x100
+
+/* Maximum number of DWARF expression executed operations before returning an
+   error.  */
+#define DWARF_EXPR_STEPS_MAX 0x1000
+
+int
+internal_function
+__libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno, Dwarf_Addr *val)
+{
+  Ebl *ebl = state->thread->process->ebl;
+  if (! ebl_dwarf_to_regno (ebl, &regno))
+    return -1;
+  if (regno >= ebl_frame_nregs (ebl))
+    return -1;
+  if ((state->regs_set[regno / sizeof (*state->regs_set) / 8]
+       & ((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)))) == 0)
+    return 1;
+  if (val)
+    *val = state->regs[regno];
+  return 0;
+}
+
+bool
+internal_function
+__libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno, Dwarf_Addr val)
+{
+  Ebl *ebl = state->thread->process->ebl;
+  if (! ebl_dwarf_to_regno (ebl, &regno))
+    return false;
+  if (regno >= ebl_frame_nregs (ebl))
+    return false;
+  /* For example i386 user_regs_struct has signed fields.  */
+  if (ebl_get_elfclass (ebl) == ELFCLASS32)
+    val &= 0xffffffff;
+  state->regs_set[regno / sizeof (*state->regs_set) / 8] |=
+		((uint64_t) 1U << (regno % (sizeof (*state->regs_set) * 8)));
+  state->regs[regno] = val;
+  return true;
+}
+
+static int
+bra_compar (const void *key_voidp, const void *elem_voidp)
+{
+  Dwarf_Word offset = (uintptr_t) key_voidp;
+  const Dwarf_Op *op = elem_voidp;
+  return (offset > op->offset) - (offset < op->offset);
+}
+
+struct eval_stack {
+  Dwarf_Addr *addrs;
+  size_t used;
+  size_t allocated;
+};
+
+static bool
+do_push (struct eval_stack *stack, Dwarf_Addr val)
+{
+  if (stack->used >= DWARF_EXPR_STACK_MAX)
+    {
+      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+      return false;
+    }
+  if (stack->used == stack->allocated)
+    {
+      stack->allocated = MAX (stack->allocated * 2, 32);
+      Dwarf_Addr *new_addrs;
+      new_addrs = realloc (stack->addrs,
+			   stack->allocated * sizeof (*stack->addrs));
+      if (new_addrs == NULL)
+        {
+          __libdwfl_seterrno (DWFL_E_NOMEM);
+          return false;
+        }
+      stack->addrs = new_addrs;
+    }
+  stack->addrs[stack->used++] = val;
+  return true;
+}
+
+static bool
+do_pop (struct eval_stack *stack, Dwarf_Addr *val)
+{
+  if (stack->used == 0)
+    {
+      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+      return false;
+    }
+  *val = stack->addrs[--stack->used];
+  return true;
+}
+
+/* If FRAME is NULL is are computing CFI frame base.  In such case another
+   DW_OP_call_frame_cfa is no longer permitted.  */
+
+static bool
+expr_eval (Dwfl_Frame *state, Dwarf_Frame *frame, const Dwarf_Op *ops,
+	   size_t nops, Dwarf_Addr *result, Dwarf_Addr bias)
+{
+  Dwfl_Process *process = state->thread->process;
+  if (nops == 0)
+    {
+      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+      return false;
+    }
+  struct eval_stack stack =
+    {
+      .addrs = NULL,
+      .used = 0,
+      .allocated = 0
+    };
+
+#define pop(x) do_pop(&stack, x)
+#define push(x) do_push(&stack, x)
+
+  Dwarf_Addr val1, val2;
+  bool is_location = false;
+  size_t steps_count = 0;
+  for (const Dwarf_Op *op = ops; op < ops + nops; op++)
+    {
+      if (++steps_count > DWARF_EXPR_STEPS_MAX)
+	{
+	  __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	  return false;
+	}
+      switch (op->atom)
+      {
+	/* DW_OP_* order matches libgcc/unwind-dw2.c execute_stack_op:  */
+	case DW_OP_lit0 ... DW_OP_lit31:
+	  if (! push (op->atom - DW_OP_lit0))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_addr:
+	  if (! push (op->number + bias))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_GNU_encoded_addr:
+	  /* Missing support in the rest of elfutils.  */
+	  __libdwfl_seterrno (DWFL_E_UNSUPPORTED_DWARF);
+	  return false;
+	case DW_OP_const1u:
+	case DW_OP_const1s:
+	case DW_OP_const2u:
+	case DW_OP_const2s:
+	case DW_OP_const4u:
+	case DW_OP_const4s:
+	case DW_OP_const8u:
+	case DW_OP_const8s:
+	case DW_OP_constu:
+	case DW_OP_consts:
+	  if (! push (op->number))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_reg0 ... DW_OP_reg31:
+	  if (INTUSE (dwfl_frame_reg) (state, op->atom - DW_OP_reg0, &val1) != 0
+	      || ! push (val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_regx:
+	  if (INTUSE (dwfl_frame_reg) (state, op->number, &val1) != 0 || ! push (val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_breg0 ... DW_OP_breg31:
+	  if (INTUSE (dwfl_frame_reg) (state, op->atom - DW_OP_breg0, &val1) != 0)
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  val1 += op->number;
+	  if (! push (val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_bregx:
+	  if (INTUSE (dwfl_frame_reg) (state, op->number, &val1) != 0)
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  val1 += op->number2;
+	  if (! push (val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_dup:
+	  if (! pop (&val1) || ! push (val1) || ! push (val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_drop:
+	  if (! pop (&val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_pick:
+	  if (stack.used <= op->number)
+	    {
+	      free (stack.addrs);
+	      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	      return false;
+	    }
+	  if (! push (stack.addrs[stack.used - 1 - op->number]))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_over:
+	  if (! pop (&val1) || ! pop (&val2)
+	      || ! push (val2) || ! push (val1) || ! push (val2))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_swap:
+	  if (! pop (&val1) || ! pop (&val2) || ! push (val1) || ! push (val2))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	case DW_OP_rot:
+	  {
+	    Dwarf_Addr val3;
+	    if (! pop (&val1) || ! pop (&val2) || ! pop (&val3)
+		|| ! push (val1) || ! push (val3) || ! push (val2))
+	      {
+		free (stack.addrs);
+		return false;
+	      }
+	  }
+	  break;
+	case DW_OP_deref:
+	case DW_OP_deref_size:
+	  if (process->callbacks->memory_read == NULL)
+	    {
+	      free (stack.addrs);
+	      __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+	      return false;
+	    }
+	  if (! pop (&val1)
+	      || ! process->callbacks->memory_read (process->dwfl, val1, &val1,
+						    process->callbacks_arg))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  if (op->atom == DW_OP_deref_size)
+	    {
+	      const int elfclass = frame->cache->e_ident[EI_CLASS];
+	      const unsigned addr_bytes = elfclass == ELFCLASS32 ? 4 : 8;
+	      if (op->number > addr_bytes)
+		{
+		  free (stack.addrs);
+		  __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+		  return false;
+		}
+#if BYTE_ORDER == BIG_ENDIAN
+	      if (op->number == 0)
+		val1 = 0;
+	      else
+		val1 >>= (addr_bytes - op->number) * 8;
+#else
+	      if (op->number < 8)
+		val1 &= (1ULL << (op->number * 8)) - 1;
+#endif
+	    }
+	  if (! push (val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+#define UNOP(atom, expr)						\
+	case atom:							\
+	  if (! pop (&val1) || ! push (expr))				\
+	    {								\
+	      free (stack.addrs);					\
+	      return false;						\
+	    }								\
+	  break;
+	UNOP (DW_OP_abs, llabs ((int64_t) val1))
+	UNOP (DW_OP_neg, -(int64_t) val1)
+	UNOP (DW_OP_not, ~val1)
+#undef UNOP
+	case DW_OP_plus_uconst:
+	  if (! pop (&val1) || ! push (val1 + op->number))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+#define BINOP(atom, op)							\
+	case atom:							\
+	  if (! pop (&val2) || ! pop (&val1) || ! push (val1 op val2))	\
+	    {								\
+	      free (stack.addrs);					\
+	      return false;						\
+	    }								\
+	  break;
+#define BINOP_SIGNED(atom, op)						\
+	case atom:							\
+	  if (! pop (&val2) || ! pop (&val1)				\
+	      || ! push ((int64_t) val1 op (int64_t) val2))		\
+	    {								\
+	      free (stack.addrs);					\
+	      return false;						\
+	    }								\
+	  break;
+	BINOP (DW_OP_and, &)
+	case DW_OP_div:
+	  if (! pop (&val2) || ! pop (&val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  if (val2 == 0)
+	    {
+	      free (stack.addrs);
+	      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	      return false;
+	    }
+	  if (! push ((int64_t) val1 / (int64_t) val2))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	BINOP (DW_OP_minus, -)
+	case DW_OP_mod:
+	  if (! pop (&val2) || ! pop (&val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  if (val2 == 0)
+	    {
+	      free (stack.addrs);
+	      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	      return false;
+	    }
+	  if (! push (val1 % val2))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  break;
+	BINOP (DW_OP_mul, *)
+	BINOP (DW_OP_or, |)
+	BINOP (DW_OP_plus, +)
+	BINOP (DW_OP_shl, <<)
+	BINOP (DW_OP_shr, >>)
+	BINOP_SIGNED (DW_OP_shra, >>)
+	BINOP (DW_OP_xor, ^)
+	BINOP_SIGNED (DW_OP_le, <=)
+	BINOP_SIGNED (DW_OP_ge, >=)
+	BINOP_SIGNED (DW_OP_eq, ==)
+	BINOP_SIGNED (DW_OP_lt, <)
+	BINOP_SIGNED (DW_OP_gt, >)
+	BINOP_SIGNED (DW_OP_ne, !=)
+#undef BINOP
+#undef BINOP_SIGNED
+	case DW_OP_bra:
+	  if (! pop (&val1))
+	    {
+	      free (stack.addrs);
+	      return false;
+	    }
+	  if (val1 == 0)
+	    break;
+	  FALLTHROUGH;
+	case DW_OP_skip:;
+	  Dwarf_Word offset = op->offset + 1 + 2 + (int16_t) op->number;
+	  const Dwarf_Op *found = bsearch ((void *) (uintptr_t) offset, ops, nops,
+					   sizeof (*ops), bra_compar);
+	  if (found == NULL)
+	    {
+	      free (stack.addrs);
+	      /* PPC32 vDSO has such invalid operations.  */
+	      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	      return false;
+	    }
+	  /* Undo the 'for' statement increment.  */
+	  op = found - 1;
+	  break;
+	case DW_OP_nop:
+	  break;
+	/* DW_OP_* not listed in libgcc/unwind-dw2.c execute_stack_op:  */
+	case DW_OP_call_frame_cfa:;
+	  // Not used by CFI itself but it is synthetized by elfutils internation.
+	  Dwarf_Op *cfa_ops;
+	  size_t cfa_nops;
+	  Dwarf_Addr cfa;
+	  if (frame == NULL
+	      || dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0
+	      || ! expr_eval (state, NULL, cfa_ops, cfa_nops, &cfa, bias)
+	      || ! push (cfa))
+	    {
+	      __libdwfl_seterrno (DWFL_E_LIBDW);
+	      free (stack.addrs);
+	      return false;
+	    }
+	  is_location = true;
+	  break;
+	case DW_OP_stack_value:
+	  // Not used by CFI itself but it is synthetized by elfutils internation.
+	  is_location = false;
+	  break;
+	default:
+	  __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	  return false;
+      }
+    }
+  if (! pop (result))
+    {
+      free (stack.addrs);
+      return false;
+    }
+  free (stack.addrs);
+  if (is_location)
+    {
+      if (process->callbacks->memory_read == NULL)
+	{
+	  __libdwfl_seterrno (DWFL_E_INVALID_ARGUMENT);
+	  return false;
+	}
+      if (! process->callbacks->memory_read (process->dwfl, *result, result,
+					     process->callbacks_arg))
+	return false;
+    }
+  return true;
+#undef push
+#undef pop
+}
+
+static Dwfl_Frame *
+new_unwound (Dwfl_Frame *state)
+{
+  assert (state->unwound == NULL);
+  Dwfl_Thread *thread = state->thread;
+  Dwfl_Process *process = thread->process;
+  Ebl *ebl = process->ebl;
+  size_t nregs = ebl_frame_nregs (ebl);
+  assert (nregs > 0);
+  Dwfl_Frame *unwound;
+  unwound = malloc (sizeof (*unwound) + sizeof (*unwound->regs) * nregs);
+  if (unlikely (unwound == NULL))
+    return NULL;
+  state->unwound = unwound;
+  unwound->thread = thread;
+  unwound->unwound = NULL;
+  unwound->signal_frame = false;
+  unwound->initial_frame = false;
+  unwound->pc_state = DWFL_FRAME_STATE_ERROR;
+  memset (unwound->regs_set, 0, sizeof (unwound->regs_set));
+  return unwound;
+}
+
+/* The logic is to call __libdwfl_seterrno for any CFI bytecode interpretation
+   error so one can easily catch the problem with a debugger.  Still there are
+   archs with invalid CFI for some registers where the registers are never used
+   later.  Therefore we continue unwinding leaving the registers undefined.  */
+
+static void
+handle_cfi (Dwfl_Frame *state, Dwarf_Addr pc, Dwarf_CFI *cfi, Dwarf_Addr bias)
+{
+  Dwarf_Frame *frame;
+  if (INTUSE(dwarf_cfi_addrframe) (cfi, pc, &frame) != 0)
+    {
+      __libdwfl_seterrno (DWFL_E_LIBDW);
+      return;
+    }
+
+  Dwfl_Frame *unwound = new_unwound (state);
+  if (unwound == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return;
+    }
+
+  unwound->signal_frame = frame->fde->cie->signal_frame;
+  Dwfl_Thread *thread = state->thread;
+  Dwfl_Process *process = thread->process;
+  Ebl *ebl = process->ebl;
+  size_t nregs = ebl_frame_nregs (ebl);
+  assert (nregs > 0);
+
+  /* The return register is special for setting the unwound->pc_state.  */
+  unsigned ra = frame->fde->cie->return_address_register;
+  bool ra_set = false;
+  if (! ebl_dwarf_to_regno (ebl, &ra))
+    {
+      __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+      return;
+    }
+
+  for (unsigned regno = 0; regno < nregs; regno++)
+    {
+      Dwarf_Op reg_ops_mem[3], *reg_ops;
+      size_t reg_nops;
+      if (dwarf_frame_register (frame, regno, reg_ops_mem, &reg_ops,
+				&reg_nops) != 0)
+	{
+	  __libdwfl_seterrno (DWFL_E_LIBDW);
+	  continue;
+	}
+      Dwarf_Addr regval;
+      if (reg_nops == 0)
+	{
+	  if (reg_ops == reg_ops_mem)
+	    {
+	      /* REGNO is undefined.  */
+	      if (regno == ra)
+		unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+	      continue;
+	    }
+	  else if (reg_ops == NULL)
+	    {
+	      /* REGNO is same-value.  */
+	      if (INTUSE (dwfl_frame_reg) (state, regno, &regval) != 0)
+		continue;
+	    }
+	  else
+	    {
+	      __libdwfl_seterrno (DWFL_E_INVALID_DWARF);
+	      continue;
+	    }
+	}
+      else if (! expr_eval (state, frame, reg_ops, reg_nops, &regval, bias))
+	{
+	  /* PPC32 vDSO has various invalid operations, ignore them.  The
+	     register will look as unset causing an error later, if used.
+	     But PPC32 does not use such registers.  */
+	  continue;
+	}
+
+      /* Some architectures encode some extra info in the return address.  */
+      if (regno == frame->fde->cie->return_address_register)
+	regval &= ebl_func_addr_mask (ebl);
+
+      /* This is another strange PPC[64] case.  There are two
+	 registers numbers that can represent the same DWARF return
+	 register number.  We only want one to actually set the return
+	 register value.  But we always want to override the value if
+	 the register is the actual CIE return address register.  */
+      if (ra_set && regno != frame->fde->cie->return_address_register)
+	{
+	  unsigned r = regno;
+	  if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
+	    continue;
+	}
+
+      if (! __libdwfl_frame_reg_set (unwound, regno, regval))
+	{
+	  __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+	  continue;
+	}
+      else if (! ra_set)
+	{
+	  unsigned r = regno;
+          if (ebl_dwarf_to_regno (ebl, &r) && r == ra)
+	    ra_set = true;
+	}
+    }
+  if (unwound->pc_state == DWFL_FRAME_STATE_ERROR)
+    {
+      int res = INTUSE (dwfl_frame_reg) (unwound,
+          frame->fde->cie->return_address_register,
+          &unwound->pc);
+      if (res == 0)
+	{
+	  /* PPC32 __libc_start_main properly CFI-unwinds PC as zero.
+	     Currently none of the archs supported for unwinding have
+	     zero as a valid PC.  */
+	  if (unwound->pc == 0)
+	    unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+	  else
+	    {
+	      unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
+	      /* In SPARC the return address register actually contains
+		 the address of the call instruction instead of the return
+		 address.  Therefore we add here an offset defined by the
+		 backend.  Most likely 0.  */
+	      unwound->pc += ebl_ra_offset (ebl);
+	    }
+	}
+      else
+	{
+	  /* We couldn't set the return register, either it was bogus,
+	     or the return pc is undefined, maybe end of call stack.  */
+	  unsigned pcreg = frame->fde->cie->return_address_register;
+	  if (! ebl_dwarf_to_regno (ebl, &pcreg)
+	      || pcreg >= ebl_frame_nregs (ebl))
+	    __libdwfl_seterrno (DWFL_E_INVALID_REGISTER);
+	  else
+	    unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+	}
+    }
+  free (frame);
+}
+
+static bool
+setfunc (int firstreg, unsigned nregs, const Dwarf_Word *regs, void *arg)
+{
+  Dwfl_Frame *state = arg;
+  Dwfl_Frame *unwound = state->unwound;
+  if (firstreg < 0)
+    {
+      assert (firstreg == -1);
+      assert (nregs == 1);
+      assert (unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED);
+      unwound->pc = *regs;
+      unwound->pc_state = DWFL_FRAME_STATE_PC_SET;
+      return true;
+    }
+  while (nregs--)
+    if (! __libdwfl_frame_reg_set (unwound, firstreg++, *regs++))
+      return false;
+  return true;
+}
+
+static bool
+getfunc (int firstreg, unsigned nregs, Dwarf_Word *regs, void *arg)
+{
+  Dwfl_Frame *state = arg;
+  assert (firstreg >= 0);
+  while (nregs--)
+    if (INTUSE (dwfl_frame_reg) (state, firstreg++, regs++) != 0)
+      return false;
+  return true;
+}
+
+static bool
+readfunc (Dwarf_Addr addr, Dwarf_Word *datap, void *arg)
+{
+  Dwfl_Frame *state = arg;
+  Dwfl_Thread *thread = state->thread;
+  Dwfl_Process *process = thread->process;
+  return process->callbacks->memory_read (process->dwfl, addr, datap,
+					  process->callbacks_arg);
+}
+
+void
+internal_function
+__libdwfl_frame_unwind (Dwfl_Frame *state)
+{
+  if (state->unwound)
+    return;
+  /* Do not ask dwfl_frame_pc for ISACTIVATION, it would try to unwind STATE
+     which would deadlock us.  */
+  Dwarf_Addr pc;
+  bool ok = INTUSE(dwfl_frame_pc) (state, &pc, NULL);
+  if (!ok)
+    return;
+  /* Check whether this is the initial frame or a signal frame.
+     Then we need to unwind from the original, unadjusted PC.  */
+  if (! state->initial_frame && ! state->signal_frame)
+    pc--;
+  Dwfl_Module *mod = INTUSE(dwfl_addrmodule) (state->thread->process->dwfl, pc);
+  if (mod == NULL)
+    __libdwfl_seterrno (DWFL_E_NO_DWARF);
+  else
+    {
+      Dwarf_Addr bias;
+      Dwarf_CFI *cfi_eh = INTUSE(dwfl_module_eh_cfi) (mod, &bias);
+      if (cfi_eh)
+	{
+	  handle_cfi (state, pc - bias, cfi_eh, bias);
+	  if (state->unwound)
+	    return;
+	}
+      Dwarf_CFI *cfi_dwarf = INTUSE(dwfl_module_dwarf_cfi) (mod, &bias);
+      if (cfi_dwarf)
+	{
+	  handle_cfi (state, pc - bias, cfi_dwarf, bias);
+	  if (state->unwound)
+	    return;
+	}
+    }
+  assert (state->unwound == NULL);
+  Dwfl_Thread *thread = state->thread;
+  Dwfl_Process *process = thread->process;
+  Ebl *ebl = process->ebl;
+  if (new_unwound (state) == NULL)
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return;
+    }
+  state->unwound->pc_state = DWFL_FRAME_STATE_PC_UNDEFINED;
+  // &Dwfl_Frame.signal_frame cannot be passed as it is a bitfield.
+  bool signal_frame = false;
+  if (! ebl_unwind (ebl, pc, setfunc, getfunc, readfunc, state, &signal_frame))
+    {
+      // Discard the unwind attempt.  During next __libdwfl_frame_unwind call
+      // we may have for example the appropriate Dwfl_Module already mapped.
+      assert (state->unwound->unwound == NULL);
+      free (state->unwound);
+      state->unwound = NULL;
+      // __libdwfl_seterrno has been called above.
+      return;
+    }
+  assert (state->unwound->pc_state == DWFL_FRAME_STATE_PC_SET);
+  state->unwound->signal_frame = signal_frame;
+}
diff --git a/libdwfl/gzip.c b/libdwfl/gzip.c
new file mode 100644
index 0000000..002afc4
--- /dev/null
+++ b/libdwfl/gzip.c
@@ -0,0 +1,402 @@
+/* Decompression support for libdwfl: zlib (gzip) and/or bzlib (bzip2).
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "system.h"
+
+#ifdef LZMA
+# define USE_INFLATE	1
+# include <lzma.h>
+# define unzip		__libdw_unlzma
+# define DWFL_E_ZLIB	DWFL_E_LZMA
+# define MAGIC		"\xFD" "7zXZ\0" /* XZ file format.  */
+# define MAGIC2		"\x5d\0"	/* Raw LZMA format.  */
+# define Z(what)	LZMA_##what
+# define LZMA_ERRNO	LZMA_PROG_ERROR
+# define z_stream	lzma_stream
+# define inflateInit(z)	lzma_auto_decoder (z, 1 << 30, 0)
+# define do_inflate(z)	lzma_code (z, LZMA_RUN)
+# define inflateEnd(z)	lzma_end (z)
+#elif defined ZSTD
+# define USE_INFLATE	1
+# include <zstd.h>
+# define unzip		__libdw_unzstd
+# define DWFL_E_ZLIB	DWFL_E_ZSTD
+# define MAGIC		"\x28\xb5\x2f\xfd"
+#elif defined BZLIB
+# define USE_INFLATE	1
+# include <bzlib.h>
+# define unzip		__libdw_bunzip2
+# define DWFL_E_ZLIB	DWFL_E_BZLIB
+# define MAGIC		"BZh"
+# define Z(what)	BZ_##what
+# define BZ_ERRNO	BZ_IO_ERROR
+# define z_stream	bz_stream
+# define inflateInit(z)	BZ2_bzDecompressInit (z, 0, 0)
+# define do_inflate(z)	BZ2_bzDecompress (z)
+# define inflateEnd(z)	BZ2_bzDecompressEnd (z)
+#else
+# define USE_INFLATE	0
+# define crc32		loser_crc32
+# include <zlib.h>
+# define unzip		__libdw_gunzip
+# define MAGIC		"\037\213"
+# define Z(what)	Z_##what
+#endif
+
+#define READ_SIZE		(1 << 20)
+
+struct unzip_state {
+#if !USE_INFLATE
+  gzFile zf;
+#endif
+  size_t mapped_size;
+  void **whole;
+  void *buffer;
+  size_t size;
+  void *input_buffer;
+  off_t input_pos;
+};
+
+static inline bool
+bigger_buffer (struct unzip_state *state, size_t start)
+{
+  size_t more = state->size ? state->size * 2 : start;
+  char *b = realloc (state->buffer, more);
+  while (unlikely (b == NULL) && more >= state->size + 1024)
+    b = realloc (state->buffer, more -= 1024);
+  if (unlikely (b == NULL))
+    return false;
+  state->buffer = b;
+  state->size = more;
+  return true;
+}
+
+static inline void
+smaller_buffer (struct unzip_state *state, size_t end)
+{
+  state->buffer =
+      realloc (state->buffer, end) ?: end == 0 ? NULL : state->buffer;
+  state->size = end;
+}
+
+static inline Dwfl_Error
+fail (struct unzip_state *state, Dwfl_Error failure)
+{
+  if (state->input_pos == (off_t) state->mapped_size)
+    *state->whole = state->input_buffer;
+  else
+    {
+      free (state->input_buffer);
+      *state->whole = NULL;
+    }
+  free (state->buffer);
+  return failure;
+}
+
+#ifndef ZSTD
+static inline Dwfl_Error
+zlib_fail (struct unzip_state *state, int result)
+{
+  switch (result)
+    {
+    case Z (MEM_ERROR):
+      return fail (state, DWFL_E_NOMEM);
+    case Z (ERRNO):
+      return fail (state, DWFL_E_ERRNO);
+    default:
+      return fail (state, DWFL_E_ZLIB);
+    }
+}
+#endif
+
+#if !USE_INFLATE
+static Dwfl_Error
+open_stream (int fd, off_t start_offset, struct unzip_state *state)
+{
+    int d = dup (fd);
+    if (unlikely (d < 0))
+      return DWFL_E_ERRNO;
+    if (start_offset != 0)
+      {
+	off_t off = lseek (d, start_offset, SEEK_SET);
+	if (off != start_offset)
+	  {
+	    close (d);
+	    return DWFL_E_ERRNO;
+	  }
+      }
+    state->zf = gzdopen (d, "r");
+    if (unlikely (state->zf == NULL))
+      {
+	close (d);
+	return DWFL_E_NOMEM;
+      }
+
+    /* From here on, zlib will close D.  */
+
+    return DWFL_E_NOERROR;
+}
+#endif
+
+/* If this is not a compressed image, return DWFL_E_BADELF.
+   If we uncompressed it into *WHOLE, *WHOLE_SIZE, return DWFL_E_NOERROR.
+   Otherwise return an error for bad compressed data or I/O failure.
+   If we return an error after reading the first part of the file,
+   leave that portion malloc'd in *WHOLE, *WHOLE_SIZE.  If *WHOLE
+   is not null on entry, we'll use it in lieu of repeating a read.  */
+
+Dwfl_Error internal_function
+unzip (int fd, off_t start_offset,
+       void *mapped, size_t _mapped_size,
+       void **_whole, size_t *whole_size)
+{
+  struct unzip_state state =
+    {
+#if !USE_INFLATE
+      .zf = NULL,
+#endif
+      .mapped_size = _mapped_size,
+      .whole = _whole,
+      .buffer = NULL,
+      .size = 0,
+      .input_buffer = NULL,
+      .input_pos = 0
+    };
+
+  if (mapped == NULL)
+    {
+      if (*state.whole == NULL)
+	{
+	  state.input_buffer = malloc (READ_SIZE);
+	  if (unlikely (state.input_buffer == NULL))
+	    return DWFL_E_NOMEM;
+
+	  ssize_t n = pread_retry (fd, state.input_buffer, READ_SIZE, start_offset);
+	  if (unlikely (n < 0))
+	    return fail (&state, DWFL_E_ERRNO);
+
+	  state.input_pos = n;
+	  mapped = state.input_buffer;
+	  state.mapped_size = n;
+	}
+      else
+	{
+	  state.input_buffer = *state.whole;
+	  state.input_pos = state.mapped_size = *whole_size;
+	}
+    }
+
+#define NOMAGIC(magic) \
+  (state.mapped_size <= sizeof magic || \
+   memcmp (mapped, magic, sizeof magic - 1))
+
+  /* First, look at the header.  */
+  if (NOMAGIC (MAGIC)
+#ifdef MAGIC2
+      && NOMAGIC (MAGIC2)
+#endif
+      )
+    /* Not a compressed file.  */
+    return fail (&state, DWFL_E_BADELF);
+
+#ifdef ZSTD
+  /* special case for libzstd since it is slightly different from the
+     API provided by bzlib and liblzma.  */
+
+  void *next_in = mapped;
+  size_t avail_in = state.mapped_size;
+  void *next_out = NULL;
+  size_t avail_out = 0;
+  size_t total_out = 0;
+
+  size_t result;
+  ZSTD_DCtx *dctx = ZSTD_createDCtx();
+  if (dctx == NULL)
+    return fail (&state, DWFL_E_NOMEM);
+
+  do
+    {
+      if (avail_in == 0 && state.input_buffer != NULL)
+	{
+	  ssize_t n = pread_retry (fd, state.input_buffer, READ_SIZE,
+				   start_offset + state.input_pos);
+	  if (unlikely (n < 0))
+	    {
+	      ZSTD_freeDCtx (dctx);
+	      return fail (&state, DWFL_E_ERRNO);
+	    }
+	  next_in = state.input_buffer;
+	  avail_in = n;
+	  state.input_pos += n;
+	}
+      if (avail_out == 0)
+	{
+	  ptrdiff_t pos = (void *) next_out - state.buffer;
+	  if (!bigger_buffer (&state, avail_in))
+	    {
+	      ZSTD_freeDCtx (dctx);
+	      return fail (&state, DWFL_E_NOMEM);
+	    }
+	  next_out = state.buffer + pos;
+	  avail_out = state.size - pos;
+	}
+
+      ZSTD_inBuffer input = { next_in, avail_in, 0 };
+      ZSTD_outBuffer output = { next_out, avail_out, 0 };
+      result = ZSTD_decompressStream (dctx, &output, &input);
+
+      if (! ZSTD_isError (result))
+	{
+	  total_out += output.pos;
+	  next_out += output.pos;
+	  avail_out -= output.pos;
+	  next_in += input.pos;
+	  avail_in -= input.pos;
+	}
+
+      if (result == 0)
+	break;
+    }
+  while (avail_in > 0 && ! ZSTD_isError (result));
+
+  ZSTD_freeDCtx (dctx);
+
+  if (ZSTD_isError (result))
+    return fail (&state, DWFL_E_ZSTD);
+
+  smaller_buffer (&state, total_out);
+
+#elif USE_INFLATE
+
+  /* This style actually only works with bzlib and liblzma.
+     The stupid zlib interface has nothing to grok the
+     gzip file headers except the slow gzFile interface.  */
+
+  z_stream z = { .next_in = mapped, .avail_in = state.mapped_size };
+  int result = inflateInit (&z);
+  if (result != Z (OK))
+    {
+      inflateEnd (&z);
+      return zlib_fail (&state, result);
+    }
+
+  do
+    {
+      if (z.avail_in == 0 && state.input_buffer != NULL)
+	{
+	  ssize_t n = pread_retry (fd, state.input_buffer, READ_SIZE,
+				   start_offset + state.input_pos);
+	  if (unlikely (n < 0))
+	    {
+	      inflateEnd (&z);
+	      return zlib_fail (&state, Z (ERRNO));
+	    }
+	  z.next_in = state.input_buffer;
+	  z.avail_in = n;
+	  state.input_pos += n;
+	}
+      if (z.avail_out == 0)
+	{
+	  ptrdiff_t pos = (void *) z.next_out - state.buffer;
+	  if (!bigger_buffer (&state, z.avail_in))
+	    {
+	      result = Z (MEM_ERROR);
+	      break;
+	    }
+	  z.next_out = state.buffer + pos;
+	  z.avail_out = state.size - pos;
+	}
+    }
+  while ((result = do_inflate (&z)) == Z (OK));
+
+#ifdef BZLIB
+  uint64_t total_out = (((uint64_t) z.total_out_hi32 << 32)
+			| z.total_out_lo32);
+  smaller_buffer (&state, total_out);
+#else
+  smaller_buffer (&state, z.total_out);
+#endif
+
+  inflateEnd (&z);
+
+  if (result != Z (STREAM_END))
+    return zlib_fail (&state, result);
+
+#else  /* gzip only.  */
+
+  /* Let the decompression library read the file directly.  */
+
+  Dwfl_Error result = open_stream (fd, start_offset, &state);
+
+  if (result == DWFL_E_NOERROR && gzdirect (state.zf))
+    {
+      gzclose (state.zf);
+      /* Not a compressed stream after all.  */
+      return fail (&state, DWFL_E_BADELF);
+    }
+
+  if (result != DWFL_E_NOERROR)
+    return fail (&state, result);
+
+  ptrdiff_t pos = 0;
+  while (1)
+    {
+      if (!bigger_buffer (&state, 1024))
+	{
+	  gzclose (state.zf);
+	  return zlib_fail (&state, Z (MEM_ERROR));
+	}
+      int n = gzread (state.zf, state.buffer + pos, state.size - pos);
+      if (n < 0)
+	{
+	  int code;
+	  gzerror (state.zf, &code);
+	  gzclose (state.zf);
+	  return zlib_fail (&state, code);
+	}
+      if (n == 0)
+	break;
+      pos += n;
+    }
+
+  gzclose (state.zf);
+  smaller_buffer (&state, pos);
+#endif
+
+  free (state.input_buffer);
+
+  *state.whole = state.buffer;
+  *whole_size = state.size;
+
+  return DWFL_E_NOERROR;
+}
diff --git a/libdwfl/image-header.c b/libdwfl/image-header.c
new file mode 100644
index 0000000..03cd7a7
--- /dev/null
+++ b/libdwfl/image-header.c
@@ -0,0 +1,113 @@
+/* Linux kernel image support for libdwfl.
+   Copyright (C) 2009-2011 Red Hat, Inc.
+   Copyright (C) 2022, 2024 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define LE16(x)	(x)
+#else
+# define LE16(x)	bswap_16 (x)
+#endif
+
+/* See Documentation/x86/boot.txt in Linux kernel sources
+   for an explanation of these format details.  */
+
+#define MAGIC1			0xaa55
+#define MAGIC2			0x53726448 /* "HdrS" little-endian */
+#define MIN_VERSION		0x0208
+
+#define H_START			(H_SETUP_SECTS & -4)
+#define H_SETUP_SECTS		0x1f1
+#define H_MAGIC1		0x1fe
+#define H_MAGIC2		0x202
+#define H_VERSION		0x206
+#define H_PAYLOAD_OFFSET	0x248
+#define H_PAYLOAD_LENGTH	0x24c
+#define H_END			0x250
+#define H_READ_SIZE		(H_END - H_START)
+
+Dwfl_Error
+internal_function
+__libdw_image_header (int fd, off_t *start_offset,
+		      void *mapped, size_t mapped_size)
+{
+  if (likely (mapped_size > H_END))
+    {
+      const void *header = mapped;
+      char header_buffer[H_READ_SIZE + H_START];
+      if (header == NULL)
+	{
+	  ssize_t n = pread_retry (fd, header_buffer + H_START, H_READ_SIZE,
+				   *start_offset + H_START);
+	  if (n < 0)
+	    return DWFL_E_ERRNO;
+	  if (n < H_READ_SIZE)
+	    return DWFL_E_BADELF;
+
+	  header = header_buffer;
+	}
+
+      uint16_t magic1;
+      uint32_t magic2;
+      uint16_t version;
+      memcpy (&magic1, header + H_MAGIC1, sizeof (uint16_t));
+      memcpy (&magic2, header + H_MAGIC2, sizeof (uint32_t));
+      memcpy (&version, header + H_VERSION, sizeof (uint16_t));
+      if (magic1 == LE16 (MAGIC1) && magic2 == LE32 (MAGIC2)
+	  && LE16 (version) >= MIN_VERSION)
+	{
+	  /* The magic numbers match and the version field is sufficient.
+	     Extract the payload bounds.  */
+
+	  uint32_t offset;
+	  uint32_t length;
+	  uint8_t sects;
+	  memcpy (&offset, header + H_PAYLOAD_OFFSET, sizeof (uint32_t));
+	  memcpy (&length, header + H_PAYLOAD_LENGTH, sizeof (uint32_t));
+	  memcpy (&sects, header + H_SETUP_SECTS, sizeof (uint8_t));
+	  offset = LE32 (offset);
+	  length = LE32 (length);
+
+	  offset += ((sects ?: 4) + 1) * 512;
+
+	  if (offset > H_END && offset < mapped_size
+	      && mapped_size - offset >= length)
+	    {
+	      /* It looks kosher.  Use it!  */
+	      *start_offset += offset;
+	      return DWFL_E_NOERROR;
+	    }
+	}
+    }
+  return DWFL_E_BADELF;
+}
diff --git a/libdwfl/libdwfl.h b/libdwfl/libdwfl.h
new file mode 100644
index 0000000..49ad666
--- /dev/null
+++ b/libdwfl/libdwfl.h
@@ -0,0 +1,825 @@
+/* Interfaces for libdwfl.
+   Copyright (C) 2005-2010, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBDWFL_H
+#define _LIBDWFL_H	1
+
+#include "libdw.h"
+#include <stdio.h>
+
+/* Handle for a session using the library.  */
+typedef struct Dwfl Dwfl;
+
+/* Handle for a module.  */
+typedef struct Dwfl_Module Dwfl_Module;
+
+/* Handle describing a line record.  */
+typedef struct Dwfl_Line Dwfl_Line;
+
+/* This holds information common for all the frames of one backtrace for
+   a particular thread/task/TID.  Several threads belong to one Dwfl.  */
+typedef struct Dwfl_Thread Dwfl_Thread;
+
+/* This holds everything we know about the state of the frame at a particular
+   PC location described by an FDE belonging to Dwfl_Thread.  */
+typedef struct Dwfl_Frame Dwfl_Frame;
+
+/* Handle for debuginfod-client connection.  */
+#ifndef _ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF
+typedef struct debuginfod_client debuginfod_client;
+#define _ELFUTILS_DEBUGINFOD_CLIENT_TYPEDEF 1
+#endif
+
+/* Callbacks.  */
+typedef struct
+{
+  int (*find_elf) (Dwfl_Module *mod, void **userdata,
+		   const char *modname, Dwarf_Addr base,
+		   char **file_name, Elf **elfp);
+
+  int (*find_debuginfo) (Dwfl_Module *mod, void **userdata,
+			 const char *modname, Dwarf_Addr base,
+			 const char *file_name,
+			 const char *debuglink_file, GElf_Word debuglink_crc,
+			 char **debuginfo_file_name);
+
+  /* Fill *ADDR with the loaded address of the section called SECNAME in
+     the given module.  Use (Dwarf_Addr) -1 if this section is omitted from
+     accessible memory.  This is called exactly once for each SHF_ALLOC
+     section that relocations affecting DWARF data refer to, so it can
+     easily be used to collect state about the sections referenced.  */
+  int (*section_address) (Dwfl_Module *mod, void **userdata,
+			  const char *modname, Dwarf_Addr base,
+			  const char *secname,
+			  GElf_Word shndx, const GElf_Shdr *shdr,
+			  Dwarf_Addr *addr);
+
+  char **debuginfo_path;	/* See dwfl_standard_find_debuginfo.  */
+} Dwfl_Callbacks;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Start a new session with the library.  */
+extern Dwfl *dwfl_begin (const Dwfl_Callbacks *callbacks)
+  __nonnull_attribute__ (1);
+
+
+/* End a session.  */
+extern void dwfl_end (Dwfl *);
+
+/* Return implementation's version string suitable for printing.  */
+extern const char *dwfl_version (Dwfl *);
+
+/* Return error code of last failing function call.  This value is kept
+   separately for each thread.  */
+extern int dwfl_errno (void);
+
+/* Return error string for ERROR.  If ERROR is zero, return error string
+   for most recent error or NULL if none occurred.  If ERROR is -1 the
+   behaviour is similar to the last case except that not NULL but a legal
+   string is returned.  */
+extern const char *dwfl_errmsg (int err);
+
+
+/* Start reporting the current set of segments and modules to the library.
+   All existing segments are wiped.  Existing modules are marked to be
+   deleted, and will not be found via dwfl_addrmodule et al if they are not
+   re-reported before dwfl_report_end is called.  */
+extern void dwfl_report_begin (Dwfl *dwfl);
+
+/* Report that segment NDX begins at PHDR->p_vaddr + BIAS.
+   If NDX is < 0, the value succeeding the last call's NDX
+   is used instead (zero on the first call).  IDENT is ignored.
+
+   If nonzero, the smallest PHDR->p_align value seen sets the
+   effective page size for the address space DWFL describes.
+   This is the granularity at which reported module boundary
+   addresses will be considered to fall in or out of a segment.
+
+   Returns -1 for errors, or NDX (or its assigned replacement) on success.
+
+   Reporting segments at all is optional.  Its only benefit to the caller is to
+   offer this quick lookup via dwfl_addrsegment, or use other segment-based
+   calls.  */
+extern int dwfl_report_segment (Dwfl *dwfl, int ndx,
+				const GElf_Phdr *phdr, GElf_Addr bias,
+				const void *ident);
+
+/* Report that a module called NAME spans addresses [START, END).
+   Returns the module handle, either existing or newly allocated,
+   or returns a null pointer for an allocation error.  */
+extern Dwfl_Module *dwfl_report_module (Dwfl *dwfl, const char *name,
+					Dwarf_Addr start, Dwarf_Addr end);
+
+/* Report a module to address BASE with start and end addresses computed
+   from the ELF program headers in the given file - see the table below.
+   FD may be -1 to open FILE_NAME.  On success, FD is consumed by the
+   library, and the `find_elf' callback will not be used for this module.
+	    ADD_P_VADDR  BASE
+   ET_EXEC  ignored      ignored
+   ET_DYN   false        absolute address where to place the file
+	    true         start address relative to ELF's phdr p_vaddr
+   ET_REL   ignored      absolute address where to place the file
+   ET_CORE  ignored      ignored
+   ET_DYN ELF phdr p_vaddr address can be non-zero if the shared library
+   has been prelinked by tool prelink(8).  */
+extern Dwfl_Module *dwfl_report_elf (Dwfl *dwfl, const char *name,
+				     const char *file_name, int fd,
+				     GElf_Addr base, bool add_p_vaddr);
+
+/* Similar, but report the module for offline use.  All ET_EXEC files
+   being reported must be reported before any relocatable objects.
+   If this is used, dwfl_report_module and dwfl_report_elf may not be
+   used in the same reporting session.  */
+extern Dwfl_Module *dwfl_report_offline (Dwfl *dwfl, const char *name,
+					 const char *file_name, int fd);
+
+/* Similar, but report ELF from memory region.  */
+extern Dwfl_Module *dwfl_report_offline_memory (Dwfl *dwfl, const char *name,
+						const char *file_name,
+						char *data, size_t size);
+
+/* Finish reporting the current set of modules to the library.
+   If REMOVED is not null, it's called for each module that
+   existed before but was not included in the current report.
+   Returns a nonzero return value from the callback.
+   The callback may call dwfl_report_module; doing so with the
+   details of the module being removed prevents its removal.
+   DWFL cannot be used until this function has returned zero.  */
+extern int dwfl_report_end (Dwfl *dwfl,
+			    int (*removed) (Dwfl_Module *, void *,
+					    const char *, Dwarf_Addr,
+					    void *arg),
+			    void *arg);
+
+/* Start reporting additional modules to the library.  No calls but
+   dwfl_report_* can be made on DWFL until dwfl_report_end is called.
+   This is like dwfl_report_begin, but all the old modules are kept on.
+   More dwfl_report_* calls can follow to add more modules.
+   When dwfl_report_end is called, no old modules will be removed.  */
+extern void dwfl_report_begin_add (Dwfl *dwfl);
+
+
+/* Return the name of the module, and for each non-null argument store
+   interesting details: *USERDATA is a location for storing your own
+   pointer, **USERDATA is initially null; *START and *END give the address
+   range covered by the module; *DWBIAS is the address bias for debugging
+   information, and *SYMBIAS for symbol table entries (either is -1 if not
+   yet accessed); *MAINFILE is the name of the ELF file, and *DEBUGFILE the
+   name of the debuginfo file (might be equal to *MAINFILE; either is null
+   if not yet accessed).  */
+extern const char *dwfl_module_info (Dwfl_Module *mod, void ***userdata,
+				     Dwarf_Addr *start, Dwarf_Addr *end,
+				     Dwarf_Addr *dwbias, Dwarf_Addr *symbias,
+				     const char **mainfile,
+				     const char **debugfile);
+
+/* Iterate through the modules, starting the walk with OFFSET == 0.
+   Calls *CALLBACK for each module as long as it returns DWARF_CB_OK.
+   When *CALLBACK returns another value, the walk stops and the
+   return value can be passed as OFFSET to resume it.  Returns 0 when
+   there are no more modules, or -1 for errors.  */
+extern ptrdiff_t dwfl_getmodules (Dwfl *dwfl,
+				  int (*callback) (Dwfl_Module *, void **,
+						   const char *, Dwarf_Addr,
+						   void *arg),
+				  void *arg,
+				  ptrdiff_t offset);
+
+/* Find the module containing the given address.  */
+extern Dwfl_Module *dwfl_addrmodule (Dwfl *dwfl, Dwarf_Addr address);
+
+/* Find the segment, if any, and module, if any, containing ADDRESS.
+   Returns a segment index returned by dwfl_report_segment, or -1
+   if no segment matches the address.  Regardless of the return value,
+   *MOD is always set to the module containing ADDRESS, or to null.  */
+extern int dwfl_addrsegment (Dwfl *dwfl, Dwarf_Addr address, Dwfl_Module **mod);
+
+
+
+/* Report the known build ID bits associated with a module.
+   If VADDR is nonzero, it gives the absolute address where those
+   bits are found within the module.  This can be called at any
+   time, but is usually used immediately after dwfl_report_module.
+   Once the module's main ELF file is opened, the ID note found
+   there takes precedence and cannot be changed.  */
+extern int dwfl_module_report_build_id (Dwfl_Module *mod,
+					const unsigned char *bits, size_t len,
+					GElf_Addr vaddr)
+  __nonnull_attribute__ (2);
+
+/* Extract the build ID bits associated with a module.
+   Returns -1 for errors, 0 if no ID is known, or the number of ID bytes.
+   When an ID is found, *BITS points to it; *VADDR is the absolute address
+   at which the ID bits are found within the module, or 0 if unknown.
+
+   This returns 0 when the module's main ELF file has not yet been loaded
+   and its build ID bits were not reported.  To ensure the ID is always
+   returned when determinable, call dwfl_module_getelf first.  */
+extern int dwfl_module_build_id (Dwfl_Module *mod,
+				 const unsigned char **bits, GElf_Addr *vaddr)
+  __nonnull_attribute__ (2, 3);
+
+
+/*** Standard callbacks ***/
+
+/* These standard find_elf and find_debuginfo callbacks are
+   controlled by a string specifying directories to look in.
+   If `debuginfo_path' is set in the Dwfl_Callbacks structure
+   and the char * it points to is not null, that supplies the
+   string.  Otherwise a default path is used.
+
+   If the first character of the string is + or - that enables or
+   disables CRC32 checksum validation when it's necessary.  The
+   remainder of the string is composed of elements separated by
+   colons.  Each element can start with + or - to override the
+   global checksum behavior.  This flag is never relevant when
+   working with build IDs, but it's always parsed in the path
+   string.  The remainder of the element indicates a directory.
+
+   Searches by build ID consult only the elements naming absolute
+   directory paths.  They look under those directories for a link
+   named ".build-id/xx/yy" or ".build-id/xx/yy.debug", where "xxyy"
+   is the lower-case hexadecimal representation of the ID bytes.
+
+   In searches for debuginfo by name, if the remainder of the
+   element is empty, the directory containing the main file is
+   tried; if it's an absolute path name, the absolute directory path
+   (and any subdirectory of that path) containing the main file is
+   taken as a subdirectory of this path; a relative path name is taken
+   as a subdirectory of the directory containing the main file.
+   Hence for /usr/bin/ls, the default string ":.debug:/usr/lib/debug"
+   says to look in /usr/bin, then /usr/bin/.debug, then the path subdirs
+   under /usr/lib/debug, in the order /usr/lib/debug/usr/bin, then
+   /usr/lib/debug/bin, and finally /usr/lib/debug, for the file name in
+   the .gnu_debuglink section (or "ls.debug" if none was found).  */
+
+/* Standard find_elf callback function working solely on build ID.
+   This can be tried first by any find_elf callback, to use the
+   bits passed to dwfl_module_report_build_id, if any.  */
+extern int dwfl_build_id_find_elf (Dwfl_Module *, void **,
+				   const char *, Dwarf_Addr,
+				   char **, Elf **);
+
+/* Standard find_debuginfo callback function working solely on build ID.
+   This can be tried first by any find_debuginfo callback,
+   to use the build ID bits from the main file when present.  */
+extern int dwfl_build_id_find_debuginfo (Dwfl_Module *, void **,
+					 const char *, Dwarf_Addr,
+					 const char *, const char *,
+					 GElf_Word, char **);
+
+/* Standard find_debuginfo callback function.
+   If a build ID is available, this tries first to use that.
+   If there is no build ID or no valid debuginfo found by ID,
+   it searches the debuginfo path by name, as described above.
+   Any file found in the path is validated by build ID if possible,
+   or else by CRC32 checksum if enabled, and skipped if it does not match.  */
+extern int dwfl_standard_find_debuginfo (Dwfl_Module *, void **,
+					 const char *, Dwarf_Addr,
+					 const char *, const char *,
+					 GElf_Word, char **);
+
+
+/* This callback must be used when using dwfl_offline_* to report modules,
+   if ET_REL is to be supported.  */
+extern int dwfl_offline_section_address (Dwfl_Module *, void **,
+					 const char *, Dwarf_Addr,
+					 const char *, GElf_Word,
+					 const GElf_Shdr *,
+					 Dwarf_Addr *addr);
+
+
+/* Callbacks for working with kernel modules in the running Linux kernel.  */
+extern int dwfl_linux_kernel_find_elf (Dwfl_Module *, void **,
+				       const char *, Dwarf_Addr,
+				       char **, Elf **);
+extern int dwfl_linux_kernel_module_section_address (Dwfl_Module *, void **,
+						     const char *, Dwarf_Addr,
+						     const char *, GElf_Word,
+						     const GElf_Shdr *,
+						     Dwarf_Addr *addr);
+
+/* Call dwfl_report_elf for the running Linux kernel.
+   Returns zero on success, -1 if dwfl_report_module failed,
+   or an errno code if opening the kernel binary failed.  */
+extern int dwfl_linux_kernel_report_kernel (Dwfl *dwfl);
+
+/* Call dwfl_report_module for each kernel module in the running Linux kernel.
+   Returns zero on success, -1 if dwfl_report_module failed,
+   or an errno code if reading the list of modules failed.  */
+extern int dwfl_linux_kernel_report_modules (Dwfl *dwfl);
+
+/* Report a kernel and its modules found on disk, for offline use.
+   If RELEASE starts with '/', it names a directory to look in;
+   if not, it names a directory to find under /lib/modules/;
+   if null, /lib/modules/`uname -r` is used.
+   Returns zero on success, -1 if dwfl_report_module failed,
+   or an errno code if finding the files on disk failed.
+
+   If PREDICATE is not null, it is called with each module to be reported;
+   its arguments are the module name, and the ELF file name or null if unknown,
+   and its return value should be zero to skip the module, one to report it,
+   or -1 to cause the call to fail and return errno.  */
+extern int dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
+					     int (*predicate) (const char *,
+							       const char *));
+
+/* Examine an ET_CORE file and report modules based on its contents.
+   This can follow a dwfl_report_offline call to bootstrap the
+   DT_DEBUG method of following the dynamic linker link_map chain, in
+   case the core file does not contain enough of the executable's text
+   segment to locate its PT_DYNAMIC in the dump.  In such case you need to
+   supply non-NULL EXECUTABLE, otherwise dynamic libraries will not be loaded
+   into the DWFL map.  This might call dwfl_report_elf on file names found in
+   the dump if reading some link_map files is the only way to ascertain those
+   modules' addresses.  Returns the number of modules reported, or -1 for
+   errors.  */
+extern int dwfl_core_file_report (Dwfl *dwfl, Elf *elf, const char *executable);
+
+/* Call dwfl_report_module for each file mapped into the address space of PID.
+   Returns zero on success, -1 if dwfl_report_module failed,
+   or an errno code if opening the proc files failed.  */
+extern int dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid);
+
+/* Similar, but reads an input stream in the format of Linux /proc/PID/maps
+   files giving module layout, not the file for a live process.  */
+extern int dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *);
+
+/* Trivial find_elf callback for use with dwfl_linux_proc_report.
+   This uses the module name as a file name directly and tries to open it
+   if it begin with a slash, or handles the magic string "[vdso]".  */
+extern int dwfl_linux_proc_find_elf (Dwfl_Module *mod, void **userdata,
+				     const char *module_name, Dwarf_Addr base,
+				     char **file_name, Elf **);
+
+/* Standard argument parsing for using a standard callback set.  */
+struct argp;
+extern const struct argp *dwfl_standard_argp (void) __const_attribute__;
+
+
+/*** Relocation of addresses from Dwfl ***/
+
+/* Return the number of relocatable bases associated with the module,
+   which is zero for ET_EXEC and one for ET_DYN.  Returns -1 for errors.  */
+extern int dwfl_module_relocations (Dwfl_Module *mod);
+
+/* Return the relocation base index associated with the *ADDRESS location,
+   and adjust *ADDRESS to be an offset relative to that base.
+   Returns -1 for errors.  */
+extern int dwfl_module_relocate_address (Dwfl_Module *mod,
+					 Dwarf_Addr *address);
+
+/* Return the ELF section name for the given relocation base index;
+   if SHNDXP is not null, set *SHNDXP to the ELF section index.
+   For ET_DYN, returns "" and sets *SHNDXP to SHN_ABS; the relocation
+   base is the runtime start address reported for the module.
+   Returns null for errors.  */
+extern const char *dwfl_module_relocation_info (Dwfl_Module *mod,
+						unsigned int idx,
+						GElf_Word *shndxp);
+
+/* Validate that ADDRESS and ADDRESS+OFFSET lie in a known module
+   and both within the same contiguous region for relocation purposes.
+   Returns zero for success and -1 for errors.  */
+extern int dwfl_validate_address (Dwfl *dwfl,
+				  Dwarf_Addr address, Dwarf_Sword offset);
+
+
+/*** ELF access functions ***/
+
+/* Fetch the module main ELF file (where the allocated sections
+   are found) for use with libelf.  If successful, fills in *BIAS
+   with the difference between addresses within the loaded module
+   and those in symbol tables or Dwarf information referring to it.  */
+extern Elf *dwfl_module_getelf (Dwfl_Module *, GElf_Addr *bias)
+  __nonnull_attribute__ (2);
+
+/* Return the number of symbols in the module's symbol table,
+   or -1 for errors.  */
+extern int dwfl_module_getsymtab (Dwfl_Module *mod);
+
+/* Return the index of the first global symbol in the module's symbol
+   table, or -1 for errors.  In each symbol table, all symbols with
+   STB_LOCAL binding precede the weak and global symbols.  This
+   function returns the symbol table index one greater than the last
+   local symbol.  */
+extern int dwfl_module_getsymtab_first_global (Dwfl_Module *mod);
+
+/* Fetch one entry from the module's symbol table.  On errors, returns
+   NULL.  If successful, fills in *SYM and returns the string for st_name.
+   This works like gelf_getsym except that st_value is always adjusted to
+   an absolute value based on the module's location, when the symbol is in
+   an SHF_ALLOC section.  If SHNDXP is non-null, it's set with the section
+   index (whether from st_shndx or extended index table); in case of a
+   symbol in a non-allocated section, *SHNDXP is instead set to -1.
+   Note that since symbols can come from either the main, debug or auxiliary
+   ELF symbol file (either dynsym or symtab) the section index can only
+   be reliably used to compare against special section constants like
+   SHN_UNDEF or SHN_ABS.  It is recommended to use dwfl_module_getsym_info
+   which doesn't have these deficiencies.  */
+extern const char *dwfl_module_getsym (Dwfl_Module *mod, int ndx,
+				       GElf_Sym *sym, GElf_Word *shndxp)
+  __nonnull_attribute__ (3);
+
+/* Fetch one entry from the module's symbol table and the associated
+   address value.  On errors, returns NULL.  If successful, fills in
+   *SYM, *ADDR and returns the string for st_name.  This works like
+   gelf_getsym.  *ADDR is set to the st_value adjusted to an absolute
+   value based on the module's location, when the symbol is in an
+   SHF_ALLOC section.  For non-ET_REL files, if the arch uses function
+   descriptors, and the st_value points to one, *ADDR will be resolved
+   to the actual function entry address.  The SYM->ST_VALUE itself
+   isn't adjusted in any way.  Fills in ELFP, if not NULL, with the
+   ELF file the symbol originally came from.  Note that symbols can
+   come from either the main, debug or auxiliary ELF symbol file
+   (either dynsym or symtab).  If SHNDXP is non-null, it's set with
+   the section index (whether from st_shndx or extended index table);
+   in case of a symbol in a non-allocated section, *SHNDXP is instead
+   set to -1.  Fills in BIAS, if not NULL, with the difference between
+   addresses within the loaded module and those in symbol table of the
+   ELF file.  Note that the address associated with the symbol might
+   be in a different section than the returned symbol.  The section in
+   the main elf file in which returned ADDR falls can be found with
+   dwfl_module_address_section.  */
+extern const char *dwfl_module_getsym_info (Dwfl_Module *mod, int ndx,
+					    GElf_Sym *sym, GElf_Addr *addr,
+					    GElf_Word *shndxp,
+					    Elf **elfp, Dwarf_Addr *bias)
+  __nonnull_attribute__ (3, 4);
+
+/* Find the symbol that ADDRESS lies inside, and return its name.  */
+extern const char *dwfl_module_addrname (Dwfl_Module *mod, GElf_Addr address);
+
+/* Find the symbol associated with ADDRESS.  Return its name or NULL
+   when nothing was found.  If the architecture uses function
+   descriptors, and symbol st_value points to one, ADDRESS will be
+   matched against either the adjusted st_value or the associated
+   function entry value as described in dwfl_module_getsym_info.
+   OFFSET will be filled in with the difference from the start of the
+   symbol (or function entry), OFFSET cannot be NULL.  SYM is filled
+   in with the symbol associated with the matched ADDRESS, SYM cannot
+   be NULL.  The SYM->ST_VALUE itself isn't adjusted in any way.
+   Fills in ELFP, if not NULL, with the ELF file the symbol originally
+   came from.  Note that symbols can come from either the main, debug
+   or auxiliary ELF symbol file (either dynsym or symtab).  If SHNDXP
+   is non-null, it's set with the section index (whether from st_shndx
+   or extended index table).  Fills in BIAS, if not NULL, with the
+   difference between addresses within the loaded module and those in
+   symbol table of the ELF file.  Note that the address matched
+   against the symbol might be in a different section than the
+   returned symbol.  The section in the main elf file in ADDRESS falls
+   can be found with dwfl_module_address_section.  */
+extern const char *dwfl_module_addrinfo (Dwfl_Module *mod, GElf_Addr address,
+					 GElf_Off *offset, GElf_Sym *sym,
+					 GElf_Word *shndxp, Elf **elfp,
+					 Dwarf_Addr *bias)
+  __nonnull_attribute__ (3, 4);
+
+/* Find the symbol that ADDRESS lies inside, and return detailed
+   information as for dwfl_module_getsym (above).  Note that like
+   dwfl_module_getsym this function also adjusts SYM->ST_VALUE to an
+   absolute value based on the module's location.  ADDRESS is only
+   matched against this adjusted SYM->ST_VALUE.  This means that
+   depending on architecture this might only match symbols that
+   represent function descriptor addresses (and not function entry
+   addresses).  For these reasons it is recommended to use
+   dwfl_module_addrinfo instead.  */
+extern const char *dwfl_module_addrsym (Dwfl_Module *mod, GElf_Addr address,
+					GElf_Sym *sym, GElf_Word *shndxp)
+  __nonnull_attribute__ (3);
+
+/* Find the ELF section that *ADDRESS lies inside and return it.
+   On success, adjusts *ADDRESS to be relative to the section,
+   and sets *BIAS to the difference between addresses used in
+   the returned section's headers and run-time addresses.  */
+extern Elf_Scn *dwfl_module_address_section (Dwfl_Module *mod,
+					     Dwarf_Addr *address,
+					     Dwarf_Addr *bias)
+  __nonnull_attribute__ (2, 3);
+
+
+/*** Dwarf access functions ***/
+
+/* Fetch the module's debug information for use with libdw.
+   If successful, fills in *BIAS with the difference between
+   addresses within the loaded module and those  to use with libdw.  */
+extern Dwarf *dwfl_module_getdwarf (Dwfl_Module *, Dwarf_Addr *bias)
+     __nonnull_attribute__ (2);
+
+/* Get the libdw handle for each module.  */
+extern ptrdiff_t dwfl_getdwarf (Dwfl *,
+				int (*callback) (Dwfl_Module *, void **,
+						 const char *, Dwarf_Addr,
+						 Dwarf *, Dwarf_Addr, void *),
+				void *arg, ptrdiff_t offset);
+
+/* Look up the module containing ADDR and return its debugging information,
+   loading it if necessary.  */
+extern Dwarf *dwfl_addrdwarf (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias)
+     __nonnull_attribute__ (3);
+
+
+/* Find the CU containing ADDR and return its DIE.  */
+extern Dwarf_Die *dwfl_addrdie (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Addr *bias)
+     __nonnull_attribute__ (3);
+extern Dwarf_Die *dwfl_module_addrdie (Dwfl_Module *mod,
+				       Dwarf_Addr addr, Dwarf_Addr *bias)
+     __nonnull_attribute__ (3);
+
+/* Iterate through the CUs, start with null for LASTCU.  */
+extern Dwarf_Die *dwfl_nextcu (Dwfl *dwfl, Dwarf_Die *lastcu, Dwarf_Addr *bias)
+     __nonnull_attribute__ (3);
+extern Dwarf_Die *dwfl_module_nextcu (Dwfl_Module *mod,
+				      Dwarf_Die *lastcu, Dwarf_Addr *bias)
+     __nonnull_attribute__ (3);
+
+/* Return the module containing the CU DIE.  */
+extern Dwfl_Module *dwfl_cumodule (Dwarf_Die *cudie);
+
+
+/* Cache the source line information for the CU and return the
+   number of Dwfl_Line entries it has.  */
+extern int dwfl_getsrclines (Dwarf_Die *cudie, size_t *nlines);
+
+/* Access one line number entry within the CU.  */
+extern Dwfl_Line *dwfl_onesrcline (Dwarf_Die *cudie, size_t idx);
+
+/* Get source for address.  */
+extern Dwfl_Line *dwfl_module_getsrc (Dwfl_Module *mod, Dwarf_Addr addr);
+extern Dwfl_Line *dwfl_getsrc (Dwfl *dwfl, Dwarf_Addr addr);
+
+/* Get address for source.  */
+extern int dwfl_module_getsrc_file (Dwfl_Module *mod,
+				    const char *fname, int lineno, int column,
+				    Dwfl_Line ***srcsp, size_t *nsrcs);
+
+/* Return the module containing this line record.  */
+extern Dwfl_Module *dwfl_linemodule (Dwfl_Line *line);
+
+/* Return the CU containing this line record.  */
+extern Dwarf_Die *dwfl_linecu (Dwfl_Line *line);
+
+/* Return the source file name and fill in other information.
+   Arguments may be null for unneeded fields.  */
+extern const char *dwfl_lineinfo (Dwfl_Line *line, Dwarf_Addr *addr,
+				  int *linep, int *colp,
+				  Dwarf_Word *mtime, Dwarf_Word *length);
+
+  /* Return the equivalent Dwarf_Line and the bias to apply to its address.  */
+extern Dwarf_Line *dwfl_dwarf_line (Dwfl_Line *line, Dwarf_Addr *bias);
+
+/* Return the compilation directory (AT_comp_dir) from this line's CU.  */
+extern const char *dwfl_line_comp_dir (Dwfl_Line *line);
+
+
+/*** Machine backend access functions ***/
+
+/* Return location expression to find return value given a
+   DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing
+   function itself (whose DW_AT_type attribute describes its return type).
+   The given DIE must come from the given module.  Returns -1 for errors.
+   Returns zero if the function has no return value (e.g. "void" in C).
+   Otherwise, *LOCOPS gets a location expression to find the return value,
+   and returns the number of operations in the expression.  The pointer is
+   permanently allocated at least as long as the module is live.  */
+extern int dwfl_module_return_value_location (Dwfl_Module *mod,
+					      Dwarf_Die *functypedie,
+					      const Dwarf_Op **locops);
+
+/* Enumerate the DWARF register numbers and their names.
+   For each register, CALLBACK gets its DWARF number, a string describing
+   the register set (such as "integer" or "FPU"), a prefix used in
+   assembler syntax (such as "%" or "$", may be ""), and the name for the
+   register (contains identifier characters only, possibly all digits).
+   The REGNAME string is valid only during the callback. */
+extern int dwfl_module_register_names (Dwfl_Module *mod,
+				       int (*callback) (void *arg,
+							int regno,
+							const char *setname,
+							const char *prefix,
+							const char *regname,
+							int bits, int type),
+				       void *arg);
+
+
+/* Find the CFI for this module.  Returns NULL if there is no CFI.
+   On success, fills in *BIAS with the difference between addresses
+   within the loaded module and those in the CFI referring to it.
+   The pointer returned can be used until the module is cleaned up.
+   Calling these more than once returns the same pointers.
+
+   dwfl_module_dwarf_cfi gets the '.debug_frame' information found with the
+   rest of the DWARF information.  dwfl_module_eh_cfi gets the '.eh_frame'
+   information found linked into the text.  A module might have either or
+   both.  */
+extern Dwarf_CFI *dwfl_module_dwarf_cfi (Dwfl_Module *mod, Dwarf_Addr *bias);
+extern Dwarf_CFI *dwfl_module_eh_cfi (Dwfl_Module *mod, Dwarf_Addr *bias);
+
+
+typedef struct
+{
+  /* Called to iterate through threads.  Returns next TID (thread ID) on
+     success, a negative number on failure and zero if there are no more
+     threads.  dwfl_errno () should be set if negative number has been
+     returned.  *THREAD_ARGP is NULL on first call, and may be optionally
+     set by the implementation. The value set by the implementation will
+     be passed in on the next call to NEXT_THREAD.  THREAD_ARGP is never
+     NULL.  *THREAD_ARGP will be passed to set_initial_registers or
+     thread_detach callbacks together with Dwfl_Thread *thread.  This
+     method must not be NULL.  */
+  pid_t (*next_thread) (Dwfl *dwfl, void *dwfl_arg, void **thread_argp)
+    __nonnull_attribute__ (1);
+
+  /* Called to get a specific thread.  Returns true if there is a
+     thread with the given thread id number, returns false if no such
+     thread exists and will set dwfl_errno in that case.  THREAD_ARGP
+     is never NULL.  *THREAD_ARGP will be passed to
+     set_initial_registers or thread_detach callbacks together with
+     Dwfl_Thread *thread.  This method may be NULL and will then be
+     emulated using the next_thread callback. */
+  bool (*get_thread) (Dwfl *dwfl, pid_t tid, void *dwfl_arg,
+		      void **thread_argp)
+    __nonnull_attribute__ (1);
+
+  /* Called during unwinding to access memory (stack) state.  Returns true for
+     successfully read *RESULT or false and sets dwfl_errno () on failure.
+     This method may be NULL - in such case dwfl_thread_getframes will return
+     only the initial frame.  */
+  bool (*memory_read) (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
+                       void *dwfl_arg)
+    __nonnull_attribute__ (1, 3);
+
+  /* Called on initial unwind to get the initial register state of the first
+     frame.  Should call dwfl_thread_state_registers, possibly multiple times
+     for different ranges and possibly also dwfl_thread_state_register_pc, to
+     fill in initial (DWARF) register values.  After this call, till at least
+     thread_detach is called, the thread is assumed to be frozen, so that it is
+     safe to unwind.  Returns true on success or false and sets dwfl_errno ()
+     on failure.  In the case of a failure thread_detach will not be called.
+     This method must not be NULL.  */
+  bool (*set_initial_registers) (Dwfl_Thread *thread, void *thread_arg)
+    __nonnull_attribute__ (1);
+
+  /* Called by dwfl_end.  All thread_detach method calls have been already
+     done.  This method may be NULL.  */
+  void (*detach) (Dwfl *dwfl, void *dwfl_arg)
+    __nonnull_attribute__ (1);
+
+  /* Called when unwinding is done.  No callback will be called after
+     this method has been called.  Iff set_initial_registers was called for
+     a TID and it returned success thread_detach will be called before the
+     detach method above.  This method may be NULL.  */
+  void (*thread_detach) (Dwfl_Thread *thread, void *thread_arg)
+    __nonnull_attribute__ (1);
+} Dwfl_Thread_Callbacks;
+
+/* PID is the process id associated with the DWFL state.  Architecture of DWFL
+   modules is specified by ELF, ELF must remain valid during DWFL lifetime.
+   Use NULL ELF to detect architecture from DWFL, the function will then detect
+   it from arbitrary Dwfl_Module of DWFL.  DWFL_ARG is the callback backend
+   state.  DWFL_ARG will be provided to the callbacks.  *THREAD_CALLBACKS
+   function pointers must remain valid during lifetime of DWFL.  Function
+   returns true on success, false otherwise.  */
+bool dwfl_attach_state (Dwfl *dwfl, Elf *elf, pid_t pid,
+                        const Dwfl_Thread_Callbacks *thread_callbacks,
+			void *dwfl_arg)
+  __nonnull_attribute__ (1, 4);
+
+/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting
+   thread state from the ELF core file.  Returns the pid number extracted
+   from the core file, or -1 for errors.  */
+extern int dwfl_core_file_attach (Dwfl *dwfl, Elf *elf);
+
+/* Calls dwfl_attach_state with Dwfl_Thread_Callbacks setup for extracting
+   thread state from the proc file system.  Uses ptrace to attach and stop
+   the thread under inspection and detaches when thread_detach is called
+   and unwinding for the thread is done, unless ASSUME_PTRACE_STOPPED is
+   true.  If ASSUME_PTRACE_STOPPED is true the caller should make sure that
+   the thread is ptrace attached and stopped before unwinding by calling
+   either dwfl_thread_getframes or dwfl_getthread_frames.  Returns zero on
+   success, -1 if dwfl_attach_state failed, or an errno code if opening the
+   proc files failed.  */
+extern int dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid,
+				   bool assume_ptrace_stopped);
+
+/* Return PID for the process associated with DWFL.  Function returns -1 if
+   dwfl_attach_state was not called for DWFL.  */
+pid_t dwfl_pid (Dwfl *dwfl)
+  __nonnull_attribute__ (1);
+
+/* Return DWFL from which THREAD was created using dwfl_getthreads.  */
+Dwfl *dwfl_thread_dwfl (Dwfl_Thread *thread)
+  __nonnull_attribute__ (1);
+
+/* Return positive TID (thread ID) for THREAD.  This function never fails.  */
+pid_t dwfl_thread_tid (Dwfl_Thread *thread)
+  __nonnull_attribute__ (1);
+
+/* Return thread for frame STATE.  This function never fails.  */
+Dwfl_Thread *dwfl_frame_thread (Dwfl_Frame *state)
+  __nonnull_attribute__ (1);
+
+/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation.
+   For every known continuous block of registers <FIRSTREG..FIRSTREG+NREGS)
+   (inclusive..exclusive) set their content to REGS (array of NREGS items).
+   Function returns false if any of the registers has invalid number.  */
+bool dwfl_thread_state_registers (Dwfl_Thread *thread, int firstreg,
+                                  unsigned nregs, const Dwarf_Word *regs)
+  __nonnull_attribute__ (1, 4);
+
+/* Called by Dwfl_Thread_Callbacks.set_initial_registers implementation.
+   If PC is not contained among DWARF registers passed by
+   dwfl_thread_state_registers on the target architecture pass the PC value
+   here.  */
+void dwfl_thread_state_register_pc (Dwfl_Thread *thread, Dwarf_Word pc)
+  __nonnull_attribute__ (1);
+
+/* Iterate through the threads for a process.  Returns zero if all threads have
+   been processed by the callback, returns -1 on error, or the value of the
+   callback when not DWARF_CB_OK.  -1 returned on error will set dwfl_errno ().
+   Keeps calling the callback with the next thread while the callback returns
+   DWARF_CB_OK, till there are no more threads.  */
+int dwfl_getthreads (Dwfl *dwfl,
+		     int (*callback) (Dwfl_Thread *thread, void *arg),
+		     void *arg)
+  __nonnull_attribute__ (1, 2);
+
+/* Iterate through the frames for a thread.  Returns zero if all frames
+   have been processed by the callback, returns -1 on error, or the value of
+   the callback when not DWARF_CB_OK.  -1 returned on error will
+   set dwfl_errno ().  Some systems return error instead of zero on end of the
+   backtrace, for cross-platform compatibility callers should consider error as
+   a zero.  Keeps calling the callback with the next frame while the callback
+   returns DWARF_CB_OK, till there are no more frames.  On start will call the
+   set_initial_registers callback and on return will call the detach_thread
+   callback of the Dwfl_Thread.  */
+int dwfl_thread_getframes (Dwfl_Thread *thread,
+			   int (*callback) (Dwfl_Frame *state, void *arg),
+			   void *arg)
+  __nonnull_attribute__ (1, 2);
+
+/* Like dwfl_thread_getframes, but specifying the thread by its unique
+   identifier number.  Returns zero if all frames have been processed
+   by the callback, returns -1 on error (and when no thread with
+   the given thread id number exists), or the value of the callback
+   when not DWARF_CB_OK.  -1 returned on error will set dwfl_errno ().  */
+int dwfl_getthread_frames (Dwfl *dwfl, pid_t tid,
+			   int (*callback) (Dwfl_Frame *thread, void *arg),
+			   void *arg)
+  __nonnull_attribute__ (1, 3);
+
+/* Return *PC (program counter) for thread-specific frame STATE.
+   Set *ISACTIVATION according to DWARF frame "activation" definition.
+   Typically you need to subtract 1 from *PC if *ACTIVATION is false to safely
+   find function of the caller.  ACTIVATION may be NULL.  PC must not be NULL.
+   Function returns false if it failed to find *PC.  */
+bool dwfl_frame_pc (Dwfl_Frame *state, Dwarf_Addr *pc, bool *isactivation)
+  __nonnull_attribute__ (1, 2);
+
+/* Get the value of the DWARF register number in the given frame.
+   Returns zero on success, -1 on error (invalid DWARF register
+   number) or 1 if the value of the register in the frame is unknown.  */
+int dwfl_frame_reg (Dwfl_Frame *state, unsigned regno, Dwarf_Word *val)
+  __nonnull_attribute__ (1);
+
+/* Return the internal debuginfod-client connection handle for the DWFL session.
+   When the client connection has not yet been initialized, it will be done on the
+   first call to this function. If elfutils is compiled without support for debuginfod,
+   NULL will be returned.
+ */
+extern debuginfod_client *dwfl_get_debuginfod_client (Dwfl *dwfl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* libdwfl.h */
diff --git a/libdwfl/libdwflP.h b/libdwfl/libdwflP.h
new file mode 100644
index 0000000..b3dfea1
--- /dev/null
+++ b/libdwfl/libdwflP.h
@@ -0,0 +1,806 @@
+/* Internal definitions for libdwfl.
+   Copyright (C) 2005-2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBDWFLP_H
+#define _LIBDWFLP_H	1
+
+#include <libdwfl.h>
+#include <libebl.h>
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libdwP.h"	/* We need its INTDECLs.  */
+#include "libdwelfP.h"
+
+typedef struct Dwfl_Process Dwfl_Process;
+
+#define DWFL_ERRORS							      \
+  DWFL_ERROR (NOERROR, N_("no error"))					      \
+  DWFL_ERROR (UNKNOWN_ERROR, N_("unknown error"))			      \
+  DWFL_ERROR (NOMEM, N_("out of memory"))				      \
+  DWFL_ERROR (ERRNO, N_("See errno"))					      \
+  DWFL_ERROR (LIBELF, N_("See elf_errno"))				      \
+  DWFL_ERROR (LIBDW, N_("See dwarf_errno"))				      \
+  DWFL_ERROR (LIBEBL, N_("See ebl_errno (XXX missing)"))		      \
+  DWFL_ERROR (ZLIB, N_("gzip decompression failed"))			      \
+  DWFL_ERROR (BZLIB, N_("bzip2 decompression failed"))			      \
+  DWFL_ERROR (LZMA, N_("LZMA decompression failed"))			      \
+  DWFL_ERROR (ZSTD, N_("zstd decompression failed"))			      \
+  DWFL_ERROR (UNKNOWN_MACHINE, N_("no support library found for machine"))    \
+  DWFL_ERROR (NOREL, N_("Callbacks missing for ET_REL file"))		      \
+  DWFL_ERROR (BADRELTYPE, N_("Unsupported relocation type"))		      \
+  DWFL_ERROR (BADRELOFF, N_("r_offset is bogus"))			      \
+  DWFL_ERROR (BADSTROFF, N_("offset out of range"))			      \
+  DWFL_ERROR (RELUNDEF, N_("relocation refers to undefined symbol"))	      \
+  DWFL_ERROR (CB, N_("Callback returned failure"))			      \
+  DWFL_ERROR (NO_DWARF, N_("No DWARF information found"))		      \
+  DWFL_ERROR (NO_SYMTAB, N_("No symbol table found"))			      \
+  DWFL_ERROR (NO_PHDR, N_("No ELF program headers"))			      \
+  DWFL_ERROR (OVERLAP, N_("address range overlaps an existing module"))	      \
+  DWFL_ERROR (ADDR_OUTOFRANGE, N_("address out of range"))		      \
+  DWFL_ERROR (NO_MATCH, N_("no matching address range"))		      \
+  DWFL_ERROR (TRUNCATED, N_("image truncated"))				      \
+  DWFL_ERROR (ALREADY_ELF, N_("ELF file opened"))			      \
+  DWFL_ERROR (BADELF, N_("not a valid ELF file"))			      \
+  DWFL_ERROR (WEIRD_TYPE, N_("cannot handle DWARF type description"))	      \
+  DWFL_ERROR (WRONG_ID_ELF, N_("ELF file does not match build ID"))	      \
+  DWFL_ERROR (BAD_PRELINK, N_("corrupt .gnu.prelink_undo section data"))      \
+  DWFL_ERROR (LIBEBL_BAD, N_("Internal error due to ebl"))		      \
+  DWFL_ERROR (CORE_MISSING, N_("Missing data in core file"))		      \
+  DWFL_ERROR (INVALID_REGISTER, N_("Invalid register"))			      \
+  DWFL_ERROR (REGISTER_VAL_UNKNOWN, N_("Unknown register value"))			      \
+  DWFL_ERROR (PROCESS_MEMORY_READ, N_("Error reading process memory"))	      \
+  DWFL_ERROR (PROCESS_NO_ARCH, N_("Couldn't find architecture of any ELF"))   \
+  DWFL_ERROR (PARSE_PROC, N_("Error parsing /proc filesystem"))		      \
+  DWFL_ERROR (INVALID_DWARF, N_("Invalid DWARF"))			      \
+  DWFL_ERROR (UNSUPPORTED_DWARF, N_("Unsupported DWARF"))		      \
+  DWFL_ERROR (NEXT_THREAD_FAIL, N_("Unable to find more threads"))	      \
+  DWFL_ERROR (ATTACH_STATE_CONFLICT, N_("Dwfl already has attached state"))   \
+  DWFL_ERROR (NO_ATTACH_STATE, N_("Dwfl has no attached state"))	      \
+  DWFL_ERROR (NO_UNWIND, N_("Unwinding not supported for this architecture")) \
+  DWFL_ERROR (INVALID_ARGUMENT, N_("Invalid argument"))			      \
+  DWFL_ERROR (NO_CORE_FILE, N_("Not an ET_CORE ELF file"))
+
+#define DWFL_ERROR(name, text) DWFL_E_##name,
+typedef enum { DWFL_ERRORS DWFL_E_NUM } Dwfl_Error;
+#undef	DWFL_ERROR
+
+#define OTHER_ERROR(name)	((unsigned int) DWFL_E_##name << 16)
+#define DWFL_E(name, errno)	(OTHER_ERROR (name) | (errno))
+
+extern int __libdwfl_canon_error (Dwfl_Error) internal_function;
+extern void __libdwfl_seterrno (Dwfl_Error) internal_function;
+
+/* Resources we might keep for the user about the core file that the
+   Dwfl might have been created from.  Can currently only be set
+   through std-argp.  */
+struct Dwfl_User_Core
+{
+  char *executable_for_core;	/* --executable if --core was specified.  */
+  Elf *core;                    /* non-NULL if we need to free it.  */
+  int fd;                       /* close if >= 0.  */
+};
+
+struct Dwfl
+{
+  const Dwfl_Callbacks *callbacks;
+#ifdef ENABLE_LIBDEBUGINFOD
+  debuginfod_client *debuginfod;
+#endif
+  Dwfl_Module *modulelist;    /* List in order used by full traversals.  */
+
+  Dwfl_Process *process;
+  Dwfl_Error attacherr;      /* Previous error attaching process.  */
+
+  GElf_Addr offline_next_address;
+
+  GElf_Addr segment_align;	/* Smallest granularity of segments.  */
+
+  /* Binary search table in three parallel malloc'd arrays.  */
+  size_t lookup_elts;		/* Elements in use.  */
+  size_t lookup_alloc;		/* Elements allococated.  */
+  GElf_Addr *lookup_addr;	/* Start address of segment.  */
+  Dwfl_Module **lookup_module;	/* Module associated with segment, or null.  */
+  int *lookup_segndx;		/* User segment index, or -1.  */
+  int next_segndx;
+
+  struct Dwfl_User_Core *user_core;
+};
+
+#define OFFLINE_REDZONE		0x10000
+
+struct dwfl_file
+{
+  char *name;
+  int fd;
+  bool valid;			/* The build ID note has been matched.  */
+  bool relocated;		/* Partial relocation of all sections done.  */
+
+  Elf *elf;
+
+  /* This is the lowest p_vaddr in this ELF file, aligned to p_align.
+     For a file without phdrs, this is zero.  */
+  GElf_Addr vaddr;
+
+  /* This is an address chosen for synchronization between the main file
+     and the debug file.  See dwfl_module_getdwarf.c for how it's chosen.  */
+  GElf_Addr address_sync;
+};
+
+struct Dwfl_Module
+{
+  Dwfl *dwfl;
+  struct Dwfl_Module *next;	/* Link on Dwfl.modulelist.  */
+
+  void *userdata;
+
+  char *name;			/* Iterator name for this module.  */
+  GElf_Addr low_addr, high_addr;
+
+  struct dwfl_file main, debug, aux_sym;
+  GElf_Addr main_bias;
+  Ebl *ebl;
+  GElf_Half e_type;		/* GElf_Ehdr.e_type cache.  */
+  Dwfl_Error elferr;		/* Previous failure to open main file.  */
+
+  struct dwfl_relocation *reloc_info; /* Relocatable sections.  */
+
+  struct dwfl_file *symfile;	/* Either main or debug.  */
+  Elf_Data *symdata;		/* Data in the ELF symbol table section.  */
+  Elf_Data *aux_symdata;	/* Data in the auxiliary ELF symbol table.  */
+  size_t syments;		/* sh_size / sh_entsize of that section.  */
+  size_t aux_syments;		/* sh_size / sh_entsize of aux_sym section.  */
+  int first_global;		/* Index of first global symbol of table.  */
+  int aux_first_global;		/* Index of first global of aux_sym table.  */
+  Elf_Data *symstrdata;		/* Data for its string table.  */
+  Elf_Data *aux_symstrdata;	/* Data for aux_sym string table.  */
+  Elf_Data *symxndxdata;	/* Data in the extended section index table. */
+  Elf_Data *aux_symxndxdata;	/* Data in the extended auxiliary table. */
+
+  char *elfpath;		/* The path where we found the main Elf.  */
+
+  Dwarf *dw;			/* libdw handle for its debugging info.  */
+  Dwarf *alt;			/* Dwarf used for dwarf_setalt, or NULL.  */
+  int alt_fd; 			/* descriptor, only valid when alt != NULL.  */
+  Elf *alt_elf; 		/* Elf for alt Dwarf.  */
+
+  Dwfl_Error symerr;		/* Previous failure to load symbols.  */
+  Dwfl_Error dwerr;		/* Previous failure to load DWARF.  */
+
+  /* Known CU's in this module.  */
+  struct dwfl_cu *first_cu, **cu;
+
+  void *lazy_cu_root;		/* Table indexed by Dwarf_Off of CU.  */
+
+  struct dwfl_arange *aranges;	/* Mapping of addresses in module to CUs.  */
+
+  void *build_id_bits;		/* malloc'd copy of build ID bits.  */
+  GElf_Addr build_id_vaddr;	/* Address where they reside, 0 if unknown.  */
+  int build_id_len;		/* -1 for prior failure, 0 if unset.  */
+
+  unsigned int ncu;
+  unsigned int lazycu;		/* Possible users, deleted when none left.  */
+  unsigned int naranges;
+
+  Dwarf_CFI *dwarf_cfi;		/* Cached DWARF CFI for this module.  */
+  Dwarf_CFI *eh_cfi;		/* Cached EH CFI for this module.  */
+
+  int segment;			/* Index of first segment table entry.  */
+  bool gc;			/* Mark/sweep flag.  */
+  bool is_executable;		/* Use Dwfl::executable_for_core?  */
+};
+
+/* This holds information common for all the threads/tasks/TIDs of one process
+   for backtraces.  */
+
+struct Dwfl_Process
+{
+  struct Dwfl *dwfl;
+  pid_t pid;
+  const Dwfl_Thread_Callbacks *callbacks;
+  void *callbacks_arg;
+  struct ebl *ebl;
+  bool ebl_close:1;
+};
+
+/* See its typedef in libdwfl.h.  */
+
+struct Dwfl_Thread
+{
+  Dwfl_Process *process;
+  pid_t tid;
+  /* Bottom (innermost) frame while we're initializing, NULL afterwards.  */
+  Dwfl_Frame *unwound;
+  void *callbacks_arg;
+};
+
+/* See its typedef in libdwfl.h.  */
+
+struct Dwfl_Frame
+{
+  Dwfl_Thread *thread;
+  /* Previous (outer) frame.  */
+  Dwfl_Frame *unwound;
+  bool signal_frame : 1;
+  bool initial_frame : 1;
+  enum
+  {
+    /* This structure is still being initialized or there was an error
+       initializing it.  */
+    DWFL_FRAME_STATE_ERROR,
+    /* PC field is valid.  */
+    DWFL_FRAME_STATE_PC_SET,
+    /* PC field is undefined, this means the next (inner) frame was the
+       outermost frame.  */
+    DWFL_FRAME_STATE_PC_UNDEFINED
+  } pc_state;
+  /* Either initialized from appropriate REGS element or on some archs
+     initialized separately as the return address has no DWARF register.  */
+  Dwarf_Addr pc;
+  /* (1 << X) bitmask where 0 <= X < ebl_frame_nregs.  */
+  uint64_t regs_set[3];
+  /* REGS array size is ebl_frame_nregs.
+     REGS_SET tells which of the REGS are valid.  */
+  Dwarf_Addr regs[];
+};
+
+/* Fetch value from Dwfl_Frame->regs indexed by DWARF REGNO.  The
+   function returns 0 on success, -1 on error (invalid DWARF register
+   number), 1 if the value of the register in the frame is unknown.
+   Even on error, no error code is set.  */
+int __libdwfl_frame_reg_get (Dwfl_Frame *state, unsigned regno,
+			      Dwarf_Addr *val)
+  internal_function;
+
+/* Store value to Dwfl_Frame->regs indexed by DWARF REGNO.
+   No error code is set if the function returns FALSE.  */
+bool __libdwfl_frame_reg_set (Dwfl_Frame *state, unsigned regno,
+			      Dwarf_Addr val)
+  internal_function;
+
+/* Information cached about each CU in Dwfl_Module.dw.  */
+struct dwfl_cu
+{
+  /* This caches libdw information about the CU.  It's also the
+     address passed back to users, so we take advantage of the
+     fact that it's placed first to cast back.  */
+  Dwarf_Die die;
+
+  Dwfl_Module *mod;		/* Pointer back to containing module.  */
+
+  struct dwfl_cu *next;		/* CU immediately following in the file.  */
+
+  struct Dwfl_Lines *lines;
+};
+
+struct Dwfl_Lines
+{
+  struct dwfl_cu *cu;
+
+  /* This is what the opaque Dwfl_Line * pointers we pass to users are.
+     We need to recover pointers to our struct dwfl_cu and a record in
+     libdw's Dwarf_Line table.  To minimize the memory used in addition
+     to libdw's Dwarf_Lines buffer, we just point to our own index in
+     this table, and have one pointer back to the CU.  The indices here
+     match those in libdw's Dwarf_CU.lines->info table.  */
+  struct Dwfl_Line
+  {
+    unsigned int idx;		/* My index in the dwfl_cu.lines table.  */
+  } idx[0];
+};
+
+static inline struct dwfl_cu *
+dwfl_linecu_inline (const Dwfl_Line *line)
+{
+  const struct Dwfl_Lines *lines = ((const void *) line
+				    - offsetof (struct Dwfl_Lines,
+						idx[line->idx]));
+  return lines->cu;
+}
+#define dwfl_linecu dwfl_linecu_inline
+
+static inline GElf_Addr
+dwfl_adjusted_address (Dwfl_Module *mod, GElf_Addr addr)
+{
+  return addr + mod->main_bias;
+}
+
+static inline GElf_Addr
+dwfl_deadjust_address (Dwfl_Module *mod, GElf_Addr addr)
+{
+  return addr - mod->main_bias;
+}
+
+static inline Dwarf_Addr
+dwfl_adjusted_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return dwfl_adjusted_address (mod, (addr
+				      - mod->debug.address_sync
+				      + mod->main.address_sync));
+}
+
+static inline Dwarf_Addr
+dwfl_deadjust_dwarf_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return (dwfl_deadjust_address (mod, addr)
+	  - mod->main.address_sync
+	  + mod->debug.address_sync);
+}
+
+static inline Dwarf_Addr
+dwfl_adjusted_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return dwfl_adjusted_address (mod, (addr
+				      - mod->aux_sym.address_sync
+				      + mod->main.address_sync));
+}
+
+static inline Dwarf_Addr
+dwfl_deadjust_aux_sym_addr (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  return (dwfl_deadjust_address (mod, addr)
+	  - mod->main.address_sync
+	  + mod->aux_sym.address_sync);
+}
+
+static inline GElf_Addr
+dwfl_adjusted_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
+{
+  if (symelf == mod->main.elf)
+    return dwfl_adjusted_address (mod, addr);
+  if (symelf == mod->debug.elf)
+    return dwfl_adjusted_dwarf_addr (mod, addr);
+  return dwfl_adjusted_aux_sym_addr (mod, addr);
+}
+
+static inline GElf_Addr
+dwfl_deadjust_st_value (Dwfl_Module *mod, Elf *symelf, GElf_Addr addr)
+{
+  if (symelf == mod->main.elf)
+    return dwfl_deadjust_address (mod, addr);
+  if (symelf == mod->debug.elf)
+    return dwfl_deadjust_dwarf_addr (mod, addr);
+  return dwfl_deadjust_aux_sym_addr (mod, addr);
+}
+
+/* This describes a contiguous address range that lies in a single CU.
+   We condense runs of Dwarf_Arange entries for the same CU into this.  */
+struct dwfl_arange
+{
+  struct dwfl_cu *cu;
+  size_t arange;		/* Index in Dwarf_Aranges.  */
+};
+
+#define __LIBDWFL_REMOTE_MEM_CACHE_SIZE 4096
+/* Structure for caching remote memory reads as used by __libdwfl_pid_arg.  */
+struct __libdwfl_remote_mem_cache
+{
+  Dwarf_Addr addr; /* Remote address.  */
+  Dwarf_Off len;   /* Zero if cleared, otherwise likely 4K. */
+  unsigned char buf[__LIBDWFL_REMOTE_MEM_CACHE_SIZE]; /* The actual cache.  */
+};
+
+/* Structure used for keeping track of ptrace attaching a thread.
+   Shared by linux-pid-attach and linux-proc-maps.  If it has been setup
+   then get the instance through __libdwfl_get_pid_arg.  */
+struct __libdwfl_pid_arg
+{
+  /* /proc/PID/task/.  */
+  DIR *dir;
+  /* Elf for /proc/PID/exe.  Set to NULL if it couldn't be opened.  */
+  Elf *elf;
+  /* Remote memory cache, NULL if there is no memory cached.
+     Should be cleared on detachment (because that makes the thread
+     runnable and the cache invalid).  */
+  struct __libdwfl_remote_mem_cache *mem_cache;
+  /* fd for /proc/PID/exe.  Set to -1 if it couldn't be opened.  */
+  int elf_fd;
+  /* It is 0 if not used.  */
+  pid_t tid_attached;
+  /* Valid only if TID_ATTACHED is not zero.  */
+  bool tid_was_stopped;
+  /* True if threads are ptrace stopped by caller.  */
+  bool assume_ptrace_stopped;
+};
+
+/* If DWfl is not NULL and a Dwfl_Process has been setup that has
+   Dwfl_Thread_Callbacks set to pid_thread_callbacks, then return the
+   callbacks_arg, which will be a struct __libdwfl_pid_arg.  Otherwise
+   returns NULL.  */
+extern struct __libdwfl_pid_arg *__libdwfl_get_pid_arg (Dwfl *dwfl)
+  internal_function;
+
+/* Makes sure the given tid is attached. On success returns true and
+   sets tid_was_stopped.  */
+extern bool __libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
+  internal_function;
+
+/* Detaches a tid that was attached through
+   __libdwfl_ptrace_attach. Must be given the tid_was_stopped as set
+   by __libdwfl_ptrace_attach.  */
+extern void __libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
+  internal_function;
+
+
+/* Internal wrapper for old dwfl_module_getsym and new dwfl_module_getsym_info.
+   adjust_st_value set to true returns adjusted SYM st_value, set to false
+   it will not adjust SYM at all, but does match against resolved *ADDR. */
+extern const char *__libdwfl_getsym (Dwfl_Module *mod, int ndx, GElf_Sym *sym,
+				     GElf_Addr *addr, GElf_Word *shndxp,
+				     Elf **elfp, Dwarf_Addr *biasp,
+				     bool *resolved, bool adjust_st_value)
+  internal_function;
+
+extern void __libdwfl_module_free (Dwfl_Module *mod) internal_function;
+
+/* Find the main ELF file, update MOD->elferr and/or MOD->main.elf.  */
+extern void __libdwfl_getelf (Dwfl_Module *mod) internal_function;
+
+/* Process relocations in debugging sections in an ET_REL file.
+   FILE must be opened with ELF_C_READ_MMAP_PRIVATE or ELF_C_READ,
+   to make it possible to relocate the data in place (or ELF_C_RDWR or
+   ELF_C_RDWR_MMAP if you intend to modify the Elf file on disk).  After
+   this, dwarf_begin_elf on FILE will read the relocated data.
+
+   When DEBUG is false, apply partial relocation to all sections.  */
+extern Dwfl_Error __libdwfl_relocate (Dwfl_Module *mod, Elf *file, bool debug)
+  internal_function;
+
+/* Find the section index in mod->main.elf that contains the given
+   *ADDR.  Adjusts *ADDR to be section relative on success, returns
+   SHN_UNDEF on failure.  */
+extern size_t __libdwfl_find_section_ndx (Dwfl_Module *mod, Dwarf_Addr *addr)
+  internal_function;
+
+/* Process (simple) relocations in arbitrary section TSCN of an ET_REL file.
+   RELOCSCN is SHT_REL or SHT_RELA and TSCN is its sh_info target section.  */
+extern Dwfl_Error __libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
+					      Elf_Scn *relocscn, Elf_Scn *tscn,
+					      bool partial)
+  internal_function;
+
+/* Adjust *VALUE from section-relative to absolute.
+   MOD->dwfl->callbacks->section_address is called to determine the actual
+   address of a loaded section.  */
+extern Dwfl_Error __libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf,
+					    size_t *shstrndx_cache,
+					    Elf32_Word shndx,
+					    GElf_Addr *value)
+     internal_function;
+
+/* Ensure that MOD->ebl is set up.  */
+extern Dwfl_Error __libdwfl_module_getebl (Dwfl_Module *mod) internal_function;
+
+/* Install a new Dwarf_CFI in *SLOT (MOD->eh_cfi or MOD->dwarf_cfi).  */
+extern Dwarf_CFI *__libdwfl_set_cfi (Dwfl_Module *mod, Dwarf_CFI **slot,
+				     Dwarf_CFI *cfi)
+  internal_function;
+
+/* Iterate through all the CU's in the module.  Start by passing a null
+   LASTCU, and then pass the last *CU returned.  Success return with null
+   *CU no more CUs.  */
+extern Dwfl_Error __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
+				    struct dwfl_cu **cu) internal_function;
+
+/* Find the CU by address.  */
+extern Dwfl_Error __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr,
+				    struct dwfl_cu **cu) internal_function;
+
+/* Ensure that CU->lines (and CU->cu->lines) is set up.  */
+extern Dwfl_Error __libdwfl_cu_getsrclines (struct dwfl_cu *cu)
+  internal_function;
+
+/* Look in ELF for an NT_GNU_BUILD_ID note.  Store it to BUILD_ID_BITS,
+   its vaddr in ELF to BUILD_ID_VADDR (it is unrelocated, even if MOD is not
+   NULL) and store length to BUILD_ID_LEN.  Returns -1 for errors, 1 if it was
+   stored and 0 if no note is found.  MOD may be NULL, MOD must be non-NULL
+   only if ELF is ET_REL.  */
+extern int __libdwfl_find_elf_build_id (Dwfl_Module *mod, Elf *elf,
+					const void **build_id_bits,
+					GElf_Addr *build_id_elfaddr,
+					int *build_id_len)
+  internal_function;
+
+/* Look in ELF for an NT_GNU_BUILD_ID note.  If SET is true, store it
+   in MOD and return its length.  If SET is false, instead compare it
+   to that stored in MOD and return 2 if they match, 1 if they do not.
+   Returns -1 for errors, 0 if no note is found.  */
+extern int __libdwfl_find_build_id (Dwfl_Module *mod, bool set, Elf *elf)
+  internal_function;
+
+/* Open a main or debuginfo file by its build ID, returns the fd.  */
+extern int __libdwfl_open_mod_by_build_id (Dwfl_Module *mod, bool debug,
+					   char **file_name) internal_function;
+
+/* Same, but takes an explicit build_id, can also be used for alt debug.  */
+extern int __libdwfl_open_by_build_id (Dwfl_Module *mod, bool debug,
+				       char **file_name, const size_t id_len,
+				       const uint8_t *id) internal_function;
+
+extern uint32_t __libdwfl_crc32 (uint32_t crc, unsigned char *buf, size_t len)
+  attribute_hidden;
+extern int __libdwfl_crc32_file (int fd, uint32_t *resp) attribute_hidden;
+
+
+/* Given ELF and some parameters return TRUE if the *P return value parameters
+   have been successfully filled in.  Any of the *P parameters can be NULL.  */
+extern bool __libdwfl_elf_address_range (Elf *elf, GElf_Addr base,
+					 bool add_p_vaddr, bool sanity,
+					 GElf_Addr *vaddrp,
+					 GElf_Addr *address_syncp,
+					 GElf_Addr *startp, GElf_Addr *endp,
+					 GElf_Addr *biasp, GElf_Half *e_typep)
+  internal_function;
+
+/* Meat of dwfl_report_elf, given elf_begin just called.
+   Consumes ELF on success, not on failure.  */
+extern Dwfl_Module *__libdwfl_report_elf (Dwfl *dwfl, const char *name,
+					  const char *file_name, int fd,
+					  Elf *elf, GElf_Addr base,
+					  bool add_p_vaddr, bool sanity)
+  internal_function;
+
+/* Meat of dwfl_report_offline.  */
+extern Dwfl_Module *__libdwfl_report_offline (Dwfl *dwfl, const char *name,
+					      const char *file_name,
+					      int fd, bool closefd,
+					      int (*predicate) (const char *,
+								const char *))
+  internal_function;
+
+/* Free PROCESS.  Unlink and free also any structures it references.  */
+extern void __libdwfl_process_free (Dwfl_Process *process)
+  internal_function;
+
+/* Update STATE->unwound for the unwound frame.
+   On error STATE->unwound == NULL
+   or STATE->unwound->pc_state == DWFL_FRAME_STATE_ERROR;
+   in such case dwfl_errno () is set.
+   If STATE->unwound->pc_state == DWFL_FRAME_STATE_PC_UNDEFINED
+   then STATE was the last valid frame.  */
+extern void __libdwfl_frame_unwind (Dwfl_Frame *state)
+  internal_function;
+
+/* Align segment START downwards or END upwards addresses according to DWFL.  */
+extern GElf_Addr __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
+  internal_function;
+extern GElf_Addr __libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
+  internal_function;
+
+/* Decompression wrappers: decompress whole file into memory.  */
+extern Dwfl_Error __libdw_gunzip  (int fd, off_t start_offset,
+				   void *mapped, size_t mapped_size,
+				   void **whole, size_t *whole_size)
+  internal_function;
+extern Dwfl_Error __libdw_bunzip2 (int fd, off_t start_offset,
+				   void *mapped, size_t mapped_size,
+				   void **whole, size_t *whole_size)
+  internal_function;
+extern Dwfl_Error __libdw_unlzma (int fd, off_t start_offset,
+				  void *mapped, size_t mapped_size,
+				  void **whole, size_t *whole_size)
+  internal_function;
+extern Dwfl_Error __libdw_unzstd (int fd, off_t start_offset,
+				  void *mapped, size_t mapped_size,
+				  void **whole, size_t *whole_size)
+  internal_function;
+
+/* Skip the image header before a file image: updates *START_OFFSET.  */
+extern Dwfl_Error __libdw_image_header (int fd, off_t *start_offset,
+					void *mapped, size_t mapped_size)
+  internal_function;
+
+/* Open Elf handle on *FDP.  This handles decompression and checks
+   elf_kind.  Succeed only for ELF_K_ELF, or also ELF_K_AR if ARCHIVE_OK.
+   Returns DWFL_E_NOERROR and sets *ELFP on success, resets *FDP to -1 if
+   it's no longer used.  Resets *FDP on failure too iff CLOSE_ON_FAIL.  */
+extern Dwfl_Error __libdw_open_file (int *fdp, Elf **elfp,
+				     bool close_on_fail, bool archive_ok)
+  internal_function;
+
+/* Same as __libdw_open_file, but opens Elf handle from memory region.  */
+extern Dwfl_Error __libdw_open_elf_memory (char *data, size_t size, Elf **elfp,
+					   bool archive_ok)
+  internal_function;
+
+/* Same as __libdw_open_file, but never closes the given file
+   descriptor and ELF_K_AR is always an acceptable type.  */
+extern Dwfl_Error __libdw_open_elf (int fd, Elf **elfp) internal_function;
+
+/* Fetch PT_DYNAMIC P_VADDR from ELF and store it to *VADDRP.  Return success.
+   *VADDRP is not modified if the function fails.  */
+extern bool __libdwfl_dynamic_vaddr_get (Elf *elf, GElf_Addr *vaddrp)
+  internal_function;
+
+#ifdef ENABLE_LIBDEBUGINFOD
+/* Internal interface to libdebuginfod (if installed).  */
+int
+__libdwfl_debuginfod_find_executable (Dwfl *dwfl,
+				      const unsigned char *build_id_bits,
+				      size_t build_id_len);
+int
+__libdwfl_debuginfod_find_debuginfo (Dwfl *dwfl,
+				     const unsigned char *build_id_bits,
+				     size_t build_id_len);
+void
+__libdwfl_debuginfod_end (debuginfod_client *c);
+#endif
+
+
+/* These are working nicely for --core, but are not ready to be
+   exported interfaces quite yet.  */
+
+/* Type of callback function ...
+ */
+typedef bool Dwfl_Memory_Callback (Dwfl *dwfl, int segndx,
+				   void **buffer, size_t *buffer_available,
+				   GElf_Addr vaddr, size_t minread, void *arg);
+
+/* Type of callback function ...
+ */
+typedef bool Dwfl_Module_Callback (Dwfl_Module *mod, void **userdata,
+				   const char *name, Dwarf_Addr base,
+				   void **buffer, size_t *buffer_available,
+				   GElf_Off cost, GElf_Off worthwhile,
+				   GElf_Off whole, GElf_Off contiguous,
+				   void *arg, Elf **elfp);
+
+/* One shared library (or executable) info from DT_DEBUG link map.  */
+struct r_debug_info_module
+{
+  struct r_debug_info_module *next;
+  /* FD is -1 iff ELF is NULL.  */
+  int fd;
+  Elf *elf;
+  GElf_Addr l_ld;
+  /* START and END are both zero if not valid.  */
+  GElf_Addr start, end;
+  bool disk_file_has_build_id;
+  char name[0];
+};
+
+/* Information gathered from DT_DEBUG by dwfl_link_map_report hinted to
+   dwfl_segment_report_module.  */
+struct r_debug_info
+{
+  struct r_debug_info_module *module;
+};
+
+/* ...
+ */
+extern int dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name,
+				       Dwfl_Memory_Callback *memory_callback,
+				       void *memory_callback_arg,
+				       Dwfl_Module_Callback *read_eagerly,
+				       void *read_eagerly_arg,
+				       size_t maxread,
+				       const void *note_file,
+				       size_t note_file_size,
+				       const struct r_debug_info *r_debug_info);
+
+/* Report a module for entry in the dynamic linker's struct link_map list.
+   For each link_map entry, if an existing module resides at its address,
+   this just modifies that module's name and suggested file name.  If
+   no such module exists, this calls dwfl_report_elf on the l_name string.
+
+   If AUXV is not null, it points to AUXV_SIZE bytes of auxiliary vector
+   data as contained in an NT_AUXV note or read from a /proc/pid/auxv
+   file.  When this is available, it guides the search.  If AUXV is null
+   or the memory it points to is not accessible, then this search can
+   only find where to begin if the correct executable file was
+   previously reported and preloaded as with dwfl_report_elf.
+
+   Fill in R_DEBUG_INFO if it is not NULL.  It should be cleared by the
+   caller, this function does not touch fields it does not need to modify.
+   If R_DEBUG_INFO is not NULL then no modules get added to DWFL, caller
+   has to add them from filled in R_DEBUG_INFO.
+
+   Returns the number of modules found, or -1 for errors.  */
+extern int dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
+				 Dwfl_Memory_Callback *memory_callback,
+				 void *memory_callback_arg,
+				 struct r_debug_info *r_debug_info);
+
+
+/* Avoid PLT entries.  */
+INTDECL (dwfl_begin)
+INTDECL (dwfl_errmsg)
+INTDECL (dwfl_errno)
+INTDECL (dwfl_addrmodule)
+INTDECL (dwfl_addrsegment)
+INTDECL (dwfl_addrdwarf)
+INTDECL (dwfl_addrdie)
+INTDECL (dwfl_core_file_attach)
+INTDECL (dwfl_core_file_report)
+INTDECL (dwfl_getmodules)
+INTDECL (dwfl_module_addrdie)
+INTDECL (dwfl_module_address_section)
+INTDECL (dwfl_module_addrinfo)
+INTDECL (dwfl_module_addrsym)
+INTDECL (dwfl_module_build_id)
+INTDECL (dwfl_module_getdwarf)
+INTDECL (dwfl_module_getelf)
+INTDECL (dwfl_module_getsym)
+INTDECL (dwfl_module_getsym_info)
+INTDECL (dwfl_module_getsymtab)
+INTDECL (dwfl_module_getsymtab_first_global)
+INTDECL (dwfl_module_getsrc)
+INTDECL (dwfl_module_report_build_id)
+INTDECL (dwfl_report_elf)
+INTDECL (dwfl_report_begin)
+INTDECL (dwfl_report_begin_add)
+INTDECL (dwfl_report_module)
+INTDECL (dwfl_report_segment)
+INTDECL (dwfl_report_offline)
+INTDECL (dwfl_report_offline_memory)
+INTDECL (dwfl_report_end)
+INTDECL (dwfl_build_id_find_elf)
+INTDECL (dwfl_build_id_find_debuginfo)
+INTDECL (dwfl_standard_find_debuginfo)
+INTDECL (dwfl_link_map_report)
+INTDECL (dwfl_linux_kernel_find_elf)
+INTDECL (dwfl_linux_kernel_module_section_address)
+INTDECL (dwfl_linux_proc_attach)
+INTDECL (dwfl_linux_proc_report)
+INTDECL (dwfl_linux_proc_maps_report)
+INTDECL (dwfl_linux_proc_find_elf)
+INTDECL (dwfl_linux_kernel_report_kernel)
+INTDECL (dwfl_linux_kernel_report_modules)
+INTDECL (dwfl_linux_kernel_report_offline)
+INTDECL (dwfl_offline_section_address)
+INTDECL (dwfl_module_relocate_address)
+INTDECL (dwfl_module_dwarf_cfi)
+INTDECL (dwfl_module_eh_cfi)
+INTDECL (dwfl_attach_state)
+INTDECL (dwfl_pid)
+INTDECL (dwfl_thread_dwfl)
+INTDECL (dwfl_thread_tid)
+INTDECL (dwfl_frame_thread)
+INTDECL (dwfl_thread_state_registers)
+INTDECL (dwfl_thread_state_register_pc)
+INTDECL (dwfl_getthread_frames)
+INTDECL (dwfl_getthreads)
+INTDECL (dwfl_thread_getframes)
+INTDECL (dwfl_frame_pc)
+INTDECL (dwfl_frame_reg)
+INTDECL (dwfl_get_debuginfod_client)
+
+/* Leading arguments standard to callbacks passed a Dwfl_Module.  */
+#define MODCB_ARGS(mod)	(mod), &(mod)->userdata, (mod)->name, (mod)->low_addr
+#define CBFAIL		(errno ? DWFL_E (ERRNO, errno) : DWFL_E_CB);
+
+
+/* The default used by dwfl_standard_find_debuginfo.  */
+#define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug"
+
+
+#endif	/* libdwflP.h */
diff --git a/libdwfl/libdwfl_crc32.c b/libdwfl/libdwfl_crc32.c
new file mode 100644
index 0000000..5bc7a4a
--- /dev/null
+++ b/libdwfl/libdwfl_crc32.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define crc32 attribute_hidden __libdwfl_crc32
+#include <libdwflP.h>
+#include "../lib/crc32.c"
diff --git a/libdwfl/libdwfl_crc32_file.c b/libdwfl/libdwfl_crc32_file.c
new file mode 100644
index 0000000..f849128
--- /dev/null
+++ b/libdwfl/libdwfl_crc32_file.c
@@ -0,0 +1,35 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define crc32_file attribute_hidden __libdwfl_crc32_file
+#define crc32 __libdwfl_crc32
+#include <libdwflP.h>
+#include "../lib/crc32_file.c"
diff --git a/libdwfl/lines.c b/libdwfl/lines.c
new file mode 100644
index 0000000..a7f3004
--- /dev/null
+++ b/libdwfl/lines.c
@@ -0,0 +1,56 @@
+/* Fetch source line info for CU.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include "libdwP.h"
+
+Dwfl_Error
+internal_function
+__libdwfl_cu_getsrclines (struct dwfl_cu *cu)
+{
+  if (cu->lines == NULL)
+    {
+      Dwarf_Lines *lines;
+      size_t nlines;
+      if (INTUSE(dwarf_getsrclines) (&cu->die, &lines, &nlines) != 0)
+	return DWFL_E_LIBDW;
+
+      cu->lines = malloc (offsetof (struct Dwfl_Lines, idx[nlines]));
+      if (cu->lines == NULL)
+	return DWFL_E_NOMEM;
+      cu->lines->cu = cu;
+      for (unsigned int i = 0; i < nlines; ++i)
+	cu->lines->idx[i].idx = i;
+    }
+
+  return DWFL_E_NOERROR;
+}
diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c
new file mode 100644
index 0000000..a6c66c7
--- /dev/null
+++ b/libdwfl/link_map.c
@@ -0,0 +1,1125 @@
+/* Report modules by examining dynamic linker data structures.
+   Copyright (C) 2008-2016 Red Hat, Inc.
+   Copyright (C) 2021 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include "libdwflP.h"
+#include "memory-access.h"
+#include "system.h"
+
+#include <fcntl.h>
+
+/* This element is always provided and always has a constant value.
+   This makes it an easy thing to scan for to discern the format.  */
+#define PROBE_TYPE	AT_PHENT
+#define PROBE_VAL32	sizeof (Elf32_Phdr)
+#define PROBE_VAL64	sizeof (Elf64_Phdr)
+
+
+static inline bool
+do_check64 (const char *a64, uint_fast8_t *elfdata)
+{
+  /* The AUXV pointer might not even be naturally aligned for 64-bit
+     data, because note payloads in a core file are not aligned.  */
+  const char *typep = a64 + offsetof (Elf64_auxv_t, a_type);
+  uint64_t type = read_8ubyte_unaligned_noncvt (typep);
+  const char *valp = a64 + offsetof (Elf64_auxv_t, a_un.a_val);
+  uint64_t val = read_8ubyte_unaligned_noncvt (valp);
+
+  if (type == BE64 (PROBE_TYPE)
+      && val == BE64 (PROBE_VAL64))
+    {
+      *elfdata = ELFDATA2MSB;
+      return true;
+    }
+
+  if (type == LE64 (PROBE_TYPE)
+      && val == LE64 (PROBE_VAL64))
+    {
+      *elfdata = ELFDATA2LSB;
+      return true;
+    }
+
+  return false;
+}
+
+static inline bool
+do_check32 (const char *a32, uint_fast8_t *elfdata)
+{
+  /* The AUXV pointer might not even be naturally aligned for 32-bit
+     data, because note payloads in a core file are not aligned.  */
+  const char *typep = a32 + offsetof (Elf32_auxv_t, a_type);
+  uint32_t type = read_4ubyte_unaligned_noncvt (typep);
+  const char *valp = a32 + offsetof (Elf32_auxv_t, a_un.a_val);
+  uint32_t val = read_4ubyte_unaligned_noncvt (valp);
+
+  if (type == BE32 (PROBE_TYPE)
+      && val == BE32 (PROBE_VAL32))
+    {
+      *elfdata = ELFDATA2MSB;
+      return true;
+    }
+
+  if (type == LE32 (PROBE_TYPE)
+      && val == LE32 (PROBE_VAL32))
+    {
+      *elfdata = ELFDATA2LSB;
+      return true;
+    }
+
+  return false;
+}
+
+/* Examine an auxv data block and determine its format.
+   Return true iff we figured it out.  */
+static bool
+auxv_format_probe (const void *auxv, size_t size,
+		   uint_fast8_t *elfclass, uint_fast8_t *elfdata)
+{
+  for (size_t i = 0; i < size / sizeof (Elf64_auxv_t); ++i)
+    {
+      if (do_check64 (auxv + i * sizeof (Elf64_auxv_t), elfdata))
+	{
+	  *elfclass = ELFCLASS64;
+	  return true;
+	}
+
+      if (do_check32 (auxv + (i * 2) * sizeof (Elf32_auxv_t), elfdata)
+	  || do_check32 (auxv + (i * 2 + 1) * sizeof (Elf32_auxv_t), elfdata))
+	{
+	  *elfclass = ELFCLASS32;
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+/* This is a Dwfl_Memory_Callback that wraps another memory callback.
+   If the underlying callback cannot fill the data, then this will
+   fall back to fetching data from module files.  */
+
+struct integrated_memory_callback
+{
+  Dwfl_Memory_Callback *memory_callback;
+  void *memory_callback_arg;
+  void *buffer;
+};
+
+static bool
+integrated_memory_callback (Dwfl *dwfl, int ndx,
+			       void **buffer, size_t *buffer_available,
+			       GElf_Addr vaddr,
+			       size_t minread,
+			       void *arg)
+{
+  struct integrated_memory_callback *info = arg;
+
+  if (ndx == -1)
+    {
+      /* Called for cleanup.  */
+      if (info->buffer != NULL)
+	{
+	  /* The last probe buffer came from the underlying callback.
+	     Let it do its cleanup.  */
+	  assert (*buffer == info->buffer); /* XXX */
+	  *buffer = info->buffer;
+	  info->buffer = NULL;
+	  return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
+					   vaddr, minread,
+					   info->memory_callback_arg);
+	}
+      *buffer = NULL;
+      *buffer_available = 0;
+      return false;
+    }
+
+  if (*buffer != NULL)
+    /* For a final-read request, we only use the underlying callback.  */
+    return (*info->memory_callback) (dwfl, ndx, buffer, buffer_available,
+				     vaddr, minread, info->memory_callback_arg);
+
+  /* Let the underlying callback try to fill this request.  */
+  if ((*info->memory_callback) (dwfl, ndx, &info->buffer, buffer_available,
+				vaddr, minread, info->memory_callback_arg))
+    {
+      *buffer = info->buffer;
+      return true;
+    }
+
+  /* Now look for module text covering this address.  */
+
+  Dwfl_Module *mod;
+  (void) INTUSE(dwfl_addrsegment) (dwfl, vaddr, &mod);
+  if (mod == NULL)
+    return false;
+
+  Dwarf_Addr bias;
+  Elf_Scn *scn = INTUSE(dwfl_module_address_section) (mod, &vaddr, &bias);
+  if (unlikely (scn == NULL))
+    {
+#if 0 // XXX would have to handle ndx=-1 cleanup calls passed down.
+      /* If we have no sections we can try to fill it from the module file
+	 based on its phdr mappings.  */
+      if (likely (mod->e_type != ET_REL) && mod->main.elf != NULL)
+	return INTUSE(dwfl_elf_phdr_memory_callback)
+	  (dwfl, 0, buffer, buffer_available,
+	   vaddr - mod->main.bias, minread, mod->main.elf);
+#endif
+      return false;
+    }
+
+  Elf_Data *data = elf_rawdata (scn, NULL);
+  if (unlikely (data == NULL))
+    // XXX throw error?
+    return false;
+
+  if (unlikely (data->d_size < vaddr))
+    return false;
+
+  /* Provide as much data as we have.  */
+  void *contents = data->d_buf + vaddr;
+  size_t avail = data->d_size - vaddr;
+  if (unlikely (avail < minread))
+    return false;
+
+  /* If probing for a string, make sure it's terminated.  */
+  if (minread == 0 && unlikely (memchr (contents, '\0', avail) == NULL))
+    return false;
+
+  /* We have it! */
+  *buffer = contents;
+  *buffer_available = avail;
+  return true;
+}
+
+static size_t
+addrsize (uint_fast8_t elfclass)
+{
+  return elfclass * 4;
+}
+
+struct memory_closure
+{
+  Dwfl *dwfl;
+  Dwfl_Memory_Callback *callback;
+  void *arg;
+};
+
+static inline int
+release_buffer (struct memory_closure *closure,
+                void **buffer, size_t *buffer_available, int result)
+{
+  if (*buffer != NULL)
+    (*closure->callback) (closure->dwfl, -1, buffer, buffer_available, 0, 0,
+                          closure->arg);
+
+  return result;
+}
+
+static inline bool
+read_addrs (struct memory_closure *closure,
+	    uint_fast8_t elfclass, uint_fast8_t elfdata,
+	    void **buffer, size_t *buffer_available,
+	    GElf_Addr vaddr, GElf_Addr *read_vaddr,
+	    size_t n, GElf_Addr *addrs /* [4] */)
+{
+  size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read.  */
+  Dwfl *dwfl = closure->dwfl;
+
+  /* Read a new buffer if the old one doesn't cover these words.  */
+  if (*buffer == NULL
+      || vaddr < *read_vaddr
+      || nb > *buffer_available
+      || vaddr - (*read_vaddr) > *buffer_available - nb)
+    {
+      release_buffer (closure, buffer, buffer_available, 0);
+
+      *read_vaddr = vaddr;
+      int segndx = INTUSE(dwfl_addrsegment) (dwfl, vaddr, NULL);
+      if (unlikely (segndx < 0)
+	  || unlikely (! (*closure->callback) (dwfl, segndx,
+					       buffer, buffer_available,
+					       vaddr, nb, closure->arg)))
+	return true;
+    }
+
+  unsigned char *addr = vaddr - (*read_vaddr) + (*buffer);
+
+  if (elfclass == ELFCLASS32)
+    {
+      if (elfdata == ELFDATA2MSB)
+	for (size_t i = 0; i < n; ++i)
+	  addrs[i] = BE32 (read_4ubyte_unaligned_noncvt (addr + i * 4));
+      else
+	for (size_t i = 0; i < n; ++i)
+	  addrs[i] = LE32 (read_4ubyte_unaligned_noncvt (addr + i * 4));
+    }
+  else
+    {
+      if (elfdata == ELFDATA2MSB)
+	for (size_t i = 0; i < n; ++i)
+	  addrs[i] = BE64 (read_8ubyte_unaligned_noncvt (addr + i * 8));
+      else
+	for (size_t i = 0; i < n; ++i)
+	  addrs[i] = LE64 (read_8ubyte_unaligned_noncvt (addr + i * 8));
+    }
+
+  return false;
+}
+
+/* Report a module for each struct link_map in the linked list at r_map
+   in the struct r_debug at R_DEBUG_VADDR.  For r_debug_info description
+   see dwfl_link_map_report in libdwflP.h.  If R_DEBUG_INFO is not NULL then no
+   modules get added to DWFL, caller has to add them from filled in
+   R_DEBUG_INFO.
+
+   For each link_map entry, if an existing module resides at its address,
+   this just modifies that module's name and suggested file name.  If
+   no such module exists, this calls dwfl_report_elf on the l_name string.
+
+   Returns the number of modules found, or -1 for errors.  */
+
+static int
+report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata,
+		Dwfl *dwfl, GElf_Addr r_debug_vaddr,
+		Dwfl_Memory_Callback *memory_callback,
+		void *memory_callback_arg,
+		struct r_debug_info *r_debug_info)
+{
+  /* Skip r_version, to aligned r_map field.  */
+  GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass);
+
+  void *buffer = NULL;
+  size_t buffer_available = 0;
+  GElf_Addr addrs[4];
+  struct memory_closure memory_closure = { dwfl, memory_callback,
+                                           memory_callback_arg };
+  if (unlikely (read_addrs (&memory_closure, elfclass, elfdata,
+			    &buffer, &buffer_available, read_vaddr, &read_vaddr,
+			    1, addrs)))
+    return release_buffer (&memory_closure, &buffer, &buffer_available, -1);
+
+  GElf_Addr next = addrs[0];
+
+  Dwfl_Module **lastmodp = &dwfl->modulelist;
+  int result = 0;
+
+  /* There can't be more elements in the link_map list than there are
+     segments.  A segment is created for each PT_LOAD and there can be
+     up to 5 per module (-z separate-code, tends to create four LOAD
+     segments, gold has -z text-unlikely-segment, which might result
+     in creating that number of load segments) DWFL->lookup_elts is
+     probably twice the number of modules, so that multiplied by max
+     PT_LOADs is certainly above the upper bound.  If we iterate too
+     many times, there must be a loop in the pointers due to link_map
+     clobberation.  */
+#define MAX_PT_LOAD 5
+  size_t iterations = 0;
+  while (next != 0 && ++iterations < dwfl->lookup_elts * MAX_PT_LOAD)
+    {
+      if (read_addrs (&memory_closure, elfclass, elfdata,
+		      &buffer, &buffer_available, next, &read_vaddr,
+		      4, addrs))
+	return release_buffer (&memory_closure, &buffer, &buffer_available, -1);
+
+      /* Unused: l_addr is the difference between the address in memory
+         and the ELF file when the core was created. We need to
+         recalculate the difference below because the ELF file we use
+         might be differently pre-linked.  */
+      // GElf_Addr l_addr = addrs[0];
+      GElf_Addr l_name = addrs[1];
+      GElf_Addr l_ld = addrs[2];
+      next = addrs[3];
+
+      /* If a clobbered or truncated memory image has no useful pointer,
+	 just skip this element.  */
+      if (l_ld == 0)
+	continue;
+
+      /* Fetch the string at the l_name address.  */
+      const char *name = NULL;
+      if (buffer != NULL
+	  && read_vaddr <= l_name
+	  && l_name + 1 - read_vaddr < buffer_available
+	  && memchr (l_name - read_vaddr + buffer, '\0',
+		     buffer_available - (l_name - read_vaddr)) != NULL)
+	name = l_name - read_vaddr + buffer;
+      else
+	{
+	  release_buffer (&memory_closure, &buffer, &buffer_available, 0);
+	  read_vaddr = l_name;
+	  int segndx = INTUSE(dwfl_addrsegment) (dwfl, l_name, NULL);
+	  if (likely (segndx >= 0)
+	      && (*memory_callback) (dwfl, segndx,
+				     &buffer, &buffer_available,
+				     l_name, 0, memory_callback_arg))
+	    name = buffer;
+	}
+
+      if (name != NULL && name[0] == '\0')
+	name = NULL;
+
+      if (iterations == 1
+	  && dwfl->user_core != NULL
+	  && dwfl->user_core->executable_for_core != NULL)
+	name = dwfl->user_core->executable_for_core;
+
+      struct r_debug_info_module *r_debug_info_module = NULL;
+      if (r_debug_info != NULL)
+	{
+	  /* Save link map information about valid shared library (or
+	     executable) which has not been found on disk.  */
+	  const char *name1 = name == NULL ? "" : name;
+	  r_debug_info_module = malloc (sizeof (*r_debug_info_module)
+					+ strlen (name1) + 1);
+	  if (unlikely (r_debug_info_module == NULL))
+	    release_buffer (&memory_closure, &buffer,
+                            &buffer_available, result);
+	  r_debug_info_module->fd = -1;
+	  r_debug_info_module->elf = NULL;
+	  r_debug_info_module->l_ld = l_ld;
+	  r_debug_info_module->start = 0;
+	  r_debug_info_module->end = 0;
+	  r_debug_info_module->disk_file_has_build_id = false;
+	  strcpy (r_debug_info_module->name, name1);
+	  r_debug_info_module->next = r_debug_info->module;
+	  r_debug_info->module = r_debug_info_module;
+	}
+
+      Dwfl_Module *mod = NULL;
+      if (name != NULL)
+	{
+	  /* This code is mostly inlined dwfl_report_elf.  */
+	  // XXX hook for sysroot
+	  int fd = open (name, O_RDONLY);
+	  if (fd >= 0)
+	    {
+	      Elf *elf;
+	      Dwfl_Error error = __libdw_open_file (&fd, &elf, true, false);
+	      GElf_Addr elf_dynamic_vaddr;
+	      if (error == DWFL_E_NOERROR
+		  && __libdwfl_dynamic_vaddr_get (elf, &elf_dynamic_vaddr))
+		{
+		  const void *build_id_bits;
+		  GElf_Addr build_id_elfaddr;
+		  int build_id_len;
+		  bool valid = true;
+
+		  if (__libdwfl_find_elf_build_id (NULL, elf, &build_id_bits,
+						   &build_id_elfaddr,
+						   &build_id_len) > 0
+		      && build_id_elfaddr != 0)
+		    {
+		      if (r_debug_info_module != NULL)
+			r_debug_info_module->disk_file_has_build_id = true;
+		      GElf_Addr build_id_vaddr = (build_id_elfaddr
+						  - elf_dynamic_vaddr + l_ld);
+
+		      release_buffer (&memory_closure, &buffer,
+				      &buffer_available, 0);
+		      int segndx = INTUSE(dwfl_addrsegment) (dwfl,
+							     build_id_vaddr,
+							     NULL);
+		      if (! (*memory_callback) (dwfl, segndx,
+						&buffer, &buffer_available,
+						build_id_vaddr, build_id_len,
+						memory_callback_arg))
+			{
+			  /* File has valid build-id which cannot be read from
+			     memory.  This happens for core files without bit 4
+			     (0x10) set in Linux /proc/PID/coredump_filter.  */
+			}
+		      else
+			{
+			  if (memcmp (build_id_bits, buffer, build_id_len) != 0)
+			    /* File has valid build-id which does not match
+			       the one in memory.  */
+			    valid = false;
+			  release_buffer (&memory_closure, &buffer,
+					  &buffer_available, 0);
+
+			}
+		    }
+
+		  if (valid)
+		    {
+		      // It is like l_addr but it handles differently prelinked
+		      // files at core dumping vs. core loading time.
+		      GElf_Addr base = l_ld - elf_dynamic_vaddr;
+		      if (r_debug_info_module == NULL)
+			{
+			  // XXX hook for sysroot
+			  mod = __libdwfl_report_elf (dwfl, xbasename (name),
+						      name, fd, elf, base,
+						      true, true);
+			  if (mod != NULL)
+			    {
+			      elf = NULL;
+			      fd = -1;
+			    }
+			}
+		      else if (__libdwfl_elf_address_range (elf, base, true,
+							    true, NULL, NULL,
+						    &r_debug_info_module->start,
+						    &r_debug_info_module->end,
+							    NULL, NULL))
+			{
+			  r_debug_info_module->elf = elf;
+			  r_debug_info_module->fd = fd;
+			  elf = NULL;
+			  fd = -1;
+			}
+		    }
+		  if (elf != NULL)
+		    elf_end (elf);
+		  if (fd != -1)
+		    close (fd);
+		}
+	    }
+	}
+
+      if (mod != NULL)
+	{
+	  ++result;
+
+	  /* Move this module to the end of the list, so that we end
+	     up with a list in the same order as the link_map chain.  */
+	  if (mod->next != NULL)
+	    {
+	      if (*lastmodp != mod)
+		{
+		  lastmodp = &dwfl->modulelist;
+		  while (*lastmodp != mod)
+		    lastmodp = &(*lastmodp)->next;
+		}
+	      *lastmodp = mod->next;
+	      mod->next = NULL;
+	      while (*lastmodp != NULL)
+		lastmodp = &(*lastmodp)->next;
+	      *lastmodp = mod;
+	    }
+
+	  lastmodp = &mod->next;
+	}
+    }
+
+  return release_buffer (&memory_closure, &buffer, &buffer_available, result);
+}
+
+static GElf_Addr
+consider_executable (Dwfl_Module *mod, GElf_Addr at_phdr, GElf_Addr at_entry,
+		     uint_fast8_t *elfclass, uint_fast8_t *elfdata,
+		     Dwfl_Memory_Callback *memory_callback,
+		     void *memory_callback_arg)
+{
+  GElf_Ehdr ehdr;
+  if (unlikely (gelf_getehdr (mod->main.elf, &ehdr) == NULL))
+    return 0;
+
+  if (at_entry != 0)
+    {
+      /* If we have an AT_ENTRY value, reject this executable if
+	 its entry point address could not have supplied that.  */
+
+      if (ehdr.e_entry == 0)
+	return 0;
+
+      if (mod->e_type == ET_EXEC)
+	{
+	  if (ehdr.e_entry != at_entry)
+	    return 0;
+	}
+      else
+	{
+	  /* It could be a PIE.  */
+	}
+    }
+
+  // XXX this could be saved in the file cache: phdr vaddr, DT_DEBUG d_val vaddr
+  /* Find the vaddr of the DT_DEBUG's d_ptr.  This is the memory
+     address where &r_debug was written at runtime.  */
+  GElf_Xword align = mod->dwfl->segment_align;
+  GElf_Addr d_val_vaddr = 0;
+  size_t phnum;
+  if (elf_getphdrnum (mod->main.elf, &phnum) != 0)
+    return 0;
+
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (mod->main.elf, i, &phdr_mem);
+      if (phdr == NULL)
+	break;
+
+      if (phdr->p_align > 1 && (align == 0 || phdr->p_align < align))
+	align = phdr->p_align;
+
+      if (at_phdr != 0
+	  && phdr->p_type == PT_LOAD
+	  && (phdr->p_offset & -align) == (ehdr.e_phoff & -align))
+	{
+	  /* This is the segment that would map the phdrs.
+	     If we have an AT_PHDR value, reject this executable
+	     if its phdr mapping could not have supplied that.  */
+	  if (mod->e_type == ET_EXEC)
+	    {
+	      if (ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr != at_phdr)
+		return 0;
+	    }
+	  else
+	    {
+	      /* It could be a PIE.  If the AT_PHDR value and our
+		 phdr address don't match modulo ALIGN, then this
+		 could not have been the right PIE.  */
+	      if (((ehdr.e_phoff - phdr->p_offset + phdr->p_vaddr) & -align)
+		  != (at_phdr & -align))
+		return 0;
+
+	      /* Calculate the bias applied to the PIE's p_vaddr values.  */
+	      GElf_Addr bias = (at_phdr - (ehdr.e_phoff - phdr->p_offset
+					   + phdr->p_vaddr));
+
+	      /* Final sanity check: if we have an AT_ENTRY value,
+		 reject this PIE unless its biased e_entry matches.  */
+	      if (at_entry != 0 && at_entry != ehdr.e_entry + bias)
+		return 0;
+
+	      /* If we're changing the module's address range,
+		 we've just invalidated the module lookup table.  */
+	      GElf_Addr mod_bias = dwfl_adjusted_address (mod, 0);
+	      if (bias != mod_bias)
+		{
+		  mod->low_addr -= mod_bias;
+		  mod->high_addr -= mod_bias;
+		  mod->low_addr += bias;
+		  mod->high_addr += bias;
+
+		  free (mod->dwfl->lookup_module);
+		  mod->dwfl->lookup_module = NULL;
+		}
+	    }
+	}
+
+      if (phdr->p_type == PT_DYNAMIC)
+	{
+	  Elf_Data *data = elf_getdata_rawchunk (mod->main.elf, phdr->p_offset,
+						 phdr->p_filesz, ELF_T_DYN);
+	  if (data == NULL)
+	    continue;
+	  const size_t entsize = gelf_fsize (mod->main.elf,
+					     ELF_T_DYN, 1, EV_CURRENT);
+	  const size_t n = data->d_size / entsize;
+	  for (size_t j = 0; j < n; ++j)
+	    {
+	      GElf_Dyn dyn_mem;
+	      GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
+	      if (dyn != NULL && dyn->d_tag == DT_DEBUG)
+		{
+		  d_val_vaddr = phdr->p_vaddr + entsize * j + entsize / 2;
+		  break;
+		}
+	    }
+	}
+    }
+
+  if (d_val_vaddr != 0)
+    {
+      /* Now we have the final address from which to read &r_debug.  */
+      d_val_vaddr = dwfl_adjusted_address (mod, d_val_vaddr);
+
+      void *buffer = NULL;
+      size_t buffer_available = addrsize (ehdr.e_ident[EI_CLASS]);
+
+      int segndx = INTUSE(dwfl_addrsegment) (mod->dwfl, d_val_vaddr, NULL);
+
+      if ((*memory_callback) (mod->dwfl, segndx,
+			      &buffer, &buffer_available,
+			      d_val_vaddr, buffer_available,
+			      memory_callback_arg))
+	{
+	  const union
+	  {
+	    Elf32_Addr a32;
+	    Elf64_Addr a64;
+	  } *u = buffer;
+
+	  GElf_Addr vaddr;
+	  if (ehdr.e_ident[EI_CLASS] == ELFCLASS32)
+	    vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
+		     ? BE32 (u->a32) : LE32 (u->a32));
+	  else
+	    vaddr = (ehdr.e_ident[EI_DATA] == ELFDATA2MSB
+		     ? BE64 (u->a64) : LE64 (u->a64));
+
+	  (*memory_callback) (mod->dwfl, -1, &buffer, &buffer_available, 0, 0,
+			      memory_callback_arg);
+
+	  if (*elfclass == ELFCLASSNONE)
+	    *elfclass = ehdr.e_ident[EI_CLASS];
+	  else if (*elfclass != ehdr.e_ident[EI_CLASS])
+	    return 0;
+
+	  if (*elfdata == ELFDATANONE)
+	    *elfdata = ehdr.e_ident[EI_DATA];
+	  else if (*elfdata != ehdr.e_ident[EI_DATA])
+	    return 0;
+
+	  return vaddr;
+	}
+    }
+
+  return 0;
+}
+
+/* Try to find an existing executable module with a DT_DEBUG.  */
+static GElf_Addr
+find_executable (Dwfl *dwfl, GElf_Addr at_phdr, GElf_Addr at_entry,
+		 uint_fast8_t *elfclass, uint_fast8_t *elfdata,
+		 Dwfl_Memory_Callback *memory_callback,
+		 void *memory_callback_arg)
+{
+  for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
+    if (mod->main.elf != NULL)
+      {
+	GElf_Addr r_debug_vaddr = consider_executable (mod, at_phdr, at_entry,
+						       elfclass, elfdata,
+						       memory_callback,
+						       memory_callback_arg);
+	if (r_debug_vaddr != 0)
+	  return r_debug_vaddr;
+      }
+
+  return 0;
+}
+
+
+int
+dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size,
+		      Dwfl_Memory_Callback *memory_callback,
+		      void *memory_callback_arg,
+		      struct r_debug_info *r_debug_info)
+{
+  GElf_Addr r_debug_vaddr = 0;
+
+  uint_fast8_t elfclass = ELFCLASSNONE;
+  uint_fast8_t elfdata = ELFDATANONE;
+  if (likely (auxv != NULL)
+      && likely (auxv_format_probe (auxv, auxv_size, &elfclass, &elfdata)))
+    {
+      GElf_Addr entry = 0;
+      GElf_Addr phdr = 0;
+      GElf_Xword phent = 0;
+      GElf_Xword phnum = 0;
+
+#define READ_AUXV32(ptr)	read_4ubyte_unaligned_noncvt (ptr)
+#define READ_AUXV64(ptr)	read_8ubyte_unaligned_noncvt (ptr)
+#define AUXV_SCAN(NN, BL) do                                            \
+	{                                                               \
+	  const Elf##NN##_auxv_t *av = auxv;                            \
+	  for (size_t i = 0; i < auxv_size / sizeof av[0]; ++i)         \
+	    {                                                           \
+	      const char *typep = auxv + i * sizeof (Elf##NN##_auxv_t); \
+	      typep += offsetof (Elf##NN##_auxv_t, a_type);             \
+	      uint##NN##_t type = READ_AUXV##NN (typep);                \
+	      const char *valp = auxv + i * sizeof (Elf##NN##_auxv_t);  \
+	      valp += offsetof (Elf##NN##_auxv_t, a_un.a_val);          \
+	      uint##NN##_t val = BL##NN (READ_AUXV##NN (valp));         \
+	      if (type == BL##NN (AT_ENTRY))                            \
+		entry = val;                                            \
+	      else if (type == BL##NN (AT_PHDR))                        \
+		phdr = val;                                             \
+	      else if (type == BL##NN (AT_PHNUM))                       \
+		phnum = val;                                            \
+	      else if (type == BL##NN (AT_PHENT))                       \
+		phent = val;                                            \
+	      else if (type == BL##NN (AT_PAGESZ))                      \
+		{                                                       \
+		  if (val > 1                                           \
+		      && (dwfl->segment_align == 0                      \
+			  || val < dwfl->segment_align))                \
+		    dwfl->segment_align = val;                          \
+		}                                                       \
+	    }                                                           \
+	}                                                               \
+      while (0)
+
+      if (elfclass == ELFCLASS32)
+	{
+	  if (elfdata == ELFDATA2MSB)
+	    AUXV_SCAN (32, BE);
+	  else
+	    AUXV_SCAN (32, LE);
+	}
+      else
+	{
+	  if (elfdata == ELFDATA2MSB)
+	    AUXV_SCAN (64, BE);
+	  else
+	    AUXV_SCAN (64, LE);
+	}
+
+      /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC.  */
+      GElf_Addr dyn_vaddr = 0;
+      GElf_Xword dyn_filesz = 0;
+      GElf_Addr dyn_bias = (GElf_Addr) -1;
+
+      if (phdr != 0 && phnum != 0
+	  && ((elfclass == ELFCLASS32 && phent == sizeof (Elf32_Phdr))
+	      || (elfclass == ELFCLASS64 && phent == sizeof (Elf64_Phdr))))
+	{
+	  Dwfl_Module *phdr_mod;
+	  int phdr_segndx = INTUSE(dwfl_addrsegment) (dwfl, phdr, &phdr_mod);
+	  Elf_Data in =
+	    {
+	      .d_type = ELF_T_PHDR,
+	      .d_version = EV_CURRENT,
+	      .d_size = phnum * phent,
+	      .d_buf = NULL
+	    };
+	  bool in_ok = (*memory_callback) (dwfl, phdr_segndx, &in.d_buf,
+					   &in.d_size, phdr, phnum * phent,
+					   memory_callback_arg);
+	  bool in_from_exec = false;
+	  if (! in_ok
+	      && dwfl->user_core != NULL
+	      && dwfl->user_core->executable_for_core != NULL)
+	    {
+	      /* AUXV -> PHDR -> DYNAMIC
+		 Both AUXV and DYNAMIC should be always present in a core file.
+		 PHDR may be missing in core file, try to read it from
+		 EXECUTABLE_FOR_CORE to find where DYNAMIC is located in the
+		 core file.  */
+
+	      int fd = open (dwfl->user_core->executable_for_core, O_RDONLY);
+	      Elf *elf;
+	      Dwfl_Error error = DWFL_E_ERRNO;
+	      if (fd != -1)
+		error = __libdw_open_file (&fd, &elf, true, false);
+	      if (error != DWFL_E_NOERROR)
+		{
+		  __libdwfl_seterrno (error);
+		  return false;
+		}
+	      GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+	      if (ehdr == NULL)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_LIBELF);
+		  return false;
+		}
+	      size_t e_phnum;
+	      if (elf_getphdrnum (elf, &e_phnum) != 0)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_LIBELF);
+		  return false;
+		}
+	      if (e_phnum != phnum || ehdr->e_phentsize != phent)
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_BADELF);
+		  return false;
+		}
+	      off_t off = ehdr->e_phoff;
+	      assert (in.d_buf == NULL);
+	      /* Note this in the !in_ok path.  That means memory_callback
+		 failed.  But the callback might still have reset the d_size
+		 value (to zero).  So explicitly set it here again.  */
+	      if (unlikely (phnum > SIZE_MAX / phent))
+		{
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      in.d_size = phnum * phent;
+	      in.d_buf = malloc (in.d_size);
+	      if (unlikely (in.d_buf == NULL))
+		{
+		  elf_end (elf);
+		  close (fd);
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      ssize_t nread = pread_retry (fd, in.d_buf, in.d_size, off);
+	      elf_end (elf);
+	      close (fd);
+	      if (nread != (ssize_t) in.d_size)
+		{
+		  free (in.d_buf);
+		  __libdwfl_seterrno (DWFL_E_ERRNO);
+		  return false;
+		}
+	      in_ok = true;
+	      in_from_exec = true;
+	    }
+	  if (in_ok)
+	    {
+	      if (unlikely (phnum > SIZE_MAX / phent))
+		{
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      size_t nbytes = phnum * phent;
+	      /* We can only process as many bytes/phnum as there are
+		 in in.d_size. The data might have been truncated.  */
+	      if (nbytes > in.d_size)
+		{
+		  nbytes = in.d_size;
+		  phnum = nbytes / phent;
+		  if (phnum == 0)
+		    {
+		      __libdwfl_seterrno (DWFL_E_BADELF);
+		      return false;
+		    }
+		}
+	      void *buf = malloc (nbytes);
+	      Elf32_Phdr (*p32)[phnum] = buf;
+	      Elf64_Phdr (*p64)[phnum] = buf;
+	      if (unlikely (buf == NULL))
+		{
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      Elf_Data out =
+		{
+		  .d_type = ELF_T_PHDR,
+		  .d_version = EV_CURRENT,
+		  .d_size = nbytes,
+		  .d_buf = buf
+		};
+	      if (in.d_size > out.d_size)
+		{
+		  in.d_size = out.d_size;
+		  phnum = in.d_size / phent;
+		  if (phnum == 0)
+		    {
+		      free (buf);
+		      __libdwfl_seterrno (DWFL_E_BADELF);
+		      return false;
+		    }
+		}
+	      bool is32 = (elfclass == ELFCLASS32);
+	      size_t phdr_align = (is32
+				   ? __alignof__ (Elf32_Phdr)
+				   : __alignof__ (Elf64_Phdr));
+	      if (!in_from_exec
+		  && ((uintptr_t) in.d_buf & (phdr_align - 1)) != 0)
+		{
+		  memcpy (out.d_buf, in.d_buf, in.d_size);
+		  in.d_buf = out.d_buf;
+		}
+	      if (likely ((elfclass == ELFCLASS32
+			   ? elf32_xlatetom : elf64_xlatetom)
+			  (&out, &in, elfdata) != NULL))
+		{
+		  for (size_t i = 0; i < phnum; ++i)
+		    {
+		      GElf_Word type = (is32
+					? (*p32)[i].p_type
+					: (*p64)[i].p_type);
+		      GElf_Addr vaddr = (is32
+					 ? (*p32)[i].p_vaddr
+					 : (*p64)[i].p_vaddr);
+		      GElf_Xword filesz = (is32
+					   ? (*p32)[i].p_filesz
+					   : (*p64)[i].p_filesz);
+
+		      if (type == PT_PHDR)
+			{
+			  if (dyn_bias == (GElf_Addr) -1
+			      /* Do a sanity check on the putative address.  */
+			      && ((vaddr & (dwfl->segment_align - 1))
+				  == (phdr & (dwfl->segment_align - 1))))
+			    {
+			      dyn_bias = phdr - vaddr;
+			      if (dyn_vaddr != 0)
+				break;
+			    }
+
+			}
+		      else if (type == PT_DYNAMIC)
+			{
+			  dyn_vaddr = vaddr;
+			  dyn_filesz = filesz;
+			  if (dyn_bias != (GElf_Addr) -1)
+			    break;
+			}
+		    }
+		}
+
+	      if (in_from_exec)
+		free (in.d_buf);
+	      else
+		(*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
+				    memory_callback_arg);
+	      free (buf);
+	    }
+	  else
+	    /* We could not read the executable's phdrs from the
+	       memory image.  If we have a presupplied executable,
+	       we can still use the AT_PHDR and AT_ENTRY values to
+	       verify it, and to adjust its bias if it's a PIE.
+
+	       If there was an ET_EXEC module presupplied that contains
+	       the AT_PHDR address, then we only consider that one.
+	       We'll either accept it if its phdr location and e_entry
+	       make sense or reject it if they don't.  If there is no
+	       presupplied ET_EXEC, then look for a presupplied module,
+	       which might be a PIE (ET_DYN) that needs its bias adjusted.  */
+	    r_debug_vaddr = ((phdr_mod == NULL
+			      || phdr_mod->main.elf == NULL
+			      || phdr_mod->e_type != ET_EXEC)
+			     ? find_executable (dwfl, phdr, entry,
+						&elfclass, &elfdata,
+						memory_callback,
+						memory_callback_arg)
+			     : consider_executable (phdr_mod, phdr, entry,
+						    &elfclass, &elfdata,
+						    memory_callback,
+						    memory_callback_arg));
+	}
+
+      /* If we found PT_DYNAMIC, search it for DT_DEBUG.  */
+      if (dyn_filesz != 0)
+	{
+	  if (dyn_bias != (GElf_Addr) -1)
+	    dyn_vaddr += dyn_bias;
+
+	  Elf_Data in =
+	    {
+	      .d_type = ELF_T_DYN,
+	      .d_version = EV_CURRENT,
+	      .d_size = dyn_filesz,
+	      .d_buf = NULL
+	    };
+	  int dyn_segndx = dwfl_addrsegment (dwfl, dyn_vaddr, NULL);
+	  if ((*memory_callback) (dwfl, dyn_segndx, &in.d_buf, &in.d_size,
+				  dyn_vaddr, dyn_filesz, memory_callback_arg))
+	    {
+	      size_t entsize = (elfclass == ELFCLASS32
+				? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn));
+	      if (unlikely (dyn_filesz > SIZE_MAX / entsize))
+		{
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      /* We can only process as many bytes as there are in
+	         in.d_size. The data might have been truncated.  */
+	      if (dyn_filesz > in.d_size)
+		dyn_filesz = in.d_size;
+	      if (dyn_filesz / entsize == 0)
+		{
+		  __libdwfl_seterrno (DWFL_E_BADELF);
+		  return false;
+		}
+	      void *buf = malloc (dyn_filesz);
+	      if (unlikely (buf == NULL))
+		{
+		  __libdwfl_seterrno (DWFL_E_NOMEM);
+		  return false;
+		}
+	      Elf_Data out =
+		{
+		  .d_type = ELF_T_DYN,
+		  .d_version = EV_CURRENT,
+		  .d_size = dyn_filesz,
+		  .d_buf = buf
+		};
+	      if (in.d_size > out.d_size)
+		in.d_size = out.d_size;
+	      size_t dyn_align = (elfclass == ELFCLASS32
+			          ? __alignof__ (Elf32_Dyn)
+				  : __alignof__ (Elf64_Dyn));
+	      if (((uintptr_t) in.d_buf & (dyn_align - 1)) != 0)
+		{
+		  memcpy (out.d_buf, in.d_buf, in.d_size);
+		  in.d_buf = out.d_buf;
+		}
+	      if (likely ((elfclass == ELFCLASS32
+			   ? elf32_xlatetom : elf64_xlatetom)
+			  (&out, &in, elfdata) != NULL))
+		{
+		  /* We are looking for DT_DEBUG.  */
+		  if (elfclass == ELFCLASS32)
+		    {
+		      Elf32_Dyn (*d32)[dyn_filesz / sizeof (Elf32_Dyn)] = buf;
+		      size_t n = dyn_filesz / sizeof (Elf32_Dyn);
+		      for (size_t i = 0; i < n; ++i)
+			if ((*d32)[i].d_tag == DT_DEBUG)
+			  {
+			    r_debug_vaddr = (*d32)[i].d_un.d_val;
+			    break;
+			  }
+		    }
+		  else
+		    {
+		      Elf64_Dyn (*d64)[dyn_filesz / sizeof (Elf64_Dyn)] = buf;
+		      size_t n = dyn_filesz / sizeof (Elf64_Dyn);
+		      for (size_t i = 0; i < n; ++i)
+			if ((*d64)[i].d_tag == DT_DEBUG)
+			  {
+			    r_debug_vaddr = (*d64)[i].d_un.d_val;
+			    break;
+			  }
+		    }
+		}
+
+	      (*memory_callback) (dwfl, -1, &in.d_buf, &in.d_size, 0, 0,
+				  memory_callback_arg);
+	      free (buf);
+	    }
+	}
+    }
+  else
+    /* We have to look for a presupplied executable file to determine
+       the vaddr of its dynamic section and DT_DEBUG therein.  */
+    r_debug_vaddr = find_executable (dwfl, 0, 0, &elfclass, &elfdata,
+				     memory_callback, memory_callback_arg);
+
+  if (r_debug_vaddr == 0)
+    return 0;
+
+  /* For following pointers from struct link_map, we will use an
+     integrated memory access callback that can consult module text
+     elided from the core file.  This is necessary when the l_name
+     pointer for the dynamic linker's own entry is a pointer into the
+     executable's .interp section.  */
+  struct integrated_memory_callback mcb =
+    {
+      .memory_callback = memory_callback,
+      .memory_callback_arg = memory_callback_arg
+    };
+
+  /* Now we can follow the dynamic linker's library list.  */
+  return report_r_debug (elfclass, elfdata, dwfl, r_debug_vaddr,
+			 &integrated_memory_callback, &mcb, r_debug_info);
+}
+INTDEF (dwfl_link_map_report)
diff --git a/libdwfl/linux-core-attach.c b/libdwfl/linux-core-attach.c
new file mode 100644
index 0000000..d6f9e97
--- /dev/null
+++ b/libdwfl/linux-core-attach.c
@@ -0,0 +1,434 @@
+/* Get Dwarf Frame state for target core file.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <fcntl.h>
+#include "system.h"
+
+#include "memory-access.h"
+
+struct core_arg
+{
+  Elf *core;
+  Elf_Data *note_data;
+  size_t thread_note_offset;
+  Ebl *ebl;
+};
+
+struct thread_arg
+{
+  struct core_arg *core_arg;
+  size_t note_offset;
+};
+
+static bool
+core_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
+		  void *dwfl_arg)
+{
+  Dwfl_Process *process = dwfl->process;
+  struct core_arg *core_arg = dwfl_arg;
+  Elf *core = core_arg->core;
+  assert (core != NULL);
+  static size_t phnum;
+  if (elf_getphdrnum (core, &phnum) < 0)
+    {
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+      return false;
+    }
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    {
+      GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
+      if (phdr == NULL || phdr->p_type != PT_LOAD)
+	continue;
+      /* Bias is zero here, a core file itself has no bias.  */
+      GElf_Addr start = __libdwfl_segment_start (dwfl, phdr->p_vaddr);
+      GElf_Addr end = __libdwfl_segment_end (dwfl,
+					     phdr->p_vaddr + phdr->p_memsz);
+      unsigned bytes = ebl_get_elfclass (process->ebl) == ELFCLASS64 ? 8 : 4;
+      if (addr < start || addr + bytes > end)
+	continue;
+      Elf_Data *data;
+      data = elf_getdata_rawchunk (core, phdr->p_offset + addr - start,
+				   bytes, ELF_T_ADDR);
+      if (data == NULL)
+	{
+	  __libdwfl_seterrno (DWFL_E_LIBELF);
+	  return false;
+	}
+      assert (data->d_size == bytes);
+      if (bytes == 8)
+	*result = read_8ubyte_unaligned_noncvt (data->d_buf);
+      else
+	*result = read_4ubyte_unaligned_noncvt (data->d_buf);
+      return true;
+    }
+  __libdwfl_seterrno (DWFL_E_ADDR_OUTOFRANGE);
+  return false;
+}
+
+static pid_t
+core_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
+		  void **thread_argp)
+{
+  struct core_arg *core_arg = dwfl_arg;
+  Elf *core = core_arg->core;
+  GElf_Nhdr nhdr;
+  size_t name_offset;
+  size_t desc_offset;
+  Elf_Data *note_data = core_arg->note_data;
+  size_t offset;
+
+  struct thread_arg *thread_arg;
+  if (*thread_argp == NULL)
+    {
+      core_arg->thread_note_offset = 0;
+      thread_arg = malloc (sizeof (*thread_arg));
+      if (thread_arg == NULL)
+	{
+	  __libdwfl_seterrno (DWFL_E_NOMEM);
+	  return -1;
+	}
+      thread_arg->core_arg = core_arg;
+      *thread_argp = thread_arg;
+    }
+  else
+    thread_arg = (struct thread_arg *) *thread_argp;
+
+  while (offset = core_arg->thread_note_offset, offset < note_data->d_size
+	 && (core_arg->thread_note_offset = gelf_getnote (note_data, offset,
+							  &nhdr, &name_offset,
+							  &desc_offset)) > 0)
+    {
+      /* Do not check NAME for now, help broken Linux kernels.  */
+      const char *name = (nhdr.n_namesz == 0
+			  ? "" : note_data->d_buf + name_offset);
+      const char *desc = note_data->d_buf + desc_offset;
+      GElf_Word regs_offset;
+      size_t nregloc;
+      const Ebl_Register_Location *reglocs;
+      size_t nitems;
+      const Ebl_Core_Item *items;
+      if (! ebl_core_note (core_arg->ebl, &nhdr, name, desc,
+			   &regs_offset, &nregloc, &reglocs, &nitems, &items))
+	{
+	  /* This note may be just not recognized, skip it.  */
+	  continue;
+	}
+      if (nhdr.n_type != NT_PRSTATUS)
+	continue;
+      const Ebl_Core_Item *item;
+      for (item = items; item < items + nitems; item++)
+	if (strcmp (item->name, "pid") == 0)
+	  break;
+      if (item == items + nitems)
+	continue;
+      uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
+      val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+		? be32toh (val32) : le32toh (val32));
+      pid_t tid = (int32_t) val32;
+      eu_static_assert (sizeof val32 <= sizeof tid);
+      thread_arg->note_offset = offset;
+      return tid;
+    }
+
+  free (thread_arg);
+  return 0;
+}
+
+static bool
+core_set_initial_registers (Dwfl_Thread *thread, void *thread_arg_voidp)
+{
+  struct thread_arg *thread_arg = thread_arg_voidp;
+  struct core_arg *core_arg = thread_arg->core_arg;
+  Elf *core = core_arg->core;
+  size_t offset = thread_arg->note_offset;
+  GElf_Nhdr nhdr;
+  size_t name_offset;
+  size_t desc_offset;
+  Elf_Data *note_data = core_arg->note_data;
+  size_t nregs = ebl_frame_nregs (core_arg->ebl);
+  assert (nregs > 0);
+  assert (offset < note_data->d_size);
+  size_t getnote_err = gelf_getnote (note_data, offset, &nhdr, &name_offset,
+				     &desc_offset);
+  /* __libdwfl_attach_state_for_core already verified the note is there.  */
+  if (getnote_err == 0)
+    return false;
+  /* Do not check NAME for now, help broken Linux kernels.  */
+  const char *name = (nhdr.n_namesz == 0
+		      ? "" : note_data->d_buf + name_offset);
+  const char *desc = note_data->d_buf + desc_offset;
+  GElf_Word regs_offset;
+  size_t nregloc;
+  const Ebl_Register_Location *reglocs;
+  size_t nitems;
+  const Ebl_Core_Item *items;
+  int core_note_err = ebl_core_note (core_arg->ebl, &nhdr, name, desc,
+				     &regs_offset, &nregloc, &reglocs,
+				     &nitems, &items);
+  /* __libdwfl_attach_state_for_core already verified the note is there.  */
+  if (core_note_err == 0 || nhdr.n_type != NT_PRSTATUS)
+    return false;
+  const Ebl_Core_Item *item;
+  for (item = items; item < items + nitems; item++)
+    if (strcmp (item->name, "pid") == 0)
+      break;
+  assert (item < items + nitems);
+  pid_t tid;
+  {
+    uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
+    val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+	     ? be32toh (val32) : le32toh (val32));
+    tid = (int32_t) val32;
+    eu_static_assert (sizeof val32 <= sizeof tid);
+  }
+  /* core_next_thread already found this TID there.  */
+  assert (tid == INTUSE(dwfl_thread_tid) (thread));
+  for (item = items; item < items + nitems; item++)
+    if (item->pc_register)
+      break;
+  if (item < items + nitems)
+    {
+      Dwarf_Word pc;
+      switch (gelf_getclass (core) == ELFCLASS32 ? 32 : 64)
+      {
+	case 32:;
+	  uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
+	  val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+		   ? be32toh (val32) : le32toh (val32));
+	  /* Do a host width conversion.  */
+	  pc = val32;
+	  break;
+	case 64:;
+	  uint64_t val64 = read_8ubyte_unaligned_noncvt (desc + item->offset);
+	  val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+		   ? be64toh (val64) : le64toh (val64));
+	  pc = val64;
+	  break;
+	default:
+	  abort ();
+      }
+      INTUSE(dwfl_thread_state_register_pc) (thread, pc);
+    }
+  desc += regs_offset;
+  for (size_t regloci = 0; regloci < nregloc; regloci++)
+    {
+      const Ebl_Register_Location *regloc = reglocs + regloci;
+      // Iterate even regs out of NREGS range so that we can find pc_register.
+      if (regloc->bits != 32 && regloc->bits != 64)
+	continue;
+      const char *reg_desc = desc + regloc->offset;
+      for (unsigned regno = regloc->regno;
+	   regno < regloc->regno + (regloc->count ?: 1U);
+	   regno++)
+	{
+	  /* PPC provides DWARF register 65 irrelevant for
+	     CFI which clashes with register 108 (LR) we need.
+	     LR (108) is provided earlier (in NT_PRSTATUS) than the # 65.
+	     FIXME: It depends now on their order in core notes.
+	     FIXME: It uses private function.  */
+	  if (regno < nregs
+	      && __libdwfl_frame_reg_get (thread->unwound, regno, NULL) == 0)
+	    continue;
+	  Dwarf_Word val;
+	  switch (regloc->bits)
+	  {
+	    case 32:;
+	      uint32_t val32 = read_4ubyte_unaligned_noncvt (reg_desc);
+	      reg_desc += sizeof val32;
+	      val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+		       ? be32toh (val32) : le32toh (val32));
+	      /* Do a host width conversion.  */
+	      val = val32;
+	      break;
+	    case 64:;
+	      uint64_t val64 = read_8ubyte_unaligned_noncvt (reg_desc);
+	      reg_desc += sizeof val64;
+	      val64 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+		       ? be64toh (val64) : le64toh (val64));
+	      assert (sizeof (*thread->unwound->regs) == sizeof val64);
+	      val = val64;
+	      break;
+	    default:
+	      abort ();
+	  }
+	  /* Registers not valid for CFI are just ignored.  */
+	  if (regno < nregs)
+	    INTUSE(dwfl_thread_state_registers) (thread, regno, 1, &val);
+	  if (regloc->pc_register)
+	    INTUSE(dwfl_thread_state_register_pc) (thread, val);
+	  reg_desc += regloc->pad;
+	}
+    }
+  return true;
+}
+
+static void
+core_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
+{
+  struct core_arg *core_arg = dwfl_arg;
+  ebl_closebackend (core_arg->ebl);
+  free (core_arg);
+}
+
+static const Dwfl_Thread_Callbacks core_thread_callbacks =
+{
+  core_next_thread,
+  NULL, /* get_thread */
+  core_memory_read,
+  core_set_initial_registers,
+  core_detach,
+  NULL, /* core_thread_detach */
+};
+
+int
+dwfl_core_file_attach (Dwfl *dwfl, Elf *core)
+{
+  Dwfl_Error err = DWFL_E_NOERROR;
+  Ebl *ebl = ebl_openbackend (core);
+  if (ebl == NULL)
+    {
+      err = DWFL_E_LIBEBL;
+    fail_err:
+      if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
+	dwfl->attacherr = __libdwfl_canon_error (err);
+      __libdwfl_seterrno (err);
+      return -1;
+    }
+  size_t nregs = ebl_frame_nregs (ebl);
+  if (nregs == 0)
+    {
+      err = DWFL_E_NO_UNWIND;
+    fail:
+      ebl_closebackend (ebl);
+      goto fail_err;
+    }
+  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (core, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      err = DWFL_E_LIBELF;
+      goto fail;
+    }
+  if (ehdr->e_type != ET_CORE)
+    {
+      err = DWFL_E_NO_CORE_FILE;
+      goto fail;
+    }
+  size_t phnum;
+  if (elf_getphdrnum (core, &phnum) < 0)
+    {
+      err = DWFL_E_LIBELF;
+      goto fail;
+    }
+  pid_t pid = -1;
+  Elf_Data *note_data = NULL;
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    {
+      GElf_Phdr phdr_mem, *phdr = gelf_getphdr (core, cnt, &phdr_mem);
+      if (phdr != NULL && phdr->p_type == PT_NOTE)
+	{
+	  note_data = elf_getdata_rawchunk (core, phdr->p_offset,
+					    phdr->p_filesz, (phdr->p_align == 8
+							     ? ELF_T_NHDR8
+							     : ELF_T_NHDR));
+	  break;
+	}
+    }
+  if (note_data == NULL)
+    {
+      err = DWFL_E_LIBELF;
+      goto fail;
+    }
+  size_t offset = 0;
+  GElf_Nhdr nhdr;
+  size_t name_offset;
+  size_t desc_offset;
+  while (offset < note_data->d_size
+	 && (offset = gelf_getnote (note_data, offset,
+				    &nhdr, &name_offset, &desc_offset)) > 0)
+    {
+      /* Do not check NAME for now, help broken Linux kernels.  */
+      const char *name = (nhdr.n_namesz == 0
+			  ? "" : note_data->d_buf + name_offset);
+      const char *desc = note_data->d_buf + desc_offset;
+      GElf_Word regs_offset;
+      size_t nregloc;
+      const Ebl_Register_Location *reglocs;
+      size_t nitems;
+      const Ebl_Core_Item *items;
+      if (! ebl_core_note (ebl, &nhdr, name, desc,
+			   &regs_offset, &nregloc, &reglocs, &nitems, &items))
+	{
+	  /* This note may be just not recognized, skip it.  */
+	  continue;
+	}
+      if (nhdr.n_type != NT_PRPSINFO)
+	continue;
+      const Ebl_Core_Item *item;
+      for (item = items; item < items + nitems; item++)
+	if (strcmp (item->name, "pid") == 0)
+	  break;
+      if (item == items + nitems)
+	continue;
+      uint32_t val32 = read_4ubyte_unaligned_noncvt (desc + item->offset);
+      val32 = (elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB
+		? be32toh (val32) : le32toh (val32));
+      pid = (int32_t) val32;
+      eu_static_assert (sizeof val32 <= sizeof pid);
+      break;
+    }
+  if (pid == -1)
+    {
+      /* No valid NT_PRPSINFO recognized in this CORE.  */
+      err = DWFL_E_BADELF;
+      goto fail;
+    }
+  struct core_arg *core_arg = malloc (sizeof *core_arg);
+  if (core_arg == NULL)
+    {
+      err = DWFL_E_NOMEM;
+      goto fail;
+    }
+  core_arg->core = core;
+  core_arg->note_data = note_data;
+  core_arg->thread_note_offset = 0;
+  core_arg->ebl = ebl;
+  if (! INTUSE(dwfl_attach_state) (dwfl, core, pid, &core_thread_callbacks,
+				   core_arg))
+    {
+      free (core_arg);
+      ebl_closebackend (ebl);
+      return -1;
+    }
+  return pid;
+}
+INTDEF (dwfl_core_file_attach)
diff --git a/libdwfl/linux-kernel-modules.c b/libdwfl/linux-kernel-modules.c
new file mode 100644
index 0000000..e9faba2
--- /dev/null
+++ b/libdwfl/linux-kernel-modules.c
@@ -0,0 +1,1040 @@
+/* Standard libdwfl callbacks for debugging the running Linux kernel.
+   Copyright (C) 2005-2011, 2013, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* In case we have a bad fts we include this before config.h because it
+   can't handle _FILE_OFFSET_BITS.
+   Everything we need here is fine if its declarations just come first.
+   Also, include sys/types.h before fts. On some systems fts.h is not self
+   contained. */
+#ifdef BAD_FTS
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+#include <config.h>
+#include <system.h>
+
+#include "libelfP.h"
+#include "libdwflP.h"
+#include <inttypes.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/utsname.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* If fts.h is included before config.h, its indirect inclusions may not
+   give us the right LFS aliases of these functions, so map them manually.  */
+#ifdef BAD_FTS
+  #ifdef _FILE_OFFSET_BITS
+    #define open open64
+    #define fopen fopen64
+  #endif
+#else
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+
+#define KERNEL_MODNAME	"kernel"
+
+#define MODULEDIRFMT	"/lib/modules/%s"
+
+#define KNOTESFILE	"/sys/kernel/notes"
+#define	MODNOTESFMT	"/sys/module/%s/notes"
+#define KSYMSFILE	"/proc/kallsyms"
+#define MODULELIST	"/proc/modules"
+#define	SECADDRDIRFMT	"/sys/module/%s/sections/"
+#define MODULE_SECT_NAME_LEN 32	/* Minimum any linux/module.h has had.  */
+
+
+static const char *vmlinux_suffixes[] =
+  {
+    ".gz",
+#ifdef USE_BZLIB
+    ".bz2",
+#endif
+#ifdef USE_LZMA
+    ".xz",
+#endif
+  };
+
+/* Try to open the given file as it is or under the debuginfo directory.  */
+static int
+try_kernel_name (Dwfl *dwfl, char **fname, bool try_debug)
+{
+  if (*fname == NULL)
+    return -1;
+
+  /* Don't bother trying *FNAME itself here if the path will cause it to be
+     tried because we give its own basename as DEBUGLINK_FILE.  */
+  int fd = ((((dwfl->callbacks->debuginfo_path
+	       ? *dwfl->callbacks->debuginfo_path : NULL)
+	      ?: DEFAULT_DEBUGINFO_PATH)[0] == ':') ? -1
+	    : TEMP_FAILURE_RETRY (open (*fname, O_RDONLY)));
+
+  if (fd < 0)
+    {
+      Dwfl_Module fakemod = { .dwfl = dwfl };
+
+      if (try_debug)
+	/* Passing NULL for DEBUGLINK_FILE searches for both the basenamer
+	   "vmlinux" and the default of basename + ".debug", to look for
+	   "vmlinux.debug" files.  */
+	fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
+						   *fname, NULL, 0,
+						   &fakemod.debug.name);
+      else
+	/* Try the file's unadorned basename as DEBUGLINK_FILE,
+	   to look only for "vmlinux" files.  */
+	fd = INTUSE(dwfl_standard_find_debuginfo) (&fakemod, NULL, NULL, 0,
+						   *fname, xbasename (*fname),
+						   0, &fakemod.debug.name);
+
+      if (fakemod.debug.name != NULL)
+	{
+	  free (*fname);
+	  *fname = fakemod.debug.name;
+	}
+    }
+
+  if (fd < 0)
+    for (size_t i = 0;
+	 i < sizeof vmlinux_suffixes / sizeof vmlinux_suffixes[0] && fd < 0;
+	 ++i)
+      {
+	char *zname;
+	if (asprintf (&zname, "%s%s", *fname, vmlinux_suffixes[i]) > 0)
+	  {
+	    fd = TEMP_FAILURE_RETRY (open (zname, O_RDONLY));
+	    if (fd < 0)
+	      free (zname);
+	    else
+	      {
+		free (*fname);
+		*fname = zname;
+	      }
+	  }
+      }
+
+  if (fd < 0)
+    {
+      free (*fname);
+      *fname = NULL;
+    }
+
+  return fd;
+}
+
+static inline const char *
+kernel_release (void)
+{
+#ifdef __linux__
+  /* Cache the `uname -r` string we'll use.  */
+  static struct utsname utsname;
+  if (utsname.release[0] == '\0' && uname (&utsname) != 0)
+    return NULL;
+  return utsname.release;
+#else
+  /* Used for finding the running linux kernel, which isn't supported
+     on non-linux kernel systems.  */
+  errno = ENOTSUP;
+  return NULL;
+#endif
+}
+
+static int
+find_kernel_elf (Dwfl *dwfl, const char *release, char **fname)
+{
+  /* First try to find an uncompressed vmlinux image.  Possibly
+     including debuginfo.  */
+  if (release == NULL
+      || ((release[0] == '/'
+	   ? asprintf (fname, "%s/vmlinux", release)
+	   : asprintf (fname, "/boot/vmlinux-%s", release)) < 0))
+    return -1;
+
+  int fd = try_kernel_name (dwfl, fname, true);
+  if (fd < 0 && release[0] != '/')
+    {
+      free (*fname);
+      if (asprintf (fname, MODULEDIRFMT "/vmlinux", release) < 0)
+	return -1;
+      fd = try_kernel_name (dwfl, fname, true);
+    }
+
+  /* There might be a compressed vmlinuz image.  Probably without
+     debuginfo, but try to find it under the debug path also, just in
+     case.  */
+  if (fd < 0)
+    {
+      free (*fname);
+      if ((release[0] == '/'
+           ? asprintf (fname, "%s/vmlinuz", release)
+           : asprintf (fname, "/boot/vmlinuz-%s", release)) < 0)
+        return -1;
+
+      fd = try_kernel_name (dwfl, fname, true);
+      if (fd < 0 && release[0] != '/')
+	{
+	  free (*fname);
+	  if (asprintf (fname, MODULEDIRFMT "/vmlinuz", release) < 0)
+	    return -1;
+	  fd = try_kernel_name (dwfl, fname, true);
+	}
+    }
+
+  return fd;
+}
+
+static int
+get_release (Dwfl *dwfl, const char **release)
+{
+  if (dwfl == NULL)
+    return -1;
+
+  const char *release_string = release == NULL ? NULL : *release;
+  if (release_string == NULL)
+    {
+      release_string = kernel_release ();
+      if (release_string == NULL)
+	return errno;
+      if (release != NULL)
+	*release = release_string;
+    }
+
+  return 0;
+}
+
+static int
+report_kernel (Dwfl *dwfl, const char **release,
+	       int (*predicate) (const char *module, const char *file))
+{
+  int result = get_release (dwfl, release);
+  if (unlikely (result != 0))
+    return result;
+
+  if (release == NULL || *release == NULL)
+    return EINVAL;
+
+  char *fname;
+  int fd = find_kernel_elf (dwfl, *release, &fname);
+
+  if (fd < 0)
+    result = ((predicate != NULL && !(*predicate) (KERNEL_MODNAME, NULL))
+	      ? 0 : errno ?: ENOENT);
+  else
+    {
+      bool report = true;
+
+      if (predicate != NULL)
+	{
+	  /* Let the predicate decide whether to use this one.  */
+	  int want = (*predicate) (KERNEL_MODNAME, fname);
+	  if (want < 0)
+	    result = errno;
+	  report = want > 0;
+	}
+
+      if (report)
+	{
+	  /* Note that on some architectures (e.g. x86_64) the vmlinux
+	     is ET_EXEC, while on others (e.g. ppc64) it is ET_DYN.
+	     In both cases the phdr p_vaddr load address will be non-zero.
+	     We want the image to be placed as if it was ET_DYN, so
+	     pass true for add_p_vaddr which will do the right thing
+	     (in combination with a zero base) in either case.  */
+	  Dwfl_Module *mod = INTUSE(dwfl_report_elf) (dwfl, KERNEL_MODNAME,
+						      fname, fd, 0, true);
+	  if (mod == NULL)
+	    result = -1;
+	  else
+	    /* The kernel is ET_EXEC, but always treat it as relocatable.  */
+	    mod->e_type = ET_DYN;
+	}
+
+      free (fname);
+
+      if (!report || result < 0)
+	close (fd);
+    }
+
+  return result;
+}
+
+/* Look for a kernel debug archive.  If we find one, report all its modules.
+   If not, return ENOENT.  */
+static int
+report_kernel_archive (Dwfl *dwfl, const char **release,
+		       int (*predicate) (const char *module, const char *file))
+{
+  int result = get_release (dwfl, release);
+  if (unlikely (result != 0))
+    return result;
+
+  if (release == NULL || *release == NULL)
+    return EINVAL;
+
+  char *archive;
+  int res = (((*release)[0] == '/')
+	     ? asprintf (&archive, "%s/debug.a", *release)
+	     : asprintf (&archive, MODULEDIRFMT "/debug.a", *release));
+  if (unlikely (res < 0))
+    return ENOMEM;
+
+  int fd = try_kernel_name (dwfl, &archive, false);
+  if (fd < 0)
+    result = errno ?: ENOENT;
+  else
+    {
+      /* We have the archive file open!  */
+      Dwfl_Module *last = __libdwfl_report_offline (dwfl, NULL, archive, fd,
+						    true, predicate);
+      if (unlikely (last == NULL))
+	result = -1;
+      else
+	{
+	  /* Find the kernel and move it to the head of the list.  */
+	  Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
+	  for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
+	    if (!m->gc && m->e_type != ET_REL && !strcmp (m->name, "kernel"))
+	      {
+		*prevp = m->next;
+		m->next = *tailp;
+		*tailp = m;
+		break;
+	      }
+	}
+    }
+
+  free (archive);
+  return result;
+}
+
+static size_t
+check_suffix (const FTSENT *f, size_t namelen)
+{
+#define TRY(sfx)							\
+  if ((namelen ? f->fts_namelen == namelen + sizeof sfx - 1		\
+       : f->fts_namelen >= sizeof sfx)					\
+      && !memcmp (f->fts_name + f->fts_namelen - (sizeof sfx - 1),	\
+		  sfx, sizeof sfx))					\
+    return sizeof sfx - 1
+
+  TRY (".ko");
+  TRY (".ko.gz");
+#if USE_BZLIB
+  TRY (".ko.bz2");
+#endif
+#if USE_LZMA
+  TRY (".ko.xz");
+#endif
+#if USE_ZSTD
+  TRY (".ko.zst");
+#endif
+
+  return 0;
+
+#undef	TRY
+}
+
+/* Report a kernel and all its modules found on disk, for offline use.
+   If RELEASE starts with '/', it names a directory to look in;
+   if not, it names a directory to find under /lib/modules/;
+   if null, /lib/modules/`uname -r` is used.
+   Returns zero on success, -1 if dwfl_report_module failed,
+   or an errno code if finding the files on disk failed.  */
+int
+dwfl_linux_kernel_report_offline (Dwfl *dwfl, const char *release,
+				  int (*predicate) (const char *module,
+						    const char *file))
+{
+  int result = report_kernel_archive (dwfl, &release, predicate);
+  if (result != ENOENT)
+    return result;
+
+  /* First report the kernel.  */
+  result = report_kernel (dwfl, &release, predicate);
+  if (result == 0)
+    {
+      /* Do "find /lib/modules/RELEASE -name *.ko".  */
+
+      char *modulesdir[] = { NULL, NULL };
+      if (release[0] == '/')
+	modulesdir[0] = (char *) release;
+      else
+	{
+	  if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
+	    return errno;
+	}
+
+      FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
+      if (modulesdir[0] == (char *) release)
+	modulesdir[0] = NULL;
+      if (fts == NULL)
+	{
+	  free (modulesdir[0]);
+	  return errno;
+	}
+
+      FTSENT *f;
+      while ((f = fts_read (fts)) != NULL)
+	{
+	  /* Skip a "source" subtree, which tends to be large.
+	     This insane hard-coding of names is what depmod does too.  */
+	  if (f->fts_namelen == sizeof "source" - 1
+	      && !strcmp (f->fts_name, "source"))
+	    {
+	      fts_set (fts, f, FTS_SKIP);
+	      continue;
+	    }
+
+	  switch (f->fts_info)
+	    {
+	    case FTS_F:
+	    case FTS_SL:
+	    case FTS_NSOK:;
+	      /* See if this file name matches "*.ko".  */
+	      const size_t suffix = check_suffix (f, 0);
+	      if (suffix)
+		{
+		  /* We have a .ko file to report.  Following the algorithm
+		     by which the kernel makefiles set KBUILD_MODNAME, we
+		     replace all ',' or '-' with '_' in the file name and
+		     call that the module name.  Modules could well be
+		     built using different embedded names than their file
+		     names.  To handle that, we would have to look at the
+		     __this_module.name contents in the module's text.  */
+
+		  char *name = strndup (f->fts_name, f->fts_namelen - suffix);
+		  if (unlikely (name == NULL))
+		    {
+		      __libdwfl_seterrno (DWFL_E_NOMEM);
+		      result = -1;
+		      break;
+		    }
+		  for (size_t i = 0; i < f->fts_namelen - suffix; ++i)
+		    if (name[i] == '-' || name[i] == ',')
+		      name[i] = '_';
+
+		  if (predicate != NULL)
+		    {
+		      /* Let the predicate decide whether to use this one.  */
+		      int want = (*predicate) (name, f->fts_path);
+		      if (want < 0)
+			{
+			  result = -1;
+			  free (name);
+			  break;
+			}
+		      if (!want)
+			{
+			  free (name);
+			  continue;
+			}
+		    }
+
+		  if (dwfl_report_offline (dwfl, name, f->fts_path, -1) == NULL)
+		    {
+		      free (name);
+		      result = -1;
+		      break;
+		    }
+		  free (name);
+		}
+	      continue;
+
+	    case FTS_ERR:
+	    case FTS_DNR:
+	    case FTS_NS:
+	      result = f->fts_errno;
+	      break;
+
+	    case FTS_SLNONE:
+	    default:
+	      continue;
+	    }
+
+	  /* We only get here in error cases.  */
+	  break;
+	}
+      fts_close (fts);
+      free (modulesdir[0]);
+    }
+
+  return result;
+}
+INTDEF (dwfl_linux_kernel_report_offline)
+
+
+/* State of read_address used by intuit_kernel_bounds. */
+struct read_address_state {
+  FILE *f;
+  char *line;
+  size_t linesz;
+  size_t n;
+  char *p;
+  const char *type;
+};
+
+static inline bool
+read_address (struct read_address_state *state, Dwarf_Addr *addr)
+{
+  if ((state->n = getline (&state->line, &state->linesz, state->f)) < 1 ||
+      state->line[state->n - 2] == ']')
+    return false;
+  *addr = strtoull (state->line, &state->p, 16);
+  state->p += strspn (state->p, " \t");
+  state->type = strsep (&state->p, " \t\n");
+  if (state->type == NULL)
+    return false;
+  return state->p != NULL && state->p != state->line;
+}
+
+
+/* Grovel around to guess the bounds of the runtime kernel image.  */
+static int
+intuit_kernel_bounds (Dwarf_Addr *start, Dwarf_Addr *end, Dwarf_Addr *notes)
+{
+  struct read_address_state state = { NULL, NULL, 0, 0, NULL, NULL };
+
+  *notes = 0;
+
+  state.f = fopen (KSYMSFILE, "r");
+  if (state.f == NULL)
+    return errno;
+
+  (void) __fsetlocking (state.f, FSETLOCKING_BYCALLER);
+
+  int result;
+  do
+    result = read_address (&state, start) ? 0 : -1;
+  while (result == 0 && strchr ("TtRr", *state.type) == NULL);
+
+  if (result == 0)
+    {
+      Dwarf_Addr addr;
+      *end = *start;
+      while (read_address (&state, &addr) && addr >= *end)
+	{
+	  *end = addr;
+	  if (*notes == 0 && !strcmp (state.p, "__start_notes\n"))
+	    *notes = *end;
+	}
+
+      Dwarf_Addr round_kernel = sysconf (_SC_PAGESIZE);
+      *start &= -(Dwarf_Addr) round_kernel;
+      *end += round_kernel - 1;
+      *end &= -(Dwarf_Addr) round_kernel;
+      if (*start >= *end || *end - *start < round_kernel)
+	result = -1;
+    }
+  free (state.line);
+
+  if (result == -1)
+    result = ferror_unlocked (state.f) ? errno : ENOEXEC;
+
+  fclose (state.f);
+
+  return result;
+}
+
+
+/* Look for a build ID note in NOTESFILE and associate the ID with MOD.  */
+static int
+check_notes (Dwfl_Module *mod, const char *notesfile,
+	     Dwarf_Addr vaddr, const char *secname)
+{
+  int fd = open (notesfile, O_RDONLY);
+  if (fd < 0)
+    return 1;
+
+  assert (sizeof (Elf32_Nhdr) == sizeof (GElf_Nhdr));
+  assert (sizeof (Elf64_Nhdr) == sizeof (GElf_Nhdr));
+  union
+  {
+    GElf_Nhdr nhdr;
+    unsigned char data[8192];
+  } buf;
+
+  ssize_t n = read (fd, buf.data, sizeof buf);
+  close (fd);
+
+  if (n <= 0)
+    return 1;
+
+  unsigned char *p = buf.data;
+  size_t len = 0;
+  while (p < &buf.data[n])
+    {
+      /* No translation required since we are reading the native kernel.  */
+      GElf_Nhdr *nhdr = (void *) p;
+      len += sizeof *nhdr;
+      p += len;
+      unsigned char *name = p;
+      unsigned char *bits;
+      /* This is somewhat ugly, GNU Property notes use different padding,
+	 but all we have is the file content, so we have to actually check
+	 the name and type.  */
+      if (nhdr->n_type == NT_GNU_PROPERTY_TYPE_0
+          && nhdr->n_namesz == sizeof "GNU"
+          && name + nhdr->n_namesz < &buf.data[n]
+          && !memcmp (name, "GNU", sizeof "GNU"))
+	{
+	  len += nhdr->n_namesz;
+	  len = NOTE_ALIGN8 (len);
+	  p = buf.data + len;
+	  bits = p;
+	  len += nhdr->n_descsz;
+	  len = NOTE_ALIGN8 (len);
+	  p = buf.data + len;
+	}
+      else
+	{
+	  len += nhdr->n_namesz;
+	  len = NOTE_ALIGN4 (len);
+	  p = buf.data + len;
+	  bits = p;
+	  len += nhdr->n_descsz;
+	  len = NOTE_ALIGN4 (len);
+	  p = buf.data + len;
+	}
+
+      if (p <= &buf.data[n]
+	  && nhdr->n_type == NT_GNU_BUILD_ID
+	  && nhdr->n_namesz == sizeof "GNU"
+	  && !memcmp (name, "GNU", sizeof "GNU"))
+	{
+	  /* Found it.  For a module we must figure out its VADDR now.  */
+
+	  if (secname != NULL
+	      && (INTUSE(dwfl_linux_kernel_module_section_address)
+		  (mod, NULL, mod->name, 0, secname, 0, NULL, &vaddr) != 0
+		  || vaddr == (GElf_Addr) -1l))
+	    vaddr = 0;
+
+	  if (vaddr != 0)
+	    vaddr += bits - buf.data;
+	  return INTUSE(dwfl_module_report_build_id) (mod, bits,
+						      nhdr->n_descsz, vaddr);
+	}
+    }
+
+  return 0;
+}
+
+/* Look for a build ID for the kernel.  */
+static int
+check_kernel_notes (Dwfl_Module *kernelmod, GElf_Addr vaddr)
+{
+  return check_notes (kernelmod, KNOTESFILE, vaddr, NULL) < 0 ? -1 : 0;
+}
+
+/* Look for a build ID for a loaded kernel module.  */
+static int
+check_module_notes (Dwfl_Module *mod)
+{
+  char *dirs[2] = { NULL, NULL };
+  if (asprintf (&dirs[0], MODNOTESFMT, mod->name) < 0)
+    return ENOMEM;
+
+  FTS *fts = fts_open (dirs, FTS_NOSTAT | FTS_LOGICAL, NULL);
+  if (fts == NULL)
+    {
+      free (dirs[0]);
+      return 0;
+    }
+
+  int result = 0;
+  FTSENT *f;
+  while ((f = fts_read (fts)) != NULL)
+    {
+      switch (f->fts_info)
+	{
+	case FTS_F:
+	case FTS_SL:
+	case FTS_NSOK:
+	  result = check_notes (mod, f->fts_accpath, 0, f->fts_name);
+	  if (result > 0)	/* Nothing found.  */
+	    {
+	      result = 0;
+	      continue;
+	    }
+	  break;
+
+	case FTS_ERR:
+	case FTS_DNR:
+	  result = f->fts_errno;
+	  break;
+
+	case FTS_NS:
+	case FTS_SLNONE:
+	default:
+	  continue;
+	}
+
+      /* We only get here when finished or in error cases.  */
+      break;
+    }
+  fts_close (fts);
+  free (dirs[0]);
+
+  return result;
+}
+
+int
+dwfl_linux_kernel_report_kernel (Dwfl *dwfl)
+{
+  Dwarf_Addr start = 0;
+  Dwarf_Addr end = 0;
+
+  #define report() \
+    (INTUSE(dwfl_report_module) (dwfl, KERNEL_MODNAME, start, end))
+
+  /* This is a bit of a kludge.  If we already reported the kernel,
+     don't bother figuring it out again--it never changes.  */
+  for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
+    if (!strcmp (m->name, KERNEL_MODNAME))
+      {
+	start = m->low_addr;
+	end = m->high_addr;
+	return report () == NULL ? -1 : 0;
+      }
+
+  /* Try to figure out the bounds of the kernel image without
+     looking for any vmlinux file.  */
+  Dwarf_Addr notes;
+  int result = intuit_kernel_bounds (&start, &end, &notes);
+  if (result == 0)
+    {
+      Dwfl_Module *mod = report ();
+      return unlikely (mod == NULL) ? -1 : check_kernel_notes (mod, notes);
+    }
+  if (result != ENOENT)
+    return result;
+
+  /* Find the ELF file for the running kernel and dwfl_report_elf it.  */
+  return report_kernel (dwfl, NULL, NULL);
+}
+INTDEF (dwfl_linux_kernel_report_kernel)
+
+
+static inline bool
+subst_name (char from, char to,
+            const char * const module_name,
+            char * const alternate_name,
+            const size_t namelen)
+{
+  const char *n = memchr (module_name, from, namelen);
+  if (n == NULL)
+    return false;
+  char *a = mempcpy (alternate_name, module_name, n - module_name);
+  *a++ = to;
+  ++n;
+  const char *p;
+  while ((p = memchr (n, from, namelen - (n - module_name))) != NULL)
+    {
+      a = mempcpy (a, n, p - n);
+      *a++ = to;
+      n = p + 1;
+    }
+  memcpy (a, n, namelen - (n - module_name) + 1);
+  return true;
+}
+
+/* Dwfl_Callbacks.find_elf for the running Linux kernel and its modules.  */
+
+int
+dwfl_linux_kernel_find_elf (Dwfl_Module *mod,
+			    void **userdata __attribute__ ((unused)),
+			    const char *module_name,
+			    Dwarf_Addr base __attribute__ ((unused)),
+			    char **file_name, Elf **elfp)
+{
+  if (mod->build_id_len > 0)
+    {
+      int fd = INTUSE(dwfl_build_id_find_elf) (mod, NULL, NULL, 0,
+					       file_name, elfp);
+      if (fd >= 0 || mod->main.elf != NULL || errno != 0)
+	return fd;
+    }
+
+  const char *release = kernel_release ();
+  if (release == NULL)
+    return errno;
+
+  if (!strcmp (module_name, KERNEL_MODNAME))
+    return find_kernel_elf (mod->dwfl, release, file_name);
+
+  /* Do "find /lib/modules/`uname -r` -name MODULE_NAME.ko".  */
+
+  char *modulesdir[] = { NULL, NULL };
+  if (asprintf (&modulesdir[0], MODULEDIRFMT, release) < 0)
+    return -1;
+
+  FTS *fts = fts_open (modulesdir, FTS_NOSTAT | FTS_LOGICAL, NULL);
+  if (fts == NULL)
+    {
+      free (modulesdir[0]);
+      return -1;
+    }
+
+  size_t namelen = strlen (module_name);
+
+  /* This is a kludge.  There is no actual necessary relationship between
+     the name of the .ko file installed and the module name the kernel
+     knows it by when it's loaded.  The kernel's only idea of the module
+     name comes from the name embedded in the object's magic
+     .gnu.linkonce.this_module section.
+
+     In practice, these module names match the .ko file names except for
+     some using '_' and some using '-'.  So our cheap kludge is to look for
+     two files when either a '_' or '-' appears in a module name, one using
+     only '_' and one only using '-'.  */
+
+  char *alternate_name = malloc (namelen + 1);
+  if (unlikely (alternate_name == NULL))
+    {
+      free (modulesdir[0]);
+      return ENOMEM;
+    }
+  if (!subst_name ('-', '_', module_name, alternate_name, namelen) &&
+      !subst_name ('_', '-', module_name, alternate_name, namelen))
+    alternate_name[0] = '\0';
+
+  FTSENT *f;
+  int error = ENOENT;
+  while ((f = fts_read (fts)) != NULL)
+    {
+      /* Skip a "source" subtree, which tends to be large.
+	 This insane hard-coding of names is what depmod does too.  */
+      if (f->fts_namelen == sizeof "source" - 1
+	  && !strcmp (f->fts_name, "source"))
+	{
+	  fts_set (fts, f, FTS_SKIP);
+	  continue;
+	}
+
+      error = ENOENT;
+      switch (f->fts_info)
+	{
+	case FTS_F:
+	case FTS_SL:
+	case FTS_NSOK:
+	  /* See if this file name is "MODULE_NAME.ko".  */
+	  if (check_suffix (f, namelen)
+	      && (!memcmp (f->fts_name, module_name, namelen)
+		  || !memcmp (f->fts_name, alternate_name, namelen)))
+	    {
+	      int fd = open (f->fts_accpath, O_RDONLY);
+	      *file_name = strdup (f->fts_path);
+	      fts_close (fts);
+	      free (modulesdir[0]);
+	      free (alternate_name);
+	      if (fd < 0)
+		free (*file_name);
+	      else if (*file_name == NULL)
+		{
+		  close (fd);
+		  fd = -1;
+		}
+	      return fd;
+	    }
+	  break;
+
+	case FTS_ERR:
+	case FTS_DNR:
+	case FTS_NS:
+	  error = f->fts_errno;
+	  break;
+
+	case FTS_SLNONE:
+	default:
+	  break;
+	}
+    }
+
+  fts_close (fts);
+  free (modulesdir[0]);
+  free (alternate_name);
+  errno = error;
+  return -1;
+}
+INTDEF (dwfl_linux_kernel_find_elf)
+
+
+/* Dwfl_Callbacks.section_address for kernel modules in the running Linux.
+   We read the information from /sys/module directly.  */
+
+int
+dwfl_linux_kernel_module_section_address
+(Dwfl_Module *mod __attribute__ ((unused)),
+ void **userdata __attribute__ ((unused)),
+ const char *modname, Dwarf_Addr base __attribute__ ((unused)),
+ const char *secname, Elf32_Word shndx __attribute__ ((unused)),
+ const GElf_Shdr *shdr __attribute__ ((unused)),
+ Dwarf_Addr *addr)
+{
+  char *sysfile;
+  if (asprintf (&sysfile, SECADDRDIRFMT "%s", modname, secname) < 0)
+    return DWARF_CB_ABORT;
+
+  FILE *f = fopen (sysfile, "r");
+  free (sysfile);
+
+  if (f == NULL)
+    {
+      if (errno == ENOENT)
+	{
+	  /* The .modinfo and .data.percpu sections are never kept
+	     loaded in the kernel.  If the kernel was compiled without
+	     CONFIG_MODULE_UNLOAD, the .exit.* sections are not
+	     actually loaded at all.
+
+	     Setting *ADDR to -1 tells the caller this section is
+	     actually absent from memory.  */
+
+	  if (!strcmp (secname, ".modinfo")
+	      || !strcmp (secname, ".data.percpu")
+	      || startswith (secname, ".exit"))
+	    {
+	      *addr = (Dwarf_Addr) -1l;
+	      return DWARF_CB_OK;
+	    }
+
+	  /* The goofy PPC64 module_frob_arch_sections function tweaks
+	     the section names as a way to control other kernel code's
+	     behavior, and this cruft leaks out into the /sys information.
+	     The file name for ".init*" may actually look like "_init*".  */
+
+	  const bool is_init = startswith (secname, ".init");
+	  if (is_init)
+	    {
+	      if (asprintf (&sysfile, SECADDRDIRFMT "_%s",
+			    modname, &secname[1]) < 0)
+		return ENOMEM;
+	      f = fopen (sysfile, "r");
+	      free (sysfile);
+	      if (f != NULL)
+		goto ok;
+	    }
+
+	  /* The kernel truncates section names to MODULE_SECT_NAME_LEN - 1.
+	     In case that size increases in the future, look for longer
+	     truncated names first.  */
+	  size_t namelen = strlen (secname);
+	  if (namelen >= MODULE_SECT_NAME_LEN)
+	    {
+	      int len = asprintf (&sysfile, SECADDRDIRFMT "%s",
+				  modname, secname);
+	      if (len < 0)
+		return DWARF_CB_ABORT;
+	      char *end = sysfile + len;
+	      do
+		{
+		  *--end = '\0';
+		  f = fopen (sysfile, "r");
+		  if (is_init && f == NULL && errno == ENOENT)
+		    {
+		      sysfile[len - namelen] = '_';
+		      f = fopen (sysfile, "r");
+		      sysfile[len - namelen] = '.';
+		    }
+		}
+	      while (f == NULL && errno == ENOENT
+		     && end - &sysfile[len - namelen] >= MODULE_SECT_NAME_LEN);
+	      free (sysfile);
+
+	      if (f != NULL)
+		goto ok;
+	    }
+	}
+
+      return DWARF_CB_ABORT;
+    }
+
+ ok:
+  (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
+
+  int result = (fscanf (f, "%" PRIx64 "\n", addr) == 1 ? 0
+		: ferror_unlocked (f) ? errno : ENOEXEC);
+  fclose (f);
+
+  if (result == 0)
+    return DWARF_CB_OK;
+
+  errno = result;
+  return DWARF_CB_ABORT;
+}
+INTDEF (dwfl_linux_kernel_module_section_address)
+
+int
+dwfl_linux_kernel_report_modules (Dwfl *dwfl)
+{
+  FILE *f = fopen (MODULELIST, "r");
+  if (f == NULL)
+    return errno;
+
+  (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
+
+  int result = 0;
+  Dwarf_Addr modaddr;
+  unsigned long int modsz;
+  char modname[128+1];
+  char *line = NULL;
+  size_t linesz = 0;
+  /* We can't just use fscanf here because it's not easy to distinguish \n
+     from other whitespace so as to take the optional word following the
+     address but always stop at the end of the line.  */
+  while (getline (&line, &linesz, f) > 0
+	 && sscanf (line, "%128s %lu %*s %*s %*s %" PRIx64 " %*s\n",
+		    modname, &modsz, &modaddr) == 3)
+    {
+      Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, modname,
+						     modaddr, modaddr + modsz);
+      if (mod == NULL)
+	{
+	  result = -1;
+	  break;
+	}
+
+      result = check_module_notes (mod);
+    }
+  free (line);
+
+  if (result == 0)
+    result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
+
+  fclose (f);
+
+  return result;
+}
+INTDEF (dwfl_linux_kernel_report_modules)
diff --git a/libdwfl/linux-pid-attach.c b/libdwfl/linux-pid-attach.c
new file mode 100644
index 0000000..de86785
--- /dev/null
+++ b/libdwfl/linux-pid-attach.c
@@ -0,0 +1,539 @@
+/* Get Dwarf Frame state for target live PID process.
+   Copyright (C) 2013, 2014, 2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include "libelfP.h"
+#include "libdwflP.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+
+#ifdef __linux__
+
+#include <sys/uio.h>
+#include <sys/ptrace.h>
+#include <sys/syscall.h>
+#include <sys/wait.h>
+
+static bool
+linux_proc_pid_is_stopped (pid_t pid)
+{
+  char buffer[64];
+  FILE *procfile;
+  bool retval, have_state;
+
+  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
+  procfile = fopen (buffer, "r");
+  if (procfile == NULL)
+    return false;
+
+  have_state = false;
+  while (fgets (buffer, sizeof (buffer), procfile) != NULL)
+    if (startswith (buffer, "State:"))
+      {
+	have_state = true;
+	break;
+      }
+  retval = (have_state && strstr (buffer, "T (stopped)") != NULL);
+  fclose (procfile);
+  return retval;
+}
+
+bool
+internal_function
+__libdwfl_ptrace_attach (pid_t tid, bool *tid_was_stoppedp)
+{
+  if (ptrace (PTRACE_ATTACH, tid, NULL, NULL) != 0)
+    {
+      __libdwfl_seterrno (DWFL_E_ERRNO);
+      return false;
+    }
+  *tid_was_stoppedp = linux_proc_pid_is_stopped (tid);
+  if (*tid_was_stoppedp)
+    {
+      /* Make sure there is a SIGSTOP signal pending even when the process is
+	 already State: T (stopped).  Older kernels might fail to generate
+	 a SIGSTOP notification in that case in response to our PTRACE_ATTACH
+	 above.  Which would make the waitpid below wait forever.  So emulate
+	 it.  Since there can only be one SIGSTOP notification pending this is
+	 safe.  See also gdb/linux-nat.c linux_nat_post_attach_wait.  */
+      syscall (__NR_tkill, tid, SIGSTOP);
+      ptrace (PTRACE_CONT, tid, NULL, NULL);
+    }
+  for (;;)
+    {
+      int status;
+      if (waitpid (tid, &status, __WALL) != tid || !WIFSTOPPED (status))
+	{
+	  int saved_errno = errno;
+	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
+	  errno = saved_errno;
+	  __libdwfl_seterrno (DWFL_E_ERRNO);
+	  return false;
+	}
+      if (WSTOPSIG (status) == SIGSTOP)
+	break;
+      if (ptrace (PTRACE_CONT, tid, NULL,
+		  (void *) (uintptr_t) WSTOPSIG (status)) != 0)
+	{
+	  int saved_errno = errno;
+	  ptrace (PTRACE_DETACH, tid, NULL, NULL);
+	  errno = saved_errno;
+	  __libdwfl_seterrno (DWFL_E_ERRNO);
+	  return false;
+	}
+    }
+  return true;
+}
+
+#ifdef HAVE_PROCESS_VM_READV
+/* Note that the result word size depends on the architecture word size.
+   That is sizeof long. */
+static bool
+read_cached_memory (struct __libdwfl_pid_arg *pid_arg,
+		    Dwarf_Addr addr, Dwarf_Word *result)
+{
+  /* Let the ptrace fallback deal with the corner case of the address
+     possibly crossing a page boundary.  */
+  if ((addr & ((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1))
+      > (Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - sizeof (unsigned long))
+    return false;
+
+  struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
+  if (mem_cache == NULL)
+    {
+      size_t mem_cache_size = sizeof (struct __libdwfl_remote_mem_cache);
+      mem_cache = malloc (mem_cache_size);
+      if (mem_cache == NULL)
+	return false;
+
+      mem_cache->addr = 0;
+      mem_cache->len = 0;
+      pid_arg->mem_cache = mem_cache;
+    }
+
+  unsigned char *d;
+  if (addr >= mem_cache->addr && addr - mem_cache->addr < mem_cache->len)
+    {
+      d = &mem_cache->buf[addr - mem_cache->addr];
+      if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
+	*result = *(unsigned long *) d;
+      else
+	memcpy (result, d, sizeof (unsigned long));
+      return true;
+    }
+
+  struct iovec local, remote;
+  mem_cache->addr = addr & ~((Dwarf_Addr)__LIBDWFL_REMOTE_MEM_CACHE_SIZE - 1);
+  local.iov_base = mem_cache->buf;
+  local.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
+  remote.iov_base = (void *) (uintptr_t) mem_cache->addr;
+  remote.iov_len = __LIBDWFL_REMOTE_MEM_CACHE_SIZE;
+
+  ssize_t res = process_vm_readv (pid_arg->tid_attached,
+				  &local, 1, &remote, 1, 0);
+  if (res != __LIBDWFL_REMOTE_MEM_CACHE_SIZE)
+    {
+      mem_cache->len = 0;
+      return false;
+    }
+
+  mem_cache->len = res;
+  d = &mem_cache->buf[addr - mem_cache->addr];
+  if ((((uintptr_t) d) & (sizeof (unsigned long) - 1)) == 0)
+    *result = *(unsigned long *) d;
+  else
+    memcpy (result, d, sizeof (unsigned long));
+  return true;
+}
+#endif /* HAVE_PROCESS_VM_READV */
+
+static void
+clear_cached_memory (struct __libdwfl_pid_arg *pid_arg)
+{
+  struct __libdwfl_remote_mem_cache *mem_cache = pid_arg->mem_cache;
+  if (mem_cache != NULL)
+    mem_cache->len = 0;
+}
+
+/* Note that the result word size depends on the architecture word size.
+   That is sizeof long. */
+static bool
+pid_memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result, void *arg)
+{
+  struct __libdwfl_pid_arg *pid_arg = arg;
+  pid_t tid = pid_arg->tid_attached;
+  Dwfl_Process *process = dwfl->process;
+  assert (tid > 0);
+
+#ifdef HAVE_PROCESS_VM_READV
+  if (read_cached_memory (pid_arg, addr, result))
+    {
+#if SIZEOF_LONG == 8
+# if BYTE_ORDER == BIG_ENDIAN
+      if (ebl_get_elfclass (process->ebl) == ELFCLASS32)
+	*result >>= 32;
+# endif
+#endif
+    return true;
+    }
+#endif
+
+  if (ebl_get_elfclass (process->ebl) == ELFCLASS64)
+    {
+#if SIZEOF_LONG == 8
+      errno = 0;
+      *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
+      return errno == 0;
+#else /* SIZEOF_LONG != 8 */
+      /* This should not happen.  */
+      return false;
+#endif /* SIZEOF_LONG != 8 */
+    }
+#if SIZEOF_LONG == 8
+  /* We do not care about reads unaliged to 4 bytes boundary.
+     But 0x...ffc read of 8 bytes could overrun a page.  */
+  bool lowered = (addr & 4) != 0;
+  if (lowered)
+    addr -= 4;
+#endif /* SIZEOF_LONG == 8 */
+  errno = 0;
+  *result = ptrace (PTRACE_PEEKDATA, tid, (void *) (uintptr_t) addr, NULL);
+  if (errno != 0)
+    return false;
+#if SIZEOF_LONG == 8
+# if BYTE_ORDER == BIG_ENDIAN
+  if (! lowered)
+    *result >>= 32;
+# else
+  if (lowered)
+    *result >>= 32;
+# endif
+#endif /* SIZEOF_LONG == 8 */
+  *result &= 0xffffffff;
+  return true;
+}
+
+static pid_t
+pid_next_thread (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg,
+		 void **thread_argp)
+{
+  struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
+  struct dirent *dirent;
+  /* Start fresh on first traversal. */
+  if (*thread_argp == NULL)
+    rewinddir (pid_arg->dir);
+  do
+    {
+      errno = 0;
+      dirent = readdir (pid_arg->dir);
+      if (dirent == NULL)
+	{
+	  if (errno != 0)
+	    {
+	      __libdwfl_seterrno (DWFL_E_ERRNO);
+	      return -1;
+	    }
+	  return 0;
+	}
+    }
+  while (strcmp (dirent->d_name, ".") == 0
+	 || strcmp (dirent->d_name, "..") == 0);
+  char *end;
+  errno = 0;
+  long tidl = strtol (dirent->d_name, &end, 10);
+  if (errno != 0)
+    {
+      __libdwfl_seterrno (DWFL_E_ERRNO);
+      return -1;
+    }
+  pid_t tid = tidl;
+  if (tidl <= 0 || (end && *end) || tid != tidl)
+    {
+      __libdwfl_seterrno (DWFL_E_PARSE_PROC);
+      return -1;
+    }
+  *thread_argp = dwfl_arg;
+  return tid;
+}
+
+/* Just checks that the thread id exists.  */
+static bool
+pid_getthread (Dwfl *dwfl __attribute__ ((unused)), pid_t tid,
+	       void *dwfl_arg, void **thread_argp)
+{
+  *thread_argp = dwfl_arg;
+  if (kill (tid, 0) < 0)
+    {
+      __libdwfl_seterrno (DWFL_E_ERRNO);
+      return false;
+    }
+  return true;
+}
+
+/* Implement the ebl_set_initial_registers_tid setfunc callback.  */
+
+static bool
+pid_thread_state_registers_cb (int firstreg, unsigned nregs,
+			       const Dwarf_Word *regs, void *arg)
+{
+  Dwfl_Thread *thread = (Dwfl_Thread *) arg;
+  if (firstreg < 0)
+    {
+      assert (firstreg == -1);
+      assert (nregs == 1);
+      INTUSE(dwfl_thread_state_register_pc) (thread, *regs);
+      return true;
+    }
+  assert (nregs > 0);
+  return INTUSE(dwfl_thread_state_registers) (thread, firstreg, nregs, regs);
+}
+
+static bool
+pid_set_initial_registers (Dwfl_Thread *thread, void *thread_arg)
+{
+  struct __libdwfl_pid_arg *pid_arg = thread_arg;
+  assert (pid_arg->tid_attached == 0);
+  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
+  if (! pid_arg->assume_ptrace_stopped
+      && ! __libdwfl_ptrace_attach (tid, &pid_arg->tid_was_stopped))
+    return false;
+  pid_arg->tid_attached = tid;
+  Dwfl_Process *process = thread->process;
+  Ebl *ebl = process->ebl;
+  return ebl_set_initial_registers_tid (ebl, tid,
+					pid_thread_state_registers_cb, thread);
+}
+
+static void
+pid_detach (Dwfl *dwfl __attribute__ ((unused)), void *dwfl_arg)
+{
+  struct __libdwfl_pid_arg *pid_arg = dwfl_arg;
+  elf_end (pid_arg->elf);
+  free (pid_arg->mem_cache);
+  close (pid_arg->elf_fd);
+  closedir (pid_arg->dir);
+  free (pid_arg);
+}
+
+void
+internal_function
+__libdwfl_ptrace_detach (pid_t tid, bool tid_was_stopped)
+{
+  /* This handling is needed only on older Linux kernels such as
+     2.6.32-358.23.2.el6.ppc64.  Later kernels such as
+     3.11.7-200.fc19.x86_64 remember the T (stopped) state
+     themselves and no longer need to pass SIGSTOP during
+     PTRACE_DETACH.  */
+  ptrace (PTRACE_DETACH, tid, NULL,
+	  (void *) (intptr_t) (tid_was_stopped ? SIGSTOP : 0));
+}
+
+static void
+pid_thread_detach (Dwfl_Thread *thread, void *thread_arg)
+{
+  struct __libdwfl_pid_arg *pid_arg = thread_arg;
+  pid_t tid = INTUSE(dwfl_thread_tid) (thread);
+  assert (pid_arg->tid_attached == tid);
+  pid_arg->tid_attached = 0;
+  clear_cached_memory (pid_arg);
+  if (! pid_arg->assume_ptrace_stopped)
+    __libdwfl_ptrace_detach (tid, pid_arg->tid_was_stopped);
+}
+
+static const Dwfl_Thread_Callbacks pid_thread_callbacks =
+{
+  pid_next_thread,
+  pid_getthread,
+  pid_memory_read,
+  pid_set_initial_registers,
+  pid_detach,
+  pid_thread_detach,
+};
+
+int
+dwfl_linux_proc_attach (Dwfl *dwfl, pid_t pid, bool assume_ptrace_stopped)
+{
+  char buffer[36];
+  FILE *procfile;
+  int err = 0; /* The errno to return and set for dwfl->attcherr.  */
+
+  /* Make sure to report the actual PID (thread group leader) to
+     dwfl_attach_state.  */
+  snprintf (buffer, sizeof (buffer), "/proc/%ld/status", (long) pid);
+  procfile = fopen (buffer, "r");
+  if (procfile == NULL)
+    {
+      err = errno;
+    fail:
+      if (dwfl->process == NULL && dwfl->attacherr == DWFL_E_NOERROR)
+	{
+	  errno = err;
+	  dwfl->attacherr = __libdwfl_canon_error (DWFL_E_ERRNO);
+	}
+      return err;
+    }
+
+  char *line = NULL;
+  size_t linelen = 0;
+  while (getline (&line, &linelen, procfile) >= 0)
+    if (startswith (line, "Tgid:"))
+      {
+	errno = 0;
+	char *endptr;
+	long val = strtol (&line[5], &endptr, 10);
+	if ((errno == ERANGE && val == LONG_MAX)
+	    || *endptr != '\n' || val < 0 || val != (pid_t) val)
+	  pid = 0;
+	else
+	  pid = (pid_t) val;
+	break;
+      }
+  free (line);
+  fclose (procfile);
+
+  if (pid == 0)
+    {
+      err = ESRCH;
+      goto fail;
+    }
+
+  char name[64];
+  int i = snprintf (name, sizeof (name), "/proc/%ld/task", (long) pid);
+  if (i <= 0 || i >= (ssize_t) sizeof (name) - 1)
+    {
+      errno = -ENOMEM;
+      goto fail;
+    }
+  DIR *dir = opendir (name);
+  if (dir == NULL)
+    {
+      err = errno;
+      goto fail;
+    }
+
+  Elf *elf;
+  i = snprintf (name, sizeof (name), "/proc/%ld/exe", (long) pid);
+  assert (i > 0 && i < (ssize_t) sizeof (name) - 1);
+  int elf_fd = open (name, O_RDONLY);
+  if (elf_fd >= 0)
+    {
+      elf = elf_begin (elf_fd, ELF_C_READ_MMAP, NULL);
+      if (elf == NULL)
+	{
+	  /* Just ignore, dwfl_attach_state will fall back to trying
+	     to associate the Dwfl with one of the existing DWfl_Module
+	     ELF images (to know the machine/class backend to use).  */
+	  close (elf_fd);
+	  elf_fd = -1;
+	}
+    }
+  else
+    elf = NULL;
+  struct __libdwfl_pid_arg *pid_arg = malloc (sizeof *pid_arg);
+  if (pid_arg == NULL)
+    {
+      elf_end (elf);
+      close (elf_fd);
+      closedir (dir);
+      err = ENOMEM;
+      goto fail;
+    }
+  pid_arg->dir = dir;
+  pid_arg->elf = elf;
+  pid_arg->elf_fd = elf_fd;
+  pid_arg->mem_cache = NULL;
+  pid_arg->tid_attached = 0;
+  pid_arg->assume_ptrace_stopped = assume_ptrace_stopped;
+  if (! INTUSE(dwfl_attach_state) (dwfl, elf, pid, &pid_thread_callbacks,
+				   pid_arg))
+    {
+      elf_end (elf);
+      close (elf_fd);
+      closedir (dir);
+      free (pid_arg);
+      return -1;
+    }
+  return 0;
+}
+INTDEF (dwfl_linux_proc_attach)
+
+struct __libdwfl_pid_arg *
+internal_function
+__libdwfl_get_pid_arg (Dwfl *dwfl)
+{
+  if (dwfl != NULL && dwfl->process != NULL
+      && dwfl->process->callbacks == &pid_thread_callbacks)
+    return (struct __libdwfl_pid_arg *) dwfl->process->callbacks_arg;
+
+  return NULL;
+}
+
+#else	/* __linux__ */
+
+bool
+internal_function
+__libdwfl_ptrace_attach (pid_t tid __attribute__ ((unused)),
+			 bool *tid_was_stoppedp __attribute__ ((unused)))
+{
+  errno = ENOSYS;
+  __libdwfl_seterrno (DWFL_E_ERRNO);
+  return false;
+}
+
+void
+internal_function
+__libdwfl_ptrace_detach (pid_t tid __attribute__ ((unused)),
+			 bool tid_was_stopped __attribute__ ((unused)))
+{
+}
+
+int
+dwfl_linux_proc_attach (Dwfl *dwfl __attribute__ ((unused)),
+			pid_t pid __attribute__ ((unused)),
+			bool assume_ptrace_stopped __attribute__ ((unused)))
+{
+  return ENOSYS;
+}
+INTDEF (dwfl_linux_proc_attach)
+
+struct __libdwfl_pid_arg *
+internal_function
+__libdwfl_get_pid_arg (Dwfl *dwfl __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+#endif /* ! __linux __ */
+
diff --git a/libdwfl/linux-proc-maps.c b/libdwfl/linux-proc-maps.c
new file mode 100644
index 0000000..719cba6
--- /dev/null
+++ b/libdwfl/linux-proc-maps.c
@@ -0,0 +1,440 @@
+/* Standard libdwfl callbacks for debugging a live Linux process.
+   Copyright (C) 2005-2010, 2013, 2014, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <assert.h>
+#include <endian.h>
+#include "system.h"
+
+
+#define PROCMAPSFMT	"/proc/%d/maps"
+#define PROCMEMFMT	"/proc/%d/mem"
+#define PROCAUXVFMT	"/proc/%d/auxv"
+#define PROCEXEFMT	"/proc/%d/exe"
+
+
+/* Return ELFCLASS64 or ELFCLASS32 for the main ELF executable.  Return
+   ELFCLASSNONE for an error.  */
+
+static unsigned char
+get_pid_class (pid_t pid)
+{
+  char *fname;
+  if (asprintf (&fname, PROCEXEFMT, pid) < 0)
+    return ELFCLASSNONE;
+
+  int fd = open (fname, O_RDONLY);
+  free (fname);
+  if (fd < 0)
+    return ELFCLASSNONE;
+
+  unsigned char buf[EI_CLASS + 1];
+  ssize_t nread = pread_retry (fd, &buf, sizeof buf, 0);
+  close (fd);
+  if (nread != sizeof buf || buf[EI_MAG0] != ELFMAG0
+      || buf[EI_MAG1] != ELFMAG1 || buf[EI_MAG2] != ELFMAG2
+      || buf[EI_MAG3] != ELFMAG3
+      || (buf[EI_CLASS] != ELFCLASS64 && buf[EI_CLASS] != ELFCLASS32))
+    return ELFCLASSNONE;
+
+  return buf[EI_CLASS];
+}
+
+/* Search /proc/PID/auxv for the AT_SYSINFO_EHDR tag.
+
+   It would be easiest to call get_pid_class and parse everything according to
+   the 32-bit or 64-bit class.  But this would bring the overhead of syscalls
+   to open and read the "/proc/%d/exe" file.
+
+   Therefore this function tries to parse the "/proc/%d/auxv" content both
+   ways, as if it were the 32-bit format and also if it were the 64-bit format.
+   Only if it gives some valid data in both cases get_pid_class gets called.
+   In most cases only one of the format bit sizes gives valid data and the
+   get_pid_class call overhead can be saved.  */
+
+static int
+grovel_auxv (pid_t pid, Dwfl *dwfl, GElf_Addr *sysinfo_ehdr)
+{
+  char *fname;
+  if (asprintf (&fname, PROCAUXVFMT, pid) < 0)
+    return ENOMEM;
+
+  int fd = open (fname, O_RDONLY);
+  free (fname);
+  if (fd < 0)
+    return errno == ENOENT ? 0 : errno;
+
+  GElf_Addr sysinfo_ehdr64 = 0;
+  GElf_Addr sysinfo_ehdr32 = 0;
+  GElf_Addr segment_align64 = dwfl->segment_align;
+  GElf_Addr segment_align32 = dwfl->segment_align;
+  off_t offset = 0;
+  ssize_t nread;
+  union
+  {
+    Elf64_auxv_t a64[64];
+    Elf32_auxv_t a32[128];
+  } d;
+  do
+    {
+      eu_static_assert (sizeof d.a64 == sizeof d.a32);
+      nread = pread_retry (fd, d.a64, sizeof d.a64, offset);
+      if (nread < 0)
+	{
+	  int ret = errno;
+	  close (fd);
+	  return ret;
+	}
+      for (size_t a32i = 0; a32i < nread / sizeof d.a32[0]; a32i++)
+	{
+	  const Elf32_auxv_t *a32 = d.a32 + a32i;
+	  switch (a32->a_type)
+	  {
+	    case AT_SYSINFO_EHDR:
+	      sysinfo_ehdr32 = a32->a_un.a_val;
+	      break;
+	    case AT_PAGESZ:
+	      segment_align32 = a32->a_un.a_val;
+	      break;
+	  }
+	}
+      for (size_t a64i = 0; a64i < nread / sizeof d.a64[0]; a64i++)
+	{
+	  const Elf64_auxv_t *a64 = d.a64 + a64i;
+	  switch (a64->a_type)
+	  {
+	    case AT_SYSINFO_EHDR:
+	      sysinfo_ehdr64 = a64->a_un.a_val;
+	      break;
+	    case AT_PAGESZ:
+	      segment_align64 = a64->a_un.a_val;
+	      break;
+	  }
+	}
+      offset += nread;
+    }
+  while (nread == sizeof d.a64);
+
+  close (fd);
+
+  bool valid64 = sysinfo_ehdr64 != 0 || segment_align64 != dwfl->segment_align;
+  bool valid32 = sysinfo_ehdr32 != 0 || segment_align32 != dwfl->segment_align;
+
+  unsigned char pid_class = ELFCLASSNONE;
+  if (valid64 && valid32)
+    pid_class = get_pid_class (pid);
+
+  if (pid_class == ELFCLASS64 || (valid64 && ! valid32))
+    {
+      *sysinfo_ehdr = sysinfo_ehdr64;
+      dwfl->segment_align = segment_align64;
+      return 0;
+    }
+  if (pid_class == ELFCLASS32 || (! valid64 && valid32))
+    {
+      *sysinfo_ehdr = sysinfo_ehdr32;
+      dwfl->segment_align = segment_align32;
+      return 0;
+    }
+  return ENOEXEC;
+}
+
+static inline bool
+do_report (Dwfl *dwfl, char **plast_file, Dwarf_Addr low, Dwarf_Addr high)
+{
+  if (*plast_file != NULL)
+    {
+      Dwfl_Module *mod = INTUSE(dwfl_report_module) (dwfl, *plast_file,
+						     low, high);
+      free (*plast_file);
+      *plast_file = NULL;
+      if (unlikely (mod == NULL))
+        return true;
+    }
+  return false;
+}
+
+#define report() do_report(dwfl, &last_file, low, high)
+
+static int
+proc_maps_report (Dwfl *dwfl, FILE *f, GElf_Addr sysinfo_ehdr, pid_t pid)
+{
+  unsigned int last_dmajor = -1, last_dminor = -1;
+  uint64_t last_ino = -1;
+  char *last_file = NULL;
+  Dwarf_Addr low = 0, high = 0;
+
+  char *line = NULL;
+  size_t linesz;
+  ssize_t len;
+  while ((len = getline (&line, &linesz, f)) > 0)
+    {
+      if (line[len - 1] == '\n')
+	line[len - 1] = '\0';
+
+      Dwarf_Addr start, end, offset;
+      unsigned int dmajor, dminor;
+      uint64_t ino;
+      int nread = -1;
+      if (sscanf (line, "%" PRIx64 "-%" PRIx64 " %*s %" PRIx64
+		  " %x:%x %" PRIu64 " %n",
+		  &start, &end, &offset, &dmajor, &dminor, &ino, &nread) < 6
+	  || nread <= 0)
+	{
+	  free (line);
+	  free (last_file);
+	  return ENOEXEC;
+	}
+
+      /* If this is the special mapping AT_SYSINFO_EHDR pointed us at,
+	 report the last one and then this special one.  */
+      if (start == sysinfo_ehdr && start != 0)
+	{
+	  if (report ())
+	    {
+	    bad_report:
+	      free (line);
+	      return -1;
+	    }
+
+	  low = start;
+	  high = end;
+	  if (asprintf (&last_file, "[vdso: %d]", (int) pid) < 0
+	      || report ())
+	    goto bad_report;
+	}
+
+      char *file = line + nread + strspn (line + nread, " \t");
+      if (file[0] != '/' || (ino == 0 && dmajor == 0 && dminor == 0))
+	/* This line doesn't indicate a file mapping.  */
+	continue;
+
+      if (last_file != NULL
+	  && ino == last_ino && dmajor == last_dmajor && dminor == last_dminor)
+	{
+	  /* This is another portion of the same file's mapping.  */
+	  if (strcmp (last_file, file) != 0)
+	    {
+	      free (last_file);
+	      goto bad_report;
+	    }
+	  high = end;
+	}
+      else
+	{
+	  /* This is a different file mapping.  Report the last one.  */
+	  if (report ())
+	    goto bad_report;
+	  low = start;
+	  high = end;
+	  last_file = strdup (file);
+	  last_ino = ino;
+	  last_dmajor = dmajor;
+	  last_dminor = dminor;
+	}
+    }
+  free (line);
+
+  int result = ferror_unlocked (f) ? errno : feof_unlocked (f) ? 0 : ENOEXEC;
+
+  /* Report the final one.  */
+  bool lose = report ();
+
+  return result != 0 ? result : lose ? -1 : 0;
+}
+
+int
+dwfl_linux_proc_maps_report (Dwfl *dwfl, FILE *f)
+{
+  return proc_maps_report (dwfl, f, 0, 0);
+}
+INTDEF (dwfl_linux_proc_maps_report)
+
+int
+dwfl_linux_proc_report (Dwfl *dwfl, pid_t pid)
+{
+  if (dwfl == NULL)
+    return -1;
+
+  /* We'll notice the AT_SYSINFO_EHDR address specially when we hit it.  */
+  GElf_Addr sysinfo_ehdr = 0;
+  int result = grovel_auxv (pid, dwfl, &sysinfo_ehdr);
+  if (result != 0)
+    return result;
+
+  char *fname;
+  if (asprintf (&fname, PROCMAPSFMT, pid) < 0)
+    return ENOMEM;
+
+  FILE *f = fopen (fname, "r");
+  free (fname);
+  if (f == NULL)
+    return errno;
+
+  (void) __fsetlocking (f, FSETLOCKING_BYCALLER);
+
+  result = proc_maps_report (dwfl, f, sysinfo_ehdr, pid);
+
+  fclose (f);
+
+  return result;
+}
+INTDEF (dwfl_linux_proc_report)
+
+static ssize_t
+read_proc_memory (void *arg, void *data, GElf_Addr address,
+		  size_t minread, size_t maxread)
+{
+  const int fd = *(const int *) arg;
+
+  /* This code relies on the fact the Linux kernel accepts negative
+     offsets when seeking /dev/$$/mem files, as a special case. In
+     particular pread cannot be used here, because it will always
+     return EINVAL when passed a negative offset.  */
+
+  if (lseek (fd, (off_t) address, SEEK_SET) == -1)
+    return -1;
+
+  ssize_t nread = read (fd, data, maxread);
+
+  if (nread > 0 && (size_t) nread < minread)
+    nread = 0;
+  return nread;
+}
+
+extern Elf *elf_from_remote_memory (GElf_Addr ehdr_vma,
+				    GElf_Xword pagesize,
+				    GElf_Addr *loadbasep,
+				    ssize_t (*read_memory) (void *arg,
+							    void *data,
+							    GElf_Addr address,
+							    size_t minread,
+							    size_t maxread),
+				    void *arg);
+
+
+/* Dwfl_Callbacks.find_elf */
+
+int
+dwfl_linux_proc_find_elf (Dwfl_Module *mod __attribute__ ((unused)),
+			  void **userdata __attribute__ ((unused)),
+			  const char *module_name, Dwarf_Addr base,
+			  char **file_name, Elf **elfp)
+{
+  int pid = -1;
+  if (module_name[0] == '/')
+    {
+      /* When this callback is used together with dwfl_linux_proc_report
+	 then we might see mappings of special character devices.  Make
+	 sure we only open and return regular files.  Special devices
+	 might hang on open or read.  (deleted) files are super special.
+	 The image might come from memory if we are attached.  */
+      struct stat sb;
+      if (stat (module_name, &sb) == -1 || (sb.st_mode & S_IFMT) != S_IFREG)
+	{
+	  if (strcmp (strrchr (module_name, ' ') ?: "", " (deleted)") == 0)
+	    pid = INTUSE(dwfl_pid) (mod->dwfl);
+	  else
+	    return -1;
+	}
+
+      if (pid == -1)
+	{
+	  int fd = open (module_name, O_RDONLY);
+	  if (fd >= 0)
+	    {
+	      *file_name = strdup (module_name);
+	      if (*file_name == NULL)
+		{
+		  close (fd);
+		  return ENOMEM;
+		}
+	    }
+	  return fd;
+	}
+    }
+
+  if (pid != -1 || sscanf (module_name, "[vdso: %d]", &pid) == 1)
+    {
+      /* Special case for in-memory ELF image.  */
+
+      bool detach = false;
+      bool tid_was_stopped = false;
+      struct __libdwfl_pid_arg *pid_arg = __libdwfl_get_pid_arg (mod->dwfl);
+      if (pid_arg != NULL && ! pid_arg->assume_ptrace_stopped)
+	{
+	  /* If any thread is already attached we are fine.  Read
+	     through that thread.  It doesn't have to be the main
+	     thread pid.  */
+	  pid_t tid = pid_arg->tid_attached;
+	  if (tid != 0)
+	    pid = tid;
+	  else
+	    detach = __libdwfl_ptrace_attach (pid, &tid_was_stopped);
+	}
+
+      char *fname;
+      if (asprintf (&fname, PROCMEMFMT, pid) < 0)
+	goto detach;
+
+      int fd = open (fname, O_RDONLY);
+      free (fname);
+      if (fd < 0)
+	goto detach;
+
+      *elfp = elf_from_remote_memory (base, sysconf (_SC_PAGESIZE), NULL,
+				      &read_proc_memory, &fd);
+
+      close (fd);
+
+      *file_name = NULL;
+
+    detach:
+      if (detach)
+	__libdwfl_ptrace_detach (pid, tid_was_stopped);
+      return -1;
+    }
+
+  return -1;
+}
+INTDEF (dwfl_linux_proc_find_elf)
diff --git a/libdwfl/lzma.c b/libdwfl/lzma.c
new file mode 100644
index 0000000..3edfdc2
--- /dev/null
+++ b/libdwfl/lzma.c
@@ -0,0 +1,4 @@
+/* liblzma is pretty close to zlib and bzlib.  */
+
+#define LZMA
+#include "gzip.c"
diff --git a/libdwfl/offline.c b/libdwfl/offline.c
new file mode 100644
index 0000000..24e9e18
--- /dev/null
+++ b/libdwfl/offline.c
@@ -0,0 +1,349 @@
+/* Recover relocatibility for addresses computed from debug information.
+   Copyright (C) 2005-2009, 2012 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   Copyright (C) 2022 Google LLC
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libelfP.h"
+#include "libdwflP.h"
+#include <fcntl.h>
+
+/* Since dwfl_report_elf lays out the sections already, this will only be
+   called when the section headers of the debuginfo file are being
+   consulted instead, or for the section placed at 0.  With binutils
+   strip-to-debug, the symbol table is in the debuginfo file and relocation
+   looks there.  */
+int
+dwfl_offline_section_address (Dwfl_Module *mod,
+			      void **userdata __attribute__ ((unused)),
+			      const char *modname __attribute__ ((unused)),
+			      Dwarf_Addr base __attribute__ ((unused)),
+			      const char *secname __attribute__ ((unused)),
+			      Elf32_Word shndx,
+			      const GElf_Shdr *shdr __attribute__ ((unused)),
+			      Dwarf_Addr *addr)
+{
+  if (mod->e_type != ET_REL
+      || shdr->sh_addr != 0
+      || !(shdr->sh_flags & SHF_ALLOC)
+      || shndx == 0)
+    return -1;
+
+  if (mod->debug.elf == NULL)
+    /* We are only here because sh_addr is zero even though layout is complete.
+       The first section in the first file under -e is placed at 0.  */
+    return 0;
+
+  /* The section numbers might not match between the two files.
+     The best we can rely on is the order of SHF_ALLOC sections.  */
+
+  Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
+  Elf_Scn *scn = NULL;
+  uint_fast32_t skip_alloc = 0;
+  while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
+    {
+      assert (scn != NULL);
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (sh == NULL))
+	return -1;
+      if (sh->sh_flags & SHF_ALLOC)
+	++skip_alloc;
+    }
+
+  scn = NULL;
+  while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (main_shdr == NULL))
+	return -1;
+      if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
+	{
+	  assert (main_shdr->sh_flags == shdr->sh_flags);
+	  *addr = main_shdr->sh_addr;
+	  return 0;
+	}
+    }
+
+  /* This should never happen.  */
+  return -1;
+}
+INTDEF (dwfl_offline_section_address)
+
+/* Forward declarations.  */
+static Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
+				 const char *file_name, int fd, Elf *elf);
+static Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
+				     const char *file_name, int fd, Elf *elf,
+				     int (*predicate) (const char *module,
+						       const char *file));
+
+/* Report one module for an ELF file, or many for an archive.
+   Always consumes ELF and FD.  */
+static Dwfl_Module *
+process_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
+	      Elf *elf, int (*predicate) (const char *module,
+					  const char *file))
+{
+  switch (elf_kind (elf))
+    {
+    default:
+    case ELF_K_NONE:
+      __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
+      return NULL;
+
+    case ELF_K_ELF:
+      return process_elf (dwfl, name, file_name, fd, elf);
+
+    case ELF_K_AR:
+      return process_archive (dwfl, name, file_name, fd, elf, predicate);
+    }
+}
+
+/* Report the open ELF file as a module.  Always consumes ELF and FD.  */
+static Dwfl_Module *
+process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
+	     Elf *elf)
+{
+  Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
+					   dwfl->offline_next_address, true,
+					   false);
+  if (mod != NULL)
+    {
+      /* If this is an ET_EXEC file with fixed addresses, the address range
+	 it consumed may or may not intersect with the arbitrary range we
+	 will use for relocatable modules.  Make sure we always use a free
+	 range for the offline allocations.  If this module did use
+	 offline_next_address, it may have rounded it up for the module's
+	 alignment requirements.  */
+      if ((dwfl->offline_next_address >= mod->low_addr
+	   || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
+	  && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
+	dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
+
+      /* Don't keep the file descriptor around.  */
+      if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
+	{
+	  /* Grab the path in case we want to report this file as
+	     Dwarf later.  */
+	  mod->elfpath = __libdw_elfpath (mod->main.fd);
+	  close (mod->main.fd);
+	  mod->main.fd = -1;
+	}
+    }
+
+  return mod;
+}
+
+/* Always consumes MEMBER.  Returns elf_next result on success.
+   For errors returns ELF_C_NULL with *MOD set to null.  */
+static Elf_Cmd
+process_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
+			int (*predicate) (const char *module, const char *file),
+			int fd, Elf *member, Dwfl_Module **mod)
+{
+  const Elf_Arhdr *h = elf_getarhdr (member);
+  if (unlikely (h == NULL))
+    {
+      __libdwfl_seterrno (DWFL_E_LIBELF);
+    fail:
+      elf_end (member);
+      *mod = NULL;
+      return ELF_C_NULL;
+    }
+
+  if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//")
+      || !strcmp (h->ar_name, "/SYM64/"))
+    {
+    skip:;
+      /* Skip this and go to the next.  */
+      Elf_Cmd result = elf_next (member);
+      elf_end (member);
+      return result;
+    }
+
+  char *member_name;
+  if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
+    {
+    nomem:
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      elf_end (member);
+      *mod = NULL;
+      return ELF_C_NULL;
+    }
+
+  char *module_name = NULL;
+  if (name == NULL || name[0] == '\0')
+    name = h->ar_name;
+  else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
+    {
+      free (member_name);
+      goto nomem;
+    }
+  else
+    name = module_name;
+
+  if (predicate != NULL)
+    {
+      /* Let the predicate decide whether to use this one.  */
+      int want = (*predicate) (name, member_name);
+      if (want <= 0)
+	{
+	  free (member_name);
+	  free (module_name);
+	  if (unlikely (want < 0))
+	    {
+	      __libdwfl_seterrno (DWFL_E_CB);
+	      goto fail;
+	    }
+	  goto skip;
+	}
+    }
+
+  /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
+     though it's the same fd for all the members.
+     On module teardown we will close it only on the last Elf reference.  */
+  *mod = process_file (dwfl, name, member_name, fd, member, predicate);
+  free (member_name);
+  free (module_name);
+
+  if (*mod == NULL)
+    {
+      elf_end (member);
+      return ELF_C_NULL;
+    }
+
+  /* Advance the archive-reading offset for the next iteration.  */
+  return elf_next (member);
+}
+
+/* Report each member of the archive as its own module.  */
+static Dwfl_Module *
+process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
+		 Elf *archive,
+		 int (*predicate) (const char *module, const char *file))
+
+{
+  Dwfl_Module *mod = NULL;
+  /* elf_begin supports opening archives even with fd == -1 passed.  */
+  Elf *member = elf_begin (fd, archive->cmd, archive);
+  if (unlikely (member == NULL)) /* Empty archive.  */
+    {
+      __libdwfl_seterrno (DWFL_E_BADELF);
+      return NULL;
+    }
+
+  while (process_archive_member (dwfl, name, file_name, predicate,
+				 fd, member, &mod) != ELF_C_NULL)
+    member = elf_begin (fd, archive->cmd, archive);
+
+  /* We can drop the archive Elf handle even if we're still using members
+     in live modules.  When the last module's elf_end on a member returns
+     zero, that module will close FD.  If no modules survived the predicate,
+     we are all done with the file right here.  */
+  if (mod != NULL		/* If no modules, caller will clean up.  */
+      && elf_end (archive) == 0)
+    close (fd);
+
+  return mod;
+}
+
+Dwfl_Module *
+internal_function
+__libdwfl_report_offline (Dwfl *dwfl, const char *name,
+			  const char *file_name, int fd, bool closefd,
+			  int (*predicate) (const char *module,
+					    const char *file))
+{
+  Elf *elf;
+  Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true);
+  if (error != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (error);
+      return NULL;
+    }
+  Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
+  if (mod == NULL)
+    {
+      elf_end (elf);
+      if (closefd)
+	close (fd);
+    }
+  return mod;
+}
+
+Dwfl_Module *
+dwfl_report_offline (Dwfl *dwfl, const char *name,
+		     const char *file_name, int fd)
+{
+  if (dwfl == NULL)
+    return NULL;
+
+  bool closefd = false;
+  if (fd < 0)
+    {
+      closefd = true;
+      fd = open (file_name, O_RDONLY);
+      if (fd < 0)
+	{
+	  __libdwfl_seterrno (DWFL_E_ERRNO);
+	  return NULL;
+	}
+    }
+
+  return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
+}
+INTDEF (dwfl_report_offline)
+
+Dwfl_Module *
+dwfl_report_offline_memory (Dwfl *dwfl, const char *name,
+			    const char *file_name, char *data, size_t size)
+{
+  if (dwfl == NULL)
+    return NULL;
+
+  Elf *elf;
+  Dwfl_Error error = __libdw_open_elf_memory (data, size, &elf, true);
+  if (error != DWFL_E_NOERROR)
+    {
+      __libdwfl_seterrno (error);
+      return NULL;
+    }
+  /* It is ok to pass fd == -1 here, because libelf uses it as a value for
+     "no file opened" and supports working with files without fd, thanks to
+     the existence of the elf_memory function.  */
+  Dwfl_Module *mod = process_file (dwfl, name, file_name, -1, elf, NULL);
+  if (mod == NULL)
+    elf_end (elf);
+  return mod;
+}
+INTDEF (dwfl_report_offline_memory)
diff --git a/libdwfl/open.c b/libdwfl/open.c
new file mode 100644
index 0000000..43b29fa
--- /dev/null
+++ b/libdwfl/open.c
@@ -0,0 +1,225 @@
+/* Decompression support for libdwfl: zlib (gzip), bzlib (bzip2) or lzma (xz).
+   Copyright (C) 2009, 2016 Red Hat, Inc.
+   Copyright (C) 2022 Google LLC
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libelfP.h"
+#include "libdwflP.h"
+
+#if !USE_BZLIB
+# define __libdw_bunzip2(...)	DWFL_E_BADELF
+#endif
+
+#if !USE_LZMA
+# define __libdw_unlzma(...)	DWFL_E_BADELF
+#endif
+
+#if !USE_ZSTD
+# define __libdw_unzstd(...)	DWFL_E_BADELF
+#endif
+
+/* Consumes and replaces *ELF only on success.  */
+static Dwfl_Error
+decompress (int fd __attribute__ ((unused)), Elf **elf)
+{
+  Dwfl_Error error = DWFL_E_BADELF;
+  /* ELF cannot be decompressed, if there is no file descriptor.  */
+  if (fd == -1)
+    return error;
+  void *buffer = NULL;
+  size_t size = 0;
+
+  const off_t offset = (*elf)->start_offset;
+  void *const mapped = ((*elf)->map_address == NULL ? NULL
+			: (*elf)->map_address + offset);
+  const size_t mapped_size = (*elf)->maximum_size;
+  if (mapped_size == 0)
+    return error;
+
+  error = __libdw_gunzip (fd, offset, mapped, mapped_size, &buffer, &size);
+  if (error == DWFL_E_BADELF)
+    error = __libdw_bunzip2 (fd, offset, mapped, mapped_size, &buffer, &size);
+  if (error == DWFL_E_BADELF)
+    error = __libdw_unlzma (fd, offset, mapped, mapped_size, &buffer, &size);
+  if (error == DWFL_E_BADELF)
+    error = __libdw_unzstd (fd, offset, mapped, mapped_size, &buffer, &size);
+
+  if (error == DWFL_E_NOERROR)
+    {
+      if (unlikely (size == 0))
+	{
+	  error = DWFL_E_BADELF;
+	  free (buffer);
+	}
+      else
+	{
+	  Elf *memelf = elf_memory (buffer, size);
+	  if (memelf == NULL)
+	    {
+	      error = DWFL_E_LIBELF;
+	      free (buffer);
+	    }
+	  else
+	    {
+	      memelf->flags |= ELF_F_MALLOCED;
+	      elf_end (*elf);
+	      *elf = memelf;
+	    }
+	}
+    }
+  else
+    free (buffer);
+
+  return error;
+}
+
+static Dwfl_Error
+what_kind (int fd, Elf **elfp, Elf_Kind *kind, bool *may_close_fd)
+{
+  Dwfl_Error error = DWFL_E_NOERROR;
+  *kind = elf_kind (*elfp);
+  if (unlikely (*kind == ELF_K_NONE))
+    {
+      if (unlikely (*elfp == NULL))
+	error = DWFL_E_LIBELF;
+      else
+	{
+	  error = decompress (fd, elfp);
+	  if (error == DWFL_E_NOERROR)
+	    {
+	      *may_close_fd = true;
+	      *kind = elf_kind (*elfp);
+	    }
+	}
+    }
+  return error;
+}
+
+static Dwfl_Error
+libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
+		bool never_close_fd, bool bad_elf_ok, bool use_elfp)
+{
+  bool may_close_fd = false;
+
+  Elf *elf =
+      use_elfp ? *elfp : elf_begin (*fdp, ELF_C_READ_MMAP_PRIVATE, NULL);
+
+  Elf_Kind kind;
+  Dwfl_Error error = what_kind (*fdp, &elf, &kind, &may_close_fd);
+  if (error == DWFL_E_BADELF)
+    {
+      /* It's not an ELF file or a compressed file.
+	 See if it's an image with a header preceding the real file.  */
+
+      off_t offset = elf->start_offset;
+      error = __libdw_image_header (*fdp, &offset,
+				    (elf->map_address == NULL ? NULL
+				     : elf->map_address + offset),
+				    elf->maximum_size);
+      if (error == DWFL_E_NOERROR)
+	{
+	  /* Pure evil.  libelf needs some better interfaces.  */
+	  elf->kind = ELF_K_AR;
+	  elf->state.ar.elf_ar_hdr.ar_name = "libdwfl is faking you out";
+	  elf->state.ar.elf_ar_hdr.ar_size = elf->maximum_size - offset;
+	  elf->state.ar.offset = offset - sizeof (struct ar_hdr);
+	  Elf *subelf = elf_begin (-1, elf->cmd, elf);
+	  elf->kind = ELF_K_NONE;
+	  if (unlikely (subelf == NULL))
+	    error = DWFL_E_LIBELF;
+	  else
+	    {
+	      subelf->parent = NULL;
+	      subelf->flags |= elf->flags & (ELF_F_MMAPPED | ELF_F_MALLOCED);
+	      elf->flags &= ~(ELF_F_MMAPPED | ELF_F_MALLOCED);
+	      elf_end (elf);
+	      elf = subelf;
+	      error = what_kind (*fdp, &elf, &kind, &may_close_fd);
+	    }
+	}
+    }
+
+  if (error == DWFL_E_NOERROR
+      && kind != ELF_K_ELF
+      && !(archive_ok && kind == ELF_K_AR))
+    error = DWFL_E_BADELF;
+
+  /* This basically means, we keep a ELF_K_NONE Elf handle and return it.  */
+  if (bad_elf_ok && error == DWFL_E_BADELF)
+    error = DWFL_E_NOERROR;
+
+  if (error != DWFL_E_NOERROR)
+    {
+      elf_end (elf);
+      elf = NULL;
+    }
+
+  if (! never_close_fd
+      && error == DWFL_E_NOERROR ? may_close_fd : close_on_fail)
+    {
+      close (*fdp);
+      *fdp = -1;
+    }
+
+  *elfp = elf;
+  return error;
+}
+
+Dwfl_Error internal_function
+__libdw_open_file (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok)
+{
+  return libdw_open_elf (fdp, elfp, close_on_fail, archive_ok, false, false,
+			 false);
+}
+
+Dwfl_Error internal_function
+__libdw_open_elf_memory (char *data, size_t size, Elf **elfp, bool archive_ok)
+{
+  /* It is ok to use `fd == -1` here, because libelf uses it as a value for
+     "no file opened" and code supports working with this value, and also
+     `never_close_fd == false` is passed to prevent closing non-existent file.
+     The only caveat is in `decompress` method, which doesn't support
+     decompressing from memory, so reading compressed zImage using this method
+     won't work.  */
+  int fd = -1;
+  *elfp = elf_memory (data, size);
+  if (unlikely(*elfp == NULL))
+    {
+      return DWFL_E_LIBELF;
+    }
+  return libdw_open_elf (&fd, elfp, false, archive_ok, true, false, true);
+}
+
+Dwfl_Error internal_function
+__libdw_open_elf (int fd, Elf **elfp)
+{
+  return libdw_open_elf (&fd, elfp, false, true, true, true, false);
+}
diff --git a/libdwfl/relocate.c b/libdwfl/relocate.c
new file mode 100644
index 0000000..0497bd4
--- /dev/null
+++ b/libdwfl/relocate.c
@@ -0,0 +1,824 @@
+/* Relocate debug information.
+   Copyright (C) 2005-2011, 2014, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include "libelfP.h"
+#include "libdwflP.h"
+
+typedef uint8_t GElf_Byte;
+
+/* Adjust *VALUE to add the load address of the SHNDX section.
+   We update the section header in place to cache the result.  */
+
+Dwfl_Error
+internal_function
+__libdwfl_relocate_value (Dwfl_Module *mod, Elf *elf, size_t *shstrndx,
+			  Elf32_Word shndx, GElf_Addr *value)
+{
+  /* No adjustment needed for section zero, it is never loaded.
+     Handle it first, just in case the ELF file has strange section
+     zero flags set.  */
+  if (shndx == 0)
+    return DWFL_E_NOERROR;
+
+  Elf_Scn *refscn = elf_getscn (elf, shndx);
+  GElf_Shdr refshdr_mem, *refshdr = gelf_getshdr (refscn, &refshdr_mem);
+  if (refshdr == NULL)
+    return DWFL_E_LIBELF;
+
+  if (refshdr->sh_addr == 0 && (refshdr->sh_flags & SHF_ALLOC))
+    {
+      /* This is a loaded section.  Find its actual
+	 address and update the section header.  */
+
+      if (*shstrndx == SHN_UNDEF
+	  && unlikely (elf_getshdrstrndx (elf, shstrndx) < 0))
+	return DWFL_E_LIBELF;
+
+      const char *name = elf_strptr (elf, *shstrndx, refshdr->sh_name);
+      if (unlikely (name == NULL))
+	return DWFL_E_LIBELF;
+
+      if ((*mod->dwfl->callbacks->section_address) (MODCB_ARGS (mod),
+						    name, shndx, refshdr,
+						    &refshdr->sh_addr))
+	return CBFAIL;
+
+      if (refshdr->sh_addr == (Dwarf_Addr) -1l)
+	/* The callback indicated this section wasn't really loaded but we
+	   don't really care.  */
+	refshdr->sh_addr = 0;	/* Make no adjustment below.  */
+
+      /* Update the in-core file's section header to show the final
+	 load address (or unloadedness).  This serves as a cache,
+	 so we won't get here again for the same section.  */
+      if (likely (refshdr->sh_addr != 0)
+	  && unlikely (! gelf_update_shdr (refscn, refshdr)))
+	return DWFL_E_LIBELF;
+    }
+
+  if (refshdr->sh_flags & SHF_ALLOC)
+    /* Apply the adjustment.  */
+    *value += dwfl_adjusted_address (mod, refshdr->sh_addr);
+
+  return DWFL_E_NOERROR;
+}
+
+
+/* Cache used by relocate_getsym.  */
+struct reloc_symtab_cache
+{
+  Elf *symelf;
+  Elf_Data *symdata;
+  Elf_Data *symxndxdata;
+  Elf_Data *symstrdata;
+  size_t symshstrndx;
+  size_t strtabndx;
+};
+#define RELOC_SYMTAB_CACHE(cache)	\
+  struct reloc_symtab_cache cache =	\
+    { NULL, NULL, NULL, NULL, SHN_UNDEF, SHN_UNDEF }
+
+/* This is just doing dwfl_module_getsym, except that we must always use
+   the symbol table in RELOCATED itself when it has one, not MOD->symfile.  */
+static Dwfl_Error
+relocate_getsym (Dwfl_Module *mod,
+		 Elf *relocated, struct reloc_symtab_cache *cache,
+		 int symndx, GElf_Sym *sym, GElf_Word *shndx)
+{
+  if (cache->symdata == NULL)
+    {
+      if (mod->symfile == NULL || mod->symfile->elf != relocated)
+	{
+	  /* We have to look up the symbol table in the file we are
+	     relocating, if it has its own.  These reloc sections refer to
+	     the symbol table in this file, and a symbol table in the main
+	     file might not match.  However, some tools did produce ET_REL
+	     .debug files with relocs but no symtab of their own.  */
+	  Elf_Scn *scn = NULL;
+	  while ((scn = elf_nextscn (relocated, scn)) != NULL)
+	    {
+	      GElf_Shdr shdr_mem, *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  /* We need uncompressed data.  */
+		  if ((shdr->sh_type == SHT_SYMTAB
+		       || shdr->sh_type == SHT_SYMTAB_SHNDX)
+		      && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+		    if (elf_compress (scn, 0, 0) < 0)
+		      return DWFL_E_LIBELF;
+
+		  switch (shdr->sh_type)
+		    {
+		    default:
+		      continue;
+		    case SHT_SYMTAB:
+		      cache->symelf = relocated;
+		      cache->symdata = elf_getdata (scn, NULL);
+		      cache->strtabndx = shdr->sh_link;
+		      if (unlikely (cache->symdata == NULL))
+			return DWFL_E_LIBELF;
+		      break;
+		    case SHT_SYMTAB_SHNDX:
+		      cache->symxndxdata = elf_getdata (scn, NULL);
+		      if (unlikely (cache->symxndxdata == NULL))
+			return DWFL_E_LIBELF;
+		      break;
+		    }
+		}
+	      if (cache->symdata != NULL && cache->symxndxdata != NULL)
+		break;
+	    }
+	}
+      if (cache->symdata == NULL)
+	{
+	  /* We might not have looked for a symbol table file yet,
+	     when coming from __libdwfl_relocate_section.  */
+	  if (unlikely (mod->symfile == NULL)
+	      && unlikely (INTUSE(dwfl_module_getsymtab) (mod) < 0))
+	    return dwfl_errno ();
+
+	  /* The symbol table we have already cached is the one from
+	     the file being relocated, so it's what we need.  Or else
+	     this is an ET_REL .debug file with no .symtab of its own;
+	     the symbols refer to the section indices in the main file.  */
+	  cache->symelf = mod->symfile->elf;
+	  cache->symdata = mod->symdata;
+	  cache->symxndxdata = mod->symxndxdata;
+	  cache->symstrdata = mod->symstrdata;
+	}
+    }
+
+  if (unlikely (gelf_getsymshndx (cache->symdata, cache->symxndxdata,
+				  symndx, sym, shndx) == NULL))
+    return DWFL_E_LIBELF;
+
+  if (sym->st_shndx != SHN_XINDEX)
+    *shndx = sym->st_shndx;
+
+  switch (sym->st_shndx)
+    {
+    case SHN_ABS:
+    case SHN_UNDEF:
+      return DWFL_E_NOERROR;
+
+    case SHN_COMMON:
+      sym->st_value = 0;	/* Value is size, not helpful. */
+      return DWFL_E_NOERROR;
+    }
+
+  return __libdwfl_relocate_value (mod, cache->symelf, &cache->symshstrndx,
+				   *shndx, &sym->st_value);
+}
+
+/* Handle an undefined symbol.  We really only support ET_REL for Linux
+   kernel modules, and offline archives.  The behavior of the Linux module
+   loader is very simple and easy to mimic.  It only matches magically
+   exported symbols, and we match any defined symbols.  But we get the same
+   answer except when the module's symbols are undefined and would prevent
+   it from being loaded.  */
+static Dwfl_Error
+resolve_symbol (Dwfl_Module *referer, struct reloc_symtab_cache *symtab,
+		GElf_Sym *sym, GElf_Word shndx)
+{
+  /* First we need its name.  */
+  if (sym->st_name != 0)
+    {
+      if (symtab->symstrdata == NULL)
+	{
+	  /* Cache the strtab for this symtab.  */
+	  assert (referer->symfile == NULL
+		  || referer->symfile->elf != symtab->symelf);
+
+	  Elf_Scn *scn = elf_getscn (symtab->symelf, symtab->strtabndx);
+	  if (scn == NULL)
+	    return DWFL_E_LIBELF;
+
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    return DWFL_E_LIBELF;
+
+	  if (symtab->symshstrndx == SHN_UNDEF
+	      && elf_getshdrstrndx (symtab->symelf, &symtab->symshstrndx) < 0)
+	    return DWFL_E_LIBELF;
+
+	  const char *sname = elf_strptr (symtab->symelf, symtab->symshstrndx,
+					  shdr->sh_name);
+	  if (sname == NULL)
+	    return DWFL_E_LIBELF;
+
+	  /* If the section is already decompressed, that isn't an error.  */
+	  if (startswith (sname, ".zdebug"))
+	    elf_compress_gnu (scn, 0, 0);
+
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    if (elf_compress (scn, 0, 0) < 0)
+	      return DWFL_E_LIBELF;
+
+	  symtab->symstrdata = elf_getdata (scn, NULL);
+	  if (unlikely (symtab->symstrdata == NULL
+			|| symtab->symstrdata->d_buf == NULL))
+	    return DWFL_E_LIBELF;
+	}
+      if (unlikely (sym->st_name >= symtab->symstrdata->d_size))
+	return DWFL_E_BADSTROFF;
+
+      const char *name = symtab->symstrdata->d_buf;
+      name += sym->st_name;
+
+      for (Dwfl_Module *m = referer->dwfl->modulelist; m != NULL; m = m->next)
+	if (m != referer)
+	  {
+	    /* Get this module's symtab.
+	       If we got a fresh error reading the table, report it.
+	       If we just have no symbols in this module, no harm done.  */
+	    if (m->symdata == NULL
+		&& m->symerr == DWFL_E_NOERROR
+		&& INTUSE(dwfl_module_getsymtab) (m) < 0
+		&& m->symerr != DWFL_E_NO_SYMTAB)
+	      return m->symerr;
+
+	    for (size_t ndx = 1; ndx < m->syments; ++ndx)
+	      {
+		sym = gelf_getsymshndx (m->symdata, m->symxndxdata,
+					ndx, sym, &shndx);
+		if (unlikely (sym == NULL))
+		  return DWFL_E_LIBELF;
+		if (sym->st_shndx != SHN_XINDEX)
+		  shndx = sym->st_shndx;
+
+		/* We are looking for a defined global symbol with a name.  */
+		if (shndx == SHN_UNDEF || shndx == SHN_COMMON
+		    || GELF_ST_BIND (sym->st_info) == STB_LOCAL
+		    || sym->st_name == 0)
+		  continue;
+
+		/* Get this candidate symbol's name.  */
+		if (unlikely (sym->st_name >= m->symstrdata->d_size))
+		  return DWFL_E_BADSTROFF;
+		const char *n = m->symstrdata->d_buf;
+		n += sym->st_name;
+
+		/* Does the name match?  */
+		if (strcmp (name, n))
+		  continue;
+
+		/* We found it!  */
+		if (shndx == SHN_ABS) /* XXX maybe should apply bias? */
+		  return DWFL_E_NOERROR;
+
+		if (m->e_type != ET_REL)
+		  {
+		    sym->st_value = dwfl_adjusted_st_value (m, m->symfile->elf,
+							    sym->st_value);
+		    return DWFL_E_NOERROR;
+		  }
+
+		/* In an ET_REL file, the symbol table values are relative
+		   to the section, not to the module's load base.  */
+		size_t symshstrndx = SHN_UNDEF;
+		return __libdwfl_relocate_value (m, m->symfile->elf,
+						 &symshstrndx,
+						 shndx, &sym->st_value);
+	      }
+	  }
+    }
+
+  return DWFL_E_RELUNDEF;
+}
+
+/* Apply one relocation.  Returns true for any invalid data.  */
+static Dwfl_Error
+relocate (Dwfl_Module * const mod,
+          Elf * const relocated,
+          struct reloc_symtab_cache * const reloc_symtab,
+          Elf_Data * const tdata,
+          const GElf_Ehdr * const ehdr,
+          GElf_Addr offset,
+          const GElf_Sxword *addend,
+          int rtype,
+          int symndx)
+{
+    /* First see if this is a reloc we can handle.
+       If we are skipping it, don't bother resolving the symbol.  */
+
+    if (unlikely (rtype == 0))
+      /* In some odd situations, the linker can leave R_*_NONE relocs
+	 behind.  This is probably bogus ld -r behavior, but the only
+	 cases it's known to appear in are harmless: DWARF data
+	 referring to addresses in a section that has been discarded.
+	 So we just pretend it's OK without further relocation.  */
+      return DWFL_E_NOERROR;
+
+    int addsub = 0;
+    Elf_Type type = ebl_reloc_simple_type (mod->ebl, rtype, &addsub);
+    if (unlikely (type == ELF_T_NUM))
+      return DWFL_E_BADRELTYPE;
+
+    /* First, resolve the symbol to an absolute value.  */
+    GElf_Addr value;
+
+    if (symndx == STN_UNDEF)
+      /* When strip removes a section symbol referring to a
+	 section moved into the debuginfo file, it replaces
+	 that symbol index in relocs with STN_UNDEF.  We
+	 don't actually need the symbol, because those relocs
+	 are always references relative to the nonallocated
+	 debugging sections, which start at zero.  */
+      value = 0;
+    else
+      {
+	GElf_Sym sym;
+	GElf_Word shndx;
+	Dwfl_Error error = relocate_getsym (mod, relocated, reloc_symtab,
+					    symndx, &sym, &shndx);
+	if (unlikely (error != DWFL_E_NOERROR))
+	  return error;
+
+	if (shndx == SHN_UNDEF || shndx == SHN_COMMON)
+	  {
+	    /* Maybe we can figure it out anyway.  */
+	    error = resolve_symbol (mod, reloc_symtab, &sym, shndx);
+	    if (error != DWFL_E_NOERROR
+		&& !(error == DWFL_E_RELUNDEF && shndx == SHN_COMMON))
+	      return error;
+	  }
+
+	value = sym.st_value;
+      }
+
+    /* These are the types we can relocate.  */
+#define TYPES		DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);	\
+    DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);			\
+    DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
+    size_t size;
+    switch (type)
+      {
+#define DO_TYPE(NAME, Name)			\
+	case ELF_T_##NAME:			\
+	  if (addsub != 0 && addend == NULL)	\
+	    /* These do not make sense with SHT_REL.  */ \
+	    return DWFL_E_BADRELTYPE;		\
+	  size = sizeof (GElf_##Name);		\
+	break
+	TYPES;
+#undef DO_TYPE
+      default:
+	return DWFL_E_BADRELTYPE;
+      }
+
+    if (offset > tdata->d_size || tdata->d_size - offset < size)
+      return DWFL_E_BADRELOFF;
+
+#define DO_TYPE(NAME, Name) GElf_##Name Name;
+    union { TYPES; } tmpbuf;
+#undef DO_TYPE
+    Elf_Data tmpdata =
+      {
+	.d_type = type,
+	.d_buf = &tmpbuf,
+	.d_size = size,
+	.d_version = EV_CURRENT,
+      };
+    Elf_Data rdata =
+      {
+	.d_type = type,
+	.d_buf = tdata->d_buf + offset,
+	.d_size = size,
+	.d_version = EV_CURRENT,
+      };
+
+    /* XXX check for overflow? */
+    if (addend)
+      {
+	/* For the addend form, we have the value already.  */
+	value += *addend;
+	/* For ADD/SUB relocations we need to fetch the section
+	   contents.  */
+	if (addsub != 0)
+	  {
+	    Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
+					 ehdr->e_ident[EI_DATA]);
+	    if (d == NULL)
+	      return DWFL_E_LIBELF;
+	    assert (d == &tmpdata);
+	  }
+	switch (type)
+	  {
+#define DO_TYPE(NAME, Name)			\
+	    case ELF_T_##NAME:			\
+	      if (addsub != 0)			\
+		tmpbuf.Name += value * addsub;	\
+	      else				\
+		tmpbuf.Name = value;		\
+	    break
+	    TYPES;
+#undef DO_TYPE
+	  default:
+	    abort ();
+	  }
+      }
+    else
+      {
+	/* Extract the original value and apply the reloc.  */
+	Elf_Data *d = gelf_xlatetom (relocated, &tmpdata, &rdata,
+				     ehdr->e_ident[EI_DATA]);
+	if (d == NULL)
+	  return DWFL_E_LIBELF;
+	assert (d == &tmpdata);
+	switch (type)
+	  {
+#define DO_TYPE(NAME, Name)				\
+	    case ELF_T_##NAME:				\
+	      tmpbuf.Name += (GElf_##Name) value;	\
+	    break
+	    TYPES;
+#undef DO_TYPE
+	  default:
+	    abort ();
+	  }
+      }
+
+    /* Now convert the relocated datum back to the target
+       format.  This will write into rdata.d_buf, which
+       points into the raw section data being relocated.  */
+    Elf_Data *s = gelf_xlatetof (relocated, &rdata, &tmpdata,
+				 ehdr->e_ident[EI_DATA]);
+    if (s == NULL)
+      return DWFL_E_LIBELF;
+    assert (s == &rdata);
+
+    /* We have applied this relocation!  */
+    return DWFL_E_NOERROR;
+}
+
+static inline void
+check_badreltype (bool *first_badreltype,
+                  Dwfl_Module *mod,
+                  Dwfl_Error *result)
+{
+  if (*first_badreltype)
+    {
+       *first_badreltype = false;
+       if (ebl_get_elfmachine (mod->ebl) == EM_NONE)
+          /* This might be because ebl_openbackend failed to find
+             any libebl_CPU.so library.  Diagnose that clearly.  */
+          *result = DWFL_E_UNKNOWN_MACHINE;
+     }
+}
+
+static Dwfl_Error
+relocate_section (Dwfl_Module *mod, Elf *relocated, const GElf_Ehdr *ehdr,
+		  size_t shstrndx, struct reloc_symtab_cache *reloc_symtab,
+		  Elf_Scn *scn, GElf_Shdr *shdr,
+		  Elf_Scn *tscn, bool debugscn, bool partial)
+{
+  /* First, fetch the name of the section these relocations apply to.
+     Then try to decompress both relocation and target section.  */
+  GElf_Shdr tshdr_mem;
+  GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+  if (tshdr == NULL)
+    return DWFL_E_LIBELF;
+
+  const char *tname = elf_strptr (relocated, shstrndx, tshdr->sh_name);
+  if (tname == NULL)
+    return DWFL_E_LIBELF;
+
+  if (debugscn && ! ebl_debugscn_p (mod->ebl, tname))
+    /* This relocation section is not for a debugging section.
+       Nothing to do here.  */
+    return DWFL_E_NOERROR;
+
+  if (startswith (tname, ".zdebug"))
+    elf_compress_gnu (tscn, 0, 0);
+
+  if ((tshdr->sh_flags & SHF_COMPRESSED) != 0)
+    if (elf_compress (tscn, 0, 0) < 0)
+      return DWFL_E_LIBELF;
+
+  /* Reload Shdr in case section was just decompressed.  */
+  tshdr = gelf_getshdr (tscn, &tshdr_mem);
+  if (tshdr == NULL)
+    return DWFL_E_LIBELF;
+
+  if (unlikely (tshdr->sh_type == SHT_NOBITS)
+      || unlikely (tshdr->sh_size == 0))
+    /* No contents to relocate.  */
+    return DWFL_E_NOERROR;
+
+  const char *sname = elf_strptr (relocated, shstrndx, shdr->sh_name);
+  if (sname == NULL)
+    return DWFL_E_LIBELF;
+
+  if (startswith (sname, ".zdebug"))
+    elf_compress_gnu (scn, 0, 0);
+
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+    if (elf_compress (scn, 0, 0) < 0)
+      return DWFL_E_LIBELF;
+
+  /* Reload Shdr in case section was just decompressed.  */
+  GElf_Shdr shdr_mem;
+  shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    return DWFL_E_LIBELF;
+
+  /* Fetch the section data that needs the relocations applied.  */
+  Elf_Data *tdata = elf_rawdata (tscn, NULL);
+  if (tdata == NULL)
+    return DWFL_E_LIBELF;
+
+  /* If either the section that needs the relocation applied, or the
+     section that the relocations come from overlap one of the ehdrs,
+     shdrs or phdrs data then we refuse to do the relocations.  It
+     isn't illegal for ELF section data to overlap the header data,
+     but updating the (relocation) data might corrupt the in-memory
+     libelf headers causing strange corruptions or errors.
+
+     This is only an issue if the ELF is mmapped and the section data
+     comes from the mmapped region (is not malloced or decompressed).
+  */
+  if (relocated->map_address != NULL)
+    {
+      size_t ehsize = gelf_fsize (relocated, ELF_T_EHDR, 1, EV_CURRENT);
+      if (unlikely (shdr->sh_offset < ehsize
+		    || tshdr->sh_offset < ehsize))
+	return DWFL_E_BADELF;
+
+      GElf_Off shdrs_start = ehdr->e_shoff;
+      size_t shnums;
+      if (elf_getshdrnum (relocated, &shnums) < 0)
+	return DWFL_E_LIBELF;
+      /* Overflows will have been checked by elf_getshdrnum/get|rawdata.  */
+      size_t shentsize = gelf_fsize (relocated, ELF_T_SHDR, 1, EV_CURRENT);
+      GElf_Off shdrs_end = shdrs_start + shnums * shentsize;
+      if (unlikely (shdrs_start < shdr->sh_offset + shdr->sh_size
+		    && shdr->sh_offset < shdrs_end))
+	if ((scn->flags & ELF_F_MALLOCED) == 0)
+	  return DWFL_E_BADELF;
+
+      if (unlikely (shdrs_start < tshdr->sh_offset + tshdr->sh_size
+		    && tshdr->sh_offset < shdrs_end))
+	if ((tscn->flags & ELF_F_MALLOCED) == 0)
+	  return DWFL_E_BADELF;
+
+      GElf_Off phdrs_start = ehdr->e_phoff;
+      size_t phnums;
+      if (elf_getphdrnum (relocated, &phnums) < 0)
+	return DWFL_E_LIBELF;
+      if (phdrs_start != 0 && phnums != 0)
+	{
+	  /* Overflows will have been checked by elf_getphdrnum/get|rawdata.  */
+	  size_t phentsize = gelf_fsize (relocated, ELF_T_PHDR, 1, EV_CURRENT);
+	  GElf_Off phdrs_end = phdrs_start + phnums * phentsize;
+	  if (unlikely (phdrs_start < shdr->sh_offset + shdr->sh_size
+			&& shdr->sh_offset < phdrs_end))
+	    if ((scn->flags & ELF_F_MALLOCED) == 0)
+	      return DWFL_E_BADELF;
+
+	  if (unlikely (phdrs_start < tshdr->sh_offset + tshdr->sh_size
+			&& tshdr->sh_offset < phdrs_end))
+	    if ((tscn->flags & ELF_F_MALLOCED) == 0)
+	      return DWFL_E_BADELF;
+	}
+    }
+
+  /* Fetch the relocation section and apply each reloc in it.  */
+  Elf_Data *reldata = elf_getdata (scn, NULL);
+  if (reldata == NULL)
+    return DWFL_E_LIBELF;
+
+  Dwfl_Error result = DWFL_E_NOERROR;
+  bool first_badreltype = true;
+
+  size_t sh_entsize
+    = gelf_fsize (relocated, shdr->sh_type == SHT_REL ? ELF_T_REL : ELF_T_RELA,
+		  1, EV_CURRENT);
+  size_t nrels = shdr->sh_size / sh_entsize;
+  size_t complete = 0;
+  if (shdr->sh_type == SHT_REL)
+    for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
+      {
+	GElf_Rel rel_mem, *r = gelf_getrel (reldata, relidx, &rel_mem);
+	if (r == NULL)
+	  return DWFL_E_LIBELF;
+	result = relocate (mod, relocated, reloc_symtab, tdata, ehdr,
+			   r->r_offset, NULL,
+			   GELF_R_TYPE (r->r_info),
+			   GELF_R_SYM (r->r_info));
+	check_badreltype (&first_badreltype, mod, &result);
+	if (partial)
+	  switch (result)
+	    {
+	    case DWFL_E_NOERROR:
+	      /* We applied the relocation.  Elide it.  */
+	      memset (&rel_mem, 0, sizeof rel_mem);
+	      if (unlikely (gelf_update_rel (reldata, relidx, &rel_mem) == 0))
+		return DWFL_E_LIBELF;
+	      ++complete;
+	      break;
+	    case DWFL_E_BADRELTYPE:
+	    case DWFL_E_RELUNDEF:
+	      /* We couldn't handle this relocation.  Skip it.  */
+	      result = DWFL_E_NOERROR;
+	      break;
+	    default:
+	      break;
+	    }
+      }
+  else
+    for (size_t relidx = 0; !result && relidx < nrels; ++relidx)
+      {
+	GElf_Rela rela_mem, *r = gelf_getrela (reldata, relidx,
+					       &rela_mem);
+	if (r == NULL)
+	  return DWFL_E_LIBELF;
+	result = relocate (mod, relocated, reloc_symtab, tdata, ehdr,
+			   r->r_offset, &r->r_addend,
+			   GELF_R_TYPE (r->r_info),
+			   GELF_R_SYM (r->r_info));
+	check_badreltype (&first_badreltype, mod, &result);
+	if (partial)
+	  switch (result)
+	    {
+	    case DWFL_E_NOERROR:
+	      /* We applied the relocation.  Elide it.  */
+	      memset (&rela_mem, 0, sizeof rela_mem);
+	      if (unlikely (gelf_update_rela (reldata, relidx,
+					      &rela_mem) == 0))
+		return DWFL_E_LIBELF;
+	      ++complete;
+	      break;
+	    case DWFL_E_BADRELTYPE:
+	    case DWFL_E_RELUNDEF:
+	      /* We couldn't handle this relocation.  Skip it.  */
+	      result = DWFL_E_NOERROR;
+	      break;
+	    default:
+	      break;
+	    }
+      }
+
+  if (likely (result == DWFL_E_NOERROR))
+    {
+      if (!partial || complete == nrels)
+	/* Mark this relocation section as being empty now that we have
+	   done its work.  This affects unstrip -R, so e.g. it emits an
+	   empty .rela.debug_info along with a .debug_info that has
+	   already been fully relocated.  */
+	nrels = 0;
+      else if (complete != 0)
+	{
+	  /* We handled some of the relocations but not all.
+	     We've zeroed out the ones we processed.
+	     Now remove them from the section.  */
+
+	  size_t next = 0;
+	  if (shdr->sh_type == SHT_REL)
+	    for (size_t relidx = 0; relidx < nrels; ++relidx)
+	      {
+		GElf_Rel rel_mem;
+		GElf_Rel *r = gelf_getrel (reldata, relidx, &rel_mem);
+		if (unlikely (r == NULL))
+		  return DWFL_E_LIBELF;
+		if (r->r_info != 0 || r->r_offset != 0)
+		  {
+		    if (next != relidx)
+		      if (unlikely (gelf_update_rel (reldata, next, r) == 0))
+			return DWFL_E_LIBELF;
+		    ++next;
+		  }
+	      }
+	  else
+	    for (size_t relidx = 0; relidx < nrels; ++relidx)
+	      {
+		GElf_Rela rela_mem;
+		GElf_Rela *r = gelf_getrela (reldata, relidx, &rela_mem);
+		if (unlikely (r == NULL))
+		  return DWFL_E_LIBELF;
+		if (r->r_info != 0 || r->r_offset != 0 || r->r_addend != 0)
+		  {
+		    if (next != relidx)
+		      if (unlikely (gelf_update_rela (reldata, next, r) == 0))
+			return DWFL_E_LIBELF;
+		    ++next;
+		  }
+	      }
+	  nrels = next;
+	}
+
+      shdr->sh_size = reldata->d_size = nrels * sh_entsize;
+      if (unlikely (gelf_update_shdr (scn, shdr) == 0))
+	return DWFL_E_LIBELF;
+    }
+
+  return result;
+}
+
+Dwfl_Error
+internal_function
+__libdwfl_relocate (Dwfl_Module *mod, Elf *debugfile, bool debug)
+{
+  assert (mod->e_type == ET_REL);
+
+  GElf_Ehdr ehdr_mem;
+  const GElf_Ehdr *ehdr = gelf_getehdr (debugfile, &ehdr_mem);
+  if (ehdr == NULL)
+    return DWFL_E_LIBELF;
+
+  size_t d_shstrndx;
+  if (elf_getshdrstrndx (debugfile, &d_shstrndx) < 0)
+    return DWFL_E_LIBELF;
+
+  RELOC_SYMTAB_CACHE (reloc_symtab);
+
+  /* Look at each section in the debuginfo file, and process the
+     relocation sections for debugging sections.  */
+  Dwfl_Error result = DWFL_E_NOERROR;
+  Elf_Scn *scn = NULL;
+  while (result == DWFL_E_NOERROR
+	 && (scn = elf_nextscn (debugfile, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (shdr == NULL))
+	return DWFL_E_LIBELF;
+
+      if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+	  && shdr->sh_size != 0)
+	{
+	  /* It's a relocation section.  */
+
+	  Elf_Scn *tscn = elf_getscn (debugfile, shdr->sh_info);
+	  if (unlikely (tscn == NULL))
+	    result = DWFL_E_LIBELF;
+	  else
+	    result = relocate_section (mod, debugfile, ehdr, d_shstrndx,
+				       &reloc_symtab, scn, shdr, tscn,
+				       debug, true /* partial always OK. */);
+	}
+    }
+
+  return result;
+}
+
+Dwfl_Error
+internal_function
+__libdwfl_relocate_section (Dwfl_Module *mod, Elf *relocated,
+			    Elf_Scn *relocscn, Elf_Scn *tscn, bool partial)
+{
+  GElf_Ehdr ehdr_mem;
+  GElf_Shdr shdr_mem;
+
+  RELOC_SYMTAB_CACHE (reloc_symtab);
+
+  size_t shstrndx;
+  if (elf_getshdrstrndx (relocated, &shstrndx) < 0)
+    return DWFL_E_LIBELF;
+
+  Dwfl_Error result = __libdwfl_module_getebl (mod);
+  if (unlikely (result != DWFL_E_NOERROR))
+    return result;
+
+  GElf_Ehdr *ehdr = gelf_getehdr (relocated, &ehdr_mem);
+  if (unlikely (ehdr == NULL))
+    return DWFL_E_LIBELF;
+
+  GElf_Shdr *shdr = gelf_getshdr (relocscn, &shdr_mem);
+  if (unlikely (shdr == NULL))
+    return DWFL_E_LIBELF;
+
+  return relocate_section (mod, relocated, ehdr, shstrndx, &reloc_symtab,
+			   relocscn, shdr, tscn, false, partial);
+}
diff --git a/libdwfl/segment.c b/libdwfl/segment.c
new file mode 100644
index 0000000..f6a3e84
--- /dev/null
+++ b/libdwfl/segment.c
@@ -0,0 +1,330 @@
+/* Manage address space lookup table for libdwfl.
+   Copyright (C) 2008, 2009, 2010, 2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwflP.h"
+
+GElf_Addr
+internal_function
+__libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
+{
+  if (dwfl->segment_align > 1)
+    start &= -dwfl->segment_align;
+  return start;
+}
+
+GElf_Addr
+internal_function
+__libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
+{
+  if (dwfl->segment_align > 1)
+    end = (end + dwfl->segment_align - 1) & -dwfl->segment_align;
+  return end;
+}
+
+static bool
+insert (Dwfl *dwfl, size_t i, GElf_Addr start, GElf_Addr end, int segndx)
+{
+  bool need_start = (i == 0 || dwfl->lookup_addr[i - 1] != start);
+  bool need_end = (i + 1 >= dwfl->lookup_elts
+		   || dwfl->lookup_addr[i + 1] != end);
+  size_t need = need_start + need_end;
+  if (need == 0)
+    return false;
+
+  if (dwfl->lookup_alloc - dwfl->lookup_elts < need)
+    {
+      size_t n = dwfl->lookup_alloc == 0 ? 16 : dwfl->lookup_alloc * 2;
+      GElf_Addr *naddr = realloc (dwfl->lookup_addr, sizeof naddr[0] * n);
+      if (unlikely (naddr == NULL))
+	return true;
+      int *nsegndx = realloc (dwfl->lookup_segndx, sizeof nsegndx[0] * n);
+      if (unlikely (nsegndx == NULL))
+	{
+	  if (naddr != dwfl->lookup_addr)
+	    free (naddr);
+	  return true;
+	}
+      dwfl->lookup_alloc = n;
+      dwfl->lookup_addr = naddr;
+      dwfl->lookup_segndx = nsegndx;
+
+      if (dwfl->lookup_module != NULL)
+	{
+	  /* Make sure this array is big enough too.  */
+	  Dwfl_Module **old = dwfl->lookup_module;
+	  dwfl->lookup_module = realloc (dwfl->lookup_module,
+					 sizeof dwfl->lookup_module[0] * n);
+	  if (unlikely (dwfl->lookup_module == NULL))
+	    {
+	      free (old);
+	      return true;
+	    }
+	}
+    }
+
+  if (unlikely (i < dwfl->lookup_elts))
+    {
+      const size_t move = dwfl->lookup_elts - i;
+      memmove (&dwfl->lookup_addr[i + need], &dwfl->lookup_addr[i],
+	       move * sizeof dwfl->lookup_addr[0]);
+      memmove (&dwfl->lookup_segndx[i + need], &dwfl->lookup_segndx[i],
+	       move * sizeof dwfl->lookup_segndx[0]);
+      if (dwfl->lookup_module != NULL)
+	memmove (&dwfl->lookup_module[i + need], &dwfl->lookup_module[i],
+		 move * sizeof dwfl->lookup_module[0]);
+    }
+
+  if (need_start)
+    {
+      dwfl->lookup_addr[i] = start;
+      dwfl->lookup_segndx[i] = segndx;
+      if (dwfl->lookup_module != NULL)
+	dwfl->lookup_module[i] = NULL;
+      ++i;
+    }
+  else
+    dwfl->lookup_segndx[i - 1] = segndx;
+
+  if (need_end)
+    {
+      dwfl->lookup_addr[i] = end;
+      dwfl->lookup_segndx[i] = -1;
+      if (dwfl->lookup_module != NULL)
+	dwfl->lookup_module[i] = NULL;
+    }
+
+  dwfl->lookup_elts += need;
+
+  return false;
+}
+
+static int
+lookup (Dwfl *dwfl, GElf_Addr address, int hint)
+{
+  if (hint >= 0
+      && address >= dwfl->lookup_addr[hint]
+      && ((size_t) hint + 1 == dwfl->lookup_elts
+	  || address < dwfl->lookup_addr[hint + 1]))
+    return hint;
+
+  /* Do binary search on the array indexed by module load address.  */
+  size_t l = 0, u = dwfl->lookup_elts;
+  while (l < u)
+    {
+      size_t idx = (l + u) / 2;
+      if (address < dwfl->lookup_addr[idx])
+	u = idx;
+      else
+	{
+	  l = idx + 1;
+	  if (l == dwfl->lookup_elts || address < dwfl->lookup_addr[l])
+	    return idx;
+	}
+    }
+
+  return -1;
+}
+
+static bool
+reify_segments (Dwfl *dwfl)
+{
+  int hint = -1;
+  int highest = -1;
+  bool fixup = false;
+  for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
+    if (! mod->gc)
+      {
+	const GElf_Addr start = __libdwfl_segment_start (dwfl, mod->low_addr);
+	const GElf_Addr end = __libdwfl_segment_end (dwfl, mod->high_addr);
+	bool resized = false;
+
+	int idx = lookup (dwfl, start, hint);
+	if (unlikely (idx < 0))
+	  {
+	    /* Module starts below any segment.  Insert a low one.  */
+	    if (unlikely (insert (dwfl, 0, start, end, -1)))
+	      return true;
+	    idx = 0;
+	    resized = true;
+	  }
+	else if (dwfl->lookup_addr[idx] > start)
+	  {
+	    /* The module starts in the middle of this segment.  Split it.  */
+	    if (unlikely (insert (dwfl, idx + 1, start, end,
+				  dwfl->lookup_segndx[idx])))
+	      return true;
+	    ++idx;
+	    resized = true;
+	  }
+	else if (dwfl->lookup_addr[idx] < start)
+	  {
+	    /* The module starts past the end of this segment.
+	       Add a new one.  */
+	    if (unlikely (insert (dwfl, idx + 1, start, end, -1)))
+	      return true;
+	    ++idx;
+	    resized = true;
+	  }
+
+	if ((size_t) idx + 1 < dwfl->lookup_elts
+	    && end < dwfl->lookup_addr[idx + 1])
+	  {
+	    /* The module ends in the middle of this segment.  Split it.  */
+	    if (unlikely (insert (dwfl, idx + 1,
+				  end, dwfl->lookup_addr[idx + 1], -1)))
+	      return true;
+	    resized = true;
+	  }
+
+	if (dwfl->lookup_module == NULL)
+	  {
+	    dwfl->lookup_module = calloc (dwfl->lookup_alloc,
+					  sizeof dwfl->lookup_module[0]);
+	    if (unlikely (dwfl->lookup_module == NULL))
+	      return true;
+	  }
+
+	/* Cache a backpointer in the module.  */
+	mod->segment = idx;
+
+	/* Put MOD in the table for each segment that's inside it.  */
+	do
+	  dwfl->lookup_module[idx++] = mod;
+	while ((size_t) idx < dwfl->lookup_elts
+	       && dwfl->lookup_addr[idx] < end);
+	assert (dwfl->lookup_module[mod->segment] == mod);
+
+	if (resized && idx - 1 >= highest)
+	  /* Expanding the lookup tables invalidated backpointers
+	     we've already stored.  Reset those ones.  */
+	  fixup = true;
+
+	highest = idx - 1;
+	hint = (size_t) idx < dwfl->lookup_elts ? idx : -1;
+      }
+
+  if (fixup)
+    /* Reset backpointer indices invalidated by table insertions.  */
+    for (size_t idx = 0; idx < dwfl->lookup_elts; ++idx)
+      if (dwfl->lookup_module[idx] != NULL)
+	dwfl->lookup_module[idx]->segment = idx;
+
+  return false;
+}
+
+int
+dwfl_addrsegment (Dwfl *dwfl, Dwarf_Addr address, Dwfl_Module **mod)
+{
+  if (unlikely (dwfl == NULL))
+    return -1;
+
+  if (unlikely (dwfl->lookup_module == NULL)
+      && mod != NULL
+      && unlikely (reify_segments (dwfl)))
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return -1;
+    }
+
+  int idx = lookup (dwfl, address, -1);
+  if (likely (mod != NULL))
+    {
+      if (unlikely (idx < 0) || unlikely (dwfl->lookup_module == NULL))
+	*mod = NULL;
+      else
+	{
+	  *mod = dwfl->lookup_module[idx];
+
+	  /* If this segment does not have a module, but the address is
+	     the upper boundary of the previous segment's module, use that.  */
+	  if (*mod == NULL && idx > 0 && dwfl->lookup_addr[idx] == address)
+	    {
+	      *mod = dwfl->lookup_module[idx - 1];
+	      if (*mod != NULL && (*mod)->high_addr != address)
+		*mod = NULL;
+	    }
+	}
+    }
+
+  if (likely (idx >= 0))
+    /* Translate internal segment table index to user segment index.  */
+    idx = dwfl->lookup_segndx[idx];
+
+  return idx;
+}
+INTDEF (dwfl_addrsegment)
+
+int
+dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias,
+		     const void *ident)
+{
+  /* This was previously used for coalescing segments, but it was buggy since
+     day one.  We don't use it anymore.  */
+  (void)ident;
+
+  if (dwfl == NULL)
+    return -1;
+
+  if (ndx < 0)
+    ndx = dwfl->next_segndx;
+
+  if (phdr->p_align > 1 && (dwfl->segment_align <= 1 ||
+			    phdr->p_align < dwfl->segment_align))
+    dwfl->segment_align = phdr->p_align;
+
+  if (unlikely (dwfl->lookup_module != NULL))
+    {
+      free (dwfl->lookup_module);
+      dwfl->lookup_module = NULL;
+    }
+
+  GElf_Addr start = __libdwfl_segment_start (dwfl, bias + phdr->p_vaddr);
+  GElf_Addr end = __libdwfl_segment_end (dwfl,
+					 bias + phdr->p_vaddr + phdr->p_memsz);
+
+  /* Normally just appending keeps us sorted.  */
+
+  size_t i = dwfl->lookup_elts;
+  while (i > 0 && unlikely (start < dwfl->lookup_addr[i - 1]))
+    --i;
+
+  if (unlikely (insert (dwfl, i, start, end, ndx)))
+    {
+      __libdwfl_seterrno (DWFL_E_NOMEM);
+      return -1;
+    }
+
+  dwfl->next_segndx = ndx + 1;
+
+  return ndx;
+}
+INTDEF (dwfl_report_segment)
diff --git a/libdwfl/zstd.c b/libdwfl/zstd.c
new file mode 100644
index 0000000..dc4d523
--- /dev/null
+++ b/libdwfl/zstd.c
@@ -0,0 +1,4 @@
+/* libzstd is pretty close to zlib and bzlib.  */
+
+#define ZSTD
+#include "gzip.c"
diff --git a/libebl/ChangeLog b/libebl/ChangeLog
new file mode 100644
index 0000000..519087d
--- /dev/null
+++ b/libebl/ChangeLog
@@ -0,0 +1,1366 @@
+2022-12-21  Shahab Vahedi  <shahab@synopsys.email>
+
+	* eblopenbackend.c (arc_init): New function declaration.
+	(machines): Add entry for arc.
+
+2022-12-02  Hengqi Chen  <hengqi.chen@gmail.com>
+
+	* eblopenbackend.c (machines): Add entries for LoongArch.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* eblclosebackend.c: Remove dlfcn.h include.
+	* eblopenbackend.c: Likewise.
+
+2022-08-08  Andreas Schwab  <schwab@suse.de>
+
+	* ebldynamictagname.c (ebl_dynamic_tag_name): Handle DT_RELRSZ,
+	DT_RELR, DT_RELRENT.
+
+2022-06-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblopenbackend.c (default_machine_flag_name): Add original flag
+	as first parameter.
+	* ebl-hooks.h (machine_flag_name): Ditto.
+	* eblmachineflagname.c (ebl_machine_flag_name): Modernize, use bool
+	for first.  Pass original flag value to machine_flag_name
+	callback as well.  Add space after comma in printed list.
+	Fix appending strings provided by callback.
+
+2021-12-21  Luca Boccassi  <bluca@debian.org>
+
+	* eblobjnote.c (ebl_object_note): Handle NT_FDO_PACKAGING_METADATA.
+	* eblobjnotetypename.c (ebl_object_note_type_name): Likewise.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* eblopenbackend.c (openbackend): Remove cast of calloc return value.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* eblobjnotetypename.c (ebl_object_note_type_name): Use startswith.
+	* eblopenbackend.c (default_debugscn_p): Likewise.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* libeblP.h (_): Remove.
+
+2020-12-15  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* eblbackendname.c (ebl_backend_name): Replace gettext(...) with _(...).
+	* eblcorenotetypename.c (ebl_core_note_type_name): Likewise.
+	* ebldynamictagname.c (ebl_dynamic_tag_name): Likewise.
+	* eblobjnote.c (ebl_object_note): Likewise.
+	* eblobjnotetypename.c (ebl_object_note_type_name): Likewise.
+	* eblosabiname.c (ebl_osabi_name): Likewise.
+	* eblsectionname.c (ebl_section_name): Likewise.
+	* eblsectiontypename.c (ebl_section_type_name): Likewise.
+	* eblsegmenttypename.c (ebl_segment_type_name): Likewise.
+	* eblsymbolbindingname.c (ebl_symbol_binding_name): Likewise.
+	* eblsymboltypename.c (ebl_symbol_type_name): Likewise.
+
+2020-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* eblopenbackend.c (tilegx_init): Removed.
+	(machines): Set init to NULL for tilegx.
+
+2020-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (libebl_a_SOURCES): Remove ebl_syscall_abi.c.
+	* ebl-hooks.h (syscall_abi): Remove.
+	* ebl_syscall_abi.c: Delete.
+	* eblopenbackend.c (default_syscall_abi): Remove.
+	(fill_defaults): Remove syscall_abi assignment.
+	* libebl.h (ebl_syscall_abi): Remove.
+
+2020-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnote.c (ebl_object_note): For EM_AARCH64 handle BTI and PAC
+	in GNU_PROPERTY_AARCH64_FEATURE_1_AND.
+
+2020-07-19  Mark Wielaard  <mark@klomp.org>
+
+	* libebl.h: Only typedef Ebl if _LIBASM_H is undefined.
+
+2020-06-10  Mark Wielaard  <mark@klomp.org>
+
+	* eblopenbackend.c (i386_init, sh_init, x86_64_init, ia64_init,
+	alpha_init, arm_init, aarch64_init, sparc_init, ppc_init,
+	ppc64_init, s390_init, tilegx_init, m68k_init, bpf_init,
+	riscv_init, csky_init): Adjust signature.
+	(openbackend): Call init without sizeof(Ebl).
+	* libeblP.h (ebl_bhinit_t): Adjust signature.
+
+2020-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* eblsegmenttypename.c (ebl_segment_type_name): Remove
+	PT_GNU_PROPERTY define.
+
+2020-04-17  Mark Wielaard  <mark@klomp.org>
+
+	* eblopenbackend.c (default_debugscn_p): Handle .gnu.debuglto_
+	prefix.
+
+2020-02-08  Mark Wielaard  <mark@klomp.org>
+
+	* eblsegmenttypename.c (ebl_segment_type_name): Handle
+	PT_GNU_PROPERTY.
+
+2019-08-29  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (noinst_LIBRARIES): Add libebl.a.
+	(noinst_HEADERS): Add libebl.h.
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Make libebl.a non-PIC by default.
+	Add libebl_pic.a.
+	Remove LIBEBL_SUBDIR definition.
+	(gen_SOURCES): Remove.
+	* eblopenbackend.c (machines): Replace dsoname with init callback.
+	(try_dlopen): Remove.
+	(openbackend): Use machine callback instead of try_dlopen().
+	Don't assign result->dlhandle.
+	* eblclosebackend.c (ebl_closebackend): Remove dlclose() call.
+
+2019-04-29 Mao Han <han_mao@c-sky.com>
+
+	* eblopenbackend.c: Add C-SKY.
+
+2019-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* eblopenbackend.c (try_dlopen): Remove result->name check.
+	(openbackend): Remove result->name assignment.
+	(struct ebl): Remove name.
+
+2019-05-30  Mark Wielaard  <mark@klomp.org>
+
+	* eblopenbackend.c (try_dlopen): New function extracted from
+	openbackend.
+	(openbackend): Replace ORIGINDIR define with BINORIGINDIR and
+	LIBORIGINDIR defines. Use tryopen to open backend in bin origin
+	path, lib origin path and without an explicit path.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* eblsymbolbindingname.c (ebl_symbol_binding_name): Check ebl is
+	not NULL for STB_GNU_UNIQUE.
+	* eblsymboltypename.c (ebl_symbol_type_name): Check ebl is not
+	NULL for STT_GNU_IFUNC.
+
+2019-01-29  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnote.c (ebl_object_note): Check pr_datasz padding doesn't
+	overflow descsz.
+
+2019-01-16  Mark Wielaard  <mark@klomp.org>
+
+	* libebl.h (ebl_core_note): Add desc as argument.
+	* eblcorenote.c (ebl_core_note): Take desc as an argument, check
+	it contains a zero terminated string if it is an NT_PLATFORM note.
+
+2019-01-16  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnte.c (ebl_object_note): Check pr_datasz isn't too large.
+
+2018-12-02  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnte.c (ebl_object_note): For GNU_PROPERTY_STACK_SIZE use
+	an Elf32_Addr or Elf64_Addr to read and print the size.
+
+2018-11-15  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnotetypename.c (ebl_object_note_type_name): Don't update
+	w, t and len unnecessarily.
+
+2018-11-12  Mark Wielaard  <mark@klomp.org>
+
+	* libebl.h (ebl_object_note): Add new argument namesz.
+	* eblobjnote.c (ebl_object_note): Likewise and handle GNU Build
+	Attribute notes.
+	* eblobjnotetypename.c (ebl_object_note_type_name): Handle GNU
+	Build Attribute notes.
+
+2018-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnote.c (ebl_object_note): Recognize NT_VERSION with zero
+	descriptor. Add explicit "GNU" name check.
+	* eblobjnotetypename.c (ebl_object_note_type_name): Add extra
+	argument descsz. Recognize NT_VERSION using descsz. With "GNU"
+	name it is  NT_GNU_ABI_TAG.
+	* libebl.h (ebl_object_note_type_name): Add extra argument descsz.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* eblobjnote.c (ebl_object_note): Handle NT_GNU_PROPERTY_TYPE_0.
+	* eblobjnotetypename.c (ebl_object_note_type_name): Add
+	GNU_PROPERTY_TYPE_0.
+
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+	* ebl-hooks.h (EBLHOOK(reloc_simple_type)): Add third parameter.
+	* libebl.h (ebl_reloc_simple_type): Likewise.
+	* eblopenbackend.c (default_reloc_simple_type): Likewise.
+	* eblrelocsimpletype.c (ebl_reloc_simple_type): Pass it down.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* eblsectionstripp.c (ebl_section_strip_p): Drop ehdr argument.
+	Use elf_getshdrstrndx.
+	* libebl.h (ebl_section_strip_p): Drop ehdr argument.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* ebl-hooks.h (check_special_symbol): Drop ehdr argument.
+	* ebl_check_special_symbol.c (ebl_check_special_symbol): Likewise.
+	* eblopenbackend.c (default_check_special_symbol): Likewise.
+	* libebl.h (ebl_check_special_symbol): Likewise.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* eblopenbackend.c: Remove error.h include.
+
+2018-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* eblopenbackend.c (default_debugscn_p): Add new DWARF5 sections
+	.debug_addr, .debug_line_str, .debug_loclists, .debug_names,
+	.debug_rnglists and .debug_str_offsets.
+
+2018-04-19  Andreas Schwab  <schwab@suse.de>
+
+	* eblopenbackend.c (machines): Add entries for RISC-V.
+
+2018-03-16  Mark Wielaard  <mark@klomp.org>
+
+	* ebldynamictagname.c (ebl_dynamic_tag_name): Add SYMTAB_SHNDX to
+	stdtags. Add a eu_static_assert to make sure stdtags contains all
+	DT_NUM entries.
+
+2018-02-21  Mark Wielaard  <mark@klomp.org>
+
+	* eblcheckreloctargettype.c (ebl_check_reloc_target_type): Accept
+	SHT_NOTE.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* eblobjnote.c (ebl_object_note): Use FALLTHROUGH macro instead of
+	comment.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Use fpic_CFLAGS.
+
+2017-07-19  Gustavo Romero <gromero@linux.vnet.ibm.com>
+
+	* eblcorenotetypename.c: Add ppc64 HTM SPRs note as known type.
+
+2017-07-20  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (gen_SOURCES): Add ebl_data_marker_symbol.c.
+	* ebl-hooks.h (data_marker_symbol): New hook.
+	* ebl_data_marker_symbol.c: New file.
+	* eblopenbackend.c (default_data_marker_symbol): New function.
+	(fill_defaults): Add default_data_marker_symbol.
+	* libebl.h (ebl_data_marker_symbol): New function.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libebl.h: Use __pure_attribute__.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* eblmachineflagname.c: Include system.h.
+	* eblopenbackend.c: Likewise.
+
+2016-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Remove eblstrtab.c.
+	* eblstrtab.c: Removed.
+	* libebl.h (Ebl_Strtab): Removed.
+	(Ebl_Strent): Removed.
+	(ebl_strtabinit): Removed.
+	(ebl_strtabfree): Removed.
+	(ebl_strtabadd): Removed.
+	(ebl_strtabfinalize): Removed.
+	(ebl_strtaboffset): Removed.
+	(ebl_string): Removed.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Remove eblobjecttypename.c,
+	eblshflagscombine.c, eblwstrtab.c and eblgstrtab.c.
+	* ebl-hooks.h (object_type_name): Removed.
+	(sh_flags_combine): Likewise.
+	* eblgstrtab.c: Removed.
+	* eblobjecttypename.c: Removed.
+	* eblopenbackend.c (default_object_type_name): Removed.
+	(default_sh_flags_combine): Likewise.
+	(fill_defaults): Removed object_type_name and sh_flags_combine.
+	* eblshflagscombine.c: Removed.
+	* eblwstrtab.c: Removed.
+	* libebl.h (ebl_object_type_name): Removed.
+	(ebl_sh_flags_combine): Likewise.
+	(ebl_wstrtab*): Removed.
+	(ebl_gstrtab*): Likewise.
+
+2016-06-28  Richard Henderson <rth@redhat.com>
+
+	* ebl-hooks.h (EBLHOOK(disasm)): Add ebl parameter.
+	* eblopenbackend.c (machines): Add EM_BPF entry.
+
+2016-05-20  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* eblopenbackend.c (machines) [EM_68K]: Set class and data.
+
+2016-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* eblobjnotetypename.c (ebl_object_note_type_name): Check name is
+	"Go" and use new goknowntypes then. Otherwise check name is not
+	"GNU" and return "unknown".
+
+2016-01-09  Mark Wielaard  <mjw@redhat.com>
+
+	* eblobjnote.c (ebl_object_note): Add brackets around if statement
+	body.
+
+2015-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* eblopenbackend.c (default_debugscn_p): Also match .zdebug sections.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* libebl.h: Prototype for ebl_ra_offset.
+	* eblabicfi.c (ebl_ra_offset): New function.
+	* libeblP.h (struct ebl): new field ra_offset;
+
+2015-09-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* Makefile.am (AM_CFLAGS): Use -fPIC instead of -fpic to avoid
+	relocation overflows in some platforms.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* *.c: Remove old-style function definitions.
+
+2015-09-09  Chih-Hung Hsieh  <chh@google.com>
+
+	* ebldwarftoregno.c (ebl_dwarf_to_regno): Remove redundant NULL tests
+	on parameters declared with __nonnull_attribute__.
+	* eblinitreg.c (ebl_frame_nregs): Likewise.
+	* eblnormalizepc.c (ebl_normalize_pc): Likewise.
+	* eblunwind.c (ebl_unwind): Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* eblopenbackend.c (ebl_openbackend_machine): Replace K&R function
+	definition with ansi-C definitions.
+	* eblstother.c (ebl_check_st_other_bits): Likewise.
+
+2015-06-12  Mark Wielaard  <mjw@redhat.com>
+
+	* eblcheckreloctargettype.c (ebl_check_reloc_target_type): Allow
+	SHT_INIT_ARRAY, SHT_FINI_ARRAY and SHT_PREINIT_ARRAY.
+
+2015-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* eblobjnote.c (ebl_object_note): If allocation buf is large, then
+	allocate it with malloc.
+
+2015-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* eblopenbackend.c (MAX_PREFIX_LEN): New define (16).
+	(openbackend): Stack allocate symname array using MAX_PREFIX_LEN.
+
+2015-01-27  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl.h: Add comment from README that this is completely
+	UNSUPPORTED.
+
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* ebl-hooks.h (bss_plt_p): Remove ehdr argument.
+	* eblbsspltp.c (ebl_bss_plt_p): Likewise.
+	* eblopenbackend.c (default_bss_plt_p): Likewise.
+	* libebl.h (ebl_bss_plt_p): Likewise.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* ebldebugscnp.c (ebl_debugscn_p): Check name is not NULL.
+
+2014-06-17  Mark Wielaard  <mjw@redhat.com>
+
+	* eblinitreg.c (ebl_func_addr_mask): New function.
+	* libebl.h (ebl_func_addr_mask): Define.
+	* libeblP.h (struct ebl): Add func_addr_mask.
+
+2014-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblcheckreloctargettype.c.
+	* eblcheckreloctargettype.c: New file.
+	* ebl-hooks.h (check_reloc_target_type): New hook.
+	* eblopenbackend.c (default_check_reloc_target_type): New function.
+	(fill_defaults): Assign default_check_reloc_target_type to
+	check_reloc_target_type.
+	* libebl.h (ebl_check_reloc_target_type): New function definition.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblresolvesym.c.
+	* ebl-hooks.h (resolve_sym_value): New entry.
+	* eblresolvesym.c: New file.
+	* libebl.h (ebl_resolve_sym_value): New definition.
+	* libeblP.h (fd_addr): New field.
+	(fd_data): Likewise.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: s390 and s390x
+	* Makefile.am (gen_SOURCES): Add eblnormalizepc.c and eblunwind.c.
+	* ebl-hooks.h (normalize_pc, unwind): New.
+	* eblnormalizepc.c: New file.
+	* eblunwind.c: New file.
+	* libebl.h (Ebl_Register_Location): Add field pc_register.
+	(ebl_normalize_pc): New declaration.
+	(ebl_tid_registers_get_t, ebl_pid_memory_read_t): New definitions.
+	(ebl_unwind): New declaration.
+
+2013-12-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: ppc and ppc64
+	* Makefile.am (gen_SOURCES): Add ebldwarftoregno.c.
+	* ebl-hooks.h (dwarf_to_regno): New.
+	* ebldwarftoregno.c: New file.
+	* libebl.h (Ebl_Core_Item): New field pc_register.
+	(ebl_tid_registers_t): Add FIRSTREG -1 to the comment.
+	(ebl_dwarf_to_regno): New.
+
+2013-11-25  Petr Machata  <pmachata@redhat.com>
+
+	* eblopenbackend.c (machines): Add entry for AArch64.
+
+2013-11-14  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Code cleanup: Remove const in prototype
+	* libebl.h (ebl_tid_registers_t): Remove const from firstreg.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblinitreg.c.
+	* ebl-hooks.h (set_initial_registers_tid): New entry.
+	* eblinitreg.c: New file.
+	* libebl.h (ebl_tid_registers_t): New definition.
+	(ebl_set_initial_registers_tid, ebl_frame_nregs): New declarations.
+	* libeblP.h (struct ebl): New entry frame_nregs.
+
+2013-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl.h (ebl_abi_cfi): Document restrictions using register
+	rules.
+
+2013-09-26  Petr Machata  <pmachata@redhat.com>
+
+	* eblcorenotetypename.c: Handle NT_ARM_TLS, NT_ARM_HW_BREAK,
+	NT_ARM_HW_WATCH, NT_SIGINFO, NT_FILE.
+
+2013-09-25  Mark Wielaard  <mjw@redhat.com>
+
+	* eblsectionstripp.c (ebl_section_strip_p): Check shdr_l is not NULL.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2012-10-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* ebl-hooks.h (abi_cfi): Extend its comment for return value.
+	* eblopenbackend.c (default_abi_cfi): Return -1.
+	* libebl.h (ebl_abi_cfi): Extend its comment for return value.
+
+2012-08-30  Petr Machata  <pmachata@redhat.com>
+
+	* eblcorenotetypename.c: Handle PPC_VSX, X86_XSTATE,
+	S390_HIGH_GPRS, S390_TIMER, S390_TODCMP, S390_TODPREG, S390_CTRS,
+	S390_PREFIX, S390_LAST_BREAK, S390_SYSTEM_CALL, and ARM_VFP.
+
+2012-08-22  Jeff Kenton  <jkenton@tilera.com>
+
+	* eblopenbackend.c (machines): Add tilegx.
+
+2011-06-26  Mark Wielaard  <mjw@redhat.com>
+
+	* eblopenbackend.c (default_debugscn_p): Add .debug_macro.
+
+2011-04-26  Mark Wielaard  <mjw@redhat.com>
+
+	* libebl.h (ebl_object_note_type_name): Add const char *name arg.
+	* eblhooks.h (object_note_type_name): Likewise.
+	* eblopenbackend.c (default_object_note_type_name): Likewise.
+	* eblobjnotetypename.c (ebl_object_note_type_name): Likewise.
+	And print version if name is "stapsdt".
+	* eblobjnote.c (ebl_object_note): Add output for "stapsdt" notes.
+
+2011-03-21  Marek Polacek  <mpolacek@redhat.com>
+
+	* ebldynamictagname.c: Fix typo in TLSDESC_GOT.
+
+2011-03-10  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblstother.c.
+	* eblstother.c: New file.
+	* ebl-hooks.h: Add check_st_other_bits hook.
+	* eblopenbackend.c (default_check_st_other_bits): New function.
+	(fill_defaults): Hook default_check_st_other_bits.
+	* libebl.h (ebl_check_st_other_bits): New prototype.
+
+2010-07-07  Roland McGrath  <roland@redhat.com>
+
+	* eblopenbackend.c (default_debugscn_p): Match .gdb_index section.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2010-01-04  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenote.c (ebl_core_note): Take GElf_Nhdr * and name data
+	pointer instead of only n_type and n_descsz.
+	* libebl.h: Update declaration.
+	* ebl-hooks.h: Update core_note hook signature.
+	* eblopenbackend.c (default_core_note): Likewise.
+
+2009-10-14  Roland McGrath  <roland@redhat.com>
+
+	* eblobjnote.c (ebl_object_note): Clean up NT_GNU_GOLD_VERSION printing.
+
+2009-10-05  Roland McGrath  <roland@redhat.com>
+
+	* eblopenbackend.c (default_debugscn_p): Match .debug_pubtypes and
+	.debug_types too.
+
+2009-09-02  Petr Machata  <pmachata@redhat.com>
+
+	* libebl/eblstrtab.c (morememory): Allocate memory in multiples of
+	pagesize.
+
+2009-08-06  Petr Machata  <pmachata@redhat.com>
+
+	* libebl/eblstrtab.c (ebl_strtabfinalize): Only call copystrings
+	if we have any strings to copy.
+
+2009-07-26  Mark Wielaard  <mjw@redhat.com>
+
+	* eblobjnote.c (ebl_object_note): Handle NT_GNU_GOLD_VERSION.
+
+	* eblobjnotetypename.c (ebl_object_note_type_name): Recognize
+	NT_GNU_GOLD_VERSION.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* ebl-hooks.h: Add abi_cfi hook.
+	* eblopenbackend.c (default_abi_cfi): New function.
+	(fill_defaults): Add initializer.
+	* eblabicfi.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* libebl.h: Declare ebl_abi_cfi.
+
+2009-07-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblsymbolbindingname.c (ebl_symbol_binding_name): Handle
+	STB_GNU_UNIQUE.
+
+	* eblsymboltypename.c (ebl_symbol_type_name): Only handle STT_GNU_IFUNC
+	if the binary is marked as being for Linux.
+
+2009-04-01  Roland McGrath  <roland@redhat.com>
+
+	* eblsymboltypename.c (ebl_symbol_type_name): Add STT_GNU_IFUNC.
+
+	* eblauxvinfo.c (AUXV_TYPES): Add RANDOM and BASE_PLATFORM.
+
+2009-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblreloctypename.c (ebl_reloc_type_name): Return "<INVALID RELOC>"
+	instead of "???" for invalid relocations.
+
+2008-08-01  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenotetypename.c: Handle NT_386_IOPERM.
+
+2008-07-28  Roland McGrath  <roland@redhat.com>
+
+	* eblauxvinfo.c (AUXV_TYPES): Add EXECFN.
+
+	* eblauxvinfo.c (ebl_auxv_info): Handle missing elements of standard
+	table.
+
+2008-07-04  Roland McGrath  <roland@redhat.com>
+
+	* libebl.h: Declare ebl_syscall_abi.
+	* ebl_syscall_abi.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* ebl-hooks.h: New hook syscall_abi.
+	* eblopenbackend.c (default_syscall_abi): New function.
+	(fill_defaults): Use it.
+
+2008-03-31  Roland McGrath  <roland@redhat.com>
+
+	* ebldynamictagname.c (ebl_dynamic_tag_name): Use hex for unknown tag.
+
+	* ebl-hooks.h: Add check_special_section hook.
+	* eblopenbackend.c (fill_defaults): Set new hook to ...
+	(default_check_special_section): ... this, new function.
+	* ebl_check_special_section.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* libebl.h: Declare it.
+
+2008-02-20  Roland McGrath  <roland@redhat.com>
+
+	* libebl.h: Declare ebl_check_object_attribute.
+	* eblcheckobjattr.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* ebl-hooks.h: Add check_object_attribute hook.
+	* eblopenbackend.c (default_check_object_attribute): New function.
+	(fill_defaults): Initialize pointer to it.
+
+2008-02-19  Roland McGrath  <roland@redhat.com>
+
+	* eblsectiontypename.c (ebl_section_type_name):
+	Handle SHT_GNU_ATTRIBUTES.
+
+2008-02-08  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_PPC_SPE.
+
+2008-01-30  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_386_TLS.
+
+2007-10-18  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_PPC_VMX.
+
+2007-10-11  Roland McGrath  <roland@redhat.com>
+
+	* eblobjnote.c (ebl_object_note): Translate target format (byte-swap)
+	for NT_GNU_ABI_TAG contents.
+
+2007-08-22  Roland McGrath  <roland@redhat.com>
+
+	* libebl.h (Ebl_Core_Item): New member `group'.
+
+2007-08-19  Roland McGrath  <roland@redhat.com>
+
+	* ebl-hooks.h: Add new hook auxv_info.
+	* eblopenbackend.c (default_auxv_info): New function.
+	(fill_defaults): Initialize auxv_info hook.
+	* eblauxvinfo.c : New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* libebl.h: Declare ebl_auxv_info.
+
+	* eblcorenote.c: Rewritten with new signature.
+	* Makefile.am (gen_SOURCES): Add it.
+	* libebl.h (Ebl_Register_Location, Ebl_Core_Item): New types.
+	(ebl_core_note_info): Completely revamp signature.
+	* ebl-hooks.h: Update decl.
+	* eblopenbackend.c (default_core_note): Update signature.
+
+2007-07-09  Roland McGrath  <roland@redhat.com>
+
+	* eblobjnotetypename.c (ebl_object_note_type_name): Handle
+	NT_GNU_HWCAP, NT_GNU_BUILD_ID.
+
+	* eblobjnote.c (ebl_object_note): Handle NT_GNU_BUILD_ID.
+
+2007-04-22  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenotetypename.c (ebl_core_note_type_name): Handle NT_PRXFPREG.
+
+2007-03-10  Roland McGrath  <roland@redhat.com>
+
+	* eblcorenote.c (ebl_core_note): For normally-zero types,
+	print in hex if not zero.
+
+2007-01-11  Roland McGrath  <roland@redhat.com>
+
+	* ebl-hooks.h (machine_section_flag_check): New hook.
+	* libebl.h: Declare ebl_machine_section_flag_check.
+	* eblmachinesectionflagcheck.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* eblopenbackend.c (default_machine_section_flag_check): New function.
+	(fill_defaults): Use it.
+
+2006-09-04  Roland McGrath  <roland@redhat.com>
+
+	* ebl-hooks.h: Replace register_name hook with register_info.
+	Also yield natural bit width and base type encoding.
+	* eblopenbackend.c (default_register_name): Renamed
+	default_register_info, new args added.
+	(fill_defaults): Update initialization.
+	* eblregname.c: File renamed ...
+	* eblreginfo.c: ... to this.
+	(ebl_register_name): Renamed to ebl_register_info, new args added.
+	* libebl.h: Update decl.
+
+	* Makefile.am (gen_SOURCES): Update list.
+
+2006-07-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* ebldynamictagname.c: Add support for DT_GNU_HASH.
+	* ebldynamictagcheck.c: Likewise.
+	* eblsectiontypename.c: Add support for SHT_GNU_HASH.
+
+2006-07-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblsysvhashentrysize.c.
+	* libeblP.h (struct ebl): Add sysvhash_entrysize element.
+	* eblopenbackend.c (fill_defaults): Initialize sysvhash_entrysize.
+
+	* eblopenbackend.c (openbackend): If possible, fill machine, class,
+	and data values in from the ELF file.
+
+2006-07-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblrelativerelocp.c.
+	* eblrelativerelocp.c: New file.
+	* ebl-hooks.c: Add relative_reloc_p.
+	* eblopenbackend.c (default_relative_reloc_p): New function.
+	(fill_defaults): Hook it up.
+	* libebl.h: Declare ebl_relative_reloc_p.
+
+2006-06-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (gen_SOURCES): Add eblnonerelocp.c.
+	* eblnonerelocp.c: New file.
+	* ebl-hooks.c: Add none_reloc_p.
+	* eblopenbackend.c (default_none_reloc_p): New function.
+	(fill_defaults): Hook it up.
+	* libebl.h: Declare ebl_none_reloc_p.
+
+2006-05-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* libebl.h: Add extern "C".
+
+2005-11-25  Roland McGrath  <roland@redhat.com>
+
+	* eblregname.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* ebl-hooks.h: Declare register_name hook.
+	* libebl.h: Declare ebl_register_name.
+	* eblopenbackend.c (default_register_name): New function.
+	(fill_defaults): Use it.
+
+2005-11-16  Roland McGrath  <roland@redhat.com>
+
+	* libebl.h: Use "" for elf-knowledge.h, not <>.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Removed everything for building libebl_*.so modules,
+	now in ../backends/Makefile.am instead.
+	* alpha_init.c: Moved to ../backends.
+	* alpha_reloc.def: Likewise.
+	* alpha_retval.c: Likewise.
+	* alpha_symbol.c: Likewise.
+	* arm_init.c: Likewise.
+	* arm_reloc.def: Likewise.
+	* arm_symbol.c: Likewise.
+	* common-reloc.c: Likewise.
+	* i386_corenote.c: Likewise.
+	* i386_init.c: Likewise.
+	* i386_reloc.def: Likewise.
+	* i386_retval.c: Likewise.
+	* i386_symbol.c: Likewise.
+	* ia64_init.c: Likewise.
+	* ia64_reloc.def: Likewise.
+	* ia64_symbol.c: Likewise.
+	* libebl_CPU.h: Likewise.
+	* ppc64_init.c: Likewise.
+	* ppc64_reloc.def: Likewise.
+	* ppc64_retval.c: Likewise.
+	* ppc64_symbol.c: Likewise.
+	* ppc_init.c: Likewise.
+	* ppc_reloc.def: Likewise.
+	* ppc_retval.c: Likewise.
+	* ppc_symbol.c: Likewise.
+	* s390_init.c: Likewise.
+	* s390_reloc.def: Likewise.
+	* s390_symbol.c: Likewise.
+	* sh_init.c: Likewise.
+	* sh_reloc.def: Likewise.
+	* sh_symbol.c: Likewise.
+	* sparc_init.c: Likewise.
+	* sparc_reloc.def: Likewise.
+	* sparc_symbol.c: Likewise.
+	* x86_64_corenote.c: Likewise.
+	* x86_64_init.c: Likewise.
+	* x86_64_reloc.def: Likewise.
+	* x86_64_retval.c: Likewise.
+	* x86_64_symbol.c: Likewise.
+
+	* libebl.h: Comment fixes.
+
+	* alpha_retval.c: New file.
+	* Makefile.am (alpha_SRCS): Add it.
+	* alpha_init.c (alpha_init): Initialize return_value_location hook.
+
+	* ppc64_retval.c: New file.
+	* Makefile.am (ppc64_SRCS): Add it.
+	* ppc64_init.c (ppc64_init): Initialize return_value_location hook.
+
+	* ppc_retval.c: New file.
+	* Makefile.am (ppc_SRCS): Add it.
+	* ppc_init.c (ppc_init): Initialize return_value_location hook.
+
+2005-11-14  Roland McGrath  <roland@redhat.com>
+
+	* ia64_init.c (ia64_init): Initialize EH->reloc_simple_type.
+	* sh_init.c (sh_init): Likewise.
+	* x86_64_init.c (x86_64_init): Likewise.
+
+	* sparc_symbol.c (sparc_reloc_simple_type): New function.
+	* sparc_init.c (sparc_init): Use it.
+
+	* arm_symbol.c (arm_reloc_simple_type): New function.
+	* arm_init.c (arm_init): Use it.
+
+	* alpha_symbol.c (alpha_reloc_simple_type): New function.
+	* alpha_init.c (alpha_init): Use it.
+
+	* ia64_reloc.def: Update bits per H. J. Lu <hjl@lucon.org>.
+
+	* arm_reloc.def: Update bits per Daniel Jacobowitz <drow@false.org>.
+
+	* alpha_reloc.def: Update bits per Richard Henderson <rth@redhat.com>.
+
+2005-11-13  Roland McGrath  <roland@redhat.com>
+
+	* x86_64_retval.c: New file.
+	* Makefile.am (x86_64_SRCS): Add it.
+	* x86_64_init.c (x86_64_init): Use x86_64_return_value_location.
+
+	* i386_retval.c: New file.
+	* Makefile.am (i386_SRCS): Add it.
+	(libdw): New variable.
+	(libebl_%.so): Use $(libdw) in link; use --as-needed.
+	* i386_init.c (i386_init): Use i386_return_value_location.
+
+	* eblretval.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	(INCLUDES): Search in libdw.
+	* libebl.h: Include <libdw.h>.   Declare ebl_return_value_location.
+	* ebl-hooks.h: Declare return_value_location hook.
+	* eblopenbackend.c (default_return_value_location): New function.
+	(fill_defaults): Use it.
+
+2005-11-10  Roland McGrath  <roland@redhat.com>
+
+	* s390_init.c: New file.
+	* s390_reloc.def: New file.
+	* s390_symbol.c: New file.
+	* Makefile.am (modules, libebl_pic): Add s390.
+	(s390_SRCS, libebl_s390_pic_a_SOURCES): New variables.
+	(am_libebl_s390_pic_a_OBJECTS): New variable.
+
+	* ppc64_init.c: Use common-reloc.c.
+	* ppc64_symbol.c (ppc64_backend_name): Removed.
+	(ppc64_reloc_type_check, ppc64_reloc_type_name): Likewise.
+	(ppc64_copy_reloc_p, ppc64_reloc_valid_use): Likewise.
+
+	* ppc_init.c: Use common-reloc.c.
+	* ppc_symbol.c (ppc_backend_name): Removed.
+	(ppc_reloc_type_name, ppc_reloc_type_check): Likewise.
+	(ppc_reloc_valid_use, ppc_copy_reloc_p): Likewise.
+
+	* sparc_init.c: Use common-reloc.c.
+	* sparc_symbol.c (sparc_backend_name): Removed.
+	(sparc_reloc_type_name, sparc_reloc_type_check): Likewise.
+	(sparc_copy_reloc_p): Likewise.
+
+	* arm_init.c: Use common-reloc.c.
+	* arm_symbol.c (arm_backend_name): Removed.
+	(arm_reloc_type_name, arm_reloc_type_check, arm_copy_reloc_p): Removed.
+
+	* alpha_init.c: Use common-reloc.c.
+	* alpha_symbol.c (alpha_backend_name): Removed.
+	(alpha_reloc_type_name, alpha_reloc_type_check): Likewise.
+	(alpha_copy_reloc_p): Likewise.
+
+	* ia64_symbol.c (ia64_backend_name): Removed.
+	(ia64_reloc_type_name, ia64_reloc_type_check): Likewise.
+	(ia64_copy_reloc_p): Likewise.
+
+	* x86_64_init.c: Use common-reloc.c.
+	* x86_64_symbol.c (x86_64_backend_name): Removed.
+	(x86_64_copy_reloc_p, x86_64_reloc_valid_use): Likewise.
+	(x86_64_reloc_type_check, x86_64_reloc_type_name): Likewise.
+
+	* sh_init.c: Use common-reloc.c.
+	* sh_symbol.c: All functions removed.
+	(sh_reloc_simple_type): New function.
+	(sh_gotpc_reloc_check): New function.
+
+	* common-reloc.c: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+	* i386_init.c: Include it.
+
+	* sh_reloc.def: New file.
+	* i386_reloc.def: New file.
+	* alpha_reloc.def: New file.
+	* arm_reloc.def: New file.
+	* i386_reloc.def: New file.
+	* ia64_reloc.def: New file.
+	* ppc64_reloc.def: New file.
+	* ppc_reloc.def: New file.
+	* sh_reloc.def: New file.
+	* sparc_reloc.def: New file.
+	* x86_64_reloc.def: New file.
+	* Makefile.am (EXTRA_DIST): Add $(modules:=_reloc.def).
+
+	* libebl_alpha.map: Removed.
+	* libebl_ia64.map: Removed.
+	* libebl_ppc.map: Removed.
+	* libebl_sparc.map: Removed.
+	* libebl_arm.map: Removed.
+	* libebl_i386.map: Removed.
+	* libebl_ppc64.map: Removed.
+	* libebl_sh.map: Removed.
+	* libebl_x86_64.map: Removed.
+	* Makefile.am (EXTRA_DIST): Remove them.
+	(libebl_%.map, libebl_%.so): New pattern rules.
+
+	* libebl_alpha.h: Removed.
+	* libebl_ia64.h: Removed.
+	* libebl_ppc.h: Removed.
+	* libebl_sparc.h: Removed.
+	* libebl_arm.h: Removed.
+	* libebl_i386.h: Removed.
+	* libebl_ppc64.h: Removed.
+	* libebl_sh.h: Removed.
+	* libebl_x86_64.h: Removed.
+	* Makefile.am (noinst_HEADERS): Remove them.
+
+	* x86_64_corenote.c: Use libebl_CPU.h instead.
+	* x86_64_symbol.c: Likewise.
+	* i386_corenote.c: Likewise.
+
+2005-11-09  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_reloc_simple_type): New function.
+
+	* ebl-hooks.h (reloc_simple_type): Take the Ebl handle, not Elf handle.
+	* eblrelocsimpletype.c (ebl_reloc_simple_type): Update caller.
+	* eblopenbackend.c (default_reloc_simple_type): Update signature.
+	* i386_symbol.c (i386_reloc_simple_type): Likewise.
+	* ppc64_symbol.c (ppc64_reloc_simple_type): Likewise.
+	* ppc_symbol.c (ppc_reloc_simple_type): Likewise.
+	* x86_64_symbol.c (x86_64_reloc_simple_type): Likewise.
+
+	* i386_symbol.c (i386_backend_name): Removed.
+	(i386_reloc_type_name, i386_reloc_type_check): Likewise.
+	(i386_reloc_valid_use): Removed.
+	(i386_copy_reloc_p): Removed.
+
+	* alpha_destr.c: Removed.
+	* arm_destr.c: Removed.
+	* i386_destr.c: Removed.
+	* ia64_destr.c: Removed.
+	* ppc64_destr.c: Removed.
+	* ppc_destr.c: Removed.
+	* sh_destr.c: Removed.
+	* sparc_destr.c: Removed.
+	* x86_64_destr.c: Removed.
+
+	* ebl-hooks.h: New file, broken out of ...
+	* libeblP.h (struct ebl): ... here.  #include that for hook
+	declarations, after defining EBLHOOK macro.
+	* libebl_CPU.h: New file.
+	* Makefile.am (noinst_HEADERS): Add them.
+
+	* libeblP.h (struct ebl): Use uint_fast16_t for machine,
+	and uint_fast8_t for class and data.
+
+2005-08-14  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_section_type_name): New function.
+	(ia64_dynamic_tag_check): New function.
+	(ia64_reloc_valid_use): New function.
+	* libebl_ia64.h: Declare them.
+	* ia64_init.c (ia64_init): Use them.
+	* Makefile.am (libebl_ia64.so): Link with libelf.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Use $(LINK) not $(CC) when creating DSOs.
+
+2005-08-13  Roland McGrath  <roland@redhat.com>
+
+	* ia64_symbol.c (ia64_machine_flag_check): New function.
+	* libebl_ia64.h: Declare it.
+	* ia64_init.c (ia64_init): Use it.
+
+2005-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* libebl.h: Add ehdr parameter to ebl_bss_plt_p and
+	ebl_check_special_symbol.
+	* libeblP.h (struct ebl): Adjust callback functions.
+	* eblopenbackend.c: Adjust dummy functions.
+	* ebl_check_special_symbol.c: Add parameter and pass it on.
+	* eblbsspltp.c: Likewise.
+	* ppc_symbol.c (find_dyn_got): With ehdr passed, simplify search for
+	the dynamic section entry.
+	(ppc_check_special_symbol): Add ehdr parameter.
+	(ppc_bss_plt_p): Likewise.
+	* libebl_ppc.h: Adjust prototypes.
+	* ppc64_symbol.c (ppc_check_special_symbol): Add ehdr parameter.
+	(ppc_bss_plt_p): Likewise.
+	* libebl_ppc64.h: Adjust prototypes.
+
+2005-08-12  Roland McGrath  <roland@redhat.com>
+
+	* ppc_symbol.c (find_dyn_got): New function, broken out of ...
+	(ppc_bss_plt_p): ... here.  Call that.
+	(ppc_check_special_symbol): Use find_dyn_got to fetch value to check
+	against _GLOBAL_OFFSET_TABLE_.
+
+	* libeblP.h (struct ebl): Add bss_plt_p hook.
+	* eblopenbackend.c (default_bss_plt_p): New function.
+	(fill_defaults): Use it.
+	* eblbsspltp.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* libebl.h: Declare ebl_bss_plt_p.
+	* ppc_symbol.c (ppc_bss_plt_p): New function.
+	* libebl_ppc.h: Declare it.
+	* ppc_init.c (ppc_init): Use it.
+	* ppc64_symbol.c (ppc64_bss_plt_p): New function.
+	* libebl_ppc64.h: Declare it.
+	* ppc64_init.c (ppc64_init): Use it.
+
+	* ebl_check_special_symbol.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* libebl.h: Declare ebl_check_special_symbol.
+	* libeblP.h (struct ebl): Add check_special_symbol hook.
+	* eblopenbackend.c (default_check_special_symbol): New function.
+	(fill_defaults): Use it.
+	* ppc_symbol.c (ppc_check_special_symbol): New function.
+	* libebl_ppc.h: Add prototype.
+	* ppc_init.c (ppc_init): Use it.
+	* ppc64_symbol.c (ppc64_check_special_symbol): New function.
+	* libebl_ppc64.h: Add prototype.
+	* ppc64_init.c (ppc64_init): Use it.
+
+2005-08-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* ppc_init.c: Add support for new DT_PPC_* and R_PPC_* values.
+	* ppc_symbol.c: Likewise.
+	* libebl_ppc.h: Likewise.
+	* ppc64_init.c: There is now also a dynamic_tag_check functions
+	* ppc64_symbol.c: Add dynamic_tag_check.
+	* libebl_ppc64.h: Add prototype.
+	* alpha_init.c: Add support for new DT_ALPHA_* value.
+	* alpha_symbol.c: Likewise.
+	* libebl_alpha.h: Likewise.
+
+2005-08-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* libebl_alpha.map: Remove unnecessary exports.
+	* libebl_arm.map: Likewise.
+	* libebl_i386.map: Likewise.
+	* libebl_ia64.map: Likewise.
+	* libebl_ppc.map: Likewise.
+	* libebl_ppc64.map: Likewise.
+	* libebl_sh.map: Likewise.
+	* libebl_sparc.map: Likewise.
+	* libebl_x86_64.map: Likewise.
+
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libebl_a_SOURCES): Add eblelfclass.c, eblelfdata.c,
+	and eblelfmachine.c.
+	* elbopenbackend.c (machines): Add class and data fields.  Initialize
+	them.
+	(ebl_openbackend): Initialize machine, class, data fields in result.
+	* libebl.h: Declare Add eblelfclass, eblelfdata, and eblelfmachine.
+	* libeblP.h (Ebl): Add machine, class, data fields.
+
+2005-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblsectionstripp.c: New file.
+	* Makefile.am (gen_SOURCES): Add eblsectionstripp.c.
+	* i386_init.c (i386_init): Install specific debugscn_p callback.
+	* i386_symbol.c (i386_debugscn_p): New function.
+	* libebl.h: Declare ebl_section_strip_p.
+	* libebl_i386.h: Declare i386_debugscn_p.
+
+	* libebl.h: Move Ebl definition to...
+	* libeblP.h: ...here.
+
+2005-07-21  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (install-ebl-modules): New target, commands from ...
+	(install): ... here.  Make this depend on it.
+	(LIBEBL_SUBDIR): New variable, substituted by configure.
+	(install-ebl-modules): Install in $(libdir)/$(LIBEBL_SUBDIR).
+	* eblopenbackend.c (openbackend): Use LIBEBL_SUBDIR in module name.
+
+2005-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblcopyrelocp.c: New file.
+	* Makefile.am (gen_SOURCES): Add eblcopyrelocp.c.
+	* libebl.h: Declare ebl_copy_reloc_p.
+	* eblopenbackend.c (fill_defaults): Fill in copy_reloc_p.
+	(default_copy_reloc_p): New function.
+	* alpha_init.c: Define and use arch-specific copy_reloc_p function.
+	* alpha_symbol.c: Likewise.
+	* arm_init.c: Likewise.
+	* arm_symbol.c: Likewise.
+	* i386_init.c: Likewise.
+	* i386_symbol.c: Likewise.
+	* ia64_init.c: Likewise.
+	* ia64_symbol.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* ppc64_symbol.c: Likewise.
+	* ppc_init.c: Likewise.
+	* ppc_symbol.c: Likewise.
+	* sh_init.c: Likewise.
+	* sh_symbol.c: Likewise.
+	* sparc_init.c: Likewise.
+	* sparc_symbol.c: Likewise.
+	* x86_64_init.c: Likewise.
+	* x86_64_symbol.c: Likewise.
+	* libebl_alpha.h: Declare the copy_reloc_p function.
+	* libebl_arm.h: Likewise.
+	* libebl_i386.h: Likewise.
+	* libebl_ia64.h: Likewise.
+	* libebl_ppc.h: Likewise.
+	* libebl_ppc64.h: Likewise.
+	* libebl_sh.h: Likewise.
+	* libebl_sparc.h: Likewise.
+	* libebl_x86_64.h: Likewise.
+
+2005-05-31  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libebl_*_so_SOURCES): Set to $(*_SRCS) so dependency
+	tracking works right.
+
+2005-05-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* libebl_x86_64.map: Add x86_64_core_note.
+
+2005-05-19  Roland McGrath  <roland@redhat.com>
+
+	* libebl_i386.map: Add i386_reloc_valid_use, i386_reloc_simple_type.
+	* libebl_ppc.map: Add ppc_reloc_simple_type.
+	* libebl_ppc64.map: Add ppc64_reloc_simple_type.
+	* libebl_x86_64.map: Add x86_64_reloc_simple_type.
+
+2005-05-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblcorenote.c: Handle new AT_* values and files with different
+	endianness.
+	* Makefile.am (x86_64_SRCS): Add x86_64_corenote.c.
+	* x86-64_corenote.c: New file.
+	* x86_64_init.c: Hook in x86_64_corenote.
+	* i386_corenote.c: Make file usable on 64-bit platforms.
+
+	* eblopenbackend.c: If modules version comparison fails, reinitialize
+	hooks.
+
+2005-05-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblopenbackend.c: Require the init function to return a string.
+	Compare it with MODVERSION from config.h.
+	* alpha_init.c: Change return type.  Return MODVERSION or NULL.
+	* arm_init.c: Likewise.
+	* eblopenbackend.c: Likewise.
+	* i386_init.c: Likewise.
+	* ia64_init.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* ppc_init.c: Likewise.
+	* sh_init.c: Likewise.
+	* sparc_init.c: Likewise.
+	* x86_64_init.c: Likewise.
+	* libeblP.h: Adjust ebl_bhinit_t.
+	* libebl_alpha.h: Adjust init function prototype.
+	* libebl_arm.h: Likewise.
+	* libebl_i386.h: Likewise.
+	* libebl_ia64.h: Likewise.
+	* libebl_ppc.h: Likewise.
+	* libebl_ppc64.h: Likewise.
+	* libebl_sh.h: Likewise.
+	* libebl_sparc.h: Likewise.
+	* libebl_x86_64.h: Likewise.
+
+	* mips_destr.c: Removed.
+	* mips_init.c: Removed.
+	* mips_symbol.c: Removed.
+	* libebl_mips.h: Removed.
+	* libebl_mips.map: Removed.
+
+2005-05-03  Roland McGrath  <roland@redhat.com>
+
+	* libebl.h (Ebl): Add `reloc_simple_type' member.
+	* eblopenbackend.c (default_reloc_simple_type): New function.
+	(openbackend): Use that as default reloc_simple_type callback.
+	* eblrelocsimpletype.c: New file.
+	* Makefile.am (gen_SOURCES): Add it.
+	* i386_symbol.c (i386_reloc_simple_type): New function.
+	* libebl_i386.h: Declare it.
+	* i386_init.c (i386_init): Use it.
+	* x86_64_symbol.c (x86_64_reloc_simple_type): New function.
+	* libebl_x86_64.h: Declare it.
+	* x86_64_init.c (x86_64_init): Use it.
+	* ppc_symbol.c (ppc_reloc_simple_type): New function.
+	* libebl_ppc.h: Declare it.
+	* ppc_init.c (ppc_init): Use it.
+	* ppc64_symbol.c (ppc64_reloc_simple_type): New function.
+	* libebl_ppc64.h: Declare it.
+	* ppc64_init.c (ppc64_init): Use it.
+
+2005-03-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblcorenote.c (ebl_core_note): Add support for AT_SECURE.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -Wformat=2.
+
+2005-02-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* alpha_destr.c: Add __attribute__((unused)) where needed.
+	* alpha_init.c: Likewise.
+	* alpha_symbol.c: Likewise.
+	* arm_destr.c: Likewise.
+	* arm_init.c: Likewise.
+	* arm_symbol.c: Likewise.
+	* i386_corenote.c: Likewise.
+	* i386_destr.c: Likewise.
+	* i386_init.c: Likewise.
+	* i386_symbol.c: Likewise.
+	* ia64_destr.c: Likewise.
+	* ia64_init.c: Likewise.
+	* ia64_symbol.c: Likewise.
+	* mips_destr.c: Likewise.
+	* mips_init.c: Likewise.
+	* mips_symbol.c: Likewise.
+	* ppc64_destr.c: Likewise.
+	* ppc64_init.c: Likewise.
+	* ppc64_symbol.c: Likewise.
+	* ppc_destr.c: Likewise.
+	* ppc_init.c: Likewise.
+	* ppc_symbol.c: Likewise.
+	* sh_destr.c: Likewise.
+	* sh_init.c: Likewise.
+	* sh_symbol.c: Likewise.
+	* sparc_destr.c: Likewise.
+	* sparc_init.c: Likewise.
+	* sparc_symbol.c: Likewise.
+	* x86_64_destr.c: Likewise.
+	* x86_64_init.c: Likewise.
+	* x86_64_symbol.c: Likewise.
+
+	* x86_64_symbol.c (reloc_map_table): Fix entries for R_X86_64_64
+	and R_X86_64_32..
+
+2005-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblstrtab.c: A few cleanups.
+
+	* eblopenbackend.c: Mark unused parameters.
+
+	* eblgstrtab.c: Cleanups a few printf format strings.
+
+	* Makefile.am: Cleanup AM_CFLAGS handling.  Add -Wunused -Wextra.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Check for text relocations in constructed DSOs.
+
+	* eblstrtab.c: Minor cleanups.
+
+	* Makefile.am (AM_CFLAGS): Add -std=gnu99 and -fmudflap for MUDFLAP.
+
+2004-08-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add LIBSTR definition with base name of
+	the lib directory.
+	* eblopenbackend.c (openbackend): Use LIBSTR instead of hardcoded
+	lib in path to ebl modules.
+
+2004-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add rules for ppc and ppc64 ebl module.
+	* ppc_init..c: New file.
+	* ppc_destr.c: New file.
+	* ppc_symbol.c: New file.
+	* libebl_ppc.h: New file.
+	* libebl_ppc.map: New file.
+	* ppc64_init..c: New file.
+	* ppc64_destr.c: New file.
+	* ppc64_symbol.c: New file.
+	* libebl_ppc64.h: New file.
+	* libebl_ppc64.map: New file.
+
+2004-01-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+2004-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* libeblP.h (_): Use elfutils domain.
+
+2004-01-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblsectionname.c: Add support for SHN_BEFORE and SHN_AFTER.
+
+2004-01-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblsegmenttypename.c ((ebl_segment_type_name): Add support for
+	PT_GNU_RELRO.
+
+2004-01-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* libebl.h: Remove last traces of libtool.
+
+2004-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf-knowledge.h: Move to libelf subdir.
+
+	* Makefile.am (EXTRA_DIST): Remove libebl.map.
+	* libebl.map: Removed.
+
+2003-12-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblsectiontypename.c (ebl_section_type_name): Add support for
+	SHT_SUNW_move, SHT_CHECKSUM, and SHT_GNU_LIBLIST.
+
+2003-11-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* ia64_symbol.c (ia64_dynamic_tag_name): New function.
+	* libebl_ia64.h (ia64_dynamic_tag_name): Declare.
+	* ia64_init.c (ia64_init): Register i164_dynamic_tag_name.
+
+2003-09-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* ia64_init.c (ia64_init): Initialize segment_type_name callback.
+	* ia64_symbol.c (ia64_segment_type_name): Define.
+	* libebl_ia64.h (ia64_segment_type_name): Declare.
+
+2003-09-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -fpic.
+
+2003-08-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (install): Remove dependency on libebl.so.
+
+2003-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* eblopenbackend.c: Adjust relative path to arch-specific DSOs
+	assuming the code ends up in the application.  Add second dlopen()
+	try without any path, just the filename.
+	* Makefile.in: Remove rules to build and install libebl.so.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+        * Moved to CVS archive.
diff --git a/libebl/Makefile.am b/libebl/Makefile.am
new file mode 100644
index 0000000..d84e7ee
--- /dev/null
+++ b/libebl/Makefile.am
@@ -0,0 +1,64 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 2000-2010, 2013, 2016, 2017 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+if BUILD_STATIC
+AM_CFLAGS += $(fpic_CFLAGS)
+endif
+AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libdw -I$(srcdir)/../libasm
+VERSION = 1
+
+noinst_LIBRARIES = libebl.a libebl_pic.a
+
+libebl_a_SOURCES = eblopenbackend.c eblclosebackend.c eblreloctypename.c \
+		   eblsegmenttypename.c eblsectiontypename.c \
+		   eblmachineflagname.c eblsymboltypename.c \
+		   ebldynamictagname.c eblsectionname.c \
+		   eblsymbolbindingname.c eblbackendname.c eblosabiname.c \
+		   eblmachineflagcheck.c eblmachinesectionflagcheck.c \
+		   eblreloctypecheck.c eblrelocvaliduse.c \
+		   eblrelocsimpletype.c ebldynamictagcheck.c \
+		   eblcorenotetypename.c eblobjnotetypename.c eblcorenote.c \
+		   eblobjnote.c ebldebugscnp.c eblgotpcreloccheck.c \
+		   eblcopyrelocp.c eblsectionstripp.c eblelfclass.c \
+		   eblelfdata.c eblelfmachine.c ebl_check_special_symbol.c \
+		   eblbsspltp.c eblretval.c eblreginfo.c eblnonerelocp.c \
+		   eblrelativerelocp.c eblsysvhashentrysize.c eblauxvinfo.c \
+		   eblcheckobjattr.c ebl_check_special_section.c \
+		   eblabicfi.c eblstother.c eblinitreg.c \
+		   ebldwarftoregno.c eblnormalizepc.c eblunwind.c \
+		   eblresolvesym.c eblcheckreloctargettype.c \
+		   ebl_data_marker_symbol.c
+
+libebl_pic_a_SOURCES =
+am_libebl_pic_a_OBJECTS = $(libebl_a_SOURCES:.c=.os)
+
+noinst_HEADERS = libebl.h libeblP.h ebl-hooks.h
+
+MOSTLYCLEANFILES = $(am_libebl_pic_a_OBJECTS)
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
new file mode 100644
index 0000000..d6437e5
--- /dev/null
+++ b/libebl/ebl-hooks.h
@@ -0,0 +1,188 @@
+/* Backend hook signatures internal interface for libebl.
+   Copyright (C) 2000-2011, 2013, 2014, 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* Return symbolic representation of relocation type.  */
+const char *EBLHOOK(reloc_type_name) (int, char *, size_t);
+
+/* Check relocation type.  */
+bool EBLHOOK(reloc_type_check) (int);
+
+/* Check if relocation type is for simple absolute relocations.  */
+Elf_Type EBLHOOK(reloc_simple_type) (Ebl *, int, int *);
+
+/* Check relocation type use.  */
+bool EBLHOOK(reloc_valid_use) (Elf *, int);
+
+/* Return true if the symbol type is that referencing the GOT.  */
+bool EBLHOOK(gotpc_reloc_check) (Elf *, int);
+
+/* Return symbolic representation of segment type.  */
+const char *EBLHOOK(segment_type_name) (int, char *, size_t);
+
+/* Return symbolic representation of section type.  */
+const char *EBLHOOK(section_type_name) (int, char *, size_t);
+
+/* Return section name.  */
+const char *EBLHOOK(section_name) (int, int, char *, size_t);
+
+/* Return next machine flag name.  */
+const char *EBLHOOK(machine_flag_name) (GElf_Word, GElf_Word *);
+
+/* Check whether machine flags are valid.  */
+bool EBLHOOK(machine_flag_check) (GElf_Word);
+
+/* Check whether SHF_MASKPROC flag bits are valid.  */
+bool EBLHOOK(machine_section_flag_check) (GElf_Xword);
+
+/* Check whether the section with the given index, header, and name
+   is a special machine section that is valid despite a combination
+   of flags or other details that are not generically valid.  */
+bool EBLHOOK(check_special_section) (Ebl *, int,
+				     const GElf_Shdr *, const char *);
+
+/* Return symbolic representation of symbol type.  */
+const char *EBLHOOK(symbol_type_name) (int, char *, size_t);
+
+/* Return symbolic representation of symbol binding.  */
+const char *EBLHOOK(symbol_binding_name) (int, char *, size_t);
+
+/* Return symbolic representation of dynamic tag.  */
+const char *EBLHOOK(dynamic_tag_name) (int64_t, char *, size_t);
+
+/* Check dynamic tag.  */
+bool EBLHOOK(dynamic_tag_check) (int64_t);
+
+/* Return symbolic representation of OS ABI.  */
+const char *EBLHOOK(osabi_name) (int, char *, size_t);
+
+/* Name of a note entry type for core files.  */
+const char *EBLHOOK(core_note_type_name) (uint32_t, char *, size_t);
+
+/* Name of a note entry type for object files.  */
+const char *EBLHOOK(object_note_type_name) (const char *, uint32_t,
+					    char *, size_t);
+
+/* Describe core note format.  */
+int EBLHOOK(core_note) (const GElf_Nhdr *, const char *,
+			GElf_Word *, size_t *, const Ebl_Register_Location **,
+			size_t *, const Ebl_Core_Item **);
+
+/* Handle object file note.  */
+bool EBLHOOK(object_note) (const char *, uint32_t, uint32_t, const char *);
+
+/* Check object attribute.  */
+bool EBLHOOK(check_object_attribute) (Ebl *, const char *, int, uint64_t,
+				      const char **, const char **);
+
+/* Check reloc target section type.  */
+bool EBLHOOK(check_reloc_target_type) (Ebl *, Elf64_Word);
+
+/* Describe auxv element type.  */
+int EBLHOOK(auxv_info) (GElf_Xword, const char **, const char **);
+
+/* Check section name for being that of a debug informatino section.  */
+bool EBLHOOK(debugscn_p) (const char *);
+
+/* Check whether given relocation is a copy relocation.  */
+bool EBLHOOK(copy_reloc_p) (int);
+
+/* Check whether given relocation is a no-op relocation.  */
+bool EBLHOOK(none_reloc_p) (int);
+
+/* Check whether given relocation is a relative relocation.  */
+bool EBLHOOK(relative_reloc_p) (int);
+
+/* Check whether given symbol's value is ok despite normal checks.  */
+bool EBLHOOK(check_special_symbol) (Elf *, const GElf_Sym *,
+			      const char *, const GElf_Shdr *);
+
+/* Check if this is a data marker symbol.  e.g. '$d' symbols for ARM.  */
+bool EBLHOOK(data_marker_symbol) (const GElf_Sym *sym, const char *sname);
+
+/* Check whether only valid bits are set on the st_other symbol flag.
+   Standard ST_VISIBILITY have already been masked off.  */
+bool EBLHOOK(check_st_other_bits) (unsigned char st_other);
+
+/* Check if backend uses a bss PLT in this file.  */
+bool EBLHOOK(bss_plt_p) (Elf *);
+
+/* Return location expression to find return value given the
+   DW_AT_type DIE of a DW_TAG_subprogram DIE.  */
+int EBLHOOK(return_value_location) (Dwarf_Die *functypedie,
+				    const Dwarf_Op **locp);
+
+/* Return register name information.  */
+ssize_t EBLHOOK(register_info) (Ebl *ebl,
+				int regno, char *name, size_t namelen,
+				const char **prefix, const char **setname,
+				int *bits, int *type);
+
+/* Disassembler function.  */
+int EBLHOOK(disasm) (Ebl *ebl, const uint8_t **startp, const uint8_t *end,
+		     GElf_Addr addr, const char *fmt, DisasmOutputCB_t outcb,
+		     DisasmGetSymCB_t symcb, void *outcbarg, void *symcbarg);
+
+/* Supply the machine-specific state of CFI before CIE initial programs.
+   Function returns 0 on success and -1 on error.  */
+int EBLHOOK(abi_cfi) (Ebl *ebl, Dwarf_CIE *abi_info);
+
+/* Fetch process data from live TID and call SETFUNC one or more times.
+   Method should be present only when EBL_FRAME_NREGS > 0, otherwise the
+   backend doesn't support unwinding.  */
+bool EBLHOOK(set_initial_registers_tid) (pid_t tid,
+					 ebl_tid_registers_t *setfunc,
+					 void *arg);
+
+/* Convert *REGNO as is in DWARF to a lower range suitable for
+   Dwarf_Frame->REGS indexing.  */
+bool EBLHOOK(dwarf_to_regno) (Ebl *ebl, unsigned *regno);
+
+/* Optionally modify *PC as fetched from inferior data into valid PC
+   instruction pointer.  */
+void EBLHOOK(normalize_pc) (Ebl *ebl, Dwarf_Addr *pc);
+
+/* Get previous frame state for an existing frame state.  Method is called only
+   if unwinder could not find CFI for current PC.  PC is for the
+   existing frame.  SETFUNC sets register in the previous frame.  GETFUNC gets
+   register from the existing frame.  Note that GETFUNC vs. SETFUNC act on
+   a disjunct set of registers.  READFUNC reads memory.  ARG has to be passed
+   for SETFUNC, GETFUNC and READFUNC.  *SIGNAL_FRAMEP is initialized to false,
+   it can be set to true if existing frame is a signal frame.  SIGNAL_FRAMEP is
+   never NULL.  */
+bool EBLHOOK(unwind) (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+		      ebl_tid_registers_get_t *getfunc,
+		      ebl_pid_memory_read_t *readfunc, void *arg,
+		      bool *signal_framep);
+
+/* Returns true if the value can be resolved to an address in an
+   allocated section, which will be returned in *ADDR.
+   (e.g. function descriptor resolving)  */
+bool EBLHOOK(resolve_sym_value) (Ebl *ebl, GElf_Addr *addr);
+
+/* Destructor for ELF backend handle.  */
+void EBLHOOK(destr) (struct ebl *);
diff --git a/libebl/ebl_check_special_section.c b/libebl/ebl_check_special_section.c
new file mode 100644
index 0000000..903b69d
--- /dev/null
+++ b/libebl/ebl_check_special_section.c
@@ -0,0 +1,41 @@
+/* Check for a special section allowed to violate generic constraints.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_check_special_section (Ebl *ebl, int ndx, const GElf_Shdr *shdr,
+			   const char *sname)
+{
+  return ebl != NULL && ebl->check_special_section (ebl, ndx, shdr, sname);
+}
diff --git a/libebl/ebl_check_special_symbol.c b/libebl/ebl_check_special_symbol.c
new file mode 100644
index 0000000..1f60c3f
--- /dev/null
+++ b/libebl/ebl_check_special_symbol.c
@@ -0,0 +1,45 @@
+/* Check special symbol's st_value.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <libeblP.h>
+
+
+bool
+ebl_check_special_symbol (Ebl *ebl, const GElf_Sym *sym,
+			  const char *name, const GElf_Shdr *destshdr)
+{
+  if (ebl == NULL)
+    return false;
+
+  return ebl->check_special_symbol (ebl->elf, sym, name, destshdr);
+}
diff --git a/libebl/ebl_data_marker_symbol.c b/libebl/ebl_data_marker_symbol.c
new file mode 100644
index 0000000..922d720
--- /dev/null
+++ b/libebl/ebl_data_marker_symbol.c
@@ -0,0 +1,44 @@
+/* Check whether a symbol is a special data marker.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <libeblP.h>
+
+
+bool
+ebl_data_marker_symbol (Ebl *ebl, const GElf_Sym *sym, const char *sname)
+{
+  if (ebl == NULL)
+    return false;
+
+  return ebl->data_marker_symbol (sym, sname);
+}
diff --git a/libebl/eblabicfi.c b/libebl/eblabicfi.c
new file mode 100644
index 0000000..8bf189f
--- /dev/null
+++ b/libebl/eblabicfi.c
@@ -0,0 +1,46 @@
+/* Return ABI-specific DWARF CFI details.
+   Copyright (C) 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+int
+ebl_abi_cfi (Ebl *ebl, Dwarf_CIE *abi_info)
+{
+  return ebl == NULL ? -1 : ebl->abi_cfi (ebl, abi_info);
+}
+
+int
+ebl_ra_offset (Ebl *ebl)
+{
+  return ebl->ra_offset;
+}
diff --git a/libebl/eblauxvinfo.c b/libebl/eblauxvinfo.c
new file mode 100644
index 0000000..ce1141b
--- /dev/null
+++ b/libebl/eblauxvinfo.c
@@ -0,0 +1,100 @@
+/* Describe known auxv types.
+   Copyright (C) 2007, 2008, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <byteswap.h>
+#include <endian.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <libeblP.h>
+
+#define AUXV_TYPES							      \
+  TYPE (NULL, "")							      \
+  TYPE (IGNORE, "")							      \
+  TYPE (EXECFD, "d")							      \
+  TYPE (EXECFN, "s")							      \
+  TYPE (PHDR, "p")							      \
+  TYPE (PHENT, "u")							      \
+  TYPE (PHNUM, "u")							      \
+  TYPE (PAGESZ, "u")							      \
+  TYPE (BASE, "p")							      \
+  TYPE (FLAGS, "x")							      \
+  TYPE (ENTRY, "p")							      \
+  TYPE (NOTELF, "")							      \
+  TYPE (UID, "u")							      \
+  TYPE (EUID, "u")							      \
+  TYPE (GID, "u")							      \
+  TYPE (EGID, "u")							      \
+  TYPE (CLKTCK, "u")							      \
+  TYPE (PLATFORM, "s")							      \
+  TYPE (BASE_PLATFORM, "s")						      \
+  TYPE (HWCAP, "x")							      \
+  TYPE (FPUCW, "x")							      \
+  TYPE (DCACHEBSIZE, "d")						      \
+  TYPE (ICACHEBSIZE, "d")						      \
+  TYPE (UCACHEBSIZE, "d")						      \
+  TYPE (IGNOREPPC, "")							      \
+  TYPE (SECURE, "u")							      \
+  TYPE (SYSINFO, "p")							      \
+  TYPE (SYSINFO_EHDR, "p")						      \
+  TYPE (L1I_CACHESHAPE, "d")						      \
+  TYPE (L1D_CACHESHAPE, "d")						      \
+  TYPE (L2_CACHESHAPE, "d")						      \
+  TYPE (L3_CACHESHAPE, "d")						      \
+  TYPE (RANDOM, "p")
+
+static const struct
+{
+  const char *name, *format;
+} auxv_types[] =
+  {
+#define TYPE(name, fmt) [AT_##name] = { #name, fmt },
+    AUXV_TYPES
+#undef	TYPE
+  };
+#define nauxv_types (sizeof auxv_types / sizeof auxv_types[0])
+
+int
+ebl_auxv_info (Ebl *ebl, GElf_Xword a_type, const char **name,
+	       const char **format)
+{
+  int result = ebl->auxv_info (a_type, name, format);
+  if (result == 0 && a_type < nauxv_types && auxv_types[a_type].name != NULL)
+    {
+      /* The machine specific function did not know this type.  */
+      *name = auxv_types[a_type].name;
+      *format = auxv_types[a_type].format;
+      result = 1;
+    }
+  return result;
+}
diff --git a/libebl/eblbackendname.c b/libebl/eblbackendname.c
new file mode 100644
index 0000000..e52b1e8
--- /dev/null
+++ b/libebl/eblbackendname.c
@@ -0,0 +1,42 @@
+/* Return backend name.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_backend_name (Ebl *ebl)
+{
+  return ebl != NULL ? ebl->emulation : _("No backend");
+}
diff --git a/libebl/eblbsspltp.c b/libebl/eblbsspltp.c
new file mode 100644
index 0000000..24c4a08
--- /dev/null
+++ b/libebl/eblbsspltp.c
@@ -0,0 +1,41 @@
+/* Check if backend uses a bss PLT.
+   Copyright (C) 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <libeblP.h>
+
+
+bool
+ebl_bss_plt_p (Ebl *ebl)
+{
+  return ebl == NULL ? false : ebl->bss_plt_p (ebl->elf);
+}
diff --git a/libebl/eblcheckobjattr.c b/libebl/eblcheckobjattr.c
new file mode 100644
index 0000000..b590a03
--- /dev/null
+++ b/libebl/eblcheckobjattr.c
@@ -0,0 +1,56 @@
+/* Check object attributes.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <libeblP.h>
+
+
+bool
+ebl_check_object_attribute (Ebl *ebl, const char *vendor, int tag,
+			    uint64_t value, const char **tag_name,
+			    const char **value_name)
+{
+  if (ebl->check_object_attribute (ebl, vendor, tag, value,
+				   tag_name, value_name))
+    return true;
+
+  if (strcmp (vendor, "gnu"))
+    return false;
+
+  if (tag == 32)
+    {
+      *tag_name = "compatibility";
+      return true;
+    }
+
+  return false;
+}
diff --git a/libebl/eblcheckreloctargettype.c b/libebl/eblcheckreloctargettype.c
new file mode 100644
index 0000000..068ad8f
--- /dev/null
+++ b/libebl/eblcheckreloctargettype.c
@@ -0,0 +1,55 @@
+/* Check whether a section type is a valid target for relocation.
+   Copyright (C) 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_check_reloc_target_type (Ebl *ebl, Elf64_Word sh_type)
+{
+  if (ebl->check_reloc_target_type (ebl, sh_type))
+    return true;
+
+  switch (sh_type)
+    {
+      case SHT_PROGBITS:
+      case SHT_NOBITS:
+      case SHT_INIT_ARRAY:
+      case SHT_FINI_ARRAY:
+      case SHT_PREINIT_ARRAY:
+      case SHT_NOTE:
+	return true;
+
+      default:
+	return false;
+    }
+}
diff --git a/libebl/eblclosebackend.c b/libebl/eblclosebackend.c
new file mode 100644
index 0000000..7fa068e
--- /dev/null
+++ b/libebl/eblclosebackend.c
@@ -0,0 +1,49 @@
+/* Free ELF backend handle.
+   Copyright (C) 2000, 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include <libeblP.h>
+
+
+void
+ebl_closebackend (Ebl *ebl)
+{
+  if (ebl != NULL)
+    {
+      /* Run the destructor.  */
+      ebl->destr (ebl);
+
+      /* Free the resources.  */
+      free (ebl);
+    }
+}
diff --git a/libebl/eblcopyrelocp.c b/libebl/eblcopyrelocp.c
new file mode 100644
index 0000000..0458c4f
--- /dev/null
+++ b/libebl/eblcopyrelocp.c
@@ -0,0 +1,41 @@
+/* Check whether given relocation is a copy relocation.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_copy_reloc_p (Ebl *ebl, int reloc)
+{
+  return ebl->copy_reloc_p (reloc);
+}
diff --git a/libebl/eblcorenote.c b/libebl/eblcorenote.c
new file mode 100644
index 0000000..7fab397
--- /dev/null
+++ b/libebl/eblcorenote.c
@@ -0,0 +1,79 @@
+/* Describe known core note formats.
+   Copyright (C) 2007, 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <byteswap.h>
+#include <endian.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <string.h>
+#include <libeblP.h>
+
+
+int
+ebl_core_note (Ebl *ebl, const GElf_Nhdr *nhdr, const char *name,
+	       const char *desc,
+	       GElf_Word *regs_offset, size_t *nregloc,
+	       const Ebl_Register_Location **reglocs, size_t *nitems,
+	       const Ebl_Core_Item **items)
+{
+  int result = ebl->core_note (nhdr, name,
+			       regs_offset, nregloc, reglocs, nitems, items);
+  if (result == 0)
+    {
+      /* The machine specific function did not know this type.  */
+
+      /* NT_PLATFORM is kind of special since it needs a zero terminated
+         string (other notes often have a fixed size string).  */
+      static const Ebl_Core_Item platform[] =
+	{
+	  {
+	    .name = "Platform",
+	    .type = ELF_T_BYTE, .count = 0, .format = 's'
+	  }
+	};
+
+      if (nhdr->n_type == NT_PLATFORM
+	  && memchr (desc, '\0', nhdr->n_descsz) != NULL)
+        {
+	  *regs_offset = 0;
+	  *nregloc = 0;
+	  *reglocs = NULL;
+	  *items = platform;
+	  *nitems = 1;
+	  result = 1;
+	}
+    }
+
+  return result;
+}
diff --git a/libebl/eblcorenotetypename.c b/libebl/eblcorenotetypename.c
new file mode 100644
index 0000000..0e790d0
--- /dev/null
+++ b/libebl/eblcorenotetypename.c
@@ -0,0 +1,107 @@
+/* Return note type name.
+   Copyright (C) 2002, 2007, 2008, 2012, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <libeblP.h>
+
+const char *
+ebl_core_note_type_name (Ebl *ebl, uint32_t type, char *buf, size_t len)
+{
+  const char *res = ebl->core_note_type_name (type, buf, len);
+
+  if (res == NULL)
+    {
+      static const char *knowntypes[] =
+	{
+#define KNOWNSTYPE(name) [NT_##name] = #name
+	  KNOWNSTYPE (PRSTATUS),
+	  KNOWNSTYPE (FPREGSET),
+	  KNOWNSTYPE (PRPSINFO),
+	  KNOWNSTYPE (TASKSTRUCT),
+	  KNOWNSTYPE (PLATFORM),
+	  KNOWNSTYPE (AUXV),
+	  KNOWNSTYPE (GWINDOWS),
+	  KNOWNSTYPE (ASRS),
+	  KNOWNSTYPE (PSTATUS),
+	  KNOWNSTYPE (PSINFO),
+	  KNOWNSTYPE (PRCRED),
+	  KNOWNSTYPE (UTSNAME),
+	  KNOWNSTYPE (LWPSTATUS),
+	  KNOWNSTYPE (LWPSINFO),
+	  KNOWNSTYPE (PRFPXREG)
+#undef KNOWNSTYPE
+	};
+
+      /* Handle standard names.  */
+      if (type < sizeof (knowntypes) / sizeof (knowntypes[0])
+	  && knowntypes[type] != NULL)
+	res = knowntypes[type];
+      else
+	switch (type)
+	  {
+#define KNOWNSTYPE(name) case NT_##name: res = #name; break
+	    KNOWNSTYPE (PRXFPREG);
+	    KNOWNSTYPE (PPC_VMX);
+	    KNOWNSTYPE (PPC_SPE);
+	    KNOWNSTYPE (PPC_VSX);
+	    KNOWNSTYPE (PPC_TM_SPR);
+	    KNOWNSTYPE (386_TLS);
+	    KNOWNSTYPE (386_IOPERM);
+	    KNOWNSTYPE (X86_XSTATE);
+	    KNOWNSTYPE (S390_HIGH_GPRS);
+	    KNOWNSTYPE (S390_TIMER);
+	    KNOWNSTYPE (S390_TODCMP);
+	    KNOWNSTYPE (S390_TODPREG);
+	    KNOWNSTYPE (S390_CTRS);
+	    KNOWNSTYPE (S390_PREFIX);
+	    KNOWNSTYPE (S390_LAST_BREAK);
+	    KNOWNSTYPE (S390_SYSTEM_CALL);
+	    KNOWNSTYPE (ARM_VFP);
+	    KNOWNSTYPE (ARM_TLS);
+	    KNOWNSTYPE (ARM_HW_BREAK);
+	    KNOWNSTYPE (ARM_HW_WATCH);
+	    KNOWNSTYPE (ARM_SYSTEM_CALL);
+	    KNOWNSTYPE (SIGINFO);
+	    KNOWNSTYPE (FILE);
+#undef KNOWNSTYPE
+
+	  default:
+	    snprintf (buf, len, "%s: %" PRIu32, _("<unknown>"), type);
+
+	    res = buf;
+	  }
+    }
+
+  return res;
+}
diff --git a/libebl/ebldebugscnp.c b/libebl/ebldebugscnp.c
new file mode 100644
index 0000000..2964fdb
--- /dev/null
+++ b/libebl/ebldebugscnp.c
@@ -0,0 +1,42 @@
+/* Check section name for being that of a debug informatino section.
+   Copyright (C) 2002, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <libeblP.h>
+
+
+bool
+ebl_debugscn_p (Ebl *ebl, const char *name)
+{
+  return name != NULL && ebl->debugscn_p (name);
+}
diff --git a/libebl/ebldwarftoregno.c b/libebl/ebldwarftoregno.c
new file mode 100644
index 0000000..c664496
--- /dev/null
+++ b/libebl/ebldwarftoregno.c
@@ -0,0 +1,40 @@
+/* Convert *REGNO as is in DWARF to a lower range.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+bool
+ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
+{
+  /* ebl is declared NN */
+  return ebl->dwarf_to_regno == NULL ? true : ebl->dwarf_to_regno (ebl, regno);
+}
diff --git a/libebl/ebldynamictagcheck.c b/libebl/ebldynamictagcheck.c
new file mode 100644
index 0000000..c2311cc
--- /dev/null
+++ b/libebl/ebldynamictagcheck.c
@@ -0,0 +1,54 @@
+/* Check dynamic tag.
+   Copyright (C) 2001, 2002, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <libeblP.h>
+
+
+bool
+ebl_dynamic_tag_check (Ebl *ebl, int64_t tag)
+{
+  bool res = ebl != NULL ? ebl->dynamic_tag_check (tag) : false;
+
+  if (!res
+      && ((tag >= 0 && tag < DT_NUM)
+	  || (tag >= DT_GNU_PRELINKED && tag <= DT_SYMINENT)
+	  || (tag >= DT_GNU_HASH && tag <= DT_SYMINFO)
+	  || tag == DT_VERSYM
+	  || (tag >= DT_RELACOUNT && tag <= DT_VERNEEDNUM)
+	  || tag == DT_AUXILIARY
+	  || tag == DT_FILTER))
+    res = true;
+
+  return res;
+}
diff --git a/libebl/ebldynamictagname.c b/libebl/ebldynamictagname.c
new file mode 100644
index 0000000..5d4a3a5
--- /dev/null
+++ b/libebl/ebldynamictagname.c
@@ -0,0 +1,111 @@
+/* Return dynamic tag name.
+   Copyright (C) 2001, 2002, 2006, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <libeblP.h>
+#include "system.h"
+
+
+const char *
+ebl_dynamic_tag_name (Ebl *ebl, int64_t tag, char *buf, size_t len)
+{
+  const char *res = ebl != NULL ? ebl->dynamic_tag_name (tag, buf, len) : NULL;
+
+  if (res == NULL)
+    {
+      if (tag >= 0 && tag < DT_NUM)
+	{
+	  static const char *stdtags[] =
+	    {
+	      "NULL", "NEEDED", "PLTRELSZ", "PLTGOT", "HASH", "STRTAB",
+	      "SYMTAB", "RELA", "RELASZ", "RELAENT", "STRSZ", "SYMENT",
+	      "INIT", "FINI", "SONAME", "RPATH", "SYMBOLIC", "REL", "RELSZ",
+	      "RELENT", "PLTREL", "DEBUG", "TEXTREL", "JMPREL", "BIND_NOW",
+	      "INIT_ARRAY", "FINI_ARRAY", "INIT_ARRAYSZ", "FINI_ARRAYSZ",
+	      "RUNPATH", "FLAGS", "ENCODING", "PREINIT_ARRAY",
+	      "PREINIT_ARRAYSZ", "SYMTAB_SHNDX", "RELRSZ", "RELR", "RELRENT"
+	    };
+	  eu_static_assert (sizeof (stdtags) / sizeof (const char *) == DT_NUM);
+
+	  res = stdtags[tag];
+	}
+      else if (tag == DT_VERSYM)
+	res = "VERSYM";
+      else if (tag >= DT_GNU_PRELINKED && tag <= DT_SYMINENT)
+	{
+	  static const char *valrntags[] =
+	    {
+	      "GNU_PRELINKED", "GNU_CONFLICTSZ", "GNU_LIBLISTSZ",
+	      "CHECKSUM", "PLTPADSZ", "MOVEENT", "MOVESZ", "FEATURE_1",
+	      "POSFLAG_1", "SYMINSZ", "SYMINENT"
+	    };
+
+	  res = valrntags[tag - DT_GNU_PRELINKED];
+	}
+      else if (tag >= DT_GNU_HASH && tag <= DT_SYMINFO)
+	{
+	  static const char *addrrntags[] =
+	    {
+	      "GNU_HASH", "TLSDESC_PLT", "TLSDESC_GOT",
+	      "GNU_CONFLICT", "GNU_LIBLIST", "CONFIG", "DEPAUDIT", "AUDIT",
+	      "PLTPAD", "MOVETAB", "SYMINFO"
+	    };
+
+	  res = addrrntags[tag - DT_GNU_HASH];
+	}
+      else if (tag >= DT_RELACOUNT && tag <= DT_VERNEEDNUM)
+	{
+	  static const char *suntags[] =
+	    {
+	      "RELACOUNT", "RELCOUNT", "FLAGS_1", "VERDEF", "VERDEFNUM",
+	      "VERNEED", "VERNEEDNUM"
+	    };
+
+	  res = suntags[tag - DT_RELACOUNT];
+	}
+      else if (tag == DT_AUXILIARY)
+	res = "AUXILIARY";
+      else if (tag == DT_FILTER)
+	res = "FILTER";
+      else
+	{
+	  snprintf (buf, len, _("<unknown>: %#" PRIx64), tag);
+
+	  res = buf;
+
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblelfclass.c b/libebl/eblelfclass.c
new file mode 100644
index 0000000..2ffef30
--- /dev/null
+++ b/libebl/eblelfclass.c
@@ -0,0 +1,41 @@
+/* Return ELF class.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+int
+ebl_get_elfclass (Ebl *ebl)
+{
+  return ebl->class;
+}
diff --git a/libebl/eblelfdata.c b/libebl/eblelfdata.c
new file mode 100644
index 0000000..072924b
--- /dev/null
+++ b/libebl/eblelfdata.c
@@ -0,0 +1,41 @@
+/* Return ELF data encoding.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+int
+ebl_get_elfdata (Ebl *ebl)
+{
+  return ebl->data;
+}
diff --git a/libebl/eblelfmachine.c b/libebl/eblelfmachine.c
new file mode 100644
index 0000000..c2c8627
--- /dev/null
+++ b/libebl/eblelfmachine.c
@@ -0,0 +1,41 @@
+/* Return ELF machine.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+int
+ebl_get_elfmachine (Ebl *ebl)
+{
+  return ebl->machine;
+}
diff --git a/libebl/eblgotpcreloccheck.c b/libebl/eblgotpcreloccheck.c
new file mode 100644
index 0000000..7c9c079
--- /dev/null
+++ b/libebl/eblgotpcreloccheck.c
@@ -0,0 +1,42 @@
+/* Return true if the symbol type is that referencing the GOT.  E.g.,
+   R_386_GOTPC.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_gotpc_reloc_check (Ebl *ebl, int reloc)
+{
+  return ebl != NULL ? ebl->gotpc_reloc_check (ebl->elf, reloc) : false;
+}
diff --git a/libebl/eblinitreg.c b/libebl/eblinitreg.c
new file mode 100644
index 0000000..8a3fb18
--- /dev/null
+++ b/libebl/eblinitreg.c
@@ -0,0 +1,59 @@
+/* Fetch live process Dwfl_Frame from PID.
+   Copyright (C) 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+#include <assert.h>
+
+bool
+ebl_set_initial_registers_tid (Ebl *ebl, pid_t tid,
+			       ebl_tid_registers_t *setfunc,
+			       void *arg)
+{
+  /* Otherwise caller could not allocate THREAD frame of proper size.
+     If set_initial_registers_tid is unsupported then FRAME_NREGS is zero.  */
+  assert (ebl->set_initial_registers_tid != NULL);
+  return ebl->set_initial_registers_tid (tid, setfunc, arg);
+}
+
+size_t
+ebl_frame_nregs (Ebl *ebl)
+{
+  /* ebl is declared NN */
+  return ebl->frame_nregs;
+}
+
+GElf_Addr
+ebl_func_addr_mask (Ebl *ebl)
+{
+  return ((ebl == NULL || ebl->func_addr_mask == 0)
+	  ? ~(GElf_Addr)0 : ebl->func_addr_mask);
+}
diff --git a/libebl/eblmachineflagcheck.c b/libebl/eblmachineflagcheck.c
new file mode 100644
index 0000000..e98b600
--- /dev/null
+++ b/libebl/eblmachineflagcheck.c
@@ -0,0 +1,41 @@
+/* Check machine flag.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_machine_flag_check (Ebl *ebl, Elf64_Word flags)
+{
+  return ebl != NULL ? ebl->machine_flag_check (flags) : (flags == 0);
+}
diff --git a/libebl/eblmachineflagname.c b/libebl/eblmachineflagname.c
new file mode 100644
index 0000000..02e11c6
--- /dev/null
+++ b/libebl/eblmachineflagname.c
@@ -0,0 +1,91 @@
+/* Return machine flag names.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <system.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_machine_flag_name (Ebl *ebl, Elf64_Word flags, char *buf, size_t len)
+{
+  const char *res;
+
+  if (flags == 0)
+    res = "";
+  else
+    {
+      Elf64_Word orig_flags = flags;
+      char *cp = buf;
+      bool first = true;
+      const char *machstr;
+      size_t machstrlen;
+
+      do
+	{
+	  if (! first)
+	    {
+	      if (cp + 2 >= buf + len)
+		break;
+	      *cp++ = ',';
+	      *cp++ = ' ';
+	    }
+
+	  machstr = ebl != NULL ? ebl->machine_flag_name (orig_flags, &flags) : NULL;
+	  if (machstr == NULL)
+	    {
+	      /* No more known flag.  */
+	      snprintf (cp, buf + len - cp, "%#x", flags);
+	      break;
+	    }
+
+	  machstrlen = strlen (machstr) + 1;
+	  if ((size_t) (buf + len - cp) < machstrlen)
+	    {
+	      *((char *) mempcpy (cp, machstr, buf + len - cp - 1)) = '\0';
+	      break;
+	    }
+
+	  cp = mempcpy (cp, machstr, machstrlen);
+	  --cp;
+
+	  first = false;
+	}
+      while (flags != 0);
+
+      res = buf;
+    }
+
+  return res;
+}
diff --git a/libebl/eblmachinesectionflagcheck.c b/libebl/eblmachinesectionflagcheck.c
new file mode 100644
index 0000000..a73b230
--- /dev/null
+++ b/libebl/eblmachinesectionflagcheck.c
@@ -0,0 +1,40 @@
+/* Check SHF_MASKPROC flags.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_machine_section_flag_check (Ebl *ebl, GElf_Xword flags)
+{
+  return ebl != NULL ? ebl->machine_section_flag_check (flags) : (flags == 0);
+}
diff --git a/libebl/eblnonerelocp.c b/libebl/eblnonerelocp.c
new file mode 100644
index 0000000..e51a3b0
--- /dev/null
+++ b/libebl/eblnonerelocp.c
@@ -0,0 +1,41 @@
+/* Check whether given relocation is a no-op relocation.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2006.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_none_reloc_p (Ebl *ebl, int reloc)
+{
+  return ebl->none_reloc_p (reloc);
+}
diff --git a/libebl/eblnormalizepc.c b/libebl/eblnormalizepc.c
new file mode 100644
index 0000000..1629353
--- /dev/null
+++ b/libebl/eblnormalizepc.c
@@ -0,0 +1,41 @@
+/* Modify PC as fetched from inferior data into valid PC.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+void
+ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+{
+  /* ebl is declared NN */
+  if (ebl->normalize_pc != NULL)
+    ebl->normalize_pc (ebl, pc);
+}
diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c
new file mode 100644
index 0000000..1ba5d8b
--- /dev/null
+++ b/libebl/eblobjnote.c
@@ -0,0 +1,662 @@
+/* Print contents of object file note.
+   Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <libeblP.h>
+
+#include "common.h"
+#include "libelfP.h"
+#include "libdwP.h"
+#include "memory-access.h"
+
+
+void
+ebl_object_note (Ebl *ebl, uint32_t namesz, const char *name, uint32_t type,
+		 uint32_t descsz, const char *desc)
+{
+  if (! ebl->object_note (name, type, descsz, desc))
+    {
+      /* The machine specific function did not know this type.  */
+
+      if (strcmp ("stapsdt", name) == 0)
+	{
+	  if (type != 3)
+	    {
+	      printf (_("unknown SDT version %u\n"), type);
+	      return;
+	    }
+
+	  /* Descriptor starts with three addresses, pc, base ref and
+	     semaphore.  Then three zero terminated strings provider,
+	     name and arguments.  */
+
+	  union
+	  {
+	    Elf64_Addr a64[3];
+	    Elf32_Addr a32[3];
+	  } addrs;
+
+	  size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT);
+	  if (descsz < addrs_size + 3)
+	    {
+	    invalid_sdt:
+	      printf (_("invalid SDT probe descriptor\n"));
+	      return;
+	    }
+
+	  Elf_Data src =
+	    {
+	      .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+	      .d_buf = (void *) desc, .d_size = addrs_size
+	    };
+
+	  Elf_Data dst =
+	    {
+	      .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+	      .d_buf = &addrs, .d_size = addrs_size
+	    };
+
+	  if (gelf_xlatetom (ebl->elf, &dst, &src,
+			     elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL)
+	    {
+	      printf ("%s\n", elf_errmsg (-1));
+	      return;
+	    }
+
+	  const char *provider = desc + addrs_size;
+	  const char *pname = memchr (provider, '\0', desc + descsz - provider);
+	  if (pname == NULL)
+	    goto invalid_sdt;
+
+	  ++pname;
+	  const char *args = memchr (pname, '\0', desc + descsz - pname);
+	  if (args == NULL ||
+	      memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1)
+	    goto invalid_sdt;
+
+	  GElf_Addr pc;
+	  GElf_Addr base;
+	  GElf_Addr sem;
+	  if (gelf_getclass (ebl->elf) == ELFCLASS32)
+	    {
+	      pc = addrs.a32[0];
+	      base = addrs.a32[1];
+	      sem = addrs.a32[2];
+	    }
+	  else
+	    {
+	      pc = addrs.a64[0];
+	      base = addrs.a64[1];
+	      sem = addrs.a64[2];
+	    }
+
+	  printf (_("    PC: "));
+	  printf ("%#" PRIx64 ",", pc);
+	  printf (_(" Base: "));
+	  printf ("%#" PRIx64 ",", base);
+	  printf (_(" Semaphore: "));
+	  printf ("%#" PRIx64 "\n", sem);
+	  printf (_("    Provider: "));
+	  printf ("%s,", provider);
+	  printf (_(" Name: "));
+	  printf ("%s,", pname);
+	  printf (_(" Args: "));
+	  printf ("'%s'\n", args);
+	  return;
+	}
+
+      if (strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
+		   strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0
+	  && (type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+	      || type == NT_GNU_BUILD_ATTRIBUTE_FUNC))
+	{
+	  /* There might or might not be a pair of addresses in the desc.  */
+	  if (descsz > 0)
+	    {
+	      printf ("    Address Range: ");
+
+	      union
+	      {
+		Elf64_Addr a64[2];
+		Elf32_Addr a32[2];
+	      } addrs;
+
+	      size_t addr_size = gelf_fsize (ebl->elf, ELF_T_ADDR,
+					     1, EV_CURRENT);
+	      if (descsz != addr_size * 2)
+		printf ("<unknown data>\n");
+	      else
+		{
+		  Elf_Data src =
+		    {
+		     .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+		     .d_buf = (void *) desc, .d_size = descsz
+		    };
+
+		  Elf_Data dst =
+		    {
+		     .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+		     .d_buf = &addrs, .d_size = descsz
+		    };
+
+		  if (gelf_xlatetom (ebl->elf, &dst, &src,
+				     elf_getident (ebl->elf,
+						   NULL)[EI_DATA]) == NULL)
+		    printf ("%s\n", elf_errmsg (-1));
+		  else
+		    {
+		      if (addr_size == 4)
+			printf ("%#" PRIx32 " - %#" PRIx32 "\n",
+				addrs.a32[0], addrs.a32[1]);
+		      else
+			printf ("%#" PRIx64 " - %#" PRIx64 "\n",
+				addrs.a64[0], addrs.a64[1]);
+		    }
+		}
+	    }
+
+	  /* Most data actually is inside the name.
+	     https://fedoraproject.org/wiki/Toolchain/Watermark  */
+
+	  /* We need at least 2 chars of data to describe the
+	     attribute and value encodings.  */
+	  const char *data = (name
+			      + strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX));
+	  if (namesz < 2)
+	    {
+	      printf ("<insufficient data>\n");
+	      return;
+	    }
+
+	  printf ("    ");
+
+	  /* In most cases the value comes right after the encoding bytes.  */
+	  const char *value = &data[2];
+	  switch (data[1])
+	    {
+	    case GNU_BUILD_ATTRIBUTE_VERSION:
+	      printf ("VERSION: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+	      printf ("STACK_PROT: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_RELRO:
+	      printf ("RELRO: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
+	      printf ("STACK_SIZE: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_TOOL:
+	      printf ("TOOL: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_ABI:
+	      printf ("ABI: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_PIC:
+	      printf ("PIC: ");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_SHORT_ENUM:
+	      printf ("SHORT_ENUM: ");
+	      break;
+	    case 32 ... 126:
+	      printf ("\"%s\": ", &data[1]);
+	      value += strlen (&data[1]) + 1;
+	      break;
+	    default:
+	      printf ("<unknown>: ");
+	      break;
+	    }
+
+	  switch (data[0])
+	    {
+	    case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
+	      {
+		/* Any numbers are always in (unsigned) little endian.  */
+		static const Dwarf dbg
+		  = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
+		size_t bytes = namesz - (value - name);
+		uint64_t val;
+		if (bytes == 1)
+		  val = *(unsigned char *) value;
+		else if (bytes == 2)
+		  val = read_2ubyte_unaligned (&dbg, value);
+		else if (bytes == 4)
+		  val = read_4ubyte_unaligned (&dbg, value);
+		else if (bytes == 8)
+		  val = read_8ubyte_unaligned (&dbg, value);
+		else
+		  goto unknown;
+		printf ("%" PRIx64, val);
+	      }
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
+	      printf ("\"%s\"", value);
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
+	      printf ("TRUE");
+	      break;
+	    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
+	      printf ("FALSE");
+	      break;
+	    default:
+	      {
+	      unknown:
+		printf ("<unknown>");
+	      }
+	      break;
+	    }
+
+	  printf ("\n");
+
+	  return;
+	}
+
+      /* NT_VERSION doesn't have any info.  All data is in the name.  */
+      if (descsz == 0 && type == NT_VERSION)
+	return;
+
+      if (strcmp ("FDO", name) == 0 && type == NT_FDO_PACKAGING_METADATA
+	  && descsz > 0 && desc[descsz - 1] == '\0')
+	printf("    Packaging Metadata: %.*s\n", (int) descsz, desc);
+
+      /* Everything else should have the "GNU" owner name.  */
+      if (strcmp ("GNU", name) != 0)
+	return;
+
+      switch (type)
+	{
+	case NT_GNU_BUILD_ID:
+	  if (strcmp (name, "GNU") == 0 && descsz > 0)
+	    {
+	      printf (_("    Build ID: "));
+	      uint_fast32_t i;
+	      for (i = 0; i < descsz - 1; ++i)
+		printf ("%02" PRIx8, (uint8_t) desc[i]);
+	      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+	    }
+	  break;
+
+	case NT_GNU_GOLD_VERSION:
+	  if (strcmp (name, "GNU") == 0 && descsz > 0)
+	    /* A non-null terminated version string.  */
+	    printf (_("    Linker version: %.*s\n"),
+		    (int) descsz, desc);
+	  break;
+
+	case NT_GNU_PROPERTY_TYPE_0:
+	  if (strcmp (name, "GNU") == 0 && descsz > 0)
+	    {
+	      /* There are at least 2 words. type and datasz.  */
+	      while (descsz >= 8)
+		{
+		  struct pr_prop
+		  {
+		    GElf_Word pr_type;
+		    GElf_Word pr_datasz;
+		  } prop;
+
+		  Elf_Data in =
+		    {
+		      .d_version = EV_CURRENT,
+		      .d_type = ELF_T_WORD,
+		      .d_size = 8,
+		      .d_buf = (void *) desc
+		    };
+		  Elf_Data out =
+		    {
+		      .d_version = EV_CURRENT,
+		      .d_type = ELF_T_WORD,
+		      .d_size = descsz,
+		      .d_buf = (void *) &prop
+		    };
+
+		  if (gelf_xlatetom (ebl->elf, &out, &in,
+				     elf_getident (ebl->elf,
+						   NULL)[EI_DATA]) == NULL)
+		    {
+		      printf ("%s\n", elf_errmsg (-1));
+		      return;
+		    }
+
+		  desc += 8;
+		  descsz -= 8;
+
+		  if (prop.pr_datasz > descsz)
+		    {
+		      printf ("BAD property datasz: %" PRId32 "\n",
+			      prop.pr_datasz);
+		      return;
+		    }
+
+		  int elfclass = gelf_getclass (ebl->elf);
+		  char *elfident = elf_getident (ebl->elf, NULL);
+		  GElf_Ehdr ehdr;
+		  gelf_getehdr (ebl->elf, &ehdr);
+
+		  /* Prefix.  */
+		  printf ("    ");
+		  if (prop.pr_type == GNU_PROPERTY_STACK_SIZE)
+		    {
+		      printf ("STACK_SIZE ");
+		      union
+			{
+			  Elf64_Addr a64;
+			  Elf32_Addr a32;
+			} addr;
+		      if ((elfclass == ELFCLASS32 && prop.pr_datasz == 4)
+			  || (elfclass == ELFCLASS64 && prop.pr_datasz == 8))
+			{
+			  in.d_type = ELF_T_ADDR;
+			  out.d_type = ELF_T_ADDR;
+			  in.d_size = prop.pr_datasz;
+			  out.d_size = prop.pr_datasz;
+			  in.d_buf = (void *) desc;
+			  out.d_buf = (elfclass == ELFCLASS32
+				       ? (void *) &addr.a32
+				       : (void *) &addr.a64);
+
+			  if (gelf_xlatetom (ebl->elf, &out, &in,
+					     elfident[EI_DATA]) == NULL)
+			    {
+			      printf ("%s\n", elf_errmsg (-1));
+			      return;
+			    }
+			  if (elfclass == ELFCLASS32)
+			    printf ("%#" PRIx32 "\n", addr.a32);
+			  else
+			    printf ("%#" PRIx64 "\n", addr.a64);
+			}
+		      else
+			printf (" (garbage datasz: %" PRIx32 ")\n",
+				prop.pr_datasz);
+		    }
+		  else if (prop.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
+		    {
+		      printf ("NO_COPY_ON_PROTECTION");
+		      if (prop.pr_datasz == 0)
+			printf ("\n");
+		      else
+			printf (" (garbage datasz: %" PRIx32 ")\n",
+				prop.pr_datasz);
+		    }
+		  else if (prop.pr_type >= GNU_PROPERTY_LOPROC
+		      && prop.pr_type <= GNU_PROPERTY_HIPROC
+		      && (ehdr.e_machine == EM_386
+			  || ehdr.e_machine == EM_X86_64))
+		    {
+		      printf ("X86 ");
+		      if (prop.pr_type == GNU_PROPERTY_X86_FEATURE_1_AND)
+			{
+			  printf ("FEATURE_1_AND: ");
+
+			  if (prop.pr_datasz == 4)
+			    {
+			      GElf_Word data;
+			      in.d_type = ELF_T_WORD;
+			      out.d_type = ELF_T_WORD;
+			      in.d_size = 4;
+			      out.d_size = 4;
+			      in.d_buf = (void *) desc;
+			      out.d_buf = (void *) &data;
+
+			      if (gelf_xlatetom (ebl->elf, &out, &in,
+						 elfident[EI_DATA]) == NULL)
+				{
+				  printf ("%s\n", elf_errmsg (-1));
+				  return;
+				}
+			      printf ("%08" PRIx32 " ", data);
+
+			      if ((data & GNU_PROPERTY_X86_FEATURE_1_IBT)
+				  != 0)
+				{
+				  printf ("IBT");
+				  data &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
+				  if (data != 0)
+				    printf (" ");
+				}
+
+			      if ((data & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
+				  != 0)
+				{
+				  printf ("SHSTK");
+				  data &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+				  if (data != 0)
+				    printf (" ");
+				}
+
+			      if (data != 0)
+				printf ("UNKNOWN");
+			    }
+			  else
+			    printf ("<bad datasz: %" PRId32 ">",
+				    prop.pr_datasz);
+
+			  printf ("\n");
+			}
+		      else
+			{
+			  printf ("%#" PRIx32, prop.pr_type);
+			  if (prop.pr_datasz > 0)
+			    {
+			      printf (" data: ");
+			      size_t i;
+			      for (i = 0; i < prop.pr_datasz - 1; i++)
+				printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
+			      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+			    }
+			}
+		    }
+		  else if (prop.pr_type >= GNU_PROPERTY_LOPROC
+			   && prop.pr_type <= GNU_PROPERTY_HIPROC
+			   && ehdr.e_machine == EM_AARCH64)
+		    {
+		      printf ("AARCH64 ");
+		      if (prop.pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
+			{
+			  printf ("FEATURE_1_AND: ");
+
+			  if (prop.pr_datasz == 4)
+			    {
+			      GElf_Word data;
+			      in.d_type = ELF_T_WORD;
+			      out.d_type = ELF_T_WORD;
+			      in.d_size = 4;
+			      out.d_size = 4;
+			      in.d_buf = (void *) desc;
+			      out.d_buf = (void *) &data;
+
+			      if (gelf_xlatetom (ebl->elf, &out, &in,
+						 elfident[EI_DATA]) == NULL)
+				{
+				  printf ("%s\n", elf_errmsg (-1));
+				  return;
+				}
+			      printf ("%08" PRIx32 " ", data);
+
+			      if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
+				  != 0)
+				{
+				  printf ("BTI");
+				  data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
+				  if (data != 0)
+				    printf (" ");
+				}
+
+			      if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
+				  != 0)
+				{
+				  printf ("PAC");
+				  data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
+				  if (data != 0)
+				    printf (" ");
+				}
+
+			      if (data != 0)
+				printf ("UNKNOWN");
+			    }
+			  else
+			    printf ("<bad datasz: %" PRId32 ">",
+				    prop.pr_datasz);
+
+			  printf ("\n");
+			}
+		      else
+			{
+			  printf ("%#" PRIx32, prop.pr_type);
+			  if (prop.pr_datasz > 0)
+			    {
+			      printf (" data: ");
+			      size_t i;
+			      for (i = 0; i < prop.pr_datasz - 1; i++)
+				printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
+			      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+			    }
+			}
+		    }
+		  else
+		    {
+		      if (prop.pr_type >= GNU_PROPERTY_LOPROC
+			  && prop.pr_type <= GNU_PROPERTY_HIPROC)
+			printf ("proc_type %#" PRIx32, prop.pr_type);
+		      else if (prop.pr_type >= GNU_PROPERTY_LOUSER
+			  && prop.pr_type <= GNU_PROPERTY_HIUSER)
+			printf ("app_type %#" PRIx32, prop.pr_type);
+		      else
+			printf ("unknown_type %#" PRIx32, prop.pr_type);
+
+		      if (prop.pr_datasz > 0)
+			{
+			  printf (" data: ");
+			  size_t i;
+			  for (i = 0; i < prop.pr_datasz - 1; i++)
+			    printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
+			  printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+			}
+		    }
+
+		  if (elfclass == ELFCLASS32)
+		    prop.pr_datasz = NOTE_ALIGN4 (prop.pr_datasz);
+		  else
+		    prop.pr_datasz = NOTE_ALIGN8 (prop.pr_datasz);
+
+		  desc += prop.pr_datasz;
+		  if (descsz > prop.pr_datasz)
+		    descsz -= prop.pr_datasz;
+		  else
+		    descsz = 0;
+		}
+	    }
+	  break;
+
+	case NT_GNU_ABI_TAG:
+	  if (descsz >= 8 && descsz % 4 == 0)
+	    {
+	      Elf_Data in =
+		{
+		  .d_version = EV_CURRENT,
+		  .d_type = ELF_T_WORD,
+		  .d_size = descsz,
+		  .d_buf = (void *) desc
+		};
+	      /* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes).  If it
+		 is much (4*) larger dynamically allocate memory to convert.  */
+#define FIXED_TAG_BYTES 16
+	      uint32_t sbuf[FIXED_TAG_BYTES];
+	      uint32_t *buf;
+	      if (unlikely (descsz / 4 > FIXED_TAG_BYTES))
+		{
+		  buf = malloc (descsz);
+		  if (unlikely (buf == NULL))
+		    return;
+		}
+	      else
+		buf = sbuf;
+	      Elf_Data out =
+		{
+		  .d_version = EV_CURRENT,
+		  .d_type = ELF_T_WORD,
+		  .d_size = descsz,
+		  .d_buf = buf
+		};
+
+	      if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
+		{
+		  const char *os;
+		  switch (buf[0])
+		    {
+		    case ELF_NOTE_OS_LINUX:
+		      os = "Linux";
+		      break;
+
+		    case ELF_NOTE_OS_GNU:
+		      os = "GNU";
+		      break;
+
+		    case ELF_NOTE_OS_SOLARIS2:
+		      os = "Solaris";
+		      break;
+
+		    case ELF_NOTE_OS_FREEBSD:
+		      os = "FreeBSD";
+		      break;
+
+		    default:
+		      os = "???";
+		      break;
+		    }
+
+		  printf (_("    OS: %s, ABI: "), os);
+		  for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
+		    {
+		      if (cnt > 1)
+			putchar_unlocked ('.');
+		      printf ("%" PRIu32, buf[cnt]);
+		    }
+		  putchar_unlocked ('\n');
+		}
+	      if (descsz / 4 > FIXED_TAG_BYTES)
+		free (buf);
+	      break;
+	    }
+	  FALLTHROUGH;
+
+	default:
+	  /* Unknown type.  */
+	  break;
+	}
+    }
+}
diff --git a/libebl/eblobjnotetypename.c b/libebl/eblobjnotetypename.c
new file mode 100644
index 0000000..473a1f2
--- /dev/null
+++ b/libebl/eblobjnotetypename.c
@@ -0,0 +1,141 @@
+/* Return note type name.
+   Copyright (C) 2002, 2007, 2009, 2011, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_object_note_type_name (Ebl *ebl, const char *name, uint32_t type,
+			   GElf_Word descsz,
+			   char *buf, size_t len)
+{
+  const char *res = ebl->object_note_type_name (name, type, buf, len);
+
+  if (res == NULL)
+    {
+      if (strcmp (name, "stapsdt") == 0)
+	{
+	  snprintf (buf, len, "Version: %" PRIu32, type);
+	  return buf;
+	}
+
+#define ELF_NOTE_GOPKGLIST 1
+#define ELF_NOTE_GOABIHASH 2
+#define ELF_NOTE_GODEPS    3
+#define ELF_NOTE_GOBUILDID 4
+
+      static const char *goknowntypes[] =
+	{
+#define KNOWNSTYPE(name) [ELF_NOTE_GO##name] = #name
+	  KNOWNSTYPE (PKGLIST),
+	  KNOWNSTYPE (ABIHASH),
+	  KNOWNSTYPE (DEPS),
+	  KNOWNSTYPE (BUILDID),
+#undef KNOWNSTYPE
+	};
+
+      if (strcmp (name, "Go") == 0)
+	{
+	  if (type < sizeof (goknowntypes) / sizeof (goknowntypes[0])
+	      && goknowntypes[type] != NULL)
+	    return goknowntypes[type];
+	  else
+	    {
+	      snprintf (buf, len, "%s: %" PRIu32, _("<unknown>"), type);
+	      return buf;
+	    }
+	}
+
+      if (startswith (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX))
+	{
+	  /* GNU Build Attribute notes (ab)use the owner name to store
+	     most of their data.  Don't decode everything here.  Just
+	     the type.*/
+	  char *t = buf;
+	  const char *gba = "GNU Build Attribute";
+	  int w = snprintf (t, len, "%s ", gba);
+	  t += w;
+	  len -= w;
+	  if (type == NT_GNU_BUILD_ATTRIBUTE_OPEN)
+	    snprintf (t, len, "OPEN");
+	  else if (type == NT_GNU_BUILD_ATTRIBUTE_FUNC)
+	    snprintf (t, len, "FUNC");
+	  else
+	    snprintf (t, len, "%x", type);
+
+	  return buf;
+	}
+
+      if (strcmp (name, "FDO") == 0 && type == NT_FDO_PACKAGING_METADATA)
+	return "FDO_PACKAGING_METADATA";
+
+      if (strcmp (name, "GNU") != 0)
+	{
+	  /* NT_VERSION is special, all data is in the name.  */
+	  if (descsz == 0 && type == NT_VERSION)
+	    return "VERSION";
+
+	  snprintf (buf, len, "%s: %" PRIu32, _("<unknown>"), type);
+	  return buf;
+	}
+
+      /* And finally all the "GNU" note types.  */
+      static const char *knowntypes[] =
+	{
+#define KNOWNSTYPE(name) [NT_##name] = #name
+	  KNOWNSTYPE (GNU_ABI_TAG),
+	  KNOWNSTYPE (GNU_HWCAP),
+	  KNOWNSTYPE (GNU_BUILD_ID),
+	  KNOWNSTYPE (GNU_GOLD_VERSION),
+	  KNOWNSTYPE (GNU_PROPERTY_TYPE_0),
+	};
+
+      /* Handle standard names.  */
+      if (type < sizeof (knowntypes) / sizeof (knowntypes[0])
+	  && knowntypes[type] != NULL)
+	res = knowntypes[type];
+      else
+	{
+	  snprintf (buf, len, "%s: %" PRIu32, _("<unknown>"), type);
+
+	  res = buf;
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
new file mode 100644
index 0000000..084a154
--- /dev/null
+++ b/libebl/eblopenbackend.c
@@ -0,0 +1,717 @@
+/* Generate ELF backend handle.
+   Copyright (C) 2000-2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <libelfP.h>
+#include <dwarf.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#include <system.h>
+#include <libeblP.h>
+
+Ebl *i386_init (Elf *, GElf_Half, Ebl *);
+Ebl *sh_init (Elf *, GElf_Half, Ebl *);
+Ebl *x86_64_init (Elf *, GElf_Half, Ebl *);
+Ebl *ia64_init (Elf *, GElf_Half, Ebl *);
+Ebl *alpha_init (Elf *, GElf_Half, Ebl *);
+Ebl *arm_init (Elf *, GElf_Half, Ebl *);
+Ebl *aarch64_init (Elf *, GElf_Half, Ebl *);
+Ebl *sparc_init (Elf *, GElf_Half, Ebl *);
+Ebl *ppc_init (Elf *, GElf_Half, Ebl *);
+Ebl *ppc64_init (Elf *, GElf_Half, Ebl *);
+Ebl *s390_init (Elf *, GElf_Half, Ebl *);
+Ebl *m68k_init (Elf *, GElf_Half, Ebl *);
+Ebl *bpf_init (Elf *, GElf_Half, Ebl *);
+Ebl *riscv_init (Elf *, GElf_Half, Ebl *);
+Ebl *csky_init (Elf *, GElf_Half, Ebl *);
+Ebl *loongarch_init (Elf *, GElf_Half, Ebl *);
+Ebl *arc_init (Elf *, GElf_Half, Ebl *);
+
+/* This table should contain the complete list of architectures as far
+   as the ELF specification is concerned.  */
+/* XXX When things are stable replace the string pointers with char
+   arrays to avoid relocations.  */
+static const struct
+{
+  ebl_bhinit_t init;
+  const char *emulation;
+  const char *prefix;
+  int prefix_len;
+  int em;
+  int class;
+  int data;
+} machines[] =
+{
+  { i386_init, "elf_i386", "i386", 4, EM_386, ELFCLASS32, ELFDATA2LSB },
+  { ia64_init, "elf_ia64", "ia64", 4, EM_IA_64, ELFCLASS64, ELFDATA2LSB },
+  { alpha_init, "elf_alpha", "alpha", 5, EM_ALPHA, ELFCLASS64, ELFDATA2LSB },
+  { x86_64_init, "elf_x86_64", "x86_64", 6, EM_X86_64, ELFCLASS64, ELFDATA2LSB },
+  { ppc_init, "elf_ppc", "ppc", 3, EM_PPC, ELFCLASS32, ELFDATA2MSB },
+  { ppc64_init, "elf_ppc64", "ppc64", 5, EM_PPC64, ELFCLASS64, ELFDATA2MSB },
+  // XXX class and machine fields need to be filled in for all archs.
+  { sh_init, "elf_sh", "sh", 2, EM_SH, 0, 0 },
+  { arm_init, "ebl_arm", "arm", 3, EM_ARM, 0, 0 },
+  { sparc_init, "elf_sparcv9", "sparc", 5, EM_SPARCV9, 0, 0 },
+  { sparc_init, "elf_sparc", "sparc", 5, EM_SPARC, 0, 0 },
+  { sparc_init, "elf_sparcv8plus", "sparc", 5, EM_SPARC32PLUS, 0, 0 },
+  { s390_init, "ebl_s390", "s390", 4, EM_S390, 0, 0 },
+
+  { NULL, "elf_tilegx", "tilegx", 6, EM_TILEGX, ELFCLASS64, ELFDATA2LSB },
+  { NULL, "elf_m32", "m32", 3, EM_M32, 0, 0 },
+  { m68k_init, "elf_m68k", "m68k", 4, EM_68K, ELFCLASS32, ELFDATA2MSB },
+  { NULL, "elf_m88k", "m88k", 4, EM_88K, 0, 0 },
+  { NULL, "elf_i860", "i860", 4, EM_860, 0, 0 },
+  { NULL, "ebl_s370", "s370", 4, EM_S370, 0, 0 },
+  { NULL, "elf_parisc", "parisc", 6, EM_PARISC, 0, 0 },
+  { NULL, "elf_vpp500", "vpp500", 5, EM_VPP500, 0, 0 },
+  { sparc_init, "elf_v8plus", "v8plus", 6, EM_SPARC32PLUS, 0, 0 },
+  { NULL, "elf_i960", "i960", 4, EM_960, 0, 0 },
+  { NULL, "ebl_v800", "v800", 4, EM_V800, 0, 0 },
+  { NULL, "ebl_fr20", "fr20", 4, EM_FR20, 0, 0 },
+  { NULL, "ebl_rh32", "rh32", 4, EM_RH32, 0, 0 },
+  { NULL, "ebl_rce", "rce", 3, EM_RCE, 0, 0 },
+  { NULL, "elf_tricore", "tricore", 7, EM_TRICORE, 0, 0 },
+  { NULL, "elf_arc", "arc", 3, EM_ARC, 0, 0 },
+  { NULL, "elf_h8_300", "h8_300", 6, EM_H8_300, 0, 0 },
+  { NULL, "elf_h8_300h", "h8_300h", 6, EM_H8_300H, 0, 0 },
+  { NULL, "elf_h8s", "h8s", 6, EM_H8S, 0, 0 },
+  { NULL, "elf_h8_500", "h8_500", 6, EM_H8_500, 0, 0 },
+  { NULL, "elf_coldfire", "coldfire", 8, EM_COLDFIRE, 0, 0 },
+  { m68k_init, "elf_68hc12", "68hc12", 6, EM_68HC12, 0, 0 },
+  { NULL, "elf_mma", "mma", 3, EM_MMA, 0, 0 },
+  { NULL, "elf_pcp", "pcp", 3, EM_PCP, 0, 0 },
+  { NULL, "elf_ncpu", "ncpu", 4, EM_NCPU, 0, 0 },
+  { NULL, "elf_ndr1", "ndr1", 4, EM_NDR1, 0, 0 },
+  { NULL, "elf_starcore", "starcore", 8, EM_STARCORE, 0, 0 },
+  { NULL, "elf_me16", "em16", 4, EM_ME16, 0, 0 },
+  { NULL, "elf_st100", "st100", 5, EM_ST100, 0, 0 },
+  { NULL, "elf_tinyj", "tinyj", 5, EM_TINYJ, 0, 0 },
+  { NULL, "elf_pdsp", "pdsp", 4, EM_PDSP, 0, 0 },
+  { NULL, "elf_fx66", "fx66", 4, EM_FX66, 0, 0 },
+  { NULL, "elf_st9plus", "st9plus", 7, EM_ST9PLUS, 0, 0 },
+  { NULL, "elf_st7", "st7", 3, EM_ST7, 0, 0 },
+  { m68k_init, "elf_68hc16", "68hc16", 6, EM_68HC16, 0, 0 },
+  { m68k_init, "elf_68hc11", "68hc11", 6, EM_68HC11, 0, 0 },
+  { m68k_init, "elf_68hc08", "68hc08", 6, EM_68HC08, 0, 0 },
+  { m68k_init, "elf_68hc05", "68hc05", 6, EM_68HC05, 0, 0 },
+  { NULL, "elf_svx", "svx", 3, EM_SVX, 0, 0 },
+  { NULL, "elf_st19", "st19", 4, EM_ST19, 0, 0 },
+  { NULL, "elf_vax", "vax", 3, EM_VAX, 0, 0 },
+  { NULL, "elf_cris", "cris", 4, EM_CRIS, 0, 0 },
+  { NULL, "elf_javelin", "javelin", 7, EM_JAVELIN, 0, 0 },
+  { NULL, "elf_firepath", "firepath", 8, EM_FIREPATH, 0, 0 },
+  { NULL, "elf_zsp", "zsp", 3, EM_ZSP, 0, 0 },
+  { NULL, "elf_mmix", "mmix", 4, EM_MMIX, 0, 0 },
+  { NULL, "elf_huany", "huany", 5, EM_HUANY, 0, 0 },
+  { NULL, "elf_prism", "prism", 5, EM_PRISM, 0, 0 },
+  { NULL, "elf_avr", "avr", 3, EM_AVR, 0, 0 },
+  { NULL, "elf_fr30", "fr30", 4, EM_FR30, 0, 0 },
+  { NULL, "elf_dv10", "dv10", 4, EM_D10V, 0, 0 },
+  { NULL, "elf_dv30", "dv30", 4, EM_D30V, 0, 0 },
+  { NULL, "elf_v850", "v850", 4, EM_V850, 0, 0 },
+  { NULL, "elf_m32r", "m32r", 4, EM_M32R, 0, 0 },
+  { NULL, "elf_mn10300", "mn10300", 7, EM_MN10300, 0, 0 },
+  { NULL, "elf_mn10200", "mn10200", 7, EM_MN10200, 0, 0 },
+  { NULL, "elf_pj", "pj", 2, EM_PJ, 0, 0 },
+  { NULL, "elf_openrisc", "openrisc", 8, EM_OPENRISC, 0, 0 },
+  { NULL, "elf_arc_a5", "arc_a5", 6, EM_ARC_A5, 0, 0 },
+  { NULL, "elf_xtensa", "xtensa", 6, EM_XTENSA, 0, 0 },
+  { aarch64_init, "elf_aarch64", "aarch64", 7, EM_AARCH64, ELFCLASS64, 0 },
+  { bpf_init, "elf_bpf", "bpf", 3, EM_BPF, 0, 0 },
+  { riscv_init, "elf_riscv", "riscv", 5, EM_RISCV, ELFCLASS64, ELFDATA2LSB },
+  { riscv_init, "elf_riscv", "riscv", 5, EM_RISCV, ELFCLASS32, ELFDATA2LSB },
+  { csky_init, "elf_csky", "csky", 4, EM_CSKY, ELFCLASS32, ELFDATA2LSB },
+  { loongarch_init, "elf_loongarch", "loongarch", 9, EM_LOONGARCH, ELFCLASS64, ELFDATA2LSB },
+  { arc_init, "elf_arc", "arc", 3, EM_ARCV2, ELFCLASS32, ELFDATA2LSB },
+};
+#define nmachines (sizeof (machines) / sizeof (machines[0]))
+
+/* No machine prefix should be larger than this.  */
+#define MAX_PREFIX_LEN 16
+
+/* Default callbacks.  Mostly they just return the error value.  */
+static const char *default_reloc_type_name (int ignore, char *buf, size_t len);
+static bool default_reloc_type_check (int ignore);
+static bool default_reloc_valid_use (Elf *elf, int ignore);
+static Elf_Type default_reloc_simple_type (Ebl *ebl, int ignore, int *addsub);
+static bool default_gotpc_reloc_check (Elf *elf, int ignore);
+static const char *default_segment_type_name (int ignore, char *buf,
+					      size_t len);
+static const char *default_section_type_name (int ignore, char *buf,
+					      size_t len);
+static const char *default_section_name (int ignore, int ignore2, char *buf,
+					 size_t len);
+static const char *default_machine_flag_name (Elf64_Word orig, Elf64_Word *ignore);
+static bool default_machine_flag_check (Elf64_Word flags);
+static bool default_machine_section_flag_check (GElf_Xword flags);
+static const char *default_symbol_type_name (int ignore, char *buf,
+					     size_t len);
+static const char *default_symbol_binding_name (int ignore, char *buf,
+						size_t len);
+static const char *default_dynamic_tag_name (int64_t ignore, char *buf,
+					     size_t len);
+static bool default_dynamic_tag_check (int64_t ignore);
+static const char *default_osabi_name (int ignore, char *buf, size_t len);
+static void default_destr (struct ebl *ignore);
+static const char *default_core_note_type_name (uint32_t, char *buf,
+						size_t len);
+static const char *default_object_note_type_name (const char *name, uint32_t,
+						  char *buf, size_t len);
+static int default_core_note (const GElf_Nhdr *nhdr, const char *name,
+			      GElf_Word *regs_offset, size_t *nregloc,
+			      const Ebl_Register_Location **reglocs,
+			      size_t *nitems, const Ebl_Core_Item **);
+static int default_auxv_info (GElf_Xword a_type,
+			      const char **name, const char **format);
+static bool default_object_note (const char *name, uint32_t type,
+				 uint32_t descsz, const char *desc);
+static bool default_debugscn_p (const char *name);
+static bool default_copy_reloc_p (int reloc);
+static bool default_none_reloc_p (int reloc);
+static bool default_relative_reloc_p (int reloc);
+static bool default_check_special_symbol (Elf *elf,
+					  const GElf_Sym *sym,
+					  const char *name,
+					  const GElf_Shdr *destshdr);
+static bool default_data_marker_symbol (const GElf_Sym *sym, const char *sname);
+static bool default_check_st_other_bits (unsigned char st_other);
+static bool default_check_special_section (Ebl *, int,
+					   const GElf_Shdr *, const char *);
+static bool default_bss_plt_p (Elf *elf);
+static int default_return_value_location (Dwarf_Die *functypedie,
+					  const Dwarf_Op **locops);
+static ssize_t default_register_info (Ebl *ebl,
+				      int regno, char *name, size_t namelen,
+				      const char **prefix,
+				      const char **setname,
+				      int *bits, int *type);
+static bool default_check_object_attribute (Ebl *ebl, const char *vendor,
+					    int tag, uint64_t value,
+					    const char **tag_name,
+					    const char **value_name);
+static bool default_check_reloc_target_type (Ebl *ebl, Elf64_Word sh_type);
+static int default_abi_cfi (Ebl *ebl, Dwarf_CIE *abi_info);
+
+
+static void
+fill_defaults (Ebl *result)
+{
+  result->reloc_type_name = default_reloc_type_name;
+  result->reloc_type_check = default_reloc_type_check;
+  result->reloc_valid_use = default_reloc_valid_use;
+  result->reloc_simple_type = default_reloc_simple_type;
+  result->gotpc_reloc_check = default_gotpc_reloc_check;
+  result->segment_type_name = default_segment_type_name;
+  result->section_type_name = default_section_type_name;
+  result->section_name = default_section_name;
+  result->machine_flag_name = default_machine_flag_name;
+  result->machine_flag_check = default_machine_flag_check;
+  result->machine_section_flag_check = default_machine_section_flag_check;
+  result->check_special_section = default_check_special_section;
+  result->symbol_type_name = default_symbol_type_name;
+  result->symbol_binding_name = default_symbol_binding_name;
+  result->dynamic_tag_name = default_dynamic_tag_name;
+  result->dynamic_tag_check = default_dynamic_tag_check;
+  result->osabi_name = default_osabi_name;
+  result->core_note_type_name = default_core_note_type_name;
+  result->object_note_type_name = default_object_note_type_name;
+  result->core_note = default_core_note;
+  result->auxv_info = default_auxv_info;
+  result->object_note = default_object_note;
+  result->debugscn_p = default_debugscn_p;
+  result->copy_reloc_p = default_copy_reloc_p;
+  result->none_reloc_p = default_none_reloc_p;
+  result->relative_reloc_p = default_relative_reloc_p;
+  result->check_special_symbol = default_check_special_symbol;
+  result->data_marker_symbol = default_data_marker_symbol;
+  result->check_st_other_bits = default_check_st_other_bits;
+  result->bss_plt_p = default_bss_plt_p;
+  result->return_value_location = default_return_value_location;
+  result->register_info = default_register_info;
+  result->check_object_attribute = default_check_object_attribute;
+  result->check_reloc_target_type = default_check_reloc_target_type;
+  result->disasm = NULL;
+  result->abi_cfi = default_abi_cfi;
+  result->destr = default_destr;
+  result->sysvhash_entrysize = sizeof (Elf32_Word);
+}
+
+/* Find an appropriate backend for the file associated with ELF.  */
+static Ebl *
+openbackend (Elf *elf, const char *emulation, GElf_Half machine)
+{
+  Ebl *result;
+  size_t cnt;
+
+  /* First allocate the data structure for the result.  We do this
+     here since this assures that the structure is always large
+     enough.  */
+  result = calloc (1, sizeof (Ebl));
+  if (result == NULL)
+    {
+      // XXX uncomment
+      // __libebl_seterror (ELF_E_NOMEM);
+      return NULL;
+    }
+
+  /* Fill in the default callbacks.  The initializer for the machine
+     specific module can overwrite the values.  */
+  fill_defaults (result);
+
+  /* XXX Currently all we do is to look at 'e_machine' value in the
+     ELF header.  With an internal mapping table from EM_* value to
+     DSO name we try to load the appropriate module to handle this
+     binary type.
+
+     Multiple modules for the same machine type are possible and they
+     will be tried in sequence.  The lookup process will only stop
+     when a module which can handle the machine type is found or all
+     available matching modules are tried.  */
+  for (cnt = 0; cnt < nmachines; ++cnt)
+    if ((emulation != NULL && strcmp (emulation, machines[cnt].emulation) == 0)
+	|| (emulation == NULL && machines[cnt].em == machine))
+      {
+	/* Well, we know the emulation name now.  */
+	result->emulation = machines[cnt].emulation;
+
+	/* We access some data structures directly.  Make sure the 32 and
+	   64 bit variants are laid out the same.  */
+	assert (offsetof (Elf32_Ehdr, e_machine)
+		== offsetof (Elf64_Ehdr, e_machine));
+	assert (sizeof (((Elf32_Ehdr *) 0)->e_machine)
+		== sizeof (((Elf64_Ehdr *) 0)->e_machine));
+	assert (offsetof (Elf, state.elf32.ehdr)
+		== offsetof (Elf, state.elf64.ehdr));
+
+	/* Prefer taking the information from the ELF file.  */
+	if (elf == NULL)
+	  {
+	    result->machine = machines[cnt].em;
+	    result->class = machines[cnt].class;
+	    result->data = machines[cnt].data;
+	  }
+	else
+	  {
+	    result->machine = elf->state.elf32.ehdr->e_machine;
+	    result->class = elf->state.elf32.ehdr->e_ident[EI_CLASS];
+	    result->data = elf->state.elf32.ehdr->e_ident[EI_DATA];
+	  }
+
+        if (machines[cnt].init &&
+            machines[cnt].init (elf, machine, result))
+          {
+            result->elf = elf;
+            /* A few entries are mandatory.  */
+            assert (result->destr != NULL);
+            return result;
+          }
+
+	/* We don't have a backend but the emulation/machine ID matches.
+	   Return that information.  */
+	result->elf = elf;
+	fill_defaults (result);
+
+	return result;
+      }
+
+  /* Nothing matched.  We use only the default callbacks.   */
+  result->elf = elf;
+  result->emulation = "<unknown>";
+  fill_defaults (result);
+
+  return result;
+}
+
+
+/* Find an appropriate backend for the file associated with ELF.  */
+Ebl *
+ebl_openbackend (Elf *elf)
+{
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+
+  /* Get the ELF header of the object.  */
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      // XXX uncomment
+      // __libebl_seterror (elf_errno ());
+      return NULL;
+    }
+
+  return openbackend (elf, NULL, ehdr->e_machine);
+}
+
+
+/* Find backend without underlying ELF file.  */
+Ebl *
+ebl_openbackend_machine (GElf_Half machine)
+{
+  return openbackend (NULL, NULL, machine);
+}
+
+
+/* Find backend with given emulation name.  */
+Ebl *
+ebl_openbackend_emulation (const char *emulation)
+{
+  return openbackend (NULL, emulation, EM_NONE);
+}
+
+
+/* Default callbacks.  Mostly they just return the error value.  */
+static const char *
+default_reloc_type_name (int ignore __attribute__ ((unused)),
+			 char *buf __attribute__ ((unused)),
+			 size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static bool
+default_reloc_type_check (int ignore __attribute__ ((unused)))
+{
+  return false;
+}
+
+static bool
+default_reloc_valid_use (Elf *elf __attribute__ ((unused)),
+			 int ignore __attribute__ ((unused)))
+{
+  return false;
+}
+
+static Elf_Type
+default_reloc_simple_type (Ebl *eh __attribute__ ((unused)),
+			   int ignore __attribute__ ((unused)),
+			   int *addsub __attribute__ ((unused)))
+{
+  return ELF_T_NUM;
+}
+
+static bool
+default_gotpc_reloc_check (Elf *elf __attribute__ ((unused)),
+			   int ignore __attribute__ ((unused)))
+{
+  return false;
+}
+
+static const char *
+default_segment_type_name (int ignore __attribute__ ((unused)),
+			   char *buf __attribute__ ((unused)),
+			   size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static const char *
+default_section_type_name (int ignore __attribute__ ((unused)),
+			   char *buf __attribute__ ((unused)),
+			   size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static const char *
+default_section_name (int ignore __attribute__ ((unused)),
+		      int ignore2 __attribute__ ((unused)),
+		      char *buf __attribute__ ((unused)),
+		      size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static const char *
+default_machine_flag_name (Elf64_Word orig __attribute__ ((unused)),
+			   Elf64_Word *ignore __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static bool
+default_machine_flag_check (Elf64_Word flags __attribute__ ((unused)))
+{
+  return flags == 0;
+}
+
+static bool
+default_machine_section_flag_check (GElf_Xword flags)
+{
+  return flags == 0;
+}
+
+static bool
+default_check_special_section (Ebl *ebl __attribute__ ((unused)),
+			       int ndx __attribute__ ((unused)),
+			       const GElf_Shdr *shdr __attribute__ ((unused)),
+			       const char *sname __attribute__ ((unused)))
+{
+  return false;
+}
+
+static const char *
+default_symbol_type_name (int ignore __attribute__ ((unused)),
+			  char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static const char *
+default_symbol_binding_name (int ignore __attribute__ ((unused)),
+			     char *buf __attribute__ ((unused)),
+			     size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static const char *
+default_dynamic_tag_name (int64_t ignore __attribute__ ((unused)),
+			  char *buf __attribute__ ((unused)),
+			  size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static bool
+default_dynamic_tag_check (int64_t ignore __attribute__ ((unused)))
+{
+  return false;
+}
+
+static void
+default_destr (struct ebl *ignore __attribute__ ((unused)))
+{
+}
+
+static const char *
+default_osabi_name (int ignore __attribute__ ((unused)),
+		    char *buf __attribute__ ((unused)),
+		    size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static const char *
+default_core_note_type_name (uint32_t ignore __attribute__ ((unused)),
+			     char *buf __attribute__ ((unused)),
+			     size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static int
+default_auxv_info (GElf_Xword a_type __attribute__ ((unused)),
+		   const char **name __attribute__ ((unused)),
+		   const char **format __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static int
+default_core_note (const GElf_Nhdr *nhdr __attribute__ ((unused)),
+		   const char *name __attribute__ ((unused)),
+		   GElf_Word *ro __attribute__ ((unused)),
+		   size_t *nregloc  __attribute__ ((unused)),
+		   const Ebl_Register_Location **reglocs
+		   __attribute__ ((unused)),
+		   size_t *nitems __attribute__ ((unused)),
+		   const Ebl_Core_Item **items __attribute__ ((unused)))
+{
+  return 0;
+}
+
+static const char *
+default_object_note_type_name (const char *name __attribute__ ((unused)),
+			       uint32_t ignore __attribute__ ((unused)),
+			       char *buf __attribute__ ((unused)),
+			       size_t len __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static bool
+default_object_note (const char *name __attribute__ ((unused)),
+		     uint32_t type __attribute__ ((unused)),
+		     uint32_t descsz __attribute__ ((unused)),
+		     const char *desc __attribute__ ((unused)))
+{
+  return NULL;
+}
+
+static bool
+default_debugscn_p (const char *name)
+{
+  /* We know by default only about the DWARF debug sections which have
+     fixed names.  */
+  static const char *dwarf_scn_names[] =
+    {
+      /* DWARF 1 */
+      ".debug",
+      ".line",
+      /* GNU DWARF 1 extensions */
+      ".debug_srcinfo",
+      ".debug_sfnames",
+      /* DWARF 1.1 and DWARF 2 */
+      ".debug_aranges",
+      ".debug_pubnames",
+      /* DWARF 2 */
+      ".debug_info",
+      ".debug_abbrev",
+      ".debug_line",
+      ".debug_frame",
+      ".debug_str",
+      ".debug_loc",
+      ".debug_macinfo",
+      /* DWARF 3 */
+      ".debug_ranges",
+      ".debug_pubtypes",
+      /* DWARF 4 */
+      ".debug_types",
+      /* GDB DWARF 4 extension */
+      ".gdb_index",
+      /* GNU/DWARF 5 extension/proposal */
+      ".debug_macro",
+      /* DWARF 5 */
+      ".debug_addr",
+      ".debug_line_str",
+      ".debug_loclists",
+      ".debug_names",
+      ".debug_rnglists",
+      ".debug_str_offsets",
+      /* SGI/MIPS DWARF 2 extensions */
+      ".debug_weaknames",
+      ".debug_funcnames",
+      ".debug_typenames",
+      ".debug_varnames"
+    };
+  const size_t ndwarf_scn_names = (sizeof (dwarf_scn_names)
+				   / sizeof (dwarf_scn_names[0]));
+  for (size_t cnt = 0; cnt < ndwarf_scn_names; ++cnt)
+    if (strcmp (name, dwarf_scn_names[cnt]) == 0
+	|| (startswith (name, ".zdebug")
+	    && strcmp (&name[2], &dwarf_scn_names[cnt][1]) == 0)
+	|| (startswith (name, ".gnu.debuglto_")
+	    && strcmp (&name[14], dwarf_scn_names[cnt]) == 0))
+      return true;
+
+  return false;
+}
+
+static bool
+default_copy_reloc_p (int reloc __attribute__ ((unused)))
+{
+  return false;
+}
+strong_alias (default_copy_reloc_p, default_none_reloc_p)
+strong_alias (default_copy_reloc_p, default_relative_reloc_p)
+
+static bool
+default_check_special_symbol (Elf *elf __attribute__ ((unused)),
+			      const GElf_Sym *sym __attribute__ ((unused)),
+			      const char *name __attribute__ ((unused)),
+			      const GElf_Shdr *destshdr __attribute__ ((unused)))
+{
+  return false;
+}
+
+static bool
+default_data_marker_symbol (const GElf_Sym *sym __attribute__ ((unused)),
+			    const char *sname __attribute__ ((unused)))
+{
+  return false;
+}
+
+static bool
+default_check_st_other_bits (unsigned char st_other __attribute__ ((unused)))
+{
+  return false;
+}
+
+
+static bool
+default_bss_plt_p (Elf *elf __attribute__ ((unused)))
+{
+  return false;
+}
+
+static int
+default_return_value_location (Dwarf_Die *functypedie __attribute__ ((unused)),
+			       const Dwarf_Op **locops __attribute__ ((unused)))
+{
+  return -2;
+}
+
+static ssize_t
+default_register_info (Ebl *ebl __attribute__ ((unused)),
+		       int regno, char *name, size_t namelen,
+		       const char **prefix,
+		       const char **setname,
+		       int *bits, int *type)
+{
+  if (name == NULL)
+    return 0;
+
+  *setname = "???";
+  *prefix = "";
+  *bits = -1;
+  *type = DW_ATE_void;
+  return snprintf (name, namelen, "reg%d", regno);
+}
+
+static bool
+default_check_object_attribute (Ebl *ebl __attribute__ ((unused)),
+				const char *vendor  __attribute__ ((unused)),
+				int tag __attribute__ ((unused)),
+				uint64_t value __attribute__ ((unused)),
+				const char **tag_name, const char **value_name)
+{
+  *tag_name = NULL;
+  *value_name = NULL;
+  return false;
+}
+
+static bool
+default_check_reloc_target_type (Ebl *ebl __attribute__ ((unused)),
+				 Elf64_Word sh_type __attribute__ ((unused)))
+{
+  return false;
+}
+
+static int
+default_abi_cfi (Ebl *ebl __attribute__ ((unused)),
+		 Dwarf_CIE *abi_info __attribute__ ((unused)))
+{
+  return -1;
+}
diff --git a/libebl/eblosabiname.c b/libebl/eblosabiname.c
new file mode 100644
index 0000000..48b3c05
--- /dev/null
+++ b/libebl/eblosabiname.c
@@ -0,0 +1,80 @@
+/* Return OS ABI name
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_osabi_name (Ebl *ebl, int osabi, char *buf, size_t len)
+{
+  const char *res = ebl != NULL ? ebl->osabi_name (osabi, buf, len) : NULL;
+
+  if (res == NULL)
+    {
+      if (osabi == ELFOSABI_NONE)
+	res = "UNIX - System V";
+      else if (osabi == ELFOSABI_HPUX)
+	res = "HP/UX";
+      else if (osabi == ELFOSABI_NETBSD)
+	res = "NetBSD";
+      else if (osabi == ELFOSABI_LINUX)
+	res = "Linux";
+      else if (osabi == ELFOSABI_SOLARIS)
+	res = "Solaris";
+      else if (osabi == ELFOSABI_AIX)
+	res = "AIX";
+      else if (osabi == ELFOSABI_IRIX)
+	res = "Irix";
+      else if (osabi == ELFOSABI_FREEBSD)
+	res = "FreeBSD";
+      else if (osabi == ELFOSABI_TRU64)
+	res = "TRU64";
+      else if (osabi == ELFOSABI_MODESTO)
+	res = "Modesto";
+      else if (osabi == ELFOSABI_OPENBSD)
+	res = "OpenBSD";
+      else if (osabi == ELFOSABI_ARM)
+	res = "Arm";
+      else if (osabi == ELFOSABI_STANDALONE)
+	res = _("Stand alone");
+      else
+	{
+	  snprintf (buf, len, "%s: %d", _("<unknown>"), osabi);
+
+	  res = buf;
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblreginfo.c b/libebl/eblreginfo.c
new file mode 100644
index 0000000..acc4849
--- /dev/null
+++ b/libebl/eblreginfo.c
@@ -0,0 +1,44 @@
+/* Return register name information.
+   Copyright (C) 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <libeblP.h>
+
+
+ssize_t
+ebl_register_info (Ebl *ebl, int regno, char *name, size_t namelen,
+		   const char **prefix, const char **setname,
+		   int *bits, int *type)
+{
+  return ebl == NULL ? -1 : ebl->register_info (ebl, regno, name, namelen,
+						prefix, setname, bits, type);
+}
diff --git a/libebl/eblrelativerelocp.c b/libebl/eblrelativerelocp.c
new file mode 100644
index 0000000..51f5dce
--- /dev/null
+++ b/libebl/eblrelativerelocp.c
@@ -0,0 +1,41 @@
+/* Check whether given relocation is a relative relocation.
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2006.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_relative_reloc_p (Ebl *ebl, int reloc)
+{
+  return ebl->relative_reloc_p (reloc);
+}
diff --git a/libebl/eblrelocsimpletype.c b/libebl/eblrelocsimpletype.c
new file mode 100644
index 0000000..1229280
--- /dev/null
+++ b/libebl/eblrelocsimpletype.c
@@ -0,0 +1,40 @@
+/* Check relocation type for simple types.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+Elf_Type
+ebl_reloc_simple_type (Ebl *ebl, int reloc, int *addsub)
+{
+  return ebl != NULL ? ebl->reloc_simple_type (ebl, reloc, addsub) : ELF_T_NUM;
+}
diff --git a/libebl/eblreloctypecheck.c b/libebl/eblreloctypecheck.c
new file mode 100644
index 0000000..80e67ef
--- /dev/null
+++ b/libebl/eblreloctypecheck.c
@@ -0,0 +1,41 @@
+/* Check relocation type.
+   Copyright (C) 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_reloc_type_check (Ebl *ebl, int reloc)
+{
+  return ebl != NULL ? ebl->reloc_type_check (reloc) : false;
+}
diff --git a/libebl/eblreloctypename.c b/libebl/eblreloctypename.c
new file mode 100644
index 0000000..e53ec0c
--- /dev/null
+++ b/libebl/eblreloctypename.c
@@ -0,0 +1,49 @@
+/* Return relocation type name.
+   Copyright (C) 2001, 2002, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_reloc_type_name (Ebl *ebl, int reloc, char *buf, size_t len)
+{
+  const char *res;
+
+  res = ebl != NULL ? ebl->reloc_type_name (reloc, buf, len) : NULL;
+  if (res == NULL)
+    /* There are no generic relocation type names.  */
+    res = "<INVALID RELOC>";
+
+  return res;
+}
diff --git a/libebl/eblrelocvaliduse.c b/libebl/eblrelocvaliduse.c
new file mode 100644
index 0000000..f0bed34
--- /dev/null
+++ b/libebl/eblrelocvaliduse.c
@@ -0,0 +1,41 @@
+/* Check relocation type use.
+   Copyright (C) 2003 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_reloc_valid_use (Ebl *ebl, int reloc)
+{
+  return ebl != NULL ? ebl->reloc_valid_use (ebl->elf, reloc) : false;
+}
diff --git a/libebl/eblresolvesym.c b/libebl/eblresolvesym.c
new file mode 100644
index 0000000..470f6f0
--- /dev/null
+++ b/libebl/eblresolvesym.c
@@ -0,0 +1,43 @@
+/* Resolve a symbol value to an allocated section of the Elf file.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+#include <assert.h>
+
+bool
+ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+{
+  if (ebl == NULL || ebl->resolve_sym_value == NULL)
+    return false;
+
+  return ebl->resolve_sym_value (ebl, addr);
+}
diff --git a/libebl/eblretval.c b/libebl/eblretval.c
new file mode 100644
index 0000000..7c03982
--- /dev/null
+++ b/libebl/eblretval.c
@@ -0,0 +1,42 @@
+/* Return location expression to find return value given a function type DIE.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <libeblP.h>
+
+
+int
+ebl_return_value_location (Ebl *ebl, Dwarf_Die *functypedie,
+			   const Dwarf_Op **locops)
+{
+  return ebl == NULL ? -1 : ebl->return_value_location (functypedie, locops);
+}
diff --git a/libebl/eblsectionname.c b/libebl/eblsectionname.c
new file mode 100644
index 0000000..825ad2f
--- /dev/null
+++ b/libebl/eblsectionname.c
@@ -0,0 +1,90 @@
+/* Return section name.
+   Copyright (C) 2001, 2002, 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_section_name (Ebl *ebl, int section, int xsection, char *buf, size_t len,
+		  const char *scnnames[], size_t shnum)
+{
+  const char *res = ebl != NULL ? ebl->section_name (section, xsection,
+						     buf, len) : NULL;
+
+  if (res == NULL)
+    {
+      if (section == SHN_UNDEF)
+	res = "UNDEF";
+      else if (section == SHN_ABS)
+	res = "ABS";
+      else if (section == SHN_COMMON)
+	res = "COMMON";
+      else if (section == SHN_BEFORE)
+	res = "BEFORE";
+      else if (section == SHN_AFTER)
+	res = "AFTER";
+      else if ((section < SHN_LORESERVE || section == SHN_XINDEX)
+	       && (size_t) section < shnum)
+	{
+	  int idx = section != SHN_XINDEX ? section : xsection;
+
+	  if (scnnames != NULL)
+	    res = scnnames[idx];
+	  else
+	    {
+	      snprintf (buf, len, "%d", idx);
+	      res = buf;
+	    }
+	}
+      else
+	{
+	  /* Handle OS-specific section names.  */
+	  if (section == SHN_XINDEX)
+	    snprintf (buf, len, "%s: %d", "XINDEX", xsection);
+	  else if (section >= SHN_LOOS && section <= SHN_HIOS)
+	    snprintf (buf, len, "LOOS+%x", section - SHN_LOOS);
+	  /* Handle processor-specific section names.  */
+	  else if (section >= SHN_LOPROC && section <= SHN_HIPROC)
+	    snprintf (buf, len, "LOPROC+%x", section - SHN_LOPROC);
+	  else if (section >= SHN_LORESERVE && section <= SHN_HIRESERVE)
+	    snprintf (buf, len, "LORESERVE+%x", section - SHN_LORESERVE);
+	  else
+	    snprintf (buf, len, "%s: %d", _("<unknown>"), section);
+
+	  res = buf;
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblsectionstripp.c b/libebl/eblsectionstripp.c
new file mode 100644
index 0000000..a5624ff
--- /dev/null
+++ b/libebl/eblsectionstripp.c
@@ -0,0 +1,70 @@
+/* Check whether section can be stripped.
+   Copyright (C) 2005, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include "libeblP.h"
+
+
+bool
+ebl_section_strip_p (Ebl *ebl, const GElf_Shdr *shdr,
+		     const char *name, bool remove_comment,
+		     bool only_remove_debug)
+{
+  /* If only debug information should be removed check the name.  There
+     is unfortunately no other way.  */
+  if (unlikely (only_remove_debug))
+    {
+      if (ebl_debugscn_p (ebl, name))
+	return true;
+
+      if (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL)
+	{
+	  Elf_Scn *scn_l = elf_getscn (ebl->elf, (shdr)->sh_info);
+	  GElf_Shdr shdr_mem_l;
+	  GElf_Shdr *shdr_l = gelf_getshdr (scn_l, &shdr_mem_l);
+	  if (shdr_l != NULL)
+	    {
+	      size_t shstrndx;
+	      if (elf_getshdrstrndx (ebl->elf, &shstrndx) != 0)
+		return false;
+	      const char *s_l = elf_strptr (ebl->elf, shstrndx,
+					    shdr_l->sh_name);
+	      if (s_l != NULL && ebl_debugscn_p (ebl, s_l))
+		return true;
+	    }
+	}
+
+      return false;
+    }
+
+  return SECTION_STRIP_P (shdr, name, remove_comment);
+}
diff --git a/libebl/eblsectiontypename.c b/libebl/eblsectiontypename.c
new file mode 100644
index 0000000..ade25d4
--- /dev/null
+++ b/libebl/eblsectiontypename.c
@@ -0,0 +1,124 @@
+/* Return section type name.
+   Copyright (C) 2001, 2002, 2006, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_section_type_name (Ebl *ebl, int section, char *buf, size_t len)
+{
+  const char *res = ebl->section_type_name (section, buf, len);
+
+  if (res == NULL)
+    {
+      static const char *knowntypes[] =
+	{
+#define KNOWNSTYPE(name) [SHT_##name] = #name
+	  KNOWNSTYPE (NULL),
+	  KNOWNSTYPE (PROGBITS),
+	  KNOWNSTYPE (SYMTAB),
+	  KNOWNSTYPE (STRTAB),
+	  KNOWNSTYPE (RELA),
+	  KNOWNSTYPE (HASH),
+	  KNOWNSTYPE (DYNAMIC),
+	  KNOWNSTYPE (NOTE),
+	  KNOWNSTYPE (NOBITS),
+	  KNOWNSTYPE (REL),
+	  KNOWNSTYPE (SHLIB),
+	  KNOWNSTYPE (DYNSYM),
+	  KNOWNSTYPE (INIT_ARRAY),
+	  KNOWNSTYPE (FINI_ARRAY),
+	  KNOWNSTYPE (PREINIT_ARRAY),
+	  KNOWNSTYPE (GROUP),
+	  KNOWNSTYPE (SYMTAB_SHNDX),
+	  KNOWNSTYPE (RELR)
+	};
+
+      /* Handle standard names.  */
+      if ((size_t) section < sizeof (knowntypes) / sizeof (knowntypes[0])
+	  && knowntypes[section] != NULL)
+	res = knowntypes[section];
+      /* The symbol versioning/Sun extensions.  */
+      else if (section >= SHT_LOSUNW && section <= SHT_HISUNW)
+	{
+	  static const char *sunwtypes[] =
+	    {
+#undef KNOWNSTYPE
+#define KNOWNSTYPE(name) [SHT_##name - SHT_LOSUNW] = #name
+	      KNOWNSTYPE (SUNW_move),
+	      KNOWNSTYPE (SUNW_COMDAT),
+	      KNOWNSTYPE (SUNW_syminfo),
+	      KNOWNSTYPE (GNU_verdef),
+	      KNOWNSTYPE (GNU_verneed),
+	      KNOWNSTYPE (GNU_versym)
+	    };
+	  res = sunwtypes[section - SHT_LOSUNW];
+	}
+      else
+	/* A few GNU additions.  */
+	switch (section)
+	  {
+	  case SHT_CHECKSUM:
+	    res = "CHECKSUM";
+	    break;
+	  case SHT_GNU_LIBLIST:
+	    res = "GNU_LIBLIST";
+	    break;
+	  case SHT_GNU_HASH:
+	    res = "GNU_HASH";
+	    break;
+	  case SHT_GNU_ATTRIBUTES:
+	    res = "GNU_ATTRIBUTES";
+	    break;
+
+	  default:
+	    /* Handle OS-specific section names.  */
+	    if (section >= SHT_LOOS && section <= SHT_HIOS)
+	      snprintf (buf, len, "SHT_LOOS+%x", section - SHT_LOOS);
+	    /* Handle processor-specific section names.  */
+	    else if (section >= SHT_LOPROC && section <= SHT_HIPROC)
+	      snprintf (buf, len, "SHT_LOPROC+%x", section - SHT_LOPROC);
+	    else if ((unsigned int) section >= SHT_LOUSER
+		     && (unsigned int) section <= SHT_HIUSER)
+	      snprintf (buf, len, "SHT_LOUSER+%x", section - SHT_LOUSER);
+	    else
+	      snprintf (buf, len, "%s: %d", _("<unknown>"), section);
+
+	    res = buf;
+	    break;
+	  }
+    }
+
+  return res;
+}
diff --git a/libebl/eblsegmenttypename.c b/libebl/eblsegmenttypename.c
new file mode 100644
index 0000000..9977921
--- /dev/null
+++ b/libebl/eblsegmenttypename.c
@@ -0,0 +1,88 @@
+/* Return segment type name.
+   Copyright (C) 2001, 2002, 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_segment_type_name (Ebl *ebl, int segment, char *buf, size_t len)
+{
+  const char *res;
+
+  res = ebl != NULL ? ebl->segment_type_name (segment, buf, len) : NULL;
+  if (res == NULL)
+    {
+      static const char *ptypes[PT_NUM] =
+	{
+#define PTYPE(name) [PT_##name] = #name
+	  PTYPE (NULL),
+	  PTYPE (LOAD),
+	  PTYPE (DYNAMIC),
+	  PTYPE (INTERP),
+	  PTYPE (NOTE),
+	  PTYPE (SHLIB),
+	  PTYPE (PHDR),
+	  PTYPE (TLS)
+	};
+
+      /* Is it one of the standard segment types?  */
+      if (segment >= PT_NULL && segment < PT_NUM)
+	res = ptypes[segment];
+      else if (segment == PT_GNU_EH_FRAME)
+	res = "GNU_EH_FRAME";
+      else if (segment == PT_GNU_STACK)
+	res = "GNU_STACK";
+      else if (segment == PT_GNU_RELRO)
+	res = "GNU_RELRO";
+      else if (segment == PT_GNU_PROPERTY)
+	res = "GNU_PROPERTY";
+      else if (segment == PT_SUNWBSS)
+	res = "SUNWBSS";
+      else if (segment == PT_SUNWSTACK)
+	res = "SUNWSTACK";
+      else
+	{
+	  if (segment >= PT_LOOS && segment <= PT_HIOS)
+	    snprintf (buf, len, "LOOS+%d", segment - PT_LOOS);
+	  else if (segment >= PT_LOPROC && segment <= PT_HIPROC)
+	    snprintf (buf, len, "LOPROC+%d", segment - PT_LOPROC);
+	  else
+	    snprintf (buf, len, "%s: %d", _("<unknown>"), segment);
+
+	  res = buf;
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblstother.c b/libebl/eblstother.c
new file mode 100644
index 0000000..273f6fc
--- /dev/null
+++ b/libebl/eblstother.c
@@ -0,0 +1,41 @@
+/* Check st_other flag.
+   Copyright (C) 2011 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+bool
+ebl_check_st_other_bits (Ebl *ebl, unsigned char st_other)
+{
+  return ((st_other ^ GELF_ST_VISIBILITY (st_other)) == 0
+	  || ebl->check_st_other_bits (st_other ^ GELF_ST_VISIBILITY (st_other)));
+}
diff --git a/libebl/eblsymbolbindingname.c b/libebl/eblsymbolbindingname.c
new file mode 100644
index 0000000..ebd8c2e
--- /dev/null
+++ b/libebl/eblsymbolbindingname.c
@@ -0,0 +1,75 @@
+/* Return symbol binding name.
+   Copyright (C) 2001, 2002, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_symbol_binding_name (Ebl *ebl, int binding, char *buf, size_t len)
+{
+  const char *res;
+
+  res = ebl != NULL ? ebl->symbol_type_name (binding, buf, len) : NULL;
+  if (res == NULL)
+    {
+      static const char *stb_names[STB_NUM] =
+	{
+	  "LOCAL", "GLOBAL", "WEAK"
+	};
+
+      /* Standard binding?  */
+      if (binding < STB_NUM)
+	res = stb_names[binding];
+      else
+	{
+	  char *ident;
+
+	  if (binding >= STB_LOPROC && binding <= STB_HIPROC)
+	    snprintf (buf, len, "LOPROC+%d", binding - STB_LOPROC);
+	  else if (binding == STB_GNU_UNIQUE
+		   && ebl != NULL
+		   && (ident = elf_getident (ebl->elf, NULL)) != NULL
+		   && ident[EI_OSABI] == ELFOSABI_LINUX)
+	    return "GNU_UNIQUE";
+	  else if (binding >= STB_LOOS && binding <= STB_HIOS)
+	    snprintf (buf, len, "LOOS+%d", binding - STB_LOOS);
+	  else
+	    snprintf (buf, len, _("<unknown>: %d"), binding);
+
+	  res = buf;
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblsymboltypename.c b/libebl/eblsymboltypename.c
new file mode 100644
index 0000000..0ff1722
--- /dev/null
+++ b/libebl/eblsymboltypename.c
@@ -0,0 +1,81 @@
+/* Return symbol type name.
+   Copyright (C) 2001, 2002, 2009 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <libeblP.h>
+
+
+const char *
+ebl_symbol_type_name (Ebl *ebl, int symbol, char *buf, size_t len)
+{
+  const char *res;
+
+  res = ebl != NULL ? ebl->symbol_type_name (symbol, buf, len) : NULL;
+  if (res == NULL)
+    {
+      static const char *stt_names[STT_NUM] =
+	{
+	  [STT_NOTYPE] = "NOTYPE",
+	  [STT_OBJECT] = "OBJECT",
+	  [STT_FUNC] = "FUNC",
+	  [STT_SECTION] = "SECTION",
+	  [STT_FILE] = "FILE",
+	  [STT_COMMON] = "COMMON",
+	  [STT_TLS] = "TLS"
+	};
+
+      /* Standard type?  */
+      if (symbol < STT_NUM)
+	res = stt_names[symbol];
+      else
+	{
+	  char *ident;
+
+	  if (symbol >= STT_LOPROC && symbol <= STT_HIPROC)
+	    snprintf (buf, len, "LOPROC+%d", symbol - STT_LOPROC);
+	  else if (symbol == STT_GNU_IFUNC
+		   && ebl != NULL
+		   && (ident = elf_getident (ebl->elf, NULL)) != NULL
+		   && ident[EI_OSABI] == ELFOSABI_LINUX)
+	    return "GNU_IFUNC";
+	  else if (symbol >= STT_LOOS && symbol <= STT_HIOS)
+	    snprintf (buf, len, "LOOS+%d", symbol - STT_LOOS);
+	  else
+	    snprintf (buf, len, _("<unknown>: %d"), symbol);
+
+	  res = buf;
+	}
+    }
+
+  return res;
+}
diff --git a/libebl/eblsysvhashentrysize.c b/libebl/eblsysvhashentrysize.c
new file mode 100644
index 0000000..2049431
--- /dev/null
+++ b/libebl/eblsysvhashentrysize.c
@@ -0,0 +1,41 @@
+/* Return OS ABI name
+   Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2006.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+
+int
+ebl_sysvhash_entrysize (Ebl *ebl)
+{
+  return ebl->sysvhash_entrysize;
+}
diff --git a/libebl/eblunwind.c b/libebl/eblunwind.c
new file mode 100644
index 0000000..2970d03
--- /dev/null
+++ b/libebl/eblunwind.c
@@ -0,0 +1,44 @@
+/* Get previous frame state for an existing frame state.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libeblP.h>
+
+bool
+ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+	    ebl_tid_registers_get_t *getfunc, ebl_pid_memory_read_t *readfunc,
+	    void *arg, bool *signal_framep)
+{
+  /* ebl is declared NN */
+  if (ebl->unwind == NULL)
+    return false;
+  return ebl->unwind (ebl, pc, setfunc, getfunc, readfunc, arg, signal_framep);
+}
diff --git a/libebl/libebl.h b/libebl/libebl.h
new file mode 100644
index 0000000..731001d
--- /dev/null
+++ b/libebl/libebl.h
@@ -0,0 +1,403 @@
+/* Interface for libebl.
+   Copyright (C) 2000-2010, 2013, 2014, 2015, 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+/* This is the interface for the Elfutils Backend Library.
+   It is a completely UNSUPPORTED interface.  Don't use any libebl
+   function directly.  These are only for internal elfutils backends
+   and tools.  There is NO source or binary compatible guarantee.  */
+
+
+#ifndef _LIBEBL_H
+#define _LIBEBL_H 1
+
+#include <gelf.h>
+#include "libdw.h"
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "elf-knowledge.h"
+
+
+/* Opaque type for the handle.  libasm.h defined the same thing.  */
+#ifndef _LIBASM_H
+typedef struct ebl Ebl;
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Get backend handle for object associated with ELF handle.  */
+extern Ebl *ebl_openbackend (Elf *elf);
+/* Similar but without underlying ELF file.  */
+extern Ebl *ebl_openbackend_machine (GElf_Half machine);
+/* Similar but with emulation name given.  */
+extern Ebl *ebl_openbackend_emulation (const char *emulation);
+
+/* Free resources allocated for backend handle.  */
+extern void ebl_closebackend (Ebl *bh);
+
+
+/* Information about the descriptor.  */
+
+/* Get ELF machine.  */
+extern int ebl_get_elfmachine (Ebl *ebl) __pure_attribute__;
+
+/* Get ELF class.  */
+extern int ebl_get_elfclass (Ebl *ebl) __pure_attribute__;
+
+/* Get ELF data encoding.  */
+extern int ebl_get_elfdata (Ebl *ebl) __pure_attribute__;
+
+
+/* Function to call the callback functions including default ELF
+   handling.  */
+
+/* Return backend name.  */
+extern const char *ebl_backend_name (Ebl *ebl);
+
+/* Return relocation type name.  */
+extern const char *ebl_reloc_type_name (Ebl *ebl, int reloc,
+					char *buf, size_t len);
+
+/* Check relocation type.  */
+extern bool ebl_reloc_type_check (Ebl *ebl, int reloc);
+
+/* Check relocation type use.  */
+extern bool ebl_reloc_valid_use (Ebl *ebl, int reloc);
+
+/* Check if relocation type is for simple absolute relocations.
+   Return ELF_T_{BYTE,HALF,SWORD,SXWORD} for a simple type, else ELF_T_NUM.
+   If the relocation type is an ADD or SUB relocation, set *ADDSUB to 1 or -1,
+   resp.  */
+extern Elf_Type ebl_reloc_simple_type (Ebl *ebl, int reloc, int *addsub);
+
+/* Return true if the symbol type is that referencing the GOT.  E.g.,
+   R_386_GOTPC.  */
+extern bool ebl_gotpc_reloc_check (Ebl *ebl, int reloc);
+
+/* Return segment type name.  */
+extern const char *ebl_segment_type_name (Ebl *ebl, int segment,
+					  char *buf, size_t len);
+
+/* Return section type name.  */
+extern const char *ebl_section_type_name (Ebl *ebl, int section,
+					  char *buf, size_t len);
+
+/* Return section name.  */
+extern const char *ebl_section_name (Ebl *ebl, int section, int xsection,
+				     char *buf, size_t len,
+				     const char *scnnames[], size_t shnum);
+
+/* Return machine flag names.  */
+extern const char *ebl_machine_flag_name (Ebl *ebl, GElf_Word flags,
+					  char *buf, size_t len);
+
+/* Check whether machine flag is valid.  */
+extern bool ebl_machine_flag_check (Ebl *ebl, GElf_Word flags);
+
+/* Check whether SHF_MASKPROC flags are valid.  */
+extern bool ebl_machine_section_flag_check (Ebl *ebl, GElf_Xword flags);
+
+/* Check whether the section with the given index, header, and name
+   is a special machine section that is valid despite a combination
+   of flags or other details that are not generically valid.  */
+extern bool ebl_check_special_section (Ebl *ebl, int ndx,
+				       const GElf_Shdr *shdr, const char *name);
+
+/* Return symbol type name.  */
+extern const char *ebl_symbol_type_name (Ebl *ebl, int symbol,
+					 char *buf, size_t len);
+
+/* Return symbol binding name.  */
+extern const char *ebl_symbol_binding_name (Ebl *ebl, int binding,
+					    char *buf, size_t len);
+
+/* Return dynamic tag name.  */
+extern const char *ebl_dynamic_tag_name (Ebl *ebl, int64_t tag,
+					 char *buf, size_t len);
+
+/* Check dynamic tag.  */
+extern bool ebl_dynamic_tag_check (Ebl *ebl, int64_t tag);
+
+/* Check whether given symbol's st_value and st_size are OK despite failing
+   normal checks.  */
+extern bool ebl_check_special_symbol (Ebl *ebl,
+				      const GElf_Sym *sym, const char *name,
+				      const GElf_Shdr *destshdr);
+
+/* Check if this is a data marker symbol.  e.g. '$d' symbols for ARM.  */
+extern bool ebl_data_marker_symbol (Ebl *ebl, const GElf_Sym *sym,
+				    const char *sname);
+
+/* Check whether only valid bits are set on the st_other symbol flag.  */
+extern bool ebl_check_st_other_bits (Ebl *ebl, unsigned char st_other);
+
+/* Return symbolic representation of OS ABI.  */
+extern const char *ebl_osabi_name (Ebl *ebl, int osabi, char *buf, size_t len);
+
+
+/* Return name of the note section type for a core file.  */
+extern const char *ebl_core_note_type_name (Ebl *ebl, uint32_t type, char *buf,
+					    size_t len);
+
+/* Return name of the note section type for an object file.  */
+extern const char *ebl_object_note_type_name (Ebl *ebl, const char *name,
+					      uint32_t type, GElf_Word descsz,
+					      char *buf, size_t len);
+
+/* Print information about object note if available.  */
+extern void ebl_object_note (Ebl *ebl, uint32_t namesz, const char *name,
+			     uint32_t type, uint32_t descsz, const char *desc);
+
+/* Check whether an attribute in a .gnu_attributes section is recognized.
+   Fills in *TAG_NAME with the name for this tag.
+   If VALUE is a known value for that tag, also fills in *VALUE_NAME.  */
+extern bool ebl_check_object_attribute (Ebl *ebl, const char *vendor,
+					int tag, uint64_t value,
+					const char **tag_name,
+					const char **value_name);
+
+/* Check whether a section type is a valid reloc target.  */
+extern bool ebl_check_reloc_target_type (Ebl *ebl, Elf64_Word sh_type);
+
+
+/* Check section name for being that of a debug informatino section.  */
+extern bool ebl_debugscn_p (Ebl *ebl, const char *name);
+
+/* Check whether given relocation is a copy relocation.  */
+extern bool ebl_copy_reloc_p (Ebl *ebl, int reloc);
+
+/* Check whether given relocation is a no-op relocation.  */
+extern bool ebl_none_reloc_p (Ebl *ebl, int reloc);
+
+/* Check whether given relocation is a relative relocation.  */
+extern bool ebl_relative_reloc_p (Ebl *ebl, int reloc);
+
+/* Check whether section should be stripped.  */
+extern bool ebl_section_strip_p (Ebl *ebl,
+				 const GElf_Shdr *shdr, const char *name,
+				 bool remove_comment, bool only_remove_debug);
+
+/* Check if backend uses a bss PLT in this file.  */
+extern bool ebl_bss_plt_p (Ebl *ebl);
+
+/* Return size of entry in SysV-style hash table.  */
+extern int ebl_sysvhash_entrysize (Ebl *ebl);
+
+/* Return location expression to find return value given a
+   DW_TAG_subprogram, DW_TAG_subroutine_type, or similar DIE describing
+   function itself (whose DW_AT_type attribute describes its return type).
+   Returns -1 for a libdw error (see dwarf_errno).
+   Returns -2 for an unrecognized type formation.
+   Returns zero if the function has no return value (e.g. "void" in C).
+   Otherwise, *LOCOPS gets a location expression to find the return value,
+   and returns the number of operations in the expression.  The pointer is
+   permanently allocated at least as long as the Ebl handle is open.  */
+extern int ebl_return_value_location (Ebl *ebl,
+				      Dwarf_Die *functypedie,
+				      const Dwarf_Op **locops);
+
+/* Fill in register information given DWARF register numbers.
+   If NAME is null, return the maximum REGNO + 1 that has a name.
+   Otherwise, store in NAME the name for DWARF register number REGNO
+   and return the number of bytes written (including '\0' terminator).
+   Return -1 if NAMELEN is too short or REGNO is negative or too large.
+   Return 0 if REGNO is unused (a gap in the DWARF number assignment).
+   On success, set *SETNAME to a description like "integer" or "FPU"
+   fit for "%s registers" title display, and *PREFIX to the string
+   that precedes NAME in canonical assembler syntax (e.g. "%" or "$").
+   The NAME string contains identifier characters only (maybe just digits).  */
+extern ssize_t ebl_register_info (Ebl *ebl,
+				  int regno, char *name, size_t namelen,
+				  const char **prefix, const char **setname,
+				  int *bits, int *type);
+
+/* Supply the ABI-specified state of DWARF CFI before CIE initial programs.
+
+   The DWARF 3.0 spec says that the default initial states of all registers
+   are "undefined", unless otherwise specified by the machine/compiler ABI.
+
+   This default is wrong for every machine with the CFI generated by GCC.
+   The EH unwinder does not really distinguish "same_value" and "undefined",
+   since it doesn't matter for unwinding (in either case there is no change
+   to make for that register).  GCC generates CFI that says nothing at all
+   about registers it hasn't spilled somewhere.  For our unwinder to give
+   the true story, the backend must supply an initial state that uses
+   "same_value" rules for all the callee-saves registers.
+
+   This can fill in the initial_instructions, initial_instructions_end
+   members of *ABI_INFO to point at a CFI instruction stream to process
+   before each CIE's initial instructions.  It should set the
+   data_alignment_factor member if it affects the initial instructions.
+
+   The callback should not use the register rules DW_CFA_expression or
+   DW_CFA_val_expression.  Defining the CFA using DW_CFA_def_cfa_expression
+   is allowed.  This is an implementation detail since register rules
+   store expressions as offsets from the .eh_frame or .debug_frame data.
+
+   As a shorthand for some common cases, for this instruction stream
+   we overload some CFI instructions that cannot be used in a CIE:
+
+	DW_CFA_restore		-- Change default rule for all unmentioned
+				   registers from undefined to same_value.
+
+   This function can also fill in ABI_INFO->return_address_register with the
+   DWARF register number that identifies the actual PC in machine state.
+   If there is no canonical DWARF register number with that meaning, it's
+   left unchanged (callers usually initialize with (Dwarf_Word) -1).
+   This value is not used by CFI per se.
+
+   Function returns 0 on success and -1 for error or unsupported by the
+   backend.  */
+extern int ebl_abi_cfi (Ebl *ebl, Dwarf_CIE *abi_info)
+  __nonnull_attribute__ (2);
+
+/* Register map info. */
+typedef struct
+{
+  Dwarf_Half offset;		/* Byte offset in register data block.  */
+  Dwarf_Half regno;		/* DWARF register number.  */
+  uint8_t bits;			/* Bits of data for one register.  */
+  uint8_t pad;			/* Bytes of padding after register's data.  */
+  Dwarf_Half count;		/* Consecutive register numbers here.  */
+  bool pc_register;
+} Ebl_Register_Location;
+
+/* Non-register data items in core notes.  */
+typedef struct
+{
+  const char *name;		/* Printable identifier.  */
+  const char *group;		/* Identifier for category of related items.  */
+  Dwarf_Half offset;		/* Byte offset in note data.  */
+  Dwarf_Half count;
+  Elf_Type type;
+  char format;
+  bool thread_identifier;
+  bool pc_register;
+} Ebl_Core_Item;
+
+/* Describe the format of a core file note with the given header and NAME.
+   NAME is not guaranteed terminated, it's NHDR->n_namesz raw bytes.  */
+extern int ebl_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
+			  const char *name, const char *desc,
+			  GElf_Word *regs_offset, size_t *nregloc,
+			  const Ebl_Register_Location **reglocs,
+			  size_t *nitems, const Ebl_Core_Item **items)
+  __nonnull_attribute__ (1, 2, 3, 4, 5, 6, 7, 8);
+
+/* Describe the auxv type number.  */
+extern int ebl_auxv_info (Ebl *ebl, GElf_Xword a_type,
+			  const char **name, const char **format)
+  __nonnull_attribute__ (1, 3, 4);
+
+/* Callback type for ebl_set_initial_registers_tid.
+   Register -1 is mapped to PC (if arch PC has no DWARF number).
+   If FIRSTREG is -1 then NREGS has to be 1.  */
+typedef bool (ebl_tid_registers_t) (int firstreg, unsigned nregs,
+				    const Dwarf_Word *regs, void *arg)
+  __nonnull_attribute__ (3);
+
+/* Callback to fetch process data from live TID.
+   EBL architecture has to have EBL_FRAME_NREGS > 0, otherwise the
+   backend doesn't support unwinding and this function call may crash.  */
+extern bool ebl_set_initial_registers_tid (Ebl *ebl,
+					   pid_t tid,
+					   ebl_tid_registers_t *setfunc,
+					   void *arg)
+  __nonnull_attribute__ (1, 3);
+
+/* Number of registers to allocate for ebl_set_initial_registers_tid.
+   EBL architecture can unwind iff EBL_FRAME_NREGS > 0.  */
+extern size_t ebl_frame_nregs (Ebl *ebl)
+  __nonnull_attribute__ (1);
+
+/* Offset to apply to the value of the return_address_register, as
+   fetched from a Dwarf CFI.  This is used by some backends, where the
+   return_address_register actually contains the call address.  */
+extern int ebl_ra_offset (Ebl *ebl)
+  __nonnull_attribute__ (1);
+
+/* Mask to use for function symbol or unwind return addresses in case
+   the architecture adds some extra non-address bits to it.  This is
+   different from ebl_resolve_sym_value which only works for actual
+   symbol addresses (in non-ET_REL files) that might resolve to an
+   address in a different section.  ebl_func_addr_mask is called to
+   turn a given function value into the a real address or offset (the
+   original value might not be a real address).  This works for all
+   cases where an actual function address (or offset in ET_REL symbol
+   tables) is needed.  */
+extern GElf_Addr ebl_func_addr_mask (Ebl *ebl);
+
+/* Convert *REGNO as is in DWARF to a lower range suitable for
+   Dwarf_Frame->REGS indexing.  */
+extern bool ebl_dwarf_to_regno (Ebl *ebl, unsigned *regno)
+  __nonnull_attribute__ (1, 2);
+
+/* Modify PC as fetched from inferior data into valid PC.  */
+extern void ebl_normalize_pc (Ebl *ebl, Dwarf_Addr *pc)
+  __nonnull_attribute__ (1, 2);
+
+/* Callback type for ebl_unwind's parameter getfunc.  */
+typedef bool (ebl_tid_registers_get_t) (int firstreg, unsigned nregs,
+					Dwarf_Word *regs, void *arg)
+  __nonnull_attribute__ (3);
+
+/* Callback type for ebl_unwind's parameter readfunc.  */
+typedef bool (ebl_pid_memory_read_t) (Dwarf_Addr addr, Dwarf_Word *data,
+				      void *arg)
+  __nonnull_attribute__ (3);
+
+/* Get previous frame state for an existing frame state.  Method is called only
+   if unwinder could not find CFI for current PC.  PC is for the
+   existing frame.  SETFUNC sets register in the previous frame.  GETFUNC gets
+   register from the existing frame.  Note that GETFUNC vs. SETFUNC act on
+   a disjunct set of registers.  READFUNC reads memory.  ARG has to be passed
+   for SETFUNC, GETFUNC and READFUNC.  *SIGNAL_FRAMEP is initialized to false,
+   it can be set to true if existing frame is a signal frame.  SIGNAL_FRAMEP is
+   never NULL.  */
+extern bool ebl_unwind (Ebl *ebl, Dwarf_Addr pc, ebl_tid_registers_t *setfunc,
+			ebl_tid_registers_get_t *getfunc,
+			ebl_pid_memory_read_t *readfunc, void *arg,
+			bool *signal_framep)
+  __nonnull_attribute__ (1, 3, 4, 5, 7);
+
+/* Returns true if the value can be resolved to an address in an
+   allocated section, which will be returned in *ADDR
+   (e.g. function descriptor resolving)  */
+extern bool ebl_resolve_sym_value (Ebl *ebl, GElf_Addr *addr)
+   __nonnull_attribute__ (2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* libebl.h */
diff --git a/libebl/libeblP.h b/libebl/libeblP.h
new file mode 100644
index 0000000..c408ed9
--- /dev/null
+++ b/libebl/libeblP.h
@@ -0,0 +1,93 @@
+/* Internal definitions for interface for libebl.
+   Copyright (C) 2000-2009, 2013, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBEBLP_H
+#define _LIBEBLP_H 1
+
+#include <gelf.h>
+#include <libasm.h>
+#include <libebl.h>
+
+
+/* Backend handle.  */
+struct ebl
+{
+  /* Emulation name.  */
+  const char *emulation;
+
+  /* ELF machine, class, and data encoding.  */
+  uint_fast16_t machine;
+  uint_fast8_t class;
+  uint_fast8_t data;
+
+  /* The libelf handle (if known).  */
+  Elf *elf;
+
+  /* See ebl-hooks.h for the declarations of the hook functions.  */
+# define EBLHOOK(name) (*name)
+# include "ebl-hooks.h"
+# undef EBLHOOK
+
+  /* Size of entry in Sysv-style hash table.  */
+  int sysvhash_entrysize;
+
+  /* Number of registers to allocate for ebl_set_initial_registers_tid.
+     Ebl architecture can unwind iff FRAME_NREGS > 0.  */
+  size_t frame_nregs;
+
+  /* Offset to apply to the value of the return_address_register, as
+     fetched from a Dwarf CFI.  This is used by some backends, where
+     the return_address_register actually contains the call
+     address.  */
+  int ra_offset;
+
+  /* Mask to use to turn a function value into a real function address
+     in case the architecture adds some extra non-address bits to it.
+     If not initialized (0) then ebl_func_addr_mask will return ~0,
+     otherwise it should be the actual mask to use.  */
+  GElf_Addr func_addr_mask;
+
+  /* Function descriptor load address and table as used by
+     ebl_resolve_sym_value if available for this arch.  */
+  GElf_Addr fd_addr;
+  Elf_Data *fd_data;
+};
+
+
+/* Type of the initialization functions in the backend modules.
+   The init function returns the given Ebl * or NULL if it couldn't
+   initialize for the given Elf or machine.  */
+typedef Ebl *(*ebl_bhinit_t) (Elf *, GElf_Half, Ebl *);
+
+
+/* LEB128 constant helper macros.  */
+#define ULEB128_7(x)	(BUILD_BUG_ON_ZERO ((x) >= (1U << 7)) + (x))
+
+#define BUILD_BUG_ON_ZERO(x) (sizeof (char [(x) ? -1 : 1]) - 1)
+
+#endif	/* libeblP.h */
diff --git a/libelf/ChangeLog b/libelf/ChangeLog
new file mode 100644
index 0000000..0e314ab
--- /dev/null
+++ b/libelf/ChangeLog
@@ -0,0 +1,2035 @@
+2023-09-09  Yanglin Xun  <xunyanglins@gmail.com>
+
+ * libelf.h: Fix typo in comment
+
+2023-04-01  Youling Tang  <tangyouling@loongson.cn>
+
+	* elf.h: Update from glibc.
+
+2023-03-03  Mark Wielaard  <mark@klomp.org>
+
+	* libelf.h: Define ELFCOMPRESS_ZSTD if undefined.
+	(elf_compress): Document ELFCOMPRESS_ZSTD compression type.
+
+2023-02-20  Mark Wielaard  <mark@klomp.org>
+
+	* gnuhash_xlate.h (elf_cvt_gnuhash): memmove any left over bytes.
+
+2022-11-30  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2022-10-28  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2022-10-21  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* libelf_crc32.c: Remove LIB_SYSTEM_H define.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* elf32_checksum.c: Use BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN.
+	* elf32_xlatetof.c: Likewise.
+	* elf_getarsym.c: Likewise.
+
+2022-10-16  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* common.h: Remove ar.h, byteswap.h and endian.h.
+	* elf32_checksum.c: Remove endian.h.
+	* elf32_getphdr.c: Remove unistd.h and system.h.
+	* elf32_getshdr.c: Remove unistd.h.h and system.h.
+	* elf32_updatefile.c: Remove unistd.h, sys/mman.h and system.h.
+	* elf32_updatenull.c: Remove endian.h and system.h.
+	* elf32_xlatetof.c: Remove endian.h.
+	* elf32_xlatetom.c: Likewise.
+	* elf_begin.c: Remove unistd.h, sys/mman.h and system.h.
+	* elf_cntl.c: Remove unistd.h.
+	* elf_compress.c: Remove system.h and unistd.h.
+	* elf_end.c: Remove sys.mman.h.
+	* elf_getarsym.c: Remove byteswap.h, endian.h, unistd.h and
+	system.h.
+	* elf_getdata.c: Remove unistd.h and system.h.
+	* elf_getdata_rawchunk.c: Remove unistd.h and system.h.
+	* elf_getshdrstrndx.c: Likewise.
+	* elf_readall.c: Likewise.
+	* elf_update.c: Remove unistd.h and sys/mman.h.
+	* gelf_xlate.c: Remove byteswap.h.
+	* libelfP.h: Add system.h.
+	* nlist.c: Remove unistd.h.
+
+2022-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (__libelf_next_arhdr_wrlock): Add OCT_FIELD macro,
+	like INT_FIELD but use strtol with octal base 8. Use for ar_mode.
+
+2022-08-08  Andreas Schwab  <schwab@suse.de>
+
+	* elf.h: Update from glibc.
+
+2022-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* elf_update.c (write_file): Check HAVE_MREMAP.
+
+2022-04-01  Mark Wielaard  <mark@klomp.org>
+
+	* libelfP.h (struct Elf_Data_Chunk): Add an int64_t offset field.
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Check whether the
+	requested chunk, offset, size and type, was already handed out.
+	Set new Elf_Data_Chunk offset field.
+
+2022-03-29  Mark Wielaard  <mark@klomp.org>
+
+	* gelf_xlate.c (START): Define and use sz variable.
+	(END): Use sz variable to decide whether to do a memmove.
+
+2022-03-24  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2022-03-22  Mark Wielaard  <mark@klomp.org>
+
+	* elf_getdata.c (__libelf_type_aligns): ELF_T_GNUHASH has different
+	alignment for ELFCLASS32 and ELFCLASS64.
+
+2022-03-20  Mark Wielaard  <mark@klomp.org>
+
+	* version_xlate.h (elf_cvt_Verdef): Make sure aux_offset and
+	def_offset don't overflow.
+	(elf_cvt_Verneed): Make sure aux_offset and need_offset don't
+	overflow.
+
+2022-03-18  Mark Wielaard  <mark@klomp.org>
+
+	* version_xlate.h (elf_cvt_Verdef): Check alignment of def_offset
+	and aux_offset.
+	(elf_cvt_Verneed): Check alignment of need_offset and aux_offset.
+
+2022-03-17  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (read_long_names): Check ar_size starts with a digit.
+
+2022-03-17  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (get_shnum): Take offset into account for Shdr
+	alignment check.
+
+2021-12-19  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (file_read_elf): Cast ehdr to uintptr_t before e_shoff
+	alignment check. Only set shdr state when scncnt is larger than zero.
+
+2021-12-16  Mark Wielaard  <mark@klomp.org>
+
+	* libelfP.h (NOTE_ALIGN4): And with negative unsigned long.
+	(NOTE_ALIGN8): Likewise.
+
+2021-12-15  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (get_shnum): Use offsetof to get field of unaligned
+	struct.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* common.h (allocate_elf): Remove cast of calloc return value.
+	* elf_newdata.c (elf_newdata): Likewise.
+	* elf_getscn.c (elf_getscn): Remove casts of calloc return values.
+	* elf_newscn.c (elf_newscn): Likewise.
+	* elf32_updatefile.c (__elfw2): Remove casts of malloc return values.
+	* elf_getdata.c (convert_data): Likewise.
+	(__libelf_set_rawdata_wrlock): Remove cast of malloc return value.
+	* elf_begin.c (read_long_names): Remove cast of malloc return value.
+	* elf_readall.c (__libelf_readall): Likewise.
+	* elf_getarsym.c (elf_getarsym): Remove casts of malloc and realloc
+	return values.
+
+2021-07-19  Mark Wielaard  <mark@klomp.org>
+
+	* elf_strptr.c (validate_str): Check last char is zero first before
+	calling memrchr on the whole block.
+
+2021-06-09  Andrei Homescu  <ah@immunant.com>
+
+	* elf_getdata.c: Fix d_align for sections where alignment is larger
+	than offset.
+
+2020-12-12  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* libelfP.h (_): Remove.
+
+2020-12-15  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (get_shnum): Make sure the full Ehdr is available.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* common.h: Fix spelling typo in comment.
+	* gelf.h: Likewise.
+	* libelf.h: Likewise.
+	* libelfP.h: Likewise.
+	* elf32_checksum.c (elfw2): Likewise.
+	* elf_begin.c (dup_elf, write_file): Likewise.
+	* elf_compress.c (__libelf_compress): Likewise.
+	* elf_compress_gnu.c (elf_compress_gnu): Likewise.
+
+2020-12-11  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (GCC_INCLUDE): Remove.
+
+2020-12-09  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (noinst_PROGRAMS): Rename to noinst_DATA.
+	(libelf_so_SOURCES): Remove.
+	(CLEANFILES): Add libelf.so.
+
+2020-11-30  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (libelf.so$(EXEEXT)): Drop $(EXEEXT) suffix.
+
+2020-11-06  Mark Wielaard  <mark@klomp.org>
+
+	* elf-knowledge.h (SH_ENTSIZE_HASH): Update comment.
+
+2020-11-01  Mark Wielaard  <mark@klomp.org>
+
+	* elf_strptr.c (elf_strptr): Check shdr is not NULL.
+
+2020-11-01  Mark Wielaard  <mark@klomp.org>
+
+	* elf_getphdrnum.c (__elf_getphdrnum_rdlock): Set *dst to zero on
+	error.
+
+2020-11-01  Mark Wielaard  <mark@klomp.org>
+
+	* libelfP.h (__libelf_data_type): Take an GElf_Ehdr instead of an
+	Elf handle.
+	* elf_getdata.c (__libelf_data_type): Likewise. And check ehdr
+	directly instead of fetching a new one.
+	(__libelf_set_rawdata_wrlock): Fetch Ehdr, report an error when that
+	fails, otherwise call __libelf_data_type.
+
+2020-10-28  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2020-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2020-08-19  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatenull.c (updatenull_wrlock): Fixup the sh_addralign
+	of an SHF_COMPRESSED section if necessary.
+
+2020-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2020-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* elf_strptr.c (elf_strptr): Check shdr is not NULL.
+
+2020-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Check
+	__gelf_getehdr_rdlock return value.
+
+2020-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* elf_compress.c (__libelf_compress): Remove free (out_buf).
+
+2020-03-18  Omar Sandoval  <osandov@fb.com>
+
+	* elf_getphdrnum.c (__elf_getphdrnum_rdlock): Call
+	__elf{32,64}_getshdr_rdlock if the shdr is not cached.
+
+2019-03-20  Matthias Maennich  <maennich@google.com>
+
+	* elf_compress.c (__libelf_compress): Always call deflate_cleanup
+	in failure path. Call deflateEnd only once.
+	(__libelf_decompress): Call inflateEnd only once.
+
+2019-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* common.h (allocate_elf): Use int64_t instead of off_t for offset.
+	* elf32_newphdr.c (newphdr): Document why Elf32/64_Word is correct.
+	* elf32_updatefile.c (fill): Use int64_t instead of off_t for pos.
+	(updatefile): Define last_offset, shdr_offset and scn_start as
+	int64_t instead of off_t.
+	* elf32_updatenull.c: Define Elf32_SizeWord and Elf64_SizeWord.
+	(updatenull_wrlock): Return int64_t instead of off_t. Define size,
+	sh_entsize, sh_align and sh_size as SizeWords. Define offset as
+	int64_t.  Cast data->d_off to SizeWord instead of GElf_Word. Drop
+	size GElf_Word cast. Cast offset to SizeWord instead of GElf_Word
+	when comparing with sh_size.
+	* elf_begin.c (get_shnum): Define offset as int64_t instead of
+	off_t. Document why use GElf_Word is correct.
+	(file_read_elf): Define offset as int64_t instead of off_t.
+	(__libelf_read_mmaped_file): Likewise.
+	(read_unmmaped_file): Likewise.
+	(read_file): Likewise.
+	* elf_getaroff.c (elf_getaroff): Return int64_t.
+	* elf_getbase.c (elf_getbase): Likewise.
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Define offset as
+	int64_t instead of off_t.
+	* elf_update.c (write_file): Return int64_t instead of off_t,
+	define size as int64_t instead of off_t.
+	(elf_update): Likewise.
+	* libelfP.h (struct Elf): Define start_offset, sizestr_offset and
+	offset as int64_t.
+	(__libelf_read_mmaped_file): Define offset as int64_t.
+	(__elf32_updatenull_wrlock): Return int64_t.
+	(__elf64_updatenull_wrlock): Return int64_t.
+
+2019-05-12  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatenull.c (updatenull_wrlock): Mark shdr_flags dirty if
+	either offset or size changed.
+
+2019-05-01  Mark Wielaard  <mark@klomp.org>
+
+	* gelf_getnote.c (gelf_getnote): Check n_namesz doesn't overflow
+	offset.
+
+2019-04-30  Mark Wielaard  <mark@klomp.org>
+
+	* note_xlate.h (elf_cvt_note): Indicate we only translated the note
+	header if we ran out of data by updating len, src and dest.
+
+2019-04-01  Mao Han  <han_mao@c-sky.com>
+
+	* elf.h: Update from glibc.
+
+2019-03-07  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatefile.c (updatemmap): Use posix_memalign instead of
+	aligned_alloc.
+
+2019-03-06  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatefile.c (updatemmap): Free scns before returning
+	allocation failure.
+
+2019-02-24  Mark Wielaard  <mark@klomp.org>
+
+	* gelf_xlate.c (__elf_xfctstof): Remove alias.
+	* libelfP.h (__elf_xfctstof): Remove definition.
+
+2019-02-24  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_fsize.c (local_strong_alias): Remove definition.
+	(msize): Remove alias.
+	* libelfP.h (__elf32_msize): Remove definition.
+	(__elf64_msize): Likewise.
+
+2019-02-21  Mark Wielaard  <mark@klomp.org>
+
+	* common.h (determine_kind): Only accept EV_CURRENT.
+	* elf32_fsize.c (fsize): Just check version is EV_CURRENT.
+	Use __libelf_type_size without version dimension.
+	* elf32_updatefile.c (updatemmap): Define fctp from __elf_xfctstom
+	without version dimension.
+	(updatefile): Likewise.
+	* elf32_updatenull.c (default_ehdr): Check e_version is EV_CURRENT.
+	(updatenull_wrlock): Check d_version is EV_CURRENT.
+	(elf32_xlatetof): Likewise. And get recsize without version
+	dimension from __elf_xfctstom.
+	(elf32_xlatetom): Likewise.
+	* elf_begin.c (elf_begin): Check __libelf_version is EV_CURRENT.
+	* elf_compress.c (__libelf_reset_rawdata): Set d_version to
+	EV_CURRENT.
+	* elf_getdata.c (shtype_map): Remove version dimension.
+	(__libelf_type_aligns): Likewise.
+	(__libelf_data_type): Use shtype_map without version dimension.
+	(convert_data): Remove unused version argument. Get fp from
+	__elf_xfctstom without version dimensions.
+	(__libelf_set_data_list_rdlock): Call convert_data without version.
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Call __elfcfctstom
+	conversion function without version dimensions. Set d_version to
+	EV_CURRENT.
+	* elf_newdata.c (elf_newdata): Set d_version to EV_CURRENT.
+	* elf_version.c (__libelf_version_initialized): Removed.
+	(__libelf_version): Initialized to EV_NONE.
+	(elf_version): Always return EV_CURRENT for EV_NONE version.
+	Only accept (and return) EV_CURRENT as version.
+	* gelf_fsize.c (__libelf_type_sizes): Remove version dimension.
+	(gelf_fsize): Only accept EV_CURRENT as version.
+	Use __libelf_type_sizes without version dimension.
+	* gelf_xlate.c (__elf_xftstom): Remove version dimensions.
+	* libelfP.h (__elf_xfctstom): Defined without version dimensions.
+	(__elf_xfctstof): Likewise.
+	(__libelf_type_sizes): Define without version dimension.
+	(elf_typesize): Define using __libelf_type_sizes without version
+	dimension.
+	(__libelf_version_initialized): Remove definition.
+	(__libelf_version): Add definition.
+	(LIBELF_EV_IDX): Removed define.
+	(__libelf_type_aligns): Remove version dimension.
+	* nlist.c (nlist): Call elf_version unconditionally.
+
+2019-02-19  Mark Wielaard  <mark@klomp.org>
+
+	* elf_compress.c (do_deflate_cleanup): Remove ei_data argument,
+	check cdatap is not NULL before calling free.
+	(deflate_cleanup): Add cdata as argument.
+	(__libelf_compress): Also check whether the d_size is not zero
+	before converting data. Call deflate_cleanup with an extra
+	argument depending on whether there is converted data to free.
+	Always allocate allocate at least one byte for buf_out.
+
+2019-02-14  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (read_long_names): Make sure ar_size is properly
+	terminated. Sanity check len early if we can.
+
+2019-01-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (INSTALL_ELFH): Add elf.h to include_HEADERS when
+	defined, otherwise (the default) add elf.h to noinst_HEADERS.
+
+2019-01-16  Mark Wielaard  <mark@klomp.org>
+
+	* note_xlate.h (elf_cvt_note): Check n_namesz and n_descsz don't
+	overflow note_len into note header.
+
+2018-11-17  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatefile.c (updatemmap): Make sure to call convert
+	function on a properly aligned destination.
+
+2018-11-16  Mark Wielaard  <mark@klomp.org>
+
+	* libebl.h (__elf32_msize): Mark with const attribute.
+	(__elf64_msize): Likewise.
+
+2018-11-13  Mark Wielaard  <mark@klomp.org>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Explicitly set the
+	alignment of SHF_COMPRESSED data to the alignment of ELF_T_CHDR.
+	* elf_compress.c (elf_compress): After compression set sh_addralign
+	to the alignment of ELF_T_CHDR.
+
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* elf_compress_gnu.c (elf_compress_gnu): Use elf_getdata.
+
+2018-11-12  Mark Wielaard  <mark@klomp.org>
+
+	* elf-knowledge.c (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX): New define.
+	(NT_GNU_BUILD_ATTRIBUTE_{OPEN,FUNC}): Likewise.
+	(GNU_BUILD_ATTRIBUTE_TYPE_{NUMERIC,STRING,BOOL_TRUE,BOOL_FALSE}):
+	Likewise.
+	(GNU_BUILD_ATTRIBUTE_{VERSION,STACK_PROT,RELRO,STACK_SIZE,TOOL,ABI,
+	PIC,SHORT_ENUM}): Likewise.
+
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* elf_compress.c (__libelf_reset_rawdata): Make rawdata change
+	explicit by calling __libelf_set_data_list.
+	* elf_getdata.c (convert_data): Don't convert if type is ELF_T_BYTE
+	even if endianness is different.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* libelf.h (Elf_Type): Add ELF_T_NHDR8.
+	* libelfP.h (__libelf_data_type): Add align argument.
+	(NOTE_ALIGN): Split into...
+	(NOTE_ALIGN4): ... and ...
+	(NOTE_ALIGN8): this.
+	* elf32_xlatetom.c (xlatetom): Recognize both ELF_T_NHDR and
+	ELF_T_NHDR8.
+	* elf_compress.c (elf_compress): Pass zdata_align to
+	__libelf_data_type.
+	* elf_compress_gnu.c (elf_compress_gnu): Pass sh_addralign to
+	__libelf_data_type.
+	* elf_getdata.c (shtype_map): Add ELF_T_NHDR8.
+	(__libelf_data_type): Take align as extra argument, use it to
+	determine Elf_Type.
+	(__libelf_set_rawdata_wrlock): Recognize ELF_T_NHDR8. Pass align to
+	__libelf_data_type.
+	* gelf_fsize.c (__libelf_type_sizes): Add ELF_T_NHDR8.
+	* gelf_getnote.c (gelf_getnote): Use Elf_Type of Elf_Data to calculate
+	padding.
+	* gelf_xlate.c (__elf_xfctstom): Set ELF_T_NHDR to elf_cvt_note4,
+	add ELF_T_NHDR8.
+	* note_xlate.h (elf_cvt_note): Take nhdr8 argument and use it to
+	determine padding.
+	(elf_cvt_note4): New function.
+	(elf_cvt_note8): Likewise.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatefile.c (updatemmap): Use shnum, not ehdr->e_shnum.
+	* elf_getscn.c (elf_getscn): Create section zero if it is requested,
+	but doesn't exist yet.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatefile.c (updatemmap): Use memmove, not memcpy.
+	* elf_update.c (write_file): Try to mremap if file needs to be
+	extended.
+
+2018-08-18  Mark Wielaard  <mark@klomp.org>
+
+	* libelf.h (elf_compress_gnu): Add documentation about
+	interaction between SHF_COMPRESED and elf_compress_gnu.
+	* elf_compress_gnu.c (elf_compress_gnu): Return error if section
+	sh_flags has SHF_COMPRESSED set.
+
+2018-07-27  Mark Wielaard  <mark@klomp.org>
+
+	* libelf.h (elf_getshdrstrndx): Fix documentation.
+	(elf_getshstrndx): Likewise.
+
+2018-06-19  Mark Wielaard  <mark@klomp.org>
+
+	* libelfP.h (__libelf_type_align): Remove !ALLOW_UNALIGNED guard.
+	* elf_getdata.c (__libelf_type_aligns): Likewise.
+	(convert_data): Remove ALLOW_UNALIGNED check.
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Likewise.
+
+2018-06-21  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2018-04-19  Andreas Schwab  <schwab@suse.de>
+
+	* elf.h: Update from glibc.
+
+2018-02-16  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* elf32_updatenull.c (updatenull_wrlock): Use FALLTHROUGH macro
+	instead of comment.
+	* elf_begin.c (read_unmmaped_file): Likewise.
+	(elf_begin): Likewise.
+	* elf_cntl.c (elf_cntl): Likewise.
+
+2017-10-04  Mark Wielaard  <mark@klomp.org>
+
+	* elf_begin.c (file_read_elf): Skip sanity checking e_shoff if scncnt
+	is zero, we won't use it then.
+
+2017-10-04  Mark Wielaard  <mark@klomp.org>
+
+	* libelfP.h: Add ELF_E_INVALID_ELF to error values enum.
+	* elf_error.c (ELF_E_INVALID_ELF_IDX): New define. Use it as value
+	for ELF_E_INVALID_ELF in msgidx.
+	* elf_getshdrstrndx.c (elf_getshdrstrndx): Distinquish between pread
+	failing and not having enough data.
+	* elf_begin.c (get_shnum): Likewise. Explicitly set libelf errno on
+	too large value.
+	(file_read_elf): Make sure to always set libelf errno when returning
+	NULL. Distinquish between i/o file and elf data errors.
+
+2017-08-18  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* gelf_xlate.c: Use attribute_packed.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libelfP.h: Use attribute_hidden.
+
+2017-04-27  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Use fpic_CFLAGS and dso_LDFLAGS.
+
+2017-08-15  Mark Wielaard  <mark@klomp.org>
+
+	* elf.h: Update from glibc. Add new powerpc note descriptors.
+
+2017-07-19  Gustavo Romero <gromero@linux.vnet.ibm.com>
+
+	* elf.h: Add known type in notes segment descriptor for HTM SPRs.
+
+2017-02-17  Ulf hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Add libelf_so_DEPS, which include libeu.a,
+	libelf_so_LIBS.
+	(libelf_so_LDLIBS): Add $(libelf_so_DEPS).
+	(libelf.so$(EXEEXT): Use $(libelf_so_LIBS), require libelf.map
+	from the right directory.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libelfP.h: Don't include config.h.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* elf_begin.c: Use F_GETFD rather than F_GETFL.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* libelf.h: Define macros for various function attributes and use
+	them.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* elf_update.c: Set ELF_F_MMAPPED flag if we mmap from elf_update.
+
+2017-04-19  Mark Wielaard  <mark@klomp.org>
+
+	* elf_getarsym.c (elf_getarsym): Initialize n to zero.
+
+2017-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* elf32_updatefile.c (updatemmap): Always update last_positition.
+	(updatefile): Likewise.
+
+2017-03-24  Mark Wielaard  <mark@klomp.org>
+
+	* elf_compress.c (__libelf_decompress): Check insane compression
+	ratios before trying to allocate output buffer.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* gelf.h (gelf_newehdr): Change return type to void *.
+	(gelf_newphdr): Likewise.
+	* gelf_newehdr.c (gelf_newehdr): Likewise.
+	* gelf_newphdr.c (gelf_newphdr): Likewise.
+
+2016-10-21  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Sanity check
+	offset and size before trying to malloc and read data.
+
+2016-10-26  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (read_file): Always set maxsize when parent == NULL.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* elf_getarsym.c (elf_getarsym): Open code rawmemchr when not
+	available.
+	* elf_strptr.c: Include stdbool.h.
+	(validate_str): New function.
+	(elf_strptr): Use validate_str instead of memrchr.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* elf32_updatefile.c: Remove sys/param.h include.
+	* elf32_updatenull.c: Likewise. Add system.h include.
+	* elf_begin.c: Remove sys/param.h.
+	* elf_compress: Likewise. Add system.h include.
+	(MAX): Remove definition.
+
+2016-08-07  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_compress.c (__libelf_reset_rawdata): Check scn->flags and
+	free rawdata_base when malloced. Set ELF_F_MALLOCED for scn->flags.
+	* elf_end.c (elf_end): Check scn->flags and free rawdata_base if
+	malloced.
+	* libelfP.h (struct Elf_Scn): Document flags ELF_F_MALLOCED usage.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-knowledge.h (SH_FLAGS_COMBINE): Removed.
+	(SH_FLAGS_IMPORTANT): Likewise.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatenull.c (updatenull_wrlock): Ignore e_type when
+	updating phdrs.
+	* elf_getphdrnum.c (__elf_getphdrnum_chk_rdlock): Only do sanity
+	checking if phdrs haven't been read in yet.
+
+2016-06-24  John Ogness  <john.ogness@linutronix.de>
+
+	* elf32_updatenull.c (updatenull_wrlock): Find first section.
+	* elf_nextscn.c (elf_nextscn): When scn is NULL start from 0th
+	section.
+
+2016-06-28  Richard Henderson  <rth@redhat.com>
+
+	* elf.h: Update from glibc.  Add lots of new EM_* definitions.
+
+2016-04-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_compress.c (__libelf_compress): Free out_buf if deflateInit
+	fails.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (updatemmap): Free scns when out of memory.
+
+2016-01-28  Mark Wielaard  <mjw@redhat.com>
+
+	* elf.h: Update from glibc. Add new i386 and x86_64 relocations.
+
+2016-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* elf.h: Update from glibc. Add NT_ARM_SYSTEM_CALL.
+
+2016-02-04  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Don't adjust align
+	for SHT_NOBITS sections.
+
+2016-01-22  Chih-Hung Hsieh <chh@google.com>
+
+	* elf_compress.c (__libelf_compress): Move nested function
+	'do_deflate_cleanup' to file scope to compile with clang.
+	* elf_strptr.c (elf_strptr): Move nested function 'get_zdata'
+	to file scope to compile with clang.
+
+2016-01-13  Mark Wielaard  <mjw@redhat.com>
+
+	* libelf.h: Check SHF_COMPRESSED is defined. If not define it and the
+	associated ELF compression types/defines.
+
+2015-11-26  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_compress.c (__libelf_decompress_elf): New function, extracted
+	from...
+	(elf_compress): here. Check zdata_base use __libelf_decompress_elf.
+	* elf_strptr.c (elf_strptr): If SHF_COMPRESSED check, uncompress and
+	use zdata.
+	* libelfP.h (struct Elf_Scn): Add zdata_size and zdata_align.
+	(__libelf_decompress_elf): New internal function definition.
+
+2015-10-21  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libelf_a_SOURCES): Add elf_compress.c and
+	elf_compress_gnu.c.
+	* elf_compress.c: New file.
+	* elf_compress_gnu.c: Likewise.
+	* elf_begin.c (file_read_elf): Make a writable copy of the shdrs
+	for ELF_C_READ_MMAP.
+	* elf_end.c (elf_end): Free zdata_base.
+	* elf_error.c: Add ELF_E_ALREADY_COMPRESSED,
+	ELF_E_UNKNOWN_COMPRESSION_TYPE, ELF_E_COMPRESS_ERROR and
+	ELF_E_DECOMPRESS_ERROR.
+	* elf_data.c (__libelf_data_type): New internal function extracted
+	from convert_data.
+	(convert_data): Handle SHF_COMPRESSED.
+	* elf32_updatenull.c (updatenull_wrlock): Check sh_entsize against
+	uncompressed section data size if SHF_COMPRESSED.
+	* elf32_getshdr.c (load_shdr_wrlock): Adjust assert to account for
+	ELF_C_READ_MMAP.
+	* libelf.h: Define elf_compress and elf_compress_gnu.
+	* libelf.map (ELFUTILS_1.7): Add elf_compress and elf_compress_gnu.
+	* libelfP.h: Add ELF_E_ALREADY_COMPRESSED,
+	ELF_E_UNKNOWN_COMPRESSION_TYPE, ELF_E_COMPRESS_ERROR and
+	ELF_E_DECOMPRESS_ERROR. Define __libelf_data_type.
+	(__libelf_compress): New internal function definition.
+	(__libelf_decompress): Likewise.
+	(__libelf_reset_rawdata): Likewise.
+	(__libelf_data_type): Likewise.
+	(struct Elf_Scn): Add zdata_base.
+
+2015-11-19  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libelf_a_SOURCES): Add elf32_getchdr.c,
+	elf64_getchdr.c and gelf_getchdr.c.
+	(noinst_HEADERS): Add chdr_xlate.h.
+	* abstract.h: Define Chdr32 and Chdr64.
+	* chdr_xlate.h: New file.
+	* elf32_getchdr.c: New file.
+	* elf64_getchdr.c: New file.
+	* elf_error.c: Add ELF_E_NOT_COMPRESSED, ELF_E_INVALID_SECTION_TYPE
+	and ELF_E_INVALID_SECTION_FLAGS.
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Set d_type to
+	ELF_T_CHDR for SHF_COMPRESSED sections.
+	* exttypes.h: Add Chdr32 and Chdr64.
+	* gelf.h (GElf_Chdr): New typedef.
+	(gelf_getchdr): New function definition.
+	* gelf_fsize.c (__libelf_type_sizes): Add ELF_T_CHDR.
+	* gelf_getchdr.c: New file.
+	* gelf_xlate.c (__elf_xfctstom): Add ELF_T_CHDR cvt_chdr.
+	* gelf_xlate.h: Add Chdr.
+	* libelf.h (Elf_Type): Add ELF_T_CHDR.
+	(elf32_getchdr): New function definition.
+	(elf64_getchdr): Likewise.
+	* libelf.map (ELFUTILS_1.7): New sections add elf32_getchdr,
+	elf64_getchdr and gelf_getchdr.
+	* libelfP.h: Add ELF_E_NOT_COMPRESSED, ELF_E_INVALID_SECTION_TYPE
+	and ELF_E_INVALID_SECTION_FLAGS.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libelf_so_LDLIBS): Add -lz.
+
+2015-10-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elf.h: Update from glibc. Add section compression constants and
+	structures.
+
+2015-10-20  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* elf_begin.c (get_shnum): Elf64_Shdr.sh_size is an Elf64_Xword.
+	Fix the size argument to pread_retry.
+
+2015-10-13  Chih-Hung Hsieh  <chh@google.com>
+
+	* elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)): Move nested
+	function 'fill_mmap' to file scope.
+	* elf_begin.c (elf_begin): Move nested function 'lock_dup_elf'
+	to file scope.
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* libelf.h: Replace loff_t with int64_t throughout.
+
+2015-10-05  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_update.c (write_file): Only use posix_fallocate when using
+	mmap. Only report failure when errno is ENOSPC.
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* libelfP.h (struct Elf): Replace off64_t with off_t.
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Likewise.
+
+2015-10-05  Chih-Hung Hsieh <chh@google.com>
+
+	* elf_getarsym.c (elf_getarsym): Do not use
+	union of variable length arrays.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (libelf.so): Add AM_V_CCLD and AM_V_at silencers.
+
+2015-09-24  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* Makefile.am (AM_CFLAGS): Use -fPIC instead of -fpic to avoid
+	relocation overflows in some platforms.
+
+2015-09-29  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatenull.c (default_ehdr): Set e_version when EV_NONE.
+	(updatenull_wrlock): Always set e_shentsize.
+
+2015-09-23  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_getehdr.c (getehdr_wrlock): Mark as internal_function.
+	* elf32_getshdr.c (getshdr_rdlock): Likewise.
+	(getshdr_wrlock): Likewise.
+	* elf_error.c (__libelf_seterrno): Likewise.
+	* elf_getphdrnum.c (__elf_getphdrnum_rdlock): Likewise.
+	(__elf_getphdrnum_chk_rdlock): Likewise.
+	* elf_getshdrnum.c (__elf_getphdrnum_rdlock): Likewise.
+	(__elf_getphdrnum_chk_rdlock): Likewise.
+	* elf_getshdrnum.c (__elf_getshdrnum_rdlock): Likewise.
+	* elf_readall.c (__libelf_readall): Likewise.
+	* gelf_getehdr.c (__gelf_getehdr_rdlock): Likewise.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* *.c: Remove old-style function definitions.
+
+2015-06-22  Mark Wielaard  <mjw@redhat.com>
+
+	* dl-hash.h: Update from glibc.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (updatefile): Always free shdr_data and scns
+	when allocated on failure paths.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* nlist.c (nlist): Check symscn shdr exists before use.
+
+2015-06-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_update.c (write_file): Always also use ftruncate before
+	posix_fallocate to make sure file has the right size.
+
+2015-06-04  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (__libelf_type_aligns): Add entries for ELF_T_EHDR,
+	ELF_T_OFF, ELF_T_PHDR, ELF_T_SHDR, ELF_T_SWORD, ELF_T_XWORD,
+	ELF_T_SXWORD, ELF_T_GNUHASH, ELF_T_AUXV.
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Check alignment
+	of rawdata against requested type.
+
+2015-06-02  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (convert_data): Make sure source data is properly
+	aligned for type before calling actual conversion function.
+
+2015-06-04  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (get_shnum): Check alignment of Shdr, not Ehdr before
+	direct access.
+
+2015-06-02  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (file_read_elf): Split checks for ehdr and shdr
+	alignment, drop phdr alignment check.
+
+2015-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_getshdr.c (load_shdr_wrlock): Allocate shdrs with malloc,
+	not alloca and free after conversion when a copy needs to be made.
+
+2015-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_getphdr.c (getphdr_wrlock): Allocate phdrs with malloc, not
+	alloca and free after conversion when a copy needs to be made.
+
+2015-05-31  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getarsym.c (elf_getarsym): Allocate temporary file_date with
+	malloc, not alloca also in !ALLOW_UNALIGNED case.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* gelf_xlate.c (elf_cvt_Byte): Only call memmove with non-zero size.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (updatemmap): Only call mempcpy and update
+	last_position when d_size is non-zero.
+
+2015-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (updatefile): Allocate shdr_data and scns
+	with malloc, not alloca. Free after writing section headers.
+
+2015-05-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (updatemmap): Allocate temporary shdr storage
+	with malloc, not alloca. Free after writing section header.
+
+2015-05-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getarsym.c (elf_getarsym): Allocate temporary file_date with
+	malloc, not alloca. Call free after out.
+
+2015-05-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_update.c (write_file): Use posix_fallocate instead of
+	ftruncate to extend file if necessary.
+
+2015-05-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatenull.c (default_ehdr): If e_phnum is zero then set
+	e_phoff also to zero.
+
+2015-05-12  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatenull.c (updatenull_wrlock): Check that sh_addralign
+	is a powerof2.
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Clamp large d_aligns
+	to the elf image offset.
+
+2015-05-12  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_newphdr.c (newphdr): Call __libelf_seterrno with
+	ELF_E_INVALID_INDEX before failing. Check whether section zero shdr
+	actually exists if we need to put extended phnum in section zero.
+
+2015-05-08  Mark Wielaard  <mjw@redhat.com>
+
+	* nlist.c (nlist): Call gelf_fsize with EV_CURRENT.
+
+2015-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* version_xlate.h (elf_cvt_Verdef): Use memmove to copy src to dest.
+	(elf_cvt_Verneed): Likewise.
+
+2015-03-28  Mark Wielaard  <mjw@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2015-03-23  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatenull.c (updatenull_wrlock): Don't extend size with
+	SHT_NOBITS sh_offset.
+
+2015-02-18  Mark Wielaard  <mjw@redhat.com>
+
+	* libelfP.h (__libelf_set_data_list_rdlock): Make internal_function.
+
+2015-02-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* elf32_updatenull.c (__elfw2(LIBELFBITS,updatenull_wrlock)): Consider
+	sh_addralign 0 as 1.
+
+2015-01-22  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_strptr (elf_strptr): Make sure returned string is NUL
+	terminated.
+
+2015-01-21  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_strptr.c (elf_strptr): Check data_list_rear == NULL instead
+	of rawdata_base != NULL before using rawdata directly.
+
+2015-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* libelfP.h (__elf_strptr_internal): New function declaration.
+	* elf_getdata.c (__libelf_set_data_list_rdlock): New internal
+	function extracted from...
+	(__elf_getdata_rdlock): ... here.
+	* elf_newdata.c (elf_newdata): Check scn->rawdata_base and update
+	datalist if necessary.
+
+2015-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_strptr.c (elf_strptr): Call __elf[32|64]_getshdr_rdlock if
+	necessary.
+
+2014-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getphdrnum.c (__elf_getphdrnum_chk_rdlock): New function.
+	(elf_getphdrnum): Call __elf_getphdrnum_chk_rdlock.
+	* gelf_getphdr (gelf_getphdr): Call __elf_getphdrnum_chk_rdlock
+	and always check ndx against phnum.
+	* libelfP.h (__elf_getphdrnum_chk_rdlock): New internal function.
+
+2014-12-25  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (__libelf_next_arhdr_wrlock): ar_size cannot be
+	negative. Include start_offset in maxsize.
+
+2014-12-28  Alexander Cherepanov  <cherepan@mccme.ru>
+
+	* elf_begin.c (read_long_names): Don't miss '/' right after
+	another '/'. Fixes a dir traversal vuln in ar extraction.
+
+2014-12-18  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am: Suppress output of textrel_check command.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (read_long_names): Make sure long_names len fits
+	in mapped ELF file.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getarsym.c (elf_getarsym): Check index_size doesn't overflow.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (read_long_names): Clear any garbage left in the
+	name table.
+
+2014-12-11  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (file_read_elf): Correct ELF64 section offset check.
+
+2014-12-11  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (read_long_names): Check for offset overflow.
+	(__libelf_next_arhdr_wrlock): Likewise. Sanity check the ar_size.
+	Don't allow it to go beyond end of file.
+
+2014-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getarsym.c (elf_getarsym): Make sure n * w doesn't overflow.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libelf.so): Use textrel_check.
+
+2014-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Change signed
+	overflow check to unsigned.
+
+2014-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* note_xlate.h (elf_cvt_note): Copy over any leftover data if
+	src != dest. The data is probably part of truncated name/desc.
+
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getphdrnum.c (elf_getphdrnum): Sanity check the
+	__elf_getphdrnum_rdlock result.
+
+2014-11-18  Mark Wielaard  <mjw@redhat.com>
+
+	* version_xlate.h (elf_cvt_Verdef): Check for overflow.
+	(elf_cvt_Verneed): Likewise.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* elf-knowledge.h (SECTION_STRIP_P): Check name is not NULL.
+
+2014-11-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getshdrstrndx.c: Check there are section headers before
+	handling SHN_XINDEX.
+
+2014-11-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_getphdr.c (getphdr_wrlock): Check e_phoff isn't zero.
+	Check for too many pheaders.
+	* elf_getphdrnum.c (__elf_getphdrnum_rdlock): Check section zero
+	actually exists before handling PN_XNUM.
+
+2014-11-16  Mark Wielaard  <mjw@redhat.com>
+
+	* gelf_getnote.c (gelf_getnote): Check padding overflow.
+
+2014-11-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Declare offset, size
+	and align as Elf64_Off and Elf64_Xword not size_t.
+
+2014-11-14  Mark Wielaard  <mjw@redhat.com>
+
+	* gelf_getnote.c (gelf_getnote): Check offset overflow.
+
+2014-11-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Fix unsigned overflow
+	check.
+
+2014-11-08  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (__libelf_next_arhdr_wrlock): Use mempcpy not __mempcpy.
+
+2014-11-07  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_begin.c (file_read_elf): Correct sh_size check.
+	* elf_getdata.c (__libelf_set_rawdata_wrlock): Check for unsigned
+	overflow.
+
+2014-09-10  Petr Machata  <pmachata@redhat.com>
+
+	* elf_begin (read_unmmaped_file): Call __libelf_seterrno if the
+	file is unreadable.
+
+2014-07-07  Mark Wielaard  <mjw@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2014-04-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove !MUDFLAP conditions.
+	* elf_begin.c (read_file): Don't clear use_mmap when _MUDFLAP is
+	defined.
+	* elf_update.c (write_file): Remove _MUDFLAP condition.
+
+2014-01-17  Jakub Jelinek  <jakub@redhat.com>
+	    Roland McGrath  <roland@redhat.com>
+
+	* libelfP.h (INVALID_NDX): Define.
+	* gelf_getdyn.c (gelf_getdyn): Use it.  Remove ndx < 0 test if any.
+	* gelf_getlib.c (gelf_getlib): Likewise.
+	* gelf_getmove.c (gelf_getmove): Likewise.
+	* gelf_getrel.c (gelf_getrel): Likewise.
+	* gelf_getrela.c (gelf_getrela): Likewise.
+	* gelf_getsym.c (gelf_getsym): Likewise.
+	* gelf_getsyminfo.c (gelf_getsyminfo): Likewise.
+	* gelf_getsymshndx.c (gelf_getsymshndx): Likewise.
+	* gelf_getversym.c (gelf_getversym): Likewise.
+	* gelf_update_dyn.c (gelf_update_dyn): Likewise.
+	* gelf_update_lib.c (gelf_update_lib): Likewise.
+	* gelf_update_move.c (gelf_update_move): Likewise.
+	* gelf_update_rel.c (gelf_update_rel): Likewise.
+	* gelf_update_rela.c (gelf_update_rela): Likewise.
+	* gelf_update_sym.c (gelf_update_sym): Likewise.
+	* gelf_update_syminfo.c (gelf_update_syminfo): Likewise.
+	* gelf_update_symshndx.c (gelf_update_symshndx): Likewise.
+	* gelf_update_versym.c (gelf_update_versym): Likewise.
+
+2014-01-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* elf32_getphdr.c (elfw2(LIBELFBITS,getphdr)): Check if program header
+	table fits into object's bounds.
+	* elf_getshdrstrndx.c (elf_getshstrndx): Add elf->start_offset to
+	elf->map_address.  Check if first section header fits into object's
+	bounds.
+	* elf32_getshdr.c (elfw2(LIBELFBITS,getshdr)):
+	Check if section header table fits into object's bounds.
+	* elf_begin.c (get_shnum): Ensure section headers fits into
+	object's bounds.
+	(file_read_elf): Make sure scncnt is small enough to allocate both
+	ElfXX_Shdr and Elf_Scn array.  Make sure section and program header
+	tables fit into object's bounds.  Avoid memory leak on failure.
+	* elf_newscn.c (elf_newscn): Check for overflow.
+	* elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)): Likewise.
+	(__elfw2(LIBELFBITS,updatefile)): Likewise.
+	* elf32_newphdr.c (elfw2(LIBELFBITS,newphdr)): Likewise.
+	* elf_getarsym.c (elf_getarsym): Likewise.
+
+2013-11-08  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (elfXX_updatemmap): Only memcpy ehdr when not
+	already directly mmapped.
+
+2013-11-05  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_updatefile.c (elfXX_updatefile): Copy all section headers
+	if elf->flags dirty.
+
+2013-11-01  Michael Forney  <mforney@mforney.org>
+
+	* Makefile.am: Use READELF.
+
+2013-10-01  Petr Machata  <pmachata@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2013-06-17  Petr Machata  <pmachata@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2013-08-28  Namhyung Kim  <namhyung@gmail.com>
+
+	* gelf.h (gelf_fsize): Fix typo in comment.
+
+2013-08-28  Mark Wielaard  <mjw@redhat.com>
+
+	* gelf_getauxv.c (gelf_getauxv): Add missing whitespace.
+
+2013-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* gelf_getauxv.c (gelf_getauxv): Remove unnecessary casts to char *.
+
+2013-08-25  Kurt Roeckx  <kurt@roeckx.be>
+
+	* gelf_getauxv.c (gelf_getauxv): Use memcpy instead of pointer
+	dereference to avoid alignment problems.
+
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* elf_getarsym.c (elf_getarsym): Copy FILE_DATA into stack space if it
+	would be unaligned and !ALLOW_UNALIGNED.
+
+	* elf_getarsym.c (read_number_entries): Use memcpy instead of pointer
+	dereference so as not to assume the field is naturally aligned.
+
+2012-09-17  Petr Machata  <pmachata@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2012-08-16  Roland McGrath  <roland@hack.frob.com>
+
+	* elf.h: Update from glibc.
+
+2012-08-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_checksum.c (ebl_debugscn_p): Removed unused define and
+	confusing outdated comment.
+
+2012-08-01  Petr Machata  <pmachata@redhat.com>
+
+	* elf_getarsym (read_number_entries): New function.
+	(elf_getarsym): Handle 64-bit symbol table, stored in special
+	entry named "/SYM64/".
+	* elf_begin.c (__libelf_next_arhdr_wrlock): Don't reject archive
+	because it contains 64-bit symbol table.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_getshdr.c (load_shdr_wrlock): Add elf->flags & ELF_F_MALLOCED
+	to asserts.
+
+2012-07-17  Petr Machata  <pmachata@redhat.com>
+
+	* elf32_xlatetom.c (elfw2(LIBELFBITS, xlatetom)): Do not check for
+	integer number of records in case of ELF_T_NHDR.
+
+2012-04-02  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32_offscn.c: Do not match SHT_NOBITS sections at OFFSET unless
+	there are no nonempty sections at that offset.
+
+2012-03-21  Roland McGrath  <roland@hack.frob.com>
+
+	* elf-knowledge.h (SECTION_STRIP_P): Remove < SHT_NUM check.
+
+2011-02-26  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_end.c (elf_end): Call rwlock_unlock before rwlock_fini.
+
+2011-01-05  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Fix off64_t overflow
+	when MAXIMUM_SIZE == ~0.
+
+2010-08-18  Roland McGrath  <roland@redhat.com>
+
+	* gelf_fsize.c (__libelf_type_sizes): Add entries for ELF_T_LIB
+	and ELF_T_GNUHASH.
+	Reported by Mark Hatle <mark.hatle@windriver.com>.
+
+	* exttypes.h: Add cases for ElfNN_Lib.
+	Reported by Mark Hatle <mark.hatle@windriver.com>.
+
+2010-06-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* gelf_update_shdr.c: Implicitly set ELF_F_DIRTY bit.
+	* gelf_update_phdr.c: Likewise.
+	* gelf_update_ehdr.c: Likewise.
+
+2010-04-14  Roland McGrath  <roland@redhat.com>
+
+	* elf32_getphdr.c: Check for e_phoff/size outside the file bounds.
+	* elf_begin.c (file_read_elf): Don't set .phdr here.
+
+2010-04-13  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2010-04-06  Roland McGrath  <roland@redhat.com>
+
+	* elf_error.c (ELF_E_FD_MISMATCH_IDX): Avoid nonobvious abbreviation
+	in error message.
+
+2010-04-01  Petr Machata  <pmachata@redhat.com>
+
+	* elf_getdata.c (__elf_getdata_rdlock): Initialize data.s for data
+	that do not need a conversion.
+
+2010-03-11  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2010-03-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2010-02-17  Roland McGrath  <roland@redhat.com>
+
+	* elf_begin.c (file_read_elf): Leave section rawdata_base and
+	data_base pointers null when [sh_offset,sh_size) points outside
+	the mapped file.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+2010-01-07  Roland McGrath  <roland@redhat.com>
+
+	* elf32_getphdr.c: Use __elf_getphdrnum_rdlock.
+	* gelf_getphdr.c: Likewise.
+	* gelf_update_phdr.c: Likewise.
+	* elf32_updatefile.c (__elf32_updatemmap, __elf32_updatefile): Likewise.
+	* elf32_updatenull.c (__elf32_updatenull_wrlock): Likewise.
+	* elf32_newphdr.c: Clear section 0's sh_info when resetting e_phnum.
+	If COUNT is too large, use store PN_XNUM instead and set sh_info.
+	* elf_begin.c (file_read_elf): Always allocate space we can use later
+	for section 0 if doing RDWR.
+
+	* elf_getphdrnum.c: New file.
+	* Makefile.am (libelf_a_SOURCES): Add it.
+	* libelf.h: Declare elf_getphdrnum.
+	* libelfP.h: Declare __elf_getphdrnum_rdlock.
+	* libelf.map (ELFUTILS_1.6): New set, add elf_getphdrnum.
+
+	* elf.h: Update from glibc.
+
+2009-10-23  Lubomir Rintel  <lkundrak@v3.sk>
+
+	* elf32_updatefile.c (fill_mmap): When starting past shdr_end, start
+	filling from section start, not shdr_end.
+
+2009-11-10  Roland McGrath  <roland@redhat.com>
+
+	* elf_readall.c (__libelf_readall): Fetch file size if not yet known.
+
+2009-11-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elf_next.c (elf_next): Mark the archive header as unusable when
+	there is no next ar element.
+
+2009-08-12  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (libelf.so): Use -Wl,-z,defs not -defs.
+
+2009-07-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2009-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (__elfXX_updatemmap): Fix handling of gaps between
+	sections.  Patch by Lubomir Rintel <lkundrak@v3.sk>.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* libelfP.h (struct Elf): Remove unused ar.has_index field.
+	Reorder various members for optimal packing.
+
+2009-07-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2009-06-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libelf_a_SOURCES): Replace elf_getshnum.c and
+	elf_getshstrndx.c with elf_getshdrnum.c and elf_getshdrstrndx.c.
+	* elf_getshnum.c: Renamed to...
+	* elf_getshdrnum.c: ...this.  Rename function and add old name as
+	alias.  Likewise for internal functions with derived names.
+	* elf_getshstrndx.c: Renamed to...
+	* elf_getshdrstrndx.c: ...this.  Rename function and add old name as
+	alias.  Likewise for internal functions with derived names.
+	* libelf.h: Add prototypes for new names.  Make old names as
+	deprecated.
+	* libelfP.h: Rename internal function prototypes.
+	* libelf.map: Export for names.
+	* elf32_checksum.c: Don't use deprecated functions.
+	* elf32_getshdr.c: Likewise.
+
+2009-06-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2009-04-01  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2009-02-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (updatefile): For the zeroth section we still
+	have to copy the section header.
+
+2009-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_strptr.c: Add comment re possible problem.
+
+2009-01-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatenull.c (updatenull_wrlock): Fix comment of
+	ELF_F_LAYOUT behaviour re section header table.
+
+2009-01-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (__elfXX_updatemmap): Fill the gap between
+	sections even if only the section at the start of the gap has been
+	changed.
+	(__elfXX_updatefile): Likewise.
+
+2009-01-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (__elfXX_updatemmap): Skip most of the loop to
+	handle sections for NOBITS sections.
+	(elfXX_updatefile): Likewise.
+
+	* elf32_updatefile.c (__elfXX_updatemmap): When skipping non-NOBITS
+	sections we haven't loaded, update last_position based on scn_start,
+	not based on old value.  Don't run the loop for the dummy section 0.
+	(elfXX_updatefile): Don't run the loop for the dummy section 0.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* libelfP.h (_): We only have one translation domain, elfutils.
+
+	* Makefile.am: Use USE_LOCKS instead of USE_TLS.
+	* elf_error.c: Always use __thread.  Remove all !USE_TLS code.
+
+2009-01-04  Roland McGrath  <roland@redhat.com>
+
+	* note_xlate.h (elf_cvt_note): Don't examine a size too small to
+	container a note header.
+
+2008-12-11  Roland McGrath  <roland@redhat.com>
+
+	* elf32_updatefile.c (__elfw2(LIBELFBITS,updatemmap)): Handle
+	placement offset going backwards, for out-of-order or overlapping
+	(bogus) sh_offset layouts.  It's a dumb use, but should not crash.
+	(__elfw2(LIBELFBITS,updatefile)): Likewise.
+	Fixes RHBZ#476136.
+
+	* libelf.h (Elf_Data): Whitespace fix.
+
+2008-12-10  Roland McGrath  <roland@redhat.com>
+
+	* elf_getarhdr.c (elf_getarhdr): Fix missing rename in last change.
+
+2008-10-22  Petr Machata  <pmachata@redhat.com>
+
+	* elf_rawfile.c (elf_rawfile): Lock around elf-> references.
+
+2008-10-21  Petr Machata  <pmachata@redhat.com>
+
+	* libelfP.h: Rename getehdr_rdlock to getehdr_wrlock.
+	* elf32_getehdr.c (getehdr_rdlock): Move the code to new function
+	getehdr_impl and make it a wrapper.  Rename to getehdr_wrlock.
+	(getehdr_impl): Guard elf->class init with wrlock.
+	(getehdr): Also make it a wrapper of getehdr_impl.
+	* elf32_updatenull.c (updatenull_wrlock): Call getehdr_wrlock.
+
+2008-10-20  Petr Machata  <pmachata@redhat.com>
+
+	* elf_getdata_rawchunk.c (elf_getdata_rawchunk): Lock around the
+	code that reads mutable elf state.  Relock to write lock to chain
+	the new chunk on the elf rawchunks list.
+
+2008-10-20  Petr Machata  <pmachata@redhat.com>
+
+	* elf32_checksum.c (checksum): Place a lock around the code that
+	processes data.  Make it wrlock if the code needs to xlate the
+	data before processing.
+
+2008-10-16  Petr Machata  <pmachata@redhat.com>
+
+	* elf_begin.c
+	(__libelf_next_arhdr): Rename to __libelf_next_arhdr_wrlock.
+	(dup_elf): Adjust the call.
+	(elf_begin): New local function lock_dup_elf.  Relocks the elf if
+	necessary before calling dup.  Call this instead of dup_elf.
+	* elf_getarhdr.c
+	(elf_getarhdr): Lock before calling __libelf_next_arhdr_wrlock.
+	* elf_next.c (elf_next): Likewise.
+	* elf_rand.c (elf_rand): Likewise.
+
+2008-10-14  Petr Machata  <pmachata@redhat.com>
+
+	* elf_getdata.c (__elf_getdata_rdlock): Lock before converting.
+
+2008-11-26  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2008-10-06  Roland McGrath  <roland@redhat.com>
+
+	* elf_getarhdr.c (elf_getarhdr): Return NULL when passed NULL.
+
+2008-08-27  Roland McGrath  <roland@redhat.com>
+
+	* elf_begin.c (get_shnum): Avoid misaligned reads for matching endian.
+
+	* libelfP.h [!ALLOW_UNALIGNED] (__libelf_type_align): Fix CLASS index.
+
+2008-08-25  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libelf_so_LDLIBS): New variable.
+	(libelf.so): Use it in the link.
+
+2008-08-21  Petr Machata  <pmachata@redhat.com>
+
+	* elf_getdata.c, libelfP.h
+	(__elf_getdata_internal): Rename to __elf_getdata_rdlock.
+	(__libelf_set_rawdata_wrlock): New function.
+	(__libelf_set_rawdata): Make it a wrapper that calls *_wrlock.
+	* elf32_updatenull.c, libelfP.h
+	(__elfNN_updatenull): Rename to __elfNN_updatenull_wrlock.
+
+2008-08-21  Petr Machata  <pmachata@redhat.com>
+
+	* elf32_getphdr.c, libelfP.h
+	(__elfNN_getphdr_internal): Drop.  Move __elfNN_getphdr_internal
+	code to __elfNN_getphdr_wrlock.
+	(__elfNN_getphdr_rdlock, __elfNN_getphdr_wrlock): New functions.
+	(__elfNN_getphdr_rdlock, __elfNN_getphdr_wrlock): Make these
+	wrappers of getphdr_impl.
+
+2008-08-21  Petr Machata  <pmachata@redhat.com>
+
+	* elf32_getehdr.c, libelfP.h
+	(__elfNN_getehdr_internal): Rename to __elfNN_getehdr_rdlock.
+	* gelf_getehdr, libelfP.h:
+	(__gelf_getehdr_internal): Rename to __gelf_getehdr_rdlock.
+
+2008-08-21  Petr Machata  <pmachata@redhat.com>
+
+	* elf32_getshdr.c
+	(__elfNN_getshdr_internal): Drop.
+	(load_shdr_wrlock, scn_valid): New functions, contain bits of
+	behaviour from __elfNN_getshdr_internal.
+	(__elfNN_getshdr_rdlock, __elfNN_getshdr_wrlock): Replacements for
+	dropped _internal functions above.
+	* elf_getshnum.c
+	(__elf_getshnum_internal): Rename to __elf_getshnum_rdlock.
+
+2008-08-04  Petr Machata  <pmachata@redhat.com>
+
+	* libelfP.h (RWLOCK_RDLOCK, RWLOCK_WRLOCK, RWLOCK_UNLOCK): New macros.
+
+2008-07-28  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2008-03-31  Roland McGrath  <roland@redhat.com>
+
+	* elf32_offscn.c: Make sure shdrs have been read in.
+
+2008-02-19  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2008-02-08  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2008-01-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_strptr.c (elf_strptr): Don't fail if the ELF file is currently
+	under construction and no raw data can be read from disk.
+
+2008-01-30  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2008-01-26  Roland McGrath  <roland@redhat.com>
+
+	* elf_begin.c (__libelf_next_arhdr): Rewrite conversions using a macro.
+	Fixes various pastos in wrong type in sizeof, wrong string parsed.
+
+2008-01-20  Roland McGrath  <roland@redhat.com>
+
+	* elf_getaroff.c: Calculate from start_offset, instead of using
+	parent's state.ar.offset field.
+
+2008-01-08  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (euinclude): Variable removed.
+	(pkginclude_HEADERS): Set this instead of euinclude_HEADERS.
+
+2008-01-03  Roland McGrath  <roland@redhat.com>
+
+	* common.h: Add __attribute__ ((unused)) to static functions.
+
+2007-12-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (libelf_a_SOURCES): Add elf_scnshndx.
+	* libelfP.h (struct Elf_Scn): Add shndx_index field.
+	Declare __elf_scnshndx_internal.
+	* elf32_getshdr.c: Record location of extended section header.
+	* elf_begin.c (file_read_elf): Likewise.
+	* elf_scnshndx.c: New file.
+	* libelf.h: Declare elf_scnshndx.
+	* libelf.map: Add elf_scnshndx to version ELFUTILS_1.4.
+
+2007-11-12  Roland McGrath  <roland@redhat.com>
+
+	* libelf.h: Replace off64_t with loff_t throughout.
+	Only that type name is unconditionally defined by <sys/types.h>
+
+2007-11-03  Roland McGrath  <roland@redhat.com>
+
+	* libelf.h (Elf_Data): Comment fix.
+
+2007-10-18  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2007-10-07  Roland McGrath  <roland@redhat.com>
+
+	* elf_begin.c (__libelf_next_arhdr): Fix fencepost error and wrong
+	member access in terminating name with no trailing /.  Trim trailing
+	spaces when there is no /.
+
+2007-10-04  Roland McGrath  <roland@redhat.com>
+
+	* elf_end.c (elf_end): Don't free ELF->state.ar.ar_sym when it's -1l.
+
+2007-10-03  Roland McGrath  <roland@redhat.com>
+
+	* libelf.h (Elf_Data): Use off64_t for d_off.
+	(Elf_Arhdr): Use off64_t for ar_size.
+	(elf_update, elf_getbase, elf_getaroff): Return off64_t.
+
+	* gelf_rawchunk.c: File removed.
+	* gelf_freechunk.c: File removed.
+	* Makefile.am (libelf_a_SOURCES): Remove them.
+	* libelf.map (ELFUTILS_1.0): Remove exports.
+	* gelf.h: Remove decls.
+
+	* elf_getdata_rawchunk.c: New file.
+	* Makefile.am (libelf_a_SOURCES): Add it.
+	* libelf.map (ELFUTILS_1.3): Add elf_getdata_rawchunk.
+	* libelf.h: Declare it.
+	* libelfP.h (Elf_Data_Chunk): New type.
+	(struct Elf.elf): New member `rawchunks'.
+	* elf_end.c (elf_end): Free recorded rawchunk buffers.
+
+2007-08-24  Roland McGrath  <roland@redhat.com>
+
+	* gelf_getnote.c: New file.
+	* Makefile.am (libelf_a_SOURCES): Add it.
+	* gelf.h: Declare gelf_getnote.
+	* libelf.map (ELFUTILS_1.3): Add gelf_getnote.
+
+	* libelfP.h (NOTE_ALIGN): New macro.
+	* note_xlate.h: New file.
+	* Makefile.am (noinst_HEADERS): Add it.
+	* gelf_xlate.c: Include it.
+	(__elf_xfctstom): Use elf_cvt_note.
+	* elf_getdata.c (shtype_map, __libelf_type_align): Handle SHT_NOTE.
+	(__libelf_set_rawdata): Likewise.
+
+2007-08-19  Roland McGrath  <roland@redhat.com>
+
+	* gelf_update_auxv.c: New file.
+	* gelf_getauxv.c: New file.
+	* Makefile.am (libelf_a_SOURCES): Add them.
+	* gelf.h: Declare gelf_getauxv, gelf_update_auxv.
+	* libelf.map (ELFUTILS_1.3): New set, inherits fom ELFUTILS_1.2.
+	Export gelf_getauxv, gelf_update_auxv.
+
+	* libelf.h (Elf_Type): Add ELF_T_AUXV.
+	* abstract.h: Add auxv_t entries.
+	* exttypes.h: Likewise.
+	* gelf_xlate.h: Likewise.
+	* gelf_xlate.c (__elf_xfctstom): Add ELF_T_AUXV entries.
+	* gelf_fsize.c (__libelf_type_sizes): Likewise.
+
+2007-08-12  Roland McGrath  <roland@redhat.com>
+
+	* elf32_updatefile.c (compare_sections): Sort secondarily on sh_size,
+	and only tertiarily on index.
+
+2007-07-09  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2007-04-22  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2007-03-18  Roland McGrath  <roland@redhat.com>
+
+	* elf_begin.c (get_shnum): Fix test for e_shoff being out of bounds.
+	Return zero when the section headers do not fit within MAXSIZE.
+
+2007-03-09  Roland McGrath  <roland@redhat.com>
+
+	* libelfP.h (LIBELF_EV_IDX): New macro.
+	(__libelf_type_align): New macro.
+	[! ALLOW_UNALIGNED]: Declare __libc_type_aligns array.
+	* elf_getdata.c (shtype_map): Convert to just Elf_Type[][].
+	(convert_data, __libelf_set_rawdata): Use that, __libelf_type_align,
+	and __libelf_type_sizes, in place of old table.
+	(__libc_type_aligns): New const variable.
+
+2007-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile (libelf.so): Build with -z relro.
+
+	* elf_begin.c (read_file): When using ELF_C_READ_MMAP use MAP_PRIVATE.
+
+2007-01-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* nlist.c: Close file descriptor before returning.
+
+2007-01-20  Roland McGrath  <roland@redhat.com>
+
+	* gnuhash_xlate.h (elf_cvt_gnuhash): Fix fence-post error so we
+	convert the final word.
+
+	* elf32_getshdr.c: Don't byteswap shdr fields when EI_DATA matches
+	MY_ELFDATA on !ALLOW_UNALIGNED machines.
+
+2007-01-18  Roland McGrath  <roland@redhat.com>
+
+	* gelf_rawchunk.c (gelf_rawchunk): Clear RESULT pointer after freeing
+	it on read error.
+
+2006-10-13  Roland McGrath  <roland@redhat.com>
+
+	* elf32_updatenull.c: Look for and accept phdr also for ET_CORE.
+	* elf_error.c (msgstr): Change ELF_E_INVALID_PHDR string.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* elf32_getphdr.c: Don't byteswap phdr fields when EI_DATA matches
+	MY_ELFDATA on !ALLOW_UNALIGNED machines.
+	Reported by Christian Aichinger <Greek0@gmx.net>.
+
+	* Makefile.am (CLEANFILES): Add libelf.so.$(VERSION).
+
+2006-08-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h (DT_VALNUM): Update.
+	(DT_ADDRNUM): Likewise.
+
+2006-07-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c: Adjust for internal_function_def removal.
+	* elf32_updatenull.c: Likewise.
+	* elf_begin.c: Likewise.
+	* elf_getdata.c: Likewise.
+
+2006-07-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* libelf.h: Define ELF_T_GNUHASH.
+	* elf_getdata.c (TYPEIDX): Handle SHT_GNU_HASH.
+	(shtype_map): Add SHT_GNU_HASH entries.
+	* gelf_xlate.c (__elf_xfctstom): Add ELF_T_GNUHASH entries.
+	* gnuhash_xlate.h: New file.
+	* Makefile.am (noinst_HEADERS): Add gnuhash_xlate.h.
+
+2006-07-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_gnu_hash.c: New file.
+	* libelf.h: Declare elf_gnu_hash.
+	* Makefile.am (libelf_a_SOURCES): Add elf_gnu_hash.
+	* libelf.map: Add elf_gnu_map for version ELFUTILS_1.2.
+
+2006-06-15  Roland McGrath  <roland@redhat.com>
+
+	* libelf.h (elf_getarsym): Fix comment typo.
+	Rename second parameter to be more explanatory.
+	(elf_getident, elf_rawhide): Likewise.
+
+2006-05-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (updatemmap): Preserve section content if
+	copying would overwrite them.
+	Fix msync paramters.
+
+2006-04-04  Roland McGrath  <roland@redhat.com>
+
+	* elf32_updatefile.c (updatemmap): Handle other-endian case.
+
+2006-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (updatemmap): Cleanups.  Remove shdr_dest
+	variable.  Before writing sections, make a copy of the section
+	header data if necessary.  Don't write section header while
+	writing the section constent, it might overwrite some sections.
+	Restore the pointer afterwards.
+	* elf32_updatenull.c (updatenull): If the offset of a section in a
+	file changed make sure we read the section so that it'll be written
+	out.
+
+	* elf_update.c: Remove debug message.
+
+2005-12-07  Roland McGrath  <roland@redhat.com>
+
+	* gelf_xlate.c [! ALLOW_UNALIGNED] (union unaligned): New type.
+	(FETCH, STORE): New macros.
+	(INLINE3): Use those to do alignment-friendly conversion.
+
+	* elf32_getshdr.c: Include map_address and start_offset in alignment
+	calculations.
+	* elf32_getphdr.c: Likewise.
+
+2005-11-19  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2005-11-17  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2005-11-10  Roland McGrath  <roland@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2005-09-09  Roland McGrath  <roland@redhat.com>
+
+	* elf_update.c (write_file): Stat the file and fchmod it after update
+	if its mode had S_ISUID or S_ISGID bits set.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_getphdr.c: Include <system.h>.  Use pread_retry instead of
+	pread.  And branch prediction where useful.
+	* elf_begin.c: Likewise.
+	* elf_getdata.c: Likewise.
+	* elf_getshstrndx.c: Likewise.
+	* elf_readall.c: Likewise.
+	* gelf_rawchunk.c: Likewise.
+	* elf32_updatefile.c: Include <system.h>.  Use pread_retry instead of
+	pread.  And branch prediction where useful.
+	* elf_getarsym.c: Don't define pread_retry here.
+
+	* Makefile.am: Use $(LINK) not $(CC) when creating DSO.
+	(%.os): Use COMPILE.os.
+	(COMPILE.os): Filter out gconv options.
+
+2005-08-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_begin.c (file_read_elf): Avoid reading ELF header from file
+	again.  Instead accept additional parameter which points to it if we
+	don't use mmap.
+	(get_shnum): Use passed in e_ident value as source of ELF header.
+
+2005-08-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_begin.c (__libelf_next_arhdr): Use TEMP_FAILURE_RETRY.
+
+	* Makefile (libelf_a_SOURCES): Add elf_getaroff.c.
+	* libelf.map: Export elf_getaroff.
+	* libelf.h: Declare elf_getaroff.
+	* elf_getaroff.c: New file.
+
+2005-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_begin.c (get_shnum): Optimize memory handling.  Always read from
+	mapped file if available.  Fix access to 64-bit sh_size.  Recognize
+	overflow.
+	(file_read_elf): Likewise.
+
+2005-08-12  Roland McGrath  <roland@redhat.com>
+
+	* elf32_offscn.c: Do not match empty sections at OFFSET unless
+	there are no nonempty sections at that offset.
+
+2005-08-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2005-08-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (AM_CFLAGS): Add -fpic when BUILD_STATIC.
+
+2005-08-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* libelf.map: Move elf32_offscn, elf64_offscn, and gelf_offscn in
+	new version ELFUTILS_1.1.1.
+
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_error.c: Add handling of ELF_E_INVALID_OFFSET.
+	* elf32_offscn.c: New file.
+	* elf64_offscn.c: New file.
+	* gelf_offscn.c: New file.
+	* Makefile.am (libelf_a_SOURCES): Add elf32_offscn.c, elf64_offscn.c,
+	and gelf_offscn.c.
+	* libelf.sym: Export new symbols.
+
+2005-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf-knowledge.h (SECTION_STRIP_P): Don't handle removal of debug
+	sections here anymore.
+	* elf32_checksum.c: Adjust for change in SECTION_STRIP_P interface.
+
+	* elf_update.c (elf_update): Get write lock, not read lock.
+
+	* elf32_updatenull.c (updatenull): Get section headers if necessary
+	and possible.
+
+2005-07-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatenull.c (updatenull): If program header hasn't been loaded
+	yet, try to do it now.
+	Don't unnecessarily update overflow of section count in zeroth section
+	sh_size field.
+	If section content hasn't been read yet, do it before looking for the
+	block size.  If no section data present, infer size of section header.
+
+2005-05-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update again.
+
+2005-05-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2005-05-08  Roland McGrath  <roland@redhat.com>
+
+	* elf_begin.c (read_file) [_MUDFLAP]: Don't use mmap for now.
+	* elf_update.c (write_file) [_MUDFLAP]: Likewise.
+
+2005-03-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_checksum.c: Use INTUSE and INTDEF to avoid PLTs.
+	* elf_end.c: Likewise.
+	* elf_getdata.c: Likewise.
+	* gelf_getehdr.c: Likewise.
+	* nlist.c: Likewise.
+	* libelfP.h: Add declarations of internal functions.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* common.h (CONVERT): Make sure all values are unsigned.
+	(CONVERT_TO): Likewise.
+
+	* Makefile.am (AM_CFLAGS): Add -Wformat=2.
+	Fix rule to build libelf.so.
+
+2005-02-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Cleanup AM_CFLAGS handling.  Add -Wunused -Wextra.
+	Remove lint handling.
+	* elf32_getphdr.c: Minor cleanups.
+	* elf32_getshdr.c: Likewise.
+	* elf32_updatefile.c: Likewise.
+	* elf32_updatenull.c: Likewise.
+	* elf_begin.c: Likewise.
+	* elf_error.c: Likewise.
+	* elf_getarsym.c: Likewise.
+	* elf_getdata.c: Likewise.
+	* elf_update.c: Likewise.
+	* gelf_xlate.c: Likewise.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Check for text relocations in constructed DSO.
+
+	* Makefile.am [MUDFLAP] (AM_CFLAGS): Add -Werror -fpic -fmudflap.
+
+2005-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* gelf_getehdr.c (gelf_getehdr): Slight optimization.
+
+	* elf32_checksum.c (checksum): Do not look at NOBITS sections.
+
+	* gelf.h: Add gelf_checksum prototype.
+
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_checksum.c: Make compile with gcc 4.0.
+	* elf32_updatefile.c: Likewise.
+	* elf32_updatenull.c: Likewise.
+	* elf_begin.c: Likewise.
+	* elf_error.c: Likewise.
+	* elf_getdata.c: Likewise.
+	* elf_getident.c: Likewise.
+
+2004-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Update from glibc.
+
+2004-01-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf_update.c: Fix locking.
+	* elf_clone.c: Likewise.
+
+	* libelf.h: Define ELF_T_LIB.
+	* gelf_getlib.c: New file.
+	* gelf_update_lib.c: New file.
+	* gelf.h: Declare the new functions.  Define GElf_Lib.
+	* abstract.h: Define Lib, Lib32, Lib64.
+	* gelf_xlate.c (__elf_xfctstom): Add ELF_T_LIB entry.
+	* gelf_xlate.h: Add entry for ElfXX_Lib.
+	* elf_getdata.c: Recognize SHT_GNU_LIBLIST as a known section type.
+	* libelf.map: Add new symbols to ELFUTILS_1.1.
+	* Makefile.am (libelf_a_SOURCES): Add gelf_getlib.c and
+	gelf_update_lib.c.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+	* gelf_xlate.c (INLINE3): Avoid using cast as lvalue.
+	* dl-hash.h (_dl_elf_hash): Likewise.
+
+2004-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf-knowledge.h: New file.  From libelf subdir.
+	* Makefile.am (euincludedir): Define.
+	(euinclude_HEADERS): Add elf-knowledge.h.
+
+2003-09-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf.h: Define some PT_IA_64_HP_* constants.
+
+2003-09-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* libelfP.h (struct Elf): Move state.elf64.sizestr_offset after
+	state.elf64.scnincr to match state.elf{,32}.
+
+2003-08-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32_updatefile.c (__updatemmap): When writing back file where
+	some sections have not been read in, count their sizes based on
+	the section header.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/libelf/Makefile.am b/libelf/Makefile.am
new file mode 100644
index 0000000..3402863
--- /dev/null
+++ b/libelf/Makefile.am
@@ -0,0 +1,138 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 1996-2010, 2015 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of either
+##
+##   * the GNU Lesser General Public License as published by the Free
+##     Software Foundation; either version 3 of the License, or (at
+##     your option) any later version
+##
+## or
+##
+##   * the GNU General Public License as published by the Free
+##     Software Foundation; either version 2 of the License, or (at
+##     your option) any later version
+##
+## or both in parallel, as here.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+## General Public License for more details.
+##
+## You should have received copies of the GNU General Public License and
+## the GNU Lesser General Public License along with this program.  If
+## not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+if BUILD_STATIC
+AM_CFLAGS += $(fpic_CFLAGS)
+endif
+
+VERSION = 1
+
+lib_LIBRARIES = libelf.a
+noinst_LIBRARIES = libelf_pic.a
+noinst_DATA = $(noinst_LIBRARIES:_pic.a=.so)
+include_HEADERS = libelf.h gelf.h nlist.h
+
+noinst_HEADERS = abstract.h common.h exttypes.h gelf_xlate.h libelfP.h \
+		 version_xlate.h gnuhash_xlate.h note_xlate.h dl-hash.h \
+		 chdr_xlate.h elf32_getchdr.h
+
+if INSTALL_ELFH
+include_HEADERS += elf.h
+else
+noinst_HEADERS += elf.h
+endif
+
+pkginclude_HEADERS = elf-knowledge.h
+
+libelf_a_SOURCES = elf_version.c elf_hash.c elf_error.c elf_fill.c \
+		   elf_begin.c elf_next.c elf_rand.c elf_end.c elf_kind.c \
+		   gelf_getclass.c elf_getbase.c elf_getident.c \
+		   elf32_fsize.c elf64_fsize.c gelf_fsize.c \
+		   elf32_xlatetof.c elf32_xlatetom.c elf64_xlatetof.c \
+		   elf64_xlatetom.c gelf_xlate.c \
+		   elf32_getehdr.c elf64_getehdr.c gelf_getehdr.c \
+		   elf32_newehdr.c elf64_newehdr.c gelf_newehdr.c \
+		   gelf_update_ehdr.c \
+		   elf32_getphdr.c elf64_getphdr.c gelf_getphdr.c \
+		   elf32_newphdr.c elf64_newphdr.c gelf_newphdr.c \
+		   gelf_update_phdr.c \
+		   elf_getarhdr.c elf_getarsym.c \
+		   elf_rawfile.c elf_readall.c elf_cntl.c \
+		   elf_getscn.c elf_nextscn.c elf_ndxscn.c elf_newscn.c \
+		   elf32_getshdr.c elf64_getshdr.c gelf_getshdr.c \
+		   gelf_update_shdr.c \
+		   elf_strptr.c elf_rawdata.c elf_getdata.c elf_newdata.c \
+		   elf_getdata_rawchunk.c \
+		   elf_flagelf.c elf_flagehdr.c elf_flagphdr.c elf_flagscn.c \
+		   elf_flagshdr.c elf_flagdata.c elf_memory.c \
+		   elf_update.c elf32_updatenull.c elf64_updatenull.c \
+		   elf32_updatefile.c elf64_updatefile.c \
+		   gelf_getsym.c gelf_update_sym.c \
+		   gelf_getversym.c gelf_getverneed.c gelf_getvernaux.c \
+		   gelf_getverdef.c gelf_getverdaux.c \
+		   gelf_getrel.c gelf_getrela.c \
+		   gelf_update_rel.c gelf_update_rela.c \
+		   gelf_getdyn.c gelf_update_dyn.c \
+		   gelf_getmove.c gelf_update_move.c \
+		   gelf_getsyminfo.c gelf_update_syminfo.c \
+		   gelf_getauxv.c gelf_update_auxv.c \
+		   gelf_getnote.c \
+		   gelf_xlatetof.c gelf_xlatetom.c \
+		   nlist.c \
+		   gelf_getsymshndx.c gelf_update_symshndx.c \
+		   gelf_update_versym.c gelf_update_verneed.c \
+		   gelf_update_vernaux.c gelf_update_verdef.c \
+		   gelf_update_verdaux.c \
+		   elf_getphdrnum.c elf_getshdrnum.c elf_getshdrstrndx.c \
+		   gelf_checksum.c elf32_checksum.c elf64_checksum.c \
+		   libelf_crc32.c libelf_next_prime.c \
+		   elf_clone.c \
+		   gelf_getlib.c gelf_update_lib.c \
+		   elf32_offscn.c elf64_offscn.c gelf_offscn.c \
+		   elf_getaroff.c \
+		   elf_gnu_hash.c \
+		   elf_scnshndx.c \
+		   elf32_getchdr.c elf64_getchdr.c gelf_getchdr.c \
+		   elf_compress.c elf_compress_gnu.c
+
+libelf_pic_a_SOURCES =
+am_libelf_pic_a_OBJECTS = $(libelf_a_SOURCES:.c=.os)
+
+libelf_so_DEPS = ../lib/libeu.a
+libelf_so_LDLIBS = $(libelf_so_DEPS) -lz $(zstd_LIBS)
+if USE_LOCKS
+libelf_so_LDLIBS += -lpthread
+endif
+
+libelf_so_LIBS = libelf_pic.a
+libelf.so: $(srcdir)/libelf.map $(libelf_so_LIBS) $(libelf_so_DEPS)
+	$(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \
+		-Wl,--soname,$@.$(VERSION) \
+		-Wl,--version-script,$< \
+		$(NO_UNDEFINED) \
+		-Wl,--whole-archive $(libelf_so_LIBS) -Wl,--no-whole-archive \
+		$(libelf_so_LDLIBS)
+	@$(textrel_check)
+	$(AM_V_at)ln -fs $@ $@.$(VERSION)
+
+install: install-am libelf.so
+	$(mkinstalldirs) $(DESTDIR)$(libdir)
+	$(INSTALL_PROGRAM) libelf.so $(DESTDIR)$(libdir)/libelf-$(PACKAGE_VERSION).so
+	ln -fs libelf-$(PACKAGE_VERSION).so $(DESTDIR)$(libdir)/libelf.so.$(VERSION)
+	ln -fs libelf.so.$(VERSION) $(DESTDIR)$(libdir)/libelf.so
+
+uninstall: uninstall-am
+	rm -f $(DESTDIR)$(libdir)/libelf-$(PACKAGE_VERSION).so
+	rm -f $(DESTDIR)$(libdir)/libelf.so.$(VERSION)
+	rm -f $(DESTDIR)$(libdir)/libelf.so
+
+EXTRA_DIST = libelf.map
+
+CLEANFILES += $(am_libelf_pic_a_OBJECTS) libelf.so libelf.so.$(VERSION)
diff --git a/libelf/abstract.h b/libelf/abstract.h
new file mode 100644
index 0000000..d4515f2
--- /dev/null
+++ b/libelf/abstract.h
@@ -0,0 +1,330 @@
+/* Abstract description of component ELF types.
+   Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+/* ELF header.  */
+#define Ehdr(Bits, Ext) \
+START (Bits, Ehdr, Ext##Ehdr)						      \
+  TYPE_EXTRA (unsigned char e_ident[EI_NIDENT];)			      \
+  TYPE_XLATE (memmove (tdest->e_ident, tsrc->e_ident, EI_NIDENT);)	      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_type)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_machine)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), e_version)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Addr), e_entry)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Off), e_phoff)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Off), e_shoff)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), e_flags)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_ehsize)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_phentsize)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_phnum)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_shentsize)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_shnum)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), e_shstrndx)			      \
+END (Bits, Ext##Ehdr)
+
+#define Ehdr32(Ext) \
+  Ehdr(32, Ext)
+#define Ehdr64(Ext) \
+  Ehdr(64, Ext)
+
+
+/* Program header.  */
+#define Phdr32(Ext) \
+START (32, Phdr, Ext##Phdr)						      \
+  TYPE_NAME (ElfW2(32, Ext##Word), p_type)				      \
+  TYPE_NAME (ElfW2(32, Ext##Off), p_offset)				      \
+  TYPE_NAME (ElfW2(32, Ext##Addr), p_vaddr)				      \
+  TYPE_NAME (ElfW2(32, Ext##Addr), p_paddr)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), p_filesz)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), p_memsz)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), p_flags)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), p_align)				      \
+END (32, Ext##Phdr)
+#define Phdr64(Ext) \
+START (64, Phdr, Ext##Phdr)						      \
+  TYPE_NAME (ElfW2(64, Ext##Word), p_type)				      \
+  TYPE_NAME (ElfW2(64, Ext##Word), p_flags)				      \
+  TYPE_NAME (ElfW2(64, Ext##Off), p_offset)				      \
+  TYPE_NAME (ElfW2(64, Ext##Addr), p_vaddr)				      \
+  TYPE_NAME (ElfW2(64, Ext##Addr), p_paddr)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), p_filesz)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), p_memsz)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), p_align)				      \
+END (64, Ext##Phdr)
+
+
+/* Section header.  */
+#define Shdr32(Ext) \
+START (32, Shdr, Ext##Shdr)						      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_name)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_type)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_flags)				      \
+  TYPE_NAME (ElfW2(32, Ext##Addr), sh_addr)				      \
+  TYPE_NAME (ElfW2(32, Ext##Off), sh_offset)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_size)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_link)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_info)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_addralign)			      \
+  TYPE_NAME (ElfW2(32, Ext##Word), sh_entsize)				      \
+END (32, Ext##Shdr)
+#define Shdr64(Ext) \
+START (64, Shdr, Ext##Shdr)						      \
+  TYPE_NAME (ElfW2(64, Ext##Word), sh_name)				      \
+  TYPE_NAME (ElfW2(64, Ext##Word), sh_type)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), sh_flags)				      \
+  TYPE_NAME (ElfW2(64, Ext##Addr), sh_addr)				      \
+  TYPE_NAME (ElfW2(64, Ext##Off), sh_offset)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), sh_size)				      \
+  TYPE_NAME (ElfW2(64, Ext##Word), sh_link)				      \
+  TYPE_NAME (ElfW2(64, Ext##Word), sh_info)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), sh_addralign)			      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), sh_entsize)				      \
+END (64, Ext##Shdr)
+
+
+/* Symbol table.  */
+#define Sym32(Ext) \
+START (32, Sym, Ext##Sym)						      \
+  TYPE_NAME (ElfW2(32, Ext##Word), st_name)				      \
+  TYPE_NAME (ElfW2(32, Ext##Addr), st_value)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), st_size)				      \
+  TYPE_EXTRA (unsigned char st_info;)					      \
+  TYPE_XLATE (tdest->st_info = tsrc->st_info;)				      \
+  TYPE_EXTRA (unsigned char st_other;)					      \
+  TYPE_XLATE (tdest->st_other = tsrc->st_other;)			      \
+  TYPE_NAME (ElfW2(32, Ext##Half), st_shndx)				      \
+END (32, Ext##Sym)
+#define Sym64(Ext) \
+START (64, Sym, Ext##Sym)						      \
+  TYPE_NAME (ElfW2(64, Ext##Word), st_name)				      \
+  TYPE_EXTRA (unsigned char st_info;)					      \
+  TYPE_XLATE (tdest->st_info = tsrc->st_info;)				      \
+  TYPE_EXTRA (unsigned char st_other;)					      \
+  TYPE_XLATE (tdest->st_other = tsrc->st_other;)			      \
+  TYPE_NAME (ElfW2(64, Ext##Half), st_shndx)				      \
+  TYPE_NAME (ElfW2(64, Ext##Addr), st_value)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), st_size)				      \
+END (64, Ext##Sym)
+
+
+/* Relocation.  */
+#define Rel32(Ext) \
+START (32, Rel, Ext##Rel)						      \
+  TYPE_NAME (ElfW2(32, Ext##Addr), r_offset)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), r_info)				      \
+END (32, Ext##Rel)
+#define Rel64(Ext) \
+START (64, Rel, Ext##Rel)						      \
+  TYPE_NAME (ElfW2(64, Ext##Addr), r_offset)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), r_info)				      \
+END (64, Ext##Rel)
+
+#define Rela32(Ext) \
+START (32, Rela, Ext##Rela)						      \
+  TYPE_NAME (ElfW2(32, Ext##Addr), r_offset)				      \
+  TYPE_NAME (ElfW2(32, Ext##Word), r_info)				      \
+  TYPE_NAME (ElfW2(32, Ext##Sword), r_addend)				      \
+END (32, Ext##Rela)
+#define Rela64(Ext) \
+START (64, Rela, Ext##Rela)						      \
+  TYPE_NAME (ElfW2(64, Ext##Addr), r_offset)				      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), r_info)				      \
+  TYPE_NAME (ElfW2(64, Ext##Sxword), r_addend)				      \
+END (64, Ext##Rela)
+
+
+/* Note entry header.  */
+#define Note(Bits, Ext) \
+START (Bits, Nhdr, Ext##Nhdr)						      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), n_namesz)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), n_descsz)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), n_type)				      \
+END (Bits, Ext##Nhdr)
+
+#define Note32(Ext) \
+  Note (32, Ext)
+#define Note64(Ext) \
+  Note (64, Ext)
+
+
+/* Dynamic section data.  */
+#define Dyn32(Ext) \
+START (32, Dyn, Ext##Dyn)						      \
+  TYPE_NAME (ElfW2(32, Ext##Sword), d_tag)				      \
+  TYPE_EXTRA (union {)							      \
+  TYPE_EXTRA (ElfW2(32, Ext##Word) d_val;)				      \
+  TYPE_EXTRA (ElfW2(32, Ext##Addr) d_ptr;)				      \
+  TYPE_XLATE (Elf32_cvt_Addr1 (&tdest->d_un.d_val, &tsrc->d_un.d_val);)	      \
+  TYPE_EXTRA (ElfW2(32, Ext##Off) d_off;)				      \
+  TYPE_EXTRA (} d_un;)							      \
+END (32, Ext##Dyn)
+#define Dyn64(Ext) \
+START (64, Dyn, Ext##Dyn)						      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), d_tag)				      \
+  TYPE_EXTRA (union {)							      \
+  TYPE_EXTRA (ElfW2(64, Ext##Xword) d_val;)				      \
+  TYPE_EXTRA (ElfW2(64, Ext##Addr) d_ptr;)				      \
+  TYPE_XLATE (Elf64_cvt_Addr1 (&tdest->d_un.d_val, &tsrc->d_un.d_val);)	      \
+  TYPE_EXTRA (} d_un;)							      \
+END (64, Ext##Dyn)
+
+
+#ifndef GENERATE_CONVERSION
+/* Version definitions.  */
+# define Verdef(Bits, Ext) \
+START (Bits, Verdef, Ext##Verdef)					      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vd_version)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vd_flags)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vd_ndx)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vd_cnt)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vd_hash)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vd_aux)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vd_next)				      \
+END (Bits, Ext##Verdef)
+
+# define Verdef32(Ext) \
+  Verdef (32, Ext)
+# define Verdef64(Ext) \
+  Verdef (64, Ext)
+
+# define Verdaux(Bits, Ext) \
+START (Bits, Verdaux, Ext##Verdaux)					      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vda_name)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vda_next)				      \
+END (Bits, Ext##Verdaux)
+
+# define Verdaux32(Ext) \
+  Verdaux (32, Ext)
+# define Verdaux64(Ext) \
+  Verdaux (64, Ext)
+
+/* Required versions.  */
+# define Verneed(Bits, Ext) \
+START (Bits, Verneed, Ext##Verneed)					      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vn_version)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vn_cnt)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vn_file)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vn_aux)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vn_next)				      \
+END (Bits, Ext##Verneed)
+
+# define Verneed32(Ext) \
+  Verneed (32, Ext)
+# define Verneed64(Ext) \
+  Verneed (64, Ext)
+
+# define Vernaux(Bits, Ext) \
+START (Bits, Vernaux, Ext##Vernaux)					      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vna_hash)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vna_flags)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), vna_other)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vna_name)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), vna_next)				      \
+END (Bits, Ext##Vernaux)
+
+# define Vernaux32(Ext) \
+  Vernaux (32, Ext)
+# define Vernaux64(Ext) \
+  Vernaux (64, Ext)
+#endif
+
+/* Symbol information.  */
+#define Syminfo(Bits, Ext) \
+START (Bits, Syminfo, Ext##Syminfo)					      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), si_boundto)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), si_flags)				      \
+END (Bits, Ext##Syminfo)
+
+#define Syminfo32(Ext) \
+  Syminfo (32, Ext)
+#define Syminfo64(Ext) \
+  Syminfo (64, Ext)
+
+/* Move information.  */
+#define Move(Bits, Ext) \
+START (Bits, Move, Ext##Move)						      \
+  TYPE_NAME (ElfW2(Bits, Ext##Xword), m_value)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Xword), m_info)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Xword), m_poffset)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), m_repeat)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Half), m_stride)				      \
+END (Bits, Ext##Move)
+
+#define Move32(Ext) \
+  Move (32, Ext)
+#define Move64(Ext) \
+  Move (64, Ext)
+
+#define Lib(Bits, Ext) \
+START (Bits, Lib, Ext##Lib)						      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), l_name)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), l_time_stamp)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), l_checksum)			      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), l_version)				      \
+  TYPE_NAME (ElfW2(Bits, Ext##Word), l_flags)				      \
+END (Bits, Ext##Lib)
+
+#define Lib32(Ext) \
+  Lib (32, Ext)
+#define Lib64(Ext) \
+  Lib (64, Ext)
+
+#define auxv_t32(Ext) \
+START (32, auxv_t, Ext##auxv_t)						      \
+  TYPE_NAME (ElfW2(32, Ext##Word), a_type)				      \
+  TYPE_EXTRA (union {)							      \
+  TYPE_EXTRA (ElfW2(32, Ext##Word) a_val;)				      \
+  TYPE_XLATE (Elf32_cvt_Addr1 (&tdest->a_un.a_val, &tsrc->a_un.a_val);)	      \
+  TYPE_EXTRA (} a_un;)							      \
+END (32, Ext##auxv_t)
+#define auxv_t64(Ext) \
+START (64, auxv_t, Ext##auxv_t)						      \
+  TYPE_NAME (ElfW2(64, Ext##Xword), a_type)				      \
+  TYPE_EXTRA (union {)							      \
+  TYPE_EXTRA (ElfW2(64, Ext##Xword) a_val;)				      \
+  TYPE_XLATE (Elf64_cvt_Addr1 (&tdest->a_un.a_val, &tsrc->a_un.a_val);)	      \
+  TYPE_EXTRA (} a_un;)							      \
+END (64, Ext##auxv_t)
+
+/* Note that there is actual compression data right after the Chdr.
+   So we also have a separate conversion function for the whole
+   section.  */
+#define Chdr32(Ext) \
+START (32, Chdr, Ext##Chdr)						\
+  TYPE_NAME (ElfW2(32, Ext##Word), ch_type)				\
+  TYPE_NAME (ElfW2(32, Ext##Word), ch_size)				\
+  TYPE_NAME (ElfW2(32, Ext##Word), ch_addralign)			\
+END (32, Ext##Chdr)
+
+#define Chdr64(Ext) \
+START (64, Chdr, Ext##Chdr)						\
+  TYPE_NAME (ElfW2(64, Ext##Word), ch_type)				\
+  TYPE_NAME (ElfW2(64, Ext##Word), ch_reserved)				\
+  TYPE_NAME (ElfW2(64, Ext##Xword), ch_size)				\
+  TYPE_NAME (ElfW2(64, Ext##Xword), ch_addralign)			\
+END (64, Ext##Chdr)
diff --git a/libelf/chdr_xlate.h b/libelf/chdr_xlate.h
new file mode 100644
index 0000000..70782b4
--- /dev/null
+++ b/libelf/chdr_xlate.h
@@ -0,0 +1,33 @@
+#include "common.h"
+
+/* These functions convert a while section, one Chdr plus compression data.  */
+
+static void
+Elf32_cvt_chdr (void *dest, const void *src, size_t len, int encode)
+{
+  if (len == 0)
+    return;
+
+  /* Move everything over, if necessary, we only need to xlate the
+     header, not the compressed data following it.  */
+  if (dest != src)
+    memmove (dest, src, len);
+
+  if (len >= sizeof (Elf32_Chdr))
+    Elf32_cvt_Chdr (dest, src, sizeof (Elf32_Chdr), encode);
+}
+
+static void
+Elf64_cvt_chdr (void *dest, const void *src, size_t len, int encode)
+{
+  if (len == 0)
+    return;
+
+  /* Move everything over, if necessary, we only need to xlate the
+     header, not the compressed data following it.  */
+  if (dest != src)
+    memmove (dest, src, len);
+
+  if (len >= sizeof (Elf64_Chdr))
+    Elf64_cvt_Chdr (dest, src, sizeof (Elf64_Chdr), encode);
+}
diff --git a/libelf/common.h b/libelf/common.h
new file mode 100644
index 0000000..9b2a856
--- /dev/null
+++ b/libelf/common.h
@@ -0,0 +1,160 @@
+/* Common definitions for handling files in memory or only on disk.
+   Copyright (C) 1998, 1999, 2000, 2002, 2005, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _COMMON_H
+#define _COMMON_H       1
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+static inline Elf_Kind
+__attribute__ ((unused))
+determine_kind (void *buf, size_t len)
+{
+  /* First test for an archive.  */
+  if (len >= SARMAG && memcmp (buf, ARMAG, SARMAG) == 0)
+    return ELF_K_AR;
+
+  /* Next try ELF files.  */
+  if (len >= EI_NIDENT && memcmp (buf, ELFMAG, SELFMAG) == 0)
+    {
+      /* Could be an ELF file.  */
+      int eclass = (int) ((unsigned char *) buf)[EI_CLASS];
+      int data = (int) ((unsigned char *) buf)[EI_DATA];
+      int version = (int) ((unsigned char *) buf)[EI_VERSION];
+
+      if (eclass > ELFCLASSNONE && eclass < ELFCLASSNUM
+	  && data > ELFDATANONE && data < ELFDATANUM
+	  && version == EV_CURRENT)
+	return ELF_K_ELF;
+    }
+
+  /* We do not know this file type.  */
+  return ELF_K_NONE;
+}
+
+
+/* Allocate an Elf descriptor and fill in the generic information.  */
+static inline Elf *
+__attribute__ ((unused))
+allocate_elf (int fildes, void *map_address, int64_t offset, size_t maxsize,
+              Elf_Cmd cmd, Elf *parent, Elf_Kind kind, size_t extra)
+{
+  Elf *result = calloc (1, sizeof (Elf) + extra);
+  if (result == NULL)
+    __libelf_seterrno (ELF_E_NOMEM);
+  else
+    {
+      result->kind = kind;
+      result->ref_count = 1;
+      result->cmd = cmd;
+      result->fildes = fildes;
+      result->start_offset = offset;
+      result->maximum_size = maxsize;
+      result->map_address = map_address;
+      result->parent = parent;
+
+      rwlock_init (result->lock);
+    }
+
+  return result;
+}
+
+
+/* Acquire lock for the descriptor and all children.  */
+static void
+__attribute__ ((unused))
+libelf_acquire_all (Elf *elf)
+{
+  rwlock_wrlock (elf->lock);
+
+  if (elf->kind == ELF_K_AR)
+    {
+      Elf *child = elf->state.ar.children;
+
+      while (child != NULL)
+	{
+	  if (child->ref_count != 0)
+	    libelf_acquire_all (child);
+	  child = child->next;
+	}
+    }
+}
+
+/* Release own lock and those of the children.  */
+static void
+__attribute__ ((unused))
+libelf_release_all (Elf *elf)
+{
+  if (elf->kind == ELF_K_AR)
+    {
+      Elf *child = elf->state.ar.children;
+
+      while (child != NULL)
+	{
+	  if (child->ref_count != 0)
+	    libelf_release_all (child);
+	  child = child->next;
+	}
+    }
+
+  rwlock_unlock (elf->lock);
+}
+
+
+/* Macro to convert endianness in place.  It determines the function it
+   has to use itself.  */
+#define CONVERT(Var) \
+  (Var) = (sizeof (Var) == 1						      \
+	   ? (unsigned char) (Var)					      \
+	   : (sizeof (Var) == 2						      \
+	      ? bswap_16 (Var)						      \
+	      : (sizeof (Var) == 4					      \
+		 ? bswap_32 (Var)					      \
+		 : bswap_64 (Var))))
+
+#define CONVERT_TO(Dst, Var) \
+  (Dst) = (sizeof (Var) == 1						      \
+	   ? (unsigned char) (Var)					      \
+	   : (sizeof (Var) == 2						      \
+	      ? bswap_16 (Var)						      \
+	      : (sizeof (Var) == 4					      \
+		 ? bswap_32 (Var)					      \
+		 : bswap_64 (Var))))
+
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define MY_ELFDATA	ELFDATA2LSB
+#else
+# define MY_ELFDATA	ELFDATA2MSB
+#endif
+
+#endif	/* common.h */
diff --git a/libelf/dl-hash.h b/libelf/dl-hash.h
new file mode 100644
index 0000000..6ee5d1a
--- /dev/null
+++ b/libelf/dl-hash.h
@@ -0,0 +1,75 @@
+/* Compute hash value for given string according to ELF standard.
+   Copyright (C) 1995-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _DL_HASH_H
+#define _DL_HASH_H	1
+
+
+/* This is the hashing function specified by the ELF ABI.  In the
+   first five operations no overflow is possible so we optimized it a
+   bit.  */
+static unsigned int
+__attribute__ ((unused))
+_dl_elf_hash (const char *name_arg)
+{
+  const unsigned char *name = (const unsigned char *) name_arg;
+  unsigned long int hash = *name;
+  if (hash != 0 && name[1] != '\0')
+    {
+      hash = (hash << 4) + name[1];
+      if (name[2] != '\0')
+	{
+	  hash = (hash << 4) + name[2];
+	  if (name[3] != '\0')
+	    {
+	      hash = (hash << 4) + name[3];
+	      if (name[4] != '\0')
+		{
+		  hash = (hash << 4) + name[4];
+		  name += 5;
+		  while (*name != '\0')
+		    {
+		      unsigned long int hi;
+		      hash = (hash << 4) + *name++;
+		      hi = hash & 0xf0000000;
+
+		      /* The algorithm specified in the ELF ABI is as
+			 follows:
+
+			 if (hi != 0)
+			   hash ^= hi >> 24;
+
+			 hash &= ~hi;
+
+			 But the following is equivalent and a lot
+			 faster, especially on modern processors.  */
+
+		      hash ^= hi >> 24;
+		    }
+
+		  /* Second part of the modified formula.  This
+		     operation can be lifted outside the loop.  */
+		  hash &= 0x0fffffff;
+		}
+	    }
+	}
+    }
+  return hash;
+}
+
+#endif /* dl-hash.h */
diff --git a/libelf/elf-knowledge.h b/libelf/elf-knowledge.h
new file mode 100644
index 0000000..6e005fa
--- /dev/null
+++ b/libelf/elf-knowledge.h
@@ -0,0 +1,101 @@
+/* Accumulation of various pieces of knowledge about ELF.
+   Copyright (C) 2000-2012, 2014, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ELF_KNOWLEDGE_H
+#define _ELF_KNOWLEDGE_H	1
+
+#include <stdbool.h>
+
+
+/* Test whether a section can be stripped or not.  */
+#define SECTION_STRIP_P(shdr, name, remove_comment) \
+  /* Sections which are allocated are not removed.  */			      \
+  (((shdr)->sh_flags & SHF_ALLOC) == 0					      \
+   /* We never remove .note sections.  */				      \
+   && (shdr)->sh_type != SHT_NOTE					      \
+   && (((shdr)->sh_type) != SHT_PROGBITS				      \
+       /* Never remove .gnu.warning.* sections.  */			      \
+       || (name != NULL							      \
+	   && strncmp (name, ".gnu.warning.", sizeof ".gnu.warning." - 1) != 0\
+	   /* We remove .comment sections only if explicitly told to do so. */\
+	   && (remove_comment						      \
+	       || strcmp (name, ".comment") != 0))))
+
+
+/* Test whether `sh_info' field in section header contains a section
+   index.  There are two kinds of sections doing this:
+
+   - the sections containing relocation information reference in this
+     field the section to which the relocations apply;
+
+   - section with the SHF_INFO_LINK flag set to signal that `sh_info'
+     references a section.  This allows correct handling of unknown
+     sections.  */
+#define SH_INFO_LINK_P(Shdr) \
+  ((Shdr)->sh_type == SHT_REL || (Shdr)->sh_type == SHT_RELA		      \
+   || ((Shdr)->sh_flags & SHF_INFO_LINK) != 0)
+
+
+/* Size of an entry in the hash table.  The ELF specification says all
+   entries are regardless of platform 32-bits in size.  Early 64-bit
+   ports (namely Alpha for Linux) got this wrong.  The wording was not
+   clear.
+
+   Several years later the ABI for the 64-bit S390s was developed.
+   Many things were copied from the IA-64 ABI (which uses the correct
+   32-bit entry size) but it does get the SHT_HASH entry size wrong by
+   using a 64-bit entry size.  So now we need this macro to special
+   case both the alpha and s390x ABIs.  */
+#define SH_ENTSIZE_HASH(Ehdr) \
+  ((Ehdr)->e_machine == EM_ALPHA					      \
+   || ((Ehdr)->e_machine == EM_S390					      \
+       && (Ehdr)->e_ident[EI_CLASS] == ELFCLASS64) ? 8 : 4)
+
+/* GNU Annobin notes are not fully standardized and abuses the owner name.  */
+
+#define ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX "GA"
+
+#define NT_GNU_BUILD_ATTRIBUTE_OPEN 0x100
+#define NT_GNU_BUILD_ATTRIBUTE_FUNC 0x101
+
+#define GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC	'*'
+#define GNU_BUILD_ATTRIBUTE_TYPE_STRING		'$'
+#define GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE	'+'
+#define GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE	'!'
+
+#define GNU_BUILD_ATTRIBUTE_VERSION	1
+#define GNU_BUILD_ATTRIBUTE_STACK_PROT	2
+#define GNU_BUILD_ATTRIBUTE_RELRO	3
+#define GNU_BUILD_ATTRIBUTE_STACK_SIZE	4
+#define GNU_BUILD_ATTRIBUTE_TOOL	5
+#define GNU_BUILD_ATTRIBUTE_ABI		6
+#define GNU_BUILD_ATTRIBUTE_PIC		7
+#define GNU_BUILD_ATTRIBUTE_SHORT_ENUM	8
+
+#endif	/* elf-knowledge.h */
diff --git a/libelf/elf.h b/libelf/elf.h
new file mode 100644
index 0000000..f2206e5
--- /dev/null
+++ b/libelf/elf.h
@@ -0,0 +1,4477 @@
+/* This file defines standard ELF types, structures, and macros.
+   Copyright (C) 1995-2024 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _ELF_H
+#define	_ELF_H 1
+
+/* Standard ELF types.  */
+
+#include <stdint.h>
+
+/* Type for a 16-bit quantity.  */
+typedef uint16_t Elf32_Half;
+typedef uint16_t Elf64_Half;
+
+/* Types for signed and unsigned 32-bit quantities.  */
+typedef uint32_t Elf32_Word;
+typedef	int32_t  Elf32_Sword;
+typedef uint32_t Elf64_Word;
+typedef	int32_t  Elf64_Sword;
+
+/* Types for signed and unsigned 64-bit quantities.  */
+typedef uint64_t Elf32_Xword;
+typedef	int64_t  Elf32_Sxword;
+typedef uint64_t Elf64_Xword;
+typedef	int64_t  Elf64_Sxword;
+
+/* Type of addresses.  */
+typedef uint32_t Elf32_Addr;
+typedef uint64_t Elf64_Addr;
+
+/* Type of file offsets.  */
+typedef uint32_t Elf32_Off;
+typedef uint64_t Elf64_Off;
+
+/* Type for section indices, which are 16-bit quantities.  */
+typedef uint16_t Elf32_Section;
+typedef uint16_t Elf64_Section;
+
+/* Type for version symbol information.  */
+typedef Elf32_Half Elf32_Versym;
+typedef Elf64_Half Elf64_Versym;
+
+
+/* The ELF file header.  This appears at the start of every ELF file.  */
+
+#define EI_NIDENT (16)
+
+typedef struct
+{
+  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
+  Elf32_Half	e_type;			/* Object file type */
+  Elf32_Half	e_machine;		/* Architecture */
+  Elf32_Word	e_version;		/* Object file version */
+  Elf32_Addr	e_entry;		/* Entry point virtual address */
+  Elf32_Off	e_phoff;		/* Program header table file offset */
+  Elf32_Off	e_shoff;		/* Section header table file offset */
+  Elf32_Word	e_flags;		/* Processor-specific flags */
+  Elf32_Half	e_ehsize;		/* ELF header size in bytes */
+  Elf32_Half	e_phentsize;		/* Program header table entry size */
+  Elf32_Half	e_phnum;		/* Program header table entry count */
+  Elf32_Half	e_shentsize;		/* Section header table entry size */
+  Elf32_Half	e_shnum;		/* Section header table entry count */
+  Elf32_Half	e_shstrndx;		/* Section header string table index */
+} Elf32_Ehdr;
+
+typedef struct
+{
+  unsigned char	e_ident[EI_NIDENT];	/* Magic number and other info */
+  Elf64_Half	e_type;			/* Object file type */
+  Elf64_Half	e_machine;		/* Architecture */
+  Elf64_Word	e_version;		/* Object file version */
+  Elf64_Addr	e_entry;		/* Entry point virtual address */
+  Elf64_Off	e_phoff;		/* Program header table file offset */
+  Elf64_Off	e_shoff;		/* Section header table file offset */
+  Elf64_Word	e_flags;		/* Processor-specific flags */
+  Elf64_Half	e_ehsize;		/* ELF header size in bytes */
+  Elf64_Half	e_phentsize;		/* Program header table entry size */
+  Elf64_Half	e_phnum;		/* Program header table entry count */
+  Elf64_Half	e_shentsize;		/* Section header table entry size */
+  Elf64_Half	e_shnum;		/* Section header table entry count */
+  Elf64_Half	e_shstrndx;		/* Section header string table index */
+} Elf64_Ehdr;
+
+/* Fields in the e_ident array.  The EI_* macros are indices into the
+   array.  The macros under each EI_* macro are the values the byte
+   may have.  */
+
+#define EI_MAG0		0		/* File identification byte 0 index */
+#define ELFMAG0		0x7f		/* Magic number byte 0 */
+
+#define EI_MAG1		1		/* File identification byte 1 index */
+#define ELFMAG1		'E'		/* Magic number byte 1 */
+
+#define EI_MAG2		2		/* File identification byte 2 index */
+#define ELFMAG2		'L'		/* Magic number byte 2 */
+
+#define EI_MAG3		3		/* File identification byte 3 index */
+#define ELFMAG3		'F'		/* Magic number byte 3 */
+
+/* Conglomeration of the identification bytes, for easy testing as a word.  */
+#define	ELFMAG		"\177ELF"
+#define	SELFMAG		4
+
+#define EI_CLASS	4		/* File class byte index */
+#define ELFCLASSNONE	0		/* Invalid class */
+#define ELFCLASS32	1		/* 32-bit objects */
+#define ELFCLASS64	2		/* 64-bit objects */
+#define ELFCLASSNUM	3
+
+#define EI_DATA		5		/* Data encoding byte index */
+#define ELFDATANONE	0		/* Invalid data encoding */
+#define ELFDATA2LSB	1		/* 2's complement, little endian */
+#define ELFDATA2MSB	2		/* 2's complement, big endian */
+#define ELFDATANUM	3
+
+#define EI_VERSION	6		/* File version byte index */
+					/* Value must be EV_CURRENT */
+
+#define EI_OSABI	7		/* OS ABI identification */
+#define ELFOSABI_NONE		0	/* UNIX System V ABI */
+#define ELFOSABI_SYSV		0	/* Alias.  */
+#define ELFOSABI_HPUX		1	/* HP-UX */
+#define ELFOSABI_NETBSD		2	/* NetBSD.  */
+#define ELFOSABI_GNU		3	/* Object uses GNU ELF extensions.  */
+#define ELFOSABI_LINUX		ELFOSABI_GNU /* Compatibility alias.  */
+#define ELFOSABI_SOLARIS	6	/* Sun Solaris.  */
+#define ELFOSABI_AIX		7	/* IBM AIX.  */
+#define ELFOSABI_IRIX		8	/* SGI Irix.  */
+#define ELFOSABI_FREEBSD	9	/* FreeBSD.  */
+#define ELFOSABI_TRU64		10	/* Compaq TRU64 UNIX.  */
+#define ELFOSABI_MODESTO	11	/* Novell Modesto.  */
+#define ELFOSABI_OPENBSD	12	/* OpenBSD.  */
+#define ELFOSABI_ARM_AEABI	64	/* ARM EABI */
+#define ELFOSABI_ARM		97	/* ARM */
+#define ELFOSABI_STANDALONE	255	/* Standalone (embedded) application */
+
+#define EI_ABIVERSION	8		/* ABI version */
+
+#define EI_PAD		9		/* Byte index of padding bytes */
+
+/* Legal values for e_type (object file type).  */
+
+#define ET_NONE		0		/* No file type */
+#define ET_REL		1		/* Relocatable file */
+#define ET_EXEC		2		/* Executable file */
+#define ET_DYN		3		/* Shared object file */
+#define ET_CORE		4		/* Core file */
+#define	ET_NUM		5		/* Number of defined types */
+#define ET_LOOS		0xfe00		/* OS-specific range start */
+#define ET_HIOS		0xfeff		/* OS-specific range end */
+#define ET_LOPROC	0xff00		/* Processor-specific range start */
+#define ET_HIPROC	0xffff		/* Processor-specific range end */
+
+/* Legal values for e_machine (architecture).  */
+
+#define EM_NONE		 0	/* No machine */
+#define EM_M32		 1	/* AT&T WE 32100 */
+#define EM_SPARC	 2	/* SUN SPARC */
+#define EM_386		 3	/* Intel 80386 */
+#define EM_68K		 4	/* Motorola m68k family */
+#define EM_88K		 5	/* Motorola m88k family */
+#define EM_IAMCU	 6	/* Intel MCU */
+#define EM_860		 7	/* Intel 80860 */
+#define EM_MIPS		 8	/* MIPS R3000 big-endian */
+#define EM_S370		 9	/* IBM System/370 */
+#define EM_MIPS_RS3_LE	10	/* MIPS R3000 little-endian */
+				/* reserved 11-14 */
+#define EM_PARISC	15	/* HPPA */
+				/* reserved 16 */
+#define EM_VPP500	17	/* Fujitsu VPP500 */
+#define EM_SPARC32PLUS	18	/* Sun's "v8plus" */
+#define EM_960		19	/* Intel 80960 */
+#define EM_PPC		20	/* PowerPC */
+#define EM_PPC64	21	/* PowerPC 64-bit */
+#define EM_S390		22	/* IBM S390 */
+#define EM_SPU		23	/* IBM SPU/SPC */
+				/* reserved 24-35 */
+#define EM_V800		36	/* NEC V800 series */
+#define EM_FR20		37	/* Fujitsu FR20 */
+#define EM_RH32		38	/* TRW RH-32 */
+#define EM_RCE		39	/* Motorola RCE */
+#define EM_ARM		40	/* ARM */
+#define EM_FAKE_ALPHA	41	/* Digital Alpha */
+#define EM_SH		42	/* Hitachi SH */
+#define EM_SPARCV9	43	/* SPARC v9 64-bit */
+#define EM_TRICORE	44	/* Siemens Tricore */
+#define EM_ARC		45	/* Argonaut RISC Core */
+#define EM_H8_300	46	/* Hitachi H8/300 */
+#define EM_H8_300H	47	/* Hitachi H8/300H */
+#define EM_H8S		48	/* Hitachi H8S */
+#define EM_H8_500	49	/* Hitachi H8/500 */
+#define EM_IA_64	50	/* Intel Merced */
+#define EM_MIPS_X	51	/* Stanford MIPS-X */
+#define EM_COLDFIRE	52	/* Motorola Coldfire */
+#define EM_68HC12	53	/* Motorola M68HC12 */
+#define EM_MMA		54	/* Fujitsu MMA Multimedia Accelerator */
+#define EM_PCP		55	/* Siemens PCP */
+#define EM_NCPU		56	/* Sony nCPU embedded RISC */
+#define EM_NDR1		57	/* Denso NDR1 microprocessor */
+#define EM_STARCORE	58	/* Motorola Start*Core processor */
+#define EM_ME16		59	/* Toyota ME16 processor */
+#define EM_ST100	60	/* STMicroelectronic ST100 processor */
+#define EM_TINYJ	61	/* Advanced Logic Corp. Tinyj emb.fam */
+#define EM_X86_64	62	/* AMD x86-64 architecture */
+#define EM_PDSP		63	/* Sony DSP Processor */
+#define EM_PDP10	64	/* Digital PDP-10 */
+#define EM_PDP11	65	/* Digital PDP-11 */
+#define EM_FX66		66	/* Siemens FX66 microcontroller */
+#define EM_ST9PLUS	67	/* STMicroelectronics ST9+ 8/16 mc */
+#define EM_ST7		68	/* STmicroelectronics ST7 8 bit mc */
+#define EM_68HC16	69	/* Motorola MC68HC16 microcontroller */
+#define EM_68HC11	70	/* Motorola MC68HC11 microcontroller */
+#define EM_68HC08	71	/* Motorola MC68HC08 microcontroller */
+#define EM_68HC05	72	/* Motorola MC68HC05 microcontroller */
+#define EM_SVX		73	/* Silicon Graphics SVx */
+#define EM_ST19		74	/* STMicroelectronics ST19 8 bit mc */
+#define EM_VAX		75	/* Digital VAX */
+#define EM_CRIS		76	/* Axis Communications 32-bit emb.proc */
+#define EM_JAVELIN	77	/* Infineon Technologies 32-bit emb.proc */
+#define EM_FIREPATH	78	/* Element 14 64-bit DSP Processor */
+#define EM_ZSP		79	/* LSI Logic 16-bit DSP Processor */
+#define EM_MMIX		80	/* Donald Knuth's educational 64-bit proc */
+#define EM_HUANY	81	/* Harvard University machine-independent object files */
+#define EM_PRISM	82	/* SiTera Prism */
+#define EM_AVR		83	/* Atmel AVR 8-bit microcontroller */
+#define EM_FR30		84	/* Fujitsu FR30 */
+#define EM_D10V		85	/* Mitsubishi D10V */
+#define EM_D30V		86	/* Mitsubishi D30V */
+#define EM_V850		87	/* NEC v850 */
+#define EM_M32R		88	/* Mitsubishi M32R */
+#define EM_MN10300	89	/* Matsushita MN10300 */
+#define EM_MN10200	90	/* Matsushita MN10200 */
+#define EM_PJ		91	/* picoJava */
+#define EM_OPENRISC	92	/* OpenRISC 32-bit embedded processor */
+#define EM_ARC_COMPACT	93	/* ARC International ARCompact */
+#define EM_XTENSA	94	/* Tensilica Xtensa Architecture */
+#define EM_VIDEOCORE	95	/* Alphamosaic VideoCore */
+#define EM_TMM_GPP	96	/* Thompson Multimedia General Purpose Proc */
+#define EM_NS32K	97	/* National Semi. 32000 */
+#define EM_TPC		98	/* Tenor Network TPC */
+#define EM_SNP1K	99	/* Trebia SNP 1000 */
+#define EM_ST200	100	/* STMicroelectronics ST200 */
+#define EM_IP2K		101	/* Ubicom IP2xxx */
+#define EM_MAX		102	/* MAX processor */
+#define EM_CR		103	/* National Semi. CompactRISC */
+#define EM_F2MC16	104	/* Fujitsu F2MC16 */
+#define EM_MSP430	105	/* Texas Instruments msp430 */
+#define EM_BLACKFIN	106	/* Analog Devices Blackfin DSP */
+#define EM_SE_C33	107	/* Seiko Epson S1C33 family */
+#define EM_SEP		108	/* Sharp embedded microprocessor */
+#define EM_ARCA		109	/* Arca RISC */
+#define EM_UNICORE	110	/* PKU-Unity & MPRC Peking Uni. mc series */
+#define EM_EXCESS	111	/* eXcess configurable cpu */
+#define EM_DXP		112	/* Icera Semi. Deep Execution Processor */
+#define EM_ALTERA_NIOS2 113	/* Altera Nios II */
+#define EM_CRX		114	/* National Semi. CompactRISC CRX */
+#define EM_XGATE	115	/* Motorola XGATE */
+#define EM_C166		116	/* Infineon C16x/XC16x */
+#define EM_M16C		117	/* Renesas M16C */
+#define EM_DSPIC30F	118	/* Microchip Technology dsPIC30F */
+#define EM_CE		119	/* Freescale Communication Engine RISC */
+#define EM_M32C		120	/* Renesas M32C */
+				/* reserved 121-130 */
+#define EM_TSK3000	131	/* Altium TSK3000 */
+#define EM_RS08		132	/* Freescale RS08 */
+#define EM_SHARC	133	/* Analog Devices SHARC family */
+#define EM_ECOG2	134	/* Cyan Technology eCOG2 */
+#define EM_SCORE7	135	/* Sunplus S+core7 RISC */
+#define EM_DSP24	136	/* New Japan Radio (NJR) 24-bit DSP */
+#define EM_VIDEOCORE3	137	/* Broadcom VideoCore III */
+#define EM_LATTICEMICO32 138	/* RISC for Lattice FPGA */
+#define EM_SE_C17	139	/* Seiko Epson C17 */
+#define EM_TI_C6000	140	/* Texas Instruments TMS320C6000 DSP */
+#define EM_TI_C2000	141	/* Texas Instruments TMS320C2000 DSP */
+#define EM_TI_C5500	142	/* Texas Instruments TMS320C55x DSP */
+#define EM_TI_ARP32	143	/* Texas Instruments App. Specific RISC */
+#define EM_TI_PRU	144	/* Texas Instruments Prog. Realtime Unit */
+				/* reserved 145-159 */
+#define EM_MMDSP_PLUS	160	/* STMicroelectronics 64bit VLIW DSP */
+#define EM_CYPRESS_M8C	161	/* Cypress M8C */
+#define EM_R32C		162	/* Renesas R32C */
+#define EM_TRIMEDIA	163	/* NXP Semi. TriMedia */
+#define EM_QDSP6	164	/* QUALCOMM DSP6 */
+#define EM_8051		165	/* Intel 8051 and variants */
+#define EM_STXP7X	166	/* STMicroelectronics STxP7x */
+#define EM_NDS32	167	/* Andes Tech. compact code emb. RISC */
+#define EM_ECOG1X	168	/* Cyan Technology eCOG1X */
+#define EM_MAXQ30	169	/* Dallas Semi. MAXQ30 mc */
+#define EM_XIMO16	170	/* New Japan Radio (NJR) 16-bit DSP */
+#define EM_MANIK	171	/* M2000 Reconfigurable RISC */
+#define EM_CRAYNV2	172	/* Cray NV2 vector architecture */
+#define EM_RX		173	/* Renesas RX */
+#define EM_METAG	174	/* Imagination Tech. META */
+#define EM_MCST_ELBRUS	175	/* MCST Elbrus */
+#define EM_ECOG16	176	/* Cyan Technology eCOG16 */
+#define EM_CR16		177	/* National Semi. CompactRISC CR16 */
+#define EM_ETPU		178	/* Freescale Extended Time Processing Unit */
+#define EM_SLE9X	179	/* Infineon Tech. SLE9X */
+#define EM_L10M		180	/* Intel L10M */
+#define EM_K10M		181	/* Intel K10M */
+				/* reserved 182 */
+#define EM_AARCH64	183	/* ARM AARCH64 */
+				/* reserved 184 */
+#define EM_AVR32	185	/* Amtel 32-bit microprocessor */
+#define EM_STM8		186	/* STMicroelectronics STM8 */
+#define EM_TILE64	187	/* Tilera TILE64 */
+#define EM_TILEPRO	188	/* Tilera TILEPro */
+#define EM_MICROBLAZE	189	/* Xilinx MicroBlaze */
+#define EM_CUDA		190	/* NVIDIA CUDA */
+#define EM_TILEGX	191	/* Tilera TILE-Gx */
+#define EM_CLOUDSHIELD	192	/* CloudShield */
+#define EM_COREA_1ST	193	/* KIPO-KAIST Core-A 1st gen. */
+#define EM_COREA_2ND	194	/* KIPO-KAIST Core-A 2nd gen. */
+#define EM_ARCV2	195	/* Synopsys ARCv2 ISA.  */
+#define EM_OPEN8	196	/* Open8 RISC */
+#define EM_RL78		197	/* Renesas RL78 */
+#define EM_VIDEOCORE5	198	/* Broadcom VideoCore V */
+#define EM_78KOR	199	/* Renesas 78KOR */
+#define EM_56800EX	200	/* Freescale 56800EX DSC */
+#define EM_BA1		201	/* Beyond BA1 */
+#define EM_BA2		202	/* Beyond BA2 */
+#define EM_XCORE	203	/* XMOS xCORE */
+#define EM_MCHP_PIC	204	/* Microchip 8-bit PIC(r) */
+#define EM_INTELGT	205	/* Intel Graphics Technology */
+				/* reserved 206-209 */
+#define EM_KM32		210	/* KM211 KM32 */
+#define EM_KMX32	211	/* KM211 KMX32 */
+#define EM_EMX16	212	/* KM211 KMX16 */
+#define EM_EMX8		213	/* KM211 KMX8 */
+#define EM_KVARC	214	/* KM211 KVARC */
+#define EM_CDP		215	/* Paneve CDP */
+#define EM_COGE		216	/* Cognitive Smart Memory Processor */
+#define EM_COOL		217	/* Bluechip CoolEngine */
+#define EM_NORC		218	/* Nanoradio Optimized RISC */
+#define EM_CSR_KALIMBA	219	/* CSR Kalimba */
+#define EM_Z80		220	/* Zilog Z80 */
+#define EM_VISIUM	221	/* Controls and Data Services VISIUMcore */
+#define EM_FT32		222	/* FTDI Chip FT32 */
+#define EM_MOXIE	223	/* Moxie processor */
+#define EM_AMDGPU	224	/* AMD GPU */
+				/* reserved 225-242 */
+#define EM_RISCV	243	/* RISC-V */
+
+#define EM_BPF		247	/* Linux BPF -- in-kernel virtual machine */
+#define EM_CSKY		252     /* C-SKY */
+#define EM_LOONGARCH	258	/* LoongArch */
+
+#define EM_NUM		259
+
+/* Old spellings/synonyms.  */
+
+#define EM_ARC_A5	EM_ARC_COMPACT
+
+/* If it is necessary to assign new unofficial EM_* values, please
+   pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the
+   chances of collision with official or non-GNU unofficial values.  */
+
+#define EM_ALPHA	0x9026
+
+/* Legal values for e_version (version).  */
+
+#define EV_NONE		0		/* Invalid ELF version */
+#define EV_CURRENT	1		/* Current version */
+#define EV_NUM		2
+
+/* Section header.  */
+
+typedef struct
+{
+  Elf32_Word	sh_name;		/* Section name (string tbl index) */
+  Elf32_Word	sh_type;		/* Section type */
+  Elf32_Word	sh_flags;		/* Section flags */
+  Elf32_Addr	sh_addr;		/* Section virtual addr at execution */
+  Elf32_Off	sh_offset;		/* Section file offset */
+  Elf32_Word	sh_size;		/* Section size in bytes */
+  Elf32_Word	sh_link;		/* Link to another section */
+  Elf32_Word	sh_info;		/* Additional section information */
+  Elf32_Word	sh_addralign;		/* Section alignment */
+  Elf32_Word	sh_entsize;		/* Entry size if section holds table */
+} Elf32_Shdr;
+
+typedef struct
+{
+  Elf64_Word	sh_name;		/* Section name (string tbl index) */
+  Elf64_Word	sh_type;		/* Section type */
+  Elf64_Xword	sh_flags;		/* Section flags */
+  Elf64_Addr	sh_addr;		/* Section virtual addr at execution */
+  Elf64_Off	sh_offset;		/* Section file offset */
+  Elf64_Xword	sh_size;		/* Section size in bytes */
+  Elf64_Word	sh_link;		/* Link to another section */
+  Elf64_Word	sh_info;		/* Additional section information */
+  Elf64_Xword	sh_addralign;		/* Section alignment */
+  Elf64_Xword	sh_entsize;		/* Entry size if section holds table */
+} Elf64_Shdr;
+
+/* Special section indices.  */
+
+#define SHN_UNDEF	0		/* Undefined section */
+#define SHN_LORESERVE	0xff00		/* Start of reserved indices */
+#define SHN_LOPROC	0xff00		/* Start of processor-specific */
+#define SHN_BEFORE	0xff00		/* Order section before all others
+					   (Solaris).  */
+#define SHN_AFTER	0xff01		/* Order section after all others
+					   (Solaris).  */
+#define SHN_HIPROC	0xff1f		/* End of processor-specific */
+#define SHN_LOOS	0xff20		/* Start of OS-specific */
+#define SHN_HIOS	0xff3f		/* End of OS-specific */
+#define SHN_ABS		0xfff1		/* Associated symbol is absolute */
+#define SHN_COMMON	0xfff2		/* Associated symbol is common */
+#define SHN_XINDEX	0xffff		/* Index is in extra table.  */
+#define SHN_HIRESERVE	0xffff		/* End of reserved indices */
+
+/* Legal values for sh_type (section type).  */
+
+#define SHT_NULL	  0		/* Section header table entry unused */
+#define SHT_PROGBITS	  1		/* Program data */
+#define SHT_SYMTAB	  2		/* Symbol table */
+#define SHT_STRTAB	  3		/* String table */
+#define SHT_RELA	  4		/* Relocation entries with addends */
+#define SHT_HASH	  5		/* Symbol hash table */
+#define SHT_DYNAMIC	  6		/* Dynamic linking information */
+#define SHT_NOTE	  7		/* Notes */
+#define SHT_NOBITS	  8		/* Program space with no data (bss) */
+#define SHT_REL		  9		/* Relocation entries, no addends */
+#define SHT_SHLIB	  10		/* Reserved */
+#define SHT_DYNSYM	  11		/* Dynamic linker symbol table */
+#define SHT_INIT_ARRAY	  14		/* Array of constructors */
+#define SHT_FINI_ARRAY	  15		/* Array of destructors */
+#define SHT_PREINIT_ARRAY 16		/* Array of pre-constructors */
+#define SHT_GROUP	  17		/* Section group */
+#define SHT_SYMTAB_SHNDX  18		/* Extended section indices */
+#define SHT_RELR	  19            /* RELR relative relocations */
+#define	SHT_NUM		  20		/* Number of defined types.  */
+#define SHT_LOOS	  0x60000000	/* Start OS-specific.  */
+#define SHT_GNU_ATTRIBUTES 0x6ffffff5	/* Object attributes.  */
+#define SHT_GNU_HASH	  0x6ffffff6	/* GNU-style hash table.  */
+#define SHT_GNU_LIBLIST	  0x6ffffff7	/* Prelink library list */
+#define SHT_CHECKSUM	  0x6ffffff8	/* Checksum for DSO content.  */
+#define SHT_LOSUNW	  0x6ffffffa	/* Sun-specific low bound.  */
+#define SHT_SUNW_move	  0x6ffffffa
+#define SHT_SUNW_COMDAT   0x6ffffffb
+#define SHT_SUNW_syminfo  0x6ffffffc
+#define SHT_GNU_verdef	  0x6ffffffd	/* Version definition section.  */
+#define SHT_GNU_verneed	  0x6ffffffe	/* Version needs section.  */
+#define SHT_GNU_versym	  0x6fffffff	/* Version symbol table.  */
+#define SHT_HISUNW	  0x6fffffff	/* Sun-specific high bound.  */
+#define SHT_HIOS	  0x6fffffff	/* End OS-specific type */
+#define SHT_LOPROC	  0x70000000	/* Start of processor-specific */
+#define SHT_HIPROC	  0x7fffffff	/* End of processor-specific */
+#define SHT_LOUSER	  0x80000000	/* Start of application-specific */
+#define SHT_HIUSER	  0x8fffffff	/* End of application-specific */
+
+/* Legal values for sh_flags (section flags).  */
+
+#define SHF_WRITE	     (1 << 0)	/* Writable */
+#define SHF_ALLOC	     (1 << 1)	/* Occupies memory during execution */
+#define SHF_EXECINSTR	     (1 << 2)	/* Executable */
+#define SHF_MERGE	     (1 << 4)	/* Might be merged */
+#define SHF_STRINGS	     (1 << 5)	/* Contains nul-terminated strings */
+#define SHF_INFO_LINK	     (1 << 6)	/* `sh_info' contains SHT index */
+#define SHF_LINK_ORDER	     (1 << 7)	/* Preserve order after combining */
+#define SHF_OS_NONCONFORMING (1 << 8)	/* Non-standard OS specific handling
+					   required */
+#define SHF_GROUP	     (1 << 9)	/* Section is member of a group.  */
+#define SHF_TLS		     (1 << 10)	/* Section hold thread-local data.  */
+#define SHF_COMPRESSED	     (1 << 11)	/* Section with compressed data. */
+#define SHF_MASKOS	     0x0ff00000	/* OS-specific.  */
+#define SHF_MASKPROC	     0xf0000000	/* Processor-specific */
+#define SHF_GNU_RETAIN	     (1 << 21)  /* Not to be GCed by linker.  */
+#define SHF_ORDERED	     (1 << 30)	/* Special ordering requirement
+					   (Solaris).  */
+#define SHF_EXCLUDE	     (1U << 31)	/* Section is excluded unless
+					   referenced or allocated (Solaris).*/
+
+/* Section compression header.  Used when SHF_COMPRESSED is set.  */
+
+typedef struct
+{
+  Elf32_Word	ch_type;	/* Compression format.  */
+  Elf32_Word	ch_size;	/* Uncompressed data size.  */
+  Elf32_Word	ch_addralign;	/* Uncompressed data alignment.  */
+} Elf32_Chdr;
+
+typedef struct
+{
+  Elf64_Word	ch_type;	/* Compression format.  */
+  Elf64_Word	ch_reserved;
+  Elf64_Xword	ch_size;	/* Uncompressed data size.  */
+  Elf64_Xword	ch_addralign;	/* Uncompressed data alignment.  */
+} Elf64_Chdr;
+
+/* Legal values for ch_type (compression algorithm).  */
+#define ELFCOMPRESS_ZLIB	1	   /* ZLIB/DEFLATE algorithm.  */
+#define ELFCOMPRESS_ZSTD	2	   /* Zstandard algorithm.  */
+#define ELFCOMPRESS_LOOS	0x60000000 /* Start of OS-specific.  */
+#define ELFCOMPRESS_HIOS	0x6fffffff /* End of OS-specific.  */
+#define ELFCOMPRESS_LOPROC	0x70000000 /* Start of processor-specific.  */
+#define ELFCOMPRESS_HIPROC	0x7fffffff /* End of processor-specific.  */
+
+/* Section group handling.  */
+#define GRP_COMDAT	0x1		/* Mark group as COMDAT.  */
+
+/* Symbol table entry.  */
+
+typedef struct
+{
+  Elf32_Word	st_name;		/* Symbol name (string tbl index) */
+  Elf32_Addr	st_value;		/* Symbol value */
+  Elf32_Word	st_size;		/* Symbol size */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char	st_other;		/* Symbol visibility */
+  Elf32_Section	st_shndx;		/* Section index */
+} Elf32_Sym;
+
+typedef struct
+{
+  Elf64_Word	st_name;		/* Symbol name (string tbl index) */
+  unsigned char	st_info;		/* Symbol type and binding */
+  unsigned char st_other;		/* Symbol visibility */
+  Elf64_Section	st_shndx;		/* Section index */
+  Elf64_Addr	st_value;		/* Symbol value */
+  Elf64_Xword	st_size;		/* Symbol size */
+} Elf64_Sym;
+
+/* The syminfo section if available contains additional information about
+   every dynamic symbol.  */
+
+typedef struct
+{
+  Elf32_Half si_boundto;		/* Direct bindings, symbol bound to */
+  Elf32_Half si_flags;			/* Per symbol flags */
+} Elf32_Syminfo;
+
+typedef struct
+{
+  Elf64_Half si_boundto;		/* Direct bindings, symbol bound to */
+  Elf64_Half si_flags;			/* Per symbol flags */
+} Elf64_Syminfo;
+
+/* Possible values for si_boundto.  */
+#define SYMINFO_BT_SELF		0xffff	/* Symbol bound to self */
+#define SYMINFO_BT_PARENT	0xfffe	/* Symbol bound to parent */
+#define SYMINFO_BT_LOWRESERVE	0xff00	/* Beginning of reserved entries */
+
+/* Possible bitmasks for si_flags.  */
+#define SYMINFO_FLG_DIRECT	0x0001	/* Direct bound symbol */
+#define SYMINFO_FLG_PASSTHRU	0x0002	/* Pass-through symbol for translator */
+#define SYMINFO_FLG_COPY	0x0004	/* Symbol is a copy-reloc */
+#define SYMINFO_FLG_LAZYLOAD	0x0008	/* Symbol bound to object to be lazy
+					   loaded */
+/* Syminfo version values.  */
+#define SYMINFO_NONE		0
+#define SYMINFO_CURRENT		1
+#define SYMINFO_NUM		2
+
+
+/* How to extract and insert information held in the st_info field.  */
+
+#define ELF32_ST_BIND(val)		(((unsigned char) (val)) >> 4)
+#define ELF32_ST_TYPE(val)		((val) & 0xf)
+#define ELF32_ST_INFO(bind, type)	(((bind) << 4) + ((type) & 0xf))
+
+/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field.  */
+#define ELF64_ST_BIND(val)		ELF32_ST_BIND (val)
+#define ELF64_ST_TYPE(val)		ELF32_ST_TYPE (val)
+#define ELF64_ST_INFO(bind, type)	ELF32_ST_INFO ((bind), (type))
+
+/* Legal values for ST_BIND subfield of st_info (symbol binding).  */
+
+#define STB_LOCAL	0		/* Local symbol */
+#define STB_GLOBAL	1		/* Global symbol */
+#define STB_WEAK	2		/* Weak symbol */
+#define	STB_NUM		3		/* Number of defined types.  */
+#define STB_LOOS	10		/* Start of OS-specific */
+#define STB_GNU_UNIQUE	10		/* Unique symbol.  */
+#define STB_HIOS	12		/* End of OS-specific */
+#define STB_LOPROC	13		/* Start of processor-specific */
+#define STB_HIPROC	15		/* End of processor-specific */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_NOTYPE	0		/* Symbol type is unspecified */
+#define STT_OBJECT	1		/* Symbol is a data object */
+#define STT_FUNC	2		/* Symbol is a code object */
+#define STT_SECTION	3		/* Symbol associated with a section */
+#define STT_FILE	4		/* Symbol's name is file name */
+#define STT_COMMON	5		/* Symbol is a common data object */
+#define STT_TLS		6		/* Symbol is thread-local data object*/
+#define	STT_NUM		7		/* Number of defined types.  */
+#define STT_LOOS	10		/* Start of OS-specific */
+#define STT_GNU_IFUNC	10		/* Symbol is indirect code object */
+#define STT_HIOS	12		/* End of OS-specific */
+#define STT_LOPROC	13		/* Start of processor-specific */
+#define STT_HIPROC	15		/* End of processor-specific */
+
+
+/* Symbol table indices are found in the hash buckets and chain table
+   of a symbol hash table section.  This special index value indicates
+   the end of a chain, meaning no further symbols are found in that bucket.  */
+
+#define STN_UNDEF	0		/* End of a chain.  */
+
+
+/* How to extract and insert information held in the st_other field.  */
+
+#define ELF32_ST_VISIBILITY(o)	((o) & 0x03)
+
+/* For ELF64 the definitions are the same.  */
+#define ELF64_ST_VISIBILITY(o)	ELF32_ST_VISIBILITY (o)
+
+/* Symbol visibility specification encoded in the st_other field.  */
+#define STV_DEFAULT	0		/* Default symbol visibility rules */
+#define STV_INTERNAL	1		/* Processor specific hidden class */
+#define STV_HIDDEN	2		/* Sym unavailable in other modules */
+#define STV_PROTECTED	3		/* Not preemptible, not exported */
+
+
+/* Relocation table entry without addend (in section of type SHT_REL).  */
+
+typedef struct
+{
+  Elf32_Addr	r_offset;		/* Address */
+  Elf32_Word	r_info;			/* Relocation type and symbol index */
+} Elf32_Rel;
+
+/* I have seen two different definitions of the Elf64_Rel and
+   Elf64_Rela structures, so we'll leave them out until Novell (or
+   whoever) gets their act together.  */
+/* The following, at least, is used on Sparc v9, MIPS, and Alpha.  */
+
+typedef struct
+{
+  Elf64_Addr	r_offset;		/* Address */
+  Elf64_Xword	r_info;			/* Relocation type and symbol index */
+} Elf64_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA).  */
+
+typedef struct
+{
+  Elf32_Addr	r_offset;		/* Address */
+  Elf32_Word	r_info;			/* Relocation type and symbol index */
+  Elf32_Sword	r_addend;		/* Addend */
+} Elf32_Rela;
+
+typedef struct
+{
+  Elf64_Addr	r_offset;		/* Address */
+  Elf64_Xword	r_info;			/* Relocation type and symbol index */
+  Elf64_Sxword	r_addend;		/* Addend */
+} Elf64_Rela;
+
+/* RELR relocation table entry */
+
+typedef Elf32_Word	Elf32_Relr;
+typedef Elf64_Xword	Elf64_Relr;
+
+/* How to extract and insert information held in the r_info field.  */
+
+#define ELF32_R_SYM(val)		((val) >> 8)
+#define ELF32_R_TYPE(val)		((val) & 0xff)
+#define ELF32_R_INFO(sym, type)		(((sym) << 8) + ((type) & 0xff))
+
+#define ELF64_R_SYM(i)			((i) >> 32)
+#define ELF64_R_TYPE(i)			((i) & 0xffffffff)
+#define ELF64_R_INFO(sym,type)		((((Elf64_Xword) (sym)) << 32) + (type))
+
+/* Program segment header.  */
+
+typedef struct
+{
+  Elf32_Word	p_type;			/* Segment type */
+  Elf32_Off	p_offset;		/* Segment file offset */
+  Elf32_Addr	p_vaddr;		/* Segment virtual address */
+  Elf32_Addr	p_paddr;		/* Segment physical address */
+  Elf32_Word	p_filesz;		/* Segment size in file */
+  Elf32_Word	p_memsz;		/* Segment size in memory */
+  Elf32_Word	p_flags;		/* Segment flags */
+  Elf32_Word	p_align;		/* Segment alignment */
+} Elf32_Phdr;
+
+typedef struct
+{
+  Elf64_Word	p_type;			/* Segment type */
+  Elf64_Word	p_flags;		/* Segment flags */
+  Elf64_Off	p_offset;		/* Segment file offset */
+  Elf64_Addr	p_vaddr;		/* Segment virtual address */
+  Elf64_Addr	p_paddr;		/* Segment physical address */
+  Elf64_Xword	p_filesz;		/* Segment size in file */
+  Elf64_Xword	p_memsz;		/* Segment size in memory */
+  Elf64_Xword	p_align;		/* Segment alignment */
+} Elf64_Phdr;
+
+/* Special value for e_phnum.  This indicates that the real number of
+   program headers is too large to fit into e_phnum.  Instead the real
+   value is in the field sh_info of section 0.  */
+
+#define PN_XNUM		0xffff
+
+/* Legal values for p_type (segment type).  */
+
+#define	PT_NULL		0		/* Program header table entry unused */
+#define PT_LOAD		1		/* Loadable program segment */
+#define PT_DYNAMIC	2		/* Dynamic linking information */
+#define PT_INTERP	3		/* Program interpreter */
+#define PT_NOTE		4		/* Auxiliary information */
+#define PT_SHLIB	5		/* Reserved */
+#define PT_PHDR		6		/* Entry for header table itself */
+#define PT_TLS		7		/* Thread-local storage segment */
+#define	PT_NUM		8		/* Number of defined types */
+#define PT_LOOS		0x60000000	/* Start of OS-specific */
+#define PT_GNU_EH_FRAME	0x6474e550	/* GCC .eh_frame_hdr segment */
+#define PT_GNU_STACK	0x6474e551	/* Indicates stack executability */
+#define PT_GNU_RELRO	0x6474e552	/* Read-only after relocation */
+#define PT_GNU_PROPERTY	0x6474e553	/* GNU property */
+#define PT_GNU_SFRAME	0x6474e554	/* SFrame segment.  */
+#define PT_LOSUNW	0x6ffffffa
+#define PT_SUNWBSS	0x6ffffffa	/* Sun Specific segment */
+#define PT_SUNWSTACK	0x6ffffffb	/* Stack segment */
+#define PT_HISUNW	0x6fffffff
+#define PT_HIOS		0x6fffffff	/* End of OS-specific */
+#define PT_LOPROC	0x70000000	/* Start of processor-specific */
+#define PT_HIPROC	0x7fffffff	/* End of processor-specific */
+
+/* Legal values for p_flags (segment flags).  */
+
+#define PF_X		(1 << 0)	/* Segment is executable */
+#define PF_W		(1 << 1)	/* Segment is writable */
+#define PF_R		(1 << 2)	/* Segment is readable */
+#define PF_MASKOS	0x0ff00000	/* OS-specific */
+#define PF_MASKPROC	0xf0000000	/* Processor-specific */
+
+/* Legal values for note segment descriptor types for core files. */
+
+#define NT_PRSTATUS	1		/* Contains copy of prstatus struct */
+#define NT_PRFPREG	2		/* Contains copy of fpregset
+					   struct.  */
+#define NT_FPREGSET	2		/* Contains copy of fpregset struct */
+#define NT_PRPSINFO	3		/* Contains copy of prpsinfo struct */
+#define NT_PRXREG	4		/* Contains copy of prxregset struct */
+#define NT_TASKSTRUCT	4		/* Contains copy of task structure */
+#define NT_PLATFORM	5		/* String from sysinfo(SI_PLATFORM) */
+#define NT_AUXV		6		/* Contains copy of auxv array */
+#define NT_GWINDOWS	7		/* Contains copy of gwindows struct */
+#define NT_ASRS		8		/* Contains copy of asrset struct */
+#define NT_PSTATUS	10		/* Contains copy of pstatus struct */
+#define NT_PSINFO	13		/* Contains copy of psinfo struct */
+#define NT_PRCRED	14		/* Contains copy of prcred struct */
+#define NT_UTSNAME	15		/* Contains copy of utsname struct */
+#define NT_LWPSTATUS	16		/* Contains copy of lwpstatus struct */
+#define NT_LWPSINFO	17		/* Contains copy of lwpinfo struct */
+#define NT_PRFPXREG	20		/* Contains copy of fprxregset struct */
+#define NT_SIGINFO	0x53494749	/* Contains copy of siginfo_t,
+					   size might increase */
+#define NT_FILE		0x46494c45	/* Contains information about mapped
+					   files */
+#define NT_PRXFPREG	0x46e62b7f	/* Contains copy of user_fxsr_struct */
+#define NT_PPC_VMX	0x100		/* PowerPC Altivec/VMX registers */
+#define NT_PPC_SPE	0x101		/* PowerPC SPE/EVR registers */
+#define NT_PPC_VSX	0x102		/* PowerPC VSX registers */
+#define NT_PPC_TAR	0x103		/* Target Address Register */
+#define NT_PPC_PPR	0x104		/* Program Priority Register */
+#define NT_PPC_DSCR	0x105		/* Data Stream Control Register */
+#define NT_PPC_EBB	0x106		/* Event Based Branch Registers */
+#define NT_PPC_PMU	0x107		/* Performance Monitor Registers */
+#define NT_PPC_TM_CGPR	0x108		/* TM checkpointed GPR Registers */
+#define NT_PPC_TM_CFPR	0x109		/* TM checkpointed FPR Registers */
+#define NT_PPC_TM_CVMX	0x10a		/* TM checkpointed VMX Registers */
+#define NT_PPC_TM_CVSX	0x10b		/* TM checkpointed VSX Registers */
+#define NT_PPC_TM_SPR	0x10c		/* TM Special Purpose Registers */
+#define NT_PPC_TM_CTAR	0x10d		/* TM checkpointed Target Address
+					   Register */
+#define NT_PPC_TM_CPPR	0x10e		/* TM checkpointed Program Priority
+					   Register */
+#define NT_PPC_TM_CDSCR	0x10f		/* TM checkpointed Data Stream Control
+					   Register */
+#define NT_PPC_PKEY	0x110		/* Memory Protection Keys
+					   registers.  */
+#define NT_PPC_DEXCR	0x111		/* PowerPC DEXCR registers.  */
+#define NT_PPC_HASHKEYR	0x112		/* PowerPC HASHKEYR register.  */
+#define NT_386_TLS	0x200		/* i386 TLS slots (struct user_desc) */
+#define NT_386_IOPERM	0x201		/* x86 io permission bitmap (1=deny) */
+#define NT_X86_XSTATE	0x202		/* x86 extended state using xsave */
+#define NT_X86_SHSTK	0x204		/* x86 SHSTK state */
+#define NT_S390_HIGH_GPRS	0x300	/* s390 upper register halves */
+#define NT_S390_TIMER	0x301		/* s390 timer register */
+#define NT_S390_TODCMP	0x302		/* s390 TOD clock comparator register */
+#define NT_S390_TODPREG	0x303		/* s390 TOD programmable register */
+#define NT_S390_CTRS	0x304		/* s390 control registers */
+#define NT_S390_PREFIX	0x305		/* s390 prefix register */
+#define NT_S390_LAST_BREAK	0x306	/* s390 breaking event address */
+#define NT_S390_SYSTEM_CALL	0x307	/* s390 system call restart data */
+#define NT_S390_TDB	0x308		/* s390 transaction diagnostic block */
+#define NT_S390_VXRS_LOW	0x309	/* s390 vector registers 0-15
+					   upper half.  */
+#define NT_S390_VXRS_HIGH	0x30a	/* s390 vector registers 16-31.  */
+#define NT_S390_GS_CB	0x30b		/* s390 guarded storage registers.  */
+#define NT_S390_GS_BC	0x30c		/* s390 guarded storage
+					   broadcast control block.  */
+#define NT_S390_RI_CB	0x30d		/* s390 runtime instrumentation.  */
+#define NT_S390_PV_CPU_DATA	0x30e	/* s390 protvirt cpu dump data.  */
+#define NT_ARM_VFP	0x400		/* ARM VFP/NEON registers */
+#define NT_ARM_TLS	0x401		/* ARM TLS register */
+#define NT_ARM_HW_BREAK	0x402		/* ARM hardware breakpoint registers */
+#define NT_ARM_HW_WATCH	0x403		/* ARM hardware watchpoint registers */
+#define NT_ARM_SYSTEM_CALL	0x404	/* ARM system call number */
+#define NT_ARM_SVE	0x405		/* ARM Scalable Vector Extension
+					   registers */
+#define NT_ARM_PAC_MASK	0x406		/* ARM pointer authentication
+					   code masks.  */
+#define NT_ARM_PACA_KEYS	0x407	/* ARM pointer authentication
+					   address keys.  */
+#define NT_ARM_PACG_KEYS	0x408	/* ARM pointer authentication
+					   generic key.  */
+#define NT_ARM_TAGGED_ADDR_CTRL	0x409	/* AArch64 tagged address
+					   control.  */
+#define NT_ARM_PAC_ENABLED_KEYS	0x40a	/* AArch64 pointer authentication
+					   enabled keys.  */
+#define NT_VMCOREDD	0x700		/* Vmcore Device Dump Note.  */
+#define NT_MIPS_DSP	0x800		/* MIPS DSP ASE registers.  */
+#define NT_MIPS_FP_MODE	0x801		/* MIPS floating-point mode.  */
+#define NT_MIPS_MSA	0x802		/* MIPS SIMD registers.  */
+#define NT_RISCV_CSR	0x900		/* RISC-V Control and Status Registers */
+#define NT_RISCV_VECTOR	0x901		/* RISC-V vector registers */
+#define NT_LOONGARCH_CPUCFG	0xa00	/* LoongArch CPU config registers.  */
+#define NT_LOONGARCH_CSR	0xa01	/* LoongArch control and
+					   status registers.  */
+#define NT_LOONGARCH_LSX	0xa02	/* LoongArch Loongson SIMD
+					   Extension registers.  */
+#define NT_LOONGARCH_LASX	0xa03	/* LoongArch Loongson Advanced
+					   SIMD Extension registers.  */
+#define NT_LOONGARCH_LBT	0xa04	/* LoongArch Loongson Binary
+					   Translation registers.  */
+#define NT_LOONGARCH_HW_BREAK	0xa05   /* LoongArch hardware breakpoint registers */
+#define NT_LOONGARCH_HW_WATCH	0xa06   /* LoongArch hardware watchpoint registers */
+
+/* Legal values for the note segment descriptor types for object files.  */
+
+#define NT_VERSION	1		/* Contains a version string.  */
+
+
+/* Dynamic section entry.  */
+
+typedef struct
+{
+  Elf32_Sword	d_tag;			/* Dynamic entry type */
+  union
+    {
+      Elf32_Word d_val;			/* Integer value */
+      Elf32_Addr d_ptr;			/* Address value */
+    } d_un;
+} Elf32_Dyn;
+
+typedef struct
+{
+  Elf64_Sxword	d_tag;			/* Dynamic entry type */
+  union
+    {
+      Elf64_Xword d_val;		/* Integer value */
+      Elf64_Addr d_ptr;			/* Address value */
+    } d_un;
+} Elf64_Dyn;
+
+/* Legal values for d_tag (dynamic entry type).  */
+
+#define DT_NULL		0		/* Marks end of dynamic section */
+#define DT_NEEDED	1		/* Name of needed library */
+#define DT_PLTRELSZ	2		/* Size in bytes of PLT relocs */
+#define DT_PLTGOT	3		/* Processor defined value */
+#define DT_HASH		4		/* Address of symbol hash table */
+#define DT_STRTAB	5		/* Address of string table */
+#define DT_SYMTAB	6		/* Address of symbol table */
+#define DT_RELA		7		/* Address of Rela relocs */
+#define DT_RELASZ	8		/* Total size of Rela relocs */
+#define DT_RELAENT	9		/* Size of one Rela reloc */
+#define DT_STRSZ	10		/* Size of string table */
+#define DT_SYMENT	11		/* Size of one symbol table entry */
+#define DT_INIT		12		/* Address of init function */
+#define DT_FINI		13		/* Address of termination function */
+#define DT_SONAME	14		/* Name of shared object */
+#define DT_RPATH	15		/* Library search path (deprecated) */
+#define DT_SYMBOLIC	16		/* Start symbol search here */
+#define DT_REL		17		/* Address of Rel relocs */
+#define DT_RELSZ	18		/* Total size of Rel relocs */
+#define DT_RELENT	19		/* Size of one Rel reloc */
+#define DT_PLTREL	20		/* Type of reloc in PLT */
+#define DT_DEBUG	21		/* For debugging; unspecified */
+#define DT_TEXTREL	22		/* Reloc might modify .text */
+#define DT_JMPREL	23		/* Address of PLT relocs */
+#define	DT_BIND_NOW	24		/* Process relocations of object */
+#define	DT_INIT_ARRAY	25		/* Array with addresses of init fct */
+#define	DT_FINI_ARRAY	26		/* Array with addresses of fini fct */
+#define	DT_INIT_ARRAYSZ	27		/* Size in bytes of DT_INIT_ARRAY */
+#define	DT_FINI_ARRAYSZ	28		/* Size in bytes of DT_FINI_ARRAY */
+#define DT_RUNPATH	29		/* Library search path */
+#define DT_FLAGS	30		/* Flags for the object being loaded */
+#define DT_ENCODING	32		/* Start of encoded range */
+#define DT_PREINIT_ARRAY 32		/* Array with addresses of preinit fct*/
+#define DT_PREINIT_ARRAYSZ 33		/* size in bytes of DT_PREINIT_ARRAY */
+#define DT_SYMTAB_SHNDX	34		/* Address of SYMTAB_SHNDX section */
+#define DT_RELRSZ	35		/* Total size of RELR relative relocations */
+#define DT_RELR		36		/* Address of RELR relative relocations */
+#define DT_RELRENT	37		/* Size of one RELR relative relocaction */
+#define	DT_NUM		38		/* Number used */
+#define DT_LOOS		0x6000000d	/* Start of OS-specific */
+#define DT_HIOS		0x6ffff000	/* End of OS-specific */
+#define DT_LOPROC	0x70000000	/* Start of processor-specific */
+#define DT_HIPROC	0x7fffffff	/* End of processor-specific */
+#define	DT_PROCNUM	DT_MIPS_NUM	/* Most used by any processor */
+
+/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the
+   Dyn.d_un.d_val field of the Elf*_Dyn structure.  This follows Sun's
+   approach.  */
+#define DT_VALRNGLO	0x6ffffd00
+#define DT_GNU_PRELINKED 0x6ffffdf5	/* Prelinking timestamp */
+#define DT_GNU_CONFLICTSZ 0x6ffffdf6	/* Size of conflict section */
+#define DT_GNU_LIBLISTSZ 0x6ffffdf7	/* Size of library list */
+#define DT_CHECKSUM	0x6ffffdf8
+#define DT_PLTPADSZ	0x6ffffdf9
+#define DT_MOVEENT	0x6ffffdfa
+#define DT_MOVESZ	0x6ffffdfb
+#define DT_FEATURE_1	0x6ffffdfc	/* Feature selection (DTF_*).  */
+#define DT_POSFLAG_1	0x6ffffdfd	/* Flags for DT_* entries, effecting
+					   the following DT_* entry.  */
+#define DT_SYMINSZ	0x6ffffdfe	/* Size of syminfo table (in bytes) */
+#define DT_SYMINENT	0x6ffffdff	/* Entry size of syminfo */
+#define DT_VALRNGHI	0x6ffffdff
+#define DT_VALTAGIDX(tag)	(DT_VALRNGHI - (tag))	/* Reverse order! */
+#define DT_VALNUM 12
+
+/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the
+   Dyn.d_un.d_ptr field of the Elf*_Dyn structure.
+
+   If any adjustment is made to the ELF object after it has been
+   built these entries will need to be adjusted.  */
+#define DT_ADDRRNGLO	0x6ffffe00
+#define DT_GNU_HASH	0x6ffffef5	/* GNU-style hash table.  */
+#define DT_TLSDESC_PLT	0x6ffffef6
+#define DT_TLSDESC_GOT	0x6ffffef7
+#define DT_GNU_CONFLICT	0x6ffffef8	/* Start of conflict section */
+#define DT_GNU_LIBLIST	0x6ffffef9	/* Library list */
+#define DT_CONFIG	0x6ffffefa	/* Configuration information.  */
+#define DT_DEPAUDIT	0x6ffffefb	/* Dependency auditing.  */
+#define DT_AUDIT	0x6ffffefc	/* Object auditing.  */
+#define	DT_PLTPAD	0x6ffffefd	/* PLT padding.  */
+#define	DT_MOVETAB	0x6ffffefe	/* Move table.  */
+#define DT_SYMINFO	0x6ffffeff	/* Syminfo table.  */
+#define DT_ADDRRNGHI	0x6ffffeff
+#define DT_ADDRTAGIDX(tag)	(DT_ADDRRNGHI - (tag))	/* Reverse order! */
+#define DT_ADDRNUM 11
+
+/* The versioning entry types.  The next are defined as part of the
+   GNU extension.  */
+#define DT_VERSYM	0x6ffffff0
+
+#define DT_RELACOUNT	0x6ffffff9
+#define DT_RELCOUNT	0x6ffffffa
+
+/* These were chosen by Sun.  */
+#define DT_FLAGS_1	0x6ffffffb	/* State flags, see DF_1_* below.  */
+#define	DT_VERDEF	0x6ffffffc	/* Address of version definition
+					   table */
+#define	DT_VERDEFNUM	0x6ffffffd	/* Number of version definitions */
+#define	DT_VERNEED	0x6ffffffe	/* Address of table with needed
+					   versions */
+#define	DT_VERNEEDNUM	0x6fffffff	/* Number of needed versions */
+#define DT_VERSIONTAGIDX(tag)	(DT_VERNEEDNUM - (tag))	/* Reverse order! */
+#define DT_VERSIONTAGNUM 16
+
+/* Sun added these machine-independent extensions in the "processor-specific"
+   range.  Be compatible.  */
+#define DT_AUXILIARY    0x7ffffffd      /* Shared object to load before self */
+#define DT_FILTER       0x7fffffff      /* Shared object to get values from */
+#define DT_EXTRATAGIDX(tag)	((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1)
+#define DT_EXTRANUM	3
+
+/* Values of `d_un.d_val' in the DT_FLAGS entry.  */
+#define DF_ORIGIN	0x00000001	/* Object may use DF_ORIGIN */
+#define DF_SYMBOLIC	0x00000002	/* Symbol resolutions starts here */
+#define DF_TEXTREL	0x00000004	/* Object contains text relocations */
+#define DF_BIND_NOW	0x00000008	/* No lazy binding for this object */
+#define DF_STATIC_TLS	0x00000010	/* Module uses the static TLS model */
+
+/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1
+   entry in the dynamic section.  */
+#define DF_1_NOW	0x00000001	/* Set RTLD_NOW for this object.  */
+#define DF_1_GLOBAL	0x00000002	/* Set RTLD_GLOBAL for this object.  */
+#define DF_1_GROUP	0x00000004	/* Set RTLD_GROUP for this object.  */
+#define DF_1_NODELETE	0x00000008	/* Set RTLD_NODELETE for this object.*/
+#define DF_1_LOADFLTR	0x00000010	/* Trigger filtee loading at runtime.*/
+#define DF_1_INITFIRST	0x00000020	/* Set RTLD_INITFIRST for this object*/
+#define DF_1_NOOPEN	0x00000040	/* Set RTLD_NOOPEN for this object.  */
+#define DF_1_ORIGIN	0x00000080	/* $ORIGIN must be handled.  */
+#define DF_1_DIRECT	0x00000100	/* Direct binding enabled.  */
+#define DF_1_TRANS	0x00000200
+#define DF_1_INTERPOSE	0x00000400	/* Object is used to interpose.  */
+#define DF_1_NODEFLIB	0x00000800	/* Ignore default lib search path.  */
+#define DF_1_NODUMP	0x00001000	/* Object can't be dldump'ed.  */
+#define DF_1_CONFALT	0x00002000	/* Configuration alternative created.*/
+#define DF_1_ENDFILTEE	0x00004000	/* Filtee terminates filters search. */
+#define	DF_1_DISPRELDNE	0x00008000	/* Disp reloc applied at build time. */
+#define	DF_1_DISPRELPND	0x00010000	/* Disp reloc applied at run-time.  */
+#define	DF_1_NODIRECT	0x00020000	/* Object has no-direct binding. */
+#define	DF_1_IGNMULDEF	0x00040000
+#define	DF_1_NOKSYMS	0x00080000
+#define	DF_1_NOHDR	0x00100000
+#define	DF_1_EDITED	0x00200000	/* Object is modified after built.  */
+#define	DF_1_NORELOC	0x00400000
+#define	DF_1_SYMINTPOSE	0x00800000	/* Object has individual interposers.  */
+#define	DF_1_GLOBAUDIT	0x01000000	/* Global auditing required.  */
+#define	DF_1_SINGLETON	0x02000000	/* Singleton symbols are used.  */
+#define	DF_1_STUB	0x04000000
+#define	DF_1_PIE	0x08000000
+#define	DF_1_KMOD       0x10000000
+#define	DF_1_WEAKFILTER 0x20000000
+#define	DF_1_NOCOMMON   0x40000000
+
+/* Flags for the feature selection in DT_FEATURE_1.  */
+#define DTF_1_PARINIT	0x00000001
+#define DTF_1_CONFEXP	0x00000002
+
+/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry.  */
+#define DF_P1_LAZYLOAD	0x00000001	/* Lazyload following object.  */
+#define DF_P1_GROUPPERM	0x00000002	/* Symbols from next object are not
+					   generally available.  */
+
+/* Version definition sections.  */
+
+typedef struct
+{
+  Elf32_Half	vd_version;		/* Version revision */
+  Elf32_Half	vd_flags;		/* Version information */
+  Elf32_Half	vd_ndx;			/* Version Index */
+  Elf32_Half	vd_cnt;			/* Number of associated aux entries */
+  Elf32_Word	vd_hash;		/* Version name hash value */
+  Elf32_Word	vd_aux;			/* Offset in bytes to verdaux array */
+  Elf32_Word	vd_next;		/* Offset in bytes to next verdef
+					   entry */
+} Elf32_Verdef;
+
+typedef struct
+{
+  Elf64_Half	vd_version;		/* Version revision */
+  Elf64_Half	vd_flags;		/* Version information */
+  Elf64_Half	vd_ndx;			/* Version Index */
+  Elf64_Half	vd_cnt;			/* Number of associated aux entries */
+  Elf64_Word	vd_hash;		/* Version name hash value */
+  Elf64_Word	vd_aux;			/* Offset in bytes to verdaux array */
+  Elf64_Word	vd_next;		/* Offset in bytes to next verdef
+					   entry */
+} Elf64_Verdef;
+
+
+/* Legal values for vd_version (version revision).  */
+#define VER_DEF_NONE	0		/* No version */
+#define VER_DEF_CURRENT	1		/* Current version */
+#define VER_DEF_NUM	2		/* Given version number */
+
+/* Legal values for vd_flags (version information flags).  */
+#define VER_FLG_BASE	0x1		/* Version definition of file itself */
+#define VER_FLG_WEAK	0x2		/* Weak version identifier.  Also
+					   used by vna_flags below.  */
+
+/* Versym symbol index values.  */
+#define	VER_NDX_LOCAL		0	/* Symbol is local.  */
+#define	VER_NDX_GLOBAL		1	/* Symbol is global.  */
+#define	VER_NDX_LORESERVE	0xff00	/* Beginning of reserved entries.  */
+#define	VER_NDX_ELIMINATE	0xff01	/* Symbol is to be eliminated.  */
+
+/* Auxiliary version information.  */
+
+typedef struct
+{
+  Elf32_Word	vda_name;		/* Version or dependency names */
+  Elf32_Word	vda_next;		/* Offset in bytes to next verdaux
+					   entry */
+} Elf32_Verdaux;
+
+typedef struct
+{
+  Elf64_Word	vda_name;		/* Version or dependency names */
+  Elf64_Word	vda_next;		/* Offset in bytes to next verdaux
+					   entry */
+} Elf64_Verdaux;
+
+
+/* Version dependency section.  */
+
+typedef struct
+{
+  Elf32_Half	vn_version;		/* Version of structure */
+  Elf32_Half	vn_cnt;			/* Number of associated aux entries */
+  Elf32_Word	vn_file;		/* Offset of filename for this
+					   dependency */
+  Elf32_Word	vn_aux;			/* Offset in bytes to vernaux array */
+  Elf32_Word	vn_next;		/* Offset in bytes to next verneed
+					   entry */
+} Elf32_Verneed;
+
+typedef struct
+{
+  Elf64_Half	vn_version;		/* Version of structure */
+  Elf64_Half	vn_cnt;			/* Number of associated aux entries */
+  Elf64_Word	vn_file;		/* Offset of filename for this
+					   dependency */
+  Elf64_Word	vn_aux;			/* Offset in bytes to vernaux array */
+  Elf64_Word	vn_next;		/* Offset in bytes to next verneed
+					   entry */
+} Elf64_Verneed;
+
+
+/* Legal values for vn_version (version revision).  */
+#define VER_NEED_NONE	 0		/* No version */
+#define VER_NEED_CURRENT 1		/* Current version */
+#define VER_NEED_NUM	 2		/* Given version number */
+
+/* Auxiliary needed version information.  */
+
+typedef struct
+{
+  Elf32_Word	vna_hash;		/* Hash value of dependency name */
+  Elf32_Half	vna_flags;		/* Dependency specific information */
+  Elf32_Half	vna_other;		/* Unused */
+  Elf32_Word	vna_name;		/* Dependency name string offset */
+  Elf32_Word	vna_next;		/* Offset in bytes to next vernaux
+					   entry */
+} Elf32_Vernaux;
+
+typedef struct
+{
+  Elf64_Word	vna_hash;		/* Hash value of dependency name */
+  Elf64_Half	vna_flags;		/* Dependency specific information */
+  Elf64_Half	vna_other;		/* Unused */
+  Elf64_Word	vna_name;		/* Dependency name string offset */
+  Elf64_Word	vna_next;		/* Offset in bytes to next vernaux
+					   entry */
+} Elf64_Vernaux;
+
+
+/* Auxiliary vector.  */
+
+/* This vector is normally only used by the program interpreter.  The
+   usual definition in an ABI supplement uses the name auxv_t.  The
+   vector is not usually defined in a standard <elf.h> file, but it
+   can't hurt.  We rename it to avoid conflicts.  The sizes of these
+   types are an arrangement between the exec server and the program
+   interpreter, so we don't fully specify them here.  */
+
+typedef struct
+{
+  uint32_t a_type;		/* Entry type */
+  union
+    {
+      uint32_t a_val;		/* Integer value */
+      /* We use to have pointer elements added here.  We cannot do that,
+	 though, since it does not work when using 32-bit definitions
+	 on 64-bit platforms and vice versa.  */
+    } a_un;
+} Elf32_auxv_t;
+
+typedef struct
+{
+  uint64_t a_type;		/* Entry type */
+  union
+    {
+      uint64_t a_val;		/* Integer value */
+      /* We use to have pointer elements added here.  We cannot do that,
+	 though, since it does not work when using 32-bit definitions
+	 on 64-bit platforms and vice versa.  */
+    } a_un;
+} Elf64_auxv_t;
+
+/* Legal values for a_type (entry type).  */
+
+#define AT_NULL		0		/* End of vector */
+#define AT_IGNORE	1		/* Entry should be ignored */
+#define AT_EXECFD	2		/* File descriptor of program */
+#define AT_PHDR		3		/* Program headers for program */
+#define AT_PHENT	4		/* Size of program header entry */
+#define AT_PHNUM	5		/* Number of program headers */
+#define AT_PAGESZ	6		/* System page size */
+#define AT_BASE		7		/* Base address of interpreter */
+#define AT_FLAGS	8		/* Flags */
+#define AT_ENTRY	9		/* Entry point of program */
+#define AT_NOTELF	10		/* Program is not ELF */
+#define AT_UID		11		/* Real uid */
+#define AT_EUID		12		/* Effective uid */
+#define AT_GID		13		/* Real gid */
+#define AT_EGID		14		/* Effective gid */
+#define AT_CLKTCK	17		/* Frequency of times() */
+
+/* Some more special a_type values describing the hardware.  */
+#define AT_PLATFORM	15		/* String identifying platform.  */
+#define AT_HWCAP	16		/* Machine-dependent hints about
+					   processor capabilities.  */
+
+/* This entry gives some information about the FPU initialization
+   performed by the kernel.  */
+#define AT_FPUCW	18		/* Used FPU control word.  */
+
+/* Cache block sizes.  */
+#define AT_DCACHEBSIZE	19		/* Data cache block size.  */
+#define AT_ICACHEBSIZE	20		/* Instruction cache block size.  */
+#define AT_UCACHEBSIZE	21		/* Unified cache block size.  */
+
+/* A special ignored value for PPC, used by the kernel to control the
+   interpretation of the AUXV. Must be > 16.  */
+#define AT_IGNOREPPC	22		/* Entry should be ignored.  */
+
+#define	AT_SECURE	23		/* Boolean, was exec setuid-like?  */
+
+#define AT_BASE_PLATFORM 24		/* String identifying real platforms.*/
+
+#define AT_RANDOM	25		/* Address of 16 random bytes.  */
+
+#define AT_HWCAP2	26		/* More machine-dependent hints about
+					   processor capabilities.  */
+
+#define AT_RSEQ_FEATURE_SIZE	27	/* rseq supported feature size.  */
+#define AT_RSEQ_ALIGN	28		/* rseq allocation alignment.  */
+
+#define AT_EXECFN	31		/* Filename of executable.  */
+
+/* Pointer to the global system page used for system calls and other
+   nice things.  */
+#define AT_SYSINFO	32
+#define AT_SYSINFO_EHDR	33
+
+/* Shapes of the caches.  Bits 0-3 contains associativity; bits 4-7 contains
+   log2 of line size; mask those to get cache size.  */
+#define AT_L1I_CACHESHAPE	34
+#define AT_L1D_CACHESHAPE	35
+#define AT_L2_CACHESHAPE	36
+#define AT_L3_CACHESHAPE	37
+
+/* Shapes of the caches, with more room to describe them.
+   *GEOMETRY are comprised of cache line size in bytes in the bottom 16 bits
+   and the cache associativity in the next 16 bits.  */
+#define AT_L1I_CACHESIZE	40
+#define AT_L1I_CACHEGEOMETRY	41
+#define AT_L1D_CACHESIZE	42
+#define AT_L1D_CACHEGEOMETRY	43
+#define AT_L2_CACHESIZE		44
+#define AT_L2_CACHEGEOMETRY	45
+#define AT_L3_CACHESIZE		46
+#define AT_L3_CACHEGEOMETRY	47
+
+#define AT_MINSIGSTKSZ		51 /* Stack needed for signal delivery  */
+
+/* Note section contents.  Each entry in the note section begins with
+   a header of a fixed form.  */
+
+typedef struct
+{
+  Elf32_Word n_namesz;			/* Length of the note's name.  */
+  Elf32_Word n_descsz;			/* Length of the note's descriptor.  */
+  Elf32_Word n_type;			/* Type of the note.  */
+} Elf32_Nhdr;
+
+typedef struct
+{
+  Elf64_Word n_namesz;			/* Length of the note's name.  */
+  Elf64_Word n_descsz;			/* Length of the note's descriptor.  */
+  Elf64_Word n_type;			/* Type of the note.  */
+} Elf64_Nhdr;
+
+/* Known names of notes.  */
+
+/* Solaris entries in the note section have this name.  */
+#define ELF_NOTE_SOLARIS	"SUNW Solaris"
+
+/* Note entries for GNU systems have this name.  */
+#define ELF_NOTE_GNU		"GNU"
+
+/* Note entries for freedesktop.org have this name.  */
+#define ELF_NOTE_FDO		"FDO"
+
+/* Defined types of notes for Solaris.  */
+
+/* Value of descriptor (one word) is desired pagesize for the binary.  */
+#define ELF_NOTE_PAGESIZE_HINT	1
+
+
+/* Defined note types for GNU systems.  */
+
+/* ABI information.  The descriptor consists of words:
+   word 0: OS descriptor
+   word 1: major version of the ABI
+   word 2: minor version of the ABI
+   word 3: subminor version of the ABI
+*/
+#define NT_GNU_ABI_TAG	1
+#define ELF_NOTE_ABI	NT_GNU_ABI_TAG /* Old name.  */
+
+/* Known OSes.  These values can appear in word 0 of an
+   NT_GNU_ABI_TAG note section entry.  */
+#define ELF_NOTE_OS_LINUX	0
+#define ELF_NOTE_OS_GNU		1
+#define ELF_NOTE_OS_SOLARIS2	2
+#define ELF_NOTE_OS_FREEBSD	3
+
+/* Synthetic hwcap information.  The descriptor begins with two words:
+   word 0: number of entries
+   word 1: bitmask of enabled entries
+   Then follow variable-length entries, one byte followed by a
+   '\0'-terminated hwcap name string.  The byte gives the bit
+   number to test if enabled, (1U << bit) & bitmask.  */
+#define NT_GNU_HWCAP	2
+
+/* Build ID bits as generated by ld --build-id.
+   The descriptor consists of any nonzero number of bytes.  */
+#define NT_GNU_BUILD_ID	3
+
+/* Version note generated by GNU gold containing a version string.  */
+#define NT_GNU_GOLD_VERSION	4
+
+/* Program property.  */
+#define NT_GNU_PROPERTY_TYPE_0 5
+
+/* Packaging metadata as defined on
+   https://systemd.io/COREDUMP_PACKAGE_METADATA/ */
+#define NT_FDO_PACKAGING_METADATA 0xcafe1a7e
+
+/* Note section name of program property.   */
+#define NOTE_GNU_PROPERTY_SECTION_NAME ".note.gnu.property"
+
+/* Values used in GNU .note.gnu.property notes (NT_GNU_PROPERTY_TYPE_0).  */
+
+/* Stack size.  */
+#define GNU_PROPERTY_STACK_SIZE			1
+/* No copy relocation on protected data symbol.  */
+#define GNU_PROPERTY_NO_COPY_ON_PROTECTED	2
+
+/* A 4-byte unsigned integer property: A bit is set if it is set in all
+   relocatable inputs.  */
+#define GNU_PROPERTY_UINT32_AND_LO	0xb0000000
+#define GNU_PROPERTY_UINT32_AND_HI	0xb0007fff
+
+/* A 4-byte unsigned integer property: A bit is set if it is set in any
+   relocatable inputs.  */
+#define GNU_PROPERTY_UINT32_OR_LO	0xb0008000
+#define GNU_PROPERTY_UINT32_OR_HI	0xb000ffff
+
+/* The needed properties by the object file.  */
+#define GNU_PROPERTY_1_NEEDED		GNU_PROPERTY_UINT32_OR_LO
+
+/* Set if the object file requires canonical function pointers and
+   cannot be used with copy relocation.  */
+#define GNU_PROPERTY_1_NEEDED_INDIRECT_EXTERN_ACCESS (1U << 0)
+
+/* Processor-specific semantics, lo */
+#define GNU_PROPERTY_LOPROC			0xc0000000
+/* Processor-specific semantics, hi */
+#define GNU_PROPERTY_HIPROC			0xdfffffff
+/* Application-specific semantics, lo */
+#define GNU_PROPERTY_LOUSER			0xe0000000
+/* Application-specific semantics, hi */
+#define GNU_PROPERTY_HIUSER			0xffffffff
+
+/* AArch64 specific GNU properties.  */
+#define GNU_PROPERTY_AARCH64_FEATURE_1_AND	0xc0000000
+
+#define GNU_PROPERTY_AARCH64_FEATURE_1_BTI	(1U << 0)
+#define GNU_PROPERTY_AARCH64_FEATURE_1_PAC	(1U << 1)
+
+/* The x86 instruction sets indicated by the corresponding bits are
+   used in program.  Their support in the hardware is optional.  */
+#define GNU_PROPERTY_X86_ISA_1_USED		0xc0010002
+/* The x86 instruction sets indicated by the corresponding bits are
+   used in program and they must be supported by the hardware.   */
+#define GNU_PROPERTY_X86_ISA_1_NEEDED		0xc0008002
+/* X86 processor-specific features used in program.  */
+#define GNU_PROPERTY_X86_FEATURE_1_AND		0xc0000002
+
+/* GNU_PROPERTY_X86_ISA_1_BASELINE: CMOV, CX8 (cmpxchg8b), FPU (fld),
+   MMX, OSFXSR (fxsave), SCE (syscall), SSE and SSE2.  */
+#define GNU_PROPERTY_X86_ISA_1_BASELINE		(1U << 0)
+/* GNU_PROPERTY_X86_ISA_1_V2: GNU_PROPERTY_X86_ISA_1_BASELINE,
+   CMPXCHG16B (cmpxchg16b), LAHF-SAHF (lahf), POPCNT (popcnt), SSE3,
+   SSSE3, SSE4.1 and SSE4.2.  */
+#define GNU_PROPERTY_X86_ISA_1_V2		(1U << 1)
+/* GNU_PROPERTY_X86_ISA_1_V3: GNU_PROPERTY_X86_ISA_1_V2, AVX, AVX2, BMI1,
+   BMI2, F16C, FMA, LZCNT, MOVBE, XSAVE.  */
+#define GNU_PROPERTY_X86_ISA_1_V3		(1U << 2)
+/* GNU_PROPERTY_X86_ISA_1_V4: GNU_PROPERTY_X86_ISA_1_V3, AVX512F,
+   AVX512BW, AVX512CD, AVX512DQ and AVX512VL.  */
+#define GNU_PROPERTY_X86_ISA_1_V4		(1U << 3)
+
+/* This indicates that all executable sections are compatible with
+   IBT.  */
+#define GNU_PROPERTY_X86_FEATURE_1_IBT		(1U << 0)
+/* This indicates that all executable sections are compatible with
+   SHSTK.  */
+#define GNU_PROPERTY_X86_FEATURE_1_SHSTK	(1U << 1)
+
+/* Move records.  */
+typedef struct
+{
+  Elf32_Xword m_value;		/* Symbol value.  */
+  Elf32_Word m_info;		/* Size and index.  */
+  Elf32_Word m_poffset;		/* Symbol offset.  */
+  Elf32_Half m_repeat;		/* Repeat count.  */
+  Elf32_Half m_stride;		/* Stride info.  */
+} Elf32_Move;
+
+typedef struct
+{
+  Elf64_Xword m_value;		/* Symbol value.  */
+  Elf64_Xword m_info;		/* Size and index.  */
+  Elf64_Xword m_poffset;	/* Symbol offset.  */
+  Elf64_Half m_repeat;		/* Repeat count.  */
+  Elf64_Half m_stride;		/* Stride info.  */
+} Elf64_Move;
+
+/* Macro to construct move records.  */
+#define ELF32_M_SYM(info)	((info) >> 8)
+#define ELF32_M_SIZE(info)	((unsigned char) (info))
+#define ELF32_M_INFO(sym, size)	(((sym) << 8) + (unsigned char) (size))
+
+#define ELF64_M_SYM(info)	ELF32_M_SYM (info)
+#define ELF64_M_SIZE(info)	ELF32_M_SIZE (info)
+#define ELF64_M_INFO(sym, size)	ELF32_M_INFO (sym, size)
+
+
+/* Motorola 68k specific definitions.  */
+
+/* Values for Elf32_Ehdr.e_flags.  */
+#define EF_CPU32	0x00810000
+
+/* m68k relocs.  */
+
+#define R_68K_NONE	0		/* No reloc */
+#define R_68K_32	1		/* Direct 32 bit  */
+#define R_68K_16	2		/* Direct 16 bit  */
+#define R_68K_8		3		/* Direct 8 bit  */
+#define R_68K_PC32	4		/* PC relative 32 bit */
+#define R_68K_PC16	5		/* PC relative 16 bit */
+#define R_68K_PC8	6		/* PC relative 8 bit */
+#define R_68K_GOT32	7		/* 32 bit PC relative GOT entry */
+#define R_68K_GOT16	8		/* 16 bit PC relative GOT entry */
+#define R_68K_GOT8	9		/* 8 bit PC relative GOT entry */
+#define R_68K_GOT32O	10		/* 32 bit GOT offset */
+#define R_68K_GOT16O	11		/* 16 bit GOT offset */
+#define R_68K_GOT8O	12		/* 8 bit GOT offset */
+#define R_68K_PLT32	13		/* 32 bit PC relative PLT address */
+#define R_68K_PLT16	14		/* 16 bit PC relative PLT address */
+#define R_68K_PLT8	15		/* 8 bit PC relative PLT address */
+#define R_68K_PLT32O	16		/* 32 bit PLT offset */
+#define R_68K_PLT16O	17		/* 16 bit PLT offset */
+#define R_68K_PLT8O	18		/* 8 bit PLT offset */
+#define R_68K_COPY	19		/* Copy symbol at runtime */
+#define R_68K_GLOB_DAT	20		/* Create GOT entry */
+#define R_68K_JMP_SLOT	21		/* Create PLT entry */
+#define R_68K_RELATIVE	22		/* Adjust by program base */
+#define R_68K_TLS_GD32      25          /* 32 bit GOT offset for GD */
+#define R_68K_TLS_GD16      26          /* 16 bit GOT offset for GD */
+#define R_68K_TLS_GD8       27          /* 8 bit GOT offset for GD */
+#define R_68K_TLS_LDM32     28          /* 32 bit GOT offset for LDM */
+#define R_68K_TLS_LDM16     29          /* 16 bit GOT offset for LDM */
+#define R_68K_TLS_LDM8      30          /* 8 bit GOT offset for LDM */
+#define R_68K_TLS_LDO32     31          /* 32 bit module-relative offset */
+#define R_68K_TLS_LDO16     32          /* 16 bit module-relative offset */
+#define R_68K_TLS_LDO8      33          /* 8 bit module-relative offset */
+#define R_68K_TLS_IE32      34          /* 32 bit GOT offset for IE */
+#define R_68K_TLS_IE16      35          /* 16 bit GOT offset for IE */
+#define R_68K_TLS_IE8       36          /* 8 bit GOT offset for IE */
+#define R_68K_TLS_LE32      37          /* 32 bit offset relative to
+					   static TLS block */
+#define R_68K_TLS_LE16      38          /* 16 bit offset relative to
+					   static TLS block */
+#define R_68K_TLS_LE8       39          /* 8 bit offset relative to
+					   static TLS block */
+#define R_68K_TLS_DTPMOD32  40          /* 32 bit module number */
+#define R_68K_TLS_DTPREL32  41          /* 32 bit module-relative offset */
+#define R_68K_TLS_TPREL32   42          /* 32 bit TP-relative offset */
+/* Keep this the last entry.  */
+#define R_68K_NUM	43
+
+/* Intel 80386 specific definitions.  */
+
+/* i386 relocs.  */
+
+#define R_386_NONE	   0		/* No reloc */
+#define R_386_32	   1		/* Direct 32 bit  */
+#define R_386_PC32	   2		/* PC relative 32 bit */
+#define R_386_GOT32	   3		/* 32 bit GOT entry */
+#define R_386_PLT32	   4		/* 32 bit PLT address */
+#define R_386_COPY	   5		/* Copy symbol at runtime */
+#define R_386_GLOB_DAT	   6		/* Create GOT entry */
+#define R_386_JMP_SLOT	   7		/* Create PLT entry */
+#define R_386_RELATIVE	   8		/* Adjust by program base */
+#define R_386_GOTOFF	   9		/* 32 bit offset to GOT */
+#define R_386_GOTPC	   10		/* 32 bit PC relative offset to GOT */
+#define R_386_32PLT	   11
+#define R_386_TLS_TPOFF	   14		/* Offset in static TLS block */
+#define R_386_TLS_IE	   15		/* Address of GOT entry for static TLS
+					   block offset */
+#define R_386_TLS_GOTIE	   16		/* GOT entry for static TLS block
+					   offset */
+#define R_386_TLS_LE	   17		/* Offset relative to static TLS
+					   block */
+#define R_386_TLS_GD	   18		/* Direct 32 bit for GNU version of
+					   general dynamic thread local data */
+#define R_386_TLS_LDM	   19		/* Direct 32 bit for GNU version of
+					   local dynamic thread local data
+					   in LE code */
+#define R_386_16	   20
+#define R_386_PC16	   21
+#define R_386_8		   22
+#define R_386_PC8	   23
+#define R_386_TLS_GD_32	   24		/* Direct 32 bit for general dynamic
+					   thread local data */
+#define R_386_TLS_GD_PUSH  25		/* Tag for pushl in GD TLS code */
+#define R_386_TLS_GD_CALL  26		/* Relocation for call to
+					   __tls_get_addr() */
+#define R_386_TLS_GD_POP   27		/* Tag for popl in GD TLS code */
+#define R_386_TLS_LDM_32   28		/* Direct 32 bit for local dynamic
+					   thread local data in LE code */
+#define R_386_TLS_LDM_PUSH 29		/* Tag for pushl in LDM TLS code */
+#define R_386_TLS_LDM_CALL 30		/* Relocation for call to
+					   __tls_get_addr() in LDM code */
+#define R_386_TLS_LDM_POP  31		/* Tag for popl in LDM TLS code */
+#define R_386_TLS_LDO_32   32		/* Offset relative to TLS block */
+#define R_386_TLS_IE_32	   33		/* GOT entry for negated static TLS
+					   block offset */
+#define R_386_TLS_LE_32	   34		/* Negated offset relative to static
+					   TLS block */
+#define R_386_TLS_DTPMOD32 35		/* ID of module containing symbol */
+#define R_386_TLS_DTPOFF32 36		/* Offset in TLS block */
+#define R_386_TLS_TPOFF32  37		/* Negated offset in static TLS block */
+#define R_386_SIZE32	   38 		/* 32-bit symbol size */
+#define R_386_TLS_GOTDESC  39		/* GOT offset for TLS descriptor.  */
+#define R_386_TLS_DESC_CALL 40		/* Marker of call through TLS
+					   descriptor for
+					   relaxation.  */
+#define R_386_TLS_DESC     41		/* TLS descriptor containing
+					   pointer to code and to
+					   argument, returning the TLS
+					   offset for the symbol.  */
+#define R_386_IRELATIVE	   42		/* Adjust indirectly by program base */
+#define R_386_GOT32X	   43		/* Load from 32 bit GOT entry,
+					   relaxable. */
+/* Keep this the last entry.  */
+#define R_386_NUM	   44
+
+/* SUN SPARC specific definitions.  */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_SPARC_REGISTER	13	/* Global register reserved to app. */
+
+/* Values for Elf64_Ehdr.e_flags.  */
+
+#define EF_SPARCV9_MM		3
+#define EF_SPARCV9_TSO		0
+#define EF_SPARCV9_PSO		1
+#define EF_SPARCV9_RMO		2
+#define EF_SPARC_LEDATA		0x800000 /* little endian data */
+#define EF_SPARC_EXT_MASK	0xFFFF00
+#define EF_SPARC_32PLUS		0x000100 /* generic V8+ features */
+#define EF_SPARC_SUN_US1	0x000200 /* Sun UltraSPARC1 extensions */
+#define EF_SPARC_HAL_R1		0x000400 /* HAL R1 extensions */
+#define EF_SPARC_SUN_US3	0x000800 /* Sun UltraSPARCIII extensions */
+
+/* SPARC relocs.  */
+
+#define R_SPARC_NONE		0	/* No reloc */
+#define R_SPARC_8		1	/* Direct 8 bit */
+#define R_SPARC_16		2	/* Direct 16 bit */
+#define R_SPARC_32		3	/* Direct 32 bit */
+#define R_SPARC_DISP8		4	/* PC relative 8 bit */
+#define R_SPARC_DISP16		5	/* PC relative 16 bit */
+#define R_SPARC_DISP32		6	/* PC relative 32 bit */
+#define R_SPARC_WDISP30		7	/* PC relative 30 bit shifted */
+#define R_SPARC_WDISP22		8	/* PC relative 22 bit shifted */
+#define R_SPARC_HI22		9	/* High 22 bit */
+#define R_SPARC_22		10	/* Direct 22 bit */
+#define R_SPARC_13		11	/* Direct 13 bit */
+#define R_SPARC_LO10		12	/* Truncated 10 bit */
+#define R_SPARC_GOT10		13	/* Truncated 10 bit GOT entry */
+#define R_SPARC_GOT13		14	/* 13 bit GOT entry */
+#define R_SPARC_GOT22		15	/* 22 bit GOT entry shifted */
+#define R_SPARC_PC10		16	/* PC relative 10 bit truncated */
+#define R_SPARC_PC22		17	/* PC relative 22 bit shifted */
+#define R_SPARC_WPLT30		18	/* 30 bit PC relative PLT address */
+#define R_SPARC_COPY		19	/* Copy symbol at runtime */
+#define R_SPARC_GLOB_DAT	20	/* Create GOT entry */
+#define R_SPARC_JMP_SLOT	21	/* Create PLT entry */
+#define R_SPARC_RELATIVE	22	/* Adjust by program base */
+#define R_SPARC_UA32		23	/* Direct 32 bit unaligned */
+
+/* Additional Sparc64 relocs.  */
+
+#define R_SPARC_PLT32		24	/* Direct 32 bit ref to PLT entry */
+#define R_SPARC_HIPLT22		25	/* High 22 bit PLT entry */
+#define R_SPARC_LOPLT10		26	/* Truncated 10 bit PLT entry */
+#define R_SPARC_PCPLT32		27	/* PC rel 32 bit ref to PLT entry */
+#define R_SPARC_PCPLT22		28	/* PC rel high 22 bit PLT entry */
+#define R_SPARC_PCPLT10		29	/* PC rel trunc 10 bit PLT entry */
+#define R_SPARC_10		30	/* Direct 10 bit */
+#define R_SPARC_11		31	/* Direct 11 bit */
+#define R_SPARC_64		32	/* Direct 64 bit */
+#define R_SPARC_OLO10		33	/* 10bit with secondary 13bit addend */
+#define R_SPARC_HH22		34	/* Top 22 bits of direct 64 bit */
+#define R_SPARC_HM10		35	/* High middle 10 bits of ... */
+#define R_SPARC_LM22		36	/* Low middle 22 bits of ... */
+#define R_SPARC_PC_HH22		37	/* Top 22 bits of pc rel 64 bit */
+#define R_SPARC_PC_HM10		38	/* High middle 10 bit of ... */
+#define R_SPARC_PC_LM22		39	/* Low miggle 22 bits of ... */
+#define R_SPARC_WDISP16		40	/* PC relative 16 bit shifted */
+#define R_SPARC_WDISP19		41	/* PC relative 19 bit shifted */
+#define R_SPARC_GLOB_JMP	42	/* was part of v9 ABI but was removed */
+#define R_SPARC_7		43	/* Direct 7 bit */
+#define R_SPARC_5		44	/* Direct 5 bit */
+#define R_SPARC_6		45	/* Direct 6 bit */
+#define R_SPARC_DISP64		46	/* PC relative 64 bit */
+#define R_SPARC_PLT64		47	/* Direct 64 bit ref to PLT entry */
+#define R_SPARC_HIX22		48	/* High 22 bit complemented */
+#define R_SPARC_LOX10		49	/* Truncated 11 bit complemented */
+#define R_SPARC_H44		50	/* Direct high 12 of 44 bit */
+#define R_SPARC_M44		51	/* Direct mid 22 of 44 bit */
+#define R_SPARC_L44		52	/* Direct low 10 of 44 bit */
+#define R_SPARC_REGISTER	53	/* Global register usage */
+#define R_SPARC_UA64		54	/* Direct 64 bit unaligned */
+#define R_SPARC_UA16		55	/* Direct 16 bit unaligned */
+#define R_SPARC_TLS_GD_HI22	56
+#define R_SPARC_TLS_GD_LO10	57
+#define R_SPARC_TLS_GD_ADD	58
+#define R_SPARC_TLS_GD_CALL	59
+#define R_SPARC_TLS_LDM_HI22	60
+#define R_SPARC_TLS_LDM_LO10	61
+#define R_SPARC_TLS_LDM_ADD	62
+#define R_SPARC_TLS_LDM_CALL	63
+#define R_SPARC_TLS_LDO_HIX22	64
+#define R_SPARC_TLS_LDO_LOX10	65
+#define R_SPARC_TLS_LDO_ADD	66
+#define R_SPARC_TLS_IE_HI22	67
+#define R_SPARC_TLS_IE_LO10	68
+#define R_SPARC_TLS_IE_LD	69
+#define R_SPARC_TLS_IE_LDX	70
+#define R_SPARC_TLS_IE_ADD	71
+#define R_SPARC_TLS_LE_HIX22	72
+#define R_SPARC_TLS_LE_LOX10	73
+#define R_SPARC_TLS_DTPMOD32	74
+#define R_SPARC_TLS_DTPMOD64	75
+#define R_SPARC_TLS_DTPOFF32	76
+#define R_SPARC_TLS_DTPOFF64	77
+#define R_SPARC_TLS_TPOFF32	78
+#define R_SPARC_TLS_TPOFF64	79
+#define R_SPARC_GOTDATA_HIX22	80
+#define R_SPARC_GOTDATA_LOX10	81
+#define R_SPARC_GOTDATA_OP_HIX22	82
+#define R_SPARC_GOTDATA_OP_LOX10	83
+#define R_SPARC_GOTDATA_OP	84
+#define R_SPARC_H34		85
+#define R_SPARC_SIZE32		86
+#define R_SPARC_SIZE64		87
+#define R_SPARC_WDISP10		88
+#define R_SPARC_JMP_IREL	248
+#define R_SPARC_IRELATIVE	249
+#define R_SPARC_GNU_VTINHERIT	250
+#define R_SPARC_GNU_VTENTRY	251
+#define R_SPARC_REV32		252
+/* Keep this the last entry.  */
+#define R_SPARC_NUM		253
+
+/* For Sparc64, legal values for d_tag of Elf64_Dyn.  */
+
+#define DT_SPARC_REGISTER	0x70000001
+#define DT_SPARC_NUM		2
+
+/* MIPS R3000 specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_MIPS_NOREORDER	1     /* A .noreorder directive was used.  */
+#define EF_MIPS_PIC		2     /* Contains PIC code.  */
+#define EF_MIPS_CPIC		4     /* Uses PIC calling sequence.  */
+#define EF_MIPS_XGOT		8
+#define EF_MIPS_UCODE		16
+#define EF_MIPS_ABI2		32
+#define EF_MIPS_ABI_ON32	64
+#define EF_MIPS_OPTIONS_FIRST	0x00000080 /* Process the .MIPS.options
+					      section first by ld.  */
+#define EF_MIPS_32BITMODE	0x00000100 /* Indicates code compiled for
+					      a 64-bit machine in 32-bit
+					      mode (regs are 32-bits
+					      wide).  */
+#define EF_MIPS_FP64		512  /* Uses FP64 (12 callee-saved).  */
+#define EF_MIPS_NAN2008	1024  /* Uses IEEE 754-2008 NaN encoding.  */
+#define EF_MIPS_ARCH_ASE	0x0f000000 /* Architectural Extensions
+					      used by this file.  */
+#define EF_MIPS_ARCH_ASE_MDMX	0x08000000 /* Use MDMX multimedia
+					      extensions.  */
+#define EF_MIPS_ARCH_ASE_M16	0x04000000 /* Use MIPS-16 ISA
+					      extensions.  */
+#define EF_MIPS_ARCH_ASE_MICROMIPS	0x02000000 /* Use MICROMIPS ISA
+						      extensions.  */
+#define EF_MIPS_ARCH		0xf0000000 /* MIPS architecture level.  */
+
+/* Legal values for MIPS architecture level.  */
+
+#define EF_MIPS_ARCH_1		0x00000000 /* -mips1 code.  */
+#define EF_MIPS_ARCH_2		0x10000000 /* -mips2 code.  */
+#define EF_MIPS_ARCH_3		0x20000000 /* -mips3 code.  */
+#define EF_MIPS_ARCH_4		0x30000000 /* -mips4 code.  */
+#define EF_MIPS_ARCH_5		0x40000000 /* -mips5 code.  */
+#define EF_MIPS_ARCH_32		0x50000000 /* MIPS32 code.  */
+#define EF_MIPS_ARCH_64		0x60000000 /* MIPS64 code.  */
+#define EF_MIPS_ARCH_32R2	0x70000000 /* MIPS32r2 code.  */
+#define EF_MIPS_ARCH_64R2	0x80000000 /* MIPS64r2 code.  */
+#define EF_MIPS_ARCH_32R6	0x90000000 /* MIPS32r6 code.  */
+#define EF_MIPS_ARCH_64R6	0xa0000000 /* MIPS64r6 code.  */
+#define EF_MIPS_ABI		0x0000F000 /* The ABI of the file.  Also
+					      see EF_MIPS_ABI2 above.  */
+#define EF_MIPS_ABI_O32		0x00001000 /* The original o32 abi.  */
+#define EF_MIPS_ABI_O64		0x00002000 /* O32 extended to work on
+					      64 bit architectures.  */
+#define EF_MIPS_ABI_EABI32	0x00003000 /* EABI in 32 bit mode.  */
+#define EF_MIPS_ABI_EABI64	0x00004000 /* EABI in 64 bit mode.  */
+#define EF_MIPS_MACH		0x00FF0000
+#define EF_MIPS_MACH_3900	0x00810000
+#define EF_MIPS_MACH_4010	0x00820000
+#define EF_MIPS_MACH_4100	0x00830000
+#define EF_MIPS_MACH_ALLEGREX	0x00840000
+#define EF_MIPS_MACH_4650	0x00850000
+#define EF_MIPS_MACH_4120	0x00870000
+#define EF_MIPS_MACH_4111	0x00880000
+#define EF_MIPS_MACH_SB1	0x008a0000
+#define EF_MIPS_MACH_OCTEON	0x008b0000
+#define EF_MIPS_MACH_XLR	0x008c0000
+#define EF_MIPS_MACH_OCTEON2	0x008d0000
+#define EF_MIPS_MACH_OCTEON3	0x008e0000
+#define EF_MIPS_MACH_5400	0x00910000
+#define EF_MIPS_MACH_5900	0x00920000
+#define EF_MIPS_MACH_IAMR2	0x00930000
+#define EF_MIPS_MACH_5500	0x00980000
+#define EF_MIPS_MACH_9000	0x00990000
+#define EF_MIPS_MACH_LS2E	0x00A00000
+#define EF_MIPS_MACH_LS2F	0x00A10000
+#define EF_MIPS_MACH_GS464	0x00A20000
+#define EF_MIPS_MACH_GS464E	0x00A30000
+#define EF_MIPS_MACH_GS264E	0x00A40000
+
+/* The following are unofficial names and should not be used.  */
+
+#define E_MIPS_ARCH_1		EF_MIPS_ARCH_1
+#define E_MIPS_ARCH_2		EF_MIPS_ARCH_2
+#define E_MIPS_ARCH_3		EF_MIPS_ARCH_3
+#define E_MIPS_ARCH_4		EF_MIPS_ARCH_4
+#define E_MIPS_ARCH_5		EF_MIPS_ARCH_5
+#define E_MIPS_ARCH_32		EF_MIPS_ARCH_32
+#define E_MIPS_ARCH_64		EF_MIPS_ARCH_64
+
+/* Special section indices.  */
+
+#define SHN_MIPS_ACOMMON	0xff00	/* Allocated common symbols.  */
+#define SHN_MIPS_TEXT		0xff01	/* Allocated test symbols.  */
+#define SHN_MIPS_DATA		0xff02	/* Allocated data symbols.  */
+#define SHN_MIPS_SCOMMON 	0xff03	/* Small common symbols.  */
+#define SHN_MIPS_SUNDEFINED	0xff04	/* Small undefined symbols.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_MIPS_LIBLIST	0x70000000 /* Shared objects used in link.  */
+#define SHT_MIPS_MSYM		0x70000001
+#define SHT_MIPS_CONFLICT	0x70000002 /* Conflicting symbols.  */
+#define SHT_MIPS_GPTAB		0x70000003 /* Global data area sizes.  */
+#define SHT_MIPS_UCODE		0x70000004 /* Reserved for SGI/MIPS compilers */
+#define SHT_MIPS_DEBUG		0x70000005 /* MIPS ECOFF debugging info.  */
+#define SHT_MIPS_REGINFO	0x70000006 /* Register usage information.  */
+#define SHT_MIPS_PACKAGE	0x70000007
+#define SHT_MIPS_PACKSYM	0x70000008
+#define SHT_MIPS_RELD		0x70000009
+#define SHT_MIPS_IFACE		0x7000000b
+#define SHT_MIPS_CONTENT	0x7000000c
+#define SHT_MIPS_OPTIONS	0x7000000d /* Miscellaneous options.  */
+#define SHT_MIPS_SHDR		0x70000010
+#define SHT_MIPS_FDESC		0x70000011
+#define SHT_MIPS_EXTSYM		0x70000012
+#define SHT_MIPS_DENSE		0x70000013
+#define SHT_MIPS_PDESC		0x70000014
+#define SHT_MIPS_LOCSYM		0x70000015
+#define SHT_MIPS_AUXSYM		0x70000016
+#define SHT_MIPS_OPTSYM		0x70000017
+#define SHT_MIPS_LOCSTR		0x70000018
+#define SHT_MIPS_LINE		0x70000019
+#define SHT_MIPS_RFDESC		0x7000001a
+#define SHT_MIPS_DELTASYM	0x7000001b
+#define SHT_MIPS_DELTAINST	0x7000001c
+#define SHT_MIPS_DELTACLASS	0x7000001d
+#define SHT_MIPS_DWARF		0x7000001e /* DWARF debugging information.  */
+#define SHT_MIPS_DELTADECL	0x7000001f
+#define SHT_MIPS_SYMBOL_LIB	0x70000020
+#define SHT_MIPS_EVENTS		0x70000021 /* Event section.  */
+#define SHT_MIPS_TRANSLATE	0x70000022
+#define SHT_MIPS_PIXIE		0x70000023
+#define SHT_MIPS_XLATE		0x70000024
+#define SHT_MIPS_XLATE_DEBUG	0x70000025
+#define SHT_MIPS_WHIRL		0x70000026
+#define SHT_MIPS_EH_REGION	0x70000027
+#define SHT_MIPS_XLATE_OLD	0x70000028
+#define SHT_MIPS_PDR_EXCEPTION	0x70000029
+#define SHT_MIPS_ABIFLAGS	0x7000002a
+#define SHT_MIPS_XHASH		0x7000002b
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_MIPS_GPREL		0x10000000 /* Must be in global data area.  */
+#define SHF_MIPS_MERGE		0x20000000
+#define SHF_MIPS_ADDR		0x40000000
+#define SHF_MIPS_STRINGS	0x80000000
+#define SHF_MIPS_NOSTRIP	0x08000000
+#define SHF_MIPS_LOCAL		0x04000000
+#define SHF_MIPS_NAMES		0x02000000
+#define SHF_MIPS_NODUPE		0x01000000
+
+
+/* Symbol tables.  */
+
+/* MIPS specific values for `st_other'.  */
+#define STO_MIPS_DEFAULT		0x0
+#define STO_MIPS_INTERNAL		0x1
+#define STO_MIPS_HIDDEN			0x2
+#define STO_MIPS_PROTECTED		0x3
+#define STO_MIPS_PLT			0x8
+#define STO_MIPS_SC_ALIGN_UNUSED	0xff
+
+/* MIPS specific values for `st_info'.  */
+#define STB_MIPS_SPLIT_COMMON		13
+
+/* Entries found in sections of type SHT_MIPS_GPTAB.  */
+
+typedef union
+{
+  struct
+    {
+      Elf32_Word gt_current_g_value;	/* -G value used for compilation.  */
+      Elf32_Word gt_unused;		/* Not used.  */
+    } gt_header;			/* First entry in section.  */
+  struct
+    {
+      Elf32_Word gt_g_value;		/* If this value were used for -G.  */
+      Elf32_Word gt_bytes;		/* This many bytes would be used.  */
+    } gt_entry;				/* Subsequent entries in section.  */
+} Elf32_gptab;
+
+/* Entry found in sections of type SHT_MIPS_REGINFO.  */
+
+typedef struct
+{
+  Elf32_Word ri_gprmask;		/* General registers used.  */
+  Elf32_Word ri_cprmask[4];		/* Coprocessor registers used.  */
+  Elf32_Sword ri_gp_value;		/* $gp register value.  */
+} Elf32_RegInfo;
+
+/* Entries found in sections of type SHT_MIPS_OPTIONS.  */
+
+typedef struct
+{
+  unsigned char kind;		/* Determines interpretation of the
+				   variable part of descriptor.  */
+  unsigned char size;		/* Size of descriptor, including header.  */
+  Elf32_Section section;	/* Section header index of section affected,
+				   0 for global options.  */
+  Elf32_Word info;		/* Kind-specific information.  */
+} Elf_Options;
+
+/* Values for `kind' field in Elf_Options.  */
+
+#define ODK_NULL	0	/* Undefined.  */
+#define ODK_REGINFO	1	/* Register usage information.  */
+#define ODK_EXCEPTIONS	2	/* Exception processing options.  */
+#define ODK_PAD		3	/* Section padding options.  */
+#define ODK_HWPATCH	4	/* Hardware workarounds performed */
+#define ODK_FILL	5	/* record the fill value used by the linker. */
+#define ODK_TAGS	6	/* reserve space for desktop tools to write. */
+#define ODK_HWAND	7	/* HW workarounds.  'AND' bits when merging. */
+#define ODK_HWOR	8	/* HW workarounds.  'OR' bits when merging.  */
+
+/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries.  */
+
+#define OEX_FPU_MIN	0x1f	/* FPE's which MUST be enabled.  */
+#define OEX_FPU_MAX	0x1f00	/* FPE's which MAY be enabled.  */
+#define OEX_PAGE0	0x10000	/* page zero must be mapped.  */
+#define OEX_SMM		0x20000	/* Force sequential memory mode?  */
+#define OEX_FPDBUG	0x40000	/* Force floating point debug mode?  */
+#define OEX_PRECISEFP	OEX_FPDBUG
+#define OEX_DISMISS	0x80000	/* Dismiss invalid address faults?  */
+
+#define OEX_FPU_INVAL	0x10
+#define OEX_FPU_DIV0	0x08
+#define OEX_FPU_OFLO	0x04
+#define OEX_FPU_UFLO	0x02
+#define OEX_FPU_INEX	0x01
+
+/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry.  */
+
+#define OHW_R4KEOP	0x1	/* R4000 end-of-page patch.  */
+#define OHW_R8KPFETCH	0x2	/* may need R8000 prefetch patch.  */
+#define OHW_R5KEOP	0x4	/* R5000 end-of-page patch.  */
+#define OHW_R5KCVTL	0x8	/* R5000 cvt.[ds].l bug.  clean=1.  */
+
+#define OPAD_PREFIX	0x1
+#define OPAD_POSTFIX	0x2
+#define OPAD_SYMBOL	0x4
+
+/* Entry found in `.options' section.  */
+
+typedef struct
+{
+  Elf32_Word hwp_flags1;	/* Extra flags.  */
+  Elf32_Word hwp_flags2;	/* Extra flags.  */
+} Elf_Options_Hw;
+
+/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries.  */
+
+#define OHWA0_R4KEOP_CHECKED	0x00000001
+#define OHWA1_R4KEOP_CLEAN	0x00000002
+
+/* MIPS relocs.  */
+
+#define R_MIPS_NONE		0	/* No reloc */
+#define R_MIPS_16		1	/* Direct 16 bit */
+#define R_MIPS_32		2	/* Direct 32 bit */
+#define R_MIPS_REL32		3	/* PC relative 32 bit */
+#define R_MIPS_26		4	/* Direct 26 bit shifted */
+#define R_MIPS_HI16		5	/* High 16 bit */
+#define R_MIPS_LO16		6	/* Low 16 bit */
+#define R_MIPS_GPREL16		7	/* GP relative 16 bit */
+#define R_MIPS_LITERAL		8	/* 16 bit literal entry */
+#define R_MIPS_GOT16		9	/* 16 bit GOT entry */
+#define R_MIPS_PC16		10	/* PC relative 16 bit */
+#define R_MIPS_CALL16		11	/* 16 bit GOT entry for function */
+#define R_MIPS_GPREL32		12	/* GP relative 32 bit */
+
+#define R_MIPS_SHIFT5		16
+#define R_MIPS_SHIFT6		17
+#define R_MIPS_64		18
+#define R_MIPS_GOT_DISP		19
+#define R_MIPS_GOT_PAGE		20
+#define R_MIPS_GOT_OFST		21
+#define R_MIPS_GOT_HI16		22
+#define R_MIPS_GOT_LO16		23
+#define R_MIPS_SUB		24
+#define R_MIPS_INSERT_A		25
+#define R_MIPS_INSERT_B		26
+#define R_MIPS_DELETE		27
+#define R_MIPS_HIGHER		28
+#define R_MIPS_HIGHEST		29
+#define R_MIPS_CALL_HI16	30
+#define R_MIPS_CALL_LO16	31
+#define R_MIPS_SCN_DISP		32
+#define R_MIPS_REL16		33
+#define R_MIPS_ADD_IMMEDIATE	34
+#define R_MIPS_PJUMP		35
+#define R_MIPS_RELGOT		36
+#define R_MIPS_JALR		37
+#define R_MIPS_TLS_DTPMOD32	38	/* Module number 32 bit */
+#define R_MIPS_TLS_DTPREL32	39	/* Module-relative offset 32 bit */
+#define R_MIPS_TLS_DTPMOD64	40	/* Module number 64 bit */
+#define R_MIPS_TLS_DTPREL64	41	/* Module-relative offset 64 bit */
+#define R_MIPS_TLS_GD		42	/* 16 bit GOT offset for GD */
+#define R_MIPS_TLS_LDM		43	/* 16 bit GOT offset for LDM */
+#define R_MIPS_TLS_DTPREL_HI16	44	/* Module-relative offset, high 16 bits */
+#define R_MIPS_TLS_DTPREL_LO16	45	/* Module-relative offset, low 16 bits */
+#define R_MIPS_TLS_GOTTPREL	46	/* 16 bit GOT offset for IE */
+#define R_MIPS_TLS_TPREL32	47	/* TP-relative offset, 32 bit */
+#define R_MIPS_TLS_TPREL64	48	/* TP-relative offset, 64 bit */
+#define R_MIPS_TLS_TPREL_HI16	49	/* TP-relative offset, high 16 bits */
+#define R_MIPS_TLS_TPREL_LO16	50	/* TP-relative offset, low 16 bits */
+#define R_MIPS_GLOB_DAT		51
+#define R_MIPS_PC21_S2		60
+#define R_MIPS_PC26_S2		61
+#define R_MIPS_PC18_S3		62
+#define R_MIPS_PC19_S2		63
+#define R_MIPS_PCHI16		64
+#define R_MIPS_PCLO16		65
+#define R_MIPS16_26		100
+#define R_MIPS16_GPREL		101
+#define R_MIPS16_GOT16		102
+#define R_MIPS16_CALL16		103
+#define R_MIPS16_HI16		104
+#define R_MIPS16_LO16		105
+#define R_MIPS16_TLS_GD		106
+#define R_MIPS16_TLS_LDM	107
+#define R_MIPS16_TLS_DTPREL_HI16	108
+#define R_MIPS16_TLS_DTPREL_LO16	109
+#define R_MIPS16_TLS_GOTTPREL	110
+#define R_MIPS16_TLS_TPREL_HI16	111
+#define R_MIPS16_TLS_TPREL_LO16	112
+#define R_MIPS16_PC16_S1	113
+#define R_MIPS_COPY		126
+#define R_MIPS_JUMP_SLOT        127
+#define R_MIPS_RELATIVE		128
+#define R_MICROMIPS_26_S1	133
+#define R_MICROMIPS_HI16	134
+#define R_MICROMIPS_LO16	135
+#define R_MICROMIPS_GPREL16	136
+#define R_MICROMIPS_LITERAL	137
+#define R_MICROMIPS_GOT16	138
+#define R_MICROMIPS_PC7_S1	139
+#define R_MICROMIPS_PC10_S1	140
+#define R_MICROMIPS_PC16_S1	141
+#define R_MICROMIPS_CALL16	142
+#define R_MICROMIPS_GOT_DISP	145
+#define R_MICROMIPS_GOT_PAGE	146
+#define R_MICROMIPS_GOT_OFST	147
+#define R_MICROMIPS_GOT_HI16	148
+#define R_MICROMIPS_GOT_LO16	149
+#define R_MICROMIPS_SUB		150
+#define R_MICROMIPS_HIGHER	151
+#define R_MICROMIPS_HIGHEST	152
+#define R_MICROMIPS_CALL_HI16	153
+#define R_MICROMIPS_CALL_LO16	154
+#define R_MICROMIPS_SCN_DISP	155
+#define R_MICROMIPS_JALR	156
+#define R_MICROMIPS_HI0_LO16	157
+#define R_MICROMIPS_TLS_GD	162
+#define R_MICROMIPS_TLS_LDM	163
+#define R_MICROMIPS_TLS_DTPREL_HI16	164
+#define R_MICROMIPS_TLS_DTPREL_LO16	165
+#define R_MICROMIPS_TLS_GOTTPREL	166
+#define R_MICROMIPS_TLS_TPREL_HI16	169
+#define R_MICROMIPS_TLS_TPREL_LO16	170
+#define R_MICROMIPS_GPREL7_S2	172
+#define R_MICROMIPS_PC23_S2	173
+#define R_MIPS_PC32		248
+#define R_MIPS_EH		249
+#define R_MIPS_GNU_REL16_S2	250
+#define R_MIPS_GNU_VTINHERIT	253
+#define R_MIPS_GNU_VTENTRY	254
+/* Keep this the last entry.  */
+#define R_MIPS_NUM		255
+
+/* Legal values for p_type field of Elf32_Phdr.  */
+
+#define PT_MIPS_REGINFO	  0x70000000	/* Register usage information. */
+#define PT_MIPS_RTPROC	  0x70000001	/* Runtime procedure table. */
+#define PT_MIPS_OPTIONS	  0x70000002
+#define PT_MIPS_ABIFLAGS  0x70000003	/* FP mode requirement. */
+
+/* Special program header types.  */
+
+#define PF_MIPS_LOCAL	0x10000000
+
+/* Legal values for d_tag field of Elf32_Dyn.  */
+
+#define DT_MIPS_RLD_VERSION  0x70000001	/* Runtime linker interface version */
+#define DT_MIPS_TIME_STAMP   0x70000002	/* Timestamp */
+#define DT_MIPS_ICHECKSUM    0x70000003	/* Checksum */
+#define DT_MIPS_IVERSION     0x70000004	/* Version string (string tbl index) */
+#define DT_MIPS_FLAGS	     0x70000005	/* Flags */
+#define DT_MIPS_BASE_ADDRESS 0x70000006	/* Base address */
+#define DT_MIPS_MSYM	     0x70000007
+#define DT_MIPS_CONFLICT     0x70000008	/* Address of CONFLICT section */
+#define DT_MIPS_LIBLIST	     0x70000009	/* Address of LIBLIST section */
+#define DT_MIPS_LOCAL_GOTNO  0x7000000a	/* Number of local GOT entries */
+#define DT_MIPS_CONFLICTNO   0x7000000b	/* Number of CONFLICT entries */
+#define DT_MIPS_LIBLISTNO    0x70000010	/* Number of LIBLIST entries */
+#define DT_MIPS_SYMTABNO     0x70000011	/* Number of DYNSYM entries */
+#define DT_MIPS_UNREFEXTNO   0x70000012	/* First external DYNSYM */
+#define DT_MIPS_GOTSYM	     0x70000013	/* First GOT entry in DYNSYM */
+#define DT_MIPS_HIPAGENO     0x70000014	/* Number of GOT page table entries */
+#define DT_MIPS_RLD_MAP	     0x70000016	/* Address of run time loader map.  */
+#define DT_MIPS_DELTA_CLASS  0x70000017	/* Delta C++ class definition.  */
+#define DT_MIPS_DELTA_CLASS_NO    0x70000018 /* Number of entries in
+						DT_MIPS_DELTA_CLASS.  */
+#define DT_MIPS_DELTA_INSTANCE    0x70000019 /* Delta C++ class instances.  */
+#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in
+						DT_MIPS_DELTA_INSTANCE.  */
+#define DT_MIPS_DELTA_RELOC  0x7000001b /* Delta relocations.  */
+#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in
+					     DT_MIPS_DELTA_RELOC.  */
+#define DT_MIPS_DELTA_SYM    0x7000001d /* Delta symbols that Delta
+					   relocations refer to.  */
+#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in
+					   DT_MIPS_DELTA_SYM.  */
+#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the
+					     class declaration.  */
+#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in
+						DT_MIPS_DELTA_CLASSSYM.  */
+#define DT_MIPS_CXX_FLAGS    0x70000022 /* Flags indicating for C++ flavor.  */
+#define DT_MIPS_PIXIE_INIT   0x70000023
+#define DT_MIPS_SYMBOL_LIB   0x70000024
+#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025
+#define DT_MIPS_LOCAL_GOTIDX 0x70000026
+#define DT_MIPS_HIDDEN_GOTIDX 0x70000027
+#define DT_MIPS_PROTECTED_GOTIDX 0x70000028
+#define DT_MIPS_OPTIONS	     0x70000029 /* Address of .options.  */
+#define DT_MIPS_INTERFACE    0x7000002a /* Address of .interface.  */
+#define DT_MIPS_DYNSTR_ALIGN 0x7000002b
+#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */
+#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve
+						    function stored in GOT.  */
+#define DT_MIPS_PERF_SUFFIX  0x7000002e /* Default suffix of dso to be added
+					   by rld on dlopen() calls.  */
+#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */
+#define DT_MIPS_GP_VALUE     0x70000030 /* GP value for aux GOTs.  */
+#define DT_MIPS_AUX_DYNAMIC  0x70000031 /* Address of aux .dynamic.  */
+/* The address of .got.plt in an executable using the new non-PIC ABI.  */
+#define DT_MIPS_PLTGOT	     0x70000032
+/* The base of the PLT in an executable using the new non-PIC ABI if that
+   PLT is writable.  For a non-writable PLT, this is omitted or has a zero
+   value.  */
+#define DT_MIPS_RWPLT        0x70000034
+/* An alternative description of the classic MIPS RLD_MAP that is usable
+   in a PIE as it stores a relative offset from the address of the tag
+   rather than an absolute address.  */
+#define DT_MIPS_RLD_MAP_REL  0x70000035
+/* GNU-style hash table with xlat.  */
+#define DT_MIPS_XHASH	     0x70000036
+#define DT_MIPS_NUM	     0x37
+
+/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry.  */
+
+#define RHF_NONE		   0		/* No flags */
+#define RHF_QUICKSTART		   (1 << 0)	/* Use quickstart */
+#define RHF_NOTPOT		   (1 << 1)	/* Hash size not power of 2 */
+#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2)	/* Ignore LD_LIBRARY_PATH */
+#define RHF_NO_MOVE		   (1 << 3)
+#define RHF_SGI_ONLY		   (1 << 4)
+#define RHF_GUARANTEE_INIT	   (1 << 5)
+#define RHF_DELTA_C_PLUS_PLUS	   (1 << 6)
+#define RHF_GUARANTEE_START_INIT   (1 << 7)
+#define RHF_PIXIE		   (1 << 8)
+#define RHF_DEFAULT_DELAY_LOAD	   (1 << 9)
+#define RHF_REQUICKSTART	   (1 << 10)
+#define RHF_REQUICKSTARTED	   (1 << 11)
+#define RHF_CORD		   (1 << 12)
+#define RHF_NO_UNRES_UNDEF	   (1 << 13)
+#define RHF_RLD_ORDER_SAFE	   (1 << 14)
+
+/* Entries found in sections of type SHT_MIPS_LIBLIST.  */
+
+typedef struct
+{
+  Elf32_Word l_name;		/* Name (string table index) */
+  Elf32_Word l_time_stamp;	/* Timestamp */
+  Elf32_Word l_checksum;	/* Checksum */
+  Elf32_Word l_version;		/* Interface version */
+  Elf32_Word l_flags;		/* Flags */
+} Elf32_Lib;
+
+typedef struct
+{
+  Elf64_Word l_name;		/* Name (string table index) */
+  Elf64_Word l_time_stamp;	/* Timestamp */
+  Elf64_Word l_checksum;	/* Checksum */
+  Elf64_Word l_version;		/* Interface version */
+  Elf64_Word l_flags;		/* Flags */
+} Elf64_Lib;
+
+
+/* Legal values for l_flags.  */
+
+#define LL_NONE		  0
+#define LL_EXACT_MATCH	  (1 << 0)	/* Require exact match */
+#define LL_IGNORE_INT_VER (1 << 1)	/* Ignore interface version */
+#define LL_REQUIRE_MINOR  (1 << 2)
+#define LL_EXPORTS	  (1 << 3)
+#define LL_DELAY_LOAD	  (1 << 4)
+#define LL_DELTA	  (1 << 5)
+
+/* Entries found in sections of type SHT_MIPS_CONFLICT.  */
+
+typedef Elf32_Addr Elf32_Conflict;
+
+typedef struct
+{
+  /* Version of flags structure.  */
+  Elf32_Half version;
+  /* The level of the ISA: 1-5, 32, 64.  */
+  unsigned char isa_level;
+  /* The revision of ISA: 0 for MIPS V and below, 1-n otherwise.  */
+  unsigned char isa_rev;
+  /* The size of general purpose registers.  */
+  unsigned char gpr_size;
+  /* The size of co-processor 1 registers.  */
+  unsigned char cpr1_size;
+  /* The size of co-processor 2 registers.  */
+  unsigned char cpr2_size;
+  /* The floating-point ABI.  */
+  unsigned char fp_abi;
+  /* Processor-specific extension.  */
+  Elf32_Word isa_ext;
+  /* Mask of ASEs used.  */
+  Elf32_Word ases;
+  /* Mask of general flags.  */
+  Elf32_Word flags1;
+  Elf32_Word flags2;
+} Elf_MIPS_ABIFlags_v0;
+
+/* Values for the register size bytes of an abi flags structure.  */
+
+#define MIPS_AFL_REG_NONE	0x00	 /* No registers.  */
+#define MIPS_AFL_REG_32		0x01	 /* 32-bit registers.  */
+#define MIPS_AFL_REG_64		0x02	 /* 64-bit registers.  */
+#define MIPS_AFL_REG_128	0x03	 /* 128-bit registers.  */
+
+/* Masks for the ases word of an ABI flags structure.  */
+
+#define MIPS_AFL_ASE_DSP	0x00000001 /* DSP ASE.  */
+#define MIPS_AFL_ASE_DSPR2	0x00000002 /* DSP R2 ASE.  */
+#define MIPS_AFL_ASE_EVA	0x00000004 /* Enhanced VA Scheme.  */
+#define MIPS_AFL_ASE_MCU	0x00000008 /* MCU (MicroController) ASE.  */
+#define MIPS_AFL_ASE_MDMX	0x00000010 /* MDMX ASE.  */
+#define MIPS_AFL_ASE_MIPS3D	0x00000020 /* MIPS-3D ASE.  */
+#define MIPS_AFL_ASE_MT		0x00000040 /* MT ASE.  */
+#define MIPS_AFL_ASE_SMARTMIPS	0x00000080 /* SmartMIPS ASE.  */
+#define MIPS_AFL_ASE_VIRT	0x00000100 /* VZ ASE.  */
+#define MIPS_AFL_ASE_MSA	0x00000200 /* MSA ASE.  */
+#define MIPS_AFL_ASE_MIPS16	0x00000400 /* MIPS16 ASE.  */
+#define MIPS_AFL_ASE_MICROMIPS	0x00000800 /* MICROMIPS ASE.  */
+#define MIPS_AFL_ASE_XPA	0x00001000 /* XPA ASE.  */
+#define MIPS_AFL_ASE_MASK	0x00001fff /* All ASEs.  */
+
+/* Values for the isa_ext word of an ABI flags structure.  */
+
+#define MIPS_AFL_EXT_XLR	  1   /* RMI Xlr instruction.  */
+#define MIPS_AFL_EXT_OCTEON2	  2   /* Cavium Networks Octeon2.  */
+#define MIPS_AFL_EXT_OCTEONP	  3   /* Cavium Networks OcteonP.  */
+#define MIPS_AFL_EXT_LOONGSON_3A  4   /* Loongson 3A.  */
+#define MIPS_AFL_EXT_OCTEON	  5   /* Cavium Networks Octeon.  */
+#define MIPS_AFL_EXT_5900	  6   /* MIPS R5900 instruction.  */
+#define MIPS_AFL_EXT_4650	  7   /* MIPS R4650 instruction.  */
+#define MIPS_AFL_EXT_4010	  8   /* LSI R4010 instruction.  */
+#define MIPS_AFL_EXT_4100	  9   /* NEC VR4100 instruction.  */
+#define MIPS_AFL_EXT_3900	  10  /* Toshiba R3900 instruction.  */
+#define MIPS_AFL_EXT_10000	  11  /* MIPS R10000 instruction.  */
+#define MIPS_AFL_EXT_SB1	  12  /* Broadcom SB-1 instruction.  */
+#define MIPS_AFL_EXT_4111	  13  /* NEC VR4111/VR4181 instruction.  */
+#define MIPS_AFL_EXT_4120	  14  /* NEC VR4120 instruction.  */
+#define MIPS_AFL_EXT_5400	  15  /* NEC VR5400 instruction.  */
+#define MIPS_AFL_EXT_5500	  16  /* NEC VR5500 instruction.  */
+#define MIPS_AFL_EXT_LOONGSON_2E  17  /* ST Microelectronics Loongson 2E.  */
+#define MIPS_AFL_EXT_LOONGSON_2F  18  /* ST Microelectronics Loongson 2F.  */
+
+/* Masks for the flags1 word of an ABI flags structure.  */
+#define MIPS_AFL_FLAGS1_ODDSPREG  1  /* Uses odd single-precision registers.  */
+
+/* Object attribute values.  */
+enum
+{
+  /* Not tagged or not using any ABIs affected by the differences.  */
+  Val_GNU_MIPS_ABI_FP_ANY = 0,
+  /* Using hard-float -mdouble-float.  */
+  Val_GNU_MIPS_ABI_FP_DOUBLE = 1,
+  /* Using hard-float -msingle-float.  */
+  Val_GNU_MIPS_ABI_FP_SINGLE = 2,
+  /* Using soft-float.  */
+  Val_GNU_MIPS_ABI_FP_SOFT = 3,
+  /* Using -mips32r2 -mfp64.  */
+  Val_GNU_MIPS_ABI_FP_OLD_64 = 4,
+  /* Using -mfpxx.  */
+  Val_GNU_MIPS_ABI_FP_XX = 5,
+  /* Using -mips32r2 -mfp64.  */
+  Val_GNU_MIPS_ABI_FP_64 = 6,
+  /* Using -mips32r2 -mfp64 -mno-odd-spreg.  */
+  Val_GNU_MIPS_ABI_FP_64A = 7,
+  /* Maximum allocated FP ABI value.  */
+  Val_GNU_MIPS_ABI_FP_MAX = 7
+};
+
+/* HPPA specific definitions.  */
+
+/* Legal values for e_flags field of Elf32_Ehdr.  */
+
+#define EF_PARISC_TRAPNIL	0x00010000 /* Trap nil pointer dereference.  */
+#define EF_PARISC_EXT		0x00020000 /* Program uses arch. extensions. */
+#define EF_PARISC_LSB		0x00040000 /* Program expects little endian. */
+#define EF_PARISC_WIDE		0x00080000 /* Program expects wide mode.  */
+#define EF_PARISC_NO_KABP	0x00100000 /* No kernel assisted branch
+					      prediction.  */
+#define EF_PARISC_LAZYSWAP	0x00400000 /* Allow lazy swapping.  */
+#define EF_PARISC_ARCH		0x0000ffff /* Architecture version.  */
+
+/* Defined values for `e_flags & EF_PARISC_ARCH' are:  */
+
+#define EFA_PARISC_1_0		    0x020b /* PA-RISC 1.0 big-endian.  */
+#define EFA_PARISC_1_1		    0x0210 /* PA-RISC 1.1 big-endian.  */
+#define EFA_PARISC_2_0		    0x0214 /* PA-RISC 2.0 big-endian.  */
+
+/* Additional section indices.  */
+
+#define SHN_PARISC_ANSI_COMMON	0xff00	   /* Section for tentatively declared
+					      symbols in ANSI C.  */
+#define SHN_PARISC_HUGE_COMMON	0xff01	   /* Common blocks in huge model.  */
+
+/* Legal values for sh_type field of Elf32_Shdr.  */
+
+#define SHT_PARISC_EXT		0x70000000 /* Contains product specific ext. */
+#define SHT_PARISC_UNWIND	0x70000001 /* Unwind information.  */
+#define SHT_PARISC_DOC		0x70000002 /* Debug info for optimized code. */
+
+/* Legal values for sh_flags field of Elf32_Shdr.  */
+
+#define SHF_PARISC_SHORT	0x20000000 /* Section with short addressing. */
+#define SHF_PARISC_HUGE		0x40000000 /* Section far from gp.  */
+#define SHF_PARISC_SBP		0x80000000 /* Static branch prediction code. */
+
+/* Legal values for ST_TYPE subfield of st_info (symbol type).  */
+
+#define STT_PARISC_MILLICODE	13	/* Millicode function entry point.  */
+
+#define STT_HP_OPAQUE		(STT_LOOS + 0x1)
+#define STT_HP_STUB		(STT_LOOS + 0x2)
+
+/* HPPA relocs.  */
+
+#define R_PARISC_NONE		0	/* No reloc.  */
+#define R_PARISC_DIR32		1	/* Direct 32-bit reference.  */
+#define R_PARISC_DIR21L		2	/* Left 21 bits of eff. address.  */
+#define R_PARISC_DIR17R		3	/* Right 17 bits of eff. address.  */
+#define R_PARISC_DIR17F		4	/* 17 bits of eff. address.  */
+#define R_PARISC_DIR14R		6	/* Right 14 bits of eff. address.  */
+#define R_PARISC_PCREL32	9	/* 32-bit rel. address.  */
+#define R_PARISC_PCREL21L	10	/* Left 21 bits of rel. address.  */
+#define R_PARISC_PCREL17R	11	/* Right 17 bits of rel. address.  */
+#define R_PARISC_PCREL17F	12	/* 17 bits of rel. address.  */
+#define R_PARISC_PCREL14R	14	/* Right 14 bits of rel. address.  */
+#define R_PARISC_DPREL21L	18	/* Left 21 bits of rel. address.  */
+#define R_PARISC_DPREL14R	22	/* Right 14 bits of rel. address.  */
+#define R_PARISC_GPREL21L	26	/* GP-relative, left 21 bits.  */
+#define R_PARISC_GPREL14R	30	/* GP-relative, right 14 bits.  */
+#define R_PARISC_LTOFF21L	34	/* LT-relative, left 21 bits.  */
+#define R_PARISC_LTOFF14R	38	/* LT-relative, right 14 bits.  */
+#define R_PARISC_SECREL32	41	/* 32 bits section rel. address.  */
+#define R_PARISC_SEGBASE	48	/* No relocation, set segment base.  */
+#define R_PARISC_SEGREL32	49	/* 32 bits segment rel. address.  */
+#define R_PARISC_PLTOFF21L	50	/* PLT rel. address, left 21 bits.  */
+#define R_PARISC_PLTOFF14R	54	/* PLT rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_FPTR32	57	/* 32 bits LT-rel. function pointer. */
+#define R_PARISC_LTOFF_FPTR21L	58	/* LT-rel. fct ptr, left 21 bits. */
+#define R_PARISC_LTOFF_FPTR14R	62	/* LT-rel. fct ptr, right 14 bits. */
+#define R_PARISC_FPTR64		64	/* 64 bits function address.  */
+#define R_PARISC_PLABEL32	65	/* 32 bits function address.  */
+#define R_PARISC_PLABEL21L	66	/* Left 21 bits of fdesc address.  */
+#define R_PARISC_PLABEL14R	70	/* Right 14 bits of fdesc address.  */
+#define R_PARISC_PCREL64	72	/* 64 bits PC-rel. address.  */
+#define R_PARISC_PCREL22F	74	/* 22 bits PC-rel. address.  */
+#define R_PARISC_PCREL14WR	75	/* PC-rel. address, right 14 bits.  */
+#define R_PARISC_PCREL14DR	76	/* PC rel. address, right 14 bits.  */
+#define R_PARISC_PCREL16F	77	/* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16WF	78	/* 16 bits PC-rel. address.  */
+#define R_PARISC_PCREL16DF	79	/* 16 bits PC-rel. address.  */
+#define R_PARISC_DIR64		80	/* 64 bits of eff. address.  */
+#define R_PARISC_DIR14WR	83	/* 14 bits of eff. address.  */
+#define R_PARISC_DIR14DR	84	/* 14 bits of eff. address.  */
+#define R_PARISC_DIR16F		85	/* 16 bits of eff. address.  */
+#define R_PARISC_DIR16WF	86	/* 16 bits of eff. address.  */
+#define R_PARISC_DIR16DF	87	/* 16 bits of eff. address.  */
+#define R_PARISC_GPREL64	88	/* 64 bits of GP-rel. address.  */
+#define R_PARISC_GPREL14WR	91	/* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL14DR	92	/* GP-rel. address, right 14 bits.  */
+#define R_PARISC_GPREL16F	93	/* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16WF	94	/* 16 bits GP-rel. address.  */
+#define R_PARISC_GPREL16DF	95	/* 16 bits GP-rel. address.  */
+#define R_PARISC_LTOFF64	96	/* 64 bits LT-rel. address.  */
+#define R_PARISC_LTOFF14WR	99	/* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF14DR	100	/* LT-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF16F	101	/* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16WF	102	/* 16 bits LT-rel. address.  */
+#define R_PARISC_LTOFF16DF	103	/* 16 bits LT-rel. address.  */
+#define R_PARISC_SECREL64	104	/* 64 bits section rel. address.  */
+#define R_PARISC_SEGREL64	112	/* 64 bits segment rel. address.  */
+#define R_PARISC_PLTOFF14WR	115	/* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF14DR	116	/* PLT-rel. address, right 14 bits.  */
+#define R_PARISC_PLTOFF16F	117	/* 16 bits LT-rel. address.  */
+#define R_PARISC_PLTOFF16WF	118	/* 16 bits PLT-rel. address.  */
+#define R_PARISC_PLTOFF16DF	119	/* 16 bits PLT-rel. address.  */
+#define R_PARISC_LTOFF_FPTR64	120	/* 64 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR14WR	123	/* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR14DR	124	/* LT-rel. fct. ptr., right 14 bits. */
+#define R_PARISC_LTOFF_FPTR16F	125	/* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16WF	126	/* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LTOFF_FPTR16DF	127	/* 16 bits LT-rel. function ptr.  */
+#define R_PARISC_LORESERVE	128
+#define R_PARISC_COPY		128	/* Copy relocation.  */
+#define R_PARISC_IPLT		129	/* Dynamic reloc, imported PLT */
+#define R_PARISC_EPLT		130	/* Dynamic reloc, exported PLT */
+#define R_PARISC_TPREL32	153	/* 32 bits TP-rel. address.  */
+#define R_PARISC_TPREL21L	154	/* TP-rel. address, left 21 bits.  */
+#define R_PARISC_TPREL14R	158	/* TP-rel. address, right 14 bits.  */
+#define R_PARISC_LTOFF_TP21L	162	/* LT-TP-rel. address, left 21 bits. */
+#define R_PARISC_LTOFF_TP14R	166	/* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14F	167	/* 14 bits LT-TP-rel. address.  */
+#define R_PARISC_TPREL64	216	/* 64 bits TP-rel. address.  */
+#define R_PARISC_TPREL14WR	219	/* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL14DR	220	/* TP-rel. address, right 14 bits.  */
+#define R_PARISC_TPREL16F	221	/* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16WF	222	/* 16 bits TP-rel. address.  */
+#define R_PARISC_TPREL16DF	223	/* 16 bits TP-rel. address.  */
+#define R_PARISC_LTOFF_TP64	224	/* 64 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP14WR	227	/* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP14DR	228	/* LT-TP-rel. address, right 14 bits.*/
+#define R_PARISC_LTOFF_TP16F	229	/* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16WF	230	/* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_LTOFF_TP16DF	231	/* 16 bits LT-TP-rel. address.  */
+#define R_PARISC_GNU_VTENTRY	232
+#define R_PARISC_GNU_VTINHERIT	233
+#define R_PARISC_TLS_GD21L	234	/* GD 21-bit left.  */
+#define R_PARISC_TLS_GD14R	235	/* GD 14-bit right.  */
+#define R_PARISC_TLS_GDCALL	236	/* GD call to __t_g_a.  */
+#define R_PARISC_TLS_LDM21L	237	/* LD module 21-bit left.  */
+#define R_PARISC_TLS_LDM14R	238	/* LD module 14-bit right.  */
+#define R_PARISC_TLS_LDMCALL	239	/* LD module call to __t_g_a.  */
+#define R_PARISC_TLS_LDO21L	240	/* LD offset 21-bit left.  */
+#define R_PARISC_TLS_LDO14R	241	/* LD offset 14-bit right.  */
+#define R_PARISC_TLS_DTPMOD32	242	/* DTP module 32-bit.  */
+#define R_PARISC_TLS_DTPMOD64	243	/* DTP module 64-bit.  */
+#define R_PARISC_TLS_DTPOFF32	244	/* DTP offset 32-bit.  */
+#define R_PARISC_TLS_DTPOFF64	245	/* DTP offset 32-bit.  */
+#define R_PARISC_TLS_LE21L	R_PARISC_TPREL21L
+#define R_PARISC_TLS_LE14R	R_PARISC_TPREL14R
+#define R_PARISC_TLS_IE21L	R_PARISC_LTOFF_TP21L
+#define R_PARISC_TLS_IE14R	R_PARISC_LTOFF_TP14R
+#define R_PARISC_TLS_TPREL32	R_PARISC_TPREL32
+#define R_PARISC_TLS_TPREL64	R_PARISC_TPREL64
+#define R_PARISC_HIRESERVE	255
+
+/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PT_HP_TLS		(PT_LOOS + 0x0)
+#define PT_HP_CORE_NONE		(PT_LOOS + 0x1)
+#define PT_HP_CORE_VERSION	(PT_LOOS + 0x2)
+#define PT_HP_CORE_KERNEL	(PT_LOOS + 0x3)
+#define PT_HP_CORE_COMM		(PT_LOOS + 0x4)
+#define PT_HP_CORE_PROC		(PT_LOOS + 0x5)
+#define PT_HP_CORE_LOADABLE	(PT_LOOS + 0x6)
+#define PT_HP_CORE_STACK	(PT_LOOS + 0x7)
+#define PT_HP_CORE_SHM		(PT_LOOS + 0x8)
+#define PT_HP_CORE_MMF		(PT_LOOS + 0x9)
+#define PT_HP_PARALLEL		(PT_LOOS + 0x10)
+#define PT_HP_FASTBIND		(PT_LOOS + 0x11)
+#define PT_HP_OPT_ANNOT		(PT_LOOS + 0x12)
+#define PT_HP_HSL_ANNOT		(PT_LOOS + 0x13)
+#define PT_HP_STACK		(PT_LOOS + 0x14)
+
+#define PT_PARISC_ARCHEXT	0x70000000
+#define PT_PARISC_UNWIND	0x70000001
+
+/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr.  */
+
+#define PF_PARISC_SBP		0x08000000
+
+#define PF_HP_PAGE_SIZE		0x00100000
+#define PF_HP_FAR_SHARED	0x00200000
+#define PF_HP_NEAR_SHARED	0x00400000
+#define PF_HP_CODE		0x01000000
+#define PF_HP_MODIFY		0x02000000
+#define PF_HP_LAZYSWAP		0x04000000
+#define PF_HP_SBP		0x08000000
+
+
+/* Alpha specific definitions.  */
+
+/* Legal values for e_flags field of Elf64_Ehdr.  */
+
+#define EF_ALPHA_32BIT		1	/* All addresses must be < 2GB.  */
+#define EF_ALPHA_CANRELAX	2	/* Relocations for relaxing exist.  */
+
+/* Legal values for sh_type field of Elf64_Shdr.  */
+
+/* These two are primerily concerned with ECOFF debugging info.  */
+#define SHT_ALPHA_DEBUG		0x70000001
+#define SHT_ALPHA_REGINFO	0x70000002
+
+/* Legal values for sh_flags field of Elf64_Shdr.  */
+
+#define SHF_ALPHA_GPREL		0x10000000
+
+/* Legal values for st_other field of Elf64_Sym.  */
+#define STO_ALPHA_NOPV		0x80	/* No PV required.  */
+#define STO_ALPHA_STD_GPLOAD	0x88	/* PV only used for initial ldgp.  */
+
+/* Alpha relocs.  */
+
+#define R_ALPHA_NONE		0	/* No reloc */
+#define R_ALPHA_REFLONG		1	/* Direct 32 bit */
+#define R_ALPHA_REFQUAD		2	/* Direct 64 bit */
+#define R_ALPHA_GPREL32		3	/* GP relative 32 bit */
+#define R_ALPHA_LITERAL		4	/* GP relative 16 bit w/optimization */
+#define R_ALPHA_LITUSE		5	/* Optimization hint for LITERAL */
+#define R_ALPHA_GPDISP		6	/* Add displacement to GP */
+#define R_ALPHA_BRADDR		7	/* PC+4 relative 23 bit shifted */
+#define R_ALPHA_HINT		8	/* PC+4 relative 16 bit shifted */
+#define R_ALPHA_SREL16		9	/* PC relative 16 bit */
+#define R_ALPHA_SREL32		10	/* PC relative 32 bit */
+#define R_ALPHA_SREL64		11	/* PC relative 64 bit */
+#define R_ALPHA_GPRELHIGH	17	/* GP relative 32 bit, high 16 bits */
+#define R_ALPHA_GPRELLOW	18	/* GP relative 32 bit, low 16 bits */
+#define R_ALPHA_GPREL16		19	/* GP relative 16 bit */
+#define R_ALPHA_COPY		24	/* Copy symbol at runtime */
+#define R_ALPHA_GLOB_DAT	25	/* Create GOT entry */
+#define R_ALPHA_JMP_SLOT	26	/* Create PLT entry */
+#define R_ALPHA_RELATIVE	27	/* Adjust by program base */
+#define R_ALPHA_TLS_GD_HI	28
+#define R_ALPHA_TLSGD		29
+#define R_ALPHA_TLS_LDM		30
+#define R_ALPHA_DTPMOD64	31
+#define R_ALPHA_GOTDTPREL	32
+#define R_ALPHA_DTPREL64	33
+#define R_ALPHA_DTPRELHI	34
+#define R_ALPHA_DTPRELLO	35
+#define R_ALPHA_DTPREL16	36
+#define R_ALPHA_GOTTPREL	37
+#define R_ALPHA_TPREL64		38
+#define R_ALPHA_TPRELHI		39
+#define R_ALPHA_TPRELLO		40
+#define R_ALPHA_TPREL16		41
+/* Keep this the last entry.  */
+#define R_ALPHA_NUM		46
+
+/* Magic values of the LITUSE relocation addend.  */
+#define LITUSE_ALPHA_ADDR	0
+#define LITUSE_ALPHA_BASE	1
+#define LITUSE_ALPHA_BYTOFF	2
+#define LITUSE_ALPHA_JSR	3
+#define LITUSE_ALPHA_TLS_GD	4
+#define LITUSE_ALPHA_TLS_LDM	5
+
+/* Legal values for d_tag of Elf64_Dyn.  */
+#define DT_ALPHA_PLTRO		(DT_LOPROC + 0)
+#define DT_ALPHA_NUM		1
+
+/* PowerPC specific declarations */
+
+/* Values for Elf32/64_Ehdr.e_flags.  */
+#define EF_PPC_EMB		0x80000000	/* PowerPC embedded flag */
+
+/* Cygnus local bits below */
+#define EF_PPC_RELOCATABLE	0x00010000	/* PowerPC -mrelocatable flag*/
+#define EF_PPC_RELOCATABLE_LIB	0x00008000	/* PowerPC -mrelocatable-lib
+						   flag */
+
+/* PowerPC relocations defined by the ABIs */
+#define R_PPC_NONE		0
+#define R_PPC_ADDR32		1	/* 32bit absolute address */
+#define R_PPC_ADDR24		2	/* 26bit address, 2 bits ignored.  */
+#define R_PPC_ADDR16		3	/* 16bit absolute address */
+#define R_PPC_ADDR16_LO		4	/* lower 16bit of absolute address */
+#define R_PPC_ADDR16_HI		5	/* high 16bit of absolute address */
+#define R_PPC_ADDR16_HA		6	/* adjusted high 16bit */
+#define R_PPC_ADDR14		7	/* 16bit address, 2 bits ignored */
+#define R_PPC_ADDR14_BRTAKEN	8
+#define R_PPC_ADDR14_BRNTAKEN	9
+#define R_PPC_REL24		10	/* PC relative 26 bit */
+#define R_PPC_REL14		11	/* PC relative 16 bit */
+#define R_PPC_REL14_BRTAKEN	12
+#define R_PPC_REL14_BRNTAKEN	13
+#define R_PPC_GOT16		14
+#define R_PPC_GOT16_LO		15
+#define R_PPC_GOT16_HI		16
+#define R_PPC_GOT16_HA		17
+#define R_PPC_PLTREL24		18
+#define R_PPC_COPY		19
+#define R_PPC_GLOB_DAT		20
+#define R_PPC_JMP_SLOT		21
+#define R_PPC_RELATIVE		22
+#define R_PPC_LOCAL24PC		23
+#define R_PPC_UADDR32		24
+#define R_PPC_UADDR16		25
+#define R_PPC_REL32		26
+#define R_PPC_PLT32		27
+#define R_PPC_PLTREL32		28
+#define R_PPC_PLT16_LO		29
+#define R_PPC_PLT16_HI		30
+#define R_PPC_PLT16_HA		31
+#define R_PPC_SDAREL16		32
+#define R_PPC_SECTOFF		33
+#define R_PPC_SECTOFF_LO	34
+#define R_PPC_SECTOFF_HI	35
+#define R_PPC_SECTOFF_HA	36
+
+/* PowerPC relocations defined for the TLS access ABI.  */
+#define R_PPC_TLS		67 /* none	(sym+add)@tls */
+#define R_PPC_DTPMOD32		68 /* word32	(sym+add)@dtpmod */
+#define R_PPC_TPREL16		69 /* half16*	(sym+add)@tprel */
+#define R_PPC_TPREL16_LO	70 /* half16	(sym+add)@tprel@l */
+#define R_PPC_TPREL16_HI	71 /* half16	(sym+add)@tprel@h */
+#define R_PPC_TPREL16_HA	72 /* half16	(sym+add)@tprel@ha */
+#define R_PPC_TPREL32		73 /* word32	(sym+add)@tprel */
+#define R_PPC_DTPREL16		74 /* half16*	(sym+add)@dtprel */
+#define R_PPC_DTPREL16_LO	75 /* half16	(sym+add)@dtprel@l */
+#define R_PPC_DTPREL16_HI	76 /* half16	(sym+add)@dtprel@h */
+#define R_PPC_DTPREL16_HA	77 /* half16	(sym+add)@dtprel@ha */
+#define R_PPC_DTPREL32		78 /* word32	(sym+add)@dtprel */
+#define R_PPC_GOT_TLSGD16	79 /* half16*	(sym+add)@got@tlsgd */
+#define R_PPC_GOT_TLSGD16_LO	80 /* half16	(sym+add)@got@tlsgd@l */
+#define R_PPC_GOT_TLSGD16_HI	81 /* half16	(sym+add)@got@tlsgd@h */
+#define R_PPC_GOT_TLSGD16_HA	82 /* half16	(sym+add)@got@tlsgd@ha */
+#define R_PPC_GOT_TLSLD16	83 /* half16*	(sym+add)@got@tlsld */
+#define R_PPC_GOT_TLSLD16_LO	84 /* half16	(sym+add)@got@tlsld@l */
+#define R_PPC_GOT_TLSLD16_HI	85 /* half16	(sym+add)@got@tlsld@h */
+#define R_PPC_GOT_TLSLD16_HA	86 /* half16	(sym+add)@got@tlsld@ha */
+#define R_PPC_GOT_TPREL16	87 /* half16*	(sym+add)@got@tprel */
+#define R_PPC_GOT_TPREL16_LO	88 /* half16	(sym+add)@got@tprel@l */
+#define R_PPC_GOT_TPREL16_HI	89 /* half16	(sym+add)@got@tprel@h */
+#define R_PPC_GOT_TPREL16_HA	90 /* half16	(sym+add)@got@tprel@ha */
+#define R_PPC_GOT_DTPREL16	91 /* half16*	(sym+add)@got@dtprel */
+#define R_PPC_GOT_DTPREL16_LO	92 /* half16*	(sym+add)@got@dtprel@l */
+#define R_PPC_GOT_DTPREL16_HI	93 /* half16*	(sym+add)@got@dtprel@h */
+#define R_PPC_GOT_DTPREL16_HA	94 /* half16*	(sym+add)@got@dtprel@ha */
+#define R_PPC_TLSGD		95 /* none	(sym+add)@tlsgd */
+#define R_PPC_TLSLD		96 /* none	(sym+add)@tlsld */
+
+/* The remaining relocs are from the Embedded ELF ABI, and are not
+   in the SVR4 ELF ABI.  */
+#define R_PPC_EMB_NADDR32	101
+#define R_PPC_EMB_NADDR16	102
+#define R_PPC_EMB_NADDR16_LO	103
+#define R_PPC_EMB_NADDR16_HI	104
+#define R_PPC_EMB_NADDR16_HA	105
+#define R_PPC_EMB_SDAI16	106
+#define R_PPC_EMB_SDA2I16	107
+#define R_PPC_EMB_SDA2REL	108
+#define R_PPC_EMB_SDA21		109	/* 16 bit offset in SDA */
+#define R_PPC_EMB_MRKREF	110
+#define R_PPC_EMB_RELSEC16	111
+#define R_PPC_EMB_RELST_LO	112
+#define R_PPC_EMB_RELST_HI	113
+#define R_PPC_EMB_RELST_HA	114
+#define R_PPC_EMB_BIT_FLD	115
+#define R_PPC_EMB_RELSDA	116	/* 16 bit relative offset in SDA */
+
+/* Diab tool relocations.  */
+#define R_PPC_DIAB_SDA21_LO	180	/* like EMB_SDA21, but lower 16 bit */
+#define R_PPC_DIAB_SDA21_HI	181	/* like EMB_SDA21, but high 16 bit */
+#define R_PPC_DIAB_SDA21_HA	182	/* like EMB_SDA21, adjusted high 16 */
+#define R_PPC_DIAB_RELSDA_LO	183	/* like EMB_RELSDA, but lower 16 bit */
+#define R_PPC_DIAB_RELSDA_HI	184	/* like EMB_RELSDA, but high 16 bit */
+#define R_PPC_DIAB_RELSDA_HA	185	/* like EMB_RELSDA, adjusted high 16 */
+
+/* GNU extension to support local ifunc.  */
+#define R_PPC_IRELATIVE		248
+
+/* GNU relocs used in PIC code sequences.  */
+#define R_PPC_REL16		249	/* half16   (sym+add-.) */
+#define R_PPC_REL16_LO		250	/* half16   (sym+add-.)@l */
+#define R_PPC_REL16_HI		251	/* half16   (sym+add-.)@h */
+#define R_PPC_REL16_HA		252	/* half16   (sym+add-.)@ha */
+
+/* This is a phony reloc to handle any old fashioned TOC16 references
+   that may still be in object files.  */
+#define R_PPC_TOC16		255
+
+/* PowerPC specific values for the Dyn d_tag field.  */
+#define DT_PPC_GOT		(DT_LOPROC + 0)
+#define DT_PPC_OPT		(DT_LOPROC + 1)
+#define DT_PPC_NUM		2
+
+/* PowerPC specific values for the DT_PPC_OPT Dyn entry.  */
+#define PPC_OPT_TLS		1
+
+/* PowerPC64 relocations defined by the ABIs */
+#define R_PPC64_NONE		R_PPC_NONE
+#define R_PPC64_ADDR32		R_PPC_ADDR32 /* 32bit absolute address */
+#define R_PPC64_ADDR24		R_PPC_ADDR24 /* 26bit address, word aligned */
+#define R_PPC64_ADDR16		R_PPC_ADDR16 /* 16bit absolute address */
+#define R_PPC64_ADDR16_LO	R_PPC_ADDR16_LO	/* lower 16bits of address */
+#define R_PPC64_ADDR16_HI	R_PPC_ADDR16_HI	/* high 16bits of address. */
+#define R_PPC64_ADDR16_HA	R_PPC_ADDR16_HA /* adjusted high 16bits.  */
+#define R_PPC64_ADDR14		R_PPC_ADDR14 /* 16bit address, word aligned */
+#define R_PPC64_ADDR14_BRTAKEN	R_PPC_ADDR14_BRTAKEN
+#define R_PPC64_ADDR14_BRNTAKEN	R_PPC_ADDR14_BRNTAKEN
+#define R_PPC64_REL24		R_PPC_REL24 /* PC-rel. 26 bit, word aligned */
+#define R_PPC64_REL14		R_PPC_REL14 /* PC relative 16 bit */
+#define R_PPC64_REL14_BRTAKEN	R_PPC_REL14_BRTAKEN
+#define R_PPC64_REL14_BRNTAKEN	R_PPC_REL14_BRNTAKEN
+#define R_PPC64_GOT16		R_PPC_GOT16
+#define R_PPC64_GOT16_LO	R_PPC_GOT16_LO
+#define R_PPC64_GOT16_HI	R_PPC_GOT16_HI
+#define R_PPC64_GOT16_HA	R_PPC_GOT16_HA
+
+#define R_PPC64_COPY		R_PPC_COPY
+#define R_PPC64_GLOB_DAT	R_PPC_GLOB_DAT
+#define R_PPC64_JMP_SLOT	R_PPC_JMP_SLOT
+#define R_PPC64_RELATIVE	R_PPC_RELATIVE
+
+#define R_PPC64_UADDR32		R_PPC_UADDR32
+#define R_PPC64_UADDR16		R_PPC_UADDR16
+#define R_PPC64_REL32		R_PPC_REL32
+#define R_PPC64_PLT32		R_PPC_PLT32
+#define R_PPC64_PLTREL32	R_PPC_PLTREL32
+#define R_PPC64_PLT16_LO	R_PPC_PLT16_LO
+#define R_PPC64_PLT16_HI	R_PPC_PLT16_HI
+#define R_PPC64_PLT16_HA	R_PPC_PLT16_HA
+
+#define R_PPC64_SECTOFF		R_PPC_SECTOFF
+#define R_PPC64_SECTOFF_LO	R_PPC_SECTOFF_LO
+#define R_PPC64_SECTOFF_HI	R_PPC_SECTOFF_HI
+#define R_PPC64_SECTOFF_HA	R_PPC_SECTOFF_HA
+#define R_PPC64_ADDR30		37 /* word30 (S + A - P) >> 2 */
+#define R_PPC64_ADDR64		38 /* doubleword64 S + A */
+#define R_PPC64_ADDR16_HIGHER	39 /* half16 #higher(S + A) */
+#define R_PPC64_ADDR16_HIGHERA	40 /* half16 #highera(S + A) */
+#define R_PPC64_ADDR16_HIGHEST	41 /* half16 #highest(S + A) */
+#define R_PPC64_ADDR16_HIGHESTA	42 /* half16 #highesta(S + A) */
+#define R_PPC64_UADDR64		43 /* doubleword64 S + A */
+#define R_PPC64_REL64		44 /* doubleword64 S + A - P */
+#define R_PPC64_PLT64		45 /* doubleword64 L + A */
+#define R_PPC64_PLTREL64	46 /* doubleword64 L + A - P */
+#define R_PPC64_TOC16		47 /* half16* S + A - .TOC */
+#define R_PPC64_TOC16_LO	48 /* half16 #lo(S + A - .TOC.) */
+#define R_PPC64_TOC16_HI	49 /* half16 #hi(S + A - .TOC.) */
+#define R_PPC64_TOC16_HA	50 /* half16 #ha(S + A - .TOC.) */
+#define R_PPC64_TOC		51 /* doubleword64 .TOC */
+#define R_PPC64_PLTGOT16	52 /* half16* M + A */
+#define R_PPC64_PLTGOT16_LO	53 /* half16 #lo(M + A) */
+#define R_PPC64_PLTGOT16_HI	54 /* half16 #hi(M + A) */
+#define R_PPC64_PLTGOT16_HA	55 /* half16 #ha(M + A) */
+
+#define R_PPC64_ADDR16_DS	56 /* half16ds* (S + A) >> 2 */
+#define R_PPC64_ADDR16_LO_DS	57 /* half16ds  #lo(S + A) >> 2 */
+#define R_PPC64_GOT16_DS	58 /* half16ds* (G + A) >> 2 */
+#define R_PPC64_GOT16_LO_DS	59 /* half16ds  #lo(G + A) >> 2 */
+#define R_PPC64_PLT16_LO_DS	60 /* half16ds  #lo(L + A) >> 2 */
+#define R_PPC64_SECTOFF_DS	61 /* half16ds* (R + A) >> 2 */
+#define R_PPC64_SECTOFF_LO_DS	62 /* half16ds  #lo(R + A) >> 2 */
+#define R_PPC64_TOC16_DS	63 /* half16ds* (S + A - .TOC.) >> 2 */
+#define R_PPC64_TOC16_LO_DS	64 /* half16ds  #lo(S + A - .TOC.) >> 2 */
+#define R_PPC64_PLTGOT16_DS	65 /* half16ds* (M + A) >> 2 */
+#define R_PPC64_PLTGOT16_LO_DS	66 /* half16ds  #lo(M + A) >> 2 */
+
+/* PowerPC64 relocations defined for the TLS access ABI.  */
+#define R_PPC64_TLS		67 /* none	(sym+add)@tls */
+#define R_PPC64_DTPMOD64	68 /* doubleword64 (sym+add)@dtpmod */
+#define R_PPC64_TPREL16		69 /* half16*	(sym+add)@tprel */
+#define R_PPC64_TPREL16_LO	70 /* half16	(sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HI	71 /* half16	(sym+add)@tprel@h */
+#define R_PPC64_TPREL16_HA	72 /* half16	(sym+add)@tprel@ha */
+#define R_PPC64_TPREL64		73 /* doubleword64 (sym+add)@tprel */
+#define R_PPC64_DTPREL16	74 /* half16*	(sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO	75 /* half16	(sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HI	76 /* half16	(sym+add)@dtprel@h */
+#define R_PPC64_DTPREL16_HA	77 /* half16	(sym+add)@dtprel@ha */
+#define R_PPC64_DTPREL64	78 /* doubleword64 (sym+add)@dtprel */
+#define R_PPC64_GOT_TLSGD16	79 /* half16*	(sym+add)@got@tlsgd */
+#define R_PPC64_GOT_TLSGD16_LO	80 /* half16	(sym+add)@got@tlsgd@l */
+#define R_PPC64_GOT_TLSGD16_HI	81 /* half16	(sym+add)@got@tlsgd@h */
+#define R_PPC64_GOT_TLSGD16_HA	82 /* half16	(sym+add)@got@tlsgd@ha */
+#define R_PPC64_GOT_TLSLD16	83 /* half16*	(sym+add)@got@tlsld */
+#define R_PPC64_GOT_TLSLD16_LO	84 /* half16	(sym+add)@got@tlsld@l */
+#define R_PPC64_GOT_TLSLD16_HI	85 /* half16	(sym+add)@got@tlsld@h */
+#define R_PPC64_GOT_TLSLD16_HA	86 /* half16	(sym+add)@got@tlsld@ha */
+#define R_PPC64_GOT_TPREL16_DS	87 /* half16ds*	(sym+add)@got@tprel */
+#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */
+#define R_PPC64_GOT_TPREL16_HI	89 /* half16	(sym+add)@got@tprel@h */
+#define R_PPC64_GOT_TPREL16_HA	90 /* half16	(sym+add)@got@tprel@ha */
+#define R_PPC64_GOT_DTPREL16_DS	91 /* half16ds*	(sym+add)@got@dtprel */
+#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */
+#define R_PPC64_GOT_DTPREL16_HI	93 /* half16	(sym+add)@got@dtprel@h */
+#define R_PPC64_GOT_DTPREL16_HA	94 /* half16	(sym+add)@got@dtprel@ha */
+#define R_PPC64_TPREL16_DS	95 /* half16ds*	(sym+add)@tprel */
+#define R_PPC64_TPREL16_LO_DS	96 /* half16ds	(sym+add)@tprel@l */
+#define R_PPC64_TPREL16_HIGHER	97 /* half16	(sym+add)@tprel@higher */
+#define R_PPC64_TPREL16_HIGHERA	98 /* half16	(sym+add)@tprel@highera */
+#define R_PPC64_TPREL16_HIGHEST	99 /* half16	(sym+add)@tprel@highest */
+#define R_PPC64_TPREL16_HIGHESTA 100 /* half16	(sym+add)@tprel@highesta */
+#define R_PPC64_DTPREL16_DS	101 /* half16ds* (sym+add)@dtprel */
+#define R_PPC64_DTPREL16_LO_DS	102 /* half16ds	(sym+add)@dtprel@l */
+#define R_PPC64_DTPREL16_HIGHER	103 /* half16	(sym+add)@dtprel@higher */
+#define R_PPC64_DTPREL16_HIGHERA 104 /* half16	(sym+add)@dtprel@highera */
+#define R_PPC64_DTPREL16_HIGHEST 105 /* half16	(sym+add)@dtprel@highest */
+#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16	(sym+add)@dtprel@highesta */
+#define R_PPC64_TLSGD		107 /* none	(sym+add)@tlsgd */
+#define R_PPC64_TLSLD		108 /* none	(sym+add)@tlsld */
+#define R_PPC64_TOCSAVE		109 /* none */
+
+/* Added when HA and HI relocs were changed to report overflows.  */
+#define R_PPC64_ADDR16_HIGH	110
+#define R_PPC64_ADDR16_HIGHA	111
+#define R_PPC64_TPREL16_HIGH	112
+#define R_PPC64_TPREL16_HIGHA	113
+#define R_PPC64_DTPREL16_HIGH	114
+#define R_PPC64_DTPREL16_HIGHA	115
+
+/* GNU extension to support local ifunc.  */
+#define R_PPC64_JMP_IREL	247
+#define R_PPC64_IRELATIVE	248
+#define R_PPC64_REL16		249	/* half16   (sym+add-.) */
+#define R_PPC64_REL16_LO	250	/* half16   (sym+add-.)@l */
+#define R_PPC64_REL16_HI	251	/* half16   (sym+add-.)@h */
+#define R_PPC64_REL16_HA	252	/* half16   (sym+add-.)@ha */
+
+/* e_flags bits specifying ABI.
+   1 for original function descriptor using ABI,
+   2 for revised ABI without function descriptors,
+   0 for unspecified or not using any features affected by the differences.  */
+#define EF_PPC64_ABI	3
+
+/* PowerPC64 specific values for the Dyn d_tag field.  */
+#define DT_PPC64_GLINK  (DT_LOPROC + 0)
+#define DT_PPC64_OPD	(DT_LOPROC + 1)
+#define DT_PPC64_OPDSZ	(DT_LOPROC + 2)
+#define DT_PPC64_OPT	(DT_LOPROC + 3)
+#define DT_PPC64_NUM    4
+
+/* PowerPC64 specific bits in the DT_PPC64_OPT Dyn entry.  */
+#define PPC64_OPT_TLS		1
+#define PPC64_OPT_MULTI_TOC	2
+#define PPC64_OPT_LOCALENTRY	4
+
+/* PowerPC64 specific values for the Elf64_Sym st_other field.  */
+#define STO_PPC64_LOCAL_BIT	5
+#define STO_PPC64_LOCAL_MASK	(7 << STO_PPC64_LOCAL_BIT)
+#define PPC64_LOCAL_ENTRY_OFFSET(other)				\
+ (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2)
+
+
+/* ARM specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_ARM_RELEXEC		0x01
+#define EF_ARM_HASENTRY		0x02
+#define EF_ARM_INTERWORK	0x04
+#define EF_ARM_APCS_26		0x08
+#define EF_ARM_APCS_FLOAT	0x10
+#define EF_ARM_PIC		0x20
+#define EF_ARM_ALIGN8		0x40 /* 8-bit structure alignment is in use */
+#define EF_ARM_NEW_ABI		0x80
+#define EF_ARM_OLD_ABI		0x100
+#define EF_ARM_SOFT_FLOAT	0x200
+#define EF_ARM_VFP_FLOAT	0x400
+#define EF_ARM_MAVERICK_FLOAT	0x800
+
+#define EF_ARM_ABI_FLOAT_SOFT	0x200   /* NB conflicts with EF_ARM_SOFT_FLOAT */
+#define EF_ARM_ABI_FLOAT_HARD	0x400   /* NB conflicts with EF_ARM_VFP_FLOAT */
+
+
+/* Other constants defined in the ARM ELF spec. version B-01.  */
+/* NB. These conflict with values defined above.  */
+#define EF_ARM_SYMSARESORTED	0x04
+#define EF_ARM_DYNSYMSUSESEGIDX	0x08
+#define EF_ARM_MAPSYMSFIRST	0x10
+#define EF_ARM_EABIMASK		0XFF000000
+
+/* Constants defined in AAELF.  */
+#define EF_ARM_BE8	    0x00800000
+#define EF_ARM_LE8	    0x00400000
+
+#define EF_ARM_EABI_VERSION(flags)	((flags) & EF_ARM_EABIMASK)
+#define EF_ARM_EABI_UNKNOWN	0x00000000
+#define EF_ARM_EABI_VER1	0x01000000
+#define EF_ARM_EABI_VER2	0x02000000
+#define EF_ARM_EABI_VER3	0x03000000
+#define EF_ARM_EABI_VER4	0x04000000
+#define EF_ARM_EABI_VER5	0x05000000
+
+/* Additional symbol types for Thumb.  */
+#define STT_ARM_TFUNC		STT_LOPROC /* A Thumb function.  */
+#define STT_ARM_16BIT		STT_HIPROC /* A Thumb label.  */
+
+/* ARM-specific values for sh_flags */
+#define SHF_ARM_ENTRYSECT	0x10000000 /* Section contains an entry point */
+#define SHF_ARM_COMDEF		0x80000000 /* Section may be multiply defined
+					      in the input to a link step.  */
+
+/* ARM-specific program header flags */
+#define PF_ARM_SB		0x10000000 /* Segment contains the location
+					      addressed by the static base. */
+#define PF_ARM_PI		0x20000000 /* Position-independent segment.  */
+#define PF_ARM_ABS		0x40000000 /* Absolute segment.  */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_ARM_EXIDX		(PT_LOPROC + 1)	/* ARM unwind segment.  */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_ARM_EXIDX		(SHT_LOPROC + 1) /* ARM unwind section.  */
+#define SHT_ARM_PREEMPTMAP	(SHT_LOPROC + 2) /* Preemption details.  */
+#define SHT_ARM_ATTRIBUTES	(SHT_LOPROC + 3) /* ARM attributes section.  */
+
+
+/* AArch64 relocs.  */
+
+#define R_AARCH64_NONE            0	/* No relocation.  */
+
+/* ILP32 AArch64 relocs.  */
+#define R_AARCH64_P32_ABS32		  1	/* Direct 32 bit.  */
+#define R_AARCH64_P32_COPY		180	/* Copy symbol at runtime.  */
+#define R_AARCH64_P32_GLOB_DAT		181	/* Create GOT entry.  */
+#define R_AARCH64_P32_JUMP_SLOT		182	/* Create PLT entry.  */
+#define R_AARCH64_P32_RELATIVE		183	/* Adjust by program base.  */
+#define R_AARCH64_P32_TLS_DTPMOD	184	/* Module number, 32 bit.  */
+#define R_AARCH64_P32_TLS_DTPREL	185	/* Module-relative offset, 32 bit.  */
+#define R_AARCH64_P32_TLS_TPREL		186	/* TP-relative offset, 32 bit.  */
+#define R_AARCH64_P32_TLSDESC		187	/* TLS Descriptor.  */
+#define R_AARCH64_P32_IRELATIVE		188	/* STT_GNU_IFUNC relocation. */
+
+/* LP64 AArch64 relocs.  */
+#define R_AARCH64_ABS64         257	/* Direct 64 bit. */
+#define R_AARCH64_ABS32         258	/* Direct 32 bit.  */
+#define R_AARCH64_ABS16		259	/* Direct 16-bit.  */
+#define R_AARCH64_PREL64	260	/* PC-relative 64-bit.	*/
+#define R_AARCH64_PREL32	261	/* PC-relative 32-bit.	*/
+#define R_AARCH64_PREL16	262	/* PC-relative 16-bit.	*/
+#define R_AARCH64_MOVW_UABS_G0	263	/* Dir. MOVZ imm. from bits 15:0.  */
+#define R_AARCH64_MOVW_UABS_G0_NC 264	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_UABS_G1	265	/* Dir. MOVZ imm. from bits 31:16.  */
+#define R_AARCH64_MOVW_UABS_G1_NC 266	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_UABS_G2	267	/* Dir. MOVZ imm. from bits 47:32.  */
+#define R_AARCH64_MOVW_UABS_G2_NC 268	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_UABS_G3	269	/* Dir. MOV{K,Z} imm. from 63:48.  */
+#define R_AARCH64_MOVW_SABS_G0	270	/* Dir. MOV{N,Z} imm. from 15:0.  */
+#define R_AARCH64_MOVW_SABS_G1	271	/* Dir. MOV{N,Z} imm. from 31:16.  */
+#define R_AARCH64_MOVW_SABS_G2	272	/* Dir. MOV{N,Z} imm. from 47:32.  */
+#define R_AARCH64_LD_PREL_LO19	273	/* PC-rel. LD imm. from bits 20:2.  */
+#define R_AARCH64_ADR_PREL_LO21	274	/* PC-rel. ADR imm. from bits 20:0.  */
+#define R_AARCH64_ADR_PREL_PG_HI21 275	/* Page-rel. ADRP imm. from 32:12.  */
+#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 /* Likewise; no overflow check.  */
+#define R_AARCH64_ADD_ABS_LO12_NC 277	/* Dir. ADD imm. from bits 11:0.  */
+#define R_AARCH64_LDST8_ABS_LO12_NC 278	/* Likewise for LD/ST; no check. */
+#define R_AARCH64_TSTBR14	279	/* PC-rel. TBZ/TBNZ imm. from 15:2.  */
+#define R_AARCH64_CONDBR19	280	/* PC-rel. cond. br. imm. from 20:2. */
+#define R_AARCH64_JUMP26	282	/* PC-rel. B imm. from bits 27:2.  */
+#define R_AARCH64_CALL26	283	/* Likewise for CALL.  */
+#define R_AARCH64_LDST16_ABS_LO12_NC 284 /* Dir. ADD imm. from bits 11:1.  */
+#define R_AARCH64_LDST32_ABS_LO12_NC 285 /* Likewise for bits 11:2.  */
+#define R_AARCH64_LDST64_ABS_LO12_NC 286 /* Likewise for bits 11:3.  */
+#define R_AARCH64_MOVW_PREL_G0	287	/* PC-rel. MOV{N,Z} imm. from 15:0.  */
+#define R_AARCH64_MOVW_PREL_G0_NC 288	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_PREL_G1	289	/* PC-rel. MOV{N,Z} imm. from 31:16. */
+#define R_AARCH64_MOVW_PREL_G1_NC 290	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_PREL_G2	291	/* PC-rel. MOV{N,Z} imm. from 47:32. */
+#define R_AARCH64_MOVW_PREL_G2_NC 292	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_PREL_G3	293	/* PC-rel. MOV{N,Z} imm. from 63:48. */
+#define R_AARCH64_LDST128_ABS_LO12_NC 299 /* Dir. ADD imm. from bits 11:4.  */
+#define R_AARCH64_MOVW_GOTOFF_G0 300	/* GOT-rel. off. MOV{N,Z} imm. 15:0. */
+#define R_AARCH64_MOVW_GOTOFF_G0_NC 301	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_GOTOFF_G1 302	/* GOT-rel. o. MOV{N,Z} imm. 31:16.  */
+#define R_AARCH64_MOVW_GOTOFF_G1_NC 303	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_GOTOFF_G2 304	/* GOT-rel. o. MOV{N,Z} imm. 47:32.  */
+#define R_AARCH64_MOVW_GOTOFF_G2_NC 305	/* Likewise for MOVK; no check.  */
+#define R_AARCH64_MOVW_GOTOFF_G3 306	/* GOT-rel. o. MOV{N,Z} imm. 63:48.  */
+#define R_AARCH64_GOTREL64	307	/* GOT-relative 64-bit.  */
+#define R_AARCH64_GOTREL32	308	/* GOT-relative 32-bit.  */
+#define R_AARCH64_GOT_LD_PREL19	309	/* PC-rel. GOT off. load imm. 20:2.  */
+#define R_AARCH64_LD64_GOTOFF_LO15 310	/* GOT-rel. off. LD/ST imm. 14:3.  */
+#define R_AARCH64_ADR_GOT_PAGE	311	/* P-page-rel. GOT off. ADRP 32:12.  */
+#define R_AARCH64_LD64_GOT_LO12_NC 312	/* Dir. GOT off. LD/ST imm. 11:3.  */
+#define R_AARCH64_LD64_GOTPAGE_LO15 313	/* GOT-page-rel. GOT off. LD/ST 14:3 */
+#define R_AARCH64_TLSGD_ADR_PREL21 512	/* PC-relative ADR imm. 20:0.  */
+#define R_AARCH64_TLSGD_ADR_PAGE21 513	/* page-rel. ADRP imm. 32:12.  */
+#define R_AARCH64_TLSGD_ADD_LO12_NC 514	/* direct ADD imm. from 11:0.  */
+#define R_AARCH64_TLSGD_MOVW_G1	515	/* GOT-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSGD_MOVW_G0_NC 516	/* GOT-rel. MOVK imm. 15:0.  */
+#define R_AARCH64_TLSLD_ADR_PREL21 517	/* Like 512; local dynamic model.  */
+#define R_AARCH64_TLSLD_ADR_PAGE21 518	/* Like 513; local dynamic model.  */
+#define R_AARCH64_TLSLD_ADD_LO12_NC 519	/* Like 514; local dynamic model.  */
+#define R_AARCH64_TLSLD_MOVW_G1	520	/* Like 515; local dynamic model.  */
+#define R_AARCH64_TLSLD_MOVW_G0_NC 521	/* Like 516; local dynamic model.  */
+#define R_AARCH64_TLSLD_LD_PREL19 522	/* TLS PC-rel. load imm. 20:2.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G2 523 /* TLS DTP-rel. MOV{N,Z} 47:32.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1 524 /* TLS DTP-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G1_NC 525 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0 526 /* TLS DTP-rel. MOV{N,Z} 15:0.  */
+#define R_AARCH64_TLSLD_MOVW_DTPREL_G0_NC 527 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLD_ADD_DTPREL_HI12 528 /* DTP-rel. ADD imm. from 23:12. */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12 529 /* DTP-rel. ADD imm. from 11:0.  */
+#define R_AARCH64_TLSLD_ADD_DTPREL_LO12_NC 530 /* Likewise; no ovfl. check.  */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12 531 /* DTP-rel. LD/ST imm. 11:0.  */
+#define R_AARCH64_TLSLD_LDST8_DTPREL_LO12_NC 532 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12 533 /* DTP-rel. LD/ST imm. 11:1.  */
+#define R_AARCH64_TLSLD_LDST16_DTPREL_LO12_NC 534 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12 535 /* DTP-rel. LD/ST imm. 11:2.  */
+#define R_AARCH64_TLSLD_LDST32_DTPREL_LO12_NC 536 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12 537 /* DTP-rel. LD/ST imm. 11:3.  */
+#define R_AARCH64_TLSLD_LDST64_DTPREL_LO12_NC 538 /* Likewise; no check.  */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G1 539 /* GOT-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSIE_MOVW_GOTTPREL_G0_NC 540 /* GOT-rel. MOVK 15:0.  */
+#define R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21 541 /* Page-rel. ADRP 32:12.  */
+#define R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC 542 /* Direct LD off. 11:3.  */
+#define R_AARCH64_TLSIE_LD_GOTTPREL_PREL19 543 /* PC-rel. load imm. 20:2.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G2 544 /* TLS TP-rel. MOV{N,Z} 47:32.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1 545 /* TLS TP-rel. MOV{N,Z} 31:16.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G1_NC 546 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0 547 /* TLS TP-rel. MOV{N,Z} 15:0.  */
+#define R_AARCH64_TLSLE_MOVW_TPREL_G0_NC 548 /* Likewise; MOVK; no check.  */
+#define R_AARCH64_TLSLE_ADD_TPREL_HI12 549 /* TP-rel. ADD imm. 23:12.  */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12 550 /* TP-rel. ADD imm. 11:0.  */
+#define R_AARCH64_TLSLE_ADD_TPREL_LO12_NC 551 /* Likewise; no ovfl. check.  */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12 552 /* TP-rel. LD/ST off. 11:0.  */
+#define R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC 553 /* Likewise; no ovfl. check. */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12 554 /* TP-rel. LD/ST off. 11:1.  */
+#define R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC 555 /* Likewise; no check.  */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12 556 /* TP-rel. LD/ST off. 11:2.  */
+#define R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC 557 /* Likewise; no check.  */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12 558 /* TP-rel. LD/ST off. 11:3.  */
+#define R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC 559 /* Likewise; no check.  */
+#define R_AARCH64_TLSDESC_LD_PREL19 560	/* PC-rel. load immediate 20:2.  */
+#define R_AARCH64_TLSDESC_ADR_PREL21 561 /* PC-rel. ADR immediate 20:0.  */
+#define R_AARCH64_TLSDESC_ADR_PAGE21 562 /* Page-rel. ADRP imm. 32:12.  */
+#define R_AARCH64_TLSDESC_LD64_LO12 563	/* Direct LD off. from 11:3.  */
+#define R_AARCH64_TLSDESC_ADD_LO12 564	/* Direct ADD imm. from 11:0.  */
+#define R_AARCH64_TLSDESC_OFF_G1 565	/* GOT-rel. MOV{N,Z} imm. 31:16.  */
+#define R_AARCH64_TLSDESC_OFF_G0_NC 566	/* GOT-rel. MOVK imm. 15:0; no ck.  */
+#define R_AARCH64_TLSDESC_LDR	567	/* Relax LDR.  */
+#define R_AARCH64_TLSDESC_ADD	568	/* Relax ADD.  */
+#define R_AARCH64_TLSDESC_CALL	569	/* Relax BLR.  */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12 570 /* TP-rel. LD/ST off. 11:4.  */
+#define R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC 571 /* Likewise; no check.  */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12 572 /* DTP-rel. LD/ST imm. 11:4. */
+#define R_AARCH64_TLSLD_LDST128_DTPREL_LO12_NC 573 /* Likewise; no check.  */
+#define R_AARCH64_COPY         1024	/* Copy symbol at runtime.  */
+#define R_AARCH64_GLOB_DAT     1025	/* Create GOT entry.  */
+#define R_AARCH64_JUMP_SLOT    1026	/* Create PLT entry.  */
+#define R_AARCH64_RELATIVE     1027	/* Adjust by program base.  */
+#define R_AARCH64_TLS_DTPMOD   1028	/* Module number, 64 bit.  */
+#define R_AARCH64_TLS_DTPREL   1029	/* Module-relative offset, 64 bit.  */
+#define R_AARCH64_TLS_TPREL    1030	/* TP-relative offset, 64 bit.  */
+#define R_AARCH64_TLSDESC      1031	/* TLS Descriptor.  */
+#define R_AARCH64_IRELATIVE	1032	/* STT_GNU_IFUNC relocation.  */
+
+/* MTE memory tag segment type.  */
+#define PT_AARCH64_MEMTAG_MTE	(PT_LOPROC + 2)
+
+/* AArch64 specific values for the Dyn d_tag field.  */
+#define DT_AARCH64_BTI_PLT	(DT_LOPROC + 1)
+#define DT_AARCH64_PAC_PLT	(DT_LOPROC + 3)
+#define DT_AARCH64_VARIANT_PCS	(DT_LOPROC + 5)
+#define DT_AARCH64_NUM		6
+
+/* AArch64 specific values for the st_other field.  */
+#define STO_AARCH64_VARIANT_PCS 0x80
+
+/* ARM relocs.  */
+
+#define R_ARM_NONE		0	/* No reloc */
+#define R_ARM_PC24		1	/* Deprecated PC relative 26
+					   bit branch.  */
+#define R_ARM_ABS32		2	/* Direct 32 bit  */
+#define R_ARM_REL32		3	/* PC relative 32 bit */
+#define R_ARM_PC13		4
+#define R_ARM_ABS16		5	/* Direct 16 bit */
+#define R_ARM_ABS12		6	/* Direct 12 bit */
+#define R_ARM_THM_ABS5		7	/* Direct & 0x7C (LDR, STR).  */
+#define R_ARM_ABS8		8	/* Direct 8 bit */
+#define R_ARM_SBREL32		9
+#define R_ARM_THM_PC22		10	/* PC relative 24 bit (Thumb32 BL).  */
+#define R_ARM_THM_PC8		11	/* PC relative & 0x3FC
+					   (Thumb16 LDR, ADD, ADR).  */
+#define R_ARM_AMP_VCALL9	12
+#define R_ARM_SWI24		13	/* Obsolete static relocation.  */
+#define R_ARM_TLS_DESC		13      /* Dynamic relocation.  */
+#define R_ARM_THM_SWI8		14	/* Reserved.  */
+#define R_ARM_XPC25		15	/* Reserved.  */
+#define R_ARM_THM_XPC22		16	/* Reserved.  */
+#define R_ARM_TLS_DTPMOD32	17	/* ID of module containing symbol */
+#define R_ARM_TLS_DTPOFF32	18	/* Offset in TLS block */
+#define R_ARM_TLS_TPOFF32	19	/* Offset in static TLS block */
+#define R_ARM_COPY		20	/* Copy symbol at runtime */
+#define R_ARM_GLOB_DAT		21	/* Create GOT entry */
+#define R_ARM_JUMP_SLOT		22	/* Create PLT entry */
+#define R_ARM_RELATIVE		23	/* Adjust by program base */
+#define R_ARM_GOTOFF		24	/* 32 bit offset to GOT */
+#define R_ARM_GOTPC		25	/* 32 bit PC relative offset to GOT */
+#define R_ARM_GOT32		26	/* 32 bit GOT entry */
+#define R_ARM_PLT32		27	/* Deprecated, 32 bit PLT address.  */
+#define R_ARM_CALL		28	/* PC relative 24 bit (BL, BLX).  */
+#define R_ARM_JUMP24		29	/* PC relative 24 bit
+					   (B, BL<cond>).  */
+#define R_ARM_THM_JUMP24	30	/* PC relative 24 bit (Thumb32 B.W).  */
+#define R_ARM_BASE_ABS		31	/* Adjust by program base.  */
+#define R_ARM_ALU_PCREL_7_0	32	/* Obsolete.  */
+#define R_ARM_ALU_PCREL_15_8	33	/* Obsolete.  */
+#define R_ARM_ALU_PCREL_23_15	34	/* Obsolete.  */
+#define R_ARM_LDR_SBREL_11_0	35	/* Deprecated, prog. base relative.  */
+#define R_ARM_ALU_SBREL_19_12	36	/* Deprecated, prog. base relative.  */
+#define R_ARM_ALU_SBREL_27_20	37	/* Deprecated, prog. base relative.  */
+#define R_ARM_TARGET1		38
+#define R_ARM_SBREL31		39	/* Program base relative.  */
+#define R_ARM_V4BX		40
+#define R_ARM_TARGET2		41
+#define R_ARM_PREL31		42	/* 32 bit PC relative.  */
+#define R_ARM_MOVW_ABS_NC	43	/* Direct 16-bit (MOVW).  */
+#define R_ARM_MOVT_ABS		44	/* Direct high 16-bit (MOVT).  */
+#define R_ARM_MOVW_PREL_NC	45	/* PC relative 16-bit (MOVW).  */
+#define R_ARM_MOVT_PREL		46	/* PC relative (MOVT).  */
+#define R_ARM_THM_MOVW_ABS_NC	47	/* Direct 16 bit (Thumb32 MOVW).  */
+#define R_ARM_THM_MOVT_ABS	48	/* Direct high 16 bit
+					   (Thumb32 MOVT).  */
+#define R_ARM_THM_MOVW_PREL_NC	49	/* PC relative 16 bit
+					   (Thumb32 MOVW).  */
+#define R_ARM_THM_MOVT_PREL	50	/* PC relative high 16 bit
+					   (Thumb32 MOVT).  */
+#define R_ARM_THM_JUMP19	51	/* PC relative 20 bit
+					   (Thumb32 B<cond>.W).  */
+#define R_ARM_THM_JUMP6		52	/* PC relative X & 0x7E
+					   (Thumb16 CBZ, CBNZ).  */
+#define R_ARM_THM_ALU_PREL_11_0	53	/* PC relative 12 bit
+					   (Thumb32 ADR.W).  */
+#define R_ARM_THM_PC12		54	/* PC relative 12 bit
+					   (Thumb32 LDR{D,SB,H,SH}).  */
+#define R_ARM_ABS32_NOI		55	/* Direct 32-bit.  */
+#define R_ARM_REL32_NOI		56	/* PC relative 32-bit.  */
+#define R_ARM_ALU_PC_G0_NC	57	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G0		58	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G1_NC	59	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G1		60	/* PC relative (ADD, SUB).  */
+#define R_ARM_ALU_PC_G2		61	/* PC relative (ADD, SUB).  */
+#define R_ARM_LDR_PC_G1		62	/* PC relative (LDR,STR,LDRB,STRB).  */
+#define R_ARM_LDR_PC_G2		63	/* PC relative (LDR,STR,LDRB,STRB).  */
+#define R_ARM_LDRS_PC_G0	64	/* PC relative (STR{D,H},
+					   LDR{D,SB,H,SH}).  */
+#define R_ARM_LDRS_PC_G1	65	/* PC relative (STR{D,H},
+					   LDR{D,SB,H,SH}).  */
+#define R_ARM_LDRS_PC_G2	66	/* PC relative (STR{D,H},
+					   LDR{D,SB,H,SH}).  */
+#define R_ARM_LDC_PC_G0		67	/* PC relative (LDC, STC).  */
+#define R_ARM_LDC_PC_G1		68	/* PC relative (LDC, STC).  */
+#define R_ARM_LDC_PC_G2		69	/* PC relative (LDC, STC).  */
+#define R_ARM_ALU_SB_G0_NC	70	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G0		71	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G1_NC	72	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G1		73	/* Program base relative (ADD,SUB).  */
+#define R_ARM_ALU_SB_G2		74	/* Program base relative (ADD,SUB).  */
+#define R_ARM_LDR_SB_G0		75	/* Program base relative (LDR,
+					   STR, LDRB, STRB).  */
+#define R_ARM_LDR_SB_G1		76	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDR_SB_G2		77	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDRS_SB_G0	78	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDRS_SB_G1	79	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDRS_SB_G2	80	/* Program base relative
+					   (LDR, STR, LDRB, STRB).  */
+#define R_ARM_LDC_SB_G0		81	/* Program base relative (LDC,STC).  */
+#define R_ARM_LDC_SB_G1		82	/* Program base relative (LDC,STC).  */
+#define R_ARM_LDC_SB_G2		83	/* Program base relative (LDC,STC).  */
+#define R_ARM_MOVW_BREL_NC	84	/* Program base relative 16
+					   bit (MOVW).  */
+#define R_ARM_MOVT_BREL		85	/* Program base relative high
+					   16 bit (MOVT).  */
+#define R_ARM_MOVW_BREL		86	/* Program base relative 16
+					   bit (MOVW).  */
+#define R_ARM_THM_MOVW_BREL_NC	87	/* Program base relative 16
+					   bit (Thumb32 MOVW).  */
+#define R_ARM_THM_MOVT_BREL	88	/* Program base relative high
+					   16 bit (Thumb32 MOVT).  */
+#define R_ARM_THM_MOVW_BREL	89	/* Program base relative 16
+					   bit (Thumb32 MOVW).  */
+#define R_ARM_TLS_GOTDESC	90
+#define R_ARM_TLS_CALL		91
+#define R_ARM_TLS_DESCSEQ	92	/* TLS relaxation.  */
+#define R_ARM_THM_TLS_CALL	93
+#define R_ARM_PLT32_ABS		94
+#define R_ARM_GOT_ABS		95	/* GOT entry.  */
+#define R_ARM_GOT_PREL		96	/* PC relative GOT entry.  */
+#define R_ARM_GOT_BREL12	97	/* GOT entry relative to GOT
+					   origin (LDR).  */
+#define R_ARM_GOTOFF12		98	/* 12 bit, GOT entry relative
+					   to GOT origin (LDR, STR).  */
+#define R_ARM_GOTRELAX		99
+#define R_ARM_GNU_VTENTRY	100
+#define R_ARM_GNU_VTINHERIT	101
+#define R_ARM_THM_PC11		102	/* PC relative & 0xFFE (Thumb16 B).  */
+#define R_ARM_THM_PC9		103	/* PC relative & 0x1FE
+					   (Thumb16 B/B<cond>).  */
+#define R_ARM_TLS_GD32		104	/* PC-rel 32 bit for global dynamic
+					   thread local data */
+#define R_ARM_TLS_LDM32		105	/* PC-rel 32 bit for local dynamic
+					   thread local data */
+#define R_ARM_TLS_LDO32		106	/* 32 bit offset relative to TLS
+					   block */
+#define R_ARM_TLS_IE32		107	/* PC-rel 32 bit for GOT entry of
+					   static TLS block offset */
+#define R_ARM_TLS_LE32		108	/* 32 bit offset relative to static
+					   TLS block */
+#define R_ARM_TLS_LDO12		109	/* 12 bit relative to TLS
+					   block (LDR, STR).  */
+#define R_ARM_TLS_LE12		110	/* 12 bit relative to static
+					   TLS block (LDR, STR).  */
+#define R_ARM_TLS_IE12GP	111	/* 12 bit GOT entry relative
+					   to GOT origin (LDR).  */
+#define R_ARM_ME_TOO		128	/* Obsolete.  */
+#define R_ARM_THM_TLS_DESCSEQ	129
+#define R_ARM_THM_TLS_DESCSEQ16	129
+#define R_ARM_THM_TLS_DESCSEQ32	130
+#define R_ARM_THM_GOT_BREL12	131	/* GOT entry relative to GOT
+					   origin, 12 bit (Thumb32 LDR).  */
+#define R_ARM_IRELATIVE		160
+#define R_ARM_RXPC25		249
+#define R_ARM_RSBREL32		250
+#define R_ARM_THM_RPC22		251
+#define R_ARM_RREL32		252
+#define R_ARM_RABS22		253
+#define R_ARM_RPC24		254
+#define R_ARM_RBASE		255
+/* Keep this the last entry.  */
+#define R_ARM_NUM		256
+
+/* C-SKY */
+#define R_CKCORE_NONE               0	/* no reloc */
+#define R_CKCORE_ADDR32             1	/* direct 32 bit (S + A) */
+#define R_CKCORE_PCRELIMM8BY4       2	/* disp ((S + A - P) >> 2) & 0xff   */
+#define R_CKCORE_PCRELIMM11BY2      3	/* disp ((S + A - P) >> 1) & 0x7ff  */
+#define R_CKCORE_PCREL32            5	/* 32-bit rel (S + A - P)           */
+#define R_CKCORE_PCRELJSR_IMM11BY2  6	/* disp ((S + A - P) >>1) & 0x7ff   */
+#define R_CKCORE_RELATIVE           9	/* 32 bit adjust program base(B + A)*/
+#define R_CKCORE_COPY               10	/* 32 bit adjust by program base    */
+#define R_CKCORE_GLOB_DAT           11	/* off between got and sym (S)      */
+#define R_CKCORE_JUMP_SLOT          12	/* PLT entry (S) */
+#define R_CKCORE_GOTOFF             13	/* offset to GOT (S + A - GOT)      */
+#define R_CKCORE_GOTPC              14	/* PC offset to GOT (GOT + A - P)   */
+#define R_CKCORE_GOT32              15	/* 32 bit GOT entry (G) */
+#define R_CKCORE_PLT32              16	/* 32 bit PLT entry (G) */
+#define R_CKCORE_ADDRGOT            17	/* GOT entry in GLOB_DAT (GOT + G)  */
+#define R_CKCORE_ADDRPLT            18	/* PLT entry in GLOB_DAT (GOT + G)  */
+#define R_CKCORE_PCREL_IMM26BY2     19	/* ((S + A - P) >> 1) & 0x3ffffff   */
+#define R_CKCORE_PCREL_IMM16BY2     20	/* disp ((S + A - P) >> 1) & 0xffff */
+#define R_CKCORE_PCREL_IMM16BY4     21	/* disp ((S + A - P) >> 2) & 0xffff */
+#define R_CKCORE_PCREL_IMM10BY2     22	/* disp ((S + A - P) >> 1) & 0x3ff  */
+#define R_CKCORE_PCREL_IMM10BY4     23	/* disp ((S + A - P) >> 2) & 0x3ff  */
+#define R_CKCORE_ADDR_HI16          24	/* high & low 16 bit ADDR */
+                                        /* ((S + A) >> 16) & 0xffff */
+#define R_CKCORE_ADDR_LO16          25	/* (S + A) & 0xffff */
+#define R_CKCORE_GOTPC_HI16         26	/* high & low 16 bit GOTPC */
+                                        /* ((GOT + A - P) >> 16) & 0xffff */
+#define R_CKCORE_GOTPC_LO16         27	/* (GOT + A - P) & 0xffff */
+#define R_CKCORE_GOTOFF_HI16        28	/* high & low 16 bit GOTOFF */
+                                        /* ((S + A - GOT) >> 16) & 0xffff */
+#define R_CKCORE_GOTOFF_LO16        29	/* (S + A - GOT) & 0xffff */
+#define R_CKCORE_GOT12              30	/* 12 bit disp GOT entry (G) */
+#define R_CKCORE_GOT_HI16           31	/* high & low 16 bit GOT */
+                                        /* (G >> 16) & 0xffff */
+#define R_CKCORE_GOT_LO16           32	/* (G & 0xffff) */
+#define R_CKCORE_PLT12              33	/* 12 bit disp PLT entry (G) */
+#define R_CKCORE_PLT_HI16           34	/* high & low 16 bit PLT */
+                                        /* (G >> 16) & 0xffff */
+#define R_CKCORE_PLT_LO16           35	/* G & 0xffff */
+#define R_CKCORE_ADDRGOT_HI16       36	/* high & low 16 bit ADDRGOT */
+                                        /* (GOT + G * 4) & 0xffff */
+#define R_CKCORE_ADDRGOT_LO16       37	/* (GOT + G * 4) & 0xffff */
+#define R_CKCORE_ADDRPLT_HI16       38	/* high & low 16 bit ADDRPLT */
+                                        /* ((GOT + G * 4) >> 16) & 0xFFFF */
+#define R_CKCORE_ADDRPLT_LO16       39	/* (GOT+G*4) & 0xffff */
+#define R_CKCORE_PCREL_JSR_IMM26BY2 40	/* disp ((S+A-P) >>1) & x3ffffff */
+#define R_CKCORE_TOFFSET_LO16       41	/* (S+A-BTEXT) & 0xffff */
+#define R_CKCORE_DOFFSET_LO16       42	/* (S+A-BTEXT) & 0xffff */
+#define R_CKCORE_PCREL_IMM18BY2     43	/* disp ((S+A-P) >>1) & 0x3ffff */
+#define R_CKCORE_DOFFSET_IMM18      44	/* disp (S+A-BDATA) & 0x3ffff */
+#define R_CKCORE_DOFFSET_IMM18BY2   45	/* disp ((S+A-BDATA)>>1) & 0x3ffff */
+#define R_CKCORE_DOFFSET_IMM18BY4   46	/* disp ((S+A-BDATA)>>2) & 0x3ffff */
+#define R_CKCORE_GOT_IMM18BY4       48	/* disp (G >> 2) */
+#define R_CKCORE_PLT_IMM18BY4       49	/* disp (G >> 2) */
+#define R_CKCORE_PCREL_IMM7BY4      50	/* disp ((S+A-P) >>2) & 0x7f */
+#define R_CKCORE_TLS_LE32           51	/* 32 bit offset to TLS block */
+#define R_CKCORE_TLS_IE32           52
+#define R_CKCORE_TLS_GD32           53
+#define R_CKCORE_TLS_LDM32          54
+#define R_CKCORE_TLS_LDO32          55
+#define R_CKCORE_TLS_DTPMOD32       56
+#define R_CKCORE_TLS_DTPOFF32       57
+#define R_CKCORE_TLS_TPOFF32        58
+
+/* C-SKY elf header definition.  */
+#define EF_CSKY_ABIMASK		    0XF0000000
+#define EF_CSKY_OTHER		    0X0FFF0000
+#define EF_CSKY_PROCESSOR	    0X0000FFFF
+
+#define EF_CSKY_ABIV1		    0X10000000
+#define EF_CSKY_ABIV2		    0X20000000
+
+/* C-SKY attributes section.  */
+#define SHT_CSKY_ATTRIBUTES	    (SHT_LOPROC + 1)
+
+/* IA-64 specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_IA_64_MASKOS		0x0000000f	/* os-specific flags */
+#define EF_IA_64_ABI64		0x00000010	/* 64-bit ABI */
+#define EF_IA_64_ARCH		0xff000000	/* arch. version mask */
+
+/* Processor specific values for the Phdr p_type field.  */
+#define PT_IA_64_ARCHEXT	(PT_LOPROC + 0)	/* arch extension bits */
+#define PT_IA_64_UNWIND		(PT_LOPROC + 1)	/* ia64 unwind bits */
+#define PT_IA_64_HP_OPT_ANOT	(PT_LOOS + 0x12)
+#define PT_IA_64_HP_HSL_ANOT	(PT_LOOS + 0x13)
+#define PT_IA_64_HP_STACK	(PT_LOOS + 0x14)
+
+/* Processor specific flags for the Phdr p_flags field.  */
+#define PF_IA_64_NORECOV	0x80000000	/* spec insns w/o recovery */
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_IA_64_EXT		(SHT_LOPROC + 0) /* extension bits */
+#define SHT_IA_64_UNWIND	(SHT_LOPROC + 1) /* unwind bits */
+
+/* Processor specific flags for the Shdr sh_flags field.  */
+#define SHF_IA_64_SHORT		0x10000000	/* section near gp */
+#define SHF_IA_64_NORECOV	0x20000000	/* spec insns w/o recovery */
+
+/* Processor specific values for the Dyn d_tag field.  */
+#define DT_IA_64_PLT_RESERVE	(DT_LOPROC + 0)
+#define DT_IA_64_NUM		1
+
+/* IA-64 relocations.  */
+#define R_IA64_NONE		0x00	/* none */
+#define R_IA64_IMM14		0x21	/* symbol + addend, add imm14 */
+#define R_IA64_IMM22		0x22	/* symbol + addend, add imm22 */
+#define R_IA64_IMM64		0x23	/* symbol + addend, mov imm64 */
+#define R_IA64_DIR32MSB		0x24	/* symbol + addend, data4 MSB */
+#define R_IA64_DIR32LSB		0x25	/* symbol + addend, data4 LSB */
+#define R_IA64_DIR64MSB		0x26	/* symbol + addend, data8 MSB */
+#define R_IA64_DIR64LSB		0x27	/* symbol + addend, data8 LSB */
+#define R_IA64_GPREL22		0x2a	/* @gprel(sym + add), add imm22 */
+#define R_IA64_GPREL64I		0x2b	/* @gprel(sym + add), mov imm64 */
+#define R_IA64_GPREL32MSB	0x2c	/* @gprel(sym + add), data4 MSB */
+#define R_IA64_GPREL32LSB	0x2d	/* @gprel(sym + add), data4 LSB */
+#define R_IA64_GPREL64MSB	0x2e	/* @gprel(sym + add), data8 MSB */
+#define R_IA64_GPREL64LSB	0x2f	/* @gprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF22		0x32	/* @ltoff(sym + add), add imm22 */
+#define R_IA64_LTOFF64I		0x33	/* @ltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF22		0x3a	/* @pltoff(sym + add), add imm22 */
+#define R_IA64_PLTOFF64I	0x3b	/* @pltoff(sym + add), mov imm64 */
+#define R_IA64_PLTOFF64MSB	0x3e	/* @pltoff(sym + add), data8 MSB */
+#define R_IA64_PLTOFF64LSB	0x3f	/* @pltoff(sym + add), data8 LSB */
+#define R_IA64_FPTR64I		0x43	/* @fptr(sym + add), mov imm64 */
+#define R_IA64_FPTR32MSB	0x44	/* @fptr(sym + add), data4 MSB */
+#define R_IA64_FPTR32LSB	0x45	/* @fptr(sym + add), data4 LSB */
+#define R_IA64_FPTR64MSB	0x46	/* @fptr(sym + add), data8 MSB */
+#define R_IA64_FPTR64LSB	0x47	/* @fptr(sym + add), data8 LSB */
+#define R_IA64_PCREL60B		0x48	/* @pcrel(sym + add), brl */
+#define R_IA64_PCREL21B		0x49	/* @pcrel(sym + add), ptb, call */
+#define R_IA64_PCREL21M		0x4a	/* @pcrel(sym + add), chk.s */
+#define R_IA64_PCREL21F		0x4b	/* @pcrel(sym + add), fchkf */
+#define R_IA64_PCREL32MSB	0x4c	/* @pcrel(sym + add), data4 MSB */
+#define R_IA64_PCREL32LSB	0x4d	/* @pcrel(sym + add), data4 LSB */
+#define R_IA64_PCREL64MSB	0x4e	/* @pcrel(sym + add), data8 MSB */
+#define R_IA64_PCREL64LSB	0x4f	/* @pcrel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_FPTR22	0x52	/* @ltoff(@fptr(s+a)), imm22 */
+#define R_IA64_LTOFF_FPTR64I	0x53	/* @ltoff(@fptr(s+a)), imm64 */
+#define R_IA64_LTOFF_FPTR32MSB	0x54	/* @ltoff(@fptr(s+a)), data4 MSB */
+#define R_IA64_LTOFF_FPTR32LSB	0x55	/* @ltoff(@fptr(s+a)), data4 LSB */
+#define R_IA64_LTOFF_FPTR64MSB	0x56	/* @ltoff(@fptr(s+a)), data8 MSB */
+#define R_IA64_LTOFF_FPTR64LSB	0x57	/* @ltoff(@fptr(s+a)), data8 LSB */
+#define R_IA64_SEGREL32MSB	0x5c	/* @segrel(sym + add), data4 MSB */
+#define R_IA64_SEGREL32LSB	0x5d	/* @segrel(sym + add), data4 LSB */
+#define R_IA64_SEGREL64MSB	0x5e	/* @segrel(sym + add), data8 MSB */
+#define R_IA64_SEGREL64LSB	0x5f	/* @segrel(sym + add), data8 LSB */
+#define R_IA64_SECREL32MSB	0x64	/* @secrel(sym + add), data4 MSB */
+#define R_IA64_SECREL32LSB	0x65	/* @secrel(sym + add), data4 LSB */
+#define R_IA64_SECREL64MSB	0x66	/* @secrel(sym + add), data8 MSB */
+#define R_IA64_SECREL64LSB	0x67	/* @secrel(sym + add), data8 LSB */
+#define R_IA64_REL32MSB		0x6c	/* data 4 + REL */
+#define R_IA64_REL32LSB		0x6d	/* data 4 + REL */
+#define R_IA64_REL64MSB		0x6e	/* data 8 + REL */
+#define R_IA64_REL64LSB		0x6f	/* data 8 + REL */
+#define R_IA64_LTV32MSB		0x74	/* symbol + addend, data4 MSB */
+#define R_IA64_LTV32LSB		0x75	/* symbol + addend, data4 LSB */
+#define R_IA64_LTV64MSB		0x76	/* symbol + addend, data8 MSB */
+#define R_IA64_LTV64LSB		0x77	/* symbol + addend, data8 LSB */
+#define R_IA64_PCREL21BI	0x79	/* @pcrel(sym + add), 21bit inst */
+#define R_IA64_PCREL22		0x7a	/* @pcrel(sym + add), 22bit inst */
+#define R_IA64_PCREL64I		0x7b	/* @pcrel(sym + add), 64bit inst */
+#define R_IA64_IPLTMSB		0x80	/* dynamic reloc, imported PLT, MSB */
+#define R_IA64_IPLTLSB		0x81	/* dynamic reloc, imported PLT, LSB */
+#define R_IA64_COPY		0x84	/* copy relocation */
+#define R_IA64_SUB		0x85	/* Addend and symbol difference */
+#define R_IA64_LTOFF22X		0x86	/* LTOFF22, relaxable.  */
+#define R_IA64_LDXMOV		0x87	/* Use of LTOFF22X.  */
+#define R_IA64_TPREL14		0x91	/* @tprel(sym + add), imm14 */
+#define R_IA64_TPREL22		0x92	/* @tprel(sym + add), imm22 */
+#define R_IA64_TPREL64I		0x93	/* @tprel(sym + add), imm64 */
+#define R_IA64_TPREL64MSB	0x96	/* @tprel(sym + add), data8 MSB */
+#define R_IA64_TPREL64LSB	0x97	/* @tprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_TPREL22	0x9a	/* @ltoff(@tprel(s+a)), imm2 */
+#define R_IA64_DTPMOD64MSB	0xa6	/* @dtpmod(sym + add), data8 MSB */
+#define R_IA64_DTPMOD64LSB	0xa7	/* @dtpmod(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPMOD22	0xaa	/* @ltoff(@dtpmod(sym + add)), imm22 */
+#define R_IA64_DTPREL14		0xb1	/* @dtprel(sym + add), imm14 */
+#define R_IA64_DTPREL22		0xb2	/* @dtprel(sym + add), imm22 */
+#define R_IA64_DTPREL64I	0xb3	/* @dtprel(sym + add), imm64 */
+#define R_IA64_DTPREL32MSB	0xb4	/* @dtprel(sym + add), data4 MSB */
+#define R_IA64_DTPREL32LSB	0xb5	/* @dtprel(sym + add), data4 LSB */
+#define R_IA64_DTPREL64MSB	0xb6	/* @dtprel(sym + add), data8 MSB */
+#define R_IA64_DTPREL64LSB	0xb7	/* @dtprel(sym + add), data8 LSB */
+#define R_IA64_LTOFF_DTPREL22	0xba	/* @ltoff(@dtprel(s+a)), imm22 */
+
+/* SH specific declarations */
+
+/* Processor specific flags for the ELF header e_flags field.  */
+#define EF_SH_MACH_MASK		0x1f
+#define EF_SH_UNKNOWN		0x0
+#define EF_SH1			0x1
+#define EF_SH2			0x2
+#define EF_SH3			0x3
+#define EF_SH_DSP		0x4
+#define EF_SH3_DSP		0x5
+#define EF_SH4AL_DSP		0x6
+#define EF_SH3E			0x8
+#define EF_SH4			0x9
+#define EF_SH2E			0xb
+#define EF_SH4A			0xc
+#define EF_SH2A			0xd
+#define EF_SH4_NOFPU		0x10
+#define EF_SH4A_NOFPU		0x11
+#define EF_SH4_NOMMU_NOFPU	0x12
+#define EF_SH2A_NOFPU		0x13
+#define EF_SH3_NOMMU		0x14
+#define EF_SH2A_SH4_NOFPU	0x15
+#define EF_SH2A_SH3_NOFPU	0x16
+#define EF_SH2A_SH4		0x17
+#define EF_SH2A_SH3E		0x18
+
+/* SH relocs.  */
+#define	R_SH_NONE		0
+#define	R_SH_DIR32		1
+#define	R_SH_REL32		2
+#define	R_SH_DIR8WPN		3
+#define	R_SH_IND12W		4
+#define	R_SH_DIR8WPL		5
+#define	R_SH_DIR8WPZ		6
+#define	R_SH_DIR8BP		7
+#define	R_SH_DIR8W		8
+#define	R_SH_DIR8L		9
+#define	R_SH_SWITCH16		25
+#define	R_SH_SWITCH32		26
+#define	R_SH_USES		27
+#define	R_SH_COUNT		28
+#define	R_SH_ALIGN		29
+#define	R_SH_CODE		30
+#define	R_SH_DATA		31
+#define	R_SH_LABEL		32
+#define	R_SH_SWITCH8		33
+#define	R_SH_GNU_VTINHERIT	34
+#define	R_SH_GNU_VTENTRY	35
+#define	R_SH_TLS_GD_32		144
+#define	R_SH_TLS_LD_32		145
+#define	R_SH_TLS_LDO_32		146
+#define	R_SH_TLS_IE_32		147
+#define	R_SH_TLS_LE_32		148
+#define	R_SH_TLS_DTPMOD32	149
+#define	R_SH_TLS_DTPOFF32	150
+#define	R_SH_TLS_TPOFF32	151
+#define	R_SH_GOT32		160
+#define	R_SH_PLT32		161
+#define	R_SH_COPY		162
+#define	R_SH_GLOB_DAT		163
+#define	R_SH_JMP_SLOT		164
+#define	R_SH_RELATIVE		165
+#define	R_SH_GOTOFF		166
+#define	R_SH_GOTPC		167
+/* Keep this the last entry.  */
+#define	R_SH_NUM		256
+
+/* S/390 specific definitions.  */
+
+/* Valid values for the e_flags field.  */
+
+#define EF_S390_HIGH_GPRS    0x00000001  /* High GPRs kernel facility needed.  */
+
+/* Additional s390 relocs */
+
+#define R_390_NONE		0	/* No reloc.  */
+#define R_390_8			1	/* Direct 8 bit.  */
+#define R_390_12		2	/* Direct 12 bit.  */
+#define R_390_16		3	/* Direct 16 bit.  */
+#define R_390_32		4	/* Direct 32 bit.  */
+#define R_390_PC32		5	/* PC relative 32 bit.	*/
+#define R_390_GOT12		6	/* 12 bit GOT offset.  */
+#define R_390_GOT32		7	/* 32 bit GOT offset.  */
+#define R_390_PLT32		8	/* 32 bit PC relative PLT address.  */
+#define R_390_COPY		9	/* Copy symbol at runtime.  */
+#define R_390_GLOB_DAT		10	/* Create GOT entry.  */
+#define R_390_JMP_SLOT		11	/* Create PLT entry.  */
+#define R_390_RELATIVE		12	/* Adjust by program base.  */
+#define R_390_GOTOFF32		13	/* 32 bit offset to GOT.	 */
+#define R_390_GOTPC		14	/* 32 bit PC relative offset to GOT.  */
+#define R_390_GOT16		15	/* 16 bit GOT offset.  */
+#define R_390_PC16		16	/* PC relative 16 bit.	*/
+#define R_390_PC16DBL		17	/* PC relative 16 bit shifted by 1.  */
+#define R_390_PLT16DBL		18	/* 16 bit PC rel. PLT shifted by 1.  */
+#define R_390_PC32DBL		19	/* PC relative 32 bit shifted by 1.  */
+#define R_390_PLT32DBL		20	/* 32 bit PC rel. PLT shifted by 1.  */
+#define R_390_GOTPCDBL		21	/* 32 bit PC rel. GOT shifted by 1.  */
+#define R_390_64		22	/* Direct 64 bit.  */
+#define R_390_PC64		23	/* PC relative 64 bit.	*/
+#define R_390_GOT64		24	/* 64 bit GOT offset.  */
+#define R_390_PLT64		25	/* 64 bit PC relative PLT address.  */
+#define R_390_GOTENT		26	/* 32 bit PC rel. to GOT entry >> 1. */
+#define R_390_GOTOFF16		27	/* 16 bit offset to GOT. */
+#define R_390_GOTOFF64		28	/* 64 bit offset to GOT. */
+#define R_390_GOTPLT12		29	/* 12 bit offset to jump slot.	*/
+#define R_390_GOTPLT16		30	/* 16 bit offset to jump slot.	*/
+#define R_390_GOTPLT32		31	/* 32 bit offset to jump slot.	*/
+#define R_390_GOTPLT64		32	/* 64 bit offset to jump slot.	*/
+#define R_390_GOTPLTENT		33	/* 32 bit rel. offset to jump slot.  */
+#define R_390_PLTOFF16		34	/* 16 bit offset from GOT to PLT. */
+#define R_390_PLTOFF32		35	/* 32 bit offset from GOT to PLT. */
+#define R_390_PLTOFF64		36	/* 16 bit offset from GOT to PLT. */
+#define R_390_TLS_LOAD		37	/* Tag for load insn in TLS code.  */
+#define R_390_TLS_GDCALL	38	/* Tag for function call in general
+					   dynamic TLS code. */
+#define R_390_TLS_LDCALL	39	/* Tag for function call in local
+					   dynamic TLS code. */
+#define R_390_TLS_GD32		40	/* Direct 32 bit for general dynamic
+					   thread local data.  */
+#define R_390_TLS_GD64		41	/* Direct 64 bit for general dynamic
+					  thread local data.  */
+#define R_390_TLS_GOTIE12	42	/* 12 bit GOT offset for static TLS
+					   block offset.  */
+#define R_390_TLS_GOTIE32	43	/* 32 bit GOT offset for static TLS
+					   block offset.  */
+#define R_390_TLS_GOTIE64	44	/* 64 bit GOT offset for static TLS
+					   block offset. */
+#define R_390_TLS_LDM32		45	/* Direct 32 bit for local dynamic
+					   thread local data in LE code.  */
+#define R_390_TLS_LDM64		46	/* Direct 64 bit for local dynamic
+					   thread local data in LE code.  */
+#define R_390_TLS_IE32		47	/* 32 bit address of GOT entry for
+					   negated static TLS block offset.  */
+#define R_390_TLS_IE64		48	/* 64 bit address of GOT entry for
+					   negated static TLS block offset.  */
+#define R_390_TLS_IEENT		49	/* 32 bit rel. offset to GOT entry for
+					   negated static TLS block offset.  */
+#define R_390_TLS_LE32		50	/* 32 bit negated offset relative to
+					   static TLS block.  */
+#define R_390_TLS_LE64		51	/* 64 bit negated offset relative to
+					   static TLS block.  */
+#define R_390_TLS_LDO32		52	/* 32 bit offset relative to TLS
+					   block.  */
+#define R_390_TLS_LDO64		53	/* 64 bit offset relative to TLS
+					   block.  */
+#define R_390_TLS_DTPMOD	54	/* ID of module containing symbol.  */
+#define R_390_TLS_DTPOFF	55	/* Offset in TLS block.	 */
+#define R_390_TLS_TPOFF		56	/* Negated offset in static TLS
+					   block.  */
+#define R_390_20		57	/* Direct 20 bit.  */
+#define R_390_GOT20		58	/* 20 bit GOT offset.  */
+#define R_390_GOTPLT20		59	/* 20 bit offset to jump slot.  */
+#define R_390_TLS_GOTIE20	60	/* 20 bit GOT offset for static TLS
+					   block offset.  */
+#define R_390_IRELATIVE         61      /* STT_GNU_IFUNC relocation.  */
+/* Keep this the last entry.  */
+#define R_390_NUM		62
+
+
+/* CRIS relocations.  */
+#define R_CRIS_NONE		0
+#define R_CRIS_8		1
+#define R_CRIS_16		2
+#define R_CRIS_32		3
+#define R_CRIS_8_PCREL		4
+#define R_CRIS_16_PCREL		5
+#define R_CRIS_32_PCREL		6
+#define R_CRIS_GNU_VTINHERIT	7
+#define R_CRIS_GNU_VTENTRY	8
+#define R_CRIS_COPY		9
+#define R_CRIS_GLOB_DAT		10
+#define R_CRIS_JUMP_SLOT	11
+#define R_CRIS_RELATIVE		12
+#define R_CRIS_16_GOT		13
+#define R_CRIS_32_GOT		14
+#define R_CRIS_16_GOTPLT	15
+#define R_CRIS_32_GOTPLT	16
+#define R_CRIS_32_GOTREL	17
+#define R_CRIS_32_PLT_GOTREL	18
+#define R_CRIS_32_PLT_PCREL	19
+
+#define R_CRIS_NUM		20
+
+
+/* AMD x86-64 relocations.  */
+#define R_X86_64_NONE		0	/* No reloc */
+#define R_X86_64_64		1	/* Direct 64 bit  */
+#define R_X86_64_PC32		2	/* PC relative 32 bit signed */
+#define R_X86_64_GOT32		3	/* 32 bit GOT entry */
+#define R_X86_64_PLT32		4	/* 32 bit PLT address */
+#define R_X86_64_COPY		5	/* Copy symbol at runtime */
+#define R_X86_64_GLOB_DAT	6	/* Create GOT entry */
+#define R_X86_64_JUMP_SLOT	7	/* Create PLT entry */
+#define R_X86_64_RELATIVE	8	/* Adjust by program base */
+#define R_X86_64_GOTPCREL	9	/* 32 bit signed PC relative
+					   offset to GOT */
+#define R_X86_64_32		10	/* Direct 32 bit zero extended */
+#define R_X86_64_32S		11	/* Direct 32 bit sign extended */
+#define R_X86_64_16		12	/* Direct 16 bit zero extended */
+#define R_X86_64_PC16		13	/* 16 bit sign extended pc relative */
+#define R_X86_64_8		14	/* Direct 8 bit sign extended  */
+#define R_X86_64_PC8		15	/* 8 bit sign extended pc relative */
+#define R_X86_64_DTPMOD64	16	/* ID of module containing symbol */
+#define R_X86_64_DTPOFF64	17	/* Offset in module's TLS block */
+#define R_X86_64_TPOFF64	18	/* Offset in initial TLS block */
+#define R_X86_64_TLSGD		19	/* 32 bit signed PC relative offset
+					   to two GOT entries for GD symbol */
+#define R_X86_64_TLSLD		20	/* 32 bit signed PC relative offset
+					   to two GOT entries for LD symbol */
+#define R_X86_64_DTPOFF32	21	/* Offset in TLS block */
+#define R_X86_64_GOTTPOFF	22	/* 32 bit signed PC relative offset
+					   to GOT entry for IE symbol */
+#define R_X86_64_TPOFF32	23	/* Offset in initial TLS block */
+#define R_X86_64_PC64		24	/* PC relative 64 bit */
+#define R_X86_64_GOTOFF64	25	/* 64 bit offset to GOT */
+#define R_X86_64_GOTPC32	26	/* 32 bit signed pc relative
+					   offset to GOT */
+#define R_X86_64_GOT64		27	/* 64-bit GOT entry offset */
+#define R_X86_64_GOTPCREL64	28	/* 64-bit PC relative offset
+					   to GOT entry */
+#define R_X86_64_GOTPC64	29	/* 64-bit PC relative offset to GOT */
+#define R_X86_64_GOTPLT64	30 	/* like GOT64, says PLT entry needed */
+#define R_X86_64_PLTOFF64	31	/* 64-bit GOT relative offset
+					   to PLT entry */
+#define R_X86_64_SIZE32		32	/* Size of symbol plus 32-bit addend */
+#define R_X86_64_SIZE64		33	/* Size of symbol plus 64-bit addend */
+#define R_X86_64_GOTPC32_TLSDESC 34	/* GOT offset for TLS descriptor.  */
+#define R_X86_64_TLSDESC_CALL   35	/* Marker for call through TLS
+					   descriptor.  */
+#define R_X86_64_TLSDESC        36	/* TLS descriptor.  */
+#define R_X86_64_IRELATIVE	37	/* Adjust indirectly by program base */
+#define R_X86_64_RELATIVE64	38	/* 64-bit adjust by program base */
+					/* 39 Reserved was R_X86_64_PC32_BND */
+					/* 40 Reserved was R_X86_64_PLT32_BND */
+#define R_X86_64_GOTPCRELX	41	/* Load from 32 bit signed pc relative
+					   offset to GOT entry without REX
+					   prefix, relaxable.  */
+#define R_X86_64_REX_GOTPCRELX	42	/* Load from 32 bit signed pc relative
+					   offset to GOT entry with REX prefix,
+					   relaxable.  */
+#define R_X86_64_NUM		43
+
+/* x86-64 sh_type values.  */
+#define SHT_X86_64_UNWIND	0x70000001 /* Unwind information.  */
+
+/* x86-64 d_tag values.  */
+#define DT_X86_64_PLT		(DT_LOPROC + 0)
+#define DT_X86_64_PLTSZ		(DT_LOPROC + 1)
+#define DT_X86_64_PLTENT	(DT_LOPROC + 3)
+#define DT_X86_64_NUM		4
+
+/* AM33 relocations.  */
+#define R_MN10300_NONE		0	/* No reloc.  */
+#define R_MN10300_32		1	/* Direct 32 bit.  */
+#define R_MN10300_16		2	/* Direct 16 bit.  */
+#define R_MN10300_8		3	/* Direct 8 bit.  */
+#define R_MN10300_PCREL32	4	/* PC-relative 32-bit.  */
+#define R_MN10300_PCREL16	5	/* PC-relative 16-bit signed.  */
+#define R_MN10300_PCREL8	6	/* PC-relative 8-bit signed.  */
+#define R_MN10300_GNU_VTINHERIT	7	/* Ancient C++ vtable garbage... */
+#define R_MN10300_GNU_VTENTRY	8	/* ... collection annotation.  */
+#define R_MN10300_24		9	/* Direct 24 bit.  */
+#define R_MN10300_GOTPC32	10	/* 32-bit PCrel offset to GOT.  */
+#define R_MN10300_GOTPC16	11	/* 16-bit PCrel offset to GOT.  */
+#define R_MN10300_GOTOFF32	12	/* 32-bit offset from GOT.  */
+#define R_MN10300_GOTOFF24	13	/* 24-bit offset from GOT.  */
+#define R_MN10300_GOTOFF16	14	/* 16-bit offset from GOT.  */
+#define R_MN10300_PLT32		15	/* 32-bit PCrel to PLT entry.  */
+#define R_MN10300_PLT16		16	/* 16-bit PCrel to PLT entry.  */
+#define R_MN10300_GOT32		17	/* 32-bit offset to GOT entry.  */
+#define R_MN10300_GOT24		18	/* 24-bit offset to GOT entry.  */
+#define R_MN10300_GOT16		19	/* 16-bit offset to GOT entry.  */
+#define R_MN10300_COPY		20	/* Copy symbol at runtime.  */
+#define R_MN10300_GLOB_DAT	21	/* Create GOT entry.  */
+#define R_MN10300_JMP_SLOT	22	/* Create PLT entry.  */
+#define R_MN10300_RELATIVE	23	/* Adjust by program base.  */
+#define R_MN10300_TLS_GD	24	/* 32-bit offset for global dynamic.  */
+#define R_MN10300_TLS_LD	25	/* 32-bit offset for local dynamic.  */
+#define R_MN10300_TLS_LDO	26	/* Module-relative offset.  */
+#define R_MN10300_TLS_GOTIE	27	/* GOT offset for static TLS block
+					   offset.  */
+#define R_MN10300_TLS_IE	28	/* GOT address for static TLS block
+					   offset.  */
+#define R_MN10300_TLS_LE	29	/* Offset relative to static TLS
+					   block.  */
+#define R_MN10300_TLS_DTPMOD	30	/* ID of module containing symbol.  */
+#define R_MN10300_TLS_DTPOFF	31	/* Offset in module TLS block.  */
+#define R_MN10300_TLS_TPOFF	32	/* Offset in static TLS block.  */
+#define R_MN10300_SYM_DIFF	33	/* Adjustment for next reloc as needed
+					   by linker relaxation.  */
+#define R_MN10300_ALIGN		34	/* Alignment requirement for linker
+					   relaxation.  */
+#define R_MN10300_NUM		35
+
+
+/* M32R relocs.  */
+#define R_M32R_NONE		0	/* No reloc. */
+#define R_M32R_16		1	/* Direct 16 bit. */
+#define R_M32R_32		2	/* Direct 32 bit. */
+#define R_M32R_24		3	/* Direct 24 bit. */
+#define R_M32R_10_PCREL		4	/* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL		5	/* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL		6	/* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO		7	/* High 16 bit with unsigned low. */
+#define R_M32R_HI16_SLO		8	/* High 16 bit with signed low. */
+#define R_M32R_LO16		9	/* Low 16 bit. */
+#define R_M32R_SDA16		10	/* 16 bit offset in SDA. */
+#define R_M32R_GNU_VTINHERIT	11
+#define R_M32R_GNU_VTENTRY	12
+/* M32R relocs use SHT_RELA.  */
+#define R_M32R_16_RELA		33	/* Direct 16 bit. */
+#define R_M32R_32_RELA		34	/* Direct 32 bit. */
+#define R_M32R_24_RELA		35	/* Direct 24 bit. */
+#define R_M32R_10_PCREL_RELA	36	/* PC relative 10 bit shifted. */
+#define R_M32R_18_PCREL_RELA	37	/* PC relative 18 bit shifted. */
+#define R_M32R_26_PCREL_RELA	38	/* PC relative 26 bit shifted. */
+#define R_M32R_HI16_ULO_RELA	39	/* High 16 bit with unsigned low */
+#define R_M32R_HI16_SLO_RELA	40	/* High 16 bit with signed low */
+#define R_M32R_LO16_RELA	41	/* Low 16 bit */
+#define R_M32R_SDA16_RELA	42	/* 16 bit offset in SDA */
+#define R_M32R_RELA_GNU_VTINHERIT	43
+#define R_M32R_RELA_GNU_VTENTRY	44
+#define R_M32R_REL32		45	/* PC relative 32 bit.  */
+
+#define R_M32R_GOT24		48	/* 24 bit GOT entry */
+#define R_M32R_26_PLTREL	49	/* 26 bit PC relative to PLT shifted */
+#define R_M32R_COPY		50	/* Copy symbol at runtime */
+#define R_M32R_GLOB_DAT		51	/* Create GOT entry */
+#define R_M32R_JMP_SLOT		52	/* Create PLT entry */
+#define R_M32R_RELATIVE		53	/* Adjust by program base */
+#define R_M32R_GOTOFF		54	/* 24 bit offset to GOT */
+#define R_M32R_GOTPC24		55	/* 24 bit PC relative offset to GOT */
+#define R_M32R_GOT16_HI_ULO	56	/* High 16 bit GOT entry with unsigned
+					   low */
+#define R_M32R_GOT16_HI_SLO	57	/* High 16 bit GOT entry with signed
+					   low */
+#define R_M32R_GOT16_LO		58	/* Low 16 bit GOT entry */
+#define R_M32R_GOTPC_HI_ULO	59	/* High 16 bit PC relative offset to
+					   GOT with unsigned low */
+#define R_M32R_GOTPC_HI_SLO	60	/* High 16 bit PC relative offset to
+					   GOT with signed low */
+#define R_M32R_GOTPC_LO		61	/* Low 16 bit PC relative offset to
+					   GOT */
+#define R_M32R_GOTOFF_HI_ULO	62	/* High 16 bit offset to GOT
+					   with unsigned low */
+#define R_M32R_GOTOFF_HI_SLO	63	/* High 16 bit offset to GOT
+					   with signed low */
+#define R_M32R_GOTOFF_LO	64	/* Low 16 bit offset to GOT */
+#define R_M32R_NUM		256	/* Keep this the last entry. */
+
+/* MicroBlaze relocations */
+#define R_MICROBLAZE_NONE		0	/* No reloc. */
+#define R_MICROBLAZE_32 		1	/* Direct 32 bit. */
+#define R_MICROBLAZE_32_PCREL		2	/* PC relative 32 bit. */
+#define R_MICROBLAZE_64_PCREL		3	/* PC relative 64 bit. */
+#define R_MICROBLAZE_32_PCREL_LO	4	/* Low 16 bits of PCREL32. */
+#define R_MICROBLAZE_64 		5	/* Direct 64 bit. */
+#define R_MICROBLAZE_32_LO		6	/* Low 16 bit. */
+#define R_MICROBLAZE_SRO32		7	/* Read-only small data area. */
+#define R_MICROBLAZE_SRW32		8	/* Read-write small data area. */
+#define R_MICROBLAZE_64_NONE		9	/* No reloc. */
+#define R_MICROBLAZE_32_SYM_OP_SYM	10	/* Symbol Op Symbol relocation. */
+#define R_MICROBLAZE_GNU_VTINHERIT	11	/* GNU C++ vtable hierarchy. */
+#define R_MICROBLAZE_GNU_VTENTRY	12	/* GNU C++ vtable member usage. */
+#define R_MICROBLAZE_GOTPC_64		13	/* PC-relative GOT offset.  */
+#define R_MICROBLAZE_GOT_64		14	/* GOT entry offset.  */
+#define R_MICROBLAZE_PLT_64		15	/* PLT offset (PC-relative).  */
+#define R_MICROBLAZE_REL		16	/* Adjust by program base.  */
+#define R_MICROBLAZE_JUMP_SLOT		17	/* Create PLT entry.  */
+#define R_MICROBLAZE_GLOB_DAT		18	/* Create GOT entry.  */
+#define R_MICROBLAZE_GOTOFF_64		19	/* 64 bit offset to GOT. */
+#define R_MICROBLAZE_GOTOFF_32		20	/* 32 bit offset to GOT. */
+#define R_MICROBLAZE_COPY		21	/* Runtime copy.  */
+#define R_MICROBLAZE_TLS		22	/* TLS Reloc. */
+#define R_MICROBLAZE_TLSGD		23	/* TLS General Dynamic. */
+#define R_MICROBLAZE_TLSLD		24	/* TLS Local Dynamic. */
+#define R_MICROBLAZE_TLSDTPMOD32	25	/* TLS Module ID. */
+#define R_MICROBLAZE_TLSDTPREL32	26	/* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSDTPREL64	27	/* TLS Offset Within TLS Block. */
+#define R_MICROBLAZE_TLSGOTTPREL32	28	/* TLS Offset From Thread Pointer. */
+#define R_MICROBLAZE_TLSTPREL32 	29	/* TLS Offset From Thread Pointer. */
+
+/* Legal values for d_tag (dynamic entry type).  */
+#define DT_NIOS2_GP             0x70000002 /* Address of _gp.  */
+
+/* Nios II relocations.  */
+#define R_NIOS2_NONE		0	/* No reloc.  */
+#define R_NIOS2_S16		1	/* Direct signed 16 bit.  */
+#define R_NIOS2_U16		2	/* Direct unsigned 16 bit.  */
+#define R_NIOS2_PCREL16		3	/* PC relative 16 bit.  */
+#define R_NIOS2_CALL26		4	/* Direct call.  */
+#define R_NIOS2_IMM5		5	/* 5 bit constant expression.  */
+#define R_NIOS2_CACHE_OPX	6	/* 5 bit expression, shift 22.  */
+#define R_NIOS2_IMM6		7	/* 6 bit constant expression.  */
+#define R_NIOS2_IMM8		8	/* 8 bit constant expression.  */
+#define R_NIOS2_HI16		9	/* High 16 bit.  */
+#define R_NIOS2_LO16		10	/* Low 16 bit.  */
+#define R_NIOS2_HIADJ16		11	/* High 16 bit, adjusted.  */
+#define R_NIOS2_BFD_RELOC_32	12	/* 32 bit symbol value + addend.  */
+#define R_NIOS2_BFD_RELOC_16	13	/* 16 bit symbol value + addend.  */
+#define R_NIOS2_BFD_RELOC_8	14	/* 8 bit symbol value + addend.  */
+#define R_NIOS2_GPREL		15	/* 16 bit GP pointer offset.  */
+#define R_NIOS2_GNU_VTINHERIT	16	/* GNU C++ vtable hierarchy.  */
+#define R_NIOS2_GNU_VTENTRY	17	/* GNU C++ vtable member usage.  */
+#define R_NIOS2_UJMP		18	/* Unconditional branch.  */
+#define R_NIOS2_CJMP		19	/* Conditional branch.  */
+#define R_NIOS2_CALLR		20	/* Indirect call through register.  */
+#define R_NIOS2_ALIGN		21	/* Alignment requirement for
+					   linker relaxation.  */
+#define R_NIOS2_GOT16		22	/* 16 bit GOT entry.  */
+#define R_NIOS2_CALL16		23	/* 16 bit GOT entry for function.  */
+#define R_NIOS2_GOTOFF_LO	24	/* %lo of offset to GOT pointer.  */
+#define R_NIOS2_GOTOFF_HA	25	/* %hiadj of offset to GOT pointer.  */
+#define R_NIOS2_PCREL_LO	26	/* %lo of PC relative offset.  */
+#define R_NIOS2_PCREL_HA	27	/* %hiadj of PC relative offset.  */
+#define R_NIOS2_TLS_GD16	28	/* 16 bit GOT offset for TLS GD.  */
+#define R_NIOS2_TLS_LDM16	29	/* 16 bit GOT offset for TLS LDM.  */
+#define R_NIOS2_TLS_LDO16	30	/* 16 bit module relative offset.  */
+#define R_NIOS2_TLS_IE16	31	/* 16 bit GOT offset for TLS IE.  */
+#define R_NIOS2_TLS_LE16	32	/* 16 bit LE TP-relative offset.  */
+#define R_NIOS2_TLS_DTPMOD	33	/* Module number.  */
+#define R_NIOS2_TLS_DTPREL	34	/* Module-relative offset.  */
+#define R_NIOS2_TLS_TPREL	35	/* TP-relative offset.  */
+#define R_NIOS2_COPY		36	/* Copy symbol at runtime.  */
+#define R_NIOS2_GLOB_DAT	37	/* Create GOT entry.  */
+#define R_NIOS2_JUMP_SLOT	38	/* Create PLT entry.  */
+#define R_NIOS2_RELATIVE	39	/* Adjust by program base.  */
+#define R_NIOS2_GOTOFF		40	/* 16 bit offset to GOT pointer.  */
+#define R_NIOS2_CALL26_NOAT	41	/* Direct call in .noat section.  */
+#define R_NIOS2_GOT_LO		42	/* %lo() of GOT entry.  */
+#define R_NIOS2_GOT_HA		43	/* %hiadj() of GOT entry.  */
+#define R_NIOS2_CALL_LO		44	/* %lo() of function GOT entry.  */
+#define R_NIOS2_CALL_HA		45	/* %hiadj() of function GOT entry.  */
+
+/* TILEPro relocations.  */
+#define R_TILEPRO_NONE		0	/* No reloc */
+#define R_TILEPRO_32		1	/* Direct 32 bit */
+#define R_TILEPRO_16		2	/* Direct 16 bit */
+#define R_TILEPRO_8		3	/* Direct 8 bit */
+#define R_TILEPRO_32_PCREL	4	/* PC relative 32 bit */
+#define R_TILEPRO_16_PCREL	5	/* PC relative 16 bit */
+#define R_TILEPRO_8_PCREL	6	/* PC relative 8 bit */
+#define R_TILEPRO_LO16		7	/* Low 16 bit */
+#define R_TILEPRO_HI16		8	/* High 16 bit */
+#define R_TILEPRO_HA16		9	/* High 16 bit, adjusted */
+#define R_TILEPRO_COPY		10	/* Copy relocation */
+#define R_TILEPRO_GLOB_DAT	11	/* Create GOT entry */
+#define R_TILEPRO_JMP_SLOT	12	/* Create PLT entry */
+#define R_TILEPRO_RELATIVE	13	/* Adjust by program base */
+#define R_TILEPRO_BROFF_X1	14	/* X1 pipe branch offset */
+#define R_TILEPRO_JOFFLONG_X1	15	/* X1 pipe jump offset */
+#define R_TILEPRO_JOFFLONG_X1_PLT 16	/* X1 pipe jump offset to PLT */
+#define R_TILEPRO_IMM8_X0	17	/* X0 pipe 8-bit */
+#define R_TILEPRO_IMM8_Y0	18	/* Y0 pipe 8-bit */
+#define R_TILEPRO_IMM8_X1	19	/* X1 pipe 8-bit */
+#define R_TILEPRO_IMM8_Y1	20	/* Y1 pipe 8-bit */
+#define R_TILEPRO_MT_IMM15_X1	21	/* X1 pipe mtspr */
+#define R_TILEPRO_MF_IMM15_X1	22	/* X1 pipe mfspr */
+#define R_TILEPRO_IMM16_X0	23	/* X0 pipe 16-bit */
+#define R_TILEPRO_IMM16_X1	24	/* X1 pipe 16-bit */
+#define R_TILEPRO_IMM16_X0_LO	25	/* X0 pipe low 16-bit */
+#define R_TILEPRO_IMM16_X1_LO	26	/* X1 pipe low 16-bit */
+#define R_TILEPRO_IMM16_X0_HI	27	/* X0 pipe high 16-bit */
+#define R_TILEPRO_IMM16_X1_HI	28	/* X1 pipe high 16-bit */
+#define R_TILEPRO_IMM16_X0_HA	29	/* X0 pipe high 16-bit, adjusted */
+#define R_TILEPRO_IMM16_X1_HA	30	/* X1 pipe high 16-bit, adjusted */
+#define R_TILEPRO_IMM16_X0_PCREL 31	/* X0 pipe PC relative 16 bit */
+#define R_TILEPRO_IMM16_X1_PCREL 32	/* X1 pipe PC relative 16 bit */
+#define R_TILEPRO_IMM16_X0_LO_PCREL 33	/* X0 pipe PC relative low 16 bit */
+#define R_TILEPRO_IMM16_X1_LO_PCREL 34	/* X1 pipe PC relative low 16 bit */
+#define R_TILEPRO_IMM16_X0_HI_PCREL 35	/* X0 pipe PC relative high 16 bit */
+#define R_TILEPRO_IMM16_X1_HI_PCREL 36	/* X1 pipe PC relative high 16 bit */
+#define R_TILEPRO_IMM16_X0_HA_PCREL 37	/* X0 pipe PC relative ha() 16 bit */
+#define R_TILEPRO_IMM16_X1_HA_PCREL 38	/* X1 pipe PC relative ha() 16 bit */
+#define R_TILEPRO_IMM16_X0_GOT	39	/* X0 pipe 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT	40	/* X1 pipe 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_LO 41	/* X0 pipe low 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_LO 42	/* X1 pipe low 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_HI 43	/* X0 pipe high 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_HI 44	/* X1 pipe high 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X0_GOT_HA 45	/* X0 pipe ha() 16-bit GOT offset */
+#define R_TILEPRO_IMM16_X1_GOT_HA 46	/* X1 pipe ha() 16-bit GOT offset */
+#define R_TILEPRO_MMSTART_X0	47	/* X0 pipe mm "start" */
+#define R_TILEPRO_MMEND_X0	48	/* X0 pipe mm "end" */
+#define R_TILEPRO_MMSTART_X1	49	/* X1 pipe mm "start" */
+#define R_TILEPRO_MMEND_X1	50	/* X1 pipe mm "end" */
+#define R_TILEPRO_SHAMT_X0	51	/* X0 pipe shift amount */
+#define R_TILEPRO_SHAMT_X1	52	/* X1 pipe shift amount */
+#define R_TILEPRO_SHAMT_Y0	53	/* Y0 pipe shift amount */
+#define R_TILEPRO_SHAMT_Y1	54	/* Y1 pipe shift amount */
+#define R_TILEPRO_DEST_IMM8_X1	55	/* X1 pipe destination 8-bit */
+/* Relocs 56-59 are currently not defined.  */
+#define R_TILEPRO_TLS_GD_CALL	60	/* "jal" for TLS GD */
+#define R_TILEPRO_IMM8_X0_TLS_GD_ADD 61	/* X0 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_X1_TLS_GD_ADD 62	/* X1 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_Y0_TLS_GD_ADD 63	/* Y0 pipe "addi" for TLS GD */
+#define R_TILEPRO_IMM8_Y1_TLS_GD_ADD 64	/* Y1 pipe "addi" for TLS GD */
+#define R_TILEPRO_TLS_IE_LOAD	65	/* "lw_tls" for TLS IE */
+#define R_TILEPRO_IMM16_X0_TLS_GD 66	/* X0 pipe 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD 67	/* X1 pipe 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_LO 68	/* X0 pipe low 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_LO 69	/* X1 pipe low 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_HI 70	/* X0 pipe high 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_HI 71	/* X1 pipe high 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_GD_HA 72	/* X0 pipe ha() 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X1_TLS_GD_HA 73	/* X1 pipe ha() 16-bit TLS GD offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE 74	/* X0 pipe 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE 75	/* X1 pipe 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_LO 76	/* X0 pipe low 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_LO 77	/* X1 pipe low 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_HI 78	/* X0 pipe high 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_HI 79	/* X1 pipe high 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X0_TLS_IE_HA 80	/* X0 pipe ha() 16-bit TLS IE offset */
+#define R_TILEPRO_IMM16_X1_TLS_IE_HA 81	/* X1 pipe ha() 16-bit TLS IE offset */
+#define R_TILEPRO_TLS_DTPMOD32	82	/* ID of module containing symbol */
+#define R_TILEPRO_TLS_DTPOFF32	83	/* Offset in TLS block */
+#define R_TILEPRO_TLS_TPOFF32	84	/* Offset in static TLS block */
+#define R_TILEPRO_IMM16_X0_TLS_LE 85	/* X0 pipe 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE 86	/* X1 pipe 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_LO 87	/* X0 pipe low 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_LO 88	/* X1 pipe low 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_HI 89	/* X0 pipe high 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_HI 90	/* X1 pipe high 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X0_TLS_LE_HA 91	/* X0 pipe ha() 16-bit TLS LE offset */
+#define R_TILEPRO_IMM16_X1_TLS_LE_HA 92	/* X1 pipe ha() 16-bit TLS LE offset */
+
+#define R_TILEPRO_GNU_VTINHERIT	128	/* GNU C++ vtable hierarchy */
+#define R_TILEPRO_GNU_VTENTRY	129	/* GNU C++ vtable member usage */
+
+#define R_TILEPRO_NUM		130
+
+
+/* TILE-Gx relocations.  */
+#define R_TILEGX_NONE		0	/* No reloc */
+#define R_TILEGX_64		1	/* Direct 64 bit */
+#define R_TILEGX_32		2	/* Direct 32 bit */
+#define R_TILEGX_16		3	/* Direct 16 bit */
+#define R_TILEGX_8		4	/* Direct 8 bit */
+#define R_TILEGX_64_PCREL	5	/* PC relative 64 bit */
+#define R_TILEGX_32_PCREL	6	/* PC relative 32 bit */
+#define R_TILEGX_16_PCREL	7	/* PC relative 16 bit */
+#define R_TILEGX_8_PCREL	8	/* PC relative 8 bit */
+#define R_TILEGX_HW0		9	/* hword 0 16-bit */
+#define R_TILEGX_HW1		10	/* hword 1 16-bit */
+#define R_TILEGX_HW2		11	/* hword 2 16-bit */
+#define R_TILEGX_HW3		12	/* hword 3 16-bit */
+#define R_TILEGX_HW0_LAST	13	/* last hword 0 16-bit */
+#define R_TILEGX_HW1_LAST	14	/* last hword 1 16-bit */
+#define R_TILEGX_HW2_LAST	15	/* last hword 2 16-bit */
+#define R_TILEGX_COPY		16	/* Copy relocation */
+#define R_TILEGX_GLOB_DAT	17	/* Create GOT entry */
+#define R_TILEGX_JMP_SLOT	18	/* Create PLT entry */
+#define R_TILEGX_RELATIVE	19	/* Adjust by program base */
+#define R_TILEGX_BROFF_X1	20	/* X1 pipe branch offset */
+#define R_TILEGX_JUMPOFF_X1	21	/* X1 pipe jump offset */
+#define R_TILEGX_JUMPOFF_X1_PLT	22	/* X1 pipe jump offset to PLT */
+#define R_TILEGX_IMM8_X0	23	/* X0 pipe 8-bit */
+#define R_TILEGX_IMM8_Y0	24	/* Y0 pipe 8-bit */
+#define R_TILEGX_IMM8_X1	25	/* X1 pipe 8-bit */
+#define R_TILEGX_IMM8_Y1	26	/* Y1 pipe 8-bit */
+#define R_TILEGX_DEST_IMM8_X1	27	/* X1 pipe destination 8-bit */
+#define R_TILEGX_MT_IMM14_X1	28	/* X1 pipe mtspr */
+#define R_TILEGX_MF_IMM14_X1	29	/* X1 pipe mfspr */
+#define R_TILEGX_MMSTART_X0	30	/* X0 pipe mm "start" */
+#define R_TILEGX_MMEND_X0	31	/* X0 pipe mm "end" */
+#define R_TILEGX_SHAMT_X0	32	/* X0 pipe shift amount */
+#define R_TILEGX_SHAMT_X1	33	/* X1 pipe shift amount */
+#define R_TILEGX_SHAMT_Y0	34	/* Y0 pipe shift amount */
+#define R_TILEGX_SHAMT_Y1	35	/* Y1 pipe shift amount */
+#define R_TILEGX_IMM16_X0_HW0	36	/* X0 pipe hword 0 */
+#define R_TILEGX_IMM16_X1_HW0	37	/* X1 pipe hword 0 */
+#define R_TILEGX_IMM16_X0_HW1	38	/* X0 pipe hword 1 */
+#define R_TILEGX_IMM16_X1_HW1	39	/* X1 pipe hword 1 */
+#define R_TILEGX_IMM16_X0_HW2	40	/* X0 pipe hword 2 */
+#define R_TILEGX_IMM16_X1_HW2	41	/* X1 pipe hword 2 */
+#define R_TILEGX_IMM16_X0_HW3	42	/* X0 pipe hword 3 */
+#define R_TILEGX_IMM16_X1_HW3	43	/* X1 pipe hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_LAST 44	/* X0 pipe last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST 45	/* X1 pipe last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST 46	/* X0 pipe last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST 47	/* X1 pipe last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST 48	/* X0 pipe last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST 49	/* X1 pipe last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_PCREL 50	/* X0 pipe PC relative hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_PCREL 51	/* X1 pipe PC relative hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_PCREL 52	/* X0 pipe PC relative hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_PCREL 53	/* X1 pipe PC relative hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_PCREL 54	/* X0 pipe PC relative hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_PCREL 55	/* X1 pipe PC relative hword 2 */
+#define R_TILEGX_IMM16_X0_HW3_PCREL 56	/* X0 pipe PC relative hword 3 */
+#define R_TILEGX_IMM16_X1_HW3_PCREL 57	/* X1 pipe PC relative hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_PCREL 58 /* X0 pipe PC-rel last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST_PCREL 59 /* X1 pipe PC-rel last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST_PCREL 60 /* X0 pipe PC-rel last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST_PCREL 61 /* X1 pipe PC-rel last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST_PCREL 62 /* X0 pipe PC-rel last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST_PCREL 63 /* X1 pipe PC-rel last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_GOT 64	/* X0 pipe hword 0 GOT offset */
+#define R_TILEGX_IMM16_X1_HW0_GOT 65	/* X1 pipe hword 0 GOT offset */
+#define R_TILEGX_IMM16_X0_HW0_PLT_PCREL 66 /* X0 pipe PC-rel PLT hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_PLT_PCREL 67 /* X1 pipe PC-rel PLT hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_PLT_PCREL 68 /* X0 pipe PC-rel PLT hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_PLT_PCREL 69 /* X1 pipe PC-rel PLT hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_PLT_PCREL 70 /* X0 pipe PC-rel PLT hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_PLT_PCREL 71 /* X1 pipe PC-rel PLT hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_GOT 72 /* X0 pipe last hword 0 GOT offset */
+#define R_TILEGX_IMM16_X1_HW0_LAST_GOT 73 /* X1 pipe last hword 0 GOT offset */
+#define R_TILEGX_IMM16_X0_HW1_LAST_GOT 74 /* X0 pipe last hword 1 GOT offset */
+#define R_TILEGX_IMM16_X1_HW1_LAST_GOT 75 /* X1 pipe last hword 1 GOT offset */
+#define R_TILEGX_IMM16_X0_HW3_PLT_PCREL 76 /* X0 pipe PC-rel PLT hword 3 */
+#define R_TILEGX_IMM16_X1_HW3_PLT_PCREL 77 /* X1 pipe PC-rel PLT hword 3 */
+#define R_TILEGX_IMM16_X0_HW0_TLS_GD 78	/* X0 pipe hword 0 TLS GD offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_GD 79	/* X1 pipe hword 0 TLS GD offset */
+#define R_TILEGX_IMM16_X0_HW0_TLS_LE 80	/* X0 pipe hword 0 TLS LE offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_LE 81	/* X1 pipe hword 0 TLS LE offset */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_LE 82 /* X0 pipe last hword 0 LE off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_LE 83 /* X1 pipe last hword 0 LE off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_LE 84 /* X0 pipe last hword 1 LE off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_LE 85 /* X1 pipe last hword 1 LE off */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_GD 86 /* X0 pipe last hword 0 GD off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_GD 87 /* X1 pipe last hword 0 GD off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_GD 88 /* X0 pipe last hword 1 GD off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_GD 89 /* X1 pipe last hword 1 GD off */
+/* Relocs 90-91 are currently not defined.  */
+#define R_TILEGX_IMM16_X0_HW0_TLS_IE 92	/* X0 pipe hword 0 TLS IE offset */
+#define R_TILEGX_IMM16_X1_HW0_TLS_IE 93	/* X1 pipe hword 0 TLS IE offset */
+#define R_TILEGX_IMM16_X0_HW0_LAST_PLT_PCREL 94 /* X0 pipe PC-rel PLT last hword 0 */
+#define R_TILEGX_IMM16_X1_HW0_LAST_PLT_PCREL 95 /* X1 pipe PC-rel PLT last hword 0 */
+#define R_TILEGX_IMM16_X0_HW1_LAST_PLT_PCREL 96 /* X0 pipe PC-rel PLT last hword 1 */
+#define R_TILEGX_IMM16_X1_HW1_LAST_PLT_PCREL 97 /* X1 pipe PC-rel PLT last hword 1 */
+#define R_TILEGX_IMM16_X0_HW2_LAST_PLT_PCREL 98 /* X0 pipe PC-rel PLT last hword 2 */
+#define R_TILEGX_IMM16_X1_HW2_LAST_PLT_PCREL 99 /* X1 pipe PC-rel PLT last hword 2 */
+#define R_TILEGX_IMM16_X0_HW0_LAST_TLS_IE 100 /* X0 pipe last hword 0 IE off */
+#define R_TILEGX_IMM16_X1_HW0_LAST_TLS_IE 101 /* X1 pipe last hword 0 IE off */
+#define R_TILEGX_IMM16_X0_HW1_LAST_TLS_IE 102 /* X0 pipe last hword 1 IE off */
+#define R_TILEGX_IMM16_X1_HW1_LAST_TLS_IE 103 /* X1 pipe last hword 1 IE off */
+/* Relocs 104-105 are currently not defined.  */
+#define R_TILEGX_TLS_DTPMOD64	106	/* 64-bit ID of symbol's module */
+#define R_TILEGX_TLS_DTPOFF64	107	/* 64-bit offset in TLS block */
+#define R_TILEGX_TLS_TPOFF64	108	/* 64-bit offset in static TLS block */
+#define R_TILEGX_TLS_DTPMOD32	109	/* 32-bit ID of symbol's module */
+#define R_TILEGX_TLS_DTPOFF32	110	/* 32-bit offset in TLS block */
+#define R_TILEGX_TLS_TPOFF32	111	/* 32-bit offset in static TLS block */
+#define R_TILEGX_TLS_GD_CALL	112	/* "jal" for TLS GD */
+#define R_TILEGX_IMM8_X0_TLS_GD_ADD 113	/* X0 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_X1_TLS_GD_ADD 114	/* X1 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_Y0_TLS_GD_ADD 115	/* Y0 pipe "addi" for TLS GD */
+#define R_TILEGX_IMM8_Y1_TLS_GD_ADD 116	/* Y1 pipe "addi" for TLS GD */
+#define R_TILEGX_TLS_IE_LOAD	117	/* "ld_tls" for TLS IE */
+#define R_TILEGX_IMM8_X0_TLS_ADD 118	/* X0 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_X1_TLS_ADD 119	/* X1 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_Y0_TLS_ADD 120	/* Y0 pipe "addi" for TLS GD/IE */
+#define R_TILEGX_IMM8_Y1_TLS_ADD 121	/* Y1 pipe "addi" for TLS GD/IE */
+
+#define R_TILEGX_GNU_VTINHERIT	128	/* GNU C++ vtable hierarchy */
+#define R_TILEGX_GNU_VTENTRY	129	/* GNU C++ vtable member usage */
+
+#define R_TILEGX_NUM		130
+
+/* RISC-V ELF Flags */
+#define EF_RISCV_RVC 			0x0001
+#define EF_RISCV_FLOAT_ABI 		0x0006
+#define EF_RISCV_FLOAT_ABI_SOFT 	0x0000
+#define EF_RISCV_FLOAT_ABI_SINGLE 	0x0002
+#define EF_RISCV_FLOAT_ABI_DOUBLE 	0x0004
+#define EF_RISCV_FLOAT_ABI_QUAD 	0x0006
+#define EF_RISCV_RVE			0x0008
+#define EF_RISCV_TSO			0x0010
+
+/* RISC-V relocations.  */
+#define R_RISCV_NONE		 0
+#define R_RISCV_32		 1
+#define R_RISCV_64		 2
+#define R_RISCV_RELATIVE	 3
+#define R_RISCV_COPY		 4
+#define R_RISCV_JUMP_SLOT	 5
+#define R_RISCV_TLS_DTPMOD32	 6
+#define R_RISCV_TLS_DTPMOD64	 7
+#define R_RISCV_TLS_DTPREL32	 8
+#define R_RISCV_TLS_DTPREL64	 9
+#define R_RISCV_TLS_TPREL32	10
+#define R_RISCV_TLS_TPREL64	11
+#define R_RISCV_BRANCH		16
+#define R_RISCV_JAL		17
+#define R_RISCV_CALL		18
+#define R_RISCV_CALL_PLT	19
+#define R_RISCV_GOT_HI20	20
+#define R_RISCV_TLS_GOT_HI20	21
+#define R_RISCV_TLS_GD_HI20	22
+#define R_RISCV_PCREL_HI20	23
+#define R_RISCV_PCREL_LO12_I	24
+#define R_RISCV_PCREL_LO12_S	25
+#define R_RISCV_HI20		26
+#define R_RISCV_LO12_I		27
+#define R_RISCV_LO12_S		28
+#define R_RISCV_TPREL_HI20	29
+#define R_RISCV_TPREL_LO12_I	30
+#define R_RISCV_TPREL_LO12_S	31
+#define R_RISCV_TPREL_ADD	32
+#define R_RISCV_ADD8		33
+#define R_RISCV_ADD16		34
+#define R_RISCV_ADD32		35
+#define R_RISCV_ADD64		36
+#define R_RISCV_SUB8		37
+#define R_RISCV_SUB16		38
+#define R_RISCV_SUB32		39
+#define R_RISCV_SUB64		40
+#define R_RISCV_GNU_VTINHERIT	41
+#define R_RISCV_GNU_VTENTRY	42
+#define R_RISCV_ALIGN		43
+#define R_RISCV_RVC_BRANCH	44
+#define R_RISCV_RVC_JUMP	45
+#define R_RISCV_RVC_LUI		46
+#define R_RISCV_GPREL_I		47
+#define R_RISCV_GPREL_S		48
+#define R_RISCV_TPREL_I		49
+#define R_RISCV_TPREL_S		50
+#define R_RISCV_RELAX		51
+#define R_RISCV_SUB6		52
+#define R_RISCV_SET6		53
+#define R_RISCV_SET8		54
+#define R_RISCV_SET16		55
+#define R_RISCV_SET32		56
+#define R_RISCV_32_PCREL	57
+#define R_RISCV_IRELATIVE	58
+#define R_RISCV_PLT32		59
+#define R_RISCV_SET_ULEB128	60
+#define R_RISCV_SUB_ULEB128	61
+
+#define R_RISCV_NUM		62
+
+/* RISC-V specific values for the st_other field.  */
+#define STO_RISCV_VARIANT_CC	0x80	/* Function uses variant calling
+					   convention */
+
+/* RISC-V specific values for the sh_type field.  */
+#define SHT_RISCV_ATTRIBUTES	(SHT_LOPROC + 3)
+
+/* RISC-V specific values for the p_type field.  */
+#define PT_RISCV_ATTRIBUTES	(PT_LOPROC + 3)
+
+/* RISC-V specific values for the d_tag field.  */
+#define DT_RISCV_VARIANT_CC	(DT_LOPROC + 1)
+
+/* BPF specific declarations.  */
+
+#define R_BPF_NONE		0	/* No reloc */
+#define R_BPF_64_64		1
+#define R_BPF_64_32		10
+
+/* Imagination Meta specific relocations. */
+
+#define R_METAG_HIADDR16	0
+#define R_METAG_LOADDR16	1
+#define R_METAG_ADDR32		2	/* 32bit absolute address */
+#define R_METAG_NONE		3	/* No reloc */
+#define R_METAG_RELBRANCH	4
+#define R_METAG_GETSETOFF	5
+
+/* Backward compatibility */
+#define R_METAG_REG32OP1	6
+#define R_METAG_REG32OP2	7
+#define R_METAG_REG32OP3	8
+#define R_METAG_REG16OP1	9
+#define R_METAG_REG16OP2	10
+#define R_METAG_REG16OP3	11
+#define R_METAG_REG32OP4	12
+
+#define R_METAG_HIOG		13
+#define R_METAG_LOOG		14
+
+#define R_METAG_REL8		15
+#define R_METAG_REL16		16
+
+/* GNU */
+#define R_METAG_GNU_VTINHERIT	30
+#define R_METAG_GNU_VTENTRY	31
+
+/* PIC relocations */
+#define R_METAG_HI16_GOTOFF	32
+#define R_METAG_LO16_GOTOFF	33
+#define R_METAG_GETSET_GOTOFF	34
+#define R_METAG_GETSET_GOT	35
+#define R_METAG_HI16_GOTPC	36
+#define R_METAG_LO16_GOTPC	37
+#define R_METAG_HI16_PLT	38
+#define R_METAG_LO16_PLT	39
+#define R_METAG_RELBRANCH_PLT	40
+#define R_METAG_GOTOFF		41
+#define R_METAG_PLT		42
+#define R_METAG_COPY		43
+#define R_METAG_JMP_SLOT	44
+#define R_METAG_RELATIVE	45
+#define R_METAG_GLOB_DAT	46
+
+/* TLS relocations */
+#define R_METAG_TLS_GD		47
+#define R_METAG_TLS_LDM		48
+#define R_METAG_TLS_LDO_HI16	49
+#define R_METAG_TLS_LDO_LO16	50
+#define R_METAG_TLS_LDO		51
+#define R_METAG_TLS_IE		52
+#define R_METAG_TLS_IENONPIC	53
+#define R_METAG_TLS_IENONPIC_HI16 54
+#define R_METAG_TLS_IENONPIC_LO16 55
+#define R_METAG_TLS_TPOFF	56
+#define R_METAG_TLS_DTPMOD	57
+#define R_METAG_TLS_DTPOFF	58
+#define R_METAG_TLS_LE		59
+#define R_METAG_TLS_LE_HI16	60
+#define R_METAG_TLS_LE_LO16	61
+
+/* NDS32 relocations.  */
+#define R_NDS32_NONE		0
+#define R_NDS32_32_RELA 	20
+#define R_NDS32_COPY		39
+#define R_NDS32_GLOB_DAT	40
+#define R_NDS32_JMP_SLOT	41
+#define R_NDS32_RELATIVE	42
+#define R_NDS32_TLS_TPOFF	102
+#define R_NDS32_TLS_DESC	119
+
+/* LoongArch ELF Flags */
+#define EF_LARCH_ABI_MODIFIER_MASK  0x07
+#define EF_LARCH_ABI_SOFT_FLOAT     0x01
+#define EF_LARCH_ABI_SINGLE_FLOAT   0x02
+#define EF_LARCH_ABI_DOUBLE_FLOAT   0x03
+#define EF_LARCH_OBJABI_V1          0x40
+
+/* LoongArch specific dynamic relocations */
+#define R_LARCH_NONE		0
+#define R_LARCH_32		1
+#define R_LARCH_64		2
+#define R_LARCH_RELATIVE	3
+#define R_LARCH_COPY		4
+#define R_LARCH_JUMP_SLOT	5
+#define R_LARCH_TLS_DTPMOD32	6
+#define R_LARCH_TLS_DTPMOD64	7
+#define R_LARCH_TLS_DTPREL32	8
+#define R_LARCH_TLS_DTPREL64	9
+#define R_LARCH_TLS_TPREL32	10
+#define R_LARCH_TLS_TPREL64	11
+#define R_LARCH_IRELATIVE	12
+
+/* Reserved for future relocs that the dynamic linker must understand.  */
+
+/* used by the static linker for relocating .text.  */
+#define R_LARCH_MARK_LA  20
+#define R_LARCH_MARK_PCREL  21
+#define R_LARCH_SOP_PUSH_PCREL  22
+#define R_LARCH_SOP_PUSH_ABSOLUTE  23
+#define R_LARCH_SOP_PUSH_DUP  24
+#define R_LARCH_SOP_PUSH_GPREL  25
+#define R_LARCH_SOP_PUSH_TLS_TPREL  26
+#define R_LARCH_SOP_PUSH_TLS_GOT  27
+#define R_LARCH_SOP_PUSH_TLS_GD  28
+#define R_LARCH_SOP_PUSH_PLT_PCREL  29
+#define R_LARCH_SOP_ASSERT  30
+#define R_LARCH_SOP_NOT  31
+#define R_LARCH_SOP_SUB  32
+#define R_LARCH_SOP_SL  33
+#define R_LARCH_SOP_SR  34
+#define R_LARCH_SOP_ADD  35
+#define R_LARCH_SOP_AND  36
+#define R_LARCH_SOP_IF_ELSE  37
+#define R_LARCH_SOP_POP_32_S_10_5  38
+#define R_LARCH_SOP_POP_32_U_10_12  39
+#define R_LARCH_SOP_POP_32_S_10_12  40
+#define R_LARCH_SOP_POP_32_S_10_16  41
+#define R_LARCH_SOP_POP_32_S_10_16_S2  42
+#define R_LARCH_SOP_POP_32_S_5_20  43
+#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2  44
+#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2  45
+#define R_LARCH_SOP_POP_32_U  46
+
+/* used by the static linker for relocating non .text.  */
+#define R_LARCH_ADD8  47
+#define R_LARCH_ADD16  48
+#define R_LARCH_ADD24  49
+#define R_LARCH_ADD32  50
+#define R_LARCH_ADD64  51
+#define R_LARCH_SUB8  52
+#define R_LARCH_SUB16  53
+#define R_LARCH_SUB24  54
+#define R_LARCH_SUB32  55
+#define R_LARCH_SUB64  56
+#define R_LARCH_GNU_VTINHERIT  57
+#define R_LARCH_GNU_VTENTRY  58
+
+/* reserved 59-63 */
+
+#define R_LARCH_B16 64
+#define R_LARCH_B21 65
+#define R_LARCH_B26 66
+#define R_LARCH_ABS_HI20 67
+#define R_LARCH_ABS_LO12 68
+#define R_LARCH_ABS64_LO20 69
+#define R_LARCH_ABS64_HI12 70
+#define R_LARCH_PCALA_HI20 71
+#define R_LARCH_PCALA_LO12 72
+#define R_LARCH_PCALA64_LO20 73
+#define R_LARCH_PCALA64_HI12 74
+#define R_LARCH_GOT_PC_HI20 75
+#define R_LARCH_GOT_PC_LO12 76
+#define R_LARCH_GOT64_PC_LO20 77
+#define R_LARCH_GOT64_PC_HI12 78
+#define R_LARCH_GOT_HI20 79
+#define R_LARCH_GOT_LO12 80
+#define R_LARCH_GOT64_LO20 81
+#define R_LARCH_GOT64_HI12 82
+#define R_LARCH_TLS_LE_HI20 83
+#define R_LARCH_TLS_LE_LO12 84
+#define R_LARCH_TLS_LE64_LO20 85
+#define R_LARCH_TLS_LE64_HI12 86
+#define R_LARCH_TLS_IE_PC_HI20 87
+#define R_LARCH_TLS_IE_PC_LO12 88
+#define R_LARCH_TLS_IE64_PC_LO20 89
+#define R_LARCH_TLS_IE64_PC_HI12 90
+#define R_LARCH_TLS_IE_HI20 91
+#define R_LARCH_TLS_IE_LO12 92
+#define R_LARCH_TLS_IE64_LO20 93
+#define R_LARCH_TLS_IE64_HI12 94
+#define R_LARCH_TLS_LD_PC_HI20 95
+#define R_LARCH_TLS_LD_HI20 96
+#define R_LARCH_TLS_GD_PC_HI20 97
+#define R_LARCH_TLS_GD_HI20 98
+#define R_LARCH_32_PCREL 99
+#define R_LARCH_RELAX 100
+#define R_LARCH_DELETE 101
+#define R_LARCH_ALIGN 102
+#define R_LARCH_PCREL20_S2 103
+#define R_LARCH_CFA 104
+#define R_LARCH_ADD6 105
+#define R_LARCH_SUB6 106
+#define R_LARCH_ADD_ULEB128 107
+#define R_LARCH_SUB_ULEB128 108
+#define R_LARCH_64_PCREL 109
+#define R_LARCH_CALL36 110
+#define R_LARCH_TLS_DESC_PC_HI20 111
+#define R_LARCH_TLS_DESC_PC_LO12 112
+#define R_LARCH_TLS_DESC64_PC_LO20 113
+#define R_LARCH_TLS_DESC64_PC_HI12 114
+#define R_LARCH_TLS_DESC_HI20 115
+#define R_LARCH_TLS_DESC_LO12 116
+#define R_LARCH_TLS_DESC64_LO20 117
+#define R_LARCH_TLS_DESC64_HI12 118
+#define R_LARCH_TLS_DESC_LD 119
+#define R_LARCH_TLS_DESC_CALL 120
+#define R_LARCH_TLS_LE_HI20_R 121
+#define R_LARCH_TLS_LE_ADD_R 122
+#define R_LARCH_TLS_LE_LO12_R 123
+#define R_LARCH_TLS_LD_PCREL20_S2 124
+#define R_LARCH_TLS_GD_PCREL20_S2 125
+#define R_LARCH_TLS_DESC_PCREL20_S2 126
+
+/* ARC specific declarations.  */
+
+/* Processor specific flags for the Ehdr e_flags field.  */
+#define EF_ARC_MACH_MSK	    0x000000ff
+#define EF_ARC_OSABI_MSK    0x00000f00
+#define EF_ARC_ALL_MSK	    (EF_ARC_MACH_MSK | EF_ARC_OSABI_MSK)
+
+/* Processor specific values for the Shdr sh_type field.  */
+#define SHT_ARC_ATTRIBUTES	(SHT_LOPROC + 1) /* ARC attributes section.  */
+
+/* ARCompact/ARCv2 specific relocs.  */
+#define R_ARC_NONE		0x0
+#define R_ARC_8			0x1
+#define R_ARC_16		0x2
+#define R_ARC_24		0x3
+#define R_ARC_32		0x4
+
+#define R_ARC_B22_PCREL		0x6
+#define R_ARC_H30		0x7
+#define R_ARC_N8		0x8
+#define R_ARC_N16		0x9
+#define R_ARC_N24		0xA
+#define R_ARC_N32		0xB
+#define R_ARC_SDA		0xC
+#define R_ARC_SECTOFF		0xD
+#define R_ARC_S21H_PCREL	0xE
+#define R_ARC_S21W_PCREL	0xF
+#define R_ARC_S25H_PCREL	0x10
+#define R_ARC_S25W_PCREL	0x11
+#define R_ARC_SDA32		0x12
+#define R_ARC_SDA_LDST		0x13
+#define R_ARC_SDA_LDST1		0x14
+#define R_ARC_SDA_LDST2		0x15
+#define R_ARC_SDA16_LD		0x16
+#define R_ARC_SDA16_LD1		0x17
+#define R_ARC_SDA16_LD2		0x18
+#define R_ARC_S13_PCREL		0x19
+#define R_ARC_W			0x1A
+#define R_ARC_32_ME		0x1B
+#define R_ARC_N32_ME		0x1C
+#define R_ARC_SECTOFF_ME	0x1D
+#define R_ARC_SDA32_ME		0x1E
+#define R_ARC_W_ME		0x1F
+#define R_ARC_H30_ME		0x20
+#define R_ARC_SECTOFF_U8	0x21
+#define R_ARC_SECTOFF_S9	0x22
+#define R_AC_SECTOFF_U8		0x23
+#define R_AC_SECTOFF_U8_1	0x24
+#define R_AC_SECTOFF_U8_2	0x25
+#define R_AC_SECTOFF_S9		0x26
+#define R_AC_SECTOFF_S9_1	0x27
+#define R_AC_SECTOFF_S9_2	0x28
+#define R_ARC_SECTOFF_ME_1	0x29
+#define R_ARC_SECTOFF_ME_2	0x2A
+#define R_ARC_SECTOFF_1		0x2B
+#define R_ARC_SECTOFF_2		0x2C
+#define R_ARC_SDA_12		0x2D
+#define R_ARC_SDA16_ST2		0x30
+#define R_ARC_32_PCREL		0x31
+#define R_ARC_PC32		0x32
+#define R_ARC_GOTPC32		0x33
+#define R_ARC_PLT32		0x34
+#define R_ARC_COPY		0x35
+#define R_ARC_GLOB_DAT		0x36
+#define R_ARC_JMP_SLOT		0x37
+#define R_ARC_RELATIVE		0x38
+#define R_ARC_GOTOFF		0x39
+#define R_ARC_GOTPC		0x3A
+#define R_ARC_GOT32		0x3B
+#define R_ARC_S21W_PCREL_PLT	0x3C
+#define R_ARC_S25H_PCREL_PLT	0x3D
+
+#define R_ARC_JLI_SECTOFF	0x3F
+
+#define R_ARC_TLS_DTPMOD	0x42
+#define R_ARC_TLS_DTPOFF	0x43
+#define R_ARC_TLS_TPOFF		0x44
+#define R_ARC_TLS_GD_GOT	0x45
+#define R_ARC_TLS_GD_LD	        0x46
+#define R_ARC_TLS_GD_CALL	0x47
+#define R_ARC_TLS_IE_GOT	0x48
+#define R_ARC_TLS_DTPOFF_S9	0x49
+#define R_ARC_TLS_LE_S9		0x4A
+#define R_ARC_TLS_LE_32		0x4B
+#define R_ARC_S25W_PCREL_PLT	0x4C
+#define R_ARC_S21H_PCREL_PLT	0x4D
+#define R_ARC_NPS_CMEM16	0x4E
+
+/* OpenRISC 1000 specific relocs.  */
+#define R_OR1K_NONE		0
+#define R_OR1K_32		1
+#define R_OR1K_16		2
+#define R_OR1K_8		3
+#define R_OR1K_LO_16_IN_INSN	4
+#define R_OR1K_HI_16_IN_INSN	5
+#define R_OR1K_INSN_REL_26	6
+#define R_OR1K_GNU_VTENTRY	7
+#define R_OR1K_GNU_VTINHERIT	8
+#define R_OR1K_32_PCREL		9
+#define R_OR1K_16_PCREL		10
+#define R_OR1K_8_PCREL		11
+#define R_OR1K_GOTPC_HI16	12
+#define R_OR1K_GOTPC_LO16	13
+#define R_OR1K_GOT16		14
+#define R_OR1K_PLT26		15
+#define R_OR1K_GOTOFF_HI16	16
+#define R_OR1K_GOTOFF_LO16	17
+#define R_OR1K_COPY		18
+#define R_OR1K_GLOB_DAT		19
+#define R_OR1K_JMP_SLOT		20
+#define R_OR1K_RELATIVE		21
+#define R_OR1K_TLS_GD_HI16	22
+#define R_OR1K_TLS_GD_LO16	23
+#define R_OR1K_TLS_LDM_HI16	24
+#define R_OR1K_TLS_LDM_LO16	25
+#define R_OR1K_TLS_LDO_HI16	26
+#define R_OR1K_TLS_LDO_LO16	27
+#define R_OR1K_TLS_IE_HI16	28
+#define R_OR1K_TLS_IE_LO16	29
+#define R_OR1K_TLS_LE_HI16	30
+#define R_OR1K_TLS_LE_LO16	31
+#define R_OR1K_TLS_TPOFF	32
+#define R_OR1K_TLS_DTPOFF	33
+#define R_OR1K_TLS_DTPMOD	34
+
+#endif	/* elf.h */
diff --git a/libelf/elf32_checksum.c b/libelf/elf32_checksum.c
new file mode 100644
index 0000000..a47b307
--- /dev/null
+++ b/libelf/elf32_checksum.c
@@ -0,0 +1,167 @@
+/* Compute simple checksum from permanent parts of the ELF file.
+   Copyright (C) 2002, 2003, 2004, 2005, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "gelf.h"
+#include "libelfP.h"
+#include "elf-knowledge.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+#define process_block(crc, data) \
+  __libelf_crc32 (crc, data->d_buf, data->d_size)
+
+
+long int
+elfw2(LIBELFBITS,checksum) (Elf *elf)
+{
+  size_t shstrndx;
+  Elf_Scn *scn;
+  long int result = 0;
+  unsigned char *ident;
+  bool same_byte_order;
+
+  if (elf == NULL)
+    return -1l;
+
+  /* Find the section header string table.  */
+  if  (INTUSE(elf_getshdrstrndx) (elf, &shstrndx) < 0)
+    {
+      /* This can only happen if the ELF handle is not for real.  */
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return -1l;
+    }
+
+  /* Determine whether the byte order of the file and that of the host
+     is the same.  */
+  ident = elf->state.ELFW(elf,LIBELFBITS).ehdr->e_ident;
+  same_byte_order = ((ident[EI_DATA] == ELFDATA2LSB
+		      && BYTE_ORDER == LITTLE_ENDIAN)
+		     || (ident[EI_DATA] == ELFDATA2MSB
+			 && BYTE_ORDER == BIG_ENDIAN));
+
+  /* If we don't have native byte order, we will likely need to
+     convert the data with xlate functions.  We do it upfront instead
+     of relocking mid-iteration. */
+  if (!likely (same_byte_order))
+    rwlock_wrlock (elf->lock);
+  else
+    rwlock_rdlock (elf->lock);
+
+  /* Iterate over all sections to find those which are not strippable.  */
+  scn = NULL;
+  while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+      Elf_Data *data;
+
+      /* Get the section header.  */
+      shdr = INTUSE(gelf_getshdr) (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+	  result = -1l;
+	  goto out;
+	}
+
+      if (SECTION_STRIP_P (shdr,
+			   INTUSE(elf_strptr) (elf, shstrndx, shdr->sh_name),
+			   true))
+	/* The section can be stripped.  Don't use it.  */
+	continue;
+
+      /* Do not look at NOBITS sections.  */
+      if (shdr->sh_type == SHT_NOBITS)
+	continue;
+
+      /* To compute the checksum we need to get to the data.  For
+	 repeatable results we must use the external format.  The data
+	 we get with 'elf'getdata' might be changed for endianness
+	 reasons.  Therefore we use 'elf_rawdata' if possible.  But
+	 this function can fail if the data was constructed by the
+	 program.  In this case we have to use 'elf_getdata' and
+	 eventually convert the data to the external format.  */
+      data = INTUSE(elf_rawdata) (scn, NULL);
+      if (data != NULL)
+	{
+	  /* The raw data is available.  */
+	  result = process_block (result, data);
+
+	  /* Maybe the user added more data.  These blocks cannot be
+	     read using 'elf_rawdata'.  Simply proceed with looking
+	     for more data block with 'elf_getdata'.  */
+	}
+
+      /* Iterate through the list of data blocks.  */
+      while ((data = INTUSE(elf_getdata) (scn, data)) != NULL)
+	/* If the file byte order is the same as the host byte order
+	   process the buffer directly.  If the data is just a stream
+	   of bytes which the library will not convert we can use it
+	   as well.  */
+	if (likely (same_byte_order) || data->d_type == ELF_T_BYTE)
+	  result = process_block (result, data);
+	else
+	  {
+	    /* Convert the data to file byte order.  */
+	    if (INTUSE(elfw2(LIBELFBITS,xlatetof)) (data, data, ident[EI_DATA])
+		== NULL)
+	      {
+		result = -1l;
+		goto out;
+	      }
+
+	    result = process_block (result, data);
+
+	    /* And convert it back.  */
+	    if (INTUSE(elfw2(LIBELFBITS,xlatetom)) (data, data, ident[EI_DATA])
+		== NULL)
+	      {
+		result = -1l;
+		goto out;
+	      }
+	  }
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+  return result;
+}
+INTDEF(elfw2(LIBELFBITS,checksum))
diff --git a/libelf/elf32_fsize.c b/libelf/elf32_fsize.c
new file mode 100644
index 0000000..139f4a9
--- /dev/null
+++ b/libelf/elf32_fsize.c
@@ -0,0 +1,60 @@
+/* Return the size of an object file type.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+size_t
+elfw2(LIBELFBITS, fsize) (Elf_Type type, size_t count, unsigned int version)
+{
+  /* We do not have differences between file and memory sizes.  Better
+     not since otherwise `mmap' would not work.  */
+  if (unlikely (version != EV_CURRENT))
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
+      return 0;
+    }
+
+  if (unlikely (type >= ELF_T_NUM))
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
+      return 0;
+    }
+
+  return (count * __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][type]);
+}
diff --git a/libelf/elf32_getchdr.c b/libelf/elf32_getchdr.c
new file mode 100644
index 0000000..4159130
--- /dev/null
+++ b/libelf/elf32_getchdr.c
@@ -0,0 +1,45 @@
+/* Return section compression header.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include "libelfP.h"
+#include "common.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+#define ELF_WRLOCK_HELD 1
+#include "elf32_getchdr.h"
+
+#define ELF_WRLOCK_HELD 0
+#include "elf32_getchdr.h"
\ No newline at end of file
diff --git a/libelf/elf32_getchdr.h b/libelf/elf32_getchdr.h
new file mode 100644
index 0000000..04d47e7
--- /dev/null
+++ b/libelf/elf32_getchdr.h
@@ -0,0 +1,61 @@
+#undef ADD_ROUTINE_PREFIX
+#undef ADD_ROUTINE_SUFFIX
+
+#if ELF_WRLOCK_HELD
+#define CONCAT(x,y) x##y
+#define ADD_ROUTINE_PREFIX(y) CONCAT(__,y)
+#define ADD_ROUTINE_SUFFIX(x) x ## _wrlock
+#define INTERNAL internal_function
+#else
+#define ADD_ROUTINE_PREFIX(y) y
+#define ADD_ROUTINE_SUFFIX(x) x
+#define INTERNAL
+#endif
+
+ElfW2(LIBELFBITS,Chdr) *
+INTERNAL
+ADD_ROUTINE_PREFIX(elfw2(LIBELFBITS, ADD_ROUTINE_SUFFIX(getchdr))) (Elf_Scn *scn)
+{
+
+  ElfW2(LIBELFBITS,Shdr) *shdr = ADD_ROUTINE_PREFIX(elfw2(LIBELFBITS, ADD_ROUTINE_SUFFIX(getshdr)))(scn);
+
+  if (shdr == NULL)
+    return NULL;
+
+  /* Must have SHF_COMPRESSED flag set.  Allocated or no bits sections
+     can never be compressed.  */
+  if ((shdr->sh_flags & SHF_ALLOC) != 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
+      return NULL;
+    }
+
+  if (shdr->sh_type == SHT_NULL
+      || shdr->sh_type == SHT_NOBITS)
+    {
+      __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
+      return NULL;
+    }
+
+  if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
+    {
+      __libelf_seterrno (ELF_E_NOT_COMPRESSED);
+      return NULL;
+    }
+
+  /* This makes sure the data is in the correct format, so we don't
+     need to swap fields. */
+  Elf_Data *d  = ADD_ROUTINE_PREFIX(ADD_ROUTINE_SUFFIX(elf_getdata)) (scn, NULL);
+  if (d == NULL)
+    return NULL;
+
+  if (d->d_size < sizeof (ElfW2(LIBELFBITS,Chdr)) || d->d_buf == NULL)
+    {
+      __libelf_seterrno (ELF_E_INVALID_DATA);
+      return NULL;
+    }
+
+  return (ElfW2(LIBELFBITS,Chdr) *) d->d_buf;
+}
+#undef INTERNAL
+#undef ELF_WRLOCK_HELD
\ No newline at end of file
diff --git a/libelf/elf32_getehdr.c b/libelf/elf32_getehdr.c
new file mode 100644
index 0000000..89e3c40
--- /dev/null
+++ b/libelf/elf32_getehdr.c
@@ -0,0 +1,96 @@
+/* Get ELF header.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+static ElfW2(LIBELFBITS,Ehdr) *
+getehdr_impl (Elf *elf, int wrlock)
+{
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+ again:
+  if (elf->class == 0)
+    {
+      if (!wrlock)
+	{
+	  rwlock_unlock (elf->lock);
+	  rwlock_wrlock (elf->lock);
+	  wrlock = 1;
+	  goto again;
+	}
+      elf->class = ELFW(ELFCLASS,LIBELFBITS);
+    }
+  else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
+    {
+      __libelf_seterrno (ELF_E_INVALID_CLASS);
+      return NULL;
+    }
+
+  return elf->state.ELFW(elf,LIBELFBITS).ehdr;
+}
+
+ElfW2(LIBELFBITS,Ehdr) *
+internal_function
+__elfw2(LIBELFBITS,getehdr_wrlock) (Elf *elf)
+{
+  return getehdr_impl (elf, 1);
+}
+
+ElfW2(LIBELFBITS,Ehdr) *
+elfw2(LIBELFBITS,getehdr) (Elf *elf)
+{
+  ElfW2(LIBELFBITS,Ehdr) *result;
+  if (elf == NULL)
+    return NULL;
+
+  rwlock_rdlock (elf->lock);
+  result = getehdr_impl (elf, 0);
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/elf32_getphdr.c b/libelf/elf32_getphdr.c
new file mode 100644
index 0000000..4bfca24
--- /dev/null
+++ b/libelf/elf32_getphdr.c
@@ -0,0 +1,263 @@
+/* Get ELF program header table.
+   Copyright (C) 1998-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "libelfP.h"
+#include "common.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+ElfW2(LIBELFBITS,Phdr) *
+__elfw2(LIBELFBITS,getphdr_wrlock) (Elf *elf)
+{
+  ElfW2(LIBELFBITS,Phdr) *result;
+
+  /* If the program header entry has already been filled in the code
+     below must already have been run.  So the class is set, too.  No
+     need to waste any more time here.  */
+  result = elf->state.ELFW(elf,LIBELFBITS).phdr;
+  if (likely (result != NULL))
+    return result;
+
+  if (elf->class == 0)
+    elf->class = ELFW(ELFCLASS,LIBELFBITS);
+  else if (elf->class != ELFW(ELFCLASS,LIBELFBITS))
+    {
+      __libelf_seterrno (ELF_E_INVALID_CLASS);
+      result = NULL;
+      goto out;
+    }
+
+  if (likely (result == NULL))
+    {
+      /* Read the section header table.  */
+      ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+
+      /* If no program header exists return NULL.  */
+      size_t phnum;
+      if (__elf_getphdrnum_rdlock (elf, &phnum) != 0)
+	goto out;
+      if (phnum == 0 || ehdr->e_phoff == 0)
+	{
+	  __libelf_seterrno (ELF_E_NO_PHDR);
+	  goto out;
+	}
+
+      /* Check this doesn't overflow.  */
+      size_t size = phnum * sizeof (ElfW2(LIBELFBITS,Phdr));
+
+      if (phnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))
+	  || ehdr->e_phoff > elf->maximum_size
+	  || elf->maximum_size - ehdr->e_phoff < size)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      if (elf->map_address != NULL)
+	{
+	  /* First see whether the information in the ELF header is
+	     valid and it does not ask for too much.  */
+	  if (unlikely (ehdr->e_phoff >= elf->maximum_size)
+	      || unlikely (elf->maximum_size - ehdr->e_phoff < size))
+	    {
+	      /* Something is wrong.  */
+	      __libelf_seterrno (ELF_E_INVALID_PHDR);
+	      goto out;
+	    }
+
+	  /* All the data is already mapped.  Use it.  */
+	  void *file_phdr = ((char *) elf->map_address
+			     + elf->start_offset + ehdr->e_phoff);
+	  if (ehdr->e_ident[EI_DATA] == MY_ELFDATA
+	      && (ALLOW_UNALIGNED
+		  || ((uintptr_t) file_phdr
+		      & (__alignof__ (ElfW2(LIBELFBITS,Phdr)) - 1)) == 0))
+	    /* Simply use the mapped data.  */
+	    elf->state.ELFW(elf,LIBELFBITS).phdr = file_phdr;
+	  else
+	    {
+	      ElfW2(LIBELFBITS,Phdr) *notcvt;
+	      ElfW2(LIBELFBITS,Phdr) *phdr;
+
+	      /* Allocate memory for the program headers.  We know the number
+		 of entries from the ELF header.  */
+	      phdr = elf->state.ELFW(elf,LIBELFBITS).phdr =
+		(ElfW2(LIBELFBITS,Phdr) *) malloc (size);
+	      if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
+		{
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  goto out;
+		}
+	      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
+		ELF_F_MALLOCED | ELF_F_DIRTY;
+
+	      /* Now copy the data and at the same time convert the
+		 byte order.  */
+
+	      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
+		{
+		  assert (! ALLOW_UNALIGNED);
+		  memcpy (phdr, file_phdr, size);
+		}
+	      else
+		{
+		  bool copy = ! (ALLOW_UNALIGNED
+				 || ((uintptr_t) file_phdr
+				     & (__alignof__ (ElfW2(LIBELFBITS,Phdr))
+					- 1)) == 0);
+		  if (! copy)
+		    notcvt = file_phdr;
+		  else
+		    {
+		      notcvt = (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
+		      if (unlikely (notcvt == NULL))
+			{
+			  __libelf_seterrno (ELF_E_NOMEM);
+			  goto out;
+			}
+		      memcpy (notcvt, file_phdr, size);
+		    }
+
+		  for (size_t cnt = 0; cnt < phnum; ++cnt)
+		    {
+		      CONVERT_TO (phdr[cnt].p_type, notcvt[cnt].p_type);
+		      CONVERT_TO (phdr[cnt].p_offset, notcvt[cnt].p_offset);
+		      CONVERT_TO (phdr[cnt].p_vaddr, notcvt[cnt].p_vaddr);
+		      CONVERT_TO (phdr[cnt].p_paddr, notcvt[cnt].p_paddr);
+		      CONVERT_TO (phdr[cnt].p_filesz, notcvt[cnt].p_filesz);
+		      CONVERT_TO (phdr[cnt].p_memsz, notcvt[cnt].p_memsz);
+		      CONVERT_TO (phdr[cnt].p_flags, notcvt[cnt].p_flags);
+		      CONVERT_TO (phdr[cnt].p_align, notcvt[cnt].p_align);
+		    }
+
+		  if (copy)
+		    free (notcvt);
+		}
+	    }
+	}
+      else if (likely (elf->fildes != -1))
+	{
+	  /* Allocate memory for the program headers.  We know the number
+	     of entries from the ELF header.  */
+	  elf->state.ELFW(elf,LIBELFBITS).phdr =
+	    (ElfW2(LIBELFBITS,Phdr) *) malloc (size);
+	  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      goto out;
+	    }
+	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_MALLOCED;
+
+	  /* Read the header.  */
+	  ssize_t n = pread_retry (elf->fildes,
+				   elf->state.ELFW(elf,LIBELFBITS).phdr, size,
+				   elf->start_offset + ehdr->e_phoff);
+	  if (unlikely ((size_t) n != size))
+	    {
+	      /* Severe problems.  We cannot read the data.  */
+	      __libelf_seterrno (ELF_E_READ_ERROR);
+	      free (elf->state.ELFW(elf,LIBELFBITS).phdr);
+	      elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
+	      goto out;
+	    }
+
+	  /* If the byte order of the file is not the same as the one
+	     of the host convert the data now.  */
+	  if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
+	    {
+	      ElfW2(LIBELFBITS,Phdr) *phdr
+		= elf->state.ELFW(elf,LIBELFBITS).phdr;
+
+	      for (size_t cnt = 0; cnt < phnum; ++cnt)
+		{
+		  CONVERT (phdr[cnt].p_type);
+		  CONVERT (phdr[cnt].p_offset);
+		  CONVERT (phdr[cnt].p_vaddr);
+		  CONVERT (phdr[cnt].p_paddr);
+		  CONVERT (phdr[cnt].p_filesz);
+		  CONVERT (phdr[cnt].p_memsz);
+		  CONVERT (phdr[cnt].p_flags);
+		  CONVERT (phdr[cnt].p_align);
+		}
+	    }
+	}
+      else
+	{
+	  /* The file descriptor was already enabled and not all data was
+	     read.  */
+	  __libelf_seterrno (ELF_E_FD_DISABLED);
+	  goto out;
+	}
+
+      result = elf->state.ELFW(elf,LIBELFBITS).phdr;
+    }
+
+ out:
+  return result;
+}
+
+ElfW2(LIBELFBITS,Phdr) *
+elfw2(LIBELFBITS,getphdr) (Elf *elf)
+{
+  ElfW2(LIBELFBITS,Phdr) *result;
+
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* If the program header entry has already been filled in the code
+   * in getphdr_wrlock must already have been run.  So the class is
+   * set, too.  No need to waste any more time here.  */
+  result = elf->state.ELFW(elf,LIBELFBITS).phdr;
+  if (likely (result != NULL))
+    return result;
+
+  rwlock_wrlock (elf->lock);
+  result = __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elfw2(LIBELFBITS,getphdr))
diff --git a/libelf/elf32_getshdr.c b/libelf/elf32_getshdr.c
new file mode 100644
index 0000000..fc69630
--- /dev/null
+++ b/libelf/elf32_getshdr.c
@@ -0,0 +1,297 @@
+/* Return section header.
+   Copyright (C) 1998-2002, 2005, 2007, 2009, 2012, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#include "libelfP.h"
+#include "common.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+static ElfW2(LIBELFBITS,Shdr) *
+load_shdr_wrlock (Elf_Scn *scn)
+{
+  ElfW2(LIBELFBITS,Shdr) *result;
+
+  /* Read the section header table.  */
+  Elf *elf = scn->elf;
+  ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+
+  /* Try again, maybe the data is there now.  */
+  result = scn->shdr.ELFW(e,LIBELFBITS);
+  if (result != NULL)
+    goto out;
+
+  size_t shnum;
+  if (__elf_getshdrnum_rdlock (elf, &shnum) != 0
+      || shnum > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Shdr)))
+    goto out;
+  size_t size = shnum * sizeof (ElfW2(LIBELFBITS,Shdr));
+
+  /* Allocate memory for the section headers.  We know the number
+     of entries from the ELF header.  */
+  ElfW2(LIBELFBITS,Shdr) *shdr = elf->state.ELFW(elf,LIBELFBITS).shdr =
+    (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
+  if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL)
+    {
+      __libelf_seterrno (ELF_E_NOMEM);
+      goto out;
+    }
+  elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 1;
+
+  if (elf->map_address != NULL)
+    {
+      /* First see whether the information in the ELF header is
+	 valid and it does not ask for too much.  */
+      if (unlikely (ehdr->e_shoff >= elf->maximum_size)
+	  || unlikely (elf->maximum_size - ehdr->e_shoff < size))
+	{
+	  /* Something is wrong.  */
+	  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+	  goto free_and_out;
+	}
+
+      ElfW2(LIBELFBITS,Shdr) *notcvt;
+
+      /* All the data is already mapped.  If we could use it
+	 directly this would already have happened.  Unless
+	 we allocated the memory ourselves and the ELF_F_MALLOCED
+	 flag is set.  */
+      void *file_shdr = ((char *) elf->map_address
+			 + elf->start_offset + ehdr->e_shoff);
+
+      assert ((elf->flags & ELF_F_MALLOCED)
+	      || ehdr->e_ident[EI_DATA] != MY_ELFDATA
+	      || elf->cmd == ELF_C_READ_MMAP
+	      || (! ALLOW_UNALIGNED
+		  && ((uintptr_t) file_shdr
+		      & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1)) != 0));
+
+      /* Now copy the data and at the same time convert the byte order.  */
+      if (ehdr->e_ident[EI_DATA] == MY_ELFDATA)
+	{
+	  assert ((elf->flags & ELF_F_MALLOCED)
+		  || elf->cmd == ELF_C_READ_MMAP
+		  || ! ALLOW_UNALIGNED);
+	  memcpy (shdr, file_shdr, size);
+	}
+      else
+	{
+	  bool copy = ! (ALLOW_UNALIGNED
+			 || ((uintptr_t) file_shdr
+			     & (__alignof__ (ElfW2(LIBELFBITS,Shdr)) - 1))
+			     == 0);
+	  if (! copy)
+	    notcvt = (ElfW2(LIBELFBITS,Shdr) *)
+	      ((char *) elf->map_address
+	       + elf->start_offset + ehdr->e_shoff);
+	  else
+	    {
+	      notcvt = (ElfW2(LIBELFBITS,Shdr) *) malloc (size);
+	      if (unlikely (notcvt == NULL))
+		{
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  goto out;
+		}
+	      memcpy (notcvt, ((char *) elf->map_address
+			       + elf->start_offset + ehdr->e_shoff),
+		      size);
+	    }
+
+	  for (size_t cnt = 0; cnt < shnum; ++cnt)
+	    {
+	      CONVERT_TO (shdr[cnt].sh_name, notcvt[cnt].sh_name);
+	      CONVERT_TO (shdr[cnt].sh_type, notcvt[cnt].sh_type);
+	      CONVERT_TO (shdr[cnt].sh_flags, notcvt[cnt].sh_flags);
+	      CONVERT_TO (shdr[cnt].sh_addr, notcvt[cnt].sh_addr);
+	      CONVERT_TO (shdr[cnt].sh_offset, notcvt[cnt].sh_offset);
+	      CONVERT_TO (shdr[cnt].sh_size, notcvt[cnt].sh_size);
+	      CONVERT_TO (shdr[cnt].sh_link, notcvt[cnt].sh_link);
+	      CONVERT_TO (shdr[cnt].sh_info, notcvt[cnt].sh_info);
+	      CONVERT_TO (shdr[cnt].sh_addralign,
+			  notcvt[cnt].sh_addralign);
+	      CONVERT_TO (shdr[cnt].sh_entsize, notcvt[cnt].sh_entsize);
+
+	      /* If this is a section with an extended index add a
+		 reference in the section which uses the extended
+		 index.  */
+	      if (shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
+		  && shdr[cnt].sh_link < shnum)
+		elf->state.ELFW(elf,LIBELFBITS).scns.data[shdr[cnt].sh_link].shndx_index
+		  = cnt;
+
+	      /* Set the own shndx_index field in case it has not yet
+		 been set.  */
+	      if (elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index == 0)
+		elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shndx_index
+		  = -1;
+	    }
+
+	  if (copy)
+	    free (notcvt);
+	}
+    }
+  else if (likely (elf->fildes != -1))
+    {
+      /* Read the header.  */
+      ssize_t n = pread_retry (elf->fildes,
+			       elf->state.ELFW(elf,LIBELFBITS).shdr, size,
+			       elf->start_offset + ehdr->e_shoff);
+      if (unlikely ((size_t) n != size))
+	{
+	  /* Severe problems.  We cannot read the data.  */
+	  __libelf_seterrno (ELF_E_READ_ERROR);
+	  goto free_and_out;
+	}
+
+      /* If the byte order of the file is not the same as the one
+	 of the host convert the data now.  */
+      if (ehdr->e_ident[EI_DATA] != MY_ELFDATA)
+	for (size_t cnt = 0; cnt < shnum; ++cnt)
+	  {
+	    CONVERT (shdr[cnt].sh_name);
+	    CONVERT (shdr[cnt].sh_type);
+	    CONVERT (shdr[cnt].sh_flags);
+	    CONVERT (shdr[cnt].sh_addr);
+	    CONVERT (shdr[cnt].sh_offset);
+	    CONVERT (shdr[cnt].sh_size);
+	    CONVERT (shdr[cnt].sh_link);
+	    CONVERT (shdr[cnt].sh_info);
+	    CONVERT (shdr[cnt].sh_addralign);
+	    CONVERT (shdr[cnt].sh_entsize);
+	  }
+    }
+  else
+    {
+      /* The file descriptor was already enabled and not all data was
+	 read.  Undo the allocation.  */
+      __libelf_seterrno (ELF_E_FD_DISABLED);
+
+    free_and_out:
+      free (shdr);
+      elf->state.ELFW(elf,LIBELFBITS).shdr = NULL;
+      elf->state.ELFW(elf,LIBELFBITS).shdr_malloced = 0;
+
+      goto out;
+    }
+
+  /* Set the pointers in the `scn's.  */
+  for (size_t cnt = 0; cnt < shnum; ++cnt)
+    elf->state.ELFW(elf,LIBELFBITS).scns.data[cnt].shdr.ELFW(e,LIBELFBITS)
+      = &elf->state.ELFW(elf,LIBELFBITS).shdr[cnt];
+
+  result = scn->shdr.ELFW(e,LIBELFBITS);
+  assert (result != NULL);
+
+out:
+  return result;
+}
+
+static bool
+scn_valid (Elf_Scn *scn)
+{
+  if (scn == NULL)
+    return false;
+
+  if (unlikely (scn->elf->state.elf.ehdr == NULL))
+    {
+      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+      return false;
+    }
+
+  if (unlikely (scn->elf->class != ELFW(ELFCLASS,LIBELFBITS)))
+    {
+      __libelf_seterrno (ELF_E_INVALID_CLASS);
+      return false;
+    }
+
+  return true;
+}
+
+ElfW2(LIBELFBITS,Shdr) *
+internal_function
+__elfw2(LIBELFBITS,getshdr_rdlock) (Elf_Scn *scn)
+{
+  ElfW2(LIBELFBITS,Shdr) *result;
+
+  if (!scn_valid (scn))
+    return NULL;
+
+  result = scn->shdr.ELFW(e,LIBELFBITS);
+  if (result == NULL)
+    {
+      rwlock_unlock (scn->elf->lock);
+      rwlock_wrlock (scn->elf->lock);
+      result = scn->shdr.ELFW(e,LIBELFBITS);
+      if (result == NULL)
+	result = load_shdr_wrlock (scn);
+    }
+
+  return result;
+}
+
+ElfW2(LIBELFBITS,Shdr) *
+internal_function
+__elfw2(LIBELFBITS,getshdr_wrlock) (Elf_Scn *scn)
+{
+  ElfW2(LIBELFBITS,Shdr) *result;
+
+  if (!scn_valid (scn))
+    return NULL;
+
+  result = scn->shdr.ELFW(e,LIBELFBITS);
+  if (result == NULL)
+    result = load_shdr_wrlock (scn);
+
+  return result;
+}
+
+ElfW2(LIBELFBITS,Shdr) *
+elfw2(LIBELFBITS,getshdr) (Elf_Scn *scn)
+{
+  ElfW2(LIBELFBITS,Shdr) *result;
+
+  if (!scn_valid (scn))
+    return NULL;
+
+  rwlock_rdlock (scn->elf->lock);
+  result = __elfw2(LIBELFBITS,getshdr_rdlock) (scn);
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/elf32_newehdr.c b/libelf/elf32_newehdr.c
new file mode 100644
index 0000000..775d115
--- /dev/null
+++ b/libelf/elf32_newehdr.c
@@ -0,0 +1,91 @@
+/* Create new ELF header.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+ElfW2(LIBELFBITS,Ehdr) *
+elfw2(LIBELFBITS,newehdr) (Elf *elf)
+{
+  ElfW2(LIBELFBITS,Ehdr) *result;
+
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  rwlock_wrlock (elf->lock);
+
+  if (elf->class == 0)
+    elf->class = ELFW(ELFCLASS,LIBELFBITS);
+  else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
+    {
+      __libelf_seterrno (ELF_E_INVALID_CLASS);
+      result = NULL;
+      goto out;
+    }
+
+  /* Don't create an ELF header if one already exists.  */
+  if (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL)
+    {
+      /* We use the memory in the ELF descriptor.  */
+      elf->state.ELFW(elf,LIBELFBITS).ehdr =
+	&elf->state.ELFW(elf,LIBELFBITS).ehdr_mem;
+
+      /* We clear this memory.  */
+      memset (elf->state.ELFW(elf,LIBELFBITS).ehdr, '\0',
+	      sizeof (ElfW2(LIBELFBITS,Ehdr)));
+
+      /* Mark the ELF header has modified.  */
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
+    }
+
+  result = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elfw2(LIBELFBITS,newehdr))
diff --git a/libelf/elf32_newphdr.c b/libelf/elf32_newphdr.c
new file mode 100644
index 0000000..7dd78ca
--- /dev/null
+++ b/libelf/elf32_newphdr.c
@@ -0,0 +1,193 @@
+/* Create new ELF program header table.
+   Copyright (C) 1999-2010, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+ElfW2(LIBELFBITS,Phdr) *
+elfw2(LIBELFBITS,newphdr) (Elf *elf, size_t count)
+{
+  ElfW2(LIBELFBITS,Phdr) *result;
+
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* This check is correct, it is for sh_info, which is either
+     Elf32_Word or Elf64_Word, both being 32 bits.  But count is size_t
+     so might not fit on 32bit ELF files.  */
+  if (unlikely ((ElfW2(LIBELFBITS,Word)) count != count))
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return NULL;
+    }
+
+  rwlock_wrlock (elf->lock);
+
+  if (elf->class == 0)
+    elf->class = ELFW(ELFCLASS,LIBELFBITS);
+  else if (unlikely (elf->class != ELFW(ELFCLASS,LIBELFBITS)))
+    {
+      __libelf_seterrno (ELF_E_INVALID_CLASS);
+      result = NULL;
+      goto out;
+    }
+
+  if (unlikely (elf->state.ELFW(elf,LIBELFBITS).ehdr == NULL))
+    {
+      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+      result = NULL;
+      goto out;
+    }
+
+  /* A COUNT of zero means remove existing table.  */
+  if (count == 0)
+    {
+      /* Free the old program header.  */
+      if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
+	{
+	  if (elf->state.ELFW(elf,LIBELFBITS).phdr_flags & ELF_F_MALLOCED)
+	    free (elf->state.ELFW(elf,LIBELFBITS).phdr);
+
+	  /* Set the pointer to NULL.  */
+	  elf->state.ELFW(elf,LIBELFBITS).phdr = NULL;
+	  /* Set the `e_phnum' member to the new value.  */
+	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = 0;
+	  /* Also clear any old PN_XNUM extended value.  */
+	  if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0)
+	    elf->state.ELFW(elf,LIBELFBITS).scns.data[0]
+	      .shdr.ELFW(e,LIBELFBITS)->sh_info = 0;
+	  /* Also set the size.  */
+	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
+	    sizeof (ElfW2(LIBELFBITS,Phdr));
+
+	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
+	  elf->flags |= ELF_F_DIRTY;
+	  __libelf_seterrno (ELF_E_NOERROR);
+	}
+
+      result = NULL;
+    }
+  else if (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum != count
+	   || count == PN_XNUM
+	   || elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
+    {
+      if (unlikely (count > SIZE_MAX / sizeof (ElfW2(LIBELFBITS,Phdr))))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  result = NULL;
+	  goto out;
+	}
+
+      Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
+      if (unlikely (count >= PN_XNUM && scn0->shdr.ELFW(e,LIBELFBITS) == NULL))
+	{
+	  /* Something is wrong with section zero, but we need it to write
+	     the extended phdr count.  */
+	  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+	  result = NULL;
+	  goto out;
+	}
+
+      /* Allocate a new program header with the appropriate number of
+	 elements.  */
+      result = (ElfW2(LIBELFBITS,Phdr) *)
+	realloc (elf->state.ELFW(elf,LIBELFBITS).phdr,
+		 count * sizeof (ElfW2(LIBELFBITS,Phdr)));
+      if (result == NULL)
+	__libelf_seterrno (ELF_E_NOMEM);
+      else
+	{
+	  /* Now set the result.  */
+	  elf->state.ELFW(elf,LIBELFBITS).phdr = result;
+	  if (count >= PN_XNUM)
+	    {
+	      /* We have to write COUNT into the zeroth section's sh_info.  */
+	      if (elf->state.ELFW(elf,LIBELFBITS).scns.cnt == 0)
+		{
+		  assert (elf->state.ELFW(elf,LIBELFBITS).scns.max > 0);
+		  elf->state.ELFW(elf,LIBELFBITS).scns.cnt = 1;
+		}
+	      scn0->shdr.ELFW(e,LIBELFBITS)->sh_info = count;
+	      scn0->shdr_flags |= ELF_F_DIRTY;
+	      elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = PN_XNUM;
+	    }
+	  else
+	    /* Set the `e_phnum' member to the new value.  */
+	    elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phnum = count;
+	  /* Clear the whole memory.  */
+	  memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
+	  /* Also set the size.  */
+	  elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize =
+	    elf_typesize (LIBELFBITS, ELF_T_PHDR, 1);
+	  /* Remember we allocated the array and mark the structure is
+	     modified.  */
+	  elf->state.ELFW(elf,LIBELFBITS).phdr_flags |=
+	    ELF_F_DIRTY | ELF_F_MALLOCED;
+	  /* We have to rewrite the entire file if the size of the
+	     program header is changed.  */
+	  elf->flags |= ELF_F_DIRTY;
+	}
+    }
+  else
+    {
+      /* We have the same number of entries.  Just clear the array.  */
+      assert (elf->state.ELFW(elf,LIBELFBITS).ehdr->e_phentsize
+	      == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
+
+      /* Mark the structure as modified.  */
+      elf->state.ELFW(elf,LIBELFBITS).phdr_flags |= ELF_F_DIRTY;
+
+      result = elf->state.ELFW(elf,LIBELFBITS).phdr;
+      memset (result, '\0', count * sizeof (ElfW2(LIBELFBITS,Phdr)));
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elfw2(LIBELFBITS,newphdr))
diff --git a/libelf/elf32_offscn.c b/libelf/elf32_offscn.c
new file mode 100644
index 0000000..9e757c8
--- /dev/null
+++ b/libelf/elf32_offscn.c
@@ -0,0 +1,99 @@
+/* Get section at specific index.
+   Copyright (C) 2005, 2008, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+Elf_Scn *
+elfw2(LIBELFBITS,offscn) (Elf *elf, ElfW2(LIBELFBITS,Off) offset)
+{
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  Elf_ScnList *runp = &elf->state.ELFW(elf,LIBELFBITS).scns;
+
+  /* If we have not looked at section headers before,
+     we might need to read them in first.  */
+  if (runp->cnt > 0
+      && unlikely (runp->data[0].shdr.ELFW(e,LIBELFBITS) == NULL)
+      && unlikely (elfw2(LIBELFBITS,getshdr) (&runp->data[0]) == NULL))
+    return NULL;
+
+  rwlock_rdlock (elf->lock);
+
+  Elf_Scn *result = NULL;
+
+  /* Find the section in the list.  */
+  while (1)
+    {
+      for (unsigned int i = 0; i < runp->cnt; ++i)
+	if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_offset == offset)
+	  {
+	    result = &runp->data[i];
+
+	    /* If this section is empty, the following one has the same
+	       sh_offset.  We presume the caller is looking for a nonempty
+	       section, so keep looking if this one is empty.  */
+	    if (runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_size != 0
+		&& runp->data[i].shdr.ELFW(e,LIBELFBITS)->sh_type != SHT_NOBITS)
+	      goto out;
+	  }
+
+      runp = runp->next;
+      if (runp == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_OFFSET);
+	  break;
+	}
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elfw2(LIBELFBITS,offscn))
diff --git a/libelf/elf32_updatefile.c b/libelf/elf32_updatefile.c
new file mode 100644
index 0000000..46afa1f
--- /dev/null
+++ b/libelf/elf32_updatefile.c
@@ -0,0 +1,852 @@
+/* Write changed data structures.
+   Copyright (C) 2000-2010, 2014, 2015, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <libelf.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+
+static int
+compare_sections (const void *a, const void *b)
+{
+  const Elf_Scn **scna = (const Elf_Scn **) a;
+  const Elf_Scn **scnb = (const Elf_Scn **) b;
+
+  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
+      < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
+    return -1;
+
+  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_offset
+      > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_offset)
+    return 1;
+
+  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
+      < (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
+    return -1;
+
+  if ((*scna)->shdr.ELFW(e,LIBELFBITS)->sh_size
+      > (*scnb)->shdr.ELFW(e,LIBELFBITS)->sh_size)
+    return 1;
+
+  if ((*scna)->index < (*scnb)->index)
+    return -1;
+
+  if ((*scna)->index > (*scnb)->index)
+    return 1;
+
+  return 0;
+}
+
+
+/* Insert the sections in the list into the provided array and sort
+   them according to their start offsets.  For sections with equal
+   start offsets, the size is used; for sections with equal start
+   offsets and sizes, the section index is used.  Sorting by size
+   ensures that zero-length sections are processed first, which
+   is what we want since they do not advance our file writing position.  */
+static void
+sort_sections (Elf_Scn **scns, Elf_ScnList *list)
+{
+  Elf_Scn **scnp = scns;
+  do
+    for (size_t cnt = 0; cnt < list->cnt; ++cnt)
+      *scnp++ = &list->data[cnt];
+  while ((list = list->next) != NULL);
+
+  qsort (scns, scnp - scns, sizeof (*scns), compare_sections);
+}
+
+
+static inline void
+fill_mmap (size_t offset, char *last_position, char *scn_start,
+           char *const shdr_start, char *const shdr_end)
+{
+  size_t written = 0;
+
+  if (last_position < shdr_start)
+    {
+      written = MIN (scn_start + offset - last_position,
+                     shdr_start - last_position);
+
+      memset (last_position, __libelf_fill_byte, written);
+    }
+
+  if (last_position + written != scn_start + offset
+      && shdr_end < scn_start + offset)
+    {
+      char *fill_start = MAX (shdr_end, scn_start);
+      memset (fill_start, __libelf_fill_byte,
+              scn_start + offset - fill_start);
+    }
+}
+
+int
+internal_function
+__elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum)
+{
+  bool previous_scn_changed = false;
+
+  /* We need the ELF header several times.  */
+  ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+
+  /* Write out the ELF header.  */
+  if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
+    {
+      /* If the type sizes should be different at some time we have to
+	 rewrite this code.  */
+      assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
+	      == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
+
+      if (unlikely (change_bo))
+	{
+	  /* Today there is only one version of the ELF header.  */
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
+
+	  /* Do the real work.  */
+	  (*fctp) ((char *) elf->map_address + elf->start_offset, ehdr,
+		   sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
+	}
+      else if (elf->map_address + elf->start_offset != ehdr)
+	memcpy (elf->map_address + elf->start_offset, ehdr,
+		sizeof (ElfW2(LIBELFBITS,Ehdr)));
+
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
+
+      /* We start writing sections after the ELF header only if there is
+	 no program header.  */
+      previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
+    }
+
+  size_t phnum;
+  if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
+    return -1;
+
+  /* Write out the program header table.  */
+  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
+      && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
+	  & ELF_F_DIRTY))
+    {
+      /* If the type sizes should be different at some time we have to
+	 rewrite this code.  */
+      assert (sizeof (ElfW2(LIBELFBITS,Phdr))
+	      == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
+
+      /* Maybe the user wants a gap between the ELF header and the program
+	 header.  */
+      if (ehdr->e_phoff > ehdr->e_ehsize)
+	memset (elf->map_address + elf->start_offset + ehdr->e_ehsize,
+		__libelf_fill_byte, ehdr->e_phoff - ehdr->e_ehsize);
+
+      if (unlikely (change_bo))
+	{
+	  /* Today there is only one version of the ELF header.  */
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
+
+	  /* Do the real work.  */
+	  (*fctp) (elf->map_address + elf->start_offset + ehdr->e_phoff,
+		   elf->state.ELFW(elf,LIBELFBITS).phdr,
+		   sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
+	}
+      else
+	memmove (elf->map_address + elf->start_offset + ehdr->e_phoff,
+		elf->state.ELFW(elf,LIBELFBITS).phdr,
+		sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
+
+      elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
+
+      /* We modified the program header.  Maybe this created a gap so
+	 we have to write fill bytes, if necessary.  */
+      previous_scn_changed = true;
+    }
+
+  /* From now on we have to keep track of the last position to eventually
+     fill the gaps with the prescribed fill byte.  */
+  char *last_position = ((char *) elf->map_address + elf->start_offset
+			 + MAX (elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
+				ehdr->e_phoff)
+			 + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
+
+  /* Write all the sections.  Well, only those which are modified.  */
+  if (shnum > 0)
+    {
+      if (unlikely (shnum > SIZE_MAX / sizeof (Elf_Scn *)))
+	return 1;
+
+      Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
+      Elf_Scn **scns = malloc (shnum * sizeof (Elf_Scn *));
+      if (unlikely (scns == NULL))
+	{
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  return -1;
+	}
+      char *const shdr_start = ((char *) elf->map_address + elf->start_offset
+				+ ehdr->e_shoff);
+      char *const shdr_end = shdr_start + shnum * ehdr->e_shentsize;
+
+#undef shdr_fctp
+#define shdr_fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
+#define shdr_dest ((ElfW2(LIBELFBITS,Shdr) *) shdr_start)
+
+      /* Get all sections into the array and sort them.  */
+      sort_sections (scns, list);
+
+      /* We possibly have to copy the section header data because moving
+	 the sections might overwrite the data.  */
+      for (size_t cnt = 0; cnt < shnum; ++cnt)
+	{
+	  Elf_Scn *scn = scns[cnt];
+
+	  if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
+	      && (scn->shdr_flags & ELF_F_MALLOCED) == 0
+	      && scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
+	    {
+	      assert ((char *) elf->map_address + elf->start_offset
+		      < (char *) scn->shdr.ELFW(e,LIBELFBITS));
+	      assert ((char *) scn->shdr.ELFW(e,LIBELFBITS)
+		      < ((char *) elf->map_address + elf->start_offset
+			 + elf->maximum_size));
+
+	      void *p = malloc (sizeof (ElfW2(LIBELFBITS,Shdr)));
+	      if (unlikely (p == NULL))
+		{
+		  free (scns);
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  return -1;
+		}
+	      scn->shdr.ELFW(e,LIBELFBITS)
+		= memcpy (p, scn->shdr.ELFW(e,LIBELFBITS),
+			  sizeof (ElfW2(LIBELFBITS,Shdr)));
+	    }
+
+	  /* If the file is mmaped and the original position of the
+	     section in the file is lower than the new position we
+	     need to save the section content since otherwise it is
+	     overwritten before it can be copied.  If there are
+	     multiple data segments in the list only the first can be
+	     from the file.  */
+	  if (((char *) elf->map_address + elf->start_offset
+	       <= (char  *) scn->data_list.data.d.d_buf)
+	      && ((char *) scn->data_list.data.d.d_buf
+		  < ((char *) elf->map_address + elf->start_offset
+		     + elf->maximum_size))
+	      && (((char *) elf->map_address + elf->start_offset
+		   + scn->shdr.ELFW(e,LIBELFBITS)->sh_offset)
+		  > (char *) scn->data_list.data.d.d_buf))
+	    {
+	      void *p = malloc (scn->data_list.data.d.d_size);
+	      if (unlikely (p == NULL))
+		{
+		  free (scns);
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  return -1;
+		}
+	      scn->data_list.data.d.d_buf = scn->data_base
+		= memcpy (p, scn->data_list.data.d.d_buf,
+			  scn->data_list.data.d.d_size);
+	    }
+	}
+
+      /* Iterate over all the section in the order in which they
+	 appear in the output file.  */
+      for (size_t cnt = 0; cnt < shnum; ++cnt)
+	{
+	  Elf_Scn *scn = scns[cnt];
+	  if (scn->index == 0)
+	    {
+	      /* The dummy section header entry.  It should not be
+		 possible to mark this "section" as dirty.  */
+	      assert ((scn->flags & ELF_F_DIRTY) == 0);
+	      continue;
+	    }
+
+	  ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
+	  if (shdr->sh_type == SHT_NOBITS)
+	    goto next;
+
+	  char *scn_start = ((char *) elf->map_address
+			     + elf->start_offset + shdr->sh_offset);
+	  Elf_Data_List *dl = &scn->data_list;
+	  bool scn_changed = false;
+
+	  if (scn->data_list_rear != NULL)
+	    do
+	      {
+		assert (dl->data.d.d_off >= 0);
+		assert ((GElf_Off) dl->data.d.d_off <= shdr->sh_size);
+		assert (dl->data.d.d_size <= (shdr->sh_size
+					      - (GElf_Off) dl->data.d.d_off));
+
+		/* If there is a gap, fill it.  */
+		if (scn_start + dl->data.d.d_off > last_position
+		    && (dl->data.d.d_off == 0
+			|| ((scn->flags | dl->flags | elf->flags)
+			    & ELF_F_DIRTY) != 0))
+		  {
+		    fill_mmap (dl->data.d.d_off, last_position, scn_start,
+		               shdr_start, shdr_end);
+		  }
+
+		last_position = scn_start + dl->data.d.d_off;
+
+		if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
+		  {
+		    /* Let it go backward if the sections use a bogus
+		       layout with overlaps.  We'll overwrite the stupid
+		       user's section data with the latest one, rather than
+		       crashing.  */
+
+		    if (unlikely (change_bo
+				  && dl->data.d.d_size != 0
+				  && dl->data.d.d_type != ELF_T_BYTE))
+		      {
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
+
+			size_t align;
+			align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
+						     dl->data.d.d_type);
+			if ((((uintptr_t) last_position)
+			     & (uintptr_t) (align - 1)) == 0)
+			  {
+			    /* No need to copy, we can convert directly.  */
+			    (*fctp) (last_position, dl->data.d.d_buf,
+				     dl->data.d.d_size, 1);
+			  }
+			else
+			  {
+			    /* We have to do the conversion on properly
+			       aligned memory first.  align is a power of 2,
+			       but posix_memalign only works for alignments
+			       which are a multiple of sizeof (void *).
+			       So use normal malloc for smaller alignments.  */
+			    size_t size = dl->data.d.d_size;
+			    void *converted;
+			    if (align < sizeof (void *))
+			      converted = malloc (size);
+			    else
+			      {
+				int res;
+				res = posix_memalign (&converted, align, size);
+				if (res != 0)
+				  converted = NULL;
+			      }
+
+			    if (converted == NULL)
+			      {
+				free (scns);
+				__libelf_seterrno (ELF_E_NOMEM);
+				return 1;
+			      }
+
+			    (*fctp) (converted, dl->data.d.d_buf, size, 1);
+
+			    /* And then write it to the mmapped file.  */
+			    memcpy (last_position, converted, size);
+			    free (converted);
+			  }
+
+			last_position += dl->data.d.d_size;
+		      }
+		    else if (dl->data.d.d_size != 0)
+		      {
+			memmove (last_position, dl->data.d.d_buf,
+				 dl->data.d.d_size);
+			last_position += dl->data.d.d_size;
+		      }
+
+		    scn_changed = true;
+		  }
+		else
+		  last_position += dl->data.d.d_size;
+
+		assert (scn_start + dl->data.d.d_off + dl->data.d.d_size
+			== last_position);
+
+		dl->flags &= ~ELF_F_DIRTY;
+
+		dl = dl->next;
+	      }
+	    while (dl != NULL);
+	  else
+	    {
+	      /* If the previous section (or the ELF/program
+		 header) changed we might have to fill the gap.  */
+	      if (scn_start > last_position && previous_scn_changed)
+		fill_mmap (0, last_position, scn_start,
+		           shdr_start, shdr_end);
+
+	      /* We have to trust the existing section header information.  */
+	      last_position = scn_start + shdr->sh_size;
+	    }
+
+
+	  previous_scn_changed = scn_changed;
+	next:
+	  scn->flags &= ~ELF_F_DIRTY;
+	}
+
+      /* Fill the gap between last section and section header table if
+	 necessary.  */
+      if ((elf->flags & ELF_F_DIRTY)
+	  && last_position < ((char *) elf->map_address + elf->start_offset
+			      + ehdr->e_shoff))
+	memset (last_position, __libelf_fill_byte,
+		(char *) elf->map_address + elf->start_offset + ehdr->e_shoff
+		- last_position);
+
+      /* Write the section header table entry if necessary.  */
+      for (size_t cnt = 0; cnt < shnum; ++cnt)
+	{
+	  Elf_Scn *scn = scns[cnt];
+
+	  if ((scn->shdr_flags | elf->flags) & ELF_F_DIRTY)
+	    {
+	      if (unlikely (change_bo))
+		(*shdr_fctp) (&shdr_dest[scn->index],
+			      scn->shdr.ELFW(e,LIBELFBITS),
+			      sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
+	      else
+		memcpy (&shdr_dest[scn->index],
+			scn->shdr.ELFW(e,LIBELFBITS),
+			sizeof (ElfW2(LIBELFBITS,Shdr)));
+
+	      /* If we previously made a copy of the section header
+		 entry we now have to adjust the pointer again so
+		 point to new place in the mapping.  */
+	      if (!elf->state.ELFW(elf,LIBELFBITS).shdr_malloced
+		  && (scn->shdr_flags & ELF_F_MALLOCED) == 0
+		  && scn->shdr.ELFW(e,LIBELFBITS) != &shdr_dest[scn->index])
+		{
+		  free (scn->shdr.ELFW(e,LIBELFBITS));
+		  scn->shdr.ELFW(e,LIBELFBITS) = &shdr_dest[scn->index];
+		}
+
+	      scn->shdr_flags &= ~ELF_F_DIRTY;
+	    }
+	}
+      free (scns);
+    }
+
+  /* That was the last part.  Clear the overall flag.  */
+  elf->flags &= ~ELF_F_DIRTY;
+
+  /* Make sure the content hits the disk.  */
+  char *msync_start = ((char *) elf->map_address
+		       + (elf->start_offset & ~(sysconf (_SC_PAGESIZE) - 1)));
+  char *msync_end = ((char *) elf->map_address
+		     + elf->start_offset + ehdr->e_shoff
+		     + ehdr->e_shentsize * shnum);
+  (void) msync (msync_start, msync_end - msync_start, MS_SYNC);
+
+  return 0;
+}
+
+
+/* Size of the buffer we use to generate the blocks of fill bytes.  */
+#define FILLBUFSIZE	4096
+
+/* If we have to convert the section buffer contents we have to use
+   temporary buffer.  Only buffers up to MAX_TMPBUF bytes are allocated
+   on the stack.  */
+#define MAX_TMPBUF	32768
+
+
+/* Helper function to write out fill bytes.  */
+static int
+fill (int fd, int64_t pos, size_t len, char *fillbuf, size_t *filledp)
+{
+  size_t filled = *filledp;
+  size_t fill_len = MIN (len, FILLBUFSIZE);
+
+  if (unlikely (fill_len > filled) && filled < FILLBUFSIZE)
+    {
+      /* Initialize a few more bytes.  */
+      memset (fillbuf + filled, __libelf_fill_byte, fill_len - filled);
+      *filledp = filled = fill_len;
+    }
+
+  do
+    {
+      /* This many bytes we want to write in this round.  */
+      size_t n = MIN (filled, len);
+
+      if (unlikely ((size_t) pwrite_retry (fd, fillbuf, n, pos) != n))
+	{
+	  __libelf_seterrno (ELF_E_WRITE_ERROR);
+	  return 1;
+	}
+
+      pos += n;
+      len -= n;
+    }
+  while (len > 0);
+
+  return 0;
+}
+
+
+int
+internal_function
+__elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum)
+{
+  char fillbuf[FILLBUFSIZE];
+  size_t filled = 0;
+  bool previous_scn_changed = false;
+
+  /* We need the ELF header several times.  */
+  ElfW2(LIBELFBITS,Ehdr) *ehdr = elf->state.ELFW(elf,LIBELFBITS).ehdr;
+
+  /* Write out the ELF header.  */
+  if ((elf->state.ELFW(elf,LIBELFBITS).ehdr_flags | elf->flags) & ELF_F_DIRTY)
+    {
+      ElfW2(LIBELFBITS,Ehdr) tmp_ehdr;
+      ElfW2(LIBELFBITS,Ehdr) *out_ehdr = ehdr;
+
+      /* If the type sizes should be different at some time we have to
+	 rewrite this code.  */
+      assert (sizeof (ElfW2(LIBELFBITS,Ehdr))
+	      == elf_typesize (LIBELFBITS, ELF_T_EHDR, 1));
+
+      if (unlikely (change_bo))
+	{
+	  /* Today there is only one version of the ELF header.  */
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_EHDR]
+
+	  /* Write the converted ELF header in a temporary buffer.  */
+	  (*fctp) (&tmp_ehdr, ehdr, sizeof (ElfW2(LIBELFBITS,Ehdr)), 1);
+
+	  /* This is the buffer we want to write.  */
+	  out_ehdr = &tmp_ehdr;
+	}
+
+      /* Write out the ELF header.  */
+      if (unlikely (pwrite_retry (elf->fildes, out_ehdr,
+				  sizeof (ElfW2(LIBELFBITS,Ehdr)), 0)
+		    != sizeof (ElfW2(LIBELFBITS,Ehdr))))
+	{
+	  __libelf_seterrno (ELF_E_WRITE_ERROR);
+	  return 1;
+	}
+
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags &= ~ELF_F_DIRTY;
+
+      /* We start writing sections after the ELF header only if there is
+	 no program header.  */
+      previous_scn_changed = elf->state.ELFW(elf,LIBELFBITS).phdr == NULL;
+    }
+
+  /* If the type sizes should be different at some time we have to
+     rewrite this code.  */
+  assert (sizeof (ElfW2(LIBELFBITS,Phdr))
+	  == elf_typesize (LIBELFBITS, ELF_T_PHDR, 1));
+
+  size_t phnum;
+  if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
+    return -1;
+
+  /* Write out the program header table.  */
+  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL
+      && ((elf->state.ELFW(elf,LIBELFBITS).phdr_flags | elf->flags)
+	  & ELF_F_DIRTY))
+    {
+      ElfW2(LIBELFBITS,Phdr) *tmp_phdr = NULL;
+      ElfW2(LIBELFBITS,Phdr) *out_phdr = elf->state.ELFW(elf,LIBELFBITS).phdr;
+
+      /* Maybe the user wants a gap between the ELF header and the program
+	 header.  */
+      if (ehdr->e_phoff > ehdr->e_ehsize
+	  && unlikely (fill (elf->fildes, ehdr->e_ehsize,
+			     ehdr->e_phoff - ehdr->e_ehsize, fillbuf, &filled)
+		       != 0))
+	return 1;
+
+      if (unlikely (change_bo))
+	{
+	  /* Today there is only one version of the ELF header.  */
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_PHDR]
+
+	  /* Allocate sufficient memory.  */
+	  tmp_phdr = (ElfW2(LIBELFBITS,Phdr) *)
+	    malloc (sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
+	  if (unlikely (tmp_phdr == NULL))
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return 1;
+	    }
+
+	  /* Write the converted ELF header in a temporary buffer.  */
+	  (*fctp) (tmp_phdr, elf->state.ELFW(elf,LIBELFBITS).phdr,
+		   sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum, 1);
+
+	  /* This is the buffer we want to write.  */
+	  out_phdr = tmp_phdr;
+	}
+
+      /* Write out the ELF header.  */
+      size_t phdr_size = sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum;
+      if (unlikely ((size_t) pwrite_retry (elf->fildes, out_phdr,
+					   phdr_size, ehdr->e_phoff)
+		    != phdr_size))
+	{
+	  __libelf_seterrno (ELF_E_WRITE_ERROR);
+	  return 1;
+	}
+
+      /* This is a no-op we we have not allocated any memory.  */
+      free (tmp_phdr);
+
+      elf->state.ELFW(elf,LIBELFBITS).phdr_flags &= ~ELF_F_DIRTY;
+
+      /* We modified the program header.  Maybe this created a gap so
+	 we have to write fill bytes, if necessary.  */
+      previous_scn_changed = true;
+    }
+
+  /* From now on we have to keep track of the last position to eventually
+     fill the gaps with the prescribed fill byte.  */
+  int64_t last_offset;
+  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
+    last_offset = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
+  else
+    last_offset = (ehdr->e_phoff + sizeof (ElfW2(LIBELFBITS,Phdr)) * phnum);
+
+  /* Write all the sections.  Well, only those which are modified.  */
+  if (shnum > 0)
+    {
+      if (unlikely (shnum > SIZE_MAX / (sizeof (Elf_Scn *)
+					+ sizeof (ElfW2(LIBELFBITS,Shdr)))))
+	return 1;
+
+      int64_t shdr_offset = elf->start_offset + ehdr->e_shoff;
+#undef shdr_fctp
+#define shdr_fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][ELF_T_SHDR]
+
+      ElfW2(LIBELFBITS,Shdr) *shdr_data;
+      ElfW2(LIBELFBITS,Shdr) *shdr_data_mem = NULL;
+      if (change_bo || elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
+	  || (elf->flags & ELF_F_DIRTY))
+	{
+	  shdr_data_mem = (ElfW2(LIBELFBITS,Shdr) *)
+	    malloc (shnum * sizeof (ElfW2(LIBELFBITS,Shdr)));
+	  if (unlikely (shdr_data_mem == NULL))
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return -1;
+	    }
+	  shdr_data = shdr_data_mem;
+	}
+      else
+	shdr_data = elf->state.ELFW(elf,LIBELFBITS).shdr;
+      int shdr_flags = elf->flags;
+
+      /* Get all sections into the array and sort them.  */
+      Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns;
+      Elf_Scn **scns = malloc (shnum * sizeof (Elf_Scn *));
+      if (unlikely (scns == NULL))
+	{
+	  free (shdr_data_mem);
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  return -1;
+	}
+      sort_sections (scns, list);
+
+      for (size_t cnt = 0; cnt < shnum; ++cnt)
+	{
+	  Elf_Scn *scn = scns[cnt];
+	  if (scn->index == 0)
+	    {
+	      /* The dummy section header entry.  It should not be
+		 possible to mark this "section" as dirty.  */
+	      assert ((scn->flags & ELF_F_DIRTY) == 0);
+	      goto next;
+	    }
+
+	  ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
+	  if (shdr->sh_type == SHT_NOBITS)
+	    goto next;
+
+	  int64_t scn_start = elf->start_offset + shdr->sh_offset;
+	  Elf_Data_List *dl = &scn->data_list;
+	  bool scn_changed = false;
+
+	  if (scn->data_list_rear != NULL)
+	    do
+	      {
+		/* If there is a gap, fill it.  */
+		if (scn_start + dl->data.d.d_off > last_offset
+		    && ((previous_scn_changed && dl->data.d.d_off == 0)
+			|| ((scn->flags | dl->flags | elf->flags)
+			    & ELF_F_DIRTY) != 0))
+		  {
+		    if (unlikely (fill (elf->fildes, last_offset,
+					(scn_start + dl->data.d.d_off)
+					- last_offset, fillbuf,
+					&filled) != 0))
+		      {
+		      fail_free:
+			free (shdr_data_mem);
+			free (scns);
+			return 1;
+		      }
+		  }
+
+		last_offset = scn_start + dl->data.d.d_off;
+
+		if ((scn->flags | dl->flags | elf->flags) & ELF_F_DIRTY)
+		  {
+		    char tmpbuf[MAX_TMPBUF];
+		    void *buf = dl->data.d.d_buf;
+
+		    /* Let it go backward if the sections use a bogus
+		       layout with overlaps.  We'll overwrite the stupid
+		       user's section data with the latest one, rather than
+		       crashing.  */
+
+		    if (unlikely (change_bo))
+		      {
+#undef fctp
+#define fctp __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][dl->data.d.d_type]
+
+			buf = tmpbuf;
+			if (dl->data.d.d_size > MAX_TMPBUF)
+			  {
+			    buf = malloc (dl->data.d.d_size);
+			    if (unlikely (buf == NULL))
+			      {
+				__libelf_seterrno (ELF_E_NOMEM);
+				goto fail_free;
+			      }
+			  }
+
+			/* Do the real work.  */
+			(*fctp) (buf, dl->data.d.d_buf, dl->data.d.d_size, 1);
+		      }
+
+		    ssize_t n = pwrite_retry (elf->fildes, buf,
+					      dl->data.d.d_size,
+					      last_offset);
+		    if (unlikely ((size_t) n != dl->data.d.d_size))
+		      {
+			if (buf != dl->data.d.d_buf && buf != tmpbuf)
+			  free (buf);
+
+			__libelf_seterrno (ELF_E_WRITE_ERROR);
+			goto fail_free;
+		      }
+
+		    if (buf != dl->data.d.d_buf && buf != tmpbuf)
+		      free (buf);
+
+		    scn_changed = true;
+		  }
+
+		last_offset += dl->data.d.d_size;
+
+		dl->flags &= ~ELF_F_DIRTY;
+
+		dl = dl->next;
+	      }
+	    while (dl != NULL);
+	  else
+	    {
+	      /* If the previous section (or the ELF/program
+		 header) changed we might have to fill the gap.  */
+	      if (scn_start > last_offset && previous_scn_changed)
+		{
+		  if (unlikely (fill (elf->fildes, last_offset,
+				      scn_start - last_offset, fillbuf,
+				      &filled) != 0))
+		    goto fail_free;
+		}
+
+	      last_offset = scn_start + shdr->sh_size;
+	    }
+
+	  previous_scn_changed = scn_changed;
+	next:
+	  /* Collect the section header table information.  */
+	  if (unlikely (change_bo))
+	    (*shdr_fctp) (&shdr_data[scn->index],
+			  scn->shdr.ELFW(e,LIBELFBITS),
+			  sizeof (ElfW2(LIBELFBITS,Shdr)), 1);
+	  else if (elf->state.ELFW(elf,LIBELFBITS).shdr == NULL
+		   || (elf->flags & ELF_F_DIRTY))
+	    memcpy (&shdr_data[scn->index], scn->shdr.ELFW(e,LIBELFBITS),
+		    sizeof (ElfW2(LIBELFBITS,Shdr)));
+
+	  shdr_flags |= scn->shdr_flags;
+	  scn->shdr_flags &= ~ELF_F_DIRTY;
+	}
+
+      /* Fill the gap between last section and section header table if
+	 necessary.  */
+      if ((elf->flags & ELF_F_DIRTY) && last_offset < shdr_offset
+	  && unlikely (fill (elf->fildes, last_offset,
+			     shdr_offset - last_offset,
+			     fillbuf, &filled) != 0))
+	goto fail_free;
+
+      /* Write out the section header table.  */
+      if (shdr_flags & ELF_F_DIRTY
+	  && unlikely ((size_t) pwrite_retry (elf->fildes, shdr_data,
+					      sizeof (ElfW2(LIBELFBITS,Shdr))
+					      * shnum, shdr_offset)
+		       != sizeof (ElfW2(LIBELFBITS,Shdr)) * shnum))
+	{
+	  __libelf_seterrno (ELF_E_WRITE_ERROR);
+	  goto fail_free;
+	}
+
+      free (shdr_data_mem);
+      free (scns);
+    }
+
+  /* That was the last part.  Clear the overall flag.  */
+  elf->flags &= ~ELF_F_DIRTY;
+
+  return 0;
+}
diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c
new file mode 100644
index 0000000..3594e8b
--- /dev/null
+++ b/libelf/elf32_updatenull.c
@@ -0,0 +1,462 @@
+/* Update data structures for changes.
+   Copyright (C) 2000-2010, 2015, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <libelf.h>
+#include <stdbool.h>
+#include <string.h>
+
+#include "libelfP.h"
+#include "elf-knowledge.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS 32
+#endif
+
+/* Some fields contain 32/64 sizes.  We cannot use Elf32/64_Word for those,
+   since those are both 32bits.  Elf32/64_Xword is always 64bits.  */
+#define Elf32_SizeWord Elf32_Word
+#define Elf64_SizeWord Elf64_Xword
+
+
+static int
+ELFW(default_ehdr,LIBELFBITS) (Elf *elf, ElfW2(LIBELFBITS,Ehdr) *ehdr,
+			       size_t shnum, int *change_bop)
+{
+  /* Always write the magic bytes.  */
+  if (memcmp (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0)
+    {
+      memcpy (&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG);
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
+    }
+
+  /* Always set the file class.  */
+  update_if_changed (ehdr->e_ident[EI_CLASS], ELFW(ELFCLASS,LIBELFBITS),
+		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
+
+  /* Set the data encoding if necessary.  */
+  if (unlikely (ehdr->e_ident[EI_DATA] == ELFDATANONE))
+    {
+      ehdr->e_ident[EI_DATA] =
+	BYTE_ORDER == BIG_ENDIAN ? ELFDATA2MSB : ELFDATA2LSB;
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
+    }
+  else if (unlikely (ehdr->e_ident[EI_DATA] >= ELFDATANUM))
+    {
+      __libelf_seterrno (ELF_E_DATA_ENCODING);
+      return 1;
+    }
+  else
+    *change_bop = ((BYTE_ORDER == LITTLE_ENDIAN
+		    && ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
+		   || (BYTE_ORDER == BIG_ENDIAN
+		       && ehdr->e_ident[EI_DATA] != ELFDATA2MSB));
+
+  /* Unconditionally overwrite the ELF version.  */
+  update_if_changed (ehdr->e_ident[EI_VERSION], EV_CURRENT,
+		     elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
+
+  if (unlikely (ehdr->e_version == EV_NONE))
+    {
+      ehdr->e_version = EV_CURRENT;
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
+    }
+  else if (unlikely (ehdr->e_version != EV_CURRENT))
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
+      return 1;
+    }
+
+  if (unlikely (shnum >= SHN_LORESERVE))
+    {
+      update_if_changed (ehdr->e_shnum, 0,
+			 elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
+    }
+  else
+    update_if_changed (ehdr->e_shnum, shnum,
+		       elf->state.ELFW(elf,LIBELFBITS).ehdr_flags);
+
+  if (unlikely (ehdr->e_ehsize != elf_typesize (LIBELFBITS, ELF_T_EHDR, 1)))
+    {
+      ehdr->e_ehsize = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
+    }
+
+  /* If phnum is zero make sure e_phoff is also zero and not some random
+     value.  That would cause trouble in update_file.  */
+  if (ehdr->e_phnum == 0 && ehdr->e_phoff != 0)
+    {
+      ehdr->e_phoff = 0;
+      elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ELF_F_DIRTY;
+    }
+
+  return 0;
+}
+
+
+int64_t
+internal_function
+__elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
+{
+  ElfW2(LIBELFBITS,Ehdr) *ehdr;
+  int changed = 0;
+  int ehdr_flags = 0;
+
+  ehdr = __elfw2(LIBELFBITS,getehdr_wrlock) (elf);
+
+  /* Set the default values.  */
+  if (ELFW(default_ehdr,LIBELFBITS) (elf, ehdr, shnum, change_bop) != 0)
+    return -1;
+
+  /* At least the ELF header is there.  */
+  ElfW2(LIBELFBITS,SizeWord) size = elf_typesize (LIBELFBITS, ELF_T_EHDR, 1);
+
+  /* Set the program header position.  */
+  if (elf->state.ELFW(elf,LIBELFBITS).phdr == NULL)
+    (void) __elfw2(LIBELFBITS,getphdr_wrlock) (elf);
+  if (elf->state.ELFW(elf,LIBELFBITS).phdr != NULL)
+    {
+      size_t phnum;
+      if (unlikely (__elf_getphdrnum_rdlock (elf, &phnum) != 0))
+	return -1;
+
+      if (elf->flags & ELF_F_LAYOUT)
+	{
+	  /* The user is supposed to fill out e_phoff.  Use it and
+	     e_phnum to determine the maximum extend.  */
+	  size = MAX (size,
+		      ehdr->e_phoff
+		      + elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum));
+	}
+      else
+	{
+	  update_if_changed (ehdr->e_phoff,
+			     elf_typesize (LIBELFBITS, ELF_T_EHDR, 1),
+			     ehdr_flags);
+
+	  /* We need no alignment here.  */
+	  size += elf_typesize (LIBELFBITS, ELF_T_PHDR, phnum);
+	}
+    }
+
+  if (shnum > 0)
+    {
+      struct Elf_Scn *scn1 = NULL;
+      Elf_ScnList *list;
+      bool first = true;
+
+      assert (elf->state.ELFW(elf,LIBELFBITS).scns.cnt > 0);
+
+      if (shnum >= SHN_LORESERVE)
+	{
+	  /* We have to  fill in the number of sections in the header
+	     of the zeroth section.  */
+	  Elf_Scn *scn0 = &elf->state.ELFW(elf,LIBELFBITS).scns.data[0];
+
+	  update_if_changed (scn0->shdr.ELFW(e,LIBELFBITS)->sh_size,
+			     shnum, scn0->shdr_flags);
+	}
+
+      /* Go over all sections and find out how large they are.  */
+      list = &elf->state.ELFW(elf,LIBELFBITS).scns;
+
+      /* Find the first section. */
+      if (list->cnt > 1)
+	scn1 = &list->data[1];
+      else if (list->next != NULL)
+	scn1 = &list->next->data[0];
+
+      /* Load the section headers if necessary.  This loads the
+	 headers for all sections.  */
+      if (scn1 != NULL && scn1->shdr.ELFW(e,LIBELFBITS) == NULL)
+	(void) __elfw2(LIBELFBITS,getshdr_wrlock) (scn1);
+
+      do
+	{
+	  for (size_t cnt = first == true; cnt < list->cnt; ++cnt)
+	    {
+	      Elf_Scn *scn = &list->data[cnt];
+	      ElfW2(LIBELFBITS,Shdr) *shdr = scn->shdr.ELFW(e,LIBELFBITS);
+	      int64_t offset = 0;
+
+	      assert (shdr != NULL);
+	      ElfW2(LIBELFBITS,SizeWord) sh_entsize = shdr->sh_entsize;
+	      ElfW2(LIBELFBITS,SizeWord) sh_align = shdr->sh_addralign ?: 1;
+	      if (unlikely (! powerof2 (sh_align)))
+		{
+		  __libelf_seterrno (ELF_E_INVALID_ALIGN);
+		  return -1;
+		}
+
+	      /* Set the sh_entsize value if we can reliably detect it.  */
+	      switch (shdr->sh_type)
+		{
+		case SHT_SYMTAB:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
+		  break;
+		case SHT_RELA:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELA, 1);
+		  break;
+		case SHT_GROUP:
+		  /* Only relocatable files can contain section groups.  */
+		  if (ehdr->e_type != ET_REL)
+		    {
+		      __libelf_seterrno (ELF_E_GROUP_NOT_REL);
+		      return -1;
+		    }
+		  FALLTHROUGH;
+		case SHT_SYMTAB_SHNDX:
+		  sh_entsize = elf_typesize (32, ELF_T_WORD, 1);
+		  break;
+		case SHT_HASH:
+		  sh_entsize = SH_ENTSIZE_HASH (ehdr);
+		  break;
+		case SHT_DYNAMIC:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_DYN, 1);
+		  break;
+		case SHT_REL:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_REL, 1);
+		  break;
+		case SHT_DYNSYM:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYM, 1);
+		  break;
+		case SHT_SUNW_move:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_MOVE, 1);
+		  break;
+		case SHT_SUNW_syminfo:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
+		  break;
+		case SHT_RELR:
+		  sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELR, 1);
+		  break;
+		default:
+		  break;
+		}
+
+	      /* If the section header contained the wrong entry size
+		 correct it and mark the header as modified.  */
+	      update_if_changed (shdr->sh_entsize, sh_entsize,
+				 scn->shdr_flags);
+
+	      /* Likewise for the alignment of a compressed section.
+	         For a SHF_COMPRESSED section set the correct
+	         sh_addralign value, which must match the d_align of
+	         the data (see __libelf_set_rawdata in elf_getdata.c).  */
+	      if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+		{
+		  sh_align = __libelf_type_align (ELFW(ELFCLASS,LIBELFBITS),
+						  ELF_T_CHDR);
+		  update_if_changed (shdr->sh_addralign, sh_align,
+				     scn->shdr_flags);
+		}
+
+	      if (scn->data_read == 0
+		  && __libelf_set_rawdata_wrlock (scn) != 0)
+		/* Something went wrong.  The error value is already set.  */
+		return -1;
+
+	      /* Iterate over all data blocks.  */
+	      if (list->data[cnt].data_list_rear != NULL)
+		{
+		  Elf_Data_List *dl = &scn->data_list;
+
+		  while (dl != NULL)
+		    {
+		      Elf_Data *data = &dl->data.d;
+		      if (dl == &scn->data_list && data->d_buf == NULL
+			  && scn->rawdata.d.d_buf != NULL)
+			data = &scn->rawdata.d;
+
+		      if (unlikely (data->d_version != EV_CURRENT))
+			{
+			  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
+			  return -1;
+			}
+
+		      if (unlikely (! powerof2 (data->d_align)))
+			{
+			  __libelf_seterrno (ELF_E_INVALID_ALIGN);
+			  return -1;
+			}
+
+		      sh_align = MAX (sh_align, data->d_align);
+
+		      if (elf->flags & ELF_F_LAYOUT)
+			{
+			  /* The user specified the offset and the size.
+			     All we have to do is check whether this block
+			     fits in the size specified for the section.  */
+			  if (unlikely ((ElfW2(LIBELFBITS,SizeWord))
+					(data->d_off + data->d_size)
+					> shdr->sh_size))
+			    {
+			      __libelf_seterrno (ELF_E_SECTION_TOO_SMALL);
+			      return -1;
+			    }
+			}
+		      else
+			{
+			  /* Determine the padding.  */
+			  offset = ((offset + data->d_align - 1)
+				    & ~(data->d_align - 1));
+
+			  update_if_changed (data->d_off, offset, changed);
+
+			  offset += data->d_size;
+			}
+
+		      /* Next data block.  */
+		      dl = dl->next;
+		    }
+		}
+	      else
+		/* Get the size of the section from the raw data.  If
+		   none is available the value is zero.  */
+		offset += scn->rawdata.d.d_size;
+
+	      if (elf->flags & ELF_F_LAYOUT)
+		{
+		  size = MAX (size,
+			      (shdr->sh_type != SHT_NOBITS
+			       ? shdr->sh_offset + shdr->sh_size : 0));
+
+		  /* The alignment must be a power of two.  This is a
+		     requirement from the ELF specification.  Additionally
+		     we test for the alignment of the section being large
+		     enough for the largest alignment required by a data
+		     block.  */
+		  if (unlikely (! powerof2 (shdr->sh_addralign))
+		      || unlikely ((shdr->sh_addralign ?: 1) < sh_align))
+		    {
+		      __libelf_seterrno (ELF_E_INVALID_ALIGN);
+		      return -1;
+		    }
+		}
+	      else
+		{
+		  /* How much alignment do we need for this section.  */
+		  update_if_changed (shdr->sh_addralign, sh_align,
+				     scn->shdr_flags);
+
+		  size = (size + sh_align - 1) & ~(sh_align - 1);
+		  int offset_changed = 0;
+		  update_if_changed (shdr->sh_offset, size, offset_changed);
+		  changed |= offset_changed;
+
+		  if (offset_changed && scn->data_list_rear == NULL)
+		    {
+		      /* The position of the section in the file
+			 changed.  Create the section data list.  */
+		      if (__elf_getdata_rdlock (scn, NULL) == NULL)
+			return -1;
+		    }
+
+		  /* See whether the section size is correct.  */
+		  int size_changed = 0;
+		  update_if_changed (shdr->sh_size,
+				     (ElfW2(LIBELFBITS,SizeWord)) offset,
+				     size_changed);
+		  changed |= size_changed;
+
+		  if (shdr->sh_type != SHT_NOBITS)
+		    size += offset;
+
+		  scn->shdr_flags |= (offset_changed | size_changed);
+		  scn->flags |= changed;
+		}
+
+	      /* Check that the section size is actually a multiple of
+		 the entry size.  */
+	      if (shdr->sh_entsize != 0 && shdr->sh_entsize != 1
+		  && (elf->flags & ELF_F_PERMISSIVE) == 0)
+		{
+		  /* For compressed sections check the uncompressed size.  */
+		  ElfW2(LIBELFBITS,SizeWord) sh_size;
+		  if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
+		    sh_size = shdr->sh_size;
+		  else
+		    {
+		      ElfW2(LIBELFBITS,Chdr) *chdr;
+		      chdr = __elfw2(LIBELFBITS,getchdr_wrlock) (scn);
+		      if (unlikely (chdr == NULL))
+			return -1;
+		      sh_size = chdr->ch_size;
+		    }
+
+		  if (unlikely (sh_size % shdr->sh_entsize != 0))
+		    {
+		      __libelf_seterrno (ELF_E_INVALID_SHENTSIZE);
+		      return -1;
+		    }
+		}
+	    }
+
+	  assert (list->next == NULL || list->cnt == list->max);
+
+	  first = false;
+	}
+      while ((list = list->next) != NULL);
+
+      /* Store section information.  */
+      update_if_changed (ehdr->e_shentsize,
+			 elf_typesize (LIBELFBITS, ELF_T_SHDR, 1), ehdr_flags);
+      if (elf->flags & ELF_F_LAYOUT)
+	{
+	  /* The user is supposed to fill out e_shoff.  Use it and
+	     e_shnum (or sh_size of the dummy, first section header)
+	     to determine the maximum extend.  */
+	  size = MAX (size,
+		      (ehdr->e_shoff
+		       + (elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum))));
+	}
+      else
+	{
+	  /* Align for section header table.
+
+	     Yes, we use `sizeof' and not `__alignof__' since we do not
+	     want to be surprised by architectures with less strict
+	     alignment rules.  */
+#define SHDR_ALIGN sizeof (ElfW2(LIBELFBITS,Off))
+	  size = (size + SHDR_ALIGN - 1) & ~(SHDR_ALIGN - 1);
+
+	  update_if_changed (ehdr->e_shoff, size, elf->flags);
+
+	  /* Account for the section header size.  */
+	  size += elf_typesize (LIBELFBITS, ELF_T_SHDR, shnum);
+	}
+    }
+
+  elf->state.ELFW(elf,LIBELFBITS).ehdr_flags |= ehdr_flags;
+
+  return size;
+}
diff --git a/libelf/elf32_xlatetof.c b/libelf/elf32_xlatetof.c
new file mode 100644
index 0000000..ab85740
--- /dev/null
+++ b/libelf/elf32_xlatetof.c
@@ -0,0 +1,108 @@
+/* Convert from memory to file representation.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS	32
+#endif
+
+
+Elf_Data *
+elfw2(LIBELFBITS, xlatetof) (Elf_Data *dest, const Elf_Data *src,
+			     unsigned int encode)
+{
+  /* First test whether the input data is really suitable for this
+     type.  This means, whether there is an integer number of records.
+     Note that for this implementation the memory and file size of the
+     data types are identical.  */
+  size_t recsize = __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
+
+  if (src->d_size % recsize != 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_DATA);
+      return NULL;
+    }
+
+  /* Next see whether the converted data fits in the output buffer.  */
+  if (src->d_size > dest->d_size)
+    {
+      __libelf_seterrno (ELF_E_DEST_SIZE);
+      return NULL;
+    }
+
+  /* Test the encode parameter.  */
+  if (encode != ELFDATA2LSB && encode != ELFDATA2MSB)
+    {
+      __libelf_seterrno (ELF_E_INVALID_ENCODING);
+      return NULL;
+    }
+
+  /* Determine the translation function to use.
+
+     At this point we make an assumption which is valid for all
+     existing implementations so far: the memory and file sizes are
+     the same.  This has very important consequences:
+     a) The requirement that the source and destination buffer can
+	overlap can easily be fulfilled.
+     b) We need only one function to convert from and memory to file
+	and vice versa since the function only has to copy and/or
+	change the byte order.
+  */
+  if ((BYTE_ORDER == LITTLE_ENDIAN && encode == ELFDATA2LSB)
+      || (BYTE_ORDER == BIG_ENDIAN && encode == ELFDATA2MSB))
+    {
+      /* We simply have to copy since the byte order is the same.  */
+      if (src->d_buf != dest->d_buf)
+	memmove (dest->d_buf, src->d_buf, src->d_size);
+    }
+  else
+    {
+      xfct_t fctp;
+      fctp = __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
+
+      /* Do the real work.  */
+      (*fctp) (dest->d_buf, src->d_buf, src->d_size, 1);
+    }
+
+  /* Now set the real destination type and length since the operation was
+     successful.  */
+  dest->d_type = src->d_type;
+  dest->d_size = src->d_size;
+
+  return dest;
+}
+INTDEF(elfw2(LIBELFBITS, xlatetof))
diff --git a/libelf/elf32_xlatetom.c b/libelf/elf32_xlatetom.c
new file mode 100644
index 0000000..fa3dc9a
--- /dev/null
+++ b/libelf/elf32_xlatetom.c
@@ -0,0 +1,113 @@
+/* Convert from file to memory representation.
+   Copyright (C) 1998, 1999, 2000, 2002, 2012, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS	32
+#endif
+
+
+Elf_Data *
+elfw2(LIBELFBITS, xlatetom) (Elf_Data *dest, const Elf_Data *src,
+			     unsigned int encode)
+{
+  /* First test whether the input data is really suitable for this
+     type.  This means, whether there is an integer number of records.
+     Note that for this implementation the memory and file size of the
+     data types are identical.  */
+  size_t recsize = __libelf_type_sizes[ELFW(ELFCLASS,LIBELFBITS) - 1][src->d_type];
+
+
+  /* We shouldn't require integer number of records when processing
+     notes.  Payload bytes follow the header immediately, it's not an
+     array of records as is the case otherwise.  */
+  if (src->d_type != ELF_T_NHDR && src->d_type != ELF_T_NHDR8
+      && src->d_size % recsize != 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_DATA);
+      return NULL;
+    }
+
+  /* Next see whether the converted data fits in the output buffer.  */
+  if (src->d_size > dest->d_size)
+    {
+      __libelf_seterrno (ELF_E_DEST_SIZE);
+      return NULL;
+    }
+
+  /* Test the encode parameter.  */
+  if (encode != ELFDATA2LSB && encode != ELFDATA2MSB)
+    {
+      __libelf_seterrno (ELF_E_INVALID_ENCODING);
+      return NULL;
+    }
+
+  /* Determine the translation function to use.
+
+     At this point we make an assumption which is valid for all
+     existing implementations so far: the memory and file sizes are
+     the same.  This has very important consequences:
+     a) The requirement that the source and destination buffer can
+	overlap can easily be fulfilled.
+     b) We need only one function to convert from and memory to file
+	and vice versa since the function only has to copy and/or
+	change the byte order.
+  */
+  if ((BYTE_ORDER == LITTLE_ENDIAN && encode == ELFDATA2LSB)
+      || (BYTE_ORDER == BIG_ENDIAN && encode == ELFDATA2MSB))
+    {
+      /* We simply have to copy since the byte order is the same.  */
+      if (src->d_buf != dest->d_buf)
+	memmove (dest->d_buf, src->d_buf, src->d_size);
+    }
+  else
+    {
+      xfct_t fctp;
+      fctp = __elf_xfctstom[ELFW(ELFCLASS, LIBELFBITS) - 1][src->d_type];
+
+      /* Do the real work.  */
+      (*fctp) (dest->d_buf, src->d_buf, src->d_size, 0);
+    }
+
+  /* Now set the real destination type and length since the operation was
+     successful.  */
+  dest->d_type = src->d_type;
+  dest->d_size = src->d_size;
+
+  return dest;
+}
+INTDEF(elfw2(LIBELFBITS, xlatetom))
diff --git a/libelf/elf64_checksum.c b/libelf/elf64_checksum.c
new file mode 100644
index 0000000..1802240
--- /dev/null
+++ b/libelf/elf64_checksum.c
@@ -0,0 +1,31 @@
+/* Compute simple checksum from permanent parts of the ELF file.
+   Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_checksum.c"
diff --git a/libelf/elf64_fsize.c b/libelf/elf64_fsize.c
new file mode 100644
index 0000000..1ee1067
--- /dev/null
+++ b/libelf/elf64_fsize.c
@@ -0,0 +1,31 @@
+/* Return the size of an object file type.
+   Copyright (C) 1998, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_fsize.c"
diff --git a/libelf/elf64_getchdr.c b/libelf/elf64_getchdr.c
new file mode 100644
index 0000000..6588b79
--- /dev/null
+++ b/libelf/elf64_getchdr.c
@@ -0,0 +1,30 @@
+/* Return section compression header.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_getchdr.c"
diff --git a/libelf/elf64_getehdr.c b/libelf/elf64_getehdr.c
new file mode 100644
index 0000000..b35e7f6
--- /dev/null
+++ b/libelf/elf64_getehdr.c
@@ -0,0 +1,31 @@
+/* Return program header table.
+   Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_getehdr.c"
diff --git a/libelf/elf64_getphdr.c b/libelf/elf64_getphdr.c
new file mode 100644
index 0000000..c1ee60f
--- /dev/null
+++ b/libelf/elf64_getphdr.c
@@ -0,0 +1,31 @@
+/* Return program header table.
+   Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_getphdr.c"
diff --git a/libelf/elf64_getshdr.c b/libelf/elf64_getshdr.c
new file mode 100644
index 0000000..c50cc71
--- /dev/null
+++ b/libelf/elf64_getshdr.c
@@ -0,0 +1,31 @@
+/* Return section header.
+   Copyright (C) 1998, 1999, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_getshdr.c"
diff --git a/libelf/elf64_newehdr.c b/libelf/elf64_newehdr.c
new file mode 100644
index 0000000..65dd0f7
--- /dev/null
+++ b/libelf/elf64_newehdr.c
@@ -0,0 +1,31 @@
+/* Create new program header table.
+   Copyright (C) 1999, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_newehdr.c"
diff --git a/libelf/elf64_newphdr.c b/libelf/elf64_newphdr.c
new file mode 100644
index 0000000..58bfc73
--- /dev/null
+++ b/libelf/elf64_newphdr.c
@@ -0,0 +1,31 @@
+/* Create new program header table.
+   Copyright (C) 1999, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_newphdr.c"
diff --git a/libelf/elf64_offscn.c b/libelf/elf64_offscn.c
new file mode 100644
index 0000000..1b37b36
--- /dev/null
+++ b/libelf/elf64_offscn.c
@@ -0,0 +1,31 @@
+/* Return program header table.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_offscn.c"
diff --git a/libelf/elf64_updatefile.c b/libelf/elf64_updatefile.c
new file mode 100644
index 0000000..6941fe9
--- /dev/null
+++ b/libelf/elf64_updatefile.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2000, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_updatefile.c"
diff --git a/libelf/elf64_updatenull.c b/libelf/elf64_updatenull.c
new file mode 100644
index 0000000..8333b5b
--- /dev/null
+++ b/libelf/elf64_updatenull.c
@@ -0,0 +1,30 @@
+/* Copyright (C) 2000, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_updatenull.c"
diff --git a/libelf/elf64_xlatetof.c b/libelf/elf64_xlatetof.c
new file mode 100644
index 0000000..aacf5b0
--- /dev/null
+++ b/libelf/elf64_xlatetof.c
@@ -0,0 +1,31 @@
+/* Convert from memory to file representation.
+   Copyright (C) 1998, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_xlatetof.c"
diff --git a/libelf/elf64_xlatetom.c b/libelf/elf64_xlatetom.c
new file mode 100644
index 0000000..034262c
--- /dev/null
+++ b/libelf/elf64_xlatetom.c
@@ -0,0 +1,31 @@
+/* Convert from file to memory representation.
+   Copyright (C) 1998, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#define LIBELFBITS 64
+#include "elf32_xlatetom.c"
diff --git a/libelf/elf_begin.c b/libelf/elf_begin.c
new file mode 100644
index 0000000..8a49f35
--- /dev/null
+++ b/libelf/elf_begin.c
@@ -0,0 +1,1233 @@
+/* Create descriptor for processing file.
+   Copyright (C) 1998-2010, 2012, 2014, 2015, 2016 Red Hat, Inc.
+   Copyright (C) 2021, 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "libelfP.h"
+#include "common.h"
+
+
+/* Create descriptor for archive in memory.  */
+static inline Elf *
+file_read_ar (int fildes, void *map_address, off_t offset, size_t maxsize,
+	      Elf_Cmd cmd, Elf *parent)
+{
+  Elf *elf;
+
+  /* Create a descriptor.  */
+  elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
+                      ELF_K_AR, 0);
+  if (elf != NULL)
+    {
+      /* We don't read all the symbol tables in advance.  All this will
+	 happen on demand.  */
+      elf->state.ar.offset = offset + SARMAG;
+
+      elf->state.ar.elf_ar_hdr.ar_rawname = elf->state.ar.raw_name;
+    }
+
+  return elf;
+}
+
+
+static size_t
+get_shnum (void *map_address, unsigned char *e_ident, int fildes,
+	   int64_t offset, size_t maxsize)
+{
+  size_t result;
+  union
+  {
+    Elf32_Ehdr *e32;
+    Elf64_Ehdr *e64;
+    void *p;
+  } ehdr;
+  union
+  {
+    Elf32_Ehdr e32;
+    Elf64_Ehdr e64;
+  } ehdr_mem;
+  bool is32 = e_ident[EI_CLASS] == ELFCLASS32;
+
+  if ((is32 && maxsize < sizeof (Elf32_Ehdr))
+      || (!is32 && maxsize < sizeof (Elf64_Ehdr)))
+    {
+       __libelf_seterrno (ELF_E_INVALID_ELF);
+      return (size_t) -1l;
+    }
+
+  /* Make the ELF header available.  */
+  if (e_ident[EI_DATA] == MY_ELFDATA
+      && (ALLOW_UNALIGNED
+	  || (((size_t) e_ident
+	       & ((is32 ? __alignof__ (Elf32_Ehdr) : __alignof__ (Elf64_Ehdr))
+		  - 1)) == 0)))
+    ehdr.p = e_ident;
+  else
+    {
+      /* We already read the ELF header.  We have to copy the header
+	 since we possibly modify the data here and the caller
+	 expects the memory it passes in to be preserved.  */
+      ehdr.p = &ehdr_mem;
+
+      if (is32)
+	{
+	  if (ALLOW_UNALIGNED)
+	    {
+	      ehdr_mem.e32.e_shnum = ((Elf32_Ehdr *) e_ident)->e_shnum;
+	      ehdr_mem.e32.e_shoff = ((Elf32_Ehdr *) e_ident)->e_shoff;
+	    }
+	  else
+	    memcpy (&ehdr_mem, e_ident, sizeof (Elf32_Ehdr));
+
+	  if (e_ident[EI_DATA] != MY_ELFDATA)
+	    {
+	      CONVERT (ehdr_mem.e32.e_shnum);
+	      CONVERT (ehdr_mem.e32.e_shoff);
+	    }
+	}
+      else
+	{
+	  if (ALLOW_UNALIGNED)
+	    {
+	      ehdr_mem.e64.e_shnum = ((Elf64_Ehdr *) e_ident)->e_shnum;
+	      ehdr_mem.e64.e_shoff = ((Elf64_Ehdr *) e_ident)->e_shoff;
+	    }
+	  else
+	    memcpy (&ehdr_mem, e_ident, sizeof (Elf64_Ehdr));
+
+	  if (e_ident[EI_DATA] != MY_ELFDATA)
+	    {
+	      CONVERT (ehdr_mem.e64.e_shnum);
+	      CONVERT (ehdr_mem.e64.e_shoff);
+	    }
+	}
+    }
+
+  if (is32)
+    {
+      /* Get the number of sections from the ELF header.  */
+      result = ehdr.e32->e_shnum;
+
+      if (unlikely (result == 0) && ehdr.e32->e_shoff != 0)
+	{
+	  if (unlikely (ehdr.e32->e_shoff >= maxsize)
+	      || unlikely (maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr)))
+	    /* Cannot read the first section header.  */
+	    return 0;
+
+	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
+	      && (ALLOW_UNALIGNED
+		  || (((size_t) ((char *) (map_address + ehdr.e32->e_shoff
+					   + offset)))
+		      & (__alignof__ (Elf32_Shdr) - 1)) == 0))
+	    /* We can directly access the memory.  */
+	    result = ((Elf32_Shdr *) ((char *) map_address + ehdr.e32->e_shoff
+				      + offset))->sh_size;
+	  else
+	    {
+	      Elf32_Word size;
+	      ssize_t r;
+
+	      if (likely (map_address != NULL))
+		/* gcc will optimize the memcpy to a simple memory
+		   access while taking care of alignment issues.  */
+		memcpy (&size, ((char *) map_address
+					 + ehdr.e32->e_shoff
+					 + offset
+					 + offsetof (Elf32_Shdr, sh_size)),
+			sizeof (Elf32_Word));
+	      else
+		if (unlikely ((r = pread_retry (fildes, &size,
+						sizeof (Elf32_Word),
+						offset + ehdr.e32->e_shoff
+						+ offsetof (Elf32_Shdr,
+							    sh_size)))
+			      != sizeof (Elf32_Word)))
+		  {
+		    if (r < 0)
+		      __libelf_seterrno (ELF_E_INVALID_FILE);
+		    else
+		      __libelf_seterrno (ELF_E_INVALID_ELF);
+		    return (size_t) -1l;
+		  }
+
+	      if (e_ident[EI_DATA] != MY_ELFDATA)
+		CONVERT (size);
+
+	      result = size;
+	    }
+	}
+
+      /* If the section headers were truncated, pretend none were there.  */
+      if (ehdr.e32->e_shoff > maxsize
+	  || maxsize - ehdr.e32->e_shoff < sizeof (Elf32_Shdr) * result)
+	result = 0;
+    }
+  else
+    {
+      /* Get the number of sections from the ELF header.  */
+      result = ehdr.e64->e_shnum;
+
+      if (unlikely (result == 0) && ehdr.e64->e_shoff != 0)
+	{
+	  if (unlikely (ehdr.e64->e_shoff >= maxsize)
+	      || unlikely (ehdr.e64->e_shoff + sizeof (Elf64_Shdr) > maxsize))
+	    /* Cannot read the first section header.  */
+	    return 0;
+
+	  Elf64_Xword size;
+	  if (likely (map_address != NULL) && e_ident[EI_DATA] == MY_ELFDATA
+	      && (ALLOW_UNALIGNED
+		  || (((size_t) ((char *) (map_address + ehdr.e64->e_shoff
+					   + offset)))
+		      & (__alignof__ (Elf64_Shdr) - 1)) == 0))
+	    /* We can directly access the memory.  */
+	    size = ((Elf64_Shdr *) ((char *) map_address + ehdr.e64->e_shoff
+				    + offset))->sh_size;
+	  else
+	    {
+	      ssize_t r;
+	      if (likely (map_address != NULL))
+		/* gcc will optimize the memcpy to a simple memory
+		   access while taking care of alignment issues.  */
+		memcpy (&size, ((char *) map_address
+					 + ehdr.e64->e_shoff
+					 + offset
+					 + offsetof (Elf64_Shdr, sh_size)),
+			sizeof (Elf64_Xword));
+	      else
+		if (unlikely ((r = pread_retry (fildes, &size,
+						sizeof (Elf64_Xword),
+						offset + ehdr.e64->e_shoff
+						+ offsetof (Elf64_Shdr,
+							    sh_size)))
+			      != sizeof (Elf64_Xword)))
+		  {
+		    if (r < 0)
+		      __libelf_seterrno (ELF_E_INVALID_FILE);
+		    else
+		      __libelf_seterrno (ELF_E_INVALID_ELF);
+		    return (size_t) -1l;
+		  }
+
+	      if (e_ident[EI_DATA] != MY_ELFDATA)
+		CONVERT (size);
+	    }
+
+	  /* Although sh_size is an Elf64_Xword and can contain a 64bit
+	     value, we only expect an 32bit value max.  GElf_Word is
+	     32bit unsigned.  */
+	  if (size > ~((GElf_Word) 0))
+	    {
+	      /* Invalid value, it is too large.  */
+	      __libelf_seterrno (ELF_E_INVALID_ELF);
+	      return (size_t) -1l;
+	    }
+
+	  result = size;
+	}
+
+      /* If the section headers were truncated, pretend none were there.  */
+      if (ehdr.e64->e_shoff > maxsize
+	  || maxsize - ehdr.e64->e_shoff < sizeof (Elf64_Shdr) * result)
+	result = 0;
+    }
+
+  return result;
+}
+
+
+/* Create descriptor for ELF file in memory.  */
+static Elf *
+file_read_elf (int fildes, void *map_address, unsigned char *e_ident,
+	       int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent)
+{
+  /* Verify the binary is of the class we can handle.  */
+  if (unlikely ((e_ident[EI_CLASS] != ELFCLASS32
+		 && e_ident[EI_CLASS] != ELFCLASS64)
+		/* We also can only handle two encodings.  */
+		|| (e_ident[EI_DATA] != ELFDATA2LSB
+		    && e_ident[EI_DATA] != ELFDATA2MSB)))
+    {
+      /* Cannot handle this.  */
+      __libelf_seterrno (ELF_E_INVALID_ELF);
+      return NULL;
+    }
+
+  /* Determine the number of sections.  Returns -1 and sets libelf errno
+     if the file handle or elf file is invalid.  Returns zero if there
+     are no section headers (or they cannot be read).  */
+  size_t scncnt = get_shnum (map_address, e_ident, fildes, offset, maxsize);
+  if (scncnt == (size_t) -1l)
+    /* Could not determine the number of sections.  */
+    return NULL;
+
+  /* Check for too many sections.  */
+  if (e_ident[EI_CLASS] == ELFCLASS32)
+    {
+      if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf32_Shdr)))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_ELF);
+	  return NULL;
+	}
+    }
+  else if (scncnt > SIZE_MAX / (sizeof (Elf_Scn) + sizeof (Elf64_Shdr)))
+    {
+      __libelf_seterrno (ELF_E_INVALID_ELF);
+      return NULL;
+    }
+
+  /* We can now allocate the memory.  Even if there are no section headers,
+     we allocate space for a zeroth section in case we need it later.  */
+  const size_t scnmax = (scncnt ?: (cmd == ELF_C_RDWR || cmd == ELF_C_RDWR_MMAP)
+			 ? 1 : 0);
+  Elf *elf = allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
+			   ELF_K_ELF, scnmax * sizeof (Elf_Scn));
+  if (elf == NULL)
+    /* Not enough memory.  allocate_elf will have set libelf errno.  */
+    return NULL;
+
+  assert ((unsigned int) scncnt == scncnt);
+  assert (offsetof (struct Elf, state.elf32.scns)
+	  == offsetof (struct Elf, state.elf64.scns));
+  elf->state.elf32.scns.cnt = scncnt;
+  elf->state.elf32.scns.max = scnmax;
+
+  /* Some more or less arbitrary value.  */
+  elf->state.elf.scnincr = 10;
+
+  /* Make the class easily available.  */
+  elf->class = e_ident[EI_CLASS];
+
+  if (e_ident[EI_CLASS] == ELFCLASS32)
+    {
+      /* This pointer might not be directly usable if the alignment is
+	 not sufficient for the architecture.  */
+      uintptr_t ehdr = (uintptr_t) map_address + offset;
+
+      /* This is a 32-bit binary.  */
+      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
+	  && (ALLOW_UNALIGNED
+	      || (ehdr & (__alignof__ (Elf32_Ehdr) - 1)) == 0))
+	{
+	  /* We can use the mmapped memory.  */
+	  elf->state.elf32.ehdr = (Elf32_Ehdr *) ehdr;
+	}
+      else
+	{
+	  /* Copy the ELF header.  */
+	  elf->state.elf32.ehdr = memcpy (&elf->state.elf32.ehdr_mem, e_ident,
+					  sizeof (Elf32_Ehdr));
+
+	  if (e_ident[EI_DATA] != MY_ELFDATA)
+	    {
+	      CONVERT (elf->state.elf32.ehdr_mem.e_type);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_machine);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_version);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_entry);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_phoff);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_shoff);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_flags);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_ehsize);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_phentsize);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_phnum);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_shentsize);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_shnum);
+	      CONVERT (elf->state.elf32.ehdr_mem.e_shstrndx);
+	    }
+	}
+
+      /* Don't precache the phdr pointer here.
+	 elf32_getphdr will validate it against the size when asked.  */
+
+      Elf32_Off e_shoff = elf->state.elf32.ehdr->e_shoff;
+      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
+	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
+	  && (ALLOW_UNALIGNED
+	      || (((ehdr + e_shoff) & (__alignof__ (Elf32_Shdr) - 1)) == 0)))
+	{
+	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
+	      || unlikely (maxsize - e_shoff
+			   < scncnt * sizeof (Elf32_Shdr)))
+	    {
+	    free_and_out:
+	      free (elf);
+	      __libelf_seterrno (ELF_E_INVALID_ELF);
+	      return NULL;
+	    }
+
+	  if (scncnt > 0)
+	    elf->state.elf32.shdr = (Elf32_Shdr *) (ehdr + e_shoff);
+
+	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
+	    {
+	      elf->state.elf32.scns.data[cnt].index = cnt;
+	      elf->state.elf32.scns.data[cnt].elf = elf;
+	      elf->state.elf32.scns.data[cnt].shdr.e32 =
+		&elf->state.elf32.shdr[cnt];
+	      if (likely (elf->state.elf32.shdr[cnt].sh_offset < maxsize)
+		  && likely (elf->state.elf32.shdr[cnt].sh_size
+			     <= maxsize - elf->state.elf32.shdr[cnt].sh_offset))
+		elf->state.elf32.scns.data[cnt].rawdata_base =
+		  elf->state.elf32.scns.data[cnt].data_base =
+		  ((char *) map_address + offset
+		   + elf->state.elf32.shdr[cnt].sh_offset);
+	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
+
+	      /* If this is a section with an extended index add a
+		 reference in the section which uses the extended
+		 index.  */
+	      if (elf->state.elf32.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
+		  && elf->state.elf32.shdr[cnt].sh_link < scncnt)
+		elf->state.elf32.scns.data[elf->state.elf32.shdr[cnt].sh_link].shndx_index
+		  = cnt;
+
+	      /* Set the own shndx_index field in case it has not yet
+		 been set.  */
+	      if (elf->state.elf32.scns.data[cnt].shndx_index == 0)
+		elf->state.elf32.scns.data[cnt].shndx_index = -1;
+	    }
+	}
+      else
+	{
+	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
+	    {
+	      elf->state.elf32.scns.data[cnt].index = cnt;
+	      elf->state.elf32.scns.data[cnt].elf = elf;
+	      elf->state.elf32.scns.data[cnt].list = &elf->state.elf32.scns;
+	    }
+	}
+
+      /* So far only one block with sections.  */
+      elf->state.elf32.scns_last = &elf->state.elf32.scns;
+    }
+  else
+    {
+      /* This pointer might not be directly usable if the alignment is
+	 not sufficient for the architecture.  */
+      uintptr_t ehdr = (uintptr_t) map_address + offset;
+
+      /* This is a 64-bit binary.  */
+      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
+	  && (ALLOW_UNALIGNED
+	      || (ehdr & (__alignof__ (Elf64_Ehdr) - 1)) == 0))
+	{
+	  /* We can use the mmapped memory.  */
+	  elf->state.elf64.ehdr = (Elf64_Ehdr *) ehdr;
+	}
+      else
+	{
+	  /* Copy the ELF header.  */
+	  elf->state.elf64.ehdr = memcpy (&elf->state.elf64.ehdr_mem, e_ident,
+					  sizeof (Elf64_Ehdr));
+
+	  if (e_ident[EI_DATA] != MY_ELFDATA)
+	    {
+	      CONVERT (elf->state.elf64.ehdr_mem.e_type);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_machine);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_version);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_entry);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_phoff);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_shoff);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_flags);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_ehsize);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_phentsize);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_phnum);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_shentsize);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_shnum);
+	      CONVERT (elf->state.elf64.ehdr_mem.e_shstrndx);
+	    }
+	}
+
+      /* Don't precache the phdr pointer here.
+	 elf64_getphdr will validate it against the size when asked.  */
+
+      Elf64_Off e_shoff = elf->state.elf64.ehdr->e_shoff;
+      if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA
+	  && cmd != ELF_C_READ_MMAP /* We need a copy to be able to write.  */
+	  && (ALLOW_UNALIGNED
+	      || (((ehdr + e_shoff) & (__alignof__ (Elf64_Shdr) - 1)) == 0)))
+	{
+	  if (unlikely (scncnt > 0 && e_shoff >= maxsize)
+	      || unlikely (maxsize - e_shoff
+			   < scncnt * sizeof (Elf64_Shdr)))
+	    goto free_and_out;
+
+	  if (scncnt > 0)
+	    elf->state.elf64.shdr = (Elf64_Shdr *) (ehdr + (ptrdiff_t) e_shoff);
+
+	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
+	    {
+	      elf->state.elf64.scns.data[cnt].index = cnt;
+	      elf->state.elf64.scns.data[cnt].elf = elf;
+	      elf->state.elf64.scns.data[cnt].shdr.e64 =
+		&elf->state.elf64.shdr[cnt];
+	      if (likely (elf->state.elf64.shdr[cnt].sh_offset < maxsize)
+		  && likely (elf->state.elf64.shdr[cnt].sh_size
+			     <= maxsize - elf->state.elf64.shdr[cnt].sh_offset))
+		elf->state.elf64.scns.data[cnt].rawdata_base =
+		  elf->state.elf64.scns.data[cnt].data_base =
+		  ((char *) map_address + offset
+		   + elf->state.elf64.shdr[cnt].sh_offset);
+	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
+
+	      /* If this is a section with an extended index add a
+		 reference in the section which uses the extended
+		 index.  */
+	      if (elf->state.elf64.shdr[cnt].sh_type == SHT_SYMTAB_SHNDX
+		  && elf->state.elf64.shdr[cnt].sh_link < scncnt)
+		elf->state.elf64.scns.data[elf->state.elf64.shdr[cnt].sh_link].shndx_index
+		  = cnt;
+
+	      /* Set the own shndx_index field in case it has not yet
+		 been set.  */
+	      if (elf->state.elf64.scns.data[cnt].shndx_index == 0)
+		elf->state.elf64.scns.data[cnt].shndx_index = -1;
+	    }
+	}
+      else
+	{
+	  for (size_t cnt = 0; cnt < scncnt; ++cnt)
+	    {
+	      elf->state.elf64.scns.data[cnt].index = cnt;
+	      elf->state.elf64.scns.data[cnt].elf = elf;
+	      elf->state.elf64.scns.data[cnt].list = &elf->state.elf64.scns;
+	    }
+	}
+
+      /* So far only one block with sections.  */
+      elf->state.elf64.scns_last = &elf->state.elf64.scns;
+    }
+
+  return elf;
+}
+
+
+Elf *
+internal_function
+__libelf_read_mmaped_file (int fildes, void *map_address,  int64_t offset,
+			   size_t maxsize, Elf_Cmd cmd, Elf *parent)
+{
+  /* We have to find out what kind of file this is.  We handle ELF
+     files and archives.  To find out what we have we must look at the
+     header.  The header for an ELF file is EI_NIDENT bytes in size,
+     the header for an archive file SARMAG bytes long.  */
+  unsigned char *e_ident = (unsigned char *) map_address + offset;
+
+  /* See what kind of object we have here.  */
+  Elf_Kind kind = determine_kind (e_ident, maxsize);
+
+  switch (kind)
+    {
+    case ELF_K_ELF:
+      return file_read_elf (fildes, map_address, e_ident, offset, maxsize,
+			    cmd, parent);
+
+    case ELF_K_AR:
+      return file_read_ar (fildes, map_address, offset, maxsize, cmd, parent);
+
+    default:
+      break;
+    }
+
+  /* This case is easy.  Since we cannot do anything with this file
+     create a dummy descriptor.  */
+  return allocate_elf (fildes, map_address, offset, maxsize, cmd, parent,
+		       ELF_K_NONE, 0);
+}
+
+
+static Elf *
+read_unmmaped_file (int fildes, int64_t offset, size_t maxsize, Elf_Cmd cmd,
+		    Elf *parent)
+{
+  /* We have to find out what kind of file this is.  We handle ELF
+     files and archives.  To find out what we have we must read the
+     header.  The identification header for an ELF file is EI_NIDENT
+     bytes in size, but we read the whole ELF header since we will
+     need it anyway later.  For archives the header in SARMAG bytes
+     long.  Read the maximum of these numbers.
+
+     XXX We have to change this for the extended `ar' format some day.
+
+     Use a union to ensure alignment.  We might later access the
+     memory as a ElfXX_Ehdr.  */
+  union
+  {
+    Elf64_Ehdr ehdr;
+    unsigned char header[MAX (sizeof (Elf64_Ehdr), SARMAG)];
+  } mem;
+
+  /* Read the head of the file.  */
+  ssize_t nread = pread_retry (fildes, mem.header,
+			       MIN (MAX (sizeof (Elf64_Ehdr), SARMAG),
+				    maxsize),
+			       offset);
+  if (unlikely (nread == -1))
+    {
+      /* We cannot even read the head of the file.  Maybe FILDES is associated
+	 with an unseekable device.  This is nothing we can handle.  */
+      __libelf_seterrno (ELF_E_INVALID_FILE);
+      return NULL;
+    }
+
+  /* See what kind of object we have here.  */
+  Elf_Kind kind = determine_kind (mem.header, nread);
+
+  switch (kind)
+    {
+    case ELF_K_AR:
+      return file_read_ar (fildes, NULL, offset, maxsize, cmd, parent);
+
+    case ELF_K_ELF:
+      /* Make sure at least the ELF header is contained in the file.  */
+      if ((size_t) nread >= (mem.header[EI_CLASS] == ELFCLASS32
+			     ? sizeof (Elf32_Ehdr) : sizeof (Elf64_Ehdr)))
+	return file_read_elf (fildes, NULL, mem.header, offset, maxsize, cmd,
+			      parent);
+      FALLTHROUGH;
+
+    default:
+      break;
+    }
+
+  /* This case is easy.  Since we cannot do anything with this file
+     create a dummy descriptor.  */
+  return allocate_elf (fildes, NULL, offset, maxsize, cmd, parent,
+		       ELF_K_NONE, 0);
+}
+
+
+/* Open a file for reading.  If possible we will try to mmap() the file.  */
+static struct Elf *
+read_file (int fildes, int64_t offset, size_t maxsize,
+	   Elf_Cmd cmd, Elf *parent)
+{
+  void *map_address = NULL;
+  int use_mmap = (cmd == ELF_C_READ_MMAP || cmd == ELF_C_RDWR_MMAP
+		  || cmd == ELF_C_WRITE_MMAP
+		  || cmd == ELF_C_READ_MMAP_PRIVATE);
+
+  if (parent == NULL)
+    {
+      if (maxsize == ~((size_t) 0))
+	{
+	  /* We don't know in the moment how large the file is.
+	     Determine it now.  */
+	  struct stat st;
+
+	  if (fstat (fildes, &st) == 0
+	      && (sizeof (size_t) >= sizeof (st.st_size)
+		  || st.st_size <= ~((size_t) 0)))
+	    maxsize = (size_t) st.st_size;
+	}
+    }
+  else
+    {
+      /* The parent is already loaded.  Use it.  */
+      assert (maxsize != ~((size_t) 0));
+    }
+
+  if (use_mmap)
+    {
+      if (parent == NULL)
+	{
+	  /* We try to map the file ourself.  */
+	  map_address = mmap (NULL, maxsize, (cmd == ELF_C_READ_MMAP
+					      ? PROT_READ
+					      : PROT_READ|PROT_WRITE),
+			      cmd == ELF_C_READ_MMAP_PRIVATE
+			      || cmd == ELF_C_READ_MMAP
+			      ? MAP_PRIVATE : MAP_SHARED,
+			      fildes, offset);
+
+	  if (map_address == MAP_FAILED)
+	    map_address = NULL;
+	}
+      else
+	{
+	  map_address = parent->map_address;
+	}
+    }
+
+  /* If we have the file in memory optimize the access.  */
+  if (map_address != NULL)
+    {
+      assert (map_address != MAP_FAILED);
+
+      struct Elf *result = __libelf_read_mmaped_file (fildes, map_address,
+						      offset, maxsize, cmd,
+						      parent);
+
+      /* If something went wrong during the initialization unmap the
+	 memory if we mmaped here.  */
+      if (result == NULL
+	  && (parent == NULL
+	      || parent->map_address != map_address))
+	munmap (map_address, maxsize);
+      else if (parent == NULL)
+	/* Remember that we mmap()ed the memory.  */
+	result->flags |= ELF_F_MMAPPED;
+
+      return result;
+    }
+
+  /* Otherwise we have to do it the hard way.  We read as much as necessary
+     from the file whenever we need information which is not available.  */
+  return read_unmmaped_file (fildes, offset, maxsize, cmd, parent);
+}
+
+
+/* Find the entry with the long names for the content of this archive.  */
+static const char *
+read_long_names (Elf *elf)
+{
+  off_t offset = SARMAG;	/* This is the first entry.  */
+  struct ar_hdr hdrm;
+  struct ar_hdr *hdr;
+  char *newp;
+  size_t len;
+
+  while (1)
+    {
+      if (elf->map_address != NULL)
+	{
+	  if ((size_t) offset > elf->maximum_size
+	      || elf->maximum_size - offset < sizeof (struct ar_hdr))
+	    return NULL;
+
+	  /* The data is mapped.  */
+	  hdr = (struct ar_hdr *) (elf->map_address + offset);
+	}
+      else
+	{
+	  /* Read the header from the file.  */
+	  if (unlikely (pread_retry (elf->fildes, &hdrm, sizeof (hdrm),
+				     elf->start_offset + offset)
+			!= sizeof (hdrm)))
+	    return NULL;
+
+	  hdr = &hdrm;
+	}
+
+      /* The ar_size is given as a fixed size decimal string, right
+	 padded with spaces.  Make sure we read it properly even if
+	 there is no terminating space.  */
+      char buf[sizeof (hdr->ar_size) + 1];
+      const char *string = hdr->ar_size;
+      if (hdr->ar_size[sizeof (hdr->ar_size) - 1] != ' ')
+	{
+	  *((char *) mempcpy (buf, hdr->ar_size, sizeof (hdr->ar_size))) = '\0';
+	  string = buf;
+	}
+
+      /* atol expects to see at least one digit.
+	 It also cannot be negative (-).  */
+      if (!isdigit(string[0]))
+	return NULL;
+      len = atol (string);
+
+      if (memcmp (hdr->ar_name, "//              ", 16) == 0)
+	break;
+
+      offset += sizeof (struct ar_hdr) + ((len + 1) & ~1l);
+    }
+
+  /* Sanity check len early if we can.  */
+  if (elf->map_address != NULL)
+    {
+      if (len > elf->maximum_size - offset - sizeof (struct ar_hdr))
+	return NULL;
+    }
+
+  /* Due to the stupid format of the long name table entry (which are not
+     NUL terminted) we have to provide an appropriate representation anyhow.
+     Therefore we always make a copy which has the appropriate form.  */
+  newp = malloc (len);
+  if (newp != NULL)
+    {
+      char *runp;
+
+      if (elf->map_address != NULL)
+	{
+	  /* Simply copy it over.  */
+	  elf->state.ar.long_names = (char *) memcpy (newp,
+						      elf->map_address + offset
+						      + sizeof (struct ar_hdr),
+						      len);
+	}
+      else
+	{
+	  if (unlikely ((size_t) pread_retry (elf->fildes, newp, len,
+					      elf->start_offset + offset
+					      + sizeof (struct ar_hdr))
+			!= len))
+	    {
+	      /* We were not able to read all data.  */
+	      free (newp);
+	      elf->state.ar.long_names = NULL;
+	      return NULL;
+	    }
+	  elf->state.ar.long_names = newp;
+	}
+
+      elf->state.ar.long_names_len = len;
+
+      /* Now NUL-terminate the strings.  */
+      runp = newp;
+      while (1)
+        {
+	  char *startp = runp;
+	  runp = (char *) memchr (runp, '/', newp + len - runp);
+	  if (runp == NULL)
+	    {
+	      /* This was the last entry.  Clear any left overs.  */
+	      memset (startp, '\0', newp + len - startp);
+	      break;
+	    }
+
+	  /* NUL-terminate the string.  */
+	  *runp++ = '\0';
+
+	  /* A sanity check.  Somebody might have generated invalid
+	     archive.  */
+	  if (runp >= newp + len)
+	    break;
+	}
+    }
+
+  return newp;
+}
+
+
+/* Read the next archive header.  */
+int
+internal_function
+__libelf_next_arhdr_wrlock (Elf *elf)
+{
+  struct ar_hdr *ar_hdr;
+  Elf_Arhdr *elf_ar_hdr;
+
+  if (elf->map_address != NULL)
+    {
+      /* See whether this entry is in the file.  */
+      if (unlikely ((size_t) elf->state.ar.offset
+		    > elf->start_offset + elf->maximum_size
+		    || (elf->start_offset + elf->maximum_size
+			- elf->state.ar.offset) < sizeof (struct ar_hdr)))
+	{
+	  /* This record is not anymore in the file.  */
+	  __libelf_seterrno (ELF_E_RANGE);
+	  return -1;
+	}
+      ar_hdr = (struct ar_hdr *) (elf->map_address + elf->state.ar.offset);
+    }
+  else
+    {
+      ar_hdr = &elf->state.ar.ar_hdr;
+
+      if (unlikely (pread_retry (elf->fildes, ar_hdr, sizeof (struct ar_hdr),
+				 elf->state.ar.offset)
+		    != sizeof (struct ar_hdr)))
+	{
+	  /* Something went wrong while reading the file.  */
+	  __libelf_seterrno (ELF_E_RANGE);
+	  return -1;
+	}
+    }
+
+  /* One little consistency check.  */
+  if (unlikely (memcmp (ar_hdr->ar_fmag, ARFMAG, 2) != 0))
+    {
+      /* This is no valid archive.  */
+      __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
+      return -1;
+    }
+
+  /* Copy the raw name over to a NUL terminated buffer.  */
+  *((char *) mempcpy (elf->state.ar.raw_name, ar_hdr->ar_name, 16)) = '\0';
+
+  elf_ar_hdr = &elf->state.ar.elf_ar_hdr;
+
+  /* Now convert the `struct ar_hdr' into `Elf_Arhdr'.
+     Determine whether this is a special entry.  */
+  if (ar_hdr->ar_name[0] == '/')
+    {
+      if (ar_hdr->ar_name[1] == ' '
+	  && memcmp (ar_hdr->ar_name, "/               ", 16) == 0)
+	/* This is the index.  */
+	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/", 2);
+      else if (ar_hdr->ar_name[1] == 'S'
+	       && memcmp (ar_hdr->ar_name, "/SYM64/         ", 16) == 0)
+	/* 64-bit index.  */
+	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "/SYM64/", 8);
+      else if (ar_hdr->ar_name[1] == '/'
+	       && memcmp (ar_hdr->ar_name, "//              ", 16) == 0)
+	/* This is the array with the long names.  */
+	elf_ar_hdr->ar_name = memcpy (elf->state.ar.ar_name, "//", 3);
+      else if (likely  (isdigit (ar_hdr->ar_name[1])))
+	{
+	  size_t offset;
+
+	  /* This is a long name.  First we have to read the long name
+	     table, if this hasn't happened already.  */
+	  if (unlikely (elf->state.ar.long_names == NULL
+			&& read_long_names (elf) == NULL))
+	    {
+	      /* No long name table although it is reference.  The archive is
+		 broken.  */
+	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
+	      return -1;
+	    }
+
+	  offset = atol (ar_hdr->ar_name + 1);
+	  if (unlikely (offset >= elf->state.ar.long_names_len))
+	    {
+	      /* The index in the long name table is larger than the table.  */
+	      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
+	      return -1;
+	    }
+	  elf_ar_hdr->ar_name = elf->state.ar.long_names + offset;
+	}
+      else
+	{
+	  /* This is none of the known special entries.  */
+	  __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
+	  return -1;
+	}
+    }
+  else
+    {
+      char *endp;
+
+      /* It is a normal entry.  Copy over the name.  */
+      endp = (char *) memccpy (elf->state.ar.ar_name, ar_hdr->ar_name,
+			       '/', 16);
+      if (endp != NULL)
+	endp[-1] = '\0';
+      else
+	{
+	  /* In the old BSD style of archive, there is no / terminator.
+	     Instead, there is space padding at the end of the name.  */
+	  size_t i = 15;
+	  do
+	    elf->state.ar.ar_name[i] = '\0';
+	  while (i > 0 && elf->state.ar.ar_name[--i] == ' ');
+	}
+
+      elf_ar_hdr->ar_name = elf->state.ar.ar_name;
+    }
+
+  if (unlikely (ar_hdr->ar_size[0] == ' '))
+    /* Something is really wrong.  We cannot live without a size for
+       the member since it will not be possible to find the next
+       archive member.  */
+    {
+      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
+      return -1;
+    }
+
+  /* Since there are no specialized functions to convert ASCII to
+     time_t, uid_t, gid_t, mode_t, and off_t we use either atol or
+     atoll depending on the size of the types.  We are also prepared
+     for the case where the whole field in the `struct ar_hdr' is
+     filled in which case we cannot simply use atol/l but instead have
+     to create a temporary copy.  Note that all fields use decimal
+     encoding, except ar_mode which uses octal.  */
+
+#define INT_FIELD(FIELD)						      \
+  do									      \
+    {									      \
+      char buf[sizeof (ar_hdr->FIELD) + 1];				      \
+      const char *string = ar_hdr->FIELD;				      \
+      if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
+	{								      \
+	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
+	    = '\0';							      \
+	  string = buf;							      \
+	}								      \
+      if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
+	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atol (string);     \
+      else								      \
+	elf_ar_hdr->FIELD = (__typeof (elf_ar_hdr->FIELD)) atoll (string);    \
+    }									      \
+  while (0)
+
+#define OCT_FIELD(FIELD)						      \
+  do									      \
+    {									      \
+      char buf[sizeof (ar_hdr->FIELD) + 1];				      \
+      const char *string = ar_hdr->FIELD;				      \
+      if (ar_hdr->FIELD[sizeof (ar_hdr->FIELD) - 1] != ' ')		      \
+	{								      \
+	  *((char *) mempcpy (buf, ar_hdr->FIELD, sizeof (ar_hdr->FIELD)))  \
+	    = '\0';							      \
+	  string = buf;							      \
+	}								      \
+      if (sizeof (elf_ar_hdr->FIELD) <= sizeof (long int))		      \
+	elf_ar_hdr->FIELD						      \
+	  = (__typeof (elf_ar_hdr->FIELD)) strtol (string, NULL, 8);	      \
+      else								      \
+	elf_ar_hdr->FIELD						      \
+	  = (__typeof (elf_ar_hdr->FIELD)) strtoll (string, NULL, 8);	      \
+    }									      \
+  while (0)
+
+  INT_FIELD (ar_date);
+  INT_FIELD (ar_uid);
+  INT_FIELD (ar_gid);
+  OCT_FIELD (ar_mode);
+  INT_FIELD (ar_size);
+
+  if (elf_ar_hdr->ar_size < 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_ARCHIVE);
+      return -1;
+    }
+
+  /* Truncated file?  */
+  size_t maxsize;
+  maxsize = (elf->start_offset + elf->maximum_size
+	     - elf->state.ar.offset - sizeof (struct ar_hdr));
+  if ((size_t) elf_ar_hdr->ar_size > maxsize)
+    elf_ar_hdr->ar_size = maxsize;
+
+  return 0;
+}
+
+
+/* We were asked to return a clone of an existing descriptor.  This
+   function must be called with the lock on the parent descriptor
+   being held. */
+static Elf *
+dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
+{
+  struct Elf *result;
+
+  if (fildes == -1)
+    /* Allow the user to pass -1 as the file descriptor for the new file.  */
+    fildes = ref->fildes;
+  /* The file descriptor better should be the same.  If it was disconnected
+     already (using `elf_cntl') we do not test it.  */
+  else if (unlikely (ref->fildes != -1 && fildes != ref->fildes))
+    {
+      __libelf_seterrno (ELF_E_FD_MISMATCH);
+      return NULL;
+    }
+
+  /* The mode must allow reading.  I.e., a descriptor creating with a
+     command different then ELF_C_READ, ELF_C_WRITE and ELF_C_RDWR is
+     not allowed.  */
+  if (unlikely (ref->cmd != ELF_C_READ && ref->cmd != ELF_C_READ_MMAP
+		&& ref->cmd != ELF_C_WRITE && ref->cmd != ELF_C_WRITE_MMAP
+		&& ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
+		&& ref->cmd != ELF_C_READ_MMAP_PRIVATE))
+    {
+      __libelf_seterrno (ELF_E_INVALID_OP);
+      return NULL;
+    }
+
+  /* Now it is time to distinguish between reading normal files and
+     archives.  Normal files can easily be handled be incrementing the
+     reference counter and return the same descriptor.  */
+  if (ref->kind != ELF_K_AR)
+    {
+      ++ref->ref_count;
+      return ref;
+    }
+
+  /* This is an archive.  We must create a descriptor for the archive
+     member the internal pointer of the archive file descriptor is
+     pointing to.  First read the header of the next member if this
+     has not happened already.  */
+  if (ref->state.ar.elf_ar_hdr.ar_name == NULL
+      && __libelf_next_arhdr_wrlock (ref) != 0)
+    /* Something went wrong.  Maybe there is no member left.  */
+    return NULL;
+
+  /* We have all the information we need about the next archive member.
+     Now create a descriptor for it.  */
+  result = read_file (fildes, ref->state.ar.offset + sizeof (struct ar_hdr),
+		      ref->state.ar.elf_ar_hdr.ar_size, cmd, ref);
+
+  /* Enlist this new descriptor in the list of children.  */
+  if (result != NULL)
+    {
+      result->next = ref->state.ar.children;
+      ref->state.ar.children = result;
+    }
+
+  return result;
+}
+
+
+/* Return descriptor for empty file ready for writing.  */
+static struct Elf *
+write_file (int fd, Elf_Cmd cmd)
+{
+  /* We simply create an empty `Elf' structure.  */
+#define NSCNSALLOC	10
+  Elf *result = allocate_elf (fd, NULL, 0, 0, cmd, NULL, ELF_K_ELF,
+			      NSCNSALLOC * sizeof (Elf_Scn));
+
+  if (result != NULL)
+    {
+      /* We have to write to the file in any case.  */
+      result->flags = ELF_F_DIRTY;
+
+      /* Some more or less arbitrary value.  */
+      result->state.elf.scnincr = NSCNSALLOC;
+
+      /* We have allocated room for some sections.  */
+      assert (offsetof (struct Elf, state.elf32.scns)
+	      == offsetof (struct Elf, state.elf64.scns));
+      result->state.elf.scns_last = &result->state.elf32.scns;
+      result->state.elf32.scns.max = NSCNSALLOC;
+    }
+
+  return result;
+}
+
+/* Lock if necessary before dup an archive.  */
+static inline Elf *
+lock_dup_elf (int fildes, Elf_Cmd cmd, Elf *ref)
+{
+  /* We need wrlock to dup an archive.  */
+  if (ref->kind == ELF_K_AR)
+    {
+      rwlock_unlock (ref->lock);
+      rwlock_wrlock (ref->lock);
+    }
+    /* Duplicate the descriptor.  */
+  return dup_elf (fildes, cmd, ref);
+}
+
+/* Return a descriptor for the file belonging to FILDES.  */
+Elf *
+elf_begin (int fildes, Elf_Cmd cmd, Elf *ref)
+{
+  Elf *retval;
+
+  if (unlikely (__libelf_version != EV_CURRENT))
+    {
+      /* Version wasn't set so far.  */
+      __libelf_seterrno (ELF_E_NO_VERSION);
+      return NULL;
+    }
+
+  if (ref != NULL)
+    /* Make sure the descriptor is not suddenly going away.  */
+    rwlock_rdlock (ref->lock);
+  else if (unlikely (fcntl (fildes, F_GETFD) == -1 && errno == EBADF))
+    {
+      /* We cannot do anything productive without a file descriptor.  */
+      __libelf_seterrno (ELF_E_INVALID_FILE);
+      return NULL;
+    }
+
+  switch (cmd)
+    {
+    case ELF_C_NULL:
+      /* We simply return a NULL pointer.  */
+      retval = NULL;
+      break;
+
+    case ELF_C_READ_MMAP_PRIVATE:
+      /* If we have a reference it must also be opened this way.  */
+      if (unlikely (ref != NULL && ref->cmd != ELF_C_READ_MMAP_PRIVATE))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_CMD);
+	  retval = NULL;
+	  break;
+	}
+      FALLTHROUGH;
+
+    case ELF_C_READ:
+    case ELF_C_READ_MMAP:
+      if (ref != NULL)
+	retval = lock_dup_elf (fildes, cmd, ref);
+      else
+	/* Create descriptor for existing file.  */
+	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
+      break;
+
+    case ELF_C_RDWR:
+    case ELF_C_RDWR_MMAP:
+      /* If we have a REF object it must also be opened using this
+	 command.  */
+      if (ref != NULL)
+	{
+	  if (unlikely (ref->cmd != ELF_C_RDWR && ref->cmd != ELF_C_RDWR_MMAP
+			&& ref->cmd != ELF_C_WRITE
+			&& ref->cmd != ELF_C_WRITE_MMAP))
+	    {
+	      /* This is not ok.  REF must also be opened for writing.  */
+	      __libelf_seterrno (ELF_E_INVALID_CMD);
+	      retval = NULL;
+	    }
+	  else
+	    retval = lock_dup_elf (fildes, cmd, ref);
+	}
+      else
+	/* Create descriptor for existing file.  */
+	retval = read_file (fildes, 0, ~((size_t) 0), cmd, NULL);
+      break;
+
+    case ELF_C_WRITE:
+    case ELF_C_WRITE_MMAP:
+      /* We ignore REF and prepare a descriptor to write a new file.  */
+      retval = write_file (fildes, cmd);
+      break;
+
+    default:
+      __libelf_seterrno (ELF_E_INVALID_CMD);
+      retval = NULL;
+      break;
+    }
+
+  /* Release the lock.  */
+  if (ref != NULL)
+    rwlock_unlock (ref->lock);
+
+  return retval;
+}
+INTDEF(elf_begin)
diff --git a/libelf/elf_clone.c b/libelf/elf_clone.c
new file mode 100644
index 0000000..e6fe472
--- /dev/null
+++ b/libelf/elf_clone.c
@@ -0,0 +1,81 @@
+/* Create clone of a given descriptor.
+   Copyright (C) 2003, 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2003.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+#include "libelfP.h"
+#include "common.h"
+
+
+Elf *
+elf_clone (Elf *elf, Elf_Cmd cmd)
+{
+  Elf *retval = NULL;
+
+  if (elf == NULL)
+    /* Some earlier mistake.  */
+    return NULL;
+
+  /* Make sure the descriptor is not suddenly going away.  */
+  rwlock_rdlock (elf->lock);
+
+  if (cmd != ELF_C_EMPTY)
+    // XXX TODO handle ELF_C_READ/WRITE etc
+    goto out;
+
+  retval = allocate_elf (elf->fildes, elf->map_address, elf->start_offset,
+			 elf->maximum_size, elf->cmd, elf->parent, elf->kind,
+			 elf->state.elf32.scns.max * sizeof (Elf_Scn));
+  if (retval != NULL)
+    {
+      /* We have to write to the file in any case.  */
+      retval->flags = ELF_F_DIRTY;
+
+      /* Some more or less arbitrary value.  */
+      retval->state.elf.scnincr = 10;
+
+      /* We have allocated room for some sections.  */
+      assert (offsetof (struct Elf, state.elf32.scns)
+	      == offsetof (struct Elf, state.elf64.scns));
+      retval->state.elf.scns_last = &retval->state.elf32.scns;
+      retval->state.elf32.scns.max = elf->state.elf32.scns.max;
+
+      retval->class = elf->class;
+    }
+
+  /* Release the lock.  */
+ out:
+  rwlock_unlock (elf->lock);
+
+  return retval;
+}
diff --git a/libelf/elf_cntl.c b/libelf/elf_cntl.c
new file mode 100644
index 0000000..04aa913
--- /dev/null
+++ b/libelf/elf_cntl.c
@@ -0,0 +1,79 @@
+/* Control an ELF file desrciptor.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libelfP.h"
+
+
+int
+elf_cntl (Elf *elf, Elf_Cmd cmd)
+{
+  int result = 0;
+
+  if (elf == NULL)
+    return -1;
+
+  if (elf->fildes == -1)
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return -1;
+    }
+
+  rwlock_wrlock (elf->lock);
+
+  switch (cmd)
+    {
+    case ELF_C_FDREAD:
+      /* If not all of the file is in the memory read it now.  */
+      if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
+	{
+	  /* We were not able to read everything.  */
+	  result = -1;
+	  break;
+	}
+      FALLTHROUGH;
+
+    case ELF_C_FDDONE:
+      /* Mark the file descriptor as not usable.  */
+      elf->fildes = -1;
+      break;
+
+    default:
+      __libelf_seterrno (ELF_E_INVALID_CMD);
+      result = -1;
+      break;
+    }
+
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/elf_compress.c b/libelf/elf_compress.c
new file mode 100644
index 0000000..0ad6a32
--- /dev/null
+++ b/libelf/elf_compress.c
@@ -0,0 +1,749 @@
+/* Compress or decompress a section.
+   Copyright (C) 2015, 2016 Red Hat, Inc.
+   Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include "libelfP.h"
+#include "common.h"
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <zlib.h>
+
+#ifdef USE_ZSTD
+#include <zstd.h>
+#endif
+
+/* Cleanup and return result.  Don't leak memory.  */
+static void *
+do_deflate_cleanup (void *result, z_stream *z, void *out_buf,
+                    Elf_Data *cdatap)
+{
+  deflateEnd (z);
+  free (out_buf);
+  if (cdatap != NULL)
+    free (cdatap->d_buf);
+  return result;
+}
+
+#define deflate_cleanup(result, cdata) \
+    do_deflate_cleanup(result, &z, out_buf, cdata)
+
+static
+void *
+__libelf_compress_zlib (Elf_Scn *scn, size_t hsize, int ei_data,
+			size_t *orig_size, size_t *orig_addralign,
+			size_t *new_size, bool force,
+			Elf_Data *data, Elf_Data *next_data,
+			void *out_buf, size_t out_size, size_t block)
+{
+  /* Caller gets to fill in the header at the start.  Just skip it here.  */
+  size_t used = hsize;
+
+  z_stream z;
+  z.zalloc = Z_NULL;
+  z.zfree = Z_NULL;
+  z.opaque = Z_NULL;
+  int zrc = deflateInit (&z, Z_BEST_COMPRESSION);
+  if (zrc != Z_OK)
+    {
+      __libelf_seterrno (ELF_E_COMPRESS_ERROR);
+      return deflate_cleanup(NULL, NULL);
+    }
+
+  Elf_Data cdata;
+  cdata.d_buf = NULL;
+
+  /* Loop over data buffers.  */
+  int flush = Z_NO_FLUSH;
+  do
+    {
+      /* Convert to raw if different endianness.  */
+      cdata = *data;
+      bool convert = ei_data != MY_ELFDATA && data->d_size > 0;
+      if (convert)
+	{
+	  /* Don't do this conversion in place, we might want to keep
+	     the original data around, caller decides.  */
+	  cdata.d_buf = malloc (data->d_size);
+	  if (cdata.d_buf == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return deflate_cleanup (NULL, NULL);
+	    }
+	  if (gelf_xlatetof (scn->elf, &cdata, data, ei_data) == NULL)
+	    return deflate_cleanup (NULL, &cdata);
+	}
+
+      z.avail_in = cdata.d_size;
+      z.next_in = cdata.d_buf;
+
+      /* Get next buffer to see if this is the last one.  */
+      data = next_data;
+      if (data != NULL)
+	{
+	  *orig_addralign = MAX (*orig_addralign, data->d_align);
+	  *orig_size += data->d_size;
+	  next_data = elf_getdata (scn, data);
+	}
+      else
+	flush = Z_FINISH;
+
+      /* Flush one data buffer.  */
+      do
+	{
+	  z.avail_out = out_size - used;
+	  z.next_out = out_buf + used;
+	  zrc = deflate (&z, flush);
+	  if (zrc == Z_STREAM_ERROR)
+	    {
+	      __libelf_seterrno (ELF_E_COMPRESS_ERROR);
+	      return deflate_cleanup (NULL, convert ? &cdata : NULL);
+	    }
+	  used += (out_size - used) - z.avail_out;
+
+	  /* Bail out if we are sure the user doesn't want the
+	     compression forced and we are using more compressed data
+	     than original data.  */
+	  if (!force && flush == Z_FINISH && used >= *orig_size)
+	    return deflate_cleanup ((void *) -1, convert ? &cdata : NULL);
+
+	  if (z.avail_out == 0)
+	    {
+	      void *bigger = realloc (out_buf, out_size + block);
+	      if (bigger == NULL)
+		{
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  return deflate_cleanup (NULL, convert ? &cdata : NULL);
+		}
+	      out_buf = bigger;
+	      out_size += block;
+	    }
+	}
+      while (z.avail_out == 0); /* Need more output buffer.  */
+
+      if (convert)
+	{
+	  free (cdata.d_buf);
+	  cdata.d_buf = NULL;
+	}
+    }
+  while (flush != Z_FINISH); /* More data blocks.  */
+
+  if (zrc != Z_STREAM_END)
+    {
+      __libelf_seterrno (ELF_E_COMPRESS_ERROR);
+      return deflate_cleanup (NULL, NULL);
+    }
+
+  deflateEnd (&z);
+  *new_size = used;
+  return out_buf;
+}
+
+#ifdef USE_ZSTD_COMPRESS
+/* Cleanup and return result.  Don't leak memory.  */
+static void *
+do_zstd_cleanup (void *result, ZSTD_CCtx * const cctx, void *out_buf,
+		 Elf_Data *cdatap)
+{
+  ZSTD_freeCCtx (cctx);
+  free (out_buf);
+  if (cdatap != NULL)
+    free (cdatap->d_buf);
+  return result;
+}
+
+#define zstd_cleanup(result, cdata) \
+    do_zstd_cleanup(result, cctx, out_buf, cdata)
+
+static
+void *
+__libelf_compress_zstd (Elf_Scn *scn, size_t hsize, int ei_data,
+			size_t *orig_size, size_t *orig_addralign,
+			size_t *new_size, bool force,
+			Elf_Data *data, Elf_Data *next_data,
+			void *out_buf, size_t out_size, size_t block)
+{
+  /* Caller gets to fill in the header at the start.  Just skip it here.  */
+  size_t used = hsize;
+
+  ZSTD_CCtx* const cctx = ZSTD_createCCtx();
+  Elf_Data cdata;
+  cdata.d_buf = NULL;
+
+  /* Loop over data buffers.  */
+  ZSTD_EndDirective mode = ZSTD_e_continue;
+
+  do
+    {
+      /* Convert to raw if different endianness.  */
+      cdata = *data;
+      bool convert = ei_data != MY_ELFDATA && data->d_size > 0;
+      if (convert)
+	{
+	  /* Don't do this conversion in place, we might want to keep
+	     the original data around, caller decides.  */
+	  cdata.d_buf = malloc (data->d_size);
+	  if (cdata.d_buf == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return zstd_cleanup (NULL, NULL);
+	    }
+	  if (gelf_xlatetof (scn->elf, &cdata, data, ei_data) == NULL)
+	    return zstd_cleanup (NULL, &cdata);
+	}
+
+      ZSTD_inBuffer ib = { cdata.d_buf, cdata.d_size, 0 };
+
+      /* Get next buffer to see if this is the last one.  */
+      data = next_data;
+      if (data != NULL)
+	{
+	  *orig_addralign = MAX (*orig_addralign, data->d_align);
+	  *orig_size += data->d_size;
+	  next_data = elf_getdata (scn, data);
+	}
+      else
+	mode = ZSTD_e_end;
+
+      /* Flush one data buffer.  */
+      for (;;)
+	{
+	  ZSTD_outBuffer ob = { out_buf + used, out_size - used, 0 };
+	  size_t ret = ZSTD_compressStream2 (cctx, &ob, &ib, mode);
+	  if (ZSTD_isError (ret))
+	    {
+	      __libelf_seterrno (ELF_E_COMPRESS_ERROR);
+	      return zstd_cleanup (NULL, convert ? &cdata : NULL);
+	    }
+	  used += ob.pos;
+
+	  /* Bail out if we are sure the user doesn't want the
+	     compression forced and we are using more compressed data
+	     than original data.  */
+	  if (!force && mode == ZSTD_e_end && used >= *orig_size)
+	    return zstd_cleanup ((void *) -1, convert ? &cdata : NULL);
+
+	  if (ret > 0)
+	    {
+	      void *bigger = realloc (out_buf, out_size + block);
+	      if (bigger == NULL)
+		{
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  return zstd_cleanup (NULL, convert ? &cdata : NULL);
+		}
+	      out_buf = bigger;
+	      out_size += block;
+	    }
+	  else
+	    break;
+	}
+
+      if (convert)
+	{
+	  free (cdata.d_buf);
+	  cdata.d_buf = NULL;
+	}
+    }
+  while (mode != ZSTD_e_end); /* More data blocks.  */
+
+  ZSTD_freeCCtx (cctx);
+  *new_size = used;
+  return out_buf;
+}
+#endif
+
+/* Given a section, uses the (in-memory) Elf_Data to extract the
+   original data size (including the given header size) and data
+   alignment.  Returns a buffer that has at least hsize bytes (for the
+   caller to fill in with a header) plus zlib compressed date.  Also
+   returns the new buffer size in new_size (hsize + compressed data
+   size).  Returns (void *) -1 when FORCE is false and the compressed
+   data would be bigger than the original data.  */
+void *
+internal_function
+__libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
+		   size_t *orig_size, size_t *orig_addralign,
+		   size_t *new_size, bool force, bool use_zstd)
+{
+  /* The compressed data is the on-disk data.  We simplify the
+     implementation a bit by asking for the (converted) in-memory
+     data (which might be all there is if the user created it with
+     elf_newdata) and then convert back to raw if needed before
+     compressing.  Should be made a bit more clever to directly
+     use raw if that is directly available.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return NULL;
+
+  /* When not forced and we immediately know we would use more data by
+     compressing, because of the header plus zlib overhead (five bytes
+     per 16 KB block, plus a one-time overhead of six bytes for the
+     entire stream), don't do anything.
+     Size estimation for ZSTD compression would be similar.  */
+  Elf_Data *next_data = elf_getdata (scn, data);
+  if (next_data == NULL && !force
+      && data->d_size <= hsize + 5 + 6)
+    return (void *) -1;
+
+  *orig_addralign = data->d_align;
+  *orig_size = data->d_size;
+
+  /* Guess an output block size. 1/8th of the original Elf_Data plus
+     hsize.  Make the first chunk twice that size (25%), then increase
+     by a block (12.5%) when necessary.  */
+  size_t block = (data->d_size / 8) + hsize;
+  size_t out_size = 2 * block;
+  void *out_buf = malloc (out_size);
+  if (out_buf == NULL)
+    {
+      __libelf_seterrno (ELF_E_NOMEM);
+      return NULL;
+    }
+
+  if (use_zstd)
+    {
+#ifdef USE_ZSTD_COMPRESS
+      return __libelf_compress_zstd (scn, hsize, ei_data, orig_size,
+				   orig_addralign, new_size, force,
+				   data, next_data, out_buf, out_size,
+				   block);
+#else
+    __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
+    return NULL;
+#endif
+    }
+  else
+    return __libelf_compress_zlib (scn, hsize, ei_data, orig_size,
+				   orig_addralign, new_size, force,
+				   data, next_data, out_buf, out_size,
+				   block);
+}
+
+void *
+internal_function
+__libelf_decompress_zlib (void *buf_in, size_t size_in, size_t size_out)
+{
+  /* Catch highly unlikely compression ratios so we don't allocate
+     some giant amount of memory for nothing. The max compression
+     factor 1032:1 comes from http://www.zlib.net/zlib_tech.html  */
+  if (unlikely (size_out / 1032 > size_in))
+    {
+      __libelf_seterrno (ELF_E_INVALID_DATA);
+      return NULL;
+    }
+
+  /* Malloc might return NULL when requesting zero size.  This is highly
+     unlikely, it would only happen when the compression was forced.
+     But we do need a non-NULL buffer to return and set as result.
+     Just make sure to always allocate at least 1 byte.  */
+  void *buf_out = malloc (size_out ?: 1);
+  if (unlikely (buf_out == NULL))
+    {
+      __libelf_seterrno (ELF_E_NOMEM);
+      return NULL;
+    }
+
+  z_stream z =
+    {
+      .next_in = buf_in,
+      .avail_in = size_in,
+      .next_out = buf_out,
+      .avail_out = size_out
+    };
+  int zrc = inflateInit (&z);
+  while (z.avail_in > 0 && likely (zrc == Z_OK))
+    {
+      z.next_out = buf_out + (size_out - z.avail_out);
+      zrc = inflate (&z, Z_FINISH);
+      if (unlikely (zrc != Z_STREAM_END))
+	{
+	  zrc = Z_DATA_ERROR;
+	  break;
+	}
+      zrc = inflateReset (&z);
+    }
+
+  if (unlikely (zrc != Z_OK) || unlikely (z.avail_out != 0))
+    {
+      free (buf_out);
+      buf_out = NULL;
+      __libelf_seterrno (ELF_E_DECOMPRESS_ERROR);
+    }
+
+  inflateEnd(&z);
+  return buf_out;
+}
+
+#ifdef USE_ZSTD
+static void *
+__libelf_decompress_zstd (void *buf_in, size_t size_in, size_t size_out)
+{
+  /* Malloc might return NULL when requesting zero size.  This is highly
+     unlikely, it would only happen when the compression was forced.
+     But we do need a non-NULL buffer to return and set as result.
+     Just make sure to always allocate at least 1 byte.  */
+  void *buf_out = malloc (size_out ?: 1);
+  if (unlikely (buf_out == NULL))
+    {
+      __libelf_seterrno (ELF_E_NOMEM);
+      return NULL;
+    }
+
+  size_t ret = ZSTD_decompress (buf_out, size_out, buf_in, size_in);
+  if (unlikely (ZSTD_isError (ret)) || unlikely (ret != size_out))
+    {
+      free (buf_out);
+      __libelf_seterrno (ELF_E_DECOMPRESS_ERROR);
+      return NULL;
+    }
+  else
+    return buf_out;
+}
+#endif
+
+void *
+internal_function
+__libelf_decompress (int chtype, void *buf_in, size_t size_in, size_t size_out)
+{
+  if (chtype == ELFCOMPRESS_ZLIB)
+    return __libelf_decompress_zlib (buf_in, size_in, size_out);
+  else
+    {
+#ifdef USE_ZSTD
+    return __libelf_decompress_zstd (buf_in, size_in, size_out);
+#else
+    __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
+    return NULL;
+#endif
+    }
+}
+
+void *
+internal_function
+__libelf_decompress_elf (Elf_Scn *scn, size_t *size_out, size_t *addralign)
+{
+  GElf_Chdr chdr;
+  if (gelf_getchdr (scn, &chdr) == NULL)
+    return NULL;
+
+  bool unknown_compression = false;
+  if (chdr.ch_type != ELFCOMPRESS_ZLIB)
+    {
+      if (chdr.ch_type != ELFCOMPRESS_ZSTD)
+	unknown_compression = true;
+
+#ifndef USE_ZSTD
+      if (chdr.ch_type == ELFCOMPRESS_ZSTD)
+	unknown_compression = true;
+#endif
+    }
+
+  if (unknown_compression)
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
+      return NULL;
+    }
+
+  if (! powerof2 (chdr.ch_addralign))
+    {
+      __libelf_seterrno (ELF_E_INVALID_ALIGN);
+      return NULL;
+    }
+
+  /* Take the in-memory representation, so we can even handle a
+     section that has just been constructed (maybe it was copied
+     over from some other ELF file first with elf_newdata).  This
+     is slightly inefficient when the raw data needs to be
+     converted since then we'll be converting the whole buffer and
+     not just Chdr.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return NULL;
+
+  int elfclass = scn->elf->class;
+  size_t hsize = (elfclass == ELFCLASS32
+		  ? sizeof (Elf32_Chdr) : sizeof (Elf64_Chdr));
+  size_t size_in = data->d_size - hsize;
+  void *buf_in = data->d_buf + hsize;
+  void *buf_out
+    = __libelf_decompress (chdr.ch_type, buf_in, size_in, chdr.ch_size);
+
+  *size_out = chdr.ch_size;
+  *addralign = chdr.ch_addralign;
+  return buf_out;
+}
+
+/* Assumes buf is a malloced buffer.  */
+void
+internal_function
+__libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size, size_t align,
+			Elf_Type type)
+{
+  /* This is the new raw data, replace and possibly free old data.  */
+  scn->rawdata.d.d_off = 0;
+  scn->rawdata.d.d_version = EV_CURRENT;
+  scn->rawdata.d.d_buf = buf;
+  scn->rawdata.d.d_size = size;
+  scn->rawdata.d.d_align = align;
+  scn->rawdata.d.d_type = type;
+
+  /* Existing existing data is no longer valid.  */
+  scn->data_list_rear = NULL;
+  if (scn->data_base != scn->rawdata_base)
+    free (scn->data_base);
+  scn->data_base = NULL;
+  if (scn->zdata_base != buf
+      && scn->zdata_base != scn->rawdata_base)
+    {
+      free (scn->zdata_base);
+      scn->zdata_base = NULL;
+    }
+  if (scn->elf->map_address == NULL
+      || scn->rawdata_base == scn->zdata_base
+      || (scn->flags & ELF_F_MALLOCED) != 0)
+    {
+      free (scn->rawdata_base);
+      scn->rawdata_base = NULL;
+      scn->zdata_base = NULL;
+    }
+
+  scn->rawdata_base = buf;
+  scn->flags |= ELF_F_MALLOCED;
+
+  /* Pretend we (tried to) read the data from the file and setup the
+     data (might have to convert the Chdr to native format).  */
+  scn->data_read = 1;
+  scn->flags |= ELF_F_FILEDATA;
+  __libelf_set_data_list_rdlock (scn, 1);
+}
+
+int
+elf_compress (Elf_Scn *scn, int type, unsigned int flags)
+{
+  if (scn == NULL)
+    return -1;
+
+  if ((flags & ~ELF_CHF_FORCE) != 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return -1;
+    }
+
+  bool force = (flags & ELF_CHF_FORCE) != 0;
+
+  Elf *elf = scn->elf;
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    return -1;
+
+  int elfclass = elf->class;
+  int elfdata = ehdr.e_ident[EI_DATA];
+
+  Elf64_Xword sh_flags;
+  Elf64_Word sh_type;
+  Elf64_Xword sh_addralign;
+  if (elfclass == ELFCLASS32)
+    {
+      Elf32_Shdr *shdr = elf32_getshdr (scn);
+      if (shdr == NULL)
+	return -1;
+
+      sh_flags = shdr->sh_flags;
+      sh_type = shdr->sh_type;
+      sh_addralign = shdr->sh_addralign;
+    }
+  else
+    {
+      Elf64_Shdr *shdr = elf64_getshdr (scn);
+      if (shdr == NULL)
+	return -1;
+
+      sh_flags = shdr->sh_flags;
+      sh_type = shdr->sh_type;
+      sh_addralign = shdr->sh_addralign;
+    }
+
+  if ((sh_flags & SHF_ALLOC) != 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
+      return -1;
+    }
+
+  if (sh_type == SHT_NULL || sh_type == SHT_NOBITS)
+    {
+      __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
+      return -1;
+    }
+
+  int compressed = (sh_flags & SHF_COMPRESSED);
+  if (type == ELFCOMPRESS_ZLIB || type == ELFCOMPRESS_ZSTD)
+    {
+      /* Compress/Deflate.  */
+      if (compressed == 1)
+	{
+	  __libelf_seterrno (ELF_E_ALREADY_COMPRESSED);
+	  return -1;
+	}
+
+      size_t hsize = (elfclass == ELFCLASS32
+		      ? sizeof (Elf32_Chdr) : sizeof (Elf64_Chdr));
+      size_t orig_size, orig_addralign, new_size;
+      void *out_buf = __libelf_compress (scn, hsize, elfdata,
+					 &orig_size, &orig_addralign,
+					 &new_size, force,
+					 type == ELFCOMPRESS_ZSTD);
+
+      /* Compression would make section larger, don't change anything.  */
+      if (out_buf == (void *) -1)
+	return 0;
+
+      /* Compression failed, return error.  */
+      if (out_buf == NULL)
+	return -1;
+
+      /* Put the header in front of the data.  */
+      if (elfclass == ELFCLASS32)
+	{
+	  Elf32_Chdr chdr;
+	  chdr.ch_type = type;
+	  chdr.ch_size = orig_size;
+	  chdr.ch_addralign = orig_addralign;
+	  if (elfdata != MY_ELFDATA)
+	    {
+	      CONVERT (chdr.ch_type);
+	      CONVERT (chdr.ch_size);
+	      CONVERT (chdr.ch_addralign);
+	    }
+	  memcpy (out_buf, &chdr, sizeof (Elf32_Chdr));
+	}
+      else
+	{
+	  Elf64_Chdr chdr;
+	  chdr.ch_type = type;
+	  chdr.ch_reserved = 0;
+	  chdr.ch_size = orig_size;
+	  chdr.ch_addralign = sh_addralign;
+	  if (elfdata != MY_ELFDATA)
+	    {
+	      CONVERT (chdr.ch_type);
+	      CONVERT (chdr.ch_reserved);
+	      CONVERT (chdr.ch_size);
+	      CONVERT (chdr.ch_addralign);
+	    }
+	  memcpy (out_buf, &chdr, sizeof (Elf64_Chdr));
+	}
+
+      /* Note we keep the sh_entsize as is, we assume it is setup
+	 correctly and ignored when SHF_COMPRESSED is set.  */
+      if (elfclass == ELFCLASS32)
+	{
+	  Elf32_Shdr *shdr = elf32_getshdr (scn);
+	  shdr->sh_size = new_size;
+	  shdr->sh_addralign = __libelf_type_align (ELFCLASS32, ELF_T_CHDR);
+	  shdr->sh_flags |= SHF_COMPRESSED;
+	}
+      else
+	{
+	  Elf64_Shdr *shdr = elf64_getshdr (scn);
+	  shdr->sh_size = new_size;
+	  shdr->sh_addralign = __libelf_type_align (ELFCLASS64, ELF_T_CHDR);
+	  shdr->sh_flags |= SHF_COMPRESSED;
+	}
+
+      __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_CHDR);
+
+      /* The section is now compressed, we could keep the uncompressed
+	 data around, but since that might have been multiple Elf_Data
+	 buffers let the user uncompress it explicitly again if they
+	 want it to simplify bookkeeping.  */
+      free (scn->zdata_base);
+      scn->zdata_base = NULL;
+
+      return 1;
+    }
+  else if (type == 0)
+    {
+      /* Decompress/Inflate.  */
+      if (compressed == 0)
+	{
+	  __libelf_seterrno (ELF_E_NOT_COMPRESSED);
+	  return -1;
+	}
+
+      /* If the data is already decompressed (by elf_strptr), then we
+	 only need to setup the rawdata and section header. XXX what
+	 about elf_newdata?  */
+      if (scn->zdata_base == NULL)
+	{
+	  size_t size_out, addralign;
+	  void *buf_out = __libelf_decompress_elf (scn, &size_out, &addralign);
+	  if (buf_out == NULL)
+	    return -1;
+
+	  scn->zdata_base = buf_out;
+	  scn->zdata_size = size_out;
+	  scn->zdata_align = addralign;
+	}
+
+      /* Note we keep the sh_entsize as is, we assume it is setup
+	 correctly and ignored when SHF_COMPRESSED is set.  */
+      if (elfclass == ELFCLASS32)
+	{
+	  Elf32_Shdr *shdr = elf32_getshdr (scn);
+	  shdr->sh_size = scn->zdata_size;
+	  shdr->sh_addralign = scn->zdata_align;
+	  shdr->sh_flags &= ~SHF_COMPRESSED;
+	}
+      else
+	{
+	  Elf64_Shdr *shdr = elf64_getshdr (scn);
+	  shdr->sh_size = scn->zdata_size;
+	  shdr->sh_addralign = scn->zdata_align;
+	  shdr->sh_flags &= ~SHF_COMPRESSED;
+	}
+
+      __libelf_reset_rawdata (scn, scn->zdata_base,
+			      scn->zdata_size, scn->zdata_align,
+			      __libelf_data_type (&ehdr, sh_type,
+						  scn->zdata_align));
+
+      return 1;
+    }
+  else
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
+      return -1;
+    }
+}
diff --git a/libelf/elf_compress_gnu.c b/libelf/elf_compress_gnu.c
new file mode 100644
index 0000000..8e20b30
--- /dev/null
+++ b/libelf/elf_compress_gnu.c
@@ -0,0 +1,213 @@
+/* Compress or decompress a section.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include "libelfP.h"
+#include "common.h"
+
+int
+elf_compress_gnu (Elf_Scn *scn, int inflate, unsigned int flags)
+{
+  if (scn == NULL)
+    return -1;
+
+  if ((flags & ~ELF_CHF_FORCE) != 0)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return -1;
+    }
+
+  bool force = (flags & ELF_CHF_FORCE) != 0;
+
+  Elf *elf = scn->elf;
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    return -1;
+
+  int elfclass = elf->class;
+  int elfdata = ehdr.e_ident[EI_DATA];
+
+  Elf64_Xword sh_flags;
+  Elf64_Word sh_type;
+  Elf64_Xword sh_addralign;
+  if (elfclass == ELFCLASS32)
+    {
+      Elf32_Shdr *shdr = elf32_getshdr (scn);
+      if (shdr == NULL)
+	return -1;
+
+      sh_flags = shdr->sh_flags;
+      sh_type = shdr->sh_type;
+      sh_addralign = shdr->sh_addralign;
+    }
+  else
+    {
+      Elf64_Shdr *shdr = elf64_getshdr (scn);
+      if (shdr == NULL)
+	return -1;
+
+      sh_flags = shdr->sh_flags;
+      sh_type = shdr->sh_type;
+      sh_addralign = shdr->sh_addralign;
+    }
+
+  /* Allocated sections, or sections that are already are compressed
+     cannot (also) be GNU compressed.  */
+  if ((sh_flags & SHF_ALLOC) != 0 || (sh_flags & SHF_COMPRESSED))
+    {
+      __libelf_seterrno (ELF_E_INVALID_SECTION_FLAGS);
+      return -1;
+    }
+
+  if (sh_type == SHT_NULL || sh_type == SHT_NOBITS)
+    {
+      __libelf_seterrno (ELF_E_INVALID_SECTION_TYPE);
+      return -1;
+    }
+
+  /* For GNU compression we cannot really know whether the section is
+     already compressed or not.  Just try and see what happens...  */
+  // int compressed = (sh_flags & SHF_COMPRESSED);
+  if (inflate == 1)
+    {
+      size_t hsize = 4 + 8; /* GNU "ZLIB" + 8 byte size.  */
+      size_t orig_size, new_size, orig_addralign;
+      void *out_buf = __libelf_compress (scn, hsize, elfdata,
+					 &orig_size, &orig_addralign,
+					 &new_size, force,
+					 /* use_zstd */ false);
+
+      /* Compression would make section larger, don't change anything.  */
+      if (out_buf == (void *) -1)
+	return 0;
+
+      /* Compression failed, return error.  */
+      if (out_buf == NULL)
+	return -1;
+
+      uint64_t be64_size = htobe64 (orig_size);
+      memmove (out_buf, "ZLIB", 4);
+      memmove (out_buf + 4, &be64_size, sizeof (be64_size));
+
+      /* We don't know anything about sh_entsize, sh_addralign and
+	 sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
+	 Just adjust the sh_size.  */
+      if (elfclass == ELFCLASS32)
+	{
+	  Elf32_Shdr *shdr = elf32_getshdr (scn);
+	  shdr->sh_size = new_size;
+	}
+      else
+	{
+	  Elf64_Shdr *shdr = elf64_getshdr (scn);
+	  shdr->sh_size = new_size;
+	}
+
+      __libelf_reset_rawdata (scn, out_buf, new_size, 1, ELF_T_BYTE);
+
+      /* The section is now compressed, we could keep the uncompressed
+	 data around, but since that might have been multiple Elf_Data
+	 buffers let the user uncompress it explicitly again if they
+	 want it to simplify bookkeeping.  */
+      scn->zdata_base = NULL;
+
+      return 1;
+    }
+  else if (inflate == 0)
+    {
+      /* In theory the user could have constructed a compressed section
+	 by hand.  And in practice they do. For example when copying
+	 a section from one file to another using elf_newdata. So we
+	 have to use elf_getdata (not elf_rawdata).  */
+      Elf_Data *data = elf_getdata (scn, NULL);
+      if (data == NULL)
+	return -1;
+
+      size_t hsize = 4 + 8; /* GNU "ZLIB" + 8 byte size.  */
+      if (data->d_size < hsize || memcmp (data->d_buf, "ZLIB", 4) != 0)
+	{
+          __libelf_seterrno (ELF_E_NOT_COMPRESSED);
+	  return -1;
+	}
+
+      /* There is a 12-byte header of "ZLIB" followed by
+	 an 8-byte big-endian size.  There is only one type and
+	 Alignment isn't preserved separately.  */
+      uint64_t gsize;
+      memcpy (&gsize, data->d_buf + 4, sizeof gsize);
+      gsize = be64toh (gsize);
+
+      /* One more sanity check, size should be bigger than original
+	 data size plus some overhead (4 chars ZLIB + 8 bytes size + 6
+	 bytes zlib stream overhead + 5 bytes overhead max for one 16K
+	 block) and should fit into a size_t.  */
+      if (gsize + 4 + 8 + 6 + 5 < data->d_size || gsize > SIZE_MAX)
+	{
+	  __libelf_seterrno (ELF_E_NOT_COMPRESSED);
+	  return -1;
+	}
+
+      size_t size = gsize;
+      size_t size_in = data->d_size - hsize;
+      void *buf_in = data->d_buf + hsize;
+      void *buf_out = __libelf_decompress (ELFCOMPRESS_ZLIB, buf_in, size_in, size);
+      if (buf_out == NULL)
+	return -1;
+
+      /* We don't know anything about sh_entsize, sh_addralign and
+	 sh_flags won't have a SHF_COMPRESSED hint in the GNU format.
+	 Just adjust the sh_size.  */
+      if (elfclass == ELFCLASS32)
+	{
+	  Elf32_Shdr *shdr = elf32_getshdr (scn);
+	  shdr->sh_size = size;
+	}
+      else
+	{
+	  Elf64_Shdr *shdr = elf64_getshdr (scn);
+	  shdr->sh_size = size;
+	}
+
+      __libelf_reset_rawdata (scn, buf_out, size, sh_addralign,
+			      __libelf_data_type (&ehdr, sh_type,
+						  sh_addralign));
+
+      scn->zdata_base = buf_out;
+
+      return 1;
+    }
+  else
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_COMPRESSION_TYPE);
+      return -1;
+    }
+}
diff --git a/libelf/elf_end.c b/libelf/elf_end.c
new file mode 100644
index 0000000..80f4d13
--- /dev/null
+++ b/libelf/elf_end.c
@@ -0,0 +1,248 @@
+/* Free resources associated with Elf descriptor.
+   Copyright (C) 1998,1999,2000,2001,2002,2004,2005,2007,2015,2016 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <search.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+static void
+free_chunk (void *n)
+{
+  Elf_Data_Chunk *rawchunk = (Elf_Data_Chunk *)n;
+  if (rawchunk->dummy_scn.flags & ELF_F_MALLOCED)
+    free (rawchunk->data.d.d_buf);
+  free (rawchunk);
+}
+
+int
+elf_end (Elf *elf)
+{
+  Elf *parent;
+
+  if (elf == NULL)
+    /* This is allowed and is a no-op.  */
+    return 0;
+
+  /* Make sure we are alone.  */
+  rwlock_wrlock (elf->lock);
+
+  if (elf->ref_count != 0 && --elf->ref_count != 0)
+    {
+      /* Not yet the last activation.  */
+      int result = elf->ref_count;
+      rwlock_unlock (elf->lock);
+      return result;
+    }
+
+  if (elf->kind == ELF_K_AR)
+    {
+      /* We cannot remove the descriptor now since we still have some
+	 descriptors which depend on it.  But we can free the archive
+	 symbol table since this is only available via the archive ELF
+	 descriptor.  The long name table cannot be freed yet since
+	 the archive headers for the ELF files in the archive point
+	 into this array.  */
+      if (elf->state.ar.ar_sym != (Elf_Arsym *) -1l)
+	free (elf->state.ar.ar_sym);
+      elf->state.ar.ar_sym = NULL;
+
+      if (elf->state.ar.children != NULL)
+	{
+	  rwlock_unlock(elf->lock);
+	  return 0;
+	}
+    }
+
+  /* Remove this structure from the children list.  */
+  parent = elf->parent;
+  if (parent != NULL)
+    {
+      /* This is tricky.  Lock must be acquire from the father to
+	 the child but here we already have the child lock.  We
+	 solve this problem by giving free the child lock.  The
+	 state of REF_COUNT==0 is handled all over the library, so
+	 this should be ok.  */
+      rwlock_unlock (elf->lock);
+      rwlock_rdlock (parent->lock);
+      rwlock_wrlock (elf->lock);
+
+      if (parent->state.ar.children == elf)
+	parent->state.ar.children = elf->next;
+      else
+	{
+	  struct Elf *child = parent->state.ar.children;
+
+	  while (child->next != elf)
+	    child = child->next;
+
+	  child->next = elf->next;
+	}
+
+      rwlock_unlock (parent->lock);
+    }
+
+  /* This was the last activation.  Free all resources.  */
+  switch (elf->kind)
+    {
+    case ELF_K_AR:
+      if (elf->state.ar.long_names != NULL)
+	free (elf->state.ar.long_names);
+      break;
+
+    case ELF_K_ELF:
+      {
+	void *rawchunks
+	  = (elf->class == ELFCLASS32
+	     || (offsetof (struct Elf, state.elf32.rawchunks)
+		 == offsetof (struct Elf, state.elf64.rawchunks))
+	     ? elf->state.elf32.rawchunks
+	     : elf->state.elf64.rawchunks);
+	tdestroy (rawchunks, free_chunk);
+
+	Elf_ScnList *list = (elf->class == ELFCLASS32
+			     || (offsetof (struct Elf, state.elf32.scns)
+				 == offsetof (struct Elf, state.elf64.scns))
+			     ? &elf->state.elf32.scns
+			     : &elf->state.elf64.scns);
+
+	do
+	  {
+	    /* Free all separately allocated section headers.  */
+	    size_t cnt = list->max;
+
+	    while (cnt-- > 0)
+	      {
+		/* These pointers can be NULL; it's safe to use
+		   'free' since it will check for this.  */
+		Elf_Scn *scn = &list->data[cnt];
+		Elf_Data_List *runp;
+
+		if ((scn->shdr_flags & ELF_F_MALLOCED) != 0)
+		  /* It doesn't matter which pointer.  */
+		  free (scn->shdr.e32);
+
+		/* Free zdata if uncompressed, but not yet used as
+		   rawdata_base.  If it is already used it will be
+		   freed below.  */
+		if (scn->zdata_base != scn->rawdata_base)
+		  {
+		    free (scn->zdata_base);
+		    scn->zdata_base = NULL;
+		  }
+
+		/* If the file has the same byte order and the
+		   architecture doesn't require overly stringent
+		   alignment the raw data buffer is the same as the
+		   one used for presenting to the caller.  */
+		if (scn->data_base != scn->rawdata_base)
+		  free (scn->data_base);
+
+		/* The section data is allocated if we couldn't mmap
+		   the file.  Or if we had to decompress.  */
+		if (elf->map_address == NULL
+		    || scn->rawdata_base == scn->zdata_base
+		    || (scn->flags & ELF_F_MALLOCED) != 0)
+		  free (scn->rawdata_base);
+
+		/* Free the list of data buffers for the section.
+		   We don't free the buffers themselves since this
+		   is the users job.  */
+		runp = scn->data_list.next;
+		while (runp != NULL)
+		  {
+		    Elf_Data_List *oldp = runp;
+		    runp = runp->next;
+		    if ((oldp->flags & ELF_F_MALLOCED) != 0)
+		      free (oldp);
+		  }
+	      }
+
+	    /* Free the memory for the array.  */
+	    Elf_ScnList *oldp = list;
+	    list = list->next;
+	    assert (list == NULL || oldp->cnt == oldp->max);
+	    if (oldp != (elf->class == ELFCLASS32
+			 || (offsetof (struct Elf, state.elf32.scns)
+			     == offsetof (struct Elf, state.elf64.scns))
+			 ? &elf->state.elf32.scns
+			 : &elf->state.elf64.scns))
+	      free (oldp);
+	  }
+	while (list != NULL);
+      }
+
+      /* Free the section header.  */
+      if (elf->state.elf.shdr_malloced  != 0)
+	free (elf->class == ELFCLASS32
+	      || (offsetof (struct Elf, state.elf32.shdr)
+		  == offsetof (struct Elf, state.elf64.shdr))
+	      ? (void *) elf->state.elf32.shdr
+	      : (void *) elf->state.elf64.shdr);
+
+      /* Free the program header.  */
+      if ((elf->state.elf.phdr_flags & ELF_F_MALLOCED) != 0)
+	free (elf->class == ELFCLASS32
+	      || (offsetof (struct Elf, state.elf32.phdr)
+		  == offsetof (struct Elf, state.elf64.phdr))
+	      ? (void *) elf->state.elf32.phdr
+	      : (void *) elf->state.elf64.phdr);
+      break;
+
+    default:
+      break;
+    }
+
+  if (elf->map_address != NULL && parent == NULL)
+    {
+      /* The file was read or mapped for this descriptor.  */
+      if ((elf->flags & ELF_F_MALLOCED) != 0)
+	free (elf->map_address);
+      else if ((elf->flags & ELF_F_MMAPPED) != 0)
+	munmap (elf->map_address, elf->maximum_size);
+    }
+
+  rwlock_unlock (elf->lock);
+  rwlock_fini (elf->lock);
+
+  /* Finally the descriptor itself.  */
+  free (elf);
+
+  return (parent != NULL && parent->ref_count == 0
+	  ? INTUSE(elf_end) (parent) : 0);
+}
+INTDEF(elf_end)
diff --git a/libelf/elf_error.c b/libelf/elf_error.c
new file mode 100644
index 0000000..e596108
--- /dev/null
+++ b/libelf/elf_error.c
@@ -0,0 +1,354 @@
+/* Error handling in libelf.
+   Copyright (C) 1998-2010, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+/* The error number.  */
+static __thread int global_error;
+
+
+int
+elf_errno (void)
+{
+  int result = global_error;
+  global_error = ELF_E_NOERROR;
+  return result;
+}
+
+
+/* Return the appropriate message for the error.  */
+static const char msgstr[] =
+{
+#define ELF_E_NOERROR_IDX 0
+  N_("no error")
+  "\0"
+#define ELF_E_UNKNOWN_ERROR_IDX (ELF_E_NOERROR_IDX + sizeof "no error")
+  N_("unknown error")
+  "\0"
+#define ELF_E_UNKNOWN_VERSION_IDX \
+  (ELF_E_UNKNOWN_ERROR_IDX + sizeof "unknown error")
+  N_("unknown version")
+  "\0"
+#define ELF_E_UNKNOWN_TYPE_IDX \
+  (ELF_E_UNKNOWN_VERSION_IDX + sizeof "unknown version")
+  N_("unknown type")
+  "\0"
+#define ELF_E_INVALID_HANDLE_IDX \
+  (ELF_E_UNKNOWN_TYPE_IDX + sizeof "unknown type")
+  N_("invalid `Elf' handle")
+  "\0"
+#define ELF_E_SOURCE_SIZE_IDX \
+  (ELF_E_INVALID_HANDLE_IDX + sizeof "invalid `Elf' handle")
+  N_("invalid size of source operand")
+  "\0"
+#define ELF_E_DEST_SIZE_IDX \
+  (ELF_E_SOURCE_SIZE_IDX + sizeof "invalid size of source operand")
+  N_("invalid size of destination operand")
+  "\0"
+#define ELF_E_INVALID_ENCODING_IDX \
+  (ELF_E_DEST_SIZE_IDX + sizeof "invalid size of destination operand")
+  N_("invalid encoding")
+  "\0"
+#define ELF_E_NOMEM_IDX \
+  (ELF_E_INVALID_ENCODING_IDX + sizeof "invalid encoding")
+  N_("out of memory")
+  "\0"
+#define ELF_E_INVALID_FILE_IDX \
+  (ELF_E_NOMEM_IDX + sizeof "out of memory")
+  N_("invalid file descriptor")
+  "\0"
+#define ELF_E_INVALID_ELF_IDX \
+  (ELF_E_INVALID_FILE_IDX + sizeof "invalid file descriptor")
+  N_("invalid ELF file data")
+  "\0"
+#define ELF_E_INVALID_OP_IDX \
+  (ELF_E_INVALID_ELF_IDX + sizeof "invalid ELF file data")
+  N_("invalid operation")
+  "\0"
+#define ELF_E_NO_VERSION_IDX \
+  (ELF_E_INVALID_OP_IDX + sizeof "invalid operation")
+  N_("ELF version not set")
+  "\0"
+#define ELF_E_INVALID_CMD_IDX \
+  (ELF_E_NO_VERSION_IDX + sizeof "ELF version not set")
+  N_("invalid command")
+  "\0"
+#define ELF_E_RANGE_IDX \
+  (ELF_E_INVALID_CMD_IDX + sizeof "invalid command")
+  N_("offset out of range")
+  "\0"
+#define ELF_E_ARCHIVE_FMAG_IDX \
+  (ELF_E_RANGE_IDX + sizeof "offset out of range")
+  N_("invalid fmag field in archive header")
+  "\0"
+#define ELF_E_INVALID_ARCHIVE_IDX \
+  (ELF_E_ARCHIVE_FMAG_IDX + sizeof "invalid fmag field in archive header")
+  N_("invalid archive file")
+  "\0"
+#define ELF_E_NO_ARCHIVE_IDX \
+  (ELF_E_INVALID_ARCHIVE_IDX + sizeof "invalid archive file")
+  N_("descriptor is not for an archive")
+  "\0"
+#define ELF_E_NO_INDEX_IDX \
+  (ELF_E_NO_ARCHIVE_IDX + sizeof "descriptor is not for an archive")
+  N_("no index available")
+  "\0"
+#define ELF_E_READ_ERROR_IDX \
+  (ELF_E_NO_INDEX_IDX + sizeof "no index available")
+  N_("cannot read data from file")
+  "\0"
+#define ELF_E_WRITE_ERROR_IDX \
+  (ELF_E_READ_ERROR_IDX + sizeof "cannot read data from file")
+  N_("cannot write data to file")
+  "\0"
+#define ELF_E_INVALID_CLASS_IDX \
+  (ELF_E_WRITE_ERROR_IDX + sizeof "cannot write data to file")
+  N_("invalid binary class")
+  "\0"
+#define ELF_E_INVALID_INDEX_IDX \
+  (ELF_E_INVALID_CLASS_IDX + sizeof "invalid binary class")
+  N_("invalid section index")
+  "\0"
+#define ELF_E_INVALID_OPERAND_IDX \
+  (ELF_E_INVALID_INDEX_IDX + sizeof "invalid section index")
+  N_("invalid operand")
+  "\0"
+#define ELF_E_INVALID_SECTION_IDX \
+  (ELF_E_INVALID_OPERAND_IDX + sizeof "invalid operand")
+  N_("invalid section")
+  "\0"
+#define ELF_E_INVALID_COMMAND_IDX \
+  (ELF_E_INVALID_SECTION_IDX + sizeof "invalid section")
+  N_("invalid command")
+  "\0"
+#define ELF_E_WRONG_ORDER_EHDR_IDX \
+  (ELF_E_INVALID_COMMAND_IDX + sizeof "invalid command")
+  N_("executable header not created first")
+  "\0"
+#define ELF_E_FD_DISABLED_IDX \
+  (ELF_E_WRONG_ORDER_EHDR_IDX + sizeof "executable header not created first")
+  N_("file descriptor disabled")
+  "\0"
+#define ELF_E_FD_MISMATCH_IDX \
+  (ELF_E_FD_DISABLED_IDX + sizeof "file descriptor disabled")
+  N_("archive/member file descriptor mismatch")
+  "\0"
+#define ELF_E_OFFSET_RANGE_IDX \
+  (ELF_E_FD_MISMATCH_IDX + sizeof "archive/member file descriptor mismatch")
+  N_("offset out of range")
+  "\0"
+#define ELF_E_NOT_NUL_SECTION_IDX \
+  (ELF_E_OFFSET_RANGE_IDX + sizeof "offset out of range")
+  N_("cannot manipulate null section")
+  "\0"
+#define ELF_E_DATA_MISMATCH_IDX \
+  (ELF_E_NOT_NUL_SECTION_IDX + sizeof "cannot manipulate null section")
+  N_("data/scn mismatch")
+  "\0"
+#define ELF_E_INVALID_SECTION_HEADER_IDX \
+  (ELF_E_DATA_MISMATCH_IDX + sizeof "data/scn mismatch")
+  N_("invalid section header")
+  "\0"
+#define ELF_E_INVALID_DATA_IDX \
+  (ELF_E_INVALID_SECTION_HEADER_IDX + sizeof "invalid section header")
+  N_("invalid data")
+  "\0"
+#define ELF_E_DATA_ENCODING_IDX \
+  (ELF_E_INVALID_DATA_IDX + sizeof "invalid data")
+  N_("unknown data encoding")
+  "\0"
+#define ELF_E_SECTION_TOO_SMALL_IDX \
+  (ELF_E_DATA_ENCODING_IDX + sizeof "unknown data encoding")
+  N_("section `sh_size' too small for data")
+  "\0"
+#define ELF_E_INVALID_ALIGN_IDX \
+  (ELF_E_SECTION_TOO_SMALL_IDX + sizeof "section `sh_size' too small for data")
+  N_("invalid section alignment")
+  "\0"
+#define ELF_E_INVALID_SHENTSIZE_IDX \
+  (ELF_E_INVALID_ALIGN_IDX + sizeof "invalid section alignment")
+  N_("invalid section entry size")
+  "\0"
+#define ELF_E_UPDATE_RO_IDX \
+  (ELF_E_INVALID_SHENTSIZE_IDX + sizeof "invalid section entry size")
+  N_("update() for write on read-only file")
+  "\0"
+#define ELF_E_NOFILE_IDX \
+  (ELF_E_UPDATE_RO_IDX + sizeof "update() for write on read-only file")
+  N_("no such file")
+  "\0"
+#define ELF_E_GROUP_NOT_REL_IDX \
+  (ELF_E_NOFILE_IDX + sizeof "no such file")
+  N_("only relocatable files can contain section groups")
+  "\0"
+#define ELF_E_INVALID_PHDR_IDX \
+  (ELF_E_GROUP_NOT_REL_IDX \
+   + sizeof "only relocatable files can contain section groups")
+  N_("program header only allowed in executables, shared objects, and \
+core files")
+  "\0"
+#define ELF_E_NO_PHDR_IDX \
+  (ELF_E_INVALID_PHDR_IDX \
+   + sizeof "program header only allowed in executables, shared objects, and \
+core files")
+  N_("file has no program header")
+  "\0"
+#define ELF_E_INVALID_OFFSET_IDX \
+  (ELF_E_NO_PHDR_IDX \
+   + sizeof "file has no program header")
+  N_("invalid offset")
+  "\0"
+#define ELF_E_INVALID_SECTION_TYPE_IDX \
+  (ELF_E_INVALID_OFFSET_IDX \
+   + sizeof "invalid offset")
+  N_("invalid section type")
+  "\0"
+#define ELF_E_INVALID_SECTION_FLAGS_IDX \
+  (ELF_E_INVALID_SECTION_TYPE_IDX \
+   + sizeof "invalid section type")
+  N_("invalid section flags")
+  "\0"
+#define ELF_E_NOT_COMPRESSED_IDX		\
+  (ELF_E_INVALID_SECTION_FLAGS_IDX			\
+   + sizeof "invalid section flags")
+  N_("section does not contain compressed data")
+  "\0"
+#define ELF_E_ALREADY_COMPRESSED_IDX \
+  (ELF_E_NOT_COMPRESSED_IDX \
+   + sizeof "section does not contain compressed data")
+  N_("section contains compressed data")
+  "\0"
+#define ELF_E_UNKNOWN_COMPRESSION_TYPE_IDX \
+  (ELF_E_ALREADY_COMPRESSED_IDX \
+   + sizeof "section contains compressed data")
+  N_("unknown compression type")
+  "\0"
+#define ELF_E_COMPRESS_ERROR_IDX \
+  (ELF_E_UNKNOWN_COMPRESSION_TYPE_IDX \
+   + sizeof "unknown compression type")
+  N_("cannot compress data")
+  "\0"
+#define ELF_E_DECOMPRESS_ERROR_IDX \
+  (ELF_E_COMPRESS_ERROR_IDX \
+   + sizeof "cannot compress data")
+  N_("cannot decompress data")
+};
+
+
+static const uint_fast16_t msgidx[ELF_E_NUM] =
+{
+  [ELF_E_NOERROR] = ELF_E_NOERROR_IDX,
+  [ELF_E_UNKNOWN_ERROR] = ELF_E_UNKNOWN_ERROR_IDX,
+  [ELF_E_UNKNOWN_VERSION] = ELF_E_UNKNOWN_VERSION_IDX,
+  [ELF_E_UNKNOWN_TYPE] = ELF_E_UNKNOWN_TYPE_IDX,
+  [ELF_E_INVALID_HANDLE] = ELF_E_INVALID_HANDLE_IDX,
+  [ELF_E_SOURCE_SIZE] = ELF_E_SOURCE_SIZE_IDX,
+  [ELF_E_DEST_SIZE] = ELF_E_DEST_SIZE_IDX,
+  [ELF_E_INVALID_ENCODING] = ELF_E_INVALID_ENCODING_IDX,
+  [ELF_E_NOMEM] = ELF_E_NOMEM_IDX,
+  [ELF_E_INVALID_FILE] = ELF_E_INVALID_FILE_IDX,
+  [ELF_E_INVALID_ELF] = ELF_E_INVALID_ELF_IDX,
+  [ELF_E_INVALID_OP] = ELF_E_INVALID_OP_IDX,
+  [ELF_E_NO_VERSION] = ELF_E_NO_VERSION_IDX,
+  [ELF_E_INVALID_CMD] = ELF_E_INVALID_CMD_IDX,
+  [ELF_E_RANGE] = ELF_E_RANGE_IDX,
+  [ELF_E_ARCHIVE_FMAG] = ELF_E_ARCHIVE_FMAG_IDX,
+  [ELF_E_INVALID_ARCHIVE] = ELF_E_INVALID_ARCHIVE_IDX,
+  [ELF_E_NO_ARCHIVE] = ELF_E_NO_ARCHIVE_IDX,
+  [ELF_E_NO_INDEX] = ELF_E_NO_INDEX_IDX,
+  [ELF_E_READ_ERROR] = ELF_E_READ_ERROR_IDX,
+  [ELF_E_WRITE_ERROR] = ELF_E_WRITE_ERROR_IDX,
+  [ELF_E_INVALID_CLASS] = ELF_E_INVALID_CLASS_IDX,
+  [ELF_E_INVALID_INDEX] = ELF_E_INVALID_INDEX_IDX,
+  [ELF_E_INVALID_OPERAND] = ELF_E_INVALID_OPERAND_IDX,
+  [ELF_E_INVALID_SECTION] = ELF_E_INVALID_SECTION_IDX,
+  [ELF_E_INVALID_COMMAND] = ELF_E_INVALID_COMMAND_IDX,
+  [ELF_E_WRONG_ORDER_EHDR] = ELF_E_WRONG_ORDER_EHDR_IDX,
+  [ELF_E_FD_DISABLED] = ELF_E_FD_DISABLED_IDX,
+  [ELF_E_FD_MISMATCH] = ELF_E_FD_MISMATCH_IDX,
+  [ELF_E_OFFSET_RANGE] = ELF_E_OFFSET_RANGE_IDX,
+  [ELF_E_NOT_NUL_SECTION] = ELF_E_NOT_NUL_SECTION_IDX,
+  [ELF_E_DATA_MISMATCH] = ELF_E_DATA_MISMATCH_IDX,
+  [ELF_E_INVALID_SECTION_HEADER] = ELF_E_INVALID_SECTION_HEADER_IDX,
+  [ELF_E_INVALID_DATA] = ELF_E_INVALID_DATA_IDX,
+  [ELF_E_DATA_ENCODING] = ELF_E_DATA_ENCODING_IDX,
+  [ELF_E_SECTION_TOO_SMALL] = ELF_E_SECTION_TOO_SMALL_IDX,
+  [ELF_E_INVALID_ALIGN] = ELF_E_INVALID_ALIGN_IDX,
+  [ELF_E_INVALID_SHENTSIZE] = ELF_E_INVALID_SHENTSIZE_IDX,
+  [ELF_E_UPDATE_RO] = ELF_E_UPDATE_RO_IDX,
+  [ELF_E_NOFILE] = ELF_E_NOFILE_IDX,
+  [ELF_E_GROUP_NOT_REL] = ELF_E_GROUP_NOT_REL_IDX,
+  [ELF_E_INVALID_PHDR] = ELF_E_INVALID_PHDR_IDX,
+  [ELF_E_NO_PHDR] = ELF_E_NO_PHDR_IDX,
+  [ELF_E_INVALID_OFFSET] = ELF_E_INVALID_OFFSET_IDX,
+  [ELF_E_INVALID_SECTION_TYPE] = ELF_E_INVALID_SECTION_TYPE_IDX,
+  [ELF_E_INVALID_SECTION_FLAGS] = ELF_E_INVALID_SECTION_FLAGS_IDX,
+  [ELF_E_NOT_COMPRESSED] = ELF_E_NOT_COMPRESSED_IDX,
+  [ELF_E_ALREADY_COMPRESSED] = ELF_E_ALREADY_COMPRESSED_IDX,
+  [ELF_E_UNKNOWN_COMPRESSION_TYPE] = ELF_E_UNKNOWN_COMPRESSION_TYPE_IDX,
+  [ELF_E_COMPRESS_ERROR] = ELF_E_COMPRESS_ERROR_IDX,
+  [ELF_E_DECOMPRESS_ERROR] = ELF_E_DECOMPRESS_ERROR_IDX
+};
+#define nmsgidx ((int) (sizeof (msgidx) / sizeof (msgidx[0])))
+
+
+void
+internal_function
+__libelf_seterrno (int value)
+{
+  global_error = value >= 0 && value < nmsgidx ? value : ELF_E_UNKNOWN_ERROR;
+}
+
+
+const char *
+elf_errmsg (int error)
+{
+  int last_error = global_error;
+
+  if (error == 0)
+    {
+      assert (msgidx[last_error] < sizeof (msgstr));
+      return last_error != 0 ? _(msgstr + msgidx[last_error]) : NULL;
+    }
+  else if (error < -1 || error >= nmsgidx)
+    return _(msgstr + ELF_E_UNKNOWN_ERROR_IDX);
+
+  assert (msgidx[error == -1 ? last_error : error] < sizeof (msgstr));
+  return _(msgstr + msgidx[error == -1 ? last_error : error]);
+}
diff --git a/libelf/elf_fill.c b/libelf/elf_fill.c
new file mode 100644
index 0000000..6ebdf63
--- /dev/null
+++ b/libelf/elf_fill.c
@@ -0,0 +1,46 @@
+/* Set fill byte used when constructing ELF objects.
+   Copyright (C) 1998, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+
+#include "libelfP.h"
+
+
+int __libelf_fill_byte;
+
+
+void
+elf_fill (int fill)
+{
+  __libelf_fill_byte = fill;
+}
diff --git a/libelf/elf_flagdata.c b/libelf/elf_flagdata.c
new file mode 100644
index 0000000..cd2b123
--- /dev/null
+++ b/libelf/elf_flagdata.c
@@ -0,0 +1,68 @@
+/* Manipulate ELF data flag.
+   Copyright (C) 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+unsigned int
+elf_flagdata (Elf_Data *data, Elf_Cmd cmd, unsigned int flags)
+{
+  Elf_Data_Scn *data_scn;
+  unsigned int result;
+
+  if (data == NULL)
+    return 0;
+
+  data_scn = (Elf_Data_Scn *) data;
+
+  if (data_scn == NULL || unlikely (data_scn->s->elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  if (likely (cmd == ELF_C_SET))
+    result = (data_scn->s->flags |= (flags & ELF_F_DIRTY));
+  else if (likely (cmd == ELF_C_CLR))
+    result = (data_scn->s->flags &= ~(flags & ELF_F_DIRTY));
+  else
+    {
+      __libelf_seterrno (ELF_E_INVALID_COMMAND);
+      return 0;
+    }
+
+  return result;
+}
diff --git a/libelf/elf_flagehdr.c b/libelf/elf_flagehdr.c
new file mode 100644
index 0000000..a98276d
--- /dev/null
+++ b/libelf/elf_flagehdr.c
@@ -0,0 +1,65 @@
+/* Manipulate ELF header flags.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+unsigned int
+elf_flagehdr (Elf *elf, Elf_Cmd cmd, unsigned int flags)
+{
+  unsigned int result;
+
+  if (elf == NULL)
+    return 0;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  if (likely (cmd == ELF_C_SET))
+    result = (elf->state.elf.ehdr_flags |= (flags & ELF_F_DIRTY));
+  else if (cmd == ELF_C_CLR)
+    result = (elf->state.elf.ehdr_flags &= ~(flags & ELF_F_DIRTY));
+  else
+    {
+      __libelf_seterrno (ELF_E_INVALID_COMMAND);
+      return 0;
+    }
+
+  return result;
+}
diff --git a/libelf/elf_flagelf.c b/libelf/elf_flagelf.c
new file mode 100644
index 0000000..bd90a21
--- /dev/null
+++ b/libelf/elf_flagelf.c
@@ -0,0 +1,67 @@
+/* Manipulate ELF file flags.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+unsigned int
+elf_flagelf (Elf *elf, Elf_Cmd cmd, unsigned int flags)
+{
+  unsigned int result;
+
+  if (elf == NULL)
+    return 0;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  if (likely (cmd == ELF_C_SET))
+    result = (elf->flags
+	      |= (flags & (ELF_F_DIRTY | ELF_F_LAYOUT | ELF_F_PERMISSIVE)));
+  else if (likely (cmd == ELF_C_CLR))
+    result = (elf->flags
+	      &= ~(flags & (ELF_F_DIRTY | ELF_F_LAYOUT | ELF_F_PERMISSIVE)));
+  else
+    {
+      __libelf_seterrno (ELF_E_INVALID_COMMAND);
+      return 0;
+    }
+
+  return result;
+}
diff --git a/libelf/elf_flagphdr.c b/libelf/elf_flagphdr.c
new file mode 100644
index 0000000..0682d1f
--- /dev/null
+++ b/libelf/elf_flagphdr.c
@@ -0,0 +1,65 @@
+/* Manipulate ELF program header flags.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+unsigned int
+elf_flagphdr (Elf *elf, Elf_Cmd cmd, unsigned int flags)
+{
+  unsigned int result;
+
+  if (elf == NULL)
+    return 0;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  if (likely (cmd == ELF_C_SET))
+    result = (elf->state.elf.phdr_flags |= (flags & ELF_F_DIRTY));
+  else if (likely (cmd == ELF_C_CLR))
+    result = (elf->state.elf.phdr_flags &= ~(flags & ELF_F_DIRTY));
+  else
+    {
+      __libelf_seterrno (ELF_E_INVALID_COMMAND);
+      return 0;
+    }
+
+  return result;
+}
diff --git a/libelf/elf_flagscn.c b/libelf/elf_flagscn.c
new file mode 100644
index 0000000..2164a8c
--- /dev/null
+++ b/libelf/elf_flagscn.c
@@ -0,0 +1,65 @@
+/* Manipulate ELF section flags.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+unsigned int
+elf_flagscn (Elf_Scn *scn, Elf_Cmd cmd, unsigned int flags)
+{
+  unsigned int result;
+
+  if (scn == NULL)
+    return 0;
+
+  if (unlikely (scn->elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  if (likely (cmd == ELF_C_SET))
+    result = (scn->flags |= (flags & ELF_F_DIRTY));
+  else if (likely (cmd == ELF_C_CLR))
+    result = (scn->flags &= ~(flags & ELF_F_DIRTY));
+  else
+    {
+      __libelf_seterrno (ELF_E_INVALID_COMMAND);
+      return 0;
+    }
+
+  return result;
+}
diff --git a/libelf/elf_flagshdr.c b/libelf/elf_flagshdr.c
new file mode 100644
index 0000000..febf4ab
--- /dev/null
+++ b/libelf/elf_flagshdr.c
@@ -0,0 +1,65 @@
+/* Manipulate ELF section header flags.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+unsigned int
+elf_flagshdr (Elf_Scn *scn, Elf_Cmd cmd, unsigned int flags)
+{
+  unsigned int result;
+
+  if (scn == NULL)
+    return 0;
+
+  if (unlikely (scn->elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  if (likely (cmd == ELF_C_SET))
+    result = (scn->shdr_flags |= (flags & ELF_F_DIRTY));
+  else if (likely (cmd == ELF_C_CLR))
+    result = (scn->shdr_flags &= ~(flags & ELF_F_DIRTY));
+  else
+    {
+      __libelf_seterrno (ELF_E_INVALID_COMMAND);
+      return 0;
+    }
+
+  return result;
+}
diff --git a/libelf/elf_getarhdr.c b/libelf/elf_getarhdr.c
new file mode 100644
index 0000000..509f1da
--- /dev/null
+++ b/libelf/elf_getarhdr.c
@@ -0,0 +1,73 @@
+/* Read header of next archive member.
+   Copyright (C) 1998, 1999, 2000, 2002, 2008, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf_Arhdr *
+elf_getarhdr (Elf *elf)
+{
+  if (elf == NULL)
+    return NULL;
+
+  Elf *parent = elf->parent;
+
+  /* Calling this function is not ok for any file type but archives.  */
+  if (parent == NULL)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OP);
+      return NULL;
+    }
+
+  /* Make sure we have read the archive header.  */
+  if (parent->state.ar.elf_ar_hdr.ar_name == NULL
+      && __libelf_next_arhdr_wrlock (parent) != 0)
+    {
+      rwlock_wrlock (parent->lock);
+      int st = __libelf_next_arhdr_wrlock (parent);
+      rwlock_unlock (parent->lock);
+
+      if (st != 0)
+	/* Something went wrong.  Maybe there is no member left.  */
+	return NULL;
+    }
+
+  /* We can be sure the parent is an archive.  */
+  assert (parent->kind == ELF_K_AR);
+
+  return &parent->state.ar.elf_ar_hdr;
+}
diff --git a/libelf/elf_getaroff.c b/libelf/elf_getaroff.c
new file mode 100644
index 0000000..5c102ad
--- /dev/null
+++ b/libelf/elf_getaroff.c
@@ -0,0 +1,53 @@
+/* Return offset in archive for current file ELF.
+   Copyright (C) 2005, 2008, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+int64_t
+elf_getaroff (Elf *elf)
+{
+  /* Be gratious, the specs demand it.  */
+  if (elf == NULL || elf->parent == NULL)
+    return ELF_C_NULL;
+
+  /* We can be sure the parent is an archive.  */
+  Elf *parent = elf->parent;
+  assert (parent->kind == ELF_K_AR);
+
+  return elf->start_offset - sizeof (struct ar_hdr) - parent->start_offset;
+}
diff --git a/libelf/elf_getarsym.c b/libelf/elf_getarsym.c
new file mode 100644
index 0000000..281f0c1
--- /dev/null
+++ b/libelf/elf_getarsym.c
@@ -0,0 +1,326 @@
+/* Return symbol table of archive.
+   Copyright (C) 1998-2000, 2002, 2005, 2009, 2012, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <dl-hash.h>
+#include "libelfP.h"
+
+
+static int
+read_number_entries (uint64_t *nump, Elf *elf, size_t *offp, bool index64_p)
+{
+  union u
+  {
+    uint64_t ret64;
+    uint32_t ret32;
+  } u;
+
+  size_t w = index64_p ? 8 : 4;
+  if (elf->map_address != NULL)
+    /* Use memcpy instead of pointer dereference so as not to assume the
+       field is naturally aligned within the file.  */
+    memcpy (&u, elf->map_address + *offp, sizeof u);
+  else if ((size_t) pread_retry (elf->fildes, &u, w, *offp) != w)
+    return -1;
+
+  *offp += w;
+
+  if (BYTE_ORDER == LITTLE_ENDIAN)
+    *nump = index64_p ? bswap_64 (u.ret64) : bswap_32 (u.ret32);
+  else
+    *nump = index64_p ? u.ret64 : u.ret32;
+
+  return 0;
+}
+
+Elf_Arsym *
+elf_getarsym (Elf *elf, size_t *ptr)
+{
+  if (elf->kind != ELF_K_AR)
+    {
+      /* This is no archive.  */
+      __libelf_seterrno (ELF_E_NO_ARCHIVE);
+      return NULL;
+    }
+
+  if (ptr != NULL)
+    /* In case of an error or when we know the value store the expected
+       value now.  Doing this allows us easier exits in an error case.  */
+    *ptr = elf->state.ar.ar_sym_num;
+
+  if (elf->state.ar.ar_sym == (Elf_Arsym *) -1l)
+    {
+      /* There is no index.  */
+      __libelf_seterrno (ELF_E_NO_INDEX);
+      return NULL;
+    }
+
+  Elf_Arsym *result = elf->state.ar.ar_sym;
+  if (result == NULL)
+    {
+      /* We have not yet read the index.  */
+      rwlock_wrlock (elf->lock);
+
+      /* In case we find no index remember this for the next call.  */
+      elf->state.ar.ar_sym = (Elf_Arsym *) -1l;
+
+      /* We might have to allocate some temporary data for reading.  */
+      void *temp_data = NULL;
+
+      struct ar_hdr *index_hdr;
+      if (elf->map_address == NULL)
+	{
+	  /* We must read index from the file.  */
+	  assert (elf->fildes != -1);
+	  if (pread_retry (elf->fildes, &elf->state.ar.ar_hdr,
+			   sizeof (struct ar_hdr), elf->start_offset + SARMAG)
+	      != sizeof (struct ar_hdr))
+	    {
+	      /* It is not possible to read the index.  Maybe it does not
+		 exist.  */
+	      __libelf_seterrno (ELF_E_READ_ERROR);
+	      goto out;
+	    }
+
+	  index_hdr = &elf->state.ar.ar_hdr;
+	}
+      else
+	{
+	  if (SARMAG + sizeof (struct ar_hdr) > elf->maximum_size)
+	    {
+	      /* There is no room for the full archive.  */
+	      __libelf_seterrno (ELF_E_NO_INDEX);
+	      goto out;
+	    }
+
+	  index_hdr = (struct ar_hdr *) (elf->map_address
+					 + elf->start_offset + SARMAG);
+	}
+
+      /* Now test whether this really is an archive.  */
+      if (memcmp (index_hdr->ar_fmag, ARFMAG, 2) != 0)
+	{
+	  /* Invalid magic bytes.  */
+	  __libelf_seterrno (ELF_E_ARCHIVE_FMAG);
+	  goto out;
+	}
+
+      bool index64_p;
+      /* Now test whether this is the index.  If the name is "/", this
+	 is 32-bit index, if it's "/SYM64/", it's 64-bit index.
+
+	 XXX This is not entirely true.  There are some more forms.
+	 Which of them shall we handle?  */
+      if (memcmp (index_hdr->ar_name, "/               ", 16) == 0)
+	index64_p = false;
+      else if (memcmp (index_hdr->ar_name, "/SYM64/         ", 16) == 0)
+	index64_p = true;
+      else
+	{
+	  /* If the index is not the first entry, there is no index.
+
+	     XXX Is this true?  */
+	  __libelf_seterrno (ELF_E_NO_INDEX);
+	  goto out;
+	}
+      int w = index64_p ? 8 : 4;
+
+      /* We have an archive.  The first word in there is the number of
+	 entries in the table.  */
+      uint64_t n = 0;
+      size_t off = elf->start_offset + SARMAG + sizeof (struct ar_hdr);
+      if (read_number_entries (&n, elf, &off, index64_p) < 0)
+	{
+	  /* Cannot read the number of entries.  */
+	  __libelf_seterrno (ELF_E_NO_INDEX);
+	  goto out;
+	}
+
+      /* Now we can perform some first tests on whether all the data
+	 needed for the index is available.  */
+      char tmpbuf[17];
+      memcpy (tmpbuf, index_hdr->ar_size, 10);
+      tmpbuf[10] = '\0';
+      size_t index_size = atol (tmpbuf);
+
+      if (index_size > elf->maximum_size
+	  || elf->maximum_size - index_size < SARMAG + sizeof (struct ar_hdr)
+#if SIZE_MAX <= 4294967295U
+	  || n >= SIZE_MAX / sizeof (Elf_Arsym)
+#endif
+	  || n > index_size / w)
+	{
+	  /* This index table cannot be right since it does not fit into
+	     the file.  */
+	  __libelf_seterrno (ELF_E_NO_INDEX);
+	  goto out;
+	}
+
+      /* Now we can allocate the arrays needed to store the index.  */
+      size_t ar_sym_len = (n + 1) * sizeof (Elf_Arsym);
+      elf->state.ar.ar_sym = malloc (ar_sym_len);
+      if (elf->state.ar.ar_sym != NULL)
+	{
+	  void *file_data; /* unit32_t[n] or uint64_t[n] */
+	  char *str_data;
+	  size_t sz = n * w;
+
+	  if (elf->map_address == NULL)
+	    {
+	      temp_data = malloc (sz);
+	      if (unlikely (temp_data == NULL))
+		{
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  goto out;
+		}
+	      file_data = temp_data;
+
+	      ar_sym_len += index_size - n * w;
+	      Elf_Arsym *newp = realloc (elf->state.ar.ar_sym, ar_sym_len);
+	      if (newp == NULL)
+		{
+		  free (elf->state.ar.ar_sym);
+		  elf->state.ar.ar_sym = NULL;
+		  __libelf_seterrno (ELF_E_NOMEM);
+		  goto out;
+		}
+	      elf->state.ar.ar_sym = newp;
+
+	      char *new_str = (char *) (elf->state.ar.ar_sym + n + 1);
+
+	      /* Now read the data from the file.  */
+	      if ((size_t) pread_retry (elf->fildes, file_data, sz, off) != sz
+		  || ((size_t) pread_retry (elf->fildes, new_str,
+					    index_size - sz, off + sz)
+		      != index_size - sz))
+		{
+		  /* We were not able to read the data.  */
+		  free (elf->state.ar.ar_sym);
+		  elf->state.ar.ar_sym = NULL;
+		  __libelf_seterrno (ELF_E_NO_INDEX);
+		  goto out;
+		}
+
+	      str_data = (char *) new_str;
+	    }
+	  else
+	    {
+	      file_data = (void *) (elf->map_address + off);
+	      if (!ALLOW_UNALIGNED
+		  && ((uintptr_t) file_data & -(uintptr_t) n) != 0)
+		{
+		  temp_data = malloc (sz);
+		  if (unlikely (temp_data == NULL))
+		    {
+		      __libelf_seterrno (ELF_E_NOMEM);
+		      goto out;
+		    }
+		  file_data = memcpy (temp_data, elf->map_address + off, sz);
+		}
+	      str_data = (char *) (elf->map_address + off + sz);
+	    }
+
+	  /* Now we can build the data structure.  */
+	  Elf_Arsym *arsym = elf->state.ar.ar_sym;
+	  uint64_t (*u64)[n] = file_data;
+	  uint32_t (*u32)[n] = file_data;
+	  for (size_t cnt = 0; cnt < n; ++cnt)
+	    {
+	      arsym[cnt].as_name = str_data;
+	      if (index64_p)
+		{
+		  uint64_t tmp = (*u64)[cnt];
+		  if (BYTE_ORDER == LITTLE_ENDIAN)
+		    tmp = bswap_64 (tmp);
+
+		  arsym[cnt].as_off = tmp;
+
+		  /* Check whether 64-bit offset fits into 32-bit
+		     size_t.  */
+		  if (sizeof (arsym[cnt].as_off) < 8
+		      && arsym[cnt].as_off != tmp)
+		    {
+		      if (elf->map_address == NULL)
+			{
+			  free (elf->state.ar.ar_sym);
+			  elf->state.ar.ar_sym = NULL;
+			}
+
+		      __libelf_seterrno (ELF_E_RANGE);
+		      goto out;
+		    }
+		}
+	      else if (BYTE_ORDER == LITTLE_ENDIAN)
+		arsym[cnt].as_off = bswap_32 ((*u32)[cnt]);
+	      else
+		arsym[cnt].as_off = (*u32)[cnt];
+
+	      arsym[cnt].as_hash = _dl_elf_hash (str_data);
+#if HAVE_DECL_RAWMEMCHR
+	      str_data = rawmemchr (str_data, '\0') + 1;
+#else
+	      char c;
+	      do {
+		c = *str_data;
+		str_data++;
+	      } while (c);
+#endif
+	    }
+
+	  /* At the end a special entry.  */
+	  arsym[n].as_name = NULL;
+	  arsym[n].as_off = 0;
+	  arsym[n].as_hash = ~0UL;
+
+	  /* Tell the caller how many entries we have.  */
+	  elf->state.ar.ar_sym_num = n + 1;
+	}
+
+      result = elf->state.ar.ar_sym;
+
+    out:
+      free (temp_data);
+      rwlock_unlock (elf->lock);
+    }
+
+  if (ptr != NULL)
+    *ptr = elf->state.ar.ar_sym_num;
+
+  return result;
+}
diff --git a/libelf/elf_getbase.c b/libelf/elf_getbase.c
new file mode 100644
index 0000000..4890d33
--- /dev/null
+++ b/libelf/elf_getbase.c
@@ -0,0 +1,44 @@
+/* Return offset of first byte for the object.
+   Copyright (C) 1998, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+int64_t
+elf_getbase (Elf *elf)
+{
+  return elf == NULL ? (int64_t) -1 : elf->start_offset;
+}
diff --git a/libelf/elf_getdata.c b/libelf/elf_getdata.c
new file mode 100644
index 0000000..7c3ac04
--- /dev/null
+++ b/libelf/elf_getdata.c
@@ -0,0 +1,599 @@
+/* Return the next data element from the section after possibly converting it.
+   Copyright (C) 1998-2005, 2006, 2007, 2015, 2016 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stddef.h>
+#include <string.h>
+
+#include "libelfP.h"
+#include "common.h"
+#include "elf-knowledge.h"
+
+
+#define TYPEIDX(Sh_Type) \
+  (Sh_Type >= SHT_NULL && Sh_Type < SHT_NUM				      \
+   ? Sh_Type								      \
+   : (Sh_Type >= SHT_GNU_HASH && Sh_Type <= SHT_HISUNW			      \
+      ? SHT_NUM + Sh_Type - SHT_GNU_HASH				      \
+      : 0))
+
+/* Associate section types with libelf types.  */
+static const Elf_Type shtype_map[TYPEIDX (SHT_HISUNW) + 1] =
+  {
+      [SHT_SYMTAB] = ELF_T_SYM,
+      [SHT_RELA] = ELF_T_RELA,
+      [SHT_HASH] = ELF_T_WORD,
+      [SHT_DYNAMIC] = ELF_T_DYN,
+      [SHT_REL] = ELF_T_REL,
+      [SHT_DYNSYM] = ELF_T_SYM,
+      [SHT_INIT_ARRAY] = ELF_T_ADDR,
+      [SHT_FINI_ARRAY] = ELF_T_ADDR,
+      [SHT_PREINIT_ARRAY] = ELF_T_ADDR,
+      [SHT_GROUP] = ELF_T_WORD,
+      [SHT_SYMTAB_SHNDX] = ELF_T_WORD,
+      [SHT_NOTE] = ELF_T_NHDR, /* Need alignment to guess ELF_T_NHDR8.  */
+      [TYPEIDX (SHT_GNU_verdef)] = ELF_T_VDEF,
+      [TYPEIDX (SHT_GNU_verneed)] = ELF_T_VNEED,
+      [TYPEIDX (SHT_GNU_versym)] = ELF_T_HALF,
+      [TYPEIDX (SHT_SUNW_syminfo)] = ELF_T_SYMINFO,
+      [TYPEIDX (SHT_SUNW_move)] = ELF_T_MOVE,
+      [TYPEIDX (SHT_GNU_LIBLIST)] = ELF_T_LIB,
+      [TYPEIDX (SHT_GNU_HASH)] = ELF_T_GNUHASH,
+  };
+
+/* Associate libelf types with their internal alignment requirements.  */
+const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM] =
+  {
+# define TYPE_ALIGNS(Bits)						      \
+      [ELF_T_ADDR] = __alignof__ (ElfW2(Bits,Addr)),			      \
+      [ELF_T_EHDR] = __alignof__ (ElfW2(Bits,Ehdr)),			      \
+      [ELF_T_HALF] = __alignof__ (ElfW2(Bits,Half)),			      \
+      [ELF_T_OFF] = __alignof__ (ElfW2(Bits,Off)),			      \
+      [ELF_T_PHDR] = __alignof__ (ElfW2(Bits,Phdr)),			      \
+      [ELF_T_SHDR] = __alignof__ (ElfW2(Bits,Shdr)),			      \
+      [ELF_T_SWORD] = __alignof__ (ElfW2(Bits,Sword)),			      \
+      [ELF_T_WORD] = __alignof__ (ElfW2(Bits,Word)),			      \
+      [ELF_T_XWORD] = __alignof__ (ElfW2(Bits,Xword)),			      \
+      [ELF_T_SXWORD] = __alignof__ (ElfW2(Bits,Sxword)),		      \
+      [ELF_T_SYM] = __alignof__ (ElfW2(Bits,Sym)),			      \
+      [ELF_T_SYMINFO] = __alignof__ (ElfW2(Bits,Syminfo)),		      \
+      [ELF_T_REL] = __alignof__ (ElfW2(Bits,Rel)),			      \
+      [ELF_T_RELA] = __alignof__ (ElfW2(Bits,Rela)),			      \
+      [ELF_T_DYN] = __alignof__ (ElfW2(Bits,Dyn)),			      \
+      [ELF_T_VDEF] = __alignof__ (ElfW2(Bits,Verdef)),			      \
+      [ELF_T_VDAUX] = __alignof__ (ElfW2(Bits,Verdaux)),		      \
+      [ELF_T_VNEED] = __alignof__ (ElfW2(Bits,Verneed)),		      \
+      [ELF_T_VNAUX] = __alignof__ (ElfW2(Bits,Vernaux)),		      \
+      [ELF_T_MOVE] = __alignof__ (ElfW2(Bits,Move)),			      \
+      [ELF_T_LIB] = __alignof__ (ElfW2(Bits,Lib)),			      \
+      [ELF_T_NHDR] = __alignof__ (ElfW2(Bits,Nhdr)),			      \
+      [ELF_T_AUXV] = __alignof__ (ElfW2(Bits,auxv_t)),			      \
+      [ELF_T_CHDR] = __alignof__ (ElfW2(Bits,Chdr)),			      \
+      [ELF_T_NHDR8] = 8 /* Special case for GNU Property note.  */
+    [ELFCLASS32 - 1] =  {
+	TYPE_ALIGNS (32),
+	[ELF_T_GNUHASH] = __alignof__ (Elf32_Word),
+    },
+    [ELFCLASS64 - 1] = {
+	TYPE_ALIGNS (64),
+	[ELF_T_GNUHASH] = __alignof__ (Elf64_Xword),
+    },
+# undef TYPE_ALIGNS
+  };
+
+
+Elf_Type
+internal_function
+__libelf_data_type (GElf_Ehdr *ehdr, int sh_type, GElf_Xword align)
+{
+  /* Some broken ELF ABI for 64-bit machines use the wrong hash table
+     entry size.  See elf-knowledge.h for more information.  */
+  if (sh_type == SHT_HASH && ehdr->e_ident[EI_CLASS] == ELFCLASS64)
+    {
+      return (SH_ENTSIZE_HASH (ehdr) == 4 ? ELF_T_WORD : ELF_T_XWORD);
+    }
+  else
+    {
+      Elf_Type t = shtype_map[TYPEIDX (sh_type)];
+      /* Special case for GNU Property notes.  */
+      if (t == ELF_T_NHDR && align == 8)
+	t = ELF_T_NHDR8;
+      return t;
+    }
+}
+
+/* Convert the data in the current section.  */
+static void
+convert_data (Elf_Scn *scn, int eclass,
+	      int data, size_t size, Elf_Type type)
+{
+  const size_t align = __libelf_type_align (eclass, type);
+
+  /* Do we need to convert the data and/or adjust for alignment?  */
+  if (data == MY_ELFDATA || type == ELF_T_BYTE)
+    {
+      if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
+	/* No need to copy, we can use the raw data.  */
+	scn->data_base = scn->rawdata_base;
+      else
+	{
+	  scn->data_base = malloc (size);
+	  if (scn->data_base == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return;
+	    }
+
+	  /* The copy will be appropriately aligned for direct access.  */
+	  memcpy (scn->data_base, scn->rawdata_base, size);
+	}
+    }
+  else
+    {
+      xfct_t fp;
+
+      scn->data_base = malloc (size);
+      if (scn->data_base == NULL)
+	{
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  return;
+	}
+
+      /* Make sure the source is correctly aligned for the conversion
+	 function to directly access the data elements.  */
+      char *rawdata_source;
+      if (((((size_t) (char *) scn->rawdata_base)) & (align - 1)) == 0)
+	rawdata_source = scn->rawdata_base;
+      else
+	{
+	  rawdata_source = malloc (size);
+	  if (rawdata_source == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return;
+	    }
+
+	  /* The copy will be appropriately aligned for direct access.  */
+	  memcpy (rawdata_source, scn->rawdata_base, size);
+	}
+
+      /* Get the conversion function.  */
+      fp = __elf_xfctstom[eclass - 1][type];
+
+      fp (scn->data_base, rawdata_source, size, 0);
+
+      if (rawdata_source != scn->rawdata_base)
+	free (rawdata_source);
+    }
+
+  scn->data_list.data.d.d_buf = scn->data_base;
+  scn->data_list.data.d.d_size = size;
+  scn->data_list.data.d.d_type = type;
+  scn->data_list.data.d.d_off = scn->rawdata.d.d_off;
+  scn->data_list.data.d.d_align = scn->rawdata.d.d_align;
+  scn->data_list.data.d.d_version = scn->rawdata.d.d_version;
+
+  scn->data_list.data.s = scn;
+}
+
+
+/* Store the information for the raw data in the `rawdata' element.  */
+int
+internal_function
+__libelf_set_rawdata_wrlock (Elf_Scn *scn)
+{
+  Elf64_Off offset;
+  Elf64_Xword size;
+  Elf64_Xword align;
+  Elf64_Xword flags;
+  int type;
+  Elf *elf = scn->elf;
+
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_Shdr *shdr
+	= scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
+
+      if (shdr == NULL)
+	/* Something went terribly wrong.  */
+	return 1;
+
+      offset = shdr->sh_offset;
+      size = shdr->sh_size;
+      type = shdr->sh_type;
+      align = shdr->sh_addralign;
+      flags = shdr->sh_flags;
+    }
+  else
+    {
+      Elf64_Shdr *shdr
+	= scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
+
+      if (shdr == NULL)
+	/* Something went terribly wrong.  */
+	return 1;
+
+      offset = shdr->sh_offset;
+      size = shdr->sh_size;
+      type = shdr->sh_type;
+      align = shdr->sh_addralign;
+      flags = shdr->sh_flags;
+    }
+
+  /* If the section has no data (for whatever reason), leave the `d_buf'
+     pointer NULL.  */
+  if (size != 0 && type != SHT_NOBITS)
+    {
+      /* First a test whether the section is valid at all.  */
+      size_t entsize;
+
+      /* Compressed data has a header, but then compressed data.
+	 Make sure to set the alignment of the header explicitly,
+	 don't trust the file alignment for the section, it is
+	 often wrong.  */
+      if ((flags & SHF_COMPRESSED) != 0)
+	{
+	  entsize = 1;
+	  align = __libelf_type_align (elf->class, ELF_T_CHDR);
+	}
+      else if (type == SHT_HASH)
+	{
+	  GElf_Ehdr ehdr_mem;
+	  GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
+	  if (unlikely (ehdr == NULL))
+	    return 1;
+	  entsize = SH_ENTSIZE_HASH (ehdr);
+	}
+      else
+	{
+	  Elf_Type t = shtype_map[TYPEIDX (type)];
+	  if (t == ELF_T_NHDR && align == 8)
+	    t = ELF_T_NHDR8;
+	  if (t == ELF_T_VDEF || t == ELF_T_NHDR || t == ELF_T_NHDR8
+	      || (t == ELF_T_GNUHASH && elf->class == ELFCLASS64))
+	    entsize = 1;
+	  else
+	    entsize = __libelf_type_sizes[elf->class - 1][t];
+	}
+
+      /* We assume it is an array of bytes if it is none of the structured
+	 sections we know of.  */
+      if (entsize == 0)
+	entsize = 1;
+
+      if (unlikely (size % entsize != 0))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  return 1;
+	}
+
+      /* We can use the mapped or loaded data if available.  */
+      if (elf->map_address != NULL)
+	{
+	  /* First see whether the information in the section header is
+	     valid and it does not ask for too much.  Check for unsigned
+	     overflow.  */
+	  if (unlikely (offset > elf->maximum_size
+	      || elf->maximum_size - offset < size))
+	    {
+	      /* Something is wrong.  */
+	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+	      return 1;
+	    }
+
+	  scn->rawdata_base = scn->rawdata.d.d_buf
+	    = (char *) elf->map_address + elf->start_offset + offset;
+	}
+      else if (likely (elf->fildes != -1))
+	{
+	  /* First see whether the information in the section header is
+	     valid and it does not ask for too much.  Check for unsigned
+	     overflow.  */
+	  if (unlikely (offset > elf->maximum_size
+			|| elf->maximum_size - offset < size))
+	    {
+	      /* Something is wrong.  */
+	      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+	      return 1;
+	    }
+
+	  /* We have to read the data from the file.  Allocate the needed
+	     memory.  */
+	  scn->rawdata_base = scn->rawdata.d.d_buf = malloc (size);
+	  if (scn->rawdata.d.d_buf == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      return 1;
+	    }
+
+	  ssize_t n = pread_retry (elf->fildes, scn->rawdata.d.d_buf, size,
+				   elf->start_offset + offset);
+	  if (unlikely ((size_t) n != size))
+	    {
+	      /* Cannot read the data.  */
+	      free (scn->rawdata.d.d_buf);
+	      scn->rawdata_base = scn->rawdata.d.d_buf = NULL;
+	      __libelf_seterrno (ELF_E_READ_ERROR);
+	      return 1;
+	    }
+	}
+      else
+	{
+	  /* The file descriptor is already closed, we cannot get the data
+	     anymore.  */
+	  __libelf_seterrno (ELF_E_FD_DISABLED);
+	  return 1;
+	}
+    }
+
+  scn->rawdata.d.d_size = size;
+
+  /* Compressed data always has type ELF_T_CHDR regardless of the
+     section type.  */
+  if ((flags & SHF_COMPRESSED) != 0)
+    scn->rawdata.d.d_type = ELF_T_CHDR;
+  else
+    {
+      GElf_Ehdr ehdr_mem;
+      GElf_Ehdr *ehdr = __gelf_getehdr_rdlock (elf, &ehdr_mem);
+      if (unlikely (ehdr == NULL))
+	return 1;
+      scn->rawdata.d.d_type = __libelf_data_type (ehdr, type, align);
+    }
+  scn->rawdata.d.d_off = 0;
+
+  /* Make sure the alignment makes sense.  d_align should be aligned both
+     in the section (trivially true since d_off is zero) and in the file.
+     Unfortunately we cannot be too strict because there are ELF files
+     out there that fail this requirement.  We will try to fix those up
+     in elf_update when writing out the image.  But for very large
+     alignment values this can bloat the image considerably.  So here
+     just check and clamp the alignment value to not be bigger than the
+     actual offset of the data in the file.  Given that there is always
+     at least an ehdr this will only trigger for alignment values > 64
+     which should be uncommon.  */
+  align = align ?: 1;
+  if (type != SHT_NOBITS && align > offset)
+    {
+      /* Align the offset to the next power of two. Uses algorithm from
+         https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */
+      align = offset - 1;
+      align |= align >> 1;
+      align |= align >> 2;
+      align |= align >> 4;
+      align |= align >> 8;
+      align |= align >> 16;
+      align |= align >> 32;
+      align++;
+    }
+  scn->rawdata.d.d_align = align;
+  if (elf->class == ELFCLASS32
+      || (offsetof (struct Elf, state.elf32.ehdr)
+	  == offsetof (struct Elf, state.elf64.ehdr)))
+    scn->rawdata.d.d_version =
+      elf->state.elf32.ehdr->e_ident[EI_VERSION];
+  else
+    scn->rawdata.d.d_version =
+      elf->state.elf64.ehdr->e_ident[EI_VERSION];
+
+  scn->rawdata.s = scn;
+
+  scn->data_read = 1;
+
+  /* We actually read data from the file.  At least we tried.  */
+  scn->flags |= ELF_F_FILEDATA;
+
+  return 0;
+}
+
+int
+internal_function
+__libelf_set_rawdata (Elf_Scn *scn)
+{
+  int result;
+
+  if (scn == NULL)
+    return 1;
+
+  rwlock_wrlock (scn->elf->lock);
+  result = __libelf_set_rawdata_wrlock (scn);
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
+
+void
+internal_function
+__libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
+{
+  if (scn->rawdata.d.d_buf != NULL && scn->rawdata.d.d_size > 0)
+    {
+      Elf *elf = scn->elf;
+
+      /* Upgrade the lock to a write lock if necessary and check
+	 nobody else already did the work.  */
+      if (!wrlocked)
+	{
+	  rwlock_unlock (elf->lock);
+	  rwlock_wrlock (elf->lock);
+	  if (scn->data_list_rear != NULL)
+	    return;
+	}
+
+      /* Convert according to the version and the type.   */
+      convert_data (scn, elf->class,
+		    (elf->class == ELFCLASS32
+		     || (offsetof (struct Elf, state.elf32.ehdr)
+			 == offsetof (struct Elf, state.elf64.ehdr))
+		     ? elf->state.elf32.ehdr->e_ident[EI_DATA]
+		     : elf->state.elf64.ehdr->e_ident[EI_DATA]),
+		    scn->rawdata.d.d_size, scn->rawdata.d.d_type);
+    }
+  else
+    {
+      /* This is an empty or NOBITS section.  There is no buffer but
+	 the size information etc is important.  */
+      scn->data_list.data.d = scn->rawdata.d;
+      scn->data_list.data.s = scn;
+    }
+
+  scn->data_list_rear = &scn->data_list;
+}
+
+Elf_Data *
+internal_function
+__elf_getdata_rdlock (Elf_Scn *scn, Elf_Data *data)
+{
+  Elf_Data *result = NULL;
+  Elf *elf;
+  int locked = 0;
+
+  if (scn == NULL)
+    return NULL;
+
+  if (unlikely (scn->elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* We will need this multiple times later on.  */
+  elf = scn->elf;
+
+  /* If `data' is not NULL this means we are not addressing the initial
+     data in the file.  But this also means this data is already read
+     (since otherwise it is not possible to have a valid `data' pointer)
+     and all the data structures are initialized as well.  In this case
+     we can simply walk the list of data records.  */
+  if (data != NULL)
+    {
+      Elf_Data_List *runp;
+
+      /* It is not possible that if DATA is not NULL the first entry is
+	 returned.  But this also means that there must be a first data
+	 entry.  */
+      if (scn->data_list_rear == NULL
+	  /* The section the reference data is for must match the section
+	     parameter.  */
+	  || unlikely (((Elf_Data_Scn *) data)->s != scn))
+	{
+	  __libelf_seterrno (ELF_E_DATA_MISMATCH);
+	  goto out;
+	}
+
+      /* We start searching with the first entry.  */
+      runp = &scn->data_list;
+
+      while (1)
+	{
+	  /* If `data' does not match any known record punt.  */
+	  if (runp == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+	      goto out;
+	    }
+
+	  if (&runp->data.d == data)
+	    /* Found the entry.  */
+	    break;
+
+	  runp = runp->next;
+	}
+
+      /* Return the data for the next data record.  */
+      result = runp->next ? &runp->next->data.d : NULL;
+      goto out;
+    }
+
+  /* If the data for this section was not yet initialized do it now.  */
+  if (scn->data_read == 0)
+    {
+      /* We cannot acquire a write lock while we are holding a read
+         lock.  Therefore give up the read lock and then get the write
+         lock.  But this means that the data could meanwhile be
+         modified, therefore start the tests again.  */
+      rwlock_unlock (elf->lock);
+      rwlock_wrlock (elf->lock);
+      locked = 1;
+
+      /* Read the data from the file.  There is always a file (or
+	 memory region) associated with this descriptor since
+	 otherwise the `data_read' flag would be set.  */
+      if (scn->data_read == 0 && __libelf_set_rawdata_wrlock (scn) != 0)
+	/* Something went wrong.  The error value is already set.  */
+	goto out;
+    }
+
+  /* At this point we know the raw data is available.  But it might be
+     empty in case the section has size zero (for whatever reason).
+     Now create the converted data in case this is necessary.  */
+  if (scn->data_list_rear == NULL)
+    __libelf_set_data_list_rdlock (scn, locked);
+
+  /* Return the first data element in the list.  */
+  result = &scn->data_list.data.d;
+
+ out:
+  return result;
+}
+
+Elf_Data *
+elf_getdata (Elf_Scn *scn, Elf_Data *data)
+{
+  Elf_Data *result;
+
+  if (scn == NULL)
+    return NULL;
+
+  rwlock_rdlock (scn->elf->lock);
+  result = __elf_getdata_rdlock (scn, data);
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
+
+Elf_Data *
+internal_function
+__elf_getdata_wrlock (Elf_Scn *scn, Elf_Data *data)
+{
+  Elf_Data *result;
+
+  if (scn == NULL)
+    return NULL;
+
+  result = __elf_getdata_rdlock (scn, data);
+
+  return result;
+}
+INTDEF(elf_getdata)
diff --git a/libelf/elf_getdata_rawchunk.c b/libelf/elf_getdata_rawchunk.c
new file mode 100644
index 0000000..1751878
--- /dev/null
+++ b/libelf/elf_getdata_rawchunk.c
@@ -0,0 +1,229 @@
+/* Return converted data from raw chunk of ELF file.
+   Copyright (C) 2007, 2014, 2015 Red Hat, Inc.
+   Copyright (C) 2022, 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+#include "common.h"
+
+static int
+chunk_compare (const void *a, const void *b)
+{
+  Elf_Data_Chunk *da = (Elf_Data_Chunk *)a;
+  Elf_Data_Chunk *db = (Elf_Data_Chunk *)b;
+
+  if (da->offset != db->offset)
+    return da->offset - db->offset;
+
+  if (da->data.d.d_size != db->data.d.d_size)
+    return da->data.d.d_size - db->data.d.d_size;
+
+  return da->data.d.d_type - db->data.d.d_type;
+}
+
+Elf_Data *
+elf_getdata_rawchunk (Elf *elf, int64_t offset, size_t size, Elf_Type type)
+{
+  if (unlikely (elf == NULL))
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      /* No valid descriptor.  */
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  if (unlikely (offset < 0 || (uint64_t) offset > elf->maximum_size
+		|| elf->maximum_size - (uint64_t) offset < size))
+
+    {
+      /* Invalid request.  */
+      __libelf_seterrno (ELF_E_INVALID_OP);
+      return NULL;
+    }
+
+  if (type >= ELF_T_NUM)
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
+      return NULL;
+    }
+
+  /* Get the raw bytes from the file.  */
+  void *rawchunk;
+  int flags = 0;
+  Elf_Data *result = NULL;
+
+  rwlock_rdlock (elf->lock);
+
+  /* Maybe we already got this chunk?  */
+  Elf_Data_Chunk key;
+  key.offset = offset;
+  key.data.d.d_size = size;
+  key.data.d.d_type = type;
+  Elf_Data_Chunk **found = tsearch (&key, &elf->state.elf.rawchunks,
+				    &chunk_compare);
+  if (found == NULL)
+    goto nomem;
+
+  /* Existing entry.  */
+  if (*found != &key && *found != NULL)
+    {
+      result = &(*found)->data.d;
+      goto out;
+    }
+
+  /* New entry.  Note that *found will point to the newly inserted
+     (dummy) key.  We'll replace it with a real rawchunk when that is
+     setup.  Make sure to tdelete the dummy key if anything goes
+     wrong.  */
+
+  size_t align = __libelf_type_align (elf->class, type);
+  if (elf->map_address != NULL)
+    {
+    /* If the file is mmap'ed we can use it directly, if aligned for type.  */
+      char *rawdata = elf->map_address + elf->start_offset + offset;
+      if (((uintptr_t) rawdata & (align - 1)) == 0)
+	rawchunk = rawdata;
+      else
+	{
+	  /* We allocate the memory and memcpy it to get aligned data. */
+	  rawchunk = malloc (size);
+	  if (rawchunk == NULL)
+	    goto nomem;
+	  memcpy (rawchunk, rawdata, size);
+	  flags = ELF_F_MALLOCED;
+	}
+    }
+  else
+    {
+      /* We allocate the memory and read the data from the file.  */
+      rawchunk = malloc (size);
+      if (rawchunk == NULL)
+	{
+	nomem:
+	  tdelete (&key, &elf->state.elf.rawchunks, &chunk_compare);
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  goto out;
+	}
+
+      /* Read the file content.  */
+      if (unlikely ((size_t) pread_retry (elf->fildes, rawchunk, size,
+					  elf->start_offset + offset)
+		    != size))
+	{
+	  /* Something went wrong.  */
+	  tdelete (&key, &elf->state.elf.rawchunks, &chunk_compare);
+	  free (rawchunk);
+	  __libelf_seterrno (ELF_E_READ_ERROR);
+	  goto out;
+	}
+
+      flags = ELF_F_MALLOCED;
+    }
+
+  /* Copy and/or convert the data as needed for aligned native-order access.  */
+  void *buffer;
+  if (elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA)
+    {
+      if (((uintptr_t) rawchunk & (align - 1)) == 0)
+	/* No need to copy, we can use the raw data.  */
+	buffer = rawchunk;
+      else
+	{
+	  /* A malloc'd block is always sufficiently aligned.  */
+	  assert (flags == 0);
+
+	  buffer = malloc (size);
+	  if (unlikely (buffer == NULL))
+	    goto nomem;
+	  flags = ELF_F_MALLOCED;
+
+	  /* The copy will be appropriately aligned for direct access.  */
+	  memcpy (buffer, rawchunk, size);
+
+	  free (rawchunk);
+	}
+    }
+  else
+    {
+      if (flags)
+	buffer = rawchunk;
+      else
+	{
+	  buffer = malloc (size);
+	  if (unlikely (buffer == NULL))
+	    goto nomem;
+	  flags = ELF_F_MALLOCED;
+	}
+
+      /* Call the conversion function.  */
+      (*__elf_xfctstom[elf->class - 1][type])(buffer, rawchunk, size, 0);
+
+      if (!flags)
+	free (rawchunk);
+    }
+
+  /* Allocate the dummy container to point at this buffer.  */
+  Elf_Data_Chunk *chunk = calloc (1, sizeof *chunk);
+  if (chunk == NULL)
+    {
+      if (flags)
+	free (buffer);
+      goto nomem;
+    }
+
+  chunk->dummy_scn.elf = elf;
+  chunk->dummy_scn.flags = flags;
+  chunk->data.s = &chunk->dummy_scn;
+  chunk->data.d.d_buf = buffer;
+  chunk->data.d.d_size = size;
+  chunk->data.d.d_type = type;
+  chunk->data.d.d_align = align;
+  chunk->data.d.d_version = EV_CURRENT;
+  chunk->offset = offset;
+
+  rwlock_unlock (elf->lock);
+  rwlock_wrlock (elf->lock);
+
+  *found = chunk;
+  result = &chunk->data.d;
+
+ out:
+  rwlock_unlock (elf->lock);
+  return result;
+}
diff --git a/libelf/elf_getident.c b/libelf/elf_getident.c
new file mode 100644
index 0000000..5abf8c9
--- /dev/null
+++ b/libelf/elf_getident.c
@@ -0,0 +1,61 @@
+/* Retrieve file identification data.
+   Copyright (C) 1998, 1999, 2000, 2002, 2004, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+char *
+elf_getident (Elf *elf, size_t *ptr)
+{
+  /* In case this is no ELF file, the handle is invalid and we return
+     NULL.  */
+  if (elf == NULL || elf->kind != ELF_K_ELF)
+    {
+      if (ptr != NULL)
+	*ptr = 0;
+      return NULL;
+    }
+
+  /* We already read the ELF header.  Return a pointer to it and store
+     the length in *PTR.  */
+  if (ptr != NULL)
+    *ptr = EI_NIDENT;
+
+  return (char *) (elf->class == ELFCLASS32
+		   || (offsetof (struct Elf, state.elf32.ehdr)
+		       == offsetof (struct Elf, state.elf64.ehdr))
+		   ? elf->state.elf32.ehdr->e_ident
+		   : elf->state.elf64.ehdr->e_ident);
+}
diff --git a/libelf/elf_getphdrnum.c b/libelf/elf_getphdrnum.c
new file mode 100644
index 0000000..60ebec5
--- /dev/null
+++ b/libelf/elf_getphdrnum.c
@@ -0,0 +1,151 @@
+/* Return number of program headers in the ELF file.
+   Copyright (C) 2010, 2014, 2015, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+int
+internal_function
+__elf_getphdrnum_rdlock (Elf *elf, size_t *dst)
+{
+ if (unlikely (elf->state.elf64.ehdr == NULL))
+   {
+     /* Maybe no ELF header was created yet.  */
+     *dst = 0;
+     __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+     return -1;
+   }
+
+ *dst = (elf->class == ELFCLASS32
+	 ? elf->state.elf32.ehdr->e_phnum
+	 : elf->state.elf64.ehdr->e_phnum);
+
+ if (*dst == PN_XNUM)
+   {
+     const Elf_ScnList *const scns = (elf->class == ELFCLASS32
+				      ? &elf->state.elf32.scns
+				      : &elf->state.elf64.scns);
+
+     /* If there are no section headers, perhaps this is really just 65536
+	written without PN_XNUM support.  Either that or it's bad data.  */
+
+     if (elf->class == ELFCLASS32)
+       {
+	 if (likely (scns->cnt > 0))
+	   {
+	     Elf_Scn *scn = &elf->state.elf32.scns.data[0];
+	     Elf32_Shdr *shdr = scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn);
+	     if (shdr)
+	       *dst = shdr->sh_info;
+	   }
+       }
+     else
+       {
+	 if (likely (scns->cnt > 0))
+	   {
+	     Elf_Scn *scn = &elf->state.elf64.scns.data[0];
+	     Elf64_Shdr *shdr = scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn);
+	     if (shdr)
+	       *dst = shdr->sh_info;
+	   }
+       }
+   }
+
+ return 0;
+}
+
+int
+internal_function
+__elf_getphdrnum_chk_rdlock (Elf *elf, size_t *dst)
+{
+  int result = __elf_getphdrnum_rdlock (elf, dst);
+
+  /* If the phdrs haven't been created or read in yet then do some
+     sanity checking to make sure phnum and phoff are consistent.  */
+  if (elf->state.elf.phdr == NULL)
+    {
+      Elf64_Off off = (elf->class == ELFCLASS32
+		       ? elf->state.elf32.ehdr->e_phoff
+		       : elf->state.elf64.ehdr->e_phoff);
+      if (unlikely (off == 0))
+	{
+	  *dst = 0;
+	  return result;
+	}
+
+      if (unlikely (off >= elf->maximum_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  return -1;
+	}
+
+      /* Check for too many sections.  */
+      size_t phdr_size = (elf->class == ELFCLASS32
+			  ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr));
+      if (unlikely (*dst > SIZE_MAX / phdr_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  return -1;
+	}
+
+      /* Truncated file?  Don't return more than can be indexed.  */
+      if (unlikely (elf->maximum_size - off < *dst * phdr_size))
+	*dst = (elf->maximum_size - off) / phdr_size;
+    }
+
+  return result;
+}
+
+int
+elf_getphdrnum (Elf *elf, size_t *dst)
+{
+  int result;
+
+  if (elf == NULL)
+    return -1;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return -1;
+    }
+
+  rwlock_rdlock (elf->lock);
+  result = __elf_getphdrnum_chk_rdlock (elf, dst);
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/elf_getscn.c b/libelf/elf_getscn.c
new file mode 100644
index 0000000..be9c76f
--- /dev/null
+++ b/libelf/elf_getscn.c
@@ -0,0 +1,120 @@
+/* Get section at specific index.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+Elf_Scn *
+elf_getscn (Elf *elf, size_t idx)
+{
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  rwlock_rdlock (elf->lock);
+
+  Elf_Scn *result = NULL;
+
+  /* Find the section in the list.  */
+  Elf_ScnList *runp = (elf->class == ELFCLASS32
+		       || (offsetof (struct Elf, state.elf32.scns)
+			   == offsetof (struct Elf, state.elf64.scns))
+		       ? &elf->state.elf32.scns : &elf->state.elf64.scns);
+
+  /* Section zero is special.  It always exists even if there is no
+     "first" section.  And it is needed to store "overflow" values
+     from the Elf header.  */
+  if (idx == 0 && runp->cnt == 0 && runp->max > 0)
+    {
+      Elf_Scn *scn0 = &runp->data[0];
+      if (elf->class == ELFCLASS32)
+	{
+	  scn0->shdr.e32 = calloc (1, sizeof (Elf32_Shdr));
+	  if (scn0->shdr.e32 == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      goto out;
+	    }
+	}
+      else
+	{
+	  scn0->shdr.e64 = calloc (1, sizeof (Elf64_Shdr));
+	  if (scn0->shdr.e64 == NULL)
+	    {
+	      __libelf_seterrno (ELF_E_NOMEM);
+	      goto out;
+	    }
+	}
+      scn0->elf = elf;
+      scn0->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
+      scn0->list = elf->state.elf.scns_last;
+      scn0->data_read = 1;
+      runp->cnt = 1;
+    }
+
+  while (1)
+    {
+      if (idx < runp->max)
+	{
+	  if (idx < runp->cnt)
+	    result = &runp->data[idx];
+	  else
+	    __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  break;
+	}
+
+      idx -= runp->max;
+
+      runp = runp->next;
+      if (runp == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  break;
+	}
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elf_getscn)
diff --git a/libelf/elf_getshdrnum.c b/libelf/elf_getshdrnum.c
new file mode 100644
index 0000000..18e5d14
--- /dev/null
+++ b/libelf/elf_getshdrnum.c
@@ -0,0 +1,87 @@
+/* Return number of sections in the ELF file.
+   Copyright (C) 2002, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+int
+internal_function
+__elf_getshdrnum_rdlock (Elf *elf, size_t *dst)
+{
+  int result = 0;
+  int idx;
+
+  if (elf == NULL)
+    return -1;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return -1;
+    }
+
+  idx = elf->state.elf.scns_last->cnt;
+  if (idx != 0
+      || (elf->state.elf.scns_last
+	  != (elf->class == ELFCLASS32
+	      || (offsetof (Elf, state.elf32.scns)
+		  == offsetof (Elf, state.elf64.scns))
+	      ? &elf->state.elf32.scns : &elf->state.elf64.scns)))
+    /* There is at least one section.  */
+    *dst = 1 + elf->state.elf.scns_last->data[idx - 1].index;
+  else
+    *dst = 0;
+
+  return result;
+}
+
+int
+elf_getshdrnum (Elf *elf, size_t *dst)
+{
+  int result;
+
+  if (elf == NULL)
+    return -1;
+
+  rwlock_rdlock (elf->lock);
+  result = __elf_getshdrnum_rdlock (elf, dst);
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+/* Alias for the deprecated name.  */
+strong_alias (elf_getshdrnum, elf_getshnum)
diff --git a/libelf/elf_getshdrstrndx.c b/libelf/elf_getshdrstrndx.c
new file mode 100644
index 0000000..2391317
--- /dev/null
+++ b/libelf/elf_getshdrstrndx.c
@@ -0,0 +1,233 @@
+/* Return section index of section header string table.
+   Copyright (C) 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <errno.h>
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+#include "common.h"
+
+
+int
+elf_getshdrstrndx (Elf *elf, size_t *dst)
+{
+  int result = 0;
+
+  if (elf == NULL)
+    return -1;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return -1;
+    }
+
+  rwlock_rdlock (elf->lock);
+
+  /* We rely here on the fact that the `elf' element is a common prefix
+     of `elf32' and `elf64'.  */
+  assert (offsetof (struct Elf, state.elf.ehdr)
+	  == offsetof (struct Elf, state.elf32.ehdr));
+  assert (sizeof (elf->state.elf.ehdr)
+	  == sizeof (elf->state.elf32.ehdr));
+  assert (offsetof (struct Elf, state.elf.ehdr)
+	  == offsetof (struct Elf, state.elf64.ehdr));
+  assert (sizeof (elf->state.elf.ehdr)
+	  == sizeof (elf->state.elf64.ehdr));
+
+  if (unlikely (elf->state.elf.ehdr == NULL))
+    {
+      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+      result = -1;
+    }
+  else
+    {
+      Elf32_Word num;
+
+      num = (elf->class == ELFCLASS32
+	     ? elf->state.elf32.ehdr->e_shstrndx
+	     : elf->state.elf64.ehdr->e_shstrndx);
+
+      /* Determine whether the index is too big to fit in the ELF
+	 header.  */
+      if (unlikely (num == SHN_XINDEX))
+	{
+	  /* Yes.  Search the zeroth section header.  */
+	  if (elf->class == ELFCLASS32)
+	    {
+	      size_t offset;
+	      if (unlikely (elf->state.elf32.scns.cnt == 0))
+		{
+		  /* Cannot use SHN_XINDEX without section headers.  */
+		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+		  result = -1;
+		  goto out;
+		}
+
+	      if (elf->state.elf32.scns.data[0].shdr.e32 != NULL)
+		{
+		  num = elf->state.elf32.scns.data[0].shdr.e32->sh_link;
+		  goto success;
+		}
+
+	      offset = elf->state.elf32.ehdr->e_shoff;
+
+	      if (elf->map_address != NULL
+		  && elf->state.elf32.ehdr->e_ident[EI_DATA] == MY_ELFDATA
+		  && (ALLOW_UNALIGNED
+		      || (((size_t) ((char *) elf->map_address
+			   + elf->start_offset + offset))
+			  & (__alignof__ (Elf32_Shdr) - 1)) == 0))
+		{
+		  /* First see whether the information in the ELF header is
+		     valid and it does not ask for too much.  */
+		  if (unlikely (elf->maximum_size - offset
+				< sizeof (Elf32_Shdr)))
+		    {
+		      /* Something is wrong.  */
+		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+		      result = -1;
+		      goto out;
+		    }
+
+		  /* We can directly access the memory.  */
+		  num = ((Elf32_Shdr *) (elf->map_address + elf->start_offset
+					 + offset))->sh_link;
+		}
+	      else
+		{
+		  /* We avoid reading in all the section headers.  Just read
+		     the first one.  */
+		  Elf32_Shdr shdr_mem;
+		  ssize_t r;
+
+		  if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
+						  sizeof (Elf32_Shdr), offset))
+				!= sizeof (Elf32_Shdr)))
+		    {
+		      /* We must be able to read this ELF section header.  */
+		      if (r < 0)
+			__libelf_seterrno (ELF_E_INVALID_FILE);
+		      else
+			__libelf_seterrno (ELF_E_INVALID_ELF);
+		      result = -1;
+		      goto out;
+		    }
+
+		  if (elf->state.elf32.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
+		    CONVERT (shdr_mem.sh_link);
+		  num = shdr_mem.sh_link;
+		}
+	    }
+	  else
+	    {
+	      if (unlikely (elf->state.elf64.scns.cnt == 0))
+		{
+		  /* Cannot use SHN_XINDEX without section headers.  */
+		  __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+		  result = -1;
+		  goto out;
+		}
+
+	      if (elf->state.elf64.scns.data[0].shdr.e64 != NULL)
+		{
+		  num = elf->state.elf64.scns.data[0].shdr.e64->sh_link;
+		  goto success;
+		}
+
+	      size_t offset = elf->state.elf64.ehdr->e_shoff;
+
+	      if (elf->map_address != NULL
+		  && elf->state.elf64.ehdr->e_ident[EI_DATA] == MY_ELFDATA
+		  && (ALLOW_UNALIGNED
+		      || (((size_t) ((char *) elf->map_address
+			   + elf->start_offset + offset))
+			  & (__alignof__ (Elf64_Shdr) - 1)) == 0))
+		{
+		  /* First see whether the information in the ELF header is
+		     valid and it does not ask for too much.  */
+		  if (unlikely (elf->maximum_size - offset
+				< sizeof (Elf64_Shdr)))
+		    {
+		      /* Something is wrong.  */
+		      __libelf_seterrno (ELF_E_INVALID_SECTION_HEADER);
+		      result = -1;
+		      goto out;
+		    }
+
+		  /* We can directly access the memory.  */
+		  num = ((Elf64_Shdr *) (elf->map_address + elf->start_offset
+					 + offset))->sh_link;
+		}
+	      else
+		{
+		  /* We avoid reading in all the section headers.  Just read
+		     the first one.  */
+		  Elf64_Shdr shdr_mem;
+		  ssize_t r;
+
+		  if (unlikely ((r = pread_retry (elf->fildes, &shdr_mem,
+						  sizeof (Elf64_Shdr), offset))
+				!= sizeof (Elf64_Shdr)))
+		    {
+		      /* We must be able to read this ELF section header.  */
+		      if (r < 0)
+			__libelf_seterrno (ELF_E_INVALID_FILE);
+		      else
+			__libelf_seterrno (ELF_E_INVALID_ELF);
+		      result = -1;
+		      goto out;
+		    }
+
+		  if (elf->state.elf64.ehdr->e_ident[EI_DATA] != MY_ELFDATA)
+		    CONVERT (shdr_mem.sh_link);
+		  num = shdr_mem.sh_link;
+		}
+	    }
+	}
+
+      /* Store the result.  */
+    success:
+      *dst = num;
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elf_getshdrstrndx)
+/* Alias for the deprecated name.  */
+strong_alias (elf_getshdrstrndx, elf_getshstrndx)
diff --git a/libelf/elf_gnu_hash.c b/libelf/elf_gnu_hash.c
new file mode 100644
index 0000000..5a1b852
--- /dev/null
+++ b/libelf/elf_gnu_hash.c
@@ -0,0 +1,46 @@
+/* GNU-style Hash function used in ELF implementations.
+   Copyright (C) 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2006.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelfP.h>
+
+/* Get the implementation.  */
+#include <dl-hash.h>
+
+unsigned long int
+elf_gnu_hash (const char *string)
+{
+  uint_fast32_t h = 5381;
+  for (unsigned char c = *string; c != '\0'; c = *++string)
+    h = h * 33 + c;
+  return h & 0xffffffff;
+}
diff --git a/libelf/elf_hash.c b/libelf/elf_hash.c
new file mode 100644
index 0000000..345697e
--- /dev/null
+++ b/libelf/elf_hash.c
@@ -0,0 +1,44 @@
+/* Hash function used in ELF implementations.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelfP.h>
+
+/* Get the implementation.  */
+#include <dl-hash.h>
+
+unsigned long int
+elf_hash (const char *string)
+{
+  return _dl_elf_hash (string);
+}
+INTDEF(elf_hash)
diff --git a/libelf/elf_kind.c b/libelf/elf_kind.c
new file mode 100644
index 0000000..0fb3f0c
--- /dev/null
+++ b/libelf/elf_kind.c
@@ -0,0 +1,44 @@
+/* Return the kind of file associated with the descriptor.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf_Kind
+elf_kind (Elf *elf)
+{
+  return elf == NULL ? ELF_K_NONE : elf->kind;
+}
diff --git a/libelf/elf_memory.c b/libelf/elf_memory.c
new file mode 100644
index 0000000..13d77cb
--- /dev/null
+++ b/libelf/elf_memory.c
@@ -0,0 +1,50 @@
+/* Create descriptor for memory region.
+   Copyright (C) 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf *
+elf_memory (char *image, size_t size)
+{
+  if (image == NULL)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return NULL;
+    }
+
+  return __libelf_read_mmaped_file (-1, image, 0, size, ELF_C_READ_MMAP, NULL);
+}
diff --git a/libelf/elf_ndxscn.c b/libelf/elf_ndxscn.c
new file mode 100644
index 0000000..488c4e5
--- /dev/null
+++ b/libelf/elf_ndxscn.c
@@ -0,0 +1,47 @@
+/* Get index of section.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+size_t
+elf_ndxscn (Elf_Scn *scn)
+{
+  if (scn == NULL)
+    return SHN_UNDEF;
+
+  return scn->index;
+}
diff --git a/libelf/elf_newdata.c b/libelf/elf_newdata.c
new file mode 100644
index 0000000..0063d59
--- /dev/null
+++ b/libelf/elf_newdata.c
@@ -0,0 +1,136 @@
+/* Create new, empty section data.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+Elf_Data *
+elf_newdata (Elf_Scn *scn)
+{
+  Elf_Data_List *result = NULL;
+
+  if (scn == NULL)
+    return NULL;
+
+  if (unlikely (scn->index == 0))
+    {
+      /* It is not allowed to add something to the 0th section.  */
+      __libelf_seterrno (ELF_E_NOT_NUL_SECTION);
+      return NULL;
+    }
+
+  if (scn->elf->class == ELFCLASS32
+      || (offsetof (struct Elf, state.elf32.ehdr)
+	  == offsetof (struct Elf, state.elf64.ehdr))
+      ? scn->elf->state.elf32.ehdr == NULL
+      : scn->elf->state.elf64.ehdr == NULL)
+    {
+      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+      return NULL;
+    }
+
+  rwlock_wrlock (scn->elf->lock);
+
+  /* data_read is set when data has been read from the ELF image or
+     when a new section has been created by elf_newscn.  If data has
+     been read from the ELF image, then rawdata_base will point to raw
+     data.  If data_read has been set by elf_newscn, then rawdata_base
+     will be NULL.  data_list_rear will be set by elf_getdata if the
+     data has been converted, or by this function, elf_newdata, when
+     new data has been added.
+
+     Currently elf_getdata and elf_update rely on the fact that when
+     data_list_read is not NULL all they have to do is walk the data
+     list. They will ignore any (unread) raw data in that case.
+
+     So we need to make sure the data list is setup if there is
+     already data available.  */
+  if (scn->data_read
+      && scn->rawdata_base != NULL
+      && scn->data_list_rear == NULL)
+    __libelf_set_data_list_rdlock (scn, 1);
+
+  if (scn->data_read && scn->data_list_rear == NULL)
+    {
+      /* This means the section was created by the user and this is the
+	 first data.  */
+      result = &scn->data_list;
+      result->flags = ELF_F_DIRTY;
+    }
+  else
+    {
+      /* It would be more efficient to create new data without
+	 reading/converting the data from the file.  But then we
+	 have to remember this.  Currently elf_getdata and
+	 elf_update rely on the fact that they don't have to
+	 load/convert any data if data_list_rear is set.  */
+      if (scn->data_read == 0)
+	{
+	  if (__libelf_set_rawdata_wrlock (scn) != 0)
+	    /* Something went wrong.  The error value is already set.  */
+	    goto out;
+	  __libelf_set_data_list_rdlock (scn, 1);
+	}
+
+      /* Create a new, empty data descriptor.  */
+      result = calloc (1, sizeof (Elf_Data_List));
+      if (result == NULL)
+	{
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  goto out;
+	}
+
+      result->flags = ELF_F_DIRTY | ELF_F_MALLOCED;
+    }
+
+  /* Set the predefined values.  */
+  result->data.d.d_version = EV_CURRENT;
+
+  result->data.s = scn;
+
+  /* Add to the end of the list.  */
+  if (scn->data_list_rear != NULL)
+    scn->data_list_rear->next = result;
+
+  scn->data_list_rear = result;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  /* Please note that the following is thread safe and is also defined
+     for RESULT == NULL since it still return NULL.  */
+  return &result->data.d;
+}
diff --git a/libelf/elf_newscn.c b/libelf/elf_newscn.c
new file mode 100644
index 0000000..ec731f7
--- /dev/null
+++ b/libelf/elf_newscn.c
@@ -0,0 +1,162 @@
+/* Append new section.
+   Copyright (C) 1998,1999,2000,2001,2002,2005,2009,2014,2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+Elf_Scn *
+elf_newscn (Elf *elf)
+{
+  Elf_Scn *result = NULL;
+  bool first = false;
+
+  if (elf == NULL)
+    return NULL;
+
+  /* We rely on the prefix of the `elf', `elf32', and `elf64' element
+     being the same.  */
+  assert (offsetof (Elf, state.elf.scns_last)
+	  == offsetof (Elf, state.elf32.scns_last));
+  assert (offsetof (Elf, state.elf.scns_last)
+	  == offsetof (Elf, state.elf64.scns_last));
+  assert (offsetof (Elf, state.elf32.scns)
+	  == offsetof (Elf, state.elf64.scns));
+
+  rwlock_wrlock (elf->lock);
+
+ again:
+  if (elf->state.elf.scns_last->cnt < elf->state.elf.scns_last->max)
+    {
+      result = &elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt];
+
+      if (++elf->state.elf.scns_last->cnt == 1
+	  && (elf->state.elf.scns_last
+	      == (elf->class == ELFCLASS32
+		  || (offsetof (Elf, state.elf32.scns)
+		      == offsetof (Elf, state.elf64.scns))
+		  ? &elf->state.elf32.scns : &elf->state.elf64.scns)))
+	/* This is zeroth section.  */
+	first = true;
+      else
+	{
+	  assert (elf->state.elf.scns_last->cnt > 1);
+	  result->index = result[-1].index + 1;
+	}
+    }
+  else
+    {
+      /* We must allocate a new element.  */
+      Elf_ScnList *newp = NULL;
+
+      assert (elf->state.elf.scnincr > 0);
+
+      if (
+#if SIZE_MAX <= 4294967295U
+	  likely (elf->state.elf.scnincr
+		  < SIZE_MAX / 2 / sizeof (Elf_Scn) - sizeof (Elf_ScnList))
+#else
+	  1
+#endif
+	  )
+      newp = calloc (1, sizeof (Elf_ScnList)
+			+ ((elf->state.elf.scnincr *= 2)
+			   * sizeof (Elf_Scn)));
+      if (newp == NULL)
+	{
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  goto out;
+	}
+
+      result = &newp->data[0];
+
+      /* One section used.  */
+      ++newp->cnt;
+
+      /* This is the number of sections we allocated.  */
+      newp->max = elf->state.elf.scnincr;
+
+      /* Remember the index for the first section in this block.  */
+      newp->data[0].index
+	= 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->max - 1].index;
+
+      /* Enqueue the new list element.  */
+      elf->state.elf.scns_last = elf->state.elf.scns_last->next = newp;
+    }
+
+  /* Create a section header for this section.  */
+  if (elf->class == ELFCLASS32)
+    {
+      result->shdr.e32 = calloc (1, sizeof (Elf32_Shdr));
+      if (result->shdr.e32 == NULL)
+	{
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  goto out;
+	}
+    }
+  else
+    {
+      result->shdr.e64 = calloc (1, sizeof (Elf64_Shdr));
+      if (result->shdr.e64 == NULL)
+	{
+	  __libelf_seterrno (ELF_E_NOMEM);
+	  goto out;
+	}
+    }
+
+  result->elf = elf;
+  result->shdr_flags = ELF_F_DIRTY | ELF_F_MALLOCED;
+  result->list = elf->state.elf.scns_last;
+
+  /* Initialize the data part.  */
+  result->data_read = 1;
+  if (unlikely (first))
+    {
+      /* For the first section we mark the data as already available.  */
+      //result->data_list_rear = &result->data_list;
+      first = false;
+      goto again;
+    }
+
+  result->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/elf_next.c b/libelf/elf_next.c
new file mode 100644
index 0000000..6edafd2
--- /dev/null
+++ b/libelf/elf_next.c
@@ -0,0 +1,72 @@
+/* Advance in archive to next element.
+   Copyright (C) 1998-2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf_Cmd
+elf_next (Elf *elf)
+{
+  Elf *parent;
+  Elf_Cmd ret;
+
+  /* Be gratious, the specs demand it.  */
+  if (elf == NULL || elf->parent == NULL)
+    return ELF_C_NULL;
+
+  /* We can be sure the parent is an archive.  */
+  parent = elf->parent;
+  assert (parent->kind == ELF_K_AR);
+
+  rwlock_wrlock (parent->lock);
+
+  /* Now advance the offset.  */
+  parent->state.ar.offset += (sizeof (struct ar_hdr)
+			      + ((parent->state.ar.elf_ar_hdr.ar_size + 1)
+				 & ~1l));
+
+  /* Get the next archive header.  */
+  ret = __libelf_next_arhdr_wrlock (parent) != 0 ? ELF_C_NULL : elf->cmd;
+
+  /* If necessary, mark the archive header as unusable.  */
+  if (ret == ELF_C_NULL)
+    parent->state.ar.elf_ar_hdr.ar_name = NULL;
+
+  rwlock_unlock (parent->lock);
+
+  return ret;
+}
diff --git a/libelf/elf_nextscn.c b/libelf/elf_nextscn.c
new file mode 100644
index 0000000..d2f3e7c
--- /dev/null
+++ b/libelf/elf_nextscn.c
@@ -0,0 +1,83 @@
+/* Get next section.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf_Scn *
+elf_nextscn (Elf *elf, Elf_Scn *scn)
+{
+  Elf_ScnList *list;
+  Elf_Scn *result = NULL;
+
+  if (elf == NULL)
+    return NULL;
+
+  rwlock_rdlock (elf->lock);
+
+  if (scn == NULL)
+    {
+      /* If no section handle is given return the first (not 0th) section.
+	 Set scn to the 0th section and perform nextscn.  */
+      if (elf->class == ELFCLASS32
+	   || (offsetof (Elf, state.elf32.scns)
+	       == offsetof (Elf, state.elf64.scns)))
+	list = &elf->state.elf32.scns;
+      else
+	list = &elf->state.elf64.scns;
+
+      scn = &list->data[0];
+    }
+  else
+    list = scn->list;
+
+  if (scn + 1 < &list->data[list->cnt])
+    result = scn + 1;
+  else if (scn + 1 == &list->data[list->max]
+	   && (list = list->next) != NULL)
+    {
+      /* If there is another element in the section list it must
+         have at least one entry.  */
+      assert (list->cnt > 0);
+      result = &list->data[0];
+    }
+
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elf_nextscn)
diff --git a/libelf/elf_rand.c b/libelf/elf_rand.c
new file mode 100644
index 0000000..f1850e7
--- /dev/null
+++ b/libelf/elf_rand.c
@@ -0,0 +1,63 @@
+/* Select specific element in archive.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+size_t
+elf_rand (Elf *elf, size_t offset)
+{
+  /* Be gratious, the specs demand it.  */
+  if (elf == NULL || elf->kind != ELF_K_AR)
+    return 0;
+
+  rwlock_wrlock (elf->lock);
+
+  /* Save the old offset and set the offset.  */
+  elf->state.ar.offset = elf->start_offset + offset;
+
+  /* Get the next archive header.  */
+  if (__libelf_next_arhdr_wrlock (elf) != 0)
+    {
+      /* Mark the archive header as unusable.  */
+      elf->state.ar.elf_ar_hdr.ar_name = NULL;
+      return 0;
+    }
+
+  rwlock_unlock (elf->lock);
+
+  return offset;
+}
diff --git a/libelf/elf_rawdata.c b/libelf/elf_rawdata.c
new file mode 100644
index 0000000..db28f5d
--- /dev/null
+++ b/libelf/elf_rawdata.c
@@ -0,0 +1,76 @@
+/* Return raw section content.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+Elf_Data *
+elf_rawdata (Elf_Scn *scn, Elf_Data *data)
+{
+  if (scn == NULL || scn->elf->kind != ELF_K_ELF)
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* If `data' is not NULL this means we are not addressing the initial
+     data in the file.  But this also means this data is already read
+     (since otherwise it is not possible to have a valid `data' pointer)
+     and all the data structures are initialized as well.  In this case
+     we can simply walk the list of data records.  */
+  if (data != NULL
+      || (scn->data_read != 0 && (scn->flags & ELF_F_FILEDATA) == 0))
+    {
+      /* We don't allow accessing any but the data read from the file
+	 as raw.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return NULL;
+    }
+
+  /* If the data for this section was not yet initialized do it now.  */
+  if (scn->data_read == 0)
+    {
+      /* First thing we do is to read the data from the file.  There is
+	 always a file (or memory region) associated with this descriptor
+	 since otherwise the `data_read' flag would be set.  */
+      if (__libelf_set_rawdata (scn) != 0)
+	/* Something went wrong.  The error value is already set.  */
+	return NULL;
+    }
+
+  /* Return the first data element in the list.  */
+  return &scn->rawdata.d;
+}
+INTDEF(elf_rawdata)
diff --git a/libelf/elf_rawfile.c b/libelf/elf_rawfile.c
new file mode 100644
index 0000000..b3837f4
--- /dev/null
+++ b/libelf/elf_rawfile.c
@@ -0,0 +1,67 @@
+/* Retrieve uninterpreted file contents.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+char *
+elf_rawfile (Elf *elf, size_t *ptr)
+{
+  char *result;
+
+  if (elf == NULL)
+    {
+      /* No valid descriptor.  */
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+    error_out:
+      if (ptr != NULL)
+	*ptr = 0;
+      return NULL;
+    }
+
+  /* If the file is not mmap'ed and not previously loaded, do it now.  */
+  if (elf->map_address == NULL && __libelf_readall (elf) == NULL)
+    goto error_out;
+
+  rwlock_rdlock (elf->lock);
+  if (ptr != NULL)
+    *ptr = elf->maximum_size;
+
+  result = (char *) elf->map_address + elf->start_offset;
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/elf_readall.c b/libelf/elf_readall.c
new file mode 100644
index 0000000..d0f9a28
--- /dev/null
+++ b/libelf/elf_readall.c
@@ -0,0 +1,150 @@
+/* Read all of the file associated with the descriptor.
+   Copyright (C) 1998-2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <sys/stat.h>
+
+#include "libelfP.h"
+#include "common.h"
+
+
+static void
+set_address (Elf *elf, size_t offset)
+{
+  if (elf->kind == ELF_K_AR)
+    {
+      Elf *child = elf->state.ar.children;
+
+      while (child != NULL)
+	{
+	  if (child->map_address == NULL)
+	    {
+	      child->map_address = elf->map_address;
+	      child->start_offset -= offset;
+	      if (child->kind == ELF_K_AR)
+		child->state.ar.offset -= offset;
+
+	      set_address (child, offset);
+	    }
+
+	  child = child->next;
+	}
+    }
+}
+
+
+char *
+internal_function
+__libelf_readall (Elf *elf)
+{
+  /* Get the file.  */
+  rwlock_wrlock (elf->lock);
+
+  if (elf->map_address == NULL && unlikely (elf->fildes == -1))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      rwlock_unlock (elf->lock);
+      return NULL;
+    }
+
+  /* If the file is not mmap'ed and not previously loaded, do it now.  */
+  if (elf->map_address == NULL)
+    {
+      char *mem = NULL;
+
+      /* If this is an archive and we have derived descriptors get the
+	 locks for all of them.  */
+      libelf_acquire_all (elf);
+
+      if (elf->maximum_size == ~((size_t) 0))
+	{
+	  /* We don't yet know how large the file is.   Determine that now.  */
+	  struct stat st;
+
+	  if (fstat (elf->fildes, &st) < 0)
+	    goto read_error;
+
+	  if (sizeof (size_t) >= sizeof (st.st_size)
+	      || st.st_size <= ~((size_t) 0))
+	    elf->maximum_size = (size_t) st.st_size;
+	  else
+	    {
+	      errno = EOVERFLOW;
+	      goto read_error;
+	    }
+	}
+
+      /* Allocate all the memory we need.  */
+      mem = malloc (elf->maximum_size);
+      if (mem != NULL)
+	{
+	  /* Read the file content.  */
+	  if (unlikely ((size_t) pread_retry (elf->fildes, mem,
+					      elf->maximum_size,
+					      elf->start_offset)
+			!= elf->maximum_size))
+	    {
+	      /* Something went wrong.  */
+	    read_error:
+	      __libelf_seterrno (ELF_E_READ_ERROR);
+	      free (mem);
+	    }
+	  else
+	    {
+	      /* Remember the address.  */
+	      elf->map_address = mem;
+
+	      /* Also remember that we allocated the memory.  */
+	      elf->flags |= ELF_F_MALLOCED;
+
+	      /* Propagate the information down to all children and
+		 their children.  */
+	      set_address (elf, elf->start_offset);
+
+	      /* Correct the own offsets.  */
+	      if (elf->kind == ELF_K_AR)
+		elf->state.ar.offset -= elf->start_offset;
+	      elf->start_offset = 0;
+	    }
+	}
+      else
+	__libelf_seterrno (ELF_E_NOMEM);
+
+      /* Free the locks on the children.  */
+      libelf_release_all (elf);
+    }
+
+  rwlock_unlock (elf->lock);
+
+  return (char *) elf->map_address;
+}
diff --git a/libelf/elf_scnshndx.c b/libelf/elf_scnshndx.c
new file mode 100644
index 0000000..5b783fa
--- /dev/null
+++ b/libelf/elf_scnshndx.c
@@ -0,0 +1,50 @@
+/* Get the section index of the extended section index table.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libelfP.h"
+
+
+int
+elf_scnshndx (Elf_Scn *scn)
+{
+  if (unlikely (scn->shndx_index == 0))
+    {
+      /* We do not have the value yet.  We get it as a side effect of
+	 getting a section header.  */
+      GElf_Shdr shdr_mem;
+      (void) INTUSE(gelf_getshdr) (scn, &shdr_mem);
+    }
+
+  return scn->shndx_index;
+}
+INTDEF(elf_scnshndx)
diff --git a/libelf/elf_strptr.c b/libelf/elf_strptr.c
new file mode 100644
index 0000000..79a24d2
--- /dev/null
+++ b/libelf/elf_strptr.c
@@ -0,0 +1,242 @@
+/* Return string pointer from string section.
+   Copyright (C) 1998-2002, 2004, 2008, 2009, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+static void *
+get_zdata (Elf_Scn *strscn)
+{
+  size_t zsize, zalign;
+  void *zdata = __libelf_decompress_elf (strscn, &zsize, &zalign);
+  if (zdata == NULL)
+    return NULL;
+
+  strscn->zdata_base = zdata;
+  strscn->zdata_size = zsize;
+  strscn->zdata_align = zalign;
+
+  return zdata;
+}
+
+static bool validate_str (const char *str, size_t from, size_t to)
+{
+#if HAVE_DECL_MEMRCHR
+  // Check end first, which is likely a zero terminator, to prevent function call
+  return ((to > 0 && str[to - 1]  == '\0')
+	  || (to - from > 0 && memrchr (&str[from], '\0', to - from - 1) != NULL));
+#else
+  do {
+    if (to <= from)
+      return false;
+
+    to--;
+  } while (str[to]);
+
+  return true;
+#endif
+}
+
+char *
+elf_strptr (Elf *elf, size_t idx, size_t offset)
+{
+  if (elf == NULL)
+    return NULL;
+
+  if (elf->kind != ELF_K_ELF)
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  rwlock_rdlock (elf->lock);
+
+  char *result = NULL;
+  Elf_Scn *strscn;
+
+  /* Find the section in the list.  */
+  Elf_ScnList *runp = (elf->class == ELFCLASS32
+		       || (offsetof (struct Elf, state.elf32.scns)
+			   == offsetof (struct Elf, state.elf64.scns))
+		       ? &elf->state.elf32.scns : &elf->state.elf64.scns);
+  while (1)
+    {
+      if (idx < runp->max)
+	{
+	  if (idx < runp->cnt)
+	    strscn = &runp->data[idx];
+	  else
+	    {
+	      __libelf_seterrno (ELF_E_INVALID_INDEX);
+	      goto out;
+	    }
+	  break;
+	}
+
+      idx -= runp->max;
+
+      runp = runp->next;
+      if (runp == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+    }
+
+  size_t sh_size = 0;
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_Shdr *shdr = strscn->shdr.e32 ?: __elf32_getshdr_rdlock (strscn);
+      if (unlikely (shdr == NULL || shdr->sh_type != SHT_STRTAB))
+	{
+	  /* This is no string section.  */
+	  __libelf_seterrno (ELF_E_INVALID_SECTION);
+	  goto out;
+	}
+
+      if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
+	sh_size = shdr->sh_size;
+      else
+	{
+	  if (strscn->zdata_base == NULL && get_zdata (strscn) == NULL)
+	    goto out;
+	  sh_size = strscn->zdata_size;
+	}
+
+      if (unlikely (offset >= sh_size))
+	{
+	  /* The given offset is too big, it is beyond this section.  */
+	  __libelf_seterrno (ELF_E_OFFSET_RANGE);
+	  goto out;
+	}
+    }
+  else
+    {
+      Elf64_Shdr *shdr = strscn->shdr.e64 ?: __elf64_getshdr_rdlock (strscn);
+      if (unlikely (shdr == NULL || shdr->sh_type != SHT_STRTAB))
+	{
+	  /* This is no string section.  */
+	  __libelf_seterrno (ELF_E_INVALID_SECTION);
+	  goto out;
+	}
+
+      if ((shdr->sh_flags & SHF_COMPRESSED) == 0)
+	sh_size = shdr->sh_size;
+      else
+	{
+	  if (strscn->zdata_base == NULL && get_zdata (strscn) == NULL)
+	    goto out;
+	  sh_size = strscn->zdata_size;
+	}
+
+      if (unlikely (offset >= sh_size))
+	{
+	  /* The given offset is too big, it is beyond this section.  */
+	  __libelf_seterrno (ELF_E_OFFSET_RANGE);
+	  goto out;
+	}
+    }
+
+  if (strscn->rawdata_base == NULL && ! strscn->data_read)
+    {
+      rwlock_unlock (elf->lock);
+      rwlock_wrlock (elf->lock);
+      if (strscn->rawdata_base == NULL && ! strscn->data_read
+	/* Read the section data.  */
+	  && __libelf_set_rawdata_wrlock (strscn) != 0)
+	goto out;
+    }
+
+  if (unlikely (strscn->zdata_base != NULL))
+    {
+      /* Make sure the string is NUL terminated.  Start from the end,
+         which very likely is a NUL char.  */
+      if (likely (validate_str (strscn->zdata_base, offset, sh_size)))
+        result = &strscn->zdata_base[offset];
+      else
+        __libelf_seterrno (ELF_E_INVALID_INDEX);
+    }
+  else if (likely (strscn->data_list_rear == NULL))
+    {
+      // XXX The above is currently correct since elf_newdata will
+      // make sure to convert the rawdata into the datalist if
+      // necessary. But it would be more efficient to keep the rawdata
+      // unconverted and only then iterate over the rest of the (newly
+      // added data) list.  Note that when the ELF file is mmapped
+      // rawdata_base can be set while rawdata.d hasn't been
+      // initialized yet (when data_read is zero). So we cannot just
+      // look at the rawdata.d.d_size.
+
+      /* Make sure the string is NUL terminated.  Start from the end,
+	 which very likely is a NUL char.  */
+      if (likely (validate_str (strscn->rawdata_base, offset, sh_size)))
+	result = &strscn->rawdata_base[offset];
+      else
+	__libelf_seterrno (ELF_E_INVALID_INDEX);
+    }
+  else
+    {
+      /* This is a file which is currently created.  Use the list of
+	 data blocks.  */
+      struct Elf_Data_List *dl = &strscn->data_list;
+      while (dl != NULL)
+	{
+	  if (offset >= (size_t) dl->data.d.d_off
+	      && offset < dl->data.d.d_off + dl->data.d.d_size)
+	    {
+	      /* Make sure the string is NUL terminated.  Start from
+		 the end, which very likely is a NUL char.  */
+	      if (likely (validate_str ((char *) dl->data.d.d_buf,
+					offset - dl->data.d.d_off,
+					dl->data.d.d_size)))
+		result = ((char *) dl->data.d.d_buf
+			  + (offset - dl->data.d.d_off));
+	      else
+		__libelf_seterrno (ELF_E_INVALID_INDEX);
+	      break;
+	    }
+
+	  dl = dl->next;
+	}
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
+INTDEF(elf_strptr)
diff --git a/libelf/elf_update.c b/libelf/elf_update.c
new file mode 100644
index 0000000..56af3a1
--- /dev/null
+++ b/libelf/elf_update.c
@@ -0,0 +1,238 @@
+/* Update data structures for changes and write them out.
+   Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#include "libelfP.h"
+
+
+static int64_t
+write_file (Elf *elf, int64_t size, int change_bo, size_t shnum)
+{
+  int class = elf->class;
+
+  /* Check the mode bits now, before modification might change them.  */
+  struct stat st;
+  if (unlikely (fstat (elf->fildes, &st) != 0))
+    {
+      __libelf_seterrno (ELF_E_WRITE_ERROR);
+      return -1;
+    }
+
+  /* Adjust the size in any case.  We do this even if we use `write'.
+     We cannot do this if this file is in an archive.  We also don't
+     do it *now* if we are shortening the file since this would
+     prevent programs to use the data of the file in generating the
+     new file.  We truncate the file later in this case.  */
+  if (elf->parent == NULL
+      && (elf->maximum_size == ~((size_t) 0)
+	  || (size_t) size > elf->maximum_size)
+      && unlikely (ftruncate (elf->fildes, size) != 0))
+    {
+      __libelf_seterrno (ELF_E_WRITE_ERROR);
+      return -1;
+    }
+
+  /* Try to map the file if this isn't done yet.  */
+  if (elf->map_address == NULL && elf->cmd == ELF_C_WRITE_MMAP)
+    {
+      elf->map_address = mmap (NULL, size, PROT_READ | PROT_WRITE,
+			       MAP_SHARED, elf->fildes, 0);
+      if (unlikely (elf->map_address == MAP_FAILED))
+	elf->map_address = NULL;
+      else
+	elf->flags |= ELF_F_MMAPPED;
+    }
+
+  if (elf->map_address != NULL)
+    {
+      /* When using mmap we want to make sure the file content is
+	 really there. Only using ftruncate might mean the file is
+	 extended, but space isn't allocated yet.  This might cause a
+	 SIGBUS once we write into the mmapped space and the disk is
+	 full.  In glibc posix_fallocate is required to extend the
+	 file and allocate enough space even if the underlying
+	 filesystem would normally return EOPNOTSUPP.  But other
+	 implementations might not work as expected.  And the glibc
+	 fallback case might fail (with unexpected errnos) in some cases.
+	 So we only report an error when the call fails and errno is
+	 ENOSPC. Otherwise we ignore the error and treat it as just hint.  */
+      if (elf->parent == NULL
+	  && (elf->maximum_size == ~((size_t) 0)
+	      || (size_t) size > elf->maximum_size))
+	{
+	  if (unlikely (posix_fallocate (elf->fildes, 0, size) != 0))
+	    if (errno == ENOSPC)
+	      {
+		__libelf_seterrno (ELF_E_WRITE_ERROR);
+		return -1;
+	      }
+
+	  /* Extend the mmap address if needed.  */
+	  if (elf->cmd == ELF_C_RDWR_MMAP
+	      && (size_t) size > elf->maximum_size)
+	    {
+#ifdef HAVE_MREMAP
+	      if (mremap (elf->map_address, elf->maximum_size,
+			  size, 0) == MAP_FAILED)
+#endif
+		{
+		  __libelf_seterrno (ELF_E_WRITE_ERROR);
+		  return -1;
+		}
+	      elf->maximum_size = size;
+	    }
+
+	}
+
+      /* The file is mmaped.  */
+      if ((class == ELFCLASS32
+	   ? __elf32_updatemmap (elf, change_bo, shnum)
+	   : __elf64_updatemmap (elf, change_bo, shnum)) != 0)
+	/* Some problem while writing.  */
+	size = -1;
+    }
+  else
+    {
+      /* The file is not mmaped.  */
+      if ((class == ELFCLASS32
+	   ? __elf32_updatefile (elf, change_bo, shnum)
+	   : __elf64_updatefile (elf, change_bo, shnum)) != 0)
+	/* Some problem while writing.  */
+	size = -1;
+    }
+
+  /* Reduce the file size if necessary.  */
+  if (size != -1
+      && elf->parent == NULL
+      && elf->maximum_size != ~((size_t) 0)
+      && (size_t) size < elf->maximum_size
+      && unlikely (ftruncate (elf->fildes, size) != 0))
+    {
+      __libelf_seterrno (ELF_E_WRITE_ERROR);
+      size = -1;
+    }
+
+  /* POSIX says that ftruncate and write may clear the S_ISUID and S_ISGID
+     mode bits.  So make sure we restore them afterwards if they were set.
+     This is not atomic if someone else chmod's the file while we operate.  */
+  if (size != -1
+      && unlikely (st.st_mode & (S_ISUID | S_ISGID))
+      /* fchmod ignores the bits we cannot change.  */
+      && unlikely (fchmod (elf->fildes, st.st_mode) != 0))
+    {
+      __libelf_seterrno (ELF_E_WRITE_ERROR);
+      size = -1;
+    }
+
+  if (size != -1 && elf->parent == NULL)
+    elf->maximum_size = size;
+
+  return size;
+}
+
+
+int64_t
+elf_update (Elf *elf, Elf_Cmd cmd)
+{
+  size_t shnum;
+  int64_t size;
+  int change_bo = 0;
+
+  if (cmd != ELF_C_NULL
+      && cmd != ELF_C_WRITE
+      && unlikely (cmd != ELF_C_WRITE_MMAP))
+    {
+      __libelf_seterrno (ELF_E_INVALID_CMD);
+      return -1;
+    }
+
+  if (elf == NULL)
+    return -1;
+
+  if (elf->kind != ELF_K_ELF)
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return -1;
+    }
+
+  rwlock_wrlock (elf->lock);
+
+  /* Make sure we have an ELF header.  */
+  if (elf->state.elf.ehdr == NULL)
+    {
+      __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+      size = -1;
+      goto out;
+    }
+
+  /* Determine the number of sections.  */
+  shnum = (elf->state.elf.scns_last->cnt == 0
+	   ? 0
+	   : 1 + elf->state.elf.scns_last->data[elf->state.elf.scns_last->cnt - 1].index);
+
+  /* Update the ELF descriptor.  First, place the program header.  It
+     will come right after the ELF header.  The count the size of all
+     sections and finally place the section table.  */
+  size = (elf->class == ELFCLASS32
+	  ? __elf32_updatenull_wrlock (elf, &change_bo, shnum)
+	  : __elf64_updatenull_wrlock (elf, &change_bo, shnum));
+  if (likely (size != -1)
+      /* See whether we actually have to write out the data.  */
+      && (cmd == ELF_C_WRITE || cmd == ELF_C_WRITE_MMAP))
+    {
+      if (elf->cmd != ELF_C_RDWR
+	  && elf->cmd != ELF_C_RDWR_MMAP
+	  && elf->cmd != ELF_C_WRITE
+	  && unlikely (elf->cmd != ELF_C_WRITE_MMAP))
+	{
+	  __libelf_seterrno (ELF_E_UPDATE_RO);
+	  size = -1;
+	}
+      else if (unlikely (elf->fildes == -1))
+	{
+	  /* We closed the file already.  */
+	  __libelf_seterrno (ELF_E_FD_DISABLED);
+	  size = -1;
+	}
+      else
+	size = write_file (elf, size, change_bo, shnum);
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return size;
+}
diff --git a/libelf/elf_version.c b/libelf/elf_version.c
new file mode 100644
index 0000000..8296bb6
--- /dev/null
+++ b/libelf/elf_version.c
@@ -0,0 +1,71 @@
+/* Coordinate ELF library and application versions.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelfP.h>
+#include <pthread.h>
+
+/* Multiple threads may initialize __libelf_version.
+   pthread_once() ensures that __libelf_version is initialized only once. */
+once_define(static, version_once);
+
+/* Currently selected version.  Should be EV_CURRENT.
+   Will be EV_NONE if elf_version () has not been called yet.  */
+unsigned int __libelf_version = EV_NONE;
+
+static void initialize_version(void)
+{
+  __libelf_version = EV_CURRENT;
+}
+
+unsigned int
+elf_version (unsigned int version)
+{
+  if (version == EV_NONE)
+    return EV_CURRENT;
+
+  if (likely (version == EV_CURRENT))
+    {
+      /* Phew, we know this version.  */
+
+      /* Signal that the version is now initialized.  */
+      once(version_once, initialize_version);
+
+      /* And return the last (or initial) version.  */
+      return EV_CURRENT;
+    }
+
+  /* We cannot handle this version.  */
+  __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
+  return EV_NONE;
+}
+INTDEF(elf_version)
diff --git a/libelf/exttypes.h b/libelf/exttypes.h
new file mode 100644
index 0000000..7bacd65
--- /dev/null
+++ b/libelf/exttypes.h
@@ -0,0 +1,104 @@
+/* External ELF types.
+   Copyright (C) 1998-2010, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _EXTTYPES_H
+#define	_EXTTYPES_H 1
+
+/* Integral types.  */
+typedef char Elf32_Ext_Addr[ELF32_FSZ_ADDR];
+typedef char Elf32_Ext_Off[ELF32_FSZ_OFF];
+typedef char Elf32_Ext_Half[ELF32_FSZ_HALF];
+typedef char Elf32_Ext_Sword[ELF32_FSZ_SWORD];
+typedef char Elf32_Ext_Word[ELF32_FSZ_WORD];
+typedef char Elf32_Ext_Sxword[ELF32_FSZ_SXWORD];
+typedef char Elf32_Ext_Xword[ELF32_FSZ_XWORD];
+
+typedef char Elf64_Ext_Addr[ELF64_FSZ_ADDR];
+typedef char Elf64_Ext_Off[ELF64_FSZ_OFF];
+typedef char Elf64_Ext_Half[ELF64_FSZ_HALF];
+typedef char Elf64_Ext_Sword[ELF64_FSZ_SWORD];
+typedef char Elf64_Ext_Word[ELF64_FSZ_WORD];
+typedef char Elf64_Ext_Sxword[ELF64_FSZ_SXWORD];
+typedef char Elf64_Ext_Xword[ELF64_FSZ_XWORD];
+
+
+/* Define the composed types.  */
+#define START(Bits, Name, EName) typedef struct {
+#define END(Bits, Name) } ElfW2(Bits, Name)
+#define TYPE_NAME(Type, Name) Type Name;
+#define TYPE_EXTRA(Text) Text
+#define TYPE_XLATE(Text)
+
+/* Get the abstract definitions. */
+#include "abstract.h"
+
+/* And define the types.  */
+Ehdr32 (Ext_);
+Phdr32 (Ext_);
+Shdr32 (Ext_);
+Sym32 (Ext_);
+Rel32 (Ext_);
+Rela32 (Ext_);
+Note32 (Ext_);
+Dyn32 (Ext_);
+Verdef32 (Ext_);
+Verdaux32 (Ext_);
+Verneed32 (Ext_);
+Vernaux32 (Ext_);
+Syminfo32 (Ext_);
+Move32 (Ext_);
+Lib32 (Ext_);
+auxv_t32 (Ext_);
+Chdr32 (Ext_);
+
+Ehdr64 (Ext_);
+Phdr64 (Ext_);
+Shdr64 (Ext_);
+Sym64 (Ext_);
+Rel64 (Ext_);
+Rela64 (Ext_);
+Note64 (Ext_);
+Dyn64 (Ext_);
+Verdef64 (Ext_);
+Verdaux64 (Ext_);
+Verneed64 (Ext_);
+Vernaux64 (Ext_);
+Syminfo64 (Ext_);
+Move64 (Ext_);
+Lib64 (Ext_);
+auxv_t64 (Ext_);
+Chdr64 (Ext_);
+
+#undef START
+#undef END
+#undef TYPE_NAME
+#undef TYPE_EXTRA
+#undef TYPE_XLATE
+
+#endif	/* exttypes.h */
diff --git a/libelf/gelf.h b/libelf/gelf.h
new file mode 100644
index 0000000..1847021
--- /dev/null
+++ b/libelf/gelf.h
@@ -0,0 +1,345 @@
+/* This file defines generic ELF types, structures, and macros.
+   Copyright (C) 1999, 2000, 2001, 2002, 2004, 2005, 2007, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _GELF_H
+#define	_GELF_H 1
+
+#include <libelf.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Class independent type definitions.  Correctly speaking this is not
+   true.  We assume that 64-bit binaries are the largest class and
+   therefore all other classes can be represented without loss.  */
+
+/* Type for a 16-bit quantity.  */
+typedef Elf64_Half GElf_Half;
+
+/* Types for signed and unsigned 32-bit quantities.  */
+typedef Elf64_Word GElf_Word;
+typedef	Elf64_Sword GElf_Sword;
+
+/* Types for signed and unsigned 64-bit quantities.  */
+typedef Elf64_Xword GElf_Xword;
+typedef	Elf64_Sxword GElf_Sxword;
+
+/* Type of addresses.  */
+typedef Elf64_Addr GElf_Addr;
+
+/* Type of file offsets.  */
+typedef Elf64_Off GElf_Off;
+
+
+/* The ELF file header.  This appears at the start of every ELF file.  */
+typedef Elf64_Ehdr GElf_Ehdr;
+
+/* Section header.  */
+typedef Elf64_Shdr GElf_Shdr;
+
+/* Section index.  */
+/* XXX This should probably be a larger type in preparation of times when
+   regular section indices can be larger.  */
+typedef Elf64_Section GElf_Section;
+
+/* Symbol table entry.  */
+typedef Elf64_Sym GElf_Sym;
+
+/* The syminfo section if available contains additional information about
+   every dynamic symbol.  */
+typedef Elf64_Syminfo GElf_Syminfo;
+
+/* Relocation table entry without addend (in section of type SHT_REL).  */
+typedef Elf64_Rel GElf_Rel;
+
+/* Relocation table entry with addend (in section of type SHT_RELA).  */
+typedef Elf64_Rela GElf_Rela;
+
+/* Relative relocation entry (in section of type SHT_RELR).  */
+typedef Elf64_Relr GElf_Relr;
+
+/* Program segment header.  */
+typedef Elf64_Phdr GElf_Phdr;
+
+/* Header of a compressed section.  */
+typedef Elf64_Chdr GElf_Chdr;
+
+/* Dynamic section entry.  */
+typedef Elf64_Dyn GElf_Dyn;
+
+
+/* Version definition sections.  */
+typedef Elf64_Verdef GElf_Verdef;
+
+/* Auxiliary version information.  */
+typedef Elf64_Verdaux GElf_Verdaux;
+
+/* Version dependency section.  */
+typedef Elf64_Verneed GElf_Verneed;
+
+/* Auxiliary needed version information.  */
+typedef Elf64_Vernaux GElf_Vernaux;
+
+
+/* Type for version symbol information.  */
+typedef Elf64_Versym GElf_Versym;
+
+
+/* Auxiliary vector.  */
+typedef Elf64_auxv_t GElf_auxv_t;
+
+
+/* Note section contents.  */
+typedef Elf64_Nhdr GElf_Nhdr;
+
+
+/* Move structure.  */
+typedef Elf64_Move GElf_Move;
+
+
+/* Library list structure.  */
+typedef Elf64_Lib GElf_Lib;
+
+
+/* How to extract and insert information held in the st_info field.  */
+
+#define GELF_ST_BIND(val)		ELF64_ST_BIND (val)
+#define GELF_ST_TYPE(val)		ELF64_ST_TYPE (val)
+#define GELF_ST_INFO(bind, type)	ELF64_ST_INFO (bind, type)
+
+/* How to extract information held in the st_other field.  */
+
+#define GELF_ST_VISIBILITY(val)		ELF64_ST_VISIBILITY (val)
+
+
+/* How to extract and insert information held in the r_info field.  */
+
+#define GELF_R_SYM(info)		ELF64_R_SYM (info)
+#define GELF_R_TYPE(info)		ELF64_R_TYPE (info)
+#define GELF_R_INFO(sym, type)		ELF64_R_INFO (sym, type)
+
+
+/* How to extract and insert information held in the m_info field.  */
+#define GELF_M_SYM(info)		ELF64_M_SYM (info)
+#define GELF_M_SIZE(info)		ELF64_M_SIZE (info)
+#define GELF_M_INFO(sym, size)		ELF64_M_INFO (sym, size)
+
+
+/* Get class of the file associated with ELF.  */
+extern int gelf_getclass (Elf *__elf);
+
+
+/* Return size of array of COUNT elements of the type denoted by TYPE
+   in the external representation.  The binary class is taken from ELF.
+   The result is based on version VERSION of the ELF standard.  */
+extern size_t gelf_fsize (Elf *__elf, Elf_Type __type, size_t __count,
+			  unsigned int __version);
+
+/* Retrieve object file header.  */
+extern GElf_Ehdr *gelf_getehdr (Elf *__elf, GElf_Ehdr *__dest);
+
+/* Update the ELF header.  */
+extern int gelf_update_ehdr (Elf *__elf, GElf_Ehdr *__src);
+
+/* Create new ELF header if none exists.  Creates an Elf32_Ehdr if CLASS
+   is ELFCLASS32 or an Elf64_Ehdr if CLASS is ELFCLASS64.  Returns NULL
+   on error.  */
+extern void *gelf_newehdr (Elf *__elf, int __class);
+
+/* Get section at OFFSET.  */
+extern Elf_Scn *gelf_offscn (Elf *__elf, GElf_Off __offset);
+
+/* Retrieve section header.  */
+extern GElf_Shdr *gelf_getshdr (Elf_Scn *__scn, GElf_Shdr *__dst);
+
+/* Update section header.  */
+extern int gelf_update_shdr (Elf_Scn *__scn, GElf_Shdr *__src);
+
+/* Retrieve program header table entry.  */
+extern GElf_Phdr *gelf_getphdr (Elf *__elf, int __ndx, GElf_Phdr *__dst);
+
+/* Update the program header.  */
+extern int gelf_update_phdr (Elf *__elf, int __ndx, GElf_Phdr *__src);
+
+/* Create new program header with PHNUM entries.  Creates either an
+   Elf32_Phdr or an Elf64_Phdr depending on whether the given ELF is
+   ELFCLASS32 or ELFCLASS64.  Returns NULL on error.  */
+extern void *gelf_newphdr (Elf *__elf, size_t __phnum);
+
+/* Get compression header of section if any.  Returns NULL and sets
+   elf_errno if the section isn't compressed or an error occurred.  */
+extern GElf_Chdr *gelf_getchdr (Elf_Scn *__scn, GElf_Chdr *__dst);
+
+/* Convert data structure from the representation in the file represented
+   by ELF to their memory representation.  */
+extern Elf_Data *gelf_xlatetom (Elf *__elf, Elf_Data *__dest,
+				const Elf_Data *__src, unsigned int __encode);
+
+/* Convert data structure from to the representation in memory
+   represented by ELF file representation.  */
+extern Elf_Data *gelf_xlatetof (Elf *__elf, Elf_Data *__dest,
+				const Elf_Data *__src, unsigned int __encode);
+
+
+/* Retrieve REL relocation info at the given index.  */
+extern GElf_Rel *gelf_getrel (Elf_Data *__data, int __ndx, GElf_Rel *__dst);
+
+/* Retrieve RELA relocation info at the given index.  */
+extern GElf_Rela *gelf_getrela (Elf_Data *__data, int __ndx, GElf_Rela *__dst);
+
+/* Update REL relocation information at given index.  */
+extern int gelf_update_rel (Elf_Data *__dst, int __ndx, GElf_Rel *__src);
+
+/* Update RELA relocation information at given index.  */
+extern int gelf_update_rela (Elf_Data *__dst, int __ndx, GElf_Rela *__src);
+
+
+/* Retrieve symbol information from the symbol table at the given index.  */
+extern GElf_Sym *gelf_getsym (Elf_Data *__data, int __ndx, GElf_Sym *__dst);
+
+/* Update symbol information in the symbol table at the given index.  */
+extern int gelf_update_sym (Elf_Data *__data, int __ndx, GElf_Sym *__src);
+
+
+/* Retrieve symbol information and separate section index from the
+   symbol table at the given index.  */
+extern GElf_Sym *gelf_getsymshndx (Elf_Data *__symdata, Elf_Data *__shndxdata,
+				   int __ndx, GElf_Sym *__sym,
+				   Elf32_Word *__xshndx);
+
+/* Update symbol information and separate section index in the symbol
+   table at the given index.  */
+extern int gelf_update_symshndx (Elf_Data *__symdata, Elf_Data *__shndxdata,
+				 int __ndx, GElf_Sym *__sym,
+				 Elf32_Word __xshndx);
+
+
+/* Retrieve additional symbol information from the symbol table at the
+   given index.  */
+extern GElf_Syminfo *gelf_getsyminfo (Elf_Data *__data, int __ndx,
+				      GElf_Syminfo *__dst);
+
+/* Update additional symbol information in the symbol table at the
+   given index.  */
+extern int gelf_update_syminfo (Elf_Data *__data, int __ndx,
+				GElf_Syminfo *__src);
+
+
+/* Get information from dynamic table at the given index.  */
+extern GElf_Dyn *gelf_getdyn (Elf_Data *__data, int __ndx, GElf_Dyn *__dst);
+
+/* Update information in dynamic table at the given index.  */
+extern int gelf_update_dyn (Elf_Data *__dst, int __ndx, GElf_Dyn *__src);
+
+
+/* Get move structure at the given index.  */
+extern GElf_Move *gelf_getmove (Elf_Data *__data, int __ndx, GElf_Move *__dst);
+
+/* Update move structure at the given index.  */
+extern int gelf_update_move (Elf_Data *__data, int __ndx,
+			     GElf_Move *__src);
+
+
+/* Get library from table at the given index.  */
+extern GElf_Lib *gelf_getlib (Elf_Data *__data, int __ndx, GElf_Lib *__dst);
+
+/* Update library in table at the given index.  */
+extern int gelf_update_lib (Elf_Data *__data, int __ndx, GElf_Lib *__src);
+
+
+
+/* Retrieve symbol version information at given index.  */
+extern GElf_Versym *gelf_getversym (Elf_Data *__data, int __ndx,
+				    GElf_Versym *__dst);
+
+/* Update symbol version information.  */
+extern int gelf_update_versym (Elf_Data *__data, int __ndx,
+			       GElf_Versym *__src);
+
+
+/* Retrieve required symbol version information at given offset.  */
+extern GElf_Verneed *gelf_getverneed (Elf_Data *__data, int __offset,
+				      GElf_Verneed *__dst);
+
+/* Update required symbol version information.  */
+extern int gelf_update_verneed (Elf_Data *__data, int __offset,
+				GElf_Verneed *__src);
+
+/* Retrieve additional required symbol version information at given offset.  */
+extern GElf_Vernaux *gelf_getvernaux (Elf_Data *__data, int __offset,
+				      GElf_Vernaux *__dst);
+
+/* Update additional required symbol version information.  */
+extern int gelf_update_vernaux (Elf_Data *__data, int __offset,
+				GElf_Vernaux *__src);
+
+
+/* Retrieve symbol version definition information at given offset.  */
+extern GElf_Verdef *gelf_getverdef (Elf_Data *__data, int __offset,
+				    GElf_Verdef *__dst);
+
+/* Update symbol version definition information.  */
+extern int gelf_update_verdef (Elf_Data *__data, int __offset,
+			       GElf_Verdef *__src);
+
+/* Retrieve additional symbol version definition information at given
+   offset.  */
+extern GElf_Verdaux *gelf_getverdaux (Elf_Data *__data, int __offset,
+				      GElf_Verdaux *__dst);
+
+/* Update additional symbol version definition information.  */
+extern int gelf_update_verdaux (Elf_Data *__data, int __offset,
+				GElf_Verdaux *__src);
+
+
+/* Get auxv entry at the given index.  */
+extern GElf_auxv_t *gelf_getauxv (Elf_Data *__data, int __ndx,
+				  GElf_auxv_t *__dst);
+
+/* Update auxv entry at the given index.  */
+extern int gelf_update_auxv (Elf_Data *__data, int __ndx, GElf_auxv_t *__src);
+
+
+/* Get note header at the given offset into the data, and the offsets of
+   the note's name and descriptor data.  Returns the offset of the next
+   note header, or 0 for an invalid offset or corrupt note header.  */
+extern size_t gelf_getnote (Elf_Data *__data, size_t __offset,
+			    GElf_Nhdr *__result,
+			    size_t *__name_offset, size_t *__desc_offset);
+
+
+/* Compute simple checksum from permanent parts of the ELF file.  */
+extern long int gelf_checksum (Elf *__elf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif	/* gelf.h */
diff --git a/libelf/gelf_checksum.c b/libelf/gelf_checksum.c
new file mode 100644
index 0000000..831c54c
--- /dev/null
+++ b/libelf/gelf_checksum.c
@@ -0,0 +1,48 @@
+/* Convert from file to memory representation.  Generic ELF version.
+   Copyright (C) 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+long int
+gelf_checksum (Elf *elf)
+{
+  if (elf == NULL)
+    return -1l;
+
+  return (elf->class == ELFCLASS32
+	  ? INTUSE(elf32_checksum) (elf) : INTUSE(elf64_checksum) (elf));
+}
diff --git a/libelf/gelf_fsize.c b/libelf/gelf_fsize.c
new file mode 100644
index 0000000..63bcbae
--- /dev/null
+++ b/libelf/gelf_fsize.c
@@ -0,0 +1,104 @@
+/* Return the size of an object file type.
+   Copyright (C) 1998-2010, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+/* These are the sizes for all the known types.  */
+const size_t __libelf_type_sizes[ELFCLASSNUM - 1][ELF_T_NUM] =
+{
+    [ELFCLASS32 - 1] = {
+#define TYPE_SIZES(LIBELFBITS) \
+      [ELF_T_ADDR]	= ELFW2(LIBELFBITS, FSZ_ADDR),			      \
+      [ELF_T_OFF]	= ELFW2(LIBELFBITS, FSZ_OFF),			      \
+      [ELF_T_BYTE]	= 1,						      \
+      [ELF_T_HALF]	= ELFW2(LIBELFBITS, FSZ_HALF),			      \
+      [ELF_T_WORD]	= ELFW2(LIBELFBITS, FSZ_WORD),			      \
+      [ELF_T_SWORD]	= ELFW2(LIBELFBITS, FSZ_SWORD),			      \
+      [ELF_T_XWORD]	= ELFW2(LIBELFBITS, FSZ_XWORD),			      \
+      [ELF_T_SXWORD]	= ELFW2(LIBELFBITS, FSZ_SXWORD),		      \
+      [ELF_T_EHDR]	= sizeof (ElfW2(LIBELFBITS, Ext_Ehdr)),		      \
+      [ELF_T_SHDR]	= sizeof (ElfW2(LIBELFBITS, Ext_Shdr)),		      \
+      [ELF_T_SYM]	= sizeof (ElfW2(LIBELFBITS, Ext_Sym)),		      \
+      [ELF_T_REL]	= sizeof (ElfW2(LIBELFBITS, Ext_Rel)),		      \
+      [ELF_T_RELA]	= sizeof (ElfW2(LIBELFBITS, Ext_Rela)),		      \
+      [ELF_T_PHDR]	= sizeof (ElfW2(LIBELFBITS, Ext_Phdr)),		      \
+      [ELF_T_DYN]	= sizeof (ElfW2(LIBELFBITS, Ext_Dyn)),		      \
+      [ELF_T_VDEF]	= sizeof (ElfW2(LIBELFBITS, Ext_Verdef)),	      \
+      [ELF_T_VDAUX]	= sizeof (ElfW2(LIBELFBITS, Ext_Verdaux)),	      \
+      [ELF_T_VNEED]	= sizeof (ElfW2(LIBELFBITS, Ext_Verneed)),	      \
+      [ELF_T_VNAUX]	= sizeof (ElfW2(LIBELFBITS, Ext_Vernaux)),	      \
+      [ELF_T_NHDR]	= sizeof (ElfW2(LIBELFBITS, Ext_Nhdr)),		      \
+      /* Note the header size is the same, but padding is different.  */      \
+      [ELF_T_NHDR8]	= sizeof (ElfW2(LIBELFBITS, Ext_Nhdr)),		      \
+      [ELF_T_SYMINFO]	= sizeof (ElfW2(LIBELFBITS, Ext_Syminfo)),	      \
+      [ELF_T_MOVE]	= sizeof (ElfW2(LIBELFBITS, Ext_Move)),		      \
+      [ELF_T_LIB]	= sizeof (ElfW2(LIBELFBITS, Ext_Lib)),		      \
+      [ELF_T_AUXV]	= sizeof (ElfW2(LIBELFBITS, Ext_auxv_t)),	      \
+      [ELF_T_CHDR]	= sizeof (ElfW2(LIBELFBITS, Ext_Chdr)),		      \
+      [ELF_T_GNUHASH]	= ELFW2(LIBELFBITS, FSZ_WORD),			      \
+      [ELF_T_RELR]	= ELFW2(LIBELFBITS, FSZ_RELR)
+      TYPE_SIZES (32)
+    },
+    [ELFCLASS64 - 1] = {
+      TYPE_SIZES (64)
+    }
+};
+
+
+size_t
+gelf_fsize (Elf *elf, Elf_Type type, size_t count, unsigned int version)
+{
+  /* We do not have differences between file and memory sizes.  Better
+     not since otherwise `mmap' would not work.  */
+  if (elf == NULL)
+    return 0;
+
+  if (version != EV_CURRENT)
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_VERSION);
+      return 0;
+    }
+
+  if (type >= ELF_T_NUM)
+    {
+      __libelf_seterrno (ELF_E_UNKNOWN_TYPE);
+      return 0;
+    }
+
+  return count * __libelf_type_sizes[elf->class - 1][type];
+}
+INTDEF(gelf_fsize)
diff --git a/libelf/gelf_getauxv.c b/libelf/gelf_getauxv.c
new file mode 100644
index 0000000..1591be2
--- /dev/null
+++ b/libelf/gelf_getauxv.c
@@ -0,0 +1,107 @@
+/* Get information from auxiliary vector at the given index.
+   Copyright (C) 2007, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_auxv_t *
+gelf_getauxv (Elf_Data *data, int ndx, GElf_auxv_t *dst)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  GElf_auxv_t *result = NULL;
+  Elf *elf;
+
+  if (data_scn == NULL)
+    return NULL;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_AUXV))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  elf = data_scn->s->elf;
+
+  rwlock_rdlock (elf->lock);
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_auxv_t *src;
+
+      /* Here it gets a bit more complicated.  The format of the vector
+	 entries has to be converted.  The user better have provided a
+	 buffer where we can store the information.  While copying the data
+	 we convert the format.  */
+      if (unlikely ((ndx + 1) * sizeof (Elf32_auxv_t) > data_scn->d.d_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      src = &((Elf32_auxv_t *) data_scn->d.d_buf)[ndx];
+
+      /* This might look like a simple copy operation but it's
+	 not.  There are zero- and sign-extensions going on.  */
+      dst->a_type = src->a_type;
+      dst->a_un.a_val = src->a_un.a_val;
+    }
+  else
+    {
+      /* If this is a 64 bit object it's easy.  */
+      assert (sizeof (GElf_auxv_t) == sizeof (Elf64_auxv_t));
+
+      /* The data is already in the correct form.  Just make sure the
+	 index is OK.  */
+      if (unlikely ((ndx + 1) * sizeof (GElf_auxv_t) > data_scn->d.d_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      memcpy (dst, data_scn->d.d_buf + ndx * sizeof (GElf_auxv_t),
+	      sizeof (GElf_auxv_t));
+    }
+
+  result = dst;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getchdr.c b/libelf/gelf_getchdr.c
new file mode 100644
index 0000000..394bf4b
--- /dev/null
+++ b/libelf/gelf_getchdr.c
@@ -0,0 +1,69 @@
+/* Return section compression header.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libelfP.h"
+#include <gelf.h>
+#include <stddef.h>
+
+
+GElf_Chdr *
+gelf_getchdr (Elf_Scn *scn, GElf_Chdr *dest)
+{
+  if (scn == NULL)
+    return NULL;
+
+  if (dest == NULL)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return NULL;
+    }
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_Chdr *chdr = elf32_getchdr (scn);
+      if (chdr == NULL)
+	return NULL;
+      dest->ch_type = chdr->ch_type;
+      dest->ch_size = chdr->ch_size;
+      dest->ch_addralign = chdr->ch_addralign;
+    }
+  else
+    {
+      Elf64_Chdr *chdr = elf64_getchdr (scn);
+      if (chdr == NULL)
+	return NULL;
+      *dest = *chdr;
+    }
+
+  return dest;
+}
+INTDEF(gelf_getchdr)
diff --git a/libelf/gelf_getclass.c b/libelf/gelf_getclass.c
new file mode 100644
index 0000000..7d0924b
--- /dev/null
+++ b/libelf/gelf_getclass.c
@@ -0,0 +1,44 @@
+/* Return the class of file associated with the descriptor.
+   Copyright (C) 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_getclass (Elf *elf)
+{
+  return elf == NULL || elf->kind != ELF_K_ELF ? ELFCLASSNONE : elf->class;
+}
diff --git a/libelf/gelf_getdyn.c b/libelf/gelf_getdyn.c
new file mode 100644
index 0000000..a0090e1
--- /dev/null
+++ b/libelf/gelf_getdyn.c
@@ -0,0 +1,108 @@
+/* Get information from dynamic table at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Dyn *
+gelf_getdyn (Elf_Data *data, int ndx, GElf_Dyn *dst)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  GElf_Dyn *result = NULL;
+  Elf *elf;
+
+  if (data_scn == NULL)
+    return NULL;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_DYN))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  elf = data_scn->s->elf;
+
+  rwlock_rdlock (elf->lock);
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_Dyn *src;
+
+      /* Here it gets a bit more complicated.  The format of the symbol
+	 table entries has to be adopted.  The user better has provided
+	 a buffer where we can store the information.  While copying the
+	 data we are converting the format.  */
+      if (INVALID_NDX (ndx, Elf32_Dyn, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      src = &((Elf32_Dyn *) data_scn->d.d_buf)[ndx];
+
+      /* This might look like a simple copy operation but it's
+	 not.  There are zero- and sign-extensions going on.  */
+      dst->d_tag = src->d_tag;
+      /* It OK to copy `d_val' since `d_ptr' has the same size.  */
+      dst->d_un.d_val = src->d_un.d_val;
+    }
+  else
+    {
+      /* If this is a 64 bit object it's easy.  */
+      assert (sizeof (GElf_Dyn) == sizeof (Elf64_Dyn));
+
+      /* The data is already in the correct form.  Just make sure the
+	 index is OK.  */
+      if (INVALID_NDX (ndx, GElf_Dyn, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      *dst = ((GElf_Dyn *) data_scn->d.d_buf)[ndx];
+    }
+
+  result = dst;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getehdr.c b/libelf/gelf_getehdr.c
new file mode 100644
index 0000000..abeb70c
--- /dev/null
+++ b/libelf/gelf_getehdr.c
@@ -0,0 +1,108 @@
+/* Get ELF header.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Ehdr *
+internal_function
+__gelf_getehdr_rdlock (Elf *elf, GElf_Ehdr *dest)
+{
+  GElf_Ehdr *result = NULL;
+
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* The following is an optimization: the ehdr element is at the same
+     position in both the elf32 and elf64 structure.  */
+  if (offsetof (struct Elf, state.elf32.ehdr)
+      != offsetof (struct Elf, state.elf64.ehdr))
+    abort ();
+  /* Just pick one of the values.  */
+ if (unlikely (elf->state.elf64.ehdr == NULL))
+    /* Maybe no ELF header was created yet.  */
+    __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+  else if (elf->class == ELFCLASS32)
+    {
+      Elf32_Ehdr *ehdr = elf->state.elf32.ehdr;
+
+      /* Convert the 32-bit struct to an 64-bit one.  */
+      memcpy (dest->e_ident, ehdr->e_ident, EI_NIDENT);
+#define COPY(name) \
+      dest->name = ehdr->name
+      COPY (e_type);
+      COPY (e_machine);
+      COPY (e_version);
+      COPY (e_entry);
+      COPY (e_phoff);
+      COPY (e_shoff);
+      COPY (e_flags);
+      COPY (e_ehsize);
+      COPY (e_phentsize);
+      COPY (e_phnum);
+      COPY (e_shentsize);
+      COPY (e_shnum);
+      COPY (e_shstrndx);
+
+      result = dest;
+    }
+  else
+    result = memcpy (dest, elf->state.elf64.ehdr, sizeof (*dest));
+
+  return result;
+}
+
+GElf_Ehdr *
+gelf_getehdr (Elf *elf, GElf_Ehdr *dest)
+{
+  GElf_Ehdr *result;
+  if (elf == NULL)
+    return NULL;
+
+  rwlock_rdlock (elf->lock);
+  result = __gelf_getehdr_rdlock (elf, dest);
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getlib.c b/libelf/gelf_getlib.c
new file mode 100644
index 0000000..a8ac478
--- /dev/null
+++ b/libelf/gelf_getlib.c
@@ -0,0 +1,77 @@
+/* Get library from table at the given index.
+   Copyright (C) 2004, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Lib *
+gelf_getlib (Elf_Data *data, int ndx, GElf_Lib *dst)
+{
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_LIB))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  rwlock_rdlock (data_scn->s->elf->lock);
+
+  /* The on disk format of Elf32_Lib and Elf64_Lib is identical.  So
+     we can simplify things significantly.  */
+  assert (sizeof (GElf_Lib) == sizeof (Elf32_Lib));
+  assert (sizeof (GElf_Lib) == sizeof (Elf64_Lib));
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  GElf_Lib *result = NULL;
+  if (INVALID_NDX (ndx, GElf_Lib, data))
+    __libelf_seterrno (ELF_E_INVALID_INDEX);
+  else
+    {
+      *dst = ((GElf_Lib *) data->d_buf)[ndx];
+
+      result = dst;
+    }
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getmove.c b/libelf/gelf_getmove.c
new file mode 100644
index 0000000..18efedc
--- /dev/null
+++ b/libelf/gelf_getmove.c
@@ -0,0 +1,79 @@
+/* Get move structure at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+GElf_Move *
+gelf_getmove (Elf_Data *data, int ndx, GElf_Move *dst)
+{
+  GElf_Move *result = NULL;
+  Elf *elf;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_MOVE))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Move) == sizeof (Elf32_Move));
+  assert (sizeof (GElf_Move) == sizeof (Elf64_Move));
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (INVALID_NDX (ndx, GElf_Move, data))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      goto out;
+    }
+
+  elf = ((Elf_Data_Scn *) data)->s->elf;
+  rwlock_rdlock (elf->lock);
+
+  *dst = ((GElf_Move *) data->d_buf)[ndx];
+
+  rwlock_unlock (elf->lock);
+
+  result = dst;
+
+ out:
+  return result;
+}
diff --git a/libelf/gelf_getnote.c b/libelf/gelf_getnote.c
new file mode 100644
index 0000000..0f7b9d6
--- /dev/null
+++ b/libelf/gelf_getnote.c
@@ -0,0 +1,116 @@
+/* Get note information at the supplied offset.
+   Copyright (C) 2007, 2014, 2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+size_t
+gelf_getnote (Elf_Data *data, size_t offset, GElf_Nhdr *result,
+	      size_t *name_offset, size_t *desc_offset)
+{
+  if (data == NULL)
+    return 0;
+
+  if (unlikely (data->d_type != ELF_T_NHDR && data->d_type != ELF_T_NHDR8))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  /* It's easy to handle this type.  It has the same size for 32 and
+     64 bit objects.  */
+  assert (sizeof (GElf_Nhdr) == sizeof (Elf32_Nhdr));
+  assert (sizeof (GElf_Nhdr) == sizeof (Elf64_Nhdr));
+
+  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     offset is OK.  */
+  if (unlikely (offset > data->d_size
+		|| data->d_size - offset < sizeof (GElf_Nhdr)))
+    {
+      __libelf_seterrno (ELF_E_OFFSET_RANGE);
+      offset = 0;
+    }
+  else
+    {
+      const GElf_Nhdr *n = data->d_buf + offset;
+      offset += sizeof *n;
+
+      if (offset > data->d_size)
+	offset = 0;
+      else
+	{
+	  /* This is slightly tricky, offset is guaranteed to be 4
+	     byte aligned, which is what we need for the name_offset.
+	     And normally desc_offset is also 4 byte aligned, but not
+	     for GNU Property notes, then it should be 8.  So align
+	     the offset, after adding the namesz, and include padding
+	     in descsz to get to the end.  */
+	  *name_offset = offset;
+	  if (n->n_namesz > data->d_size
+	      || offset > data->d_size - n->n_namesz)
+	    offset = 0;
+	  else
+	    {
+	      offset += n->n_namesz;
+	      /* Include padding.  Check below for overflow.  */
+	      GElf_Word descsz = (data->d_type == ELF_T_NHDR8
+				  ? NOTE_ALIGN8 (n->n_descsz)
+				  : NOTE_ALIGN4 (n->n_descsz));
+
+	      if (data->d_type == ELF_T_NHDR8)
+		offset = NOTE_ALIGN8 (offset);
+	      else
+		offset = NOTE_ALIGN4 (offset);
+
+	      if (unlikely (offset > data->d_size
+			    || data->d_size - offset < descsz
+			    || (descsz == 0 && n->n_descsz != 0)))
+		offset = 0;
+	      else
+		{
+		  *desc_offset = offset;
+		  offset += descsz;
+		  *result = *n;
+		}
+	    }
+	}
+    }
+
+  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  return offset;
+}
diff --git a/libelf/gelf_getphdr.c b/libelf/gelf_getphdr.c
new file mode 100644
index 0000000..c719e4b
--- /dev/null
+++ b/libelf/gelf_getphdr.c
@@ -0,0 +1,135 @@
+/* Return program header table entry.
+   Copyright (C) 1998-2010, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include "libelfP.h"
+
+
+GElf_Phdr *
+gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst)
+{
+  GElf_Phdr *result = NULL;
+
+  if (elf == NULL)
+    return NULL;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  if (dst == NULL)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return NULL;
+    }
+
+  rwlock_rdlock (elf->lock);
+
+  if (elf->class == ELFCLASS32)
+    {
+      /* Copy the elements one-by-one.  */
+      Elf32_Phdr *phdr = elf->state.elf32.phdr;
+
+      if (phdr == NULL)
+	{
+	  rwlock_unlock (elf->lock);
+	  phdr = INTUSE(elf32_getphdr) (elf);
+	  if (phdr == NULL)
+	    /* The error number is already set.  */
+	    return NULL;
+	  rwlock_rdlock (elf->lock);
+	}
+
+      /* Test whether the index is ok.  */
+      size_t phnum;
+      if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
+	  || (size_t) ndx >= phnum)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      /* We know the result now.  */
+      result = dst;
+
+      /* Now correct the pointer to point to the correct element.  */
+      phdr += ndx;
+
+#define COPY(Name) result->Name = phdr->Name
+      COPY (p_type);
+      COPY (p_offset);
+      COPY (p_vaddr);
+      COPY (p_paddr);
+      COPY (p_filesz);
+      COPY (p_memsz);
+      COPY (p_flags);
+      COPY (p_align);
+    }
+  else
+    {
+      /* Copy the elements one-by-one.  */
+      Elf64_Phdr *phdr = elf->state.elf64.phdr;
+
+      if (phdr == NULL)
+	{
+	  rwlock_unlock (elf->lock);
+	  phdr = INTUSE(elf64_getphdr) (elf);
+	  if (phdr == NULL)
+	    /* The error number is already set.  */
+	    return NULL;
+	  rwlock_rdlock (elf->lock);
+	}
+
+      /* Test whether the index is ok.  */
+      size_t phnum;
+      if (__elf_getphdrnum_chk_rdlock (elf, &phnum) != 0
+	  || (size_t) ndx >= phnum)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      /* We only have to copy the data.  */
+      result = memcpy (dst, phdr + ndx, sizeof (GElf_Phdr));
+    }
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getrel.c b/libelf/gelf_getrel.c
new file mode 100644
index 0000000..309e3d3
--- /dev/null
+++ b/libelf/gelf_getrel.c
@@ -0,0 +1,99 @@
+/* Get REL relocation information at given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Rel *
+gelf_getrel (Elf_Data *data, int ndx, GElf_Rel *dst)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  GElf_Rel *result;
+
+  if (data_scn == NULL)
+    return NULL;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_REL))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  scn = data_scn->s;
+
+  rwlock_rdlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      /* We have to convert the data.  */
+      if (INVALID_NDX (ndx, Elf32_Rel, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  result = NULL;
+	}
+      else
+	{
+	  Elf32_Rel *src = &((Elf32_Rel *) data_scn->d.d_buf)[ndx];
+
+	  dst->r_offset = src->r_offset;
+	  dst->r_info = GELF_R_INFO (ELF32_R_SYM (src->r_info),
+				     ELF32_R_TYPE (src->r_info));
+
+	  result = dst;
+	}
+    }
+  else
+    {
+      /* Simply copy the data after we made sure we are actually getting
+	 correct data.  */
+      if (INVALID_NDX (ndx, Elf64_Rel, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  result = NULL;
+	}
+      else
+	result = memcpy (dst, &((Elf64_Rel *) data_scn->d.d_buf)[ndx],
+			 sizeof (Elf64_Rel));
+    }
+
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getrela.c b/libelf/gelf_getrela.c
new file mode 100644
index 0000000..d695f65
--- /dev/null
+++ b/libelf/gelf_getrela.c
@@ -0,0 +1,100 @@
+/* Get RELA relocation information at given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Rela *
+gelf_getrela (Elf_Data *data, int ndx, GElf_Rela *dst)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  GElf_Rela *result;
+
+  if (data_scn == NULL)
+    return NULL;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_RELA))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  scn = data_scn->s;
+
+  rwlock_rdlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      /* We have to convert the data.  */
+      if (INVALID_NDX (ndx, Elf32_Rela, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  result = NULL;
+	}
+      else
+	{
+	  Elf32_Rela *src = &((Elf32_Rela *) data_scn->d.d_buf)[ndx];
+
+	  dst->r_offset = src->r_offset;
+	  dst->r_info = GELF_R_INFO (ELF32_R_SYM (src->r_info),
+				     ELF32_R_TYPE (src->r_info));
+	  dst->r_addend = src->r_addend;
+
+	  result = dst;
+	}
+    }
+  else
+    {
+      /* Simply copy the data after we made sure we are actually getting
+	 correct data.  */
+      if (INVALID_NDX (ndx, Elf64_Rela, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  result = NULL;
+	}
+      else
+	result = memcpy (dst, &((Elf64_Rela *) data_scn->d.d_buf)[ndx],
+			 sizeof (Elf64_Rela));
+    }
+
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getshdr.c b/libelf/gelf_getshdr.c
new file mode 100644
index 0000000..3858c8e
--- /dev/null
+++ b/libelf/gelf_getshdr.c
@@ -0,0 +1,103 @@
+/* Return section header.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Shdr *
+gelf_getshdr (Elf_Scn *scn, GElf_Shdr *dst)
+{
+  GElf_Shdr *result = NULL;
+
+  if (scn == NULL)
+    return NULL;
+
+  if (dst == NULL)
+    {
+      __libelf_seterrno (ELF_E_INVALID_OPERAND);
+      return NULL;
+    }
+
+  rwlock_rdlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      /* Copy the elements one-by-one.  */
+      Elf32_Shdr *shdr
+	= scn->shdr.e32 ?: __elf32_getshdr_rdlock (scn);
+
+      if (shdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_OPERAND);
+	  goto out;
+	}
+
+#define COPY(name) \
+      dst->name = shdr->name
+      COPY (sh_name);
+      COPY (sh_type);
+      COPY (sh_flags);
+      COPY (sh_addr);
+      COPY (sh_offset);
+      COPY (sh_size);
+      COPY (sh_link);
+      COPY (sh_info);
+      COPY (sh_addralign);
+      COPY (sh_entsize);
+
+      result = dst;
+    }
+  else
+    {
+      Elf64_Shdr *shdr
+	= scn->shdr.e64 ?: __elf64_getshdr_rdlock (scn);
+
+      if (shdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_OPERAND);
+	  goto out;
+	}
+
+      /* We only have to copy the data.  */
+      result = memcpy (dst, shdr, sizeof (GElf_Shdr));
+    }
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
+INTDEF(gelf_getshdr)
diff --git a/libelf/gelf_getsym.c b/libelf/gelf_getsym.c
new file mode 100644
index 0000000..01534d2
--- /dev/null
+++ b/libelf/gelf_getsym.c
@@ -0,0 +1,114 @@
+/* Get symbol information from symbol table at the given index.
+   Copyright (C) 1999, 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Sym *
+gelf_getsym (Elf_Data *data, int ndx, GElf_Sym *dst)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  GElf_Sym *result = NULL;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_SYM))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  rwlock_rdlock (data_scn->s->elf->lock);
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  if (data_scn->s->elf->class == ELFCLASS32)
+    {
+      Elf32_Sym *src;
+
+      /* Here it gets a bit more complicated.  The format of the symbol
+	 table entries has to be adopted.  The user better has provided
+	 a buffer where we can store the information.  While copying the
+	 data we are converting the format.  */
+      if (INVALID_NDX (ndx, Elf32_Sym, data))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      src = &((Elf32_Sym *) data->d_buf)[ndx];
+
+      /* This might look like a simple copy operation but it's
+	 not.  There are zero- and sign-extensions going on.  */
+#define COPY(name) \
+      dst->name = src->name
+      COPY (st_name);
+      /* Please note that we can simply copy the `st_info' element since
+	 the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same
+	 for the 64 bit variant.  */
+      COPY (st_info);
+      COPY (st_other);
+      COPY (st_shndx);
+      COPY (st_value);
+      COPY (st_size);
+    }
+  else
+    {
+      /* If this is a 64 bit object it's easy.  */
+      assert (sizeof (GElf_Sym) == sizeof (Elf64_Sym));
+
+      /* The data is already in the correct form.  Just make sure the
+	 index is OK.  */
+      if (INVALID_NDX (ndx, GElf_Sym, data))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      *dst = ((GElf_Sym *) data->d_buf)[ndx];
+    }
+
+  result = dst;
+
+ out:
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return result;
+}
+INTDEF(gelf_getsym)
diff --git a/libelf/gelf_getsyminfo.c b/libelf/gelf_getsyminfo.c
new file mode 100644
index 0000000..8360ed3
--- /dev/null
+++ b/libelf/gelf_getsyminfo.c
@@ -0,0 +1,77 @@
+/* Get additional symbol information from symbol table at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Syminfo *
+gelf_getsyminfo (Elf_Data *data, int ndx, GElf_Syminfo *dst)
+{
+  GElf_Syminfo *result = NULL;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_SYMINFO))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Syminfo) == sizeof (Elf32_Syminfo));
+  assert (sizeof (GElf_Syminfo) == sizeof (Elf64_Syminfo));
+
+  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (INVALID_NDX (ndx, GElf_Syminfo, data))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      goto out;
+    }
+
+  *dst = ((GElf_Syminfo *) data->d_buf)[ndx];
+
+  result = dst;
+
+ out:
+  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getsymshndx.c b/libelf/gelf_getsymshndx.c
new file mode 100644
index 0000000..17c90fc
--- /dev/null
+++ b/libelf/gelf_getsymshndx.c
@@ -0,0 +1,136 @@
+/* Get symbol information and separate section index from symbol table
+   at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Sym *
+gelf_getsymshndx (Elf_Data *symdata, Elf_Data *shndxdata, int ndx,
+		  GElf_Sym *dst, Elf32_Word *dstshndx)
+{
+  Elf_Data_Scn *symdata_scn = (Elf_Data_Scn *) symdata;
+  Elf_Data_Scn *shndxdata_scn = (Elf_Data_Scn *) shndxdata;
+  GElf_Sym *result = NULL;
+  Elf32_Word shndx = 0;
+
+  if (symdata == NULL)
+    return NULL;
+
+  if (unlikely (symdata->d_type != ELF_T_SYM)
+      || (likely (shndxdata_scn != NULL)
+	  && unlikely (shndxdata->d_type != ELF_T_WORD)))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  rwlock_rdlock (symdata_scn->s->elf->lock);
+
+  /* The user is not required to pass a data descriptor for an extended
+     section index table.  */
+  if (likely (shndxdata_scn != NULL))
+    {
+      if (INVALID_NDX (ndx, Elf32_Word, &shndxdata_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      shndx = ((Elf32_Word *) shndxdata_scn->d.d_buf)[ndx];
+    }
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  if (symdata_scn->s->elf->class == ELFCLASS32)
+    {
+      Elf32_Sym *src;
+
+      /* Here it gets a bit more complicated.  The format of the symbol
+	 table entries has to be adopted.  The user better has provided
+	 a buffer where we can store the information.  While copying the
+	 data we are converting the format.  */
+      if (INVALID_NDX (ndx, Elf32_Sym, symdata))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      src = &((Elf32_Sym *) symdata->d_buf)[ndx];
+
+      /* This might look like a simple copy operation but it's
+	 not.  There are zero- and sign-extensions going on.  */
+#define COPY(name) \
+      dst->name = src->name
+      COPY (st_name);
+      /* Please note that we can simply copy the `st_info' element since
+	 the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same
+	 for the 64 bit variant.  */
+      COPY (st_info);
+      COPY (st_other);
+      COPY (st_shndx);
+      COPY (st_value);
+      COPY (st_size);
+    }
+  else
+    {
+      /* If this is a 64 bit object it's easy.  */
+      assert (sizeof (GElf_Sym) == sizeof (Elf64_Sym));
+
+      /* The data is already in the correct form.  Just make sure the
+	 index is OK.  */
+      if (INVALID_NDX (ndx, GElf_Sym, symdata))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      *dst = ((GElf_Sym *) symdata->d_buf)[ndx];
+    }
+
+  /* Now we can store the section index.  */
+  if (dstshndx != NULL)
+    *dstshndx = shndx;
+
+  result = dst;
+
+ out:
+  rwlock_unlock (symdata_scn->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getverdaux.c b/libelf/gelf_getverdaux.c
new file mode 100644
index 0000000..739a765
--- /dev/null
+++ b/libelf/gelf_getverdaux.c
@@ -0,0 +1,79 @@
+/* Get additional symbol version definition information at the given offset.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Verdaux *
+gelf_getverdaux (Elf_Data *data, int offset, GElf_Verdaux *dst)
+{
+  GElf_Verdaux *result;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_VDEF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* It's easy to handle this type.  It has the same size for 32 and
+     64 bit objects.  */
+  assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
+  assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
+
+  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (unlikely (offset < 0)
+      || unlikely (offset + sizeof (GElf_Verdaux) > data->d_size)
+      || unlikely (offset % __alignof__ (GElf_Verdaux) != 0))
+    {
+      __libelf_seterrno (ELF_E_OFFSET_RANGE);
+      result = NULL;
+    }
+  else
+    result = (GElf_Verdaux *) memcpy (dst, (char *) data->d_buf + offset,
+				      sizeof (GElf_Verdaux));
+
+
+  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getverdef.c b/libelf/gelf_getverdef.c
new file mode 100644
index 0000000..651f4fa
--- /dev/null
+++ b/libelf/gelf_getverdef.c
@@ -0,0 +1,78 @@
+/* Get symbol version definition information at the given offset.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Verdef *
+gelf_getverdef (Elf_Data *data, int offset, GElf_Verdef *dst)
+{
+  GElf_Verdef *result;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_VDEF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* It's easy to handle this type.  It has the same size for 32 and
+     64 bit objects.  */
+  assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
+  assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
+
+  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (unlikely (offset < 0)
+      || unlikely (offset + sizeof (GElf_Verdef) > data->d_size)
+      || unlikely (offset % __alignof__ (GElf_Verdef) != 0))
+    {
+      __libelf_seterrno (ELF_E_OFFSET_RANGE);
+      result = NULL;
+    }
+  else
+    result = (GElf_Verdef *) memcpy (dst, (char *) data->d_buf + offset,
+				     sizeof (GElf_Verdef));
+
+  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getvernaux.c b/libelf/gelf_getvernaux.c
new file mode 100644
index 0000000..e47fb0a
--- /dev/null
+++ b/libelf/gelf_getvernaux.c
@@ -0,0 +1,81 @@
+/* Get additional required symbol version information at the given offset.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Vernaux *
+gelf_getvernaux (Elf_Data *data, int offset, GElf_Vernaux *dst)
+{
+  GElf_Vernaux *result;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_VNEED))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* It's easy to handle this type.  It has the same size for 32 and
+     64 bit objects.  And fortunately the `ElfXXX_Vernaux' records
+     also have the same size.  */
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Verneed));
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Verneed));
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
+
+  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (unlikely (offset < 0)
+      || unlikely (offset + sizeof (GElf_Vernaux) > data->d_size)
+      || unlikely (offset % sizeof (GElf_Vernaux) != 0))
+    {
+      __libelf_seterrno (ELF_E_OFFSET_RANGE);
+      result = NULL;
+    }
+  else
+    result = (GElf_Vernaux *) memcpy (dst, (char *) data->d_buf + offset,
+				      sizeof (GElf_Verneed));
+
+  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getverneed.c b/libelf/gelf_getverneed.c
new file mode 100644
index 0000000..c1f5d34
--- /dev/null
+++ b/libelf/gelf_getverneed.c
@@ -0,0 +1,81 @@
+/* Get required symbol version information at the given offset.
+   Copyright (C) 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Verneed *
+gelf_getverneed (Elf_Data *data, int offset, GElf_Verneed *dst)
+{
+  GElf_Verneed *result;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_VNEED))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* It's easy to handle this type.  It has the same size for 32 and
+     64 bit objects.  And fortunately the `ElfXXX_Vernaux' records
+     also have the same size.  */
+  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
+  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
+  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Vernaux));
+  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Vernaux));
+
+  rwlock_rdlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (unlikely (offset < 0)
+      || unlikely (offset + sizeof (GElf_Verneed) > data->d_size)
+      || unlikely (offset % sizeof (GElf_Verneed) != 0))
+    {
+      __libelf_seterrno (ELF_E_OFFSET_RANGE);
+      result = NULL;
+    }
+  else
+    result = (GElf_Verneed *) memcpy (dst, (char *) data->d_buf + offset,
+				      sizeof (GElf_Verneed));
+
+  rwlock_unlock (((Elf_Data_Scn *) data)->s->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_getversym.c b/libelf/gelf_getversym.c
new file mode 100644
index 0000000..68d23c7
--- /dev/null
+++ b/libelf/gelf_getversym.c
@@ -0,0 +1,86 @@
+/* Get symbol version information at the given index.
+   Copyright (C) 1999, 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+GElf_Versym *
+gelf_getversym (Elf_Data *data, int ndx, GElf_Versym *dst)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  GElf_Versym *result;
+
+  if (data == NULL)
+    return NULL;
+
+  if (unlikely (data->d_type != ELF_T_HALF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return NULL;
+    }
+
+  /* This is the one place where we have to take advantage of the fact
+     that an `Elf_Data' pointer is also a pointer to `Elf_Data_Scn'.
+     The interface is broken so that it requires this hack.  */
+  scn = data_scn->s;
+
+  /* It's easy to handle this type.  It has the same size for 32 and
+     64 bit objects.  */
+  assert (sizeof (GElf_Versym) == sizeof (Elf32_Versym));
+  assert (sizeof (GElf_Versym) == sizeof (Elf64_Versym));
+
+  rwlock_rdlock (scn->elf->lock);
+
+  /* The data is already in the correct form.  Just make sure the
+     index is OK.  */
+  if (INVALID_NDX (ndx, GElf_Versym, data))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      result = NULL;
+    }
+  else
+    {
+      *dst = ((GElf_Versym *) data->d_buf)[ndx];
+
+      result = dst;
+    }
+
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_newehdr.c b/libelf/gelf_newehdr.c
new file mode 100644
index 0000000..2788906
--- /dev/null
+++ b/libelf/gelf_newehdr.c
@@ -0,0 +1,46 @@
+/* Create new ELF header.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+void *
+gelf_newehdr (Elf *elf, int class)
+{
+  return (class == ELFCLASS32
+	  ? (void *) INTUSE(elf32_newehdr) (elf)
+	  : (void *) INTUSE(elf64_newehdr) (elf));
+}
diff --git a/libelf/gelf_newphdr.c b/libelf/gelf_newphdr.c
new file mode 100644
index 0000000..84aad78
--- /dev/null
+++ b/libelf/gelf_newphdr.c
@@ -0,0 +1,46 @@
+/* Create new ELF program header.
+   Copyright (C) 1998, 1999, 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+void *
+gelf_newphdr ( Elf *elf, size_t phnum)
+{
+  return (elf->class == ELFCLASS32
+	  ? (void *) INTUSE(elf32_newphdr) (elf, phnum)
+	  : (void *) INTUSE(elf64_newphdr) (elf, phnum));
+}
diff --git a/libelf/gelf_offscn.c b/libelf/gelf_offscn.c
new file mode 100644
index 0000000..cf206f5
--- /dev/null
+++ b/libelf/gelf_offscn.c
@@ -0,0 +1,55 @@
+/* Create new ELF header.
+   Copyright (C) 2005, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+Elf_Scn *
+gelf_offscn (Elf *elf, GElf_Off offset)
+{
+  if (elf->class == ELFCLASS32)
+    {
+      if ((Elf32_Off) offset != offset)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_OFFSET);
+	  return NULL;
+	}
+
+      return INTUSE(elf32_offscn) (elf, (Elf32_Off) offset);
+    }
+
+  return INTUSE(elf64_offscn) (elf, offset);
+}
diff --git a/libelf/gelf_update_auxv.c b/libelf/gelf_update_auxv.c
new file mode 100644
index 0000000..e4e5229
--- /dev/null
+++ b/libelf/gelf_update_auxv.c
@@ -0,0 +1,111 @@
+/* Update information in dynamic table at the given index.
+   Copyright (C) 2007, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_auxv (Elf_Data *data, int ndx, GElf_auxv_t *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  int result = 0;
+
+  if (data == NULL)
+    return 0;
+
+  if (unlikely (ndx < 0))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_AUXV))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_auxv_t *auxv;
+
+      /* There is the possibility that the values in the input are
+	 too large.  */
+      if (unlikely (src->a_type > 0xffffffffll)
+	  || unlikely (src->a_un.a_val > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Check whether we have to resize the data buffer.  */
+      if (unlikely ((ndx + 1) * sizeof (Elf32_auxv_t) > data_scn->d.d_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      auxv = &((Elf32_auxv_t *) data_scn->d.d_buf)[ndx];
+
+      auxv->a_type = src->a_type;
+      auxv->a_un.a_val = src->a_un.a_val;
+    }
+  else
+    {
+      /* Check whether we have to resize the data buffer.  */
+      if (unlikely ((ndx + 1) * sizeof (Elf64_auxv_t) > data_scn->d.d_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      ((Elf64_auxv_t *) data_scn->d.d_buf)[ndx] = *src;
+    }
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_dyn.c b/libelf/gelf_update_dyn.c
new file mode 100644
index 0000000..5c515d2
--- /dev/null
+++ b/libelf/gelf_update_dyn.c
@@ -0,0 +1,107 @@
+/* Update information in dynamic table at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_dyn (Elf_Data *data, int ndx, GElf_Dyn *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  int result = 0;
+
+  if (data == NULL)
+    return 0;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_DYN))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_Dyn *dyn;
+
+      /* There is the possibility that the values in the input are
+	 too large.  */
+      if (unlikely (src->d_tag < -0x80000000ll)
+	  || unlikely (src->d_tag > 0x7fffffffll)
+	  || unlikely (src->d_un.d_val > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf32_Dyn, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      dyn = &((Elf32_Dyn *) data_scn->d.d_buf)[ndx];
+
+      dyn->d_tag = src->d_tag;
+      dyn->d_un.d_val = src->d_un.d_val;
+    }
+  else
+    {
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf64_Dyn, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      ((Elf64_Dyn *) data_scn->d.d_buf)[ndx] = *src;
+    }
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_ehdr.c b/libelf/gelf_update_ehdr.c
new file mode 100644
index 0000000..73d5af7
--- /dev/null
+++ b/libelf/gelf_update_ehdr.c
@@ -0,0 +1,118 @@
+/* Update ELF header.
+   Copyright (C) 2000, 2001, 2002, 2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_ehdr (Elf *elf, GElf_Ehdr *src)
+{
+  int result = 0;
+
+  if (elf == NULL)
+    return 0;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  rwlock_wrlock (elf->lock);
+
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_Ehdr *ehdr = elf->state.elf32.ehdr;
+
+      if (ehdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+	  goto out;
+	}
+
+      /* We have to convert the data to the 32 bit format.  This might
+	 overflow some fields so we have to test for this case before
+	 copying.  */
+      if (unlikely (src->e_entry > 0xffffffffull)
+	  || unlikely (src->e_phoff > 0xffffffffull)
+	  || unlikely (src->e_shoff > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Copy the data.  */
+      memcpy (ehdr->e_ident, src->e_ident, EI_NIDENT);
+#define COPY(name) \
+      ehdr->name = src->name
+      COPY (e_type);
+      COPY (e_machine);
+      COPY (e_version);
+      COPY (e_entry);
+      COPY (e_phoff);
+      COPY (e_shoff);
+      COPY (e_flags);
+      COPY (e_ehsize);
+      COPY (e_phentsize);
+      COPY (e_phnum);
+      COPY (e_shentsize);
+      COPY (e_shnum);
+      COPY (e_shstrndx);
+    }
+  else
+    {
+      Elf64_Ehdr *ehdr = elf->state.elf64.ehdr;
+
+      if (ehdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_WRONG_ORDER_EHDR);
+	  goto out;
+	}
+
+      /* Just copy the data.  */
+      memcpy (ehdr, src, sizeof (Elf64_Ehdr));
+    }
+
+  /* Mark the ELF header as modified.  */
+  elf->state.elf.ehdr_flags |= ELF_F_DIRTY;
+
+  result = 1;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_lib.c b/libelf/gelf_update_lib.c
new file mode 100644
index 0000000..d0f235e
--- /dev/null
+++ b/libelf/gelf_update_lib.c
@@ -0,0 +1,75 @@
+/* Update library in table at the given index.
+   Copyright (C) 2004, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2004.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_lib (Elf_Data *data, int ndx, GElf_Lib *src)
+{
+  if (data == NULL)
+    return 0;
+
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  if (unlikely (data_scn->d.d_type != ELF_T_LIB))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  Elf_Scn *scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  /* Check whether we have to resize the data buffer.  */
+  int result = 0;
+  if (INVALID_NDX (ndx, Elf64_Lib, &data_scn->d))
+    __libelf_seterrno (ELF_E_INVALID_INDEX);
+  else
+    {
+      ((Elf64_Lib *) data_scn->d.d_buf)[ndx] = *src;
+
+      result = 1;
+
+      /* Mark the section as modified.  */
+      scn->flags |= ELF_F_DIRTY;
+    }
+
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_move.c b/libelf/gelf_update_move.c
new file mode 100644
index 0000000..4190ee3
--- /dev/null
+++ b/libelf/gelf_update_move.c
@@ -0,0 +1,77 @@
+/* Update move structure at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_move (Elf_Data *data, int ndx, GElf_Move *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  if (data == NULL)
+    return 0;
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Move) == sizeof (Elf32_Move));
+  assert (sizeof (GElf_Move) == sizeof (Elf64_Move));
+
+  /* Check whether we have to resize the data buffer.  */
+  if (INVALID_NDX (ndx, GElf_Move, &data_scn->d))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_MOVE))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  rwlock_wrlock (data_scn->s->elf->lock);
+
+  ((GElf_Move *) data_scn->d.d_buf)[ndx] = *src;
+
+  /* Mark the section as modified.  */
+  data_scn->s->flags |= ELF_F_DIRTY;
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return 1;
+}
diff --git a/libelf/gelf_update_phdr.c b/libelf/gelf_update_phdr.c
new file mode 100644
index 0000000..a848677
--- /dev/null
+++ b/libelf/gelf_update_phdr.c
@@ -0,0 +1,143 @@
+/* Update program header program header table entry.
+   Copyright (C) 2000-2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_phdr (Elf *elf, int ndx, GElf_Phdr *src)
+{
+  int result = 0;
+
+  if (elf == NULL)
+    return 0;
+
+  if (unlikely (elf->kind != ELF_K_ELF))
+    {
+      __libelf_seterrno (ELF_E_INVALID_HANDLE);
+      return 0;
+    }
+
+  rwlock_wrlock (elf->lock);
+
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_Phdr *phdr = elf->state.elf32.phdr;
+
+      /* We have to convert the data to the 32 bit format.  This might
+	 overflow some fields so we have to test for this case before
+	 copying.  */
+      if (unlikely (src->p_offset > 0xffffffffull)
+	  || unlikely (src->p_vaddr > 0xffffffffull)
+	  || unlikely (src->p_paddr > 0xffffffffull)
+	  || unlikely (src->p_filesz > 0xffffffffull)
+	  || unlikely (src->p_memsz > 0xffffffffull)
+	  || unlikely (src->p_align > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      if (phdr == NULL)
+	{
+	  phdr = __elf32_getphdr_wrlock (elf);
+	  if (phdr == NULL)
+	    /* The error number is already set.  */
+	    goto out;
+	}
+
+      /* Test whether the index is ok.  */
+      size_t phnum;
+      if (ndx >= elf->state.elf32.ehdr->e_phnum
+	  && (elf->state.elf32.ehdr->e_phnum != PN_XNUM
+	      || __elf_getphdrnum_rdlock (elf, &phnum) != 0
+	      || (size_t) ndx >= phnum))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      /* Now correct the pointer to point to the correct element.  */
+      phdr += ndx;
+
+#define COPY(name) \
+      phdr->name = src->name
+      COPY (p_type);
+      COPY (p_offset);
+      COPY (p_vaddr);
+      COPY (p_paddr);
+      COPY (p_filesz);
+      COPY (p_memsz);
+      COPY (p_flags);
+      COPY (p_align);
+    }
+  else
+    {
+      Elf64_Phdr *phdr = elf->state.elf64.phdr;
+
+      if (phdr == NULL)
+	{
+	  phdr = __elf64_getphdr_wrlock (elf);
+	  if (phdr == NULL)
+	    /* The error number is already set.  */
+	    goto out;
+	}
+
+      /* Test whether the index is ok.  */
+      size_t phnum;
+      if (ndx >= elf->state.elf64.ehdr->e_phnum
+	  && (elf->state.elf64.ehdr->e_phnum != PN_XNUM
+	      || __elf_getphdrnum_rdlock (elf, &phnum) != 0
+	      || (size_t) ndx >= phnum))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      /* Just copy the data.  */
+      memcpy (phdr + ndx, src, sizeof (Elf64_Phdr));
+    }
+
+  /* Mark the program header as modified.  */
+  elf->state.elf.phdr_flags |= ELF_F_DIRTY;
+
+  result = 1;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_rel.c b/libelf/gelf_update_rel.c
new file mode 100644
index 0000000..14f62e9
--- /dev/null
+++ b/libelf/gelf_update_rel.c
@@ -0,0 +1,108 @@
+/* Update REL relocation information at given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_rel (Elf_Data *dst, int ndx, GElf_Rel *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) dst;
+  Elf_Scn *scn;
+  int result = 0;
+
+  if (dst == NULL)
+    return 0;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_REL))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_Rel *rel;
+
+      /* There is the possibility that the values in the input are
+	 too large.  */
+      if (unlikely (src->r_offset > 0xffffffffull)
+	  || unlikely (GELF_R_SYM (src->r_info) > 0xffffff)
+	  || unlikely (GELF_R_TYPE (src->r_info) > 0xff))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf32_Rel, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      rel = &((Elf32_Rel *) data_scn->d.d_buf)[ndx];
+
+      rel->r_offset = src->r_offset;
+      rel->r_info = ELF32_R_INFO (GELF_R_SYM (src->r_info),
+				  GELF_R_TYPE (src->r_info));
+    }
+  else
+    {
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf64_Rel, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      ((Elf64_Rel *) data_scn->d.d_buf)[ndx] = *src;
+    }
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_rela.c b/libelf/gelf_update_rela.c
new file mode 100644
index 0000000..8825270
--- /dev/null
+++ b/libelf/gelf_update_rela.c
@@ -0,0 +1,111 @@
+/* Update RELA relocation information at given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_rela (Elf_Data *dst, int ndx, GElf_Rela *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) dst;
+  Elf_Scn *scn;
+  int result = 0;
+
+  if (dst == NULL)
+    return 0;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_RELA))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_Rela *rel;
+
+      /* There is the possibility that the values in the input are
+	 too large.  */
+      if (unlikely (src->r_offset > 0xffffffffull)
+	  || unlikely (GELF_R_SYM (src->r_info) > 0xffffff)
+	  || unlikely (GELF_R_TYPE (src->r_info) > 0xff)
+	  || unlikely (src->r_addend < -0x80000000ll)
+	  || unlikely (src->r_addend > 0x7fffffffll))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf32_Rela, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      rel = &((Elf32_Rela *) data_scn->d.d_buf)[ndx];
+
+      rel->r_offset = src->r_offset;
+      rel->r_info = ELF32_R_INFO (GELF_R_SYM (src->r_info),
+				  GELF_R_TYPE (src->r_info));
+      rel->r_addend = src->r_addend;
+    }
+  else
+    {
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf64_Rela, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      ((Elf64_Rela *) data_scn->d.d_buf)[ndx] = *src;
+    }
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_shdr.c b/libelf/gelf_update_shdr.c
new file mode 100644
index 0000000..c93c6ec
--- /dev/null
+++ b/libelf/gelf_update_shdr.c
@@ -0,0 +1,111 @@
+/* Update section header.
+   Copyright (C) 2000, 2001, 2002, 2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_shdr (Elf_Scn *scn, GElf_Shdr *src)
+{
+  int result = 0;
+  Elf *elf;
+
+  if (scn == NULL || src == NULL)
+    return 0;
+
+  elf = scn->elf;
+  rwlock_wrlock (elf->lock);
+
+  if (elf->class == ELFCLASS32)
+    {
+      Elf32_Shdr *shdr
+	= scn->shdr.e32 ?: __elf32_getshdr_wrlock (scn);
+
+      if (shdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_OPERAND);
+	  goto out;
+	}
+
+      if (unlikely (src->sh_flags > 0xffffffffull)
+	  || unlikely (src->sh_addr > 0xffffffffull)
+	  || unlikely (src->sh_offset > 0xffffffffull)
+	  || unlikely (src->sh_size > 0xffffffffull)
+	  || unlikely (src->sh_addralign > 0xffffffffull)
+	  || unlikely (src->sh_entsize > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+#define COPY(name) \
+      shdr->name = src->name
+      COPY (sh_name);
+      COPY (sh_type);
+      COPY (sh_flags);
+      COPY (sh_addr);
+      COPY (sh_offset);
+      COPY (sh_size);
+      COPY (sh_link);
+      COPY (sh_info);
+      COPY (sh_addralign);
+      COPY (sh_entsize);
+    }
+  else
+    {
+      Elf64_Shdr *shdr
+	= scn->shdr.e64 ?: __elf64_getshdr_wrlock (scn);
+
+      if (shdr == NULL)
+	{
+	  __libelf_seterrno (ELF_E_INVALID_OPERAND);
+	  goto out;
+	}
+
+      /* We only have to copy the data.  */
+      (void) memcpy (shdr, src, sizeof (GElf_Shdr));
+    }
+
+  /* Mark the section header as modified.  */
+  scn->shdr_flags |= ELF_F_DIRTY;
+
+  result = 1;
+
+ out:
+  rwlock_unlock (elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_sym.c b/libelf/gelf_update_sym.c
new file mode 100644
index 0000000..0f47885
--- /dev/null
+++ b/libelf/gelf_update_sym.c
@@ -0,0 +1,116 @@
+/* Update symbol information in symbol table at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_sym (Elf_Data *data, int ndx, GElf_Sym *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  int result = 0;
+
+  if (data == NULL)
+    return 0;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_SYM))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_Sym *sym;
+
+      /* There is the possibility that the values in the input are
+	 too large.  */
+      if (unlikely (src->st_value > 0xffffffffull)
+	  || unlikely (src->st_size > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf32_Sym, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      sym = &((Elf32_Sym *) data_scn->d.d_buf)[ndx];
+
+#define COPY(name) \
+      sym->name = src->name
+      COPY (st_name);
+      COPY (st_value);
+      COPY (st_size);
+      /* Please note that we can simply copy the `st_info' element since
+	 the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same
+	 for the 64 bit variant.  */
+      COPY (st_info);
+      COPY (st_other);
+      COPY (st_shndx);
+    }
+  else
+    {
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf64_Sym, &data_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      ((Elf64_Sym *) data_scn->d.d_buf)[ndx] = *src;
+    }
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_syminfo.c b/libelf/gelf_update_syminfo.c
new file mode 100644
index 0000000..6f7f302
--- /dev/null
+++ b/libelf/gelf_update_syminfo.c
@@ -0,0 +1,83 @@
+/* Update additional symbol information in symbol table at the given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_syminfo (Elf_Data *data, int ndx, GElf_Syminfo *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+  Elf_Scn *scn;
+  int result = 0;
+
+  if (data == NULL)
+    return 0;
+
+  if (unlikely (data_scn->d.d_type != ELF_T_SYMINFO))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Syminfo) == sizeof (Elf32_Syminfo));
+  assert (sizeof (GElf_Syminfo) == sizeof (Elf64_Syminfo));
+
+  scn = data_scn->s;
+  rwlock_wrlock (scn->elf->lock);
+
+  /* Check whether we have to resize the data buffer.  */
+  if (INVALID_NDX (ndx, GElf_Syminfo, &data_scn->d))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      goto out;
+    }
+
+  ((GElf_Syminfo *) data_scn->d.d_buf)[ndx] = *src;
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_symshndx.c b/libelf/gelf_update_symshndx.c
new file mode 100644
index 0000000..eb80afa
--- /dev/null
+++ b/libelf/gelf_update_symshndx.c
@@ -0,0 +1,145 @@
+/* Update symbol information and section index in symbol table at the
+   given index.
+   Copyright (C) 2000, 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_symshndx (Elf_Data *symdata, Elf_Data *shndxdata, int ndx,
+		      GElf_Sym *src, Elf32_Word srcshndx)
+{
+  Elf_Data_Scn *symdata_scn = (Elf_Data_Scn *) symdata;
+  Elf_Data_Scn *shndxdata_scn = (Elf_Data_Scn *) shndxdata;
+  Elf_Scn *scn;
+  Elf32_Word *shndx = NULL;
+  int result = 0;
+
+  if (symdata == NULL)
+    return 0;
+
+  if (unlikely (symdata_scn->d.d_type != ELF_T_SYM))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  scn = symdata_scn->s;
+  /* We simply have to believe the user that the two sections belong to
+     the same ELF file.  */
+  rwlock_wrlock (scn->elf->lock);
+
+  /* The user is not required to pass a data descriptor for an extended
+     section index table.  */
+  if (shndxdata_scn != NULL)
+    {
+      if (unlikely ((ndx + 1) * sizeof (Elf32_Word) > shndxdata_scn->d.d_size))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      shndx = &((Elf32_Word *) shndxdata_scn->d.d_buf)[ndx];
+    }
+  /* But if s/he does not the extended sectio index must be zero.  */
+  else if (unlikely (srcshndx != 0))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      goto out;
+    }
+
+  if (scn->elf->class == ELFCLASS32)
+    {
+      Elf32_Sym *sym;
+
+      /* There is the possibility that the values in the input are
+	 too large.  */
+      if (unlikely (src->st_value > 0xffffffffull)
+	  || unlikely (src->st_size > 0xffffffffull))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_DATA);
+	  goto out;
+	}
+
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf32_Sym, &symdata_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      sym = &((Elf32_Sym *) symdata_scn->d.d_buf)[ndx];
+
+#define COPY(name) \
+      sym->name = src->name
+      COPY (st_name);
+      COPY (st_value);
+      COPY (st_size);
+      /* Please note that we can simply copy the `st_info' element since
+	 the definitions of ELFxx_ST_BIND and ELFxx_ST_TYPE are the same
+	 for the 64 bit variant.  */
+      COPY (st_info);
+      COPY (st_other);
+      COPY (st_shndx);
+    }
+  else
+    {
+      /* Check whether we have to resize the data buffer.  */
+      if (INVALID_NDX (ndx, Elf64_Sym, &symdata_scn->d))
+	{
+	  __libelf_seterrno (ELF_E_INVALID_INDEX);
+	  goto out;
+	}
+
+      ((Elf64_Sym *) symdata_scn->d.d_buf)[ndx] = *src;
+    }
+
+  /* Now we can store the section index.  */
+  if (shndx != NULL)
+    *shndx = srcshndx;
+
+  result = 1;
+
+  /* Mark the section as modified.  */
+  scn->flags |= ELF_F_DIRTY;
+
+ out:
+  rwlock_unlock (scn->elf->lock);
+
+  return result;
+}
diff --git a/libelf/gelf_update_verdaux.c b/libelf/gelf_update_verdaux.c
new file mode 100644
index 0000000..f3554fd
--- /dev/null
+++ b/libelf/gelf_update_verdaux.c
@@ -0,0 +1,78 @@
+/* Update additional symbol version definition information.
+   Copyright (C) 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_verdaux (Elf_Data *data, int offset, GElf_Verdaux *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  if (data == NULL)
+    return 0;
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
+  assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
+
+  /* Check whether we have to resize the data buffer.  */
+  if (unlikely (offset < 0)
+      || unlikely ((offset + sizeof (GElf_Verdaux)) > data_scn->d.d_size))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_VDEF))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  rwlock_wrlock (data_scn->s->elf->lock);
+
+  memcpy ((char *) data_scn->d.d_buf + offset, src, sizeof (GElf_Verdaux));
+
+  /* Mark the section as modified.  */
+  data_scn->s->flags |= ELF_F_DIRTY;
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return 1;
+}
diff --git a/libelf/gelf_update_verdef.c b/libelf/gelf_update_verdef.c
new file mode 100644
index 0000000..adb5db1
--- /dev/null
+++ b/libelf/gelf_update_verdef.c
@@ -0,0 +1,78 @@
+/* Update symbol version definition information.
+   Copyright (C) 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_verdef (Elf_Data *data, int offset, GElf_Verdef *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  if (data == NULL)
+    return 0;
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
+  assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
+
+  /* Check whether we have to resize the data buffer.  */
+  if (unlikely (offset < 0)
+      || unlikely ((offset + sizeof (GElf_Verdef)) > data_scn->d.d_size))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_VDEF))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  rwlock_wrlock (data_scn->s->elf->lock);
+
+  memcpy ((char *) data_scn->d.d_buf + offset, src, sizeof (GElf_Verdef));
+
+  /* Mark the section as modified.  */
+  data_scn->s->flags |= ELF_F_DIRTY;
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return 1;
+}
diff --git a/libelf/gelf_update_vernaux.c b/libelf/gelf_update_vernaux.c
new file mode 100644
index 0000000..854afab
--- /dev/null
+++ b/libelf/gelf_update_vernaux.c
@@ -0,0 +1,78 @@
+/* Update additional required symbol version information.
+   Copyright (C) 2001, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_vernaux (Elf_Data *data, int offset, GElf_Vernaux *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  if (data == NULL)
+    return 0;
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
+
+  /* Check whether we have to resize the data buffer.  */
+  if (unlikely (offset < 0)
+      || unlikely ((offset + sizeof (GElf_Vernaux)) > data_scn->d.d_size))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_VNEED))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  rwlock_wrlock (data_scn->s->elf->lock);
+
+  memcpy ((char *) data_scn->d.d_buf + offset, src, sizeof (GElf_Vernaux));
+
+  /* Mark the section as modified.  */
+  data_scn->s->flags |= ELF_F_DIRTY;
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return 1;
+}
diff --git a/libelf/gelf_update_verneed.c b/libelf/gelf_update_verneed.c
new file mode 100644
index 0000000..bf5af5a
--- /dev/null
+++ b/libelf/gelf_update_verneed.c
@@ -0,0 +1,78 @@
+/* Update required symbol version information.
+   Copyright (C) 2001, 2002, 201r Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <string.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_verneed (Elf_Data *data, int offset, GElf_Verneed *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  if (data == NULL)
+    return 0;
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
+  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
+
+  /* Check whether we have to resize the data buffer.  */
+  if (unlikely (offset < 0)
+      || unlikely ((offset + sizeof (GElf_Verneed)) > data_scn->d.d_size))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_VNEED))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  rwlock_wrlock (data_scn->s->elf->lock);
+
+  memcpy ((char *) data_scn->d.d_buf + offset, src, sizeof (GElf_Verneed));
+
+  /* Mark the section as modified.  */
+  data_scn->s->flags |= ELF_F_DIRTY;
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return 1;
+}
diff --git a/libelf/gelf_update_versym.c b/libelf/gelf_update_versym.c
new file mode 100644
index 0000000..9949dff
--- /dev/null
+++ b/libelf/gelf_update_versym.c
@@ -0,0 +1,77 @@
+/* Update symbol version information.
+   Copyright (C) 2001, 2002, 2005, 2009, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+
+int
+gelf_update_versym (Elf_Data *data, int ndx, GElf_Versym *src)
+{
+  Elf_Data_Scn *data_scn = (Elf_Data_Scn *) data;
+
+  if (data == NULL)
+    return 0;
+
+  /* The types for 32 and 64 bit are the same.  Lucky us.  */
+  assert (sizeof (GElf_Versym) == sizeof (Elf32_Versym));
+  assert (sizeof (GElf_Versym) == sizeof (Elf64_Versym));
+
+  /* Check whether we have to resize the data buffer.  */
+  if (INVALID_NDX (ndx, GElf_Versym, &data_scn->d))
+    {
+      __libelf_seterrno (ELF_E_INVALID_INDEX);
+      return 0;
+    }
+
+  if (unlikely (data_scn->d.d_type != ELF_T_HALF))
+    {
+      /* The type of the data better should match.  */
+      __libelf_seterrno (ELF_E_DATA_MISMATCH);
+      return 0;
+    }
+
+  rwlock_wrlock (data_scn->s->elf->lock);
+
+  ((GElf_Versym *) data_scn->d.d_buf)[ndx] = *src;
+
+  /* Mark the section as modified.  */
+  data_scn->s->flags |= ELF_F_DIRTY;
+
+  rwlock_unlock (data_scn->s->elf->lock);
+
+  return 1;
+}
diff --git a/libelf/gelf_xlate.c b/libelf/gelf_xlate.c
new file mode 100644
index 0000000..749da1a
--- /dev/null
+++ b/libelf/gelf_xlate.c
@@ -0,0 +1,216 @@
+/* Transformation functions for ELF data types.
+   Copyright (C) 1998,1999,2000,2002,2004,2005,2006,2007,2015 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "libelfP.h"
+
+#ifndef LIBELFBITS
+# define LIBELFBITS	32
+#endif
+
+
+/* Well, what shall I say.  Nothing to do here.  */
+#define elf_cvt_Byte(dest, src, n) \
+  (__builtin_constant_p (n) && (n) == 1					      \
+   ? (void) (*((char *) (dest)) = *((char *) (src)))			      \
+   : Elf32_cvt_Byte (dest, src, n))
+static void
+(elf_cvt_Byte) (void *dest, const void *src, size_t n,
+		int encode __attribute__ ((unused)))
+{
+  if (n != 0)
+    memmove (dest, src, n);
+}
+
+
+/* We'll optimize the definition of the conversion functions here a
+   bit.  We need only functions for 16, 32, and 64 bits.  The
+   functions referenced in the table will be aliases for one of these
+   functions.  Which one is decided by the ELFxx_FSZ_type.  */
+
+#if ALLOW_UNALIGNED
+
+#define FETCH(Bits, ptr)	(*(const uint##Bits##_t *) ptr)
+#define STORE(Bits, ptr, val)	(*(uint##Bits##_t *) ptr = val)
+
+#else
+
+union unaligned
+  {
+    uint16_t u16;
+    uint32_t u32;
+    uint64_t u64;
+  } attribute_packed;
+
+#define FETCH(Bits, ptr)	(((const union unaligned *) ptr)->u##Bits)
+#define STORE(Bits, ptr, val)	(((union unaligned *) ptr)->u##Bits = val)
+
+#endif
+
+/* Now define the conversion functions for the basic types.  We use here
+   the fact that file and memory types are the same and that we have the
+   ELFxx_FSZ_* macros.
+
+   At the same time we define inline functions which we will use to
+   convert the complex types.  */
+#define FUNDAMENTAL(NAME, Name, Bits) \
+  INLINE2 (ELFW2(Bits,FSZ_##NAME), ElfW2(Bits,cvt_##Name), ElfW2(Bits,Name))
+#define INLINE2(Bytes, FName, TName) \
+  INLINE3 (Bytes, FName, TName)
+#define INLINE3(Bytes, FName, TName)					      \
+  static inline void FName##1 (void *dest, const void *ptr)		      \
+  {									      \
+    switch (Bytes)							      \
+      {									      \
+      case 2: STORE (16, dest, bswap_16 (FETCH (16, ptr))); break;	      \
+      case 4: STORE (32, dest, bswap_32 (FETCH (32, ptr))); break;	      \
+      case 8: STORE (64, dest, bswap_64 (FETCH (64, ptr))); break;	      \
+      default:								      \
+	abort ();							      \
+      }									      \
+  }									      \
+									      \
+  static void FName (void *dest, const void *ptr, size_t len,		      \
+		     int encode __attribute__ ((unused)))		      \
+  {									      \
+    size_t n = len / sizeof (TName);					      \
+    if (dest < ptr)							      \
+      while (n-- > 0)							      \
+	{								      \
+	  FName##1 (dest, ptr);						      \
+	  dest += Bytes;						      \
+	  ptr += Bytes;							      \
+	}								      \
+    else								      \
+      {									      \
+	dest += len;							      \
+	ptr += len;							      \
+	while (n-- > 0)							      \
+	  {								      \
+	    ptr -= Bytes;						      \
+	    dest -= Bytes;						      \
+	    FName##1 (dest, ptr);					      \
+	  }								      \
+      }									      \
+  }
+
+
+/* Now the tricky part: define the transformation functions for the
+   complex types.  We will use the definitions of the types in
+   abstract.h.  */
+#define START(Bits, Name, EName) \
+  static void								      \
+  ElfW2 (Bits, cvt_##Name) (void *dest, const void *src, size_t len,	      \
+			    int encode __attribute__ ((unused)))	      \
+  { ElfW2(Bits, Name) *tdest = (ElfW2(Bits, Name) *) dest;		      \
+    ElfW2(Bits, Name) *tsrc = (ElfW2(Bits, Name) *) src;		      \
+    size_t sz = sizeof (ElfW2(Bits, Name));				      \
+    size_t n;								      \
+    for (n = len / sz; n > 0; ++tdest, ++tsrc, --n) {
+#define END(Bits, Name)							      \
+    }									      \
+    if (len % sz > 0) /* Cannot convert partial structures, just copy. */     \
+      memmove (dest, src, len % sz);					      \
+  }
+#define TYPE_EXTRA(Code)
+#define TYPE_XLATE(Code) Code
+#define TYPE_NAME(Type, Name) TYPE_NAME2 (Type, Name)
+#define TYPE_NAME2(Type, Name) Type##1 (&tdest->Name, &tsrc->Name);
+#define TYPE(Name, Bits) TYPE2 (Name, Bits)
+#define TYPE2(Name, Bits) TYPE3 (Name##Bits)
+#define TYPE3(Name) Name (cvt_)
+
+/* Signal that we are generating conversion functions.  */
+#define GENERATE_CONVERSION
+
+/* First generate the 32-bit conversion functions.  */
+#define LIBELFBITS 32
+#include "gelf_xlate.h"
+
+/* Now generate the 64-bit conversion functions.  */
+#define LIBELFBITS 64
+#include "gelf_xlate.h"
+
+
+/* We have a few functions which we must create by hand since the sections
+   do not contain records of only one type.  */
+#include "version_xlate.h"
+#include "gnuhash_xlate.h"
+#include "note_xlate.h"
+#include "chdr_xlate.h"
+
+
+/* Now the externally visible table with the function pointers.  */
+const xfct_t __elf_xfctstom[ELFCLASSNUM - 1][ELF_T_NUM] =
+{
+      [ELFCLASS32 - 1] = {
+#define define_xfcts(Bits) \
+	[ELF_T_BYTE]	= elf_cvt_Byte,					      \
+	[ELF_T_ADDR]	= ElfW2(Bits, cvt_Addr),			      \
+	[ELF_T_DYN]	= ElfW2(Bits, cvt_Dyn),				      \
+	[ELF_T_EHDR]	= ElfW2(Bits, cvt_Ehdr),			      \
+	[ELF_T_HALF]	= ElfW2(Bits, cvt_Half),			      \
+	[ELF_T_OFF]	= ElfW2(Bits, cvt_Off),				      \
+	[ELF_T_PHDR]	= ElfW2(Bits, cvt_Phdr),			      \
+	[ELF_T_RELA]	= ElfW2(Bits, cvt_Rela),			      \
+	[ELF_T_REL]	= ElfW2(Bits, cvt_Rel),				      \
+	[ELF_T_SHDR]	= ElfW2(Bits, cvt_Shdr),			      \
+	[ELF_T_SWORD]	= ElfW2(Bits, cvt_Sword),			      \
+	[ELF_T_SYM]	= ElfW2(Bits, cvt_Sym),				      \
+	[ELF_T_WORD]	= ElfW2(Bits, cvt_Word),			      \
+	[ELF_T_XWORD]	= ElfW2(Bits, cvt_Xword),			      \
+	[ELF_T_SXWORD]	= ElfW2(Bits, cvt_Sxword),			      \
+	[ELF_T_VDEF]	= elf_cvt_Verdef,				      \
+	[ELF_T_VDAUX]	= elf_cvt_Verdef,				      \
+	[ELF_T_VNEED]	= elf_cvt_Verneed,				      \
+	[ELF_T_VNAUX]	= elf_cvt_Verneed,				      \
+	[ELF_T_NHDR]	= elf_cvt_note4,				      \
+	[ELF_T_NHDR8]	= elf_cvt_note8,				      \
+	[ELF_T_SYMINFO] = ElfW2(Bits, cvt_Syminfo),			      \
+	[ELF_T_MOVE]	= ElfW2(Bits, cvt_Move),			      \
+	[ELF_T_LIB]	= ElfW2(Bits, cvt_Lib),				      \
+	[ELF_T_AUXV]	= ElfW2(Bits, cvt_auxv_t),			      \
+	[ELF_T_CHDR]	= ElfW2(Bits, cvt_chdr),			      \
+	[ELF_T_RELR]	= ElfW2(Bits, cvt_Relr)
+        define_xfcts (32),
+	[ELF_T_GNUHASH] = Elf32_cvt_Word
+      },
+      [ELFCLASS64 - 1] = {
+	define_xfcts (64),
+	[ELF_T_GNUHASH] = elf_cvt_gnuhash
+      }
+};
diff --git a/libelf/gelf_xlate.h b/libelf/gelf_xlate.h
new file mode 100644
index 0000000..d5511c3
--- /dev/null
+++ b/libelf/gelf_xlate.h
@@ -0,0 +1,58 @@
+/* Helper file for type conversion function generation.
+   Copyright (C) 1998, 1999, 2000, 2002, 2004, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+
+/* Simple types.  */
+FUNDAMENTAL (ADDR, Addr, LIBELFBITS);
+FUNDAMENTAL (OFF, Off, LIBELFBITS);
+FUNDAMENTAL (HALF, Half, LIBELFBITS);
+FUNDAMENTAL (WORD, Word, LIBELFBITS);
+FUNDAMENTAL (SWORD, Sword, LIBELFBITS);
+FUNDAMENTAL (XWORD, Xword, LIBELFBITS);
+FUNDAMENTAL (SXWORD, Sxword, LIBELFBITS);
+FUNDAMENTAL (RELR, Relr, LIBELFBITS);
+
+/* The structured types.  */
+TYPE (Ehdr, LIBELFBITS)
+TYPE (Phdr, LIBELFBITS)
+TYPE (Shdr, LIBELFBITS)
+TYPE (Sym, LIBELFBITS)
+TYPE (Rel, LIBELFBITS)
+TYPE (Rela, LIBELFBITS)
+TYPE (Note, LIBELFBITS)
+TYPE (Dyn, LIBELFBITS)
+TYPE (Syminfo, LIBELFBITS)
+TYPE (Move, LIBELFBITS)
+TYPE (Lib, LIBELFBITS)
+TYPE (auxv_t, LIBELFBITS)
+TYPE (Chdr, LIBELFBITS)
+
+
+/* Prepare for the next round.  */
+#undef LIBELFBITS
diff --git a/libelf/gelf_xlatetof.c b/libelf/gelf_xlatetof.c
new file mode 100644
index 0000000..e266180
--- /dev/null
+++ b/libelf/gelf_xlatetof.c
@@ -0,0 +1,50 @@
+/* Convert from memory to file representation.  Generic ELF version.
+   Copyright (C) 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf_Data *
+gelf_xlatetof (Elf *elf, Elf_Data *dest, const Elf_Data * src,
+	       unsigned int encode)
+{
+  if (elf == NULL)
+    return NULL;
+
+  return (elf->class == ELFCLASS32
+	  ? INTUSE(elf32_xlatetof) (dest, src, encode)
+	  : INTUSE(elf64_xlatetof) (dest, src, encode));
+}
diff --git a/libelf/gelf_xlatetom.c b/libelf/gelf_xlatetom.c
new file mode 100644
index 0000000..8499c71
--- /dev/null
+++ b/libelf/gelf_xlatetom.c
@@ -0,0 +1,50 @@
+/* Convert from file to memory representation.  Generic ELF version.
+   Copyright (C) 2000, 2002, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <gelf.h>
+#include <stddef.h>
+
+#include "libelfP.h"
+
+
+Elf_Data *
+gelf_xlatetom (Elf *elf, Elf_Data *dest, const Elf_Data * src,
+	       unsigned int encode)
+{
+  if (elf == NULL)
+    return NULL;
+
+  return (elf->class == ELFCLASS32
+	  ? INTUSE(elf32_xlatetom) (dest, src, encode)
+	  : INTUSE(elf64_xlatetom) (dest, src, encode));
+}
diff --git a/libelf/gnuhash_xlate.h b/libelf/gnuhash_xlate.h
new file mode 100644
index 0000000..3a00ae0
--- /dev/null
+++ b/libelf/gnuhash_xlate.h
@@ -0,0 +1,82 @@
+/* Conversion functions for versioning information.
+   Copyright (C) 2006, 2007 Red Hat, Inc.
+   Copyright (C) 2023, Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2006.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <gelf.h>
+
+#include "libelfP.h"
+
+
+static void
+elf_cvt_gnuhash (void *dest, const void *src, size_t len, int encode)
+{
+  size_t size = len;
+  /* The GNU hash table format on 64 bit machines mixes 32 bit and 64 bit
+     words.  We must detangle them here.   */
+  Elf32_Word *dest32 = dest;
+  const Elf32_Word *src32 = src;
+
+  /* First four control words, 32 bits.  */
+  for (unsigned int cnt = 0; cnt < 4; ++cnt)
+    {
+      if (len < 4)
+	goto done;
+      dest32[cnt] = bswap_32 (src32[cnt]);
+      len -= 4;
+    }
+
+  Elf32_Word bitmask_words = encode ? src32[2] : dest32[2];
+
+  /* Now the 64 bit words.  */
+  Elf64_Xword *dest64 = (Elf64_Xword *) &dest32[4];
+  const Elf64_Xword *src64 = (const Elf64_Xword *) &src32[4];
+  for (unsigned int cnt = 0; cnt < bitmask_words; ++cnt)
+    {
+      if (len < 8)
+	goto done;
+      dest64[cnt] = bswap_64 (src64[cnt]);
+      len -= 8;
+    }
+
+  /* The rest are 32 bit words again.  */
+  src32 = (const Elf32_Word *) &src64[bitmask_words];
+  dest32 = (Elf32_Word *) &dest64[bitmask_words];
+  while (len >= 4)
+    {
+      *dest32++ = bswap_32 (*src32++);
+      len -= 4;
+    }
+
+ done:
+  /* If there are any bytes left, we weren't able to convert the
+     partial structures, just copy them over. */
+  if (len > 0)
+    memmove (dest + size - len, src + size - len, len);
+}
diff --git a/libelf/libelf.h b/libelf/libelf.h
new file mode 100644
index 0000000..d3f057b
--- /dev/null
+++ b/libelf/libelf.h
@@ -0,0 +1,541 @@
+/* Interface for libelf.
+   Copyright (C) 1998-2010, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBELF_H
+#define _LIBELF_H 1
+
+#include <stdint.h>
+#include <sys/types.h>
+
+/* Get the ELF types.  */
+#include <elf.h>
+
+#ifndef SHF_COMPRESSED
+ /* Older glibc elf.h might not yet define the ELF compression types.  */
+ #define SHF_COMPRESSED      (1 << 11)  /* Section with compressed data. */
+
+ /* Section compression header.  Used when SHF_COMPRESSED is set.  */
+
+ typedef struct
+ {
+   Elf32_Word   ch_type;        /* Compression format.  */
+   Elf32_Word   ch_size;        /* Uncompressed data size.  */
+   Elf32_Word   ch_addralign;   /* Uncompressed data alignment.  */
+ } Elf32_Chdr;
+
+ typedef struct
+ {
+   Elf64_Word   ch_type;        /* Compression format.  */
+   Elf64_Word   ch_reserved;
+   Elf64_Xword  ch_size;        /* Uncompressed data size.  */
+   Elf64_Xword  ch_addralign;   /* Uncompressed data alignment.  */
+ } Elf64_Chdr;
+
+ /* Legal values for ch_type (compression algorithm).  */
+ #define ELFCOMPRESS_ZLIB       1          /* ZLIB/DEFLATE algorithm.  */
+ #define ELFCOMPRESS_LOOS       0x60000000 /* Start of OS-specific.  */
+ #define ELFCOMPRESS_HIOS       0x6fffffff /* End of OS-specific.  */
+ #define ELFCOMPRESS_LOPROC     0x70000000 /* Start of processor-specific.  */
+ #define ELFCOMPRESS_HIPROC     0x7fffffff /* End of processor-specific.  */
+#endif
+
+#ifndef ELFCOMPRESS_ZSTD
+ /* So ZSTD compression can be used even with an old system elf.h.  */
+ #define ELFCOMPRESS_ZSTD       2          /* Zstandard algorithm.  */
+#endif
+
+#ifndef SHT_RELR
+ /* So RELR defines/typedefs can be used even with an old system elf.h.  */
+ #define SHT_RELR       19      /* RELR relative relocations */
+
+ /* RELR relocation table entry */
+ typedef Elf32_Word     Elf32_Relr;
+ typedef Elf64_Xword    Elf64_Relr;
+
+ #define DT_RELRSZ      35      /* Total size of RELR relative relocations */
+ #define DT_RELR        36      /* Address of RELR relative relocations */
+ #define DT_RELRENT     37      /* Size of one RELR relative relocaction */
+#endif
+
+#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 3)
+# define __nonnull_attribute__(...) __attribute__ ((__nonnull__ (__VA_ARGS__)))
+# define __deprecated_attribute__ __attribute__ ((__deprecated__))
+# define __pure_attribute__ __attribute__ ((__pure__))
+# define __const_attribute__ __attribute__ ((__const__))
+#else
+# define __nonnull_attribute__(...)
+# define __deprecated_attribute__
+# define __pure_attribute__
+# define __const_attribute__
+#endif
+
+#if __GNUC__ < 4
+#define __noreturn_attribute__
+#else
+#define __noreturn_attribute__ __attribute__ ((noreturn))
+#endif
+
+#ifdef __GNUC_STDC_INLINE__
+# define __libdw_extern_inline extern __inline __attribute__ ((__gnu_inline__))
+#else
+# define __libdw_extern_inline extern __inline
+#endif
+
+/* Known translation types.  */
+typedef enum
+{
+  ELF_T_BYTE,                   /* unsigned char */
+  ELF_T_ADDR,                   /* Elf32_Addr, Elf64_Addr, ... */
+  ELF_T_DYN,                    /* Dynamic section record.  */
+  ELF_T_EHDR,                   /* ELF header.  */
+  ELF_T_HALF,                   /* Elf32_Half, Elf64_Half, ... */
+  ELF_T_OFF,                    /* Elf32_Off, Elf64_Off, ... */
+  ELF_T_PHDR,                   /* Program header.  */
+  ELF_T_RELA,                   /* Relocation entry with addend.  */
+  ELF_T_REL,                    /* Relocation entry.  */
+  ELF_T_SHDR,                   /* Section header.  */
+  ELF_T_SWORD,                  /* Elf32_Sword, Elf64_Sword, ... */
+  ELF_T_SYM,                    /* Symbol record.  */
+  ELF_T_WORD,                   /* Elf32_Word, Elf64_Word, ... */
+  ELF_T_XWORD,                  /* Elf32_Xword, Elf64_Xword, ... */
+  ELF_T_SXWORD,                 /* Elf32_Sxword, Elf64_Sxword, ... */
+  ELF_T_VDEF,                   /* Elf32_Verdef, Elf64_Verdef, ... */
+  ELF_T_VDAUX,                  /* Elf32_Verdaux, Elf64_Verdaux, ... */
+  ELF_T_VNEED,                  /* Elf32_Verneed, Elf64_Verneed, ... */
+  ELF_T_VNAUX,                  /* Elf32_Vernaux, Elf64_Vernaux, ... */
+  ELF_T_NHDR,                   /* Elf32_Nhdr, Elf64_Nhdr, ... */
+  ELF_T_SYMINFO,		/* Elf32_Syminfo, Elf64_Syminfo, ... */
+  ELF_T_MOVE,			/* Elf32_Move, Elf64_Move, ... */
+  ELF_T_LIB,			/* Elf32_Lib, Elf64_Lib, ... */
+  ELF_T_GNUHASH,		/* GNU-style hash section.  */
+  ELF_T_AUXV,			/* Elf32_auxv_t, Elf64_auxv_t, ... */
+  ELF_T_CHDR,			/* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
+  ELF_T_NHDR8,			/* Special GNU Properties note.  Same as Nhdr,
+				   except padding.  */
+  ELF_T_RELR,			/* Relative relocation entry.  */
+  /* Keep this the last entry.  */
+  ELF_T_NUM
+} Elf_Type;
+
+/* Descriptor for data to be converted to or from memory format.  */
+typedef struct
+{
+  void *d_buf;			/* Pointer to the actual data.  */
+  Elf_Type d_type;		/* Type of this piece of data.  */
+  unsigned int d_version;	/* ELF version.  */
+  size_t d_size;		/* Size in bytes.  */
+  int64_t d_off;		/* Offset into section.  */
+  size_t d_align;		/* Alignment in section.  */
+} Elf_Data;
+
+
+/* Commands for `...'.  */
+typedef enum
+{
+  ELF_C_NULL,			/* Nothing, terminate, or compute only.  */
+  ELF_C_READ,			/* Read .. */
+  ELF_C_RDWR,			/* Read and write .. */
+  ELF_C_WRITE,			/* Write .. */
+  ELF_C_CLR,			/* Clear flag.  */
+  ELF_C_SET,			/* Set flag.  */
+  ELF_C_FDDONE,			/* Signal that file descriptor will not be
+				   used anymore.  */
+  ELF_C_FDREAD,			/* Read rest of data so that file descriptor
+				   is not used anymore.  */
+  /* The following are extensions.  */
+  ELF_C_READ_MMAP,		/* Read, but mmap the file if possible.  */
+  ELF_C_RDWR_MMAP,		/* Read and write, with mmap.  */
+  ELF_C_WRITE_MMAP,		/* Write, with mmap.  */
+  ELF_C_READ_MMAP_PRIVATE,	/* Read, but memory is writable, results are
+				   not written to the file.  */
+  ELF_C_EMPTY,			/* Copy basic file data but not the content. */
+  /* Keep this the last entry.  */
+  ELF_C_NUM
+} Elf_Cmd;
+
+
+/* Flags for the ELF structures.  */
+enum
+{
+  ELF_F_DIRTY = 0x1,
+#define ELF_F_DIRTY		ELF_F_DIRTY
+  ELF_F_LAYOUT = 0x4,
+#define ELF_F_LAYOUT		ELF_F_LAYOUT
+  ELF_F_PERMISSIVE = 0x8
+#define ELF_F_PERMISSIVE	ELF_F_PERMISSIVE
+};
+
+/* Flags for elf_compress[_gnu].  */
+enum
+{
+  ELF_CHF_FORCE = 0x1
+#define ELF_CHF_FORCE ELF_CHF_FORCE
+};
+
+/* Identification values for recognized object files.  */
+typedef enum
+{
+  ELF_K_NONE,			/* Unknown.  */
+  ELF_K_AR,			/* Archive.  */
+  ELF_K_COFF,			/* Stupid old COFF.  */
+  ELF_K_ELF,			/* ELF file.  */
+  /* Keep this the last entry.  */
+  ELF_K_NUM
+} Elf_Kind;
+
+
+/* Archive member header.  */
+typedef struct
+{
+  char *ar_name;		/* Name of archive member.  */
+  time_t ar_date;		/* File date.  */
+  uid_t ar_uid;			/* User ID.  */
+  gid_t ar_gid;			/* Group ID.  */
+  mode_t ar_mode;		/* File mode.  */
+  int64_t ar_size;		/* File size.  */
+  char *ar_rawname;		/* Original name of archive member.  */
+} Elf_Arhdr;
+
+
+/* Archive symbol table entry.  */
+typedef struct
+{
+  char *as_name;		/* Symbol name.  */
+  size_t as_off;		/* Offset for this file in the archive.  */
+  unsigned long int as_hash;	/* Hash value of the name.  */
+} Elf_Arsym;
+
+
+/* Descriptor for the ELF file.  */
+typedef struct Elf Elf;
+
+/* Descriptor for ELF file section.  */
+typedef struct Elf_Scn Elf_Scn;
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Return descriptor for ELF file to work according to CMD.  */
+extern Elf *elf_begin (int __fildes, Elf_Cmd __cmd, Elf *__ref);
+
+/* Create a clone of an existing ELF descriptor.  */
+  extern Elf *elf_clone (Elf *__elf, Elf_Cmd __cmd);
+
+/* Create descriptor for memory region.  */
+extern Elf *elf_memory (char *__image, size_t __size);
+
+/* Advance archive descriptor to next element.  */
+extern Elf_Cmd elf_next (Elf *__elf);
+
+/* Free resources allocated for ELF.  */
+extern int elf_end (Elf *__elf);
+
+/* Update ELF descriptor and write file to disk.  */
+extern int64_t elf_update (Elf *__elf, Elf_Cmd __cmd);
+
+/* Determine what kind of file is associated with ELF.  */
+extern Elf_Kind elf_kind (Elf *__elf) __pure_attribute__;
+
+/* Get the base offset for an object file.  */
+extern int64_t elf_getbase (Elf *__elf);
+
+
+/* Retrieve file identification data.  */
+extern char *elf_getident (Elf *__elf, size_t *__nbytes);
+
+/* Retrieve class-dependent object file header.  */
+extern Elf32_Ehdr *elf32_getehdr (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Ehdr *elf64_getehdr (Elf *__elf);
+
+/* Create ELF header if none exists.  */
+extern Elf32_Ehdr *elf32_newehdr (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Ehdr *elf64_newehdr (Elf *__elf);
+
+/* Get the number of program headers in the ELF file.  If the file uses
+   more headers than can be represented in the e_phnum field of the ELF
+   header the information from the sh_info field in the zeroth section
+   header is used.  */
+extern int elf_getphdrnum (Elf *__elf, size_t *__dst);
+
+/* Retrieve class-dependent program header table.  */
+extern Elf32_Phdr *elf32_getphdr (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Phdr *elf64_getphdr (Elf *__elf);
+
+/* Create ELF program header.  */
+extern Elf32_Phdr *elf32_newphdr (Elf *__elf, size_t __cnt);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf64_Phdr *elf64_newphdr (Elf *__elf, size_t __cnt);
+
+
+/* Get section at INDEX.  */
+extern Elf_Scn *elf_getscn (Elf *__elf, size_t __index);
+
+/* Get section at OFFSET.  */
+extern Elf_Scn *elf32_offscn (Elf *__elf, Elf32_Off __offset);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern Elf_Scn *elf64_offscn (Elf *__elf, Elf64_Off __offset);
+
+/* Get index of section.  */
+extern size_t elf_ndxscn (Elf_Scn *__scn);
+
+/* Get section with next section index.  */
+extern Elf_Scn *elf_nextscn (Elf *__elf, Elf_Scn *__scn);
+
+/* Create a new section and append it at the end of the table.  */
+extern Elf_Scn *elf_newscn (Elf *__elf);
+
+/* Get the section index of the extended section index table for the
+   given symbol table.  */
+extern int elf_scnshndx (Elf_Scn *__scn);
+
+/* Get the number of sections in the ELF file.  If the file uses more
+   sections than can be represented in the e_shnum field of the ELF
+   header the information from the sh_size field in the zeroth section
+   header is used.  */
+extern int elf_getshdrnum (Elf *__elf, size_t *__dst);
+/* Sun messed up the implementation of 'elf_getshnum' in their implementation.
+   It was agreed to make the same functionality available under a different
+   name and obsolete the old name.  */
+extern int elf_getshnum (Elf *__elf, size_t *__dst)
+     __deprecated_attribute__;
+
+
+/* Get the section index of the section header string table in the ELF
+   file.  If the index cannot be represented in the e_shstrndx field of
+   the ELF header the information from the sh_link field in the zeroth
+   section header is used.  */
+extern int elf_getshdrstrndx (Elf *__elf, size_t *__dst);
+/* Sun messed up the implementation of 'elf_getshstrndx' in their
+   implementation.  It was agreed to make the same functionality available
+   under a different name and obsolete the old name.  */
+extern int elf_getshstrndx (Elf *__elf, size_t *__dst)
+     __deprecated_attribute__;
+
+
+/* Retrieve section header of ELFCLASS32 binary.  */
+extern Elf32_Shdr *elf32_getshdr (Elf_Scn *__scn);
+/* Similar for ELFCLASS64.  */
+extern Elf64_Shdr *elf64_getshdr (Elf_Scn *__scn);
+
+/* Returns compression header for a section if section data is
+   compressed.  Returns NULL and sets elf_errno if the section isn't
+   compressed or an error occurred.  */
+extern Elf32_Chdr *elf32_getchdr (Elf_Scn *__scn);
+extern Elf64_Chdr *elf64_getchdr (Elf_Scn *__scn);
+
+/* Compress or decompress the data of a section and adjust the section
+   header.
+
+   elf_compress works by setting or clearing the SHF_COMPRESS flag
+   from the section Shdr and will encode or decode a Elf32_Chdr or
+   Elf64_Chdr at the start of the section data.  elf_compress_gnu will
+   encode or decode any section, but is traditionally only used for
+   sections that have a name starting with ".debug" when
+   uncompressed or ".zdebug" when compressed and stores just the
+   uncompressed size.  The GNU compression method is deprecated and
+   should only be used for legacy support.
+
+   elf_compress takes a compression type that should be either zero to
+   decompress or an ELFCOMPRESS algorithm to use for compression.
+   Currently ELFCOMPRESS_ZLIB and ELFCOMPRESS_ZSTD are supported.
+   elf_compress_gnu will compress in the traditional GNU compression
+   format when compress is one and decompress the section data when
+   compress is zero.
+
+   The FLAGS argument can be zero or ELF_CHF_FORCE.  If FLAGS contains
+   ELF_CHF_FORCE then it will always compress the section, even if
+   that would not reduce the size of the data section (including the
+   header).  Otherwise elf_compress and elf_compress_gnu will compress
+   the section only if the total data size is reduced.
+
+   On successful compression or decompression the function returns
+   one.  If (not forced) compression is requested and the data section
+   would not actually reduce in size, the section is not actually
+   compressed and zero is returned.  Otherwise -1 is returned and
+   elf_errno is set.
+
+   It is an error to request compression for a section that already
+   has SHF_COMPRESSED set, or (for elf_compress) to request
+   decompression for an section that doesn't have SHF_COMPRESSED set.
+   If a section has SHF_COMPRESSED set then calling elf_compress_gnu
+   will result in an error.  The section has to be decompressed first
+   using elf_compress.  Calling elf_compress on a section compressed
+   with elf_compress_gnu is fine, but probably useless.
+
+   It is always an error to call these functions on SHT_NOBITS
+   sections or if the section has the SHF_ALLOC flag set.
+   elf_compress_gnu will not check whether the section name starts
+   with ".debug" or .zdebug".  It is the responsibility of the caller
+   to make sure the deprecated GNU compression method is only called
+   on correctly named sections (and to change the name of the section
+   when using elf_compress_gnu).
+
+   All previous returned Shdrs and Elf_Data buffers are invalidated by
+   this call and should no longer be accessed.
+
+   Note that although this changes the header and data returned it
+   doesn't mark the section as dirty.  To keep the changes when
+   calling elf_update the section has to be flagged ELF_F_DIRTY.  */
+extern int elf_compress (Elf_Scn *scn, int type, unsigned int flags);
+extern int elf_compress_gnu (Elf_Scn *scn, int compress, unsigned int flags);
+
+/* Set or clear flags for ELF file.  */
+extern unsigned int elf_flagelf (Elf *__elf, Elf_Cmd __cmd,
+				 unsigned int __flags);
+/* Similarly for the ELF header.  */
+extern unsigned int elf_flagehdr (Elf *__elf, Elf_Cmd __cmd,
+				  unsigned int __flags);
+/* Similarly for the ELF program header.  */
+extern unsigned int elf_flagphdr (Elf *__elf, Elf_Cmd __cmd,
+				  unsigned int __flags);
+/* Similarly for the given ELF section.  */
+extern unsigned int elf_flagscn (Elf_Scn *__scn, Elf_Cmd __cmd,
+				 unsigned int __flags);
+/* Similarly for the given ELF data.  */
+extern unsigned int elf_flagdata (Elf_Data *__data, Elf_Cmd __cmd,
+				  unsigned int __flags);
+/* Similarly for the given ELF section header.  */
+extern unsigned int elf_flagshdr (Elf_Scn *__scn, Elf_Cmd __cmd,
+				  unsigned int __flags);
+
+
+/* Get data from section while translating from file representation to
+   memory representation.  The Elf_Data d_type is set based on the
+   section type if known.  Otherwise d_type is set to ELF_T_BYTE.  If
+   the section contains compressed data then d_type is always set to
+   ELF_T_CHDR.  */
+extern Elf_Data *elf_getdata (Elf_Scn *__scn, Elf_Data *__data);
+
+/* Get uninterpreted section content.  */
+extern Elf_Data *elf_rawdata (Elf_Scn *__scn, Elf_Data *__data);
+
+/* Create new data descriptor for section SCN.  */
+extern Elf_Data *elf_newdata (Elf_Scn *__scn);
+
+/* Get data translated from a chunk of the file contents as section data
+   would be for TYPE.  The resulting Elf_Data pointer is valid until
+   elf_end (ELF) is called.  */
+extern Elf_Data *elf_getdata_rawchunk (Elf *__elf,
+				       int64_t __offset, size_t __size,
+				       Elf_Type __type);
+
+
+/* Return pointer to string at OFFSET in section INDEX.  */
+extern char *elf_strptr (Elf *__elf, size_t __index, size_t __offset);
+
+
+/* Return header of archive.  */
+extern Elf_Arhdr *elf_getarhdr (Elf *__elf);
+
+/* Return offset in archive for current file ELF.  */
+extern int64_t elf_getaroff (Elf *__elf);
+
+/* Select archive element at OFFSET.  */
+extern size_t elf_rand (Elf *__elf, size_t __offset);
+
+/* Get symbol table of archive.  */
+extern Elf_Arsym *elf_getarsym (Elf *__elf, size_t *__narsyms);
+
+
+/* Control ELF descriptor.  */
+extern int elf_cntl (Elf *__elf, Elf_Cmd __cmd);
+
+/* Retrieve uninterpreted file contents.  */
+extern char *elf_rawfile (Elf *__elf, size_t *__nbytes);
+
+
+/* Return size of array of COUNT elements of the type denoted by TYPE
+   in the external representation.  The binary class is taken from ELF.
+   The result is based on version VERSION of the ELF standard.  */
+extern size_t elf32_fsize (Elf_Type __type, size_t __count,
+			   unsigned int __version)
+       __const_attribute__;
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern size_t elf64_fsize (Elf_Type __type, size_t __count,
+			   unsigned int __version)
+       __const_attribute__;
+
+
+/* Convert data structure from the representation in the file represented
+   by ELF to their memory representation.  */
+extern Elf_Data *elf32_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+/* Same for 64 bit class.  */
+extern Elf_Data *elf64_xlatetom (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+
+/* Convert data structure from to the representation in memory
+   represented by ELF file representation.  */
+extern Elf_Data *elf32_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+/* Same for 64 bit class.  */
+extern Elf_Data *elf64_xlatetof (Elf_Data *__dest, const Elf_Data *__src,
+				 unsigned int __encode);
+
+
+/* Return error code of last failing function call.  This value is kept
+   separately for each thread.  */
+extern int elf_errno (void);
+
+/* Return error string for ERROR.  If ERROR is zero, return error string
+   for most recent error or NULL is none occurred.  If ERROR is -1 the
+   behaviour is similar to the last case except that not NULL but a legal
+   string is returned.  */
+extern const char *elf_errmsg (int __error);
+
+
+/* Coordinate ELF library and application versions.  */
+extern unsigned int elf_version (unsigned int __version);
+
+/* Set fill bytes used to fill holes in data structures.  */
+extern void elf_fill (int __fill);
+
+/* Compute hash value.  */
+extern unsigned long int elf_hash (const char *__string)
+       __pure_attribute__;
+
+/* Compute hash value using the GNU-specific hash function.  */
+extern unsigned long int elf_gnu_hash (const char *__string)
+       __pure_attribute__;
+
+
+/* Compute simple checksum from permanent parts of the ELF file.  */
+extern long int elf32_checksum (Elf *__elf);
+/* Similar but this time the binary calls is ELFCLASS64.  */
+extern long int elf64_checksum (Elf *__elf);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* libelf.h */
diff --git a/libelf/libelf.map b/libelf/libelf.map
new file mode 100644
index 0000000..25760bc
--- /dev/null
+++ b/libelf/libelf.map
@@ -0,0 +1,149 @@
+ELFUTILS_1.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_clone;
+    elf_cntl;
+    elf_end;
+    elf_errmsg;
+    elf_errno;
+    elf_fill;
+    elf_flagdata;
+    elf_flagehdr;
+    elf_flagelf;
+    elf_flagphdr;
+    elf_flagscn;
+    elf_flagshdr;
+    elf_getarhdr;
+    elf_getarsym;
+    elf_getbase;
+    elf_getdata;
+    elf_getident;
+    elf_getscn;
+    elf_getshnum;
+    elf_getshstrndx;
+    elf_hash;
+    elf_kind;
+    elf_memory;
+    elf_ndxscn;
+    elf_newdata;
+    elf_newscn;
+    elf_next;
+    elf_nextscn;
+    elf_rand;
+    elf_rawdata;
+    elf_rawfile;
+    elf_strptr;
+    elf_update;
+    elf_version;
+    gelf_checksum;
+    gelf_fsize;
+    gelf_getclass;
+    gelf_getdyn;
+    gelf_getehdr;
+    gelf_getmove;
+    gelf_getphdr;
+    gelf_getrel;
+    gelf_getrela;
+    gelf_getshdr;
+    gelf_getsym;
+    gelf_getsyminfo;
+    gelf_getsymshndx;
+    gelf_getverdaux;
+    gelf_getverdef;
+    gelf_getvernaux;
+    gelf_getverneed;
+    gelf_getversym;
+    gelf_newehdr;
+    gelf_newphdr;
+    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_update_verdaux;
+    gelf_update_verdef;
+    gelf_update_vernaux;
+    gelf_update_verneed;
+    gelf_update_versym;
+    gelf_xlatetof;
+    gelf_xlatetom;
+    nlist;
+
+  local:
+    *;
+};
+
+ELFUTILS_1.1 {
+  global:
+    gelf_getlib;
+    gelf_update_lib;
+} ELFUTILS_1.0;
+
+ELFUTILS_1.1.1 {
+  global:
+    elf32_offscn;
+    elf64_offscn;
+    gelf_offscn;
+    elf_getaroff;
+} ELFUTILS_1.1;
+
+ELFUTILS_1.2 {
+  global:
+    elf_gnu_hash;
+} ELFUTILS_1.1.1;
+
+ELFUTILS_1.3 {
+  global:
+    elf_getdata_rawchunk;
+    gelf_getauxv;
+    gelf_update_auxv;
+    gelf_getnote;
+} ELFUTILS_1.2;
+
+ELFUTILS_1.4 {
+  global:
+    elf_scnshndx;
+} ELFUTILS_1.3;
+
+ELFUTILS_1.5 {
+  global:
+    elf_getshdrnum; elf_getshdrstrndx;
+} ELFUTILS_1.4;
+
+ELFUTILS_1.6 {
+  global:
+    elf_getphdrnum;
+} ELFUTILS_1.5;
+
+ELFUTILS_1.7 {
+  global:
+    elf32_getchdr;
+    elf64_getchdr;
+    gelf_getchdr;
+
+    elf_compress;
+    elf_compress_gnu;
+} ELFUTILS_1.6;
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
new file mode 100644
index 0000000..ed061ab
--- /dev/null
+++ b/libelf/libelfP.h
@@ -0,0 +1,620 @@
+/* Internal interfaces for libelf.
+   Copyright (C) 1998-2010, 2015, 2016 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _LIBELFP_H
+#define _LIBELFP_H 1
+
+#include <ar.h>
+#include <gelf.h>
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <system.h>
+
+/* Helper Macros to write 32 bit and 64 bit functions.  */
+#define __elfw2_(Bits, Name) __elf##Bits##_##Name
+#define elfw2_(Bits, Name) elf##Bits##_##Name
+#define ElfW2_(Bits, Name) Elf##Bits##_##Name
+#define ELFW2_(Bits, Name) ELF##Bits##_##Name
+#define ELFW_(Name, Bits) Name##Bits
+#define __elfw2(Bits, Name) __elfw2_(Bits, Name)
+#define elfw2(Bits, Name) elfw2_(Bits, Name)
+#define ElfW2(Bits, Name) ElfW2_(Bits, Name)
+#define ELFW2(Bits, Name) ELFW2_(Bits, Name)
+#define ELFW(Name, Bits)  ELFW_(Name, Bits)
+
+
+/* Sizes of the external types, for 32 bits objects.  */
+#define ELF32_FSZ_ADDR   4
+#define ELF32_FSZ_OFF    4
+#define ELF32_FSZ_HALF   2
+#define ELF32_FSZ_WORD   4
+#define ELF32_FSZ_SWORD  4
+#define ELF32_FSZ_XWORD  8
+#define ELF32_FSZ_SXWORD 8
+#define ELF32_FSZ_RELR   4
+
+/* Same for 64 bits objects.  */
+#define ELF64_FSZ_ADDR   8
+#define ELF64_FSZ_OFF    8
+#define ELF64_FSZ_HALF   2
+#define ELF64_FSZ_WORD   4
+#define ELF64_FSZ_SWORD  4
+#define ELF64_FSZ_XWORD  8
+#define ELF64_FSZ_SXWORD 8
+#define ELF64_FSZ_RELR   8
+
+
+/* This is an extension of the ELF_F_* enumeration.  The values here are
+   not part of the library interface, they are only used internally.  */
+enum
+{
+  ELF_F_MMAPPED = 0x40,
+  ELF_F_MALLOCED = 0x80,
+  ELF_F_FILEDATA = 0x100
+};
+
+
+/* Get definition of all the external types.  */
+#include "exttypes.h"
+
+
+/* Error values.  */
+enum
+{
+  ELF_E_NOERROR = 0,
+  ELF_E_UNKNOWN_ERROR,
+  ELF_E_UNKNOWN_VERSION,
+  ELF_E_UNKNOWN_TYPE,
+  ELF_E_INVALID_HANDLE,
+  ELF_E_SOURCE_SIZE,
+  ELF_E_DEST_SIZE,
+  ELF_E_INVALID_ENCODING,
+  ELF_E_NOMEM,
+  ELF_E_INVALID_FILE,
+  ELF_E_INVALID_ELF,
+  ELF_E_INVALID_OP,
+  ELF_E_NO_VERSION,
+  ELF_E_INVALID_CMD,
+  ELF_E_RANGE,
+  ELF_E_ARCHIVE_FMAG,
+  ELF_E_INVALID_ARCHIVE,
+  ELF_E_NO_ARCHIVE,
+  ELF_E_NO_INDEX,
+  ELF_E_READ_ERROR,
+  ELF_E_WRITE_ERROR,
+  ELF_E_INVALID_CLASS,
+  ELF_E_INVALID_INDEX,
+  ELF_E_INVALID_OPERAND,
+  ELF_E_INVALID_SECTION,
+  ELF_E_INVALID_COMMAND,
+  ELF_E_WRONG_ORDER_EHDR,
+  ELF_E_FD_DISABLED,
+  ELF_E_FD_MISMATCH,
+  ELF_E_OFFSET_RANGE,
+  ELF_E_NOT_NUL_SECTION,
+  ELF_E_DATA_MISMATCH,
+  ELF_E_INVALID_SECTION_HEADER,
+  ELF_E_INVALID_DATA,
+  ELF_E_DATA_ENCODING,
+  ELF_E_SECTION_TOO_SMALL,
+  ELF_E_INVALID_ALIGN,
+  ELF_E_INVALID_SHENTSIZE,
+  ELF_E_UPDATE_RO,
+  ELF_E_NOFILE,
+  ELF_E_GROUP_NOT_REL,
+  ELF_E_INVALID_PHDR,
+  ELF_E_NO_PHDR,
+  ELF_E_INVALID_OFFSET,
+  ELF_E_INVALID_SECTION_TYPE,
+  ELF_E_INVALID_SECTION_FLAGS,
+  ELF_E_NOT_COMPRESSED,
+  ELF_E_ALREADY_COMPRESSED,
+  ELF_E_UNKNOWN_COMPRESSION_TYPE,
+  ELF_E_COMPRESS_ERROR,
+  ELF_E_DECOMPRESS_ERROR,
+  /* Keep this as the last entry.  */
+  ELF_E_NUM
+};
+
+
+/* The visible `Elf_Data' type is not sufficient for some operations due
+   to a misdesigned interface.  Extend it for internal purposes.  */
+typedef struct
+{
+  Elf_Data d;
+  Elf_Scn *s;
+} Elf_Data_Scn;
+
+
+/* List of `Elf_Data' descriptors.  This is what makes up the section
+   contents.  */
+typedef struct Elf_Data_List
+{
+  /* `data' *must* be the first element in the struct.  */
+  Elf_Data_Scn data;
+  struct Elf_Data_List *next;
+  int flags;
+} Elf_Data_List;
+
+
+/* Descriptor for ELF section.  */
+struct Elf_Scn
+{
+  /* We have to distinguish several different situations:
+
+     1. the section is user created.  Therefore there is no file or memory
+        region to read the data from.  Here we have two different subcases:
+
+        a) data was not yet added (before the first `elf_newdata' call)
+
+        b) at least one data set is available
+
+     2. this is a section from a file/memory region.  We have to read the
+        current content in one data block if we have to.  But we don't
+        read the data until it is necessary.  So we have the subcases:
+
+        a) the section in the file has size zero (for whatever reason)
+
+        b) the data of the file is not (yet) read
+
+        c) the data is read and available.
+
+     In addition to this we have different data sets, the raw and the converted
+     data.  This distinction only exists for the data read from the file.
+     All user-added data set (all but the first when read from the file or
+     all of them for user-create sections) are the same in both formats.
+     We don't create the converted data before it is necessary.
+
+     The `data_read' element signals whether data is available in the
+     raw format.
+
+     If there is data from the file/memory region or if read one data
+     set is added the `rawdata_list_read' pointer in non-NULL and points
+     to the last filled data set.  `raw_datalist_rear' is therefore NULL
+     only if there is no data set at all.
+
+     This so far allows to distinguish all but two cases (given that the
+     `rawdata_list' and `data_list' entries are initialized to zero) is
+     between not yet loaded data from the file/memory region and a section
+     with zero size and type ELF_T_BYTE.   */
+  Elf_Data_List data_list;	/* List of data buffers.  */
+  Elf_Data_List *data_list_rear; /* Pointer to the rear of the data list. */
+
+  Elf_Data_Scn rawdata;		/* Uninterpreted data of the section.  */
+
+  int data_read;		/* Nonzero if the section was created by the
+				   user or if the data from the file/memory
+				   is read.  */
+  int shndx_index;		/* Index of the extended section index
+				   table for this symbol table (if this
+				   section is a symbol table).  */
+
+  size_t index;			/* Index of this section.  */
+  struct Elf *elf;		/* The underlying ELF file.  */
+
+  union
+  {
+    Elf32_Shdr *e32;		/* Pointer to 32bit section header.  */
+    Elf64_Shdr *e64;		/* Pointer to 64bit section header.  */
+  } shdr;
+
+  unsigned int shdr_flags;	/* Section header modified?  */
+  unsigned int flags;		/* Section changed in size?
+				   ELF_F_MALLOCED for a Elf_Data_Chunk
+				   dummy_scn means the rawchunks
+				   data.d.d_buf was malloced. For normal
+				   sections it means rawdata_base was
+				   malloced (by elf_compress) even if
+				   the Elf was mmapped.  */
+
+  char *rawdata_base;		/* The unmodified data of the section.  */
+  char *data_base;		/* The converted data of the section.  */
+
+  char *zdata_base;		/* The uncompressed data of the section.  */
+  size_t zdata_size;		/* If zdata_base != NULL, the size of data.  */
+  size_t zdata_align;		/* If zdata_base != NULL, the addralign.  */
+
+  struct Elf_ScnList *list;	/* Pointer to the section list element the
+				   data is in.  */
+};
+
+
+/* List of section.  */
+typedef struct Elf_ScnList
+{
+  unsigned int cnt;		/* Number of elements of 'data' used.  */
+  unsigned int max;		/* Number of elements of 'data' allocated.  */
+  struct Elf_ScnList *next;	/* Next block of sections.  */
+  struct Elf_Scn data[0];	/* Section data.  */
+} Elf_ScnList;
+
+
+/* elf_getdata_rawchunk result.  */
+typedef struct Elf_Data_Chunk
+{
+  Elf_Data_Scn data;
+  Elf_Scn dummy_scn;
+  int64_t offset;		/* The original raw offset in the Elf image.  */
+} Elf_Data_Chunk;
+
+
+/* The ELF descriptor.  */
+struct Elf
+{
+  /* Address to which the file was mapped.  NULL if not mapped.  */
+  void *map_address;
+
+  /* When created for an archive member this points to the descriptor
+     for the archive. */
+  Elf *parent;
+  Elf *next;             /* Used in list of archive descriptors.  */
+
+  /* What kind of file is underneath (ELF file, archive...).  */
+  Elf_Kind kind;
+
+  /* Command used to create this descriptor.  */
+  Elf_Cmd cmd;
+
+  /* The binary class.  */
+  unsigned int class;
+
+  /* The used file descriptor.  -1 if not available anymore.  */
+  int fildes;
+
+  /* Offset in the archive this file starts or zero.  */
+  int64_t start_offset;
+
+  /* Size of the file in the archive or the entire file size, or ~0
+     for an (yet) unknown size.  */
+  size_t maximum_size;
+
+  /* Describes the way the memory was allocated and if the dirty bit is
+     signalled it means that the whole file has to be rewritten since
+     the layout changed.  */
+  int flags;
+
+  /* Reference counting for the descriptor.  */
+  int ref_count;
+
+  /* Lock to handle multithreaded programs.  */
+  rwlock_define (,lock);
+
+  union
+  {
+    struct
+    {
+      /* The next fields are only useful when testing for ==/!= NULL.  */
+      void *ehdr;
+      void *shdr;
+      void *phdr;
+
+      Elf_ScnList *scns_last;	/* Last element in the section list.
+				   If NULL the data has not yet been
+				   read from the file.  */
+      void *rawchunks;		/* Tree of elf_getdata_rawchunk results.  */
+      unsigned int scnincr;	/* Number of sections allocate the last
+				   time.  */
+      int ehdr_flags;		/* Flags (dirty) for ELF header.  */
+      int phdr_flags;		/* Flags (dirty|malloc) for program header.  */
+      int shdr_malloced;	/* Nonzero if shdr array was allocated.  */
+      off_t sizestr_offset;	/* Offset of the size string in the parent
+				   if this is an archive member.  */
+    } elf;
+
+    struct
+    {
+      Elf32_Ehdr *ehdr;		/* Pointer to the ELF header.  This is
+				   never malloced.  */
+      Elf32_Shdr *shdr;		/* Used when reading from a file.  */
+      Elf32_Phdr *phdr;		/* Pointer to the program header array.  */
+      Elf_ScnList *scns_last;	/* Last element in the section list.
+				   If NULL the data has not yet been
+				   read from the file.  */
+      void *rawchunks;		/* Tree of elf_getdata_rawchunk results.  */
+      unsigned int scnincr;	/* Number of sections allocate the last
+				   time.  */
+      int ehdr_flags;		/* Flags (dirty) for ELF header.  */
+      int phdr_flags;		/* Flags (dirty|malloc) for program header.  */
+      int shdr_malloced;	/* Nonzero if shdr array was allocated.  */
+      int64_t sizestr_offset;	/* Offset of the size string in the parent
+				   if this is an archive member.  */
+      Elf32_Ehdr ehdr_mem;	/* Memory used for ELF header when not
+				   mmaped.  */
+      char __e32scnspad[sizeof (Elf64_Ehdr) - sizeof (Elf32_Ehdr)];
+
+      /* The section array.  */
+      Elf_ScnList scns;
+    } elf32;
+
+    struct
+    {
+      Elf64_Ehdr *ehdr;		/* Pointer to the ELF header.  This is
+				   never malloced.  */
+      Elf64_Shdr *shdr;		/* Used when reading from a file.  */
+      Elf64_Phdr *phdr;		/* Pointer to the program header array.  */
+      Elf_ScnList *scns_last;	/* Last element in the section list.
+				   If NULL the data has not yet been
+				   read from the file.  */
+      void *rawchunks;		/* Tree of elf_getdata_rawchunk results.  */
+      unsigned int scnincr;	/* Number of sections allocate the last
+				   time.  */
+      int ehdr_flags;		/* Flags (dirty) for ELF header.  */
+      int phdr_flags;		/* Flags (dirty|malloc) for program header.  */
+      int shdr_malloced;	/* Nonzero if shdr array was allocated.  */
+      int64_t sizestr_offset;	/* Offset of the size string in the parent
+				   if this is an archive member.  */
+      Elf64_Ehdr ehdr_mem;	/* Memory used for ELF header when not
+				   mmaped.  */
+
+      /* The section array.  */
+      Elf_ScnList scns;
+    } elf64;
+
+    struct
+    {
+      Elf *children;		/* List of all descriptors for this archive. */
+      Elf_Arsym *ar_sym;	/* Symbol table returned by elf_getarsym.  */
+      size_t ar_sym_num;	/* Number of entries in `ar_sym'.  */
+      char *long_names;		/* If no index is available but long names
+				   are used this elements points to the data.*/
+      size_t long_names_len;	/* Length of the long name table.  */
+      int64_t offset;		/* Offset in file we are currently at.
+				   elf_next() advances this to the next
+				   member of the archive.  */
+      Elf_Arhdr elf_ar_hdr;	/* Structure returned by 'elf_getarhdr'.  */
+      struct ar_hdr ar_hdr;	/* Header read from file.  */
+      char ar_name[16];		/* NUL terminated ar_name of elf_ar_hdr.  */
+      char raw_name[17];	/* This is a buffer for the NUL terminated
+				   named raw_name used in the elf_ar_hdr.  */
+    } ar;
+  } state;
+
+  /* There absolutely never must be anything following the union.  */
+};
+
+/* Type of the conversion functions.  These functions will convert the
+   byte order.  */
+typedef void (*xfct_t) (void *, const void *, size_t, int);
+
+/* The table with the function pointers.  */
+extern const xfct_t __elf_xfctstom[ELFCLASSNUM - 1][ELF_T_NUM]
+  attribute_hidden;
+
+
+/* Array with sizes of the external types indexed by ELF version, binary
+   class, and type. */
+extern const size_t __libelf_type_sizes[ELFCLASSNUM - 1][ELF_T_NUM]
+  attribute_hidden;
+/* We often have to access the size for a type in the current version.  */
+# define elf_typesize(class,type,n) \
+  (__libelf_type_sizes[ELFW(ELFCLASS,class) - 1][type] * n)
+
+/* The byte value used for filling gaps.  */
+extern int __libelf_fill_byte attribute_hidden;
+
+/* EV_CURRENT if the version was set, EV_NONE otherwise.  */
+extern unsigned int __libelf_version attribute_hidden;
+
+/* Array with alignment requirements of the internal types indexed by
+   binary class, and type. */
+extern const uint_fast8_t __libelf_type_aligns[ELFCLASSNUM - 1][ELF_T_NUM]
+  attribute_hidden;
+# define __libelf_type_align(class, type)	\
+    (__libelf_type_aligns[class - 1][type] ?: 1)
+
+/* Given an GElf_Ehdr handle and a section type returns the Elf_Data d_type.
+   Should not be called when SHF_COMPRESSED is set, the d_type should
+   be ELF_T_BYTE.  */
+extern Elf_Type __libelf_data_type (GElf_Ehdr *ehdr,
+				    int sh_type, GElf_Xword align)
+  internal_function;
+
+
+/* Create Elf descriptor from memory image.  */
+extern Elf *__libelf_read_mmaped_file (int fildes, void *map_address,
+				       int64_t offset, size_t maxsize,
+				       Elf_Cmd cmd, Elf *parent)
+     internal_function;
+
+/* Set error value.  */
+extern void __libelf_seterrno (int value) internal_function;
+
+/* Get the next archive header.  */
+extern int __libelf_next_arhdr_wrlock (Elf *elf) internal_function;
+
+/* Read all of the file associated with the descriptor.  */
+extern char *__libelf_readall (Elf *elf) internal_function;
+
+/* Read the complete section table and convert the byte order if necessary.  */
+extern int __libelf_readsections (Elf *elf) internal_function;
+
+/* Store the information for the raw data in the `rawdata_list' element.  */
+extern int __libelf_set_rawdata (Elf_Scn *scn) internal_function;
+extern int __libelf_set_rawdata_wrlock (Elf_Scn *scn) internal_function;
+
+
+/* Helper functions for elf_update.  */
+extern int64_t __elf32_updatenull_wrlock (Elf *elf, int *change_bop,
+					  size_t shnum) internal_function;
+extern int64_t __elf64_updatenull_wrlock (Elf *elf, int *change_bop,
+					  size_t shnum) internal_function;
+
+extern int __elf32_updatemmap (Elf *elf, int change_bo, size_t shnum)
+     internal_function;
+extern int __elf64_updatemmap (Elf *elf, int change_bo, size_t shnum)
+     internal_function;
+extern int __elf32_updatefile (Elf *elf, int change_bo, size_t shnum)
+     internal_function;
+extern int __elf64_updatefile (Elf *elf, int change_bo, size_t shnum)
+     internal_function;
+
+
+/* Alias for exported functions to avoid PLT entries, and
+   rdlock/wrlock variants of these functions.  */
+extern int __elf_end_internal (Elf *__elf) attribute_hidden;
+extern Elf *__elf_begin_internal (int __fildes, Elf_Cmd __cmd, Elf *__ref)
+     attribute_hidden;
+extern Elf32_Ehdr *__elf32_getehdr_wrlock (Elf *__elf) internal_function;
+extern Elf64_Ehdr *__elf64_getehdr_wrlock (Elf *__elf) internal_function;
+extern Elf32_Ehdr *__elf32_newehdr_internal (Elf *__elf) attribute_hidden;
+extern Elf64_Ehdr *__elf64_newehdr_internal (Elf *__elf) attribute_hidden;
+extern Elf32_Phdr *__elf32_getphdr_internal (Elf *__elf) attribute_hidden;
+extern Elf64_Phdr *__elf64_getphdr_internal (Elf *__elf) attribute_hidden;
+extern Elf32_Phdr *__elf32_getphdr_wrlock (Elf *__elf) attribute_hidden;
+extern Elf64_Phdr *__elf64_getphdr_wrlock (Elf *__elf) attribute_hidden;
+extern Elf32_Phdr *__elf32_newphdr_internal (Elf *__elf, size_t __cnt)
+     attribute_hidden;
+extern Elf64_Phdr *__elf64_newphdr_internal (Elf *__elf, size_t __cnt)
+     attribute_hidden;
+extern Elf_Scn *__elf32_offscn_internal (Elf *__elf, Elf32_Off __offset)
+     attribute_hidden;
+extern Elf_Scn *__elf64_offscn_internal (Elf *__elf, Elf64_Off __offset)
+     attribute_hidden;
+extern int __elf_getphdrnum_rdlock (Elf *__elf, size_t *__dst)
+     internal_function;
+extern int __elf_getphdrnum_chk_rdlock (Elf *__elf, size_t *__dst)
+     internal_function;
+extern int __elf_getshdrnum_rdlock (Elf *__elf, size_t *__dst)
+     internal_function;
+extern int __elf_getshdrstrndx_internal (Elf *__elf, size_t *__dst)
+     attribute_hidden;
+extern Elf32_Shdr *__elf32_getshdr_rdlock (Elf_Scn *__scn) internal_function;
+extern Elf64_Shdr *__elf64_getshdr_rdlock (Elf_Scn *__scn) internal_function;
+extern Elf32_Shdr *__elf32_getshdr_wrlock (Elf_Scn *__scn) internal_function;
+extern Elf64_Shdr *__elf64_getshdr_wrlock (Elf_Scn *__scn) internal_function;
+extern Elf32_Chdr *__elf32_getchdr_wrlock (Elf_Scn *__scn) internal_function;
+extern Elf64_Chdr *__elf64_getchdr_wrlock (Elf_Scn *__scn) internal_function;
+extern Elf_Scn *__elf_getscn_internal (Elf *__elf, size_t __index)
+     attribute_hidden;
+extern Elf_Scn *__elf_nextscn_internal (Elf *__elf, Elf_Scn *__scn)
+     attribute_hidden;
+extern int __elf_scnshndx_internal (Elf_Scn *__scn) attribute_hidden;
+extern Elf_Data *__elf_getdata_internal (Elf_Scn *__scn, Elf_Data *__data)
+     attribute_hidden;
+extern Elf_Data *__elf_getdata_rdlock (Elf_Scn *__scn, Elf_Data *__data)
+     internal_function;
+extern Elf_Data *__elf_getdata_wrlock (Elf_Scn *__scn, Elf_Data *__data)
+     internal_function;
+extern Elf_Data *__elf_rawdata_internal (Elf_Scn *__scn, Elf_Data *__data)
+     attribute_hidden;
+/* Should be called to setup first section data element if
+   data_list_rear is NULL and we know data_read is set and there is
+   raw data available.  Might upgrade the ELF lock from a read to a
+   write lock.  If the lock is already a write lock set wrlocked.  */
+extern void __libelf_set_data_list_rdlock (Elf_Scn *scn, int wrlocked)
+     internal_function;
+extern char *__elf_strptr_internal (Elf *__elf, size_t __index,
+				    size_t __offset) attribute_hidden;
+extern Elf_Data *__elf32_xlatetom_internal (Elf_Data *__dest,
+					    const Elf_Data *__src,
+					    unsigned int __encode)
+     attribute_hidden;
+extern Elf_Data *__elf64_xlatetom_internal (Elf_Data *__dest,
+					    const Elf_Data *__src,
+					    unsigned int __encode)
+     attribute_hidden;
+extern Elf_Data *__elf32_xlatetof_internal (Elf_Data *__dest,
+					    const Elf_Data *__src,
+					    unsigned int __encode)
+     attribute_hidden;
+extern Elf_Data *__elf64_xlatetof_internal (Elf_Data *__dest,
+					    const Elf_Data *__src,
+					    unsigned int __encode)
+     attribute_hidden;
+extern unsigned int __elf_version_internal (unsigned int __version)
+     attribute_hidden;
+extern unsigned long int __elf_hash_internal (const char *__string)
+       __attribute__ ((__pure__)) attribute_hidden;
+extern long int __elf32_checksum_internal (Elf *__elf) attribute_hidden;
+extern long int __elf64_checksum_internal (Elf *__elf) attribute_hidden;
+
+
+extern GElf_Ehdr *__gelf_getehdr_rdlock (Elf *__elf, GElf_Ehdr *__dest)
+     internal_function;
+extern size_t __gelf_fsize_internal (Elf *__elf, Elf_Type __type,
+				     size_t __count, unsigned int __version)
+     attribute_hidden;
+extern GElf_Shdr *__gelf_getshdr_internal (Elf_Scn *__scn, GElf_Shdr *__dst)
+     attribute_hidden;
+extern GElf_Sym *__gelf_getsym_internal (Elf_Data *__data, int __ndx,
+					 GElf_Sym *__dst) attribute_hidden;
+
+
+extern uint32_t __libelf_crc32 (uint32_t crc, unsigned char *buf, size_t len)
+     attribute_hidden;
+
+extern void * __libelf_compress (Elf_Scn *scn, size_t hsize, int ei_data,
+				 size_t *orig_size, size_t *orig_addralign,
+				 size_t *size, bool force, bool use_zstd)
+     internal_function;
+
+extern void * __libelf_decompress (int chtype, void *buf_in, size_t size_in,
+				   size_t size_out) internal_function;
+extern void * __libelf_decompress_elf (Elf_Scn *scn,
+				       size_t *size_out, size_t *addralign)
+     internal_function;
+
+
+extern void __libelf_reset_rawdata (Elf_Scn *scn, void *buf, size_t size,
+				    size_t align, Elf_Type type)
+     internal_function;
+
+
+/* We often have to update a flag iff a value changed.  Make this
+   convenient.  */
+#define update_if_changed(var, exp, flag) \
+  do {									      \
+    __typeof__ (var) *_var = &(var);					      \
+    __typeof__ (exp) _exp = (exp);					      \
+    if (*_var != _exp)							      \
+      {									      \
+	*_var = _exp;							      \
+	(flag) |= ELF_F_DIRTY;						      \
+      }									      \
+  } while (0)
+
+/* Align offset to 4 bytes as needed for note name and descriptor data.
+   This is almost always used, except for GNU Property notes, which use
+   8 byte padding...  */
+#define NOTE_ALIGN4(n)	(((n) + 3) & -4UL)
+
+/* Special note padding rule for GNU Property notes.  */
+#define NOTE_ALIGN8(n)	(((n) + 7) & -8UL)
+
+/* Convenience macro.  */
+#define INVALID_NDX(ndx, type, data) \
+  unlikely ((data)->d_size / sizeof (type) <= (unsigned int) (ndx))
+
+#endif  /* libelfP.h */
diff --git a/libelf/libelf_crc32.c b/libelf/libelf_crc32.c
new file mode 100644
index 0000000..f1cf486
--- /dev/null
+++ b/libelf/libelf_crc32.c
@@ -0,0 +1,34 @@
+/* Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define crc32 attribute_hidden __libelf_crc32
+#include <libelf.h>
+#include "../lib/crc32.c"
diff --git a/libelf/libelf_next_prime.c b/libelf/libelf_next_prime.c
new file mode 100644
index 0000000..05229c3
--- /dev/null
+++ b/libelf/libelf_next_prime.c
@@ -0,0 +1,33 @@
+/* Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define next_prime attribute_hidden __libelf_next_prime
+#include "../lib/next_prime.c"
diff --git a/libelf/nlist.c b/libelf/nlist.c
new file mode 100644
index 0000000..b3d6043
--- /dev/null
+++ b/libelf/nlist.c
@@ -0,0 +1,245 @@
+/* Extract symbol list from binary.
+   Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005, 2007, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <nlist.h>
+
+#include "libelfP.h"
+
+
+struct hashentry
+{
+  const char *str;
+  GElf_Sym sym;
+};
+#define TYPE struct hashentry
+/* XXX Use a better hash function some day.  */
+#define HASHFCT(str, len) INTUSE(elf_hash) (str)
+#define COMPARE(p1, p2) strcmp ((p1)->str, (p2)->str)
+#define CLASS static
+#define PREFIX nlist_
+#define xcalloc(n, m) calloc (n, m)
+#define next_prime(s) __libelf_next_prime (s)
+#include <fixedsizehash.h>
+
+
+int
+nlist (const char *filename, struct nlist *nl)
+{
+  int fd;
+  Elf *elf;
+  Elf_Scn *scn = NULL;
+  Elf_Scn *symscn = NULL;
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = NULL;
+  Elf_Data *data;
+  struct nlist_fshash *table;
+  size_t nsyms;
+  size_t cnt;
+
+  /* Open the file.  */
+  fd = open (filename, O_RDONLY);
+  if (fd == -1)
+    {
+      __libelf_seterrno (ELF_E_NOFILE);
+      goto fail;
+    }
+
+  /* For compatibility reasons (`nlist' existed before ELF and libelf)
+     we don't expect the caller to set the ELF version.  Do this here
+     as if it hasn't happened yet.  */
+  INTUSE(elf_version) (EV_CURRENT);
+
+  /* Now get an ELF descriptor.  */
+  elf = INTUSE(elf_begin) (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    goto fail_fd;
+
+  /* Find a symbol table.  We prefer the real symbol table but if it
+     does not exist use the dynamic symbol table.  */
+  while ((scn = INTUSE(elf_nextscn) (elf, scn)) != NULL)
+    {
+      shdr = INTUSE(gelf_getshdr) (scn, &shdr_mem);
+      if (shdr == NULL)
+	goto fail_close;
+
+      /* That is what we are looking for.  */
+      if (shdr->sh_type == SHT_SYMTAB)
+	{
+	  symscn = scn;
+	  break;
+	}
+
+      /* Better than nothing.  Remember this section.  */
+      if (shdr->sh_type == SHT_DYNSYM)
+	symscn = scn;
+    }
+
+  if (symscn == NULL)
+    /* We haven't found anything.  Fail.  */
+    goto fail_close;
+
+  /* Re-get the section header in case we found only the dynamic symbol
+     table.  */
+  if (scn == NULL)
+    {
+      shdr = INTUSE(gelf_getshdr) (symscn, &shdr_mem);
+      if (unlikely (shdr == NULL))
+	goto fail_close;
+    }
+  /* SHDR->SH_LINK now contains the index of the string section.  */
+
+  /* Get the data for the symbol section.  */
+  data = INTUSE(elf_getdata) (symscn, NULL);
+  if (data == NULL)
+    goto fail_close;
+
+  /* How many symbols are there?  */
+  nsyms = (shdr->sh_size
+	   / INTUSE(gelf_fsize) (elf, ELF_T_SYM, 1, EV_CURRENT));
+
+  /* Create the hash table.  */
+  table = nlist_fshash_init (nsyms);
+  if (table == NULL)
+    {
+      __libelf_seterrno (ELF_E_NOMEM);
+      goto fail_close;
+    }
+
+  /* Iterate over all the symbols in the section.  */
+  for (cnt = 0; cnt < nsyms; ++cnt)
+    {
+      struct hashentry mem;
+      GElf_Sym *sym;
+
+      /* Get the symbol.  */
+      sym = INTUSE(gelf_getsym) (data, cnt, &mem.sym);
+      if (sym == NULL)
+	goto fail_dealloc;
+
+      /* Get the name of the symbol.  */
+      mem.str = INTUSE(elf_strptr) (elf, shdr->sh_link, sym->st_name);
+      if (mem.str == NULL)
+	goto fail_dealloc;
+
+      /* Don't allow zero-length strings.  */
+      if (mem.str[0] == '\0')
+	continue;
+
+      /* And add it to the hash table.  Note that we are using the
+         overwrite version.  This will ensure that
+	 a) global symbols are preferred over local symbols since
+	    they are all located at the end
+	 b) if there are multiple local symbols with the same name
+	    the last one is used.
+      */
+      (void) nlist_fshash_overwrite (table, mem.str, 0, &mem);
+    }
+
+  /* Now it is time to look for the symbols the user asked for.
+     XXX What is a `null name/null string'?  This is what the
+     standard says terminates the list.  Is it a null pointer
+     or a zero-length string?  We test for both...  */
+  while (nl->n_name != NULL && nl->n_name[0] != '\0')
+    {
+      struct hashentry search;
+      const struct hashentry *found;
+
+      /* Search for a matching entry in the hash table.  */
+      search.str = nl->n_name;
+      found = nlist_fshash_find (table, nl->n_name, 0, &search);
+
+      if (found != NULL)
+	{
+	  /* Found it.  */
+	  nl->n_value = found->sym.st_value;
+	  nl->n_scnum = found->sym.st_shndx;
+	  nl->n_type = GELF_ST_TYPE (found->sym.st_info);
+	  /* XXX What shall we fill in the next fields?  */
+	  nl->n_sclass = 0;
+	  nl->n_numaux = 0;
+	}
+      else
+	{
+	  /* Not there.  */
+	  nl->n_value = 0;
+	  nl->n_scnum = 0;
+	  nl->n_type = 0;
+	  nl->n_sclass = 0;
+	  nl->n_numaux = 0;
+	}
+
+      /* Next search request.  */
+      ++nl;
+    }
+
+  /* Free the resources.  */
+  nlist_fshash_fini (table);
+
+  /* We do not need the ELF descriptor anymore.  */
+  (void) INTUSE(elf_end) (elf);
+
+  /* Neither the file descriptor.  */
+  (void) close (fd);
+
+  return 0;
+
+ fail_dealloc:
+  nlist_fshash_fini (table);
+
+ fail_close:
+  /* We do not need the ELF descriptor anymore.  */
+  (void) INTUSE(elf_end) (elf);
+
+ fail_fd:
+  /* Neither the file descriptor.  */
+  (void) close (fd);
+
+ fail:
+  /* We have to set all entries to zero.  */
+  while (nl->n_name != NULL && nl->n_name[0] != '\0')
+    {
+      nl->n_value = 0;
+      nl->n_scnum = 0;
+      nl->n_type = 0;
+      nl->n_sclass = 0;
+      nl->n_numaux = 0;
+
+      /* Next entry.  */
+      ++nl;
+    }
+
+  return -1;
+}
diff --git a/libelf/nlist.h b/libelf/nlist.h
new file mode 100644
index 0000000..5990918
--- /dev/null
+++ b/libelf/nlist.h
@@ -0,0 +1,56 @@
+/* Interface for nlist.
+   Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _NLIST_H
+#define _NLIST_H 1
+
+
+/* Symbol list type.  */
+struct nlist
+{
+  char *n_name;			/* Symbol name.  */
+  long int n_value;		/* Value of symbol.  */
+  short int n_scnum;		/* Section number found in.  */
+  unsigned short int n_type;	/* Type of symbol.  */
+  char n_sclass;		/* Storage class.  */
+  char n_numaux;		/* Number of auxiliary entries.  */
+};
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Get specified entries from file.  */
+extern int nlist (__const char *__filename, struct nlist *__nl);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* nlist.h */
diff --git a/libelf/note_xlate.h b/libelf/note_xlate.h
new file mode 100644
index 0000000..7e2784b
--- /dev/null
+++ b/libelf/note_xlate.h
@@ -0,0 +1,98 @@
+/* Conversion functions for notes.
+   Copyright (C) 2007, 2009, 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+static void
+elf_cvt_note (void *dest, const void *src, size_t len, int encode,
+	      bool nhdr8)
+{
+  /* Note that the header is always the same size, but the padding
+     differs for GNU Property notes.  */
+  assert (sizeof (Elf32_Nhdr) == sizeof (Elf64_Nhdr));
+
+  while (len >= sizeof (Elf32_Nhdr))
+    {
+      /* Convert the header.  */
+      (1 ? Elf32_cvt_Nhdr : Elf64_cvt_Nhdr) (dest, src, sizeof (Elf32_Nhdr),
+					     encode);
+      const Elf32_Nhdr *n = encode ? src : dest;
+
+      size_t note_len = sizeof *n;
+
+      /* desc needs to be aligned.  */
+      note_len += n->n_namesz;
+      note_len = nhdr8 ? NOTE_ALIGN8 (note_len) : NOTE_ALIGN4 (note_len);
+      if (note_len > len || note_len < sizeof *n)
+	{
+	  /* Header was translated, nothing else.  */
+	  len -= sizeof *n;
+	  src += sizeof *n;
+	  dest += sizeof *n;
+	  break;
+	}
+
+      /* data as a whole needs to be aligned.  */
+      note_len += n->n_descsz;
+      note_len = nhdr8 ? NOTE_ALIGN8 (note_len) : NOTE_ALIGN4 (note_len);
+      if (note_len > len || note_len < sizeof *n)
+	{
+	  /* Header was translated, nothing else.  */
+	  len -= sizeof *n;
+	  src += sizeof *n;
+	  dest += sizeof *n;
+	  break;
+	}
+
+      /* Copy or skip the note data.  */
+      size_t note_data_len = note_len - sizeof *n;
+      src += sizeof *n;
+      dest += sizeof *n;
+      if (src != dest)
+	memcpy (dest, src, note_data_len);
+
+      src += note_data_len;
+      dest += note_data_len;
+      len -= note_len;
+    }
+
+    /* Copy over any leftover data unconverted.  Probably part of
+       truncated name/desc data.  */
+    if (unlikely (len > 0) && src != dest)
+      memcpy (dest, src, len);
+}
+
+static void
+elf_cvt_note4 (void *dest, const void *src, size_t len, int encode)
+{
+  elf_cvt_note (dest, src, len, encode, false);
+}
+
+static void
+elf_cvt_note8 (void *dest, const void *src, size_t len, int encode)
+{
+  elf_cvt_note (dest, src, len, encode, true);
+}
diff --git a/libelf/version_xlate.h b/libelf/version_xlate.h
new file mode 100644
index 0000000..97f3b73
--- /dev/null
+++ b/libelf/version_xlate.h
@@ -0,0 +1,279 @@
+/* Conversion functions for versioning information.
+   Copyright (C) 1998, 1999, 2000, 2002, 2003, 2015 Red Hat, Inc.
+   Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <gelf.h>
+
+#include "libelfP.h"
+
+
+static void
+elf_cvt_Verdef (void *dest, const void *src, size_t len, int encode)
+{
+  /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
+     To recognize them we have to walk the data structure and convert
+     them one after the other.  The ENCODE parameter specifies whether
+     we are encoding or decoding.  When we are encoding we can immediately
+     use the data in the buffer; if not, we have to decode the data before
+     using it.  */
+  size_t def_offset = 0;
+  GElf_Verdef *ddest;
+  GElf_Verdef *dsrc;
+
+  /* We rely on the types being all the same size.  */
+  assert (sizeof (GElf_Verdef) == sizeof (Elf32_Verdef));
+  assert (sizeof (GElf_Verdaux) == sizeof (Elf32_Verdaux));
+  assert (sizeof (GElf_Verdef) == sizeof (Elf64_Verdef));
+  assert (sizeof (GElf_Verdaux) == sizeof (Elf64_Verdaux));
+
+  if (len == 0)
+    return;
+
+  /* Below we rely on the next field offsets to be correct, start by
+     copying over all data as is in case some data isn't translated.
+     We don't want to leave (undefined) garbage in the dest buffer.  */
+  memmove (dest, src, len);
+
+  do
+    {
+      size_t aux_offset;
+      GElf_Verdaux *asrc;
+
+      /* Test for correct offset.  */
+      if (def_offset > len
+	  || len - def_offset < sizeof (GElf_Verdef)
+	  || (def_offset & (__alignof__ (GElf_Verdef) - 1)) != 0)
+	return;
+
+      /* Work the tree from the first record.  */
+      ddest = (GElf_Verdef *) ((char *) dest + def_offset);
+      dsrc = (GElf_Verdef *) ((char *) src + def_offset);
+
+      /* Decode first if necessary.  */
+      if (! encode)
+	{
+	  ddest->vd_version = bswap_16 (dsrc->vd_version);
+	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
+	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
+	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
+	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
+	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
+	  ddest->vd_next = bswap_32 (dsrc->vd_next);
+
+	  if (ddest->vd_aux > len - def_offset)
+	    return;
+	  aux_offset = def_offset + ddest->vd_aux;
+	}
+      else
+	{
+	  if (dsrc->vd_aux > len - def_offset)
+	    return;
+	  aux_offset = def_offset + dsrc->vd_aux;
+	}
+
+      /* Handle all the auxiliary records belonging to this definition.  */
+      do
+	{
+	  GElf_Verdaux *adest;
+
+	  /* Test for correct offset.  */
+	  if (aux_offset > len
+	      || len - aux_offset < sizeof (GElf_Verdaux)
+	      || (aux_offset & (__alignof__ (GElf_Verdaux) - 1)) != 0)
+	    return;
+
+	  adest = (GElf_Verdaux *) ((char *) dest + aux_offset);
+	  asrc = (GElf_Verdaux *) ((char *) src + aux_offset);
+
+	  if (encode)
+	    {
+	      if (asrc->vda_next > len - aux_offset)
+		return;
+	      aux_offset += asrc->vda_next;
+	    }
+
+	  adest->vda_name = bswap_32 (asrc->vda_name);
+	  adest->vda_next = bswap_32 (asrc->vda_next);
+
+	  if (! encode)
+	    {
+	      if (adest->vda_next > len - aux_offset)
+		return;
+	      aux_offset += adest->vda_next;
+	    }
+	}
+      while (asrc->vda_next != 0);
+
+      /* Encode now if necessary.  */
+      if (encode)
+	{
+	  if (dsrc->vd_next > len - def_offset)
+	    return;
+	  def_offset += dsrc->vd_next;
+
+	  ddest->vd_version = bswap_16 (dsrc->vd_version);
+	  ddest->vd_flags = bswap_16 (dsrc->vd_flags);
+	  ddest->vd_ndx = bswap_16 (dsrc->vd_ndx);
+	  ddest->vd_cnt = bswap_16 (dsrc->vd_cnt);
+	  ddest->vd_hash = bswap_32 (dsrc->vd_hash);
+	  ddest->vd_aux = bswap_32 (dsrc->vd_aux);
+	  ddest->vd_next = bswap_32 (dsrc->vd_next);
+	}
+      else
+	{
+	  if (ddest->vd_next > len - def_offset)
+	    return;
+	  def_offset += ddest->vd_next;
+	}
+    }
+  while (dsrc->vd_next != 0);
+}
+
+
+static void
+elf_cvt_Verneed (void *dest, const void *src, size_t len, int encode)
+{
+  /* We have two different record types: ElfXX_Verndef and ElfXX_Verdaux.
+     To recognize them we have to walk the data structure and convert
+     them one after the other.  The ENCODE parameter specifies whether
+     we are encoding or decoding.  When we are encoding we can immediately
+     use the data in the buffer; if not, we have to decode the data before
+     using it.  */
+  size_t need_offset = 0;
+  GElf_Verneed *ndest;
+  GElf_Verneed *nsrc;
+
+  /* We rely on the types being all the same size.  */
+  assert (sizeof (GElf_Verneed) == sizeof (Elf32_Verneed));
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf32_Vernaux));
+  assert (sizeof (GElf_Verneed) == sizeof (Elf64_Verneed));
+  assert (sizeof (GElf_Vernaux) == sizeof (Elf64_Vernaux));
+
+  if (len == 0)
+    return;
+
+  /* Below we rely on the next field offsets to be correct, start by
+     copying over all data as is in case some data isn't translated.
+     We don't want to leave (undefined) garbage in the dest buffer.  */
+  memmove (dest, src, len);
+
+  do
+    {
+      size_t aux_offset;
+      GElf_Vernaux *asrc;
+
+      /* Test for correct offset.  */
+      if (need_offset > len
+	  || len - need_offset < sizeof (GElf_Verneed)
+	  || (need_offset & (__alignof__ (GElf_Verneed) - 1)) != 0)
+	return;
+
+      /* Work the tree from the first record.  */
+      ndest = (GElf_Verneed *) ((char *) dest + need_offset);
+      nsrc = (GElf_Verneed *) ((char *) src + need_offset);
+
+      /* Decode first if necessary.  */
+      if (! encode)
+	{
+	  ndest->vn_version = bswap_16 (nsrc->vn_version);
+	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
+	  ndest->vn_file = bswap_32 (nsrc->vn_file);
+	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
+	  ndest->vn_next = bswap_32 (nsrc->vn_next);
+
+	  if (ndest->vn_aux > len - need_offset)
+	    return;
+	  aux_offset = need_offset + ndest->vn_aux;
+	}
+      else
+	{
+	  if (nsrc->vn_aux > len - need_offset)
+	    return;
+	  aux_offset = need_offset + nsrc->vn_aux;
+	}
+
+      /* Handle all the auxiliary records belonging to this requirement.  */
+      do
+	{
+	  GElf_Vernaux *adest;
+
+	  /* Test for correct offset.  */
+	  if (aux_offset > len
+	      || len - aux_offset < sizeof (GElf_Vernaux)
+	      || (aux_offset & (__alignof__ (GElf_Vernaux) - 1)) != 0)
+	    return;
+
+	  adest = (GElf_Vernaux *) ((char *) dest + aux_offset);
+	  asrc = (GElf_Vernaux *) ((char *) src + aux_offset);
+
+	  if (encode)
+	    {
+	      if (asrc->vna_next > len - aux_offset)
+		return;
+	      aux_offset += asrc->vna_next;
+	    }
+
+	  adest->vna_hash = bswap_32 (asrc->vna_hash);
+	  adest->vna_flags = bswap_16 (asrc->vna_flags);
+	  adest->vna_other = bswap_16 (asrc->vna_other);
+	  adest->vna_name = bswap_32 (asrc->vna_name);
+	  adest->vna_next = bswap_32 (asrc->vna_next);
+
+	  if (! encode)
+	    {
+	      if (adest->vna_next > len - aux_offset)
+		return;
+	      aux_offset += adest->vna_next;
+	    }
+	}
+      while (asrc->vna_next != 0);
+
+      /* Encode now if necessary.  */
+      if (encode)
+	{
+	  if (nsrc->vn_next > len - need_offset)
+	    return;
+	  need_offset += nsrc->vn_next;
+
+	  ndest->vn_version = bswap_16 (nsrc->vn_version);
+	  ndest->vn_cnt = bswap_16 (nsrc->vn_cnt);
+	  ndest->vn_file = bswap_32 (nsrc->vn_file);
+	  ndest->vn_aux = bswap_32 (nsrc->vn_aux);
+	  ndest->vn_next = bswap_32 (nsrc->vn_next);
+	}
+      else
+	{
+	  if (ndest->vn_next > len - need_offset)
+	    return;
+	  need_offset += ndest->vn_next;
+	}
+    }
+  while (nsrc->vn_next != 0);
+}
diff --git a/m4/ChangeLog b/m4/ChangeLog
new file mode 100644
index 0000000..8729f58
--- /dev/null
+++ b/m4/ChangeLog
@@ -0,0 +1,101 @@
+2022-03-20  Mark Wielaard  <mark@klomp.org>
+
+	* biarch.m4: Don't check whether -m64 works for 32bit host.
+
+2022-03-14  Mark Wielaard  <mark@klomp.org>
+
+	* biarch.m4: Use AS_HELP_STRING instead of AC_HELP_STRING.
+	* zip.m4: Likewise.
+
+2020-12-15  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+	* Makefile.am: Remove.
+
+2019-10-28  Aaron Merey  <amerey@redhat.com>
+
+	* ax_check_compile_flag.m4, ax_cxx_compile_stdcxx.m4: New files.
+
+2015-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* zip.m4: Explicitly set with_ to no, if not yes.
+
+2014-07-14  Mark Wielaard  <mjw@redhat.com>
+
+	* biarch.m4 (utrace_BIARCH): Set biarch-no for cross-compile using
+	AC_RUN_IFELSE extra argument.
+
+2013-12-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* biarch.m4 (utrace_BIARCH): Call AC_MSG_WARN if !BIARCH.
+
+2013-11-07  Roland McGrath  <roland@redhat.com>
+	    Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* biarch.m4: New file.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* gettext.m4: Upgrade to gettext-0.18.2.
+	* iconv.m4: Upgrade to gettext-0.18.2.
+	* po.m4: Upgrade to gettext-0.18.2.
+
+2010-04-14  Roland McGrath  <roland@redhat.com>
+
+	* gettext.m4: Upgrade to gettext-0.17.
+	* iconv.m4: Upgrade to gettext-0.17.
+	* po.m4: Upgrade to gettext-0.17.
+
+2009-08-26  Roland McGrath  <roland@redhat.com>
+
+	* zip.m4 (eu_ZIPLIB): Don't apply lib/LIB suffix to args.
+
+2009-02-01  Roland McGrath  <roland@redhat.com>
+
+	* zip.m4: Fix --with/--without argument handling.
+
+2009-01-08  Roland McGrath  <roland@redhat.com>
+
+	* zip.am: New file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2007-06-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* gettext.m4: Update from gettext 0.16.1.
+	* iconv.m4: Likewise.
+	* progtest.m4: Likewise.
+	* nls.m4: New file.
+	* po.m4: New file.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Remove glibc21.m4, intdiv0.m4,
+	inttypes.m4, inttypes_h.m4, inttypes-pri.m4, isc-posix.m4,
+	lib-ld.m4, lib-link.m4, lib-prefix.m4, stdint_h.m4, uintmax_t.m4,
+	and ulonglong.m4.
+	* glibc21.m4: Removed.
+	* inttypes_h.m4: Removed.
+	* inttypes.m4: Removed.
+	* inttypes-pri.m4: Removed.
+	* isc-posix.m4: Removed.
+	* lib-ld.m4: Removed.
+	* lib-link.m4: Removed.
+	* lib-prefix.m4: Removed.
+	* stdint_h.m4: Removed.
+	* uintmax_t.m4: Removed.
+	* ulonglong.m4: Removed.
+
+2002-03-22  gettextize  <bug-gnu-gettext@gnu.org>
+
+	* codeset.m4: Upgrade to gettext-0.11.
+	* gettext.m4: Upgrade to gettext-0.11.
+	* glibc21.m4: Upgrade to gettext-0.11.
+	* iconv.m4: Upgrade to gettext-0.11.
+	* isc-posix.m4: New file, from gettext-0.11.
+	* lcmessage.m4: Upgrade to gettext-0.11.
+	* lib-ld.m4: Upgrade to gettext-0.11.
+	* lib-link.m4: Upgrade to gettext-0.11.
+	* lib-prefix.m4: Upgrade to gettext-0.11.
+	* progtest.m4: Upgrade to gettext-0.11.
+	* Makefile.am (EXTRA_DIST): Add the new files.
diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
new file mode 100644
index 0000000..8edf515
--- /dev/null
+++ b/m4/ax_cxx_compile_stdcxx.m4
@@ -0,0 +1,1018 @@
+# ===========================================================================
+#  https://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
+#
+# DESCRIPTION
+#
+#   Check for baseline language coverage in the compiler for the specified
+#   version of the C++ standard.  If necessary, add switches to CXX and
+#   CXXCPP to enable support.  VERSION may be '11', '14', '17', or '20' for
+#   the respective C++ standard version.
+#
+#   The second argument, if specified, indicates whether you insist on an
+#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
+#   -std=c++11).  If neither is specified, you get whatever works, with
+#   preference for no added switch, and then for an extended mode.
+#
+#   The third argument, if specified 'mandatory' or if left unspecified,
+#   indicates that baseline support for the specified C++ standard is
+#   required and that the macro should error out if no mode with that
+#   support is found.  If specified 'optional', then configuration proceeds
+#   regardless, after defining HAVE_CXX${VERSION} if and only if a
+#   supporting mode is found.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
+#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
+#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
+#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
+#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
+#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
+#   Copyright (c) 2016, 2018 Krzesimir Nowak <qdlacz@gmail.com>
+#   Copyright (c) 2019 Enji Cooper <yaneurabeya@gmail.com>
+#   Copyright (c) 2020 Jason Merrill <jason@redhat.com>
+#   Copyright (c) 2021 Jörn Heusipp <osmanx@problemloesungsmaschine.de>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved.  This file is offered as-is, without any
+#   warranty.
+
+#serial 18
+
+dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
+dnl  (serial version number 13).
+
+AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
+  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
+        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
+        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
+        [$1], [20], [ax_cxx_compile_alternatives="20"],
+        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$2], [], [],
+        [$2], [ext], [],
+        [$2], [noext], [],
+        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
+  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
+        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
+        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
+  AC_LANG_PUSH([C++])dnl
+  ac_success=no
+
+  m4_if([$2], [], [dnl
+    AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
+		   ax_cv_cxx_compile_cxx$1,
+      [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+        [ax_cv_cxx_compile_cxx$1=yes],
+        [ax_cv_cxx_compile_cxx$1=no])])
+    if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
+      ac_success=yes
+    fi])
+
+  m4_if([$2], [noext], [], [dnl
+  if test x$ac_success = xno; then
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      switch="-std=gnu++${alternative}"
+      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                     $cachevar,
+        [ac_save_CXX="$CXX"
+         CXX="$CXX $switch"
+         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+          [eval $cachevar=yes],
+          [eval $cachevar=no])
+         CXX="$ac_save_CXX"])
+      if eval test x\$$cachevar = xyes; then
+        CXX="$CXX $switch"
+        if test -n "$CXXCPP" ; then
+          CXXCPP="$CXXCPP $switch"
+        fi
+        ac_success=yes
+        break
+      fi
+    done
+  fi])
+
+  m4_if([$2], [ext], [], [dnl
+  if test x$ac_success = xno; then
+    dnl HP's aCC needs +std=c++11 according to:
+    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
+    dnl Cray's crayCC needs "-h std=c++11"
+    dnl MSVC needs -std:c++NN for C++17 and later (default is C++14)
+    for alternative in ${ax_cxx_compile_alternatives}; do
+      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}" MSVC; do
+        if test x"$switch" = xMSVC; then
+          dnl AS_TR_SH maps both `:` and `=` to `_` so -std:c++17 would collide
+          dnl with -std=c++17.  We suffix the cache variable name with _MSVC to
+          dnl avoid this.
+          switch=-std:c++${alternative}
+          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_${switch}_MSVC])
+        else
+          cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
+        fi
+        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
+                       $cachevar,
+          [ac_save_CXX="$CXX"
+           CXX="$CXX $switch"
+           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
+            [eval $cachevar=yes],
+            [eval $cachevar=no])
+           CXX="$ac_save_CXX"])
+        if eval test x\$$cachevar = xyes; then
+          CXX="$CXX $switch"
+          if test -n "$CXXCPP" ; then
+            CXXCPP="$CXXCPP $switch"
+          fi
+          ac_success=yes
+          break
+        fi
+      done
+      if test x$ac_success = xyes; then
+        break
+      fi
+    done
+  fi])
+  AC_LANG_POP([C++])
+  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
+    if test x$ac_success = xno; then
+      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
+    fi
+  fi
+  if test x$ac_success = xno; then
+    HAVE_CXX$1=0
+    AC_MSG_NOTICE([No compiler with C++$1 support was found])
+  else
+    HAVE_CXX$1=1
+    AC_DEFINE(HAVE_CXX$1,1,
+              [define if the compiler supports basic C++$1 syntax])
+  fi
+  AC_SUBST(HAVE_CXX$1)
+])
+
+
+dnl  Test body for checking C++11 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+)
+
+dnl  Test body for checking C++14 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+)
+
+dnl  Test body for checking C++17 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+)
+
+dnl  Test body for checking C++20 support
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_20],
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
+  _AX_CXX_COMPILE_STDCXX_testbody_new_in_20
+)
+
+
+dnl  Tests for new features in C++11
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
+
+// If the compiler admits that it is not ready for C++11, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+// MSVC always sets __cplusplus to 199711L in older versions; newer versions
+// only set it correctly if /Zc:__cplusplus is specified as well as a
+// /std:c++NN switch:
+// https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/
+#elif __cplusplus < 201103L && !defined _MSC_VER
+
+#error "This is not a C++11 compiler"
+
+#else
+
+namespace cxx11
+{
+
+  namespace test_static_assert
+  {
+
+    template <typename T>
+    struct check
+    {
+      static_assert(sizeof(int) <= sizeof(T), "not big enough");
+    };
+
+  }
+
+  namespace test_final_override
+  {
+
+    struct Base
+    {
+      virtual ~Base() {}
+      virtual void f() {}
+    };
+
+    struct Derived : public Base
+    {
+      virtual ~Derived() override {}
+      virtual void f() override {}
+    };
+
+  }
+
+  namespace test_double_right_angle_brackets
+  {
+
+    template < typename T >
+    struct check {};
+
+    typedef check<void> single_type;
+    typedef check<check<void>> double_type;
+    typedef check<check<check<void>>> triple_type;
+    typedef check<check<check<check<void>>>> quadruple_type;
+
+  }
+
+  namespace test_decltype
+  {
+
+    int
+    f()
+    {
+      int a = 1;
+      decltype(a) b = 2;
+      return a + b;
+    }
+
+  }
+
+  namespace test_type_deduction
+  {
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static const bool value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static const bool value = true;
+    };
+
+    template < typename T1, typename T2 >
+    auto
+    add(T1 a1, T2 a2) -> decltype(a1 + a2)
+    {
+      return a1 + a2;
+    }
+
+    int
+    test(const int c, volatile int v)
+    {
+      static_assert(is_same<int, decltype(0)>::value == true, "");
+      static_assert(is_same<int, decltype(c)>::value == false, "");
+      static_assert(is_same<int, decltype(v)>::value == false, "");
+      auto ac = c;
+      auto av = v;
+      auto sumi = ac + av + 'x';
+      auto sumf = ac + av + 1.0;
+      static_assert(is_same<int, decltype(ac)>::value == true, "");
+      static_assert(is_same<int, decltype(av)>::value == true, "");
+      static_assert(is_same<int, decltype(sumi)>::value == true, "");
+      static_assert(is_same<int, decltype(sumf)>::value == false, "");
+      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
+      return (sumf > 0.0) ? sumi : add(c, v);
+    }
+
+  }
+
+  namespace test_noexcept
+  {
+
+    int f() { return 0; }
+    int g() noexcept { return 0; }
+
+    static_assert(noexcept(f()) == false, "");
+    static_assert(noexcept(g()) == true, "");
+
+  }
+
+  namespace test_constexpr
+  {
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
+    {
+      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
+    }
+
+    template < typename CharT >
+    unsigned long constexpr
+    strlen_c(const CharT *const s) noexcept
+    {
+      return strlen_c_r(s, 0UL);
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("1") == 1UL, "");
+    static_assert(strlen_c("example") == 7UL, "");
+    static_assert(strlen_c("another\0example") == 7UL, "");
+
+  }
+
+  namespace test_rvalue_references
+  {
+
+    template < int N >
+    struct answer
+    {
+      static constexpr int value = N;
+    };
+
+    answer<1> f(int&)       { return answer<1>(); }
+    answer<2> f(const int&) { return answer<2>(); }
+    answer<3> f(int&&)      { return answer<3>(); }
+
+    void
+    test()
+    {
+      int i = 0;
+      const int c = 0;
+      static_assert(decltype(f(i))::value == 1, "");
+      static_assert(decltype(f(c))::value == 2, "");
+      static_assert(decltype(f(0))::value == 3, "");
+    }
+
+  }
+
+  namespace test_uniform_initialization
+  {
+
+    struct test
+    {
+      static const int zero {};
+      static const int one {1};
+    };
+
+    static_assert(test::zero == 0, "");
+    static_assert(test::one == 1, "");
+
+  }
+
+  namespace test_lambdas
+  {
+
+    void
+    test1()
+    {
+      auto lambda1 = [](){};
+      auto lambda2 = lambda1;
+      lambda1();
+      lambda2();
+    }
+
+    int
+    test2()
+    {
+      auto a = [](int i, int j){ return i + j; }(1, 2);
+      auto b = []() -> int { return '0'; }();
+      auto c = [=](){ return a + b; }();
+      auto d = [&](){ return c; }();
+      auto e = [a, &b](int x) mutable {
+        const auto identity = [](int y){ return y; };
+        for (auto i = 0; i < a; ++i)
+          a += b--;
+        return x + identity(a + b);
+      }(0);
+      return a + b + c + d + e;
+    }
+
+    int
+    test3()
+    {
+      const auto nullary = [](){ return 0; };
+      const auto unary = [](int x){ return x; };
+      using nullary_t = decltype(nullary);
+      using unary_t = decltype(unary);
+      const auto higher1st = [](nullary_t f){ return f(); };
+      const auto higher2nd = [unary](nullary_t f1){
+        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
+      };
+      return higher1st(nullary) + higher2nd(nullary)(unary);
+    }
+
+  }
+
+  namespace test_variadic_templates
+  {
+
+    template <int...>
+    struct sum;
+
+    template <int N0, int... N1toN>
+    struct sum<N0, N1toN...>
+    {
+      static constexpr auto value = N0 + sum<N1toN...>::value;
+    };
+
+    template <>
+    struct sum<>
+    {
+      static constexpr auto value = 0;
+    };
+
+    static_assert(sum<>::value == 0, "");
+    static_assert(sum<1>::value == 1, "");
+    static_assert(sum<23>::value == 23, "");
+    static_assert(sum<1, 2>::value == 3, "");
+    static_assert(sum<5, 5, 11>::value == 21, "");
+    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
+
+  }
+
+  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
+  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
+  // because of this.
+  namespace test_template_alias_sfinae
+  {
+
+    struct foo {};
+
+    template<typename T>
+    using member = typename T::member_type;
+
+    template<typename T>
+    void func(...) {}
+
+    template<typename T>
+    void func(member<T>*) {}
+
+    void test();
+
+    void test() { func<foo>(0); }
+
+  }
+
+}  // namespace cxx11
+
+#endif  // __cplusplus >= 201103L
+
+]])
+
+
+dnl  Tests for new features in C++14
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
+
+// If the compiler admits that it is not ready for C++14, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201402L && !defined _MSC_VER
+
+#error "This is not a C++14 compiler"
+
+#else
+
+namespace cxx14
+{
+
+  namespace test_polymorphic_lambdas
+  {
+
+    int
+    test()
+    {
+      const auto lambda = [](auto&&... args){
+        const auto istiny = [](auto x){
+          return (sizeof(x) == 1UL) ? 1 : 0;
+        };
+        const int aretiny[] = { istiny(args)... };
+        return aretiny[0];
+      };
+      return lambda(1, 1L, 1.0f, '1');
+    }
+
+  }
+
+  namespace test_binary_literals
+  {
+
+    constexpr auto ivii = 0b0000000000101010;
+    static_assert(ivii == 42, "wrong value");
+
+  }
+
+  namespace test_generalized_constexpr
+  {
+
+    template < typename CharT >
+    constexpr unsigned long
+    strlen_c(const CharT *const s) noexcept
+    {
+      auto length = 0UL;
+      for (auto p = s; *p; ++p)
+        ++length;
+      return length;
+    }
+
+    static_assert(strlen_c("") == 0UL, "");
+    static_assert(strlen_c("x") == 1UL, "");
+    static_assert(strlen_c("test") == 4UL, "");
+    static_assert(strlen_c("another\0test") == 7UL, "");
+
+  }
+
+  namespace test_lambda_init_capture
+  {
+
+    int
+    test()
+    {
+      auto x = 0;
+      const auto lambda1 = [a = x](int b){ return a + b; };
+      const auto lambda2 = [a = lambda1(x)](){ return a; };
+      return lambda2();
+    }
+
+  }
+
+  namespace test_digit_separators
+  {
+
+    constexpr auto ten_million = 100'000'000;
+    static_assert(ten_million == 100000000, "");
+
+  }
+
+  namespace test_return_type_deduction
+  {
+
+    auto f(int& x) { return x; }
+    decltype(auto) g(int& x) { return x; }
+
+    template < typename T1, typename T2 >
+    struct is_same
+    {
+      static constexpr auto value = false;
+    };
+
+    template < typename T >
+    struct is_same<T, T>
+    {
+      static constexpr auto value = true;
+    };
+
+    int
+    test()
+    {
+      auto x = 0;
+      static_assert(is_same<int, decltype(f(x))>::value, "");
+      static_assert(is_same<int&, decltype(g(x))>::value, "");
+      return x;
+    }
+
+  }
+
+}  // namespace cxx14
+
+#endif  // __cplusplus >= 201402L
+
+]])
+
+
+dnl  Tests for new features in C++17
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
+
+// If the compiler admits that it is not ready for C++17, why torture it?
+// Hopefully, this will speed up the test.
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 201703L && !defined _MSC_VER
+
+#error "This is not a C++17 compiler"
+
+#else
+
+#include <initializer_list>
+#include <utility>
+#include <type_traits>
+
+namespace cxx17
+{
+
+  namespace test_constexpr_lambdas
+  {
+
+    constexpr int foo = [](){return 42;}();
+
+  }
+
+  namespace test::nested_namespace::definitions
+  {
+
+  }
+
+  namespace test_fold_expression
+  {
+
+    template<typename... Args>
+    int multiply(Args... args)
+    {
+      return (args * ... * 1);
+    }
+
+    template<typename... Args>
+    bool all(Args... args)
+    {
+      return (args && ...);
+    }
+
+  }
+
+  namespace test_extended_static_assert
+  {
+
+    static_assert (true);
+
+  }
+
+  namespace test_auto_brace_init_list
+  {
+
+    auto foo = {5};
+    auto bar {5};
+
+    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
+    static_assert(std::is_same<int, decltype(bar)>::value);
+  }
+
+  namespace test_typename_in_template_template_parameter
+  {
+
+    template<template<typename> typename X> struct D;
+
+  }
+
+  namespace test_fallthrough_nodiscard_maybe_unused_attributes
+  {
+
+    int f1()
+    {
+      return 42;
+    }
+
+    [[nodiscard]] int f2()
+    {
+      [[maybe_unused]] auto unused = f1();
+
+      switch (f1())
+      {
+      case 17:
+        f1();
+        [[fallthrough]];
+      case 42:
+        f1();
+      }
+      return f1();
+    }
+
+  }
+
+  namespace test_extended_aggregate_initialization
+  {
+
+    struct base1
+    {
+      int b1, b2 = 42;
+    };
+
+    struct base2
+    {
+      base2() {
+        b3 = 42;
+      }
+      int b3;
+    };
+
+    struct derived : base1, base2
+    {
+        int d;
+    };
+
+    derived d1 {{1, 2}, {}, 4};  // full initialization
+    derived d2 {{}, {}, 4};      // value-initialized bases
+
+  }
+
+  namespace test_general_range_based_for_loop
+  {
+
+    struct iter
+    {
+      int i;
+
+      int& operator* ()
+      {
+        return i;
+      }
+
+      const int& operator* () const
+      {
+        return i;
+      }
+
+      iter& operator++()
+      {
+        ++i;
+        return *this;
+      }
+    };
+
+    struct sentinel
+    {
+      int i;
+    };
+
+    bool operator== (const iter& i, const sentinel& s)
+    {
+      return i.i == s.i;
+    }
+
+    bool operator!= (const iter& i, const sentinel& s)
+    {
+      return !(i == s);
+    }
+
+    struct range
+    {
+      iter begin() const
+      {
+        return {0};
+      }
+
+      sentinel end() const
+      {
+        return {5};
+      }
+    };
+
+    void f()
+    {
+      range r {};
+
+      for (auto i : r)
+      {
+        [[maybe_unused]] auto v = i;
+      }
+    }
+
+  }
+
+  namespace test_lambda_capture_asterisk_this_by_value
+  {
+
+    struct t
+    {
+      int i;
+      int foo()
+      {
+        return [*this]()
+        {
+          return i;
+        }();
+      }
+    };
+
+  }
+
+  namespace test_enum_class_construction
+  {
+
+    enum class byte : unsigned char
+    {};
+
+    byte foo {42};
+
+  }
+
+  namespace test_constexpr_if
+  {
+
+    template <bool cond>
+    int f ()
+    {
+      if constexpr(cond)
+      {
+        return 13;
+      }
+      else
+      {
+        return 42;
+      }
+    }
+
+  }
+
+  namespace test_selection_statement_with_initializer
+  {
+
+    int f()
+    {
+      return 13;
+    }
+
+    int f2()
+    {
+      if (auto i = f(); i > 0)
+      {
+        return 3;
+      }
+
+      switch (auto i = f(); i + 4)
+      {
+      case 17:
+        return 2;
+
+      default:
+        return 1;
+      }
+    }
+
+  }
+
+  namespace test_template_argument_deduction_for_class_templates
+  {
+
+    template <typename T1, typename T2>
+    struct pair
+    {
+      pair (T1 p1, T2 p2)
+        : m1 {p1},
+          m2 {p2}
+      {}
+
+      T1 m1;
+      T2 m2;
+    };
+
+    void f()
+    {
+      [[maybe_unused]] auto p = pair{13, 42u};
+    }
+
+  }
+
+  namespace test_non_type_auto_template_parameters
+  {
+
+    template <auto n>
+    struct B
+    {};
+
+    B<5> b1;
+    B<'a'> b2;
+
+  }
+
+  namespace test_structured_bindings
+  {
+
+    int arr[2] = { 1, 2 };
+    std::pair<int, int> pr = { 1, 2 };
+
+    auto f1() -> int(&)[2]
+    {
+      return arr;
+    }
+
+    auto f2() -> std::pair<int, int>&
+    {
+      return pr;
+    }
+
+    struct S
+    {
+      int x1 : 2;
+      volatile double y1;
+    };
+
+    S f3()
+    {
+      return {};
+    }
+
+    auto [ x1, y1 ] = f1();
+    auto& [ xr1, yr1 ] = f1();
+    auto [ x2, y2 ] = f2();
+    auto& [ xr2, yr2 ] = f2();
+    const auto [ x3, y3 ] = f3();
+
+  }
+
+  namespace test_exception_spec_type_system
+  {
+
+    struct Good {};
+    struct Bad {};
+
+    void g1() noexcept;
+    void g2();
+
+    template<typename T>
+    Bad
+    f(T*, T*);
+
+    template<typename T1, typename T2>
+    Good
+    f(T1*, T2*);
+
+    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
+
+  }
+
+  namespace test_inline_variables
+  {
+
+    template<class T> void f(T)
+    {}
+
+    template<class T> inline T g(T)
+    {
+      return T{};
+    }
+
+    template<> inline void f<>(int)
+    {}
+
+    template<> int g<>(int)
+    {
+      return 5;
+    }
+
+  }
+
+}  // namespace cxx17
+
+#endif  // __cplusplus < 201703L && !defined _MSC_VER
+
+]])
+
+
+dnl  Tests for new features in C++20
+
+m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_20], [[
+
+#ifndef __cplusplus
+
+#error "This is not a C++ compiler"
+
+#elif __cplusplus < 202002L && !defined _MSC_VER
+
+#error "This is not a C++20 compiler"
+
+#else
+
+#include <version>
+
+namespace cxx20
+{
+
+// As C++20 supports feature test macros in the standard, there is no
+// immediate need to actually test for feature availability on the
+// Autoconf side.
+
+}  // namespace cxx20
+
+#endif  // __cplusplus < 202002L && !defined _MSC_VER
+
+]])
diff --git a/m4/biarch.m4 b/m4/biarch.m4
new file mode 100644
index 0000000..c7baead
--- /dev/null
+++ b/m4/biarch.m4
@@ -0,0 +1,47 @@
+AC_DEFUN([utrace_CC_m32], [dnl
+AC_CACHE_CHECK([$CC option for 32-bit word size], utrace_cv_CC_m32, [dnl
+save_CC="$CC"
+utrace_cv_CC_m32=none
+for ut_try in -m32 -m31; do
+  [CC=`echo "$save_CC" | sed 's/ -m[36][241]//'`" $ut_try"]
+  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[int foo (void) { return 1; }]])],
+		    [utrace_cv_CC_m32=$ut_try])
+  test x$utrace_cv_CC_m32 = xnone || break
+done
+CC="$save_CC"])])
+
+AC_DEFUN([utrace_HOST64], [AC_REQUIRE([utrace_CC_m32])
+AS_IF([test x$utrace_cv_CC_m32 != xnone], [dnl
+AC_CACHE_CHECK([for 64-bit host], utrace_cv_host64, [dnl
+AC_EGREP_CPP([@utrace_host64@], [#include <stdint.h>
+#if (UINTPTR_MAX > 0xffffffffUL)
+@utrace_host64@
+#endif],
+             utrace_cv_host64=yes, utrace_cv_host64=no)])
+AS_IF([test $utrace_cv_host64 = no],
+      [utrace_biarch=-m64 utrace_thisarch=$utrace_cv_CC_m32],
+      [utrace_biarch=$utrace_cv_CC_m32 utrace_thisarch=-m64])
+
+biarch_CC=`echo "$CC" | sed "s/ *${utrace_thisarch}//"`
+biarch_CC="$biarch_CC $utrace_biarch"])])
+
+AC_DEFUN([utrace_BIARCH], [AC_REQUIRE([utrace_HOST64])
+utrace_biarch_forced=no
+AC_ARG_WITH([biarch],
+	    AS_HELP_STRING([--with-biarch],
+			   [enable biarch tests despite build problems]),
+	    [AS_IF([test "x$with_biarch" != xno], [utrace_biarch_forced=yes])])
+AS_IF([test $utrace_biarch_forced = yes], [dnl
+utrace_cv_cc_biarch=yes
+AC_MSG_NOTICE([enabling biarch tests regardless using $biarch_CC])], [dnl
+AS_IF([test x$utrace_cv_CC_m32 != xnone -a x$utrace_cv_host64 != xno], [dnl
+AC_CACHE_CHECK([whether $biarch_CC makes executables we can run],
+	       utrace_cv_cc_biarch, [dnl
+save_CC="$CC"
+CC="$biarch_CC"
+AC_RUN_IFELSE([AC_LANG_PROGRAM([], [])],
+	      utrace_cv_cc_biarch=yes, utrace_cv_cc_biarch=no, utrace_cv_cc_biarch=no)
+CC="$save_CC"])], [utrace_cv_cc_biarch=no])
+AS_IF([test $utrace_cv_cc_biarch != yes], [dnl
+AC_MSG_WARN([not running biarch tests, $biarch_CC does not work])])])
+AM_CONDITIONAL(BIARCH, [test $utrace_cv_cc_biarch = yes])])
diff --git a/m4/zip.m4 b/m4/zip.m4
new file mode 100644
index 0000000..8affa3f
--- /dev/null
+++ b/m4/zip.m4
@@ -0,0 +1,20 @@
+dnl -*- Autoconf -*- test for either zlib or bzlib.
+dnl Defines --with-$1 argument, $2 automake conditional,
+dnl and sets AC_DEFINE(USE_$2) and LIBS.
+
+AC_DEFUN([eu_ZIPLIB], [dnl
+AC_ARG_WITH([[$1]],
+AS_HELP_STRING([--with-[$1]], [support [$1] compression in libdwfl]),,
+	    [with_[$1]=default])
+if test $with_[$1] != no; then
+  AC_SEARCH_LIBS([$4], [$3], [with_[$1]=yes],
+  	         [test $with_[$1] = default ||
+		  AC_MSG_ERROR([missing -l[$3] for --with-[$1]])])
+fi
+AM_CONDITIONAL([$2], test $with_[$1] = yes)
+if test $with_[$1] = yes; then
+  AC_DEFINE(USE_[$2])
+else
+  with_[$1]=no
+fi
+AH_TEMPLATE(USE_[$2], [Support $5 decompression via -l$3.])])
diff --git a/patches/0001-libdwfl-Make-dwfl_report_offline_memory-work-with-EL.patch b/patches/0001-libdwfl-Make-dwfl_report_offline_memory-work-with-EL.patch
new file mode 100644
index 0000000..07119d7
--- /dev/null
+++ b/patches/0001-libdwfl-Make-dwfl_report_offline_memory-work-with-EL.patch
@@ -0,0 +1,200 @@
+From 94cb85c3cbc59811de11869d1c1ce4f9bdb7f67c Mon Sep 17 00:00:00 2001
+From: Aleksei Vetrov <vvvvvv@google.com>
+Date: Thu, 11 Jul 2024 19:29:32 +0000
+Subject: [PATCH] libdwfl: Make dwfl_report_offline_memory work with
+ ELF_C_READ_MMAP
+To: elfutils-devel@sourceware.org
+Cc: kernel-team@android.com,
+    maennich@google.com,
+    vvvvvv@google.com
+
+elf_memory open mode recently changed from ELF_C_READ to
+ELF_C_READ_MMAP. This broken dwfl_report_offline_memory that changes
+mode to ELF_C_READ_MMAP_PRIVATE to be compatible with subsequent
+elf_begin on embedded ELF files.
+
+The proper implementation of dwfl_report_offline_memory doesn't change
+open mode and subsequent elf_begin invocations simply use cmd from the
+reference Elf*.
+
+Add tests to exercise Elf* to trigger the bug caused by incorrect cmd
+set to Elf*.
+
+	  * libdwfl/offline.c (process_archive): Use archive->cmd
+	  instead of hardcoded ELF_C_READ_MMAP_PRIVATE.
+	  * libdwfl/open.c (libdw_open_elf): Use elf->cmd instead of
+	  hardcoded ELF_C_READ_MMAP_PRIVATE.
+	  (__libdw_open_elf_memory): Don't override (*elfp)->cmd.
+	  * tests/Makefile.am (dwfl_report_offline_memory): Add libelf
+	  as dependency.
+	  * tests/dwfl-report-offline-memory.c: Add count_sections to
+	  exercise Elf* from dwfl_report_offline_memory.
+	  * tests/run-dwfl-report-offline-memory.sh: Add expected number
+	  of sections to test invocations.
+
+Signed-off-by: Aleksei Vetrov <vvvvvv@google.com>
+---
+ libdwfl/offline.c                       |  5 ++--
+ libdwfl/open.c                          |  4 +---
+ tests/Makefile.am                       |  2 +-
+ tests/dwfl-report-offline-memory.c      | 32 ++++++++++++++++++++++---
+ tests/run-dwfl-report-offline-memory.sh |  6 ++---
+ 5 files changed, 37 insertions(+), 12 deletions(-)
+
+diff --git a/libdwfl/offline.c b/libdwfl/offline.c
+index e9ab0cc1..24e9e180 100644
+--- a/libdwfl/offline.c
++++ b/libdwfl/offline.c
+@@ -32,6 +32,7 @@
+ # include <config.h>
+ #endif
+ 
++#include "libelfP.h"
+ #include "libdwflP.h"
+ #include <fcntl.h>
+ 
+@@ -254,7 +255,7 @@ process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
+ {
+   Dwfl_Module *mod = NULL;
+   /* elf_begin supports opening archives even with fd == -1 passed.  */
+-  Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
++  Elf *member = elf_begin (fd, archive->cmd, archive);
+   if (unlikely (member == NULL)) /* Empty archive.  */
+     {
+       __libdwfl_seterrno (DWFL_E_BADELF);
+@@ -263,7 +264,7 @@ process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
+ 
+   while (process_archive_member (dwfl, name, file_name, predicate,
+ 				 fd, member, &mod) != ELF_C_NULL)
+-    member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
++    member = elf_begin (fd, archive->cmd, archive);
+ 
+   /* We can drop the archive Elf handle even if we're still using members
+      in live modules.  When the last module's elf_end on a member returns
+diff --git a/libdwfl/open.c b/libdwfl/open.c
+index d0f357ed..43b29fa9 100644
+--- a/libdwfl/open.c
++++ b/libdwfl/open.c
+@@ -151,7 +151,7 @@ libdw_open_elf (int *fdp, Elf **elfp, bool close_on_fail, bool archive_ok,
+ 	  elf->state.ar.elf_ar_hdr.ar_name = "libdwfl is faking you out";
+ 	  elf->state.ar.elf_ar_hdr.ar_size = elf->maximum_size - offset;
+ 	  elf->state.ar.offset = offset - sizeof (struct ar_hdr);
+-	  Elf *subelf = elf_begin (-1, ELF_C_READ_MMAP_PRIVATE, elf);
++	  Elf *subelf = elf_begin (-1, elf->cmd, elf);
+ 	  elf->kind = ELF_K_NONE;
+ 	  if (unlikely (subelf == NULL))
+ 	    error = DWFL_E_LIBELF;
+@@ -215,8 +215,6 @@ __libdw_open_elf_memory (char *data, size_t size, Elf **elfp, bool archive_ok)
+     {
+       return DWFL_E_LIBELF;
+     }
+-  /* Allow using this ELF as reference for subsequent elf_begin calls.  */
+-  (*elfp)->cmd = ELF_C_READ_MMAP_PRIVATE;
+   return libdw_open_elf (&fd, elfp, false, archive_ok, true, false, true);
+ }
+ 
+diff --git a/tests/Makefile.am b/tests/Makefile.am
+index 77f9b90d..cfed54b7 100644
+--- a/tests/Makefile.am
++++ b/tests/Makefile.am
+@@ -792,7 +792,7 @@ test_elf_cntl_gelf_getshdr_LDADD = $(libelf)
+ dwflsyms_LDADD = $(libdw) $(libelf) $(argp_LDADD)
+ dwfllines_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
+ dwfl_report_elf_align_LDADD = $(libeu) $(libdw)
+-dwfl_report_offline_memory_LDADD = $(libeu) $(libdw)
++dwfl_report_offline_memory_LDADD = $(libeu) $(libdw) $(libelf)
+ dwfl_report_segment_contiguous_LDADD = $(libdw) $(libebl) $(libelf)
+ varlocs_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
+ backtrace_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
+diff --git a/tests/dwfl-report-offline-memory.c b/tests/dwfl-report-offline-memory.c
+index b3b4d9bd..3ecb66b9 100644
+--- a/tests/dwfl-report-offline-memory.c
++++ b/tests/dwfl-report-offline-memory.c
+@@ -18,14 +18,19 @@
+ #include <config.h>
+ 
+ #include <assert.h>
++#include <errno.h>
++#include <error.h>
+ #include <fcntl.h>
+ #include <locale.h>
+ #include <stdio.h>
+ #include <stdio_ext.h>
+ #include <stdlib.h>
++#include <string.h>
+ #include <unistd.h>
++
+ #include ELFUTILS_HEADER(dwfl)
+-#include "system.h"
++#include ELFUTILS_HEADER(elf)
++#include <gelf.h>
+ 
+ 
+ static const Dwfl_Callbacks offline_callbacks =
+@@ -45,6 +50,20 @@ count_modules (Dwfl_Module *mod __attribute__ ((unused)),
+   return DWARF_CB_OK;
+ }
+ 
++static int
++count_sections (Elf *elf)
++{
++  int result = 0;
++  Elf_Scn *section = NULL;
++  GElf_Shdr header;
++  while ((section = elf_nextscn (elf, section)) != NULL)
++    {
++      assert (gelf_getshdr (section, &header) != NULL);
++      result += 1;
++    }
++  return result;
++}
++
+ int
+ main (int argc, char **argv)
+ {
+@@ -54,10 +73,11 @@ main (int argc, char **argv)
+   /* Set locale.  */
+   (void) setlocale (LC_ALL, "");
+ 
+-  if (argc != 3)
++  if (argc != 4)
+     error (-1, 0,
+ 	   "usage: dwfl_report_offline_memory [filename] "
+-	   "[expected number of modules]");
++	   "[expected number of modules] "
++	   "[expected number of sections]");
+ 
+   const char *fname = argv[1];
+   int fd = open (fname, O_RDONLY);
+@@ -100,6 +120,12 @@ main (int argc, char **argv)
+   assert (endptr && !*endptr);
+   assert (number_of_modules == expected_number_of_modules);
+ 
++  GElf_Addr loadbase = 0;
++  Elf *elf = dwfl_module_getelf (mod, &loadbase);
++  int number_of_sections = count_sections (elf);
++  int expected_number_of_sections = atoi (argv[3]);
++  assert (number_of_sections == expected_number_of_sections);
++
+   dwfl_end (dwfl);
+   free (data);
+ 
+diff --git a/tests/run-dwfl-report-offline-memory.sh b/tests/run-dwfl-report-offline-memory.sh
+index 85f43f53..84c7f999 100755
+--- a/tests/run-dwfl-report-offline-memory.sh
++++ b/tests/run-dwfl-report-offline-memory.sh
+@@ -26,8 +26,8 @@ testfiles testarchive64.a
+ # bzip2 -zf test-ar-duplicates.a
+ testfiles test-ar-duplicates.a
+ 
+-testrun ${abs_builddir}/dwfl-report-offline-memory ./testfile-dwfl-report-elf-align-shlib.so 1
+-testrun ${abs_builddir}/dwfl-report-offline-memory ./testarchive64.a 3
+-testrun ${abs_builddir}/dwfl-report-offline-memory ./test-ar-duplicates.a 1
++testrun ${abs_builddir}/dwfl-report-offline-memory ./testfile-dwfl-report-elf-align-shlib.so 1 24
++testrun ${abs_builddir}/dwfl-report-offline-memory ./testarchive64.a 3 10
++testrun ${abs_builddir}/dwfl-report-offline-memory ./test-ar-duplicates.a 1 7
+ 
+ exit 0
+-- 
+2.45.2.993.g49e7a77208-goog
+
diff --git a/patches/add_config.patch b/patches/add_config.patch
new file mode 100644
index 0000000..7b69797
--- /dev/null
+++ b/patches/add_config.patch
@@ -0,0 +1,250 @@
+From 8a121ae1b31f4e7b9ec9b78f8b74da1852085be7 Mon Sep 17 00:00:00 2001
+From: Ian Rogers <irogers@google.com>
+Date: Mon, 11 Sep 2023 13:54:33 -0700
+Subject: [PATCH 1/2] Add Google config.h
+
+---
+ config.h | 225 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 225 insertions(+)
+ create mode 100644 config.h
+
+diff --git a/config.h b/config.h
+new file mode 100644
+index 00000000..6f4e50b1
+--- /dev/null
++++ b/config.h
+@@ -0,0 +1,225 @@
++/* GOOGLE: Generated by configure to build in the Google environment. */
++/* cmdline: ./configure --enable-maintainer-mode --without-lzma --with-zstd --disable-debuginfod --disable-libdebuginfod */
++
++/* config.h.  Generated from config.h.in by configure.  */
++/* config.h.in.  Generated from configure.ac by autoheader.  */
++
++/* Building with -fsanitize=undefined or not */
++#define CHECK_UNDEFINED 0
++
++/* Should ar and ranlib use -D behavior by default? */
++#define DEFAULT_AR_DETERMINISTIC false
++
++/* Build dummy libdebuginfod */
++/* #undef DUMMY_LIBDEBUGINFOD */
++
++/* Build debuginfod */
++/* #undef ENABLE_DEBUGINFOD */
++
++/* Enable libdebuginfod */
++/* #undef ENABLE_LIBDEBUGINFOD */
++
++/* Define to 1 if translation of program messages to the user's native
++   language is requested. */
++#define ENABLE_NLS 1
++
++/* Define to 1 if you have the Mac OS X function
++   CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
++/* #undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES */
++
++/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
++   the CoreFoundation framework. */
++/* #undef HAVE_CFPREFERENCESCOPYAPPVALUE */
++
++/* define if the compiler supports basic C++11 syntax */
++#define HAVE_CXX11 1
++
++/* Define if the GNU dcgettext() function is already present or preinstalled.
++   */
++#define HAVE_DCGETTEXT 1
++
++/* Define to 1 if you have the declaration of `mempcpy', and to 0 if you
++   don't. */
++#define HAVE_DECL_MEMPCPY 1
++
++/* Define to 1 if you have the declaration of `memrchr', and to 0 if you
++   don't. */
++#define HAVE_DECL_MEMRCHR 1
++
++/* Define to 1 if you have the declaration of `powerof2', and to 0 if you
++   don't. */
++#define HAVE_DECL_POWEROF2 1
++
++/* Define to 1 if you have the declaration of `rawmemchr', and to 0 if you
++   don't. */
++/* GOOGLE: musl support */
++#if defined(__GLIBC__) || defined(__NEWLIB__) || defined(__UCLIBC__)
++#define HAVE_DECL_RAWMEMCHR 1
++#else
++/* #undef HAVE_DECL_RAWMEMCHR */
++#endif
++
++/* Define to 1 if you have the declaration of `reallocarray', and to 0 if you
++   don't. */
++#define HAVE_DECL_REALLOCARRAY 1
++
++/* Define to 1 if you have the declaration of `strerror_r', and to 0 if you
++   don't. */
++#define HAVE_DECL_STRERROR_R 1
++
++/* Define to 1 if you have the <error.h> header file. */
++/* GOOGLE: musl support */
++#if defined(__BIONIC__) || defined(__GLIBC__) || defined(__NEWLIB__) || \
++    defined(__UCLIBC__)
++#define HAVE_ERROR_H 1
++#else
++/* #undef HAVE_ERROR_H */
++#endif
++
++/* Define to 1 if you have the <err.h> header file. */
++/* GOOGLE: musl support */
++#if defined(__NEWLIB__)
++/* undef HAVE_ERR_H */
++#else
++#define HAVE_ERR_H 1
++#endif
++
++/* Define to 1 if you have the <execinfo.h> header file. */
++#define HAVE_EXECINFO_H 1
++
++/* Defined if __attribute__((fallthrough)) is supported */
++/* GOOGLE: #undef HAVE_FALLTHROUGH */
++
++/* Defined if __attribute__((gcc_struct)) is supported */
++/* GOOGLE: #undef HAVE_GCC_STRUCT */
++
++/* Define to 1 if you have the `getrlimit' function. */
++#define HAVE_GETRLIMIT 1
++
++/* Define if the GNU gettext() function is already present or preinstalled. */
++#define HAVE_GETTEXT 1
++
++/* Define if you have the iconv() function and it works. */
++/* #undef HAVE_ICONV */
++
++/* Define to 1 if you have the <inttypes.h> header file. */
++#define HAVE_INTTYPES_H 1
++
++/* Define to 0 if libarchive is not available */
++/* #undef HAVE_LIBARCHIVE */
++
++/* Define to 1 if you have the `mremap' function. */
++#define HAVE_MREMAP 1
++
++/* Define to 1 if you have the `process_vm_readv' function. */
++#define HAVE_PROCESS_VM_READV 1
++
++/* Enable pthread_setname_np */
++#define HAVE_PTHREAD_SETNAME_NP 1
++
++/* Define to 1 if you have the `sched_getaffinity' function. */
++#define HAVE_SCHED_GETAFFINITY 1
++
++/* Define to 1 if you have the <sched.h> header file. */
++#define HAVE_SCHED_H 1
++
++/* Define to 1 if `stdatomic.h` is provided by the system, 0 otherwise. */
++#define HAVE_STDATOMIC_H 1
++
++/* Define to 1 if you have the <stdint.h> header file. */
++#define HAVE_STDINT_H 1
++
++/* Define to 1 if you have the <stdio.h> header file. */
++#define HAVE_STDIO_H 1
++
++/* Define to 1 if you have the <stdlib.h> header file. */
++#define HAVE_STDLIB_H 1
++
++/* Define if you have `strerror_r'. */
++#define HAVE_STRERROR_R 1
++
++/* Define to 1 if you have the <strings.h> header file. */
++#define HAVE_STRINGS_H 1
++
++/* Define to 1 if you have the <string.h> header file. */
++#define HAVE_STRING_H 1
++
++/* Define to 1 if you have the <sys/resource.h> header file. */
++#define HAVE_SYS_RESOURCE_H 1
++
++/* Define to 1 if you have the <sys/stat.h> header file. */
++#define HAVE_SYS_STAT_H 1
++
++/* Define to 1 if you have the <sys/types.h> header file. */
++#define HAVE_SYS_TYPES_H 1
++
++/* Define to 1 if <sys/user.h> defines struct user_regs_struct */
++#define HAVE_SYS_USER_REGS 1
++
++/* Define to 1 if you have the <unistd.h> header file. */
++#define HAVE_UNISTD_H 1
++
++/* Defined if __attribute__((visibility())) is supported */
++#define HAVE_VISIBILITY 1
++
++/* Name of package */
++#define PACKAGE "elfutils"
++
++/* Define to the address where bug reports for this package should be sent. */
++#define PACKAGE_BUGREPORT "https://sourceware.org/bugzilla"
++
++/* Define to the full name of this package. */
++#define PACKAGE_NAME "elfutils"
++
++/* Define to the full name and version of this package. */
++#define PACKAGE_STRING "elfutils 0.@eu_version@"
++
++/* Define to the one symbol short name of this package. */
++#define PACKAGE_TARNAME "elfutils"
++
++/* Define to the home page for this package. */
++#define PACKAGE_URL "http://elfutils.org/"
++
++/* Define to the version of this package. */
++#define PACKAGE_VERSION "0.@eu_version@"
++
++/* The size of `long', as computed by sizeof. */
++#define SIZEOF_LONG 8
++
++/* Define to 1 if all of the C90 standard headers exist (not just the ones
++   required in a freestanding environment). This macro is provided for
++   backward compatibility; new code need not use it. */
++#define STDC_HEADERS 1
++
++/* Define to 1 if strerror_r returns char *. */
++#define STRERROR_R_CHAR_P 1
++
++/* Support bzip2 decompression via -lbz2. */
++#define USE_BZLIB 1
++
++/* Defined if demangling is enabled */
++#define USE_DEMANGLE 1
++
++/* Defined if libraries should be thread-safe. */
++/* #undef USE_LOCKS */
++
++/* Support LZMA (xz) decompression via -llzma. */
++/* #undef USE_LZMA */
++
++/* Support gzip decompression via -lz. */
++#define USE_ZLIB 1
++
++/* Support ZSTD (zst) decompression via -lzstd. */
++#define USE_ZSTD 1
++
++/* zstd compression support */
++#define USE_ZSTD_COMPRESS 1
++
++/* Version number of package */
++#define VERSION "0.@eu_version@"
++
++/* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a
++   `char[]'. */
++#define YYTEXT_POINTER 1
++
++/* Number of bits in a file offset, on hosts where this is settable. */
++/* #undef _FILE_OFFSET_BITS */
++
++/* Define for large files, on AIX-style hosts. */
++/* #undef _LARGE_FILES */
++
++#include <eu-config.h>
+-- 
+2.42.0.283.g2d96d420d3-goog
+
diff --git a/patches/dependency-inject.patch b/patches/dependency-inject.patch
new file mode 100644
index 0000000..05919e2
--- /dev/null
+++ b/patches/dependency-inject.patch
@@ -0,0 +1,59 @@
+From 9851d533c246b3210f26cd6214877ccf1c42476a Mon Sep 17 00:00:00 2001
+From: Ian Rogers <irogers@google.com>
+Date: Mon, 11 Sep 2023 17:36:03 -0700
+Subject: [PATCH 2/2] Add google-dependency-inject.h includes
+
+The inclusion of google-dependency-inject.h is used to trick blaze's
+header file analysis to find dependencies of certain .c and .h
+files. This is necessary as the actual #includes use a #include of
+---
+ backends/common-reloc.c | 3 +++
+ libcpu/i386_disasm.c    | 3 +++
+ libcpu/i386_mne.h       | 3 +++
+ 3 files changed, 9 insertions(+)
+
+diff --git a/backends/common-reloc.c b/backends/common-reloc.c
+index a91bc87d..b780bfea 100644
+--- a/backends/common-reloc.c
++++ b/backends/common-reloc.c
+@@ -26,6 +26,9 @@
+    the GNU Lesser General Public License along with this program.  If
+    not, see <http://www.gnu.org/licenses/>.  */
+ 
++// GOOGLE
++#include "google-dependency-inject.h"
++
+ #include "libebl_CPU.h"
+ #include <assert.h>
+ 
+diff --git a/libcpu/i386_disasm.c b/libcpu/i386_disasm.c
+index dec62bfa..daa5b3d2 100644
+--- a/libcpu/i386_disasm.c
++++ b/libcpu/i386_disasm.c
+@@ -27,6 +27,9 @@
+    the GNU Lesser General Public License along with this program.  If
+    not, see <http://www.gnu.org/licenses/>.  */
+ 
++// GOOGLE
++#include "google-dependency-inject.h"
++
+ #ifdef HAVE_CONFIG_H
+ # include <config.h>
+ #endif
+diff --git a/libcpu/i386_mne.h b/libcpu/i386_mne.h
+index d5157515..dd10a4b0 100644
+--- a/libcpu/i386_mne.h
++++ b/libcpu/i386_mne.h
+@@ -29,6 +29,9 @@
+ #ifndef _I386_MNE_H
+ #define _I386_MNE_H	1
+ 
++// GOOGLE
++#include "google-dependency-inject.h"
++
+ #ifndef MNEFILE
+ # define MNEFILE "i386.mnemonics"
+ #endif
+-- 
+2.42.0.283.g2d96d420d3-goog
+
diff --git a/patches/series b/patches/series
new file mode 100644
index 0000000..ab31b2a
--- /dev/null
+++ b/patches/series
@@ -0,0 +1,3 @@
+dependency-inject.patch
+add_config.patch
+0001-libdwfl-Make-dwfl_report_offline_memory-work-with-EL.patch
diff --git a/po/ChangeLog b/po/ChangeLog
new file mode 100644
index 0000000..8894a9b
--- /dev/null
+++ b/po/ChangeLog
@@ -0,0 +1,282 @@
+2022-10-02  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.188.
+
+2022-08-05  Mark Wielaard  <mark@klomp.org>
+
+	* de.po: Set Project-Id-Version: to elfutils.
+	* es.po: Likewise.
+	* ja.po: Likewise.
+	* uk.po: Likewise.
+
+2022-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.187.
+
+2021-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.186.
+
+2021-07-25  Hayatsu Shunsuke <hayatsu.shunsuke@gmail.com>
+
+	* ja.po: update Japanese translation
+
+2021-05-22  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.185.
+
+2021-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.184.
+
+2021-03-21  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makevars (XGETTEXT_OPTIONS): Update.
+
+2021-02-21  Piotr Drąg  <piotrdrag@gmail.com>
+
+	* pl.po: Updated.
+
+2021-02-21  Piotr Drąg  <piotrdrag@gmail.com>
+
+	* POTFILES.in: Add libcpu/i386_lex.l, libcpu/i386_parse.y,
+	src/elfclassify.c and debuginfod/debuginfod-find.c.
+
+2021-02-05  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.183.
+
+2020-12-15  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makevars: Sync with Makevars.template.
+	* .gitignore: New file.
+
+	* fr.po: Remove empty translation file.
+	* it.po: Likewise.
+	* nl.po: Likewise.
+	* ru.po: Likewise.
+	* zh_CN.po: Likewise.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* *.po (msgid): Fix spelling typos.
+
+2020-10-31  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.182.
+
+2020-09-08  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.181.
+
+2020-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.180.
+
+2020-03-30  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.179.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.178.
+
+2019-08-13  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.177.
+
+2019-02-14  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.176.
+
+2018-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.172.
+
+2018-06-01  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.171.
+
+2017-09-01  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Regenerated. Replace \v with \n\n.
+
+2017-08-02  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.170.
+
+2017-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.169.
+
+2017-02-16  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* po/POTFILES.in: Removed lib/version.c, added lib/printversion.c.
+
+2016-12-27  Mark Wielaard  <mark@klomp.org>
+
+	* *.po: Update for 0.168.
+
+2016-12-24  Mark Wielaard  <mark@klomp.org>
+
+	* Makevars (COPYRIGHT_HOLDER): Set to the elfutils developers.
+	(MSGID_BUGS_ADDRESS): Set to http://sourceware.org/bugzilla/
+
+2016-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Regenerate.
+
+2016-08-04  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.167.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* po/POTFILES.in: Removed libebl/eblobjecttypename.c,
+	src/i386_ld.c, src/ld.c, src/ldgeneric.c and src/ldscript.y.
+
+2016-03-31  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.166.
+
+2016-01-11  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Regenerate.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.165.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Regenerate.
+
+2015-10-15  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.164.
+
+2015-06-19  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.163.
+
+2015-06-15  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Regenerate.
+
+2015-06-10  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.162.
+
+2014-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.161.
+
+2014-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.160.
+
+2014-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Regenerated.
+
+2014-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.159.
+
+2014-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.158.
+
+2013-07-30  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.157.
+
+2013-07-25  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* *.po: Update for 0.156.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.in.in: Upgrade to gettext-0.18.2.
+
+2012-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.155.
+
+2012-06-22  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.154.
+
+2012-02-23  Mark Wielaard  <mjw@redhat.com>
+
+	* *.po: Update for 0.153.
+
+2010-04-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* LINGUAS: Remove fr.po, it.po, nl.po, ru.po, zh_CN.  The files
+	contain no translations at all.
+
+2010-04-14  Roland McGrath  <roland@redhat.com>
+
+	* POTFILES.in: Add libdwfl/libdwflP.h.
+
+	* LINGUAS: New file.
+	* Makefile.in.in: Upgrade to gettext-0.17.
+
+2009-01-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makevars (XGETTEXT_OPTIONS): Add --flag option for argp_error.
+
+	* POTFILES.in: Add more files with translatable strings.
+
+2007-06-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in.in: Update from gettext 0.16.1.
+	* Rules-quot: Likewise.
+	* Makevars: Add more XGGETEXT_OPTIONS.
+
+	* remove-potcdata.sin: New file.
+
+	* POTFILES.in: Also include messages from libelf.
+
+2007-04-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in.in: Remove MKINSTALLDIRS.
+	Define mkinstalldirs to mkdir -p.
+
+2006-04-04  Roland McGrath  <roland@redhat.com>
+
+	* POTFILES.in: Comment out lib/xstrdup.c, not distributed any more.
+
+2005-08-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* POTFILES.in: Add src/strings.c.
+
+2005-08-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* POTFILES.in: Add src/ranlib.c.
+
+2005-08-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in.in (XGETTEXT_OPTIONS): Move adding of --flag options
+	after magic Makevars line.  Also look for ERROR from elflint.
+
+2005-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in.in: Add src/elfcmp.
+
+2005-05-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in.in (XGETTEXT_OPTIONS): Define.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* POTFILES.in: Remove unnecessary entries.
+
+2004-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* POTFILES.in: Add files from libdw, libebl, and libasm.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/po/LINGUAS b/po/LINGUAS
new file mode 100644
index 0000000..4adcc52
--- /dev/null
+++ b/po/LINGUAS
@@ -0,0 +1,5 @@
+# List of translations, i.e. .po files supplied by translators.
+de es ja pl uk
+
+# These are automagically created, not real translations.
+en@quot en@boldquot
diff --git a/po/Makevars b/po/Makevars
new file mode 100644
index 0000000..692394c
--- /dev/null
+++ b/po/Makevars
@@ -0,0 +1,74 @@
+# Makefile variables for PO directory in any package using GNU gettext.
+
+# Usually the message domain is the same as the package name.
+DOMAIN = $(PACKAGE)
+
+# These two variables depend on the location of this directory.
+subdir = po
+top_builddir = ..
+
+# These options get passed to xgettext.
+XGETTEXT_OPTIONS = --keyword=_ \
+		   --keyword=N_ \
+		   --keyword=sgettext:1g \
+		   --flag=_:1:pass-c-format \
+		   --flag=N_:1:pass-c-format \
+		   --flag=sgettext:1:pass-c-format \
+		   --flag=error:3:c-format \
+		   --flag=ERROR:1:c-format \
+		   --flag=argp_error:2:c-format \
+		   --add-comments
+
+# This is the copyright holder that gets inserted into the header of the
+# $(DOMAIN).pot file.  Set this to the copyright holder of the surrounding
+# package.  (Note that the msgstr strings, extracted from the package's
+# sources, belong to the copyright holder of the package.)  Translators are
+# expected to transfer the copyright for their translations to this person
+# or entity, or to disclaim their copyright.  The empty string stands for
+# the public domain; in this case the translators are expected to disclaim
+# their copyright.
+COPYRIGHT_HOLDER = The elfutils developers
+
+# This is the email address or URL to which the translators shall report
+# bugs in the untranslated strings:
+# - Strings which are not entire sentences, see the maintainer guidelines
+#   in the GNU gettext documentation, section 'Preparing Strings'.
+# - Strings which use unclear terms or require additional context to be
+#   understood.
+# - Strings which make invalid assumptions about notation of date, time or
+#   money.
+# - Pluralisation problems.
+# - Incorrect English spelling.
+# - Incorrect formatting.
+# It can be your email address, or a mailing list address where translators
+# can write to without being subscribed, or the URL of a web page through
+# which the translators can contact you.
+MSGID_BUGS_ADDRESS = https://sourceware.org/bugzilla/
+
+# This is the list of locale categories, beyond LC_MESSAGES, for which the
+# message catalogs shall be used.  It is usually empty.
+EXTRA_LOCALE_CATEGORIES =
+
+# This tells whether the $(DOMAIN).pot file contains messages with an 'msgctxt'
+# context.  Possible values are "yes" and "no".  Set this to yes if the
+# package uses functions taking also a message context, like pgettext(), or
+# if in $(XGETTEXT_OPTIONS) you define keywords with a context argument.
+USE_MSGCTXT = no
+
+# These options get passed to msgmerge.
+# Useful options are in particular:
+#   --previous            to keep previous msgids of translated messages,
+#   --quiet               to reduce the verbosity.
+MSGMERGE_OPTIONS =
+
+# This tells whether or not to regenerate a PO file when $(DOMAIN).pot
+# has changed.  Possible values are "yes" and "no".  Set this to no if
+# the POT file is checked in the repository and the version control
+# program ignores timestamps.
+PO_DEPENDS_ON_POT = yes
+
+# This tells whether or not to forcibly update $(DOMAIN).pot and
+# regenerate PO files on "make dist".  Possible values are "yes" and
+# "no".  Set this to no if the POT file and PO files are maintained
+# externally.
+DIST_DEPENDS_ON_UPDATE_PO = yes
diff --git a/po/POTFILES.in b/po/POTFILES.in
new file mode 100644
index 0000000..65a6cfe
--- /dev/null
+++ b/po/POTFILES.in
@@ -0,0 +1,54 @@
+# List of files which containing translatable strings.
+# Copyright (C) 2000-2010 Red Hat, Inc.
+
+# Files from the compatibility library
+lib/color.c
+lib/printversion.c
+lib/xmalloc.c
+
+# Library sources
+libasm/asm_error.c
+libcpu/i386_lex.l
+libcpu/i386_parse.y
+libdw/dwarf_error.c
+libdwfl/argp-std.c
+libdwfl/libdwflP.h
+libebl/eblbackendname.c
+libebl/eblcorenotetypename.c
+libebl/ebldynamictagname.c
+libebl/eblobjnote.c
+libebl/eblobjnotetypename.c
+libebl/eblosabiname.c
+libebl/eblsectionname.c
+libebl/eblsectiontypename.c
+libebl/eblsegmenttypename.c
+libebl/eblsymbolbindingname.c
+libebl/eblsymboltypename.c
+libelf/elf_error.c
+
+# Program sources
+src/addr2line.c
+src/ar.c
+src/arlib-argp.c
+src/arlib.c
+src/elfclassify.c
+src/elfcmp.c
+src/elfcompress.c
+src/elflint.c
+src/findtextrel.c
+src/nm.c
+src/objdump.c
+src/ranlib.c
+src/readelf.c
+src/size.c
+src/stack.c
+src/strings.c
+src/strip.c
+src/unstrip.c
+
+# debuginfod sources
+debuginfod/debuginfod-find.c
+
+# Tests
+tests/backtrace.c
+tests/dwflmodtest.c
diff --git a/po/de.po b/po/de.po
new file mode 100644
index 0000000..d6b3e2c
--- /dev/null
+++ b/po/de.po
@@ -0,0 +1,7083 @@
+# German translation of elfutils.
+# Copyright (C) 2009 THE elfutils'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the elfutils package.
+# , fuzzy
+#
+#
+# Thomas Spura <tomspur@fedoraproject.org>, 2009.
+# Cornelius Neckenig <tbull@fedoraproject.org>, 2009.
+# Michael Münch <micm@fedoraproject.org>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: elfutils\n"
+"Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n"
+"POT-Creation-Date: 2024-03-01 10:22-0500\n"
+"PO-Revision-Date: 2009-06-29 15:15+0200\n"
+"Last-Translator: Michael Münch <micm@fedoraproject.org>\n"
+"Language-Team: German\n"
+"Language: de\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Generator: Lokalize 0.3\n"
+
+#: lib/color.c:51
+msgid ""
+"colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"
+msgstr ""
+
+#: lib/color.c:127
+#, c-format
+msgid ""
+"%s: invalid argument '%s' for '--color'\n"
+"valid arguments are:\n"
+"  - 'always', 'yes', 'force'\n"
+"  - 'never', 'no', 'none'\n"
+"  - 'auto', 'tty', 'if-tty'\n"
+msgstr ""
+
+#: lib/printversion.c:39
+#, fuzzy, c-format
+msgid ""
+"Copyright (C) %s The elfutils developers <%s>.\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+msgstr ""
+"Copyright (C) %s Red Hat, Inc.\n"
+"Dies ist freie Software, siehe Quellcode für Kopierbedingungen. KEINE "
+"GARANTIE,\n"
+"auch nicht für Marktgängigkeit oder Eignung für einen Bestimmten Zweck.\n"
+
+#: lib/xmalloc.c:47 lib/xmalloc.c:60 lib/xmalloc.c:72 src/readelf.c:12203
+#: src/unstrip.c:311
+#, c-format
+msgid "memory exhausted"
+msgstr "Kein Speicher mehr verfügbar"
+
+#: libasm/asm_error.c:64 libdw/dwarf_error.c:57 libdwfl/libdwflP.h:47
+#: libelf/elf_error.c:59
+msgid "no error"
+msgstr "kein Fehler"
+
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:49
+#: libelf/elf_error.c:90
+msgid "out of memory"
+msgstr "nicht genügend Speicher"
+
+#: libasm/asm_error.c:66
+msgid "cannot create output file"
+msgstr "Ausgangsdatei konnte nicht erstellt werden"
+
+#: libasm/asm_error.c:67
+msgid "invalid parameter"
+msgstr "ungültiger Parameter"
+
+#: libasm/asm_error.c:68
+msgid "cannot change mode of output file"
+msgstr "konnte Modus der Ausgabedatei nicht ändern"
+
+#: libasm/asm_error.c:69
+msgid "cannot rename output file"
+msgstr "Ausgangsdatei konnte nicht umbenannt werden"
+
+#: libasm/asm_error.c:70
+msgid "duplicate symbol"
+msgstr "Symbol doppelt vorhanden"
+
+#: libasm/asm_error.c:71
+msgid "invalid section type for operation"
+msgstr "ungültiger Abschnittstyp für Operation"
+
+#: libasm/asm_error.c:72
+msgid "error during output of data"
+msgstr "Fehler bei Datenausgabe"
+
+#: libasm/asm_error.c:73
+msgid "no backend support available"
+msgstr "keine Backend-Unterstützung verfügbar"
+
+#: libasm/asm_error.c:82 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:48
+#: libelf/elf_error.c:62
+msgid "unknown error"
+msgstr "unbekannter Fehler"
+
+#: libcpu/i386_lex.l:121
+#, c-format
+msgid "invalid character '%c' at line %d; ignored"
+msgstr ""
+
+#: libcpu/i386_lex.l:122
+#, c-format
+msgid "invalid character '\\%o' at line %d; ignored"
+msgstr ""
+
+#: libcpu/i386_parse.y:555
+#, c-format
+msgid "while reading i386 CPU description: %s at line %d"
+msgstr ""
+
+#: libdw/dwarf_error.c:59
+msgid "invalid access"
+msgstr "Ungültiger Zugriff"
+
+#: libdw/dwarf_error.c:60
+msgid "no regular file"
+msgstr "Keine reguläre Date"
+
+#: libdw/dwarf_error.c:61
+msgid "I/O error"
+msgstr "I/O Fehler"
+
+#: libdw/dwarf_error.c:62
+msgid "invalid ELF file"
+msgstr "Ungültige ELF Datei"
+
+#: libdw/dwarf_error.c:63
+msgid "no DWARF information"
+msgstr "keine DWARF Information"
+
+#: libdw/dwarf_error.c:64
+msgid "cannot decompress DWARF"
+msgstr ""
+
+#: libdw/dwarf_error.c:65
+msgid "no ELF file"
+msgstr "keine ELF Datei"
+
+#: libdw/dwarf_error.c:66
+msgid "cannot get ELF header"
+msgstr "ELF Kopf konnte nicht ausgelesen werden"
+
+#: libdw/dwarf_error.c:68
+msgid "not implemented"
+msgstr "Nicht implementiert"
+
+#: libdw/dwarf_error.c:69 libelf/elf_error.c:110 libelf/elf_error.c:158
+msgid "invalid command"
+msgstr "Ungültiger Befehl"
+
+#: libdw/dwarf_error.c:70
+msgid "invalid version"
+msgstr "Ungültige Version"
+
+#: libdw/dwarf_error.c:71
+msgid "invalid file"
+msgstr "Ungültige Datei"
+
+#: libdw/dwarf_error.c:72
+msgid "no entries found"
+msgstr "Keine Einträge gefunden"
+
+#: libdw/dwarf_error.c:73
+msgid "invalid DWARF"
+msgstr "DWARF ungültig"
+
+#: libdw/dwarf_error.c:74
+msgid "no string data"
+msgstr ""
+
+#: libdw/dwarf_error.c:75
+#, fuzzy
+msgid ".debug_str section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:76
+#, fuzzy
+msgid ".debug_line_str section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:77
+#, fuzzy
+msgid ".debug_str_offsets section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:78
+msgid "no address value"
+msgstr "Kein Adress-Wert"
+
+#: libdw/dwarf_error.c:79
+msgid "no constant value"
+msgstr "Kein Konstanten-Wert"
+
+#: libdw/dwarf_error.c:80
+msgid "no reference value"
+msgstr "Kein Referenz-Wert"
+
+#: libdw/dwarf_error.c:81
+msgid "invalid reference value"
+msgstr "Ungültiger Referenz-Wert"
+
+#: libdw/dwarf_error.c:82
+msgid ".debug_line section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:83
+msgid "invalid .debug_line section"
+msgstr "ungültige .debug_line Sektion"
+
+#: libdw/dwarf_error.c:84
+msgid "debug information too big"
+msgstr "Debug Information zu groß"
+
+#: libdw/dwarf_error.c:85
+msgid "invalid DWARF version"
+msgstr "Ungültige DWARF Version"
+
+#: libdw/dwarf_error.c:86
+msgid "invalid directory index"
+msgstr "ungültiger Verzeichnisindex"
+
+#: libdw/dwarf_error.c:87 libdwfl/libdwflP.h:69
+msgid "address out of range"
+msgstr "Außerhalb des Adressbereiches"
+
+#: libdw/dwarf_error.c:88
+#, fuzzy
+msgid ".debug_loc section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:89
+#, fuzzy
+msgid ".debug_loclists section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:90
+#, fuzzy
+msgid "not a location list value"
+msgstr "Kein Konstanten-Wert"
+
+#: libdw/dwarf_error.c:91
+msgid "no block data"
+msgstr ""
+
+#: libdw/dwarf_error.c:92
+msgid "invalid line index"
+msgstr "Ungültiger Zeilenindex"
+
+#: libdw/dwarf_error.c:93
+msgid "invalid address range index"
+msgstr "Ungültiger Adressbereichs Index"
+
+#: libdw/dwarf_error.c:94 libdwfl/libdwflP.h:70
+msgid "no matching address range"
+msgstr "Kein passender Adressbereich"
+
+#: libdw/dwarf_error.c:95
+msgid "no flag value"
+msgstr ""
+
+#: libdw/dwarf_error.c:96 libelf/elf_error.c:235
+msgid "invalid offset"
+msgstr "ungültiger Offset"
+
+#: libdw/dwarf_error.c:97
+msgid ".debug_ranges section missing"
+msgstr ""
+
+#: libdw/dwarf_error.c:98
+#, fuzzy
+msgid ".debug_rnglists section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:99
+#, fuzzy
+msgid "invalid CFI section"
+msgstr "ungültiger Abschnitt"
+
+#: libdw/dwarf_error.c:100
+msgid "no alternative debug link found"
+msgstr ""
+
+#: libdw/dwarf_error.c:101
+#, fuzzy
+msgid "invalid opcode"
+msgstr "ungültiger Operand"
+
+#: libdw/dwarf_error.c:102
+msgid "not a CU (unit) DIE"
+msgstr ""
+
+#: libdw/dwarf_error.c:103
+#, fuzzy
+msgid "unknown language code"
+msgstr "unbekannter Typ"
+
+#: libdw/dwarf_error.c:104
+#, fuzzy
+msgid ".debug_addr section missing"
+msgstr ".debug_line Sektion fehlt"
+
+#: libdw/dwarf_error.c:105
+#, fuzzy
+#| msgid "unknown version"
+msgid "unknown section"
+msgstr "unbekannte Version"
+
+#: libdwfl/argp-std.c:45 src/stack.c:643 src/unstrip.c:2598
+msgid "Input selection options:"
+msgstr "Eingabeauswahloptionen:"
+
+#: libdwfl/argp-std.c:46
+msgid "Find addresses in FILE"
+msgstr "Finde Adressen in FILE"
+
+#: libdwfl/argp-std.c:48
+msgid "Find addresses from signatures found in COREFILE"
+msgstr "Finde Adressen von Signatur aus COREFILE"
+
+#: libdwfl/argp-std.c:50
+msgid "Find addresses in files mapped into process PID"
+msgstr ""
+
+#: libdwfl/argp-std.c:52
+msgid ""
+"Find addresses in files mapped as read from FILE in Linux /proc/PID/maps "
+"format"
+msgstr ""
+
+#: libdwfl/argp-std.c:54
+msgid "Find addresses in the running kernel"
+msgstr "Finde Adressen im laufenden Kernel"
+
+#: libdwfl/argp-std.c:56
+msgid "Kernel with all modules"
+msgstr "Kernel mit allen Modulen"
+
+#: libdwfl/argp-std.c:58 src/stack.c:650
+msgid "Search path for separate debuginfo files"
+msgstr "Dateisuchpfad für separate Debug-Informationen"
+
+#: libdwfl/argp-std.c:159
+msgid "only one of -e, -p, -k, -K, or --core allowed"
+msgstr "Nur eine Option von -e, -p, -k, -K, oder --core erlaubt"
+
+#: libdwfl/argp-std.c:232
+msgid "cannot load kernel symbols"
+msgstr "Konnte Kernel Symbole nicht laden"
+
+#. Non-fatal to have no modules since we do have the kernel.
+#: libdwfl/argp-std.c:236
+msgid "cannot find kernel modules"
+msgstr "Konnte Kernel Module nicht finden"
+
+#: libdwfl/argp-std.c:253
+msgid "cannot find kernel or modules"
+msgstr "Konnte Kernel oder Module nicht finden"
+
+#: libdwfl/argp-std.c:292
+#, c-format
+msgid "cannot read ELF core file: %s"
+msgstr "Konnte ELF Kerndatei %s nicht lesen"
+
+#: libdwfl/argp-std.c:315
+#, fuzzy
+msgid "Not enough memory"
+msgstr "nicht genügend Speicher"
+
+#: libdwfl/argp-std.c:325
+msgid "No modules recognized in core file"
+msgstr "Keine Module in der Kerndatei gefunden"
+
+#: libdwfl/libdwflP.h:50
+msgid "See errno"
+msgstr ""
+
+#: libdwfl/libdwflP.h:51
+msgid "See elf_errno"
+msgstr ""
+
+#: libdwfl/libdwflP.h:52
+msgid "See dwarf_errno"
+msgstr ""
+
+#: libdwfl/libdwflP.h:53
+msgid "See ebl_errno (XXX missing)"
+msgstr ""
+
+#: libdwfl/libdwflP.h:54
+msgid "gzip decompression failed"
+msgstr ""
+
+#: libdwfl/libdwflP.h:55
+msgid "bzip2 decompression failed"
+msgstr ""
+
+#: libdwfl/libdwflP.h:56
+msgid "LZMA decompression failed"
+msgstr ""
+
+#: libdwfl/libdwflP.h:57
+msgid "zstd decompression failed"
+msgstr ""
+
+#: libdwfl/libdwflP.h:58
+msgid "no support library found for machine"
+msgstr ""
+
+#: libdwfl/libdwflP.h:59
+msgid "Callbacks missing for ET_REL file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:60
+msgid "Unsupported relocation type"
+msgstr ""
+
+#: libdwfl/libdwflP.h:61
+msgid "r_offset is bogus"
+msgstr ""
+
+#: libdwfl/libdwflP.h:62 libelf/elf_error.c:114 libelf/elf_error.c:174
+msgid "offset out of range"
+msgstr "Offset ausserhalb des Bereichs"
+
+#: libdwfl/libdwflP.h:63
+#, fuzzy
+msgid "relocation refers to undefined symbol"
+msgstr "Zeige Grösse der definierten Symbole"
+
+#: libdwfl/libdwflP.h:64
+msgid "Callback returned failure"
+msgstr ""
+
+#: libdwfl/libdwflP.h:65
+#, fuzzy
+msgid "No DWARF information found"
+msgstr "keine DWARF Information"
+
+#: libdwfl/libdwflP.h:66
+msgid "No symbol table found"
+msgstr ""
+
+#: libdwfl/libdwflP.h:67
+#, fuzzy
+msgid "No ELF program headers"
+msgstr "Programm-Köpfe anzeigen"
+
+#: libdwfl/libdwflP.h:68
+msgid "address range overlaps an existing module"
+msgstr ""
+
+#: libdwfl/libdwflP.h:71
+msgid "image truncated"
+msgstr ""
+
+#: libdwfl/libdwflP.h:72
+#, fuzzy
+msgid "ELF file opened"
+msgstr "keine ELF Datei"
+
+#: libdwfl/libdwflP.h:73
+#, fuzzy
+msgid "not a valid ELF file"
+msgstr "Ungültige ELF Datei"
+
+#: libdwfl/libdwflP.h:74
+#, fuzzy
+msgid "cannot handle DWARF type description"
+msgstr "konnte Elf-Deskriptor nicht erzeugen: %s"
+
+#: libdwfl/libdwflP.h:75
+msgid "ELF file does not match build ID"
+msgstr ""
+
+#: libdwfl/libdwflP.h:76
+#, fuzzy
+msgid "corrupt .gnu.prelink_undo section data"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: libdwfl/libdwflP.h:77
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:78
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:79
+#, fuzzy
+msgid "Invalid register"
+msgstr "ungültiger Parameter"
+
+#: libdwfl/libdwflP.h:80
+#, fuzzy
+#| msgid "no reference value"
+msgid "Unknown register value"
+msgstr "Kein Referenz-Wert"
+
+#: libdwfl/libdwflP.h:81
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:83
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "DWARF ungültig"
+
+#: libdwfl/libdwflP.h:85
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:87
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+#, fuzzy
+msgid "Invalid argument"
+msgstr "ungültiger Parameter"
+
+#: libdwfl/libdwflP.h:91
+#, fuzzy
+msgid "Not an ET_CORE ELF file"
+msgstr "Ungültige ELF Datei"
+
+#: libebl/eblbackendname.c:41
+msgid "No backend"
+msgstr "Kein Backend"
+
+#: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:79
+#: libebl/eblobjnotetypename.c:113 libebl/eblobjnotetypename.c:134
+#: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83
+#: libebl/eblsectiontypename.c:116 libebl/eblsegmenttypename.c:81
+msgid "<unknown>"
+msgstr "<Unbekannt>"
+
+#: libebl/ebldynamictagname.c:103
+#, c-format
+msgid "<unknown>: %#<PRIx64>"
+msgstr "<Unbekannt>: %#<PRIx64>"
+
+#: libebl/eblobjnote.c:58
+#, fuzzy, c-format
+msgid "unknown SDT version %u\n"
+msgstr "unbekannte Version"
+
+#: libebl/eblobjnote.c:76
+#, fuzzy, c-format
+msgid "invalid SDT probe descriptor\n"
+msgstr "ungültiger Datei-Deskriptor"
+
+#: libebl/eblobjnote.c:126
+#, c-format
+msgid "    PC: "
+msgstr ""
+
+#: libebl/eblobjnote.c:128
+#, c-format
+msgid " Base: "
+msgstr ""
+
+#: libebl/eblobjnote.c:130
+#, c-format
+msgid " Semaphore: "
+msgstr ""
+
+#: libebl/eblobjnote.c:132
+#, c-format
+msgid "    Provider: "
+msgstr ""
+
+#: libebl/eblobjnote.c:134
+#, c-format
+msgid " Name: "
+msgstr ""
+
+#: libebl/eblobjnote.c:136
+#, c-format
+msgid " Args: "
+msgstr ""
+
+#: libebl/eblobjnote.c:304
+#, c-format
+msgid "    Build ID: "
+msgstr "    Build ID: "
+
+#. A non-null terminated version string.
+#: libebl/eblobjnote.c:315
+#, c-format
+msgid "    Linker version: %.*s\n"
+msgstr ""
+
+#: libebl/eblobjnote.c:642
+#, c-format
+msgid "    OS: %s, ABI: "
+msgstr "    OS: %s, ABI: "
+
+#: libebl/eblosabiname.c:70
+msgid "Stand alone"
+msgstr ""
+
+#: libebl/eblsymbolbindingname.c:68 libebl/eblsymboltypename.c:74
+#, c-format
+msgid "<unknown>: %d"
+msgstr "<unbekannt>: %d"
+
+#: libelf/elf_error.c:66
+msgid "unknown version"
+msgstr "unbekannte Version"
+
+#: libelf/elf_error.c:70
+msgid "unknown type"
+msgstr "unbekannter Typ"
+
+#: libelf/elf_error.c:74
+msgid "invalid `Elf' handle"
+msgstr "ungültiges `Elf'-Handle"
+
+#: libelf/elf_error.c:78
+msgid "invalid size of source operand"
+msgstr "ungültige Grösse des Quell-Operanden"
+
+#: libelf/elf_error.c:82
+msgid "invalid size of destination operand"
+msgstr "ungültige Grösse des Ziel-Operanden"
+
+#: libelf/elf_error.c:86 src/readelf.c:6759
+#, c-format
+msgid "invalid encoding"
+msgstr "ungültige Kodierung"
+
+#: libelf/elf_error.c:94
+msgid "invalid file descriptor"
+msgstr "ungültiger Datei-Deskriptor"
+
+#: libelf/elf_error.c:98
+#, fuzzy
+msgid "invalid ELF file data"
+msgstr "Ungültige ELF Datei"
+
+#: libelf/elf_error.c:102
+msgid "invalid operation"
+msgstr "ungültige Operation"
+
+#: libelf/elf_error.c:106
+msgid "ELF version not set"
+msgstr "ELF-Version nicht gesetzt"
+
+#: libelf/elf_error.c:118
+msgid "invalid fmag field in archive header"
+msgstr "ungültiges fmag-Feld im Archivheader"
+
+#: libelf/elf_error.c:122
+msgid "invalid archive file"
+msgstr "Ungültige Archiv-Datei"
+
+#: libelf/elf_error.c:126
+msgid "descriptor is not for an archive"
+msgstr ""
+
+#: libelf/elf_error.c:130
+msgid "no index available"
+msgstr "kein Index verfügbar"
+
+#: libelf/elf_error.c:134
+msgid "cannot read data from file"
+msgstr "Daten aus der Datei konnten nicht gelesen werden"
+
+#: libelf/elf_error.c:138
+msgid "cannot write data to file"
+msgstr "Daten konnten nicht in die Datei geschrieben werden"
+
+#: libelf/elf_error.c:142
+msgid "invalid binary class"
+msgstr "ungültige Binärklasse"
+
+#: libelf/elf_error.c:146
+msgid "invalid section index"
+msgstr "ungültiger Abschnittsindex"
+
+#: libelf/elf_error.c:150
+msgid "invalid operand"
+msgstr "ungültiger Operand"
+
+#: libelf/elf_error.c:154
+msgid "invalid section"
+msgstr "ungültiger Abschnitt"
+
+#: libelf/elf_error.c:162
+msgid "executable header not created first"
+msgstr "ausführbarer Header wurde nicht zuerst erstellt"
+
+#: libelf/elf_error.c:166
+msgid "file descriptor disabled"
+msgstr "Datei-Deskriptor deaktiviert"
+
+#: libelf/elf_error.c:170
+#, fuzzy
+msgid "archive/member file descriptor mismatch"
+msgstr "Datei-Deskriptor deaktiviert"
+
+#: libelf/elf_error.c:178
+msgid "cannot manipulate null section"
+msgstr ""
+
+#: libelf/elf_error.c:182
+#, fuzzy
+msgid "data/scn mismatch"
+msgstr "data/scn Unterschied"
+
+#: libelf/elf_error.c:186
+msgid "invalid section header"
+msgstr "ungültiger Abschnitts-Header"
+
+#: libelf/elf_error.c:190 src/readelf.c:10638 src/readelf.c:11243
+#: src/readelf.c:11344 src/readelf.c:11532
+#, c-format
+msgid "invalid data"
+msgstr "Ungültige Daten"
+
+#: libelf/elf_error.c:194
+msgid "unknown data encoding"
+msgstr "Unbekannte Datenkodierung"
+
+#: libelf/elf_error.c:198
+msgid "section `sh_size' too small for data"
+msgstr "Abschnitt `sh_size' zu klein für Daten"
+
+#: libelf/elf_error.c:202
+msgid "invalid section alignment"
+msgstr "ungültige Abschnittsausrichtung"
+
+#: libelf/elf_error.c:206
+msgid "invalid section entry size"
+msgstr ""
+
+#: libelf/elf_error.c:210
+msgid "update() for write on read-only file"
+msgstr ""
+
+#: libelf/elf_error.c:214
+msgid "no such file"
+msgstr "Datei nicht gefunden"
+
+#: libelf/elf_error.c:218
+msgid "only relocatable files can contain section groups"
+msgstr ""
+
+#: libelf/elf_error.c:223
+msgid ""
+"program header only allowed in executables, shared objects, and core files"
+msgstr ""
+
+#: libelf/elf_error.c:230
+msgid "file has no program header"
+msgstr "Datei hat keinen Programm-Kopf"
+
+#: libelf/elf_error.c:240
+#, fuzzy
+msgid "invalid section type"
+msgstr "ungültiger Abschnitt"
+
+#: libelf/elf_error.c:245
+#, fuzzy
+msgid "invalid section flags"
+msgstr "ungültiger Abschnitt"
+
+#: libelf/elf_error.c:250
+msgid "section does not contain compressed data"
+msgstr ""
+
+#: libelf/elf_error.c:255
+msgid "section contains compressed data"
+msgstr ""
+
+#: libelf/elf_error.c:260
+#, fuzzy
+msgid "unknown compression type"
+msgstr "unbekannter Typ"
+
+#: libelf/elf_error.c:265
+#, fuzzy
+msgid "cannot compress data"
+msgstr "konnte Abschnittsdaten nicht kopieren: %s"
+
+#: libelf/elf_error.c:270
+#, fuzzy
+msgid "cannot decompress data"
+msgstr "konnte Abschnittsdaten nicht kopieren: %s"
+
+#: src/addr2line.c:58
+#, fuzzy
+msgid "Input format options:"
+msgstr "Eingabeauswahloptionen:"
+
+#: src/addr2line.c:60
+msgid "Treat addresses as offsets relative to NAME section."
+msgstr ""
+
+#: src/addr2line.c:62
+#, fuzzy
+msgid "Output format options:"
+msgstr "Ausgabeformat:"
+
+#: src/addr2line.c:63
+msgid "Print address before each entry"
+msgstr ""
+
+#: src/addr2line.c:64
+msgid "Show only base names of source files"
+msgstr ""
+
+#: src/addr2line.c:66
+msgid "Show absolute file names using compilation directory (default)"
+msgstr ""
+
+#: src/addr2line.c:67
+msgid "Also show function names"
+msgstr ""
+
+#: src/addr2line.c:68
+msgid "Also show symbol or section names"
+msgstr ""
+
+#: src/addr2line.c:69
+msgid "Also show symbol and the section names"
+msgstr ""
+
+#: src/addr2line.c:70
+msgid "Also show line table flags"
+msgstr ""
+
+#: src/addr2line.c:72
+msgid ""
+"Show all source locations that caused inline expansion of subroutines at the "
+"address."
+msgstr ""
+
+#: src/addr2line.c:75
+msgid "Show demangled symbols (ARG is always ignored)"
+msgstr ""
+
+#: src/addr2line.c:76
+#, fuzzy
+#| msgid "Display only defined symbols"
+msgid "Show demangled symbols"
+msgstr "Zeige nur definierte Symbole"
+
+#: src/addr2line.c:78
+msgid "Print all information on one line, and indent inlines"
+msgstr ""
+
+#: src/addr2line.c:80
+msgid "Show relative file names without compilation directory"
+msgstr ""
+
+#: src/addr2line.c:82 src/elfcmp.c:69 src/findtextrel.c:65 src/nm.c:99
+#: src/strings.c:77
+msgid "Miscellaneous:"
+msgstr "Verschiedenes:"
+
+#. Short description of program.
+#: src/addr2line.c:90
+msgid ""
+"Locate source files and line information for ADDRs (in a.out by default)."
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: src/addr2line.c:94
+msgid "[ADDR...]"
+msgstr ""
+
+#: src/addr2line.c:530
+#, fuzzy
+msgid "Section syntax requires exactly one module"
+msgstr "Abschnitt syntax benötigt genau ein Modul"
+
+#: src/addr2line.c:552
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside section '%s'"
+msgstr ""
+
+#: src/addr2line.c:662
+#, c-format
+msgid "cannot find symbol '%s'"
+msgstr "Konnte Symbol '%s' nicht finden"
+
+#: src/addr2line.c:667
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
+msgstr ""
+
+#: src/ar.c:66
+msgid "Commands:"
+msgstr "Befehle:"
+
+#: src/ar.c:67
+msgid "Delete files from archive."
+msgstr "Dateien aus dem Archiv löschen."
+
+#: src/ar.c:68
+msgid "Move files in archive."
+msgstr "Dateien zum Archiv hinzufügen."
+
+#: src/ar.c:69
+msgid "Print files in archive."
+msgstr "Packe Dateien in Archiv"
+
+#: src/ar.c:70
+msgid "Quick append files to archive."
+msgstr "Hänge Dateien an ein Archiv"
+
+#: src/ar.c:72
+msgid "Replace existing or insert new file into archive."
+msgstr "Ersetze existierende oder füge neue Datei in das Archiv ein."
+
+#: src/ar.c:73
+msgid "Display content of archive."
+msgstr "Zeige Archivinhalt an."
+
+#: src/ar.c:74
+msgid "Extract files from archive."
+msgstr "Entpacke Dateien aus dem Archiv"
+
+#: src/ar.c:76
+msgid "Command Modifiers:"
+msgstr ""
+
+#: src/ar.c:77
+msgid "Preserve original dates."
+msgstr "Erhalte ursprüngliche Daten."
+
+#: src/ar.c:78
+msgid "Use instance [COUNT] of name."
+msgstr ""
+
+#: src/ar.c:80
+msgid "Do not replace existing files with extracted files."
+msgstr "Ersetze existierende Dateien nicht mit entpackten Dateien"
+
+#: src/ar.c:81
+msgid "Allow filename to be truncated if necessary."
+msgstr "Erlaube angehängte Dateinamen, wenn nötig"
+
+#: src/ar.c:83
+msgid "Provide verbose output."
+msgstr "Zeige detaillierte Ausgabe."
+
+#: src/ar.c:84
+msgid "Force regeneration of symbol table."
+msgstr "Erzwinge Regenerierung der Symboltabelle."
+
+#: src/ar.c:85
+msgid "Insert file after [MEMBER]."
+msgstr "Füge Datei nach [MEMBER] ein."
+
+#: src/ar.c:86
+msgid "Insert file before [MEMBER]."
+msgstr "Füge Datei vor [MEMBER] ein."
+
+#: src/ar.c:87
+msgid "Same as -b."
+msgstr "Genau wie -b."
+
+#: src/ar.c:88
+msgid "Suppress message when library has to be created."
+msgstr "Unterdrücke Nachricht wenn Bibliothek erstellt werden muss."
+
+#: src/ar.c:90
+#, fuzzy
+msgid "Use full path for file matching."
+msgstr "Vollständigen Pfad für Dateiabgleich verwenden."
+
+#: src/ar.c:91
+msgid "Update only older files in archive."
+msgstr "Nur ältere Datein im Archiv aktualisieren"
+
+#. Short description of program.
+#: src/ar.c:97
+msgid "Create, modify, and extract from archives."
+msgstr "Erstelle, ändere, extrahiere von Archiven"
+
+#. Strings for arguments in help texts.
+#: src/ar.c:100
+msgid "[MEMBER] [COUNT] ARCHIVE [FILE...]"
+msgstr "[MEMBER] [COUNT] ARCHIVE [FILE...]"
+
+#: src/ar.c:179
+#, c-format
+msgid "'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"
+msgstr "'a', 'b', und 'i' nur zusammen mit 'm' and 'r Optionen"
+
+#: src/ar.c:184
+#, c-format
+msgid "MEMBER parameter required for 'a', 'b', and 'i' modifiers"
+msgstr ""
+
+#: src/ar.c:200
+#, c-format
+msgid "'N' is only meaningful with the 'x' and 'd' options"
+msgstr "'N' ist nur mit den Optionen 'x' und 'd' von Bedeutung."
+
+#: src/ar.c:205
+#, c-format
+msgid "COUNT parameter required"
+msgstr "COUNT Parameter erforderlich"
+
+#: src/ar.c:217
+#, c-format
+msgid "invalid COUNT parameter %s"
+msgstr "Ungültiger COUNT Parameter %s"
+
+#: src/ar.c:224
+#, fuzzy, c-format
+msgid "'%c' is only meaningful with the 'x' option"
+msgstr "'%' ist nur mit der Option 'x' von Bedeutung"
+
+#: src/ar.c:230
+#, c-format
+msgid "archive name required"
+msgstr "Archivname erforderlich"
+
+#: src/ar.c:243
+#, c-format
+msgid "command option required"
+msgstr ""
+
+#: src/ar.c:294
+#, c-format
+msgid "More than one operation specified"
+msgstr "Mehr als eine Operation angegeben"
+
+#: src/ar.c:388
+#, c-format
+msgid "cannot open archive '%s'"
+msgstr "Konnte Archiv '%s' nicht öffnen"
+
+#: src/ar.c:398
+#, c-format
+msgid "cannot open archive '%s': %s"
+msgstr "Konnte Archiv '%s': %s nicht öffnen"
+
+#: src/ar.c:402
+#, c-format
+msgid "%s: not an archive file"
+msgstr "%s: Keine Archiv-Datei"
+
+#: src/ar.c:406
+#, c-format
+msgid "cannot stat archive '%s'"
+msgstr ""
+
+#: src/ar.c:418
+#, c-format
+msgid "no entry %s in archive\n"
+msgstr "Kein Eintrag %s in Archiv\n"
+
+#: src/ar.c:471 src/ar.c:925 src/ar.c:1131
+msgid "cannot create hash table"
+msgstr "Konnte Hash-Tabelle nicht erstellen"
+
+#: src/ar.c:477 src/ar.c:931 src/ar.c:1139
+msgid "cannot insert into hash table"
+msgstr "Konnte nicht in Hash-Tabelle einfügen"
+
+#: src/ar.c:485 src/ranlib.c:147
+#, c-format
+msgid "cannot stat '%s'"
+msgstr ""
+
+#: src/ar.c:587
+#, c-format
+msgid "cannot read content of %s: %s"
+msgstr "Konnte Inhalt von %s: %s nicht lesen"
+
+#: src/ar.c:630
+#, c-format
+msgid "cannot open %.*s"
+msgstr "Konnte %.*s nicht öffnen"
+
+#: src/ar.c:652
+#, c-format
+msgid "failed to write %s"
+msgstr "Konnte %s nicht schreiben"
+
+#: src/ar.c:664
+#, c-format
+msgid "cannot change mode of %s"
+msgstr ""
+
+#: src/ar.c:680
+#, c-format
+msgid "cannot change modification time of %s"
+msgstr "Konnte Bearbeitungszeit von %s nicht ändern"
+
+#: src/ar.c:726
+#, c-format
+msgid "cannot rename temporary file to %.*s"
+msgstr "Konnte temporäre Datei nicht in %.*s umbenennen"
+
+#: src/ar.c:762 src/ar.c:1016 src/ar.c:1419 src/ranlib.c:221
+#, c-format
+msgid "cannot create new file"
+msgstr "neue Datei konnte nicht angelegt werden"
+
+#: src/ar.c:1221
+#, c-format
+msgid "position member %s not found"
+msgstr ""
+
+#: src/ar.c:1231
+#, c-format
+msgid "%s: no entry %s in archive!\n"
+msgstr "%s: Kein Eintrag %s in dem Archiv!\n"
+
+#: src/ar.c:1260 src/objdump.c:240
+#, c-format
+msgid "cannot open %s"
+msgstr "Konnte %s nicht öffnen"
+
+#: src/ar.c:1265
+#, c-format
+msgid "cannot stat %s"
+msgstr ""
+
+#: src/ar.c:1271
+#, c-format
+msgid "%s is no regular file"
+msgstr "%s ist keine reguläre Datei"
+
+#: src/ar.c:1284
+#, c-format
+msgid "cannot get ELF descriptor for %s: %s\n"
+msgstr ""
+
+#: src/ar.c:1304
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "Konnte %s: %s nicht lesen"
+
+#: src/ar.c:1479
+#, fuzzy, c-format
+msgid "cannot represent ar_date"
+msgstr "konnte Abschnittsdaten nicht kopieren: %s"
+
+#: src/ar.c:1485
+#, fuzzy, c-format
+msgid "cannot represent ar_uid"
+msgstr "konnte Abschnittsdaten nicht kopieren: %s"
+
+#: src/ar.c:1491
+#, fuzzy, c-format
+msgid "cannot represent ar_gid"
+msgstr "konnte Abschnittsdaten nicht kopieren: %s"
+
+#: src/ar.c:1497
+#, fuzzy, c-format
+msgid "cannot represent ar_mode"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/ar.c:1503
+#, fuzzy, c-format
+msgid "cannot represent ar_size"
+msgstr "Konnte %s nicht öffnen"
+
+#: src/arlib-argp.c:31
+msgid "Use zero for uid, gid, and date in archive members."
+msgstr ""
+
+#: src/arlib-argp.c:33
+msgid "Use actual uid, gid, and date in archive members."
+msgstr ""
+
+#: src/arlib-argp.c:62
+#, c-format
+msgid "%s (default)"
+msgstr ""
+
+#. The archive is too big.
+#: src/arlib.c:212
+#, c-format
+msgid "the archive '%s' is too large"
+msgstr "Das Archiv '%s' ist zu groß"
+
+#: src/arlib.c:225
+#, c-format
+msgid "cannot read ELF header of %s(%s): %s"
+msgstr "\"Konnte ELF-Kopf von %s(%s): %s nicht lesen"
+
+#: src/elfclassify.c:91
+msgid "opening"
+msgstr ""
+
+#: src/elfclassify.c:98
+msgid "reading"
+msgstr ""
+
+#: src/elfclassify.c:244
+#, fuzzy
+#| msgid "cannot get ELF header"
+msgid "ELF header"
+msgstr "ELF Kopf konnte nicht ausgelesen werden"
+
+#: src/elfclassify.c:255
+#, fuzzy
+#| msgid "Program Headers:"
+msgid "program headers"
+msgstr "Programm-Köpfe:"
+
+#: src/elfclassify.c:264
+#, fuzzy
+#| msgid "Program Headers:"
+msgid "program header"
+msgstr "Programm-Köpfe:"
+
+#: src/elfclassify.c:284
+#, fuzzy
+#| msgid "invalid section header"
+msgid "section headers"
+msgstr "ungültiger Abschnitts-Header"
+
+#: src/elfclassify.c:295
+#, fuzzy
+msgid "section header string table index"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfclassify.c:309
+#, fuzzy
+msgid "could not obtain section header"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfclassify.c:315
+#, fuzzy
+msgid "could not obtain section name"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfclassify.c:828
+msgid "writing to standard output"
+msgstr ""
+
+#: src/elfclassify.c:855
+msgid "reading from standard input"
+msgstr ""
+
+#: src/elfclassify.c:876
+#, fuzzy
+#| msgid "Input selection options:"
+msgid "Classification options"
+msgstr "Eingabeauswahloptionen:"
+
+#: src/elfclassify.c:878
+msgid "File looks like an ELF object or archive/static library (default)"
+msgstr ""
+
+#: src/elfclassify.c:881
+msgid "File is an regular ELF object (not an archive/static library)"
+msgstr ""
+
+#: src/elfclassify.c:884
+msgid "File is an ELF archive or static library"
+msgstr ""
+
+#: src/elfclassify.c:887
+msgid "File is an ELF core dump file"
+msgstr ""
+
+#: src/elfclassify.c:890
+msgid ""
+"File is an ELF file with symbol table or .debug_* sections and can be "
+"stripped further"
+msgstr ""
+
+#: src/elfclassify.c:893
+msgid "File is (primarily) an ELF program executable (not primarily a DSO)"
+msgstr ""
+
+#: src/elfclassify.c:896
+msgid "File is an ELF program executable (might also be a DSO)"
+msgstr ""
+
+#: src/elfclassify.c:899
+msgid ""
+"File is (primarily) an ELF shared object (DSO) (not primarily an executable)"
+msgstr ""
+
+#: src/elfclassify.c:902
+msgid "File is an ELF shared object (DSO) (might also be an executable)"
+msgstr ""
+
+#: src/elfclassify.c:906
+#, fuzzy
+#| msgid "cannot find kernel modules"
+msgid "File is a linux kernel module"
+msgstr "Konnte Kernel Module nicht finden"
+
+#: src/elfclassify.c:908
+msgid "File is a debug only ELF file (separate .debug, .dwo or dwz multi-file)"
+msgstr ""
+
+#: src/elfclassify.c:911
+msgid "File is a loadable ELF object (program or shared object)"
+msgstr ""
+
+#: src/elfclassify.c:940
+msgid "Input flags"
+msgstr ""
+
+#: src/elfclassify.c:942
+msgid "Only classify regular (not symlink nor special device) files"
+msgstr ""
+
+#: src/elfclassify.c:944
+msgid ""
+"Also read file names to process from standard input, separated by newlines"
+msgstr ""
+
+#: src/elfclassify.c:947
+msgid ""
+"Also read file names to process from standard input, separated by ASCII NUL "
+"bytes"
+msgstr ""
+
+#: src/elfclassify.c:950
+msgid "Do not read files from standard input (default)"
+msgstr ""
+
+#: src/elfclassify.c:952
+msgid "Try to open compressed files or embedded (kernel) ELF images"
+msgstr ""
+
+#: src/elfclassify.c:955
+#, fuzzy
+#| msgid "Output format:"
+msgid "Output flags"
+msgstr "Ausgabeformat:"
+
+#: src/elfclassify.c:957
+msgid "Output names of files, separated by newline"
+msgstr ""
+
+#: src/elfclassify.c:959
+msgid "Output names of files, separated by ASCII NUL"
+msgstr ""
+
+#: src/elfclassify.c:961
+#, fuzzy
+#| msgid "More than one output file name given."
+msgid "Do not output file names"
+msgstr "Mehr als ein Name der Ausgabedatei angegeben."
+
+#: src/elfclassify.c:963
+msgid "If printing file names, print matching files (default)"
+msgstr ""
+
+#: src/elfclassify.c:965
+msgid "If printing file names, print files that do not match"
+msgstr ""
+
+#: src/elfclassify.c:967
+msgid "Additional flags"
+msgstr ""
+
+#: src/elfclassify.c:969
+msgid "Output additional information (can be specified multiple times)"
+msgstr ""
+
+#: src/elfclassify.c:971
+msgid "Suppress some error output (counterpart to --verbose)"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: src/elfclassify.c:979 src/elfcompress.c:1436 src/elflint.c:77
+#: src/readelf.c:161
+msgid "FILE..."
+msgstr "DATEI..."
+
+#: src/elfclassify.c:980
+msgid ""
+"Determine the type of an ELF file.\n"
+"\n"
+"All of the classification options must apply at the same time to a "
+"particular file.  Classification options can be negated using a \"--not-\" "
+"prefix.\n"
+"\n"
+"Since modern ELF does not clearly distinguish between programs and dynamic "
+"shared objects, you should normally use either --executable or --shared to "
+"identify the primary purpose of a file.  Only one of the --shared and --"
+"executable checks can pass for a file.\n"
+"\n"
+"If you want to know whether an ELF object might a program or a shared "
+"library (but could be both), then use --program or --library. Some ELF files "
+"will classify as both a program and a library.\n"
+"\n"
+"If you just want to know whether an ELF file is loadable (as program or "
+"library) use --loadable.  Note that files that only contain (separate) debug "
+"information (--debug-only) are never --loadable (even though they might "
+"contain program headers).  Linux kernel modules are also not --loadable (in "
+"the normal sense).\n"
+"\n"
+"Without any of the --print options, the program exits with status 0 if the "
+"requested checks pass for all input files, with 1 if a check fails for any "
+"file, and 2 if there is an environmental issue (such as a file read error or "
+"a memory allocation error).\n"
+"\n"
+"When printing file names, the program exits with status 0 even if no file "
+"names are printed, and exits with status 2 if there is an environmental "
+"issue.\n"
+"\n"
+"On usage error (e.g. a bad option was given), the program exits with a "
+"status code larger than 2.\n"
+"\n"
+"The --quiet or -q option suppresses some error warning output, but doesn't "
+"change the exit status."
+msgstr ""
+
+#: src/elfcmp.c:59
+msgid "Control options:"
+msgstr ""
+
+#: src/elfcmp.c:61
+msgid "Output all differences, not just the first"
+msgstr ""
+
+#: src/elfcmp.c:62
+msgid ""
+"Control treatment of gaps in loadable segments [ignore|match] (default: "
+"ignore)"
+msgstr ""
+
+#: src/elfcmp.c:64
+msgid "Ignore permutation of buckets in SHT_HASH section"
+msgstr ""
+
+#: src/elfcmp.c:66
+msgid "Ignore differences in build ID"
+msgstr ""
+
+#: src/elfcmp.c:67
+msgid "Output nothing; yield exit status only"
+msgstr ""
+
+#. Short description of program.
+#: src/elfcmp.c:74
+msgid "Compare relevant parts of two ELF files for equality."
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: src/elfcmp.c:78
+#, fuzzy
+msgid "FILE1 FILE2"
+msgstr "DATEI1 DATEI2"
+
+#: src/elfcmp.c:140
+msgid "Invalid number of parameters.\n"
+msgstr "Ungültige Anzahl von Parametern.\n"
+
+#: src/elfcmp.c:171 src/elfcmp.c:176
+#, c-format
+msgid "cannot get ELF header of '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:202
+#, c-format
+msgid "%s %s diff: ELF header"
+msgstr ""
+
+#: src/elfcmp.c:209 src/elfcmp.c:212
+#, fuzzy, c-format
+msgid "cannot get section count of '%s': %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfcmp.c:217
+#, c-format
+msgid "%s %s diff: section count"
+msgstr ""
+
+#: src/elfcmp.c:224 src/elfcmp.c:227
+#, fuzzy, c-format
+msgid "cannot get program header count of '%s': %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/elfcmp.c:232
+#, fuzzy, c-format
+msgid "%s %s diff: program header count"
+msgstr "Datei hat keinen Programm-Kopf"
+
+#: src/elfcmp.c:240 src/elfcmp.c:243
+#, fuzzy, c-format
+msgid "cannot get hdrstrndx of '%s': %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfcmp.c:248
+#, c-format
+msgid "%s %s diff: shdr string index"
+msgstr ""
+
+#: src/elfcmp.c:306
+#, c-format
+msgid "%s %s differ: section [%zu], [%zu] name"
+msgstr ""
+
+#: src/elfcmp.c:329
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' header"
+msgstr ""
+
+#: src/elfcmp.c:337 src/elfcmp.c:343
+#, c-format
+msgid "cannot get content of section %zu in '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:352
+#, c-format
+msgid "symbol table [%zu] in '%s' has zero sh_entsize"
+msgstr ""
+
+#: src/elfcmp.c:364 src/elfcmp.c:370
+#, c-format
+msgid "cannot get symbol in '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:392
+#, c-format
+msgid "%s %s differ: symbol table [%zu]"
+msgstr ""
+
+#: src/elfcmp.c:395
+#, c-format
+msgid "%s %s differ: symbol table [%zu,%zu]"
+msgstr ""
+
+#: src/elfcmp.c:442 src/elfcmp.c:512
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' number of notes"
+msgstr ""
+
+#: src/elfcmp.c:450
+#, fuzzy, c-format
+msgid "cannot read note section [%zu] '%s' in '%s': %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfcmp.c:461
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note name"
+msgstr ""
+
+#: src/elfcmp.c:469
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' type"
+msgstr ""
+
+#: src/elfcmp.c:484
+#, c-format
+msgid "%s %s differ: build ID length"
+msgstr ""
+
+#: src/elfcmp.c:492
+#, c-format
+msgid "%s %s differ: build ID content"
+msgstr ""
+
+#: src/elfcmp.c:501
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' content"
+msgstr ""
+
+#: src/elfcmp.c:542
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' content"
+msgstr ""
+
+#: src/elfcmp.c:546
+#, c-format
+msgid "%s %s differ: section [%zu,%zu] '%s' content"
+msgstr ""
+
+#: src/elfcmp.c:561
+#, c-format
+msgid "%s %s differ: unequal amount of important sections"
+msgstr ""
+
+#: src/elfcmp.c:594 src/elfcmp.c:599
+#, c-format
+msgid "cannot load data of '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:618 src/elfcmp.c:624
+#, c-format
+msgid "cannot get program header entry %d of '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:630
+#, c-format
+msgid "%s %s differ: program header %d"
+msgstr ""
+
+#: src/elfcmp.c:654
+#, c-format
+msgid "%s %s differ: gap"
+msgstr ""
+
+#: src/elfcmp.c:705
+#, c-format
+msgid "Invalid value '%s' for --gaps parameter."
+msgstr ""
+
+#: src/elfcmp.c:733 src/findtextrel.c:194 src/nm.c:363 src/ranlib.c:140
+#: src/size.c:271 src/strings.c:184 src/strip.c:1040 src/strip.c:1077
+#: src/unstrip.c:2245 src/unstrip.c:2274
+#, c-format
+msgid "cannot open '%s'"
+msgstr "'%s' kann nicht geöffnet werden"
+
+#: src/elfcmp.c:737 src/findtextrel.c:213 src/ranlib.c:157
+#, c-format
+msgid "cannot create ELF descriptor for '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:742
+#, c-format
+msgid "cannot create EBL descriptor for '%s'"
+msgstr ""
+
+#: src/elfcmp.c:760 src/findtextrel.c:384
+#, c-format
+msgid "cannot get section header of section %zu: %s"
+msgstr ""
+
+#: src/elfcmp.c:770
+#, c-format
+msgid "cannot get content of section %zu: %s"
+msgstr ""
+
+#: src/elfcmp.c:780 src/elfcmp.c:794
+#, c-format
+msgid "cannot get relocation: %s"
+msgstr ""
+
+#: src/elfcompress.c:128 src/strip.c:305 src/unstrip.c:116
+#, c-format
+msgid "-o option specified twice"
+msgstr ""
+
+#: src/elfcompress.c:135
+#, fuzzy, c-format
+msgid "-t option specified twice"
+msgstr "Option -d zweimal angegeben"
+
+#: src/elfcompress.c:147
+#, c-format
+msgid "ZSTD support is not enabled"
+msgstr ""
+
+#: src/elfcompress.c:150
+#, fuzzy, c-format
+msgid "unknown compression type '%s'"
+msgstr "unbekannter Typ"
+
+#. We need at least one input file.
+#: src/elfcompress.c:162 src/elfcompress.c:1447
+#, fuzzy, c-format
+msgid "No input file given"
+msgstr "Eingabedatei '%s' ignoriert"
+
+#: src/elfcompress.c:168 src/elfcompress.c:1451
+#, c-format
+msgid "Only one input file allowed together with '-o'"
+msgstr ""
+
+#: src/elfcompress.c:1408
+msgid "Place (de)compressed output into FILE"
+msgstr ""
+
+#: src/elfcompress.c:1411
+msgid ""
+"What type of compression to apply. TYPE can be 'none' (decompress), "
+"'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), 'zlib-"
+"gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD "
+"compression)"
+msgstr ""
+
+#: src/elfcompress.c:1415
+msgid ""
+"SECTION name to (de)compress, SECTION is an extended wildcard pattern "
+"(defaults to '.?(z)debug*')"
+msgstr ""
+
+#: src/elfcompress.c:1418
+msgid "Print a message for each section being (de)compressed"
+msgstr ""
+
+#: src/elfcompress.c:1421
+msgid ""
+"Force compression of section even if it would become larger or update/"
+"rewrite the file even if no section would be (de)compressed"
+msgstr ""
+
+#: src/elfcompress.c:1424 src/strip.c:92
+msgid "Relax a few rules to handle slightly broken ELF files"
+msgstr ""
+
+#: src/elfcompress.c:1427
+#, fuzzy
+msgid "Be silent when a section cannot be compressed"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elfcompress.c:1437
+msgid "Compress or decompress sections in an ELF file."
+msgstr ""
+
+#: src/elflint.c:63
+msgid "Be extremely strict, flag level 2 features."
+msgstr ""
+
+#: src/elflint.c:64
+msgid "Do not print anything if successful"
+msgstr "Gebe nichts aus, wenn erfolgreich"
+
+#: src/elflint.c:65
+msgid "Binary is a separate debuginfo file"
+msgstr ""
+
+#: src/elflint.c:67
+msgid ""
+"Binary has been created with GNU ld and is therefore known to be broken in "
+"certain ways"
+msgstr ""
+
+#. Short description of program.
+#: src/elflint.c:73
+msgid "Pedantic checking of ELF files compliance with gABI/psABI spec."
+msgstr ""
+
+#: src/elflint.c:154 src/readelf.c:413
+#, fuzzy, c-format
+msgid "cannot open input file '%s'"
+msgstr "Kann Eingabedatei nicht öffnen"
+
+#: src/elflint.c:161
+#, fuzzy, c-format
+msgid "cannot generate Elf descriptor for '%s': %s\n"
+msgstr "kann Elf-Deskriptor nicht erzeugen: %s\n"
+
+#: src/elflint.c:180
+#, c-format
+msgid "error while closing Elf descriptor: %s\n"
+msgstr "Fehler beim Schliessen des Elf-Desktriptor: %s\n"
+
+#: src/elflint.c:184
+msgid "No errors"
+msgstr "Keine Fehler"
+
+#: src/elflint.c:219 src/readelf.c:625
+msgid "Missing file name.\n"
+msgstr "Dateiname fehlt.\n"
+
+#: src/elflint.c:284
+#, c-format
+msgid " error while freeing sub-ELF descriptor: %s\n"
+msgstr ""
+
+#. We cannot do anything.
+#: src/elflint.c:292
+#, fuzzy, c-format
+msgid "Not an ELF file - it has the wrong magic bytes at the start\n"
+msgstr "Keine ELF-Datei - sie hat die falschen Magic Bytes am Anfang\n"
+
+#: src/elflint.c:358
+#, c-format
+msgid "e_ident[%d] == %d is no known class\n"
+msgstr ""
+
+#: src/elflint.c:363
+#, c-format
+msgid "e_ident[%d] == %d is no known data encoding\n"
+msgstr ""
+
+#: src/elflint.c:367
+#, c-format
+msgid "unknown ELF header version number e_ident[%d] == %d\n"
+msgstr ""
+
+#: src/elflint.c:375
+#, c-format
+msgid "unsupported OS ABI e_ident[%d] == '%s'\n"
+msgstr ""
+
+#: src/elflint.c:381
+#, c-format
+msgid "unsupported ABI version e_ident[%d] == %d\n"
+msgstr ""
+
+#: src/elflint.c:386
+#, c-format
+msgid "e_ident[%zu] is not zero\n"
+msgstr "e_ident[%zu] ist nicht null\n"
+
+#: src/elflint.c:391
+#, c-format
+msgid "unknown object file type %d\n"
+msgstr ""
+
+#: src/elflint.c:398
+#, c-format
+msgid "unknown machine type %d\n"
+msgstr ""
+
+#: src/elflint.c:402
+#, c-format
+msgid "unknown object file version\n"
+msgstr ""
+
+#: src/elflint.c:408
+#, c-format
+msgid "invalid program header offset\n"
+msgstr ""
+
+#: src/elflint.c:410
+#, c-format
+msgid "executables and DSOs cannot have zero program header offset\n"
+msgstr ""
+
+#: src/elflint.c:414
+#, c-format
+msgid "invalid number of program header entries\n"
+msgstr ""
+
+#: src/elflint.c:422
+#, c-format
+msgid "invalid section header table offset\n"
+msgstr ""
+
+#: src/elflint.c:425
+#, c-format
+msgid "section header table must be present\n"
+msgstr ""
+
+#: src/elflint.c:439
+#, c-format
+msgid "invalid number of section header table entries\n"
+msgstr ""
+
+#: src/elflint.c:456
+#, c-format
+msgid "invalid section header index\n"
+msgstr ""
+
+#: src/elflint.c:474
+#, c-format
+msgid "Can only check %u headers, shnum was %u\n"
+msgstr ""
+
+#: src/elflint.c:488
+#, fuzzy, c-format
+msgid "invalid number of program header table entries\n"
+msgstr "Ungültige Anzahl von Parametern.\n"
+
+#: src/elflint.c:505
+#, c-format
+msgid "Can only check %u headers, phnum was %u\n"
+msgstr ""
+
+#: src/elflint.c:510
+#, c-format
+msgid "invalid machine flags: %s\n"
+msgstr ""
+
+#: src/elflint.c:517 src/elflint.c:534
+#, c-format
+msgid "invalid ELF header size: %hd\n"
+msgstr ""
+
+#: src/elflint.c:520 src/elflint.c:537
+#, c-format
+msgid "invalid program header size: %hd\n"
+msgstr ""
+
+#: src/elflint.c:523 src/elflint.c:540
+#, c-format
+msgid "invalid program header position or size\n"
+msgstr ""
+
+#: src/elflint.c:526 src/elflint.c:543
+#, c-format
+msgid "invalid section header size: %hd\n"
+msgstr ""
+
+#: src/elflint.c:529 src/elflint.c:546
+#, c-format
+msgid "invalid section header position or size\n"
+msgstr ""
+
+#: src/elflint.c:591
+#, c-format
+msgid ""
+"section [%2d] '%s': section with SHF_GROUP flag set not part of a section "
+"group\n"
+msgstr ""
+
+#: src/elflint.c:595
+#, c-format
+msgid ""
+"section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"
+msgstr ""
+
+#: src/elflint.c:611 src/elflint.c:1509 src/elflint.c:1560 src/elflint.c:1610
+#: src/elflint.c:1692 src/elflint.c:2029 src/elflint.c:2355 src/elflint.c:2981
+#: src/elflint.c:3144 src/elflint.c:3292 src/elflint.c:3494 src/elflint.c:4511
+#, c-format
+msgid "section [%2d] '%s': cannot get section data\n"
+msgstr ""
+
+#: src/elflint.c:624 src/elflint.c:1699
+#, c-format
+msgid ""
+"section [%2d] '%s': referenced as string table for section [%2d] '%s' but "
+"type is not SHT_STRTAB\n"
+msgstr ""
+
+#: src/elflint.c:647
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol table cannot have more than one extended index "
+"section\n"
+msgstr ""
+
+#: src/elflint.c:659
+#, c-format
+msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n"
+msgstr ""
+
+#: src/elflint.c:663
+#, c-format
+msgid ""
+"section [%2u] '%s': number of local entries in 'st_info' larger than table "
+"size\n"
+msgstr ""
+
+#: src/elflint.c:672
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %d: %s\n"
+msgstr ""
+
+#: src/elflint.c:677 src/elflint.c:680 src/elflint.c:683 src/elflint.c:686
+#: src/elflint.c:689 src/elflint.c:692
+#, c-format
+msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n"
+msgstr ""
+
+#: src/elflint.c:695
+#, c-format
+msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n"
+msgstr ""
+
+#: src/elflint.c:705
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:714
+#, c-format
+msgid "section [%2d] '%s': symbol %zu: invalid name value\n"
+msgstr ""
+
+#: src/elflint.c:729
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): too large section index but no extended "
+"section index section\n"
+msgstr ""
+
+#: src/elflint.c:735
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit "
+"in st_shndx (%<PRIu32>)\n"
+msgstr ""
+
+#. || sym->st_shndx > SHN_HIRESERVE  always false
+#: src/elflint.c:747
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): invalid section index\n"
+msgstr "ungültiger Abschnittsindex"
+
+#: src/elflint.c:755
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown type\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:761
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:766
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"
+msgstr ""
+
+#: src/elflint.c:774
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable "
+"files\n"
+msgstr ""
+
+#: src/elflint.c:778
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"
+msgstr ""
+
+#: src/elflint.c:782
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"
+msgstr ""
+
+#: src/elflint.c:833
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:839 src/elflint.c:864 src/elflint.c:913
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:848
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not "
+"have SHF_TLS flag set\n"
+msgstr ""
+
+#: src/elflint.c:858 src/elflint.c:906
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:885
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header "
+"entry\n"
+msgstr ""
+
+#: src/elflint.c:891
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program "
+"header entry\n"
+msgstr ""
+
+#: src/elflint.c:899
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value short of referenced section "
+"[%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:926
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local symbol outside range described in "
+"sh_info\n"
+msgstr ""
+
+#: src/elflint.c:933
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): non-local symbol outside range "
+"described in sh_info\n"
+msgstr ""
+
+#: src/elflint.c:940
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:990
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section "
+"[%2d]\n"
+msgstr ""
+
+#: src/elflint.c:997
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] "
+"'%s'\n"
+msgstr ""
+
+#. This test is more strict than the psABIs which
+#. usually allow the symbol to be in the middle of
+#. the .got section, allowing negative offsets.
+#: src/elflint.c:1013
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#<PRIx64> does not "
+"match %s section address %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:1020
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %<PRIu64> does not "
+"match %s section size %<PRIu64>\n"
+msgstr ""
+
+#: src/elflint.c:1028
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got "
+"section\n"
+msgstr ""
+
+#: src/elflint.c:1044
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC_ symbol value %#<PRIx64> does not match dynamic "
+"segment address %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:1051
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC symbol size %<PRIu64> does not match dynamic "
+"segment size %<PRIu64>\n"
+msgstr ""
+
+#: src/elflint.c:1064
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-"
+"default visibility\n"
+msgstr ""
+
+#: src/elflint.c:1068
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:1106
+#, fuzzy, c-format
+msgid "section [%2d] '%s': cannot get section data.\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:1122
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"
+msgstr ""
+
+#: src/elflint.c:1133 src/elflint.c:1186
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"
+msgstr ""
+
+#: src/elflint.c:1158 src/elflint.c:1211
+#, c-format
+msgid ""
+"section [%2d] '%s': relative relocations after index %d as specified by "
+"DT_RELCOUNT\n"
+msgstr ""
+
+#: src/elflint.c:1164 src/elflint.c:1217
+#, c-format
+msgid ""
+"section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT "
+"specified %d relative relocations\n"
+msgstr ""
+
+#: src/elflint.c:1176
+#, c-format
+msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n"
+msgstr ""
+
+#: src/elflint.c:1259
+#, c-format
+msgid "section [%2d] '%s': invalid destination section index\n"
+msgstr ""
+
+#: src/elflint.c:1271
+#, c-format
+msgid "section [%2d] '%s': invalid destination section type\n"
+msgstr ""
+
+#: src/elflint.c:1279
+#, c-format
+msgid "section [%2d] '%s': sh_info should be zero\n"
+msgstr ""
+
+#: src/elflint.c:1287
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': no relocations for merge-able string sections possible\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:1365
+#, c-format
+msgid "text relocation flag set but there is no read-only segment\n"
+msgstr ""
+
+#: src/elflint.c:1392
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid type\n"
+msgstr ""
+
+#: src/elflint.c:1400
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: relocation type invalid for the file "
+"type\n"
+msgstr ""
+
+#: src/elflint.c:1408
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n"
+msgstr ""
+
+#: src/elflint.c:1426
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can "
+"be used with %s\n"
+msgstr ""
+
+#: src/elflint.c:1443
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:1458
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: copy relocation against symbol of type "
+"%s\n"
+msgstr ""
+
+#: src/elflint.c:1479
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: read-only section modified but text "
+"relocation flag not set\n"
+msgstr ""
+
+#: src/elflint.c:1494
+#, c-format
+msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n"
+msgstr ""
+
+#: src/elflint.c:1534 src/elflint.c:1585
+#, c-format
+msgid "section [%2d] '%s': cannot get relocation %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:1687
+#, c-format
+msgid "more than one dynamic section present\n"
+msgstr ""
+
+#: src/elflint.c:1705
+#, c-format
+msgid ""
+"section [%2d]: referenced as string table for section [%2d] '%s' but section "
+"link value is invalid\n"
+msgstr ""
+
+#: src/elflint.c:1713
+#, c-format
+msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"
+msgstr ""
+
+#: src/elflint.c:1718 src/elflint.c:2008
+#, c-format
+msgid "section [%2d] '%s': sh_info not zero\n"
+msgstr ""
+
+#: src/elflint.c:1728
+#, c-format
+msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:1736
+#, c-format
+msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"
+msgstr ""
+
+#: src/elflint.c:1743
+#, c-format
+msgid "section [%2d] '%s': entry %zu: unknown tag\n"
+msgstr ""
+
+#: src/elflint.c:1754
+#, c-format
+msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n"
+msgstr ""
+
+#: src/elflint.c:1764
+#, c-format
+msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n"
+msgstr ""
+
+#: src/elflint.c:1782
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"
+msgstr ""
+
+#: src/elflint.c:1795
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: pointer does not match address of section "
+"[%2d] '%s' referenced by sh_link\n"
+msgstr ""
+
+#: src/elflint.c:1839
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"
+msgstr ""
+
+#: src/elflint.c:1854
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must be valid offset in section "
+"[%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:1874 src/elflint.c:1902
+#, c-format
+msgid "section [%2d] '%s': contains %s entry but not %s\n"
+msgstr ""
+
+#: src/elflint.c:1886
+#, c-format
+msgid "section [%2d] '%s': mandatory tag %s not present\n"
+msgstr ""
+
+#: src/elflint.c:1895
+#, c-format
+msgid "section [%2d] '%s': no hash section present\n"
+msgstr ""
+
+#: src/elflint.c:1910 src/elflint.c:1917
+#, c-format
+msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n"
+msgstr ""
+
+#: src/elflint.c:1927 src/elflint.c:1931
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"
+msgstr ""
+
+#: src/elflint.c:1937
+#, c-format
+msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n"
+msgstr ""
+
+#: src/elflint.c:1948 src/elflint.c:1952 src/elflint.c:1956 src/elflint.c:1960
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in prelinked executable\n"
+msgstr ""
+
+#: src/elflint.c:1972
+#, c-format
+msgid ""
+"section [%2d] '%s': only relocatable files can have extended section index\n"
+msgstr ""
+
+#: src/elflint.c:1982
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index section not for symbol table\n"
+msgstr ""
+
+#: src/elflint.c:1986
+#, c-format
+msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"
+msgstr ""
+
+#: src/elflint.c:1991
+#, c-format
+msgid "cannot get data for symbol section\n"
+msgstr ""
+
+#: src/elflint.c:1994
+#, c-format
+msgid "section [%2d] '%s': entry size does not match Elf32_Word\n"
+msgstr ""
+
+#: src/elflint.c:2003
+#, c-format
+msgid "section [%2d] '%s': extended index table too small for symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2018
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index in section [%2zu] '%s' refers to "
+"same symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2036
+#, c-format
+msgid "symbol 0 should have zero extended section index\n"
+msgstr ""
+
+#: src/elflint.c:2048
+#, c-format
+msgid "cannot get data for symbol %zu\n"
+msgstr ""
+
+#: src/elflint.c:2053
+#, c-format
+msgid "extended section index is %<PRIu32> but symbol index is not XINDEX\n"
+msgstr ""
+
+#: src/elflint.c:2070 src/elflint.c:2127
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"
+msgstr ""
+
+#: src/elflint.c:2084 src/elflint.c:2141
+#, c-format
+msgid "section [%2d] '%s': chain array too large\n"
+msgstr ""
+
+#: src/elflint.c:2098 src/elflint.c:2155
+#, c-format
+msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2108
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2165
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %<PRIu64> out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2178
+#, c-format
+msgid "section [%2d] '%s': not enough data\n"
+msgstr ""
+
+#: src/elflint.c:2190
+#, c-format
+msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n"
+msgstr ""
+
+#: src/elflint.c:2206
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected at "
+"least %ld)\n"
+msgstr ""
+
+#: src/elflint.c:2215
+#, c-format
+msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n"
+msgstr ""
+
+#: src/elflint.c:2249
+#, c-format
+msgid ""
+"section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"
+msgstr ""
+
+#: src/elflint.c:2270
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %u referenced in chain for bucket %zu is "
+"undefined\n"
+msgstr ""
+
+#: src/elflint.c:2283
+#, c-format
+msgid ""
+"section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+
+#: src/elflint.c:2292
+#, c-format
+msgid ""
+"section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+
+#: src/elflint.c:2322
+#, c-format
+msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2327
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2333
+#, c-format
+msgid "section [%2d] '%s': bitmask does not match names in the hash table\n"
+msgstr ""
+
+#: src/elflint.c:2346
+#, c-format
+msgid "section [%2d] '%s': relocatable files cannot have hash tables\n"
+msgstr ""
+
+#: src/elflint.c:2364
+#, c-format
+msgid "section [%2d] '%s': hash table not for dynamic symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2368
+#, c-format
+msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"
+msgstr ""
+
+#: src/elflint.c:2378
+#, c-format
+msgid "section [%2d] '%s': hash table entry size incorrect\n"
+msgstr ""
+
+#: src/elflint.c:2383
+#, c-format
+msgid "section [%2d] '%s': not marked to be allocated\n"
+msgstr ""
+
+#: src/elflint.c:2388
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table has not even room for initial administrative "
+"entries\n"
+msgstr ""
+
+#: src/elflint.c:2437
+#, c-format
+msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"
+msgstr ""
+
+#: src/elflint.c:2461 src/elflint.c:2526 src/elflint.c:2561
+#, c-format
+msgid "hash section [%2zu] '%s' does not contain enough data\n"
+msgstr ""
+
+#: src/elflint.c:2482
+#, c-format
+msgid "hash section [%2zu] '%s' has zero bit mask words\n"
+msgstr ""
+
+#: src/elflint.c:2493 src/elflint.c:2537 src/elflint.c:2574
+#, c-format
+msgid "hash section [%2zu] '%s' uses too much data\n"
+msgstr ""
+
+#: src/elflint.c:2508
+#, c-format
+msgid ""
+"hash section [%2zu] '%s' invalid symbol index %<PRIu32> (max_nsyms: "
+"%<PRIu32>, nentries: %<PRIu32>\n"
+msgstr ""
+
+#: src/elflint.c:2595
+#, c-format
+msgid "hash section [%2zu] '%s' invalid sh_entsize\n"
+msgstr ""
+
+#: src/elflint.c:2605 src/elflint.c:2609
+#, c-format
+msgid "section [%2zu] '%s': reference to symbol index 0\n"
+msgstr ""
+
+#: src/elflint.c:2616
+#, c-format
+msgid ""
+"symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:2628
+#, c-format
+msgid ""
+"symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:2644
+#, c-format
+msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n"
+msgstr ""
+
+#: src/elflint.c:2664
+#, c-format
+msgid ""
+"section [%2d] '%s': section groups only allowed in relocatable object files\n"
+msgstr ""
+
+#: src/elflint.c:2675
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol table: %s\n"
+msgstr ""
+
+#: src/elflint.c:2680
+#, c-format
+msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2686
+#, c-format
+msgid "section [%2d] '%s': invalid symbol index in sh_info\n"
+msgstr ""
+
+#: src/elflint.c:2691
+#, c-format
+msgid "section [%2d] '%s': sh_flags not zero\n"
+msgstr ""
+
+#: src/elflint.c:2698
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol for signature\n"
+msgstr ""
+
+#: src/elflint.c:2702
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol name for signature\n"
+msgstr ""
+
+#: src/elflint.c:2707
+#, c-format
+msgid "section [%2d] '%s': signature symbol cannot be empty string\n"
+msgstr ""
+
+#: src/elflint.c:2713
+#, c-format
+msgid "section [%2d] '%s': sh_flags not set correctly\n"
+msgstr ""
+
+#: src/elflint.c:2719
+#, c-format
+msgid "section [%2d] '%s': cannot get data: %s\n"
+msgstr ""
+
+#: src/elflint.c:2728
+#, c-format
+msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"
+msgstr ""
+
+#: src/elflint.c:2734
+#, c-format
+msgid "section [%2d] '%s': section group without flags word\n"
+msgstr ""
+
+#: src/elflint.c:2742
+#, c-format
+msgid "section [%2d] '%s': section group without member\n"
+msgstr ""
+
+#: src/elflint.c:2746
+#, c-format
+msgid "section [%2d] '%s': section group with only one member\n"
+msgstr ""
+
+#: src/elflint.c:2757
+#, c-format
+msgid "section [%2d] '%s': unknown section group flags\n"
+msgstr ""
+
+#: src/elflint.c:2769
+#, fuzzy, c-format
+msgid "section [%2d] '%s': section index %zu out of range\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:2778
+#, c-format
+msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:2785
+#, c-format
+msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:2791
+#, c-format
+msgid ""
+"section [%2d] '%s': element %zu references section [%2d] '%s' without "
+"SHF_GROUP flag set\n"
+msgstr ""
+
+#: src/elflint.c:2798
+#, c-format
+msgid "section [%2d] '%s' is contained in more than one section group\n"
+msgstr ""
+
+#: src/elflint.c:2995
+#, c-format
+msgid ""
+"section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no "
+"dynamic symbol table\n"
+msgstr ""
+
+#: src/elflint.c:3007
+#, c-format
+msgid ""
+"section [%2d] '%s' has different number of entries than symbol table [%2d] "
+"'%s'\n"
+msgstr ""
+
+#: src/elflint.c:3023
+#, c-format
+msgid "section [%2d] '%s': symbol %d: cannot read version data\n"
+msgstr ""
+
+#: src/elflint.c:3039
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n"
+msgstr ""
+
+#: src/elflint.c:3047
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with version\n"
+msgstr ""
+
+#: src/elflint.c:3061
+#, c-format
+msgid "section [%2d] '%s': symbol %d: invalid version index %d\n"
+msgstr ""
+
+#: src/elflint.c:3066
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for defined version\n"
+msgstr ""
+
+#: src/elflint.c:3076
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for requested version\n"
+msgstr ""
+
+#: src/elflint.c:3129
+#, c-format
+msgid "more than one version reference section present\n"
+msgstr ""
+
+#: src/elflint.c:3137 src/elflint.c:3284
+#, c-format
+msgid "section [%2d] '%s': sh_link does not link to string table\n"
+msgstr ""
+
+#: src/elflint.c:3162 src/elflint.c:3338
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong version %d\n"
+msgstr ""
+
+#: src/elflint.c:3169 src/elflint.c:3345
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"
+msgstr ""
+
+#: src/elflint.c:3179
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid file reference\n"
+msgstr ""
+
+#: src/elflint.c:3187
+#, c-format
+msgid "section [%2d] '%s': entry %d references unknown dependency\n"
+msgstr ""
+
+#: src/elflint.c:3199
+#, c-format
+msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"
+msgstr ""
+
+#: src/elflint.c:3207
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has invalid name "
+"reference\n"
+msgstr ""
+
+#: src/elflint.c:3216
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: "
+"%#x, expected %#x\n"
+msgstr ""
+
+#: src/elflint.c:3225
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version "
+"name '%s'\n"
+msgstr ""
+
+#: src/elflint.c:3236
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"
+msgstr ""
+
+#: src/elflint.c:3253 src/elflint.c:3429
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n"
+msgstr ""
+
+#: src/elflint.c:3261 src/elflint.c:3437
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says "
+"there are more entries\n"
+msgstr ""
+
+#: src/elflint.c:3276
+#, c-format
+msgid "more than one version definition section present\n"
+msgstr ""
+
+#: src/elflint.c:3323
+#, c-format
+msgid "section [%2d] '%s': more than one BASE definition\n"
+msgstr ""
+
+#: src/elflint.c:3327
+#, c-format
+msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"
+msgstr ""
+
+#: src/elflint.c:3333
+#, c-format
+msgid "section [%2d] '%s': entry %d has unknown flag\n"
+msgstr ""
+
+#: src/elflint.c:3360
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid name reference\n"
+msgstr ""
+
+#: src/elflint.c:3367
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"
+msgstr ""
+
+#: src/elflint.c:3375
+#, c-format
+msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n"
+msgstr ""
+
+#: src/elflint.c:3395
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"
+msgstr ""
+
+#: src/elflint.c:3412
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"
+msgstr ""
+
+#: src/elflint.c:3445
+#, c-format
+msgid "section [%2d] '%s': no BASE definition\n"
+msgstr ""
+
+#: src/elflint.c:3461
+#, c-format
+msgid "section [%2d] '%s': unknown parent version '%s'\n"
+msgstr ""
+
+#: src/elflint.c:3486
+#, c-format
+msgid "section [%2d] '%s': empty object attributes section\n"
+msgstr ""
+
+#: src/elflint.c:3502
+#, c-format
+msgid "section [%2d] '%s': unrecognized attribute format\n"
+msgstr ""
+
+#: src/elflint.c:3513
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3522
+#, c-format
+msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3534
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n"
+msgstr ""
+
+#: src/elflint.c:3551
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"
+msgstr ""
+
+#: src/elflint.c:3560
+#, c-format
+msgid "section [%2d] '%s': offset %zu: truncated attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3569
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"
+msgstr ""
+
+#: src/elflint.c:3584
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"
+msgstr ""
+
+#. Tag_File
+#: src/elflint.c:3595
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"
+msgstr ""
+
+#: src/elflint.c:3616
+#, c-format
+msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"
+msgstr ""
+
+#: src/elflint.c:3627
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n"
+msgstr ""
+
+#: src/elflint.c:3640
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"
+msgstr ""
+
+#: src/elflint.c:3644
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: unrecognized %s attribute value %<PRIu64>\n"
+msgstr ""
+
+#: src/elflint.c:3654
+#, c-format
+msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n"
+msgstr ""
+
+#: src/elflint.c:3660
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3758
+#, c-format
+msgid "cannot get section header of zeroth section\n"
+msgstr ""
+
+#: src/elflint.c:3762
+#, c-format
+msgid "zeroth section has nonzero name\n"
+msgstr ""
+
+#: src/elflint.c:3764
+#, c-format
+msgid "zeroth section has nonzero type\n"
+msgstr ""
+
+#: src/elflint.c:3766
+#, c-format
+msgid "zeroth section has nonzero flags\n"
+msgstr ""
+
+#: src/elflint.c:3768
+#, c-format
+msgid "zeroth section has nonzero address\n"
+msgstr ""
+
+#: src/elflint.c:3770
+#, c-format
+msgid "zeroth section has nonzero offset\n"
+msgstr ""
+
+#: src/elflint.c:3772
+#, c-format
+msgid "zeroth section has nonzero align value\n"
+msgstr ""
+
+#: src/elflint.c:3774
+#, c-format
+msgid "zeroth section has nonzero entry size value\n"
+msgstr ""
+
+#: src/elflint.c:3777
+#, c-format
+msgid ""
+"zeroth section has nonzero size value while ELF header has nonzero shnum "
+"value\n"
+msgstr ""
+
+#: src/elflint.c:3781
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in shstrndx\n"
+msgstr ""
+
+#: src/elflint.c:3785
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in phnum\n"
+msgstr ""
+
+#: src/elflint.c:3803
+#, c-format
+msgid "cannot get section header for section [%2zu] '%s': %s\n"
+msgstr ""
+
+#: src/elflint.c:3812
+#, c-format
+msgid "section [%2zu]: invalid name\n"
+msgstr ""
+
+#: src/elflint.c:3839
+#, c-format
+msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n"
+msgstr ""
+
+#: src/elflint.c:3856
+#, c-format
+msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n"
+msgstr ""
+
+#: src/elflint.c:3874
+#, c-format
+msgid ""
+"section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"
+msgstr ""
+
+#: src/elflint.c:3891
+#, c-format
+msgid "section [%2zu] '%s' present in object file\n"
+msgstr ""
+
+#: src/elflint.c:3897 src/elflint.c:3929
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"
+msgstr ""
+
+#: src/elflint.c:3902 src/elflint.c:3934
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable "
+"segments\n"
+msgstr ""
+
+#: src/elflint.c:3910
+#, c-format
+msgid ""
+"section [%2zu] '%s' is extension section index table in non-object file\n"
+msgstr ""
+
+#: src/elflint.c:3953
+#, c-format
+msgid "section [%2zu] '%s': size not multiple of entry size\n"
+msgstr ""
+
+#: src/elflint.c:3958
+#, c-format
+msgid "cannot get section header\n"
+msgstr ""
+
+#: src/elflint.c:3968
+#, c-format
+msgid "section [%2zu] '%s' has unsupported type %d\n"
+msgstr ""
+
+#: src/elflint.c:3988
+#, c-format
+msgid ""
+"section [%2zu] '%s' contains invalid processor-specific flag(s) %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:3998
+#, c-format
+msgid "section [%2zu] '%s' contains unknown flag(s) %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:4006
+#, c-format
+msgid "section [%2zu] '%s': thread-local data sections address not zero\n"
+msgstr ""
+
+#: src/elflint.c:4016
+#, fuzzy, c-format
+msgid "section [%2zu] '%s': allocated section cannot be compressed\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:4021
+#, fuzzy, c-format
+msgid "section [%2zu] '%s': nobits section cannot be compressed\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/elflint.c:4027
+#, c-format
+msgid ""
+"section [%2zu] '%s': compressed section with no compression header: %s\n"
+msgstr ""
+
+#: src/elflint.c:4033
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in link value\n"
+msgstr ""
+
+#: src/elflint.c:4038
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in info value\n"
+msgstr ""
+
+#: src/elflint.c:4045
+#, c-format
+msgid "section [%2zu] '%s': strings flag set without merge flag\n"
+msgstr ""
+
+#: src/elflint.c:4050
+#, c-format
+msgid "section [%2zu] '%s': merge flag set but entry size is zero\n"
+msgstr ""
+
+#: src/elflint.c:4069
+#, c-format
+msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n"
+msgstr ""
+
+#: src/elflint.c:4078
+#, c-format
+msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"
+msgstr ""
+
+#: src/elflint.c:4085
+#, c-format
+msgid "section [%2zu] '%s' is both executable and writable\n"
+msgstr ""
+
+#: src/elflint.c:4116
+#, c-format
+msgid ""
+"section [%2zu] '%s' not fully contained in segment of program header entry "
+"%d\n"
+msgstr ""
+
+#: src/elflint.c:4126
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d\n"
+msgstr ""
+
+#: src/elflint.c:4152
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d and file contents is non-zero\n"
+msgstr ""
+
+#: src/elflint.c:4163
+#, c-format
+msgid ""
+"section [%2zu] '%s' has not type NOBITS but is not read from the file in "
+"segment of program header entry %d\n"
+msgstr ""
+
+#: src/elflint.c:4174
+#, c-format
+msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n"
+msgstr ""
+
+#: src/elflint.c:4184
+#, c-format
+msgid "section [%2zu] '%s' is writable in unwritable segment %d\n"
+msgstr ""
+
+#: src/elflint.c:4194
+#, c-format
+msgid ""
+"section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"
+msgstr ""
+
+#: src/elflint.c:4200
+#, c-format
+msgid ""
+"section [%2zu] '%s': ELF header says this is the section header string table "
+"but type is not SHT_TYPE\n"
+msgstr ""
+
+#: src/elflint.c:4208
+#, c-format
+msgid ""
+"section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"
+msgstr ""
+
+#: src/elflint.c:4263
+#, c-format
+msgid "more than one version symbol table present\n"
+msgstr ""
+
+#: src/elflint.c:4286
+#, c-format
+msgid "INTERP program header entry but no .interp section\n"
+msgstr ""
+
+#: src/elflint.c:4297
+#, c-format
+msgid ""
+"loadable segment [%u] is executable but contains no executable sections\n"
+msgstr ""
+
+#: src/elflint.c:4303
+#, c-format
+msgid "loadable segment [%u] is writable but contains no writable sections\n"
+msgstr ""
+
+#: src/elflint.c:4314
+#, c-format
+msgid ""
+"no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section "
+"exist\n"
+msgstr ""
+
+#: src/elflint.c:4327
+#, c-format
+msgid "duplicate version index %d\n"
+msgstr ""
+
+#: src/elflint.c:4341
+#, c-format
+msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"
+msgstr ""
+
+#: src/elflint.c:4390
+#, c-format
+msgid "phdr[%d]: unknown core file note type %<PRIu32> at offset %<PRIu64>\n"
+msgstr ""
+
+#: src/elflint.c:4394
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown core file note type %<PRIu32> at offset %zu\n"
+msgstr ""
+
+#: src/elflint.c:4450
+#, c-format
+msgid ""
+"phdr[%d]: unknown object file note type %<PRIu32> with owner name '%s' at "
+"offset %zu\n"
+msgstr ""
+
+#: src/elflint.c:4455
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown object file note type %<PRIu32> with owner name "
+"'%s' at offset %zu\n"
+msgstr ""
+
+#: src/elflint.c:4474
+#, c-format
+msgid "phdr[%d]: no note entries defined for the type of file\n"
+msgstr ""
+
+#: src/elflint.c:4494
+#, c-format
+msgid "phdr[%d]: cannot get content of note section: %s\n"
+msgstr ""
+
+#: src/elflint.c:4497
+#, c-format
+msgid "phdr[%d]: extra %<PRIu64> bytes after last note\n"
+msgstr ""
+
+#: src/elflint.c:4518
+#, c-format
+msgid "section [%2d] '%s': no note entries defined for the type of file\n"
+msgstr ""
+
+#: src/elflint.c:4525
+#, c-format
+msgid "section [%2d] '%s': cannot get content of note section\n"
+msgstr ""
+
+#: src/elflint.c:4528
+#, c-format
+msgid "section [%2d] '%s': extra %<PRIu64> bytes after last note\n"
+msgstr ""
+
+#: src/elflint.c:4546
+#, c-format
+msgid ""
+"only executables, shared objects, and core files can have program headers\n"
+msgstr ""
+
+#: src/elflint.c:4561
+#, c-format
+msgid "cannot get program header entry %d: %s\n"
+msgstr ""
+
+#: src/elflint.c:4571
+#, c-format
+msgid "program header entry %d: unknown program header entry type %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:4582
+#, c-format
+msgid "more than one INTERP entry in program header\n"
+msgstr ""
+
+#: src/elflint.c:4590
+#, c-format
+msgid "more than one TLS entry in program header\n"
+msgstr ""
+
+#: src/elflint.c:4597
+#, c-format
+msgid "static executable cannot have dynamic sections\n"
+msgstr ""
+
+#: src/elflint.c:4611
+#, c-format
+msgid "dynamic section reference in program header has wrong offset\n"
+msgstr ""
+
+#: src/elflint.c:4614
+#, c-format
+msgid "dynamic section size mismatch in program and section header\n"
+msgstr ""
+
+#: src/elflint.c:4624
+#, c-format
+msgid "more than one GNU_RELRO entry in program header\n"
+msgstr ""
+
+#: src/elflint.c:4645
+#, c-format
+msgid "loadable segment GNU_RELRO applies to is not writable\n"
+msgstr ""
+
+#: src/elflint.c:4656
+#, c-format
+msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"
+msgstr ""
+
+#: src/elflint.c:4663
+#, c-format
+msgid ""
+"GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"
+msgstr ""
+
+#: src/elflint.c:4672 src/elflint.c:4695
+#, c-format
+msgid "%s segment not contained in a loaded segment\n"
+msgstr ""
+
+#: src/elflint.c:4701
+#, c-format
+msgid "program header offset in ELF header and PHDR entry do not match"
+msgstr ""
+
+#: src/elflint.c:4728
+#, c-format
+msgid "call frame search table reference in program header has wrong offset\n"
+msgstr ""
+
+#: src/elflint.c:4731
+#, c-format
+msgid "call frame search table size mismatch in program and section header\n"
+msgstr ""
+
+#: src/elflint.c:4744
+#, c-format
+msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"
+msgstr ""
+
+#: src/elflint.c:4752
+#, c-format
+msgid "call frame search table must be allocated\n"
+msgstr ""
+
+#: src/elflint.c:4755
+#, c-format
+msgid "section [%2zu] '%s' must be allocated\n"
+msgstr ""
+
+#: src/elflint.c:4759
+#, c-format
+msgid "call frame search table must not be writable\n"
+msgstr ""
+
+#: src/elflint.c:4762
+#, c-format
+msgid "section [%2zu] '%s' must not be writable\n"
+msgstr ""
+
+#: src/elflint.c:4767
+#, c-format
+msgid "call frame search table must not be executable\n"
+msgstr ""
+
+#: src/elflint.c:4770
+#, c-format
+msgid "section [%2zu] '%s' must not be executable\n"
+msgstr ""
+
+#: src/elflint.c:4784
+#, c-format
+msgid "program header entry %d: file size greater than memory size\n"
+msgstr ""
+
+#: src/elflint.c:4791
+#, c-format
+msgid "program header entry %d: alignment not a power of 2\n"
+msgstr ""
+
+#: src/elflint.c:4794
+#, c-format
+msgid ""
+"program header entry %d: file offset and virtual address not module of "
+"alignment\n"
+msgstr ""
+
+#: src/elflint.c:4807
+#, c-format
+msgid ""
+"executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME "
+"program header entry"
+msgstr ""
+
+#: src/elflint.c:4841
+#, c-format
+msgid "cannot read ELF header: %s\n"
+msgstr ""
+
+#: src/elflint.c:4853
+#, fuzzy, c-format
+msgid "cannot create backend for ELF file\n"
+msgstr "neue Datei konnte nicht angelegt werden"
+
+#: src/elflint.c:4874
+#, c-format
+msgid "text relocation flag set but not needed\n"
+msgstr ""
+
+#: src/findtextrel.c:60
+msgid "Input Selection:"
+msgstr ""
+
+#: src/findtextrel.c:61
+msgid "Prepend PATH to all file names"
+msgstr ""
+
+#: src/findtextrel.c:63
+msgid "Use PATH as root of debuginfo hierarchy"
+msgstr ""
+
+#. Short description of program.
+#: src/findtextrel.c:70
+msgid "Locate source of text relocations in FILEs (a.out by default)."
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: src/findtextrel.c:74 src/nm.c:107 src/objdump.c:70 src/size.c:79
+#: src/strings.c:86 src/strip.c:100
+msgid "[FILE...]"
+msgstr ""
+
+#: src/findtextrel.c:223
+#, c-format
+msgid "cannot get ELF header '%s': %s"
+msgstr ""
+
+#: src/findtextrel.c:234
+#, c-format
+msgid "'%s' is not a DSO or PIE"
+msgstr ""
+
+#: src/findtextrel.c:254
+#, c-format
+msgid "getting get section header of section %zu: %s"
+msgstr ""
+
+#: src/findtextrel.c:278
+#, c-format
+msgid "cannot read dynamic section: %s"
+msgstr ""
+
+#: src/findtextrel.c:299
+#, c-format
+msgid "no text relocations reported in '%s'"
+msgstr ""
+
+#: src/findtextrel.c:310
+#, c-format
+msgid "while reading ELF file"
+msgstr ""
+
+#: src/findtextrel.c:314
+#, fuzzy, c-format
+msgid "cannot get program header count: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/findtextrel.c:325 src/findtextrel.c:340
+#, fuzzy, c-format
+msgid "cannot get program header index at offset %zd: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/findtextrel.c:396
+#, c-format
+msgid "cannot get symbol table section %zu in '%s': %s"
+msgstr ""
+
+#: src/findtextrel.c:417 src/findtextrel.c:440
+#, c-format
+msgid "cannot get relocation at index %d in section %zu in '%s': %s"
+msgstr ""
+
+#: src/findtextrel.c:506
+#, c-format
+msgid "%s not compiled with -fpic/-fPIC\n"
+msgstr ""
+
+#: src/findtextrel.c:560
+#, c-format
+msgid ""
+"the file containing the function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+
+#: src/findtextrel.c:567 src/findtextrel.c:587
+#, c-format
+msgid ""
+"the file containing the function '%s' might not be compiled with -fpic/-"
+"fPIC\n"
+msgstr ""
+
+#: src/findtextrel.c:575
+#, c-format
+msgid ""
+"either the file containing the function '%s' or the file containing the "
+"function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+
+#: src/findtextrel.c:595
+#, c-format
+msgid ""
+"a relocation modifies memory at offset %llu in a write-protected segment\n"
+msgstr ""
+
+#: src/nm.c:65 src/strip.c:69
+msgid "Output selection:"
+msgstr ""
+
+#: src/nm.c:66
+msgid "Display debugger-only symbols"
+msgstr ""
+
+#: src/nm.c:67
+msgid "Display only defined symbols"
+msgstr "Zeige nur definierte Symbole"
+
+#: src/nm.c:70
+msgid "Display dynamic symbols instead of normal symbols"
+msgstr "Zeige dynamische Symbole anstelle normaler Symbole"
+
+#: src/nm.c:71
+msgid "Display only external symbols"
+msgstr "Zeige nur externe Symbole"
+
+#: src/nm.c:72
+msgid "Display only undefined symbols"
+msgstr "Zeige nur undefinierte Symbole"
+
+#: src/nm.c:74
+msgid "Include index for symbols from archive members"
+msgstr ""
+
+#: src/nm.c:76 src/size.c:53
+msgid "Output format:"
+msgstr "Ausgabeformat:"
+
+#: src/nm.c:78
+#, fuzzy
+msgid "Print name of the input file before every symbol"
+msgstr "Zeige Name der Eingabedatei vor jedem Symbol"
+
+#: src/nm.c:81
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The "
+"default is `sysv'"
+msgstr ""
+"Benutze das Ausgabeformat FORMAT. FORMAT kann `bsd', `sysv' or `posix' sein. "
+"Der Standard ist `sysv'"
+
+#: src/nm.c:83
+msgid "Same as --format=bsd"
+msgstr "Genau wie --format=bsd"
+
+#: src/nm.c:84
+msgid "Same as --format=posix"
+msgstr "Genau wie --format=posix"
+
+#: src/nm.c:85 src/size.c:59
+msgid "Use RADIX for printing symbol values"
+msgstr "Benutze RADIX zur Ausgabe von Symbolwerten"
+
+#: src/nm.c:86
+#, fuzzy
+msgid "Mark special symbols"
+msgstr "Kennzeichne schwache Symbole"
+
+#: src/nm.c:88
+#, fuzzy
+msgid "Print size of defined symbols"
+msgstr "Zeige Grösse der definierten Symbole"
+
+#: src/nm.c:90 src/size.c:67 src/strip.c:74 src/unstrip.c:68
+msgid "Output options:"
+msgstr "Ausgabeoptionen:"
+
+#: src/nm.c:91
+msgid "Sort symbols numerically by address"
+msgstr "Symbole anhand der Adresse numerisch sortieren"
+
+#: src/nm.c:93
+msgid "Do not sort the symbols"
+msgstr "Symbole nicht sortieren"
+
+#: src/nm.c:94
+msgid "Reverse the sense of the sort"
+msgstr "Sortierreihenfolge umkehren"
+
+#: src/nm.c:97
+msgid "Decode low-level symbol names into source code names"
+msgstr ""
+
+#. Short description of program.
+#: src/nm.c:104
+msgid "List symbols from FILEs (a.out by default)."
+msgstr ""
+
+#: src/nm.c:115 src/objdump.c:78
+#, fuzzy
+msgid "Output formatting"
+msgstr "Ausgabeformat:"
+
+#: src/nm.c:139 src/objdump.c:102 src/size.c:104 src/strip.c:132
+#, fuzzy, c-format
+msgid "%s: INTERNAL ERROR %d (%s): %s"
+msgstr "%s: INTERNER FEHLER %d (%s-%s): %s"
+
+#: src/nm.c:380 src/nm.c:392 src/size.c:287 src/size.c:296 src/size.c:307
+#: src/strip.c:2763
+#, c-format
+msgid "while closing '%s'"
+msgstr "beim Schliessen von '%s'"
+
+#: src/nm.c:402 src/objdump.c:279 src/strip.c:827
+#, c-format
+msgid "%s: File format not recognized"
+msgstr "%s: Dateiformat nicht erkannt"
+
+#. Note: 0 is no valid offset.
+#: src/nm.c:442
+#, fuzzy
+msgid ""
+"\n"
+"Archive index:\n"
+msgstr ""
+"\n"
+"Archiv-Index:"
+
+#: src/nm.c:451
+#, c-format
+msgid "invalid offset %zu for symbol %s"
+msgstr "ungültiger Offset %zu für Symbol %s"
+
+#: src/nm.c:456
+#, c-format
+msgid "%s in %s\n"
+msgstr ""
+
+#: src/nm.c:464
+#, c-format
+msgid "cannot reset archive offset to beginning"
+msgstr ""
+
+#: src/nm.c:489 src/objdump.c:327
+#, c-format
+msgid "%s%s%s: file format not recognized"
+msgstr "%s%s%s: Dateiformat nicht erkannt"
+
+#: src/nm.c:702
+msgid "cannot create search tree"
+msgstr "Kann Suchbaum nicht erstellen"
+
+#: src/nm.c:742 src/nm.c:1234 src/objdump.c:778 src/readelf.c:685
+#: src/readelf.c:1506 src/readelf.c:1655 src/readelf.c:1882 src/readelf.c:2123
+#: src/readelf.c:2312 src/readelf.c:2482 src/readelf.c:2604 src/readelf.c:2854
+#: src/readelf.c:3140 src/readelf.c:3215 src/readelf.c:3301 src/readelf.c:3897
+#: src/readelf.c:3945 src/readelf.c:4014 src/readelf.c:12030
+#: src/readelf.c:13213 src/readelf.c:13423 src/readelf.c:13491 src/size.c:396
+#: src/size.c:467 src/strip.c:1093
+#, c-format
+msgid "cannot get section header string table index"
+msgstr ""
+
+#. We always print this prolog.
+#: src/nm.c:767
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s:\n"
+"\n"
+msgstr ""
+"\n"
+"\n"
+"Symbole aus %s:\n"
+"\n"
+
+#. The header line.
+#: src/nm.c:770
+#, c-format
+msgid ""
+"%*s%-*s %-*s Class  Type     %-*s %*s Section\n"
+"\n"
+msgstr ""
+
+#: src/nm.c:772
+msgctxt "sysv"
+msgid "Name"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:774
+msgctxt "sysv"
+msgid "Value"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:776
+msgctxt "sysv"
+msgid "Size"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:778
+msgctxt "sysv"
+msgid "Line"
+msgstr ""
+
+#: src/nm.c:1245
+#, fuzzy, c-format
+msgid "%s: entry size in section %zd `%s' is not what we expect"
+msgstr "%s: entry size in section `%s' is not what we expect"
+
+#: src/nm.c:1250
+#, fuzzy, c-format
+msgid "%s: size of section %zd `%s' is not multiple of entry size"
+msgstr "%s: entry size in section `%s' is not what we expect"
+
+#: src/nm.c:1330
+#, fuzzy, c-format
+msgid "%s: entries (%zd) in section %zd `%s' is too large"
+msgstr "%s: entry size in section `%s' is not what we expect"
+
+#. XXX Add machine specific object file types.
+#: src/nm.c:1566
+#, c-format
+msgid "%s%s%s%s: Invalid operation"
+msgstr "%s%s%s%s: Ungültige Operation"
+
+#: src/nm.c:1616
+#, c-format
+msgid "%s%s%s: no symbols"
+msgstr "%s%s%s: keine Symbole"
+
+#: src/objdump.c:51
+msgid "Mode selection:"
+msgstr ""
+
+#: src/objdump.c:52
+msgid "Display relocation information."
+msgstr ""
+
+#: src/objdump.c:54
+msgid "Display the full contents of all sections requested"
+msgstr ""
+
+#: src/objdump.c:56
+msgid "Display assembler code of executable sections"
+msgstr ""
+
+#: src/objdump.c:58
+#, fuzzy
+msgid "Output content selection:"
+msgstr "Eingabeauswahloptionen:"
+
+#: src/objdump.c:60
+msgid "Only display information for section NAME."
+msgstr ""
+
+#. Short description of program.
+#: src/objdump.c:66
+msgid "Show information from FILEs (a.out by default)."
+msgstr ""
+
+#: src/objdump.c:217 src/readelf.c:630
+msgid "No operation specified.\n"
+msgstr "Keine Operation angegeben.\n"
+
+#: src/objdump.c:257 src/objdump.c:269
+#, c-format
+msgid "while close `%s'"
+msgstr ""
+
+#: src/objdump.c:362 src/readelf.c:2218 src/readelf.c:2409
+msgid "INVALID SYMBOL"
+msgstr ""
+
+#: src/objdump.c:377 src/readelf.c:2252 src/readelf.c:2445
+msgid "INVALID SECTION"
+msgstr ""
+
+#: src/objdump.c:497
+#, c-format
+msgid ""
+"\n"
+"RELOCATION RECORDS FOR [%s]:\n"
+"%-*s TYPE                 VALUE\n"
+msgstr ""
+
+#: src/objdump.c:500
+msgid "OFFSET"
+msgstr "OFFSET"
+
+#: src/objdump.c:565
+#, c-format
+msgid "Contents of section %s:\n"
+msgstr "Inhalt des Abschnitts %s:\n"
+
+#: src/objdump.c:686
+msgid "cannot disassemble"
+msgstr "Disassemblieren nicht möglich"
+
+#: src/objdump.c:757
+#, fuzzy
+msgid "cannot create backend for elf file"
+msgstr "neue Datei konnte nicht angelegt werden"
+
+#. Short description of program.
+#: src/ranlib.c:62
+msgid "Generate an index to speed access to archives."
+msgstr "Erstelle einen Index zur Beschleunigung des Zugriffs auf Archive."
+
+#. Strings for arguments in help texts.
+#: src/ranlib.c:65
+msgid "ARCHIVE"
+msgstr "ARCHIV"
+
+#: src/ranlib.c:101
+#, c-format
+msgid "Archive name required"
+msgstr "Archivname benötigt"
+
+#: src/ranlib.c:165
+#, c-format
+msgid "'%s' is no archive"
+msgstr "'%s' ist kein Archiv"
+
+#: src/ranlib.c:200
+#, c-format
+msgid "error while freeing sub-ELF descriptor: %s"
+msgstr ""
+
+#: src/readelf.c:97
+#, fuzzy
+msgid "ELF input selection:"
+msgstr "Eingabeauswahloptionen:"
+
+#: src/readelf.c:99
+msgid ""
+"Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data"
+msgstr ""
+
+#: src/readelf.c:102
+msgid ""
+"Used with -w to find the skeleton Compile Units in FILE associated with the "
+"Split Compile units in a .dwo input file"
+msgstr ""
+
+#: src/readelf.c:104
+#, fuzzy
+msgid "ELF output selection:"
+msgstr "Eingabeauswahloptionen:"
+
+#: src/readelf.c:106
+msgid "All these plus -p .strtab -p .dynstr -p .comment"
+msgstr ""
+
+#: src/readelf.c:107
+msgid "Display the dynamic segment"
+msgstr ""
+
+#: src/readelf.c:108
+msgid "Display the ELF file header"
+msgstr ""
+
+#: src/readelf.c:110
+msgid "Display histogram of bucket list lengths"
+msgstr ""
+
+#: src/readelf.c:111
+msgid "Display the program headers"
+msgstr "Programm-Köpfe anzeigen"
+
+#: src/readelf.c:113
+msgid "Display relocations"
+msgstr "Relocations anzeigen"
+
+#: src/readelf.c:114
+#, fuzzy
+msgid "Display the section groups"
+msgstr "Programm-Köpfe anzeigen"
+
+#: src/readelf.c:115
+#, fuzzy
+msgid "Display the sections' headers"
+msgstr "Programm-Köpfe anzeigen"
+
+#: src/readelf.c:118
+#, fuzzy
+msgid "Display the symbol table sections"
+msgstr "Symboltabelle anzeigen"
+
+#: src/readelf.c:121
+#, fuzzy
+msgid "Display (only) the dynamic symbol table"
+msgstr "Zeige nur externe Symbole"
+
+#: src/readelf.c:122
+msgid "Display versioning information"
+msgstr "Versionierungsinformationen anzeigen"
+
+#: src/readelf.c:123
+#, fuzzy
+msgid "Display the ELF notes"
+msgstr "Kernnotizen anzeigen"
+
+#: src/readelf.c:125
+#, fuzzy
+msgid "Display architecture specific information, if any"
+msgstr "Architekturspezifische Informationen anzeigen (falls vorhanden)"
+
+#: src/readelf.c:127
+msgid "Display sections for exception handling"
+msgstr "Abschnitte für Ausnahmebehandlung anzeigen"
+
+#: src/readelf.c:129
+msgid "Additional output selection:"
+msgstr ""
+
+#: src/readelf.c:131
+msgid ""
+"Display DWARF section content.  SECTION can be one of abbrev, addr, aranges, "
+"decodedaranges, frame, gdb_index, info, info+, loc, line, decodedline, "
+"ranges, pubnames, str, macinfo, macro or exception"
+msgstr ""
+
+#: src/readelf.c:135
+msgid "Dump the uninterpreted contents of SECTION, by number or name"
+msgstr ""
+
+#: src/readelf.c:137
+msgid "Print string contents of sections"
+msgstr ""
+
+#: src/readelf.c:140
+msgid "Display the symbol index of an archive"
+msgstr "Symbolindex des Archivs anzeigen"
+
+#: src/readelf.c:142
+msgid "Use the dynamic segment when possible for displaying info"
+msgstr ""
+
+#: src/readelf.c:144
+msgid "Output control:"
+msgstr "Ausgabekontrolle:"
+
+#: src/readelf.c:146
+msgid "Do not find symbol names for addresses in DWARF data"
+msgstr "Keine symbolischen Namen für Adressen in DWARF-Daten suchen"
+
+#: src/readelf.c:148
+#, fuzzy
+msgid ""
+"Display just offsets instead of resolving values to addresses in DWARF data"
+msgstr "Keine symbolischen Namen für Adressen in DWARF-Daten suchen"
+
+#: src/readelf.c:150
+msgid "Ignored for compatibility (lines always wide)"
+msgstr ""
+
+#: src/readelf.c:152
+msgid ""
+"Show compression information for compressed sections (when used with -S); "
+"decompress section before dumping data (when used with -p or -x)"
+msgstr ""
+
+#. Short description of program.
+#: src/readelf.c:157
+msgid "Print information from ELF file in human-readable form."
+msgstr "Informationen aus der ELF-Datei in menschenlesbarer Form ausgeben."
+
+#. Look up once.
+#: src/readelf.c:395
+msgid "yes"
+msgstr "ja"
+
+#: src/readelf.c:396
+msgid "no"
+msgstr "nein"
+
+#: src/readelf.c:598
+#, c-format
+msgid "Unknown DWARF debug section `%s'.\n"
+msgstr ""
+
+#: src/readelf.c:669 src/readelf.c:780
+#, c-format
+msgid "cannot generate Elf descriptor: %s"
+msgstr "konnte Elf-Deskriptor nicht erzeugen: %s"
+
+#: src/readelf.c:676 src/readelf.c:1002 src/strip.c:1188
+#, c-format
+msgid "cannot determine number of sections: %s"
+msgstr ""
+
+#: src/readelf.c:694 src/readelf.c:1322 src/readelf.c:1530
+#, c-format
+msgid "cannot get section: %s"
+msgstr ""
+
+#: src/readelf.c:703 src/readelf.c:1329 src/readelf.c:1537 src/readelf.c:13443
+#: src/unstrip.c:396 src/unstrip.c:427 src/unstrip.c:490 src/unstrip.c:622
+#: src/unstrip.c:640 src/unstrip.c:680 src/unstrip.c:897 src/unstrip.c:1263
+#: src/unstrip.c:1390 src/unstrip.c:1414 src/unstrip.c:1470 src/unstrip.c:1511
+#: src/unstrip.c:1703 src/unstrip.c:1854 src/unstrip.c:1998 src/unstrip.c:2106
+#, c-format
+msgid "cannot get section header: %s"
+msgstr ""
+
+#: src/readelf.c:711
+#, fuzzy, c-format
+msgid "cannot get section name"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:720 src/readelf.c:7177 src/readelf.c:11231 src/readelf.c:11333
+#: src/readelf.c:11517
+#, c-format
+msgid "cannot get %s content: %s"
+msgstr ""
+
+#: src/readelf.c:736
+#, fuzzy, c-format
+msgid "cannot create temp file '%s'"
+msgstr "neue Datei konnte nicht angelegt werden"
+
+#: src/readelf.c:745
+#, fuzzy, c-format
+msgid "cannot write section data"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:751 src/readelf.c:768 src/readelf.c:797
+#, c-format
+msgid "error while closing Elf descriptor: %s"
+msgstr ""
+
+#: src/readelf.c:758
+#, fuzzy, c-format
+msgid "error while rewinding file descriptor"
+msgstr "Fehler beim Schliessen des Elf-Desktriptor: %s\n"
+
+#: src/readelf.c:792
+#, c-format
+msgid "'%s' is not an archive, cannot print archive index"
+msgstr ""
+
+#: src/readelf.c:896
+#, c-format
+msgid "cannot stat input file"
+msgstr ""
+
+#: src/readelf.c:898
+#, c-format
+msgid "input file is empty"
+msgstr ""
+
+#: src/readelf.c:900
+#, c-format
+msgid "failed reading '%s': %s"
+msgstr "Konnte '%s' nicht lesen: %s"
+
+#: src/readelf.c:929
+#, fuzzy, c-format
+msgid "No such section '%s' in '%s'"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:988
+#, c-format
+msgid "cannot read ELF header: %s"
+msgstr ""
+
+#: src/readelf.c:996
+#, c-format
+msgid "cannot create EBL handle"
+msgstr ""
+
+#: src/readelf.c:1007
+#, fuzzy, c-format
+msgid "cannot determine number of program headers: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/readelf.c:1039
+#, fuzzy, c-format
+msgid "cannot read ELF: %s"
+msgstr "Konnte %s: %s nicht lesen"
+
+#: src/readelf.c:1072
+#, fuzzy
+msgid "cannot find section"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:1109
+msgid "NONE (None)"
+msgstr ""
+
+#: src/readelf.c:1110
+msgid "REL (Relocatable file)"
+msgstr ""
+
+#: src/readelf.c:1111
+msgid "EXEC (Executable file)"
+msgstr ""
+
+#: src/readelf.c:1112
+msgid "DYN (Shared object file)"
+msgstr ""
+
+#: src/readelf.c:1113
+msgid "CORE (Core file)"
+msgstr ""
+
+#: src/readelf.c:1118
+#, c-format
+msgid "OS Specific: (%x)\n"
+msgstr ""
+
+#. && e_type <= ET_HIPROC always true
+#: src/readelf.c:1120
+#, c-format
+msgid "Processor Specific: (%x)\n"
+msgstr ""
+
+#: src/readelf.c:1130
+msgid ""
+"ELF Header:\n"
+"  Magic:  "
+msgstr ""
+
+#: src/readelf.c:1134
+#, c-format
+msgid ""
+"\n"
+"  Class:                             %s\n"
+msgstr ""
+
+#: src/readelf.c:1139
+#, fuzzy, c-format
+msgid "  Data:                              %s\n"
+msgstr "  Daten:                             %s\n"
+
+#: src/readelf.c:1145
+#, c-format
+msgid "  Ident Version:                     %hhd %s\n"
+msgstr ""
+
+#: src/readelf.c:1147 src/readelf.c:1169
+msgid "(current)"
+msgstr "(aktuell)"
+
+#: src/readelf.c:1151
+#, c-format
+msgid "  OS/ABI:                            %s\n"
+msgstr ""
+
+#: src/readelf.c:1154
+#, c-format
+msgid "  ABI Version:                       %hhd\n"
+msgstr ""
+
+#: src/readelf.c:1157
+msgid "  Type:                              "
+msgstr "  Typ:                               "
+
+#: src/readelf.c:1162
+#, c-format
+msgid "  Machine:                           %s\n"
+msgstr ""
+
+#: src/readelf.c:1164
+#, fuzzy, c-format
+msgid "  Machine:                           <unknown>: 0x%x\n"
+msgstr "  Daten:                             %s\n"
+
+#: src/readelf.c:1167
+#, c-format
+msgid "  Version:                           %d %s\n"
+msgstr ""
+
+#: src/readelf.c:1171
+#, c-format
+msgid "  Entry point address:               %#<PRIx64>\n"
+msgstr ""
+
+#: src/readelf.c:1174
+#, c-format
+msgid "  Start of program headers:          %<PRId64> %s\n"
+msgstr ""
+
+#: src/readelf.c:1175 src/readelf.c:1178
+msgid "(bytes into file)"
+msgstr ""
+
+#: src/readelf.c:1177
+#, c-format
+msgid "  Start of section headers:          %<PRId64> %s\n"
+msgstr ""
+
+#: src/readelf.c:1180
+#, c-format
+msgid "  Flags:                             %s\n"
+msgstr ""
+
+#: src/readelf.c:1183
+#, c-format
+msgid "  Size of this header:               %<PRId16> %s\n"
+msgstr ""
+
+#: src/readelf.c:1184 src/readelf.c:1187 src/readelf.c:1204
+msgid "(bytes)"
+msgstr "(Bytes)"
+
+#: src/readelf.c:1186
+#, c-format
+msgid "  Size of program header entries:    %<PRId16> %s\n"
+msgstr ""
+
+#: src/readelf.c:1189
+#, c-format
+msgid "  Number of program headers entries: %<PRId16>"
+msgstr ""
+
+#: src/readelf.c:1196
+#, c-format
+msgid " (%<PRIu32> in [0].sh_info)"
+msgstr ""
+
+#: src/readelf.c:1199 src/readelf.c:1216 src/readelf.c:1230
+msgid " ([0] not available)"
+msgstr ""
+
+#: src/readelf.c:1203
+#, c-format
+msgid "  Size of section header entries:    %<PRId16> %s\n"
+msgstr ""
+
+#: src/readelf.c:1206
+#, c-format
+msgid "  Number of section headers entries: %<PRId16>"
+msgstr ""
+
+#: src/readelf.c:1213
+#, c-format
+msgid " (%<PRIu32> in [0].sh_size)"
+msgstr ""
+
+#. We managed to get the zeroth section.
+#: src/readelf.c:1226
+#, c-format
+msgid " (%<PRIu32> in [0].sh_link)"
+msgstr ""
+
+#: src/readelf.c:1234
+#, c-format
+msgid ""
+"  Section header string table index: XINDEX%s\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:1238
+#, c-format
+msgid ""
+"  Section header string table index: %<PRId16>\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:1288 src/readelf.c:1496
+#, fuzzy, c-format
+msgid "cannot get number of sections: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/readelf.c:1291
+#, fuzzy, c-format
+msgid ""
+"There are %zd section headers, starting at offset %#<PRIx64>:\n"
+"\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:1299
+#, fuzzy, c-format
+msgid "cannot get section header string table index: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:1302
+msgid "Section Headers:"
+msgstr ""
+
+#: src/readelf.c:1305
+msgid ""
+"[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk "
+"Inf Al"
+msgstr ""
+
+#: src/readelf.c:1307
+msgid ""
+"[Nr] Name                 Type         Addr             Off      Size     ES "
+"Flags Lk Inf Al"
+msgstr ""
+
+#: src/readelf.c:1312
+msgid "     [Compression  Size   Al]"
+msgstr ""
+
+#: src/readelf.c:1314
+msgid "     [Compression  Size     Al]"
+msgstr ""
+
+#: src/readelf.c:1392
+#, c-format
+msgid "bad compression header for section %zd: %s"
+msgstr ""
+
+#: src/readelf.c:1403
+#, c-format
+msgid "bad gnu compressed size for section %zd: %s"
+msgstr ""
+
+#: src/readelf.c:1421
+msgid "Program Headers:"
+msgstr "Programm-Köpfe:"
+
+#: src/readelf.c:1423
+msgid ""
+"  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"
+msgstr ""
+
+#: src/readelf.c:1426
+msgid ""
+"  Type           Offset   VirtAddr           PhysAddr           FileSiz  "
+"MemSiz   Flg Align"
+msgstr ""
+
+#: src/readelf.c:1483
+#, c-format
+msgid "\t[Requesting program interpreter: %s]\n"
+msgstr ""
+
+#: src/readelf.c:1508
+msgid ""
+"\n"
+" Section to Segment mapping:\n"
+"  Segment Sections..."
+msgstr ""
+
+#: src/readelf.c:1519 src/unstrip.c:2165 src/unstrip.c:2207 src/unstrip.c:2214
+#, c-format
+msgid "cannot get program header: %s"
+msgstr ""
+
+#: src/readelf.c:1663
+#, c-format
+msgid ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:1668
+#, c-format
+msgid ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:1676
+msgid "<INVALID SYMBOL>"
+msgstr ""
+
+#: src/readelf.c:1690
+msgid "<INVALID SECTION>"
+msgstr ""
+
+#: src/readelf.c:1713 src/readelf.c:2614 src/readelf.c:3913 src/readelf.c:4213
+#: src/readelf.c:13315 src/readelf.c:13322 src/readelf.c:13366
+#: src/readelf.c:13373
+msgid "Couldn't uncompress section"
+msgstr ""
+
+#: src/readelf.c:1717 src/readelf.c:2619 src/readelf.c:3917
+#, fuzzy, c-format
+msgid "cannot get section [%zd] header: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:1886 src/readelf.c:2860 src/readelf.c:3146 src/readelf.c:3221
+#: src/readelf.c:3524 src/readelf.c:3598 src/readelf.c:5963
+#, fuzzy, c-format
+msgid "invalid sh_link value in section %zu"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:1889
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:1902
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:1912
+msgid "  Type              Value\n"
+msgstr ""
+
+#: src/readelf.c:1921
+#, fuzzy
+msgid "cannot get string table by using dynamic segment"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:1960
+#, c-format
+msgid "Shared library: [%s]\n"
+msgstr ""
+
+#: src/readelf.c:1964
+#, c-format
+msgid "Library soname: [%s]\n"
+msgstr ""
+
+#: src/readelf.c:1968
+#, c-format
+msgid "Library rpath: [%s]\n"
+msgstr ""
+
+#: src/readelf.c:1972
+#, c-format
+msgid "Library runpath: [%s]\n"
+msgstr ""
+
+#: src/readelf.c:1993
+#, c-format
+msgid "%<PRId64> (bytes)\n"
+msgstr ""
+
+#: src/readelf.c:2109 src/readelf.c:2298
+#, c-format
+msgid ""
+"\n"
+"Invalid symbol table at offset %#0<PRIx64>\n"
+msgstr ""
+
+#: src/readelf.c:2126 src/readelf.c:2315
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#. The .rel.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. The .rela.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. A .relr.dyn section does not refer to a specific section.
+#: src/readelf.c:2141 src/readelf.c:2330 src/readelf.c:2485
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:2151
+msgid "  Offset      Type                 Value       Name\n"
+msgstr ""
+
+#: src/readelf.c:2153
+msgid "  Offset              Type                 Value               Name\n"
+msgstr ""
+
+#: src/readelf.c:2206 src/readelf.c:2217 src/readelf.c:2230 src/readelf.c:2251
+#: src/readelf.c:2263 src/readelf.c:2396 src/readelf.c:2408 src/readelf.c:2422
+#: src/readelf.c:2444 src/readelf.c:2457
+msgid "<INVALID RELOC>"
+msgstr ""
+
+#: src/readelf.c:2340
+msgid "  Offset      Type            Value       Addend Name\n"
+msgstr ""
+
+#: src/readelf.c:2342
+msgid "  Offset              Type            Value               Addend Name\n"
+msgstr ""
+
+#: src/readelf.c:2654
+#, c-format
+msgid "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+msgstr ""
+
+#: src/readelf.c:2750
+#, c-format
+msgid "bad dynamic symbol"
+msgstr ""
+
+#: src/readelf.c:2868
+#, c-format
+msgid ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entry:\n"
+msgid_plural ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:2873
+#, c-format
+msgid " %lu local symbol  String table: [%2u] '%s'\n"
+msgid_plural " %lu local symbols  String table: [%2u] '%s'\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:2881
+msgid "  Num:    Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr ""
+
+#: src/readelf.c:2883
+msgid "  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr ""
+
+#: src/readelf.c:3002
+msgid "Dynamic symbol information is not available for displaying symbols."
+msgstr ""
+
+#: src/readelf.c:3102
+msgid "none"
+msgstr "keine"
+
+#: src/readelf.c:3119
+msgid "| <unknown>"
+msgstr "| <unbekannt>"
+
+#: src/readelf.c:3149
+#, c-format
+msgid ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:3170
+#, fuzzy, c-format
+msgid "  %#06x: Version: %hu  File: %s  Cnt: %hu\n"
+msgstr "  %#06x: Version: %hu  Datei: %s  Cnt: %hu\n"
+
+#: src/readelf.c:3183
+#, c-format
+msgid "  %#06x: Name: %s  Flags: %s  Version: %hu\n"
+msgstr "  %#06x: Name: %s  Flags: %s  Version: %hu\n"
+
+#: src/readelf.c:3225
+#, c-format
+msgid ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:3253
+#, c-format
+msgid "  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"
+msgstr ""
+
+#: src/readelf.c:3268
+#, c-format
+msgid "  %#06x: Parent %d: %s\n"
+msgstr ""
+
+#. Print the header.
+#: src/readelf.c:3528
+#, c-format
+msgid ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgid_plural ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:3556
+msgid "   0 *local*                     "
+msgstr "   0 *lokal*                     "
+
+#: src/readelf.c:3561
+msgid "   1 *global*                    "
+msgstr "   1 *global*                    "
+
+#: src/readelf.c:3603
+#, c-format
+msgid ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"bucket):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"buckets):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:3625
+#, no-c-format
+msgid " Length  Number  % of total  Coverage\n"
+msgstr ""
+
+#: src/readelf.c:3627
+#, c-format
+msgid "      0  %6<PRIu32>      %5.1f%%\n"
+msgstr "      0  %6<PRIu32>      %5.1f%%\n"
+
+#: src/readelf.c:3634
+#, c-format
+msgid "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+msgstr "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+
+#: src/readelf.c:3648
+#, c-format
+msgid ""
+" Average number of tests:   successful lookup: %f\n"
+"\t\t\t  unsuccessful lookup: %f\n"
+msgstr ""
+
+#: src/readelf.c:3666 src/readelf.c:3730 src/readelf.c:3796
+#, c-format
+msgid "cannot get data for section %d: %s"
+msgstr ""
+
+#: src/readelf.c:3674
+#, fuzzy, c-format
+msgid "invalid data in sysv.hash section %d"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:3703
+#, fuzzy, c-format
+msgid "invalid chain in sysv.hash section %d"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:3738
+#, fuzzy, c-format
+msgid "invalid data in sysv.hash64 section %d"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:3769
+#, fuzzy, c-format
+msgid "invalid chain in sysv.hash64 section %d"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:3805
+#, fuzzy, c-format
+msgid "invalid data in gnu.hash section %d"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:3871
+#, c-format
+msgid ""
+" Symbol Bias: %u\n"
+" Bitmask Size: %zu bytes  %<PRIuFAST32>%% bits set  2nd hash shift: %u\n"
+msgstr ""
+
+#: src/readelf.c:3956
+#, c-format
+msgid ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:3970
+msgid ""
+"       Library                       Time Stamp          Checksum Version "
+"Flags"
+msgstr ""
+
+#: src/readelf.c:4030
+#, c-format
+msgid ""
+"\n"
+"Object attributes section [%2zu] '%s' of %<PRIu64> bytes at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:4047
+msgid "  Owner          Size\n"
+msgstr ""
+
+#: src/readelf.c:4071
+#, c-format
+msgid "  %-13s  %4<PRIu32>\n"
+msgstr "  %-13s  %4<PRIu32>\n"
+
+#. Unknown subsection, print and skip.
+#: src/readelf.c:4110
+#, c-format
+msgid "    %-4u %12<PRIu32>\n"
+msgstr "    %-4u %12<PRIu32>\n"
+
+#. Tag_File
+#: src/readelf.c:4115
+#, c-format
+msgid "    File: %11<PRIu32>\n"
+msgstr "    File: %11<PRIu32>\n"
+
+#: src/readelf.c:4165
+#, c-format
+msgid "      %s: %<PRId64>, %s\n"
+msgstr "      %s: %<PRId64>, %s\n"
+
+#: src/readelf.c:4168
+#, c-format
+msgid "      %s: %<PRId64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:4171
+#, c-format
+msgid "      %s: %s\n"
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:4181
+#, c-format
+msgid "      %u: %<PRId64>\n"
+msgstr "      %u: %<PRId64>\n"
+
+#: src/readelf.c:4184
+#, c-format
+msgid "      %u: %s\n"
+msgstr "      %u: %s\n"
+
+#: src/readelf.c:4222
+#, fuzzy
+msgid "Couldn't get data from section"
+msgstr "konnte Versionierungsabschnitt nicht erstellen: %s"
+
+#: src/readelf.c:4287
+#, fuzzy
+msgid "sprintf failure"
+msgstr "mprotect fehlgeschlagen"
+
+#: src/readelf.c:4771
+msgid "empty block"
+msgstr ""
+
+#: src/readelf.c:4774
+#, c-format
+msgid "%zu byte block:"
+msgstr ""
+
+#: src/readelf.c:5252
+#, c-format
+msgid "%*s[%2<PRIuMAX>] %s  <TRUNCATED>\n"
+msgstr ""
+
+#: src/readelf.c:5424
+#, c-format
+msgid "%s %#<PRIx64> used with different address sizes"
+msgstr ""
+
+#: src/readelf.c:5431
+#, c-format
+msgid "%s %#<PRIx64> used with different offset sizes"
+msgstr ""
+
+#: src/readelf.c:5438
+#, c-format
+msgid "%s %#<PRIx64> used with different base addresses"
+msgstr ""
+
+#: src/readelf.c:5445
+#, c-format
+msgid "%s %#<PRIx64> used with different attribute %s and %s"
+msgstr ""
+
+#: src/readelf.c:5545
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"
+msgstr ""
+
+#: src/readelf.c:5553
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE> ... %<PRIu64> bytes ...\n"
+msgstr ""
+
+#: src/readelf.c:5659
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [ Code]\n"
+msgstr ""
+
+#: src/readelf.c:5667
+#, c-format
+msgid ""
+"\n"
+"Abbreviation section at offset %<PRIu64>:\n"
+msgstr ""
+
+#: src/readelf.c:5680
+#, c-format
+msgid " *** error while reading abbreviation: %s\n"
+msgstr ""
+
+#: src/readelf.c:5696
+#, c-format
+msgid " [%5u] offset: %<PRId64>, children: %s, tag: %s\n"
+msgstr ""
+
+#: src/readelf.c:5733 src/readelf.c:6026 src/readelf.c:6197 src/readelf.c:6568
+#: src/readelf.c:7194 src/readelf.c:8963 src/readelf.c:9705 src/readelf.c:10173
+#: src/readelf.c:10428 src/readelf.c:10590 src/readelf.c:10971
+#: src/readelf.c:11042
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:5836 src/readelf.c:5860 src/readelf.c:6233 src/readelf.c:9741
+#, fuzzy, c-format
+msgid " Length:         %8<PRIu64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:5838 src/readelf.c:5875 src/readelf.c:6246 src/readelf.c:9754
+#, fuzzy, c-format
+msgid " DWARF version:  %8<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:5839 src/readelf.c:5884 src/readelf.c:6255 src/readelf.c:9763
+#, fuzzy, c-format
+msgid " Address size:   %8<PRIu64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:5841 src/readelf.c:5894 src/readelf.c:6265 src/readelf.c:9773
+#, fuzzy, c-format
+msgid " Segment size:   %8<PRIu64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:5879 src/readelf.c:6250 src/readelf.c:9758 src/readelf.c:11164
+#, fuzzy, c-format
+msgid "Unknown version"
+msgstr "unbekannte Version"
+
+#: src/readelf.c:5889 src/readelf.c:6096 src/readelf.c:6260 src/readelf.c:9768
+#, fuzzy, c-format
+msgid "unsupported address size"
+msgstr "Kein Adress-Wert"
+
+#: src/readelf.c:5900 src/readelf.c:6107 src/readelf.c:6270 src/readelf.c:9778
+#, c-format
+msgid "unsupported segment size"
+msgstr ""
+
+#: src/readelf.c:5953
+#, c-format
+msgid "cannot get .debug_aranges content: %s"
+msgstr ""
+
+#: src/readelf.c:5968
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entries:\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:5999
+#, c-format
+msgid " [%*zu] ???\n"
+msgstr " [%*zu] ???\n"
+
+#: src/readelf.c:6001
+#, c-format
+msgid ""
+" [%*zu] start: %0#*<PRIx64>, length: %5<PRIu64>, CU DIE offset: %6<PRId64>\n"
+msgstr ""
+
+#: src/readelf.c:6039 src/readelf.c:8982
+#, c-format
+msgid ""
+"\n"
+"Table at offset %zu:\n"
+msgstr ""
+
+#: src/readelf.c:6043 src/readelf.c:6214 src/readelf.c:7218 src/readelf.c:8993
+#: src/readelf.c:9722
+#, c-format
+msgid "invalid data in section [%zu] '%s'"
+msgstr ""
+
+#: src/readelf.c:6059
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Length:        %6<PRIu64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6071
+#, fuzzy, c-format
+msgid " DWARF version: %6<PRIuFAST16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6075
+#, c-format
+msgid "unsupported aranges version"
+msgstr ""
+
+#: src/readelf.c:6086
+#, fuzzy, c-format
+msgid " CU offset:     %6<PRIx64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6092
+#, c-format
+msgid " Address size:  %6<PRIu64>\n"
+msgstr ""
+
+#: src/readelf.c:6103
+#, c-format
+msgid ""
+" Segment size:  %6<PRIu64>\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:6158
+#, c-format
+msgid "   %zu padding bytes\n"
+msgstr ""
+
+#: src/readelf.c:6220 src/readelf.c:9728
+#, fuzzy, c-format
+msgid ""
+"Table at Offset 0x%<PRIx64>:\n"
+"\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6275 src/readelf.c:9783
+#, fuzzy, c-format
+msgid " Offset entries: %8<PRIu64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6291 src/readelf.c:9799
+#, c-format
+msgid " Unknown CU base: "
+msgstr ""
+
+#: src/readelf.c:6293 src/readelf.c:9801
+#, c-format
+msgid " CU [%6<PRIx64>] base: "
+msgstr ""
+
+#: src/readelf.c:6299 src/readelf.c:9807
+#, c-format
+msgid " Not associated with a CU.\n"
+msgstr ""
+
+#: src/readelf.c:6310 src/readelf.c:9818
+#, c-format
+msgid "too many offset entries for unit length"
+msgstr ""
+
+#: src/readelf.c:6314 src/readelf.c:9822
+#, fuzzy, c-format
+msgid "  Offsets starting at 0x%<PRIx64>:\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6366
+#, fuzzy, c-format
+msgid "invalid range list data"
+msgstr "Ungültige Daten"
+
+#: src/readelf.c:6551 src/readelf.c:10157
+#, c-format
+msgid ""
+"   %zu padding bytes\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:6599 src/readelf.c:10206
+#, c-format
+msgid ""
+"\n"
+" Unknown CU base: "
+msgstr ""
+
+#: src/readelf.c:6601 src/readelf.c:10208
+#, c-format
+msgid ""
+"\n"
+" CU [%6<PRIx64>] base: "
+msgstr ""
+
+#: src/readelf.c:6610 src/readelf.c:10234 src/readelf.c:10260
+#, c-format
+msgid " [%6tx]  <INVALID DATA>\n"
+msgstr ""
+
+#: src/readelf.c:6635 src/readelf.c:10344
+#, fuzzy
+msgid "base address"
+msgstr "Außerhalb des Adressbereiches"
+
+#: src/readelf.c:6645 src/readelf.c:10354
+#, fuzzy, c-format
+msgid " [%6tx] empty list\n"
+msgstr " [%6tx]  %s..%s\n"
+
+#: src/readelf.c:6909
+msgid "         <INVALID DATA>\n"
+msgstr ""
+
+#: src/readelf.c:7166
+#, fuzzy, c-format
+msgid "cannot get ELF: %s"
+msgstr "ELF Kopf konnte nicht ausgelesen werden"
+
+#: src/readelf.c:7190
+#, c-format
+msgid ""
+"\n"
+"Call frame information section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:7240
+#, c-format
+msgid ""
+"\n"
+" [%6tx] Zero terminator\n"
+msgstr ""
+
+#: src/readelf.c:7344 src/readelf.c:7498
+#, fuzzy, c-format
+msgid "invalid augmentation length"
+msgstr "ungültige Abschnittsausrichtung"
+
+#: src/readelf.c:7359
+msgid "FDE address encoding: "
+msgstr ""
+
+#: src/readelf.c:7365
+msgid "LSDA pointer encoding: "
+msgstr ""
+
+#: src/readelf.c:7475
+#, c-format
+msgid " (offset: %#<PRIx64>)"
+msgstr ""
+
+#: src/readelf.c:7482
+#, c-format
+msgid " (end offset: %#<PRIx64>)"
+msgstr ""
+
+#: src/readelf.c:7519
+#, c-format
+msgid "   %-26sLSDA pointer: %#<PRIx64>\n"
+msgstr ""
+
+#: src/readelf.c:7604
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute code: %s"
+msgstr ""
+
+#: src/readelf.c:7614
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute form: %s"
+msgstr ""
+
+#: src/readelf.c:7636
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute '%s' (%s) value: %s"
+msgstr ""
+
+#: src/readelf.c:7966
+#, fuzzy, c-format
+msgid "invalid file (%<PRId64>): %s"
+msgstr "Ungültige Datei"
+
+#: src/readelf.c:7970
+#, fuzzy, c-format
+msgid "no srcfiles for CU [%<PRIx64>]"
+msgstr "unbekannte Form %<PRIx64>"
+
+#: src/readelf.c:7974
+#, fuzzy, c-format
+msgid "couldn't get DWARF CU: %s"
+msgstr "ELF Kopf konnte nicht ausgelesen werden"
+
+#: src/readelf.c:8296
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [Offset]\n"
+msgstr ""
+
+#: src/readelf.c:8346
+#, fuzzy, c-format
+msgid "cannot get next unit: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:8366
+#, c-format
+msgid ""
+" Type unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+" Type signature: %#<PRIx64>, Type offset: %#<PRIx64> [%<PRIx64>]\n"
+msgstr ""
+
+#: src/readelf.c:8378
+#, c-format
+msgid ""
+" Compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+
+#: src/readelf.c:8388 src/readelf.c:8549
+#, c-format
+msgid " Unit type: %s (%<PRIu8>)"
+msgstr ""
+
+#: src/readelf.c:8415
+#, c-format
+msgid "unknown version (%d) or unit type (%d)"
+msgstr ""
+
+#: src/readelf.c:8444
+#, c-format
+msgid "cannot get DIE offset: %s"
+msgstr ""
+
+#: src/readelf.c:8453
+#, fuzzy, c-format
+msgid "cannot get tag of DIE at offset [%<PRIx64>] in section '%s': %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/readelf.c:8489
+#, c-format
+msgid "cannot get next DIE: %s\n"
+msgstr ""
+
+#: src/readelf.c:8497
+#, c-format
+msgid "cannot get next DIE: %s"
+msgstr ""
+
+#: src/readelf.c:8541
+#, c-format
+msgid ""
+" Split compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+
+#: src/readelf.c:8593
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:8925
+#, fuzzy, c-format
+msgid "unknown form: %s"
+msgstr "unbekannte Form %<PRIx64>"
+
+#. Print what we got so far.
+#: src/readelf.c:9073
+#, c-format
+msgid ""
+"\n"
+" Length:                         %<PRIu64>\n"
+" DWARF version:                  %<PRIuFAST16>\n"
+" Prologue length:                %<PRIu64>\n"
+" Address size:                   %zd\n"
+" Segment selector size:          %zd\n"
+" Min instruction length:         %<PRIuFAST8>\n"
+" Max operations per instruction: %<PRIuFAST8>\n"
+" Initial value if 'is_stmt':     %<PRIuFAST8>\n"
+" Line base:                      %<PRIdFAST8>\n"
+" Line range:                     %<PRIuFAST8>\n"
+" Opcode base:                    %<PRIuFAST8>\n"
+"\n"
+"Opcodes:\n"
+msgstr ""
+
+#: src/readelf.c:9095
+#, fuzzy, c-format
+msgid "cannot handle .debug_line version: %u\n"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/readelf.c:9103
+#, fuzzy, c-format
+msgid "cannot handle address size: %u\n"
+msgstr "Kein Adress-Wert"
+
+#: src/readelf.c:9111
+#, c-format
+msgid "cannot handle segment selector size: %u\n"
+msgstr ""
+
+#: src/readelf.c:9121
+#, c-format
+msgid "invalid data at offset %tu in section [%zu] '%s'"
+msgstr ""
+
+#: src/readelf.c:9136
+#, c-format
+msgid "  [%*<PRIuFAST8>]  %hhu argument\n"
+msgid_plural "  [%*<PRIuFAST8>]  %hhu arguments\n"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:9147
+msgid ""
+"\n"
+"Directory table:"
+msgstr ""
+
+#: src/readelf.c:9153 src/readelf.c:9230
+#, fuzzy, c-format
+msgid "      ["
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:9224
+msgid ""
+"\n"
+"File name table:"
+msgstr ""
+
+#: src/readelf.c:9285
+msgid " Entry Dir   Time      Size      Name"
+msgstr ""
+
+#: src/readelf.c:9331
+msgid ""
+"\n"
+"No line number statements."
+msgstr ""
+
+#: src/readelf.c:9335
+msgid ""
+"\n"
+"Line number statements:"
+msgstr ""
+
+#: src/readelf.c:9350
+#, c-format
+msgid "invalid maximum operations per instruction is zero"
+msgstr ""
+
+#: src/readelf.c:9384
+#, c-format
+msgid " special opcode %u: address+%u = "
+msgstr ""
+
+#: src/readelf.c:9388
+#, c-format
+msgid ", op_index = %u, line%+d = %zu\n"
+msgstr ""
+
+#: src/readelf.c:9391
+#, c-format
+msgid ", line%+d = %zu\n"
+msgstr ""
+
+#: src/readelf.c:9409
+#, c-format
+msgid " extended opcode %u: "
+msgstr ""
+
+#: src/readelf.c:9414
+msgid " end of sequence"
+msgstr ""
+
+#: src/readelf.c:9432
+#, fuzzy, c-format
+msgid " set address to "
+msgstr "Außerhalb des Adressbereiches"
+
+#: src/readelf.c:9460
+#, c-format
+msgid " define new file: dir=%u, mtime=%<PRIu64>, length=%<PRIu64>, name=%s\n"
+msgstr ""
+
+#: src/readelf.c:9474
+#, c-format
+msgid " set discriminator to %u\n"
+msgstr ""
+
+#: src/readelf.c:9501
+#, c-format
+msgid " set inlined context %u, function name %s (0x%x)\n"
+msgstr ""
+
+#: src/readelf.c:9525
+#, c-format
+msgid " set function name %s (0x%x)\n"
+msgstr ""
+
+#. Unknown, ignore it.
+#: src/readelf.c:9532
+#, fuzzy
+msgid " unknown opcode"
+msgstr "unbekannter Typ"
+
+#. Takes no argument.
+#: src/readelf.c:9544
+msgid " copy"
+msgstr ""
+
+#: src/readelf.c:9555
+#, c-format
+msgid " advance address by %u to "
+msgstr ""
+
+#: src/readelf.c:9559 src/readelf.c:9620
+#, c-format
+msgid ", op_index to %u"
+msgstr ""
+
+#: src/readelf.c:9571
+#, c-format
+msgid " advance line by constant %d to %<PRId64>\n"
+msgstr ""
+
+#: src/readelf.c:9581
+#, c-format
+msgid " set file to %<PRIu64>\n"
+msgstr ""
+
+#: src/readelf.c:9592
+#, c-format
+msgid " set column to %<PRIu64>\n"
+msgstr ""
+
+#: src/readelf.c:9599
+#, c-format
+msgid " set '%s' to %<PRIuFAST8>\n"
+msgstr ""
+
+#. Takes no argument.
+#: src/readelf.c:9605
+msgid " set basic block flag"
+msgstr ""
+
+#: src/readelf.c:9616
+#, c-format
+msgid " advance address by constant %u to "
+msgstr ""
+
+#: src/readelf.c:9636
+#, c-format
+msgid " advance address by fixed value %u to \n"
+msgstr ""
+
+#. Takes no argument.
+#: src/readelf.c:9646
+msgid " set prologue end flag"
+msgstr ""
+
+#. Takes no argument.
+#: src/readelf.c:9651
+msgid " set epilogue begin flag"
+msgstr ""
+
+#: src/readelf.c:9661
+#, c-format
+msgid " set isa to %u\n"
+msgstr ""
+
+#. This is a new opcode the generator but not we know about.
+#. Read the parameters associated with it but then discard
+#. everything.  Read all the parameters for this opcode.
+#: src/readelf.c:9670
+#, c-format
+msgid " unknown opcode with %<PRIu8> parameter:"
+msgid_plural " unknown opcode with %<PRIu8> parameters:"
+msgstr[0] ""
+msgstr[1] ""
+
+#: src/readelf.c:9871
+#, c-format
+msgid "    <INVALID DATA>\n"
+msgstr ""
+
+#: src/readelf.c:9911
+#, fuzzy, c-format
+msgid "invalid loclists data"
+msgstr "Ungültige Daten"
+
+#: src/readelf.c:10381 src/readelf.c:11426
+msgid "   <INVALID DATA>\n"
+msgstr ""
+
+#: src/readelf.c:10512
+#, c-format
+msgid "%*s*** non-terminated string at end of section"
+msgstr ""
+
+#: src/readelf.c:10535
+#, c-format
+msgid "%*s*** missing DW_MACINFO_start_file argument at end of section"
+msgstr ""
+
+#: src/readelf.c:10630
+#, fuzzy, c-format
+msgid " Offset:             0x%<PRIx64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:10642
+#, fuzzy, c-format
+msgid " Version:            %<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:10648 src/readelf.c:11547
+#, c-format
+msgid "  unknown version, cannot parse section\n"
+msgstr ""
+
+#: src/readelf.c:10655
+#, fuzzy, c-format
+msgid " Flag:               0x%<PRIx8>"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:10684
+#, c-format
+msgid " Offset length:      %<PRIu8>\n"
+msgstr ""
+
+#: src/readelf.c:10692
+#, c-format
+msgid " .debug_line offset: 0x%<PRIx64>\n"
+msgstr ""
+
+#: src/readelf.c:10717
+#, c-format
+msgid "  extension opcode table, %<PRIu8> items:\n"
+msgstr ""
+
+#: src/readelf.c:10724
+#, c-format
+msgid "    [%<PRIx8>]"
+msgstr ""
+
+#: src/readelf.c:10736
+#, c-format
+msgid " %<PRIu8> arguments:"
+msgstr ""
+
+#: src/readelf.c:10751
+#, c-format
+msgid " no arguments."
+msgstr ""
+
+#: src/readelf.c:10952
+#, c-format
+msgid " [%5d] DIE offset: %6<PRId64>, CU DIE offset: %6<PRId64>, name: %s\n"
+msgstr ""
+
+#: src/readelf.c:11007
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" %*s  String\n"
+msgstr ""
+
+#. TRANS: the debugstr| prefix makes the string unique.
+#: src/readelf.c:11012
+msgctxt "debugstr"
+msgid "Offset"
+msgstr ""
+
+#: src/readelf.c:11022
+#, c-format
+msgid " *** error, missing string terminator\n"
+msgstr ""
+
+#: src/readelf.c:11144
+#, fuzzy, c-format
+msgid " Length:        %8<PRIu64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11146
+#, fuzzy, c-format
+msgid " Offset size:   %8<PRIu8>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11160
+#, fuzzy, c-format
+msgid " DWARF version: %8<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11169
+#, fuzzy, c-format
+msgid " Padding:       %8<PRIx16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11223
+#, c-format
+msgid ""
+"\n"
+"Call frame search table section [%2zu] '.eh_frame_hdr':\n"
+msgstr ""
+
+#: src/readelf.c:11325
+#, c-format
+msgid ""
+"\n"
+"Exception handling table section [%2zu] '.gcc_except_table':\n"
+msgstr ""
+
+#: src/readelf.c:11348
+#, c-format
+msgid " LPStart encoding:    %#x "
+msgstr ""
+
+#: src/readelf.c:11360
+#, c-format
+msgid " TType encoding:      %#x "
+msgstr ""
+
+#: src/readelf.c:11377
+#, c-format
+msgid " Call site encoding:  %#x "
+msgstr ""
+
+#: src/readelf.c:11392
+msgid ""
+"\n"
+" Call site table:"
+msgstr ""
+
+#: src/readelf.c:11408
+#, c-format
+msgid ""
+" [%4u] Call site start:   %#<PRIx64>\n"
+"        Call site length:  %<PRIu64>\n"
+"        Landing pad:       %#<PRIx64>\n"
+"        Action:            %u\n"
+msgstr ""
+
+#: src/readelf.c:11481
+#, c-format
+msgid "invalid TType encoding"
+msgstr ""
+
+#: src/readelf.c:11508
+#, c-format
+msgid ""
+"\n"
+"GDB section [%2zu] '%s' at offset %#<PRIx64> contains %<PRId64> bytes :\n"
+msgstr ""
+
+#: src/readelf.c:11537
+#, fuzzy, c-format
+msgid " Version:         %<PRId32>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11556
+#, c-format
+msgid " CU offset:       %#<PRIx32>\n"
+msgstr ""
+
+#: src/readelf.c:11563
+#, c-format
+msgid " TU offset:       %#<PRIx32>\n"
+msgstr ""
+
+#: src/readelf.c:11570
+#, c-format
+msgid " address offset:  %#<PRIx32>\n"
+msgstr ""
+
+#: src/readelf.c:11577
+#, c-format
+msgid " symbol offset:   %#<PRIx32>\n"
+msgstr ""
+
+#: src/readelf.c:11587
+#, fuzzy, c-format
+msgid " shortcut offset: %#<PRIx32>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11595
+#, c-format
+msgid " constant offset: %#<PRIx32>\n"
+msgstr ""
+
+#: src/readelf.c:11609
+#, c-format
+msgid ""
+"\n"
+" CU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+
+#: src/readelf.c:11634
+#, c-format
+msgid ""
+"\n"
+" TU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+
+#: src/readelf.c:11663
+#, c-format
+msgid ""
+"\n"
+" Address list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+
+#: src/readelf.c:11706
+#, c-format
+msgid ""
+"\n"
+" Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+
+#: src/readelf.c:11791
+#, c-format
+msgid ""
+"\n"
+"Shortcut table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+
+#: src/readelf.c:11803
+#, c-format
+msgid "Language of main: %s\n"
+msgstr ""
+
+#: src/readelf.c:11804
+#, c-format
+msgid "Name of main: "
+msgstr ""
+
+#: src/readelf.c:11887
+#, c-format
+msgid "cannot get debug context descriptor: %s"
+msgstr ""
+
+#: src/readelf.c:12253 src/readelf.c:12873 src/readelf.c:12983
+#: src/readelf.c:13040
+#, c-format
+msgid "cannot convert core note data: %s"
+msgstr ""
+
+#: src/readelf.c:12617
+#, c-format
+msgid ""
+"\n"
+"%*s... <repeats %u more times> ..."
+msgstr ""
+
+#: src/readelf.c:13119
+msgid "  Owner          Data size  Type\n"
+msgstr ""
+
+#: src/readelf.c:13147
+#, c-format
+msgid "  %-13.*s  %9<PRId32>  %s\n"
+msgstr ""
+
+#: src/readelf.c:13199
+#, fuzzy, c-format
+msgid "cannot get content of note: %s"
+msgstr "Konnte Inhalt von %s: %s nicht lesen"
+
+#: src/readelf.c:13232
+#, c-format
+msgid ""
+"\n"
+"Note section [%2zu] '%s' of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:13255
+#, c-format
+msgid ""
+"\n"
+"Note segment of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:13302
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no data to dump.\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:13329 src/readelf.c:13380
+#, fuzzy, c-format
+msgid "cannot get data for section [%zu] '%s': %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:13334
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:13339
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes (%zd uncompressed) at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:13353
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no strings to dump.\n"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/readelf.c:13385
+#, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:13390
+#, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes (%zd uncompressed) at "
+"offset %#0<PRIx64>:\n"
+msgstr ""
+
+#: src/readelf.c:13438
+#, c-format
+msgid ""
+"\n"
+"section [%lu] does not exist"
+msgstr ""
+
+#: src/readelf.c:13468
+#, c-format
+msgid ""
+"\n"
+"section '%s' does not exist"
+msgstr ""
+
+#: src/readelf.c:13523
+#, c-format
+msgid "cannot get symbol index of archive '%s': %s"
+msgstr ""
+
+#: src/readelf.c:13526
+#, c-format
+msgid ""
+"\n"
+"Archive '%s' has no symbol index\n"
+msgstr ""
+
+#: src/readelf.c:13530
+#, c-format
+msgid ""
+"\n"
+"Index of archive '%s' has %zu entries:\n"
+msgstr ""
+
+#: src/readelf.c:13548
+#, fuzzy, c-format
+msgid "cannot extract member at offset %zu in '%s': %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/readelf.c:13553
+#, c-format
+msgid "Archive member '%s' contains:\n"
+msgstr ""
+
+#: src/size.c:55
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  The default "
+"is `bsd'"
+msgstr ""
+
+#: src/size.c:57
+msgid "Same as `--format=sysv'"
+msgstr "Genau wie `--format=sysv'"
+
+#: src/size.c:58
+msgid "Same as `--format=bsd'"
+msgstr "Genau wie `--format=bsd'"
+
+#: src/size.c:61
+msgid "Same as `--radix=10'"
+msgstr "Genau wie `--radix=10'"
+
+#: src/size.c:62
+msgid "Same as `--radix=8'"
+msgstr "Genau wie `--radix=8'"
+
+#: src/size.c:63
+msgid "Same as `--radix=16'"
+msgstr "Genau wie `--radix=16'"
+
+#: src/size.c:65
+msgid "Similar to `--format=sysv' output but in one line"
+msgstr ""
+
+#: src/size.c:69
+msgid "Print size and permission flags for loadable segments"
+msgstr ""
+
+#: src/size.c:70
+msgid "Display the total sizes (bsd only)"
+msgstr ""
+
+#. Short description of program.
+#: src/size.c:75
+msgid "List section sizes of FILEs (a.out by default)."
+msgstr ""
+
+#: src/size.c:239
+#, c-format
+msgid "Invalid format: %s"
+msgstr "Ungültiges Format: %s"
+
+#: src/size.c:250
+#, c-format
+msgid "Invalid radix: %s"
+msgstr ""
+
+#: src/size.c:309
+#, c-format
+msgid "%s: file format not recognized"
+msgstr ""
+
+#: src/size.c:327
+msgctxt "bsd"
+msgid "text"
+msgstr ""
+
+#: src/size.c:328
+msgctxt "bsd"
+msgid "data"
+msgstr ""
+
+#: src/size.c:329
+msgctxt "bsd"
+msgid "bss"
+msgstr ""
+
+#: src/size.c:330
+msgctxt "bsd"
+msgid "dec"
+msgstr ""
+
+#: src/size.c:331
+msgctxt "bsd"
+msgid "hex"
+msgstr ""
+
+#: src/size.c:332
+msgctxt "bsd"
+msgid "filename"
+msgstr ""
+
+#: src/size.c:416 src/size.c:557
+#, c-format
+msgid " (ex %s)"
+msgstr ""
+
+#: src/size.c:418
+#, fuzzy
+#| msgid "invalid section"
+msgctxt "sysv"
+msgid "section"
+msgstr "ungültiger Abschnitt"
+
+#: src/size.c:419
+msgctxt "sysv"
+msgid "size"
+msgstr ""
+
+#: src/size.c:420
+msgctxt "sysv"
+msgid "addr"
+msgstr ""
+
+#: src/size.c:449 src/size.c:452 src/size.c:455
+msgctxt "sysv"
+msgid "Total"
+msgstr ""
+
+#: src/size.c:479
+#, fuzzy
+msgid "cannot get section header"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/size.c:582
+msgid "(TOTALS)\n"
+msgstr ""
+
+#: src/stack.c:487
+#, c-format
+msgid "-p PID should be a positive process id."
+msgstr ""
+
+#: src/stack.c:493
+#, fuzzy, c-format
+msgid "Cannot open core file '%s'"
+msgstr "Konnte Archiv '%s' nicht öffnen"
+
+#: src/stack.c:553
+#, c-format
+msgid "-n MAXFRAMES should be 0 or higher."
+msgstr ""
+
+#: src/stack.c:565
+#, c-format
+msgid "-e EXEC needs a core given by --core."
+msgstr ""
+
+#: src/stack.c:569
+#, c-format
+msgid "-1 needs a thread id given by -p."
+msgstr ""
+
+#: src/stack.c:573
+#, c-format
+msgid "One of -p PID or --core COREFILE should be given."
+msgstr ""
+
+#: src/stack.c:645
+#, fuzzy
+msgid "Show stack of process PID"
+msgstr "Kann Suchbaum nicht erstellen"
+
+#: src/stack.c:647
+msgid "Show stack found in COREFILE"
+msgstr ""
+
+#: src/stack.c:648
+msgid "(optional) EXECUTABLE that produced COREFILE"
+msgstr ""
+
+#: src/stack.c:652
+#, fuzzy
+msgid "Output selection options:"
+msgstr "Eingabeauswahloptionen:"
+
+#: src/stack.c:654
+msgid "Additionally show frame activation"
+msgstr ""
+
+#: src/stack.c:656
+msgid "Additionally try to lookup DWARF debuginfo name for frame address"
+msgstr ""
+
+#: src/stack.c:659
+msgid ""
+"Additionally show inlined function frames using DWARF debuginfo if available "
+"(implies -d)"
+msgstr ""
+
+#: src/stack.c:661
+msgid "Additionally show module file information"
+msgstr ""
+
+#: src/stack.c:663
+msgid "Additionally show source file information"
+msgstr ""
+
+#: src/stack.c:665
+msgid ""
+"Show all additional information (activation, debugname, inlines, module and "
+"source)"
+msgstr ""
+
+#: src/stack.c:667
+msgid "Do not resolve address to function symbol name"
+msgstr ""
+
+#: src/stack.c:669
+msgid "Show raw function symbol names, do not try to demangle names"
+msgstr ""
+
+#: src/stack.c:671
+msgid "Show module build-id, load address and pc offset"
+msgstr ""
+
+#: src/stack.c:673
+msgid "Show the backtrace of only one thread"
+msgstr ""
+
+#: src/stack.c:675
+msgid "Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"
+msgstr ""
+
+#: src/stack.c:677
+msgid "Show module memory map with build-id, elf and debug files detected"
+msgstr ""
+
+#: src/stack.c:685
+msgid ""
+"Print a stack for each thread in a process or core file.\n"
+"\n"
+"Program exits with return code 0 if all frames were shown without any "
+"errors.  If some frames were shown, but there were some non-fatal errors, "
+"possibly causing an incomplete backtrace, the program exits with return code "
+"1.  If no frames could be shown, or a fatal error occurred the program exits "
+"with return code 2.  If the program was invoked with bad or missing "
+"arguments it will exit with return code 64."
+msgstr ""
+
+#: src/stack.c:760
+#, c-format
+msgid "Couldn't show any frames."
+msgstr ""
+
+#: src/strings.c:64
+msgid "Output Selection:"
+msgstr ""
+
+#: src/strings.c:65
+msgid "Scan entire file, not only loaded sections"
+msgstr ""
+
+#: src/strings.c:67
+msgid "Only NUL-terminated sequences of MIN-LEN characters or more are printed"
+msgstr ""
+
+#: src/strings.c:68
+msgid ""
+"Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, "
+"{B,L} = 32-bit"
+msgstr ""
+
+#: src/strings.c:72
+msgid "Print name of the file before each string."
+msgstr ""
+
+#: src/strings.c:74
+msgid "Print location of the string in base 8, 10, or 16 respectively."
+msgstr ""
+
+#: src/strings.c:75
+msgid "Alias for --radix=o"
+msgstr "Alias für --radix=o"
+
+#. Short description of program.
+#: src/strings.c:82
+msgid "Print the strings of printable characters in files."
+msgstr ""
+
+#: src/strings.c:255 src/strings.c:290
+#, c-format
+msgid "invalid value '%s' for %s parameter"
+msgstr ""
+
+#: src/strings.c:300
+msgid "invalid minimum length of matched string size"
+msgstr ""
+
+#: src/strings.c:583
+#, fuzzy
+msgid "lseek failed"
+msgstr "lseek64 fehlgeschlagen"
+
+#: src/strings.c:600 src/strings.c:664
+msgid "re-mmap failed"
+msgstr "re-mmap fehlgeschlagen"
+
+#: src/strings.c:637
+msgid "mprotect failed"
+msgstr "mprotect fehlgeschlagen"
+
+#: src/strings.c:726
+#, c-format
+msgid "Skipping section %zd '%s' data outside file"
+msgstr ""
+
+#: src/strip.c:70
+msgid "Place stripped output into FILE"
+msgstr ""
+
+#: src/strip.c:71
+msgid "Extract the removed sections into FILE"
+msgstr ""
+
+#: src/strip.c:72
+msgid "Embed name FILE instead of -f argument"
+msgstr ""
+
+#: src/strip.c:76
+msgid "Remove all debugging symbols"
+msgstr ""
+
+#: src/strip.c:80
+msgid "Remove section headers (not recommended)"
+msgstr ""
+
+#: src/strip.c:82
+msgid "Copy modified/access timestamps to the output"
+msgstr ""
+
+#: src/strip.c:84
+msgid ""
+"Resolve all trivial relocations between debug sections if the removed "
+"sections are placed in a debug file (only relevant for ET_REL files, "
+"operation is not reversible, needs -f)"
+msgstr ""
+
+#: src/strip.c:86
+msgid ""
+"Similar to --reloc-debug-sections, but resolve all trivial relocations "
+"between debug sections in place.  No other stripping is performed (operation "
+"is not reversible, incompatible with -f, -g, --remove-comment and --remove-"
+"section)"
+msgstr ""
+
+#: src/strip.c:88
+msgid "Remove .comment section"
+msgstr ""
+
+#: src/strip.c:89
+msgid ""
+"Remove the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once.  Only non-allocated sections can be removed."
+msgstr ""
+
+#: src/strip.c:90
+msgid ""
+"Keep the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once."
+msgstr ""
+
+#. Short description of program.
+#: src/strip.c:97
+msgid "Discard symbols from object files."
+msgstr ""
+
+#: src/strip.c:245
+msgid "--reloc-debug-sections used without -f"
+msgstr ""
+
+#: src/strip.c:251
+msgid ""
+"--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --"
+"remove-section"
+msgstr ""
+
+#: src/strip.c:265
+msgid "Only one input file allowed together with '-o' and '-f'"
+msgstr ""
+
+#: src/strip.c:287
+#, c-format
+msgid "-f option specified twice"
+msgstr ""
+
+#: src/strip.c:296
+#, c-format
+msgid "-F option specified twice"
+msgstr ""
+
+#: src/strip.c:359
+#, c-format
+msgid "cannot both keep and remove .comment section"
+msgstr ""
+
+#: src/strip.c:478
+#, fuzzy
+msgid "bad relocation"
+msgstr "Relocations anzeigen"
+
+#: src/strip.c:756 src/strip.c:780
+#, c-format
+msgid "cannot stat input file '%s'"
+msgstr ""
+
+#: src/strip.c:770
+#, c-format
+msgid "while opening '%s'"
+msgstr ""
+
+#: src/strip.c:808
+#, c-format
+msgid "%s: cannot use -o or -f when stripping archive"
+msgstr ""
+
+#. We would like to support ar archives, but currently it just
+#. doesn't work at all since we call elf_clone on the members
+#. which doesn't really support ar members.
+#. result = handle_ar (fd, elf, NULL, fname,
+#. preserve_dates ? tv : NULL);
+#.
+#: src/strip.c:820
+#, fuzzy, c-format
+msgid "%s: no support for stripping archive"
+msgstr "%s: Kein Eintrag %s in dem Archiv!\n"
+
+#: src/strip.c:1057
+#, c-format
+msgid "cannot open EBL backend"
+msgstr ""
+
+#: src/strip.c:1101
+#, fuzzy
+msgid "cannot get number of phdrs"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/strip.c:1115 src/strip.c:1158
+#, fuzzy, c-format
+msgid "cannot create new ehdr for file '%s': %s"
+msgstr "neue Datei konnte nicht angelegt werden"
+
+#: src/strip.c:1125 src/strip.c:1168
+#, fuzzy, c-format
+msgid "cannot create new phdr for file '%s': %s"
+msgstr "neue Datei konnte nicht angelegt werden"
+
+#: src/strip.c:1248
+#, c-format
+msgid "illformed file '%s'"
+msgstr ""
+
+#: src/strip.c:1258
+#, fuzzy, c-format
+msgid "Cannot remove allocated section '%s'"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/strip.c:1267
+#, fuzzy, c-format
+msgid "Cannot both keep and remove section '%s'"
+msgstr "Konnte Archiv '%s' nicht öffnen"
+
+#: src/strip.c:1631 src/strip.c:1746
+#, c-format
+msgid "while generating output file: %s"
+msgstr ""
+
+#: src/strip.c:1695
+#, fuzzy, c-format
+msgid "%s: error while updating ELF header: %s"
+msgstr "Fehler beim Schliessen des Elf-Desktriptor: %s\n"
+
+#: src/strip.c:1704
+#, fuzzy, c-format
+msgid "%s: error while getting shdrstrndx: %s"
+msgstr "Fehler beim Schliessen des Elf-Desktriptor: %s\n"
+
+#: src/strip.c:1712 src/strip.c:2552
+#, fuzzy, c-format
+msgid "%s: error updating shdrstrndx: %s"
+msgstr "Fehler beim Schliessen des Elf-Desktriptor: %s\n"
+
+#: src/strip.c:1729
+#, c-format
+msgid "while preparing output for '%s'"
+msgstr ""
+
+#: src/strip.c:1790 src/strip.c:1852
+#, c-format
+msgid "while create section header section: %s"
+msgstr ""
+
+#: src/strip.c:1799
+#, c-format
+msgid "cannot allocate section data: %s"
+msgstr ""
+
+#: src/strip.c:1863
+#, c-format
+msgid "while create section header string table: %s"
+msgstr ""
+
+#: src/strip.c:1869
+msgid "no memory to create section header string table"
+msgstr ""
+
+#: src/strip.c:2082
+#, c-format
+msgid "Cannot remove symbol [%zd] from allocated symbol table [%zd]"
+msgstr ""
+
+#: src/strip.c:2469 src/strip.c:2574
+#, c-format
+msgid "while writing '%s': %s"
+msgstr ""
+
+#: src/strip.c:2480
+#, c-format
+msgid "while creating '%s'"
+msgstr ""
+
+#: src/strip.c:2503
+#, c-format
+msgid "while computing checksum for debug information"
+msgstr ""
+
+#: src/strip.c:2544
+#, c-format
+msgid "%s: error while creating ELF header: %s"
+msgstr ""
+
+#: src/strip.c:2560
+#, c-format
+msgid "%s: error while reading the file: %s"
+msgstr ""
+
+#: src/strip.c:2599 src/strip.c:2619
+#, fuzzy, c-format
+msgid "while writing '%s'"
+msgstr "beim Schliessen von '%s'"
+
+#: src/strip.c:2656 src/strip.c:2663
+#, c-format
+msgid "error while finishing '%s': %s"
+msgstr ""
+
+#: src/strip.c:2680 src/strip.c:2756
+#, c-format
+msgid "cannot set access and modification date of '%s'"
+msgstr ""
+
+#: src/unstrip.c:65
+msgid "Match MODULE against file names, not module names"
+msgstr ""
+
+#: src/unstrip.c:66
+msgid "Silently skip unfindable files"
+msgstr ""
+
+#: src/unstrip.c:69
+msgid "Place output into FILE"
+msgstr ""
+
+#: src/unstrip.c:71
+msgid "Create multiple output files under DIRECTORY"
+msgstr ""
+
+#: src/unstrip.c:72
+msgid "Use module rather than file names"
+msgstr ""
+
+#: src/unstrip.c:74
+msgid "Create output for modules that have no separate debug information"
+msgstr ""
+
+#: src/unstrip.c:77
+msgid "Apply relocations to section contents in ET_REL files"
+msgstr ""
+
+#: src/unstrip.c:79
+msgid "Only list module and file names, build IDs"
+msgstr ""
+
+#: src/unstrip.c:81
+msgid "Force combining files even if some ELF headers don't seem to match"
+msgstr ""
+
+#: src/unstrip.c:125
+#, c-format
+msgid "-d option specified twice"
+msgstr "Option -d zweimal angegeben"
+
+#: src/unstrip.c:160
+#, c-format
+msgid "only one of -o or -d allowed"
+msgstr "nur entweder -o oder -d erlaubt"
+
+#: src/unstrip.c:169
+#, c-format
+msgid "-n cannot be used with explicit files or -o or -d"
+msgstr "-n kann nicht mit expliziten Dateien oder -o oder -d verwendet werden"
+
+#: src/unstrip.c:184
+#, c-format
+msgid "output directory '%s'"
+msgstr "Ausgabeverzeichnis '%s'"
+
+#: src/unstrip.c:193
+#, c-format
+msgid "exactly two file arguments are required"
+msgstr "genau zwei Datei-Argumente werden benötigt"
+
+#: src/unstrip.c:199
+#, c-format
+msgid "-m, -a, -R, and -i options not allowed with explicit files"
+msgstr ""
+
+#: src/unstrip.c:212
+#, c-format
+msgid "-o or -d is required when using implicit files"
+msgstr ""
+
+#: src/unstrip.c:235
+#, c-format
+msgid "cannot create ELF header: %s"
+msgstr ""
+
+#: src/unstrip.c:239
+#, fuzzy, c-format
+msgid "cannot get shdrstrndx:%s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:243 src/unstrip.c:2136
+#, c-format
+msgid "cannot get ELF header: %s"
+msgstr ""
+
+#: src/unstrip.c:253
+#, fuzzy, c-format
+msgid "cannot get new zero section: %s"
+msgstr "konnte Versionierungsabschnitt nicht erstellen: %s"
+
+#: src/unstrip.c:256
+#, fuzzy, c-format
+msgid "cannot update new zero section: %s"
+msgstr "konnte Versionierungsabschnitt nicht erstellen: %s"
+
+#: src/unstrip.c:260
+#, c-format
+msgid "cannot copy ELF header: %s"
+msgstr ""
+
+#: src/unstrip.c:264 src/unstrip.c:2154 src/unstrip.c:2197
+#, fuzzy, c-format
+msgid "cannot get number of program headers: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/unstrip.c:269 src/unstrip.c:2158
+#, c-format
+msgid "cannot create program headers: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/unstrip.c:275
+#, c-format
+msgid "cannot copy program header: %s"
+msgstr "konnte Programm-Kopf nicht kopieren: %s"
+
+#: src/unstrip.c:285
+#, c-format
+msgid "cannot copy section header: %s"
+msgstr ""
+
+#: src/unstrip.c:288 src/unstrip.c:1748
+#, c-format
+msgid "cannot get section data: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:290 src/unstrip.c:1750
+#, c-format
+msgid "cannot copy section data: %s"
+msgstr "konnte Abschnittsdaten nicht kopieren: %s"
+
+#: src/unstrip.c:318
+#, c-format
+msgid "cannot create directory '%s'"
+msgstr "konnte Verzeichnis nicht erstellen: %s"
+
+#: src/unstrip.c:392 src/unstrip.c:666 src/unstrip.c:700 src/unstrip.c:868
+#: src/unstrip.c:1790
+#, c-format
+msgid "cannot get symbol table entry: %s"
+msgstr "konnte Eintrag aus der Symboltabelle nicht holen: %s"
+
+#: src/unstrip.c:408 src/unstrip.c:669 src/unstrip.c:690 src/unstrip.c:703
+#: src/unstrip.c:1811 src/unstrip.c:2007 src/unstrip.c:2031
+#, c-format
+msgid "cannot update symbol table: %s"
+msgstr "konnte Symboltabelle nicht aktualisieren: %s"
+
+#: src/unstrip.c:418
+#, c-format
+msgid "cannot update section header: %s"
+msgstr ""
+
+#: src/unstrip.c:464
+#, c-format
+msgid "gelf_getrel failed: %s"
+msgstr ""
+
+#: src/unstrip.c:467 src/unstrip.c:482
+#, c-format
+msgid "cannot update relocation: %s"
+msgstr ""
+
+#: src/unstrip.c:479
+#, c-format
+msgid "gelf_getrela failed: %s"
+msgstr ""
+
+#: src/unstrip.c:580
+#, c-format
+msgid "cannot get symbol version: %s"
+msgstr ""
+
+#: src/unstrip.c:593
+#, c-format
+msgid "unexpected section type in [%zu] with sh_link to symtab"
+msgstr ""
+
+#: src/unstrip.c:857
+#, fuzzy, c-format
+msgid "cannot get symbol section data: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:859
+#, fuzzy, c-format
+msgid "cannot get string section data: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:876
+#, fuzzy, c-format
+msgid "invalid string offset in symbol [%zu]"
+msgstr "ungültiger Offset %zu für Symbol %s"
+
+#: src/unstrip.c:939
+msgid "found two identical index map positions."
+msgstr ""
+
+#: src/unstrip.c:990
+msgid "section symbols in unexpected order"
+msgstr ""
+
+#: src/unstrip.c:996
+#, fuzzy
+#| msgid "Display only defined symbols"
+msgid "found two identical symbols"
+msgstr "Zeige nur definierte Symbole"
+
+#: src/unstrip.c:1066 src/unstrip.c:1474
+#, fuzzy, c-format
+msgid "cannot read section [%zu] name: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:1081
+#, fuzzy, c-format
+msgid "bad sh_link for group section: %s"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/unstrip.c:1087
+#, fuzzy, c-format
+msgid "couldn't get shdr for group section: %s"
+msgstr "konnte Versionierungsabschnitt nicht erstellen: %s"
+
+#: src/unstrip.c:1092
+#, fuzzy, c-format
+msgid "bad data for group symbol section: %s"
+msgstr "ungültige .debug_line Sektion"
+
+#: src/unstrip.c:1098
+#, fuzzy, c-format
+msgid "couldn't get symbol for group section: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/unstrip.c:1103
+#, fuzzy, c-format
+msgid "bad symbol name for group section: %s"
+msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#: src/unstrip.c:1114 src/unstrip.c:1594
+#, fuzzy, c-format
+msgid "cannot find matching section for [%zu] '%s'"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:1159 src/unstrip.c:1178 src/unstrip.c:1216
+#, c-format
+msgid "cannot read '.gnu.prelink_undo' section: %s"
+msgstr ""
+
+#: src/unstrip.c:1196
+#, c-format
+msgid "overflow with shnum = %zu in '%s' section"
+msgstr ""
+
+#: src/unstrip.c:1207
+#, c-format
+msgid "invalid contents in '%s' section"
+msgstr ""
+
+#: src/unstrip.c:1378 src/unstrip.c:1394 src/unstrip.c:1674 src/unstrip.c:1966
+#, c-format
+msgid "cannot add section name to string table: %s"
+msgstr ""
+
+#: src/unstrip.c:1403
+#, c-format
+msgid "cannot update section header string table data: %s"
+msgstr ""
+
+#: src/unstrip.c:1432 src/unstrip.c:1436
+#, c-format
+msgid "cannot get section header string table section index: %s"
+msgstr ""
+
+#: src/unstrip.c:1440 src/unstrip.c:1444 src/unstrip.c:1689
+#, c-format
+msgid "cannot get section count: %s"
+msgstr ""
+
+#: src/unstrip.c:1447
+msgid "more sections in stripped file than debug file -- arguments reversed?"
+msgstr ""
+
+#: src/unstrip.c:1451
+msgid "no sections in stripped file"
+msgstr ""
+
+#: src/unstrip.c:1499 src/unstrip.c:1609
+#, c-format
+msgid "cannot read section header string table: %s"
+msgstr ""
+
+#: src/unstrip.c:1668
+#, c-format
+msgid "cannot add new section: %s"
+msgstr ""
+
+#: src/unstrip.c:1798
+#, fuzzy, c-format
+msgid "symbol [%zu] has invalid section index"
+msgstr "ungültiger Abschnittsindex"
+
+#: src/unstrip.c:1830
+#, fuzzy, c-format
+msgid "group has invalid section index [%zd]"
+msgstr "ungültiger Abschnittsindex"
+
+#: src/unstrip.c:2115
+#, fuzzy, c-format
+msgid "cannot read section data: %s"
+msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#: src/unstrip.c:2144
+#, c-format
+msgid "cannot update ELF header: %s"
+msgstr ""
+
+#: src/unstrip.c:2168
+#, c-format
+msgid "cannot update program header: %s"
+msgstr "konnte Programm-Kopf nicht aktualisieren: %s"
+
+#: src/unstrip.c:2173 src/unstrip.c:2256
+#, c-format
+msgid "cannot write output file: %s"
+msgstr ""
+
+#: src/unstrip.c:2224
+#, c-format
+msgid "DWARF data not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+
+#: src/unstrip.c:2227
+#, c-format
+msgid ""
+"DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+
+#: src/unstrip.c:2247 src/unstrip.c:2299 src/unstrip.c:2311 src/unstrip.c:2401
+#, c-format
+msgid "cannot create ELF descriptor: %s"
+msgstr ""
+
+#: src/unstrip.c:2285
+msgid "WARNING: "
+msgstr ""
+
+#: src/unstrip.c:2287
+msgid ", use --force"
+msgstr ""
+
+#: src/unstrip.c:2315
+msgid "ELF header identification (e_ident) different"
+msgstr ""
+
+#: src/unstrip.c:2319
+msgid "ELF header type (e_type) different"
+msgstr ""
+
+#: src/unstrip.c:2323
+msgid "ELF header machine type (e_machine) different"
+msgstr ""
+
+#: src/unstrip.c:2327
+msgid "stripped program header (e_phnum) smaller than unstripped"
+msgstr ""
+
+#: src/unstrip.c:2358
+#, c-format
+msgid "cannot find stripped file for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2362
+#, c-format
+msgid "cannot open stripped file '%s' for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2377
+#, c-format
+msgid "cannot find debug file for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2381
+#, c-format
+msgid "cannot open debug file '%s' for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2394
+#, c-format
+msgid "module '%s' file '%s' is not stripped"
+msgstr ""
+
+#: src/unstrip.c:2425
+#, c-format
+msgid "cannot cache section addresses for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2553
+msgid "no matching modules found"
+msgstr "kein passendes Modul gefunden"
+
+#: src/unstrip.c:2563
+msgid "matched more than one module"
+msgstr "mehr als ein passendes Modul"
+
+#: src/unstrip.c:2608
+msgid ""
+"STRIPPED-FILE DEBUG-FILE\n"
+"[MODULE...]"
+msgstr ""
+
+#: src/unstrip.c:2609
+msgid ""
+"Combine stripped files with separate symbols and debug information.\n"
+"\n"
+"The first form puts the result in DEBUG-FILE if -o was not given.\n"
+"\n"
+"MODULE arguments give file name patterns matching modules to process.\n"
+"With -f these match the file name of the main (stripped) file (slashes are "
+"never special), otherwise they match the simple module names.  With no "
+"arguments, process all modules found.\n"
+"\n"
+"Multiple modules are written to files under OUTPUT-DIRECTORY, creating "
+"subdirectories as needed.  With -m these files have simple module names, "
+"otherwise they have the name of the main file complete with directory "
+"underneath OUTPUT-DIRECTORY.\n"
+"\n"
+"With -n no files are written, but one line to standard output for each "
+"module:\n"
+"\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n"
+"START and SIZE are hexadecimal giving the address bounds of the module.  "
+"BUILDID is hexadecimal for the build ID bits, or - if no ID is known; the "
+"hexadecimal may be followed by @0xADDR giving the address where the ID "
+"resides if that is known.  FILE is the file name found for the module, or - "
+"if none was found, or . if an ELF image is available but not from any named "
+"file.  DEBUGFILE is the separate debuginfo file name, or - if no debuginfo "
+"was found, or . if FILE contains the debug information."
+msgstr ""
+
+#. Short description of program.
+#: debuginfod/debuginfod-find.c:42
+msgid "Request debuginfo-related content from debuginfods listed in $"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: debuginfod/debuginfod-find.c:46
+msgid ""
+"debuginfo BUILDID\n"
+"debuginfo PATH\n"
+"executable BUILDID\n"
+"executable PATH\n"
+"source BUILDID /FILENAME\n"
+"source PATH /FILENAME\n"
+"section BUILDID SECTION-NAME\n"
+"section PATH SECTION-NAME\n"
+msgstr ""
+
+#: tests/backtrace.c:491
+msgid "Run executable"
+msgstr ""
+
+#: tests/dwflmodtest.c:209
+msgid "Additionally show function names"
+msgstr ""
+
+#: tests/dwflmodtest.c:210
+msgid "Show instances of inlined functions"
+msgstr ""
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_addr section data: %s"
+#~ msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_rnglists content: %s"
+#~ msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_loclists content: %s"
+#~ msgstr "konnte Eintrag aus der Symboltabelle nicht holen: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_str_offsets section data: %s"
+#~ msgstr "konnte Abschnittsdaten nicht holen: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot allocate memory"
+#~ msgstr "konnte Verzeichnis nicht erstellen: %s"
+
+#~ msgid "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#<PRIx64> <%s>"
+#~ msgstr "%s+%#<PRIx64> <%s>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s>"
+#~ msgstr "%s+%#0*<PRIx64> <%s>"
+
+#~ msgid "%#<PRIx64> <%s>"
+#~ msgstr "%#<PRIx64> <%s>"
+
+#~ msgid "%#0*<PRIx64> <%s>"
+#~ msgstr "%#0*<PRIx64> <%s>"
+
+#~ msgid "%s+%#<PRIx64>"
+#~ msgstr "%s+%#<PRIx64>"
+
+#~ msgid "%s+%#0*<PRIx64>"
+#~ msgstr "%s+%#0*<PRIx64>"
+
+#, fuzzy
+#~ msgid "   %s..%s (%<PRIx64>)\n"
+#~ msgstr "      %s: %<PRId64>\n"
+
+#, fuzzy
+#~ msgid "   %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#~ msgid " [%6tx]  %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#~ msgid "           %s..%s\n"
+#~ msgstr "           %s..%s\n"
+
+#~ msgid " [%6tx]  %s..%s"
+#~ msgstr " [%6tx]  %s..%s"
+
+#~ msgid "           %s..%s"
+#~ msgstr "           %s..%s"
+
+#~ msgid "Written by %s.\n"
+#~ msgstr "Geschrieben von %s.\n"
+
+#~ msgid "FILE"
+#~ msgstr "DATEI"
+
+#~ msgid "Start a group."
+#~ msgstr "Eine Gruppe starten."
+
+#~ msgid "End a group."
+#~ msgstr "Eine Gruppe beenden."
+
+#~ msgid "PATH"
+#~ msgstr "PFAD"
+
+#~ msgid "Same as --whole-archive."
+#~ msgstr "Genau wie --whole-archive."
+
+#~ msgid "ADDRESS"
+#~ msgstr "ADRESSE"
+
+#~ msgid "[FILE]..."
+#~ msgstr "[DATEI]..."
+
+#~ msgid "At least one input file needed"
+#~ msgstr "Mindestens eine Eingabedatei benötigt"
+
+#~ msgid "-( without matching -)"
+#~ msgstr "-( ohne Übereinstimmung -)"
+
+#~ msgid "only one option of -G and -r is allowed"
+#~ msgstr "nur eine Option aus -G und -r erlaubt"
+
+#~ msgid "-) without matching -("
+#~ msgstr "-) ohne Übereinstimmung -("
+
+#~ msgid "unknown option '-%c %s'"
+#~ msgstr "unbekannte Option '-%c %s'"
+
+#~ msgid "undefined symbol `%s' in %s"
+#~ msgstr "undefiniertes Symbol `%s' in %s"
+
+#~ msgid "cannot create versioning data: %s"
+#~ msgstr "konnte Versionierungsdaten nicht erstellen: %s"
+
+#~ msgid "cannot create program header: %s"
+#~ msgstr "konnte Programm-Kopf nicht erstellen: %s"
+
+#~ msgid "default visibility set as local and global"
+#~ msgstr "Standard-Sichtbarkeit auf lokal und global gesetzt"
+
+#, fuzzy
+#~ msgid "cannot attach to core"
+#~ msgstr "Kann Suchbaum nicht erstellen"
+
+#~ msgid "unknown tag %hx"
+#~ msgstr "unbekannter Tag %hx"
+
+#~ msgid "unknown user tag %hx"
+#~ msgstr "unbekannter Benutzer-Tag %hx"
+
+#~ msgid "unknown attribute %hx"
+#~ msgstr "unbekanntes Attribut %hx"
+
+#~ msgid "unknown user attribute %hx"
+#~ msgstr "unbekanntes Benutzer-Attribut %hx"
+
+#~ msgid ""
+#~ "\n"
+#~ "\n"
+#~ "Symbols from %s[%s]:\n"
+#~ "\n"
+#~ msgstr ""
+#~ "\n"
+#~ "\n"
+#~ "Symbole aus %s[%s]:\n"
+#~ "\n"
+
+#~ msgid "Equivalent to: -e -h -l"
+#~ msgstr "Entspricht: -e -h -l"
diff --git a/po/es.po b/po/es.po
new file mode 100644
index 0000000..76efc24
--- /dev/null
+++ b/po/es.po
@@ -0,0 +1,8214 @@
+# Fedora Spanish Translation of elfutils
+# This file is distributed under the same license as the elfutils package.
+#
+# Domingo Becker <domingobecker@gmail.com>, 2009.
+# Gladys Guerrero Lozano <gguerrer@redhat.com>, 2009.
+# Héctor Daniel Cabrera <logan@fedoraproject.org>, 2009, 2010.
+# Claudio Rodrigo Pereyra Diaz <claudio@pereyradiaz.com.ar>, 2010.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: elfutils\n"
+"Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n"
+"POT-Creation-Date: 2024-03-01 10:22-0500\n"
+"PO-Revision-Date: 2011-01-10 15:17-0300\n"
+"Last-Translator: Claudio Rodrigo Pereyra Diaz <claudiorodrigo@pereyradiaz."
+"com.ar>\n"
+"Language-Team: Fedora Spanish <trans-es@lists.fedoraproject.org>\n"
+"Language: es\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Poedit-Language: Spanish\n"
+"X-Generator: Lokalize 1.0\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+"X-Poedit-Country: ARGENTINA\n"
+
+#: lib/color.c:51
+msgid ""
+"colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"
+msgstr ""
+
+#: lib/color.c:127
+#, c-format
+msgid ""
+"%s: invalid argument '%s' for '--color'\n"
+"valid arguments are:\n"
+"  - 'always', 'yes', 'force'\n"
+"  - 'never', 'no', 'none'\n"
+"  - 'auto', 'tty', 'if-tty'\n"
+msgstr ""
+
+#: lib/printversion.c:39
+#, fuzzy, c-format
+msgid ""
+"Copyright (C) %s The elfutils developers <%s>.\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+msgstr ""
+"Copyright (C) %s Red Hat, Inc.\n"
+"El siguiente es un software libre; consulte el código para conocer las "
+"condiciones de copiado. NO tiene\n"
+"garantía, ni siquiera para SU COMERCIALIZACIÓN o PARA SER USADO CON UN FIN "
+"DETERMINADO.\n"
+
+#: lib/xmalloc.c:47 lib/xmalloc.c:60 lib/xmalloc.c:72 src/readelf.c:12203
+#: src/unstrip.c:311
+#, c-format
+msgid "memory exhausted"
+msgstr "memoria agotada"
+
+#: libasm/asm_error.c:64 libdw/dwarf_error.c:57 libdwfl/libdwflP.h:47
+#: libelf/elf_error.c:59
+msgid "no error"
+msgstr "ningún error"
+
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:49
+#: libelf/elf_error.c:90
+msgid "out of memory"
+msgstr "memoria agotada"
+
+#: libasm/asm_error.c:66
+msgid "cannot create output file"
+msgstr "no se puede crear el archivo de salida"
+
+#: libasm/asm_error.c:67
+msgid "invalid parameter"
+msgstr "Parámetro inválido"
+
+#: libasm/asm_error.c:68
+msgid "cannot change mode of output file"
+msgstr "no sepuede cambiar modo de archivo de salida"
+
+#: libasm/asm_error.c:69
+msgid "cannot rename output file"
+msgstr "no se puede renombrar el archivo de salida"
+
+#: libasm/asm_error.c:70
+msgid "duplicate symbol"
+msgstr "Duplicar símbolo"
+
+#: libasm/asm_error.c:71
+msgid "invalid section type for operation"
+msgstr "tipo de sección inválido para operación"
+
+#: libasm/asm_error.c:72
+msgid "error during output of data"
+msgstr "error durante salida de datos"
+
+#: libasm/asm_error.c:73
+msgid "no backend support available"
+msgstr "No hay soporte de segundo plano"
+
+#: libasm/asm_error.c:82 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:48
+#: libelf/elf_error.c:62
+msgid "unknown error"
+msgstr "error desconocido"
+
+#: libcpu/i386_lex.l:121
+#, fuzzy, c-format
+#| msgid "invalid page size value '%s': ignored"
+msgid "invalid character '%c' at line %d; ignored"
+msgstr "Valor de tamaño de página'%s': ignorado"
+
+#: libcpu/i386_lex.l:122
+#, fuzzy, c-format
+#| msgid "invalid page size value '%s': ignored"
+msgid "invalid character '\\%o' at line %d; ignored"
+msgstr "Valor de tamaño de página'%s': ignorado"
+
+#: libcpu/i386_parse.y:555
+#, fuzzy, c-format
+#| msgid "while reading linker script '%s': %s at line %d"
+msgid "while reading i386 CPU description: %s at line %d"
+msgstr "al leer script de enlace '%s': %s en línea %d"
+
+#: libdw/dwarf_error.c:59
+msgid "invalid access"
+msgstr "Acceso inválido"
+
+#: libdw/dwarf_error.c:60
+msgid "no regular file"
+msgstr "no es un archivo regular"
+
+#: libdw/dwarf_error.c:61
+msgid "I/O error"
+msgstr "Error de E/S"
+
+#: libdw/dwarf_error.c:62
+msgid "invalid ELF file"
+msgstr "Archivo ELF inválido"
+
+#: libdw/dwarf_error.c:63
+msgid "no DWARF information"
+msgstr "Sin información de DWARF"
+
+#: libdw/dwarf_error.c:64
+msgid "cannot decompress DWARF"
+msgstr ""
+
+#: libdw/dwarf_error.c:65
+msgid "no ELF file"
+msgstr "No hay archivo ELF"
+
+#: libdw/dwarf_error.c:66
+msgid "cannot get ELF header"
+msgstr "no se puede obtener el encabezamiento ELF"
+
+#: libdw/dwarf_error.c:68
+msgid "not implemented"
+msgstr "sin implementar"
+
+#: libdw/dwarf_error.c:69 libelf/elf_error.c:110 libelf/elf_error.c:158
+msgid "invalid command"
+msgstr "comando inválido"
+
+#: libdw/dwarf_error.c:70
+msgid "invalid version"
+msgstr "versión inválida"
+
+#: libdw/dwarf_error.c:71
+msgid "invalid file"
+msgstr "Archivo inválido"
+
+#: libdw/dwarf_error.c:72
+msgid "no entries found"
+msgstr "No se hallaron entradas"
+
+#: libdw/dwarf_error.c:73
+msgid "invalid DWARF"
+msgstr "DWARF inválido"
+
+#: libdw/dwarf_error.c:74
+msgid "no string data"
+msgstr "no hay datos de cadena"
+
+#: libdw/dwarf_error.c:75
+#, fuzzy
+msgid ".debug_str section missing"
+msgstr ".debug_ranges section faltante"
+
+#: libdw/dwarf_error.c:76
+#, fuzzy
+msgid ".debug_line_str section missing"
+msgstr ".debug_line section faltante"
+
+#: libdw/dwarf_error.c:77
+#, fuzzy
+msgid ".debug_str_offsets section missing"
+msgstr ".debug_ranges section faltante"
+
+#: libdw/dwarf_error.c:78
+msgid "no address value"
+msgstr "no hay valor de dirección"
+
+#: libdw/dwarf_error.c:79
+msgid "no constant value"
+msgstr "no hay valor constante"
+
+#: libdw/dwarf_error.c:80
+msgid "no reference value"
+msgstr "no hay valor de referencia"
+
+#: libdw/dwarf_error.c:81
+msgid "invalid reference value"
+msgstr "valor de la referencia inválido"
+
+#: libdw/dwarf_error.c:82
+msgid ".debug_line section missing"
+msgstr ".debug_line section faltante"
+
+#: libdw/dwarf_error.c:83
+msgid "invalid .debug_line section"
+msgstr ".debug_line section inválida"
+
+#: libdw/dwarf_error.c:84
+msgid "debug information too big"
+msgstr "información de depuración muy grande"
+
+#: libdw/dwarf_error.c:85
+msgid "invalid DWARF version"
+msgstr "versión DWARF inválida"
+
+#: libdw/dwarf_error.c:86
+msgid "invalid directory index"
+msgstr "Índice de directorio inválido"
+
+#: libdw/dwarf_error.c:87 libdwfl/libdwflP.h:69
+msgid "address out of range"
+msgstr "dirección fuera de rango"
+
+#: libdw/dwarf_error.c:88
+#, fuzzy
+msgid ".debug_loc section missing"
+msgstr ".debug_line section faltante"
+
+#: libdw/dwarf_error.c:89
+#, fuzzy
+msgid ".debug_loclists section missing"
+msgstr ".debug_line section faltante"
+
+#: libdw/dwarf_error.c:90
+#, fuzzy
+msgid "not a location list value"
+msgstr "valor de lista sin ubicación"
+
+#: libdw/dwarf_error.c:91
+msgid "no block data"
+msgstr "sin datos de bloque "
+
+#: libdw/dwarf_error.c:92
+msgid "invalid line index"
+msgstr "Índice de línea inválido"
+
+#: libdw/dwarf_error.c:93
+msgid "invalid address range index"
+msgstr "Índice de dirección de rango inválido"
+
+#: libdw/dwarf_error.c:94 libdwfl/libdwflP.h:70
+msgid "no matching address range"
+msgstr "dirección de rango no coincidente"
+
+#: libdw/dwarf_error.c:95
+msgid "no flag value"
+msgstr "sin valor de bandera"
+
+#: libdw/dwarf_error.c:96 libelf/elf_error.c:235
+msgid "invalid offset"
+msgstr "desplazamiento inválido"
+
+#: libdw/dwarf_error.c:97
+msgid ".debug_ranges section missing"
+msgstr ".debug_ranges section faltante"
+
+#: libdw/dwarf_error.c:98
+#, fuzzy
+msgid ".debug_rnglists section missing"
+msgstr ".debug_ranges section faltante"
+
+#: libdw/dwarf_error.c:99
+msgid "invalid CFI section"
+msgstr "sección CFI inválida"
+
+#: libdw/dwarf_error.c:100
+msgid "no alternative debug link found"
+msgstr ""
+
+#: libdw/dwarf_error.c:101
+#, fuzzy
+msgid "invalid opcode"
+msgstr "operando inválido"
+
+#: libdw/dwarf_error.c:102
+msgid "not a CU (unit) DIE"
+msgstr ""
+
+#: libdw/dwarf_error.c:103
+#, fuzzy
+msgid "unknown language code"
+msgstr "código operativo desconocido "
+
+#: libdw/dwarf_error.c:104
+#, fuzzy
+msgid ".debug_addr section missing"
+msgstr ".debug_ranges section faltante"
+
+#: libdw/dwarf_error.c:105
+#, fuzzy
+#| msgid "unknown version"
+msgid "unknown section"
+msgstr "versión desconocida"
+
+#: libdwfl/argp-std.c:45 src/stack.c:643 src/unstrip.c:2598
+msgid "Input selection options:"
+msgstr "Opciones de selección de entrada:"
+
+#: libdwfl/argp-std.c:46
+msgid "Find addresses in FILE"
+msgstr "Hallar direcciones en FICHERO"
+
+#: libdwfl/argp-std.c:48
+msgid "Find addresses from signatures found in COREFILE"
+msgstr "Buscar direcciones desde firmas encontradas en COREFILE"
+
+#: libdwfl/argp-std.c:50
+msgid "Find addresses in files mapped into process PID"
+msgstr "Busca direcciones en archivos mapeados sobre procesos PID"
+
+#: libdwfl/argp-std.c:52
+msgid ""
+"Find addresses in files mapped as read from FILE in Linux /proc/PID/maps "
+"format"
+msgstr ""
+"Busca direcciones en archivos asignados como leídos desde FILE en formato "
+"Linux /proc/PID/maps"
+
+#: libdwfl/argp-std.c:54
+msgid "Find addresses in the running kernel"
+msgstr "Busca direcciones en el kernel que está ejecutándose"
+
+#: libdwfl/argp-std.c:56
+msgid "Kernel with all modules"
+msgstr "Kernel con todos los módulos"
+
+#: libdwfl/argp-std.c:58 src/stack.c:650
+msgid "Search path for separate debuginfo files"
+msgstr "Ruta de búsqueda para archivos debugingfo independientes"
+
+#: libdwfl/argp-std.c:159
+msgid "only one of -e, -p, -k, -K, or --core allowed"
+msgstr "Sólo uno de -e, -p, -k, -K, ó --core está permitido"
+
+#: libdwfl/argp-std.c:232
+msgid "cannot load kernel symbols"
+msgstr "No se pueden cargar símbolos de kernel"
+
+#. Non-fatal to have no modules since we do have the kernel.
+#: libdwfl/argp-std.c:236
+msgid "cannot find kernel modules"
+msgstr "no se pueden hallar módulos de kernel"
+
+#: libdwfl/argp-std.c:253
+msgid "cannot find kernel or modules"
+msgstr "imposible encontrar kernel o módulos"
+
+#: libdwfl/argp-std.c:292
+#, c-format
+msgid "cannot read ELF core file: %s"
+msgstr "No se puede leer archivo core ELF: %s"
+
+#: libdwfl/argp-std.c:315
+#, fuzzy
+msgid "Not enough memory"
+msgstr "memoria agotada"
+
+#: libdwfl/argp-std.c:325
+msgid "No modules recognized in core file"
+msgstr "No hay módulos reconocidos en el archivo core"
+
+#: libdwfl/libdwflP.h:50
+msgid "See errno"
+msgstr "Ve errno"
+
+#: libdwfl/libdwflP.h:51
+msgid "See elf_errno"
+msgstr "Ver elf_errno"
+
+#: libdwfl/libdwflP.h:52
+msgid "See dwarf_errno"
+msgstr "Ver dwarf_errno"
+
+#: libdwfl/libdwflP.h:53
+msgid "See ebl_errno (XXX missing)"
+msgstr "Ver ebl_errno (no se encuentra XXX)"
+
+#: libdwfl/libdwflP.h:54
+msgid "gzip decompression failed"
+msgstr "falló la descompresión gzip"
+
+#: libdwfl/libdwflP.h:55
+msgid "bzip2 decompression failed"
+msgstr "falló la descompresión bzip2"
+
+#: libdwfl/libdwflP.h:56
+msgid "LZMA decompression failed"
+msgstr "falló la descompresión LZMA"
+
+#: libdwfl/libdwflP.h:57
+#, fuzzy
+msgid "zstd decompression failed"
+msgstr "falló la descompresión gzip"
+
+#: libdwfl/libdwflP.h:58
+msgid "no support library found for machine"
+msgstr "no se ha encontrado una biblioteca de soporte para la máquina"
+
+#: libdwfl/libdwflP.h:59
+msgid "Callbacks missing for ET_REL file"
+msgstr "No se encuentran rellamadas para el archivo ET_REL"
+
+#: libdwfl/libdwflP.h:60
+msgid "Unsupported relocation type"
+msgstr "Tipo de reubicación no soportada"
+
+#: libdwfl/libdwflP.h:61
+msgid "r_offset is bogus"
+msgstr "r_offset se encuentra inutilizable"
+
+#: libdwfl/libdwflP.h:62 libelf/elf_error.c:114 libelf/elf_error.c:174
+msgid "offset out of range"
+msgstr "desplazamiento fuera de rango"
+
+#: libdwfl/libdwflP.h:63
+msgid "relocation refers to undefined symbol"
+msgstr "la reubicación hace referencia a un símbolo no definido"
+
+#: libdwfl/libdwflP.h:64
+msgid "Callback returned failure"
+msgstr "La rellamada devolvió un fallo"
+
+#: libdwfl/libdwflP.h:65
+msgid "No DWARF information found"
+msgstr "No se ha encontrado una información DWARF"
+
+#: libdwfl/libdwflP.h:66
+msgid "No symbol table found"
+msgstr "No se ha encontrado una tabla simbólica"
+
+#: libdwfl/libdwflP.h:67
+msgid "No ELF program headers"
+msgstr "No existen encabezados de programa ELF"
+
+#: libdwfl/libdwflP.h:68
+msgid "address range overlaps an existing module"
+msgstr "el rango de dirección se superpone con un módulo existente"
+
+#: libdwfl/libdwflP.h:71
+msgid "image truncated"
+msgstr "imagen truncada"
+
+#: libdwfl/libdwflP.h:72
+msgid "ELF file opened"
+msgstr "Archivo ELF abierto"
+
+#: libdwfl/libdwflP.h:73
+msgid "not a valid ELF file"
+msgstr "no es un archivo ELF válido"
+
+#: libdwfl/libdwflP.h:74
+msgid "cannot handle DWARF type description"
+msgstr "no es posible manipular tipo de descripción DWARF"
+
+#: libdwfl/libdwflP.h:75
+msgid "ELF file does not match build ID"
+msgstr "El archivo ELF no coincide con el ID construido"
+
+#: libdwfl/libdwflP.h:76
+#, fuzzy
+msgid "corrupt .gnu.prelink_undo section data"
+msgstr "no se puede leer sección '.gnu.prelink_undo': %s"
+
+#: libdwfl/libdwflP.h:77
+msgid "Internal error due to ebl"
+msgstr ""
+
+#: libdwfl/libdwflP.h:78
+msgid "Missing data in core file"
+msgstr ""
+
+#: libdwfl/libdwflP.h:79
+#, fuzzy
+msgid "Invalid register"
+msgstr "Parámetro inválido"
+
+#: libdwfl/libdwflP.h:80
+#, fuzzy
+#| msgid "no reference value"
+msgid "Unknown register value"
+msgstr "no hay valor de referencia"
+
+#: libdwfl/libdwflP.h:81
+msgid "Error reading process memory"
+msgstr ""
+
+#: libdwfl/libdwflP.h:82
+msgid "Couldn't find architecture of any ELF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:83
+msgid "Error parsing /proc filesystem"
+msgstr ""
+
+#: libdwfl/libdwflP.h:84
+#, fuzzy
+msgid "Invalid DWARF"
+msgstr "DWARF inválido"
+
+#: libdwfl/libdwflP.h:85
+msgid "Unsupported DWARF"
+msgstr ""
+
+#: libdwfl/libdwflP.h:86
+msgid "Unable to find more threads"
+msgstr ""
+
+#: libdwfl/libdwflP.h:87
+msgid "Dwfl already has attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:88
+msgid "Dwfl has no attached state"
+msgstr ""
+
+#: libdwfl/libdwflP.h:89
+msgid "Unwinding not supported for this architecture"
+msgstr ""
+
+#: libdwfl/libdwflP.h:90
+#, fuzzy
+msgid "Invalid argument"
+msgstr "Parámetro inválido"
+
+#: libdwfl/libdwflP.h:91
+#, fuzzy
+msgid "Not an ET_CORE ELF file"
+msgstr "no es un archivo ELF válido"
+
+#: libebl/eblbackendname.c:41
+msgid "No backend"
+msgstr "No hay segundo plano (Backend)"
+
+#: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:79
+#: libebl/eblobjnotetypename.c:113 libebl/eblobjnotetypename.c:134
+#: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83
+#: libebl/eblsectiontypename.c:116 libebl/eblsegmenttypename.c:81
+msgid "<unknown>"
+msgstr "<desconocido>"
+
+#: libebl/ebldynamictagname.c:103
+#, c-format
+msgid "<unknown>: %#<PRIx64>"
+msgstr "<desconocido>: %#<PRIx64>"
+
+#: libebl/eblobjnote.c:58
+#, fuzzy, c-format
+msgid "unknown SDT version %u\n"
+msgstr "versión desconocida"
+
+#: libebl/eblobjnote.c:76
+#, fuzzy, c-format
+msgid "invalid SDT probe descriptor\n"
+msgstr "descriptor de archivo inválido"
+
+#: libebl/eblobjnote.c:126
+#, c-format
+msgid "    PC: "
+msgstr ""
+
+#: libebl/eblobjnote.c:128
+#, c-format
+msgid " Base: "
+msgstr ""
+
+#: libebl/eblobjnote.c:130
+#, c-format
+msgid " Semaphore: "
+msgstr ""
+
+#: libebl/eblobjnote.c:132
+#, c-format
+msgid "    Provider: "
+msgstr ""
+
+#: libebl/eblobjnote.c:134
+#, c-format
+msgid " Name: "
+msgstr ""
+
+#: libebl/eblobjnote.c:136
+#, c-format
+msgid " Args: "
+msgstr ""
+
+#: libebl/eblobjnote.c:304
+#, c-format
+msgid "    Build ID: "
+msgstr "    Build ID: "
+
+#. A non-null terminated version string.
+#: libebl/eblobjnote.c:315
+#, c-format
+msgid "    Linker version: %.*s\n"
+msgstr "    Versión del Enlazador: %.*s\n"
+
+#: libebl/eblobjnote.c:642
+#, c-format
+msgid "    OS: %s, ABI: "
+msgstr "    OS: %s, ABI: "
+
+#: libebl/eblosabiname.c:70
+msgid "Stand alone"
+msgstr "Autónomo"
+
+#: libebl/eblsymbolbindingname.c:68 libebl/eblsymboltypename.c:74
+#, c-format
+msgid "<unknown>: %d"
+msgstr "<desconocido>: %d"
+
+#: libelf/elf_error.c:66
+msgid "unknown version"
+msgstr "versión desconocida"
+
+#: libelf/elf_error.c:70
+msgid "unknown type"
+msgstr "tipo desconocido"
+
+#: libelf/elf_error.c:74
+msgid "invalid `Elf' handle"
+msgstr "manejo`ELF' inválido"
+
+#: libelf/elf_error.c:78
+msgid "invalid size of source operand"
+msgstr "tamaño inválido del operando fuente"
+
+#: libelf/elf_error.c:82
+msgid "invalid size of destination operand"
+msgstr "tamaño inválido del operando destino"
+
+#: libelf/elf_error.c:86 src/readelf.c:6759
+#, c-format
+msgid "invalid encoding"
+msgstr "codificación inválida"
+
+#: libelf/elf_error.c:94
+msgid "invalid file descriptor"
+msgstr "descriptor de archivo inválido"
+
+#: libelf/elf_error.c:98
+#, fuzzy
+msgid "invalid ELF file data"
+msgstr "Archivo ELF inválido"
+
+#: libelf/elf_error.c:102
+msgid "invalid operation"
+msgstr "operación inválida"
+
+#: libelf/elf_error.c:106
+msgid "ELF version not set"
+msgstr "no se estableció la versión de ELF"
+
+#: libelf/elf_error.c:118
+msgid "invalid fmag field in archive header"
+msgstr "campo fmag no válido en el encabezamiento del archivo"
+
+#: libelf/elf_error.c:122
+msgid "invalid archive file"
+msgstr "fichero de archivo inválido"
+
+#: libelf/elf_error.c:126
+msgid "descriptor is not for an archive"
+msgstr "el descriptor no es de un archivo"
+
+#: libelf/elf_error.c:130
+msgid "no index available"
+msgstr "no hay índice disponible"
+
+#: libelf/elf_error.c:134
+msgid "cannot read data from file"
+msgstr "no se pueden leer los datos del archivo"
+
+#: libelf/elf_error.c:138
+msgid "cannot write data to file"
+msgstr "no se puede escribir los datos al archivo"
+
+#: libelf/elf_error.c:142
+msgid "invalid binary class"
+msgstr "clase de binario inválida"
+
+#: libelf/elf_error.c:146
+msgid "invalid section index"
+msgstr "índice de sección inválido"
+
+#: libelf/elf_error.c:150
+msgid "invalid operand"
+msgstr "operando inválido"
+
+#: libelf/elf_error.c:154
+msgid "invalid section"
+msgstr "sección inválida"
+
+#: libelf/elf_error.c:162
+msgid "executable header not created first"
+msgstr "no se ha creado primero el encabezamiento ejecutable"
+
+#: libelf/elf_error.c:166
+msgid "file descriptor disabled"
+msgstr "descriptor de archivo inhabilitada"
+
+#: libelf/elf_error.c:170
+msgid "archive/member file descriptor mismatch"
+msgstr "archivo/miembro no coincide el descriptor de archivos"
+
+#: libelf/elf_error.c:178
+msgid "cannot manipulate null section"
+msgstr "no se pudo manipular una sección nula"
+
+#: libelf/elf_error.c:182
+msgid "data/scn mismatch"
+msgstr "no coinciden los datos/scn"
+
+#: libelf/elf_error.c:186
+msgid "invalid section header"
+msgstr "encabezamiento de sección inválida"
+
+#: libelf/elf_error.c:190 src/readelf.c:10638 src/readelf.c:11243
+#: src/readelf.c:11344 src/readelf.c:11532
+#, c-format
+msgid "invalid data"
+msgstr "datos inválidos"
+
+#: libelf/elf_error.c:194
+msgid "unknown data encoding"
+msgstr "codificación de caracteres desconocida"
+
+#: libelf/elf_error.c:198
+msgid "section `sh_size' too small for data"
+msgstr "el tamaño de la sección `sh_size' es demasiado pequeño para los datos "
+
+#: libelf/elf_error.c:202
+msgid "invalid section alignment"
+msgstr "alineación de la sección inválida"
+
+#: libelf/elf_error.c:206
+msgid "invalid section entry size"
+msgstr "tamaño de la entrada de la sección inválida"
+
+#: libelf/elf_error.c:210
+msgid "update() for write on read-only file"
+msgstr "update() para escribir sobre archivo de sólo lectura"
+
+#: libelf/elf_error.c:214
+msgid "no such file"
+msgstr "no hay tal archivo"
+
+#: libelf/elf_error.c:218
+msgid "only relocatable files can contain section groups"
+msgstr "solo los archivos reubicables pueden contener grupos de sección"
+
+#: libelf/elf_error.c:223
+msgid ""
+"program header only allowed in executables, shared objects, and core files"
+msgstr ""
+"los encabezamientos de los programas solo son permitidos en archivos "
+"ejecutables, archivos principales, u objetos compartidos"
+
+#: libelf/elf_error.c:230
+msgid "file has no program header"
+msgstr "el archivo no tiene encabezamiento de programa"
+
+#: libelf/elf_error.c:240
+#, fuzzy
+msgid "invalid section type"
+msgstr "sección inválida"
+
+#: libelf/elf_error.c:245
+#, fuzzy
+msgid "invalid section flags"
+msgstr "sección inválida"
+
+#: libelf/elf_error.c:250
+#, fuzzy
+msgid "section does not contain compressed data"
+msgstr "sección [%2zu] '%s' no debe ser ejecutable\n"
+
+#: libelf/elf_error.c:255
+msgid "section contains compressed data"
+msgstr ""
+
+#: libelf/elf_error.c:260
+#, fuzzy
+msgid "unknown compression type"
+msgstr "tipo desconocido"
+
+#: libelf/elf_error.c:265
+#, fuzzy
+msgid "cannot compress data"
+msgstr "no pueden copiar datos de sección: %s"
+
+#: libelf/elf_error.c:270
+#, fuzzy
+msgid "cannot decompress data"
+msgstr "no pueden copiar datos de sección: %s"
+
+#: src/addr2line.c:58
+#, fuzzy
+msgid "Input format options:"
+msgstr "Opciones de selección de entrada:"
+
+#: src/addr2line.c:60
+msgid "Treat addresses as offsets relative to NAME section."
+msgstr "Manejar direcciones como compensaciones relativas a sección de NOMBRE."
+
+#: src/addr2line.c:62
+#, fuzzy
+msgid "Output format options:"
+msgstr "Formato de salida:"
+
+#: src/addr2line.c:63
+#, fuzzy
+msgid "Print address before each entry"
+msgstr "Imprimir nombre de archivo antes de cada cadena."
+
+#: src/addr2line.c:64
+msgid "Show only base names of source files"
+msgstr "Mostrar sólo nombres de base de ficheros fuente"
+
+#: src/addr2line.c:66
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show absolute file names using compilation directory (default)"
+msgstr ""
+"Mostrar nombres de fichero absolutos mediante directorio de compilación"
+
+#: src/addr2line.c:67
+msgid "Also show function names"
+msgstr "También mostrar nombres de función"
+
+#: src/addr2line.c:68
+msgid "Also show symbol or section names"
+msgstr "También mostrar símbolo o nombres de sección"
+
+#: src/addr2line.c:69
+#, fuzzy
+msgid "Also show symbol and the section names"
+msgstr "También mostrar símbolo o nombres de sección"
+
+#: src/addr2line.c:70
+msgid "Also show line table flags"
+msgstr "También mostrar marcas de líneas de tabla"
+
+#: src/addr2line.c:72
+msgid ""
+"Show all source locations that caused inline expansion of subroutines at the "
+"address."
+msgstr ""
+
+#: src/addr2line.c:75
+msgid "Show demangled symbols (ARG is always ignored)"
+msgstr ""
+
+#: src/addr2line.c:76
+#, fuzzy
+#| msgid "Strip debugging symbols."
+msgid "Show demangled symbols"
+msgstr "Descartar los símbolos de depuración."
+
+#: src/addr2line.c:78
+msgid "Print all information on one line, and indent inlines"
+msgstr ""
+
+#: src/addr2line.c:80
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show relative file names without compilation directory"
+msgstr ""
+"Mostrar nombres de fichero absolutos mediante directorio de compilación"
+
+#: src/addr2line.c:82 src/elfcmp.c:69 src/findtextrel.c:65 src/nm.c:99
+#: src/strings.c:77
+msgid "Miscellaneous:"
+msgstr "Misceláneos:"
+
+#. Short description of program.
+#: src/addr2line.c:90
+msgid ""
+"Locate source files and line information for ADDRs (in a.out by default)."
+msgstr ""
+"Localizar archivos fuente e información de línea para DIRECCIONES (en a.out "
+"por defecto)."
+
+#. Strings for arguments in help texts.
+#: src/addr2line.c:94
+msgid "[ADDR...]"
+msgstr "[DIREC...]"
+
+#: src/addr2line.c:530
+msgid "Section syntax requires exactly one module"
+msgstr "Sintaxis de sección requiere exactamente un módulo"
+
+#: src/addr2line.c:552
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside section '%s'"
+msgstr "Compensación %#<PRIxMAX> se encuentra fuera de sección '%s'"
+
+#: src/addr2line.c:662
+#, c-format
+msgid "cannot find symbol '%s'"
+msgstr "no se puede encontrar símbolo '%s'"
+
+#: src/addr2line.c:667
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
+msgstr "compensación %#<PRIxMAX> se encuentra fuera de contenido de '%s'"
+
+#: src/ar.c:66
+msgid "Commands:"
+msgstr "Comandos:"
+
+#: src/ar.c:67
+msgid "Delete files from archive."
+msgstr "Borrar archivos de un archivo"
+
+#: src/ar.c:68
+msgid "Move files in archive."
+msgstr "Desplazar ficheros en archivo."
+
+#: src/ar.c:69
+msgid "Print files in archive."
+msgstr "Imprimir ficheros en archivo."
+
+#: src/ar.c:70
+msgid "Quick append files to archive."
+msgstr "Adición rápida de ficheros para archivar"
+
+#: src/ar.c:72
+msgid "Replace existing or insert new file into archive."
+msgstr "Remplazar fichero existente o insertar uno nuevo en el archivo."
+
+#: src/ar.c:73
+msgid "Display content of archive."
+msgstr "Mostrar contenido de archivo"
+
+#: src/ar.c:74
+msgid "Extract files from archive."
+msgstr "extraer ficheros de un archivo"
+
+#: src/ar.c:76
+msgid "Command Modifiers:"
+msgstr "Modificadores de comandos:"
+
+#: src/ar.c:77
+msgid "Preserve original dates."
+msgstr "Preservar fechas originales."
+
+#: src/ar.c:78
+msgid "Use instance [COUNT] of name."
+msgstr "Usar instancia [COUNT] de nombre."
+
+#: src/ar.c:80
+msgid "Do not replace existing files with extracted files."
+msgstr "No remplazar los archivos existentes por los archivos extractados."
+
+#: src/ar.c:81
+msgid "Allow filename to be truncated if necessary."
+msgstr "Permitir truncamiento del nombre de archivo de ser necesario."
+
+#: src/ar.c:83
+msgid "Provide verbose output."
+msgstr "Proporcionar salida detallada"
+
+#: src/ar.c:84
+msgid "Force regeneration of symbol table."
+msgstr "Forzar regeneración de tabla de símbolos."
+
+#: src/ar.c:85
+msgid "Insert file after [MEMBER]."
+msgstr "Insertar archivo después de [MIEMBRO]."
+
+#: src/ar.c:86
+msgid "Insert file before [MEMBER]."
+msgstr "Introducir fichero antes de [MIEMBRO]."
+
+#: src/ar.c:87
+msgid "Same as -b."
+msgstr "Igual que -b."
+
+#: src/ar.c:88
+msgid "Suppress message when library has to be created."
+msgstr "Suprimir mensaje cuando se tenga que crear la biblioteca."
+
+#: src/ar.c:90
+msgid "Use full path for file matching."
+msgstr "Usar la ruta total para fichero coincidente."
+
+#: src/ar.c:91
+msgid "Update only older files in archive."
+msgstr "Actualizar sólo ficheros antiguos en archivo."
+
+#. Short description of program.
+#: src/ar.c:97
+msgid "Create, modify, and extract from archives."
+msgstr "Crear, modificar, y extraer de archivos."
+
+#. Strings for arguments in help texts.
+#: src/ar.c:100
+msgid "[MEMBER] [COUNT] ARCHIVE [FILE...]"
+msgstr "[MIEMBRO] [CONTAR] ARCHIVO [FICHERO...]"
+
+#: src/ar.c:179
+#, c-format
+msgid "'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"
+msgstr "'a', 'b', é 'i' sólo se permiten con las opciones 'm' y 'r'."
+
+#: src/ar.c:184
+#, c-format
+msgid "MEMBER parameter required for 'a', 'b', and 'i' modifiers"
+msgstr "Parámetro MIEMBRO requerido para modificadores 'a', 'b', e 'i'"
+
+#: src/ar.c:200
+#, c-format
+msgid "'N' is only meaningful with the 'x' and 'd' options"
+msgstr "'N' sólo es significativa con las opciones `x' y `d'."
+
+#: src/ar.c:205
+#, c-format
+msgid "COUNT parameter required"
+msgstr "Parámetro CONTAR requerido"
+
+#: src/ar.c:217
+#, c-format
+msgid "invalid COUNT parameter %s"
+msgstr "Parámetro CONTAR inválido %s"
+
+#: src/ar.c:224
+#, c-format
+msgid "'%c' is only meaningful with the 'x' option"
+msgstr "'%c' es sólo significativo con la opción 'x'"
+
+#: src/ar.c:230
+#, c-format
+msgid "archive name required"
+msgstr "nombre de archivo requerido"
+
+#: src/ar.c:243
+#, c-format
+msgid "command option required"
+msgstr ""
+
+#: src/ar.c:294
+#, c-format
+msgid "More than one operation specified"
+msgstr "Más de una operación especificada"
+
+#: src/ar.c:388
+#, c-format
+msgid "cannot open archive '%s'"
+msgstr "Imposible abrir el archivo '%s'"
+
+#: src/ar.c:398
+#, c-format
+msgid "cannot open archive '%s': %s"
+msgstr "Imposible abrir el archivo '%s': %s"
+
+#: src/ar.c:402
+#, c-format
+msgid "%s: not an archive file"
+msgstr "%s: no es un fichero de archivo"
+
+#: src/ar.c:406
+#, c-format
+msgid "cannot stat archive '%s'"
+msgstr "no sepuede stat el archivo '%s'"
+
+#: src/ar.c:418
+#, c-format
+msgid "no entry %s in archive\n"
+msgstr "no hay entrada %s en archivo\n"
+
+#: src/ar.c:471 src/ar.c:925 src/ar.c:1131
+msgid "cannot create hash table"
+msgstr "Falló al crear la tabla de dispersión"
+
+#: src/ar.c:477 src/ar.c:931 src/ar.c:1139
+msgid "cannot insert into hash table"
+msgstr "no sepuede insertar en tabla de dispersión"
+
+#: src/ar.c:485 src/ranlib.c:147
+#, c-format
+msgid "cannot stat '%s'"
+msgstr "no se puede stat '%s'"
+
+#: src/ar.c:587
+#, c-format
+msgid "cannot read content of %s: %s"
+msgstr "no se puede leer el contenido de %s: %s"
+
+#: src/ar.c:630
+#, c-format
+msgid "cannot open %.*s"
+msgstr " Imposible abrir %.*s"
+
+#: src/ar.c:652
+#, c-format
+msgid "failed to write %s"
+msgstr "Falló al escribir %s"
+
+#: src/ar.c:664
+#, c-format
+msgid "cannot change mode of %s"
+msgstr "No se puede cambiar el modo de %s"
+
+#: src/ar.c:680
+#, c-format
+msgid "cannot change modification time of %s"
+msgstr "No puede cambiar tiempo de modificación de %s"
+
+#: src/ar.c:726
+#, c-format
+msgid "cannot rename temporary file to %.*s"
+msgstr "no sepuede renombrar fichero temporal para %.*s"
+
+#: src/ar.c:762 src/ar.c:1016 src/ar.c:1419 src/ranlib.c:221
+#, c-format
+msgid "cannot create new file"
+msgstr "no sepuede crear fichero nuevo"
+
+#: src/ar.c:1221
+#, c-format
+msgid "position member %s not found"
+msgstr "no se encuentra miembro de posición %s "
+
+#: src/ar.c:1231
+#, c-format
+msgid "%s: no entry %s in archive!\n"
+msgstr "%s: ¡no hay entrada %s en archive!\n"
+
+#: src/ar.c:1260 src/objdump.c:240
+#, c-format
+msgid "cannot open %s"
+msgstr "no sepuede abrir %s"
+
+#: src/ar.c:1265
+#, c-format
+msgid "cannot stat %s"
+msgstr "no sepuede efectuar stat %s"
+
+#: src/ar.c:1271
+#, c-format
+msgid "%s is no regular file"
+msgstr " %s no es un fichero ordinario "
+
+#: src/ar.c:1284
+#, c-format
+msgid "cannot get ELF descriptor for %s: %s\n"
+msgstr "no sepuede obtener descriptor ELF para %s: %s\n"
+
+#: src/ar.c:1304
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "no sepuede leer %s: %s"
+
+#: src/ar.c:1479
+#, fuzzy, c-format
+msgid "cannot represent ar_date"
+msgstr "no pueden copiar datos de sección: %s"
+
+#: src/ar.c:1485
+#, fuzzy, c-format
+msgid "cannot represent ar_uid"
+msgstr "no pueden copiar datos de sección: %s"
+
+#: src/ar.c:1491
+#, fuzzy, c-format
+msgid "cannot represent ar_gid"
+msgstr "no pueden copiar datos de sección: %s"
+
+#: src/ar.c:1497
+#, fuzzy, c-format
+msgid "cannot represent ar_mode"
+msgstr "no se puede obtener encabezamiento de sección\n"
+
+#: src/ar.c:1503
+#, fuzzy, c-format
+msgid "cannot represent ar_size"
+msgstr "no sepuede abrir %s"
+
+#: src/arlib-argp.c:31
+msgid "Use zero for uid, gid, and date in archive members."
+msgstr ""
+
+#: src/arlib-argp.c:33
+msgid "Use actual uid, gid, and date in archive members."
+msgstr ""
+
+#: src/arlib-argp.c:62
+#, c-format
+msgid "%s (default)"
+msgstr ""
+
+#. The archive is too big.
+#: src/arlib.c:212
+#, c-format
+msgid "the archive '%s' is too large"
+msgstr " El archivo '%s' es demasiado grande"
+
+#: src/arlib.c:225
+#, c-format
+msgid "cannot read ELF header of %s(%s): %s"
+msgstr "no se puede leer el encabezamiento ELF de %s(%s): %s"
+
+#: src/elfclassify.c:91
+msgid "opening"
+msgstr ""
+
+#: src/elfclassify.c:98
+msgid "reading"
+msgstr ""
+
+#: src/elfclassify.c:244
+#, fuzzy
+#| msgid "cannot get ELF header"
+msgid "ELF header"
+msgstr "no se puede obtener el encabezamiento ELF"
+
+#: src/elfclassify.c:255
+#, fuzzy
+#| msgid "Program Headers:"
+msgid "program headers"
+msgstr "encabezamientos de programa:"
+
+#: src/elfclassify.c:264
+#, fuzzy
+#| msgid "Program Headers:"
+msgid "program header"
+msgstr "encabezamientos de programa:"
+
+#: src/elfclassify.c:284
+#, fuzzy
+#| msgid "Section Headers:"
+msgid "section headers"
+msgstr "encabezamientos de sección:"
+
+#: src/elfclassify.c:295
+#, fuzzy
+#| msgid "cannot get section header string table index"
+msgid "section header string table index"
+msgstr "no se puede obtener índice de cadena de encabezamiento de sección"
+
+#: src/elfclassify.c:309
+#, fuzzy
+msgid "could not obtain section header"
+msgstr "no se puede obtener encabezamiento de sección\n"
+
+#: src/elfclassify.c:315
+#, fuzzy
+msgid "could not obtain section name"
+msgstr "no se puede obtener encabezamiento de sección\n"
+
+#: src/elfclassify.c:828
+msgid "writing to standard output"
+msgstr ""
+
+#: src/elfclassify.c:855
+msgid "reading from standard input"
+msgstr ""
+
+#: src/elfclassify.c:876
+#, fuzzy
+#| msgid "Input selection options:"
+msgid "Classification options"
+msgstr "Opciones de selección de entrada:"
+
+#: src/elfclassify.c:878
+msgid "File looks like an ELF object or archive/static library (default)"
+msgstr ""
+
+#: src/elfclassify.c:881
+msgid "File is an regular ELF object (not an archive/static library)"
+msgstr ""
+
+#: src/elfclassify.c:884
+msgid "File is an ELF archive or static library"
+msgstr ""
+
+#: src/elfclassify.c:887
+msgid "File is an ELF core dump file"
+msgstr ""
+
+#: src/elfclassify.c:890
+msgid ""
+"File is an ELF file with symbol table or .debug_* sections and can be "
+"stripped further"
+msgstr ""
+
+#: src/elfclassify.c:893
+msgid "File is (primarily) an ELF program executable (not primarily a DSO)"
+msgstr ""
+
+#: src/elfclassify.c:896
+msgid "File is an ELF program executable (might also be a DSO)"
+msgstr ""
+
+#: src/elfclassify.c:899
+msgid ""
+"File is (primarily) an ELF shared object (DSO) (not primarily an executable)"
+msgstr ""
+
+#: src/elfclassify.c:902
+msgid "File is an ELF shared object (DSO) (might also be an executable)"
+msgstr ""
+
+#: src/elfclassify.c:906
+#, fuzzy
+#| msgid "cannot find kernel modules"
+msgid "File is a linux kernel module"
+msgstr "no se pueden hallar módulos de kernel"
+
+#: src/elfclassify.c:908
+msgid "File is a debug only ELF file (separate .debug, .dwo or dwz multi-file)"
+msgstr ""
+
+#: src/elfclassify.c:911
+msgid "File is a loadable ELF object (program or shared object)"
+msgstr ""
+
+#: src/elfclassify.c:940
+msgid "Input flags"
+msgstr ""
+
+#: src/elfclassify.c:942
+msgid "Only classify regular (not symlink nor special device) files"
+msgstr ""
+
+#: src/elfclassify.c:944
+msgid ""
+"Also read file names to process from standard input, separated by newlines"
+msgstr ""
+
+#: src/elfclassify.c:947
+msgid ""
+"Also read file names to process from standard input, separated by ASCII NUL "
+"bytes"
+msgstr ""
+
+#: src/elfclassify.c:950
+msgid "Do not read files from standard input (default)"
+msgstr ""
+
+#: src/elfclassify.c:952
+msgid "Try to open compressed files or embedded (kernel) ELF images"
+msgstr ""
+
+#: src/elfclassify.c:955
+#, fuzzy
+#| msgid "Output format:"
+msgid "Output flags"
+msgstr "Formato de salida:"
+
+#: src/elfclassify.c:957
+msgid "Output names of files, separated by newline"
+msgstr ""
+
+#: src/elfclassify.c:959
+msgid "Output names of files, separated by ASCII NUL"
+msgstr ""
+
+#: src/elfclassify.c:961
+#, fuzzy
+#| msgid "More than one output file name given."
+msgid "Do not output file names"
+msgstr "Se ha dado más de un nombre de archivo de salida."
+
+#: src/elfclassify.c:963
+msgid "If printing file names, print matching files (default)"
+msgstr ""
+
+#: src/elfclassify.c:965
+msgid "If printing file names, print files that do not match"
+msgstr ""
+
+#: src/elfclassify.c:967
+msgid "Additional flags"
+msgstr ""
+
+#: src/elfclassify.c:969
+msgid "Output additional information (can be specified multiple times)"
+msgstr ""
+
+#: src/elfclassify.c:971
+msgid "Suppress some error output (counterpart to --verbose)"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: src/elfclassify.c:979 src/elfcompress.c:1436 src/elflint.c:77
+#: src/readelf.c:161
+msgid "FILE..."
+msgstr "FICHERO..."
+
+#: src/elfclassify.c:980
+msgid ""
+"Determine the type of an ELF file.\n"
+"\n"
+"All of the classification options must apply at the same time to a "
+"particular file.  Classification options can be negated using a \"--not-\" "
+"prefix.\n"
+"\n"
+"Since modern ELF does not clearly distinguish between programs and dynamic "
+"shared objects, you should normally use either --executable or --shared to "
+"identify the primary purpose of a file.  Only one of the --shared and --"
+"executable checks can pass for a file.\n"
+"\n"
+"If you want to know whether an ELF object might a program or a shared "
+"library (but could be both), then use --program or --library. Some ELF files "
+"will classify as both a program and a library.\n"
+"\n"
+"If you just want to know whether an ELF file is loadable (as program or "
+"library) use --loadable.  Note that files that only contain (separate) debug "
+"information (--debug-only) are never --loadable (even though they might "
+"contain program headers).  Linux kernel modules are also not --loadable (in "
+"the normal sense).\n"
+"\n"
+"Without any of the --print options, the program exits with status 0 if the "
+"requested checks pass for all input files, with 1 if a check fails for any "
+"file, and 2 if there is an environmental issue (such as a file read error or "
+"a memory allocation error).\n"
+"\n"
+"When printing file names, the program exits with status 0 even if no file "
+"names are printed, and exits with status 2 if there is an environmental "
+"issue.\n"
+"\n"
+"On usage error (e.g. a bad option was given), the program exits with a "
+"status code larger than 2.\n"
+"\n"
+"The --quiet or -q option suppresses some error warning output, but doesn't "
+"change the exit status."
+msgstr ""
+
+#: src/elfcmp.c:59
+msgid "Control options:"
+msgstr "Opciones de control:"
+
+#: src/elfcmp.c:61
+msgid "Output all differences, not just the first"
+msgstr ""
+
+#: src/elfcmp.c:62
+msgid ""
+"Control treatment of gaps in loadable segments [ignore|match] (default: "
+"ignore)"
+msgstr ""
+"Tratamiento de control de brechas en segmento cargables [ignorar|"
+"coincidencia] (por defecto: ignorar)"
+
+#: src/elfcmp.c:64
+msgid "Ignore permutation of buckets in SHT_HASH section"
+msgstr "Ignorar permutación de cubetas en sección SHT_HASH"
+
+#: src/elfcmp.c:66
+msgid "Ignore differences in build ID"
+msgstr ""
+
+#: src/elfcmp.c:67
+msgid "Output nothing; yield exit status only"
+msgstr "Nada de salida; producir estado de salida únicamente"
+
+#. Short description of program.
+#: src/elfcmp.c:74
+msgid "Compare relevant parts of two ELF files for equality."
+msgstr "Comparar partes relevantes de dos ficheros ELF para igualdad."
+
+#. Strings for arguments in help texts.
+#: src/elfcmp.c:78
+msgid "FILE1 FILE2"
+msgstr "FICHERO1 FICHERO2"
+
+#: src/elfcmp.c:140
+msgid "Invalid number of parameters.\n"
+msgstr "Número inválido de parámetros.\n"
+
+#: src/elfcmp.c:171 src/elfcmp.c:176
+#, c-format
+msgid "cannot get ELF header of '%s': %s"
+msgstr "no se puede obtener encabezamiento de '%s': %s"
+
+#: src/elfcmp.c:202
+#, c-format
+msgid "%s %s diff: ELF header"
+msgstr "%s %s diff: encabezamiento ELF"
+
+#: src/elfcmp.c:209 src/elfcmp.c:212
+#, c-format
+msgid "cannot get section count of '%s': %s"
+msgstr "no se puede obtener un conteo de sección en '%s': %s"
+
+#: src/elfcmp.c:217
+#, c-format
+msgid "%s %s diff: section count"
+msgstr "%s %s diff: conteo de sección"
+
+#: src/elfcmp.c:224 src/elfcmp.c:227
+#, c-format
+msgid "cannot get program header count of '%s': %s"
+msgstr "no se puede obtener un conteo de encabezado de programa de '%s': %s"
+
+#: src/elfcmp.c:232
+#, c-format
+msgid "%s %s diff: program header count"
+msgstr "%s %s diff: encabezado de programa"
+
+#: src/elfcmp.c:240 src/elfcmp.c:243
+#, fuzzy, c-format
+msgid "cannot get hdrstrndx of '%s': %s"
+msgstr "no se puede obtener encabezamiento de '%s': %s"
+
+#: src/elfcmp.c:248
+#, fuzzy, c-format
+msgid "%s %s diff: shdr string index"
+msgstr "%s %s diff: conteo de sección"
+
+#: src/elfcmp.c:306
+#, fuzzy, c-format
+msgid "%s %s differ: section [%zu], [%zu] name"
+msgstr "%s %s differ: sección [%zu,%zu] contenido '%s'"
+
+#: src/elfcmp.c:329
+#, fuzzy, c-format
+msgid "%s %s differ: section [%zu] '%s' header"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:337 src/elfcmp.c:343
+#, c-format
+msgid "cannot get content of section %zu in '%s': %s"
+msgstr "No se puede obtener contenido de sección %zu en '%s': %s"
+
+#: src/elfcmp.c:352
+#, fuzzy, c-format
+msgid "symbol table [%zu] in '%s' has zero sh_entsize"
+msgstr ""
+"\n"
+"La tabla de símbolos [%2u] '%s' contiene entrada %u:\n"
+
+#: src/elfcmp.c:364 src/elfcmp.c:370
+#, c-format
+msgid "cannot get symbol in '%s': %s"
+msgstr "No se puede obtener símbolo en '%s': %s"
+
+#: src/elfcmp.c:392
+#, c-format
+msgid "%s %s differ: symbol table [%zu]"
+msgstr "%s %s differ: tabla de símbolos [%zu]"
+
+#: src/elfcmp.c:395
+#, c-format
+msgid "%s %s differ: symbol table [%zu,%zu]"
+msgstr "%s %s differ: tabla de símbolos [%zu,%zu]"
+
+#: src/elfcmp.c:442 src/elfcmp.c:512
+#, fuzzy, c-format
+msgid "%s %s differ: section [%zu] '%s' number of notes"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:450
+#, fuzzy, c-format
+msgid "cannot read note section [%zu] '%s' in '%s': %s"
+msgstr "No se puede obtener contenido de sección %zu en '%s': %s"
+
+#: src/elfcmp.c:461
+#, fuzzy, c-format
+msgid "%s %s differ: section [%zu] '%s' note name"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:469
+#, fuzzy, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' type"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:484
+#, fuzzy, c-format
+msgid "%s %s differ: build ID length"
+msgstr "%s %s differ: brecha"
+
+#: src/elfcmp.c:492
+#, fuzzy, c-format
+msgid "%s %s differ: build ID content"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:501
+#, fuzzy, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' content"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:542
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' content"
+msgstr "%s %s differ: sección [%zu] contenido '%s'"
+
+#: src/elfcmp.c:546
+#, c-format
+msgid "%s %s differ: section [%zu,%zu] '%s' content"
+msgstr "%s %s differ: sección [%zu,%zu] contenido '%s'"
+
+#: src/elfcmp.c:561
+#, c-format
+msgid "%s %s differ: unequal amount of important sections"
+msgstr "%s %s differ: cantidad desigual de secciones importantes"
+
+#: src/elfcmp.c:594 src/elfcmp.c:599
+#, c-format
+msgid "cannot load data of '%s': %s"
+msgstr "no se pueden cargar los datos de '%s': %s"
+
+#: src/elfcmp.c:618 src/elfcmp.c:624
+#, c-format
+msgid "cannot get program header entry %d of '%s': %s"
+msgstr ""
+"no se puede obtener entrada de encabezamiento de programa %d de '%s': %s"
+
+#: src/elfcmp.c:630
+#, c-format
+msgid "%s %s differ: program header %d"
+msgstr "%s %s differ: encabezamiento de programa %d"
+
+#: src/elfcmp.c:654
+#, c-format
+msgid "%s %s differ: gap"
+msgstr "%s %s differ: brecha"
+
+#: src/elfcmp.c:705
+#, c-format
+msgid "Invalid value '%s' for --gaps parameter."
+msgstr "Valor inválido '%s' para parámetro --gaps"
+
+#: src/elfcmp.c:733 src/findtextrel.c:194 src/nm.c:363 src/ranlib.c:140
+#: src/size.c:271 src/strings.c:184 src/strip.c:1040 src/strip.c:1077
+#: src/unstrip.c:2245 src/unstrip.c:2274
+#, c-format
+msgid "cannot open '%s'"
+msgstr "Imposible abrir '%s'"
+
+#: src/elfcmp.c:737 src/findtextrel.c:213 src/ranlib.c:157
+#, c-format
+msgid "cannot create ELF descriptor for '%s': %s"
+msgstr "No puede crear descriptor ELF para '%s': %s"
+
+#: src/elfcmp.c:742
+#, c-format
+msgid "cannot create EBL descriptor for '%s'"
+msgstr "no se puede crear el descriptor EBL para '%s'"
+
+#: src/elfcmp.c:760 src/findtextrel.c:384
+#, c-format
+msgid "cannot get section header of section %zu: %s"
+msgstr "No se puede obtener el encabezamiento de sección %zu: %s"
+
+#: src/elfcmp.c:770
+#, c-format
+msgid "cannot get content of section %zu: %s"
+msgstr "No se puede obtener contenido de sección %zu: %s"
+
+#: src/elfcmp.c:780 src/elfcmp.c:794
+#, c-format
+msgid "cannot get relocation: %s"
+msgstr "No se puede obtener reubicación: %s"
+
+#: src/elfcompress.c:128 src/strip.c:305 src/unstrip.c:116
+#, c-format
+msgid "-o option specified twice"
+msgstr "opción -o especificada dos veces"
+
+#: src/elfcompress.c:135
+#, fuzzy, c-format
+msgid "-t option specified twice"
+msgstr "opción -f especificada dos veces"
+
+#: src/elfcompress.c:147
+#, c-format
+msgid "ZSTD support is not enabled"
+msgstr ""
+
+#: src/elfcompress.c:150
+#, fuzzy, c-format
+msgid "unknown compression type '%s'"
+msgstr "tipo desconocido"
+
+#. We need at least one input file.
+#: src/elfcompress.c:162 src/elfcompress.c:1447
+#, fuzzy, c-format
+msgid "No input file given"
+msgstr "archivo de entrada vacío"
+
+#: src/elfcompress.c:168 src/elfcompress.c:1451
+#, fuzzy, c-format
+msgid "Only one input file allowed together with '-o'"
+msgstr "Sólo se permite ingresar un archivo junto con '-o' y '-f'"
+
+#: src/elfcompress.c:1408
+#, fuzzy
+msgid "Place (de)compressed output into FILE"
+msgstr "Colocar la salida obtenida en FICHERO"
+
+#: src/elfcompress.c:1411
+msgid ""
+"What type of compression to apply. TYPE can be 'none' (decompress), "
+"'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), 'zlib-"
+"gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD "
+"compression)"
+msgstr ""
+
+#: src/elfcompress.c:1415
+msgid ""
+"SECTION name to (de)compress, SECTION is an extended wildcard pattern "
+"(defaults to '.?(z)debug*')"
+msgstr ""
+
+#: src/elfcompress.c:1418
+msgid "Print a message for each section being (de)compressed"
+msgstr ""
+
+#: src/elfcompress.c:1421
+msgid ""
+"Force compression of section even if it would become larger or update/"
+"rewrite the file even if no section would be (de)compressed"
+msgstr ""
+
+#: src/elfcompress.c:1424 src/strip.c:92
+msgid "Relax a few rules to handle slightly broken ELF files"
+msgstr "Relaja algunas reglas para manejar ficheros ELF rotos"
+
+#: src/elfcompress.c:1427
+#, fuzzy
+msgid "Be silent when a section cannot be compressed"
+msgstr ""
+"Sección [%2zu] '%s': dirección de secciones de datos de hilo-local no cero\n"
+
+#: src/elfcompress.c:1437
+msgid "Compress or decompress sections in an ELF file."
+msgstr ""
+
+#: src/elflint.c:63
+msgid "Be extremely strict, flag level 2 features."
+msgstr "Sea extremadamente estricto, característica de marca de nivel 2."
+
+#: src/elflint.c:64
+msgid "Do not print anything if successful"
+msgstr "No imprime nada si está correcto"
+
+#: src/elflint.c:65
+msgid "Binary is a separate debuginfo file"
+msgstr "Binario es un archivo debuginfo independiente"
+
+#: src/elflint.c:67
+msgid ""
+"Binary has been created with GNU ld and is therefore known to be broken in "
+"certain ways"
+msgstr ""
+"Binario ha sido creado con GNU Id y por lo tanto se sabe que puede estar "
+"roto de alguna forma"
+
+#. Short description of program.
+#: src/elflint.c:73
+msgid "Pedantic checking of ELF files compliance with gABI/psABI spec."
+msgstr "Chequeo minucioso de ficheros ELF de acuerdo con gABI/psABI "
+
+#: src/elflint.c:154 src/readelf.c:413
+#, fuzzy, c-format
+msgid "cannot open input file '%s'"
+msgstr "no se puede abrir el fichero de entrada"
+
+#: src/elflint.c:161
+#, fuzzy, c-format
+msgid "cannot generate Elf descriptor for '%s': %s\n"
+msgstr "no se puede crear descriptor ELF: %s\n"
+
+#: src/elflint.c:180
+#, c-format
+msgid "error while closing Elf descriptor: %s\n"
+msgstr "error al cerrar el descriptor ELF: %s\n"
+
+#: src/elflint.c:184
+msgid "No errors"
+msgstr "No hay errores"
+
+#: src/elflint.c:219 src/readelf.c:625
+msgid "Missing file name.\n"
+msgstr "Falta el nombre de archivo.\n"
+
+#: src/elflint.c:284
+#, c-format
+msgid " error while freeing sub-ELF descriptor: %s\n"
+msgstr " error al liberar descriptor sub-ELF: %s\n"
+
+#. We cannot do anything.
+#: src/elflint.c:292
+#, c-format
+msgid "Not an ELF file - it has the wrong magic bytes at the start\n"
+msgstr "No es un fichero ELF - tiene los bytes mágicos errados en el inicio\n"
+
+#: src/elflint.c:358
+#, c-format
+msgid "e_ident[%d] == %d is no known class\n"
+msgstr "e_ident[%d] == %d es una clase desconocida\n"
+
+#: src/elflint.c:363
+#, c-format
+msgid "e_ident[%d] == %d is no known data encoding\n"
+msgstr "e_ident[%d] == %d es una codificación de datos desconocida\n"
+
+#: src/elflint.c:367
+#, c-format
+msgid "unknown ELF header version number e_ident[%d] == %d\n"
+msgstr ""
+"número de versión de encabezamiento ELF desconocido e_ident[%d] == %d\n"
+
+#: src/elflint.c:375
+#, c-format
+msgid "unsupported OS ABI e_ident[%d] == '%s'\n"
+msgstr "Sistema operativo OS ABI e_ident[%d] == '%s' incompatible\n"
+
+#: src/elflint.c:381
+#, fuzzy, c-format
+msgid "unsupported ABI version e_ident[%d] == %d\n"
+msgstr "Versión incompatible ABI e_ident[%d] == %d\n"
+
+#: src/elflint.c:386
+#, c-format
+msgid "e_ident[%zu] is not zero\n"
+msgstr "e_ident[%zu] no es cero\n"
+
+#: src/elflint.c:391
+#, c-format
+msgid "unknown object file type %d\n"
+msgstr "tipo de fichero objeto desconocido %d\n"
+
+#: src/elflint.c:398
+#, c-format
+msgid "unknown machine type %d\n"
+msgstr "tipo de máquina desconocido %d\n"
+
+#: src/elflint.c:402
+#, c-format
+msgid "unknown object file version\n"
+msgstr "versión de fichero objeto desconocido\n"
+
+#: src/elflint.c:408
+#, c-format
+msgid "invalid program header offset\n"
+msgstr "Compensación de encabezamiento de programa inválida\n"
+
+#: src/elflint.c:410
+#, c-format
+msgid "executables and DSOs cannot have zero program header offset\n"
+msgstr ""
+"tanto los ejecutables como los DSO no pueden tener compensación de "
+"encabezamiento de programa cero\n"
+
+#: src/elflint.c:414
+#, c-format
+msgid "invalid number of program header entries\n"
+msgstr "cantidad no válida de entradas del encabezamiento del programa\n"
+
+#: src/elflint.c:422
+#, c-format
+msgid "invalid section header table offset\n"
+msgstr "compensación de sección de tabla de encabezamiento inválida\n"
+
+#: src/elflint.c:425
+#, c-format
+msgid "section header table must be present\n"
+msgstr "tabla de encabezamiento de sección debe estar presente\n"
+
+#: src/elflint.c:439
+#, c-format
+msgid "invalid number of section header table entries\n"
+msgstr ""
+"cantidad no válida de entradas en la tabla del encabezamiento de sección\n"
+
+#: src/elflint.c:456
+#, c-format
+msgid "invalid section header index\n"
+msgstr "Índice de sección de encabezamiento inválido\n"
+
+#: src/elflint.c:474
+#, c-format
+msgid "Can only check %u headers, shnum was %u\n"
+msgstr ""
+
+#: src/elflint.c:488
+#, c-format
+msgid "invalid number of program header table entries\n"
+msgstr "cantidad no válida de entradas de tabla de encabezado del programa\n"
+
+#: src/elflint.c:505
+#, c-format
+msgid "Can only check %u headers, phnum was %u\n"
+msgstr ""
+
+#: src/elflint.c:510
+#, c-format
+msgid "invalid machine flags: %s\n"
+msgstr "Indicadores de máquina inválidos: %s\n"
+
+#: src/elflint.c:517 src/elflint.c:534
+#, c-format
+msgid "invalid ELF header size: %hd\n"
+msgstr "tamaño inválido del encabezamiento ELF: %hd\n"
+
+#: src/elflint.c:520 src/elflint.c:537
+#, c-format
+msgid "invalid program header size: %hd\n"
+msgstr "tamaño inválido del encabezamiento del programa: %hd\n"
+
+#: src/elflint.c:523 src/elflint.c:540
+#, c-format
+msgid "invalid program header position or size\n"
+msgstr "tamaño o posición inválidos del encabezamiento del programa\n"
+
+#: src/elflint.c:526 src/elflint.c:543
+#, c-format
+msgid "invalid section header size: %hd\n"
+msgstr "tamaño inválido del encabezamiento de sección: %hd\n"
+
+#: src/elflint.c:529 src/elflint.c:546
+#, c-format
+msgid "invalid section header position or size\n"
+msgstr "tamaño o posición no válidos del encabezamiento de sección\n"
+
+#: src/elflint.c:591
+#, c-format
+msgid ""
+"section [%2d] '%s': section with SHF_GROUP flag set not part of a section "
+"group\n"
+msgstr ""
+"sección [%2d] '%s': sección con la bandera SHF_GROUP no es parte de una "
+"sección de grupo\n"
+
+#: src/elflint.c:595
+#, c-format
+msgid ""
+"section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"
+msgstr ""
+"sección [%2d] '%s': el grupo de sección [%2zu] '%s' no precede al miembro de "
+"grupo\n"
+
+#: src/elflint.c:611 src/elflint.c:1509 src/elflint.c:1560 src/elflint.c:1610
+#: src/elflint.c:1692 src/elflint.c:2029 src/elflint.c:2355 src/elflint.c:2981
+#: src/elflint.c:3144 src/elflint.c:3292 src/elflint.c:3494 src/elflint.c:4511
+#, c-format
+msgid "section [%2d] '%s': cannot get section data\n"
+msgstr "Sección [%2d] '%s': No se pueden obtener datos de sección\n"
+
+#: src/elflint.c:624 src/elflint.c:1699
+#, c-format
+msgid ""
+"section [%2d] '%s': referenced as string table for section [%2d] '%s' but "
+"type is not SHT_STRTAB\n"
+msgstr ""
+"sección [%2d] '%s': nombrado como una tabla de cadena para la sección [%2d] "
+"'%s' pero el tipo no es SHT_STRTAB\n"
+
+#: src/elflint.c:647
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol table cannot have more than one extended index "
+"section\n"
+msgstr ""
+"sección [%2d] '%s': la tabla de símbolo no puede tener más de una sección de "
+"índice extendido\n"
+
+#: src/elflint.c:659
+#, c-format
+msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n"
+msgstr ""
+"sección [%2u] '%s': el tamaño de la entrada no coincide con ElfXX_Sym\n"
+
+#: src/elflint.c:663
+#, fuzzy, c-format
+msgid ""
+"section [%2u] '%s': number of local entries in 'st_info' larger than table "
+"size\n"
+msgstr ""
+"Sección [%2d] '%s': no hay entradas de nota definidas para el tipo de "
+"archivo\n"
+
+#: src/elflint.c:672
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %d: %s\n"
+msgstr "Sección [%2d] '%s': no se puede obtener símbolo %d: %s\n"
+
+#: src/elflint.c:677 src/elflint.c:680 src/elflint.c:683 src/elflint.c:686
+#: src/elflint.c:689 src/elflint.c:692
+#, c-format
+msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n"
+msgstr "Sección [%2d] '%s': '%s' en la entrada zeroth no es cero\n"
+
+#: src/elflint.c:695
+#, c-format
+msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n"
+msgstr "sección [%2d] '%s': XINDEX en la entrada zeroth no es cero\n"
+
+#: src/elflint.c:705
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %zu: %s\n"
+msgstr "sección [%2d] '%s': no es posible obtener el símbolo %zu: %s\n"
+
+#: src/elflint.c:714
+#, c-format
+msgid "section [%2d] '%s': symbol %zu: invalid name value\n"
+msgstr "sección [%2d] '%s': símbolo %zu: valor de nombre inválido\n"
+
+#: src/elflint.c:729
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): too large section index but no extended "
+"section index section\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: el índice de sección es demasiado extenso, "
+"pero no la sección extendida de la sección de índice\n"
+
+#: src/elflint.c:735
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit "
+"in st_shndx (%<PRIu32>)\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: XINDEX es utilizado para índice que pueda "
+"caber en st_shndx (%<PRIu32>)\n"
+
+#. || sym->st_shndx > SHN_HIRESERVE  always false
+#: src/elflint.c:747
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): invalid section index\n"
+msgstr "sección [%2d] '%s': símbolo %zu: índice de sección inválido\n"
+
+#: src/elflint.c:755
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown type\n"
+msgstr "sección [%2d] '%s': símbolo %zu: tipo desconocido\n"
+
+#: src/elflint.c:761
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"
+msgstr "sección [%2d] '%s': símbolo %zu: asociación de símbolo desconocida\n"
+
+#: src/elflint.c:766
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"
+msgstr "Sección [%2d] '%s': símbolo %zu: símbolo único no de tipo de objeto\n"
+
+#: src/elflint.c:774
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable "
+"files\n"
+msgstr ""
+"sección [%2d] '%s': símbolo %zu: COMMON solo es permitido en archivos "
+"realojables\n"
+
+#: src/elflint.c:778
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: símbolos locales COMMON no tienen sentido\n"
+
+#: src/elflint.c:782
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: función en sección COMMON no tiene sentido\n"
+
+#: src/elflint.c:833
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"
+msgstr "sección [%2d] '%s': símbolo %zu: st_value fuera de límites\n"
+
+#: src/elflint.c:839 src/elflint.c:864 src/elflint.c:913
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu no se ajusta totalmente en la sección [%2d] "
+"'%s'\n"
+
+#: src/elflint.c:848
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not "
+"have SHF_TLS flag set\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: sección de referencia [%2d] '%s' no tiene "
+"establecida bandera SHF_TLS\n"
+
+#: src/elflint.c:858 src/elflint.c:906
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: st_value fuera de límites de sección de "
+"referencia [%2d] '%s'\n"
+
+#: src/elflint.c:885
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header "
+"entry\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: símbolo TLS, pero no hay entrada de "
+"programa TLS\n"
+
+#: src/elflint.c:891
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program "
+"header entry\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: símbolo TLS, pero no hay entrada de "
+"programa TLS\n"
+
+#: src/elflint.c:899
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value short of referenced section "
+"[%2d] '%s'\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: st_value falta sección de referencia [%2d] "
+"'%s'\n"
+
+#: src/elflint.c:926
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local symbol outside range described in "
+"sh_info\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: símbolo local fuera del rango descrito en "
+"sh_info\n"
+
+#: src/elflint.c:933
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): non-local symbol outside range "
+"described in sh_info\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: símbolo non-local fuera del rango descrito "
+"en sh_info\n"
+
+#: src/elflint.c:940
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"
+msgstr "Sección [%2d] '%s': símbolo %zu: símbolo de sección non-local\n"
+
+#: src/elflint.c:990
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section "
+"[%2d]\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo _GLOBAL_OFFSET_TABLE_ se refiere a sección "
+"errada [%2d]\n"
+
+#: src/elflint.c:997
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] "
+"'%s'\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo _GLOBAL_OFFSET_TABLE_ se refiere a sección [%2d] "
+"'%s'\n"
+
+#. This test is more strict than the psABIs which
+#. usually allow the symbol to be in the middle of
+#. the .got section, allowing negative offsets.
+#: src/elflint.c:1013
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#<PRIx64> does not "
+"match %s section address %#<PRIx64>\n"
+msgstr ""
+"Sección [%2d] '%s': valor del símbolo _GLOBAL_OFFSET_TABLE_ %#<PRIx64> no "
+"coincide con dirección de sección %s %#<PRIx64>\n"
+
+#: src/elflint.c:1020
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %<PRIu64> does not "
+"match %s section size %<PRIu64>\n"
+msgstr ""
+"Sección [%2d] '%s': tamaño de símbolo _GLOBAL_OFFSET_TABLE_ %<PRIu64> no "
+"coincide con tamaño de sección %s %<PRIu64>\n"
+
+#: src/elflint.c:1028
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got "
+"section\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo _GLOBAL_OFFSET_TABLE_ presente, pero no. sección "
+"got\n"
+
+#: src/elflint.c:1044
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC_ symbol value %#<PRIx64> does not match dynamic "
+"segment address %#<PRIx64>\n"
+msgstr ""
+"sección [%2d] '%s': Valor de símbolo _DYNAMIC_ %#<PRIx64> no coincide con la "
+"dirección de segmento%#<PRIx64>\n"
+
+#: src/elflint.c:1051
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC symbol size %<PRIu64> does not match dynamic "
+"segment size %<PRIu64>\n"
+msgstr ""
+"Sección [%2d] '%s': tamaño de símbolo _DYNAMIC %<PRIu64> no coincide con "
+"tamaño de segmento %<PRIu64>\n"
+
+#: src/elflint.c:1064
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-"
+"default visibility\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: símbolo en tabla de símbolos dinámicos sin "
+"visibilidad predeterminada\n"
+
+#: src/elflint.c:1068
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %zu: bit desconocido establecido en st_other\n"
+
+#: src/elflint.c:1106
+#, fuzzy, c-format
+msgid "section [%2d] '%s': cannot get section data.\n"
+msgstr "Sección [%2d] '%s': No se pueden obtener datos de sección\n"
+
+#: src/elflint.c:1122
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"
+msgstr "Sección [%2d] '%s': DT_RELCOUNT utilizada para esta sección RELA\n"
+
+#: src/elflint.c:1133 src/elflint.c:1186
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"
+msgstr ""
+"Sección [%2d] '%s': valor DT_RELCOUNT %d demasiado alto para esta sección\n"
+
+#: src/elflint.c:1158 src/elflint.c:1211
+#, c-format
+msgid ""
+"section [%2d] '%s': relative relocations after index %d as specified by "
+"DT_RELCOUNT\n"
+msgstr ""
+"Sección [%2d] '%s': reubicaciones relativas después de que el %d de índice "
+"haya sido especificado por DT_RELCOUNT\n"
+
+#: src/elflint.c:1164 src/elflint.c:1217
+#, c-format
+msgid ""
+"section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT "
+"specified %d relative relocations\n"
+msgstr ""
+"Sección [%2d] '%s': reubicación no-relativa en %zu de índice; DT_RELCOUNT "
+"especificado %d reubicaciones relativas\n"
+
+#: src/elflint.c:1176
+#, c-format
+msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n"
+msgstr "sección [%2d] '%s': DT_RELACOUNT utilizado para esta sección REL\n"
+
+#: src/elflint.c:1259
+#, c-format
+msgid "section [%2d] '%s': invalid destination section index\n"
+msgstr "Sección [%2d] '%s': índice de sección de destino inválido\n"
+
+#: src/elflint.c:1271
+#, c-format
+msgid "section [%2d] '%s': invalid destination section type\n"
+msgstr "Sección [%2d] '%s': tipo de sección de destino inválido\n"
+
+#: src/elflint.c:1279
+#, c-format
+msgid "section [%2d] '%s': sh_info should be zero\n"
+msgstr "Sección [%2d] '%s': sh_info debe ser cero\n"
+
+#: src/elflint.c:1287
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': no relocations for merge-able string sections possible\n"
+msgstr ""
+"Sección [%2d] '%s': no reubicaciones para secciones de fusión posibles\n"
+
+#: src/elflint.c:1365
+#, c-format
+msgid "text relocation flag set but there is no read-only segment\n"
+msgstr "Reubicación de bandera pero no hay segmento de sólo lectura\n"
+
+#: src/elflint.c:1392
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid type\n"
+msgstr "Sección [%2d] '%s': reubicación %zu: tipo inválido\n"
+
+#: src/elflint.c:1400
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: relocation type invalid for the file "
+"type\n"
+msgstr ""
+"Sección [%2d] '%s': reubicación %zu: tipo de reubicación inválido para el "
+"tipo de archivo\n"
+
+#: src/elflint.c:1408
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n"
+msgstr "Sección [%2d] '%s': reubicación %zu: índice de símbolo inválido\n"
+
+#: src/elflint.c:1426
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can "
+"be used with %s\n"
+msgstr ""
+"Sección [%2d] '%s': reubicación %zu: sólo el símbolo '_GLOBAL_OFFSET_TABLE_' "
+"puede utilizarse con %s\n"
+
+#: src/elflint.c:1443
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n"
+msgstr "Sección [%2d] '%s': reubicación %zu: compensación fuera de límites\n"
+
+#: src/elflint.c:1458
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: copy relocation against symbol of type "
+"%s\n"
+msgstr ""
+"Sección [%2d] '%s': reubicación %zu: reubicación de copia con símbolo de "
+"tipo %s\n"
+
+#: src/elflint.c:1479
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: read-only section modified but text "
+"relocation flag not set\n"
+msgstr ""
+"Sección [%2d] '%s': reubicación %zu: sección de sólo-lectura modificada, "
+"pero no se estableció bandera de reubicación\n"
+
+#: src/elflint.c:1494
+#, c-format
+msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n"
+msgstr ""
+"Sección [%2d] '%s': las reubicaciones se hacen con datos cargados y "
+"descargados\n"
+
+#: src/elflint.c:1534 src/elflint.c:1585
+#, c-format
+msgid "section [%2d] '%s': cannot get relocation %zu: %s\n"
+msgstr "Sección [%2d] '%s': no puede obtener reubicación %zu: %s\n"
+
+#: src/elflint.c:1687
+#, c-format
+msgid "more than one dynamic section present\n"
+msgstr "más de una sección dinámica presente\n"
+
+#: src/elflint.c:1705
+#, fuzzy, c-format
+msgid ""
+"section [%2d]: referenced as string table for section [%2d] '%s' but section "
+"link value is invalid\n"
+msgstr ""
+"sección [%2d] '%s': nombrado como una tabla de cadena para la sección [%2d] "
+"'%s' pero el tipo no es SHT_STRTAB\n"
+
+#: src/elflint.c:1713
+#, c-format
+msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"
+msgstr ""
+"Sección [%2d] '%s': tamaño de entrada de sección no coincide con ElfXX_Dyn\n"
+
+#: src/elflint.c:1718 src/elflint.c:2008
+#, c-format
+msgid "section [%2d] '%s': sh_info not zero\n"
+msgstr "Sección [%2d] '%s': sh_info no es cero\n"
+
+#: src/elflint.c:1728
+#, c-format
+msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"
+msgstr ""
+"Sección [%2d] '%s': no puede obtener entrada de sección dinámica %zu: %s\n"
+
+#: src/elflint.c:1736
+#, c-format
+msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"
+msgstr "Sección [%2d] '%s': entradas non-DT_NULL siguen a la entrada DT_NULL\n"
+
+#: src/elflint.c:1743
+#, c-format
+msgid "section [%2d] '%s': entry %zu: unknown tag\n"
+msgstr "Sección [%2d] '%s': entrada %zu: etiqueta desconocida\n"
+
+#: src/elflint.c:1754
+#, c-format
+msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n"
+msgstr "Sección [%2d] '%s': entrada %zu: más de una entrada con etiqueta %s\n"
+
+#: src/elflint.c:1764
+#, c-format
+msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n"
+msgstr "Sección [%2d] '%s': entrada %zu: nivel 2 etiqueta %s utilizada\n"
+
+#: src/elflint.c:1782
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %zu: el valor DT_PLTREL debe ser DT_REL or "
+"DT_RELA\n"
+
+#: src/elflint.c:1795
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: pointer does not match address of section "
+"[%2d] '%s' referenced by sh_link\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %zu: puntero no coincide con dirección de "
+"sección [%2d] '%s' al que hace referencia sh_link\n"
+
+#: src/elflint.c:1839
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %zu: valor %s debe apuntar en segmento cargado\n"
+
+#: src/elflint.c:1854
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must be valid offset in section "
+"[%2d] '%s'\n"
+msgstr ""
+"sección [%2d] '%s': entrada %zu: valor %s debe ser compensación válida en "
+"sección [%2d] '%s'\n"
+
+#: src/elflint.c:1874 src/elflint.c:1902
+#, c-format
+msgid "section [%2d] '%s': contains %s entry but not %s\n"
+msgstr "Sección [%2d] '%s': contiene entrada %s pero no %s\n"
+
+#: src/elflint.c:1886
+#, c-format
+msgid "section [%2d] '%s': mandatory tag %s not present\n"
+msgstr "Sección [%2d] '%s': etiqueta obligatoria %s no está presente\n"
+
+#: src/elflint.c:1895
+#, c-format
+msgid "section [%2d] '%s': no hash section present\n"
+msgstr "Sección [%2d] '%s': no hay sección de dispersión presente\n"
+
+#: src/elflint.c:1910 src/elflint.c:1917
+#, c-format
+msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n"
+msgstr "Sección [%2d] '%s': no todas las %s, %s, y %s están presentes\n"
+
+#: src/elflint.c:1927 src/elflint.c:1931
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"
+msgstr ""
+"Sección [%2d] '%s': etiqueta %s faltante en DSO marcada durante el pre-"
+"enlace\n"
+
+#: src/elflint.c:1937
+#, c-format
+msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n"
+msgstr ""
+"Sección [%2d] '%s': archivo no-DSO marcado como dependencia durante el pre-"
+"enlace\n"
+
+#: src/elflint.c:1948 src/elflint.c:1952 src/elflint.c:1956 src/elflint.c:1960
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in prelinked executable\n"
+msgstr "Sección [%2d] '%s': etiqueta %s faltante en pre-enlace ejecutable\n"
+
+#: src/elflint.c:1972
+#, c-format
+msgid ""
+"section [%2d] '%s': only relocatable files can have extended section index\n"
+msgstr ""
+"Sección [%2d] '%s': sólo los archivos reubicables pueden tener índice de "
+"sección extendido\n"
+
+#: src/elflint.c:1982
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index section not for symbol table\n"
+msgstr ""
+"Sección [%2d] '%s': índice de sección extendido no para tabla de símbolos\n"
+
+#: src/elflint.c:1986
+#, fuzzy, c-format
+msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"
+msgstr ""
+"Sección [%2d] '%s': índice de sección extendido no para tabla de símbolos\n"
+
+#: src/elflint.c:1991
+#, c-format
+msgid "cannot get data for symbol section\n"
+msgstr "no se puede obtener sección para símbolos\n"
+
+#: src/elflint.c:1994
+#, c-format
+msgid "section [%2d] '%s': entry size does not match Elf32_Word\n"
+msgstr "Sección [%2d] '%s': tamaño de entrada no coincide con Elf32_Word\n"
+
+#: src/elflint.c:2003
+#, c-format
+msgid "section [%2d] '%s': extended index table too small for symbol table\n"
+msgstr ""
+"Sección [%2d] '%s': tabla de índice extendida demasiado pequeña para tabla "
+"de símbolos\n"
+
+#: src/elflint.c:2018
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index in section [%2zu] '%s' refers to "
+"same symbol table\n"
+msgstr ""
+"Sección [%2d] '%s': índice de sección extendida en sección [%2zu] '%s' se "
+"refiere a la misma tabla de símbolos\n"
+
+#: src/elflint.c:2036
+#, c-format
+msgid "symbol 0 should have zero extended section index\n"
+msgstr "símbolo 0 debe tener índice de sección extendida cero\n"
+
+#: src/elflint.c:2048
+#, c-format
+msgid "cannot get data for symbol %zu\n"
+msgstr "no puede obtener datos para símbolo %zu\n"
+
+#: src/elflint.c:2053
+#, c-format
+msgid "extended section index is %<PRIu32> but symbol index is not XINDEX\n"
+msgstr ""
+"índice de sección extendida es %<PRIu32> pero índice de símbolo no es "
+"XINDEX\n"
+
+#: src/elflint.c:2070 src/elflint.c:2127
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"
+msgstr ""
+"Sección [%2d] '%s': sección de tabla de dispersión es demasiado pequeña (es "
+"%ld, se espera %ld)\n"
+
+#: src/elflint.c:2084 src/elflint.c:2141
+#, c-format
+msgid "section [%2d] '%s': chain array too large\n"
+msgstr "Sección [%2d] '%s': índice de la cadena es demasiado grande\n"
+
+#: src/elflint.c:2098 src/elflint.c:2155
+#, c-format
+msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n"
+msgstr ""
+"Sección [%2d] '%s': referencia de cubetas de dispersión %zu fuera de "
+"límites\n"
+
+#: src/elflint.c:2108
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n"
+msgstr ""
+"Sección [%2d] '%s': referencia de cadena de dispersión %zu fuera de límites\n"
+
+#: src/elflint.c:2165
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %<PRIu64> out of bounds\n"
+msgstr ""
+"Sección [%2d] '%s': referencia de cadena de dispersión %<PRIu64> fuera de "
+"límites\n"
+
+#: src/elflint.c:2178
+#, fuzzy, c-format
+msgid "section [%2d] '%s': not enough data\n"
+msgstr "Sección [%2d] '%s': no puede obtener datos: %s\n"
+
+#: src/elflint.c:2190
+#, fuzzy, c-format
+msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n"
+msgstr "Sección [%2d] '%s': tamaño de bitmask no es potencia de 2: %u\n"
+
+#: src/elflint.c:2206
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected at "
+"least %ld)\n"
+msgstr ""
+"Sección [%2d] '%s': sección de tabla de dispersión es demasiado pequeña (es "
+"%ld, se espera al menos least%ld)\n"
+
+#: src/elflint.c:2215
+#, c-format
+msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n"
+msgstr ""
+"Sección [%2d] '%s': segundo cambio de función de dispersión demasiado "
+"grande: %u\n"
+
+#: src/elflint.c:2249
+#, c-format
+msgid ""
+"section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"
+msgstr ""
+"Sección [%2d] '%s': cadena de dispersión para cubetas %zu inferior a "
+"polarización de índice de símbolo\n"
+
+#: src/elflint.c:2270
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %u referenced in chain for bucket %zu is "
+"undefined\n"
+msgstr ""
+"Sección [%2d] '%s': el símbolo %u al que se hace referencia en cadena para "
+"cubeta %zu es indefinido\n"
+
+#: src/elflint.c:2283
+#, c-format
+msgid ""
+"section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+"Sección [%2d] '%s': valor de dispersión para símbolo %u en cadena para "
+"cubeta %zu está errado\n"
+
+#: src/elflint.c:2292
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+"Sección [%2d] '%s': valor de dispersión para símbolo %u en cadena para "
+"cubeta %zu está errado\n"
+
+#: src/elflint.c:2322
+#, c-format
+msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n"
+msgstr ""
+"Sección [%2d] '%s': cadena de dispersión para cubeta %zu fuera de limites\n"
+
+#: src/elflint.c:2327
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"
+msgstr ""
+"Sección [%2d] '%s': referencia de símbolo en cadena para cubeta %zu fuera de "
+"límites\n"
+
+#: src/elflint.c:2333
+#, c-format
+msgid "section [%2d] '%s': bitmask does not match names in the hash table\n"
+msgstr ""
+"Sección [%2d] '%s': bitmask no coincide con nombres en la tabla de "
+"dispersión\n"
+
+#: src/elflint.c:2346
+#, c-format
+msgid "section [%2d] '%s': relocatable files cannot have hash tables\n"
+msgstr ""
+"Sección [%2d] '%s': archivos reubicables no pueden tener tablas de "
+"dispersión\n"
+
+#: src/elflint.c:2364
+#, c-format
+msgid "section [%2d] '%s': hash table not for dynamic symbol table\n"
+msgstr ""
+"Sección [%2d] '%s': tabla de dispersión no para tabla de símbolos dinámicos\n"
+
+#: src/elflint.c:2368
+#, fuzzy, c-format
+msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"
+msgstr "Sección [%2d] '%s': índice de sección de destino inválido\n"
+
+#: src/elflint.c:2378
+#, c-format
+msgid "section [%2d] '%s': hash table entry size incorrect\n"
+msgstr ""
+"Sección [%2d] '%s': tamaño incorrecto de entrada de tabla de dispersión\n"
+
+#: src/elflint.c:2383
+#, c-format
+msgid "section [%2d] '%s': not marked to be allocated\n"
+msgstr "Sección [%2d] '%s': no marcada para ser asignada\n"
+
+#: src/elflint.c:2388
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table has not even room for initial administrative "
+"entries\n"
+msgstr ""
+"Sección [%2d] '%s': tabla de dispersión no tiene ni siquiera espacio para "
+"entradas administrativas iniciales\n"
+
+#: src/elflint.c:2437
+#, c-format
+msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"
+msgstr ""
+"sh_link en secciones de dispersión [%2zu] '%s' y [%2zu] '%s' no son "
+"idénticas\n"
+
+#: src/elflint.c:2461 src/elflint.c:2526 src/elflint.c:2561
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' does not contain enough data\n"
+msgstr "sección [%2zu] '%s' no debe ser ejecutable\n"
+
+#: src/elflint.c:2482
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' has zero bit mask words\n"
+msgstr "Sección [%2d] '%s': grupo de sección sin palabra de banderas\n"
+
+#: src/elflint.c:2493 src/elflint.c:2537 src/elflint.c:2574
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' uses too much data\n"
+msgstr "sección [%2zu] '%s' debe ser asignada\n"
+
+#: src/elflint.c:2508
+#, c-format
+msgid ""
+"hash section [%2zu] '%s' invalid symbol index %<PRIu32> (max_nsyms: "
+"%<PRIu32>, nentries: %<PRIu32>\n"
+msgstr ""
+
+#: src/elflint.c:2595
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' invalid sh_entsize\n"
+msgstr "Sección [%2zu]: nombre inválido\n"
+
+#: src/elflint.c:2605 src/elflint.c:2609
+#, c-format
+msgid "section [%2zu] '%s': reference to symbol index 0\n"
+msgstr "Sección [%2zu] '%s': referencia al índice de símbolo 0\n"
+
+#: src/elflint.c:2616
+#, c-format
+msgid ""
+"symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+"Símbolo %d nombrado en nueva tabla de dispersión en [%2zu] '%s' pero no en "
+"la tabla de dispersión anterior en [%2zu] '%s'\n"
+
+#: src/elflint.c:2628
+#, c-format
+msgid ""
+"symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+"Símbolo %d nombrado en la tabla de dispersión anterior en [%2zu] '%s' pero "
+"no en la nueva tabla de dispersión en [%2zu] '%s'\n"
+
+#: src/elflint.c:2644
+#, c-format
+msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n"
+msgstr "Sección [%2d] '%s': nonzero sh_%s para sección NULL\n"
+
+#: src/elflint.c:2664
+#, c-format
+msgid ""
+"section [%2d] '%s': section groups only allowed in relocatable object files\n"
+msgstr ""
+"Sección [%2d] '%s': grupos de sección sólo permitidos en archivos de objeto "
+"reubicables\n"
+
+#: src/elflint.c:2675
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol table: %s\n"
+msgstr "Sección [%2d] '%s': no puede obtener tabla de símbolos: %s\n"
+
+#: src/elflint.c:2680
+#, c-format
+msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n"
+msgstr ""
+"Sección [%2d] '%s': referencia de sección en sh_link no es una tabla de "
+"símbolos\n"
+
+#: src/elflint.c:2686
+#, c-format
+msgid "section [%2d] '%s': invalid symbol index in sh_info\n"
+msgstr "Sección [%2d] '%s': índice de símbolo inválido en sh_info\n"
+
+#: src/elflint.c:2691
+#, c-format
+msgid "section [%2d] '%s': sh_flags not zero\n"
+msgstr "Sección [%2d] '%s': sh_flags no cero\n"
+
+#: src/elflint.c:2698
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol for signature\n"
+msgstr "Sección [%2d] '%s': no puede obtener símbolo para firma\n"
+
+#: src/elflint.c:2702
+#, fuzzy, c-format
+msgid "section [%2d] '%s': cannot get symbol name for signature\n"
+msgstr "Sección [%2d] '%s': no puede obtener símbolo para firma\n"
+
+#: src/elflint.c:2707
+#, c-format
+msgid "section [%2d] '%s': signature symbol cannot be empty string\n"
+msgstr ""
+"sección [%2d] '%s': el símbolo de firma no puede ser una cadena vacía\n"
+
+#: src/elflint.c:2713
+#, c-format
+msgid "section [%2d] '%s': sh_flags not set correctly\n"
+msgstr "Sección [%2d] '%s': sh_flags no establecida correctamente\n"
+
+#: src/elflint.c:2719
+#, c-format
+msgid "section [%2d] '%s': cannot get data: %s\n"
+msgstr "Sección [%2d] '%s': no puede obtener datos: %s\n"
+
+#: src/elflint.c:2728
+#, c-format
+msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"
+msgstr ""
+"Sección [%2d] '%s': tamaño de sección no es múltiplo de tamaño de "
+"(Elf32_Word)\n"
+
+#: src/elflint.c:2734
+#, c-format
+msgid "section [%2d] '%s': section group without flags word\n"
+msgstr "Sección [%2d] '%s': grupo de sección sin palabra de banderas\n"
+
+#: src/elflint.c:2742
+#, c-format
+msgid "section [%2d] '%s': section group without member\n"
+msgstr "Sección [%2d] '%s': grupo de sección sin miembro\n"
+
+#: src/elflint.c:2746
+#, c-format
+msgid "section [%2d] '%s': section group with only one member\n"
+msgstr "Sección [%2d] '%s': grupo de sección con sólo un miembro\n"
+
+#: src/elflint.c:2757
+#, c-format
+msgid "section [%2d] '%s': unknown section group flags\n"
+msgstr "Sección [%2d] '%s': banderas de grupo de sección desconocido\n"
+
+#: src/elflint.c:2769
+#, fuzzy, c-format
+msgid "section [%2d] '%s': section index %zu out of range\n"
+msgstr "Sección [%2d] '%s': índice de sección %Zu fuera de rango\n"
+
+#: src/elflint.c:2778
+#, c-format
+msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n"
+msgstr ""
+"Sección [%2d] '%s': no se puede obtener encabezamiento de sección para "
+"elemento %zu: %s\n"
+
+#: src/elflint.c:2785
+#, c-format
+msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n"
+msgstr "Sección [%2d] '%s': grupo de sección contiene otro grupo [%2d] '%s'\n"
+
+#: src/elflint.c:2791
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': element %zu references section [%2d] '%s' without "
+"SHF_GROUP flag set\n"
+msgstr ""
+"Sección [%2d] '%s': elemento %Zu hace referencia a sección [%2d] '%s' sin "
+"establecer bandera SHF_GROUP\n"
+
+#: src/elflint.c:2798
+#, c-format
+msgid "section [%2d] '%s' is contained in more than one section group\n"
+msgstr "Sección [%2d] '%s' está contenida en más de un grupo de sección\n"
+
+#: src/elflint.c:2995
+#, c-format
+msgid ""
+"section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no "
+"dynamic symbol table\n"
+msgstr ""
+"Sección [%2d] '%s' se refiere en sh_link a la sección [%2d] '%s' la cual no "
+"es una tabla de símbolos dinámicos\n"
+
+#: src/elflint.c:3007
+#, c-format
+msgid ""
+"section [%2d] '%s' has different number of entries than symbol table [%2d] "
+"'%s'\n"
+msgstr ""
+"Sección [%2d] '%s' tiene un número diferente de entradas a la de la tabla de "
+"símbolos [%2d] '%s'\n"
+
+#: src/elflint.c:3023
+#, c-format
+msgid "section [%2d] '%s': symbol %d: cannot read version data\n"
+msgstr ""
+"Sección [%2d] '%s': el símbolo %d: no se pueden leer datos de versión\n"
+
+#: src/elflint.c:3039
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n"
+msgstr ""
+"Sección [%2d] '%s': el símbolo %d: el símbolo local con alcance mundial\n"
+
+#: src/elflint.c:3047
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with version\n"
+msgstr "Sección [%2d] '%s': símbolo %d: símbolo local con versión\n"
+
+#: src/elflint.c:3061
+#, c-format
+msgid "section [%2d] '%s': symbol %d: invalid version index %d\n"
+msgstr "Sección [%2d] '%s': símbolo %d: índice de versión inválida %d\n"
+
+#: src/elflint.c:3066
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for defined version\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %d: índice de versión %d es para versión "
+"definida\n"
+
+#: src/elflint.c:3076
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for requested version\n"
+msgstr ""
+"Sección [%2d] '%s': símbolo %d: índice de versión %d es para la versión "
+"solicitada\n"
+
+#: src/elflint.c:3129
+#, c-format
+msgid "more than one version reference section present\n"
+msgstr "Más de una sección de referencia de versión presente\n"
+
+#: src/elflint.c:3137 src/elflint.c:3284
+#, c-format
+msgid "section [%2d] '%s': sh_link does not link to string table\n"
+msgstr "Sección [%2d] '%s': sh_link no se enlaza a la tabla de cadenas\n"
+
+#: src/elflint.c:3162 src/elflint.c:3338
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong version %d\n"
+msgstr "Sección [%2d] '%s': entrada %d tiene versión %d errada\n"
+
+#: src/elflint.c:3169 src/elflint.c:3345
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %d tiene compensación errada de datos "
+"auxiliares\n"
+
+#: src/elflint.c:3179
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid file reference\n"
+msgstr "Sección [%2d] '%s': entrada %d tiene referencia de archivo inválida\n"
+
+#: src/elflint.c:3187
+#, c-format
+msgid "section [%2d] '%s': entry %d references unknown dependency\n"
+msgstr "Sección [%2d] '%s': %d hace referencia a dependencia desconocida\n"
+
+#: src/elflint.c:3199
+#, c-format
+msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"
+msgstr ""
+"sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene bandera "
+"desconocida\n"
+
+#: src/elflint.c:3207
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has invalid name "
+"reference\n"
+msgstr ""
+"Sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene referencia de "
+"nombre inválida\n"
+
+#: src/elflint.c:3216
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: "
+"%#x, expected %#x\n"
+msgstr ""
+"Sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene valor de "
+"dispersión: %#x, esperado %#x\n"
+
+#: src/elflint.c:3225
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version "
+"name '%s'\n"
+msgstr ""
+"sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene nombre duplicado "
+"'%s'\n"
+
+#: src/elflint.c:3236
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"
+msgstr ""
+"sección [%2d] '%s': entrada auxiliar %d de entrada %d tiene próximo campo "
+"errado\n"
+
+#: src/elflint.c:3253 src/elflint.c:3429
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n"
+msgstr ""
+"sección [%2d] '%s': entrada %d tiene compensación inválida para próxima "
+"entrada\n"
+
+#: src/elflint.c:3261 src/elflint.c:3437
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says "
+"there are more entries\n"
+msgstr ""
+"sección [%2d] '%s': entrada %d tiene compensación inválida para próxima "
+"entrada\n"
+
+#: src/elflint.c:3276
+#, c-format
+msgid "more than one version definition section present\n"
+msgstr "más de una definición de versión presente de sección\n"
+
+#: src/elflint.c:3323
+#, c-format
+msgid "section [%2d] '%s': more than one BASE definition\n"
+msgstr "Sección [%2d] '%s': más de una definición de BASE\n"
+
+#: src/elflint.c:3327
+#, c-format
+msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"
+msgstr ""
+"Sección [%2d] '%s': definición de BASE debe tener índice VER_NDX_GLOBAL\n"
+
+#: src/elflint.c:3333
+#, c-format
+msgid "section [%2d] '%s': entry %d has unknown flag\n"
+msgstr "Sección [%2d] '%s': entrada %d tiene bandera desconocida\n"
+
+#: src/elflint.c:3360
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid name reference\n"
+msgstr "Sección [%2d] '%s': entrada %d tiene referencia de nombre inválida\n"
+
+#: src/elflint.c:3367
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %d tiene valor de dispersión errado: %#x, "
+"esperado %#x\n"
+
+#: src/elflint.c:3375
+#, c-format
+msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %d tiene nombre de versión duplicado '%s'\n"
+
+#: src/elflint.c:3395
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %d tiene referencia de nombre inválida en datos "
+"auxiliares\n"
+
+#: src/elflint.c:3412
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"
+msgstr ""
+"Sección [%2d] '%s': entrada %d tiene próximo campo errado en datos "
+"auxiliares\n"
+
+#: src/elflint.c:3445
+#, c-format
+msgid "section [%2d] '%s': no BASE definition\n"
+msgstr "Sección [%2d] '%s': no hay definición de BASE\n"
+
+#: src/elflint.c:3461
+#, c-format
+msgid "section [%2d] '%s': unknown parent version '%s'\n"
+msgstr "Sección [%2d] '%s': desconocida versión principal '%s'\n"
+
+#: src/elflint.c:3486
+#, c-format
+msgid "section [%2d] '%s': empty object attributes section\n"
+msgstr "Sección [%2d] '%s': sección de atributos de objeto vacío\n"
+
+#: src/elflint.c:3502
+#, c-format
+msgid "section [%2d] '%s': unrecognized attribute format\n"
+msgstr "Sección[%2d] '%s': formato de atributo no reconocido\n"
+
+#: src/elflint.c:3513
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute section\n"
+msgstr ""
+"Sección[%2d] '%s': compensación %zu: campo de longitud cero en sección de "
+"atributo\n"
+
+#: src/elflint.c:3522
+#, c-format
+msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n"
+msgstr ""
+"Sección[%2d] '%s': compensación %zu: longitud inválida en sección de "
+"atributo\n"
+
+#: src/elflint.c:3534
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n"
+msgstr ""
+"Sección[%2d] '%s': compensación %zu: cadena de nombre de proveedor sin "
+"terminar\n"
+
+#: src/elflint.c:3551
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: sin fin ULEB128 en etiqueta de sub-"
+"sección de atributo\n"
+
+#: src/elflint.c:3560
+#, c-format
+msgid "section [%2d] '%s': offset %zu: truncated attribute section\n"
+msgstr "Sección [%2d] '%s': compensación %zu: sección de atributo truncado\n"
+
+#: src/elflint.c:3569
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: campo de longitud cero length en sub-"
+"sección de atributo\n"
+
+#: src/elflint.c:3584
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: longitud inválida en sub-sección de "
+"atributo\n"
+
+#. Tag_File
+#: src/elflint.c:3595
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"
+msgstr ""
+"Sección[%2d] '%s': compensación %zu: sub-sección de atributo tiene etiqueta "
+"inesperada %u\n"
+
+#: src/elflint.c:3616
+#, c-format
+msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"
+msgstr ""
+"Sección[%2d] '%s': compensación %zu: sin fin ULEB128 en etiqueta de "
+"atributo\n"
+
+#: src/elflint.c:3627
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: cadena sin terminar en atributo\n"
+
+#: src/elflint.c:3640
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: etiqueta de atributo no reconocida %u\n"
+
+#: src/elflint.c:3644
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: unrecognized %s attribute value %<PRIu64>\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: no reconocido %s valor de atributo "
+"%<PRIu64>\n"
+
+#: src/elflint.c:3654
+#, c-format
+msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n"
+msgstr "Sección [%2d] '%s': compensación %zu: proveedor '%s' desconocido\n"
+
+#: src/elflint.c:3660
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"
+msgstr ""
+"Sección [%2d] '%s': compensación %zu: extra bytes después de la última "
+"sección de atributo\n"
+
+#: src/elflint.c:3758
+#, c-format
+msgid "cannot get section header of zeroth section\n"
+msgstr "no puede obtener encabezamiento de sección de sección zeroth\n"
+
+#: src/elflint.c:3762
+#, c-format
+msgid "zeroth section has nonzero name\n"
+msgstr "Sección zeroth tiene nombre nonzero\n"
+
+#: src/elflint.c:3764
+#, c-format
+msgid "zeroth section has nonzero type\n"
+msgstr "Sección zeroth tiene tipo nonzero\n"
+
+#: src/elflint.c:3766
+#, c-format
+msgid "zeroth section has nonzero flags\n"
+msgstr "Sección zeroth tiene banderas nonzero\n"
+
+#: src/elflint.c:3768
+#, c-format
+msgid "zeroth section has nonzero address\n"
+msgstr "Sección zeroth tiene dirección nonzero\n"
+
+#: src/elflint.c:3770
+#, c-format
+msgid "zeroth section has nonzero offset\n"
+msgstr "Sección zeroth tiene compensación nonzero\n"
+
+#: src/elflint.c:3772
+#, c-format
+msgid "zeroth section has nonzero align value\n"
+msgstr "Sección zeroth tiene valor de alineación nonzero\n"
+
+#: src/elflint.c:3774
+#, c-format
+msgid "zeroth section has nonzero entry size value\n"
+msgstr "Sección zeroth tiene valor de tamaño de entrada nonzero\n"
+
+#: src/elflint.c:3777
+#, c-format
+msgid ""
+"zeroth section has nonzero size value while ELF header has nonzero shnum "
+"value\n"
+msgstr ""
+"Sección zeroth tiene valor de tamaño nonzero mientras que el encabezamiento "
+"ELF tiene valor shnum nonzero\n"
+
+#: src/elflint.c:3781
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in shstrndx\n"
+msgstr ""
+"Sección zeroth tiene valor de enlace nonzero mientras que el encabezamiento "
+"ELF no señala sobreflujo en shstrndx\n"
+
+#: src/elflint.c:3785
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in phnum\n"
+msgstr ""
+"la sección zeroth tiene un valor de enlace distinto a cero mientras que el "
+"encabezamiento ELF no señala desbordamiento en phnum\n"
+
+#: src/elflint.c:3803
+#, c-format
+msgid "cannot get section header for section [%2zu] '%s': %s\n"
+msgstr "No se puede obtener encabezamiento para sección [%2zu] '%s': %s\n"
+
+#: src/elflint.c:3812
+#, c-format
+msgid "section [%2zu]: invalid name\n"
+msgstr "Sección [%2zu]: nombre inválido\n"
+
+#: src/elflint.c:3839
+#, c-format
+msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n"
+msgstr "Sección [%2d] '%s' tiene tipo errado: %s esperado, es %s\n"
+
+#: src/elflint.c:3856
+#, c-format
+msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n"
+msgstr "Sección [%2zu] '%s' tiene banderas erradas: %s esperado, es %s\n"
+
+#: src/elflint.c:3874
+#, c-format
+msgid ""
+"section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"
+msgstr ""
+"Sección [%2zu] '%s' tiene banderas erradas: %s esperado y posiblemente %s, "
+"es %s\n"
+
+#: src/elflint.c:3891
+#, c-format
+msgid "section [%2zu] '%s' present in object file\n"
+msgstr "Sección [%2zu] '%s' presente en archivo objeto\n"
+
+#: src/elflint.c:3897 src/elflint.c:3929
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"
+msgstr ""
+"Sección [%2zu] '%s' tiene bandera SHF_ALLOC establecida pero no es un "
+"segmento cargable\n"
+
+#: src/elflint.c:3902 src/elflint.c:3934
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable "
+"segments\n"
+msgstr ""
+"Sección [%2zu] '%s' no tiene bandera SHF_ALLOC establecida pero hay "
+"segmentos cargables\n"
+
+#: src/elflint.c:3910
+#, c-format
+msgid ""
+"section [%2zu] '%s' is extension section index table in non-object file\n"
+msgstr ""
+"Sección [%2zu] '%s' es tabla de índice de sección de extensión en archivo no-"
+"objeto\n"
+
+#: src/elflint.c:3953
+#, c-format
+msgid "section [%2zu] '%s': size not multiple of entry size\n"
+msgstr "Sección [%2zu] '%s': tamaño no es múltiplo de tamaño de entrada\n"
+
+#: src/elflint.c:3958
+#, c-format
+msgid "cannot get section header\n"
+msgstr "no se puede obtener encabezamiento de sección\n"
+
+#: src/elflint.c:3968
+#, c-format
+msgid "section [%2zu] '%s' has unsupported type %d\n"
+msgstr "sección [%2zu] '%s' tiene tipo %d incompatible \n"
+
+#: src/elflint.c:3988
+#, c-format
+msgid ""
+"section [%2zu] '%s' contains invalid processor-specific flag(s) %#<PRIx64>\n"
+msgstr ""
+"Sección [%2zu] '%s' contiene bandera(s) de procesador-específico inválidas "
+"%#<PRIx64>\n"
+
+#: src/elflint.c:3998
+#, c-format
+msgid "section [%2zu] '%s' contains unknown flag(s) %#<PRIx64>\n"
+msgstr "Sección [%2zu] '%s' contiene bandera(s) desconocidas %#<PRIx64>\n"
+
+#: src/elflint.c:4006
+#, c-format
+msgid "section [%2zu] '%s': thread-local data sections address not zero\n"
+msgstr ""
+"Sección [%2zu] '%s': dirección de secciones de datos de hilo-local no cero\n"
+
+#: src/elflint.c:4016
+#, fuzzy, c-format
+msgid "section [%2zu] '%s': allocated section cannot be compressed\n"
+msgstr ""
+"Sección [%2zu] '%s': dirección de secciones de datos de hilo-local no cero\n"
+
+#: src/elflint.c:4021
+#, fuzzy, c-format
+msgid "section [%2zu] '%s': nobits section cannot be compressed\n"
+msgstr "Sección [%2d] '%s': no hay sección de dispersión presente\n"
+
+#: src/elflint.c:4027
+#, fuzzy, c-format
+msgid ""
+"section [%2zu] '%s': compressed section with no compression header: %s\n"
+msgstr "Sección [%2d] '%s': grupo de sección con sólo un miembro\n"
+
+#: src/elflint.c:4033
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in link value\n"
+msgstr ""
+"Sección [%2zu] '%s': referencia de sección inválida en valor de enlace\n"
+
+#: src/elflint.c:4038
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in info value\n"
+msgstr ""
+"Sección [%2zu] '%s': referencia de sección inválida en valor de información\n"
+
+#: src/elflint.c:4045
+#, c-format
+msgid "section [%2zu] '%s': strings flag set without merge flag\n"
+msgstr ""
+"Sección [%2zu] '%s': bandera de cadenas establecida sin bandera de fusión\n"
+
+#: src/elflint.c:4050
+#, c-format
+msgid "section [%2zu] '%s': merge flag set but entry size is zero\n"
+msgstr ""
+"Sección [%2zu] '%s': bandera de fusión establecida pero tamaño de entrada es "
+"cero\n"
+
+#: src/elflint.c:4069
+#, c-format
+msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n"
+msgstr ""
+"Sección [%2zu] '%s' tiene un tipo %d inesperado para una sección ejecutable\n"
+
+#: src/elflint.c:4078
+#, fuzzy, c-format
+msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"
+msgstr "sección [%2zu] '%s' no debe tener permiso de escritura\n"
+
+#: src/elflint.c:4085
+#, c-format
+msgid "section [%2zu] '%s' is both executable and writable\n"
+msgstr "Sección [%2zu] '%s' es tanto de ejecución como de escritura\n"
+
+#: src/elflint.c:4116
+#, c-format
+msgid ""
+"section [%2zu] '%s' not fully contained in segment of program header entry "
+"%d\n"
+msgstr ""
+"Sección [%2zu] '%s' no contenida totalmente en segmento de entrada de "
+"encabezamiento de programa %d\n"
+
+#: src/elflint.c:4126
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d\n"
+msgstr ""
+"Sección [%2zu] '%s' no tiene tipo NOBITS pero es leída desde el archivo en "
+"segmento de entrada de encabezamiento de programa %d\n"
+
+#: src/elflint.c:4152
+#, fuzzy, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d and file contents is non-zero\n"
+msgstr ""
+"Sección [%2zu] '%s' no tiene tipo NOBITS pero es leída desde el archivo en "
+"segmento de entrada de encabezamiento de programa %d\n"
+
+#: src/elflint.c:4163
+#, c-format
+msgid ""
+"section [%2zu] '%s' has not type NOBITS but is not read from the file in "
+"segment of program header entry %d\n"
+msgstr ""
+"Sección [%2zu] '%s' no tiene tipo NOBITS pero no es leída desde el fichero "
+"en segmento de entrada de encabezamiento de programa %d\n"
+
+#: src/elflint.c:4174
+#, c-format
+msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n"
+msgstr "Sección [%2zu] '%s' es ejecutable en segmento no ejecutable %d\n"
+
+#: src/elflint.c:4184
+#, c-format
+msgid "section [%2zu] '%s' is writable in unwritable segment %d\n"
+msgstr ""
+"Sección [%2zu] '%s' es de escritura en segmento que no es de escritura %d\n"
+
+#: src/elflint.c:4194
+#, c-format
+msgid ""
+"section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"
+msgstr ""
+"Sección [%2zu] '%s': asignación de bandera establecida pero sección no en "
+"ningún segmento cargado\n"
+
+#: src/elflint.c:4200
+#, c-format
+msgid ""
+"section [%2zu] '%s': ELF header says this is the section header string table "
+"but type is not SHT_TYPE\n"
+msgstr ""
+"Sección [%2zu] '%s': encabezamiento ELF dice esta es la tabla de cadena de "
+"encabezamiento de sección, pero el tipo no es SHT_TYPE\n"
+
+#: src/elflint.c:4208
+#, c-format
+msgid ""
+"section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"
+msgstr ""
+"sección [%2zu] '%s': ficheros reubicables no pueden tener tablas de símbolos "
+"dinámicos\n"
+
+#: src/elflint.c:4263
+#, c-format
+msgid "more than one version symbol table present\n"
+msgstr "Más de una tabla de símbolos presente\n"
+
+#: src/elflint.c:4286
+#, c-format
+msgid "INTERP program header entry but no .interp section\n"
+msgstr ""
+"Entrada de encabezamiento de programa INTERP pero no la sección .interp\n"
+
+#: src/elflint.c:4297
+#, c-format
+msgid ""
+"loadable segment [%u] is executable but contains no executable sections\n"
+msgstr ""
+"segmento cargable [%u] es ejecutable pero no contiene secciones ejecutables\n"
+
+#: src/elflint.c:4303
+#, c-format
+msgid "loadable segment [%u] is writable but contains no writable sections\n"
+msgstr ""
+"segmento cargable [%u] es de escritura pero contiene secciones protegidas "
+"contra escritura\n"
+
+#: src/elflint.c:4314
+#, c-format
+msgid ""
+"no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section "
+"exist\n"
+msgstr ""
+"Sección no .gnu.versym presente, pero la sección .gnu.versym_d o la sección ."
+"gnu.versym_r existen\n"
+
+#: src/elflint.c:4327
+#, c-format
+msgid "duplicate version index %d\n"
+msgstr "Duplicar índice de versión %d\n"
+
+#: src/elflint.c:4341
+#, c-format
+msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"
+msgstr ""
+"Sección .gnu.versym presente sin las secciones .gnu.versym_d o .gnu."
+"versym_r\n"
+
+#: src/elflint.c:4390
+#, c-format
+msgid "phdr[%d]: unknown core file note type %<PRIu32> at offset %<PRIu64>\n"
+msgstr ""
+"phdr[%d]: tipo de nota de fichero core desconocido %<PRIu32> en compensación "
+"%<PRIu64>\n"
+
+#: src/elflint.c:4394
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': unknown core file note type %<PRIu32> at offset %zu\n"
+msgstr ""
+"Sección [%2d] '%s': tipo de nota de fichero core desconocido %<PRIu32> en "
+"compensación %Zu\n"
+
+#: src/elflint.c:4450
+#, fuzzy, c-format
+msgid ""
+"phdr[%d]: unknown object file note type %<PRIu32> with owner name '%s' at "
+"offset %zu\n"
+msgstr ""
+"phdr[%d]: tipo de nota de fichero objeto desconocido %<PRIu32> en "
+"compensación %Zu\n"
+
+#: src/elflint.c:4455
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': unknown object file note type %<PRIu32> with owner name "
+"'%s' at offset %zu\n"
+msgstr ""
+"Sección [%2d] '%s': tipo de nota de fichero objeto desconocido %<PRIu32> en "
+"compensación %Zu\n"
+
+#: src/elflint.c:4474
+#, c-format
+msgid "phdr[%d]: no note entries defined for the type of file\n"
+msgstr "phdr[%d]: no hay entradas de nota definidas para el tipo de archivo\n"
+
+#: src/elflint.c:4494
+#, c-format
+msgid "phdr[%d]: cannot get content of note section: %s\n"
+msgstr "phdr[%d]: no puede obtener contenido de sección de nota: %s\n"
+
+#: src/elflint.c:4497
+#, c-format
+msgid "phdr[%d]: extra %<PRIu64> bytes after last note\n"
+msgstr "phdr[%d]: extra %<PRIu64> bytes después de la última nota\n"
+
+#: src/elflint.c:4518
+#, c-format
+msgid "section [%2d] '%s': no note entries defined for the type of file\n"
+msgstr ""
+"Sección [%2d] '%s': no hay entradas de nota definidas para el tipo de "
+"archivo\n"
+
+#: src/elflint.c:4525
+#, c-format
+msgid "section [%2d] '%s': cannot get content of note section\n"
+msgstr ""
+"Sección[%2d] '%s': no se puede obtener el contenido de sección de nota\n"
+
+#: src/elflint.c:4528
+#, c-format
+msgid "section [%2d] '%s': extra %<PRIu64> bytes after last note\n"
+msgstr "Sección[%2d] '%s': extra %<PRIu64> bytes después de la última nota\n"
+
+#: src/elflint.c:4546
+#, c-format
+msgid ""
+"only executables, shared objects, and core files can have program headers\n"
+msgstr ""
+"Sólo ejecutables, objetos compartidos y ficheros core pueden tener "
+"encabezamientos de programas\n"
+
+#: src/elflint.c:4561
+#, c-format
+msgid "cannot get program header entry %d: %s\n"
+msgstr "no se puede obtener entrada de encabezamiento %d: %s\n"
+
+#: src/elflint.c:4571
+#, c-format
+msgid "program header entry %d: unknown program header entry type %#<PRIx64>\n"
+msgstr ""
+"entrada de encabezamiento de programa %d: tipo %#<PRIx64> de entrada de "
+"encabezamiento de programa desconocido\n"
+
+#: src/elflint.c:4582
+#, c-format
+msgid "more than one INTERP entry in program header\n"
+msgstr "Más de una entrada INTERP en encabezamiento de programa\n"
+
+#: src/elflint.c:4590
+#, c-format
+msgid "more than one TLS entry in program header\n"
+msgstr "más de una entrada TLS en encabezamiento de programa\n"
+
+#: src/elflint.c:4597
+#, c-format
+msgid "static executable cannot have dynamic sections\n"
+msgstr "ejecutable estático no puede tener secciones dinámicas\n"
+
+#: src/elflint.c:4611
+#, c-format
+msgid "dynamic section reference in program header has wrong offset\n"
+msgstr ""
+"Referencia de sección dinámica en encabezamiento de programa tiene "
+"compensación errada\n"
+
+#: src/elflint.c:4614
+#, c-format
+msgid "dynamic section size mismatch in program and section header\n"
+msgstr ""
+"No coinciden tamaño de sección dinámica en programa y encabezamiento de "
+"sección\n"
+
+#: src/elflint.c:4624
+#, c-format
+msgid "more than one GNU_RELRO entry in program header\n"
+msgstr "Más de una entrada GNU_RELRO en encabezamiento de programa\n"
+
+#: src/elflint.c:4645
+#, c-format
+msgid "loadable segment GNU_RELRO applies to is not writable\n"
+msgstr "Segmento cargable GNU_RELRO que se aplica no es de escritura\n"
+
+#: src/elflint.c:4656
+#, c-format
+msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"
+msgstr ""
+"Banderas de segmento cargable [%u] no coinciden con banderas GNU_RELRO [%u]\n"
+
+#: src/elflint.c:4663
+#, c-format
+msgid ""
+"GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"
+msgstr ""
+
+#: src/elflint.c:4672 src/elflint.c:4695
+#, c-format
+msgid "%s segment not contained in a loaded segment\n"
+msgstr "Segmento %s no contenido en un segmento cargable\n"
+
+#: src/elflint.c:4701
+#, c-format
+msgid "program header offset in ELF header and PHDR entry do not match"
+msgstr ""
+"Compensación de encabezamiento de programa en encabezamiento ELF y entrada "
+"PHDR no coinciden"
+
+#: src/elflint.c:4728
+#, c-format
+msgid "call frame search table reference in program header has wrong offset\n"
+msgstr ""
+"Referencia de tabla de búsqueda de marco de llamada en encabezamiento de "
+"programa tiene una compensación errada\n"
+
+#: src/elflint.c:4731
+#, c-format
+msgid "call frame search table size mismatch in program and section header\n"
+msgstr ""
+"Tamaño de tabla de búsqueda de marco de llamada no coincide con programa y "
+"encabezamiento de sección\n"
+
+#: src/elflint.c:4744
+#, c-format
+msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"
+msgstr "PT_GNU_EH_FRAME presente pero no la sección.eh_frame_hdr\n"
+
+#: src/elflint.c:4752
+#, c-format
+msgid "call frame search table must be allocated\n"
+msgstr "tabla de búsqueda de marco de llamada debe ser asignada\n"
+
+#: src/elflint.c:4755
+#, c-format
+msgid "section [%2zu] '%s' must be allocated\n"
+msgstr "sección [%2zu] '%s' debe ser asignada\n"
+
+#: src/elflint.c:4759
+#, c-format
+msgid "call frame search table must not be writable\n"
+msgstr ""
+"tabla de búsqueda de marco de llamada no debe tener permiso de escritura\n"
+
+#: src/elflint.c:4762
+#, c-format
+msgid "section [%2zu] '%s' must not be writable\n"
+msgstr "sección [%2zu] '%s' no debe tener permiso de escritura\n"
+
+#: src/elflint.c:4767
+#, c-format
+msgid "call frame search table must not be executable\n"
+msgstr "tabla de búsqueda de marco de llamada no debe ser ejecutable\n"
+
+#: src/elflint.c:4770
+#, c-format
+msgid "section [%2zu] '%s' must not be executable\n"
+msgstr "sección [%2zu] '%s' no debe ser ejecutable\n"
+
+#: src/elflint.c:4784
+#, c-format
+msgid "program header entry %d: file size greater than memory size\n"
+msgstr ""
+"entrada de encabezamiento de programa %d: tamaño de fichero mayor que el "
+"tamaño de memoria\n"
+
+#: src/elflint.c:4791
+#, c-format
+msgid "program header entry %d: alignment not a power of 2\n"
+msgstr ""
+"entrada de encabezamiento de programa %d: alineamiento no es potencia de 2\n"
+
+#: src/elflint.c:4794
+#, c-format
+msgid ""
+"program header entry %d: file offset and virtual address not module of "
+"alignment\n"
+msgstr ""
+"entrada de encabezamiento de programa %d: compensación de fichero y "
+"dirección virtual no módulo de alineación\n"
+
+#: src/elflint.c:4807
+#, c-format
+msgid ""
+"executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME "
+"program header entry"
+msgstr ""
+"ejecutable/DSO con sección .eh_frame_hdr no tiene una entrada de "
+"encabezamiento de programa PT_GNU_EH_FRAME"
+
+#: src/elflint.c:4841
+#, c-format
+msgid "cannot read ELF header: %s\n"
+msgstr "No se puede leer encabezamiento ELF: %s\n"
+
+#: src/elflint.c:4853
+#, fuzzy, c-format
+msgid "cannot create backend for ELF file\n"
+msgstr "no sepuede crear fichero nuevo"
+
+#: src/elflint.c:4874
+#, c-format
+msgid "text relocation flag set but not needed\n"
+msgstr "Bandera de reubicación de texto establecida pero no necesaria\n"
+
+#: src/findtextrel.c:60
+msgid "Input Selection:"
+msgstr "Selección de entrada:"
+
+#: src/findtextrel.c:61
+msgid "Prepend PATH to all file names"
+msgstr "Agregar RUTA a todos los nombres de ficheros"
+
+#: src/findtextrel.c:63
+msgid "Use PATH as root of debuginfo hierarchy"
+msgstr "Usar RUTA como root de jerarquía de debuginfo"
+
+#. Short description of program.
+#: src/findtextrel.c:70
+msgid "Locate source of text relocations in FILEs (a.out by default)."
+msgstr ""
+"Localizar origen de reubicaciones de texto en FICHEROS (a.out por defecto)."
+
+#. Strings for arguments in help texts.
+#: src/findtextrel.c:74 src/nm.c:107 src/objdump.c:70 src/size.c:79
+#: src/strings.c:86 src/strip.c:100
+msgid "[FILE...]"
+msgstr "[FICHERO...]"
+
+#: src/findtextrel.c:223
+#, c-format
+msgid "cannot get ELF header '%s': %s"
+msgstr "No se puede obtener encabezamiento ELF '%s': %s"
+
+#: src/findtextrel.c:234
+#, c-format
+msgid "'%s' is not a DSO or PIE"
+msgstr "'%s' es no un DSO o PIE"
+
+#: src/findtextrel.c:254
+#, c-format
+msgid "getting get section header of section %zu: %s"
+msgstr "obtener encabezamiento de sección get de sección %zu: %s"
+
+#: src/findtextrel.c:278
+#, c-format
+msgid "cannot read dynamic section: %s"
+msgstr "No se puede leer sección dinámica: %s"
+
+#: src/findtextrel.c:299
+#, c-format
+msgid "no text relocations reported in '%s'"
+msgstr "no hay reubicaciones de texto reportado en '%s'"
+
+#: src/findtextrel.c:310
+#, c-format
+msgid "while reading ELF file"
+msgstr "Error al leer fichero ELF"
+
+#: src/findtextrel.c:314
+#, fuzzy, c-format
+msgid "cannot get program header count: %s"
+msgstr "no se puede obtener memoria para encabezamiento del programa: %s"
+
+#: src/findtextrel.c:325 src/findtextrel.c:340
+#, fuzzy, c-format
+msgid "cannot get program header index at offset %zd: %s"
+msgstr ""
+"Nos se puede obtener el índice de encabezamiento de programa en compensación "
+"%d: %s"
+
+#: src/findtextrel.c:396
+#, c-format
+msgid "cannot get symbol table section %zu in '%s': %s"
+msgstr "No se puede obtener tabla de símbolos %zu en '%s': %s"
+
+#: src/findtextrel.c:417 src/findtextrel.c:440
+#, c-format
+msgid "cannot get relocation at index %d in section %zu in '%s': %s"
+msgstr ""
+"No se puede obtener reubicación en índice %d en sección %zu en '%s': %s"
+
+#: src/findtextrel.c:506
+#, c-format
+msgid "%s not compiled with -fpic/-fPIC\n"
+msgstr "%s no compilado con -fpic/-fPIC\n"
+
+#: src/findtextrel.c:560
+#, c-format
+msgid ""
+"the file containing the function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"El archivo que contiene la función '%s' no está compilado con -fpic/-fPIC\n"
+
+#: src/findtextrel.c:567 src/findtextrel.c:587
+#, c-format
+msgid ""
+"the file containing the function '%s' might not be compiled with -fpic/-"
+"fPIC\n"
+msgstr ""
+"el fichero que contiene la función '%s' podría no estar compilado con -fpic/-"
+"fPIC\n"
+
+#: src/findtextrel.c:575
+#, c-format
+msgid ""
+"either the file containing the function '%s' or the file containing the "
+"function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"Tanto el fichero que contiene la función '%s' como el fichero que contiene "
+"la función '%s' no están compilados con -fpic/-fPIC\n"
+
+#: src/findtextrel.c:595
+#, c-format
+msgid ""
+"a relocation modifies memory at offset %llu in a write-protected segment\n"
+msgstr ""
+"Una reubicación modifica memoria en compensación %llu en un segmento "
+"protegido contra escritura\n"
+
+#: src/nm.c:65 src/strip.c:69
+msgid "Output selection:"
+msgstr "Selección de salida:"
+
+#: src/nm.c:66
+msgid "Display debugger-only symbols"
+msgstr "Mostrar sólo símbolos del depurador"
+
+#: src/nm.c:67
+msgid "Display only defined symbols"
+msgstr "Mostrar sólo símbolos definidos"
+
+#: src/nm.c:70
+msgid "Display dynamic symbols instead of normal symbols"
+msgstr "Mostrar símbolos dinámicos en lugar de símbolos normales"
+
+#: src/nm.c:71
+msgid "Display only external symbols"
+msgstr "Mostrar sólo símbolos externos"
+
+#: src/nm.c:72
+msgid "Display only undefined symbols"
+msgstr "Mostrar sólo símbolos indefinidos"
+
+#: src/nm.c:74
+msgid "Include index for symbols from archive members"
+msgstr "Incluir índices para símbolos de miembros de archivo"
+
+#: src/nm.c:76 src/size.c:53
+msgid "Output format:"
+msgstr "Formato de salida:"
+
+#: src/nm.c:78
+msgid "Print name of the input file before every symbol"
+msgstr "Imprimir nombre de archivo de entrada antes de cada símbolo"
+
+#: src/nm.c:81
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The "
+"default is `sysv'"
+msgstr ""
+"Usar el formato de salida FORMATO.  FORMATO puede ser o bien `bsd', o "
+"`sysv', o `posix'. El establecido por defecto es `sysv'"
+
+#: src/nm.c:83
+msgid "Same as --format=bsd"
+msgstr "lo mismo que --format=bsd"
+
+#: src/nm.c:84
+msgid "Same as --format=posix"
+msgstr "lo mismo que --format=posix"
+
+#: src/nm.c:85 src/size.c:59
+msgid "Use RADIX for printing symbol values"
+msgstr "Utilizar RADIX para imprimir valores de símbolo"
+
+#: src/nm.c:86
+#, fuzzy
+msgid "Mark special symbols"
+msgstr "Marcar símbolos débiles"
+
+#: src/nm.c:88
+msgid "Print size of defined symbols"
+msgstr "Tamaño de impresión de símbolos definidos"
+
+#: src/nm.c:90 src/size.c:67 src/strip.c:74 src/unstrip.c:68
+msgid "Output options:"
+msgstr "Opciones de salida:"
+
+#: src/nm.c:91
+msgid "Sort symbols numerically by address"
+msgstr "Ordenar los símbolos numéricos por dirección"
+
+#: src/nm.c:93
+msgid "Do not sort the symbols"
+msgstr "No ordenar los símbolos"
+
+#: src/nm.c:94
+msgid "Reverse the sense of the sort"
+msgstr "Invertir el orden"
+
+#: src/nm.c:97
+msgid "Decode low-level symbol names into source code names"
+msgstr ""
+
+#. Short description of program.
+#: src/nm.c:104
+msgid "List symbols from FILEs (a.out by default)."
+msgstr "Listar símbolos de FICHEROS (a.out por defecto)."
+
+#: src/nm.c:115 src/objdump.c:78
+#, fuzzy
+msgid "Output formatting"
+msgstr "Formato de salida:"
+
+#: src/nm.c:139 src/objdump.c:102 src/size.c:104 src/strip.c:132
+#, fuzzy, c-format
+msgid "%s: INTERNAL ERROR %d (%s): %s"
+msgstr "%s: ERROR INTERNO %d (%s-%s): %s"
+
+#: src/nm.c:380 src/nm.c:392 src/size.c:287 src/size.c:296 src/size.c:307
+#: src/strip.c:2763
+#, c-format
+msgid "while closing '%s'"
+msgstr "error al cerrar '%s'"
+
+#: src/nm.c:402 src/objdump.c:279 src/strip.c:827
+#, c-format
+msgid "%s: File format not recognized"
+msgstr "%s: No se reconoce el formato del fichero"
+
+#. Note: 0 is no valid offset.
+#: src/nm.c:442
+#, fuzzy
+msgid ""
+"\n"
+"Archive index:\n"
+msgstr ""
+"\n"
+"Índice de archivo:"
+
+#: src/nm.c:451
+#, c-format
+msgid "invalid offset %zu for symbol %s"
+msgstr "Compensación %zu inválida para símbolo %s"
+
+#: src/nm.c:456
+#, c-format
+msgid "%s in %s\n"
+msgstr "%s en %s\n"
+
+#: src/nm.c:464
+#, c-format
+msgid "cannot reset archive offset to beginning"
+msgstr "imposible restablecer compensación de archivo al inicio"
+
+#: src/nm.c:489 src/objdump.c:327
+#, c-format
+msgid "%s%s%s: file format not recognized"
+msgstr "%s%s%s: no se reconoció el formato de fichero"
+
+#: src/nm.c:702
+msgid "cannot create search tree"
+msgstr "No se puede crear el árbol de búsqueda"
+
+#: src/nm.c:742 src/nm.c:1234 src/objdump.c:778 src/readelf.c:685
+#: src/readelf.c:1506 src/readelf.c:1655 src/readelf.c:1882 src/readelf.c:2123
+#: src/readelf.c:2312 src/readelf.c:2482 src/readelf.c:2604 src/readelf.c:2854
+#: src/readelf.c:3140 src/readelf.c:3215 src/readelf.c:3301 src/readelf.c:3897
+#: src/readelf.c:3945 src/readelf.c:4014 src/readelf.c:12030
+#: src/readelf.c:13213 src/readelf.c:13423 src/readelf.c:13491 src/size.c:396
+#: src/size.c:467 src/strip.c:1093
+#, c-format
+msgid "cannot get section header string table index"
+msgstr "no se puede obtener índice de cadena de encabezamiento de sección"
+
+#. We always print this prolog.
+#: src/nm.c:767
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s:\n"
+"\n"
+msgstr ""
+"\n"
+"\n"
+"Símbolos de %s:\n"
+"\n"
+
+#. The header line.
+#: src/nm.c:770
+#, c-format
+msgid ""
+"%*s%-*s %-*s Class  Type     %-*s %*s Section\n"
+"\n"
+msgstr ""
+"%*s%-*s %-*s Clase  Tipo     %-*s %*s Sección\n"
+"\n"
+
+#: src/nm.c:772
+msgctxt "sysv"
+msgid "Name"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:774
+msgctxt "sysv"
+msgid "Value"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:776
+msgctxt "sysv"
+msgid "Size"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:778
+msgctxt "sysv"
+msgid "Line"
+msgstr ""
+
+#: src/nm.c:1245
+#, fuzzy, c-format
+msgid "%s: entry size in section %zd `%s' is not what we expect"
+msgstr ""
+"%s: el tamaño de la entrada en la sección `%s' no es el que esperábamos "
+
+#: src/nm.c:1250
+#, fuzzy, c-format
+msgid "%s: size of section %zd `%s' is not multiple of entry size"
+msgstr "%s: Tamaño de sección `%s' no es múltiplo de tamaño de entrada"
+
+#: src/nm.c:1330
+#, fuzzy, c-format
+msgid "%s: entries (%zd) in section %zd `%s' is too large"
+msgstr ""
+"%s: el tamaño de la entrada en la sección `%s' no es el que esperábamos "
+
+#. XXX Add machine specific object file types.
+#: src/nm.c:1566
+#, c-format
+msgid "%s%s%s%s: Invalid operation"
+msgstr "%s%s%s%s: Operación inválida"
+
+#: src/nm.c:1616
+#, c-format
+msgid "%s%s%s: no symbols"
+msgstr "%s%s%s: No hay símbolos"
+
+#: src/objdump.c:51
+msgid "Mode selection:"
+msgstr "Selección de modo:"
+
+#: src/objdump.c:52
+msgid "Display relocation information."
+msgstr "Mostrar la reubicación de información."
+
+#: src/objdump.c:54
+msgid "Display the full contents of all sections requested"
+msgstr "Mostrar el contenido total de todas las secciones solicitadas"
+
+#: src/objdump.c:56
+msgid "Display assembler code of executable sections"
+msgstr "Mostrar código de ensamblador de secciones ejecutables"
+
+#: src/objdump.c:58
+#, fuzzy
+msgid "Output content selection:"
+msgstr "Selección de opción de salida:"
+
+#: src/objdump.c:60
+msgid "Only display information for section NAME."
+msgstr "Sólo muestra información para NOMBRE de sección."
+
+#. Short description of program.
+#: src/objdump.c:66
+msgid "Show information from FILEs (a.out by default)."
+msgstr "Muestra información de FICHEROS (a.out por defecto)."
+
+#: src/objdump.c:217 src/readelf.c:630
+msgid "No operation specified.\n"
+msgstr "No se especificó una operación.\n"
+
+#: src/objdump.c:257 src/objdump.c:269
+#, c-format
+msgid "while close `%s'"
+msgstr "mientras cierra `%s'"
+
+#: src/objdump.c:362 src/readelf.c:2218 src/readelf.c:2409
+msgid "INVALID SYMBOL"
+msgstr "SÍMBOLO INVÁLIDO"
+
+#: src/objdump.c:377 src/readelf.c:2252 src/readelf.c:2445
+msgid "INVALID SECTION"
+msgstr "SECCIÓN INVÁLIDA"
+
+#: src/objdump.c:497
+#, c-format
+msgid ""
+"\n"
+"RELOCATION RECORDS FOR [%s]:\n"
+"%-*s TYPE                 VALUE\n"
+msgstr ""
+"\n"
+"REUBICACIÓN DE REGISTROS PARA [%s]:\n"
+"%-*s TIPO                 VALOR\n"
+
+#: src/objdump.c:500
+msgid "OFFSET"
+msgstr "COMPENSACIÓN"
+
+#: src/objdump.c:565
+#, c-format
+msgid "Contents of section %s:\n"
+msgstr "Contenido de la sección %s:\n"
+
+#: src/objdump.c:686
+msgid "cannot disassemble"
+msgstr "No se puede desensamblar"
+
+#: src/objdump.c:757
+#, fuzzy
+msgid "cannot create backend for elf file"
+msgstr "no sepuede crear fichero nuevo"
+
+#. Short description of program.
+#: src/ranlib.c:62
+msgid "Generate an index to speed access to archives."
+msgstr " Generar un índice para acelerar el acceso a los archivos."
+
+#. Strings for arguments in help texts.
+#: src/ranlib.c:65
+msgid "ARCHIVE"
+msgstr "ARCHIVO "
+
+#: src/ranlib.c:101
+#, c-format
+msgid "Archive name required"
+msgstr "Se requiere nombre de archivo"
+
+#: src/ranlib.c:165
+#, c-format
+msgid "'%s' is no archive"
+msgstr "%s: no es un archivo"
+
+#: src/ranlib.c:200
+#, c-format
+msgid "error while freeing sub-ELF descriptor: %s"
+msgstr "error al liberar descriptor sub-ELF: %s"
+
+#: src/readelf.c:97
+#, fuzzy
+msgid "ELF input selection:"
+msgstr "Selección de salida de ELF:"
+
+#: src/readelf.c:99
+msgid ""
+"Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data"
+msgstr ""
+
+#: src/readelf.c:102
+msgid ""
+"Used with -w to find the skeleton Compile Units in FILE associated with the "
+"Split Compile units in a .dwo input file"
+msgstr ""
+
+#: src/readelf.c:104
+msgid "ELF output selection:"
+msgstr "Selección de salida de ELF:"
+
+#: src/readelf.c:106
+msgid "All these plus -p .strtab -p .dynstr -p .comment"
+msgstr "Todo esto mas -p .strtab -p .dynstr -p .comment"
+
+#: src/readelf.c:107
+msgid "Display the dynamic segment"
+msgstr "Mostrar el segmento dinámico"
+
+#: src/readelf.c:108
+msgid "Display the ELF file header"
+msgstr "Mostrar el encabezamiento del fichero ELF"
+
+#: src/readelf.c:110
+msgid "Display histogram of bucket list lengths"
+msgstr "Mostrar histograma de las longitudes de las listas de cubetas"
+
+#: src/readelf.c:111
+msgid "Display the program headers"
+msgstr "Mostrar encabezamientos de programa"
+
+#: src/readelf.c:113
+msgid "Display relocations"
+msgstr "Mostrar reubicaciones"
+
+#: src/readelf.c:114
+#, fuzzy
+msgid "Display the section groups"
+msgstr "Mostrar los encabezados de las secciones"
+
+#: src/readelf.c:115
+msgid "Display the sections' headers"
+msgstr "Mostrar los encabezados de las secciones"
+
+#: src/readelf.c:118
+#, fuzzy
+msgid "Display the symbol table sections"
+msgstr "Mostrar la tabla de símbolos"
+
+#: src/readelf.c:121
+#, fuzzy
+msgid "Display (only) the dynamic symbol table"
+msgstr "Mostrar sólo símbolos externos"
+
+#: src/readelf.c:122
+msgid "Display versioning information"
+msgstr "Mostrar información de versión"
+
+#: src/readelf.c:123
+msgid "Display the ELF notes"
+msgstr "Mostrar las notas ELF"
+
+#: src/readelf.c:125
+msgid "Display architecture specific information, if any"
+msgstr "Mostrar información específica de la arquitectura (si es que la hay)"
+
+#: src/readelf.c:127
+msgid "Display sections for exception handling"
+msgstr "Muestra secciones para manejo de excepciones"
+
+#: src/readelf.c:129
+msgid "Additional output selection:"
+msgstr "Selección de salida adicional:"
+
+#: src/readelf.c:131
+#, fuzzy
+msgid ""
+"Display DWARF section content.  SECTION can be one of abbrev, addr, aranges, "
+"decodedaranges, frame, gdb_index, info, info+, loc, line, decodedline, "
+"ranges, pubnames, str, macinfo, macro or exception"
+msgstr ""
+"Mostrar el contenido de la sección DWARF. SECCIÓN puede ser algo de lo "
+"siguiente: abbrev, aranges, frame, info, loc, line, ranges, pubnames, str, "
+"macinfo, o exception"
+
+#: src/readelf.c:135
+msgid "Dump the uninterpreted contents of SECTION, by number or name"
+msgstr "Vuelca los contenidos no interpretados de SECCIÓN, por número o nombre"
+
+#: src/readelf.c:137
+msgid "Print string contents of sections"
+msgstr "Imprime contenido de cadena de secciones"
+
+#: src/readelf.c:140
+msgid "Display the symbol index of an archive"
+msgstr "Muestra el índice de símbolos de un archivo"
+
+#: src/readelf.c:142
+msgid "Use the dynamic segment when possible for displaying info"
+msgstr ""
+
+#: src/readelf.c:144
+msgid "Output control:"
+msgstr "Control de salida:"
+
+#: src/readelf.c:146
+msgid "Do not find symbol names for addresses in DWARF data"
+msgstr ""
+"No se encuentran los nombres de símbolos para direcciones en datos DWARF"
+
+#: src/readelf.c:148
+#, fuzzy
+msgid ""
+"Display just offsets instead of resolving values to addresses in DWARF data"
+msgstr ""
+"No se encuentran los nombres de símbolos para direcciones en datos DWARF"
+
+#: src/readelf.c:150
+msgid "Ignored for compatibility (lines always wide)"
+msgstr ""
+
+#: src/readelf.c:152
+msgid ""
+"Show compression information for compressed sections (when used with -S); "
+"decompress section before dumping data (when used with -p or -x)"
+msgstr ""
+
+#. Short description of program.
+#: src/readelf.c:157
+msgid "Print information from ELF file in human-readable form."
+msgstr ""
+"Imprimir información del fichero ELF en una forma comprensible para los "
+"seres humanos."
+
+#. Look up once.
+#: src/readelf.c:395
+msgid "yes"
+msgstr "sí"
+
+#: src/readelf.c:396
+msgid "no"
+msgstr "no"
+
+#: src/readelf.c:598
+#, c-format
+msgid "Unknown DWARF debug section `%s'.\n"
+msgstr "Sección de depuración DWARF desconocida `%s'.\n"
+
+#: src/readelf.c:669 src/readelf.c:780
+#, c-format
+msgid "cannot generate Elf descriptor: %s"
+msgstr "no se puede crear descriptor ELF: %s"
+
+#: src/readelf.c:676 src/readelf.c:1002 src/strip.c:1188
+#, c-format
+msgid "cannot determine number of sections: %s"
+msgstr "no se pudieron determinar el número de secciones: %s"
+
+#: src/readelf.c:694 src/readelf.c:1322 src/readelf.c:1530
+#, c-format
+msgid "cannot get section: %s"
+msgstr "No se puede encontrar la sección: %s"
+
+#: src/readelf.c:703 src/readelf.c:1329 src/readelf.c:1537 src/readelf.c:13443
+#: src/unstrip.c:396 src/unstrip.c:427 src/unstrip.c:490 src/unstrip.c:622
+#: src/unstrip.c:640 src/unstrip.c:680 src/unstrip.c:897 src/unstrip.c:1263
+#: src/unstrip.c:1390 src/unstrip.c:1414 src/unstrip.c:1470 src/unstrip.c:1511
+#: src/unstrip.c:1703 src/unstrip.c:1854 src/unstrip.c:1998 src/unstrip.c:2106
+#, c-format
+msgid "cannot get section header: %s"
+msgstr "No se puede obtener encabezamiento de sección: %s"
+
+#: src/readelf.c:711
+#, fuzzy, c-format
+msgid "cannot get section name"
+msgstr "no se puede obtener encabezamiento de sección\n"
+
+#: src/readelf.c:720 src/readelf.c:7177 src/readelf.c:11231 src/readelf.c:11333
+#: src/readelf.c:11517
+#, c-format
+msgid "cannot get %s content: %s"
+msgstr "No se puede obtener el contenido %s: %s"
+
+#: src/readelf.c:736
+#, fuzzy, c-format
+msgid "cannot create temp file '%s'"
+msgstr "no se puede crear fichero nuevo '%s': %s"
+
+#: src/readelf.c:745
+#, fuzzy, c-format
+msgid "cannot write section data"
+msgstr "no se puede leer la sección de datos: %s"
+
+#: src/readelf.c:751 src/readelf.c:768 src/readelf.c:797
+#, c-format
+msgid "error while closing Elf descriptor: %s"
+msgstr "error al cerrar el descriptor ELF: %s"
+
+#: src/readelf.c:758
+#, fuzzy, c-format
+msgid "error while rewinding file descriptor"
+msgstr "error al cerrar el descriptor ELF: %s"
+
+#: src/readelf.c:792
+#, c-format
+msgid "'%s' is not an archive, cannot print archive index"
+msgstr "'%s' no es un archivo, no se puede imprimir índice de archivo"
+
+#: src/readelf.c:896
+#, c-format
+msgid "cannot stat input file"
+msgstr "no sepudo stat archivo de entrada"
+
+#: src/readelf.c:898
+#, c-format
+msgid "input file is empty"
+msgstr "archivo de entrada vacío"
+
+#: src/readelf.c:900
+#, c-format
+msgid "failed reading '%s': %s"
+msgstr "Falló lectura de '%s': %s"
+
+#: src/readelf.c:929
+#, fuzzy, c-format
+msgid "No such section '%s' in '%s'"
+msgstr "No se puede obtener contenido de sección %zu en '%s': %s"
+
+#: src/readelf.c:988
+#, c-format
+msgid "cannot read ELF header: %s"
+msgstr "no se pudo leer encabezamiento ELF: %s"
+
+#: src/readelf.c:996
+#, c-format
+msgid "cannot create EBL handle"
+msgstr "no se puede crear EBL"
+
+#: src/readelf.c:1007
+#, c-format
+msgid "cannot determine number of program headers: %s"
+msgstr "no se pudo determinar la cantidad de encabezados de programa: %s"
+
+#: src/readelf.c:1039
+#, fuzzy, c-format
+msgid "cannot read ELF: %s"
+msgstr "no sepuede leer %s: %s"
+
+#: src/readelf.c:1072
+#, fuzzy
+#| msgid "cannot get section: %s"
+msgid "cannot find section"
+msgstr "No se puede encontrar la sección: %s"
+
+#: src/readelf.c:1109
+msgid "NONE (None)"
+msgstr "NONE (Ninguno)"
+
+#: src/readelf.c:1110
+msgid "REL (Relocatable file)"
+msgstr "REL (Fichero reubicable)"
+
+#: src/readelf.c:1111
+msgid "EXEC (Executable file)"
+msgstr "EXEC (Fichero ejecutable)"
+
+#: src/readelf.c:1112
+msgid "DYN (Shared object file)"
+msgstr "DYN (Fichero objeto compartido)"
+
+#: src/readelf.c:1113
+msgid "CORE (Core file)"
+msgstr "CORE (Fichero núcleo)"
+
+#: src/readelf.c:1118
+#, c-format
+msgid "OS Specific: (%x)\n"
+msgstr "OS Specific: (%x)\n"
+
+#. && e_type <= ET_HIPROC always true
+#: src/readelf.c:1120
+#, c-format
+msgid "Processor Specific: (%x)\n"
+msgstr "Específico del procesador: (%x)\n"
+
+#: src/readelf.c:1130
+msgid ""
+"ELF Header:\n"
+"  Magic:  "
+msgstr ""
+"Encabezamiento ELF:\n"
+"  Mágico:  "
+
+#: src/readelf.c:1134
+#, c-format
+msgid ""
+"\n"
+"  Class:                             %s\n"
+msgstr ""
+"\n"
+"  Clase:                             %s\n"
+
+#: src/readelf.c:1139
+#, c-format
+msgid "  Data:                              %s\n"
+msgstr "  Datos:                             %s\n"
+
+#: src/readelf.c:1145
+#, c-format
+msgid "  Ident Version:                     %hhd %s\n"
+msgstr "  Versión ident:                     %hhd %s\n"
+
+#: src/readelf.c:1147 src/readelf.c:1169
+msgid "(current)"
+msgstr "(actual)"
+
+#: src/readelf.c:1151
+#, c-format
+msgid "  OS/ABI:                            %s\n"
+msgstr "  OS/ABI:                            %s\n"
+
+#: src/readelf.c:1154
+#, c-format
+msgid "  ABI Version:                       %hhd\n"
+msgstr "  Versión ABI:                       %hhd\n"
+
+#: src/readelf.c:1157
+msgid "  Type:                              "
+msgstr "  Tipo:                              "
+
+#: src/readelf.c:1162
+#, c-format
+msgid "  Machine:                           %s\n"
+msgstr "  Máquina:                           %s\n"
+
+#: src/readelf.c:1164
+#, fuzzy, c-format
+msgid "  Machine:                           <unknown>: 0x%x\n"
+msgstr "  Máquina:                           %s\n"
+
+#: src/readelf.c:1167
+#, c-format
+msgid "  Version:                           %d %s\n"
+msgstr "  Versión:                           %d %s\n"
+
+#: src/readelf.c:1171
+#, c-format
+msgid "  Entry point address:               %#<PRIx64>\n"
+msgstr "  Dirección de punto de entrada:               %#<PRIx64>\n"
+
+#: src/readelf.c:1174
+#, c-format
+msgid "  Start of program headers:          %<PRId64> %s\n"
+msgstr "  Inicio de encabezamientos de programa:          %<PRId64> %s\n"
+
+#: src/readelf.c:1175 src/readelf.c:1178
+msgid "(bytes into file)"
+msgstr " (bytes en el archivo)"
+
+#: src/readelf.c:1177
+#, c-format
+msgid "  Start of section headers:          %<PRId64> %s\n"
+msgstr "  Inicio de encabezamientos de sección:          %<PRId64> %s\n"
+
+#: src/readelf.c:1180
+#, c-format
+msgid "  Flags:                             %s\n"
+msgstr "  Indicadores:                             %s\n"
+
+#: src/readelf.c:1183
+#, c-format
+msgid "  Size of this header:               %<PRId16> %s\n"
+msgstr "  Tamaño de este encabezamiento:               %<PRId16> %s\n"
+
+#: src/readelf.c:1184 src/readelf.c:1187 src/readelf.c:1204
+msgid "(bytes)"
+msgstr "(bytes)"
+
+#: src/readelf.c:1186
+#, c-format
+msgid "  Size of program header entries:    %<PRId16> %s\n"
+msgstr ""
+"  Tamaño de las entradas en encabezamiento del programa:    %<PRId16> %s\n"
+
+#: src/readelf.c:1189
+#, c-format
+msgid "  Number of program headers entries: %<PRId16>"
+msgstr "  Cantidad de entradas de encabezados de programa: %<PRId16>"
+
+#: src/readelf.c:1196
+#, c-format
+msgid " (%<PRIu32> in [0].sh_info)"
+msgstr " (%<PRIu32> in [0].sh_info)"
+
+#: src/readelf.c:1199 src/readelf.c:1216 src/readelf.c:1230
+msgid " ([0] not available)"
+msgstr " ([0] no disponible)"
+
+#: src/readelf.c:1203
+#, c-format
+msgid "  Size of section header entries:    %<PRId16> %s\n"
+msgstr ""
+"  Tamaño de las entradas en el encabezamiento de sección:    %<PRId16> %s\n"
+
+#: src/readelf.c:1206
+#, c-format
+msgid "  Number of section headers entries: %<PRId16>"
+msgstr "  Cantidad de entradas en los encabezamientos de sección: %<PRId16>"
+
+#: src/readelf.c:1213
+#, c-format
+msgid " (%<PRIu32> in [0].sh_size)"
+msgstr " (%<PRIu32> en [0].sh_size)"
+
+#. We managed to get the zeroth section.
+#: src/readelf.c:1226
+#, c-format
+msgid " (%<PRIu32> in [0].sh_link)"
+msgstr " (%<PRIu32> en [0].sh_link)"
+
+#: src/readelf.c:1234
+#, c-format
+msgid ""
+"  Section header string table index: XINDEX%s\n"
+"\n"
+msgstr ""
+"  Índice de tabla de cadenas de sección de encabezamiento de : XINDEX%s\n"
+"\n"
+
+#: src/readelf.c:1238
+#, c-format
+msgid ""
+"  Section header string table index: %<PRId16>\n"
+"\n"
+msgstr "  Índice de tabla de cadenas de sección de encabezamiento: %<PRId16>\n"
+
+#: src/readelf.c:1288 src/readelf.c:1496
+#, fuzzy, c-format
+msgid "cannot get number of sections: %s"
+msgstr "no se pudieron determinar el número de secciones: %s"
+
+#: src/readelf.c:1291
+#, fuzzy, c-format
+msgid ""
+"There are %zd section headers, starting at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"Hay %d encabezamientos de sección, comenzando en compensación %#<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:1299
+#, fuzzy, c-format
+msgid "cannot get section header string table index: %s"
+msgstr "no se puede obtener índice de cadena de encabezamiento de sección"
+
+#: src/readelf.c:1302
+msgid "Section Headers:"
+msgstr "encabezamientos de sección:"
+
+#: src/readelf.c:1305
+msgid ""
+"[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk "
+"Inf Al"
+msgstr ""
+"[Nr] Nombre            Tipo            Dirección    Off    Tamaño    Inf Al "
+"Enlace banderas ES"
+
+#: src/readelf.c:1307
+msgid ""
+"[Nr] Name                 Type         Addr             Off      Size     ES "
+"Flags Lk Inf Al"
+msgstr ""
+"[Nr] Name                 Type         Addr             Off      Size     ES "
+"Flags Lk Inf Al"
+
+#: src/readelf.c:1312
+msgid "     [Compression  Size   Al]"
+msgstr ""
+
+#: src/readelf.c:1314
+msgid "     [Compression  Size     Al]"
+msgstr ""
+
+#: src/readelf.c:1392
+#, fuzzy, c-format
+msgid "bad compression header for section %zd: %s"
+msgstr "No se puede obtener el encabezamiento de sección %zu: %s"
+
+#: src/readelf.c:1403
+#, fuzzy, c-format
+msgid "bad gnu compressed size for section %zd: %s"
+msgstr "No se pueden obtener datos para la sección %d: %s"
+
+#: src/readelf.c:1421
+msgid "Program Headers:"
+msgstr "encabezamientos de programa:"
+
+#: src/readelf.c:1423
+msgid ""
+"  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"
+msgstr ""
+"  Tipo           Compensación  Dirección Virtual       Dirección "
+"Física       Tamaño de Fichero  Tamaño de Memoria     Alineación de bandera"
+
+#: src/readelf.c:1426
+msgid ""
+"  Type           Offset   VirtAddr           PhysAddr           FileSiz  "
+"MemSiz   Flg Align"
+msgstr ""
+"  Tipo          Compensación  Dirección Virtual            Dirección "
+"Física          Tamaño de Fichero  Tamaño de Memoria   Alineación de bandera"
+
+#: src/readelf.c:1483
+#, c-format
+msgid "\t[Requesting program interpreter: %s]\n"
+msgstr "\t[Solicitando intérprete de programa: %s]\n"
+
+#: src/readelf.c:1508
+msgid ""
+"\n"
+" Section to Segment mapping:\n"
+"  Segment Sections..."
+msgstr ""
+"\n"
+" Sección para asignación de segmento:\n"
+"  Secciones de segmento..."
+
+#: src/readelf.c:1519 src/unstrip.c:2165 src/unstrip.c:2207 src/unstrip.c:2214
+#, c-format
+msgid "cannot get program header: %s"
+msgstr "no se puede obtener memoria para encabezamiento del programa: %s"
+
+#: src/readelf.c:1663
+#, c-format
+msgid ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Grupo de sección COMDAT [%2zu] '%s' con firma '%s' contiene entrada %zu:\n"
+msgstr[1] ""
+"\n"
+"Grupo de sección COMDAT [%2zu] '%s' con firma '%s' contiene entradas %zu:\n"
+
+#: src/readelf.c:1668
+#, c-format
+msgid ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Grupo de sección [%2zu] '%s' con firma '%s' contiene entrada %zu:\n"
+msgstr[1] ""
+"\n"
+"Grupo de sección [%2zu] '%s' con firma '%s' contiene entradas %zu:\n"
+
+#: src/readelf.c:1676
+msgid "<INVALID SYMBOL>"
+msgstr "<SÍMBOLO INVÁLIDO>"
+
+#: src/readelf.c:1690
+msgid "<INVALID SECTION>"
+msgstr "<SECCIÓN INVÁLIDA>"
+
+#: src/readelf.c:1713 src/readelf.c:2614 src/readelf.c:3913 src/readelf.c:4213
+#: src/readelf.c:13315 src/readelf.c:13322 src/readelf.c:13366
+#: src/readelf.c:13373
+msgid "Couldn't uncompress section"
+msgstr ""
+
+#: src/readelf.c:1717 src/readelf.c:2619 src/readelf.c:3917
+#, fuzzy, c-format
+msgid "cannot get section [%zd] header: %s"
+msgstr "No se puede obtener encabezamiento de sección: %s"
+
+#: src/readelf.c:1886 src/readelf.c:2860 src/readelf.c:3146 src/readelf.c:3221
+#: src/readelf.c:3524 src/readelf.c:3598 src/readelf.c:5963
+#, fuzzy, c-format
+msgid "invalid sh_link value in section %zu"
+msgstr ".debug_line section inválida"
+
+#: src/readelf.c:1889
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Segmento dinámico contiene entrada %lu:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Segmento dinámico contiene entradas %lu:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:1902
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "Dynamic segment contains %lu entry:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+#| msgid_plural ""
+#| "\n"
+#| "Dynamic segment contains %lu entries:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgstr[0] ""
+"\n"
+"Segmento dinámico contiene entrada %lu:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Segmento dinámico contiene entradas %lu:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:1912
+msgid "  Type              Value\n"
+msgstr "  Tipo              Valor\n"
+
+#: src/readelf.c:1921
+#, fuzzy
+msgid "cannot get string table by using dynamic segment"
+msgstr "no se pueden obtener datos de sección: %s"
+
+#: src/readelf.c:1960
+#, c-format
+msgid "Shared library: [%s]\n"
+msgstr "Biblioteca compartida: [%s]\n"
+
+#: src/readelf.c:1964
+#, c-format
+msgid "Library soname: [%s]\n"
+msgstr "Nombre-so de la biblioteca: [%s]\n"
+
+#: src/readelf.c:1968
+#, c-format
+msgid "Library rpath: [%s]\n"
+msgstr "Rpath de la biblioteca: [%s]\n"
+
+#: src/readelf.c:1972
+#, c-format
+msgid "Library runpath: [%s]\n"
+msgstr "Ruta de ejecución de la biblioteca: [%s]\n"
+
+#: src/readelf.c:1993
+#, c-format
+msgid "%<PRId64> (bytes)\n"
+msgstr "%<PRId64> (bytes)\n"
+
+#: src/readelf.c:2109 src/readelf.c:2298
+#, c-format
+msgid ""
+"\n"
+"Invalid symbol table at offset %#0<PRIx64>\n"
+msgstr ""
+"\n"
+"Tabla de símbolos inválida en compensación %#0<PRIx64>\n"
+
+#: src/readelf.c:2126 src/readelf.c:2315
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Sección de reubicación [%2zu] '%s' para sección [%2u] '%s' en compensación "
+"%#0<PRIx64> contiene entrada %d:\n"
+msgstr[1] ""
+"\n"
+"Sección de reubicación [%2zu] '%s' para sección [%2u] '%s' en compensación "
+"%#0<PRIx64> contiene entradas %d:\n"
+
+#. The .rel.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. The .rela.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. A .relr.dyn section does not refer to a specific section.
+#: src/readelf.c:2141 src/readelf.c:2330 src/readelf.c:2485
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Sección de reubicación[%2u] '%s' en compensación %#0<PRIx64> contiene "
+"entrada %d:\n"
+msgstr[1] ""
+"\n"
+"Sección de reubicación [%2u] '%s' en compensación %#0<PRIx64> contiene "
+"entradas %d:\n"
+
+#: src/readelf.c:2151
+msgid "  Offset      Type                 Value       Name\n"
+msgstr "   Compensación           Tipo               Valor      Nombre\n"
+
+#: src/readelf.c:2153
+msgid "  Offset              Type                 Value               Name\n"
+msgstr "    Compensación           Tipo               Valor           Nombre\n"
+
+#: src/readelf.c:2206 src/readelf.c:2217 src/readelf.c:2230 src/readelf.c:2251
+#: src/readelf.c:2263 src/readelf.c:2396 src/readelf.c:2408 src/readelf.c:2422
+#: src/readelf.c:2444 src/readelf.c:2457
+msgid "<INVALID RELOC>"
+msgstr "<REUBIC INVÁLIDA>"
+
+#: src/readelf.c:2340
+msgid "  Offset      Type            Value       Addend Name\n"
+msgstr "    Compensación            Tipo               Valor    Nombre Adend\n"
+
+#: src/readelf.c:2342
+msgid "  Offset              Type            Value               Addend Name\n"
+msgstr "    Compensación            Tipo               Valor   Nombre Adend\n"
+
+#: src/readelf.c:2654
+#, c-format
+msgid "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+msgstr "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+
+#: src/readelf.c:2750
+#, c-format
+msgid "bad dynamic symbol"
+msgstr "símbolo dinámico erróneo"
+
+#: src/readelf.c:2868
+#, c-format
+msgid ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entry:\n"
+msgid_plural ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entries:\n"
+msgstr[0] ""
+"\n"
+"La tabla de símbolos [%2u] '%s' contiene entrada %u:\n"
+msgstr[1] ""
+"\n"
+"La tabla de símbolos [%2u] '%s' contiene entradas %u:\n"
+
+#: src/readelf.c:2873
+#, c-format
+msgid " %lu local symbol  String table: [%2u] '%s'\n"
+msgid_plural " %lu local symbols  String table: [%2u] '%s'\n"
+msgstr[0] "símbolos locales %lu Tabla de cadena: [%2u] '%s'\n"
+msgstr[1] " Símbolos locales %lu Tabla de cadenas: [%2u] '%s'\n"
+
+#: src/readelf.c:2881
+msgid "  Num:    Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  Núm:    Valor       Tamaño Tipo    Unión  Vis          Nombre Ndx\n"
+
+#: src/readelf.c:2883
+msgid "  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "   Num:    Valor          Tamaño Tipo    Unión  Vis      Nombre Ndx\n"
+
+#: src/readelf.c:3002
+msgid "Dynamic symbol information is not available for displaying symbols."
+msgstr ""
+
+#: src/readelf.c:3102
+msgid "none"
+msgstr "nada"
+
+#: src/readelf.c:3119
+msgid "| <unknown>"
+msgstr "| <desconocido>"
+
+#: src/readelf.c:3149
+#, c-format
+msgid ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Sección de versión necesita [%2u] '%s' contiene entrada %d entry:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Versión necesita sección [%2u] '%s' contiene entrada %d:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:3170
+#, c-format
+msgid "  %#06x: Version: %hu  File: %s  Cnt: %hu\n"
+msgstr "  %#06x: Versión: %hu  Fichero: %s  Conteo: %hu\n"
+
+#: src/readelf.c:3183
+#, c-format
+msgid "  %#06x: Name: %s  Flags: %s  Version: %hu\n"
+msgstr "  %#06x: Nombre: %s  Banderas: %s  Versión: %hu\n"
+
+#: src/readelf.c:3225
+#, c-format
+msgid ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Sección de definición de versión [%2u] '%s' contiene entrada %d:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Sección de definición de versión [%2u] '%s' contiene %d entrada:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:3253
+#, c-format
+msgid "  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"
+msgstr ""
+"  %#06x: Versión: %hd  Banderas: %s  Índice: %hd  Conteo: %hd  Nombre: %s\n"
+
+#: src/readelf.c:3268
+#, c-format
+msgid "  %#06x: Parent %d: %s\n"
+msgstr "  %#06x: Principal %d: %s\n"
+
+#. Print the header.
+#: src/readelf.c:3528
+#, c-format
+msgid ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgid_plural ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgstr[0] ""
+"\n"
+"Sección de versión de símbolos [%2u] '%s' contiene %d entrada:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'"
+msgstr[1] ""
+"\n"
+"Sección de versión de símbolos [%2u] '%s' contiene entradas %d:\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'"
+
+#: src/readelf.c:3556
+msgid "   0 *local*                     "
+msgstr "   0 *local*                     "
+
+#: src/readelf.c:3561
+msgid "   1 *global*                    "
+msgstr "   1 *global*                    "
+
+#: src/readelf.c:3603
+#, c-format
+msgid ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"bucket):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"buckets):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Histograma para longitud de lista de cubeta en sección [%2u] '%s' (total de "
+"cubetas %d):\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Histograma para longitud de lista de cubeta en sección [%2u] '%s' (total de "
+"cubetas %d):\n"
+" Dirección: %#0*<PRIx64>  Compensación: %#08<PRIx64>  Enlace a sección: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:3625
+#, no-c-format
+msgid " Length  Number  % of total  Coverage\n"
+msgstr " Longitud  Número  % of total  Cobertura\n"
+
+#: src/readelf.c:3627
+#, c-format
+msgid "      0  %6<PRIu32>      %5.1f%%\n"
+msgstr "      0  %6<PRIu32>      %5.1f%%\n"
+
+#: src/readelf.c:3634
+#, c-format
+msgid "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+msgstr "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+
+#: src/readelf.c:3648
+#, c-format
+msgid ""
+" Average number of tests:   successful lookup: %f\n"
+"\t\t\t  unsuccessful lookup: %f\n"
+msgstr ""
+" Número promedio de pruebas:   búsqueda exitosa: %f\n"
+"                          búsqueda sin éxito: %f\n"
+
+#: src/readelf.c:3666 src/readelf.c:3730 src/readelf.c:3796
+#, c-format
+msgid "cannot get data for section %d: %s"
+msgstr "No se pueden obtener datos para la sección %d: %s"
+
+#: src/readelf.c:3674
+#, fuzzy, c-format
+msgid "invalid data in sysv.hash section %d"
+msgstr "Datos inválidos en sección [%zu] '%s'"
+
+#: src/readelf.c:3703
+#, fuzzy, c-format
+msgid "invalid chain in sysv.hash section %d"
+msgstr "Datos inválidos en sección [%zu] '%s'"
+
+#: src/readelf.c:3738
+#, fuzzy, c-format
+msgid "invalid data in sysv.hash64 section %d"
+msgstr "Datos inválidos en sección [%zu] '%s'"
+
+#: src/readelf.c:3769
+#, fuzzy, c-format
+msgid "invalid chain in sysv.hash64 section %d"
+msgstr "Datos inválidos en sección [%zu] '%s'"
+
+#: src/readelf.c:3805
+#, fuzzy, c-format
+msgid "invalid data in gnu.hash section %d"
+msgstr "Datos inválidos en sección [%zu] '%s'"
+
+#: src/readelf.c:3871
+#, c-format
+msgid ""
+" Symbol Bias: %u\n"
+" Bitmask Size: %zu bytes  %<PRIuFAST32>%% bits set  2nd hash shift: %u\n"
+msgstr ""
+" Polarización de símbolo: %u\n"
+" Tamaño de Bitmask: %zu bytes  %<PRIuFAST32>%% bits establecen segundo "
+"cambio de dispersión: %u\n"
+
+#: src/readelf.c:3956
+#, c-format
+msgid ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Sección de lista de biblioteca [%2zu] '%s' en compensación %#0<PRIx64> "
+"contiene entrada %d:\n"
+msgstr[1] ""
+"\n"
+"Sección de lista de biblioteca [%2zu] '%s' en compensación %#0<PRIx64> "
+"contiene entradas %d:\n"
+
+#: src/readelf.c:3970
+msgid ""
+"       Library                       Time Stamp          Checksum Version "
+"Flags"
+msgstr ""
+"       Biblioteca                       Marca de tiempo          Indicadores "
+"de versión de suma de verificación"
+
+#: src/readelf.c:4030
+#, c-format
+msgid ""
+"\n"
+"Object attributes section [%2zu] '%s' of %<PRIu64> bytes at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sección de atributos de objeto [%2zu] '%s' de %<PRIu64> bytes con "
+"desplazamiento %#0<PRIx64>:\n"
+
+#: src/readelf.c:4047
+msgid "  Owner          Size\n"
+msgstr "  Propietario          Tamaño\n"
+
+#: src/readelf.c:4071
+#, c-format
+msgid "  %-13s  %4<PRIu32>\n"
+msgstr "  %-13s  %4<PRIu32>\n"
+
+#. Unknown subsection, print and skip.
+#: src/readelf.c:4110
+#, c-format
+msgid "    %-4u %12<PRIu32>\n"
+msgstr "    %-4u %12<PRIu32>\n"
+
+#. Tag_File
+#: src/readelf.c:4115
+#, c-format
+msgid "    File: %11<PRIu32>\n"
+msgstr "    File: %11<PRIu32>\n"
+
+#: src/readelf.c:4165
+#, c-format
+msgid "      %s: %<PRId64>, %s\n"
+msgstr "      %s: %<PRId64>, %s\n"
+
+#: src/readelf.c:4168
+#, c-format
+msgid "      %s: %<PRId64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:4171
+#, c-format
+msgid "      %s: %s\n"
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:4181
+#, c-format
+msgid "      %u: %<PRId64>\n"
+msgstr "      %u: %<PRId64>\n"
+
+#: src/readelf.c:4184
+#, c-format
+msgid "      %u: %s\n"
+msgstr "      %u: %s\n"
+
+#: src/readelf.c:4222
+#, fuzzy
+msgid "Couldn't get data from section"
+msgstr "No se puede obtener encabezamiento de sección 0th: %s"
+
+#: src/readelf.c:4287
+#, fuzzy
+msgid "sprintf failure"
+msgstr "mprotect falló"
+
+#: src/readelf.c:4771
+msgid "empty block"
+msgstr "bloque vacío"
+
+#: src/readelf.c:4774
+#, c-format
+msgid "%zu byte block:"
+msgstr "bloque de byte %zu:"
+
+#: src/readelf.c:5252
+#, fuzzy, c-format
+msgid "%*s[%2<PRIuMAX>] %s  <TRUNCATED>\n"
+msgstr "%*s[%4<PRIuMAX>] %s  <TRUNCATED>\n"
+
+#: src/readelf.c:5424
+#, c-format
+msgid "%s %#<PRIx64> used with different address sizes"
+msgstr "%s %#<PRIx64> utilizado con direcciones de diferente tamaño"
+
+#: src/readelf.c:5431
+#, c-format
+msgid "%s %#<PRIx64> used with different offset sizes"
+msgstr "%s %#<PRIx64> utilizado con offsetr de diferente tamaño"
+
+#: src/readelf.c:5438
+#, fuzzy, c-format
+msgid "%s %#<PRIx64> used with different base addresses"
+msgstr "%s %#<PRIx64> utilizado con direcciones de diferente tamaño"
+
+#: src/readelf.c:5445
+#, fuzzy, c-format
+msgid "%s %#<PRIx64> used with different attribute %s and %s"
+msgstr "%s %#<PRIx64> utilizado con direcciones de diferente tamaño"
+
+#: src/readelf.c:5545
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"
+msgstr " [%6tx] <MATERIAL INUTIL SIN UTILIZAR EN EL RESTO DE LA SECCION>\n"
+
+#: src/readelf.c:5553
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE> ... %<PRIu64> bytes ...\n"
+msgstr " [%6tx]  <MATERIAL INUTIL NO UTILIZADO> ... %<PRIu64> bytes ...\n"
+
+#: src/readelf.c:5659
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [ Code]\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64>:\n"
+" [ Código]\n"
+
+#: src/readelf.c:5667
+#, c-format
+msgid ""
+"\n"
+"Abbreviation section at offset %<PRIu64>:\n"
+msgstr ""
+"\n"
+"Sección de abreviatura en compensación %<PRIu64>:\n"
+
+#: src/readelf.c:5680
+#, c-format
+msgid " *** error while reading abbreviation: %s\n"
+msgstr " *** error en lectura de abreviatura: %s\n"
+
+#: src/readelf.c:5696
+#, c-format
+msgid " [%5u] offset: %<PRId64>, children: %s, tag: %s\n"
+msgstr " [%5u] compensación: %<PRId64>, hijos: %s, etiqueta: %s\n"
+
+#: src/readelf.c:5733 src/readelf.c:6026 src/readelf.c:6197 src/readelf.c:6568
+#: src/readelf.c:7194 src/readelf.c:8963 src/readelf.c:9705 src/readelf.c:10173
+#: src/readelf.c:10428 src/readelf.c:10590 src/readelf.c:10971
+#: src/readelf.c:11042
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64>:\n"
+
+#: src/readelf.c:5836 src/readelf.c:5860 src/readelf.c:6233 src/readelf.c:9741
+#, fuzzy, c-format
+msgid " Length:         %8<PRIu64>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:5838 src/readelf.c:5875 src/readelf.c:6246 src/readelf.c:9754
+#, fuzzy, c-format
+msgid " DWARF version:  %8<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:5839 src/readelf.c:5884 src/readelf.c:6255 src/readelf.c:9763
+#, fuzzy, c-format
+msgid " Address size:   %8<PRIu64>\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:5841 src/readelf.c:5894 src/readelf.c:6265 src/readelf.c:9773
+#, fuzzy, c-format
+msgid " Segment size:   %8<PRIu64>\n"
+msgstr " establecer archivo a %<PRIu64>\n"
+
+#: src/readelf.c:5879 src/readelf.c:6250 src/readelf.c:9758 src/readelf.c:11164
+#, fuzzy, c-format
+msgid "Unknown version"
+msgstr "versión desconocida"
+
+#: src/readelf.c:5889 src/readelf.c:6096 src/readelf.c:6260 src/readelf.c:9768
+#, fuzzy, c-format
+msgid "unsupported address size"
+msgstr "no hay valor de dirección"
+
+#: src/readelf.c:5900 src/readelf.c:6107 src/readelf.c:6270 src/readelf.c:9778
+#, c-format
+msgid "unsupported segment size"
+msgstr ""
+
+#: src/readelf.c:5953
+#, c-format
+msgid "cannot get .debug_aranges content: %s"
+msgstr "no se ha podido obtener contenido de .debug_aranges: %s"
+
+#: src/readelf.c:5968
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64> contiene entrada %zu:\n"
+msgstr[1] ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64> contiene entradas %zu:\n"
+
+#: src/readelf.c:5999
+#, c-format
+msgid " [%*zu] ???\n"
+msgstr " [%*zu] ???\n"
+
+#: src/readelf.c:6001
+#, c-format
+msgid ""
+" [%*zu] start: %0#*<PRIx64>, length: %5<PRIu64>, CU DIE offset: %6<PRId64>\n"
+msgstr ""
+" Inicio [%*zu]: %0#*<PRIx64>, longitud: %5<PRIu64>, compensación CU DIE: "
+"%6<PRId64>\n"
+
+#: src/readelf.c:6039 src/readelf.c:8982
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Table at offset %zu:\n"
+msgstr ""
+"\n"
+"Tabla en compensación %Zu:\n"
+
+#: src/readelf.c:6043 src/readelf.c:6214 src/readelf.c:7218 src/readelf.c:8993
+#: src/readelf.c:9722
+#, c-format
+msgid "invalid data in section [%zu] '%s'"
+msgstr "Datos inválidos en sección [%zu] '%s'"
+
+#: src/readelf.c:6059
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Length:        %6<PRIu64>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:6071
+#, fuzzy, c-format
+msgid " DWARF version: %6<PRIuFAST16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6075
+#, c-format
+msgid "unsupported aranges version"
+msgstr ""
+
+#: src/readelf.c:6086
+#, fuzzy, c-format
+msgid " CU offset:     %6<PRIx64>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:6092
+#, fuzzy, c-format
+msgid " Address size:  %6<PRIu64>\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:6103
+#, fuzzy, c-format
+msgid ""
+" Segment size:  %6<PRIu64>\n"
+"\n"
+msgstr " establecer archivo a %<PRIu64>\n"
+
+#: src/readelf.c:6158
+#, c-format
+msgid "   %zu padding bytes\n"
+msgstr ""
+
+#: src/readelf.c:6220 src/readelf.c:9728
+#, fuzzy, c-format
+msgid ""
+"Table at Offset 0x%<PRIx64>:\n"
+"\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:6275 src/readelf.c:9783
+#, fuzzy, c-format
+msgid " Offset entries: %8<PRIu64>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:6291 src/readelf.c:9799
+#, c-format
+msgid " Unknown CU base: "
+msgstr ""
+
+#: src/readelf.c:6293 src/readelf.c:9801
+#, c-format
+msgid " CU [%6<PRIx64>] base: "
+msgstr ""
+
+#: src/readelf.c:6299 src/readelf.c:9807
+#, c-format
+msgid " Not associated with a CU.\n"
+msgstr ""
+
+#: src/readelf.c:6310 src/readelf.c:9818
+#, c-format
+msgid "too many offset entries for unit length"
+msgstr ""
+
+#: src/readelf.c:6314 src/readelf.c:9822
+#, fuzzy, c-format
+msgid "  Offsets starting at 0x%<PRIx64>:\n"
+msgstr "  Propietario          Tamaño\n"
+
+#: src/readelf.c:6366
+#, fuzzy, c-format
+msgid "invalid range list data"
+msgstr "datos inválidos"
+
+#: src/readelf.c:6551 src/readelf.c:10157
+#, c-format
+msgid ""
+"   %zu padding bytes\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:6599 src/readelf.c:10206
+#, c-format
+msgid ""
+"\n"
+" Unknown CU base: "
+msgstr ""
+
+#: src/readelf.c:6601 src/readelf.c:10208
+#, c-format
+msgid ""
+"\n"
+" CU [%6<PRIx64>] base: "
+msgstr ""
+
+#: src/readelf.c:6610 src/readelf.c:10234 src/readelf.c:10260
+#, c-format
+msgid " [%6tx]  <INVALID DATA>\n"
+msgstr " [%6tx]  <DATOS INVÁLIDOS>\n"
+
+#: src/readelf.c:6635 src/readelf.c:10344
+#, fuzzy
+msgid "base address"
+msgstr "Establecer dirección a %s\n"
+
+#: src/readelf.c:6645 src/readelf.c:10354
+#, fuzzy, c-format
+msgid " [%6tx] empty list\n"
+msgstr " [%6tx]  lista vacía\n"
+
+#: src/readelf.c:6909
+#, fuzzy
+msgid "         <INVALID DATA>\n"
+msgstr "   <DATOS INVÁLIDOS>\n"
+
+#: src/readelf.c:7166
+#, fuzzy, c-format
+msgid "cannot get ELF: %s"
+msgstr "no se puede leer encabezamiento ELF: %s"
+
+#: src/readelf.c:7190
+#, c-format
+msgid ""
+"\n"
+"Call frame information section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sección de información de marco de llamada [%2zu] '%s' en compensación "
+"%#<PRIx64>:\n"
+
+#: src/readelf.c:7240
+#, c-format
+msgid ""
+"\n"
+" [%6tx] Zero terminator\n"
+msgstr ""
+"\n"
+" [%6tx] Terminator cero\n"
+
+#: src/readelf.c:7344 src/readelf.c:7498
+#, c-format
+msgid "invalid augmentation length"
+msgstr "longitud de aumento inválida"
+
+#: src/readelf.c:7359
+msgid "FDE address encoding: "
+msgstr "Codificación de dirección FDE:"
+
+#: src/readelf.c:7365
+msgid "LSDA pointer encoding: "
+msgstr "Codificación de puntero LSDA:"
+
+#: src/readelf.c:7475
+#, c-format
+msgid " (offset: %#<PRIx64>)"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:7482
+#, c-format
+msgid " (end offset: %#<PRIx64>)"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:7519
+#, c-format
+msgid "   %-26sLSDA pointer: %#<PRIx64>\n"
+msgstr "Puntero   %-26sLSDA: %#<PRIx64>\n"
+
+#: src/readelf.c:7604
+#, fuzzy, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute code: %s"
+msgstr "No se puede obtener código de atributo: %s"
+
+#: src/readelf.c:7614
+#, fuzzy, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute form: %s"
+msgstr "No se puede obtener forma de atributo: %s"
+
+#: src/readelf.c:7636
+#, fuzzy, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute '%s' (%s) value: %s"
+msgstr "No se puede obtener valor: %s"
+
+#: src/readelf.c:7966
+#, fuzzy, c-format
+msgid "invalid file (%<PRId64>): %s"
+msgstr "Archivo inválido"
+
+#: src/readelf.c:7970
+#, fuzzy, c-format
+msgid "no srcfiles for CU [%<PRIx64>]"
+msgstr " establecer archivo a %<PRIu64>\n"
+
+#: src/readelf.c:7974
+#, fuzzy, c-format
+msgid "couldn't get DWARF CU: %s"
+msgstr "no se puede leer encabezamiento ELF: %s"
+
+#: src/readelf.c:8296
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [Offset]\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64>:\n"
+" [Offset]\n"
+
+#: src/readelf.c:8346
+#, fuzzy, c-format
+msgid "cannot get next unit: %s"
+msgstr "No se puede obtener próximo DIE: %s"
+
+#: src/readelf.c:8366
+#, fuzzy, c-format
+msgid ""
+" Type unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+" Type signature: %#<PRIx64>, Type offset: %#<PRIx64> [%<PRIx64>]\n"
+msgstr ""
+"Tipo de unidad al compensar  %<PRIu64>:\n"
+" Versión: %<PRIu16>, Abreviación de sección de compensación: %<PRIu64>,  "
+"Tamaño de dirección: %<PRIu8>, Tamaño de compensación: %<PRIu8>\n"
+" Tipo de firma: %#<PRIx64>, Tipo de compensación: %#<PRIx64>\n"
+
+#: src/readelf.c:8378
+#, c-format
+msgid ""
+" Compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+"Unidad de compilación en compensación %<PRIu64>:\n"
+" Versión: %<PRIu16>, Compensación de sección de abreviatura: %<PRIu64>,  "
+"Tamaño de dirección: %<PRIu8>, Tamaño de compensación: %<PRIu8>\n"
+
+#: src/readelf.c:8388 src/readelf.c:8549
+#, c-format
+msgid " Unit type: %s (%<PRIu8>)"
+msgstr ""
+
+#: src/readelf.c:8415
+#, c-format
+msgid "unknown version (%d) or unit type (%d)"
+msgstr ""
+
+#: src/readelf.c:8444
+#, c-format
+msgid "cannot get DIE offset: %s"
+msgstr "no se puede obtener DIE en compensación: %s"
+
+#: src/readelf.c:8453
+#, fuzzy, c-format
+msgid "cannot get tag of DIE at offset [%<PRIx64>] in section '%s': %s"
+msgstr ""
+"no se ha podido obtener etiqueta de DIE en compensación%<PRIu64> en sección "
+"'%s': %s"
+
+#: src/readelf.c:8489
+#, c-format
+msgid "cannot get next DIE: %s\n"
+msgstr "No se puede obtener próximo DIE: %s\n"
+
+#: src/readelf.c:8497
+#, c-format
+msgid "cannot get next DIE: %s"
+msgstr "No se puede obtener próximo DIE: %s"
+
+#: src/readelf.c:8541
+#, fuzzy, c-format
+msgid ""
+" Split compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+"Unidad de compilación en compensación %<PRIu64>:\n"
+" Versión: %<PRIu16>, Compensación de sección de abreviatura: %<PRIu64>,  "
+"Tamaño de dirección: %<PRIu8>, Tamaño de compensación: %<PRIu8>\n"
+
+#: src/readelf.c:8593
+#, fuzzy, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64>:\n"
+
+#: src/readelf.c:8925
+#, fuzzy, c-format
+msgid "unknown form: %s"
+msgstr "Forma %<PRIx64> desconocida"
+
+#. Print what we got so far.
+#: src/readelf.c:9073
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Length:                         %<PRIu64>\n"
+" DWARF version:                  %<PRIuFAST16>\n"
+" Prologue length:                %<PRIu64>\n"
+" Address size:                   %zd\n"
+" Segment selector size:          %zd\n"
+" Min instruction length:         %<PRIuFAST8>\n"
+" Max operations per instruction: %<PRIuFAST8>\n"
+" Initial value if 'is_stmt':     %<PRIuFAST8>\n"
+" Line base:                      %<PRIdFAST8>\n"
+" Line range:                     %<PRIuFAST8>\n"
+" Opcode base:                    %<PRIuFAST8>\n"
+"\n"
+"Opcodes:\n"
+msgstr ""
+"\n"
+" Longitud:                   %<PRIu64>\n"
+" Versión DWARF:              %<PRIuFAST16>\n"
+" Longitud de prólogo:        %<PRIu64>\n"
+" Longitud de instrucción mínima: %<PRIuFAST8>\n"
+" Máximo operaciones por instrucción: %<PRIuFAST8>\n"
+" Valor inicial si '%s': %<PRIuFAST8>\n"
+" Base de línea:              %<PRIdFAST8>\n"
+" Rango de línea:             %<PRIuFAST8>\n"
+" Base de código operativo:   %<PRIuFAST8>\n"
+"\n"
+"Códigos operativos:\n"
+
+#: src/readelf.c:9095
+#, fuzzy, c-format
+msgid "cannot handle .debug_line version: %u\n"
+msgstr "no se puede obtener versión de símbolo: %s"
+
+#: src/readelf.c:9103
+#, fuzzy, c-format
+msgid "cannot handle address size: %u\n"
+msgstr "no hay valor de dirección"
+
+#: src/readelf.c:9111
+#, fuzzy, c-format
+msgid "cannot handle segment selector size: %u\n"
+msgstr "No se puede encontrar la sección: %s"
+
+#: src/readelf.c:9121
+#, c-format
+msgid "invalid data at offset %tu in section [%zu] '%s'"
+msgstr "datos inválidos en compensación %tu en sección [%zu] '%s'"
+
+#: src/readelf.c:9136
+#, c-format
+msgid "  [%*<PRIuFAST8>]  %hhu argument\n"
+msgid_plural "  [%*<PRIuFAST8>]  %hhu arguments\n"
+msgstr[0] "  [%*<PRIuFAST8>]  argumento %hhu \n"
+msgstr[1] "  [%*<PRIuFAST8>]  argumento %hhu\n"
+
+#: src/readelf.c:9147
+msgid ""
+"\n"
+"Directory table:"
+msgstr ""
+"\n"
+"Tabla de Directorio:"
+
+#: src/readelf.c:9153 src/readelf.c:9230
+#, fuzzy, c-format
+msgid "      ["
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:9224
+#, fuzzy
+msgid ""
+"\n"
+"File name table:"
+msgstr ""
+"\n"
+" Tabla de sitio de llamada:"
+
+#: src/readelf.c:9285
+#, fuzzy
+msgid " Entry Dir   Time      Size      Name"
+msgstr ""
+"\n"
+"Tabla de nombre de archivo:\n"
+" Directorio de entrada   Tiempo      Tamaño      Nombre"
+
+#: src/readelf.c:9331
+#, fuzzy
+msgid ""
+"\n"
+"No line number statements."
+msgstr ""
+"\n"
+" Declaraciones de número de Línea:"
+
+#: src/readelf.c:9335
+msgid ""
+"\n"
+"Line number statements:"
+msgstr ""
+"\n"
+" Declaraciones de número de Línea:"
+
+#: src/readelf.c:9350
+#, fuzzy, c-format
+msgid "invalid maximum operations per instruction is zero"
+msgstr "longitud mínima inválida de tamaño de cadena coincidente"
+
+#: src/readelf.c:9384
+#, fuzzy, c-format
+msgid " special opcode %u: address+%u = "
+msgstr " opcode especial %u: dirección+%u = %s, línea%+d = %zu\n"
+
+#: src/readelf.c:9388
+#, fuzzy, c-format
+msgid ", op_index = %u, line%+d = %zu\n"
+msgstr ""
+" opcode especial %u: dirección+%u = %s,  op_index = %u, línea%+d = %zu\n"
+
+#: src/readelf.c:9391
+#, c-format
+msgid ", line%+d = %zu\n"
+msgstr ""
+
+#: src/readelf.c:9409
+#, c-format
+msgid " extended opcode %u: "
+msgstr "  Código operativo extendido %u: "
+
+#: src/readelf.c:9414
+#, fuzzy
+msgid " end of sequence"
+msgstr "Fin de secuencia"
+
+#: src/readelf.c:9432
+#, fuzzy, c-format
+msgid " set address to "
+msgstr "Establecer dirección a %s\n"
+
+#: src/readelf.c:9460
+#, fuzzy, c-format
+msgid " define new file: dir=%u, mtime=%<PRIu64>, length=%<PRIu64>, name=%s\n"
+msgstr ""
+"definir nuevo archivo: dir=%u, mtime=%<PRIu64>, longitud=%<PRIu64>, "
+"nombre=%s\n"
+
+#: src/readelf.c:9474
+#, c-format
+msgid " set discriminator to %u\n"
+msgstr " establecer discriminador a %u\n"
+
+#: src/readelf.c:9501
+#, c-format
+msgid " set inlined context %u, function name %s (0x%x)\n"
+msgstr ""
+
+#: src/readelf.c:9525
+#, fuzzy, c-format
+#| msgid "Also show function names"
+msgid " set function name %s (0x%x)\n"
+msgstr "También mostrar nombres de función"
+
+#. Unknown, ignore it.
+#: src/readelf.c:9532
+#, fuzzy
+msgid " unknown opcode"
+msgstr "código operativo desconocido "
+
+#. Takes no argument.
+#: src/readelf.c:9544
+msgid " copy"
+msgstr "Copiar"
+
+#: src/readelf.c:9555
+#, fuzzy, c-format
+msgid " advance address by %u to "
+msgstr "Dirección de avance por %u a %s\n"
+
+#: src/readelf.c:9559 src/readelf.c:9620
+#, c-format
+msgid ", op_index to %u"
+msgstr ""
+
+#: src/readelf.c:9571
+#, c-format
+msgid " advance line by constant %d to %<PRId64>\n"
+msgstr " línea de avance por la constante %d a %<PRId64>\n"
+
+#: src/readelf.c:9581
+#, c-format
+msgid " set file to %<PRIu64>\n"
+msgstr " establecer archivo a %<PRIu64>\n"
+
+#: src/readelf.c:9592
+#, c-format
+msgid " set column to %<PRIu64>\n"
+msgstr "  Establecer columna a %<PRIu64>\n"
+
+#: src/readelf.c:9599
+#, c-format
+msgid " set '%s' to %<PRIuFAST8>\n"
+msgstr "Establecer '%s' a %<PRIuFAST8>\n"
+
+#. Takes no argument.
+#: src/readelf.c:9605
+msgid " set basic block flag"
+msgstr "Establecer bandera de bloque básico"
+
+#: src/readelf.c:9616
+#, fuzzy, c-format
+msgid " advance address by constant %u to "
+msgstr "Dirección de avance por constante %u a %s\n"
+
+#: src/readelf.c:9636
+#, fuzzy, c-format
+msgid " advance address by fixed value %u to \n"
+msgstr "dirección de avance por valor corregido %u a %s\n"
+
+#. Takes no argument.
+#: src/readelf.c:9646
+msgid " set prologue end flag"
+msgstr " Establecer bandera prologue_end"
+
+#. Takes no argument.
+#: src/readelf.c:9651
+msgid " set epilogue begin flag"
+msgstr " Establecer bandera epilogue_begin"
+
+#: src/readelf.c:9661
+#, c-format
+msgid " set isa to %u\n"
+msgstr " establecer isa para %u\n"
+
+#. This is a new opcode the generator but not we know about.
+#. Read the parameters associated with it but then discard
+#. everything.  Read all the parameters for this opcode.
+#: src/readelf.c:9670
+#, c-format
+msgid " unknown opcode with %<PRIu8> parameter:"
+msgid_plural " unknown opcode with %<PRIu8> parameters:"
+msgstr[0] " opcódigo con parámetro %<PRIu8> desconocido:"
+msgstr[1] " opcódigo con parámetros %<PRIu8> desconocido:"
+
+#: src/readelf.c:9871
+#, fuzzy, c-format
+msgid "    <INVALID DATA>\n"
+msgstr "   <DATOS INVÁLIDOS>\n"
+
+#: src/readelf.c:9911
+#, fuzzy, c-format
+msgid "invalid loclists data"
+msgstr "datos inválidos"
+
+#: src/readelf.c:10381 src/readelf.c:11426
+msgid "   <INVALID DATA>\n"
+msgstr "   <DATOS INVÁLIDOS>\n"
+
+#: src/readelf.c:10512
+#, c-format
+msgid "%*s*** non-terminated string at end of section"
+msgstr "%*s*** cadena no finalizada al final de la sección"
+
+#: src/readelf.c:10535
+#, fuzzy, c-format
+msgid "%*s*** missing DW_MACINFO_start_file argument at end of section"
+msgstr "%*s*** cadena no finalizada al final de la sección"
+
+#: src/readelf.c:10630
+#, fuzzy, c-format
+msgid " Offset:             0x%<PRIx64>\n"
+msgstr "  Propietario          Tamaño\n"
+
+#: src/readelf.c:10642
+#, fuzzy, c-format
+msgid " Version:            %<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:10648 src/readelf.c:11547
+#, c-format
+msgid "  unknown version, cannot parse section\n"
+msgstr ""
+
+#: src/readelf.c:10655
+#, fuzzy, c-format
+msgid " Flag:               0x%<PRIx8>"
+msgstr "  Dirección de punto de entrada:               %#<PRIx64>\n"
+
+#: src/readelf.c:10684
+#, fuzzy, c-format
+msgid " Offset length:      %<PRIu8>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:10692
+#, fuzzy, c-format
+msgid " .debug_line offset: 0x%<PRIx64>\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:10717
+#, fuzzy, c-format
+msgid "  extension opcode table, %<PRIu8> items:\n"
+msgstr " opcódigo con parámetro %<PRIu8> desconocido:"
+
+#: src/readelf.c:10724
+#, c-format
+msgid "    [%<PRIx8>]"
+msgstr ""
+
+#: src/readelf.c:10736
+#, fuzzy, c-format
+msgid " %<PRIu8> arguments:"
+msgstr "  [%*<PRIuFAST8>]  argumento %hhu \n"
+
+#: src/readelf.c:10751
+#, c-format
+msgid " no arguments."
+msgstr ""
+
+#: src/readelf.c:10952
+#, c-format
+msgid " [%5d] DIE offset: %6<PRId64>, CU DIE offset: %6<PRId64>, name: %s\n"
+msgstr ""
+" Compensación [%5d] DIE: %6<PRId64>, Compensación CU DIE: %6<PRId64>, "
+"nombre: %s\n"
+
+#: src/readelf.c:11007
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" %*s  String\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64>:\n"
+" %*s  String\n"
+
+#. TRANS: the debugstr| prefix makes the string unique.
+#: src/readelf.c:11012
+msgctxt "debugstr"
+msgid "Offset"
+msgstr ""
+
+#: src/readelf.c:11022
+#, fuzzy, c-format
+msgid " *** error, missing string terminator\n"
+msgstr " *** error en lectura de cadenas: %s\n"
+
+#: src/readelf.c:11144
+#, fuzzy, c-format
+msgid " Length:        %8<PRIu64>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11146
+#, fuzzy, c-format
+msgid " Offset size:   %8<PRIu8>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11160
+#, fuzzy, c-format
+msgid " DWARF version: %8<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11169
+#, fuzzy, c-format
+msgid " Padding:       %8<PRIx16>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11223
+#, c-format
+msgid ""
+"\n"
+"Call frame search table section [%2zu] '.eh_frame_hdr':\n"
+msgstr ""
+"\n"
+"Sección de tabla de búsqueda de marco de llamada [%2zu] '.eh_frame_hdr':\n"
+
+#: src/readelf.c:11325
+#, c-format
+msgid ""
+"\n"
+"Exception handling table section [%2zu] '.gcc_except_table':\n"
+msgstr ""
+"\n"
+"Excepción en el manejo de la sección de tabla [%2zu] '.gcc_except_table':\n"
+
+#: src/readelf.c:11348
+#, c-format
+msgid " LPStart encoding:    %#x "
+msgstr "Codificación LPStart:    %#x "
+
+#: src/readelf.c:11360
+#, c-format
+msgid " TType encoding:      %#x "
+msgstr "Codificación TType:      %#x "
+
+#: src/readelf.c:11377
+#, c-format
+msgid " Call site encoding:  %#x "
+msgstr "Codificación de sitio de llamada:  %#x "
+
+#: src/readelf.c:11392
+msgid ""
+"\n"
+" Call site table:"
+msgstr ""
+"\n"
+" Tabla de sitio de llamada:"
+
+#: src/readelf.c:11408
+#, c-format
+msgid ""
+" [%4u] Call site start:   %#<PRIx64>\n"
+"        Call site length:  %<PRIu64>\n"
+"        Landing pad:       %#<PRIx64>\n"
+"        Action:            %u\n"
+msgstr ""
+" [%4u] Call site start:   %#<PRIx64>\n"
+"        Call site length:  %<PRIu64>\n"
+"        Landing pad:       %#<PRIx64>\n"
+"        Action:            %u\n"
+
+#: src/readelf.c:11481
+#, c-format
+msgid "invalid TType encoding"
+msgstr "Codificación TType inválida"
+
+#: src/readelf.c:11508
+#, fuzzy, c-format
+msgid ""
+"\n"
+"GDB section [%2zu] '%s' at offset %#<PRIx64> contains %<PRId64> bytes :\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64> contiene entrada %zu:\n"
+
+#: src/readelf.c:11537
+#, fuzzy, c-format
+msgid " Version:         %<PRId32>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11556
+#, fuzzy, c-format
+msgid " CU offset:       %#<PRIx32>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11563
+#, fuzzy, c-format
+msgid " TU offset:       %#<PRIx32>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11570
+#, fuzzy, c-format
+msgid " address offset:  %#<PRIx32>\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11577
+#, fuzzy, c-format
+msgid " symbol offset:   %#<PRIx32>\n"
+msgstr " (compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11587
+#, fuzzy, c-format
+msgid " shortcut offset: %#<PRIx32>\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11595
+#, fuzzy, c-format
+msgid " constant offset: %#<PRIx32>\n"
+msgstr " (fin de compensación: %#<PRIx64>)"
+
+#: src/readelf.c:11609
+#, fuzzy, c-format
+msgid ""
+"\n"
+" CU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64> contiene entrada %zu:\n"
+
+#: src/readelf.c:11634
+#, fuzzy, c-format
+msgid ""
+"\n"
+" TU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64> contiene entrada %zu:\n"
+
+#: src/readelf.c:11663
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Address list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+"Sección DWARF [%2zu] '%s' en compensación %#<PRIx64> contiene entrada %zu:\n"
+
+#: src/readelf.c:11706
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+"Tabla de símbolos inválida en compensación %#0<PRIx64>\n"
+
+#: src/readelf.c:11791
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Shortcut table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+"Tabla de símbolos inválida en compensación %#0<PRIx64>\n"
+
+#: src/readelf.c:11803
+#, c-format
+msgid "Language of main: %s\n"
+msgstr ""
+
+#: src/readelf.c:11804
+#, c-format
+msgid "Name of main: "
+msgstr ""
+
+#: src/readelf.c:11887
+#, c-format
+msgid "cannot get debug context descriptor: %s"
+msgstr "no se puede depurar descriptor de contexto: %s"
+
+#: src/readelf.c:12253 src/readelf.c:12873 src/readelf.c:12983
+#: src/readelf.c:13040
+#, c-format
+msgid "cannot convert core note data: %s"
+msgstr "no es posible convertir datos de la nota principal: %s"
+
+#: src/readelf.c:12617
+#, c-format
+msgid ""
+"\n"
+"%*s... <repeats %u more times> ..."
+msgstr ""
+"\n"
+"%*s... <repeats %u more times> ..."
+
+#: src/readelf.c:13119
+msgid "  Owner          Data size  Type\n"
+msgstr "  Owner          Data size  Type\n"
+
+#: src/readelf.c:13147
+#, c-format
+msgid "  %-13.*s  %9<PRId32>  %s\n"
+msgstr "  %-13.*s  %9<PRId32>  %s\n"
+
+#: src/readelf.c:13199
+#, fuzzy, c-format
+msgid "cannot get content of note: %s"
+msgstr "no se puede obtener el contenido de sección de nota: %s"
+
+#: src/readelf.c:13232
+#, c-format
+msgid ""
+"\n"
+"Note section [%2zu] '%s' of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sección de nota [%2zu] '%s' de %<PRIu64> bytes en compensación %#0<PRIx64>:\n"
+
+#: src/readelf.c:13255
+#, c-format
+msgid ""
+"\n"
+"Note segment of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Segmento de nota de %<PRIu64> bytes en compensación %#0<PRIx64>:\n"
+
+#: src/readelf.c:13302
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no data to dump.\n"
+msgstr ""
+"\n"
+"Sección [%Zu] '%s' no tiene datos para volcar.\n"
+
+#: src/readelf.c:13329 src/readelf.c:13380
+#, fuzzy, c-format
+msgid "cannot get data for section [%zu] '%s': %s"
+msgstr "no se pueden obtener datos para sección [%Zu] '%s': %s"
+
+#: src/readelf.c:13334
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Volcado Hex de sección [%Zu] '%s', %<PRIu64> bytes en compensación "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13339
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes (%zd uncompressed) at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Volcado Hex de sección [%Zu] '%s', %<PRIu64> bytes en compensación "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13353
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no strings to dump.\n"
+msgstr ""
+"\n"
+"Sección [%Zu] '%s' no tiene datos para volcar.\n"
+
+#: src/readelf.c:13385
+#, fuzzy, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sección de cadena [%Zu] '%s' contiene %<PRIu64> bytes en compensación "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13390
+#, fuzzy, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes (%zd uncompressed) at "
+"offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sección de cadena [%Zu] '%s' contiene %<PRIu64> bytes en compensación "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13438
+#, c-format
+msgid ""
+"\n"
+"section [%lu] does not exist"
+msgstr ""
+"\n"
+"sección [%lu] no existe"
+
+#: src/readelf.c:13468
+#, c-format
+msgid ""
+"\n"
+"section '%s' does not exist"
+msgstr ""
+"\n"
+"sección '%s' no existe"
+
+#: src/readelf.c:13523
+#, c-format
+msgid "cannot get symbol index of archive '%s': %s"
+msgstr "no se puede obtener el índice de símbolo de archivo '%s': %s"
+
+#: src/readelf.c:13526
+#, c-format
+msgid ""
+"\n"
+"Archive '%s' has no symbol index\n"
+msgstr ""
+"\n"
+"Archivo '%s' no tiene índice de símbolo\n"
+
+#: src/readelf.c:13530
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Index of archive '%s' has %zu entries:\n"
+msgstr ""
+"\n"
+"Índice de archivo '%s' tiene %Zu entradas:\n"
+
+#: src/readelf.c:13548
+#, fuzzy, c-format
+msgid "cannot extract member at offset %zu in '%s': %s"
+msgstr "no es posible extraer miembro en compensación %Zu en '%s': %s"
+
+#: src/readelf.c:13553
+#, c-format
+msgid "Archive member '%s' contains:\n"
+msgstr "Miembro de archivo contiene '%s':\n"
+
+#: src/size.c:55
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  The default "
+"is `bsd'"
+msgstr ""
+"Utilice el formato de salida FORMAT. FORMAT puede ser tanto `bsd' como "
+"`sysv'. El establecido por defecto es `bsd'"
+
+#: src/size.c:57
+msgid "Same as `--format=sysv'"
+msgstr "lo mismo que `--format=sysv'"
+
+#: src/size.c:58
+msgid "Same as `--format=bsd'"
+msgstr "lo mismo que `--format=bsd'"
+
+#: src/size.c:61
+msgid "Same as `--radix=10'"
+msgstr "lo mismo que `--radix=10'"
+
+#: src/size.c:62
+msgid "Same as `--radix=8'"
+msgstr "lo mismo que `--radix=8'"
+
+#: src/size.c:63
+msgid "Same as `--radix=16'"
+msgstr "lo mismo que`--radix=16'"
+
+#: src/size.c:65
+msgid "Similar to `--format=sysv' output but in one line"
+msgstr "Similar a la salida `--format=sysv' pero en una sola línea"
+
+#: src/size.c:69
+msgid "Print size and permission flags for loadable segments"
+msgstr ""
+"Imprime el tamaño y las marcas de permiso para los segmentos que pueden ser "
+"cargados"
+
+#: src/size.c:70
+msgid "Display the total sizes (bsd only)"
+msgstr "Muestra el tamaño total (bsd solamente)"
+
+#. Short description of program.
+#: src/size.c:75
+msgid "List section sizes of FILEs (a.out by default)."
+msgstr "Lista los tamaños de sección de FICHEROS (por defecto a.out). "
+
+#: src/size.c:239
+#, c-format
+msgid "Invalid format: %s"
+msgstr "Formato de archivo inválido: %s"
+
+#: src/size.c:250
+#, c-format
+msgid "Invalid radix: %s"
+msgstr "Radical inválido: %s"
+
+#: src/size.c:309
+#, c-format
+msgid "%s: file format not recognized"
+msgstr "%s: No se reconoce el formato del fichero"
+
+#: src/size.c:327
+msgctxt "bsd"
+msgid "text"
+msgstr ""
+
+#: src/size.c:328
+msgctxt "bsd"
+msgid "data"
+msgstr ""
+
+#: src/size.c:329
+msgctxt "bsd"
+msgid "bss"
+msgstr ""
+
+#: src/size.c:330
+msgctxt "bsd"
+msgid "dec"
+msgstr ""
+
+#: src/size.c:331
+msgctxt "bsd"
+msgid "hex"
+msgstr ""
+
+#: src/size.c:332
+msgctxt "bsd"
+msgid "filename"
+msgstr ""
+
+#: src/size.c:416 src/size.c:557
+#, c-format
+msgid " (ex %s)"
+msgstr " (ex %s)"
+
+#: src/size.c:418
+#, fuzzy
+#| msgid "invalid section"
+msgctxt "sysv"
+msgid "section"
+msgstr "sección inválida"
+
+#: src/size.c:419
+msgctxt "sysv"
+msgid "size"
+msgstr ""
+
+#: src/size.c:420
+msgctxt "sysv"
+msgid "addr"
+msgstr ""
+
+#: src/size.c:449 src/size.c:452 src/size.c:455
+msgctxt "sysv"
+msgid "Total"
+msgstr ""
+
+#: src/size.c:479
+#, fuzzy
+msgid "cannot get section header"
+msgstr "no se puede obtener encabezamiento de sección\n"
+
+#: src/size.c:582
+msgid "(TOTALS)\n"
+msgstr "(TOTALES)\n"
+
+#: src/stack.c:487
+#, c-format
+msgid "-p PID should be a positive process id."
+msgstr ""
+
+#: src/stack.c:493
+#, fuzzy, c-format
+msgid "Cannot open core file '%s'"
+msgstr "Imposible abrir el archivo '%s'"
+
+#: src/stack.c:553
+#, c-format
+msgid "-n MAXFRAMES should be 0 or higher."
+msgstr ""
+
+#: src/stack.c:565
+#, c-format
+msgid "-e EXEC needs a core given by --core."
+msgstr ""
+
+#: src/stack.c:569
+#, c-format
+msgid "-1 needs a thread id given by -p."
+msgstr ""
+
+#: src/stack.c:573
+#, c-format
+msgid "One of -p PID or --core COREFILE should be given."
+msgstr ""
+
+#: src/stack.c:645
+#, fuzzy
+msgid "Show stack of process PID"
+msgstr "No se puede crear el árbol de búsqueda"
+
+#: src/stack.c:647
+msgid "Show stack found in COREFILE"
+msgstr ""
+
+#: src/stack.c:648
+msgid "(optional) EXECUTABLE that produced COREFILE"
+msgstr ""
+
+#: src/stack.c:652
+msgid "Output selection options:"
+msgstr "Opciones de selección de salida:"
+
+#: src/stack.c:654
+#, fuzzy
+msgid "Additionally show frame activation"
+msgstr "Selección de salida adicional:"
+
+#: src/stack.c:656
+msgid "Additionally try to lookup DWARF debuginfo name for frame address"
+msgstr ""
+
+#: src/stack.c:659
+msgid ""
+"Additionally show inlined function frames using DWARF debuginfo if available "
+"(implies -d)"
+msgstr ""
+
+#: src/stack.c:661
+msgid "Additionally show module file information"
+msgstr ""
+
+#: src/stack.c:663
+#, fuzzy
+msgid "Additionally show source file information"
+msgstr "Selección de salida adicional:"
+
+#: src/stack.c:665
+msgid ""
+"Show all additional information (activation, debugname, inlines, module and "
+"source)"
+msgstr ""
+
+#: src/stack.c:667
+msgid "Do not resolve address to function symbol name"
+msgstr ""
+
+#: src/stack.c:669
+msgid "Show raw function symbol names, do not try to demangle names"
+msgstr ""
+
+#: src/stack.c:671
+msgid "Show module build-id, load address and pc offset"
+msgstr ""
+
+#: src/stack.c:673
+msgid "Show the backtrace of only one thread"
+msgstr ""
+
+#: src/stack.c:675
+msgid "Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"
+msgstr ""
+
+#: src/stack.c:677
+msgid "Show module memory map with build-id, elf and debug files detected"
+msgstr ""
+
+#: src/stack.c:685
+msgid ""
+"Print a stack for each thread in a process or core file.\n"
+"\n"
+"Program exits with return code 0 if all frames were shown without any "
+"errors.  If some frames were shown, but there were some non-fatal errors, "
+"possibly causing an incomplete backtrace, the program exits with return code "
+"1.  If no frames could be shown, or a fatal error occurred the program exits "
+"with return code 2.  If the program was invoked with bad or missing "
+"arguments it will exit with return code 64."
+msgstr ""
+
+#: src/stack.c:760
+#, c-format
+msgid "Couldn't show any frames."
+msgstr ""
+
+#: src/strings.c:64
+msgid "Output Selection:"
+msgstr "Selección de salida:"
+
+#: src/strings.c:65
+msgid "Scan entire file, not only loaded sections"
+msgstr "Explorar todo el archivo, no sólo las secciones cargadas"
+
+#: src/strings.c:67
+msgid "Only NUL-terminated sequences of MIN-LEN characters or more are printed"
+msgstr "Sólo secuencias NUL-terminated de caracteres MIN-LEN o más se imprimen"
+
+#: src/strings.c:68
+msgid ""
+"Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, "
+"{B,L} = 32-bit"
+msgstr ""
+"Seleccionar tamaño de caracter y Endianess: s = 7-bit, S = 8-bit, {b,l} = 16-"
+"bit, {B,L} = 32-bit"
+
+#: src/strings.c:72
+msgid "Print name of the file before each string."
+msgstr "Imprimir nombre de archivo antes de cada cadena."
+
+#: src/strings.c:74
+msgid "Print location of the string in base 8, 10, or 16 respectively."
+msgstr "Imprimir ubicación de la cadena en base 8, 10, o 16 respectivamente."
+
+#: src/strings.c:75
+msgid "Alias for --radix=o"
+msgstr "Alias para --radix=o"
+
+#. Short description of program.
+#: src/strings.c:82
+msgid "Print the strings of printable characters in files."
+msgstr "Imprimir las cadenas de caracteres imprimibles en archivos."
+
+#: src/strings.c:255 src/strings.c:290
+#, c-format
+msgid "invalid value '%s' for %s parameter"
+msgstr "Valor inválido '%s' para parámetro %s"
+
+#: src/strings.c:300
+msgid "invalid minimum length of matched string size"
+msgstr "longitud mínima inválida de tamaño de cadena coincidente"
+
+#: src/strings.c:583
+#, fuzzy
+msgid "lseek failed"
+msgstr "lseek64 falló"
+
+#: src/strings.c:600 src/strings.c:664
+msgid "re-mmap failed"
+msgstr "re-mmap falló"
+
+#: src/strings.c:637
+msgid "mprotect failed"
+msgstr "mprotect falló"
+
+#: src/strings.c:726
+#, c-format
+msgid "Skipping section %zd '%s' data outside file"
+msgstr ""
+
+#: src/strip.c:70
+msgid "Place stripped output into FILE"
+msgstr "Colocar la salida obtenida en FICHERO"
+
+#: src/strip.c:71
+msgid "Extract the removed sections into FILE"
+msgstr "Extraer secciones eliminadas en FICHERO"
+
+#: src/strip.c:72
+msgid "Embed name FILE instead of -f argument"
+msgstr "Incorporar nombre FILE en lugar de argumento -f"
+
+#: src/strip.c:76
+msgid "Remove all debugging symbols"
+msgstr "Elimina todos los símbolos de depuración"
+
+#: src/strip.c:80
+msgid "Remove section headers (not recommended)"
+msgstr "Quitar sección de cabeceras (no recomendado)"
+
+#: src/strip.c:82
+msgid "Copy modified/access timestamps to the output"
+msgstr "Copiar marcas de tiempo modificadas/acceso a la salida"
+
+#: src/strip.c:84
+msgid ""
+"Resolve all trivial relocations between debug sections if the removed "
+"sections are placed in a debug file (only relevant for ET_REL files, "
+"operation is not reversible, needs -f)"
+msgstr ""
+
+#: src/strip.c:86
+msgid ""
+"Similar to --reloc-debug-sections, but resolve all trivial relocations "
+"between debug sections in place.  No other stripping is performed (operation "
+"is not reversible, incompatible with -f, -g, --remove-comment and --remove-"
+"section)"
+msgstr ""
+
+#: src/strip.c:88
+msgid "Remove .comment section"
+msgstr "Quitar sección de comentario"
+
+#: src/strip.c:89
+msgid ""
+"Remove the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once.  Only non-allocated sections can be removed."
+msgstr ""
+
+#: src/strip.c:90
+msgid ""
+"Keep the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once."
+msgstr ""
+
+#. Short description of program.
+#: src/strip.c:97
+msgid "Discard symbols from object files."
+msgstr "Descarta símbolos de archivos objeto."
+
+#: src/strip.c:245
+msgid "--reloc-debug-sections used without -f"
+msgstr ""
+
+#: src/strip.c:251
+msgid ""
+"--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --"
+"remove-section"
+msgstr ""
+
+#: src/strip.c:265
+msgid "Only one input file allowed together with '-o' and '-f'"
+msgstr "Sólo se permite ingresar un archivo junto con '-o' y '-f'"
+
+#: src/strip.c:287
+#, c-format
+msgid "-f option specified twice"
+msgstr "opción -f especificada dos veces"
+
+#: src/strip.c:296
+#, c-format
+msgid "-F option specified twice"
+msgstr "opción -F especificada dos veces"
+
+#: src/strip.c:359
+#, fuzzy, c-format
+msgid "cannot both keep and remove .comment section"
+msgstr "Quitar sección de comentario"
+
+#: src/strip.c:478
+#, fuzzy
+msgid "bad relocation"
+msgstr "Mostrar reubicaciones"
+
+#: src/strip.c:756 src/strip.c:780
+#, c-format
+msgid "cannot stat input file '%s'"
+msgstr "no sepuede stat fichero de entrada '%s'"
+
+#: src/strip.c:770
+#, c-format
+msgid "while opening '%s'"
+msgstr "mientras se abría '%s'"
+
+#: src/strip.c:808
+#, c-format
+msgid "%s: cannot use -o or -f when stripping archive"
+msgstr "%s: no puede utilizarse -o o -f cuando se extrae un archivo"
+
+#. We would like to support ar archives, but currently it just
+#. doesn't work at all since we call elf_clone on the members
+#. which doesn't really support ar members.
+#. result = handle_ar (fd, elf, NULL, fname,
+#. preserve_dates ? tv : NULL);
+#.
+#: src/strip.c:820
+#, fuzzy, c-format
+msgid "%s: no support for stripping archive"
+msgstr "%s: no puede utilizarse -o o -f cuando se extrae un archivo"
+
+#: src/strip.c:1057
+#, c-format
+msgid "cannot open EBL backend"
+msgstr "No se puede abrir el segundo plano EBL"
+
+#: src/strip.c:1101
+#, fuzzy
+msgid "cannot get number of phdrs"
+msgstr "no se pudo determinar la cantidad de encabezados de programa: %s"
+
+#: src/strip.c:1115 src/strip.c:1158
+#, fuzzy, c-format
+msgid "cannot create new ehdr for file '%s': %s"
+msgstr "no se puede crear fichero nuevo '%s': %s"
+
+#: src/strip.c:1125 src/strip.c:1168
+#, fuzzy, c-format
+msgid "cannot create new phdr for file '%s': %s"
+msgstr "no se puede crear fichero nuevo '%s': %s"
+
+#: src/strip.c:1248
+#, c-format
+msgid "illformed file '%s'"
+msgstr "Fichero illformed '%s'"
+
+#: src/strip.c:1258
+#, fuzzy, c-format
+msgid "Cannot remove allocated section '%s'"
+msgstr "No se puede asignar sección PLT: %s"
+
+#: src/strip.c:1267
+#, fuzzy, c-format
+msgid "Cannot both keep and remove section '%s'"
+msgstr "No se puede añadir nueva sección: %s"
+
+#: src/strip.c:1631 src/strip.c:1746
+#, c-format
+msgid "while generating output file: %s"
+msgstr "al generar fichero de salida: %s"
+
+#: src/strip.c:1695
+#, fuzzy, c-format
+msgid "%s: error while updating ELF header: %s"
+msgstr "%s: error al crear encabezamiento ELF: %s"
+
+#: src/strip.c:1704
+#, fuzzy, c-format
+msgid "%s: error while getting shdrstrndx: %s"
+msgstr "%s: error al crear encabezamiento ELF: %s"
+
+#: src/strip.c:1712 src/strip.c:2552
+#, fuzzy, c-format
+msgid "%s: error updating shdrstrndx: %s"
+msgstr "%s: error al crear encabezamiento ELF: %s"
+
+#: src/strip.c:1729
+#, c-format
+msgid "while preparing output for '%s'"
+msgstr "al preparar salida para '%s'"
+
+#: src/strip.c:1790 src/strip.c:1852
+#, c-format
+msgid "while create section header section: %s"
+msgstr "al crear sección de encabezamiento de sección: %s"
+
+#: src/strip.c:1799
+#, c-format
+msgid "cannot allocate section data: %s"
+msgstr "no se puede asignar espacio para los datos: %s"
+
+#: src/strip.c:1863
+#, c-format
+msgid "while create section header string table: %s"
+msgstr "al crear tabla de cadenas de encabezamiento de sección: %s"
+
+#: src/strip.c:1869
+#, fuzzy
+msgid "no memory to create section header string table"
+msgstr "al crear tabla de cadenas de encabezamiento de sección: %s"
+
+#: src/strip.c:2082
+#, c-format
+msgid "Cannot remove symbol [%zd] from allocated symbol table [%zd]"
+msgstr ""
+
+#: src/strip.c:2469 src/strip.c:2574
+#, c-format
+msgid "while writing '%s': %s"
+msgstr "al escribir '%s': %s"
+
+#: src/strip.c:2480
+#, c-format
+msgid "while creating '%s'"
+msgstr "al crear '%s'"
+
+#: src/strip.c:2503
+#, c-format
+msgid "while computing checksum for debug information"
+msgstr "al computar la suma de verificación para información de depuración"
+
+#: src/strip.c:2544
+#, c-format
+msgid "%s: error while creating ELF header: %s"
+msgstr "%s: error al crear encabezamiento ELF: %s"
+
+#: src/strip.c:2560
+#, c-format
+msgid "%s: error while reading the file: %s"
+msgstr "%s: error al leer el fichero: %s"
+
+#: src/strip.c:2599 src/strip.c:2619
+#, c-format
+msgid "while writing '%s'"
+msgstr "al escribir '%s'"
+
+#: src/strip.c:2656 src/strip.c:2663
+#, c-format
+msgid "error while finishing '%s': %s"
+msgstr "Error al terminar '%s': %s"
+
+#: src/strip.c:2680 src/strip.c:2756
+#, c-format
+msgid "cannot set access and modification date of '%s'"
+msgstr "no es posible establecer acceso y fecha de modificación de '%s'"
+
+#: src/unstrip.c:65
+msgid "Match MODULE against file names, not module names"
+msgstr "Coincidir MODULO con nombres de archivo, no con nombres de módulo"
+
+#: src/unstrip.c:66
+msgid "Silently skip unfindable files"
+msgstr "Omitir silenciosamente los archivos perdidos"
+
+#: src/unstrip.c:69
+msgid "Place output into FILE"
+msgstr "Colocar salida en FICHERO"
+
+#: src/unstrip.c:71
+msgid "Create multiple output files under DIRECTORY"
+msgstr "Crear archivos de salida múltiple bajo DIRECTORIO"
+
+#: src/unstrip.c:72
+msgid "Use module rather than file names"
+msgstr "Usar módulo en lugar de nombres de archivo"
+
+#: src/unstrip.c:74
+msgid "Create output for modules that have no separate debug information"
+msgstr ""
+"Crear salida para módulos que no tienen información de depuración "
+"independiente"
+
+#: src/unstrip.c:77
+msgid "Apply relocations to section contents in ET_REL files"
+msgstr "Aplicar reubicaciones a contenido de sección en archivos ET_REL"
+
+#: src/unstrip.c:79
+msgid "Only list module and file names, build IDs"
+msgstr "Solamente listar módulo y nombres de archivo, crear los ID"
+
+#: src/unstrip.c:81
+msgid "Force combining files even if some ELF headers don't seem to match"
+msgstr ""
+
+#: src/unstrip.c:125
+#, c-format
+msgid "-d option specified twice"
+msgstr "opción -d especificada dos veces"
+
+#: src/unstrip.c:160
+#, c-format
+msgid "only one of -o or -d allowed"
+msgstr "Sólo se permite usar -o ó -d "
+
+#: src/unstrip.c:169
+#, c-format
+msgid "-n cannot be used with explicit files or -o or -d"
+msgstr "-n no puede utilizarse con archivos explícitos o con -o ó -d"
+
+#: src/unstrip.c:184
+#, c-format
+msgid "output directory '%s'"
+msgstr "Directorio de salida '%s'"
+
+#: src/unstrip.c:193
+#, c-format
+msgid "exactly two file arguments are required"
+msgstr "dos argumentos de archivos se requieren exactamente"
+
+#: src/unstrip.c:199
+#, c-format
+msgid "-m, -a, -R, and -i options not allowed with explicit files"
+msgstr "No se permiten las opciones -m, -a, -R, ni -i con archivos explícitos"
+
+#: src/unstrip.c:212
+#, c-format
+msgid "-o or -d is required when using implicit files"
+msgstr "se requiere -o ó -d cuando se utilizan archivos implícitos"
+
+#: src/unstrip.c:235
+#, c-format
+msgid "cannot create ELF header: %s"
+msgstr "no se puede crear el encabezamiento ELF: %s"
+
+#: src/unstrip.c:239
+#, fuzzy, c-format
+msgid "cannot get shdrstrndx:%s"
+msgstr "No se puede encontrar la sección: %s"
+
+#: src/unstrip.c:243 src/unstrip.c:2136
+#, c-format
+msgid "cannot get ELF header: %s"
+msgstr "no se puede leer encabezamiento ELF: %s"
+
+#: src/unstrip.c:253
+#, fuzzy, c-format
+msgid "cannot get new zero section: %s"
+msgstr "No se puede encontrar la sección: %s"
+
+#: src/unstrip.c:256
+#, fuzzy, c-format
+msgid "cannot update new zero section: %s"
+msgstr "no se puede actualizar reubicación: %s"
+
+#: src/unstrip.c:260
+#, c-format
+msgid "cannot copy ELF header: %s"
+msgstr "no se puede copiar encabezamiento ELF: %s"
+
+#: src/unstrip.c:264 src/unstrip.c:2154 src/unstrip.c:2197
+#, fuzzy, c-format
+msgid "cannot get number of program headers: %s"
+msgstr "no se pudo determinar la cantidad de encabezados de programa: %s"
+
+#: src/unstrip.c:269 src/unstrip.c:2158
+#, c-format
+msgid "cannot create program headers: %s"
+msgstr "No pueden crear encabezamientos de programa: %s"
+
+#: src/unstrip.c:275
+#, c-format
+msgid "cannot copy program header: %s"
+msgstr "no puede copiar encabezamiento de programa: %s"
+
+#: src/unstrip.c:285
+#, c-format
+msgid "cannot copy section header: %s"
+msgstr "no se puede copiar encabezamiento de sección: %s"
+
+#: src/unstrip.c:288 src/unstrip.c:1748
+#, c-format
+msgid "cannot get section data: %s"
+msgstr "no se pueden obtener datos de sección: %s"
+
+#: src/unstrip.c:290 src/unstrip.c:1750
+#, c-format
+msgid "cannot copy section data: %s"
+msgstr "no pueden copiar datos de sección: %s"
+
+#: src/unstrip.c:318
+#, c-format
+msgid "cannot create directory '%s'"
+msgstr "no se puede crear el directorio '%s'"
+
+#: src/unstrip.c:392 src/unstrip.c:666 src/unstrip.c:700 src/unstrip.c:868
+#: src/unstrip.c:1790
+#, c-format
+msgid "cannot get symbol table entry: %s"
+msgstr "no se puede obtener entrada de tabla de símbolos: %s"
+
+#: src/unstrip.c:408 src/unstrip.c:669 src/unstrip.c:690 src/unstrip.c:703
+#: src/unstrip.c:1811 src/unstrip.c:2007 src/unstrip.c:2031
+#, c-format
+msgid "cannot update symbol table: %s"
+msgstr "no se puede actualizar tabla de símbolos: %s"
+
+#: src/unstrip.c:418
+#, c-format
+msgid "cannot update section header: %s"
+msgstr "no se puede actualizar encabezamiento de sección: %s"
+
+#: src/unstrip.c:464
+#, c-format
+msgid "gelf_getrel failed: %s"
+msgstr ""
+
+#: src/unstrip.c:467 src/unstrip.c:482
+#, c-format
+msgid "cannot update relocation: %s"
+msgstr "no se puede actualizar reubicación: %s"
+
+#: src/unstrip.c:479
+#, c-format
+msgid "gelf_getrela failed: %s"
+msgstr ""
+
+#: src/unstrip.c:580
+#, c-format
+msgid "cannot get symbol version: %s"
+msgstr "no se puede obtener versión de símbolo: %s"
+
+#: src/unstrip.c:593
+#, fuzzy, c-format
+msgid "unexpected section type in [%zu] with sh_link to symtab"
+msgstr "tipo de sección inesperado en [%Zu] con sh_link para symtab"
+
+#: src/unstrip.c:857
+#, fuzzy, c-format
+msgid "cannot get symbol section data: %s"
+msgstr "no se pueden obtener datos de sección: %s"
+
+#: src/unstrip.c:859
+#, fuzzy, c-format
+msgid "cannot get string section data: %s"
+msgstr "no se pueden obtener datos de sección: %s"
+
+#: src/unstrip.c:876
+#, fuzzy, c-format
+msgid "invalid string offset in symbol [%zu]"
+msgstr "compensación de cadena inválida en símbolo [%Zu]"
+
+#: src/unstrip.c:939
+msgid "found two identical index map positions."
+msgstr ""
+
+#: src/unstrip.c:990
+msgid "section symbols in unexpected order"
+msgstr ""
+
+#: src/unstrip.c:996
+#, fuzzy
+#| msgid "Strip debugging symbols."
+msgid "found two identical symbols"
+msgstr "Descartar los símbolos de depuración."
+
+#: src/unstrip.c:1066 src/unstrip.c:1474
+#, fuzzy, c-format
+msgid "cannot read section [%zu] name: %s"
+msgstr "no se puede leer nombre [%Zu]: %s"
+
+#: src/unstrip.c:1081
+#, fuzzy, c-format
+msgid "bad sh_link for group section: %s"
+msgstr ".debug_line section inválida"
+
+#: src/unstrip.c:1087
+#, fuzzy, c-format
+msgid "couldn't get shdr for group section: %s"
+msgstr "No se puede obtener encabezamiento de sección 0th: %s"
+
+#: src/unstrip.c:1092
+#, fuzzy, c-format
+msgid "bad data for group symbol section: %s"
+msgstr "no se puede obtener sección para símbolos\n"
+
+#: src/unstrip.c:1098
+#, fuzzy, c-format
+msgid "couldn't get symbol for group section: %s"
+msgstr "no se puede obtener versión de símbolo: %s"
+
+#: src/unstrip.c:1103
+#, fuzzy, c-format
+msgid "bad symbol name for group section: %s"
+msgstr "No se puede obtener el encabezamiento de sección %zu: %s"
+
+#: src/unstrip.c:1114 src/unstrip.c:1594
+#, fuzzy, c-format
+msgid "cannot find matching section for [%zu] '%s'"
+msgstr "no se puede hallar sección coincidente para [%Zu] '%s'"
+
+#: src/unstrip.c:1159 src/unstrip.c:1178 src/unstrip.c:1216
+#, c-format
+msgid "cannot read '.gnu.prelink_undo' section: %s"
+msgstr "no se puede leer sección '.gnu.prelink_undo': %s"
+
+#: src/unstrip.c:1196
+#, c-format
+msgid "overflow with shnum = %zu in '%s' section"
+msgstr ""
+
+#: src/unstrip.c:1207
+#, c-format
+msgid "invalid contents in '%s' section"
+msgstr "contenido inválido en sección '%s'"
+
+#: src/unstrip.c:1378 src/unstrip.c:1394 src/unstrip.c:1674 src/unstrip.c:1966
+#, c-format
+msgid "cannot add section name to string table: %s"
+msgstr "no se puede añadir nombre de sección a tabla de cadenas: %s"
+
+#: src/unstrip.c:1403
+#, c-format
+msgid "cannot update section header string table data: %s"
+msgstr ""
+"no se pueden actualizar datos de tabla de cadenas de encabezamiento de "
+"sección: %s"
+
+#: src/unstrip.c:1432 src/unstrip.c:1436
+#, c-format
+msgid "cannot get section header string table section index: %s"
+msgstr ""
+"no se puede obtener índice de sección de tabla de cadenas de encabezamiento "
+"de sección: %s"
+
+#: src/unstrip.c:1440 src/unstrip.c:1444 src/unstrip.c:1689
+#, c-format
+msgid "cannot get section count: %s"
+msgstr "No se puede obtener cuenta de sección: %s"
+
+#: src/unstrip.c:1447
+msgid "more sections in stripped file than debug file -- arguments reversed?"
+msgstr ""
+"más secciones en el archivo despojado que en el archivo de depuración -- "
+"¿argumentos invertidos?"
+
+#: src/unstrip.c:1451
+msgid "no sections in stripped file"
+msgstr ""
+
+#: src/unstrip.c:1499 src/unstrip.c:1609
+#, c-format
+msgid "cannot read section header string table: %s"
+msgstr "no se puede obtener tabla de cadenas de encabezamiento de sección: %s"
+
+#: src/unstrip.c:1668
+#, c-format
+msgid "cannot add new section: %s"
+msgstr "No se puede añadir nueva sección: %s"
+
+#: src/unstrip.c:1798
+#, fuzzy, c-format
+msgid "symbol [%zu] has invalid section index"
+msgstr "símbolo [%Zu] tiene índice de sección inválido"
+
+#: src/unstrip.c:1830
+#, fuzzy, c-format
+msgid "group has invalid section index [%zd]"
+msgstr "símbolo [%Zu] tiene índice de sección inválido"
+
+#: src/unstrip.c:2115
+#, c-format
+msgid "cannot read section data: %s"
+msgstr "no se puede leer la sección de datos: %s"
+
+#: src/unstrip.c:2144
+#, c-format
+msgid "cannot update ELF header: %s"
+msgstr "No se puede actualizar encabezamiento ELF: %s"
+
+#: src/unstrip.c:2168
+#, c-format
+msgid "cannot update program header: %s"
+msgstr "no se puede actualizar encabezamiento de programa: %s"
+
+#: src/unstrip.c:2173 src/unstrip.c:2256
+#, c-format
+msgid "cannot write output file: %s"
+msgstr "no se puede escribir al archivo de salida: %s"
+
+#: src/unstrip.c:2224
+#, c-format
+msgid "DWARF data not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+"datos DWARF no se ajustan para polarización de pre-enlace; considere prelink "
+"-u"
+
+#: src/unstrip.c:2227
+#, c-format
+msgid ""
+"DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+"Datos DWARF en '%s' no se ajustan a polarización de pre-enlace; considere "
+"prelink -u"
+
+#: src/unstrip.c:2247 src/unstrip.c:2299 src/unstrip.c:2311 src/unstrip.c:2401
+#, c-format
+msgid "cannot create ELF descriptor: %s"
+msgstr "no se puede crear un descriptor ELF: %s"
+
+#: src/unstrip.c:2285
+msgid "WARNING: "
+msgstr ""
+
+#: src/unstrip.c:2287
+msgid ", use --force"
+msgstr ""
+
+#: src/unstrip.c:2315
+msgid "ELF header identification (e_ident) different"
+msgstr ""
+
+#: src/unstrip.c:2319
+msgid "ELF header type (e_type) different"
+msgstr ""
+
+#: src/unstrip.c:2323
+msgid "ELF header machine type (e_machine) different"
+msgstr ""
+
+#: src/unstrip.c:2327
+msgid "stripped program header (e_phnum) smaller than unstripped"
+msgstr ""
+
+#: src/unstrip.c:2358
+#, c-format
+msgid "cannot find stripped file for module '%s': %s"
+msgstr "no se puede hallar archivo obtenido para módulo '%s': %s "
+
+#: src/unstrip.c:2362
+#, c-format
+msgid "cannot open stripped file '%s' for module '%s': %s"
+msgstr "No se puede abrir el archivo '%s' obtenido para módulo '%s': %s"
+
+#: src/unstrip.c:2377
+#, c-format
+msgid "cannot find debug file for module '%s': %s"
+msgstr "no puede hallar archivo de depuración para módulo '%s': %su"
+
+#: src/unstrip.c:2381
+#, c-format
+msgid "cannot open debug file '%s' for module '%s': %s"
+msgstr "No puede abrir archivo de depuración '%s' para módulo '%s': %s"
+
+#: src/unstrip.c:2394
+#, c-format
+msgid "module '%s' file '%s' is not stripped"
+msgstr "No se obtuvo el archivo '%s' de módulo '%s' "
+
+#: src/unstrip.c:2425
+#, c-format
+msgid "cannot cache section addresses for module '%s': %s"
+msgstr ""
+"No puede almacenar en cache direcciones de sección para módulo '%s': %s"
+
+#: src/unstrip.c:2553
+msgid "no matching modules found"
+msgstr "No se encontraron módulos coincidentes"
+
+#: src/unstrip.c:2563
+msgid "matched more than one module"
+msgstr "coincidió con más de un módulo"
+
+#: src/unstrip.c:2608
+msgid ""
+"STRIPPED-FILE DEBUG-FILE\n"
+"[MODULE...]"
+msgstr ""
+"STRIPPED-FILE DEBUG-FILE\n"
+"[MODULE...]"
+
+#: src/unstrip.c:2609
+#, fuzzy
+msgid ""
+"Combine stripped files with separate symbols and debug information.\n"
+"\n"
+"The first form puts the result in DEBUG-FILE if -o was not given.\n"
+"\n"
+"MODULE arguments give file name patterns matching modules to process.\n"
+"With -f these match the file name of the main (stripped) file (slashes are "
+"never special), otherwise they match the simple module names.  With no "
+"arguments, process all modules found.\n"
+"\n"
+"Multiple modules are written to files under OUTPUT-DIRECTORY, creating "
+"subdirectories as needed.  With -m these files have simple module names, "
+"otherwise they have the name of the main file complete with directory "
+"underneath OUTPUT-DIRECTORY.\n"
+"\n"
+"With -n no files are written, but one line to standard output for each "
+"module:\n"
+"\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n"
+"START and SIZE are hexadecimal giving the address bounds of the module.  "
+"BUILDID is hexadecimal for the build ID bits, or - if no ID is known; the "
+"hexadecimal may be followed by @0xADDR giving the address where the ID "
+"resides if that is known.  FILE is the file name found for the module, or - "
+"if none was found, or . if an ELF image is available but not from any named "
+"file.  DEBUGFILE is the separate debuginfo file name, or - if no debuginfo "
+"was found, or . if FILE contains the debug information."
+msgstr ""
+"Combine stripped files with separate symbols and debug information.\n"
+"\n"
+"The first form puts the result in DEBUG-FILE if -o was not given.\n"
+"\n"
+"MODULE arguments give file name patterns matching modules to process.\n"
+"With -f these match the file name of the main (stripped) file (slashes are "
+"never special), otherwise they match the simple module names.  With no "
+"arguments, process all modules found.\n"
+"\n"
+"Multiple modules are written to files under OUTPUT-DIRECTORY, creating "
+"subdirectories as needed.  With -m these files have simple module names, "
+"otherwise they have the name of the main file complete with directory "
+"underneath OUTPUT-DIRECTORY.\n"
+"\n"
+"With -n no files are written, but one line to standard output for each "
+"module:\n"
+"\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n"
+"START and SIZE are hexadecimal giving the address bounds of the module.  "
+"BUILDID is hexadecimal for the build ID bits, or - if no ID is known; the "
+"hexadecimal may be followed by @0xADDR giving the address where the ID "
+"resides if that is known.  FILE is the file name found for the module, or - "
+"if none was found, or . if an ELF image is available but not from any named "
+"file.  DEBUGFILE is the separate debuginfo file name, or - if no debuginfo "
+"was found, or . if FILE contains the debug information."
+
+#. Short description of program.
+#: debuginfod/debuginfod-find.c:42
+msgid "Request debuginfo-related content from debuginfods listed in $"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: debuginfod/debuginfod-find.c:46
+msgid ""
+"debuginfo BUILDID\n"
+"debuginfo PATH\n"
+"executable BUILDID\n"
+"executable PATH\n"
+"source BUILDID /FILENAME\n"
+"source PATH /FILENAME\n"
+"section BUILDID SECTION-NAME\n"
+"section PATH SECTION-NAME\n"
+msgstr ""
+
+#: tests/backtrace.c:491
+msgid "Run executable"
+msgstr ""
+
+#: tests/dwflmodtest.c:209
+#, fuzzy
+msgid "Additionally show function names"
+msgstr "También mostrar nombres de función"
+
+#: tests/dwflmodtest.c:210
+msgid "Show instances of inlined functions"
+msgstr ""
+
+#, c-format
+#~ msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n"
+#~ msgstr ""
+#~ "Sección [%2d] '%s': tamaño de entrada de sección no coincide con "
+#~ "ElfXX_Rela\n"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_addr section data: %s"
+#~ msgstr "no se pueden obtener datos de sección: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_rnglists content: %s"
+#~ msgstr "no se ha podido obtener contenido de .debug_ranges: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_ranges content: %s"
+#~ msgstr "no se ha podido obtener contenido de .debug_ranges: %s"
+
+#, c-format
+#~ msgid "cannot get line data section data: %s"
+#~ msgstr "No se puede obtener sección de datos de línea: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_loclists content: %s"
+#~ msgstr "no es posible obtener contenido de .debug_loc: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loc content: %s"
+#~ msgstr "no es posible obtener contenido de .debug_loc: %s"
+
+#, c-format
+#~ msgid "cannot get macro information section data: %s"
+#~ msgstr "no es posible obtener datos de la sección de macro información: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_str_offsets section data: %s"
+#~ msgstr "no se pueden obtener datos de sección: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot allocate memory"
+#~ msgstr "No se puede asignar sección PLT: %s"
+
+#, fuzzy
+#~ msgid ""
+#~ " [%6tx] base address\n"
+#~ "          "
+#~ msgstr " [%6tx]   (dirección base) %s\n"
+
+#, fuzzy
+#~ msgid "%s: error getting zero section: %s"
+#~ msgstr "%s: error al leer el fichero: %s"
+
+#, fuzzy
+#~ msgid "%s: error while updating zero section: %s"
+#~ msgstr "%s: error al leer el fichero: %s"
+
+#~ msgid "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#<PRIx64> <%s>"
+#~ msgstr "%s+%#<PRIx64> <%s>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s>"
+#~ msgstr "%s+%#0*<PRIx64> <%s>"
+
+#~ msgid "%#<PRIx64> <%s>"
+#~ msgstr "%#<PRIx64> <%s>"
+
+#~ msgid "%#0*<PRIx64> <%s>"
+#~ msgstr "%#0*<PRIx64> <%s>"
+
+#~ msgid "%s+%#<PRIx64>"
+#~ msgstr "%s+%#<PRIx64>"
+
+#~ msgid "%s+%#0*<PRIx64>"
+#~ msgstr "%s+%#0*<PRIx64>"
+
+#, fuzzy
+#~ msgid "   %s..%s (%<PRIx64>)\n"
+#~ msgstr "      %s: %<PRId64>\n"
+
+#, fuzzy
+#~ msgid "   %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#, fuzzy
+#~ msgid " advance address by %u to %s, op_index to %u\n"
+#~ msgstr "dirección avanzada por %u a %s, op_index a %u\n"
+
+#, fuzzy
+#~ msgid " advance address by constant %u to %s, op_index to %u\n"
+#~ msgstr "dirección avanzada por constante %u a %s, op_index a %u\n"
+
+#~ msgid " [%6tx]  %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#~ msgid "           %s..%s\n"
+#~ msgstr "           %s..%s\n"
+
+#~ msgid "cannot get DIE at offset %<PRIu64> in section '%s': %s"
+#~ msgstr ""
+#~ "no se puede obtener DIE en compensación %<PRIu64> en sección '%s': %s"
+
+#~ msgid " [%6tx]  %s..%s"
+#~ msgstr " [%6tx]  %s..%s"
+
+#~ msgid "           %s..%s"
+#~ msgstr "           %s..%s"
+
+#~ msgid "-R option supports only .comment section"
+#~ msgstr "la opción -R soporta únicamente. sección de comentario"
+
+#~ msgid "Written by %s.\n"
+#~ msgstr "Escrito por %s.\n"
+
+#~ msgid "cannot allocate PLTREL section: %s"
+#~ msgstr "No se puede asignar sección PLTREL: %s"
+
+#~ msgid "cannot allocate GOT section: %s"
+#~ msgstr "No se puede asignar sección GOT: %s"
+
+#~ msgid "cannot allocate GOTPLT section: %s"
+#~ msgstr "No se puede asignar sección GOTPLT: %s"
+
+#~ msgid "initial-executable TLS relocation cannot be used "
+#~ msgstr "Reubicación TLS ejecutable-inicial no se puede utilizar"
+
+#~ msgid "Input File Control:"
+#~ msgstr "Control de fichero de entrada:"
+
+#~ msgid "Include whole archives in the output from now on."
+#~ msgstr "A partir de ahora incluye archivos completos en la salida."
+
+#~ msgid "Stop including the whole archives in the output."
+#~ msgstr "Deja de incluir archivos completos en la salida."
+
+#~ msgid "FILE"
+#~ msgstr "FICHERO"
+
+#~ msgid "Start a group."
+#~ msgstr "Inicia un grupo"
+
+#~ msgid "End a group."
+#~ msgstr "Termina un grupo."
+
+#~ msgid "PATH"
+#~ msgstr "RUTA"
+
+#~ msgid "Add PATH to list of directories files are searched in."
+#~ msgstr ""
+#~ "Agrega RUTA a la lista de los directorios en los que se realiza la "
+#~ "búsqueda."
+
+#~ msgid "Only set DT_NEEDED for following dynamic libs if actually used"
+#~ msgstr ""
+#~ "Sólo se define DT_NEEDED para las siguientes bibliotecas dinámicas, si "
+#~ "están siendo utilizadas"
+
+#~ msgid "Always set DT_NEEDED for following dynamic libs"
+#~ msgstr ""
+#~ "Siempre establece DT_NEEDED para las siguientes bibliotecas dinámicas"
+
+#~ msgid "Ignore LD_LIBRARY_PATH environment variable."
+#~ msgstr "Ignora la variable de entorno LD_LIBRARY_PATH."
+
+#~ msgid "Output File Control:"
+#~ msgstr "Control de fichero de salida:"
+
+#~ msgid "Place output in FILE."
+#~ msgstr "Coloca salida en FICHERO."
+
+#~ msgid "Object is marked to not use default search path at runtime."
+#~ msgstr ""
+#~ "Objeto está marcado para no usar ruta de búsqueda predeterminada en "
+#~ "tiempo de ejecución."
+
+#~ msgid "Same as --whole-archive."
+#~ msgstr "Lo mismo que --whole-archive."
+
+#~ msgid ""
+#~ "Default rules of extracting from archive; weak references are not enough."
+#~ msgstr ""
+#~ "Reglas establecidas por defecto para extraer desde el archivo; las "
+#~ "referencias débiles no son suficientes."
+
+#~ msgid "Weak references cause extraction from archive."
+#~ msgstr "Referencias débiles causan extracción del archivo."
+
+#~ msgid "Allow multiple definitions; first is used."
+#~ msgstr "Permite definiciones múltiples; se utiliza la primera."
+
+#~ msgid "Disallow/allow undefined symbols in DSOs."
+#~ msgstr "Habilita/inhabilita símbolos indefinidos en los DSO."
+
+#~ msgid "Object requires immediate handling of $ORIGIN."
+#~ msgstr "Los objetos requieren manipulación inmediata de $ORIGIN."
+
+#~ msgid "Relocation will not be processed lazily."
+#~ msgstr "La reubicación no se procesará de forma perezosa."
+
+#~ msgid "Object cannot be unloaded at runtime."
+#~ msgstr "El objeto no se puede descargar en tiempo de ejecución."
+
+#~ msgid "Mark object to be initialized first."
+#~ msgstr "Marcar objeto a ser inicializado primero."
+
+#~ msgid "Enable/disable lazy-loading flag for following dependencies."
+#~ msgstr ""
+#~ "Activar/desactivar marca lazy-loading para las siguientes dependencias."
+
+#~ msgid "Mark object as not loadable with 'dlopen'."
+#~ msgstr "Marcar el objeto como no cargable con 'dlopen'"
+
+#~ msgid "Ignore/record dependencies on unused DSOs."
+#~ msgstr "Ignorar/registrar dependencias sobre DSO no utilizados."
+
+#~ msgid "Generated DSO will be a system library."
+#~ msgstr "El DSO generado será una biblioteca del sistema."
+
+#~ msgid "ADDRESS"
+#~ msgstr "DIRECCIÓN"
+
+#~ msgid "Set entry point address."
+#~ msgstr "Establecer dirección de entrada de punto"
+
+#~ msgid "Do not link against shared libraries."
+#~ msgstr "No enlazar con bibliotecas compartidas."
+
+#~ msgid "Prefer linking against shared libraries."
+#~ msgstr "No enlazar con bibliotecas compartidas."
+
+#~ msgid "Export all dynamic symbols."
+#~ msgstr "Exportar todos los símbolos dinámicos."
+
+#~ msgid "Strip all symbols."
+#~ msgstr "Descartar todos los símbolos."
+
+#~ msgid "Assume pagesize for the target system to be SIZE."
+#~ msgstr "Asumir que pagesize para el sistema de destino sea SIZE."
+
+#~ msgid "Set runtime DSO search path."
+#~ msgstr "Establecer la ruta de búsqueda tiempo de ejecución DSO."
+
+#~ msgid "Set link time DSO search path."
+#~ msgstr "Establecer ruta de tiempo de enlace DSO."
+
+#~ msgid "Generate dynamic shared object."
+#~ msgstr "Generar objeto compartido dinámico."
+
+#~ msgid "Generate relocatable object."
+#~ msgstr "Generar objeto reubicable"
+
+#~ msgid "Causes symbol not assigned to a version be reduced to local."
+#~ msgstr ""
+#~ "Hacer que un símbolo no asignado a una versión sea reducido a local."
+
+#~ msgid "Remove unused sections."
+#~ msgstr "Eliminar las secciones no utilizadas."
+
+#~ msgid "Don't remove unused sections."
+#~ msgstr "No eliminar las secciones no utilizadas."
+
+#~ msgid "Set soname of shared object."
+#~ msgstr "Establecer soname de objeto compartido."
+
+#~ msgid "Set the dynamic linker name."
+#~ msgstr "Establecer el nombre de enlazador dinámico."
+
+#~ msgid "Add/suppress addition indentifying link-editor to .comment section."
+#~ msgstr ""
+#~ "Añadir/suprimir adición identificando enlace-editor para .sección de "
+#~ "comentario."
+
+#~ msgid "Create .eh_frame_hdr section"
+#~ msgstr "Crear una sección .eh_frame_hdr"
+
+#~ msgid "Set hash style to sysv, gnu or both."
+#~ msgstr "Establecer el estilo de dispersión un sysv, gnu o ambos."
+
+#~ msgid "Generate build ID note (md5, sha1 (default), uuid)."
+#~ msgstr ""
+#~ "Crear una nota del ID de compilación (md5, sha1 (por defecto), uuid)."
+
+#~ msgid "Linker Operation Control:"
+#~ msgstr "Control de volumen desconocido:"
+
+#~ msgid "Verbose messages."
+#~ msgstr "Mensajes explicativos."
+
+#~ msgid "Trace file opens."
+#~ msgstr "Rastrear apertura de ficheros."
+
+#~ msgid "Trade speed for less memory usage"
+#~ msgstr "Intercambiar velocidad por menor utilización de memoria"
+
+#~ msgid "LEVEL"
+#~ msgstr "NIVEL"
+
+#~ msgid "Set optimization level to LEVEL."
+#~ msgstr "Establecer el nivel de optimización a LEVEL."
+
+#~ msgid "Use linker script in FILE."
+#~ msgstr "Usar script enlazador en FICHERO."
+
+#~ msgid "Select to get parser debug information"
+#~ msgstr "Seleccionar para obtener análisis de información de depuración"
+
+#~ msgid "Read version information from FILE."
+#~ msgstr "Leer información de versión de FICHERO."
+
+#~ msgid "Set emulation to NAME."
+#~ msgstr "Establecer emulación a NOMBRE."
+
+#~ msgid "Combine object and archive files."
+#~ msgstr "Combinar objeto y archivos de almacenamiento."
+
+#~ msgid "[FILE]..."
+#~ msgstr "[FICHERO]..."
+
+#~ msgid "At least one input file needed"
+#~ msgstr "Se necesita al menos un fichero de entrada"
+
+#~ msgid "error while preparing linking"
+#~ msgstr "Error al preparar vinculación"
+
+#~ msgid "cannot open linker script '%s'"
+#~ msgstr "no se puede abrir script enlazador '%s'"
+
+#~ msgid "-( without matching -)"
+#~ msgstr "-( sin coincidir -)"
+
+#~ msgid "only one option of -G and -r is allowed"
+#~ msgstr "Solamente una opción de -G y -r es permitida"
+
+#~ msgid "more than one '-m' parameter"
+#~ msgstr "más de un parámetro '-m'"
+
+#~ msgid "unknown option `-%c %s'"
+#~ msgstr "opción desconocida `-%c %s'"
+
+#~ msgid "invalid hash style '%s'"
+#~ msgstr "estilo de dispersión inválido '%s'"
+
+#~ msgid "invalid build-ID style '%s'"
+#~ msgstr "estilo de cuerpo-ID inválido '%s'"
+
+#~ msgid "Invalid optimization level `%s'"
+#~ msgstr "Nivel de optimización inválido `%s'"
+
+#~ msgid "nested -( -) groups are not allowed"
+#~ msgstr "no se permiten grupos -( -) en nido"
+
+#~ msgid "-) without matching -("
+#~ msgstr "-) sin coincidir -("
+
+#~ msgid "unknown option '-%c %s'"
+#~ msgstr "Opción desconocida '-%c %s'"
+
+#~ msgid "could not find input file to determine output file format"
+#~ msgstr ""
+#~ "no se pudo encontrar un archivo de entrada que determine el formato del "
+#~ "archivo de salida"
+
+#~ msgid "try again with an appropriate '-m' parameter"
+#~ msgstr "Inténtelo con una parámetro '-m' apropiado"
+
+#~ msgid "cannot read version script '%s'"
+#~ msgstr "No se puede leer script de versión '%s'"
+
+#~ msgid "duplicate definition of '%s' in linker script"
+#~ msgstr "Duplicar definición de '%s' en script enlazador"
+
+#~ msgid "cannot create string table"
+#~ msgstr "no puede crear tabla de cadenas"
+
+#~ msgid "cannot load ld backend library '%s': %s"
+#~ msgstr "no se puede cargar biblioteca ID de segundo plano '%s': %s"
+
+#~ msgid "cannot find init function in ld backend library '%s': %s"
+#~ msgstr ""
+#~ "no se pudo encontrar la función init en la biblioteca ld de segundo plano "
+#~ "'%s': %s"
+
+#~ msgid "%s listed more than once as input"
+#~ msgstr "%s listado más de una vez como entrada"
+
+#~ msgid "%s (for -l%s)\n"
+#~ msgstr "%s (para -l%s)\n"
+
+#~ msgid "%s (for DT_NEEDED %s)\n"
+#~ msgstr "%s (para DT_NEEDED %s)\n"
+
+#~ msgid "Warning: type of `%s' changed from %s in %s to %s in %s"
+#~ msgstr "Advertencia: el tipo de `%s' cambió de %s en %s a %s en %s"
+
+#~ msgid ""
+#~ "Warning: size of `%s' changed from %<PRIu64> in %s to %<PRIu64> in %s"
+#~ msgstr ""
+#~ "Advertencia: el tamaño de `%s' cambió de %<PRIu64> en %s a %<PRIu64> en %s"
+
+#~ msgid "(%s+%#<PRIx64>): multiple definition of %s `%s'\n"
+#~ msgstr "(%s+%#<PRIx64>): definición múltiplo de %s `%s'\n"
+
+#~ msgid "(%s+%#<PRIx64>): first defined here\n"
+#~ msgstr "(%s+%#<PRIx64>): se definió primero aquí\n"
+
+#~ msgid "%s: cannot get section group data: %s"
+#~ msgstr "%s: no se pueden obtener datos de sección de grupo: %s"
+
+#~ msgid "%s: section '%s' with group flag set does not belong to any group"
+#~ msgstr ""
+#~ "%s: la sección '%s' con bandera de grupo establecida no pertenece a "
+#~ "ningún grupo"
+
+#~ msgid "%s: section [%2d] '%s' is not in the correct section group"
+#~ msgstr ""
+#~ "%s: la sección [%2d] '%s' no se encuentra en el grupo de sección correcto"
+
+#~ msgid "%s: invalid ELF file (%s:%d)\n"
+#~ msgstr "%s: fichero ELF inválido (%s:%d)\n"
+
+#~ msgid "%s: only files of type ET_REL might contain section groups"
+#~ msgstr "%s: solo archivos de tipo ET_REL pueden contener grupos de sección"
+
+#~ msgid "%s: cannot determine signature of section group [%2zd] '%s': %s"
+#~ msgstr ""
+#~ "%s: no es posible determinar la firma del grupo de sección [%2zd] '%s': "
+#~ "%s "
+
+#~ msgid "%s: cannot get content of section group [%2zd] '%s': %s'"
+#~ msgstr ""
+#~ "%s: no es posible obtener el contenido de la sección del grupo [%2zd] "
+#~ "'%s': %s'"
+
+#~ msgid ""
+#~ "%s: group member %zu of section group [%2zd] '%s' has too high index: "
+#~ "%<PRIu32>"
+#~ msgstr ""
+#~ "%s el miembro del grupo %zu del grupo de sección [%2zd] '%s' posee el "
+#~ "índice demasiado alto: %<PRIu32>"
+
+#~ msgid "%s: section '%s' has unknown type: %d"
+#~ msgstr "%s: sección '%s' tiene tipo desconocido: %d"
+
+#~ msgid "cannot get descriptor for ELF file (%s:%d): %s\n"
+#~ msgstr "no es posible obtener descriptor para el archivo ELF (%s:%d): %s\n"
+
+#~ msgid "cannot read archive `%s': %s"
+#~ msgstr "no se puede leer archivo `%s': %s"
+
+#~ msgid "file of type %s cannot be linked in\n"
+#~ msgstr "archivo de tipo %s no puede ser enlazado en\n"
+
+#~ msgid "%s: input file incompatible with ELF machine type %s\n"
+#~ msgstr ""
+#~ "%s: el archivo ingresado es incompatible con una máquina ELF tipo %s\n"
+
+#~ msgid "%s: cannot get section header string table index: %s\n"
+#~ msgstr ""
+#~ "%s: no se ha podido obtener un índice para la tabla de la cadena del "
+#~ "encabezamiento de la sección: %s\n"
+
+#~ msgid "cannot use DSO '%s' when generating relocatable object file"
+#~ msgstr ""
+#~ "no es posible utilizar DSO '%s' al general un archivo de objeto realojable"
+
+#~ msgid "input file '%s' ignored"
+#~ msgstr "archivo de entrada '%s' ignorado"
+
+#~ msgid "undefined symbol `%s' in %s"
+#~ msgstr "símbolo indefinido `%s' en %s"
+
+#~ msgid "cannot create ELF descriptor for output file: %s"
+#~ msgstr "no es posible crear un descriptor ELF para el archivo de salida: %s"
+
+#~ msgid "could not create ELF header for output file: %s"
+#~ msgstr ""
+#~ "no es posible crear un encabezamiento ELF para el archivo de salida: %s"
+
+#~ msgid "cannot create section for output file: %s"
+#~ msgstr "no se puede crear sección para archivo de salida: %s"
+
+#~ msgid "address computation expression contains variable '%s'"
+#~ msgstr "la expresión de computación contiene la variable '%s'"
+
+#~ msgid ""
+#~ "argument '%<PRIuMAX>' of ALIGN in address computation expression is no "
+#~ "power of two"
+#~ msgstr ""
+#~ "el argumento '%<PRIuMAX>' de ALIGN en expresión de dirección de "
+#~ "computación no es potencia de dos"
+
+#~ msgid "cannot find entry symbol '%s': defaulting to %#0*<PRIx64>"
+#~ msgstr ""
+#~ "no se puede encontrar símbolo de entrada '%s': predeterminada para "
+#~ "%#0*<PRIx64>"
+
+#~ msgid "no entry symbol specified: defaulting to %#0*<PRIx64>"
+#~ msgstr ""
+#~ "no se ha especificado una entrada de símbolo: estableciendo por defecto a "
+#~ "%#0*<PRIx64>"
+
+#~ msgid "cannot create GNU hash table section for output file: %s"
+#~ msgstr ""
+#~ "no se puede crear una tabla de dispersión GNU para archivo de salida: %s"
+
+#~ msgid "cannot create hash table section for output file: %s"
+#~ msgstr ""
+#~ "no es posible crear una sección para la tabla de dispersión del archivo "
+#~ "de salida: %s"
+
+#~ msgid "cannot create build ID section: %s"
+#~ msgstr "no se puede crear sección de creación de ID: %s"
+
+#~ msgid "cannot convert section data to file format: %s"
+#~ msgstr ""
+#~ "no es posible convertir los datos de la sección en formato de archivo: %s"
+
+#~ msgid "cannot convert section data to memory format: %s"
+#~ msgstr ""
+#~ "no es posible convertir datos de la sección en formato de memoria: %s"
+
+#~ msgid "cannot read enough data for UUID"
+#~ msgstr "no es posible leer suficientes datos para el UUID"
+
+#~ msgid "cannot create symbol table for output file: %s"
+#~ msgstr "no es posible crear tabla de símbolo para el comando de salida: %s"
+
+#~ msgid "section index too large in dynamic symbol table"
+#~ msgstr ""
+#~ "el índice de la sección es demasiado extenso en la tabla de símbolos "
+#~ "dinámicos"
+
+#~ msgid "cannot create versioning section: %s"
+#~ msgstr "no se puede crear sección de versión: %s"
+
+#~ msgid "cannot create dynamic symbol table for output file: %s"
+#~ msgstr ""
+#~ "no es posible crear tabla de símbolos dinámicos para el archivo de "
+#~ "salida: %s"
+
+#~ msgid "cannot create versioning data: %s"
+#~ msgstr "no se pueden crear datos de versión: %s"
+
+#~ msgid "cannot create section header string section: %s"
+#~ msgstr ""
+#~ "no se puede crear sección de cadenas de encabezamiento de sección: %s"
+
+#~ msgid "cannot create section header string section"
+#~ msgstr "no se puede crear sección de cadenas de encabezamiento de sección"
+
+#~ msgid "cannot create program header: %s"
+#~ msgstr "no se puede crear encabezamiento de programa: %s"
+
+#~ msgid "while determining file layout: %s"
+#~ msgstr "al determinar diseño de fichero: %s"
+
+#~ msgid "internal error: non-nobits section follows nobits section"
+#~ msgstr "error interno: sección non-nobits sigue a sección nobits"
+
+#~ msgid "linker backend didn't specify function to relocate section"
+#~ msgstr ""
+#~ "enlazador de segundo plano no especificó función para reubicar sección"
+
+#~ msgid "while writing output file: %s"
+#~ msgstr "Ocurrió un error de fichero de salida: %s"
+
+#~ msgid "while finishing output file: %s"
+#~ msgstr "error al cerrar el fichero de salida: %s"
+
+#~ msgid "cannot stat output file"
+#~ msgstr "no se puede generar stat de fichero de salida"
+
+#~ msgid "WARNING: temporary output file overwritten before linking finished"
+#~ msgstr ""
+#~ "ADVERTENCIA: archivo de salida temporal sobreescrito antes que haya "
+#~ "concluido el enlazamiento"
+
+#~ msgid "no machine specific '%s' implementation"
+#~ msgstr "no hay máquina específica de implementación '%s'"
+
+#~ msgid "mode for segment invalid\n"
+#~ msgstr "modo para segmento inválido\n"
+
+#~ msgid "while reading version script '%s': %s at line %d"
+#~ msgstr "al leer script de versión '%s': %s en línea %d"
+
+#, fuzzy
+#~ msgid ""
+#~ "symbol '%s' is declared both local and global for unnamed version '%s'"
+#~ msgstr ""
+#~ "el símbolo '%s' es declarado tanto local como global para la versión sin "
+#~ "nombre"
+
+#~ msgid "symbol '%s' is declared both local and global for version '%s'"
+#~ msgstr ""
+#~ "el símbolo '%s' es declarado tanto local como global para la versión '%s'"
+
+#~ msgid "default visibility set as local and global"
+#~ msgstr ""
+#~ "la visibilidad establecida por defecto establecida como local y global"
+
+#~ msgid "cannot get section header of section %Zu: %s"
+#~ msgstr "No se puede obtener encabezamiento de sección %Zu: %s"
+
+#, fuzzy
+#~ msgid "cannot attach to core"
+#~ msgstr "No se puede crear el árbol de búsqueda"
+
+#~ msgid "'%s' and '%s' do not seem to match"
+#~ msgstr "Al parecer '%s' y '%s'no coinciden"
+
+#~ msgid "unknown tag %hx"
+#~ msgstr "etiqueta %hx desconocida"
+
+#~ msgid "unknown user tag %hx"
+#~ msgstr "Usuario de etiqueta %hx desconocido "
+
+#~ msgid "unknown attribute %hx"
+#~ msgstr "atributo de sección %hx desconocido"
+
+#~ msgid "unknown user attribute %hx"
+#~ msgstr "Atributo de usuario desconocido %hx"
+
+#~ msgid ""
+#~ "\n"
+#~ "\n"
+#~ "Symbols from %s[%s]:\n"
+#~ "\n"
+#~ msgstr ""
+#~ "\n"
+#~ "\n"
+#~ "Símbolos de %s[%s]:\n"
+#~ "\n"
+
+#~ msgid "%s %s differ: section header"
+#~ msgstr "%s %s differ: encabezamiento de sección"
+
+#~ msgid "Equivalent to: -e -h -l"
+#~ msgstr "Equivalente a: -e -h -l"
+
+#~ msgid "zeroth section has nonzero info field\n"
+#~ msgstr "Sección zeroth tiene campo de información nonzero\n"
+
+#~ msgid " Version String: "
+#~ msgstr "Cadena versión:"
+
+#~ msgid ""
+#~ "\n"
+#~ "Section [%Zu] '%s' is empty.\n"
+#~ msgstr ""
+#~ "\n"
+#~ "Sección [%Zu] '%s' está vacía.\n"
diff --git a/po/ja.po b/po/ja.po
new file mode 100644
index 0000000..9c46da5
--- /dev/null
+++ b/po/ja.po
@@ -0,0 +1,7803 @@
+# translation of ja.po to Japanese
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+#
+# Kiyoto Hashida <khashida@redhat.com>, 2009.
+# Hyu_gabaru Ryu_ichi <hyu_gabaru@yahoo.co.jp>, 2009.
+msgid ""
+msgstr ""
+"Project-Id-Version: elfutils\n"
+"Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n"
+"POT-Creation-Date: 2024-03-01 10:22-0500\n"
+"PO-Revision-Date: 2009-09-20 15:32+0900\n"
+"Last-Translator: Hyu_gabaru Ryu_ichi <hyu_gabaru@yahoo.co.jp>\n"
+"Language-Team: Japanese <jp@li.org>\n"
+"Language: ja\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"X-Generator: KBabel 1.11.4\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: lib/color.c:51
+msgid ""
+"colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"
+msgstr ""
+
+#: lib/color.c:127
+#, c-format
+msgid ""
+"%s: invalid argument '%s' for '--color'\n"
+"valid arguments are:\n"
+"  - 'always', 'yes', 'force'\n"
+"  - 'never', 'no', 'none'\n"
+"  - 'auto', 'tty', 'if-tty'\n"
+msgstr ""
+
+#: lib/printversion.c:39
+#, c-format
+msgid ""
+"Copyright (C) %s The elfutils developers <%s>.\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+msgstr ""
+
+#: lib/xmalloc.c:47 lib/xmalloc.c:60 lib/xmalloc.c:72 src/readelf.c:12203
+#: src/unstrip.c:311
+#, c-format
+msgid "memory exhausted"
+msgstr "メモリー枯渇"
+
+#: libasm/asm_error.c:64 libdw/dwarf_error.c:57 libdwfl/libdwflP.h:47
+#: libelf/elf_error.c:59
+msgid "no error"
+msgstr "エラー無し"
+
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:49
+#: libelf/elf_error.c:90
+msgid "out of memory"
+msgstr "メモリー不足です"
+
+#: libasm/asm_error.c:66
+msgid "cannot create output file"
+msgstr "出力ファイルを作成できません"
+
+#: libasm/asm_error.c:67
+msgid "invalid parameter"
+msgstr "不当なパラメーターです"
+
+#: libasm/asm_error.c:68
+msgid "cannot change mode of output file"
+msgstr "出力ファイルのモードを変更できません"
+
+#: libasm/asm_error.c:69
+msgid "cannot rename output file"
+msgstr "出力ファイルの名前を変更できません"
+
+#: libasm/asm_error.c:70
+msgid "duplicate symbol"
+msgstr "重複シンボルです"
+
+#: libasm/asm_error.c:71
+msgid "invalid section type for operation"
+msgstr "操作に不当なセクションタイプです"
+
+#: libasm/asm_error.c:72
+msgid "error during output of data"
+msgstr "データ出力中のエラーです"
+
+#: libasm/asm_error.c:73
+msgid "no backend support available"
+msgstr "バックエンドサポートを利用できません"
+
+#: libasm/asm_error.c:82 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:48
+#: libelf/elf_error.c:62
+msgid "unknown error"
+msgstr "不明なエラーです"
+
+#: libcpu/i386_lex.l:121
+#, c-format
+msgid "invalid character '%c' at line %d; ignored"
+msgstr "不当な文字 '%c' が %d 行目にあります; 無視しました"
+
+#: libcpu/i386_lex.l:122
+#, c-format
+msgid "invalid character '\\%o' at line %d; ignored"
+msgstr "不当な文字 '\\%o' が %d 行目にあります; 無視しました"
+
+#: libcpu/i386_parse.y:555
+#, c-format
+msgid "while reading i386 CPU description: %s at line %d"
+msgstr "i386 CPU description の読み込み中: %2$d 行目の %1$s"
+
+#: libdw/dwarf_error.c:59
+msgid "invalid access"
+msgstr "不当なアクセスです"
+
+#: libdw/dwarf_error.c:60
+msgid "no regular file"
+msgstr "一般ファイルではありません"
+
+#: libdw/dwarf_error.c:61
+msgid "I/O error"
+msgstr "I/O エラーです"
+
+#: libdw/dwarf_error.c:62
+msgid "invalid ELF file"
+msgstr "不当な ELF ファイルです"
+
+#: libdw/dwarf_error.c:63
+msgid "no DWARF information"
+msgstr "DWARF 情報がありません"
+
+#: libdw/dwarf_error.c:64
+msgid "cannot decompress DWARF"
+msgstr "DWARF を展開できません"
+
+#: libdw/dwarf_error.c:65
+msgid "no ELF file"
+msgstr "ELF ファイルではありません"
+
+#: libdw/dwarf_error.c:66
+msgid "cannot get ELF header"
+msgstr "ELF ヘッダーを取得できません"
+
+#: libdw/dwarf_error.c:68
+msgid "not implemented"
+msgstr "未実装です"
+
+#: libdw/dwarf_error.c:69 libelf/elf_error.c:110 libelf/elf_error.c:158
+msgid "invalid command"
+msgstr "不当なコマンドです"
+
+#: libdw/dwarf_error.c:70
+msgid "invalid version"
+msgstr "不当なバージョンです"
+
+#: libdw/dwarf_error.c:71
+msgid "invalid file"
+msgstr "不当なファイルです"
+
+#: libdw/dwarf_error.c:72
+msgid "no entries found"
+msgstr "項目が見つかりません"
+
+#: libdw/dwarf_error.c:73
+msgid "invalid DWARF"
+msgstr "不当な DWARFです"
+
+#: libdw/dwarf_error.c:74
+msgid "no string data"
+msgstr "文字列データではありません"
+
+#: libdw/dwarf_error.c:75
+msgid ".debug_str section missing"
+msgstr ".debug_str セクションが見つかりません"
+
+#: libdw/dwarf_error.c:76
+msgid ".debug_line_str section missing"
+msgstr ".debug_line_str セクションが見つかりません"
+
+#: libdw/dwarf_error.c:77
+msgid ".debug_str_offsets section missing"
+msgstr ".debug_str_offsets セクションが見つかりません"
+
+#: libdw/dwarf_error.c:78
+msgid "no address value"
+msgstr "アドレス値ではありません"
+
+#: libdw/dwarf_error.c:79
+msgid "no constant value"
+msgstr "定数値ではありません"
+
+#: libdw/dwarf_error.c:80
+msgid "no reference value"
+msgstr "参照値ではありません"
+
+#: libdw/dwarf_error.c:81
+msgid "invalid reference value"
+msgstr "不当な参照値です"
+
+#: libdw/dwarf_error.c:82
+msgid ".debug_line section missing"
+msgstr ".debug_line セクションが見つかりません"
+
+#: libdw/dwarf_error.c:83
+msgid "invalid .debug_line section"
+msgstr "不当な .debug_line セクションです"
+
+#: libdw/dwarf_error.c:84
+msgid "debug information too big"
+msgstr "デバッグ情報が大きすぎます"
+
+#: libdw/dwarf_error.c:85
+msgid "invalid DWARF version"
+msgstr "不当な DWARF バージョンです"
+
+#: libdw/dwarf_error.c:86
+msgid "invalid directory index"
+msgstr "不当なディレクトリー索引です"
+
+#: libdw/dwarf_error.c:87 libdwfl/libdwflP.h:69
+msgid "address out of range"
+msgstr "アドレスが範囲外です"
+
+#: libdw/dwarf_error.c:88
+msgid ".debug_loc section missing"
+msgstr ".debug_loc セクションが見つかりません"
+
+#: libdw/dwarf_error.c:89
+msgid ".debug_loclists section missing"
+msgstr ".debug_loclists セクション見つかりません"
+
+#: libdw/dwarf_error.c:90
+msgid "not a location list value"
+msgstr "ロケーションリスト値ではありません"
+
+#: libdw/dwarf_error.c:91
+msgid "no block data"
+msgstr "ブロックデータではありません"
+
+#: libdw/dwarf_error.c:92
+msgid "invalid line index"
+msgstr "不当な行索引です"
+
+#: libdw/dwarf_error.c:93
+msgid "invalid address range index"
+msgstr "不当なアドレス範囲索引です"
+
+#: libdw/dwarf_error.c:94 libdwfl/libdwflP.h:70
+msgid "no matching address range"
+msgstr "一致するアドレス範囲がありません"
+
+#: libdw/dwarf_error.c:95
+msgid "no flag value"
+msgstr "フラグ値ではありません"
+
+#: libdw/dwarf_error.c:96 libelf/elf_error.c:235
+msgid "invalid offset"
+msgstr "不当なオフセットです"
+
+#: libdw/dwarf_error.c:97
+msgid ".debug_ranges section missing"
+msgstr ".debug_ranges セクションが見つかりません"
+
+#: libdw/dwarf_error.c:98
+msgid ".debug_rnglists section missing"
+msgstr ".debug_rnglists セクションが見つかりません"
+
+#: libdw/dwarf_error.c:99
+msgid "invalid CFI section"
+msgstr "不当な CFI セクションです"
+
+#: libdw/dwarf_error.c:100
+msgid "no alternative debug link found"
+msgstr "代替デバッグリンクが見つかりません"
+
+#: libdw/dwarf_error.c:101
+msgid "invalid opcode"
+msgstr "不当なオペコードです"
+
+#: libdw/dwarf_error.c:102
+msgid "not a CU (unit) DIE"
+msgstr "CU (unit) DIE ではありません"
+
+#: libdw/dwarf_error.c:103
+msgid "unknown language code"
+msgstr "不明な言語コードです"
+
+#: libdw/dwarf_error.c:104
+msgid ".debug_addr section missing"
+msgstr ".debug_addr セクションが見つかりません"
+
+#: libdw/dwarf_error.c:105
+#, fuzzy
+#| msgid "unknown version"
+msgid "unknown section"
+msgstr "不明なバージョンです"
+
+#: libdwfl/argp-std.c:45 src/stack.c:643 src/unstrip.c:2598
+msgid "Input selection options:"
+msgstr "入力選択オプション:"
+
+#: libdwfl/argp-std.c:46
+msgid "Find addresses in FILE"
+msgstr "FILE の中から アドレスを探す"
+
+#: libdwfl/argp-std.c:48
+msgid "Find addresses from signatures found in COREFILE"
+msgstr "COREFILE 中で 見つかった 署名から アドレスを 探す"
+
+#: libdwfl/argp-std.c:50
+msgid "Find addresses in files mapped into process PID"
+msgstr "プロセス PID に 対応する ファイル中の アドレスを 探す"
+
+#: libdwfl/argp-std.c:52
+msgid ""
+"Find addresses in files mapped as read from FILE in Linux /proc/PID/maps "
+"format"
+msgstr ""
+"Linux の /proc/PID/maps 形式の FILE から 読み込んだ マッピング された ファイ"
+"ル から アドレスを 探す"
+
+#: libdwfl/argp-std.c:54
+msgid "Find addresses in the running kernel"
+msgstr "実行中の カーネルから アドレスを 探す"
+
+#: libdwfl/argp-std.c:56
+msgid "Kernel with all modules"
+msgstr "全ての モジュール付きの カーネル"
+
+#: libdwfl/argp-std.c:58 src/stack.c:650
+msgid "Search path for separate debuginfo files"
+msgstr "分離された debuginfo ファイルを 探索する パス"
+
+#: libdwfl/argp-std.c:159
+msgid "only one of -e, -p, -k, -K, or --core allowed"
+msgstr "-e か、-p、-k、-K、--core のひとつだけが認められます"
+
+#: libdwfl/argp-std.c:232
+msgid "cannot load kernel symbols"
+msgstr "カーネルシンボルをロードできません"
+
+#. Non-fatal to have no modules since we do have the kernel.
+#: libdwfl/argp-std.c:236
+msgid "cannot find kernel modules"
+msgstr "カーネルモジュールが見つかりません"
+
+#: libdwfl/argp-std.c:253
+msgid "cannot find kernel or modules"
+msgstr "カーネルまたはモジュールが見つかりません"
+
+#: libdwfl/argp-std.c:292
+#, c-format
+msgid "cannot read ELF core file: %s"
+msgstr "ELF コアファイルを読み込めません: %s"
+
+#: libdwfl/argp-std.c:315
+msgid "Not enough memory"
+msgstr "メモリーが十分ではありません"
+
+#: libdwfl/argp-std.c:325
+msgid "No modules recognized in core file"
+msgstr "コアファイルの中にモジュールを認識できません"
+
+#: libdwfl/libdwflP.h:50
+msgid "See errno"
+msgstr "errno を参照してください"
+
+#: libdwfl/libdwflP.h:51
+msgid "See elf_errno"
+msgstr "elf_errno を参照してください"
+
+#: libdwfl/libdwflP.h:52
+msgid "See dwarf_errno"
+msgstr "dwarf_errno を参照してください"
+
+#: libdwfl/libdwflP.h:53
+msgid "See ebl_errno (XXX missing)"
+msgstr "ebl_errno を参照してください(XXX が見つかりません)"
+
+#: libdwfl/libdwflP.h:54
+msgid "gzip decompression failed"
+msgstr "gzip の展開に失敗しました"
+
+#: libdwfl/libdwflP.h:55
+msgid "bzip2 decompression failed"
+msgstr "bzip2 の展開に失敗しました"
+
+#: libdwfl/libdwflP.h:56
+msgid "LZMA decompression failed"
+msgstr "LZMA の展開に失敗しました"
+
+#: libdwfl/libdwflP.h:57
+msgid "zstd decompression failed"
+msgstr "zstd の展開に失敗しました"
+
+#: libdwfl/libdwflP.h:58
+msgid "no support library found for machine"
+msgstr "マシン用のサポートライブラリが見つかりません"
+
+#: libdwfl/libdwflP.h:59
+msgid "Callbacks missing for ET_REL file"
+msgstr "ET_REL ファイル用のコールバックが見つかりません"
+
+#: libdwfl/libdwflP.h:60
+msgid "Unsupported relocation type"
+msgstr "未対応のリロケーションタイプです"
+
+#: libdwfl/libdwflP.h:61
+msgid "r_offset is bogus"
+msgstr "r_offset が偽物です"
+
+#: libdwfl/libdwflP.h:62 libelf/elf_error.c:114 libelf/elf_error.c:174
+msgid "offset out of range"
+msgstr "オフセットが範囲外です"
+
+#: libdwfl/libdwflP.h:63
+msgid "relocation refers to undefined symbol"
+msgstr "リロケーションが未定義シンボルを参照しています"
+
+#: libdwfl/libdwflP.h:64
+msgid "Callback returned failure"
+msgstr "コールバックが失敗を返しました"
+
+#: libdwfl/libdwflP.h:65
+msgid "No DWARF information found"
+msgstr "DWARF 情報が見つかりません"
+
+#: libdwfl/libdwflP.h:66
+msgid "No symbol table found"
+msgstr "シンボルテーブルが見つかりません"
+
+#: libdwfl/libdwflP.h:67
+msgid "No ELF program headers"
+msgstr "ELF プログラムヘッダーではありません"
+
+#: libdwfl/libdwflP.h:68
+msgid "address range overlaps an existing module"
+msgstr "アドレス範囲が既存モジュールと重なります"
+
+#: libdwfl/libdwflP.h:71
+msgid "image truncated"
+msgstr "イメージが切り詰められています"
+
+#: libdwfl/libdwflP.h:72
+msgid "ELF file opened"
+msgstr "既に ELF ファイルを開いています"
+
+#: libdwfl/libdwflP.h:73
+msgid "not a valid ELF file"
+msgstr "不当な ELF ファイルです"
+
+#: libdwfl/libdwflP.h:74
+msgid "cannot handle DWARF type description"
+msgstr "DWARF type description を操作できません"
+
+#: libdwfl/libdwflP.h:75
+msgid "ELF file does not match build ID"
+msgstr "ELF ファイルがビルド ID と一致しません"
+
+#: libdwfl/libdwflP.h:76
+msgid "corrupt .gnu.prelink_undo section data"
+msgstr ".gnu.prelink_undo セクションデータが壊れています"
+
+#: libdwfl/libdwflP.h:77
+msgid "Internal error due to ebl"
+msgstr "ebl に起因する内部エラー"
+
+#: libdwfl/libdwflP.h:78
+msgid "Missing data in core file"
+msgstr "コアファイルの中にデータが見つかりません"
+
+#: libdwfl/libdwflP.h:79
+msgid "Invalid register"
+msgstr "不当なレジスターです"
+
+#: libdwfl/libdwflP.h:80
+#, fuzzy
+#| msgid "no reference value"
+msgid "Unknown register value"
+msgstr "参照値ではありません"
+
+#: libdwfl/libdwflP.h:81
+msgid "Error reading process memory"
+msgstr "プロセスメモリーの読み込みエラーです"
+
+#: libdwfl/libdwflP.h:82
+msgid "Couldn't find architecture of any ELF"
+msgstr "ELF のアーキテクチャが1つも見つかりませんでした"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error parsing /proc filesystem"
+msgstr "/proc ファイルシステムのパースエラーです"
+
+#: libdwfl/libdwflP.h:84
+msgid "Invalid DWARF"
+msgstr "不当な DWARF です"
+
+#: libdwfl/libdwflP.h:85
+msgid "Unsupported DWARF"
+msgstr "未対応の DWARF です"
+
+#: libdwfl/libdwflP.h:86
+msgid "Unable to find more threads"
+msgstr "これ以上スレッドが見つかりません"
+
+#: libdwfl/libdwflP.h:87
+msgid "Dwfl already has attached state"
+msgstr "Dwfl は既にアタッチ状態です"
+
+#: libdwfl/libdwflP.h:88
+msgid "Dwfl has no attached state"
+msgstr "Dwfl はアタッチ状態ではありません"
+
+#: libdwfl/libdwflP.h:89
+msgid "Unwinding not supported for this architecture"
+msgstr "このアーキテクチャに対応していない巻き戻しです"
+
+#: libdwfl/libdwflP.h:90
+msgid "Invalid argument"
+msgstr "不当な引数です"
+
+#: libdwfl/libdwflP.h:91
+msgid "Not an ET_CORE ELF file"
+msgstr "ET_CORE ELF ファイルではありません"
+
+#: libebl/eblbackendname.c:41
+msgid "No backend"
+msgstr "バックエンドがありません"
+
+#: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:79
+#: libebl/eblobjnotetypename.c:113 libebl/eblobjnotetypename.c:134
+#: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83
+#: libebl/eblsectiontypename.c:116 libebl/eblsegmenttypename.c:81
+msgid "<unknown>"
+msgstr "<不明>"
+
+#: libebl/ebldynamictagname.c:103
+#, c-format
+msgid "<unknown>: %#<PRIx64>"
+msgstr "<不明>: %#<PRIx64>"
+
+#: libebl/eblobjnote.c:58
+#, c-format
+msgid "unknown SDT version %u\n"
+msgstr "不明な SDT バージョン %u です\n"
+
+#: libebl/eblobjnote.c:76
+#, c-format
+msgid "invalid SDT probe descriptor\n"
+msgstr "不当な SDT probe 記述子です\n"
+
+#: libebl/eblobjnote.c:126
+#, c-format
+msgid "    PC: "
+msgstr ""
+
+#: libebl/eblobjnote.c:128
+#, c-format
+msgid " Base: "
+msgstr ""
+
+#: libebl/eblobjnote.c:130
+#, c-format
+msgid " Semaphore: "
+msgstr ""
+
+#: libebl/eblobjnote.c:132
+#, c-format
+msgid "    Provider: "
+msgstr ""
+
+#: libebl/eblobjnote.c:134
+#, c-format
+msgid " Name: "
+msgstr ""
+
+#: libebl/eblobjnote.c:136
+#, c-format
+msgid " Args: "
+msgstr ""
+
+#: libebl/eblobjnote.c:304
+#, c-format
+msgid "    Build ID: "
+msgstr "   ビルド ID: "
+
+#. A non-null terminated version string.
+#: libebl/eblobjnote.c:315
+#, c-format
+msgid "    Linker version: %.*s\n"
+msgstr ""
+
+#: libebl/eblobjnote.c:642
+#, c-format
+msgid "    OS: %s, ABI: "
+msgstr ""
+
+#: libebl/eblosabiname.c:70
+msgid "Stand alone"
+msgstr "スタンドアローン"
+
+#: libebl/eblsymbolbindingname.c:68 libebl/eblsymboltypename.c:74
+#, c-format
+msgid "<unknown>: %d"
+msgstr "<不明>: %d"
+
+#: libelf/elf_error.c:66
+msgid "unknown version"
+msgstr "不明なバージョンです"
+
+#: libelf/elf_error.c:70
+msgid "unknown type"
+msgstr "不明なタイプです"
+
+#: libelf/elf_error.c:74
+msgid "invalid `Elf' handle"
+msgstr "無効な `Elf' のハンドルです"
+
+#: libelf/elf_error.c:78
+msgid "invalid size of source operand"
+msgstr "ソース演算子の大きさが無効です"
+
+#: libelf/elf_error.c:82
+msgid "invalid size of destination operand"
+msgstr "宛先演算子の大きさが無効です"
+
+#: libelf/elf_error.c:86 src/readelf.c:6759
+#, c-format
+msgid "invalid encoding"
+msgstr "無効なエンコードです"
+
+#: libelf/elf_error.c:94
+msgid "invalid file descriptor"
+msgstr "不当なファイル記述子です"
+
+#: libelf/elf_error.c:98
+msgid "invalid ELF file data"
+msgstr "不当な ELF ファイルデータです"
+
+#: libelf/elf_error.c:102
+msgid "invalid operation"
+msgstr "不当な操作です"
+
+#: libelf/elf_error.c:106
+msgid "ELF version not set"
+msgstr "ELF のバージョンが設定されていません"
+
+#: libelf/elf_error.c:118
+msgid "invalid fmag field in archive header"
+msgstr "アーカイブヘッダーの不当な fmag 領域です"
+
+#: libelf/elf_error.c:122
+msgid "invalid archive file"
+msgstr "不当なアーカイブファイルです"
+
+#: libelf/elf_error.c:126
+msgid "descriptor is not for an archive"
+msgstr "記述子がアーカイブ用ではありません"
+
+#: libelf/elf_error.c:130
+msgid "no index available"
+msgstr "利用できる索引がありません"
+
+#: libelf/elf_error.c:134
+msgid "cannot read data from file"
+msgstr "ファイルからデータを読み込めません"
+
+#: libelf/elf_error.c:138
+msgid "cannot write data to file"
+msgstr "ファイルへデータを書き込めません"
+
+#: libelf/elf_error.c:142
+msgid "invalid binary class"
+msgstr "不当なバイナリークラスです"
+
+#: libelf/elf_error.c:146
+msgid "invalid section index"
+msgstr "不当なセクション索引です"
+
+#: libelf/elf_error.c:150
+msgid "invalid operand"
+msgstr "不当なオペランドです"
+
+#: libelf/elf_error.c:154
+msgid "invalid section"
+msgstr "不当なセクションです"
+
+#: libelf/elf_error.c:162
+msgid "executable header not created first"
+msgstr "実行可能ヘッダーが最初に作られていません"
+
+#: libelf/elf_error.c:166
+msgid "file descriptor disabled"
+msgstr "ファイル記述子が無効化されています"
+
+#: libelf/elf_error.c:170
+msgid "archive/member file descriptor mismatch"
+msgstr "アーカイブ/メンバーのファイル記述子の不整合です"
+
+#: libelf/elf_error.c:178
+msgid "cannot manipulate null section"
+msgstr "null セクションを操作できません"
+
+#: libelf/elf_error.c:182
+msgid "data/scn mismatch"
+msgstr "データ/scnの不整合です"
+
+#: libelf/elf_error.c:186
+msgid "invalid section header"
+msgstr "不当なセクションヘッダーです"
+
+#: libelf/elf_error.c:190 src/readelf.c:10638 src/readelf.c:11243
+#: src/readelf.c:11344 src/readelf.c:11532
+#, c-format
+msgid "invalid data"
+msgstr "不当なデータです"
+
+#: libelf/elf_error.c:194
+msgid "unknown data encoding"
+msgstr "不明なデータエンコードです"
+
+#: libelf/elf_error.c:198
+msgid "section `sh_size' too small for data"
+msgstr "`sh_size' セクションがデータには小さすぎます"
+
+#: libelf/elf_error.c:202
+msgid "invalid section alignment"
+msgstr "不当なセクションアラインメントです"
+
+#: libelf/elf_error.c:206
+msgid "invalid section entry size"
+msgstr "不当なセクション項目の大きさです"
+
+#: libelf/elf_error.c:210
+msgid "update() for write on read-only file"
+msgstr "読み込み専用ファイルへの書き込みの update() です"
+
+#: libelf/elf_error.c:214
+msgid "no such file"
+msgstr "そのようなファイルはありません"
+
+#: libelf/elf_error.c:218
+msgid "only relocatable files can contain section groups"
+msgstr "リロケータブルファイルのみがセクショングループを含むことができます"
+
+#: libelf/elf_error.c:223
+msgid ""
+"program header only allowed in executables, shared objects, and core files"
+msgstr ""
+"プログラムヘッダーは、実行可能ファイル、共有オブジェクト、コアファイルにのみ"
+"認められています"
+
+#: libelf/elf_error.c:230
+msgid "file has no program header"
+msgstr "ファイルにプログラムヘッダーがありません"
+
+#: libelf/elf_error.c:240
+msgid "invalid section type"
+msgstr "不当なセクションタイプです"
+
+#: libelf/elf_error.c:245
+msgid "invalid section flags"
+msgstr "不当なセクションフラグです"
+
+#: libelf/elf_error.c:250
+msgid "section does not contain compressed data"
+msgstr "セクションが圧縮データを含んでいません"
+
+#: libelf/elf_error.c:255
+msgid "section contains compressed data"
+msgstr "セクションが圧縮データを含んでいます"
+
+#: libelf/elf_error.c:260
+msgid "unknown compression type"
+msgstr "不明な圧縮タイプです"
+
+#: libelf/elf_error.c:265
+msgid "cannot compress data"
+msgstr "データを圧縮できません"
+
+#: libelf/elf_error.c:270
+msgid "cannot decompress data"
+msgstr "データを展開できません"
+
+#: src/addr2line.c:58
+msgid "Input format options:"
+msgstr "入力フォーマットオプション:"
+
+#: src/addr2line.c:60
+msgid "Treat addresses as offsets relative to NAME section."
+msgstr "アドレスを NAME セクションに 対する 相対 オフセット として 扱う"
+
+#: src/addr2line.c:62
+msgid "Output format options:"
+msgstr "出力フォーマットオプション:"
+
+#: src/addr2line.c:63
+msgid "Print address before each entry"
+msgstr "各項目の前にアドレスを表示"
+
+#: src/addr2line.c:64
+msgid "Show only base names of source files"
+msgstr "ソースファイルの ベースネーム のみ 表示"
+
+#: src/addr2line.c:66
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show absolute file names using compilation directory (default)"
+msgstr "コンパイルディレクトリを 使用して 絶対ファイル名を 表示"
+
+#: src/addr2line.c:67
+msgid "Also show function names"
+msgstr "関数名も表示"
+
+#: src/addr2line.c:68
+msgid "Also show symbol or section names"
+msgstr "シンボル名 または セクション名も 表示"
+
+#: src/addr2line.c:69
+msgid "Also show symbol and the section names"
+msgstr "シンボル名と セクション名も 表示"
+
+#: src/addr2line.c:70
+msgid "Also show line table flags"
+msgstr "行テーブルフラグも表示"
+
+#: src/addr2line.c:72
+msgid ""
+"Show all source locations that caused inline expansion of subroutines at the "
+"address."
+msgstr ""
+"アドレスの サブルーチンの インライン展開を 引き起こした 全ての ソース位置を "
+"表示"
+
+#: src/addr2line.c:75
+msgid "Show demangled symbols (ARG is always ignored)"
+msgstr "デマングルされた シンボルを 表示 (ARGは常に無視される)"
+
+#: src/addr2line.c:76
+#, fuzzy
+#| msgid "Show demangled symbols (ARG is always ignored)"
+msgid "Show demangled symbols"
+msgstr "デマングルされた シンボルを 表示 (ARGは常に無視される)"
+
+#: src/addr2line.c:78
+msgid "Print all information on one line, and indent inlines"
+msgstr "全ての 情報を 一行で 表示し、 字下げする"
+
+#: src/addr2line.c:80
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show relative file names without compilation directory"
+msgstr "コンパイルディレクトリを 使用して 絶対ファイル名を 表示"
+
+#: src/addr2line.c:82 src/elfcmp.c:69 src/findtextrel.c:65 src/nm.c:99
+#: src/strings.c:77
+msgid "Miscellaneous:"
+msgstr "Misc:"
+
+#. Short description of program.
+#: src/addr2line.c:90
+msgid ""
+"Locate source files and line information for ADDRs (in a.out by default)."
+msgstr ""
+"ADDR のソースファイルと行の情報を 検索する (デフォルトでは a.out から)"
+
+#. Strings for arguments in help texts.
+#: src/addr2line.c:94
+msgid "[ADDR...]"
+msgstr ""
+
+#: src/addr2line.c:530
+msgid "Section syntax requires exactly one module"
+msgstr ""
+
+#: src/addr2line.c:552
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside section '%s'"
+msgstr ""
+
+#: src/addr2line.c:662
+#, c-format
+msgid "cannot find symbol '%s'"
+msgstr "シンボル '%s' が見つかりません"
+
+#: src/addr2line.c:667
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
+msgstr ""
+
+#: src/ar.c:66
+msgid "Commands:"
+msgstr "コマンド:"
+
+#: src/ar.c:67
+msgid "Delete files from archive."
+msgstr "アーカイブからファイルを削除。"
+
+#: src/ar.c:68
+msgid "Move files in archive."
+msgstr "アーカイブ内のファイルを移動。"
+
+#: src/ar.c:69
+msgid "Print files in archive."
+msgstr "アーカイブ内のファイルを印刷。"
+
+#: src/ar.c:70
+msgid "Quick append files to archive."
+msgstr "アーカイブへ ファイルを 素早く 追加。"
+
+#: src/ar.c:72
+msgid "Replace existing or insert new file into archive."
+msgstr "アーカイブの既存ファイルの置き換えまたは新しいファイルの挿入。"
+
+#: src/ar.c:73
+msgid "Display content of archive."
+msgstr "アーカイブの内容の表示。"
+
+#: src/ar.c:74
+msgid "Extract files from archive."
+msgstr "アーカイブからのファイルの取出し。"
+
+#: src/ar.c:76
+msgid "Command Modifiers:"
+msgstr "コマンド修飾子:"
+
+#: src/ar.c:77
+msgid "Preserve original dates."
+msgstr "元データの保存。"
+
+#: src/ar.c:78
+msgid "Use instance [COUNT] of name."
+msgstr "名前のインスタンス [COUNT] の使用。"
+
+#: src/ar.c:80
+msgid "Do not replace existing files with extracted files."
+msgstr "抽出したファイルで既存のファイルを置き換えない。"
+
+#: src/ar.c:81
+msgid "Allow filename to be truncated if necessary."
+msgstr "必要ならば ファイル名の 切り詰めを 認める。"
+
+#: src/ar.c:83
+msgid "Provide verbose output."
+msgstr "饒舌な出力を提供する。"
+
+#: src/ar.c:84
+msgid "Force regeneration of symbol table."
+msgstr "シンボルテーブルの再生成を強制する。"
+
+#: src/ar.c:85
+msgid "Insert file after [MEMBER]."
+msgstr "[MEMBER]の後にファイルを挿入する。"
+
+#: src/ar.c:86
+msgid "Insert file before [MEMBER]."
+msgstr "[MEMBER]の前にファイルを挿入する。"
+
+#: src/ar.c:87
+msgid "Same as -b."
+msgstr "-b と同じ。"
+
+#: src/ar.c:88
+msgid "Suppress message when library has to be created."
+msgstr "ライブラリーを 生作成なければ ならない時に メッセージを 抑止する。"
+
+#: src/ar.c:90
+msgid "Use full path for file matching."
+msgstr "ファイル照合にフルパスを使う。"
+
+#: src/ar.c:91
+msgid "Update only older files in archive."
+msgstr "アーカイブの 古い ファイルのみ 更新する。"
+
+#. Short description of program.
+#: src/ar.c:97
+msgid "Create, modify, and extract from archives."
+msgstr "アーカイブの作成や修正、アーカイブからの抽出を行う。"
+
+#. Strings for arguments in help texts.
+#: src/ar.c:100
+msgid "[MEMBER] [COUNT] ARCHIVE [FILE...]"
+msgstr ""
+
+#: src/ar.c:179
+#, c-format
+msgid "'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"
+msgstr "'a'や、'b'、'i'は、'm' や 'r' オプションと一緒にしか指定できません"
+
+#: src/ar.c:184
+#, c-format
+msgid "MEMBER parameter required for 'a', 'b', and 'i' modifiers"
+msgstr "'a'や、'b'、'i' 修飾子には MEMBER パラメーターが必要です"
+
+#: src/ar.c:200
+#, c-format
+msgid "'N' is only meaningful with the 'x' and 'd' options"
+msgstr "'N' は 'x' や 'd' オプションと一緒の時のみ意味を持ちます"
+
+#: src/ar.c:205
+#, c-format
+msgid "COUNT parameter required"
+msgstr "COUNT パラメーターが必要です"
+
+#: src/ar.c:217
+#, c-format
+msgid "invalid COUNT parameter %s"
+msgstr "不当な COUNT パラメーター %s です"
+
+#: src/ar.c:224
+#, c-format
+msgid "'%c' is only meaningful with the 'x' option"
+msgstr "'%c' は 'x' オプションと一緒の時のみ意味を持ちます"
+
+#: src/ar.c:230
+#, c-format
+msgid "archive name required"
+msgstr "アーカイブ名が必要です"
+
+#: src/ar.c:243
+#, c-format
+msgid "command option required"
+msgstr "コマンドオプションが必要です"
+
+#: src/ar.c:294
+#, c-format
+msgid "More than one operation specified"
+msgstr "1つを越える操作が指定されました"
+
+#: src/ar.c:388
+#, c-format
+msgid "cannot open archive '%s'"
+msgstr "アーカイブ '%s' を開けません"
+
+#: src/ar.c:398
+#, c-format
+msgid "cannot open archive '%s': %s"
+msgstr "アーカイブ '%s' を開けません: %s"
+
+#: src/ar.c:402
+#, c-format
+msgid "%s: not an archive file"
+msgstr "%s: アーカイブファイルではありません"
+
+#: src/ar.c:406
+#, c-format
+msgid "cannot stat archive '%s'"
+msgstr "アーカイブ '%s' を stat できません"
+
+#: src/ar.c:418
+#, c-format
+msgid "no entry %s in archive\n"
+msgstr "アーカイブに項目 %s がありません\n"
+
+#: src/ar.c:471 src/ar.c:925 src/ar.c:1131
+msgid "cannot create hash table"
+msgstr "ハッシュテーブルを作成できません"
+
+#: src/ar.c:477 src/ar.c:931 src/ar.c:1139
+msgid "cannot insert into hash table"
+msgstr "ハッシュテーブルに挿入できません"
+
+#: src/ar.c:485 src/ranlib.c:147
+#, c-format
+msgid "cannot stat '%s'"
+msgstr "'%s' を stat できません"
+
+#: src/ar.c:587
+#, c-format
+msgid "cannot read content of %s: %s"
+msgstr "%s の内容を読み込めません: %s"
+
+#: src/ar.c:630
+#, c-format
+msgid "cannot open %.*s"
+msgstr "%.*s を開けません"
+
+#: src/ar.c:652
+#, c-format
+msgid "failed to write %s"
+msgstr "%s への書き込みに失敗しました"
+
+#: src/ar.c:664
+#, c-format
+msgid "cannot change mode of %s"
+msgstr "%s のモードを変更できません"
+
+#: src/ar.c:680
+#, c-format
+msgid "cannot change modification time of %s"
+msgstr "%s の更新時間を変更できません"
+
+#: src/ar.c:726
+#, c-format
+msgid "cannot rename temporary file to %.*s"
+msgstr "一時ファイルを %.*s に名前変更できません"
+
+#: src/ar.c:762 src/ar.c:1016 src/ar.c:1419 src/ranlib.c:221
+#, c-format
+msgid "cannot create new file"
+msgstr "新しいファイルを作成できません"
+
+#: src/ar.c:1221
+#, c-format
+msgid "position member %s not found"
+msgstr "位置メンバー %s が見つかりません"
+
+#: src/ar.c:1231
+#, c-format
+msgid "%s: no entry %s in archive!\n"
+msgstr "%s: 項目 %s がアーカイブにありません!\n"
+
+#: src/ar.c:1260 src/objdump.c:240
+#, c-format
+msgid "cannot open %s"
+msgstr "%s を開けません"
+
+#: src/ar.c:1265
+#, c-format
+msgid "cannot stat %s"
+msgstr "%s を stat できません"
+
+#: src/ar.c:1271
+#, c-format
+msgid "%s is no regular file"
+msgstr "%s は一般ファイルではありません"
+
+#: src/ar.c:1284
+#, c-format
+msgid "cannot get ELF descriptor for %s: %s\n"
+msgstr "%s の ELF 記述子を取得できません: %s\n"
+
+#: src/ar.c:1304
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "%s を読み込めません: %s"
+
+#: src/ar.c:1479
+#, c-format
+msgid "cannot represent ar_date"
+msgstr "ar_date を表現できません"
+
+#: src/ar.c:1485
+#, c-format
+msgid "cannot represent ar_uid"
+msgstr "ar_uid を表現できません"
+
+#: src/ar.c:1491
+#, c-format
+msgid "cannot represent ar_gid"
+msgstr "ar_gid を表現できません"
+
+#: src/ar.c:1497
+#, c-format
+msgid "cannot represent ar_mode"
+msgstr "ar_mode を表現できません"
+
+#: src/ar.c:1503
+#, c-format
+msgid "cannot represent ar_size"
+msgstr "ar_size を表現できません"
+
+#: src/arlib-argp.c:31
+msgid "Use zero for uid, gid, and date in archive members."
+msgstr "アーカイブメンバの uid、 gid、 日付に ゼロを 使用する。"
+
+#: src/arlib-argp.c:33
+msgid "Use actual uid, gid, and date in archive members."
+msgstr "アーカイブメンバに 実際のuid、 gid、 日付を 使用する。"
+
+#: src/arlib-argp.c:62
+#, c-format
+msgid "%s (default)"
+msgstr "%s (デフォルト)"
+
+#. The archive is too big.
+#: src/arlib.c:212
+#, c-format
+msgid "the archive '%s' is too large"
+msgstr "アーカイブ '%s' は大きすぎます"
+
+#: src/arlib.c:225
+#, c-format
+msgid "cannot read ELF header of %s(%s): %s"
+msgstr "%s(%s) の  ELF ヘッダーを読み込めません: %s"
+
+#: src/elfclassify.c:91
+msgid "opening"
+msgstr ""
+
+#: src/elfclassify.c:98
+msgid "reading"
+msgstr ""
+
+#: src/elfclassify.c:244
+msgid "ELF header"
+msgstr ""
+
+#: src/elfclassify.c:255
+msgid "program headers"
+msgstr ""
+
+#: src/elfclassify.c:264
+msgid "program header"
+msgstr ""
+
+#: src/elfclassify.c:284
+msgid "section headers"
+msgstr ""
+
+#: src/elfclassify.c:295
+msgid "section header string table index"
+msgstr ""
+
+#: src/elfclassify.c:309
+msgid "could not obtain section header"
+msgstr "セクションヘッダーを取得できませんでした"
+
+#: src/elfclassify.c:315
+msgid "could not obtain section name"
+msgstr "セクション名を取得できませんでした"
+
+#: src/elfclassify.c:828
+msgid "writing to standard output"
+msgstr ""
+
+#: src/elfclassify.c:855
+msgid "reading from standard input"
+msgstr ""
+
+#: src/elfclassify.c:876
+msgid "Classification options"
+msgstr "分類オプション"
+
+#: src/elfclassify.c:878
+msgid "File looks like an ELF object or archive/static library (default)"
+msgstr ""
+"ELF オブジェクト または アーカイブ/静的ライブラリに 見えるファイル (デフォル"
+"ト)"
+
+#: src/elfclassify.c:881
+msgid "File is an regular ELF object (not an archive/static library)"
+msgstr ""
+"ファイルは 通常の ELF オブジェクト (アーカイブ/静的ライブラリ でない)"
+
+#: src/elfclassify.c:884
+msgid "File is an ELF archive or static library"
+msgstr "ファイルは ELF アーカイブ または 静的ライブラリ"
+
+#: src/elfclassify.c:887
+msgid "File is an ELF core dump file"
+msgstr "ファイルは ELF コアダンプファイル"
+
+#: src/elfclassify.c:890
+msgid ""
+"File is an ELF file with symbol table or .debug_* sections and can be "
+"stripped further"
+msgstr ""
+"ファイルは シンボルテーブル または .debug_* セクション付きの さらにストリップ"
+"可能な ELF ファイル"
+
+#: src/elfclassify.c:893
+msgid "File is (primarily) an ELF program executable (not primarily a DSO)"
+msgstr "ファイルは (主に) ELF 実行可能プログラム (主として DSO ではない)"
+
+#: src/elfclassify.c:896
+msgid "File is an ELF program executable (might also be a DSO)"
+msgstr "ファイルは ELF 実行可能プログラム (DSO かもしれない)"
+
+#: src/elfclassify.c:899
+msgid ""
+"File is (primarily) an ELF shared object (DSO) (not primarily an executable)"
+msgstr ""
+"ファイルは (主に) ELF 共有オブジェクト(DSO) (主として 実行可能プログラム"
+"でない)"
+
+#: src/elfclassify.c:902
+msgid "File is an ELF shared object (DSO) (might also be an executable)"
+msgstr ""
+"ファイルは ELF 共有オブジェクト(DSO) (実行可能プログラム かもしれない)"
+
+#: src/elfclassify.c:906
+msgid "File is a linux kernel module"
+msgstr "ファイルは linux カーネル モジュール"
+
+#: src/elfclassify.c:908
+msgid "File is a debug only ELF file (separate .debug, .dwo or dwz multi-file)"
+msgstr ""
+"ファイルは デバッグ専用 ELF ファイル (分離した .debug、 .dwo または dwz マル"
+"チファイル)"
+
+#: src/elfclassify.c:911
+msgid "File is a loadable ELF object (program or shared object)"
+msgstr ""
+"ファイルは ロード可能な ELF オブジェクト (プログラム または 共有オブジェク"
+"ト)"
+
+#: src/elfclassify.c:940
+msgid "Input flags"
+msgstr "入力フラグ"
+
+#: src/elfclassify.c:942
+msgid "Only classify regular (not symlink nor special device) files"
+msgstr ""
+"通常 (シンボリックリンク や 特別デバイス でない) ファイルのみを 分類する"
+
+#: src/elfclassify.c:944
+msgid ""
+"Also read file names to process from standard input, separated by newlines"
+msgstr "処理するファイル名を 標準入力から 改行区切りで 読み込む"
+
+#: src/elfclassify.c:947
+msgid ""
+"Also read file names to process from standard input, separated by ASCII NUL "
+"bytes"
+msgstr "処理するファイル名を 標準入力から ASCII ヌル文字区切りで 読み込む"
+
+#: src/elfclassify.c:950
+msgid "Do not read files from standard input (default)"
+msgstr "標準入力から ファイルを 読み込まない (デフォルト)"
+
+#: src/elfclassify.c:952
+msgid "Try to open compressed files or embedded (kernel) ELF images"
+msgstr ""
+"圧縮ファイル または 組み込み(カーネル) ELF イメージ のオープンを 試みる"
+
+#: src/elfclassify.c:955
+msgid "Output flags"
+msgstr "出力フラグ"
+
+#: src/elfclassify.c:957
+msgid "Output names of files, separated by newline"
+msgstr "改行区切りで ファイル名を 出力する"
+
+#: src/elfclassify.c:959
+msgid "Output names of files, separated by ASCII NUL"
+msgstr "ASCII ヌル文字区切りで ファイル名を 出力する"
+
+#: src/elfclassify.c:961
+msgid "Do not output file names"
+msgstr "ファイル名を出力しない"
+
+#: src/elfclassify.c:963
+msgid "If printing file names, print matching files (default)"
+msgstr ""
+"ファイル名を 表示するならば、 一致するファイルを 表示する (デフォルト)"
+
+#: src/elfclassify.c:965
+msgid "If printing file names, print files that do not match"
+msgstr "ファイル名を 表示するならば、 一致しないファイルを 表示する"
+
+#: src/elfclassify.c:967
+msgid "Additional flags"
+msgstr "追加のフラグ"
+
+#: src/elfclassify.c:969
+msgid "Output additional information (can be specified multiple times)"
+msgstr "追加の情報を 出力する (複数回指定されうる)"
+
+#: src/elfclassify.c:971
+msgid "Suppress some error output (counterpart to --verbose)"
+msgstr "いくつかのエラー出力を 抑制する ( --verbose の反対)"
+
+#. Strings for arguments in help texts.
+#: src/elfclassify.c:979 src/elfcompress.c:1436 src/elflint.c:77
+#: src/readelf.c:161
+msgid "FILE..."
+msgstr ""
+
+#: src/elfclassify.c:980
+msgid ""
+"Determine the type of an ELF file.\n"
+"\n"
+"All of the classification options must apply at the same time to a "
+"particular file.  Classification options can be negated using a \"--not-\" "
+"prefix.\n"
+"\n"
+"Since modern ELF does not clearly distinguish between programs and dynamic "
+"shared objects, you should normally use either --executable or --shared to "
+"identify the primary purpose of a file.  Only one of the --shared and --"
+"executable checks can pass for a file.\n"
+"\n"
+"If you want to know whether an ELF object might a program or a shared "
+"library (but could be both), then use --program or --library. Some ELF files "
+"will classify as both a program and a library.\n"
+"\n"
+"If you just want to know whether an ELF file is loadable (as program or "
+"library) use --loadable.  Note that files that only contain (separate) debug "
+"information (--debug-only) are never --loadable (even though they might "
+"contain program headers).  Linux kernel modules are also not --loadable (in "
+"the normal sense).\n"
+"\n"
+"Without any of the --print options, the program exits with status 0 if the "
+"requested checks pass for all input files, with 1 if a check fails for any "
+"file, and 2 if there is an environmental issue (such as a file read error or "
+"a memory allocation error).\n"
+"\n"
+"When printing file names, the program exits with status 0 even if no file "
+"names are printed, and exits with status 2 if there is an environmental "
+"issue.\n"
+"\n"
+"On usage error (e.g. a bad option was given), the program exits with a "
+"status code larger than 2.\n"
+"\n"
+"The --quiet or -q option suppresses some error warning output, but doesn't "
+"change the exit status."
+msgstr ""
+
+#: src/elfcmp.c:59
+msgid "Control options:"
+msgstr "制御オプション:"
+
+#: src/elfcmp.c:61
+msgid "Output all differences, not just the first"
+msgstr "最初のものに限らず、 全ての差異を 出力する"
+
+#: src/elfcmp.c:62
+msgid ""
+"Control treatment of gaps in loadable segments [ignore|match] (default: "
+"ignore)"
+msgstr ""
+"ロード可能セグメントの gap の 扱いを 制御する [ignore|match] (デフォルト: "
+"ignore)"
+
+#: src/elfcmp.c:64
+msgid "Ignore permutation of buckets in SHT_HASH section"
+msgstr "SHT_HASH セクションの バケットの 並べ替えを 無視"
+
+#: src/elfcmp.c:66
+msgid "Ignore differences in build ID"
+msgstr "ビルド ID の差異を 無視"
+
+#: src/elfcmp.c:67
+msgid "Output nothing; yield exit status only"
+msgstr "何も出力しない。 終了ステータスのみを生じさせる"
+
+#. Short description of program.
+#: src/elfcmp.c:74
+msgid "Compare relevant parts of two ELF files for equality."
+msgstr "2つの ELF ファイルの 関連のある部分の 等価性を 比較する。"
+
+#. Strings for arguments in help texts.
+#: src/elfcmp.c:78
+msgid "FILE1 FILE2"
+msgstr ""
+
+#: src/elfcmp.c:140
+msgid "Invalid number of parameters.\n"
+msgstr "不当なパラメータ数です\n"
+
+#: src/elfcmp.c:171 src/elfcmp.c:176
+#, c-format
+msgid "cannot get ELF header of '%s': %s"
+msgstr "'%s' の ELF ヘッダーを取得できません: %s"
+
+#: src/elfcmp.c:202
+#, c-format
+msgid "%s %s diff: ELF header"
+msgstr ""
+
+#: src/elfcmp.c:209 src/elfcmp.c:212
+#, c-format
+msgid "cannot get section count of '%s': %s"
+msgstr "'%s' のセクションヘッダー数を取得できません: %s"
+
+#: src/elfcmp.c:217
+#, c-format
+msgid "%s %s diff: section count"
+msgstr ""
+
+#: src/elfcmp.c:224 src/elfcmp.c:227
+#, c-format
+msgid "cannot get program header count of '%s': %s"
+msgstr "'%s' のプログラムヘッダー数を取得できません: %s"
+
+#: src/elfcmp.c:232
+#, c-format
+msgid "%s %s diff: program header count"
+msgstr ""
+
+#: src/elfcmp.c:240 src/elfcmp.c:243
+#, c-format
+msgid "cannot get hdrstrndx of '%s': %s"
+msgstr "'%s' の hdrstrndx を取得できません: %s"
+
+#: src/elfcmp.c:248
+#, c-format
+msgid "%s %s diff: shdr string index"
+msgstr ""
+
+#: src/elfcmp.c:306
+#, c-format
+msgid "%s %s differ: section [%zu], [%zu] name"
+msgstr ""
+
+#: src/elfcmp.c:329
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' header"
+msgstr ""
+
+#: src/elfcmp.c:337 src/elfcmp.c:343
+#, c-format
+msgid "cannot get content of section %zu in '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:352
+#, c-format
+msgid "symbol table [%zu] in '%s' has zero sh_entsize"
+msgstr ""
+
+#: src/elfcmp.c:364 src/elfcmp.c:370
+#, c-format
+msgid "cannot get symbol in '%s': %s"
+msgstr "'%s' のシンボルを取得できません: %s"
+
+#: src/elfcmp.c:392
+#, c-format
+msgid "%s %s differ: symbol table [%zu]"
+msgstr ""
+
+#: src/elfcmp.c:395
+#, c-format
+msgid "%s %s differ: symbol table [%zu,%zu]"
+msgstr ""
+
+#: src/elfcmp.c:442 src/elfcmp.c:512
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' number of notes"
+msgstr ""
+
+#: src/elfcmp.c:450
+#, c-format
+msgid "cannot read note section [%zu] '%s' in '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:461
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note name"
+msgstr ""
+
+#: src/elfcmp.c:469
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' type"
+msgstr ""
+
+#: src/elfcmp.c:484
+#, c-format
+msgid "%s %s differ: build ID length"
+msgstr ""
+
+#: src/elfcmp.c:492
+#, c-format
+msgid "%s %s differ: build ID content"
+msgstr ""
+
+#: src/elfcmp.c:501
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' content"
+msgstr ""
+
+#: src/elfcmp.c:542
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' content"
+msgstr ""
+
+#: src/elfcmp.c:546
+#, c-format
+msgid "%s %s differ: section [%zu,%zu] '%s' content"
+msgstr ""
+
+#: src/elfcmp.c:561
+#, c-format
+msgid "%s %s differ: unequal amount of important sections"
+msgstr ""
+
+#: src/elfcmp.c:594 src/elfcmp.c:599
+#, c-format
+msgid "cannot load data of '%s': %s"
+msgstr "'%s' のデータをロードできません: %s"
+
+#: src/elfcmp.c:618 src/elfcmp.c:624
+#, c-format
+msgid "cannot get program header entry %d of '%s': %s"
+msgstr ""
+
+#: src/elfcmp.c:630
+#, c-format
+msgid "%s %s differ: program header %d"
+msgstr ""
+
+#: src/elfcmp.c:654
+#, c-format
+msgid "%s %s differ: gap"
+msgstr ""
+
+#: src/elfcmp.c:705
+#, c-format
+msgid "Invalid value '%s' for --gaps parameter."
+msgstr "--gaps パラメータ に対する不当な値 '%s' です"
+
+#: src/elfcmp.c:733 src/findtextrel.c:194 src/nm.c:363 src/ranlib.c:140
+#: src/size.c:271 src/strings.c:184 src/strip.c:1040 src/strip.c:1077
+#: src/unstrip.c:2245 src/unstrip.c:2274
+#, c-format
+msgid "cannot open '%s'"
+msgstr "'%s' を開けません"
+
+#: src/elfcmp.c:737 src/findtextrel.c:213 src/ranlib.c:157
+#, c-format
+msgid "cannot create ELF descriptor for '%s': %s"
+msgstr "'%s' の ELF 記述子を作成できません: %s"
+
+#: src/elfcmp.c:742
+#, c-format
+msgid "cannot create EBL descriptor for '%s'"
+msgstr "'%s' の EBL 記述子を作成できません"
+
+#: src/elfcmp.c:760 src/findtextrel.c:384
+#, c-format
+msgid "cannot get section header of section %zu: %s"
+msgstr "セクション %zu のセクションヘッダーを取得できません: %s"
+
+#: src/elfcmp.c:770
+#, c-format
+msgid "cannot get content of section %zu: %s"
+msgstr "セクション %zu の内容を取得できません: %s"
+
+#: src/elfcmp.c:780 src/elfcmp.c:794
+#, c-format
+msgid "cannot get relocation: %s"
+msgstr "リロケーションを取得できません: %s"
+
+#: src/elfcompress.c:128 src/strip.c:305 src/unstrip.c:116
+#, c-format
+msgid "-o option specified twice"
+msgstr "-o オプションが 2 回指定されています"
+
+#: src/elfcompress.c:135
+#, c-format
+msgid "-t option specified twice"
+msgstr "-t オプションが 2 回指定されています"
+
+#: src/elfcompress.c:147
+#, c-format
+msgid "ZSTD support is not enabled"
+msgstr ""
+
+#: src/elfcompress.c:150
+#, c-format
+msgid "unknown compression type '%s'"
+msgstr "不明な圧縮タイプ '%s'"
+
+#. We need at least one input file.
+#: src/elfcompress.c:162 src/elfcompress.c:1447
+#, c-format
+msgid "No input file given"
+msgstr "入力ファイルが与えられていません"
+
+#: src/elfcompress.c:168 src/elfcompress.c:1451
+#, c-format
+msgid "Only one input file allowed together with '-o'"
+msgstr "'-o' と一緒の場合は入力ファイルは 1 つしか認められません"
+
+#: src/elfcompress.c:1408
+msgid "Place (de)compressed output into FILE"
+msgstr "圧縮(展開)した出力を FILE に置く"
+
+#: src/elfcompress.c:1411
+msgid ""
+"What type of compression to apply. TYPE can be 'none' (decompress), "
+"'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), 'zlib-"
+"gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD "
+"compression)"
+msgstr ""
+
+#: src/elfcompress.c:1415
+msgid ""
+"SECTION name to (de)compress, SECTION is an extended wildcard pattern "
+"(defaults to '.?(z)debug*')"
+msgstr ""
+"圧縮(展開)する セクション名。 SECTION は 拡張 ワイルドカード パターン(デ"
+"フォルトで  '.?(z)debug*')"
+
+#: src/elfcompress.c:1418
+msgid "Print a message for each section being (de)compressed"
+msgstr "圧縮(展開) されている 各セクション に対する メッセージを 表示"
+
+#: src/elfcompress.c:1421
+msgid ""
+"Force compression of section even if it would become larger or update/"
+"rewrite the file even if no section would be (de)compressed"
+msgstr ""
+
+#: src/elfcompress.c:1424 src/strip.c:92
+msgid "Relax a few rules to handle slightly broken ELF files"
+msgstr "少し壊れた ELF ファイルを取り扱うためにルールを少し緩和する"
+
+#: src/elfcompress.c:1427
+msgid "Be silent when a section cannot be compressed"
+msgstr "セクションを圧縮できないときに静かにする"
+
+#: src/elfcompress.c:1437
+msgid "Compress or decompress sections in an ELF file."
+msgstr "ELF ファイルの セクションを 圧縮 または 展開する"
+
+#: src/elflint.c:63
+msgid "Be extremely strict, flag level 2 features."
+msgstr "非常に厳格にする。 フラグレベル 2 機能。"
+
+#: src/elflint.c:64
+msgid "Do not print anything if successful"
+msgstr "成功した場合は何も表示しない"
+
+#: src/elflint.c:65
+msgid "Binary is a separate debuginfo file"
+msgstr "バイナリーは別の debuginfo ファイルです"
+
+#: src/elflint.c:67
+msgid ""
+"Binary has been created with GNU ld and is therefore known to be broken in "
+"certain ways"
+msgstr ""
+"バイナリーは GNU ld で作成され、 従って、 ある方法で 壊れることが 知られてい"
+"る"
+
+#. Short description of program.
+#: src/elflint.c:73
+msgid "Pedantic checking of ELF files compliance with gABI/psABI spec."
+msgstr "ELF ファイルが gABI/psABI 仕様へ準拠しているかの厳密なチェック。"
+
+#: src/elflint.c:154 src/readelf.c:413
+#, c-format
+msgid "cannot open input file '%s'"
+msgstr "入力ファイル '%s' を開けません"
+
+#: src/elflint.c:161
+#, c-format
+msgid "cannot generate Elf descriptor for '%s': %s\n"
+msgstr "'%s' に対する Elf 記述子を生成できません: %s\n"
+
+#: src/elflint.c:180
+#, c-format
+msgid "error while closing Elf descriptor: %s\n"
+msgstr "Elf 記述子を閉じている時にエラー: %s\n"
+
+#: src/elflint.c:184
+msgid "No errors"
+msgstr "エラーはありません"
+
+#: src/elflint.c:219 src/readelf.c:625
+msgid "Missing file name.\n"
+msgstr "ファイル名がありません。\n"
+
+#: src/elflint.c:284
+#, c-format
+msgid " error while freeing sub-ELF descriptor: %s\n"
+msgstr "sub-ELF 記述子を解放している時にエラー: %s\n"
+
+#. We cannot do anything.
+#: src/elflint.c:292
+#, c-format
+msgid "Not an ELF file - it has the wrong magic bytes at the start\n"
+msgstr "ELF ファイルではありません - 最初に誤ったマジックバイトがあります\n"
+
+#: src/elflint.c:358
+#, c-format
+msgid "e_ident[%d] == %d is no known class\n"
+msgstr "e_ident[%d] == %d は既知のクラスではありません\n"
+
+#: src/elflint.c:363
+#, c-format
+msgid "e_ident[%d] == %d is no known data encoding\n"
+msgstr "e_ident[%d] == %d は既知のデータエンコードではありません\n"
+
+#: src/elflint.c:367
+#, c-format
+msgid "unknown ELF header version number e_ident[%d] == %d\n"
+msgstr "不明な ELF ヘッダーバージョン数 e_ident[%d] == %d\n"
+
+#: src/elflint.c:375
+#, c-format
+msgid "unsupported OS ABI e_ident[%d] == '%s'\n"
+msgstr "不明な OS ABI e_ident[%d] == '%s'\n"
+
+#: src/elflint.c:381
+#, c-format
+msgid "unsupported ABI version e_ident[%d] == %d\n"
+msgstr "不明な ABI バージョン e_ident[%d] == %d\n"
+
+#: src/elflint.c:386
+#, c-format
+msgid "e_ident[%zu] is not zero\n"
+msgstr "e_ident[%zu] がゼロではありません\n"
+
+#: src/elflint.c:391
+#, c-format
+msgid "unknown object file type %d\n"
+msgstr "不明なオブジェクトファイルタイプ %d\n"
+
+#: src/elflint.c:398
+#, c-format
+msgid "unknown machine type %d\n"
+msgstr "不明なマシンタイプ %d\n"
+
+#: src/elflint.c:402
+#, c-format
+msgid "unknown object file version\n"
+msgstr "不明なオブジェクトファイルバージョン\n"
+
+#: src/elflint.c:408
+#, c-format
+msgid "invalid program header offset\n"
+msgstr "不当なプログラムヘッダーオフセット\n"
+
+#: src/elflint.c:410
+#, c-format
+msgid "executables and DSOs cannot have zero program header offset\n"
+msgstr ""
+"実行ファイルと DSO はプログラムヘッダーオフセットが 0 であってはいけません\n"
+
+#: src/elflint.c:414
+#, c-format
+msgid "invalid number of program header entries\n"
+msgstr "プログラムヘッダー項目数として不当な数\n"
+
+#: src/elflint.c:422
+#, c-format
+msgid "invalid section header table offset\n"
+msgstr "不当なセクションヘッダーテーブルオフセット\n"
+
+#: src/elflint.c:425
+#, c-format
+msgid "section header table must be present\n"
+msgstr "セクションヘッダーテーブルがなければなりません\n"
+
+#: src/elflint.c:439
+#, c-format
+msgid "invalid number of section header table entries\n"
+msgstr "セクションヘッダーテーブル項目数として不当な数\n"
+
+#: src/elflint.c:456
+#, c-format
+msgid "invalid section header index\n"
+msgstr "不当なセクションヘッダーインデックス\n"
+
+#: src/elflint.c:474
+#, c-format
+msgid "Can only check %u headers, shnum was %u\n"
+msgstr ""
+
+#: src/elflint.c:488
+#, c-format
+msgid "invalid number of program header table entries\n"
+msgstr "プログラムヘッダー項目数として不当な数\n"
+
+#: src/elflint.c:505
+#, c-format
+msgid "Can only check %u headers, phnum was %u\n"
+msgstr ""
+
+#: src/elflint.c:510
+#, c-format
+msgid "invalid machine flags: %s\n"
+msgstr "不当なマシンフラグ: %s\n"
+
+#: src/elflint.c:517 src/elflint.c:534
+#, c-format
+msgid "invalid ELF header size: %hd\n"
+msgstr "不当な ELF ヘッダーサイズ: %hd\n"
+
+#: src/elflint.c:520 src/elflint.c:537
+#, c-format
+msgid "invalid program header size: %hd\n"
+msgstr "不当なプログラムヘッダーサイズ: %hd\n"
+
+#: src/elflint.c:523 src/elflint.c:540
+#, c-format
+msgid "invalid program header position or size\n"
+msgstr "不当なプログラムヘッダー位置かサイズ\n"
+
+#: src/elflint.c:526 src/elflint.c:543
+#, c-format
+msgid "invalid section header size: %hd\n"
+msgstr "不当なセクションヘッダーサイズ: %hd\n"
+
+#: src/elflint.c:529 src/elflint.c:546
+#, c-format
+msgid "invalid section header position or size\n"
+msgstr "不当なセクションヘッダー位置かサイズ\n"
+
+#: src/elflint.c:591
+#, c-format
+msgid ""
+"section [%2d] '%s': section with SHF_GROUP flag set not part of a section "
+"group\n"
+msgstr ""
+"セクション [%2d] '%s': SHF_GROUP フラグのあるセクションにセクショングループの"
+"一部分が設定されていません\n"
+
+#: src/elflint.c:595
+#, c-format
+msgid ""
+"section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"
+msgstr ""
+"セクション [%2d] '%s': セクショングループ [%2zu] '%s' がグループメンバーより"
+"前にありません\n"
+
+#: src/elflint.c:611 src/elflint.c:1509 src/elflint.c:1560 src/elflint.c:1610
+#: src/elflint.c:1692 src/elflint.c:2029 src/elflint.c:2355 src/elflint.c:2981
+#: src/elflint.c:3144 src/elflint.c:3292 src/elflint.c:3494 src/elflint.c:4511
+#, c-format
+msgid "section [%2d] '%s': cannot get section data\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:624 src/elflint.c:1699
+#, c-format
+msgid ""
+"section [%2d] '%s': referenced as string table for section [%2d] '%s' but "
+"type is not SHT_STRTAB\n"
+msgstr ""
+"セクション [%2d] '%s': セクション [%2d] '%s' 用の文字列テーブルとして参照され"
+"ていますが、タイプが SHT_STRTAB ではありません\n"
+
+#: src/elflint.c:647
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol table cannot have more than one extended index "
+"section\n"
+msgstr ""
+"セクション [%2d] '%s': シンボルテーブルは 1 個を越える拡張インデックスセク"
+"ションを持てません\n"
+
+#: src/elflint.c:659
+#, c-format
+msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n"
+msgstr "セクション [%2u] '%s': 項目サイズが ElfXX_Sym と一致しません\n"
+
+#: src/elflint.c:663
+#, c-format
+msgid ""
+"section [%2u] '%s': number of local entries in 'st_info' larger than table "
+"size\n"
+msgstr ""
+
+#: src/elflint.c:672
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %d: %s\n"
+msgstr "セクション [%2d] '%s': シンボル %d を得られません: %s\n"
+
+#: src/elflint.c:677 src/elflint.c:680 src/elflint.c:683 src/elflint.c:686
+#: src/elflint.c:689 src/elflint.c:692
+#, c-format
+msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n"
+msgstr "セクション [%2d] '%s': 0番目の項目にある '%s' ゼロではありません\n"
+
+#: src/elflint.c:695
+#, c-format
+msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n"
+msgstr "セクション [%2d] '%s': 0番目の項目用の XINDEX がゼロではありません\n"
+
+#: src/elflint.c:705
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %zu: %s\n"
+msgstr "セクション [%2d] '%s': シンボル %zu を得られません: %s\n"
+
+#: src/elflint.c:714
+#, c-format
+msgid "section [%2d] '%s': symbol %zu: invalid name value\n"
+msgstr "セクション [%2d] '%s': シンボル %zu: 不当な名前の値\n"
+
+#: src/elflint.c:729
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): too large section index but no extended "
+"section index section\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: 大きすぎるセクションインデックスだが、拡"
+"張セクションインデックスセクションがありません\n"
+
+#: src/elflint.c:735
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit "
+"in st_shndx (%<PRIu32>)\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: st_shndx (%<PRIu32>) に適合するインデッ"
+"クス用に使われる XINDEX\n"
+
+#. || sym->st_shndx > SHN_HIRESERVE  always false
+#: src/elflint.c:747
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): invalid section index\n"
+msgstr "セクション [%2d] '%s': シンボル %zu: 不当なセクションインデックス\n"
+
+#: src/elflint.c:755
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown type\n"
+msgstr "セクション [%2d] '%s': シンボル %zu: 不明なタイプ\n"
+
+#: src/elflint.c:761
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"
+msgstr "セクション [%2d] '%s': シンボル %zu: 不明なシンボルバインディング\n"
+
+#: src/elflint.c:766
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: オブジェクトタイプと異なる固有のシンボ"
+"ル\n"
+
+#: src/elflint.c:774
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable "
+"files\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: COMMON はリロケータブルファイル内のみで"
+"許されます\n"
+
+#: src/elflint.c:778
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: ローカルな COMMON シンボルは意味がありま"
+"せん\n"
+
+#: src/elflint.c:782
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: COMMON セクションの機能は意味がありませ"
+"ん\n"
+
+#: src/elflint.c:833
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"
+msgstr "セクション [%2d] '%s': シンボル %zu: st_value 境界外\n"
+
+#: src/elflint.c:839 src/elflint.c:864 src/elflint.c:913
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu は参照されるセクション [%2d] '%s' とは完"
+"全に一致しません\n"
+
+#: src/elflint.c:848
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not "
+"have SHF_TLS flag set\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: 参照されるセクション [%2d] '%s' は "
+"SHF_TLS フラグが設定されていません\n"
+
+#: src/elflint.c:858 src/elflint.c:906
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: st_value 参照されるセクション [%2d] "
+"'%s' の境界外\n"
+
+#: src/elflint.c:885
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header "
+"entry\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: TLS プログラムヘッダー項目がない TLS シ"
+"ンボル\n"
+
+#: src/elflint.c:891
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program "
+"header entry\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: TLS プログラムヘッダー項目がない TLS シ"
+"ンボル\n"
+
+#: src/elflint.c:899
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value short of referenced section "
+"[%2d] '%s'\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: 参照されるセクション [%2d] '%s' の"
+"st_value 不足\n"
+
+#: src/elflint.c:926
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local symbol outside range described in "
+"sh_info\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: sh_info に記述された範囲外のローカルシン"
+"ボル\n"
+
+#: src/elflint.c:933
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): non-local symbol outside range "
+"described in sh_info\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: sh_info に記述された範囲外の非ローカルシ"
+"ンボル\n"
+
+#: src/elflint.c:940
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"
+msgstr "セクション [%2d] '%s': シンボル %zu: 非ローカルセクションシンボル\n"
+
+#: src/elflint.c:990
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section "
+"[%2d]\n"
+msgstr ""
+"セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルが間違ったセクション "
+"[%2d] を参照しています\n"
+
+#: src/elflint.c:997
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] "
+"'%s'\n"
+msgstr ""
+"セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルはセクション [%2d] '%s' "
+"を参照しています\n"
+
+#. This test is more strict than the psABIs which
+#. usually allow the symbol to be in the middle of
+#. the .got section, allowing negative offsets.
+#: src/elflint.c:1013
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#<PRIx64> does not "
+"match %s section address %#<PRIx64>\n"
+msgstr ""
+"セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボル値 %#<PRIx64> は %s のセ"
+"クションアドレス %#<PRIx64> と一致しません\n"
+
+#: src/elflint.c:1020
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %<PRIu64> does not "
+"match %s section size %<PRIu64>\n"
+msgstr ""
+"セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルサイズ %<PRIu64> は %s "
+"のセクションサイズ %<PRIu64> と一致しません\n"
+
+#: src/elflint.c:1028
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got "
+"section\n"
+msgstr ""
+"セクション [%2d] '%s': _GLOBAL_OFFSET_TABLE_ シンボルはありますが、.got セク"
+"ションがありません\n"
+
+#: src/elflint.c:1044
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC_ symbol value %#<PRIx64> does not match dynamic "
+"segment address %#<PRIx64>\n"
+msgstr ""
+"セクション [%2d] '%s': _DYNAMIC_ シンボル値 %#<PRIx64> は動的セグメントアドレ"
+"ス %#<PRIx64> と一致しません\n"
+
+#: src/elflint.c:1051
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC symbol size %<PRIu64> does not match dynamic "
+"segment size %<PRIu64>\n"
+msgstr ""
+"セクション [%2d] '%s': _DYNAMIC シンボルサイズ %<PRIu64> は動的セグメントサイ"
+"ズ %<PRIu64> と一致しません\n"
+
+#: src/elflint.c:1064
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-"
+"default visibility\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: 省略以外の可視性を持った動的シンボルテー"
+"ブル中のシンボル\n"
+
+#: src/elflint.c:1068
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: st_other 中に設定された不明なビット\n"
+
+#: src/elflint.c:1106
+#, fuzzy, c-format
+msgid "section [%2d] '%s': cannot get section data.\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:1122
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"
+msgstr "セクション [%2d] '%s': この RELA セクション用に使われる DT_RELCOUNT\n"
+
+#: src/elflint.c:1133 src/elflint.c:1186
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"
+msgstr ""
+"セクション [%2d] '%s': このセクション用には高すぎる DT_RELCOUNT 値 %d\n"
+
+#: src/elflint.c:1158 src/elflint.c:1211
+#, c-format
+msgid ""
+"section [%2d] '%s': relative relocations after index %d as specified by "
+"DT_RELCOUNT\n"
+msgstr ""
+"セクション [%2d] '%s': UT_RELOCOUNT で指定されたインデックス %d 後の相対リロ"
+"ケーション\n"
+
+#: src/elflint.c:1164 src/elflint.c:1217
+#, c-format
+msgid ""
+"section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT "
+"specified %d relative relocations\n"
+msgstr ""
+"セクション [%2d] '%s': インデックス %zu での非相対リロケーション;  %d 相対リ"
+"ロケーションで指定された DT_RELCOUNT\n"
+
+#: src/elflint.c:1176
+#, c-format
+msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n"
+msgstr "セクション [%2d] '%s': この REL セクション用に使われる DT_RELACOUNT\n"
+
+#: src/elflint.c:1259
+#, c-format
+msgid "section [%2d] '%s': invalid destination section index\n"
+msgstr "セクション [%2d] '%s': 不当な宛先セクションインデックス\n"
+
+#: src/elflint.c:1271
+#, c-format
+msgid "section [%2d] '%s': invalid destination section type\n"
+msgstr "セクション [%2d] '%s': 不当な宛先セクションタイプ\n"
+
+#: src/elflint.c:1279
+#, c-format
+msgid "section [%2d] '%s': sh_info should be zero\n"
+msgstr "セクション [%2d] '%s': sh_info はゼロでなければなりません\n"
+
+#: src/elflint.c:1287
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': no relocations for merge-able string sections possible\n"
+msgstr ""
+"セクション [%2d] '%s': マージできるセクションのリロケーションは不可能です\n"
+
+#: src/elflint.c:1365
+#, c-format
+msgid "text relocation flag set but there is no read-only segment\n"
+msgstr ""
+"テキストリロケーションフラグが設定されていますが、読込み専用セグメントがあり"
+"ません\n"
+
+#: src/elflint.c:1392
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid type\n"
+msgstr "セクション [%2d] '%s': リロケーション %zu: 不当なタイプ\n"
+
+#: src/elflint.c:1400
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: relocation type invalid for the file "
+"type\n"
+msgstr ""
+"セクション [%2d] '%s': リロケーション %zu: このファイル用のリロケーションタイ"
+"プは不当です\n"
+
+#: src/elflint.c:1408
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n"
+msgstr ""
+"セクション [%2d] '%s': リロケーション %zu: 不当なシンボルインデックス\n"
+
+#: src/elflint.c:1426
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can "
+"be used with %s\n"
+msgstr ""
+"セクション [%2d] '%s': リロケーション %zu: シンボル '_GLOBAL_OFFSET_TABLE_' "
+"のみが %s と一緒に使用できます\n"
+
+#: src/elflint.c:1443
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n"
+msgstr "セクション [%2d] '%s': リロケーション %zu: オフセット境界外\n"
+
+#: src/elflint.c:1458
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: copy relocation against symbol of type "
+"%s\n"
+msgstr ""
+"セクション [%2d] '%s': リロケーション %zu: タイプ %s のシンボルに対するコピー"
+"リロケーション\n"
+
+#: src/elflint.c:1479
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: read-only section modified but text "
+"relocation flag not set\n"
+msgstr ""
+"セクション [%2d] '%s': リロケーション %zu: 読込み専用セクションが変更されまし"
+"たが、テキストリロケーションフラグが設定されていません\n"
+
+#: src/elflint.c:1494
+#, c-format
+msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n"
+msgstr ""
+"セクション [%2d] '%s': リロケーションがロードされたデータとロードされなかった"
+"データに対してです\n"
+
+#: src/elflint.c:1534 src/elflint.c:1585
+#, c-format
+msgid "section [%2d] '%s': cannot get relocation %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:1687
+#, c-format
+msgid "more than one dynamic section present\n"
+msgstr ""
+
+#: src/elflint.c:1705
+#, fuzzy, c-format
+msgid ""
+"section [%2d]: referenced as string table for section [%2d] '%s' but section "
+"link value is invalid\n"
+msgstr ""
+"セクション [%2d] '%s': セクション [%2d] '%s' 用の文字列テーブルとして参照され"
+"ていますが、タイプが SHT_STRTAB ではありません\n"
+
+#: src/elflint.c:1713
+#, c-format
+msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"
+msgstr ""
+
+#: src/elflint.c:1718 src/elflint.c:2008
+#, c-format
+msgid "section [%2d] '%s': sh_info not zero\n"
+msgstr ""
+
+#: src/elflint.c:1728
+#, c-format
+msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:1736
+#, c-format
+msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"
+msgstr ""
+
+#: src/elflint.c:1743
+#, c-format
+msgid "section [%2d] '%s': entry %zu: unknown tag\n"
+msgstr ""
+
+#: src/elflint.c:1754
+#, c-format
+msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n"
+msgstr ""
+
+#: src/elflint.c:1764
+#, c-format
+msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n"
+msgstr ""
+
+#: src/elflint.c:1782
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"
+msgstr ""
+
+#: src/elflint.c:1795
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: pointer does not match address of section "
+"[%2d] '%s' referenced by sh_link\n"
+msgstr ""
+
+#: src/elflint.c:1839
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"
+msgstr ""
+
+#: src/elflint.c:1854
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must be valid offset in section "
+"[%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:1874 src/elflint.c:1902
+#, c-format
+msgid "section [%2d] '%s': contains %s entry but not %s\n"
+msgstr ""
+
+#: src/elflint.c:1886
+#, c-format
+msgid "section [%2d] '%s': mandatory tag %s not present\n"
+msgstr ""
+
+#: src/elflint.c:1895
+#, c-format
+msgid "section [%2d] '%s': no hash section present\n"
+msgstr ""
+
+#: src/elflint.c:1910 src/elflint.c:1917
+#, c-format
+msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n"
+msgstr ""
+
+#: src/elflint.c:1927 src/elflint.c:1931
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"
+msgstr ""
+
+#: src/elflint.c:1937
+#, c-format
+msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n"
+msgstr ""
+
+#: src/elflint.c:1948 src/elflint.c:1952 src/elflint.c:1956 src/elflint.c:1960
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in prelinked executable\n"
+msgstr ""
+
+#: src/elflint.c:1972
+#, c-format
+msgid ""
+"section [%2d] '%s': only relocatable files can have extended section index\n"
+msgstr ""
+
+#: src/elflint.c:1982
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index section not for symbol table\n"
+msgstr ""
+
+#: src/elflint.c:1986
+#, fuzzy, c-format
+msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"
+msgstr "セクション [%2d] '%s': 不当な宛先セクションインデックス\n"
+
+#: src/elflint.c:1991
+#, c-format
+msgid "cannot get data for symbol section\n"
+msgstr ""
+
+#: src/elflint.c:1994
+#, c-format
+msgid "section [%2d] '%s': entry size does not match Elf32_Word\n"
+msgstr ""
+
+#: src/elflint.c:2003
+#, c-format
+msgid "section [%2d] '%s': extended index table too small for symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2018
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index in section [%2zu] '%s' refers to "
+"same symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2036
+#, c-format
+msgid "symbol 0 should have zero extended section index\n"
+msgstr ""
+
+#: src/elflint.c:2048
+#, c-format
+msgid "cannot get data for symbol %zu\n"
+msgstr ""
+
+#: src/elflint.c:2053
+#, c-format
+msgid "extended section index is %<PRIu32> but symbol index is not XINDEX\n"
+msgstr ""
+
+#: src/elflint.c:2070 src/elflint.c:2127
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"
+msgstr ""
+
+#: src/elflint.c:2084 src/elflint.c:2141
+#, c-format
+msgid "section [%2d] '%s': chain array too large\n"
+msgstr ""
+
+#: src/elflint.c:2098 src/elflint.c:2155
+#, c-format
+msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2108
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2165
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %<PRIu64> out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2178
+#, fuzzy, c-format
+msgid "section [%2d] '%s': not enough data\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:2190
+#, fuzzy, c-format
+msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n"
+msgstr "セクション [%2d] '%s': 0番目の項目にある '%s' ゼロではありません\n"
+
+#: src/elflint.c:2206
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected at "
+"least %ld)\n"
+msgstr ""
+
+#: src/elflint.c:2215
+#, c-format
+msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n"
+msgstr ""
+
+#: src/elflint.c:2249
+#, c-format
+msgid ""
+"section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"
+msgstr ""
+
+#: src/elflint.c:2270
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %u referenced in chain for bucket %zu is "
+"undefined\n"
+msgstr ""
+
+#: src/elflint.c:2283
+#, c-format
+msgid ""
+"section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+
+#: src/elflint.c:2292
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:2322
+#, c-format
+msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2327
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"
+msgstr ""
+
+#: src/elflint.c:2333
+#, c-format
+msgid "section [%2d] '%s': bitmask does not match names in the hash table\n"
+msgstr ""
+
+#: src/elflint.c:2346
+#, c-format
+msgid "section [%2d] '%s': relocatable files cannot have hash tables\n"
+msgstr ""
+
+#: src/elflint.c:2364
+#, c-format
+msgid "section [%2d] '%s': hash table not for dynamic symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2368
+#, fuzzy, c-format
+msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"
+msgstr "セクション [%2d] '%s': 不当な宛先セクションインデックス\n"
+
+#: src/elflint.c:2378
+#, c-format
+msgid "section [%2d] '%s': hash table entry size incorrect\n"
+msgstr ""
+
+#: src/elflint.c:2383
+#, c-format
+msgid "section [%2d] '%s': not marked to be allocated\n"
+msgstr ""
+
+#: src/elflint.c:2388
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table has not even room for initial administrative "
+"entries\n"
+msgstr ""
+
+#: src/elflint.c:2437
+#, c-format
+msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"
+msgstr ""
+
+#: src/elflint.c:2461 src/elflint.c:2526 src/elflint.c:2561
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' does not contain enough data\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:2482
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' has zero bit mask words\n"
+msgstr ""
+"\n"
+"セクション [%Zu] '%s' にはダンプすべきデータがありません。\n"
+
+#: src/elflint.c:2493 src/elflint.c:2537 src/elflint.c:2574
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' uses too much data\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:2508
+#, c-format
+msgid ""
+"hash section [%2zu] '%s' invalid symbol index %<PRIu32> (max_nsyms: "
+"%<PRIu32>, nentries: %<PRIu32>\n"
+msgstr ""
+
+#: src/elflint.c:2595
+#, fuzzy, c-format
+msgid "hash section [%2zu] '%s' invalid sh_entsize\n"
+msgstr "セクション [%2d] '%s': 不当な宛先セクションタイプ\n"
+
+#: src/elflint.c:2605 src/elflint.c:2609
+#, c-format
+msgid "section [%2zu] '%s': reference to symbol index 0\n"
+msgstr ""
+
+#: src/elflint.c:2616
+#, c-format
+msgid ""
+"symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:2628
+#, c-format
+msgid ""
+"symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:2644
+#, c-format
+msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n"
+msgstr ""
+
+#: src/elflint.c:2664
+#, c-format
+msgid ""
+"section [%2d] '%s': section groups only allowed in relocatable object files\n"
+msgstr ""
+
+#: src/elflint.c:2675
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol table: %s\n"
+msgstr ""
+
+#: src/elflint.c:2680
+#, c-format
+msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n"
+msgstr ""
+
+#: src/elflint.c:2686
+#, c-format
+msgid "section [%2d] '%s': invalid symbol index in sh_info\n"
+msgstr ""
+
+#: src/elflint.c:2691
+#, c-format
+msgid "section [%2d] '%s': sh_flags not zero\n"
+msgstr ""
+
+#: src/elflint.c:2698
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol for signature\n"
+msgstr ""
+
+#: src/elflint.c:2702
+#, fuzzy, c-format
+msgid "section [%2d] '%s': cannot get symbol name for signature\n"
+msgstr "セクション [%2d] '%s': シンボル %d を得られません: %s\n"
+
+#: src/elflint.c:2707
+#, fuzzy, c-format
+msgid "section [%2d] '%s': signature symbol cannot be empty string\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:2713
+#, c-format
+msgid "section [%2d] '%s': sh_flags not set correctly\n"
+msgstr ""
+
+#: src/elflint.c:2719
+#, c-format
+msgid "section [%2d] '%s': cannot get data: %s\n"
+msgstr ""
+
+#: src/elflint.c:2728
+#, c-format
+msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"
+msgstr ""
+
+#: src/elflint.c:2734
+#, c-format
+msgid "section [%2d] '%s': section group without flags word\n"
+msgstr ""
+
+#: src/elflint.c:2742
+#, c-format
+msgid "section [%2d] '%s': section group without member\n"
+msgstr ""
+
+#: src/elflint.c:2746
+#, c-format
+msgid "section [%2d] '%s': section group with only one member\n"
+msgstr ""
+
+#: src/elflint.c:2757
+#, c-format
+msgid "section [%2d] '%s': unknown section group flags\n"
+msgstr ""
+
+#: src/elflint.c:2769
+#, fuzzy, c-format
+msgid "section [%2d] '%s': section index %zu out of range\n"
+msgstr "セクション [%2d] '%s': リロケーション %zu: オフセット境界外\n"
+
+#: src/elflint.c:2778
+#, c-format
+msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n"
+msgstr ""
+
+#: src/elflint.c:2785
+#, c-format
+msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n"
+msgstr ""
+
+#: src/elflint.c:2791
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': element %zu references section [%2d] '%s' without "
+"SHF_GROUP flag set\n"
+msgstr ""
+"セクション [%2d] '%s': シンボル %zu: 参照されるセクション [%2d] '%s' は "
+"SHF_TLS フラグが設定されていません\n"
+
+#: src/elflint.c:2798
+#, c-format
+msgid "section [%2d] '%s' is contained in more than one section group\n"
+msgstr ""
+
+#: src/elflint.c:2995
+#, c-format
+msgid ""
+"section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no "
+"dynamic symbol table\n"
+msgstr ""
+
+#: src/elflint.c:3007
+#, c-format
+msgid ""
+"section [%2d] '%s' has different number of entries than symbol table [%2d] "
+"'%s'\n"
+msgstr ""
+
+#: src/elflint.c:3023
+#, c-format
+msgid "section [%2d] '%s': symbol %d: cannot read version data\n"
+msgstr ""
+
+#: src/elflint.c:3039
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n"
+msgstr ""
+
+#: src/elflint.c:3047
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with version\n"
+msgstr ""
+
+#: src/elflint.c:3061
+#, c-format
+msgid "section [%2d] '%s': symbol %d: invalid version index %d\n"
+msgstr ""
+
+#: src/elflint.c:3066
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for defined version\n"
+msgstr ""
+
+#: src/elflint.c:3076
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for requested version\n"
+msgstr ""
+
+#: src/elflint.c:3129
+#, c-format
+msgid "more than one version reference section present\n"
+msgstr ""
+
+#: src/elflint.c:3137 src/elflint.c:3284
+#, c-format
+msgid "section [%2d] '%s': sh_link does not link to string table\n"
+msgstr ""
+
+#: src/elflint.c:3162 src/elflint.c:3338
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong version %d\n"
+msgstr ""
+
+#: src/elflint.c:3169 src/elflint.c:3345
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"
+msgstr ""
+
+#: src/elflint.c:3179
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid file reference\n"
+msgstr ""
+
+#: src/elflint.c:3187
+#, c-format
+msgid "section [%2d] '%s': entry %d references unknown dependency\n"
+msgstr ""
+
+#: src/elflint.c:3199
+#, c-format
+msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"
+msgstr ""
+
+#: src/elflint.c:3207
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has invalid name "
+"reference\n"
+msgstr ""
+
+#: src/elflint.c:3216
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: "
+"%#x, expected %#x\n"
+msgstr ""
+
+#: src/elflint.c:3225
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version "
+"name '%s'\n"
+msgstr ""
+
+#: src/elflint.c:3236
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"
+msgstr ""
+
+#: src/elflint.c:3253 src/elflint.c:3429
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n"
+msgstr ""
+
+#: src/elflint.c:3261 src/elflint.c:3437
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says "
+"there are more entries\n"
+msgstr ""
+
+#: src/elflint.c:3276
+#, c-format
+msgid "more than one version definition section present\n"
+msgstr ""
+
+#: src/elflint.c:3323
+#, c-format
+msgid "section [%2d] '%s': more than one BASE definition\n"
+msgstr ""
+
+#: src/elflint.c:3327
+#, c-format
+msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"
+msgstr ""
+
+#: src/elflint.c:3333
+#, c-format
+msgid "section [%2d] '%s': entry %d has unknown flag\n"
+msgstr ""
+
+#: src/elflint.c:3360
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid name reference\n"
+msgstr ""
+
+#: src/elflint.c:3367
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"
+msgstr ""
+
+#: src/elflint.c:3375
+#, c-format
+msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n"
+msgstr ""
+
+#: src/elflint.c:3395
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"
+msgstr ""
+
+#: src/elflint.c:3412
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"
+msgstr ""
+
+#: src/elflint.c:3445
+#, c-format
+msgid "section [%2d] '%s': no BASE definition\n"
+msgstr ""
+
+#: src/elflint.c:3461
+#, c-format
+msgid "section [%2d] '%s': unknown parent version '%s'\n"
+msgstr ""
+
+#: src/elflint.c:3486
+#, c-format
+msgid "section [%2d] '%s': empty object attributes section\n"
+msgstr ""
+
+#: src/elflint.c:3502
+#, c-format
+msgid "section [%2d] '%s': unrecognized attribute format\n"
+msgstr ""
+
+#: src/elflint.c:3513
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3522
+#, c-format
+msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3534
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n"
+msgstr ""
+
+#: src/elflint.c:3551
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"
+msgstr ""
+
+#: src/elflint.c:3560
+#, c-format
+msgid "section [%2d] '%s': offset %zu: truncated attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3569
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"
+msgstr ""
+
+#: src/elflint.c:3584
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"
+msgstr ""
+
+#. Tag_File
+#: src/elflint.c:3595
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"
+msgstr ""
+
+#: src/elflint.c:3616
+#, c-format
+msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"
+msgstr ""
+
+#: src/elflint.c:3627
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n"
+msgstr ""
+
+#: src/elflint.c:3640
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"
+msgstr ""
+
+#: src/elflint.c:3644
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: unrecognized %s attribute value %<PRIu64>\n"
+msgstr ""
+
+#: src/elflint.c:3654
+#, c-format
+msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n"
+msgstr ""
+
+#: src/elflint.c:3660
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"
+msgstr ""
+
+#: src/elflint.c:3758
+#, c-format
+msgid "cannot get section header of zeroth section\n"
+msgstr ""
+
+#: src/elflint.c:3762
+#, c-format
+msgid "zeroth section has nonzero name\n"
+msgstr ""
+
+#: src/elflint.c:3764
+#, c-format
+msgid "zeroth section has nonzero type\n"
+msgstr ""
+
+#: src/elflint.c:3766
+#, c-format
+msgid "zeroth section has nonzero flags\n"
+msgstr ""
+
+#: src/elflint.c:3768
+#, c-format
+msgid "zeroth section has nonzero address\n"
+msgstr ""
+
+#: src/elflint.c:3770
+#, c-format
+msgid "zeroth section has nonzero offset\n"
+msgstr ""
+
+#: src/elflint.c:3772
+#, c-format
+msgid "zeroth section has nonzero align value\n"
+msgstr ""
+
+#: src/elflint.c:3774
+#, c-format
+msgid "zeroth section has nonzero entry size value\n"
+msgstr ""
+
+#: src/elflint.c:3777
+#, c-format
+msgid ""
+"zeroth section has nonzero size value while ELF header has nonzero shnum "
+"value\n"
+msgstr ""
+
+#: src/elflint.c:3781
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in shstrndx\n"
+msgstr ""
+
+#: src/elflint.c:3785
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in phnum\n"
+msgstr ""
+
+#: src/elflint.c:3803
+#, c-format
+msgid "cannot get section header for section [%2zu] '%s': %s\n"
+msgstr ""
+
+#: src/elflint.c:3812
+#, c-format
+msgid "section [%2zu]: invalid name\n"
+msgstr ""
+
+#: src/elflint.c:3839
+#, c-format
+msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n"
+msgstr ""
+
+#: src/elflint.c:3856
+#, c-format
+msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n"
+msgstr ""
+
+#: src/elflint.c:3874
+#, c-format
+msgid ""
+"section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"
+msgstr ""
+
+#: src/elflint.c:3891
+#, c-format
+msgid "section [%2zu] '%s' present in object file\n"
+msgstr ""
+
+#: src/elflint.c:3897 src/elflint.c:3929
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"
+msgstr ""
+
+#: src/elflint.c:3902 src/elflint.c:3934
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable "
+"segments\n"
+msgstr ""
+
+#: src/elflint.c:3910
+#, c-format
+msgid ""
+"section [%2zu] '%s' is extension section index table in non-object file\n"
+msgstr ""
+
+#: src/elflint.c:3953
+#, c-format
+msgid "section [%2zu] '%s': size not multiple of entry size\n"
+msgstr ""
+
+#: src/elflint.c:3958
+#, c-format
+msgid "cannot get section header\n"
+msgstr ""
+
+#: src/elflint.c:3968
+#, c-format
+msgid "section [%2zu] '%s' has unsupported type %d\n"
+msgstr ""
+
+#: src/elflint.c:3988
+#, c-format
+msgid ""
+"section [%2zu] '%s' contains invalid processor-specific flag(s) %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:3998
+#, c-format
+msgid "section [%2zu] '%s' contains unknown flag(s) %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:4006
+#, c-format
+msgid "section [%2zu] '%s': thread-local data sections address not zero\n"
+msgstr ""
+
+#: src/elflint.c:4016
+#, fuzzy, c-format
+msgid "section [%2zu] '%s': allocated section cannot be compressed\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:4021
+#, fuzzy, c-format
+msgid "section [%2zu] '%s': nobits section cannot be compressed\n"
+msgstr "セクション [%2d] '%s': セクションデータを得られません\n"
+
+#: src/elflint.c:4027
+#, c-format
+msgid ""
+"section [%2zu] '%s': compressed section with no compression header: %s\n"
+msgstr ""
+
+#: src/elflint.c:4033
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in link value\n"
+msgstr ""
+
+#: src/elflint.c:4038
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in info value\n"
+msgstr ""
+
+#: src/elflint.c:4045
+#, c-format
+msgid "section [%2zu] '%s': strings flag set without merge flag\n"
+msgstr ""
+
+#: src/elflint.c:4050
+#, c-format
+msgid "section [%2zu] '%s': merge flag set but entry size is zero\n"
+msgstr ""
+
+#: src/elflint.c:4069
+#, c-format
+msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n"
+msgstr ""
+
+#: src/elflint.c:4078
+#, c-format
+msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"
+msgstr ""
+
+#: src/elflint.c:4085
+#, c-format
+msgid "section [%2zu] '%s' is both executable and writable\n"
+msgstr ""
+
+#: src/elflint.c:4116
+#, c-format
+msgid ""
+"section [%2zu] '%s' not fully contained in segment of program header entry "
+"%d\n"
+msgstr ""
+
+#: src/elflint.c:4126
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d\n"
+msgstr ""
+
+#: src/elflint.c:4152
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d and file contents is non-zero\n"
+msgstr ""
+
+#: src/elflint.c:4163
+#, c-format
+msgid ""
+"section [%2zu] '%s' has not type NOBITS but is not read from the file in "
+"segment of program header entry %d\n"
+msgstr ""
+
+#: src/elflint.c:4174
+#, c-format
+msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n"
+msgstr ""
+
+#: src/elflint.c:4184
+#, c-format
+msgid "section [%2zu] '%s' is writable in unwritable segment %d\n"
+msgstr ""
+
+#: src/elflint.c:4194
+#, c-format
+msgid ""
+"section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"
+msgstr ""
+
+#: src/elflint.c:4200
+#, c-format
+msgid ""
+"section [%2zu] '%s': ELF header says this is the section header string table "
+"but type is not SHT_TYPE\n"
+msgstr ""
+
+#: src/elflint.c:4208
+#, c-format
+msgid ""
+"section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"
+msgstr ""
+
+#: src/elflint.c:4263
+#, c-format
+msgid "more than one version symbol table present\n"
+msgstr ""
+
+#: src/elflint.c:4286
+#, c-format
+msgid "INTERP program header entry but no .interp section\n"
+msgstr ""
+
+#: src/elflint.c:4297
+#, c-format
+msgid ""
+"loadable segment [%u] is executable but contains no executable sections\n"
+msgstr ""
+
+#: src/elflint.c:4303
+#, c-format
+msgid "loadable segment [%u] is writable but contains no writable sections\n"
+msgstr ""
+
+#: src/elflint.c:4314
+#, c-format
+msgid ""
+"no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section "
+"exist\n"
+msgstr ""
+
+#: src/elflint.c:4327
+#, c-format
+msgid "duplicate version index %d\n"
+msgstr ""
+
+#: src/elflint.c:4341
+#, c-format
+msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"
+msgstr ""
+
+#: src/elflint.c:4390
+#, c-format
+msgid "phdr[%d]: unknown core file note type %<PRIu32> at offset %<PRIu64>\n"
+msgstr ""
+
+#: src/elflint.c:4394
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown core file note type %<PRIu32> at offset %zu\n"
+msgstr ""
+
+#: src/elflint.c:4450
+#, c-format
+msgid ""
+"phdr[%d]: unknown object file note type %<PRIu32> with owner name '%s' at "
+"offset %zu\n"
+msgstr ""
+
+#: src/elflint.c:4455
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown object file note type %<PRIu32> with owner name "
+"'%s' at offset %zu\n"
+msgstr ""
+
+#: src/elflint.c:4474
+#, c-format
+msgid "phdr[%d]: no note entries defined for the type of file\n"
+msgstr ""
+
+#: src/elflint.c:4494
+#, c-format
+msgid "phdr[%d]: cannot get content of note section: %s\n"
+msgstr ""
+
+#: src/elflint.c:4497
+#, c-format
+msgid "phdr[%d]: extra %<PRIu64> bytes after last note\n"
+msgstr ""
+
+#: src/elflint.c:4518
+#, c-format
+msgid "section [%2d] '%s': no note entries defined for the type of file\n"
+msgstr ""
+
+#: src/elflint.c:4525
+#, c-format
+msgid "section [%2d] '%s': cannot get content of note section\n"
+msgstr ""
+
+#: src/elflint.c:4528
+#, c-format
+msgid "section [%2d] '%s': extra %<PRIu64> bytes after last note\n"
+msgstr ""
+
+#: src/elflint.c:4546
+#, c-format
+msgid ""
+"only executables, shared objects, and core files can have program headers\n"
+msgstr ""
+
+#: src/elflint.c:4561
+#, c-format
+msgid "cannot get program header entry %d: %s\n"
+msgstr ""
+
+#: src/elflint.c:4571
+#, c-format
+msgid "program header entry %d: unknown program header entry type %#<PRIx64>\n"
+msgstr ""
+
+#: src/elflint.c:4582
+#, c-format
+msgid "more than one INTERP entry in program header\n"
+msgstr ""
+
+#: src/elflint.c:4590
+#, c-format
+msgid "more than one TLS entry in program header\n"
+msgstr ""
+
+#: src/elflint.c:4597
+#, c-format
+msgid "static executable cannot have dynamic sections\n"
+msgstr ""
+
+#: src/elflint.c:4611
+#, c-format
+msgid "dynamic section reference in program header has wrong offset\n"
+msgstr ""
+
+#: src/elflint.c:4614
+#, c-format
+msgid "dynamic section size mismatch in program and section header\n"
+msgstr ""
+
+#: src/elflint.c:4624
+#, c-format
+msgid "more than one GNU_RELRO entry in program header\n"
+msgstr ""
+
+#: src/elflint.c:4645
+#, c-format
+msgid "loadable segment GNU_RELRO applies to is not writable\n"
+msgstr ""
+
+#: src/elflint.c:4656
+#, c-format
+msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"
+msgstr ""
+
+#: src/elflint.c:4663
+#, c-format
+msgid ""
+"GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"
+msgstr ""
+
+#: src/elflint.c:4672 src/elflint.c:4695
+#, c-format
+msgid "%s segment not contained in a loaded segment\n"
+msgstr ""
+
+#: src/elflint.c:4701
+#, c-format
+msgid "program header offset in ELF header and PHDR entry do not match"
+msgstr ""
+
+#: src/elflint.c:4728
+#, c-format
+msgid "call frame search table reference in program header has wrong offset\n"
+msgstr ""
+
+#: src/elflint.c:4731
+#, c-format
+msgid "call frame search table size mismatch in program and section header\n"
+msgstr ""
+
+#: src/elflint.c:4744
+#, c-format
+msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"
+msgstr ""
+
+#: src/elflint.c:4752
+#, c-format
+msgid "call frame search table must be allocated\n"
+msgstr ""
+
+#: src/elflint.c:4755
+#, c-format
+msgid "section [%2zu] '%s' must be allocated\n"
+msgstr ""
+
+#: src/elflint.c:4759
+#, c-format
+msgid "call frame search table must not be writable\n"
+msgstr ""
+
+#: src/elflint.c:4762
+#, c-format
+msgid "section [%2zu] '%s' must not be writable\n"
+msgstr ""
+
+#: src/elflint.c:4767
+#, c-format
+msgid "call frame search table must not be executable\n"
+msgstr ""
+
+#: src/elflint.c:4770
+#, c-format
+msgid "section [%2zu] '%s' must not be executable\n"
+msgstr ""
+
+#: src/elflint.c:4784
+#, c-format
+msgid "program header entry %d: file size greater than memory size\n"
+msgstr ""
+
+#: src/elflint.c:4791
+#, c-format
+msgid "program header entry %d: alignment not a power of 2\n"
+msgstr ""
+
+#: src/elflint.c:4794
+#, c-format
+msgid ""
+"program header entry %d: file offset and virtual address not module of "
+"alignment\n"
+msgstr ""
+
+#: src/elflint.c:4807
+#, c-format
+msgid ""
+"executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME "
+"program header entry"
+msgstr ""
+
+#: src/elflint.c:4841
+#, c-format
+msgid "cannot read ELF header: %s\n"
+msgstr ""
+
+#: src/elflint.c:4853
+#, fuzzy, c-format
+msgid "cannot create backend for ELF file\n"
+msgstr "新しいファイルを生成できません"
+
+#: src/elflint.c:4874
+#, c-format
+msgid "text relocation flag set but not needed\n"
+msgstr ""
+
+#: src/findtextrel.c:60
+msgid "Input Selection:"
+msgstr "入力選択:"
+
+#: src/findtextrel.c:61
+msgid "Prepend PATH to all file names"
+msgstr "全ての ファイル名に対して PATH を先頭に 付け加える"
+
+#: src/findtextrel.c:63
+msgid "Use PATH as root of debuginfo hierarchy"
+msgstr "debuginfo 階層の ルートとして PATH を使用する"
+
+#. Short description of program.
+#: src/findtextrel.c:70
+msgid "Locate source of text relocations in FILEs (a.out by default)."
+msgstr ""
+"FILE (デフォルトでは a.out)の テキスト リロケーションの ソースを 検索する"
+
+#. Strings for arguments in help texts.
+#: src/findtextrel.c:74 src/nm.c:107 src/objdump.c:70 src/size.c:79
+#: src/strings.c:86 src/strip.c:100
+msgid "[FILE...]"
+msgstr ""
+
+#: src/findtextrel.c:223
+#, c-format
+msgid "cannot get ELF header '%s': %s"
+msgstr "ELF ヘッダー '%s' を取得できません: %s"
+
+#: src/findtextrel.c:234
+#, c-format
+msgid "'%s' is not a DSO or PIE"
+msgstr "'%s' は DSO または PIE ではありません"
+
+#: src/findtextrel.c:254
+#, c-format
+msgid "getting get section header of section %zu: %s"
+msgstr ""
+
+#: src/findtextrel.c:278
+#, c-format
+msgid "cannot read dynamic section: %s"
+msgstr "dynamic セクションを読み込めません: %s"
+
+#: src/findtextrel.c:299
+#, c-format
+msgid "no text relocations reported in '%s'"
+msgstr ""
+
+#: src/findtextrel.c:310
+#, c-format
+msgid "while reading ELF file"
+msgstr "ELF ファイルの読み込み中"
+
+#: src/findtextrel.c:314
+#, c-format
+msgid "cannot get program header count: %s"
+msgstr "プログラムヘッダー数を取得できません: %s"
+
+#: src/findtextrel.c:325 src/findtextrel.c:340
+#, c-format
+msgid "cannot get program header index at offset %zd: %s"
+msgstr "オフセット %zd に位置するプログラムヘッダー索引を取得できません: %s"
+
+#: src/findtextrel.c:396
+#, c-format
+msgid "cannot get symbol table section %zu in '%s': %s"
+msgstr ""
+
+#: src/findtextrel.c:417 src/findtextrel.c:440
+#, c-format
+msgid "cannot get relocation at index %d in section %zu in '%s': %s"
+msgstr ""
+
+#: src/findtextrel.c:506
+#, c-format
+msgid "%s not compiled with -fpic/-fPIC\n"
+msgstr "%s は -fpic/-fPIC 付きでコンパイルされていません\n"
+
+#: src/findtextrel.c:560
+#, c-format
+msgid ""
+"the file containing the function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"関数 '%s' を含むファイルは -fpic/-fPIC 付きでコンパイルされていません\n"
+
+#: src/findtextrel.c:567 src/findtextrel.c:587
+#, c-format
+msgid ""
+"the file containing the function '%s' might not be compiled with -fpic/-"
+"fPIC\n"
+msgstr ""
+"関数 '%s' を含むファイルは -fpic/-fPIC 付きでコンパイルされていないかもしれま"
+"せん\n"
+
+#: src/findtextrel.c:575
+#, c-format
+msgid ""
+"either the file containing the function '%s' or the file containing the "
+"function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"関数 '%s' を含むファイル または 関数 '%s' を含むファイルは -fpic/-fPIC 付きで"
+"コンパイルされていません\n"
+
+#: src/findtextrel.c:595
+#, c-format
+msgid ""
+"a relocation modifies memory at offset %llu in a write-protected segment\n"
+msgstr ""
+"リロケーションは 書き込み禁止セグメントの オフセット %llu に位置するメモリを "
+"修正します\n"
+
+#: src/nm.c:65 src/strip.c:69
+msgid "Output selection:"
+msgstr "出力選択:"
+
+#: src/nm.c:66
+msgid "Display debugger-only symbols"
+msgstr "デバッガ専用シンボルを表示"
+
+#: src/nm.c:67
+msgid "Display only defined symbols"
+msgstr "定義済みシンボルのみを表示"
+
+#: src/nm.c:70
+msgid "Display dynamic symbols instead of normal symbols"
+msgstr "通常シンボルの 代わりに 動的シンボルを 表示"
+
+#: src/nm.c:71
+msgid "Display only external symbols"
+msgstr "外部シンボルのみを表示"
+
+#: src/nm.c:72
+msgid "Display only undefined symbols"
+msgstr "未定義シンボルのみを表示"
+
+#: src/nm.c:74
+msgid "Include index for symbols from archive members"
+msgstr "アーカイブメンバからの シンボルの 索引を 含める"
+
+#: src/nm.c:76 src/size.c:53
+msgid "Output format:"
+msgstr "出力形式:"
+
+#: src/nm.c:78
+msgid "Print name of the input file before every symbol"
+msgstr "各シンボルの 前に 入力ファイル名を 表示"
+
+#: src/nm.c:81
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The "
+"default is `sysv'"
+msgstr ""
+"出力形式として FORMAT を使う。 FORMAT は `bsd'、`sysv'、`posix' のいずれか。"
+"デフォルトは `sysv'"
+
+#: src/nm.c:83
+msgid "Same as --format=bsd"
+msgstr "--format=bsd と同じ"
+
+#: src/nm.c:84
+msgid "Same as --format=posix"
+msgstr "--format=posix と同じ"
+
+#: src/nm.c:85 src/size.c:59
+msgid "Use RADIX for printing symbol values"
+msgstr "シンボル値の 表示に RADIX を使う"
+
+#: src/nm.c:86
+msgid "Mark special symbols"
+msgstr "特別なシンボルに印を点ける"
+
+#: src/nm.c:88
+msgid "Print size of defined symbols"
+msgstr "定義済みシンボルのサイズを表示"
+
+#: src/nm.c:90 src/size.c:67 src/strip.c:74 src/unstrip.c:68
+msgid "Output options:"
+msgstr "出力オプション:"
+
+#: src/nm.c:91
+msgid "Sort symbols numerically by address"
+msgstr "シンボルを アドレスにより 数値的に 並べ替える"
+
+#: src/nm.c:93
+msgid "Do not sort the symbols"
+msgstr "シンボルを並べ替えない"
+
+#: src/nm.c:94
+msgid "Reverse the sense of the sort"
+msgstr "並べ替えの意味を逆にする"
+
+#: src/nm.c:97
+msgid "Decode low-level symbol names into source code names"
+msgstr "低水準の シンボル名を ソースコード上の 名前に デコードする"
+
+#. Short description of program.
+#: src/nm.c:104
+msgid "List symbols from FILEs (a.out by default)."
+msgstr "FILE のシンボルを一覧表示 (デフォルトではa.out)。"
+
+#: src/nm.c:115 src/objdump.c:78
+msgid "Output formatting"
+msgstr "出力形式:"
+
+#: src/nm.c:139 src/objdump.c:102 src/size.c:104 src/strip.c:132
+#, fuzzy, c-format
+msgid "%s: INTERNAL ERROR %d (%s): %s"
+msgstr "%s: 内部エラー %d (%s-%s): %s"
+
+#: src/nm.c:380 src/nm.c:392 src/size.c:287 src/size.c:296 src/size.c:307
+#: src/strip.c:2763
+#, c-format
+msgid "while closing '%s'"
+msgstr "'%s' を閉じている最中"
+
+#: src/nm.c:402 src/objdump.c:279 src/strip.c:827
+#, c-format
+msgid "%s: File format not recognized"
+msgstr "%s: ファイル形式を認識できませんでした"
+
+#. Note: 0 is no valid offset.
+#: src/nm.c:442
+#, fuzzy
+msgid ""
+"\n"
+"Archive index:\n"
+msgstr ""
+"\n"
+"アーカイブ索引:"
+
+#: src/nm.c:451
+#, c-format
+msgid "invalid offset %zu for symbol %s"
+msgstr "シンボル %2$sの不正なオフセット %1$zu "
+
+#: src/nm.c:456
+#, c-format
+msgid "%s in %s\n"
+msgstr "%2$s の中の %1$s\n"
+
+#: src/nm.c:464
+#, c-format
+msgid "cannot reset archive offset to beginning"
+msgstr "アーカイブのオフセットを最初にリセットできません"
+
+#: src/nm.c:489 src/objdump.c:327
+#, c-format
+msgid "%s%s%s: file format not recognized"
+msgstr "%s%s%s: ファイル形式を認識できません"
+
+#: src/nm.c:702
+msgid "cannot create search tree"
+msgstr "検索ツリーを生成できません"
+
+#: src/nm.c:742 src/nm.c:1234 src/objdump.c:778 src/readelf.c:685
+#: src/readelf.c:1506 src/readelf.c:1655 src/readelf.c:1882 src/readelf.c:2123
+#: src/readelf.c:2312 src/readelf.c:2482 src/readelf.c:2604 src/readelf.c:2854
+#: src/readelf.c:3140 src/readelf.c:3215 src/readelf.c:3301 src/readelf.c:3897
+#: src/readelf.c:3945 src/readelf.c:4014 src/readelf.c:12030
+#: src/readelf.c:13213 src/readelf.c:13423 src/readelf.c:13491 src/size.c:396
+#: src/size.c:467 src/strip.c:1093
+#, c-format
+msgid "cannot get section header string table index"
+msgstr "セクションヘッダー文字列テーブル索引が得られません"
+
+#. We always print this prolog.
+#: src/nm.c:767
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s:\n"
+"\n"
+msgstr ""
+"\n"
+"\n"
+"%s からのシンボル:\n"
+"\n"
+
+#. The header line.
+#: src/nm.c:770
+#, c-format
+msgid ""
+"%*s%-*s %-*s Class  Type     %-*s %*s Section\n"
+"\n"
+msgstr ""
+"%*s%-*s %-*s クラス タイプ   %-*s %*s セクション\n"
+"\n"
+
+#: src/nm.c:772
+msgctxt "sysv"
+msgid "Name"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:774
+msgctxt "sysv"
+msgid "Value"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:776
+msgctxt "sysv"
+msgid "Size"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:778
+msgctxt "sysv"
+msgid "Line"
+msgstr ""
+
+#: src/nm.c:1245
+#, fuzzy, c-format
+msgid "%s: entry size in section %zd `%s' is not what we expect"
+msgstr "%s: セクションの項目の大きさ `%s' は予期したものとは異なります"
+
+#: src/nm.c:1250
+#, fuzzy, c-format
+msgid "%s: size of section %zd `%s' is not multiple of entry size"
+msgstr "%s: セクション `%s' の大きさは項目の大きさの整数倍ではありません"
+
+#: src/nm.c:1330
+#, fuzzy, c-format
+msgid "%s: entries (%zd) in section %zd `%s' is too large"
+msgstr "%s: セクションの項目の大きさ `%s' は予期したものとは異なります"
+
+#. XXX Add machine specific object file types.
+#: src/nm.c:1566
+#, c-format
+msgid "%s%s%s%s: Invalid operation"
+msgstr "%s%s%s%s: 不当な操作"
+
+#: src/nm.c:1616
+#, c-format
+msgid "%s%s%s: no symbols"
+msgstr "%s%s%s: シンボルがありません"
+
+#: src/objdump.c:51
+msgid "Mode selection:"
+msgstr "モード選択:"
+
+#: src/objdump.c:52
+msgid "Display relocation information."
+msgstr "リロケーション 情報の 表示"
+
+#: src/objdump.c:54
+msgid "Display the full contents of all sections requested"
+msgstr "要求された 全ての セクションの 最大限の 内容を 表示"
+
+#: src/objdump.c:56
+msgid "Display assembler code of executable sections"
+msgstr "実行可能 セクションの アセンブラコードを 表示"
+
+#: src/objdump.c:58
+msgid "Output content selection:"
+msgstr "出力内容選択:"
+
+#: src/objdump.c:60
+msgid "Only display information for section NAME."
+msgstr "NAME セクションの情報のみを表示"
+
+#. Short description of program.
+#: src/objdump.c:66
+msgid "Show information from FILEs (a.out by default)."
+msgstr "FILE から情報を表示する (デフォルトでは a.out)"
+
+#: src/objdump.c:217 src/readelf.c:630
+msgid "No operation specified.\n"
+msgstr "操作が指定されていません。\n"
+
+#: src/objdump.c:257 src/objdump.c:269
+#, c-format
+msgid "while close `%s'"
+msgstr ""
+
+#: src/objdump.c:362 src/readelf.c:2218 src/readelf.c:2409
+msgid "INVALID SYMBOL"
+msgstr "不当なシンボル"
+
+#: src/objdump.c:377 src/readelf.c:2252 src/readelf.c:2445
+msgid "INVALID SECTION"
+msgstr "不当なセクション"
+
+#: src/objdump.c:497
+#, c-format
+msgid ""
+"\n"
+"RELOCATION RECORDS FOR [%s]:\n"
+"%-*s TYPE                 VALUE\n"
+msgstr ""
+
+#: src/objdump.c:500
+msgid "OFFSET"
+msgstr ""
+
+#: src/objdump.c:565
+#, c-format
+msgid "Contents of section %s:\n"
+msgstr ""
+
+#: src/objdump.c:686
+msgid "cannot disassemble"
+msgstr "逆アセンブルできません"
+
+#: src/objdump.c:757
+msgid "cannot create backend for elf file"
+msgstr "elf ファイル用にバックエンドを作成できません"
+
+#. Short description of program.
+#: src/ranlib.c:62
+msgid "Generate an index to speed access to archives."
+msgstr "アーカイブへのアクセス加速のための索引生成"
+
+#. Strings for arguments in help texts.
+#: src/ranlib.c:65
+msgid "ARCHIVE"
+msgstr ""
+
+#: src/ranlib.c:101
+#, c-format
+msgid "Archive name required"
+msgstr "アーカイブ名が必要です"
+
+#: src/ranlib.c:165
+#, c-format
+msgid "'%s' is no archive"
+msgstr "'%s' はアーカイブではありません"
+
+#: src/ranlib.c:200
+#, c-format
+msgid "error while freeing sub-ELF descriptor: %s"
+msgstr ""
+
+#: src/readelf.c:97
+msgid "ELF input selection:"
+msgstr "ELF入力選択:"
+
+#: src/readelf.c:99
+msgid ""
+"Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data"
+msgstr ""
+"ELF 入力データとして SECTION (デフォルトでは .gnu_debugdata) を使用する"
+
+#: src/readelf.c:102
+msgid ""
+"Used with -w to find the skeleton Compile Units in FILE associated with the "
+"Split Compile units in a .dwo input file"
+msgstr ""
+
+#: src/readelf.c:104
+msgid "ELF output selection:"
+msgstr "ELF出力選択:"
+
+#: src/readelf.c:106
+msgid "All these plus -p .strtab -p .dynstr -p .comment"
+msgstr ""
+
+#: src/readelf.c:107
+msgid "Display the dynamic segment"
+msgstr "動的セグメントを表示"
+
+#: src/readelf.c:108
+msgid "Display the ELF file header"
+msgstr "ELF ファイルヘッダーを表示"
+
+#: src/readelf.c:110
+msgid "Display histogram of bucket list lengths"
+msgstr "バケットリスト長のヒストグラムを表示"
+
+#: src/readelf.c:111
+msgid "Display the program headers"
+msgstr "プログラムヘッダーを表示"
+
+#: src/readelf.c:113
+msgid "Display relocations"
+msgstr "リロケーションを表示"
+
+#: src/readelf.c:114
+msgid "Display the section groups"
+msgstr "セクショングループを表示"
+
+#: src/readelf.c:115
+msgid "Display the sections' headers"
+msgstr "セクションヘッダーを表示"
+
+#: src/readelf.c:118
+msgid "Display the symbol table sections"
+msgstr "シンボルテーブルセクションを表示"
+
+#: src/readelf.c:121
+msgid "Display (only) the dynamic symbol table"
+msgstr "動的シンボルテーブル(のみ)を表示"
+
+#: src/readelf.c:122
+msgid "Display versioning information"
+msgstr "バージョニング情報を表示"
+
+#: src/readelf.c:123
+msgid "Display the ELF notes"
+msgstr "ELF notes を表示"
+
+#: src/readelf.c:125
+msgid "Display architecture specific information, if any"
+msgstr "(もしあれば)アーキテクチャー固有の情報を表示"
+
+#: src/readelf.c:127
+msgid "Display sections for exception handling"
+msgstr "例外ハンドリングのセクションを表示"
+
+#: src/readelf.c:129
+msgid "Additional output selection:"
+msgstr "追加の出力選択:"
+
+#: src/readelf.c:131
+#, fuzzy
+msgid ""
+"Display DWARF section content.  SECTION can be one of abbrev, addr, aranges, "
+"decodedaranges, frame, gdb_index, info, info+, loc, line, decodedline, "
+"ranges, pubnames, str, macinfo, macro or exception"
+msgstr ""
+"DWARF セクションの内容を表示。SECTION は addrevか、aranges、frame、info、"
+"loc、ranges、pubnames、str、macinfo、exception のいずれかです"
+
+#: src/readelf.c:135
+msgid "Dump the uninterpreted contents of SECTION, by number or name"
+msgstr "SECTION の 未解釈の 内容を ダンプする。 番号 または 名前で指定する"
+
+#: src/readelf.c:137
+msgid "Print string contents of sections"
+msgstr "セクションの文字列内容を表示"
+
+#: src/readelf.c:140
+msgid "Display the symbol index of an archive"
+msgstr "アーカイブのシンボル索引を表示"
+
+#: src/readelf.c:142
+msgid "Use the dynamic segment when possible for displaying info"
+msgstr ""
+
+#: src/readelf.c:144
+msgid "Output control:"
+msgstr "出力制御:"
+
+#: src/readelf.c:146
+msgid "Do not find symbol names for addresses in DWARF data"
+msgstr "DWARFデータ中のアドレスのためのシンボル名を探さない"
+
+#: src/readelf.c:148
+#, fuzzy
+msgid ""
+"Display just offsets instead of resolving values to addresses in DWARF data"
+msgstr "DWARFデータ中のアドレスのためのシンボル名を探さない"
+
+#: src/readelf.c:150
+msgid "Ignored for compatibility (lines always wide)"
+msgstr ""
+
+#: src/readelf.c:152
+msgid ""
+"Show compression information for compressed sections (when used with -S); "
+"decompress section before dumping data (when used with -p or -x)"
+msgstr ""
+
+#. Short description of program.
+#: src/readelf.c:157
+msgid "Print information from ELF file in human-readable form."
+msgstr "ELF ファイルから人間が読める形で情報を表示する。"
+
+#. Look up once.
+#: src/readelf.c:395
+msgid "yes"
+msgstr "はい"
+
+#: src/readelf.c:396
+msgid "no"
+msgstr "いいえ"
+
+#: src/readelf.c:598
+#, c-format
+msgid "Unknown DWARF debug section `%s'.\n"
+msgstr "不明な DWARF デバッグセクション `%s'.\n"
+
+#: src/readelf.c:669 src/readelf.c:780
+#, c-format
+msgid "cannot generate Elf descriptor: %s"
+msgstr "Elf 記述子を生成できません: %s"
+
+#: src/readelf.c:676 src/readelf.c:1002 src/strip.c:1188
+#, c-format
+msgid "cannot determine number of sections: %s"
+msgstr "セクション数を決定できません: %s"
+
+#: src/readelf.c:694 src/readelf.c:1322 src/readelf.c:1530
+#, c-format
+msgid "cannot get section: %s"
+msgstr "セクションを取得できません: %s"
+
+#: src/readelf.c:703 src/readelf.c:1329 src/readelf.c:1537 src/readelf.c:13443
+#: src/unstrip.c:396 src/unstrip.c:427 src/unstrip.c:490 src/unstrip.c:622
+#: src/unstrip.c:640 src/unstrip.c:680 src/unstrip.c:897 src/unstrip.c:1263
+#: src/unstrip.c:1390 src/unstrip.c:1414 src/unstrip.c:1470 src/unstrip.c:1511
+#: src/unstrip.c:1703 src/unstrip.c:1854 src/unstrip.c:1998 src/unstrip.c:2106
+#, c-format
+msgid "cannot get section header: %s"
+msgstr "セクションヘッダーを取得できません: %s"
+
+#: src/readelf.c:711
+#, c-format
+msgid "cannot get section name"
+msgstr "セクション名を取得できません"
+
+#: src/readelf.c:720 src/readelf.c:7177 src/readelf.c:11231 src/readelf.c:11333
+#: src/readelf.c:11517
+#, c-format
+msgid "cannot get %s content: %s"
+msgstr "%s の内容を取得できません: %s"
+
+#: src/readelf.c:736
+#, c-format
+msgid "cannot create temp file '%s'"
+msgstr "一時ファイル '%s' を作成できません"
+
+#: src/readelf.c:745
+#, c-format
+msgid "cannot write section data"
+msgstr "セクションデータを書き込みできません"
+
+#: src/readelf.c:751 src/readelf.c:768 src/readelf.c:797
+#, c-format
+msgid "error while closing Elf descriptor: %s"
+msgstr "Elf 記述子を閉じている時にエラー: %s"
+
+#: src/readelf.c:758
+#, c-format
+msgid "error while rewinding file descriptor"
+msgstr "ファイル記述子を巻き戻している時にエラー"
+
+#: src/readelf.c:792
+#, c-format
+msgid "'%s' is not an archive, cannot print archive index"
+msgstr "'%s' はアーカイブではなく、アーカイブ索引を表示できません"
+
+#: src/readelf.c:896
+#, c-format
+msgid "cannot stat input file"
+msgstr "入力ファイルを stat できません"
+
+#: src/readelf.c:898
+#, c-format
+msgid "input file is empty"
+msgstr "入力ファイルが空です"
+
+#: src/readelf.c:900
+#, c-format
+msgid "failed reading '%s': %s"
+msgstr "'%s' の読込みに失敗: %s"
+
+#: src/readelf.c:929
+#, fuzzy, c-format
+msgid "No such section '%s' in '%s'"
+msgstr "セクション [%Zu] '%s' からデータが得られません: %s"
+
+#: src/readelf.c:988
+#, c-format
+msgid "cannot read ELF header: %s"
+msgstr "ELF ヘッダーを読み込めません: %s"
+
+#: src/readelf.c:996
+#, c-format
+msgid "cannot create EBL handle"
+msgstr "EBL ハンドルを作成できません"
+
+#: src/readelf.c:1007
+#, c-format
+msgid "cannot determine number of program headers: %s"
+msgstr "プログラムヘッダの数を決定できません: %s"
+
+#: src/readelf.c:1039
+#, c-format
+msgid "cannot read ELF: %s"
+msgstr "ELFを読み込めません: %s"
+
+#: src/readelf.c:1072
+#, fuzzy
+#| msgid "cannot get section: %s"
+msgid "cannot find section"
+msgstr "セクションを取得できません: %s"
+
+#: src/readelf.c:1109
+msgid "NONE (None)"
+msgstr "なし (なし)"
+
+#: src/readelf.c:1110
+msgid "REL (Relocatable file)"
+msgstr "REL (リロケータブルファイル)"
+
+#: src/readelf.c:1111
+msgid "EXEC (Executable file)"
+msgstr "(EXEC (実行ファイル)"
+
+#: src/readelf.c:1112
+msgid "DYN (Shared object file)"
+msgstr "DYN (共用オブジェクトファイル)"
+
+#: src/readelf.c:1113
+msgid "CORE (Core file)"
+msgstr "CORE (コアファイル)"
+
+#: src/readelf.c:1118
+#, c-format
+msgid "OS Specific: (%x)\n"
+msgstr "OS 固有: (%x)\n"
+
+#. && e_type <= ET_HIPROC always true
+#: src/readelf.c:1120
+#, c-format
+msgid "Processor Specific: (%x)\n"
+msgstr "プロセッサー固有: (%x)\n"
+
+#: src/readelf.c:1130
+msgid ""
+"ELF Header:\n"
+"  Magic:  "
+msgstr ""
+"ELF ヘッダー:\n"
+" マジック: "
+
+#: src/readelf.c:1134
+#, c-format
+msgid ""
+"\n"
+"  Class:                             %s\n"
+msgstr ""
+"\n"
+"  クラス:                            %s\n"
+
+#: src/readelf.c:1139
+#, c-format
+msgid "  Data:                              %s\n"
+msgstr "  データ:                            %s\n"
+
+#: src/readelf.c:1145
+#, c-format
+msgid "  Ident Version:                     %hhd %s\n"
+msgstr "  識別バージョン:                    %hhd %s\n"
+
+#: src/readelf.c:1147 src/readelf.c:1169
+msgid "(current)"
+msgstr "(現在)"
+
+#: src/readelf.c:1151
+#, c-format
+msgid "  OS/ABI:                            %s\n"
+msgstr "  OS/ABI:                            %s\n"
+
+#: src/readelf.c:1154
+#, c-format
+msgid "  ABI Version:                       %hhd\n"
+msgstr "  ABI バージョン:                    %hhd\n"
+
+#: src/readelf.c:1157
+msgid "  Type:                              "
+msgstr "  タイプ:                            "
+
+#: src/readelf.c:1162
+#, c-format
+msgid "  Machine:                           %s\n"
+msgstr "  マシン :                           %s\n"
+
+#: src/readelf.c:1164
+#, fuzzy, c-format
+msgid "  Machine:                           <unknown>: 0x%x\n"
+msgstr "  マシン :                           %s\n"
+
+#: src/readelf.c:1167
+#, c-format
+msgid "  Version:                           %d %s\n"
+msgstr "  バージョン:                        %d %s\n"
+
+#: src/readelf.c:1171
+#, c-format
+msgid "  Entry point address:               %#<PRIx64>\n"
+msgstr "  入口点アドレス     :               %#<PRIx64>\n"
+
+#: src/readelf.c:1174
+#, c-format
+msgid "  Start of program headers:          %<PRId64> %s\n"
+msgstr "  プログラムヘッダーの開始:          %<PRId64> %s\n"
+
+#: src/readelf.c:1175 src/readelf.c:1178
+msgid "(bytes into file)"
+msgstr "(ファイルへのバイト数)"
+
+#: src/readelf.c:1177
+#, c-format
+msgid "  Start of section headers:          %<PRId64> %s\n"
+msgstr "  セクションヘッダーの開始:          %<PRId64> %s\n"
+
+#: src/readelf.c:1180
+#, c-format
+msgid "  Flags:                             %s\n"
+msgstr "  フラグ:                            %s\n"
+
+#: src/readelf.c:1183
+#, c-format
+msgid "  Size of this header:               %<PRId16> %s\n"
+msgstr "  このヘッダーの大きさ:              %<PRId16> %s\n"
+
+#: src/readelf.c:1184 src/readelf.c:1187 src/readelf.c:1204
+msgid "(bytes)"
+msgstr "(バイト)"
+
+#: src/readelf.c:1186
+#, c-format
+msgid "  Size of program header entries:    %<PRId16> %s\n"
+msgstr "  プログラムヘッダー項目の大きさ:%<PRId16> %s\n"
+
+#: src/readelf.c:1189
+#, fuzzy, c-format
+msgid "  Number of program headers entries: %<PRId16>"
+msgstr "  プログラムヘッダー項目の数 : %<PRId16>\n"
+
+#: src/readelf.c:1196
+#, fuzzy, c-format
+msgid " (%<PRIu32> in [0].sh_info)"
+msgstr "([0].sh_link の %<PRIu32>)"
+
+#: src/readelf.c:1199 src/readelf.c:1216 src/readelf.c:1230
+msgid " ([0] not available)"
+msgstr "([0]は使えません)"
+
+#: src/readelf.c:1203
+#, c-format
+msgid "  Size of section header entries:    %<PRId16> %s\n"
+msgstr "  セクションヘッダー項目の大きさ:%<PRId16> %s\n"
+
+#: src/readelf.c:1206
+#, c-format
+msgid "  Number of section headers entries: %<PRId16>"
+msgstr "  セクションヘッダー項目の数 : %<PRId16>"
+
+#: src/readelf.c:1213
+#, c-format
+msgid " (%<PRIu32> in [0].sh_size)"
+msgstr " ([0].sh_size の %<PRIu32>)"
+
+#. We managed to get the zeroth section.
+#: src/readelf.c:1226
+#, c-format
+msgid " (%<PRIu32> in [0].sh_link)"
+msgstr "([0].sh_link の %<PRIu32>)"
+
+#: src/readelf.c:1234
+#, c-format
+msgid ""
+"  Section header string table index: XINDEX%s\n"
+"\n"
+msgstr ""
+"  セクションヘッダー文字列テーブル索引: XINDEX%s\n"
+"\n"
+
+#: src/readelf.c:1238
+#, c-format
+msgid ""
+"  Section header string table index: %<PRId16>\n"
+"\n"
+msgstr ""
+"  セクションヘッダー文字列テーブル索引: %<PRId16>\n"
+"\n"
+
+#: src/readelf.c:1288 src/readelf.c:1496
+#, fuzzy, c-format
+msgid "cannot get number of sections: %s"
+msgstr "セクション数を決定できません: %s"
+
+#: src/readelf.c:1291
+#, fuzzy, c-format
+msgid ""
+"There are %zd section headers, starting at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"オフセット %2$#<PRIx64> から始まる %1$d 個のセクションヘッダーがあります:\n"
+"\n"
+
+#: src/readelf.c:1299
+#, fuzzy, c-format
+msgid "cannot get section header string table index: %s"
+msgstr "セクションヘッダー文字列テーブル索引が得られません"
+
+#: src/readelf.c:1302
+msgid "Section Headers:"
+msgstr "セクションヘッダー:"
+
+#: src/readelf.c:1305
+msgid ""
+"[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk "
+"Inf Al"
+msgstr ""
+"[番] 名前                 タイプ       アドレス オフセ 大きさ ES フラグLk "
+"Inf Al"
+
+#: src/readelf.c:1307
+msgid ""
+"[Nr] Name                 Type         Addr             Off      Size     ES "
+"Flags Lk Inf Al"
+msgstr ""
+"[番] 名前                 タイプ       アドレス         オフセ   大きさ   ES "
+"フラグLk Inf Al"
+
+#: src/readelf.c:1312
+msgid "     [Compression  Size   Al]"
+msgstr ""
+
+#: src/readelf.c:1314
+msgid "     [Compression  Size     Al]"
+msgstr ""
+
+#: src/readelf.c:1392
+#, fuzzy, c-format
+msgid "bad compression header for section %zd: %s"
+msgstr "セクションヘッダー文字列セクションを生成できません: %s"
+
+#: src/readelf.c:1403
+#, fuzzy, c-format
+msgid "bad gnu compressed size for section %zd: %s"
+msgstr "セクションからデータを得られません %d: %s"
+
+#: src/readelf.c:1421
+msgid "Program Headers:"
+msgstr "プログラムヘッダー:"
+
+#: src/readelf.c:1423
+msgid ""
+"  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"
+msgstr ""
+"  タイプ         オフセ   仮アドレス 物アドレス ファイ量 メモ量   Flg 調整 "
+
+#: src/readelf.c:1426
+msgid ""
+"  Type           Offset   VirtAddr           PhysAddr           FileSiz  "
+"MemSiz   Flg Align"
+msgstr ""
+"  タイプ         オフセ   仮想アドレス       物理アドレス      ファイル量メモ"
+"量   Flg 調整 "
+
+#: src/readelf.c:1483
+#, c-format
+msgid "\t[Requesting program interpreter: %s]\n"
+msgstr "\t[プログラム割込みを要求: %s]\n"
+
+#: src/readelf.c:1508
+msgid ""
+"\n"
+" Section to Segment mapping:\n"
+"  Segment Sections..."
+msgstr ""
+"\n"
+" セクションからセグメントへのマッビング:\n"
+"  セグメント セクション..."
+
+#: src/readelf.c:1519 src/unstrip.c:2165 src/unstrip.c:2207 src/unstrip.c:2214
+#, c-format
+msgid "cannot get program header: %s"
+msgstr "プログラムヘッダーを得られません: %s"
+
+#: src/readelf.c:1663
+#, c-format
+msgid ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"署名 '%3$s' を持つ COMDAT セクショングループ [%1$2zu] '%2$s' には %4$zu 個の"
+"項目があります:\n"
+
+#: src/readelf.c:1668
+#, c-format
+msgid ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"署名 '%3$s' を持つセクショングループ [%1$2zu] '%2$s' には %4$zu 個の項目があ"
+"ります:\n"
+
+#: src/readelf.c:1676
+msgid "<INVALID SYMBOL>"
+msgstr "<不当なシンボル>"
+
+#: src/readelf.c:1690
+msgid "<INVALID SECTION>"
+msgstr "<不当なセクション>"
+
+#: src/readelf.c:1713 src/readelf.c:2614 src/readelf.c:3913 src/readelf.c:4213
+#: src/readelf.c:13315 src/readelf.c:13322 src/readelf.c:13366
+#: src/readelf.c:13373
+msgid "Couldn't uncompress section"
+msgstr ""
+
+#: src/readelf.c:1717 src/readelf.c:2619 src/readelf.c:3917
+#, fuzzy, c-format
+msgid "cannot get section [%zd] header: %s"
+msgstr "セクションヘッダーを得られません: %s"
+
+#: src/readelf.c:1886 src/readelf.c:2860 src/readelf.c:3146 src/readelf.c:3221
+#: src/readelf.c:3524 src/readelf.c:3598 src/readelf.c:5963
+#, fuzzy, c-format
+msgid "invalid sh_link value in section %zu"
+msgstr "不当な .debug_line セクション"
+
+#: src/readelf.c:1889
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"動的セグメントには %lu 個の項目があります:\n"
+" アドレス: %#0*<PRIx64>  オフセット: %#08<PRIx64>  セクションへのリンク: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:1902
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "Dynamic segment contains %lu entry:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+#| msgid_plural ""
+#| "\n"
+#| "Dynamic segment contains %lu entries:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgstr[0] ""
+"\n"
+"動的セグメントには %lu 個の項目があります:\n"
+" アドレス: %#0*<PRIx64>  オフセット: %#08<PRIx64>  セクションへのリンク: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:1912
+msgid "  Type              Value\n"
+msgstr "  タイプ            値\n"
+
+#: src/readelf.c:1921
+#, fuzzy
+#| msgid "cannot get string section data: %s"
+msgid "cannot get string table by using dynamic segment"
+msgstr "文字列セクションデータを取得できません: %s"
+
+#: src/readelf.c:1960
+#, c-format
+msgid "Shared library: [%s]\n"
+msgstr "共用ライブラリー: [%s]\n"
+
+#: src/readelf.c:1964
+#, c-format
+msgid "Library soname: [%s]\n"
+msgstr "ライブラリー so 名: [%s]\n"
+
+#: src/readelf.c:1968
+#, c-format
+msgid "Library rpath: [%s]\n"
+msgstr "ライブラリー rパス: [%s]\n"
+
+#: src/readelf.c:1972
+#, c-format
+msgid "Library runpath: [%s]\n"
+msgstr "ライブラリー run パス: [%s]\n"
+
+#: src/readelf.c:1993
+#, c-format
+msgid "%<PRId64> (bytes)\n"
+msgstr "%<PRId64> (バイト)\n"
+
+#: src/readelf.c:2109 src/readelf.c:2298
+#, c-format
+msgid ""
+"\n"
+"Invalid symbol table at offset %#0<PRIx64>\n"
+msgstr ""
+"\n"
+"オフセット %#0<PRIx64> に不当なシンボルテーブル\n"
+
+#: src/readelf.c:2126 src/readelf.c:2315
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"オフセット %5$#0<PRIx64> のセクション [%3$2u] '%4$s' 用のリロケーションセク"
+"ション [%1$2zu] '%2$s' には %6$d 個の項目があります:\n"
+
+#. The .rel.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. The .rela.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. A .relr.dyn section does not refer to a specific section.
+#: src/readelf.c:2141 src/readelf.c:2330 src/readelf.c:2485
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"オフセット %3$#0<PRIx64> のリロケーションセクション [%1$2u] '%2$s' には %4$d "
+"個の項目があります:\n"
+
+#: src/readelf.c:2151
+msgid "  Offset      Type                 Value       Name\n"
+msgstr "  オフセット  タイプ               値          名前\n"
+
+#: src/readelf.c:2153
+msgid "  Offset              Type                 Value               Name\n"
+msgstr "  オフセット          タイプ               値                  名前\n"
+
+#: src/readelf.c:2206 src/readelf.c:2217 src/readelf.c:2230 src/readelf.c:2251
+#: src/readelf.c:2263 src/readelf.c:2396 src/readelf.c:2408 src/readelf.c:2422
+#: src/readelf.c:2444 src/readelf.c:2457
+msgid "<INVALID RELOC>"
+msgstr "<不当なRELOC>"
+
+#: src/readelf.c:2340
+msgid "  Offset      Type            Value       Addend Name\n"
+msgstr "  オフセット  タイプ          値          付加名\n"
+
+#: src/readelf.c:2342
+msgid "  Offset              Type            Value               Addend Name\n"
+msgstr "  オフセット          タイプ          値                  付加名\n"
+
+#: src/readelf.c:2654
+#, c-format
+msgid "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+msgstr "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+
+#: src/readelf.c:2750
+#, c-format
+msgid "bad dynamic symbol"
+msgstr "不正な動的シンボル"
+
+#: src/readelf.c:2868
+#, c-format
+msgid ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entry:\n"
+msgid_plural ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entries:\n"
+msgstr[0] ""
+"\n"
+"シンボルテーブル [%2u] '%s' には %u 個の項目があります:\n"
+
+#: src/readelf.c:2873
+#, c-format
+msgid " %lu local symbol  String table: [%2u] '%s'\n"
+msgid_plural " %lu local symbols  String table: [%2u] '%s'\n"
+msgstr[0] " %lu ローカルシンボル文字列テーブル: [%2u] '%s'\n"
+
+#: src/readelf.c:2881
+msgid "  Num:    Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  数 :    値      大き タイプ  Bind   Vis          Ndx 名前\n"
+
+#: src/readelf.c:2883
+msgid "  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  数 :            値      大き タイプ  Bind   Vis          Ndx 名前\n"
+
+#: src/readelf.c:3002
+msgid "Dynamic symbol information is not available for displaying symbols."
+msgstr ""
+
+#: src/readelf.c:3102
+msgid "none"
+msgstr "なし"
+
+#: src/readelf.c:3119
+msgid "| <unknown>"
+msgstr "| <不明>"
+
+#: src/readelf.c:3149
+#, c-format
+msgid ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"セクション [%2u] '%s' を必要とするバージョンには %d 個の項目があります:\n"
+" アドレス: %#0*<PRIx64>  オフセット: %#08<PRIx64>  セクションへのリンク: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:3170
+#, c-format
+msgid "  %#06x: Version: %hu  File: %s  Cnt: %hu\n"
+msgstr "  %#06x: バージョン: %hu  ファイル: %s  数: %hu\n"
+
+#: src/readelf.c:3183
+#, c-format
+msgid "  %#06x: Name: %s  Flags: %s  Version: %hu\n"
+msgstr "  %#06x: 名前: %s  フラグ: %s  バージョン: %hu\n"
+
+#: src/readelf.c:3225
+#, c-format
+msgid ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"バージョン定義セクション [%2u] '%s' には %d 個の項目があります:\n"
+" アドレス: %#0*<PRIx64>  オフセット: %#08<PRIx64>  セクションへのリンク: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:3253
+#, c-format
+msgid "  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"
+msgstr "  %#06x: バージョン: %hd  フラグ: %s  索引: %hd  数: %hd  名前: %s\n"
+
+#: src/readelf.c:3268
+#, c-format
+msgid "  %#06x: Parent %d: %s\n"
+msgstr "  %#06x: 親 %d: %s\n"
+
+#. Print the header.
+#: src/readelf.c:3528
+#, c-format
+msgid ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgid_plural ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgstr[0] ""
+"\n"
+"バージョンシンボルセクション [%2u] '%s' には %d 個の項目があります:\n"
+" アドレス: %#0*<PRIx64>  オフセット: %#08<PRIx64>  セクションへのリンク: "
+"[%2u] '%s'"
+
+#: src/readelf.c:3556
+msgid "   0 *local*                     "
+msgstr "   0 *ローカル*                  "
+
+#: src/readelf.c:3561
+msgid "   1 *global*                    "
+msgstr "   1 *グローバル*                "
+
+#: src/readelf.c:3603
+#, c-format
+msgid ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"bucket):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"buckets):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"セクション [%2u] '%s' のバケット一覧の長さの柱状図(合計 %d バケット):\n"
+" アドレス: %#0*<PRIx64>  オフセット: %#08<PRIx64>  セクションへのリンク: "
+"[%2u] '%s'\n"
+
+#: src/readelf.c:3625
+#, fuzzy, no-c-format
+msgid " Length  Number  % of total  Coverage\n"
+msgstr " 長さ    数      全体の%     範囲    \n"
+
+#: src/readelf.c:3627
+#, c-format
+msgid "      0  %6<PRIu32>      %5.1f%%\n"
+msgstr "      0  %6<PRIu32>      %5.1f%%\n"
+
+#: src/readelf.c:3634
+#, c-format
+msgid "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+msgstr "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+
+#: src/readelf.c:3648
+#, fuzzy, c-format
+msgid ""
+" Average number of tests:   successful lookup: %f\n"
+"\t\t\t  unsuccessful lookup: %f\n"
+msgstr ""
+" テストの平均数: 検索成功: %f\n"
+"                 検索失敗: %f\n"
+
+#: src/readelf.c:3666 src/readelf.c:3730 src/readelf.c:3796
+#, c-format
+msgid "cannot get data for section %d: %s"
+msgstr "セクションからデータを得られません %d: %s"
+
+#: src/readelf.c:3674
+#, fuzzy, c-format
+msgid "invalid data in sysv.hash section %d"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/readelf.c:3703
+#, fuzzy, c-format
+msgid "invalid chain in sysv.hash section %d"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/readelf.c:3738
+#, fuzzy, c-format
+msgid "invalid data in sysv.hash64 section %d"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/readelf.c:3769
+#, fuzzy, c-format
+msgid "invalid chain in sysv.hash64 section %d"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/readelf.c:3805
+#, fuzzy, c-format
+msgid "invalid data in gnu.hash section %d"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/readelf.c:3871
+#, c-format
+msgid ""
+" Symbol Bias: %u\n"
+" Bitmask Size: %zu bytes  %<PRIuFAST32>%% bits set  2nd hash shift: %u\n"
+msgstr ""
+" シンボルの偏り: %u\n"
+" ビットマスクの大きさ: %zu バイト  %<PRIuFAST32>%% ビット設定 第2ハッシュシフ"
+"ト: %u\n"
+
+#: src/readelf.c:3956
+#, c-format
+msgid ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"オフセット %3$#0<PRIx64> のライブラリー一覧セクション [%1$2zu] '%2$s' には "
+"%4$d 個の項目があります:\n"
+
+#: src/readelf.c:3970
+msgid ""
+"       Library                       Time Stamp          Checksum Version "
+"Flags"
+msgstr ""
+"       ライブラリー                  タイムスタンプ      チェックサム バー"
+"ジョン フラグ"
+
+#: src/readelf.c:4030
+#, c-format
+msgid ""
+"\n"
+"Object attributes section [%2zu] '%s' of %<PRIu64> bytes at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %4$#0<PRIx64> の %3$<PRIu64> バイトのオブジェクト属性セクション "
+"[%1$2zu] '%2$s':\n"
+
+#: src/readelf.c:4047
+msgid "  Owner          Size\n"
+msgstr "  所有者         大きさ\n"
+
+#: src/readelf.c:4071
+#, c-format
+msgid "  %-13s  %4<PRIu32>\n"
+msgstr "  %-13s  %4<PRIu32>\n"
+
+#. Unknown subsection, print and skip.
+#: src/readelf.c:4110
+#, c-format
+msgid "    %-4u %12<PRIu32>\n"
+msgstr "    %-4u %12<PRIu32>\n"
+
+#. Tag_File
+#: src/readelf.c:4115
+#, c-format
+msgid "    File: %11<PRIu32>\n"
+msgstr "    ファイル: %11<PRIu32>\n"
+
+#: src/readelf.c:4165
+#, c-format
+msgid "      %s: %<PRId64>, %s\n"
+msgstr "      %s: %<PRId64>、%s\n"
+
+#: src/readelf.c:4168
+#, c-format
+msgid "      %s: %<PRId64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:4171
+#, c-format
+msgid "      %s: %s\n"
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:4181
+#, c-format
+msgid "      %u: %<PRId64>\n"
+msgstr "      %u: %<PRId64>\n"
+
+#: src/readelf.c:4184
+#, c-format
+msgid "      %u: %s\n"
+msgstr "      %u: %s\n"
+
+#: src/readelf.c:4222
+#, fuzzy
+#| msgid "couldn't get shdr for group section: %s"
+msgid "Couldn't get data from section"
+msgstr "グループセクションに対する shdr を取得できませんでした: %s"
+
+#: src/readelf.c:4287
+msgid "sprintf failure"
+msgstr ""
+
+#: src/readelf.c:4771
+msgid "empty block"
+msgstr "空ブロック"
+
+#: src/readelf.c:4774
+#, c-format
+msgid "%zu byte block:"
+msgstr "%zu バイトのブロック:"
+
+#: src/readelf.c:5252
+#, fuzzy, c-format
+msgid "%*s[%2<PRIuMAX>] %s  <TRUNCATED>\n"
+msgstr "%*s[%4<PRIuMAX>] %s  <TRUNCATED>\n"
+
+#: src/readelf.c:5424
+#, c-format
+msgid "%s %#<PRIx64> used with different address sizes"
+msgstr ""
+
+#: src/readelf.c:5431
+#, c-format
+msgid "%s %#<PRIx64> used with different offset sizes"
+msgstr ""
+
+#: src/readelf.c:5438
+#, c-format
+msgid "%s %#<PRIx64> used with different base addresses"
+msgstr ""
+
+#: src/readelf.c:5445
+#, c-format
+msgid "%s %#<PRIx64> used with different attribute %s and %s"
+msgstr ""
+
+#: src/readelf.c:5545
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"
+msgstr ""
+
+#: src/readelf.c:5553
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE> ... %<PRIu64> bytes ...\n"
+msgstr ""
+
+#: src/readelf.c:5659
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [ Code]\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s':\n"
+" [ コード]\n"
+
+#: src/readelf.c:5667
+#, c-format
+msgid ""
+"\n"
+"Abbreviation section at offset %<PRIu64>:\n"
+msgstr ""
+"\n"
+"オフセット %<PRIu64> の略語セクション:\n"
+
+#: src/readelf.c:5680
+#, c-format
+msgid " *** error while reading abbreviation: %s\n"
+msgstr " *** 略語を読んでいる間にエラー: %s\n"
+
+#: src/readelf.c:5696
+#, c-format
+msgid " [%5u] offset: %<PRId64>, children: %s, tag: %s\n"
+msgstr " [%5u] オフセット: %<PRId64>、子: %s、タグ: %s\n"
+
+#: src/readelf.c:5733 src/readelf.c:6026 src/readelf.c:6197 src/readelf.c:6568
+#: src/readelf.c:7194 src/readelf.c:8963 src/readelf.c:9705 src/readelf.c:10173
+#: src/readelf.c:10428 src/readelf.c:10590 src/readelf.c:10971
+#: src/readelf.c:11042
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s':\n"
+
+#: src/readelf.c:5836 src/readelf.c:5860 src/readelf.c:6233 src/readelf.c:9741
+#, fuzzy, c-format
+msgid " Length:         %8<PRIu64>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:5838 src/readelf.c:5875 src/readelf.c:6246 src/readelf.c:9754
+#, fuzzy, c-format
+msgid " DWARF version:  %8<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:5839 src/readelf.c:5884 src/readelf.c:6255 src/readelf.c:9763
+#, fuzzy, c-format
+msgid " Address size:   %8<PRIu64>\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:5841 src/readelf.c:5894 src/readelf.c:6265 src/readelf.c:9773
+#, fuzzy, c-format
+msgid " Segment size:   %8<PRIu64>\n"
+msgstr " ファイルを %<PRIu64> に設定する\n"
+
+#: src/readelf.c:5879 src/readelf.c:6250 src/readelf.c:9758 src/readelf.c:11164
+#, fuzzy, c-format
+msgid "Unknown version"
+msgstr "不明なバージョン"
+
+#: src/readelf.c:5889 src/readelf.c:6096 src/readelf.c:6260 src/readelf.c:9768
+#, fuzzy, c-format
+msgid "unsupported address size"
+msgstr "アドレス値ではありません"
+
+#: src/readelf.c:5900 src/readelf.c:6107 src/readelf.c:6270 src/readelf.c:9778
+#, c-format
+msgid "unsupported segment size"
+msgstr ""
+
+#: src/readelf.c:5953
+#, c-format
+msgid "cannot get .debug_aranges content: %s"
+msgstr ".debug_aragnes の内容を得られません: %s"
+
+#: src/readelf.c:5968
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s' には %4$zu 個の項"
+"目があります:\n"
+
+#: src/readelf.c:5999
+#, c-format
+msgid " [%*zu] ???\n"
+msgstr " [%*zu] ???\n"
+
+#: src/readelf.c:6001
+#, c-format
+msgid ""
+" [%*zu] start: %0#*<PRIx64>, length: %5<PRIu64>, CU DIE offset: %6<PRId64>\n"
+msgstr ""
+" [%*zu] 開始: %0#*<PRIx64>、長さ: %5<PRIu64>、CU DIE オフセット: %6<PRId64>\n"
+
+#: src/readelf.c:6039 src/readelf.c:8982
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Table at offset %zu:\n"
+msgstr ""
+"\n"
+"オフセット %Zu のテーブル:\n"
+
+#: src/readelf.c:6043 src/readelf.c:6214 src/readelf.c:7218 src/readelf.c:8993
+#: src/readelf.c:9722
+#, c-format
+msgid "invalid data in section [%zu] '%s'"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/readelf.c:6059
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Length:        %6<PRIu64>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:6071
+#, fuzzy, c-format
+msgid " DWARF version: %6<PRIuFAST16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:6075
+#, c-format
+msgid "unsupported aranges version"
+msgstr ""
+
+#: src/readelf.c:6086
+#, fuzzy, c-format
+msgid " CU offset:     %6<PRIx64>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:6092
+#, fuzzy, c-format
+msgid " Address size:  %6<PRIu64>\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:6103
+#, fuzzy, c-format
+msgid ""
+" Segment size:  %6<PRIu64>\n"
+"\n"
+msgstr " ファイルを %<PRIu64> に設定する\n"
+
+#: src/readelf.c:6158
+#, c-format
+msgid "   %zu padding bytes\n"
+msgstr ""
+
+#: src/readelf.c:6220 src/readelf.c:9728
+#, fuzzy, c-format
+msgid ""
+"Table at Offset 0x%<PRIx64>:\n"
+"\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:6275 src/readelf.c:9783
+#, fuzzy, c-format
+msgid " Offset entries: %8<PRIu64>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:6291 src/readelf.c:9799
+#, c-format
+msgid " Unknown CU base: "
+msgstr ""
+
+#: src/readelf.c:6293 src/readelf.c:9801
+#, c-format
+msgid " CU [%6<PRIx64>] base: "
+msgstr ""
+
+#: src/readelf.c:6299 src/readelf.c:9807
+#, c-format
+msgid " Not associated with a CU.\n"
+msgstr ""
+
+#: src/readelf.c:6310 src/readelf.c:9818
+#, c-format
+msgid "too many offset entries for unit length"
+msgstr ""
+
+#: src/readelf.c:6314 src/readelf.c:9822
+#, fuzzy, c-format
+msgid "  Offsets starting at 0x%<PRIx64>:\n"
+msgstr "  所有者         大きさ\n"
+
+#: src/readelf.c:6366
+#, fuzzy, c-format
+msgid "invalid range list data"
+msgstr "不当なデータ"
+
+#: src/readelf.c:6551 src/readelf.c:10157
+#, c-format
+msgid ""
+"   %zu padding bytes\n"
+"\n"
+msgstr ""
+
+#: src/readelf.c:6599 src/readelf.c:10206
+#, c-format
+msgid ""
+"\n"
+" Unknown CU base: "
+msgstr ""
+
+#: src/readelf.c:6601 src/readelf.c:10208
+#, c-format
+msgid ""
+"\n"
+" CU [%6<PRIx64>] base: "
+msgstr ""
+
+#: src/readelf.c:6610 src/readelf.c:10234 src/readelf.c:10260
+#, c-format
+msgid " [%6tx]  <INVALID DATA>\n"
+msgstr " [%6tx]  <不当なデータ>\n"
+
+#: src/readelf.c:6635 src/readelf.c:10344
+#, fuzzy
+msgid "base address"
+msgstr "アドレスを %s に設定する\n"
+
+#: src/readelf.c:6645 src/readelf.c:10354
+#, fuzzy, c-format
+msgid " [%6tx] empty list\n"
+msgstr ""
+"\n"
+" [%6tx] ゼロ終端\n"
+
+#: src/readelf.c:6909
+#, fuzzy
+msgid "         <INVALID DATA>\n"
+msgstr " [%6tx]  <不当なデータ>\n"
+
+#: src/readelf.c:7166
+#, fuzzy, c-format
+msgid "cannot get ELF: %s"
+msgstr "次の DIE を得られません: %s"
+
+#: src/readelf.c:7190
+#, c-format
+msgid ""
+"\n"
+"Call frame information section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の フレーム情報呼出しセクション [%1$2zu] '%2$s':\n"
+
+#: src/readelf.c:7240
+#, c-format
+msgid ""
+"\n"
+" [%6tx] Zero terminator\n"
+msgstr ""
+"\n"
+" [%6tx] ゼロ終端\n"
+
+#: src/readelf.c:7344 src/readelf.c:7498
+#, fuzzy, c-format
+msgid "invalid augmentation length"
+msgstr "不当な拡大エンコード"
+
+#: src/readelf.c:7359
+msgid "FDE address encoding: "
+msgstr "FDE アドレスエンコード"
+
+#: src/readelf.c:7365
+msgid "LSDA pointer encoding: "
+msgstr "LSDA ポインターエンコード:"
+
+#: src/readelf.c:7475
+#, c-format
+msgid " (offset: %#<PRIx64>)"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:7482
+#, c-format
+msgid " (end offset: %#<PRIx64>)"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:7519
+#, c-format
+msgid "   %-26sLSDA pointer: %#<PRIx64>\n"
+msgstr "   %-26sLSDA ポインター: %#<PRIx64>\n"
+
+#: src/readelf.c:7604
+#, fuzzy, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute code: %s"
+msgstr "属性コードを得られません: %s"
+
+#: src/readelf.c:7614
+#, fuzzy, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute form: %s"
+msgstr "属性様式を得られません: %s"
+
+#: src/readelf.c:7636
+#, fuzzy, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute '%s' (%s) value: %s"
+msgstr "属性値を得られません: %s"
+
+#: src/readelf.c:7966
+#, fuzzy, c-format
+msgid "invalid file (%<PRId64>): %s"
+msgstr "不当なファイル"
+
+#: src/readelf.c:7970
+#, fuzzy, c-format
+msgid "no srcfiles for CU [%<PRIx64>]"
+msgstr " ファイルを %<PRIu64> に設定する\n"
+
+#: src/readelf.c:7974
+#, fuzzy, c-format
+msgid "couldn't get DWARF CU: %s"
+msgstr "次の DIE を得られません: %s"
+
+#: src/readelf.c:8296
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [Offset]\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s':\n"
+" [オフセット]\n"
+
+#: src/readelf.c:8346
+#, fuzzy, c-format
+msgid "cannot get next unit: %s"
+msgstr "次の DIE を得られません: %s"
+
+#: src/readelf.c:8366
+#, fuzzy, c-format
+msgid ""
+" Type unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+" Type signature: %#<PRIx64>, Type offset: %#<PRIx64> [%<PRIx64>]\n"
+msgstr ""
+" オフセット %1$<PRIu64> のコンパイル単位:\n"
+" バージョン: %2$<PRIu16>、略語セクションオフセット: %3$<PRIu64>、アドレスの大"
+"きさ: %4$<PRIu8>、オフセットの大きさ: %5$<PRIu8>\n"
+
+#: src/readelf.c:8378
+#, c-format
+msgid ""
+" Compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+" オフセット %1$<PRIu64> のコンパイル単位:\n"
+" バージョン: %2$<PRIu16>、略語セクションオフセット: %3$<PRIu64>、アドレスの大"
+"きさ: %4$<PRIu8>、オフセットの大きさ: %5$<PRIu8>\n"
+
+#: src/readelf.c:8388 src/readelf.c:8549
+#, c-format
+msgid " Unit type: %s (%<PRIu8>)"
+msgstr ""
+
+#: src/readelf.c:8415
+#, c-format
+msgid "unknown version (%d) or unit type (%d)"
+msgstr ""
+
+#: src/readelf.c:8444
+#, c-format
+msgid "cannot get DIE offset: %s"
+msgstr "DIE オフセットを得られません: %s"
+
+#: src/readelf.c:8453
+#, fuzzy, c-format
+msgid "cannot get tag of DIE at offset [%<PRIx64>] in section '%s': %s"
+msgstr ""
+"セクション '%2$s' 中のオフセット %1$<PRIu64> の DIE のタグを得られません: "
+"%3$s"
+
+#: src/readelf.c:8489
+#, c-format
+msgid "cannot get next DIE: %s\n"
+msgstr "次の DIE を得られません: %s\n"
+
+#: src/readelf.c:8497
+#, c-format
+msgid "cannot get next DIE: %s"
+msgstr "次の DIE を得られません: %s"
+
+#: src/readelf.c:8541
+#, fuzzy, c-format
+msgid ""
+" Split compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+" オフセット %1$<PRIu64> のコンパイル単位:\n"
+" バージョン: %2$<PRIu16>、略語セクションオフセット: %3$<PRIu64>、アドレスの大"
+"きさ: %4$<PRIu8>、オフセットの大きさ: %5$<PRIu8>\n"
+
+#: src/readelf.c:8593
+#, fuzzy, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s':\n"
+
+#: src/readelf.c:8925
+#, fuzzy, c-format
+msgid "unknown form: %s"
+msgstr "不明な様式 %<PRIx64>"
+
+#. Print what we got so far.
+#: src/readelf.c:9073
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Length:                         %<PRIu64>\n"
+" DWARF version:                  %<PRIuFAST16>\n"
+" Prologue length:                %<PRIu64>\n"
+" Address size:                   %zd\n"
+" Segment selector size:          %zd\n"
+" Min instruction length:         %<PRIuFAST8>\n"
+" Max operations per instruction: %<PRIuFAST8>\n"
+" Initial value if 'is_stmt':     %<PRIuFAST8>\n"
+" Line base:                      %<PRIdFAST8>\n"
+" Line range:                     %<PRIuFAST8>\n"
+" Opcode base:                    %<PRIuFAST8>\n"
+"\n"
+"Opcodes:\n"
+msgstr ""
+"\n"
+" 長さ:             %<PRIu64>\n"
+" DWARF バージョン: %<PRIuFAST16>\n"
+" プロローグ長:     %<PRIu64>\n"
+" 最小命令長:       %<PRIuFAST8>\n"
+" もし '%s' なら初期値: %<PRIuFAST8>\n"
+" 行ベース:         %<PRIdFAST8>\n"
+" 行範囲:           %<PRIuFAST8>\n"
+" 命令コードベース: %<PRIuFAST8>\n"
+"\n"
+"命令コード:\n"
+
+#: src/readelf.c:9095
+#, c-format
+msgid "cannot handle .debug_line version: %u\n"
+msgstr ".debug_line バージョンを扱えません: %u\n"
+
+#: src/readelf.c:9103
+#, c-format
+msgid "cannot handle address size: %u\n"
+msgstr "アドレスサイズを扱えません: %u\n"
+
+#: src/readelf.c:9111
+#, c-format
+msgid "cannot handle segment selector size: %u\n"
+msgstr "セグメントセレクタサイズを扱えません: %u\n"
+
+#: src/readelf.c:9121
+#, c-format
+msgid "invalid data at offset %tu in section [%zu] '%s'"
+msgstr "セクション [%2$zu] '%3$s' 中のオフセット %1$tu に不当なデータ"
+
+#: src/readelf.c:9136
+#, c-format
+msgid "  [%*<PRIuFAST8>]  %hhu argument\n"
+msgid_plural "  [%*<PRIuFAST8>]  %hhu arguments\n"
+msgstr[0] "  [%*<PRIuFAST8>]  %hhu パラメーター\n"
+
+#: src/readelf.c:9147
+msgid ""
+"\n"
+"Directory table:"
+msgstr ""
+"\n"
+"ディレクトリーテーブル:"
+
+#: src/readelf.c:9153 src/readelf.c:9230
+#, fuzzy, c-format
+msgid "      ["
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:9224
+#, fuzzy
+msgid ""
+"\n"
+"File name table:"
+msgstr ""
+"\n"
+" 呼出しサイトテーブル:"
+
+#: src/readelf.c:9285
+#, fuzzy
+msgid " Entry Dir   Time      Size      Name"
+msgstr ""
+"\n"
+"ファイル名テーブル:\n"
+" Entry Dir   時刻     大きさ    名前"
+
+#: src/readelf.c:9331
+#, fuzzy
+msgid ""
+"\n"
+"No line number statements."
+msgstr ""
+"\n"
+"行   番号   文:"
+
+#: src/readelf.c:9335
+msgid ""
+"\n"
+"Line number statements:"
+msgstr ""
+"\n"
+"行   番号   文:"
+
+#: src/readelf.c:9350
+#, c-format
+msgid "invalid maximum operations per instruction is zero"
+msgstr ""
+
+#: src/readelf.c:9384
+#, fuzzy, c-format
+msgid " special opcode %u: address+%u = "
+msgstr " 特殊命令コード %u: アドレス+%u = %s, 行%+d = %zu\n"
+
+#: src/readelf.c:9388
+#, fuzzy, c-format
+msgid ", op_index = %u, line%+d = %zu\n"
+msgstr " 特殊命令コード %u: アドレス+%u = %s, 行%+d = %zu\n"
+
+#: src/readelf.c:9391
+#, c-format
+msgid ", line%+d = %zu\n"
+msgstr ""
+
+#: src/readelf.c:9409
+#, c-format
+msgid " extended opcode %u: "
+msgstr " 拡張命令コード %u: "
+
+#: src/readelf.c:9414
+#, fuzzy
+msgid " end of sequence"
+msgstr "列の終わり"
+
+#: src/readelf.c:9432
+#, fuzzy, c-format
+msgid " set address to "
+msgstr "アドレスを %s に設定する\n"
+
+#: src/readelf.c:9460
+#, fuzzy, c-format
+msgid " define new file: dir=%u, mtime=%<PRIu64>, length=%<PRIu64>, name=%s\n"
+msgstr ""
+"新ファイルを定義する: dir=%u、mtime=%<PRIu64>、長さh=%<PRIu64>、名前=%s\n"
+
+#: src/readelf.c:9474
+#, fuzzy, c-format
+msgid " set discriminator to %u\n"
+msgstr "カラムを %<PRIu64> に設定する\n"
+
+#: src/readelf.c:9501
+#, c-format
+msgid " set inlined context %u, function name %s (0x%x)\n"
+msgstr ""
+
+#: src/readelf.c:9525
+#, fuzzy, c-format
+#| msgid "Also show function names"
+msgid " set function name %s (0x%x)\n"
+msgstr "関数名も表示"
+
+#. Unknown, ignore it.
+#: src/readelf.c:9532
+msgid " unknown opcode"
+msgstr "不明なオペコード"
+
+#. Takes no argument.
+#: src/readelf.c:9544
+msgid " copy"
+msgstr "複写"
+
+#: src/readelf.c:9555
+#, fuzzy, c-format
+msgid " advance address by %u to "
+msgstr "アドレスを %u だけ進めて %s にする\n"
+
+#: src/readelf.c:9559 src/readelf.c:9620
+#, c-format
+msgid ", op_index to %u"
+msgstr ""
+
+#: src/readelf.c:9571
+#, c-format
+msgid " advance line by constant %d to %<PRId64>\n"
+msgstr "行を定数 %d だけ進めて %<PRId64> にする\n"
+
+#: src/readelf.c:9581
+#, c-format
+msgid " set file to %<PRIu64>\n"
+msgstr " ファイルを %<PRIu64> に設定する\n"
+
+#: src/readelf.c:9592
+#, c-format
+msgid " set column to %<PRIu64>\n"
+msgstr "カラムを %<PRIu64> に設定する\n"
+
+#: src/readelf.c:9599
+#, c-format
+msgid " set '%s' to %<PRIuFAST8>\n"
+msgstr " '%s' を %<PRIuFAST8> に設定する\n"
+
+#. Takes no argument.
+#: src/readelf.c:9605
+msgid " set basic block flag"
+msgstr "基本ブロックフラグを設定する"
+
+#: src/readelf.c:9616
+#, fuzzy, c-format
+msgid " advance address by constant %u to "
+msgstr "アドレスを定数 %u だけ済めて %s にする\n"
+
+#: src/readelf.c:9636
+#, fuzzy, c-format
+msgid " advance address by fixed value %u to \n"
+msgstr "アドレスを固定値 %u だけ進めて %s にする\n"
+
+#. Takes no argument.
+#: src/readelf.c:9646
+msgid " set prologue end flag"
+msgstr "プロローグ終了フラグを設定する"
+
+#. Takes no argument.
+#: src/readelf.c:9651
+msgid " set epilogue begin flag"
+msgstr "エピローグ開始フラグを設定する"
+
+#: src/readelf.c:9661
+#, fuzzy, c-format
+msgid " set isa to %u\n"
+msgstr " ファイルを %<PRIu64> に設定する\n"
+
+#. This is a new opcode the generator but not we know about.
+#. Read the parameters associated with it but then discard
+#. everything.  Read all the parameters for this opcode.
+#: src/readelf.c:9670
+#, c-format
+msgid " unknown opcode with %<PRIu8> parameter:"
+msgid_plural " unknown opcode with %<PRIu8> parameters:"
+msgstr[0] " %<PRIu8> 個のパラメーターのある不明な命令コード:"
+
+#: src/readelf.c:9871
+#, fuzzy, c-format
+msgid "    <INVALID DATA>\n"
+msgstr " [%6tx]  <不当なデータ>\n"
+
+#: src/readelf.c:9911
+#, fuzzy, c-format
+msgid "invalid loclists data"
+msgstr "不当なデータ"
+
+#: src/readelf.c:10381 src/readelf.c:11426
+#, fuzzy
+msgid "   <INVALID DATA>\n"
+msgstr " [%6tx]  <不当なデータ>\n"
+
+#: src/readelf.c:10512
+#, c-format
+msgid "%*s*** non-terminated string at end of section"
+msgstr "%*s*** 最後のセクションの終端していない文字列"
+
+#: src/readelf.c:10535
+#, fuzzy, c-format
+msgid "%*s*** missing DW_MACINFO_start_file argument at end of section"
+msgstr "%*s*** 最後のセクションの終端していない文字列"
+
+#: src/readelf.c:10630
+#, fuzzy, c-format
+msgid " Offset:             0x%<PRIx64>\n"
+msgstr "  所有者         大きさ\n"
+
+#: src/readelf.c:10642
+#, fuzzy, c-format
+msgid " Version:            %<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:10648 src/readelf.c:11547
+#, c-format
+msgid "  unknown version, cannot parse section\n"
+msgstr ""
+
+#: src/readelf.c:10655
+#, fuzzy, c-format
+msgid " Flag:               0x%<PRIx8>"
+msgstr "  入口点アドレス     :               %#<PRIx64>\n"
+
+#: src/readelf.c:10684
+#, fuzzy, c-format
+msgid " Offset length:      %<PRIu8>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:10692
+#, fuzzy, c-format
+msgid " .debug_line offset: 0x%<PRIx64>\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:10717
+#, fuzzy, c-format
+msgid "  extension opcode table, %<PRIu8> items:\n"
+msgstr " %<PRIu8> 個のパラメーターのある不明な命令コード:"
+
+#: src/readelf.c:10724
+#, c-format
+msgid "    [%<PRIx8>]"
+msgstr ""
+
+#: src/readelf.c:10736
+#, fuzzy, c-format
+msgid " %<PRIu8> arguments:"
+msgstr "  [%*<PRIuFAST8>]  %hhu パラメーター\n"
+
+#: src/readelf.c:10751
+#, c-format
+msgid " no arguments."
+msgstr ""
+
+#: src/readelf.c:10952
+#, c-format
+msgid " [%5d] DIE offset: %6<PRId64>, CU DIE offset: %6<PRId64>, name: %s\n"
+msgstr ""
+" [%5d] DIE オフセット: %6<PRId64>, CU DIE オフセット: %6<PRId64>, 名前: %s\n"
+
+# # "オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s':\n"
+# # " %4$*s  文字列\n" がエラーになるのは何故? 取り敢えず fuzzy扱い
+#: src/readelf.c:11007
+#, fuzzy, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" %*s  String\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s':\n"
+" %4$*s  文字列\n"
+
+#. TRANS: the debugstr| prefix makes the string unique.
+#: src/readelf.c:11012
+msgctxt "debugstr"
+msgid "Offset"
+msgstr ""
+
+#: src/readelf.c:11022
+#, fuzzy, c-format
+msgid " *** error, missing string terminator\n"
+msgstr " *** 文字列の読込み中にエラー: %s\n"
+
+#: src/readelf.c:11144
+#, fuzzy, c-format
+msgid " Length:        %8<PRIu64>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11146
+#, fuzzy, c-format
+msgid " Offset size:   %8<PRIu8>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11160
+#, fuzzy, c-format
+msgid " DWARF version: %8<PRIu16>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11169
+#, fuzzy, c-format
+msgid " Padding:       %8<PRIx16>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11223
+#, c-format
+msgid ""
+"\n"
+"Call frame search table section [%2zu] '.eh_frame_hdr':\n"
+msgstr ""
+"\n"
+"呼出しフレーム検索テーブルセクション [%2zu] '.eh_frame_hdr':\n"
+
+#: src/readelf.c:11325
+#, c-format
+msgid ""
+"\n"
+"Exception handling table section [%2zu] '.gcc_except_table':\n"
+msgstr ""
+"\n"
+"例外取扱いテーブルセクション [%2zu] '.gcc_except_table':\n"
+
+#: src/readelf.c:11348
+#, c-format
+msgid " LPStart encoding:    %#x "
+msgstr " LPStart コード化:    %#x "
+
+#: src/readelf.c:11360
+#, c-format
+msgid " TType encoding:      %#x "
+msgstr "TType コード化:       %#x "
+
+#: src/readelf.c:11377
+#, c-format
+msgid " Call site encoding:  %#x "
+msgstr "呼出しサイトコード化: %#x "
+
+#: src/readelf.c:11392
+msgid ""
+"\n"
+" Call site table:"
+msgstr ""
+"\n"
+" 呼出しサイトテーブル:"
+
+#: src/readelf.c:11408
+#, c-format
+msgid ""
+" [%4u] Call site start:   %#<PRIx64>\n"
+"        Call site length:  %<PRIu64>\n"
+"        Landing pad:       %#<PRIx64>\n"
+"        Action:            %u\n"
+msgstr ""
+" [%4u] 呼出しサイト開始 :  %#<PRIx64>\n"
+"        呼出しサイト長:     %<PRIu64>\n"
+"        離着陸場:           %#<PRIx64>\n"
+"        行動:               %u\n"
+
+#: src/readelf.c:11481
+#, c-format
+msgid "invalid TType encoding"
+msgstr "不当な TType コード化"
+
+#: src/readelf.c:11508
+#, fuzzy, c-format
+msgid ""
+"\n"
+"GDB section [%2zu] '%s' at offset %#<PRIx64> contains %<PRId64> bytes :\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s' には %4$zu 個の項"
+"目があります:\n"
+
+#: src/readelf.c:11537
+#, fuzzy, c-format
+msgid " Version:         %<PRId32>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:11556
+#, fuzzy, c-format
+msgid " CU offset:       %#<PRIx32>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11563
+#, fuzzy, c-format
+msgid " TU offset:       %#<PRIx32>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11570
+#, fuzzy, c-format
+msgid " address offset:  %#<PRIx32>\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11577
+#, fuzzy, c-format
+msgid " symbol offset:   %#<PRIx32>\n"
+msgstr " (オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11587
+#, fuzzy, c-format
+msgid " shortcut offset: %#<PRIx32>\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11595
+#, fuzzy, c-format
+msgid " constant offset: %#<PRIx32>\n"
+msgstr " (終了オフセット: %#<PRIx64>)"
+
+#: src/readelf.c:11609
+#, fuzzy, c-format
+msgid ""
+"\n"
+" CU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s' には %4$zu 個の項"
+"目があります:\n"
+
+#: src/readelf.c:11634
+#, fuzzy, c-format
+msgid ""
+"\n"
+" TU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s' には %4$zu 個の項"
+"目があります:\n"
+
+#: src/readelf.c:11663
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Address list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+"オフセット %3$#<PRIx64> の DWARF セクション [%1$2zu] '%2$s' には %4$zu 個の項"
+"目があります:\n"
+
+#: src/readelf.c:11706
+#, fuzzy, c-format
+msgid ""
+"\n"
+" Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+"オフセット %#0<PRIx64> に不当なシンボルテーブル\n"
+
+#: src/readelf.c:11791
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Shortcut table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+"オフセット %#0<PRIx64> に不当なシンボルテーブル\n"
+
+#: src/readelf.c:11803
+#, c-format
+msgid "Language of main: %s\n"
+msgstr ""
+
+#: src/readelf.c:11804
+#, c-format
+msgid "Name of main: "
+msgstr ""
+
+#: src/readelf.c:11887
+#, c-format
+msgid "cannot get debug context descriptor: %s"
+msgstr "デバッグ内容記述子を得られません: %s"
+
+#: src/readelf.c:12253 src/readelf.c:12873 src/readelf.c:12983
+#: src/readelf.c:13040
+#, c-format
+msgid "cannot convert core note data: %s"
+msgstr "コアノートデータの変換ができません: %s"
+
+#: src/readelf.c:12617
+#, c-format
+msgid ""
+"\n"
+"%*s... <repeats %u more times> ..."
+msgstr ""
+"\n"
+"%*s... < %u 回の繰返し> ..."
+
+#: src/readelf.c:13119
+msgid "  Owner          Data size  Type\n"
+msgstr "  所有者         データ大きさタイプ\n"
+
+#: src/readelf.c:13147
+#, c-format
+msgid "  %-13.*s  %9<PRId32>  %s\n"
+msgstr "  %-13.*s  %9<PRId32>  %s\n"
+
+#: src/readelf.c:13199
+#, c-format
+msgid "cannot get content of note: %s"
+msgstr "ノートセクションの内容を取得できません: %s"
+
+#: src/readelf.c:13232
+#, c-format
+msgid ""
+"\n"
+"Note section [%2zu] '%s' of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %4$#0<PRIx64> の %3$<PRIu64> バイトのノートセクション [%1$2zu] "
+"'%2$s':\n"
+
+#: src/readelf.c:13255
+#, c-format
+msgid ""
+"\n"
+"Note segment of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %2$#0<PRIx64> の %1$<PRIu64> バイトのノートセグメント:\n"
+
+#: src/readelf.c:13302
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no data to dump.\n"
+msgstr ""
+"\n"
+"セクション [%Zu] '%s' にはダンプすべきデータがありません。\n"
+
+#: src/readelf.c:13329 src/readelf.c:13380
+#, fuzzy, c-format
+msgid "cannot get data for section [%zu] '%s': %s"
+msgstr "セクション [%Zu] '%s' からデータが得られません: %s"
+
+#: src/readelf.c:13334
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %4$#0<PRIx64> のセクション [%1$Zu] '%2$s' の16進ダン"
+"プ、%3$<PRIu64> バイト:\n"
+
+#: src/readelf.c:13339
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes (%zd uncompressed) at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %4$#0<PRIx64> のセクション [%1$Zu] '%2$s' の16進ダン"
+"プ、%3$<PRIu64> バイト:\n"
+
+#: src/readelf.c:13353
+#, fuzzy, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no strings to dump.\n"
+msgstr ""
+"\n"
+"セクション [%Zu] '%s' にはダンプすべきデータがありません。\n"
+
+#: src/readelf.c:13385
+#, fuzzy, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %4$#0<PRIx64> 文字列セクション [%1$Zu] '%2$s' には %3$<PRIu64> バ"
+"イトあります:\n"
+
+#: src/readelf.c:13390
+#, fuzzy, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes (%zd uncompressed) at "
+"offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"オフセット %4$#0<PRIx64> 文字列セクション [%1$Zu] '%2$s' には %3$<PRIu64> バ"
+"イトあります:\n"
+
+#: src/readelf.c:13438
+#, c-format
+msgid ""
+"\n"
+"section [%lu] does not exist"
+msgstr ""
+"\n"
+"セクション [%lu] がありません"
+
+#: src/readelf.c:13468
+#, c-format
+msgid ""
+"\n"
+"section '%s' does not exist"
+msgstr ""
+"\n"
+"セクション '%s' がありません"
+
+#: src/readelf.c:13523
+#, c-format
+msgid "cannot get symbol index of archive '%s': %s"
+msgstr "アーカイブのシンボル索引 '%s' を得られません: %s"
+
+#: src/readelf.c:13526
+#, c-format
+msgid ""
+"\n"
+"Archive '%s' has no symbol index\n"
+msgstr ""
+"\n"
+"アーカイブ '%s' にはシンボル索引がありません\n"
+
+#: src/readelf.c:13530
+#, c-format
+msgid ""
+"\n"
+"Index of archive '%s' has %zu entries:\n"
+msgstr ""
+"\n"
+"アーカイブ '%s' の索引は %zu 個の項目を持ちます:\n"
+
+#: src/readelf.c:13548
+#, c-format
+msgid "cannot extract member at offset %zu in '%s': %s"
+msgstr "'%2$s' の オフセット %1$zu のメンバーを抽出できません: %3$s"
+
+#: src/readelf.c:13553
+#, c-format
+msgid "Archive member '%s' contains:\n"
+msgstr "アーカイブメンバー '%s' には以下があります:\n"
+
+#: src/size.c:55
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  The default "
+"is `bsd'"
+msgstr ""
+"出力形式として FORMAT を使ってください。 FORMAT は `bsd'、 `sysv' のどちらか"
+"です。 デフォルトは `bsd'です"
+
+#: src/size.c:57
+msgid "Same as `--format=sysv'"
+msgstr "`--format=sysv' と同じ"
+
+#: src/size.c:58
+msgid "Same as `--format=bsd'"
+msgstr "`--format=bsd' と同じ"
+
+#: src/size.c:61
+msgid "Same as `--radix=10'"
+msgstr "`--radix=10' と同じ"
+
+#: src/size.c:62
+msgid "Same as `--radix=8'"
+msgstr "`--radix=8' と同じ"
+
+#: src/size.c:63
+msgid "Same as `--radix=16'"
+msgstr "`--radix=16' と同じ"
+
+#: src/size.c:65
+msgid "Similar to `--format=sysv' output but in one line"
+msgstr "`--format=sysv' の出力と 似ていますが、 1行です"
+
+#: src/size.c:69
+msgid "Print size and permission flags for loadable segments"
+msgstr "ロード可能セグメント の大きさと 許可フラグの 表示"
+
+#: src/size.c:70
+msgid "Display the total sizes (bsd only)"
+msgstr "合計の大きさを表示 (bsd のみ)"
+
+#. Short description of program.
+#: src/size.c:75
+msgid "List section sizes of FILEs (a.out by default)."
+msgstr "FILE のセクションの 大きさの 一覧表示 (デフォルトでは a.out)"
+
+#: src/size.c:239
+#, c-format
+msgid "Invalid format: %s"
+msgstr "不当な形式: %s"
+
+#: src/size.c:250
+#, c-format
+msgid "Invalid radix: %s"
+msgstr "不当な基数: %s"
+
+#: src/size.c:309
+#, c-format
+msgid "%s: file format not recognized"
+msgstr "%s: ファイル形式を認識できません"
+
+#: src/size.c:327
+msgctxt "bsd"
+msgid "text"
+msgstr ""
+
+#: src/size.c:328
+msgctxt "bsd"
+msgid "data"
+msgstr ""
+
+#: src/size.c:329
+msgctxt "bsd"
+msgid "bss"
+msgstr ""
+
+#: src/size.c:330
+msgctxt "bsd"
+msgid "dec"
+msgstr ""
+
+#: src/size.c:331
+msgctxt "bsd"
+msgid "hex"
+msgstr ""
+
+#: src/size.c:332
+msgctxt "bsd"
+msgid "filename"
+msgstr ""
+
+#: src/size.c:416 src/size.c:557
+#, c-format
+msgid " (ex %s)"
+msgstr " (ex %s)"
+
+#: src/size.c:418
+msgctxt "sysv"
+msgid "section"
+msgstr ""
+
+#: src/size.c:419
+msgctxt "sysv"
+msgid "size"
+msgstr ""
+
+#: src/size.c:420
+msgctxt "sysv"
+msgid "addr"
+msgstr ""
+
+#: src/size.c:449 src/size.c:452 src/size.c:455
+msgctxt "sysv"
+msgid "Total"
+msgstr ""
+
+#: src/size.c:479
+msgid "cannot get section header"
+msgstr "セクションヘッダーを取得できません"
+
+#: src/size.c:582
+msgid "(TOTALS)\n"
+msgstr "(合計)\n"
+
+#: src/stack.c:487
+#, c-format
+msgid "-p PID should be a positive process id."
+msgstr ""
+
+#: src/stack.c:493
+#, c-format
+msgid "Cannot open core file '%s'"
+msgstr "コアファイル'%s' を開くことができません"
+
+#: src/stack.c:553
+#, c-format
+msgid "-n MAXFRAMES should be 0 or higher."
+msgstr ""
+
+#: src/stack.c:565
+#, c-format
+msgid "-e EXEC needs a core given by --core."
+msgstr ""
+
+#: src/stack.c:569
+#, c-format
+msgid "-1 needs a thread id given by -p."
+msgstr ""
+
+#: src/stack.c:573
+#, c-format
+msgid "One of -p PID or --core COREFILE should be given."
+msgstr ""
+
+#: src/stack.c:645
+msgid "Show stack of process PID"
+msgstr "process PID のスタックを表示"
+
+#: src/stack.c:647
+msgid "Show stack found in COREFILE"
+msgstr "COREFILE で見つかったスタックを表示"
+
+#: src/stack.c:648
+msgid "(optional) EXECUTABLE that produced COREFILE"
+msgstr "(optional) COREFILE を生成した EXECUTABLE"
+
+#: src/stack.c:652
+msgid "Output selection options:"
+msgstr "出力選択オプション:"
+
+#: src/stack.c:654
+msgid "Additionally show frame activation"
+msgstr "frame activation を さらに 表示"
+
+#: src/stack.c:656
+msgid "Additionally try to lookup DWARF debuginfo name for frame address"
+msgstr "フレーム アドレスに 対する DWARF debuginfo name の検索を さらに試みる"
+
+#: src/stack.c:659
+msgid ""
+"Additionally show inlined function frames using DWARF debuginfo if available "
+"(implies -d)"
+msgstr ""
+"可能であれば DWARF debuginfo を使って インライン 関数の フレームを表示 (暗黙"
+"的に -d を伴う)"
+
+#: src/stack.c:661
+msgid "Additionally show module file information"
+msgstr "モジュール ファイル情報を さらに 表示"
+
+#: src/stack.c:663
+msgid "Additionally show source file information"
+msgstr "ソース ファイル情報を さらに 表示"
+
+#: src/stack.c:665
+msgid ""
+"Show all additional information (activation, debugname, inlines, module and "
+"source)"
+msgstr ""
+"全ての 追加情報を 表示 (activation, debugname, inlines, module, source)"
+
+#: src/stack.c:667
+msgid "Do not resolve address to function symbol name"
+msgstr "アドレスを 関数シンボル名に 解決しない"
+
+#: src/stack.c:669
+msgid "Show raw function symbol names, do not try to demangle names"
+msgstr "生の 関数シンボル名を 表示し、 デマングルを 試みない"
+
+#: src/stack.c:671
+msgid "Show module build-id, load address and pc offset"
+msgstr "モジュールの ビルド ID、ロードアドレスと PC オフセット を表示"
+
+#: src/stack.c:673
+msgid "Show the backtrace of only one thread"
+msgstr "1つのスレッドだけのバックトレースを表示"
+
+#: src/stack.c:675
+msgid "Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"
+msgstr ""
+
+#: src/stack.c:677
+msgid "Show module memory map with build-id, elf and debug files detected"
+msgstr ""
+"検出された ビルド ID、 elf、 debug ファイル付きで モジュールの メモリマップ"
+"を 表示"
+
+#: src/stack.c:685
+msgid ""
+"Print a stack for each thread in a process or core file.\n"
+"\n"
+"Program exits with return code 0 if all frames were shown without any "
+"errors.  If some frames were shown, but there were some non-fatal errors, "
+"possibly causing an incomplete backtrace, the program exits with return code "
+"1.  If no frames could be shown, or a fatal error occurred the program exits "
+"with return code 2.  If the program was invoked with bad or missing "
+"arguments it will exit with return code 64."
+msgstr ""
+
+#: src/stack.c:760
+#, c-format
+msgid "Couldn't show any frames."
+msgstr "フレームを表示できません"
+
+#: src/strings.c:64
+msgid "Output Selection:"
+msgstr "出力選択:"
+
+#: src/strings.c:65
+msgid "Scan entire file, not only loaded sections"
+msgstr "ロードされる セクションだけ でなく ファイル全体を スキャンする"
+
+#: src/strings.c:67
+msgid "Only NUL-terminated sequences of MIN-LEN characters or more are printed"
+msgstr "ヌル終端された MIN-LEN 文字以上の シーケンス のみを 表示"
+
+#: src/strings.c:68
+msgid ""
+"Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, "
+"{B,L} = 32-bit"
+msgstr ""
+"文字サイズと エンディアンを 選択: s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,"
+"L} = 32-bit"
+
+#: src/strings.c:72
+msgid "Print name of the file before each string."
+msgstr "各文字列の 前に ファイル名を表示"
+
+#: src/strings.c:74
+msgid "Print location of the string in base 8, 10, or 16 respectively."
+msgstr "文字列の 位置を 基数 8、 10、 16 で 各々表示"
+
+#: src/strings.c:75
+msgid "Alias for --radix=o"
+msgstr "--radix=o と同じ"
+
+#. Short description of program.
+#: src/strings.c:82
+msgid "Print the strings of printable characters in files."
+msgstr "ファイル中の表示可能文字からなる文字列を表示する。"
+
+#: src/strings.c:255 src/strings.c:290
+#, c-format
+msgid "invalid value '%s' for %s parameter"
+msgstr ""
+
+#: src/strings.c:300
+msgid "invalid minimum length of matched string size"
+msgstr ""
+
+#: src/strings.c:583
+msgid "lseek failed"
+msgstr ""
+
+#: src/strings.c:600 src/strings.c:664
+msgid "re-mmap failed"
+msgstr ""
+
+#: src/strings.c:637
+msgid "mprotect failed"
+msgstr ""
+
+#: src/strings.c:726
+#, c-format
+msgid "Skipping section %zd '%s' data outside file"
+msgstr ""
+
+#: src/strip.c:70
+msgid "Place stripped output into FILE"
+msgstr "ストリップした 出力を FILE に置く"
+
+#: src/strip.c:71
+msgid "Extract the removed sections into FILE"
+msgstr "抽出して 取り除いた セクションを FILE に置く"
+
+#: src/strip.c:72
+msgid "Embed name FILE instead of -f argument"
+msgstr "-f 引数の 代わりに 名前 FILE を有効にする"
+
+#: src/strip.c:76
+msgid "Remove all debugging symbols"
+msgstr "デバッグ用 シンボルを 全て 取り除く"
+
+#: src/strip.c:80
+msgid "Remove section headers (not recommended)"
+msgstr "セクションヘッダーを 取り除く (非推奨)"
+
+#: src/strip.c:82
+msgid "Copy modified/access timestamps to the output"
+msgstr "修正/アクセス タイムスタンプを 出力へ 複製する"
+
+#: src/strip.c:84
+msgid ""
+"Resolve all trivial relocations between debug sections if the removed "
+"sections are placed in a debug file (only relevant for ET_REL files, "
+"operation is not reversible, needs -f)"
+msgstr ""
+
+#: src/strip.c:86
+msgid ""
+"Similar to --reloc-debug-sections, but resolve all trivial relocations "
+"between debug sections in place.  No other stripping is performed (operation "
+"is not reversible, incompatible with -f, -g, --remove-comment and --remove-"
+"section)"
+msgstr ""
+
+#: src/strip.c:88
+msgid "Remove .comment section"
+msgstr ".comment セクションを取り除く"
+
+#: src/strip.c:89
+msgid ""
+"Remove the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once.  Only non-allocated sections can be removed."
+msgstr ""
+"指定された セクションを 取り除く。 SECTION は 拡張 ワイルド カード パター"
+"ン。 2回以上 与え られても よい。割り当て されない セクション のみ 取り除け"
+"る。"
+
+#: src/strip.c:90
+msgid ""
+"Keep the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once."
+msgstr ""
+"指定された セクションを 保持する。 SECTION は 拡張 ワイルド カード パター"
+"ン。 2回以上 与え られても よい。"
+
+#. Short description of program.
+#: src/strip.c:97
+msgid "Discard symbols from object files."
+msgstr "オブジェクトファイルからシンボルを捨て去る"
+
+#: src/strip.c:245
+msgid "--reloc-debug-sections used without -f"
+msgstr ""
+
+#: src/strip.c:251
+msgid ""
+"--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --"
+"remove-section"
+msgstr ""
+
+#: src/strip.c:265
+msgid "Only one input file allowed together with '-o' and '-f'"
+msgstr "'-o' と '-f' と一緒の場合は入力ファイルは 1 つしか認められません"
+
+#: src/strip.c:287
+#, c-format
+msgid "-f option specified twice"
+msgstr "-f オプションが 2 回指定されています"
+
+#: src/strip.c:296
+#, c-format
+msgid "-F option specified twice"
+msgstr "-F オプションが 2 回指定されています"
+
+#: src/strip.c:359
+#, c-format
+msgid "cannot both keep and remove .comment section"
+msgstr ".comment セクションを保持しつつ取り除くことはできません"
+
+#: src/strip.c:478
+msgid "bad relocation"
+msgstr ""
+
+#: src/strip.c:756 src/strip.c:780
+#, c-format
+msgid "cannot stat input file '%s'"
+msgstr "入力ファイル '%s' を stat できません"
+
+#: src/strip.c:770
+#, c-format
+msgid "while opening '%s'"
+msgstr "'%s' を開いている間"
+
+#: src/strip.c:808
+#, c-format
+msgid "%s: cannot use -o or -f when stripping archive"
+msgstr "%s: アーカイブから抜き出している時は -o や -f は使えません"
+
+#. We would like to support ar archives, but currently it just
+#. doesn't work at all since we call elf_clone on the members
+#. which doesn't really support ar members.
+#. result = handle_ar (fd, elf, NULL, fname,
+#. preserve_dates ? tv : NULL);
+#.
+#: src/strip.c:820
+#, c-format
+msgid "%s: no support for stripping archive"
+msgstr "%s: アーカイブのストリップには対応していません"
+
+#: src/strip.c:1057
+#, c-format
+msgid "cannot open EBL backend"
+msgstr "EBL バックエンドを開けません"
+
+#: src/strip.c:1101
+msgid "cannot get number of phdrs"
+msgstr "phdrs の数を取得できません"
+
+#: src/strip.c:1115 src/strip.c:1158
+#, c-format
+msgid "cannot create new ehdr for file '%s': %s"
+msgstr "ファイル '%s' の新しい ehdr を作成できません: %s"
+
+#: src/strip.c:1125 src/strip.c:1168
+#, c-format
+msgid "cannot create new phdr for file '%s': %s"
+msgstr "ファイル '%s' の新しい phdr を作成できません: %s"
+
+#: src/strip.c:1248
+#, c-format
+msgid "illformed file '%s'"
+msgstr "不適格なファイル '%s'"
+
+#: src/strip.c:1258
+#, c-format
+msgid "Cannot remove allocated section '%s'"
+msgstr "割り当てされるセクション '%s' は取り除けません"
+
+#: src/strip.c:1267
+#, c-format
+msgid "Cannot both keep and remove section '%s'"
+msgstr "セクション '%s' を保持しつつ取り除くことはできません"
+
+#: src/strip.c:1631 src/strip.c:1746
+#, c-format
+msgid "while generating output file: %s"
+msgstr "出力ファイルを生成している間: %s"
+
+#: src/strip.c:1695
+#, c-format
+msgid "%s: error while updating ELF header: %s"
+msgstr "%s: ELF ヘッダーの更新中にエラー: %s"
+
+#: src/strip.c:1704
+#, c-format
+msgid "%s: error while getting shdrstrndx: %s"
+msgstr "%s: shdrstrndx の取得中にエラー: %s"
+
+#: src/strip.c:1712 src/strip.c:2552
+#, c-format
+msgid "%s: error updating shdrstrndx: %s"
+msgstr "%s: shdrstrndx の更新中にエラー: %s"
+
+#: src/strip.c:1729
+#, c-format
+msgid "while preparing output for '%s'"
+msgstr "'%s' のための出力を準備している間"
+
+#: src/strip.c:1790 src/strip.c:1852
+#, c-format
+msgid "while create section header section: %s"
+msgstr "セクションヘッダーセクションを生成している間: %s"
+
+#: src/strip.c:1799
+#, c-format
+msgid "cannot allocate section data: %s"
+msgstr "セクションデータを割り当てられません: %s"
+
+#: src/strip.c:1863
+#, c-format
+msgid "while create section header string table: %s"
+msgstr "セクションヘッダー文字列テーブルを生成中: %s"
+
+#: src/strip.c:1869
+msgid "no memory to create section header string table"
+msgstr "セクションヘッダー文字列テーブルを作成するメモリがありません"
+
+#: src/strip.c:2082
+#, c-format
+msgid "Cannot remove symbol [%zd] from allocated symbol table [%zd]"
+msgstr ""
+
+#: src/strip.c:2469 src/strip.c:2574
+#, c-format
+msgid "while writing '%s': %s"
+msgstr "'%s' を書込み中: %s"
+
+#: src/strip.c:2480
+#, c-format
+msgid "while creating '%s'"
+msgstr "'%s' を生成中"
+
+#: src/strip.c:2503
+#, c-format
+msgid "while computing checksum for debug information"
+msgstr "デバッグ情報のチェックサムを計算中"
+
+#: src/strip.c:2544
+#, c-format
+msgid "%s: error while creating ELF header: %s"
+msgstr "%s: ELF ヘッダーを生成している間にエラー: %s"
+
+#: src/strip.c:2560
+#, c-format
+msgid "%s: error while reading the file: %s"
+msgstr "%s: ファイルを読込み中にエラー: %s"
+
+#: src/strip.c:2599 src/strip.c:2619
+#, c-format
+msgid "while writing '%s'"
+msgstr "書き込み中 '%s'"
+
+#: src/strip.c:2656 src/strip.c:2663
+#, c-format
+msgid "error while finishing '%s': %s"
+msgstr "'%s' の終了中にエラー: %s"
+
+#: src/strip.c:2680 src/strip.c:2756
+#, c-format
+msgid "cannot set access and modification date of '%s'"
+msgstr "'%s' のアクセスと変更日付を設定できません"
+
+#: src/unstrip.c:65
+msgid "Match MODULE against file names, not module names"
+msgstr "モジュール名ではなく ファイル名で MODULE を一致させる"
+
+#: src/unstrip.c:66
+msgid "Silently skip unfindable files"
+msgstr "見つからない ファイルを 静かに スキップ"
+
+#: src/unstrip.c:69
+msgid "Place output into FILE"
+msgstr "出力を FILE に置く"
+
+#: src/unstrip.c:71
+msgid "Create multiple output files under DIRECTORY"
+msgstr "複数の 出力ファイルを DIRECTORY の下に 作成"
+
+#: src/unstrip.c:72
+msgid "Use module rather than file names"
+msgstr "ファイル名ではなく モジュール名を 使用"
+
+#: src/unstrip.c:74
+msgid "Create output for modules that have no separate debug information"
+msgstr "分離された デバッグ情報を 持たない モジュール用に 出力を 作成"
+
+#: src/unstrip.c:77
+msgid "Apply relocations to section contents in ET_REL files"
+msgstr "ET_REL ファイルの セクション内容に リロケーションを 適用"
+
+#: src/unstrip.c:79
+msgid "Only list module and file names, build IDs"
+msgstr "モジュール名、 ファイル名、 ビルドIDの リスト表示のみ"
+
+#: src/unstrip.c:81
+msgid "Force combining files even if some ELF headers don't seem to match"
+msgstr ""
+"いくつかの ELF ヘッダー が 一致しない ように 見えた としても ファイルの 結合"
+"を 強制"
+
+#: src/unstrip.c:125
+#, c-format
+msgid "-d option specified twice"
+msgstr ""
+
+#: src/unstrip.c:160
+#, c-format
+msgid "only one of -o or -d allowed"
+msgstr ""
+
+#: src/unstrip.c:169
+#, c-format
+msgid "-n cannot be used with explicit files or -o or -d"
+msgstr ""
+
+#: src/unstrip.c:184
+#, c-format
+msgid "output directory '%s'"
+msgstr "出力ディレクトリ '%s'"
+
+#: src/unstrip.c:193
+#, c-format
+msgid "exactly two file arguments are required"
+msgstr "ちょうど2つの引数が必要です"
+
+#: src/unstrip.c:199
+#, c-format
+msgid "-m, -a, -R, and -i options not allowed with explicit files"
+msgstr ""
+"明示的なファイルを使用する際は -m, -a, -R, -i オプションは認められていません"
+
+#: src/unstrip.c:212
+#, c-format
+msgid "-o or -d is required when using implicit files"
+msgstr "暗黙的なファイルを使用する際は -o または -d が必要です"
+
+#: src/unstrip.c:235
+#, c-format
+msgid "cannot create ELF header: %s"
+msgstr "ELF ヘッダーを作成できません: %s"
+
+#: src/unstrip.c:239
+#, c-format
+msgid "cannot get shdrstrndx:%s"
+msgstr "shdrstrndx を取得できません: %s"
+
+#: src/unstrip.c:243 src/unstrip.c:2136
+#, c-format
+msgid "cannot get ELF header: %s"
+msgstr "ELF ヘッダーを取得できません: %s"
+
+#: src/unstrip.c:253
+#, c-format
+msgid "cannot get new zero section: %s"
+msgstr "新しい zero セクションを取得できません: %s"
+
+#: src/unstrip.c:256
+#, c-format
+msgid "cannot update new zero section: %s"
+msgstr "新しい zero セクションを更新できません: %s"
+
+#: src/unstrip.c:260
+#, c-format
+msgid "cannot copy ELF header: %s"
+msgstr "ELF ヘッダーを複製できません: %s"
+
+#: src/unstrip.c:264 src/unstrip.c:2154 src/unstrip.c:2197
+#, c-format
+msgid "cannot get number of program headers: %s"
+msgstr "プログラムヘッダ数を取得できません: %s"
+
+#: src/unstrip.c:269 src/unstrip.c:2158
+#, c-format
+msgid "cannot create program headers: %s"
+msgstr "プログラムヘッダーを作成できません: %s"
+
+#: src/unstrip.c:275
+#, c-format
+msgid "cannot copy program header: %s"
+msgstr "プログラムヘッダーを複製できません: %s"
+
+#: src/unstrip.c:285
+#, c-format
+msgid "cannot copy section header: %s"
+msgstr "セクションヘッダーを複製できません: %s"
+
+#: src/unstrip.c:288 src/unstrip.c:1748
+#, c-format
+msgid "cannot get section data: %s"
+msgstr "セクションデータを取得できません: %s"
+
+#: src/unstrip.c:290 src/unstrip.c:1750
+#, c-format
+msgid "cannot copy section data: %s"
+msgstr "セクションデータを複製できません: %s"
+
+#: src/unstrip.c:318
+#, c-format
+msgid "cannot create directory '%s'"
+msgstr "ディレクトリ '%s' を作成できません"
+
+#: src/unstrip.c:392 src/unstrip.c:666 src/unstrip.c:700 src/unstrip.c:868
+#: src/unstrip.c:1790
+#, c-format
+msgid "cannot get symbol table entry: %s"
+msgstr "シンボルテーブル項目を取得できません: %s"
+
+#: src/unstrip.c:408 src/unstrip.c:669 src/unstrip.c:690 src/unstrip.c:703
+#: src/unstrip.c:1811 src/unstrip.c:2007 src/unstrip.c:2031
+#, c-format
+msgid "cannot update symbol table: %s"
+msgstr "シンボルテーブルを更新できません: %s"
+
+#: src/unstrip.c:418
+#, c-format
+msgid "cannot update section header: %s"
+msgstr "セクションヘッダーを更新できません: %s"
+
+#: src/unstrip.c:464
+#, c-format
+msgid "gelf_getrel failed: %s"
+msgstr ""
+
+#: src/unstrip.c:467 src/unstrip.c:482
+#, c-format
+msgid "cannot update relocation: %s"
+msgstr "リロケーションを更新できません: %s"
+
+#: src/unstrip.c:479
+#, c-format
+msgid "gelf_getrela failed: %s"
+msgstr ""
+
+#: src/unstrip.c:580
+#, c-format
+msgid "cannot get symbol version: %s"
+msgstr "シンボルバージョンを取得できません: %s"
+
+#: src/unstrip.c:593
+#, c-format
+msgid "unexpected section type in [%zu] with sh_link to symtab"
+msgstr ""
+
+#: src/unstrip.c:857
+#, c-format
+msgid "cannot get symbol section data: %s"
+msgstr "シンボルセクションデータを取得できません: %s"
+
+#: src/unstrip.c:859
+#, c-format
+msgid "cannot get string section data: %s"
+msgstr "文字列セクションデータを取得できません: %s"
+
+#: src/unstrip.c:876
+#, c-format
+msgid "invalid string offset in symbol [%zu]"
+msgstr "シンボル [%zu] の中に不当な文字列オフセットがあります"
+
+#: src/unstrip.c:939
+msgid "found two identical index map positions."
+msgstr ""
+
+#: src/unstrip.c:990
+msgid "section symbols in unexpected order"
+msgstr ""
+
+#: src/unstrip.c:996
+#, fuzzy
+#| msgid "Show demangled symbols (ARG is always ignored)"
+msgid "found two identical symbols"
+msgstr "デマングルされた シンボルを 表示 (ARGは常に無視される)"
+
+#: src/unstrip.c:1066 src/unstrip.c:1474
+#, c-format
+msgid "cannot read section [%zu] name: %s"
+msgstr "セクション [%zu] の名前を読み込めません: %s"
+
+#: src/unstrip.c:1081
+#, c-format
+msgid "bad sh_link for group section: %s"
+msgstr "グループセクションに対する誤った sh_link です: %s"
+
+#: src/unstrip.c:1087
+#, c-format
+msgid "couldn't get shdr for group section: %s"
+msgstr "グループセクションに対する shdr を取得できませんでした: %s"
+
+#: src/unstrip.c:1092
+#, c-format
+msgid "bad data for group symbol section: %s"
+msgstr "グループシンボルセクションに対する誤ったデータです: %s"
+
+#: src/unstrip.c:1098
+#, c-format
+msgid "couldn't get symbol for group section: %s"
+msgstr "グループセクションに対するシンボルを取得できませんでした: %s"
+
+#: src/unstrip.c:1103
+#, c-format
+msgid "bad symbol name for group section: %s"
+msgstr "グループセクションに対する誤ったシンボル名です: %s"
+
+#: src/unstrip.c:1114 src/unstrip.c:1594
+#, fuzzy, c-format
+msgid "cannot find matching section for [%zu] '%s'"
+msgstr "セクション [%zu] '%s' の不当なデータ"
+
+#: src/unstrip.c:1159 src/unstrip.c:1178 src/unstrip.c:1216
+#, c-format
+msgid "cannot read '.gnu.prelink_undo' section: %s"
+msgstr ""
+
+#: src/unstrip.c:1196
+#, c-format
+msgid "overflow with shnum = %zu in '%s' section"
+msgstr ""
+
+#: src/unstrip.c:1207
+#, c-format
+msgid "invalid contents in '%s' section"
+msgstr ""
+
+#: src/unstrip.c:1378 src/unstrip.c:1394 src/unstrip.c:1674 src/unstrip.c:1966
+#, c-format
+msgid "cannot add section name to string table: %s"
+msgstr ""
+
+#: src/unstrip.c:1403
+#, c-format
+msgid "cannot update section header string table data: %s"
+msgstr ""
+
+#: src/unstrip.c:1432 src/unstrip.c:1436
+#, c-format
+msgid "cannot get section header string table section index: %s"
+msgstr ""
+
+#: src/unstrip.c:1440 src/unstrip.c:1444 src/unstrip.c:1689
+#, c-format
+msgid "cannot get section count: %s"
+msgstr ""
+
+#: src/unstrip.c:1447
+msgid "more sections in stripped file than debug file -- arguments reversed?"
+msgstr ""
+
+#: src/unstrip.c:1451
+msgid "no sections in stripped file"
+msgstr ""
+
+#: src/unstrip.c:1499 src/unstrip.c:1609
+#, c-format
+msgid "cannot read section header string table: %s"
+msgstr ""
+
+#: src/unstrip.c:1668
+#, c-format
+msgid "cannot add new section: %s"
+msgstr ""
+
+#: src/unstrip.c:1798
+#, c-format
+msgid "symbol [%zu] has invalid section index"
+msgstr "シンボル [%zu] が不当なセクション索引を持っています"
+
+#: src/unstrip.c:1830
+#, c-format
+msgid "group has invalid section index [%zd]"
+msgstr "グループが不当なセクション索引 [%zd] を持っています"
+
+#: src/unstrip.c:2115
+#, c-format
+msgid "cannot read section data: %s"
+msgstr "セクションデータを読み込めません: %s"
+
+#: src/unstrip.c:2144
+#, c-format
+msgid "cannot update ELF header: %s"
+msgstr "ELF ヘッダーを更新できません: %s"
+
+#: src/unstrip.c:2168
+#, c-format
+msgid "cannot update program header: %s"
+msgstr ""
+
+#: src/unstrip.c:2173 src/unstrip.c:2256
+#, c-format
+msgid "cannot write output file: %s"
+msgstr ""
+
+#: src/unstrip.c:2224
+#, c-format
+msgid "DWARF data not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+
+#: src/unstrip.c:2227
+#, c-format
+msgid ""
+"DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+
+#: src/unstrip.c:2247 src/unstrip.c:2299 src/unstrip.c:2311 src/unstrip.c:2401
+#, c-format
+msgid "cannot create ELF descriptor: %s"
+msgstr ""
+
+#: src/unstrip.c:2285
+msgid "WARNING: "
+msgstr ""
+
+#: src/unstrip.c:2287
+msgid ", use --force"
+msgstr ""
+
+#: src/unstrip.c:2315
+msgid "ELF header identification (e_ident) different"
+msgstr ""
+
+#: src/unstrip.c:2319
+msgid "ELF header type (e_type) different"
+msgstr ""
+
+#: src/unstrip.c:2323
+msgid "ELF header machine type (e_machine) different"
+msgstr ""
+
+#: src/unstrip.c:2327
+msgid "stripped program header (e_phnum) smaller than unstripped"
+msgstr ""
+
+#: src/unstrip.c:2358
+#, c-format
+msgid "cannot find stripped file for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2362
+#, c-format
+msgid "cannot open stripped file '%s' for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2377
+#, c-format
+msgid "cannot find debug file for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2381
+#, c-format
+msgid "cannot open debug file '%s' for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2394
+#, c-format
+msgid "module '%s' file '%s' is not stripped"
+msgstr ""
+
+#: src/unstrip.c:2425
+#, c-format
+msgid "cannot cache section addresses for module '%s': %s"
+msgstr ""
+
+#: src/unstrip.c:2553
+msgid "no matching modules found"
+msgstr ""
+
+#: src/unstrip.c:2563
+msgid "matched more than one module"
+msgstr ""
+
+#: src/unstrip.c:2608
+msgid ""
+"STRIPPED-FILE DEBUG-FILE\n"
+"[MODULE...]"
+msgstr ""
+
+#: src/unstrip.c:2609
+msgid ""
+"Combine stripped files with separate symbols and debug information.\n"
+"\n"
+"The first form puts the result in DEBUG-FILE if -o was not given.\n"
+"\n"
+"MODULE arguments give file name patterns matching modules to process.\n"
+"With -f these match the file name of the main (stripped) file (slashes are "
+"never special), otherwise they match the simple module names.  With no "
+"arguments, process all modules found.\n"
+"\n"
+"Multiple modules are written to files under OUTPUT-DIRECTORY, creating "
+"subdirectories as needed.  With -m these files have simple module names, "
+"otherwise they have the name of the main file complete with directory "
+"underneath OUTPUT-DIRECTORY.\n"
+"\n"
+"With -n no files are written, but one line to standard output for each "
+"module:\n"
+"\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n"
+"START and SIZE are hexadecimal giving the address bounds of the module.  "
+"BUILDID is hexadecimal for the build ID bits, or - if no ID is known; the "
+"hexadecimal may be followed by @0xADDR giving the address where the ID "
+"resides if that is known.  FILE is the file name found for the module, or - "
+"if none was found, or . if an ELF image is available but not from any named "
+"file.  DEBUGFILE is the separate debuginfo file name, or - if no debuginfo "
+"was found, or . if FILE contains the debug information."
+msgstr ""
+
+#. Short description of program.
+#: debuginfod/debuginfod-find.c:42
+msgid "Request debuginfo-related content from debuginfods listed in $"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: debuginfod/debuginfod-find.c:46
+msgid ""
+"debuginfo BUILDID\n"
+"debuginfo PATH\n"
+"executable BUILDID\n"
+"executable PATH\n"
+"source BUILDID /FILENAME\n"
+"source PATH /FILENAME\n"
+"section BUILDID SECTION-NAME\n"
+"section PATH SECTION-NAME\n"
+msgstr ""
+
+#: tests/backtrace.c:491
+msgid "Run executable"
+msgstr ""
+
+#: tests/dwflmodtest.c:209
+msgid "Additionally show function names"
+msgstr "関数名を さらに 表示"
+
+#: tests/dwflmodtest.c:210
+msgid "Show instances of inlined functions"
+msgstr "インライン関数の実体を表示"
+
+#, c-format
+#~ msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n"
+#~ msgstr ""
+#~ "セクション [%2d] '%s': セクション項目サイズが ElfXX_Rela と一致しません\n"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_addr section data: %s"
+#~ msgstr "セクションデータを割り当てられません: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_rnglists content: %s"
+#~ msgstr ".degub_ranges の内容を得られません: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_ranges content: %s"
+#~ msgstr ".degub_ranges の内容を得られません: %s"
+
+#, c-format
+#~ msgid "cannot get line data section data: %s"
+#~ msgstr "ラインデータセクションデータを得られません: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loclists content: %s"
+#~ msgstr ".debug_loclists の内容を取得できません: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loc content: %s"
+#~ msgstr ".debug_loc の内容を得られません: %s"
+
+#, c-format
+#~ msgid "cannot get macro information section data: %s"
+#~ msgstr "マクロ情報セクションのデータを得られません: %s"
+
+#, fuzzy, c-format
+#~ msgid "cannot get .debug_str_offsets section data: %s"
+#~ msgstr ".degub_ranges の内容を得られません: %s"
+
+#~ msgid "cannot allocate memory"
+#~ msgstr "メモリーを割り当てられません"
+
+#, fuzzy
+#~ msgid ""
+#~ " [%6tx] base address\n"
+#~ "          "
+#~ msgstr " [%6tx]  ベースアドレス %s\n"
+
+#, fuzzy
+#~ msgid "%s: error getting zero section: %s"
+#~ msgstr "%s: ファイルを読込み中にエラー: %s"
+
+#, fuzzy
+#~ msgid "%s: error while updating zero section: %s"
+#~ msgstr "%s: ファイルを読込み中にエラー: %s"
+
+#~ msgid "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#<PRIx64> <%s>"
+#~ msgstr "%s+%#<PRIx64> <%s>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s>"
+#~ msgstr "%s+%#0*<PRIx64> <%s>"
+
+#~ msgid "%#<PRIx64> <%s>"
+#~ msgstr "%#<PRIx64> <%s>"
+
+#~ msgid "%#0*<PRIx64> <%s>"
+#~ msgstr "%#0*<PRIx64> <%s>"
+
+#~ msgid "%s+%#<PRIx64>"
+#~ msgstr "%s+%#<PRIx64>"
+
+#~ msgid "%s+%#0*<PRIx64>"
+#~ msgstr "%s+%#0*<PRIx64>"
+
+#, fuzzy
+#~ msgid "   %s..%s (%<PRIx64>)\n"
+#~ msgstr "      %s: %<PRId64>\n"
+
+#, fuzzy
+#~ msgid "   %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#, fuzzy
+#~ msgid " advance address by %u to %s, op_index to %u\n"
+#~ msgstr "アドレスを %u だけ進めて %s にする\n"
+
+#, fuzzy
+#~ msgid " advance address by constant %u to %s, op_index to %u\n"
+#~ msgstr "アドレスを定数 %u だけ済めて %s にする\n"
+
+#~ msgid " [%6tx]  %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#~ msgid "           %s..%s\n"
+#~ msgstr "           %s..%s\n"
+
+#~ msgid "cannot get DIE at offset %<PRIu64> in section '%s': %s"
+#~ msgstr ""
+#~ "セクション '%2$s' の オフセット %1$<PRIu64> の DIE を得られません: %3$s"
+
+#~ msgid " [%6tx]  %s..%s"
+#~ msgstr " [%6tx]  %s..%s"
+
+#~ msgid "           %s..%s"
+#~ msgstr "           %s..%s"
+
+#~ msgid "-R option supports only .comment section"
+#~ msgstr "-R オプションは .comment セクションのみをサポートします"
+
+#~ msgid "Written by %s.\n"
+#~ msgstr "%s によって書かれました。\n"
+
+#~ msgid "cannot allocate PLTREL section: %s"
+#~ msgstr "PLTREL セクションを割り当てられません: %s"
+
+#~ msgid "cannot allocate GOT section: %s"
+#~ msgstr "GOT セクションを割り当てられません: %s"
+
+#~ msgid "cannot allocate GOTPLT section: %s"
+#~ msgstr "GOTPLT セクションを割り当てられません: %s"
+
+#~ msgid "initial-executable TLS relocation cannot be used "
+#~ msgstr "最初に実行される TLS リロケーションが使用されません "
+
+#~ msgid "Input File Control:"
+#~ msgstr "入力ファイル制御:"
+
+#~ msgid "Include whole archives in the output from now on."
+#~ msgstr "今から出力中の全アーカイブを含める。"
+
+#, fuzzy
+#~ msgid "Stop including the whole archives in the output."
+#~ msgstr "出力中の全アーカイブを含めるのを止める。"
+
+#~ msgid "FILE"
+#~ msgstr "ふぁいる"
+
+#~ msgid "Start a group."
+#~ msgstr "グループの開始。"
+
+#~ msgid "End a group."
+#~ msgstr "グループの終了。"
+
+#~ msgid "PATH"
+#~ msgstr "パス"
+
+#~ msgid "Add PATH to list of directories files are searched in."
+#~ msgstr "ファイルが検索されるディレクトリーの一覧にPATHを追加する。"
+
+#~ msgid "Only set DT_NEEDED for following dynamic libs if actually used"
+#~ msgstr ""
+#~ "実際に使用されるのなら以下のダイナミックライブラリーに DT_NEEDED を設定す"
+#~ "る"
+
+#~ msgid "Always set DT_NEEDED for following dynamic libs"
+#~ msgstr "以下のダイナミックライブラリーに常に DT_NEEDED を設定する"
+
+#~ msgid "Ignore LD_LIBRARY_PATH environment variable."
+#~ msgstr "LD_LIBRARY_PATH 環境変数を無視する。"
+
+#~ msgid "Output File Control:"
+#~ msgstr "出力ファイル制御:"
+
+#~ msgid "Place output in FILE."
+#~ msgstr "出力を ふぁいる に置く。"
+
+#~ msgid "Object is marked to not use default search path at runtime."
+#~ msgstr "オブジェクトは実行時に省略値の検索パスを使わないと記されています。"
+
+#~ msgid "Same as --whole-archive."
+#~ msgstr "--whole-archive と同じ。"
+
+#~ msgid ""
+#~ "Default rules of extracting from archive; weak references are not enough."
+#~ msgstr ""
+#~ "アーカイブから抽出する時の省略値の規則: 弱い参照では十分ではありません。"
+
+#~ msgid "Weak references cause extraction from archive."
+#~ msgstr "弱い参照はアーカイブから抽出します。"
+
+#~ msgid "Allow multiple definitions; first is used."
+#~ msgstr "複数の定義を認めます: 最初を使用します。"
+
+#~ msgid "Disallow/allow undefined symbols in DSOs."
+#~ msgstr "DSO 中の未定義のシンボルを認めない/認める。"
+
+#~ msgid "Object requires immediate handling of $ORIGIN."
+#~ msgstr "オブジェクトには %ORIGIN の直接ハンドルが必要です。"
+
+#~ msgid "Relocation will not be processed lazily."
+#~ msgstr "リロケーションは遅延処理されません。"
+
+#~ msgid "Object cannot be unloaded at runtime."
+#~ msgstr "オプションは実行時にはアンロードできません。"
+
+#~ msgid "Mark object to be initialized first."
+#~ msgstr "オブジェクトは最初に初期化されると記します。"
+
+#~ msgid "Enable/disable lazy-loading flag for following dependencies."
+#~ msgstr "以下の依存性のための遅延ロードを有効/無効にします。"
+
+#~ msgid "Mark object as not loadable with 'dlopen'."
+#~ msgstr "'dlopen' でロードできないと記します。"
+
+#~ msgid "Ignore/record dependencies on unused DSOs."
+#~ msgstr "使用されない DSO の依存性を無視/記録します。"
+
+#~ msgid "Generated DSO will be a system library."
+#~ msgstr "生成された DSO はシステムライブラリーになります。"
+
+#~ msgid "ADDRESS"
+#~ msgstr "アドレス"
+
+#~ msgid "Set entry point address."
+#~ msgstr "入口点アドレスを設定します。"
+
+#~ msgid "Do not link against shared libraries."
+#~ msgstr "共用ライブラリーに対してリンクを設定してはいけません。"
+
+#~ msgid "Prefer linking against shared libraries."
+#~ msgstr "共用ライブラリーに対してリンクを好みます。"
+
+#~ msgid "Export all dynamic symbols."
+#~ msgstr "全ダイナミックシンボルをエクスポートします。"
+
+#~ msgid "Strip all symbols."
+#~ msgstr "全シンボルを取り除きます。"
+
+#~ msgid "Strip debugging symbols."
+#~ msgstr "デバッグシンボルを取り除きます。"
+
+#~ msgid "Assume pagesize for the target system to be SIZE."
+#~ msgstr "ターゲットシステムのページサイズを SIZE と見做します。"
+
+#~ msgid "Set runtime DSO search path."
+#~ msgstr "実行時 DSO 検索パスを設定します。"
+
+#~ msgid "Set link time DSO search path."
+#~ msgstr "リンク時 DSO 検索パスを設定します。"
+
+#~ msgid "Generate dynamic shared object."
+#~ msgstr "動的共用オブジェクトを生成します。"
+
+#~ msgid "Generate relocatable object."
+#~ msgstr "リロケータブルオブジェクトを生成します。"
+
+#~ msgid "Causes symbol not assigned to a version be reduced to local."
+#~ msgstr "バージョンが指定されていないシンボルはローカルに減少します。"
+
+#~ msgid "Remove unused sections."
+#~ msgstr "使用されていないセクションを取り除きます。"
+
+#~ msgid "Don't remove unused sections."
+#~ msgstr "利用されていていセクションを取り除いてはいけません。"
+
+#~ msgid "Set soname of shared object."
+#~ msgstr "共用ライブラリーの so 名を設定します。"
+
+#~ msgid "Set the dynamic linker name."
+#~ msgstr "動的リンカーの名前を設定します。"
+
+#~ msgid "Add/suppress addition indentifying link-editor to .comment section."
+#~ msgstr ""
+#~ ".comment セクションにリンクエディターを識別する追加情報を追加/抑止します。"
+
+#~ msgid "Create .eh_frame_hdr section"
+#~ msgstr ".eh_frame_hdr セクションを生成します"
+
+#~ msgid "Set hash style to sysv, gnu or both."
+#~ msgstr "ハッシュ形式を sysvか、gnu、両方のどれかに設定します。"
+
+#~ msgid "Generate build ID note (md5, sha1 (default), uuid)."
+#~ msgstr "ビルド ID ノート (md5、sh1 (省略値)、uuid) を生成します。"
+
+#~ msgid "Linker Operation Control:"
+#~ msgstr "リンカー操作制御:"
+
+#~ msgid "Verbose messages."
+#~ msgstr "饒舌メッセージ。"
+
+#~ msgid "Trace file opens."
+#~ msgstr "ファイルのオープンを追跡します。"
+
+#~ msgid "Trade speed for less memory usage"
+#~ msgstr "速度と引き換えにメモリー使用量を減らします"
+
+#~ msgid "LEVEL"
+#~ msgstr "れべる"
+
+#~ msgid "Set optimization level to LEVEL."
+#~ msgstr "最適化レベルを れべる に設定します。"
+
+#~ msgid "Use linker script in FILE."
+#~ msgstr "ふぁいる でリンカースクリプトを使用します。"
+
+#~ msgid "Select to get parser debug information"
+#~ msgstr "パーサーのデバッグ情報を得るように選択します"
+
+#~ msgid "Read version information from FILE."
+#~ msgstr "ふぁいる からバージョン情報を読みます。"
+
+#~ msgid "Set emulation to NAME."
+#~ msgstr "エミュレーションを なまえ に設定します。"
+
+#~ msgid "Combine object and archive files."
+#~ msgstr "オブジェクトとアーカイブファイルを一体化します。"
+
+#~ msgid "[FILE]..."
+#~ msgstr "[ふぁいる]..."
+
+#~ msgid "At least one input file needed"
+#~ msgstr "少なくとも 1 つの入力ファイルが必要です"
+
+#~ msgid "error while preparing linking"
+#~ msgstr "リンクの準備中にエラー"
+
+#~ msgid "cannot open linker script '%s'"
+#~ msgstr "リンカースクリプト '%s' を開けません"
+
+#~ msgid "-( without matching -)"
+#~ msgstr "-( 何も一致しない -)"
+
+#~ msgid "only one option of -G and -r is allowed"
+#~ msgstr "-G か -r のどちらかひとつのオプションだけ認められます"
+
+#~ msgid "more than one '-m' parameter"
+#~ msgstr "-m パラメーターが1つを越えています"
+
+#~ msgid "unknown option `-%c %s'"
+#~ msgstr "不明なオプション `%c %s'"
+
+#~ msgid "invalid hash style '%s'"
+#~ msgstr "不当なハッシュスタイル '%s'"
+
+#~ msgid "invalid build-ID style '%s'"
+#~ msgstr "不当なビルド-ID スタイル '%s'"
+
+#~ msgid "Invalid optimization level `%s'"
+#~ msgstr "不当な最適化レベル `%s'"
+
+#~ msgid "nested -( -) groups are not allowed"
+#~ msgstr "ネストされた -( -) グループは認められません"
+
+#~ msgid "-) without matching -("
+#~ msgstr "対応する -( がない -)"
+
+#~ msgid "unknown option '-%c %s'"
+#~ msgstr "不明なオプション '-%c %s'"
+
+#~ msgid "could not find input file to determine output file format"
+#~ msgstr "出力ファイル形式を決定するための入力ファイルが見つかりません"
+
+#~ msgid "try again with an appropriate '-m' parameter"
+#~ msgstr "適切な '-m' パラメーターを付けて再試行してください"
+
+#~ msgid "cannot read version script '%s'"
+#~ msgstr "バージョンスクリプト '%s' を読めません"
+
+#~ msgid "duplicate definition of '%s' in linker script"
+#~ msgstr "リンカースクリプトに '%s' の重複定義"
+
+#~ msgid "cannot create string table"
+#~ msgstr "文字列テーブルを生成できません"
+
+#~ msgid "cannot load ld backend library '%s': %s"
+#~ msgstr "ld バックエンドライブラリー '%s' をロードできません: %s"
+
+#~ msgid "cannot find init function in ld backend library '%s': %s"
+#~ msgstr "ld バックエンドライブラリー '%s' に初期化機能が見つかりません: %s "
+
+#~ msgid "%s listed more than once as input"
+#~ msgstr "入力に %s が 1回を越えて書かれています"
+
+#~ msgid "%s (for -l%s)\n"
+#~ msgstr "%s (-l%s 用)\n"
+
+#~ msgid "%s (for DT_NEEDED %s)\n"
+#~ msgstr "%s (DT_NEEDED %s 用)\n"
+
+#~ msgid "Warning: type of `%s' changed from %s in %s to %s in %s"
+#~ msgstr ""
+#~ "警告: `%1$s' のタイプが %3$s の %2$s から %5$s の %4$s に変更されました"
+
+#~ msgid ""
+#~ "Warning: size of `%s' changed from %<PRIu64> in %s to %<PRIu64> in %s"
+#~ msgstr ""
+#~ "警告: `%1$s の大きさが %3$s の %2$<PRIu64> から %5$s の %4$<PRIu64> に変更"
+#~ "されました"
+
+#~ msgid "(%s+%#<PRIx64>): multiple definition of %s `%s'\n"
+#~ msgstr "(%s+%#<PRIx64>): %s の複数定義 '%s'\n"
+
+#~ msgid "(%s+%#<PRIx64>): first defined here\n"
+#~ msgstr "(%s+%#<PRIx64>): 最初の定義はここ\n"
+
+#~ msgid "%s: cannot get section group data: %s"
+#~ msgstr "%s: セクショングループデータを得られません: %s"
+
+#~ msgid "%s: section '%s' with group flag set does not belong to any group"
+#~ msgstr ""
+#~ "%s: グループフラグが設定されているセクション '%s' はどのグループにも属して"
+#~ "いません"
+
+#~ msgid "%s: section [%2d] '%s' is not in the correct section group"
+#~ msgstr ""
+#~ "%s: セクション [%2d] '%s& は正しいセクショングループに入っていません"
+
+#~ msgid "%s: invalid ELF file (%s:%d)\n"
+#~ msgstr "%s: 不当な ELF ファイル (%s:%d)\n"
+
+#~ msgid "%s: only files of type ET_REL might contain section groups"
+#~ msgstr ""
+#~ "%s: タイプ ET_REL のファイルのみセクショングループを含むことができます"
+
+#~ msgid "%s: cannot determine signature of section group [%2zd] '%s': %s"
+#~ msgstr "%s: セクショングループ [%2zd] '%s' の署名を決定できません: %s"
+
+#~ msgid "%s: cannot get content of section group [%2zd] '%s': %s'"
+#~ msgstr "%s: セクショングループ [%2zd] '%s' の内容を得られません: %s'"
+
+#~ msgid ""
+#~ "%s: group member %zu of section group [%2zd] '%s' has too high index: "
+#~ "%<PRIu32>"
+#~ msgstr ""
+#~ "%1$s: セクショングループ [%3$2zd] '%4$s' のグループメンバー %2$zu は大きす"
+#~ "ぎるインデックスを持っています: %5$<PRIu32>"
+
+#~ msgid "%s: section '%s' has unknown type: %d"
+#~ msgstr "%s: セクション '%s' は不明なタイプを持っています: %d"
+
+#~ msgid "cannot get descriptor for ELF file (%s:%d): %s\n"
+#~ msgstr "ELF ファイル (%s:%d) のための記述子を得られません: %s\n"
+
+#~ msgid "cannot read archive `%s': %s"
+#~ msgstr "アーカイブ `%s' を読めません: %s"
+
+#~ msgid "file of type %s cannot be linked in\n"
+#~ msgstr "%s のファイルタイプがリンクされていません\n"
+
+#~ msgid "%s: input file incompatible with ELF machine type %s\n"
+#~ msgstr "%s: 入力ファイルは ELF マシンタイプ %s と互換性がありません\n"
+
+#~ msgid "%s: cannot get section header string table index: %s\n"
+#~ msgstr ""
+#~ "%s: セクションヘッダー文字列テーブルインデックスを得られません: %s\n"
+
+#~ msgid "cannot use DSO '%s' when generating relocatable object file"
+#~ msgstr "リロケータブルオブジェクトファイル生成時に DSO '%s' を使えません"
+
+#~ msgid "input file '%s' ignored"
+#~ msgstr "入力ファイル '%s' を無視しました"
+
+#~ msgid "undefined symbol `%s' in %s"
+#~ msgstr "%2$s 中に未定義のシンボル `%1$s'"
+
+#~ msgid "cannot create ELF descriptor for output file: %s"
+#~ msgstr "出力ファイル用の ELF 記述子を生成できません: %s"
+
+#~ msgid "could not create ELF header for output file: %s"
+#~ msgstr "出力ファイル用の ELF ヘッダーを生成できませんでした: %s"
+
+#~ msgid "cannot create section for output file: %s"
+#~ msgstr "出力ファイル用のセクションを生成できません: %s"
+
+#~ msgid "address computation expression contains variable '%s'"
+#~ msgstr "アドレス計算式が変数 '%s' を含んでいます"
+
+#~ msgid ""
+#~ "argument '%<PRIuMAX>' of ALIGN in address computation expression is no "
+#~ "power of two"
+#~ msgstr ""
+#~ "アドレス計算式中の ALIGN のパラメーター %<PRIuMAX> が 2 の累乗ではありませ"
+#~ "ん"
+
+#~ msgid "cannot find entry symbol '%s': defaulting to %#0*<PRIx64>"
+#~ msgstr ""
+#~ "エントリーシンボル '%s' が見つかりません: デフォルトの %#0*<PRIx64> にしま"
+#~ "す"
+
+#~ msgid "no entry symbol specified: defaulting to %#0*<PRIx64>"
+#~ msgstr ""
+#~ "エントリーシンボルが指定されていません: デフォルトの %#0*<PRIx64> にします"
+
+#~ msgid "cannot create GNU hash table section for output file: %s"
+#~ msgstr "出力ファイル用の GNU ハッシュテーブルセクションを生成できません: %s"
+
+#~ msgid "cannot create hash table section for output file: %s"
+#~ msgstr "出力ファイル用のハッシュテーブルセクションを生成できません: %s"
+
+#~ msgid "cannot create build ID section: %s"
+#~ msgstr "ビルド ID セクションを生成できません: %s"
+
+#~ msgid "cannot convert section data to file format: %s"
+#~ msgstr "セクションデータをファイル形式に変換できません: %s"
+
+#~ msgid "cannot convert section data to memory format: %s"
+#~ msgstr "セクションデータをメモリー形式に変換できません: %s"
+
+#~ msgid "cannot read enough data for UUID"
+#~ msgstr "UUID に十分なデータを読めません"
+
+#~ msgid "cannot create symbol table for output file: %s"
+#~ msgstr "出力ファイル用のシンボルテーブルを生成できません: %s"
+
+#~ msgid "section index too large in dynamic symbol table"
+#~ msgstr "動的シンボルテーブルのセクションインデックスが大きすぎます"
+
+#~ msgid "cannot create versioning section: %s"
+#~ msgstr "バージョニングセクションを生成できません: %s"
+
+#~ msgid "cannot create dynamic symbol table for output file: %s"
+#~ msgstr "出力ファイル用の動的シンボルテーブルを生成できません: %s"
+
+#~ msgid "cannot create versioning data: %s"
+#~ msgstr "バージョニングデータを生成できません: %s"
+
+#~ msgid "cannot create section header string section: %s"
+#~ msgstr "セクションヘッダー文字列セクションを生成できません: %s"
+
+#~ msgid "cannot create section header string section"
+#~ msgstr "セクションヘッダー文字列セクションを生成できません"
+
+#~ msgid "cannot create program header: %s"
+#~ msgstr "プログラムヘッダーを生成できません: %s"
+
+#~ msgid "while determining file layout: %s"
+#~ msgstr "ファイルレイアウトを決定中: %s"
+
+#~ msgid "internal error: non-nobits section follows nobits section"
+#~ msgstr "内部エラー: 非 nobits セクションが nobits セクションに続きます"
+
+#~ msgid "linker backend didn't specify function to relocate section"
+#~ msgstr ""
+#~ "リンカーバックエンドがセクションをリロケートするための機能を指定していませ"
+#~ "ん"
+
+#~ msgid "while writing output file: %s"
+#~ msgstr "出力ファイルに書込み中: %s"
+
+#~ msgid "while finishing output file: %s"
+#~ msgstr "出力ファイルの仕上げ中: %s"
+
+#~ msgid "cannot stat output file"
+#~ msgstr "出力ファイルを stat できません"
+
+#~ msgid "WARNING: temporary output file overwritten before linking finished"
+#~ msgstr "警告: リンクを仕上げる前に一時出力ファイルが上書きされました"
+
+#~ msgid "no machine specific '%s' implementation"
+#~ msgstr "マシン固有の '%s' 実装はありません"
+
+#~ msgid "mode for segment invalid\n"
+#~ msgstr "セグメント用のモードが不当です\n"
+
+#~ msgid "while reading version script '%s': %s at line %d"
+#~ msgstr "バージョンスクリプト '%1$s' 読込み中: %3$d 行目の %2$s"
+
+#, fuzzy
+#~ msgid ""
+#~ "symbol '%s' is declared both local and global for unnamed version '%s'"
+#~ msgstr "名前なしバージョン用のローカルとグローバルで宣言されたシンボル '%s'"
+
+#, fuzzy
+#~ msgid "symbol '%s' is declared both local and global for version '%s'"
+#~ msgstr ""
+#~ "バージョン '%2$s' 用のローカルとグローバルで宣言されたシンボル '%1$s'"
+
+#~ msgid "default visibility set as local and global"
+#~ msgstr "ローカルとグローバルに設定されたデフォルトの可視性"
+
+#, fuzzy
+#~ msgid "cannot attach to core"
+#~ msgstr "検索ツリーを生成できません"
+
+#~ msgid "unknown tag %hx"
+#~ msgstr "不明なタグ %hx"
+
+#~ msgid "unknown user tag %hx"
+#~ msgstr "不明な利用者タグ %hx"
+
+#~ msgid "unknown attribute %hx"
+#~ msgstr "不明な属性 %hx"
+
+#~ msgid "unknown user attribute %hx"
+#~ msgstr "不明な利用者属性 %hx"
+
+#~ msgid ""
+#~ "\n"
+#~ "\n"
+#~ "Symbols from %s[%s]:\n"
+#~ "\n"
+#~ msgstr ""
+#~ "\n"
+#~ "\n"
+#~ "%s[%s]からのシンボル:\n"
+#~ "\n"
+
+#~ msgid " Version String: "
+#~ msgstr "バージョン文字列:"
+
+#~ msgid "Equivalent to: -e -h -l"
+#~ msgstr "右記と同等: -e -h -l"
+
+#~ msgid ""
+#~ "\n"
+#~ "Section [%Zu] '%s' is empty.\n"
+#~ msgstr ""
+#~ "\n"
+#~ "セクション [%Zu] '%s' は空です。\n"
diff --git a/po/pl.po b/po/pl.po
new file mode 100644
index 0000000..8d7f519
--- /dev/null
+++ b/po/pl.po
@@ -0,0 +1,7630 @@
+# Polish translation for elfutils.
+# Copyright © 2003-2021 the elfutils authors.
+# This file is distributed under the same license as the elfutils package.
+# Jakub Bogusz <qboosh@pld-linux.org>, 2003-2007.
+# Piotr Drąg <piotrdrag@gmail.com>, 2010-2021.
+#
+msgid ""
+msgstr ""
+"Project-Id-Version: elfutils\n"
+"Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n"
+"POT-Creation-Date: 2024-03-01 10:22-0500\n"
+"PO-Revision-Date: 2021-02-22 16:25+0100\n"
+"Last-Translator: Piotr Drąg <piotrdrag@gmail.com>\n"
+"Language-Team: Polish <trans-pl@lists.fedoraproject.org>\n"
+"Language: pl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 "
+"|| n%100>=20) ? 1 : 2);\n"
+
+#: lib/color.c:51
+msgid ""
+"colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"
+msgstr ""
+"koloruje wyjście. WHEN domyślnie wynosi „always” lub może wynosić „auto” lub "
+"„never”"
+
+#: lib/color.c:127
+#, c-format
+msgid ""
+"%s: invalid argument '%s' for '--color'\n"
+"valid arguments are:\n"
+"  - 'always', 'yes', 'force'\n"
+"  - 'never', 'no', 'none'\n"
+"  - 'auto', 'tty', 'if-tty'\n"
+msgstr ""
+"%s: nieprawidłowy parametr „%s” dla „--color”\n"
+"prawidłowe parametry:\n"
+"  • „always”, „yes”, „force”\n"
+"  • „never”, „no”, „none”\n"
+"  • „auto”, „tty”, „if-tty”\n"
+
+#: lib/printversion.c:39
+#, c-format
+msgid ""
+"Copyright (C) %s The elfutils developers <%s>.\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+msgstr ""
+"Copyright © %s programiści projektu elfutils <%s>.\n"
+"Niniejszy program jest wolnym oprogramowaniem; proszę zobaczyć kod źródłowy\n"
+"w celu poznania warunków kopiowania. Niniejszy program rozprowadzany jest\n"
+"BEZ JAKIEJKOLWIEK GWARANCJI, nawet domyślnej gwarancji PRZYDATNOŚCI\n"
+"HANDLOWEJ albo PRZYDATNOŚCI DO OKREŚLONYCH ZASTOSOWAŃ.\n"
+
+#: lib/xmalloc.c:47 lib/xmalloc.c:60 lib/xmalloc.c:72 src/readelf.c:12203
+#: src/unstrip.c:311
+#, c-format
+msgid "memory exhausted"
+msgstr "pamięć wyczerpana"
+
+#: libasm/asm_error.c:64 libdw/dwarf_error.c:57 libdwfl/libdwflP.h:47
+#: libelf/elf_error.c:59
+msgid "no error"
+msgstr "brak błędu"
+
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:49
+#: libelf/elf_error.c:90
+msgid "out of memory"
+msgstr "brak pamięci"
+
+#: libasm/asm_error.c:66
+msgid "cannot create output file"
+msgstr "nie można utworzyć pliku wyjściowego"
+
+#: libasm/asm_error.c:67
+msgid "invalid parameter"
+msgstr "nieprawidłowy parametr"
+
+#: libasm/asm_error.c:68
+msgid "cannot change mode of output file"
+msgstr "nie można zmienić trybu pliku wyjściowego"
+
+#: libasm/asm_error.c:69
+msgid "cannot rename output file"
+msgstr "nie można zmienić nazwy pliku wyjściowego"
+
+#: libasm/asm_error.c:70
+msgid "duplicate symbol"
+msgstr "powtórzony symbol"
+
+#: libasm/asm_error.c:71
+msgid "invalid section type for operation"
+msgstr "nieprawidłowy typ sekcji dla działania"
+
+#: libasm/asm_error.c:72
+msgid "error during output of data"
+msgstr "błąd podczas wyprowadzania danych"
+
+#: libasm/asm_error.c:73
+msgid "no backend support available"
+msgstr "brak dostępnej obsługi zaplecza"
+
+#: libasm/asm_error.c:82 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:48
+#: libelf/elf_error.c:62
+msgid "unknown error"
+msgstr "nieznany błąd"
+
+#: libcpu/i386_lex.l:121
+#, c-format
+msgid "invalid character '%c' at line %d; ignored"
+msgstr "nieprawidłowy znak „%c” w %d. wierszu; zignorowano"
+
+#: libcpu/i386_lex.l:122
+#, c-format
+msgid "invalid character '\\%o' at line %d; ignored"
+msgstr "nieprawidłowy znak „\\%o” w %d. wierszu; zignorowano"
+
+#: libcpu/i386_parse.y:555
+#, c-format
+msgid "while reading i386 CPU description: %s at line %d"
+msgstr "podczas odczytywania opisu procesora i386: %s w %d. wierszu"
+
+#: libdw/dwarf_error.c:59
+msgid "invalid access"
+msgstr "nieprawidłowy dostęp"
+
+#: libdw/dwarf_error.c:60
+msgid "no regular file"
+msgstr "nie jest zwykłym plikiem"
+
+#: libdw/dwarf_error.c:61
+msgid "I/O error"
+msgstr "błąd wejścia/wyjścia"
+
+#: libdw/dwarf_error.c:62
+msgid "invalid ELF file"
+msgstr "nieprawidłowy plik ELF"
+
+#: libdw/dwarf_error.c:63
+msgid "no DWARF information"
+msgstr "brak informacji DWARF"
+
+#: libdw/dwarf_error.c:64
+msgid "cannot decompress DWARF"
+msgstr "nie można dekompresować DWARF"
+
+#: libdw/dwarf_error.c:65
+msgid "no ELF file"
+msgstr "brak pliku ELF"
+
+#: libdw/dwarf_error.c:66
+msgid "cannot get ELF header"
+msgstr "nie można uzyskać nagłówka ELF"
+
+#: libdw/dwarf_error.c:68
+msgid "not implemented"
+msgstr "niezaimplementowane"
+
+#: libdw/dwarf_error.c:69 libelf/elf_error.c:110 libelf/elf_error.c:158
+msgid "invalid command"
+msgstr "nieprawidłowe polecenie"
+
+#: libdw/dwarf_error.c:70
+msgid "invalid version"
+msgstr "nieprawidłowa wersja"
+
+#: libdw/dwarf_error.c:71
+msgid "invalid file"
+msgstr "nieprawidłowy plik"
+
+#: libdw/dwarf_error.c:72
+msgid "no entries found"
+msgstr "nie odnaleziono wpisów"
+
+#: libdw/dwarf_error.c:73
+msgid "invalid DWARF"
+msgstr "nieprawidłowy DWARF"
+
+#: libdw/dwarf_error.c:74
+msgid "no string data"
+msgstr "brak danych w postaci ciągu"
+
+#: libdw/dwarf_error.c:75
+msgid ".debug_str section missing"
+msgstr "brak sekcji .debug_str"
+
+#: libdw/dwarf_error.c:76
+msgid ".debug_line_str section missing"
+msgstr "brak sekcji .debug_line_str"
+
+#: libdw/dwarf_error.c:77
+msgid ".debug_str_offsets section missing"
+msgstr "brak sekcji .debug_str_offsets"
+
+#: libdw/dwarf_error.c:78
+msgid "no address value"
+msgstr "brak wartości adresu"
+
+#: libdw/dwarf_error.c:79
+msgid "no constant value"
+msgstr "brak wartości stałej"
+
+#: libdw/dwarf_error.c:80
+msgid "no reference value"
+msgstr "brak wartości odwołania"
+
+#: libdw/dwarf_error.c:81
+msgid "invalid reference value"
+msgstr "nieprawidłowa wartość odwołania"
+
+#: libdw/dwarf_error.c:82
+msgid ".debug_line section missing"
+msgstr "brak sekcji .debug_line"
+
+#: libdw/dwarf_error.c:83
+msgid "invalid .debug_line section"
+msgstr "nieprawidłowa sekcja .debug_line"
+
+#: libdw/dwarf_error.c:84
+msgid "debug information too big"
+msgstr "informacje debugowania są za duże"
+
+#: libdw/dwarf_error.c:85
+msgid "invalid DWARF version"
+msgstr "nieprawidłowa wersja DWARF"
+
+#: libdw/dwarf_error.c:86
+msgid "invalid directory index"
+msgstr "nieprawidłowy indeks katalogu"
+
+#: libdw/dwarf_error.c:87 libdwfl/libdwflP.h:69
+msgid "address out of range"
+msgstr "adres jest spoza zakresu"
+
+#: libdw/dwarf_error.c:88
+msgid ".debug_loc section missing"
+msgstr "brak sekcji .debug_loc"
+
+#: libdw/dwarf_error.c:89
+msgid ".debug_loclists section missing"
+msgstr "brak sekcji .debug_loclists"
+
+#: libdw/dwarf_error.c:90
+msgid "not a location list value"
+msgstr "nie jest wartością listy położeń"
+
+#: libdw/dwarf_error.c:91
+msgid "no block data"
+msgstr "brak danych blokowych"
+
+#: libdw/dwarf_error.c:92
+msgid "invalid line index"
+msgstr "nieprawidłowy indeks wiersza"
+
+#: libdw/dwarf_error.c:93
+msgid "invalid address range index"
+msgstr "nieprawidłowy indeks zakresu adresów"
+
+#: libdw/dwarf_error.c:94 libdwfl/libdwflP.h:70
+msgid "no matching address range"
+msgstr "brak pasującego zakresu adresów"
+
+#: libdw/dwarf_error.c:95
+msgid "no flag value"
+msgstr "brak wartości flagi"
+
+#: libdw/dwarf_error.c:96 libelf/elf_error.c:235
+msgid "invalid offset"
+msgstr "nieprawidłowy offset"
+
+#: libdw/dwarf_error.c:97
+msgid ".debug_ranges section missing"
+msgstr "brak sekcji .debug_ranges"
+
+#: libdw/dwarf_error.c:98
+msgid ".debug_rnglists section missing"
+msgstr "brak sekcji .debug_rnglists"
+
+#: libdw/dwarf_error.c:99
+msgid "invalid CFI section"
+msgstr "nieprawidłowa wersja CFI"
+
+#: libdw/dwarf_error.c:100
+msgid "no alternative debug link found"
+msgstr "nie odnaleziono alternatywnego dowiązania debugowania"
+
+#: libdw/dwarf_error.c:101
+msgid "invalid opcode"
+msgstr "nieprawidłowa instrukcja"
+
+#: libdw/dwarf_error.c:102
+msgid "not a CU (unit) DIE"
+msgstr "nie jest CU (jednostką) DIE"
+
+#: libdw/dwarf_error.c:103
+msgid "unknown language code"
+msgstr "nieznany kod języka"
+
+#: libdw/dwarf_error.c:104
+msgid ".debug_addr section missing"
+msgstr "brak sekcji .debug_addr"
+
+#: libdw/dwarf_error.c:105
+#, fuzzy
+#| msgid "unknown version"
+msgid "unknown section"
+msgstr "nieznana wersja"
+
+#: libdwfl/argp-std.c:45 src/stack.c:643 src/unstrip.c:2598
+msgid "Input selection options:"
+msgstr "Opcje wyboru wejścia:"
+
+#: libdwfl/argp-std.c:46
+msgid "Find addresses in FILE"
+msgstr "Wyszukuje adresy w PLIKU"
+
+#: libdwfl/argp-std.c:48
+msgid "Find addresses from signatures found in COREFILE"
+msgstr "Wyszukuje adresy z podpisów odnalezionych w PLIKU-CORE"
+
+#: libdwfl/argp-std.c:50
+msgid "Find addresses in files mapped into process PID"
+msgstr "Wyszukuje adresy w plikach zmapowanych do PID procesów"
+
+#: libdwfl/argp-std.c:52
+msgid ""
+"Find addresses in files mapped as read from FILE in Linux /proc/PID/maps "
+"format"
+msgstr ""
+"Wyszukuje adresy w plikach zmapowanych jako odczyt z PLIKU w formacie /proc/"
+"PID/maps systemu Linux"
+
+#: libdwfl/argp-std.c:54
+msgid "Find addresses in the running kernel"
+msgstr "Wyszukuje adresy w uruchomionych jądrze"
+
+#: libdwfl/argp-std.c:56
+msgid "Kernel with all modules"
+msgstr "Jądro ze wszystkimi modułami"
+
+#: libdwfl/argp-std.c:58 src/stack.c:650
+msgid "Search path for separate debuginfo files"
+msgstr "Wyszukuje ścieżkę dla oddzielnych plików debuginfo"
+
+#: libdwfl/argp-std.c:159
+msgid "only one of -e, -p, -k, -K, or --core allowed"
+msgstr "dopuszczalna jest tylko jedna z opcji -e, -p, -k, -K lub --core"
+
+#: libdwfl/argp-std.c:232
+msgid "cannot load kernel symbols"
+msgstr "nie można wczytać symboli jądra"
+
+#. Non-fatal to have no modules since we do have the kernel.
+#: libdwfl/argp-std.c:236
+msgid "cannot find kernel modules"
+msgstr "nie można odnaleźć modułów jądra"
+
+#: libdwfl/argp-std.c:253
+msgid "cannot find kernel or modules"
+msgstr "nie można odnaleźć jądra lub modułów"
+
+#: libdwfl/argp-std.c:292
+#, c-format
+msgid "cannot read ELF core file: %s"
+msgstr "nie można odczytać pliku core ELF: %s"
+
+#: libdwfl/argp-std.c:315
+msgid "Not enough memory"
+msgstr "Za mało pamięci"
+
+#: libdwfl/argp-std.c:325
+msgid "No modules recognized in core file"
+msgstr "Nie rozpoznano żadnych modułów w pliku core"
+
+#: libdwfl/libdwflP.h:50
+msgid "See errno"
+msgstr "Proszę zobaczyć errno"
+
+#: libdwfl/libdwflP.h:51
+msgid "See elf_errno"
+msgstr "Proszę zobaczyć elf_errno"
+
+#: libdwfl/libdwflP.h:52
+msgid "See dwarf_errno"
+msgstr "Proszę zobaczyć dwarf_errno"
+
+#: libdwfl/libdwflP.h:53
+msgid "See ebl_errno (XXX missing)"
+msgstr "Proszę zobaczyć ebl_errno (brak XXX)"
+
+#: libdwfl/libdwflP.h:54
+msgid "gzip decompression failed"
+msgstr "dekompresja gzip się nie powiodła"
+
+#: libdwfl/libdwflP.h:55
+msgid "bzip2 decompression failed"
+msgstr "dekompresja bzip2 się nie powiodła"
+
+#: libdwfl/libdwflP.h:56
+msgid "LZMA decompression failed"
+msgstr "dekompresja LZMA się nie powiodła"
+
+#: libdwfl/libdwflP.h:57
+msgid "zstd decompression failed"
+msgstr "dekompresja zstd się nie powiodła"
+
+#: libdwfl/libdwflP.h:58
+msgid "no support library found for machine"
+msgstr "nie odnaleziono biblioteki obsługi dla komputera"
+
+#: libdwfl/libdwflP.h:59
+msgid "Callbacks missing for ET_REL file"
+msgstr "Brak wywołań zwrotnych dla pliku ET_REL"
+
+#: libdwfl/libdwflP.h:60
+msgid "Unsupported relocation type"
+msgstr "Nieobsługiwany typ relokacji"
+
+#: libdwfl/libdwflP.h:61
+msgid "r_offset is bogus"
+msgstr "r_offset jest fałszywe"
+
+#: libdwfl/libdwflP.h:62 libelf/elf_error.c:114 libelf/elf_error.c:174
+msgid "offset out of range"
+msgstr "offset spoza zakresu"
+
+#: libdwfl/libdwflP.h:63
+msgid "relocation refers to undefined symbol"
+msgstr "relokacja odnosi się do nieokreślonego symbolu"
+
+#: libdwfl/libdwflP.h:64
+msgid "Callback returned failure"
+msgstr "Wywołanie zwrotne zwróciło niepowodzenie"
+
+#: libdwfl/libdwflP.h:65
+msgid "No DWARF information found"
+msgstr "Nie odnaleziono informacji DWARF"
+
+#: libdwfl/libdwflP.h:66
+msgid "No symbol table found"
+msgstr "Nie odnaleziono tabeli symboli"
+
+#: libdwfl/libdwflP.h:67
+msgid "No ELF program headers"
+msgstr "Brak nagłówków programu ELF"
+
+#: libdwfl/libdwflP.h:68
+msgid "address range overlaps an existing module"
+msgstr "zakres adresów pokrywa się z istniejącym modułem"
+
+#: libdwfl/libdwflP.h:71
+msgid "image truncated"
+msgstr "skrócono obraz"
+
+#: libdwfl/libdwflP.h:72
+msgid "ELF file opened"
+msgstr "otwarto plik ELF"
+
+#: libdwfl/libdwflP.h:73
+msgid "not a valid ELF file"
+msgstr "nie jest prawidłowym plikiem ELF"
+
+#: libdwfl/libdwflP.h:74
+msgid "cannot handle DWARF type description"
+msgstr "nie można obsłużyć opisu typu DWARF"
+
+#: libdwfl/libdwflP.h:75
+msgid "ELF file does not match build ID"
+msgstr "plik ELF nie ma pasującego identyfikatora kopii"
+
+#: libdwfl/libdwflP.h:76
+msgid "corrupt .gnu.prelink_undo section data"
+msgstr "uszkodzone dane sekcji .gnu.prelink_undo"
+
+#: libdwfl/libdwflP.h:77
+msgid "Internal error due to ebl"
+msgstr "Wewnętrzny błąd z powodu ebl"
+
+#: libdwfl/libdwflP.h:78
+msgid "Missing data in core file"
+msgstr "Brak danych w pliku core"
+
+#: libdwfl/libdwflP.h:79
+msgid "Invalid register"
+msgstr "Nieprawidłowy rejestr"
+
+#: libdwfl/libdwflP.h:80
+#, fuzzy
+#| msgid "no reference value"
+msgid "Unknown register value"
+msgstr "brak wartości odwołania"
+
+#: libdwfl/libdwflP.h:81
+msgid "Error reading process memory"
+msgstr "Błąd podczas odczytywania pamięci procesu"
+
+#: libdwfl/libdwflP.h:82
+msgid "Couldn't find architecture of any ELF"
+msgstr "Nie można odnaleźć architektury żadnego ELF"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error parsing /proc filesystem"
+msgstr "Błąd podczas przetwarzania systemu plików /proc"
+
+#: libdwfl/libdwflP.h:84
+msgid "Invalid DWARF"
+msgstr "Nieprawidłowy DWARF"
+
+#: libdwfl/libdwflP.h:85
+msgid "Unsupported DWARF"
+msgstr "Nieobsługiwany DWARF"
+
+#: libdwfl/libdwflP.h:86
+msgid "Unable to find more threads"
+msgstr "Nie można odnaleźć więcej wątków"
+
+#: libdwfl/libdwflP.h:87
+msgid "Dwfl already has attached state"
+msgstr "Dwfl już ma załączony stan"
+
+#: libdwfl/libdwflP.h:88
+msgid "Dwfl has no attached state"
+msgstr "Dwfl nie ma załączonego stanu"
+
+#: libdwfl/libdwflP.h:89
+msgid "Unwinding not supported for this architecture"
+msgstr "Odwijanie nie jest obsługiwane dla tej architektury"
+
+#: libdwfl/libdwflP.h:90
+msgid "Invalid argument"
+msgstr "Nieprawidłowy parametr"
+
+#: libdwfl/libdwflP.h:91
+msgid "Not an ET_CORE ELF file"
+msgstr "Nie jest plikiem ELF ET_CORE"
+
+#: libebl/eblbackendname.c:41
+msgid "No backend"
+msgstr "Brak zaplecza"
+
+#: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:79
+#: libebl/eblobjnotetypename.c:113 libebl/eblobjnotetypename.c:134
+#: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83
+#: libebl/eblsectiontypename.c:116 libebl/eblsegmenttypename.c:81
+msgid "<unknown>"
+msgstr "<nieznany>"
+
+#: libebl/ebldynamictagname.c:103
+#, c-format
+msgid "<unknown>: %#<PRIx64>"
+msgstr "<nieznany>: %#<PRIx64>"
+
+#: libebl/eblobjnote.c:58
+#, c-format
+msgid "unknown SDT version %u\n"
+msgstr "nieznana wersja SDT %u\n"
+
+#: libebl/eblobjnote.c:76
+#, c-format
+msgid "invalid SDT probe descriptor\n"
+msgstr "nieprawidłowy deskryptor sondy SDT\n"
+
+#: libebl/eblobjnote.c:126
+#, c-format
+msgid "    PC: "
+msgstr "    PC: "
+
+#: libebl/eblobjnote.c:128
+#, c-format
+msgid " Base: "
+msgstr " Podstawa: "
+
+#: libebl/eblobjnote.c:130
+#, c-format
+msgid " Semaphore: "
+msgstr " Semafor: "
+
+#: libebl/eblobjnote.c:132
+#, c-format
+msgid "    Provider: "
+msgstr "    Dostawca: "
+
+#: libebl/eblobjnote.c:134
+#, c-format
+msgid " Name: "
+msgstr " Nazwa: "
+
+#: libebl/eblobjnote.c:136
+#, c-format
+msgid " Args: "
+msgstr " Parametry: "
+
+#: libebl/eblobjnote.c:304
+#, c-format
+msgid "    Build ID: "
+msgstr "    Identyfikator kopii: "
+
+#. A non-null terminated version string.
+#: libebl/eblobjnote.c:315
+#, c-format
+msgid "    Linker version: %.*s\n"
+msgstr "    Wersja konsolidatora: %.*s\n"
+
+#: libebl/eblobjnote.c:642
+#, c-format
+msgid "    OS: %s, ABI: "
+msgstr "    System operacyjny: %s, ABI: "
+
+#: libebl/eblosabiname.c:70
+msgid "Stand alone"
+msgstr "Samodzielny"
+
+#: libebl/eblsymbolbindingname.c:68 libebl/eblsymboltypename.c:74
+#, c-format
+msgid "<unknown>: %d"
+msgstr "<nieznany>: %d"
+
+#: libelf/elf_error.c:66
+msgid "unknown version"
+msgstr "nieznana wersja"
+
+#: libelf/elf_error.c:70
+msgid "unknown type"
+msgstr "nieznany typ"
+
+#: libelf/elf_error.c:74
+msgid "invalid `Elf' handle"
+msgstr "nieprawidłowa obsługa „Elf”"
+
+#: libelf/elf_error.c:78
+msgid "invalid size of source operand"
+msgstr "nieprawidłowy rozmiar operandu źródłowego"
+
+#: libelf/elf_error.c:82
+msgid "invalid size of destination operand"
+msgstr "nieprawidłowy rozmiar operandu docelowego"
+
+#: libelf/elf_error.c:86 src/readelf.c:6759
+#, c-format
+msgid "invalid encoding"
+msgstr "nieprawidłowe kodowanie"
+
+#: libelf/elf_error.c:94
+msgid "invalid file descriptor"
+msgstr "nieprawidłowy deskryptor pliku"
+
+#: libelf/elf_error.c:98
+msgid "invalid ELF file data"
+msgstr "nieprawidłowe dane pliku ELF"
+
+#: libelf/elf_error.c:102
+msgid "invalid operation"
+msgstr "nieprawidłowe działanie"
+
+#: libelf/elf_error.c:106
+msgid "ELF version not set"
+msgstr "wersja ELF nie została ustawiona"
+
+#: libelf/elf_error.c:118
+msgid "invalid fmag field in archive header"
+msgstr "nieprawidłowe pole fmag w nagłówku archiwum"
+
+#: libelf/elf_error.c:122
+msgid "invalid archive file"
+msgstr "nieprawidłowy plik archiwum"
+
+#: libelf/elf_error.c:126
+msgid "descriptor is not for an archive"
+msgstr "deskryptor nie jest dla archiwum"
+
+#: libelf/elf_error.c:130
+msgid "no index available"
+msgstr "brak dostępnego indeksu"
+
+#: libelf/elf_error.c:134
+msgid "cannot read data from file"
+msgstr "nie można odczytać danych z pliku"
+
+#: libelf/elf_error.c:138
+msgid "cannot write data to file"
+msgstr "nie można zapisać danych do pliku"
+
+#: libelf/elf_error.c:142
+msgid "invalid binary class"
+msgstr "nieprawidłowa klasa pliku binarnego"
+
+#: libelf/elf_error.c:146
+msgid "invalid section index"
+msgstr "nieprawidłowy indeks sekcji"
+
+#: libelf/elf_error.c:150
+msgid "invalid operand"
+msgstr "nieprawidłowy operand"
+
+#: libelf/elf_error.c:154
+msgid "invalid section"
+msgstr "nieprawidłowa sekcja"
+
+#: libelf/elf_error.c:162
+msgid "executable header not created first"
+msgstr "nie utworzono najpierw nagłówka pliku wykonywalnego"
+
+#: libelf/elf_error.c:166
+msgid "file descriptor disabled"
+msgstr "deskryptor pliku jest wyłączony"
+
+#: libelf/elf_error.c:170
+msgid "archive/member file descriptor mismatch"
+msgstr "deskryptory archiwum/elementu nie zgadzają się"
+
+#: libelf/elf_error.c:178
+msgid "cannot manipulate null section"
+msgstr "nie można zmieniać pustej sekcji"
+
+#: libelf/elf_error.c:182
+msgid "data/scn mismatch"
+msgstr "dane/scn nie zgadzają się"
+
+#: libelf/elf_error.c:186
+msgid "invalid section header"
+msgstr "nieprawidłowy nagłówek sekcji"
+
+#: libelf/elf_error.c:190 src/readelf.c:10638 src/readelf.c:11243
+#: src/readelf.c:11344 src/readelf.c:11532
+#, c-format
+msgid "invalid data"
+msgstr "nieprawidłowe dane"
+
+#: libelf/elf_error.c:194
+msgid "unknown data encoding"
+msgstr "nieznane kodowanie danych"
+
+#: libelf/elf_error.c:198
+msgid "section `sh_size' too small for data"
+msgstr "sekcja „sh_size” jest za mała dla danych"
+
+#: libelf/elf_error.c:202
+msgid "invalid section alignment"
+msgstr "nieprawidłowe wyrównanie sekcji"
+
+#: libelf/elf_error.c:206
+msgid "invalid section entry size"
+msgstr "nieprawidłowy rozmiar wpisu sekcji"
+
+#: libelf/elf_error.c:210
+msgid "update() for write on read-only file"
+msgstr "update() dla zapisu pliku tylko do odczytu"
+
+#: libelf/elf_error.c:214
+msgid "no such file"
+msgstr "nie ma takiego pliku"
+
+#: libelf/elf_error.c:218
+msgid "only relocatable files can contain section groups"
+msgstr "tylko relokowalne pliki mogą zawierać grupy sekcji"
+
+#: libelf/elf_error.c:223
+msgid ""
+"program header only allowed in executables, shared objects, and core files"
+msgstr ""
+"tylko pliki wykonywalne, obiektów współdzielone i pliki core mogą mieć "
+"nagłówki programu"
+
+#: libelf/elf_error.c:230
+msgid "file has no program header"
+msgstr "plik nie ma nagłówków programu"
+
+#: libelf/elf_error.c:240
+msgid "invalid section type"
+msgstr "nieprawidłowy typ sekcji"
+
+#: libelf/elf_error.c:245
+msgid "invalid section flags"
+msgstr "nieprawidłowe flagi sekcji"
+
+#: libelf/elf_error.c:250
+msgid "section does not contain compressed data"
+msgstr "sekcja nie zawiera skompresowanych danych"
+
+#: libelf/elf_error.c:255
+msgid "section contains compressed data"
+msgstr "sekcja zawiera skompresowane dane"
+
+#: libelf/elf_error.c:260
+msgid "unknown compression type"
+msgstr "nieznany typ kompresji"
+
+#: libelf/elf_error.c:265
+msgid "cannot compress data"
+msgstr "nie można kompresować danych"
+
+#: libelf/elf_error.c:270
+msgid "cannot decompress data"
+msgstr "nie można dekompresować danych"
+
+#: src/addr2line.c:58
+msgid "Input format options:"
+msgstr "Opcje formatowania wejścia:"
+
+#: src/addr2line.c:60
+msgid "Treat addresses as offsets relative to NAME section."
+msgstr "Traktuje adresy jako offsety względne do sekcji NAZWA."
+
+#: src/addr2line.c:62
+msgid "Output format options:"
+msgstr "Opcje formatowania wyjścia:"
+
+#: src/addr2line.c:63
+msgid "Print address before each entry"
+msgstr "Wyświetla adres pliku przed każdym wpisem"
+
+#: src/addr2line.c:64
+msgid "Show only base names of source files"
+msgstr "Wyświetla tylko podstawowe nazwy plików źródłowych"
+
+#: src/addr2line.c:66
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show absolute file names using compilation directory (default)"
+msgstr "Wyświetla bezwzględne nazwy plików używając katalogu kompilacji"
+
+#: src/addr2line.c:67
+msgid "Also show function names"
+msgstr "Wyświetla także nazwy funkcji"
+
+#: src/addr2line.c:68
+msgid "Also show symbol or section names"
+msgstr "Wyświetla także nazwy symboli lub sekcji"
+
+#: src/addr2line.c:69
+msgid "Also show symbol and the section names"
+msgstr "Wyświetla także nazwy symboli i sekcji"
+
+#: src/addr2line.c:70
+msgid "Also show line table flags"
+msgstr "Wyświetla także flagi tabeli wierszy"
+
+#: src/addr2line.c:72
+msgid ""
+"Show all source locations that caused inline expansion of subroutines at the "
+"address."
+msgstr ""
+"Wyświetla wszystkie położenia źródłowe, które spowodowały wstawione "
+"rozszerzenie podprogramów pod tym adresem."
+
+#: src/addr2line.c:75
+msgid "Show demangled symbols (ARG is always ignored)"
+msgstr ""
+"Wyświetla symbole z usuniętym dekorowaniem (PARAMETR jest zawsze ignorowany)"
+
+#: src/addr2line.c:76
+#, fuzzy
+#| msgid "Show demangled symbols (ARG is always ignored)"
+msgid "Show demangled symbols"
+msgstr ""
+"Wyświetla symbole z usuniętym dekorowaniem (PARAMETR jest zawsze ignorowany)"
+
+#: src/addr2line.c:78
+msgid "Print all information on one line, and indent inlines"
+msgstr "Wyświetla wszystkie informacje w jednym wierszy i wyrównuje wstawki"
+
+#: src/addr2line.c:80
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show relative file names without compilation directory"
+msgstr "Wyświetla bezwzględne nazwy plików używając katalogu kompilacji"
+
+#: src/addr2line.c:82 src/elfcmp.c:69 src/findtextrel.c:65 src/nm.c:99
+#: src/strings.c:77
+msgid "Miscellaneous:"
+msgstr "Różne:"
+
+#. Short description of program.
+#: src/addr2line.c:90
+msgid ""
+"Locate source files and line information for ADDRs (in a.out by default)."
+msgstr ""
+"Odnajdywanie plików źródłowych i informacji o wierszu dla ADRESU (domyślne "
+"w a.out)."
+
+#. Strings for arguments in help texts.
+#: src/addr2line.c:94
+msgid "[ADDR...]"
+msgstr "[ADRES…]"
+
+#: src/addr2line.c:530
+msgid "Section syntax requires exactly one module"
+msgstr "Składnia sekcji wymaga dokładnie jednego modułu"
+
+#: src/addr2line.c:552
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside section '%s'"
+msgstr "offset %#<PRIxMAX> leży poza sekcją „%s”"
+
+#: src/addr2line.c:662
+#, c-format
+msgid "cannot find symbol '%s'"
+msgstr "nie można odnaleźć symbolu „%s”"
+
+#: src/addr2line.c:667
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
+msgstr "offset %#<PRIxMAX> leży poza zawartością „%s”"
+
+#: src/ar.c:66
+msgid "Commands:"
+msgstr "Polecenia:"
+
+#: src/ar.c:67
+msgid "Delete files from archive."
+msgstr "Usuwa pliki z archiwum."
+
+#: src/ar.c:68
+msgid "Move files in archive."
+msgstr "Przenosi pliki w archiwum."
+
+#: src/ar.c:69
+msgid "Print files in archive."
+msgstr "Wyświetla pliki w archiwum."
+
+#: src/ar.c:70
+msgid "Quick append files to archive."
+msgstr "Szybko dodaje pliki do archiwum."
+
+#: src/ar.c:72
+msgid "Replace existing or insert new file into archive."
+msgstr "Zastępuje istniejący lub umieszcza nowy plik w archiwum."
+
+#: src/ar.c:73
+msgid "Display content of archive."
+msgstr "Wyświetla zawartość archiwum."
+
+#: src/ar.c:74
+msgid "Extract files from archive."
+msgstr "Wypakowuje pliki z archiwum."
+
+#: src/ar.c:76
+msgid "Command Modifiers:"
+msgstr "Modyfikatory poleceń:"
+
+#: src/ar.c:77
+msgid "Preserve original dates."
+msgstr "Zachowuje pierwotne daty."
+
+#: src/ar.c:78
+msgid "Use instance [COUNT] of name."
+msgstr "Używa wystąpienia [LICZNIK] nazwy."
+
+#: src/ar.c:80
+msgid "Do not replace existing files with extracted files."
+msgstr "Nie zastępuje istniejących plików wypakowanymi plikami."
+
+#: src/ar.c:81
+msgid "Allow filename to be truncated if necessary."
+msgstr "Zezwala na skrócenie nazwy pliku, jeśli jest to wymagane."
+
+#: src/ar.c:83
+msgid "Provide verbose output."
+msgstr "Wyświetla więcej informacji."
+
+#: src/ar.c:84
+msgid "Force regeneration of symbol table."
+msgstr "Wymusza ponowne utworzenie tabeli symboli."
+
+#: src/ar.c:85
+msgid "Insert file after [MEMBER]."
+msgstr "Umieszcza plik po [ELEMENCIE]."
+
+#: src/ar.c:86
+msgid "Insert file before [MEMBER]."
+msgstr "Umieszcza plik przed [ELEMENTEM]."
+
+#: src/ar.c:87
+msgid "Same as -b."
+msgstr "To samo, co -b."
+
+#: src/ar.c:88
+msgid "Suppress message when library has to be created."
+msgstr "Zmniejsza komunikat, jeśli biblioteka musi zostać utworzona."
+
+#: src/ar.c:90
+msgid "Use full path for file matching."
+msgstr "Używa pełnej ścieżki do dopasowywania plików."
+
+#: src/ar.c:91
+msgid "Update only older files in archive."
+msgstr "Aktualizuje tylko starsze pliki w archiwum."
+
+#. Short description of program.
+#: src/ar.c:97
+msgid "Create, modify, and extract from archives."
+msgstr "Tworzenie, modyfikowanie i wypakowywanie archiwów."
+
+#. Strings for arguments in help texts.
+#: src/ar.c:100
+msgid "[MEMBER] [COUNT] ARCHIVE [FILE...]"
+msgstr "[ELEMENT] [LICZNIK] ARCHIWUM [PLIK…]"
+
+#: src/ar.c:179
+#, c-format
+msgid "'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"
+msgstr "„a”, „b” i „i” są dozwolone tylko z opcjami „m” i „r”"
+
+#: src/ar.c:184
+#, c-format
+msgid "MEMBER parameter required for 'a', 'b', and 'i' modifiers"
+msgstr "parametr ELEMENT jest wymagany dla modyfikatorów „a”, „b” i „i”"
+
+#: src/ar.c:200
+#, c-format
+msgid "'N' is only meaningful with the 'x' and 'd' options"
+msgstr "„N” ma znaczenie tylko z opcjami „x” i „d”"
+
+#: src/ar.c:205
+#, c-format
+msgid "COUNT parameter required"
+msgstr "wymagany jest parametr LICZNIK"
+
+#: src/ar.c:217
+#, c-format
+msgid "invalid COUNT parameter %s"
+msgstr "nieprawidłowy parametr LICZNIK %s"
+
+#: src/ar.c:224
+#, c-format
+msgid "'%c' is only meaningful with the 'x' option"
+msgstr "„%c” ma znaczenie tylko z opcją „x”"
+
+#: src/ar.c:230
+#, c-format
+msgid "archive name required"
+msgstr "wymagana jest nazwa archiwum"
+
+#: src/ar.c:243
+#, c-format
+msgid "command option required"
+msgstr "wymagana jest opcja polecenia"
+
+#: src/ar.c:294
+#, c-format
+msgid "More than one operation specified"
+msgstr "Podano więcej niż jedno działanie"
+
+#: src/ar.c:388
+#, c-format
+msgid "cannot open archive '%s'"
+msgstr "nie można otworzyć archiwum „%s”"
+
+#: src/ar.c:398
+#, c-format
+msgid "cannot open archive '%s': %s"
+msgstr "nie można otworzyć archiwum „%s”: %s"
+
+#: src/ar.c:402
+#, c-format
+msgid "%s: not an archive file"
+msgstr "%s: nie jest plikiem archiwum"
+
+#: src/ar.c:406
+#, c-format
+msgid "cannot stat archive '%s'"
+msgstr "nie można wykonać stat na archiwum „%s”"
+
+#: src/ar.c:418
+#, c-format
+msgid "no entry %s in archive\n"
+msgstr "brak wpisu %s w archiwum\n"
+
+#: src/ar.c:471 src/ar.c:925 src/ar.c:1131
+msgid "cannot create hash table"
+msgstr "nie można utworzyć tabeli mieszającej"
+
+#: src/ar.c:477 src/ar.c:931 src/ar.c:1139
+msgid "cannot insert into hash table"
+msgstr "nie można umieścić w tabeli mieszającej"
+
+#: src/ar.c:485 src/ranlib.c:147
+#, c-format
+msgid "cannot stat '%s'"
+msgstr "nie można wykonać stat na „%s”"
+
+#: src/ar.c:587
+#, c-format
+msgid "cannot read content of %s: %s"
+msgstr "nie można odczytać zawartości %s: %s"
+
+#: src/ar.c:630
+#, c-format
+msgid "cannot open %.*s"
+msgstr "nie można otworzyć %.*s"
+
+#: src/ar.c:652
+#, c-format
+msgid "failed to write %s"
+msgstr "zapisanie %s się nie powiodło"
+
+#: src/ar.c:664
+#, c-format
+msgid "cannot change mode of %s"
+msgstr "nie można zmienić trybu %s"
+
+#: src/ar.c:680
+#, c-format
+msgid "cannot change modification time of %s"
+msgstr "nie można zmienić czasu modyfikacji %s"
+
+#: src/ar.c:726
+#, c-format
+msgid "cannot rename temporary file to %.*s"
+msgstr "nie można zmienić nazwy pliku tymczasowego na %.*s"
+
+#: src/ar.c:762 src/ar.c:1016 src/ar.c:1419 src/ranlib.c:221
+#, c-format
+msgid "cannot create new file"
+msgstr "nie można utworzyć nowego pliku"
+
+#: src/ar.c:1221
+#, c-format
+msgid "position member %s not found"
+msgstr "nie odnaleziono położenia elementu %s"
+
+#: src/ar.c:1231
+#, c-format
+msgid "%s: no entry %s in archive!\n"
+msgstr "%s: brak wpisu %s w archiwum.\n"
+
+#: src/ar.c:1260 src/objdump.c:240
+#, c-format
+msgid "cannot open %s"
+msgstr "nie można otworzyć %s"
+
+#: src/ar.c:1265
+#, c-format
+msgid "cannot stat %s"
+msgstr "nie można wykonać stat na %s"
+
+#: src/ar.c:1271
+#, c-format
+msgid "%s is no regular file"
+msgstr "%s nie jest zwykłym plikiem"
+
+#: src/ar.c:1284
+#, c-format
+msgid "cannot get ELF descriptor for %s: %s\n"
+msgstr "nie można uzyskać deskryptora ELF dla %s: %s\n"
+
+#: src/ar.c:1304
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "nie można odczytać %s: %s"
+
+#: src/ar.c:1479
+#, c-format
+msgid "cannot represent ar_date"
+msgstr "nie można przedstawić ar_date"
+
+#: src/ar.c:1485
+#, c-format
+msgid "cannot represent ar_uid"
+msgstr "nie można przedstawić ar_uid"
+
+#: src/ar.c:1491
+#, c-format
+msgid "cannot represent ar_gid"
+msgstr "nie można przedstawić ar_gid"
+
+#: src/ar.c:1497
+#, c-format
+msgid "cannot represent ar_mode"
+msgstr "nie można przedstawić ar_mode"
+
+#: src/ar.c:1503
+#, c-format
+msgid "cannot represent ar_size"
+msgstr "nie można przedstawić ar_size"
+
+#: src/arlib-argp.c:31
+msgid "Use zero for uid, gid, and date in archive members."
+msgstr "Używa zero jako UID, GID i datę w elementach archiwum."
+
+#: src/arlib-argp.c:33
+msgid "Use actual uid, gid, and date in archive members."
+msgstr "Używa prawdziwe UID, GID i datę w elementach archiwum."
+
+#: src/arlib-argp.c:62
+#, c-format
+msgid "%s (default)"
+msgstr "%s (domyślnie)"
+
+#. The archive is too big.
+#: src/arlib.c:212
+#, c-format
+msgid "the archive '%s' is too large"
+msgstr "archiwum „%s” jest za duże"
+
+#: src/arlib.c:225
+#, c-format
+msgid "cannot read ELF header of %s(%s): %s"
+msgstr "nie można odczytać nagłówka ELF %s(%s): %s"
+
+#: src/elfclassify.c:91
+msgid "opening"
+msgstr "otwieranie"
+
+#: src/elfclassify.c:98
+msgid "reading"
+msgstr "odczytywanie"
+
+#: src/elfclassify.c:244
+msgid "ELF header"
+msgstr "nagłówek ELF"
+
+#: src/elfclassify.c:255
+msgid "program headers"
+msgstr "nagłówki programu"
+
+#: src/elfclassify.c:264
+msgid "program header"
+msgstr "nagłówek programu"
+
+#: src/elfclassify.c:284
+msgid "section headers"
+msgstr "nagłówki sekcji"
+
+#: src/elfclassify.c:295
+msgid "section header string table index"
+msgstr "sekcja nagłówek ciąg tabela indeks"
+
+#: src/elfclassify.c:309
+msgid "could not obtain section header"
+msgstr "nie można uzyskać nagłówka sekcji"
+
+#: src/elfclassify.c:315
+msgid "could not obtain section name"
+msgstr "nie można uzyskać nazwy sekcji"
+
+#: src/elfclassify.c:828
+msgid "writing to standard output"
+msgstr "zapisywanie do standardowego wyjścia"
+
+#: src/elfclassify.c:855
+msgid "reading from standard input"
+msgstr "odczytywanie ze standardowego wejścia"
+
+#: src/elfclassify.c:876
+msgid "Classification options"
+msgstr "Opcje klasyfikacji"
+
+#: src/elfclassify.c:878
+msgid "File looks like an ELF object or archive/static library (default)"
+msgstr ""
+"Plik wygląda jak obiekt ELF lub archiwum/biblioteka statyczna (domyślnie)"
+
+#: src/elfclassify.c:881
+msgid "File is an regular ELF object (not an archive/static library)"
+msgstr ""
+"Plik jest zwykłym obiektem ELF (nie jest archiwum/biblioteką statyczną)"
+
+#: src/elfclassify.c:884
+msgid "File is an ELF archive or static library"
+msgstr "Plik jest archiwum lub biblioteką statyczną ELF"
+
+#: src/elfclassify.c:887
+msgid "File is an ELF core dump file"
+msgstr "Plik jest plikiem zrzutu core ELF"
+
+#: src/elfclassify.c:890
+msgid ""
+"File is an ELF file with symbol table or .debug_* sections and can be "
+"stripped further"
+msgstr ""
+"Plik jest plikiem ELF z tabelą symboli lub sekcjami .debug_* i może być "
+"dalej okrojony"
+
+#: src/elfclassify.c:893
+msgid "File is (primarily) an ELF program executable (not primarily a DSO)"
+msgstr "Plik jest (głównie) wykonywalnym programem ELF (nie jest głównie DSO)"
+
+#: src/elfclassify.c:896
+msgid "File is an ELF program executable (might also be a DSO)"
+msgstr "Plik jest wykonywalnym programem ELF (może być także DSO)"
+
+#: src/elfclassify.c:899
+msgid ""
+"File is (primarily) an ELF shared object (DSO) (not primarily an executable)"
+msgstr ""
+"Plik jest (głównie) obiektem współdzielonym ELF (DSO) (nie jest głównie "
+"plikiem wykonywalnym)"
+
+#: src/elfclassify.c:902
+msgid "File is an ELF shared object (DSO) (might also be an executable)"
+msgstr ""
+"Plik jest obiektem współdzielonym ELF (DSO) (może być także plikiem "
+"wykonywalnym)"
+
+#: src/elfclassify.c:906
+msgid "File is a linux kernel module"
+msgstr "Plik jest modułem jądra Linux"
+
+#: src/elfclassify.c:908
+msgid "File is a debug only ELF file (separate .debug, .dwo or dwz multi-file)"
+msgstr ""
+"Plik jest wyłącznie plikiem debugowania ELF (oddzielne .debug, .dwo lub "
+"wieloplikowe dwz)"
+
+#: src/elfclassify.c:911
+msgid "File is a loadable ELF object (program or shared object)"
+msgstr ""
+"Plik jest wczytywalnym obiektem ELF (programem lub obiektem współdzielonym)"
+
+#: src/elfclassify.c:940
+msgid "Input flags"
+msgstr "Flagi wejścia"
+
+#: src/elfclassify.c:942
+msgid "Only classify regular (not symlink nor special device) files"
+msgstr ""
+"Klasyfikuje tylko zwykłe (niebędące dowiązaniami symbolicznymi lub "
+"urządzeniami specjalnymi) pliki"
+
+#: src/elfclassify.c:944
+msgid ""
+"Also read file names to process from standard input, separated by newlines"
+msgstr ""
+"Odczytuje także nazwy plików do przetworzenia ze standardowego wejścia, "
+"rozdzielone znakami nowego wiersza"
+
+#: src/elfclassify.c:947
+msgid ""
+"Also read file names to process from standard input, separated by ASCII NUL "
+"bytes"
+msgstr ""
+"Odczytuje także nazwy plików do przetworzenia ze standardowego wejścia, "
+"rozdzielone bajtami NUL ASCII"
+
+#: src/elfclassify.c:950
+msgid "Do not read files from standard input (default)"
+msgstr "Bez odczytywania plików ze standardowego wejścia (domyślnie)"
+
+#: src/elfclassify.c:952
+msgid "Try to open compressed files or embedded (kernel) ELF images"
+msgstr "Próbuje otwierać skompresowane pliki lub osadzone obrazy ELF (jądra)"
+
+#: src/elfclassify.c:955
+msgid "Output flags"
+msgstr "Flagi wyjścia"
+
+#: src/elfclassify.c:957
+msgid "Output names of files, separated by newline"
+msgstr "Wyświetla nazwy plików, rozdzielone znakami nowego wiersza"
+
+#: src/elfclassify.c:959
+msgid "Output names of files, separated by ASCII NUL"
+msgstr "Wyświetla nazwy plików, rozdzielone znakami NUL ASCII"
+
+#: src/elfclassify.c:961
+msgid "Do not output file names"
+msgstr "Bez wyświetlania nazw plików"
+
+#: src/elfclassify.c:963
+msgid "If printing file names, print matching files (default)"
+msgstr "Podczas wyświetlana nazw plików wyświetla pasujące pliki (domyślnie)"
+
+#: src/elfclassify.c:965
+msgid "If printing file names, print files that do not match"
+msgstr "Podczas wyświetlania nazw plików wyświetla niepasujące pliki"
+
+#: src/elfclassify.c:967
+msgid "Additional flags"
+msgstr "Dodatkowe flagi"
+
+#: src/elfclassify.c:969
+msgid "Output additional information (can be specified multiple times)"
+msgstr "Wyświetla dodatkowe informacje (można podać wiele razy)"
+
+#: src/elfclassify.c:971
+msgid "Suppress some error output (counterpart to --verbose)"
+msgstr "Zmniejsza wyjście błędów (odpowiednik opcji --verbose)"
+
+#. Strings for arguments in help texts.
+#: src/elfclassify.c:979 src/elfcompress.c:1436 src/elflint.c:77
+#: src/readelf.c:161
+msgid "FILE..."
+msgstr "PLIK…"
+
+#: src/elfclassify.c:980
+msgid ""
+"Determine the type of an ELF file.\n"
+"\n"
+"All of the classification options must apply at the same time to a "
+"particular file.  Classification options can be negated using a \"--not-\" "
+"prefix.\n"
+"\n"
+"Since modern ELF does not clearly distinguish between programs and dynamic "
+"shared objects, you should normally use either --executable or --shared to "
+"identify the primary purpose of a file.  Only one of the --shared and --"
+"executable checks can pass for a file.\n"
+"\n"
+"If you want to know whether an ELF object might a program or a shared "
+"library (but could be both), then use --program or --library. Some ELF files "
+"will classify as both a program and a library.\n"
+"\n"
+"If you just want to know whether an ELF file is loadable (as program or "
+"library) use --loadable.  Note that files that only contain (separate) debug "
+"information (--debug-only) are never --loadable (even though they might "
+"contain program headers).  Linux kernel modules are also not --loadable (in "
+"the normal sense).\n"
+"\n"
+"Without any of the --print options, the program exits with status 0 if the "
+"requested checks pass for all input files, with 1 if a check fails for any "
+"file, and 2 if there is an environmental issue (such as a file read error or "
+"a memory allocation error).\n"
+"\n"
+"When printing file names, the program exits with status 0 even if no file "
+"names are printed, and exits with status 2 if there is an environmental "
+"issue.\n"
+"\n"
+"On usage error (e.g. a bad option was given), the program exits with a "
+"status code larger than 2.\n"
+"\n"
+"The --quiet or -q option suppresses some error warning output, but doesn't "
+"change the exit status."
+msgstr ""
+"Ustala typ pliku ELF.\n"
+"\n"
+"Wszystkie opcje klasyfikacji muszą być zastosowane w tym samym czasie do "
+"konkretnego pliku. Opcje klasyfikacji mogą zostać zaprzeczone za pomocą "
+"przedrostka „--not-”.\n"
+"\n"
+"Ponieważ nowoczesny format ELF nie rozróżnia jasno między programami "
+"a dynamicznymi obiektami współdzielonymi, należy zwykle użyć --executable "
+"lub --shared do identyfikacji głównego zastosowania pliku. Jeden plik może "
+"pasować tylko do jednego z testów --shared lub --executable.\n"
+"\n"
+"Aby poznać, czy obiekt ELF może być programem lub biblioteką współdzieloną "
+"(ale może być obydwoma), należy użyć opcji --program lub --library. Niektóre "
+"pliki ELF będą klasyfikowane jako program oraz biblioteka jednocześnie.\n"
+"\n"
+"Aby poznać tylko, czy plik ELF jest wczytywalny (jako program lub "
+"biblioteka), należy użyć opcji --loadable. Proszę zauważyć, że pliki "
+"zawierające tylko (oddzielne) informacje debugowania (--debug-only) nigdy "
+"nie są --loadable (nawet jeśli mogą zawierać nagłówki programu). Moduły "
+"jądra Linux także nie są --loadable (w zwyczajowym sensie).\n"
+"\n"
+"Bez podania żadnej z opcji --print program kończy działanie ze stanem 0, "
+"jeśli żądane testy zgadzają się dla wszystkich plików wejściowych, ze stanem "
+"1, jeśli test się nie powiedzie dla któregoś z plików, a ze stanem 2, jeśli "
+"jest problem środowiskowy (taki jak błąd odczytu pliku lub błąd przydziału "
+"pamięci).\n"
+"\n"
+"Podczas wyświetlania nazw plików program kończy działanie ze stanem 0, nawet "
+"jeśli żadne nazwy plików nie zostały wyświetlone, a ze stanem 2, jeśli jest "
+"problem środowiskowy.\n"
+"\n"
+"Przy błędnym użyciu (np. podaniu błędnej opcji) program kończy działanie "
+"z kodem stanu wyższym niż 2.\n"
+"\n"
+"Opcje --quiet i -q zmniejszają wyjście błędów i ostrzeżeń, ale nie zmieniają "
+"stanów zakończenia."
+
+#: src/elfcmp.c:59
+msgid "Control options:"
+msgstr "Opcje sterujące:"
+
+#: src/elfcmp.c:61
+msgid "Output all differences, not just the first"
+msgstr "Wyświetlanie wszystkich różnic, nie tylko pierwszej"
+
+#: src/elfcmp.c:62
+msgid ""
+"Control treatment of gaps in loadable segments [ignore|match] (default: "
+"ignore)"
+msgstr ""
+"Sterowanie traktowaniem luk w segmentach wczytywalnych [ignore|match] "
+"(domyślne: ignore)"
+
+#: src/elfcmp.c:64
+msgid "Ignore permutation of buckets in SHT_HASH section"
+msgstr "Ignorowanie permutacji kubełków w sekcji SHT_HASH"
+
+#: src/elfcmp.c:66
+msgid "Ignore differences in build ID"
+msgstr "Ignorowanie różnic w identyfikatorze kopii"
+
+#: src/elfcmp.c:67
+msgid "Output nothing; yield exit status only"
+msgstr "Bez wypisywania; przekazanie tylko kodu wyjścia"
+
+#. Short description of program.
+#: src/elfcmp.c:74
+msgid "Compare relevant parts of two ELF files for equality."
+msgstr "Porównywanie odpowiednich części dwóch plików ELF pod kątem równości."
+
+#. Strings for arguments in help texts.
+#: src/elfcmp.c:78
+msgid "FILE1 FILE2"
+msgstr "PLIK1 PLIK2"
+
+#: src/elfcmp.c:140
+msgid "Invalid number of parameters.\n"
+msgstr "Nieprawidłowa liczba parametrów.\n"
+
+#: src/elfcmp.c:171 src/elfcmp.c:176
+#, c-format
+msgid "cannot get ELF header of '%s': %s"
+msgstr "nie można uzyskać nagłówka ELF „%s”: %s"
+
+#: src/elfcmp.c:202
+#, c-format
+msgid "%s %s diff: ELF header"
+msgstr "%s %s różnią się: nagłówek ELF"
+
+#: src/elfcmp.c:209 src/elfcmp.c:212
+#, c-format
+msgid "cannot get section count of '%s': %s"
+msgstr "nie można uzyskać licznika sekcji „%s”: %s"
+
+#: src/elfcmp.c:217
+#, c-format
+msgid "%s %s diff: section count"
+msgstr "%s %s różnią się: licznik sekcji"
+
+#: src/elfcmp.c:224 src/elfcmp.c:227
+#, c-format
+msgid "cannot get program header count of '%s': %s"
+msgstr "nie można uzyskać licznika nagłówka programu „%s”: %s"
+
+#: src/elfcmp.c:232
+#, c-format
+msgid "%s %s diff: program header count"
+msgstr "%s %s różnią się: licznik nagłówka programu"
+
+#: src/elfcmp.c:240 src/elfcmp.c:243
+#, c-format
+msgid "cannot get hdrstrndx of '%s': %s"
+msgstr "nie można uzyskać hdrstrndx „%s”: %s"
+
+#: src/elfcmp.c:248
+#, c-format
+msgid "%s %s diff: shdr string index"
+msgstr "%s %s różnią się: indeks ciągu shdr"
+
+#: src/elfcmp.c:306
+#, c-format
+msgid "%s %s differ: section [%zu], [%zu] name"
+msgstr "%s %s różnią się: nazwa sekcji [%zu], [%zu]"
+
+#: src/elfcmp.c:329
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' header"
+msgstr "%s %s różnią się: nagłówek sekcji [%zu] „%s”"
+
+#: src/elfcmp.c:337 src/elfcmp.c:343
+#, c-format
+msgid "cannot get content of section %zu in '%s': %s"
+msgstr "nie można uzyskać zawartości sekcji %zu w „%s”: %s"
+
+#: src/elfcmp.c:352
+#, c-format
+msgid "symbol table [%zu] in '%s' has zero sh_entsize"
+msgstr "tabela symboli [%zu] w „%s” ma zerowe sh_entsize"
+
+#: src/elfcmp.c:364 src/elfcmp.c:370
+#, c-format
+msgid "cannot get symbol in '%s': %s"
+msgstr "nie można uzyskać symbolu w „%s”: %s"
+
+#: src/elfcmp.c:392
+#, c-format
+msgid "%s %s differ: symbol table [%zu]"
+msgstr "%s %s różnią się: tabela symboli [%zu]"
+
+#: src/elfcmp.c:395
+#, c-format
+msgid "%s %s differ: symbol table [%zu,%zu]"
+msgstr "%s %s różnią się: tabela symboli [%zu,%zu]"
+
+#: src/elfcmp.c:442 src/elfcmp.c:512
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' number of notes"
+msgstr "%s %s różnią się: liczba notatek sekcji [%zu] „%s”"
+
+#: src/elfcmp.c:450
+#, c-format
+msgid "cannot read note section [%zu] '%s' in '%s': %s"
+msgstr "nie można odczytać notatki sekcji [%zu] „%s” w „%s”: %s"
+
+#: src/elfcmp.c:461
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note name"
+msgstr "%s %s różnią się: nazwa notatki sekcji [%zu] „%s”"
+
+#: src/elfcmp.c:469
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' type"
+msgstr "%s %s różnią się: sekcja [%zu] „%s” notatka „%s” typ"
+
+#: src/elfcmp.c:484
+#, c-format
+msgid "%s %s differ: build ID length"
+msgstr "%s %s różnią się: długość identyfikatora kopii"
+
+#: src/elfcmp.c:492
+#, c-format
+msgid "%s %s differ: build ID content"
+msgstr "%s %s różnią się: zawartość identyfikatora kopii"
+
+#: src/elfcmp.c:501
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' content"
+msgstr "%s %s różnią się: sekcja [%zu] „%s” notatka „%s” zawartość"
+
+#: src/elfcmp.c:542
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' content"
+msgstr "%s %s różnią się: zawartość sekcji [%zu] „%s”"
+
+#: src/elfcmp.c:546
+#, c-format
+msgid "%s %s differ: section [%zu,%zu] '%s' content"
+msgstr "%s %s różnią się: zawartość sekcji [%zu,%zu] „%s”"
+
+#: src/elfcmp.c:561
+#, c-format
+msgid "%s %s differ: unequal amount of important sections"
+msgstr "%s %s różnią się: różna liczba ważnych sekcji"
+
+#: src/elfcmp.c:594 src/elfcmp.c:599
+#, c-format
+msgid "cannot load data of '%s': %s"
+msgstr "nie można wczytać danych z „%s”: %s"
+
+#: src/elfcmp.c:618 src/elfcmp.c:624
+#, c-format
+msgid "cannot get program header entry %d of '%s': %s"
+msgstr "nie można uzyskać wpisu nagłówka programu %d z „%s”: %s"
+
+#: src/elfcmp.c:630
+#, c-format
+msgid "%s %s differ: program header %d"
+msgstr "%s %s różnią się: nagłówek programu %d"
+
+#: src/elfcmp.c:654
+#, c-format
+msgid "%s %s differ: gap"
+msgstr "%s %s różnią się: luka"
+
+#: src/elfcmp.c:705
+#, c-format
+msgid "Invalid value '%s' for --gaps parameter."
+msgstr "Nieprawidłowa wartość „%s” dla parametru --gaps."
+
+#: src/elfcmp.c:733 src/findtextrel.c:194 src/nm.c:363 src/ranlib.c:140
+#: src/size.c:271 src/strings.c:184 src/strip.c:1040 src/strip.c:1077
+#: src/unstrip.c:2245 src/unstrip.c:2274
+#, c-format
+msgid "cannot open '%s'"
+msgstr "nie można otworzyć „%s”"
+
+#: src/elfcmp.c:737 src/findtextrel.c:213 src/ranlib.c:157
+#, c-format
+msgid "cannot create ELF descriptor for '%s': %s"
+msgstr "nie można utworzyć deskryptora ELF dla „%s”: %s"
+
+#: src/elfcmp.c:742
+#, c-format
+msgid "cannot create EBL descriptor for '%s'"
+msgstr "nie można utworzyć deskryptora EBL dla „%s”"
+
+#: src/elfcmp.c:760 src/findtextrel.c:384
+#, c-format
+msgid "cannot get section header of section %zu: %s"
+msgstr "nie można uzyskać nagłówka sekcji dla sekcji %zu: %s"
+
+#: src/elfcmp.c:770
+#, c-format
+msgid "cannot get content of section %zu: %s"
+msgstr "nie można uzyskać zawartości sekcji %zu: %s"
+
+#: src/elfcmp.c:780 src/elfcmp.c:794
+#, c-format
+msgid "cannot get relocation: %s"
+msgstr "nie można uzyskać relokacji: %s"
+
+#: src/elfcompress.c:128 src/strip.c:305 src/unstrip.c:116
+#, c-format
+msgid "-o option specified twice"
+msgstr "Opcję -o podano dwukrotnie"
+
+#: src/elfcompress.c:135
+#, c-format
+msgid "-t option specified twice"
+msgstr "Opcję -t podano dwukrotnie"
+
+#: src/elfcompress.c:147
+#, c-format
+msgid "ZSTD support is not enabled"
+msgstr ""
+
+#: src/elfcompress.c:150
+#, c-format
+msgid "unknown compression type '%s'"
+msgstr "nieznany typ kompresji „%s”"
+
+#. We need at least one input file.
+#: src/elfcompress.c:162 src/elfcompress.c:1447
+#, c-format
+msgid "No input file given"
+msgstr "Nie podano pliku wejściowego"
+
+#: src/elfcompress.c:168 src/elfcompress.c:1451
+#, c-format
+msgid "Only one input file allowed together with '-o'"
+msgstr "Tylko jeden plik wejściowy jest dozwolony z „-o”"
+
+#: src/elfcompress.c:1408
+msgid "Place (de)compressed output into FILE"
+msgstr "Umieszcza zdekompresowane wyjście w PLIKU"
+
+#: src/elfcompress.c:1411
+#, fuzzy
+#| msgid ""
+#| "What type of compression to apply. TYPE can be 'none' (decompress), "
+#| "'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias) or "
+#| "'zlib-gnu' (.zdebug GNU style compression, 'gnu' is an alias)"
+msgid ""
+"What type of compression to apply. TYPE can be 'none' (decompress), "
+"'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), 'zlib-"
+"gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD "
+"compression)"
+msgstr ""
+"Typ stosowanej kompresji. TYP może wynosić „none” (dekompresja), "
+"„zlib” (kompresja zlib ELF, domyślna, „zlib-gabi” to alias) lub „zlib-"
+"gnu” (kompresja .zdebug w stylu GNU, „gnu” to alias)"
+
+#: src/elfcompress.c:1415
+msgid ""
+"SECTION name to (de)compress, SECTION is an extended wildcard pattern "
+"(defaults to '.?(z)debug*')"
+msgstr ""
+"Nazwa SEKCJI do (de)kompresowania, SEKCJA jest rozszerzonym wzorem "
+"(domyślnie „.?(z)debug*”)"
+
+#: src/elfcompress.c:1418
+msgid "Print a message for each section being (de)compressed"
+msgstr "Wyświetla komunikat dla każdej (de)kompresowanej sekcji"
+
+#: src/elfcompress.c:1421
+msgid ""
+"Force compression of section even if it would become larger or update/"
+"rewrite the file even if no section would be (de)compressed"
+msgstr ""
+"Wymusza kompresję sekcji, nawet jeśli spowodowałoby to jej zwiększenie lub "
+"zaktualizowanie/przepisanie pliku, nawet jeśli żadna sekcja nie zostałaby "
+"(zde)kompresowana"
+
+#: src/elfcompress.c:1424 src/strip.c:92
+msgid "Relax a few rules to handle slightly broken ELF files"
+msgstr "Łagodzi kilka reguł, aby obsłużyć lekko uszkodzone pliki ELF"
+
+#: src/elfcompress.c:1427
+msgid "Be silent when a section cannot be compressed"
+msgstr "Bez zgłaszania, kiedy nie można zdekompresować sekcji"
+
+#: src/elfcompress.c:1437
+msgid "Compress or decompress sections in an ELF file."
+msgstr "Kompresuje lub dekompresuje sekcje w pliku ELF."
+
+#: src/elflint.c:63
+msgid "Be extremely strict, flag level 2 features."
+msgstr "Bardzo ścisłe sprawdzanie, cechy poziomu 2 flag."
+
+#: src/elflint.c:64
+msgid "Do not print anything if successful"
+msgstr "Nie wypisywanie niczego w przypadku powodzenia"
+
+#: src/elflint.c:65
+msgid "Binary is a separate debuginfo file"
+msgstr "Plik binarny jest oddzielnym plikiem debuginfo"
+
+#: src/elflint.c:67
+msgid ""
+"Binary has been created with GNU ld and is therefore known to be broken in "
+"certain ways"
+msgstr ""
+"Plik binarny został utworzony przez program GNU ld, przez co jest uszkodzony "
+"w pewien sposób"
+
+#. Short description of program.
+#: src/elflint.c:73
+msgid "Pedantic checking of ELF files compliance with gABI/psABI spec."
+msgstr ""
+"Szczegółowe sprawdzanie zgodności plików ELF ze specyfikacją gABI/psABI."
+
+#: src/elflint.c:154 src/readelf.c:413
+#, c-format
+msgid "cannot open input file '%s'"
+msgstr "nie można otworzyć pliku wejściowego „%s”"
+
+#: src/elflint.c:161
+#, c-format
+msgid "cannot generate Elf descriptor for '%s': %s\n"
+msgstr "nie można utworzyć deskryptora ELF dla „%s”: %s\n"
+
+#: src/elflint.c:180
+#, c-format
+msgid "error while closing Elf descriptor: %s\n"
+msgstr "błąd podczas zamykania deskryptora ELF: %s\n"
+
+#: src/elflint.c:184
+msgid "No errors"
+msgstr "Brak błędów"
+
+#: src/elflint.c:219 src/readelf.c:625
+msgid "Missing file name.\n"
+msgstr "Brak nazwy pliku.\n"
+
+#: src/elflint.c:284
+#, c-format
+msgid " error while freeing sub-ELF descriptor: %s\n"
+msgstr " błąd podczas zwalniania deskryptora pod-ELF: %s\n"
+
+#. We cannot do anything.
+#: src/elflint.c:292
+#, c-format
+msgid "Not an ELF file - it has the wrong magic bytes at the start\n"
+msgstr "To nie jest plik ELF — ma błędne bajty magiczne na początku\n"
+
+#: src/elflint.c:358
+#, c-format
+msgid "e_ident[%d] == %d is no known class\n"
+msgstr "e_ident[%d] == %d nie jest znaną klasą\n"
+
+#: src/elflint.c:363
+#, c-format
+msgid "e_ident[%d] == %d is no known data encoding\n"
+msgstr "e_ident[%d] == %d nie jest znanym kodowaniem danych\n"
+
+#: src/elflint.c:367
+#, c-format
+msgid "unknown ELF header version number e_ident[%d] == %d\n"
+msgstr "nieznany numer wersji nagłówka ELF e_ident[%d] == %d\n"
+
+#: src/elflint.c:375
+#, c-format
+msgid "unsupported OS ABI e_ident[%d] == '%s'\n"
+msgstr "nieobsługiwane ABI systemu operacyjnego e_ident[%d] == „%s”\n"
+
+#: src/elflint.c:381
+#, c-format
+msgid "unsupported ABI version e_ident[%d] == %d\n"
+msgstr "nieobsługiwana wersja ABI e_ident[%d] == %d\n"
+
+#: src/elflint.c:386
+#, c-format
+msgid "e_ident[%zu] is not zero\n"
+msgstr "e_ident[%zu] nie wynosi zero\n"
+
+#: src/elflint.c:391
+#, c-format
+msgid "unknown object file type %d\n"
+msgstr "nieznany typ pliku obiektu %d\n"
+
+#: src/elflint.c:398
+#, c-format
+msgid "unknown machine type %d\n"
+msgstr "nieznany typ komputera %d\n"
+
+#: src/elflint.c:402
+#, c-format
+msgid "unknown object file version\n"
+msgstr "nieznana wersja pliku obiektu\n"
+
+#: src/elflint.c:408
+#, c-format
+msgid "invalid program header offset\n"
+msgstr "nieprawidłowy offset nagłówka programu\n"
+
+#: src/elflint.c:410
+#, c-format
+msgid "executables and DSOs cannot have zero program header offset\n"
+msgstr ""
+"pliki wykonywalne i DSO nie mogą mieć zerowego offsetu nagłówka programu\n"
+
+#: src/elflint.c:414
+#, c-format
+msgid "invalid number of program header entries\n"
+msgstr "nieprawidłowa liczba wpisów nagłówka programu\n"
+
+#: src/elflint.c:422
+#, c-format
+msgid "invalid section header table offset\n"
+msgstr "nieprawidłowy offset tabeli nagłówków sekcji\n"
+
+#: src/elflint.c:425
+#, c-format
+msgid "section header table must be present\n"
+msgstr "tabela nagłówków sekcji musi istnieć\n"
+
+#: src/elflint.c:439
+#, c-format
+msgid "invalid number of section header table entries\n"
+msgstr "nieprawidłowa liczba wpisów tabeli nagłówków sekcji\n"
+
+#: src/elflint.c:456
+#, c-format
+msgid "invalid section header index\n"
+msgstr "nieprawidłowy indeks nagłówka sekcji\n"
+
+#: src/elflint.c:474
+#, c-format
+msgid "Can only check %u headers, shnum was %u\n"
+msgstr "Można sprawdzić tylko nagłówki %u, shnum wynosiło %u\n"
+
+#: src/elflint.c:488
+#, c-format
+msgid "invalid number of program header table entries\n"
+msgstr "nieprawidłowa liczba wpisów tabeli nagłówka programu\n"
+
+#: src/elflint.c:505
+#, c-format
+msgid "Can only check %u headers, phnum was %u\n"
+msgstr "Można sprawdzić tylko nagłówki %u, phnum wynosiło %u\n"
+
+#: src/elflint.c:510
+#, c-format
+msgid "invalid machine flags: %s\n"
+msgstr "nieprawidłowe flagi komputera: %s\n"
+
+#: src/elflint.c:517 src/elflint.c:534
+#, c-format
+msgid "invalid ELF header size: %hd\n"
+msgstr "nieprawidłowy rozmiar nagłówka ELF: %hd\n"
+
+#: src/elflint.c:520 src/elflint.c:537
+#, c-format
+msgid "invalid program header size: %hd\n"
+msgstr "nieprawidłowa rozmiar nagłówka programu: %hd\n"
+
+#: src/elflint.c:523 src/elflint.c:540
+#, c-format
+msgid "invalid program header position or size\n"
+msgstr "nieprawidłowe położenie lub rozmiar nagłówka programu\n"
+
+#: src/elflint.c:526 src/elflint.c:543
+#, c-format
+msgid "invalid section header size: %hd\n"
+msgstr "nieprawidłowy rozmiar nagłówka sekcji: %hd\n"
+
+#: src/elflint.c:529 src/elflint.c:546
+#, c-format
+msgid "invalid section header position or size\n"
+msgstr "nieprawidłowe położenie lub rozmiar nagłówka sekcji\n"
+
+#: src/elflint.c:591
+#, c-format
+msgid ""
+"section [%2d] '%s': section with SHF_GROUP flag set not part of a section "
+"group\n"
+msgstr ""
+"sekcja [%2d] „%s”: sekcja z flagą SHF_GROUP nie jest częścią grupy sekcji\n"
+
+#: src/elflint.c:595
+#, c-format
+msgid ""
+"section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"
+msgstr ""
+"sekcja [%2d] „%s”: grupa sekcji [%2zu] „%s” nie poprzedza elementu grupy\n"
+
+#: src/elflint.c:611 src/elflint.c:1509 src/elflint.c:1560 src/elflint.c:1610
+#: src/elflint.c:1692 src/elflint.c:2029 src/elflint.c:2355 src/elflint.c:2981
+#: src/elflint.c:3144 src/elflint.c:3292 src/elflint.c:3494 src/elflint.c:4511
+#, c-format
+msgid "section [%2d] '%s': cannot get section data\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać danych sekcji\n"
+
+#: src/elflint.c:624 src/elflint.c:1699
+#, c-format
+msgid ""
+"section [%2d] '%s': referenced as string table for section [%2d] '%s' but "
+"type is not SHT_STRTAB\n"
+msgstr ""
+"sekcja [%2d] „%s”: użyta jako tabela ciągów dla sekcji [%2d] „%s”, ale nie "
+"jest typu SHT_STRTAB\n"
+
+#: src/elflint.c:647
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol table cannot have more than one extended index "
+"section\n"
+msgstr ""
+"sekcja [%2d] „%s”: tabela symboli nie może mieć więcej niż jednej "
+"rozszerzonej sekcji indeksów\n"
+
+#: src/elflint.c:659
+#, c-format
+msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n"
+msgstr "sekcja [%2u] „%s”: rozmiar wpisu nie zgadza się z ElfXX_Sym\n"
+
+#: src/elflint.c:663
+#, c-format
+msgid ""
+"section [%2u] '%s': number of local entries in 'st_info' larger than table "
+"size\n"
+msgstr ""
+"sekcja [%2u] „%s”: liczba lokalnych wpisów w „st_info” jest większa niż "
+"rozmiar tabeli\n"
+
+#: src/elflint.c:672
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %d: %s\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać symbolu %d: %s\n"
+
+#: src/elflint.c:677 src/elflint.c:680 src/elflint.c:683 src/elflint.c:686
+#: src/elflint.c:689 src/elflint.c:692
+#, c-format
+msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n"
+msgstr "sekcja [%2d] „%s”: „%s” w zerowym wpisie nie jest zerem\n"
+
+#: src/elflint.c:695
+#, c-format
+msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n"
+msgstr "sekcja [%2d] „%s”: XINDEX dla zerowego wpisu nie jest zerem\n"
+
+#: src/elflint.c:705
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %zu: %s\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać symbolu %zu: %s\n"
+
+#: src/elflint.c:714
+#, c-format
+msgid "section [%2d] '%s': symbol %zu: invalid name value\n"
+msgstr "sekcja [%2d] „%s”: symbol %zu: nieprawidłowa wartość nazwy\n"
+
+#: src/elflint.c:729
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): too large section index but no extended "
+"section index section\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): za duży indeks sekcji, ale nie ma sekcji "
+"rozszerzonych indeksów sekcji\n"
+
+#: src/elflint.c:735
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit "
+"in st_shndx (%<PRIu32>)\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): XINDEX użyty dla indeksu, który "
+"zmieściłby się w st_shndx (%<PRIu32>)\n"
+
+#. || sym->st_shndx > SHN_HIRESERVE  always false
+#: src/elflint.c:747
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): invalid section index\n"
+msgstr "sekcja [%2d] „%s”: symbol %zu (%s): nieprawidłowy indeks sekcji\n"
+
+#: src/elflint.c:755
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown type\n"
+msgstr "sekcja [%2d] „%s”: symbol %zu (%s): nieznany typ\n"
+
+#: src/elflint.c:761
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"
+msgstr "sekcja [%2d] „%s”: symbol %zu (%s): nieznane dowiązanie symbolu\n"
+
+#: src/elflint.c:766
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): unikalny symbol nie jest typem obiektu\n"
+
+#: src/elflint.c:774
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable "
+"files\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): COMMON jest dozwolone tylko w plikach "
+"relokowalnych\n"
+
+#: src/elflint.c:778
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): lokalne symbole COMMON to nonsens\n"
+
+#: src/elflint.c:782
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): funkcja w sekcji COMMON to nonsens\n"
+
+#: src/elflint.c:833
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"
+msgstr "sekcja [%2d] „%s”: symbol %zu (%s): st_value spoza zakresu\n"
+
+#: src/elflint.c:839 src/elflint.c:864 src/elflint.c:913
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s) nie mieści się w całości we wskazywanej "
+"sekcji [%2d] „%s”\n"
+
+#: src/elflint.c:848
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not "
+"have SHF_TLS flag set\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): wskazywana sekcja [%2d] „%s” nie ma "
+"ustawionej flagi SHF_TLS\n"
+
+#: src/elflint.c:858 src/elflint.c:906
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): st_value spoza zakresu wskazywanej "
+"sekcji [%2d] „%s”\n"
+
+#: src/elflint.c:885
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header "
+"entry\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): symbol TLS, ale brak wpisu TLS nagłówka "
+"programu\n"
+
+#: src/elflint.c:891
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program "
+"header entry\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): symbol TLS, ale nie można uzyskać wpisu "
+"TLS nagłówka programu\n"
+
+#: src/elflint.c:899
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value short of referenced section "
+"[%2d] '%s'\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): st_value pomija wskazywaną sekcję [%2d] "
+"„%s”\n"
+
+#: src/elflint.c:926
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local symbol outside range described in "
+"sh_info\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): lokalny symbol spoza zakresu określonego "
+"w sh_info\n"
+
+#: src/elflint.c:933
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): non-local symbol outside range "
+"described in sh_info\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): nielokalny symbol spoza zakresu "
+"określonego w sh_info\n"
+
+#: src/elflint.c:940
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"
+msgstr "sekcja [%2d] „%s”: symbol %zu (%s): nielokalny symbol sekcji\n"
+
+#: src/elflint.c:990
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section "
+"[%2d]\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol _GLOBAL_OFFSET_TABLE_ odnosi się do błędnej sekcji "
+"[%2d]\n"
+
+#: src/elflint.c:997
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] "
+"'%s'\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol _GLOBAL_OFFSET_TABLE_ odnosi się do sekcji [%2d] "
+"„%s”\n"
+
+#. This test is more strict than the psABIs which
+#. usually allow the symbol to be in the middle of
+#. the .got section, allowing negative offsets.
+#: src/elflint.c:1013
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#<PRIx64> does not "
+"match %s section address %#<PRIx64>\n"
+msgstr ""
+"sekcja [%2d] „%s”: wartość symbolu _GLOBAL_OFFSET_TABLE_ %#<PRIx64> nie "
+"pasuje do adresu sekcji %s %#<PRIx64>\n"
+
+#: src/elflint.c:1020
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %<PRIu64> does not "
+"match %s section size %<PRIu64>\n"
+msgstr ""
+"sekcja [%2d] „%s”: rozmiar symbolu _GLOBAL_OFFSET_TABLE_ %<PRIu64> nie "
+"pasuje do rozmiaru sekcji %s %<PRIu64>\n"
+
+#: src/elflint.c:1028
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got "
+"section\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol _GLOBAL_OFFSET_TABLE_ istnieje, ale brak sekcji ."
+"got\n"
+
+#: src/elflint.c:1044
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC_ symbol value %#<PRIx64> does not match dynamic "
+"segment address %#<PRIx64>\n"
+msgstr ""
+"sekcja [%2d] „%s”: wartość symbolu _DYNAMIC_ %#<PRIx64> nie pasuje do adresu "
+"segmentu dynamicznego %#<PRIx64>\n"
+
+#: src/elflint.c:1051
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC symbol size %<PRIu64> does not match dynamic "
+"segment size %<PRIu64>\n"
+msgstr ""
+"sekcja [%2d] „%s”: rozmiar symbolu _DYNAMIC_ %<PRIu64> nie pasuje do "
+"rozmiaru segmentu dynamicznego %<PRIu64>\n"
+
+#: src/elflint.c:1064
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-"
+"default visibility\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): symbol w dynamicznej tabeli symboli "
+"z niedomyślną widocznością\n"
+
+#: src/elflint.c:1068
+#, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %zu (%s): ustawiono nieznany bit w st_other\n"
+
+#: src/elflint.c:1106
+#, c-format
+msgid "section [%2d] '%s': cannot get section data.\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać danych sekcji.\n"
+
+#: src/elflint.c:1122
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"
+msgstr "sekcja [%2d] „%s”: DT_RELCOUNT użyte dla tej sekcji RELA\n"
+
+#: src/elflint.c:1133 src/elflint.c:1186
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"
+msgstr "sekcja [%2d] „%s”: DT_RELCOUNT %d za duże dla tej sekcji\n"
+
+#: src/elflint.c:1158 src/elflint.c:1211
+#, c-format
+msgid ""
+"section [%2d] '%s': relative relocations after index %d as specified by "
+"DT_RELCOUNT\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacje względne po indeksie %d podanym przez "
+"DT_RELCOUNT\n"
+
+#: src/elflint.c:1164 src/elflint.c:1217
+#, c-format
+msgid ""
+"section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT "
+"specified %d relative relocations\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacja bezwzględna pod indeksem %zu; DT_RELCOUNT podał "
+"%d relokacji względnych\n"
+
+#: src/elflint.c:1176
+#, c-format
+msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n"
+msgstr "sekcja [%2d] „%s”: DT_RELACOUNT użyte dla tej sekcji REL\n"
+
+#: src/elflint.c:1259
+#, c-format
+msgid "section [%2d] '%s': invalid destination section index\n"
+msgstr "sekcja [%2d] „%s”: nieprawidłowy indeks sekcji docelowej\n"
+
+#: src/elflint.c:1271
+#, c-format
+msgid "section [%2d] '%s': invalid destination section type\n"
+msgstr "sekcja [%2d] „%s”: nieprawidłowy typ sekcji docelowej\n"
+
+#: src/elflint.c:1279
+#, c-format
+msgid "section [%2d] '%s': sh_info should be zero\n"
+msgstr "sekcja [%2d] „%s”: sh_info musi wynosić zero\n"
+
+#: src/elflint.c:1287
+#, c-format
+msgid ""
+"section [%2d] '%s': no relocations for merge-able string sections possible\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacje dla sekcji złączalnych ciągów są niemożliwe\n"
+
+#: src/elflint.c:1365
+#, c-format
+msgid "text relocation flag set but there is no read-only segment\n"
+msgstr ""
+"flaga relokacji tekstu jest ustawiona, ale nie ma segmentu tylko do odczytu\n"
+
+#: src/elflint.c:1392
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid type\n"
+msgstr "sekcja [%2d] „%s”: relokacja %zu: nieprawidłowy typ\n"
+
+#: src/elflint.c:1400
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: relocation type invalid for the file "
+"type\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacja %zu: typ relokacji nieprawidłowy dla tego typu "
+"pliku\n"
+
+#: src/elflint.c:1408
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n"
+msgstr "sekcja [%2d] „%s”: relokacja %zu: nieprawidłowy indeks symbolu\n"
+
+#: src/elflint.c:1426
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can "
+"be used with %s\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacja %zu: z %s można użyć tylko symbolu "
+"„_GLOBAL_OFFSET_TABLE_”\n"
+
+#: src/elflint.c:1443
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n"
+msgstr "sekcja [%2d] „%s”: relokacja %zu: offset spoza zakresu\n"
+
+#: src/elflint.c:1458
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: copy relocation against symbol of type "
+"%s\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacja %zu: relokacja kopii względem symbolu typu %s\n"
+
+#: src/elflint.c:1479
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: read-only section modified but text "
+"relocation flag not set\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacja %zu: sekcja tylko do odczytu została "
+"zmodyfikowana, ale nie ustawiono flagi relokacji tekstu\n"
+
+#: src/elflint.c:1494
+#, c-format
+msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n"
+msgstr ""
+"sekcja [%2d] „%s”: relokacje względem wczytanych i niewczytanych danych\n"
+
+#: src/elflint.c:1534 src/elflint.c:1585
+#, c-format
+msgid "section [%2d] '%s': cannot get relocation %zu: %s\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać relokacji %zu: %s\n"
+
+#: src/elflint.c:1687
+#, c-format
+msgid "more than one dynamic section present\n"
+msgstr "obecna jest więcej niż jedna sekcja dynamiczna\n"
+
+#: src/elflint.c:1705
+#, c-format
+msgid ""
+"section [%2d]: referenced as string table for section [%2d] '%s' but section "
+"link value is invalid\n"
+msgstr ""
+"sekcja [%2d]: wskazane jako tabela ciągów dla sekcji [%2d] „%s”, ale wartość "
+"dowiązania sekcji jest nieprawidłowa\n"
+
+#: src/elflint.c:1713
+#, c-format
+msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"
+msgstr "sekcja [%2d] „%s”: rozmiar wpisu sekcji nie zgadza się z ElfXX_Dyn\n"
+
+#: src/elflint.c:1718 src/elflint.c:2008
+#, c-format
+msgid "section [%2d] '%s': sh_info not zero\n"
+msgstr "sekcja [%2d] „%s”: sh_info nie wynosi zero\n"
+
+#: src/elflint.c:1728
+#, c-format
+msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"
+msgstr ""
+"sekcja [%2d] „%s”: nie można uzyskać wpisu %zu sekcji dynamicznej: %s\n"
+
+#: src/elflint.c:1736
+#, c-format
+msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"
+msgstr "sekcja [%2d] „%s”: wpisy nie-DT_NULL występują po wpisie DT_NULL\n"
+
+#: src/elflint.c:1743
+#, c-format
+msgid "section [%2d] '%s': entry %zu: unknown tag\n"
+msgstr "sekcja [%2d] „%s”: wpis %zu: nieznany znacznik\n"
+
+#: src/elflint.c:1754
+#, c-format
+msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n"
+msgstr "sekcja [%2d] „%s”: wpis %zu: więcej niż jeden wpis ze znacznikiem %s\n"
+
+#: src/elflint.c:1764
+#, c-format
+msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n"
+msgstr "sekcja [%2d] „%s”: wpis %zu: użyto znacznika %s poziomu 2\n"
+
+#: src/elflint.c:1782
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %zu: wartość DT_PLTREL musi wynosić DT_REL lub "
+"DT_RELA\n"
+
+#: src/elflint.c:1795
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: pointer does not match address of section "
+"[%2d] '%s' referenced by sh_link\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %zu: wskaźnik nie pasuje do adresu sekcji [%2d] „%s” "
+"wskazywanej przez sh_link\n"
+
+#: src/elflint.c:1839
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %zu: wartość %s musi wskazywać na wczytany segment\n"
+
+#: src/elflint.c:1854
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must be valid offset in section "
+"[%2d] '%s'\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %zu: wartość %s musi być prawidłowym offsetem "
+"w sekcji [%2d] „%s”\n"
+
+#: src/elflint.c:1874 src/elflint.c:1902
+#, c-format
+msgid "section [%2d] '%s': contains %s entry but not %s\n"
+msgstr "sekcja [%2d] „%s”: zawiera wpis %s, ale nie %s\n"
+
+#: src/elflint.c:1886
+#, c-format
+msgid "section [%2d] '%s': mandatory tag %s not present\n"
+msgstr "sekcja [%2d] „%s”: brak obowiązkowego znacznika %s\n"
+
+#: src/elflint.c:1895
+#, c-format
+msgid "section [%2d] '%s': no hash section present\n"
+msgstr "sekcja [%2d] „%s”: brak sekcji skrótów\n"
+
+#: src/elflint.c:1910 src/elflint.c:1917
+#, c-format
+msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n"
+msgstr "sekcja [%2d] „%s”: nie wszystkie z %s, %s i %s są obecne\n"
+
+#: src/elflint.c:1927 src/elflint.c:1931
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"
+msgstr ""
+"sekcja [%2d] „%s”: brak znacznika %s w DSO oznaczonym podczas wstępnej "
+"konsolidacji\n"
+
+#: src/elflint.c:1937
+#, c-format
+msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n"
+msgstr ""
+"sekcja [%2d] „%s”: plik nie-DSO oznaczony jako zależność podczas wstępnej "
+"konsolidacji\n"
+
+#: src/elflint.c:1948 src/elflint.c:1952 src/elflint.c:1956 src/elflint.c:1960
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in prelinked executable\n"
+msgstr ""
+"sekcja [%2d] „%s”: brak znacznika %s we wstępnie konsolidowanym pliku "
+"wykonywalnym\n"
+
+#: src/elflint.c:1972
+#, c-format
+msgid ""
+"section [%2d] '%s': only relocatable files can have extended section index\n"
+msgstr ""
+"sekcja [%2d] „%s”: tylko pliki relokowalne mogą mieć rozszerzoną sekcję "
+"indeksów\n"
+
+#: src/elflint.c:1982
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index section not for symbol table\n"
+msgstr ""
+"sekcja [%2d] „%s”: sekcja rozszerzonych indeksów sekcji nie dla tabeli "
+"symboli\n"
+
+#: src/elflint.c:1986
+#, c-format
+msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"
+msgstr ""
+"sekcja [%2d] „%s”: rozszerzony indeks sekcji sh_link [%2d] jest "
+"nieprawidłowy\n"
+
+#: src/elflint.c:1991
+#, c-format
+msgid "cannot get data for symbol section\n"
+msgstr "nie można uzyskać danych dla sekcji symboli\n"
+
+#: src/elflint.c:1994
+#, c-format
+msgid "section [%2d] '%s': entry size does not match Elf32_Word\n"
+msgstr "sekcja [%2d] „%s”: rozmiar wpisu nie zgadza się z Elf32_Word\n"
+
+#: src/elflint.c:2003
+#, c-format
+msgid "section [%2d] '%s': extended index table too small for symbol table\n"
+msgstr ""
+"sekcja [%2d] „%s”: tabela rozszerzonych indeksów jest za mała dla tabeli "
+"symboli\n"
+
+#: src/elflint.c:2018
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index in section [%2zu] '%s' refers to "
+"same symbol table\n"
+msgstr ""
+"sekcja [%2d] „%s”: rozszerzony indeks sekcji w sekcji [%2zu] „%s” odwołuje "
+"się do tej samej tabeli symboli\n"
+
+#: src/elflint.c:2036
+#, c-format
+msgid "symbol 0 should have zero extended section index\n"
+msgstr "symbol 0 musi mieć zerowy rozszerzony indeks sekcji\n"
+
+#: src/elflint.c:2048
+#, c-format
+msgid "cannot get data for symbol %zu\n"
+msgstr "nie można uzyskać danych dla symbolu %zu\n"
+
+#: src/elflint.c:2053
+#, c-format
+msgid "extended section index is %<PRIu32> but symbol index is not XINDEX\n"
+msgstr ""
+"rozszerzony indeks sekcji wynosi %<PRIu32>, ale indeks symbolu nie wynosi "
+"XINDEX\n"
+
+#: src/elflint.c:2070 src/elflint.c:2127
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"
+msgstr ""
+"sekcja [%2d] „%s”: sekcja tabeli mieszającej jest za mała (%ld, oczekiwano "
+"%ld)\n"
+
+#: src/elflint.c:2084 src/elflint.c:2141
+#, c-format
+msgid "section [%2d] '%s': chain array too large\n"
+msgstr "sekcja [%2d] „%s”: tabela łańcuchowa jest za duża\n"
+
+#: src/elflint.c:2098 src/elflint.c:2155
+#, c-format
+msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n"
+msgstr ""
+"sekcja [%2d] „%s”: odwołanie do kubełka skrótu %zu jest spoza zakresu\n"
+
+#: src/elflint.c:2108
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n"
+msgstr ""
+"sekcja [%2d] „%s”: odwołanie do łańcucha skrótu %zu jest spoza zakresu\n"
+
+#: src/elflint.c:2165
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %<PRIu64> out of bounds\n"
+msgstr ""
+"sekcja [%2d] „%s”: odwołanie do łańcucha skrótu %<PRIu64> jest spoza "
+"zakresu\n"
+
+#: src/elflint.c:2178
+#, c-format
+msgid "section [%2d] '%s': not enough data\n"
+msgstr "sekcja [%2d] „%s”: brak wystarczającej ilości danych\n"
+
+#: src/elflint.c:2190
+#, c-format
+msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n"
+msgstr ""
+"sekcja [%2d] „%s”: rozmiar maski bitowej wynosi zero lub nie jest potęgą 2: "
+"%u\n"
+
+#: src/elflint.c:2206
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected at "
+"least %ld)\n"
+msgstr ""
+"sekcja [%2d] „%s”: sekcja tabeli mieszającej jest za mała (wynosi %ld, "
+"oczekiwano co najmniej %ld)\n"
+
+#: src/elflint.c:2215
+#, c-format
+msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n"
+msgstr ""
+"sekcja [%2d] „%s”: drugie przesunięcie funkcji mieszającej jest za duże: %u\n"
+
+#: src/elflint.c:2249
+#, c-format
+msgid ""
+"section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"
+msgstr ""
+"sekcja [%2d] „%s”: łańcuch mieszający dla kubełka %zu jest mniejszy niż "
+"przesunięcie indeksu symboli\n"
+
+#: src/elflint.c:2270
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %u referenced in chain for bucket %zu is "
+"undefined\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %u wskazywany w łańcuchu dla kubełka %zu jest "
+"nieokreślony\n"
+
+#: src/elflint.c:2283
+#, c-format
+msgid ""
+"section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+"sekcja [%2d] „%s”: wartość skrótu dla symbolu %u w łańcuchu dla kubełka %zu "
+"jest błędna\n"
+
+#: src/elflint.c:2292
+#, c-format
+msgid ""
+"section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+"sekcja [%2d] „%s”: indeks maski dla symbolu %u w łańcuchu dla kubełka %zu "
+"jest błędny\n"
+
+#: src/elflint.c:2322
+#, c-format
+msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n"
+msgstr "sekcja [%2d] „%s”: łańcuch skrótu dla kubełka %zu jest spoza zakresu\n"
+
+#: src/elflint.c:2327
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"
+msgstr ""
+"sekcja [%2d] „%s”: odwołanie do symbolu w łańcuchu dla kubełka %zu jest "
+"spoza zakresu\n"
+
+#: src/elflint.c:2333
+#, c-format
+msgid "section [%2d] '%s': bitmask does not match names in the hash table\n"
+msgstr ""
+"sekcja [%2d] „%s”: maska bitowa nie pasuje do nazw w tabeli mieszającej\n"
+
+#: src/elflint.c:2346
+#, c-format
+msgid "section [%2d] '%s': relocatable files cannot have hash tables\n"
+msgstr ""
+"sekcja [%2d] „%s”: pliki relokowalne nie mogą mieć tabeli mieszających\n"
+
+#: src/elflint.c:2364
+#, c-format
+msgid "section [%2d] '%s': hash table not for dynamic symbol table\n"
+msgstr ""
+"sekcja [%2d] „%s”: tabela mieszająca nie dla tabeli dynamicznych symboli\n"
+
+#: src/elflint.c:2368
+#, c-format
+msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"
+msgstr ""
+"sekcja [%2d] „%s”: nieprawidłowy indeks sekcji tabeli symboli sh_link [%2d]\n"
+
+#: src/elflint.c:2378
+#, c-format
+msgid "section [%2d] '%s': hash table entry size incorrect\n"
+msgstr "sekcja [%2d] „%s”: niepoprawny rozmiar wpisu tabeli mieszającej\n"
+
+#: src/elflint.c:2383
+#, c-format
+msgid "section [%2d] '%s': not marked to be allocated\n"
+msgstr "sekcja [%2d] „%s”: nieoznaczona do przydzielenia\n"
+
+#: src/elflint.c:2388
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table has not even room for initial administrative "
+"entries\n"
+msgstr ""
+"sekcja [%2d] „%s”: tabela mieszająca nie ma miejsca nawet na początkowe "
+"wpisy administracyjne\n"
+
+#: src/elflint.c:2437
+#, c-format
+msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"
+msgstr ""
+"sh_link w sekcjach skrótu [%2zu] „%s” i [%2zu] „%s” nie są identyczne\n"
+
+#: src/elflint.c:2461 src/elflint.c:2526 src/elflint.c:2561
+#, c-format
+msgid "hash section [%2zu] '%s' does not contain enough data\n"
+msgstr ""
+"sekcja mieszania [%2zu] „%s” nie zawiera wystarczającej ilości danych\n"
+
+#: src/elflint.c:2482
+#, c-format
+msgid "hash section [%2zu] '%s' has zero bit mask words\n"
+msgstr "sekcja mieszania [%2zu] „%s” ma zerowe słowa maski bitów\n"
+
+#: src/elflint.c:2493 src/elflint.c:2537 src/elflint.c:2574
+#, c-format
+msgid "hash section [%2zu] '%s' uses too much data\n"
+msgstr "sekcja mieszania [%2zu] „%s” używa za dużo danych\n"
+
+#: src/elflint.c:2508
+#, c-format
+msgid ""
+"hash section [%2zu] '%s' invalid symbol index %<PRIu32> (max_nsyms: "
+"%<PRIu32>, nentries: %<PRIu32>\n"
+msgstr ""
+"sekcja mieszająca [%2zu] „%s” nieprawidłowy indeks symboli %<PRIu32> "
+"(max_nsyms: %<PRIu32>, nentries: %<PRIu32>\n"
+
+#: src/elflint.c:2595
+#, c-format
+msgid "hash section [%2zu] '%s' invalid sh_entsize\n"
+msgstr "sekcja mieszania [%2zu] „%s” nieprawidłowe sh_entsize\n"
+
+#: src/elflint.c:2605 src/elflint.c:2609
+#, c-format
+msgid "section [%2zu] '%s': reference to symbol index 0\n"
+msgstr "sekcja [%2zu] „%s”: odwołanie do symbolu o indeksie 0\n"
+
+#: src/elflint.c:2616
+#, c-format
+msgid ""
+"symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+"symbol %d wymieniony w nowej tabeli mieszającej w [%2zu] „%s”, ale nie "
+"w poprzedniej tabeli mieszającej [%2zu] „%s”\n"
+
+#: src/elflint.c:2628
+#, c-format
+msgid ""
+"symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+"symbol %d wymieniony w poprzedniej tabeli mieszającej w [%2zu] „%s”, ale nie "
+"w nowej tabeli mieszającej w [%2zu] „%s”\n"
+
+#: src/elflint.c:2644
+#, c-format
+msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n"
+msgstr "sekcja [%2d] „%s”: niezerowe sh_%s dla sekcji NULL\n"
+
+#: src/elflint.c:2664
+#, c-format
+msgid ""
+"section [%2d] '%s': section groups only allowed in relocatable object files\n"
+msgstr ""
+"sekcja [%2d] „%s”: w plikach obiektów relokowalnych dozwolone są tylko grupy "
+"sekcji\n"
+
+#: src/elflint.c:2675
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol table: %s\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać tabeli symboli: %s\n"
+
+#: src/elflint.c:2680
+#, c-format
+msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n"
+msgstr ""
+"sekcja [%2d] „%s”: odwołanie do sekcji w sh_link nie ma tabeli symboli\n"
+
+#: src/elflint.c:2686
+#, c-format
+msgid "section [%2d] '%s': invalid symbol index in sh_info\n"
+msgstr "sekcja [%2d] „%s”: nieprawidłowy indeks symbolu w sh_info\n"
+
+#: src/elflint.c:2691
+#, c-format
+msgid "section [%2d] '%s': sh_flags not zero\n"
+msgstr "sekcja [%2d] „%s”: niezerowe sh_flags\n"
+
+#: src/elflint.c:2698
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol for signature\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać symbolu dla podpisu\n"
+
+#: src/elflint.c:2702
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol name for signature\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać nazwy symbolu dla podpisu\n"
+
+#: src/elflint.c:2707
+#, c-format
+msgid "section [%2d] '%s': signature symbol cannot be empty string\n"
+msgstr "sekcja [%2d] „%s”: symbol podpisu nie można być pustym ciągiem\n"
+
+#: src/elflint.c:2713
+#, c-format
+msgid "section [%2d] '%s': sh_flags not set correctly\n"
+msgstr "sekcja [%2d] „%s”: sh_flags nie ustawione poprawnie\n"
+
+#: src/elflint.c:2719
+#, c-format
+msgid "section [%2d] '%s': cannot get data: %s\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać danych: %s\n"
+
+#: src/elflint.c:2728
+#, c-format
+msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"
+msgstr ""
+"sekcja [%2d] „%s”: rozmiar sekcji nie jest wielokrotnością "
+"sizeof(Elf32_Word)\n"
+
+#: src/elflint.c:2734
+#, c-format
+msgid "section [%2d] '%s': section group without flags word\n"
+msgstr "sekcja [%2d] „%s”: grupa sekcji bez słowa flag\n"
+
+#: src/elflint.c:2742
+#, c-format
+msgid "section [%2d] '%s': section group without member\n"
+msgstr "sekcja [%2d] „%s”: grupa sekcji bez elementów\n"
+
+#: src/elflint.c:2746
+#, c-format
+msgid "section [%2d] '%s': section group with only one member\n"
+msgstr "sekcja [%2d] „%s”: grupa sekcji z tylko jednym elementem\n"
+
+#: src/elflint.c:2757
+#, c-format
+msgid "section [%2d] '%s': unknown section group flags\n"
+msgstr "sekcja [%2d] „%s”: nieznane flagi grupy sekcji\n"
+
+#: src/elflint.c:2769
+#, c-format
+msgid "section [%2d] '%s': section index %zu out of range\n"
+msgstr "sekcja [%2d] „%s”: indeks sekcji %zu jest spoza zakresu\n"
+
+#: src/elflint.c:2778
+#, c-format
+msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n"
+msgstr ""
+"sekcja [%2d] „%s”: nie można uzyskać nagłówka sekcji dla elementu %zu: %s\n"
+
+#: src/elflint.c:2785
+#, c-format
+msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n"
+msgstr "sekcja [%2d] „%s”: grupa sekcji zawiera inną grupę [%2d] „%s”\n"
+
+#: src/elflint.c:2791
+#, c-format
+msgid ""
+"section [%2d] '%s': element %zu references section [%2d] '%s' without "
+"SHF_GROUP flag set\n"
+msgstr ""
+"sekcja [%2d] „%s”: element %zu odwołuje się do sekcji [%2d] „%s” bez flagi "
+"SHF_GROUP\n"
+
+#: src/elflint.c:2798
+#, c-format
+msgid "section [%2d] '%s' is contained in more than one section group\n"
+msgstr "sekcja [%2d] „%s” jest zawarta w więcej niż jednej grupie sekcji\n"
+
+#: src/elflint.c:2995
+#, c-format
+msgid ""
+"section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no "
+"dynamic symbol table\n"
+msgstr ""
+"sekcja [%2d] „%s” odwołuje się w sh_link do sekcji [%2d] „%s”, która nie "
+"jest tabelą symboli dynamicznych\n"
+
+#: src/elflint.c:3007
+#, c-format
+msgid ""
+"section [%2d] '%s' has different number of entries than symbol table [%2d] "
+"'%s'\n"
+msgstr ""
+"sekcja [%2d] „%s” ma inną liczbę wpisów niż tabela symboli [%2d] „%s”\n"
+
+#: src/elflint.c:3023
+#, c-format
+msgid "section [%2d] '%s': symbol %d: cannot read version data\n"
+msgstr "sekcja [%2d] „%s”: symbol %d: nie można odczytać danych wersji\n"
+
+#: src/elflint.c:3039
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n"
+msgstr "sekcja [%2d] „%s”: symbol %d: symbol lokalny z zakresem globalnym\n"
+
+#: src/elflint.c:3047
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with version\n"
+msgstr "sekcja [%2d] „%s”: symbol %d: symbol lokalny z wersją\n"
+
+#: src/elflint.c:3061
+#, c-format
+msgid "section [%2d] '%s': symbol %d: invalid version index %d\n"
+msgstr "sekcja [%2d] „%s”: symbol %d: nieprawidłowy indeks wersji %d\n"
+
+#: src/elflint.c:3066
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for defined version\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %d: indeks wersji %d jest dla wersji określonej\n"
+
+#: src/elflint.c:3076
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for requested version\n"
+msgstr ""
+"sekcja [%2d] „%s”: symbol %d: indeks wersji %d jest dla wersji żądanej\n"
+
+#: src/elflint.c:3129
+#, c-format
+msgid "more than one version reference section present\n"
+msgstr "obecna jest więcej niż jedna sekcja odniesienia wersji\n"
+
+#: src/elflint.c:3137 src/elflint.c:3284
+#, c-format
+msgid "section [%2d] '%s': sh_link does not link to string table\n"
+msgstr "sekcja [%2d] „%s”: sh_link nie łączy się z tabelą ciągów\n"
+
+#: src/elflint.c:3162 src/elflint.c:3338
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong version %d\n"
+msgstr "sekcja [%2d] „%s”: wpis %d ma błędną wersję %d\n"
+
+#: src/elflint.c:3169 src/elflint.c:3345
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"
+msgstr "sekcja [%2d] „%s”: wpis %d ma błędny offset dla danych dodatkowych\n"
+
+#: src/elflint.c:3179
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid file reference\n"
+msgstr "sekcja [%2d] „%s”: symbol %d ma błędne odniesienie do pliku\n"
+
+#: src/elflint.c:3187
+#, c-format
+msgid "section [%2d] '%s': entry %d references unknown dependency\n"
+msgstr "sekcja [%2d] „%s”: wpis %d odnosi się do nieznanej zależności\n"
+
+#: src/elflint.c:3199
+#, c-format
+msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"
+msgstr "sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma nieznaną flagę\n"
+
+#: src/elflint.c:3207
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has invalid name "
+"reference\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma nieprawidłowe "
+"odniesienie do nazwy\n"
+
+#: src/elflint.c:3216
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: "
+"%#x, expected %#x\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma błędną wartość skrótu: "
+"%#x, oczekiwano %#x\n"
+
+#: src/elflint.c:3225
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version "
+"name '%s'\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma powtórzoną nazwę wersji "
+"„%s”\n"
+
+#: src/elflint.c:3236
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis dodatkowy %d do wpisu %d ma błędne następne pole\n"
+
+#: src/elflint.c:3253 src/elflint.c:3429
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n"
+msgstr "sekcja [%2d] „%s”: wpis %d ma błędny offset do następnego wpisu\n"
+
+#: src/elflint.c:3261 src/elflint.c:3437
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says "
+"there are more entries\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %d ma zerowy offset do następnego wpisu, ale sh_info "
+"zawiera informacje o większej liczbie wpisów\n"
+
+#: src/elflint.c:3276
+#, c-format
+msgid "more than one version definition section present\n"
+msgstr "obecna jest więcej niż jedna sekcja definicji wersji\n"
+
+#: src/elflint.c:3323
+#, c-format
+msgid "section [%2d] '%s': more than one BASE definition\n"
+msgstr "sekcja [%2d] „%s”: jest więcej niż jedna definicja BASE\n"
+
+#: src/elflint.c:3327
+#, c-format
+msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"
+msgstr "sekcja [%2d] „%s”: definicja BASE musi mieć indeks VER_NDX_GLOBAL\n"
+
+#: src/elflint.c:3333
+#, c-format
+msgid "section [%2d] '%s': entry %d has unknown flag\n"
+msgstr "sekcja [%2d] „%s”: wpis %d ma nieznaną flagę\n"
+
+#: src/elflint.c:3360
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid name reference\n"
+msgstr "sekcja [%2d] „%s”: wpis %d ma nieprawidłowe odniesienie do nazwy\n"
+
+#: src/elflint.c:3367
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %d ma błędną wartość skrótu: %#x, oczekiwano %#x\n"
+
+#: src/elflint.c:3375
+#, c-format
+msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n"
+msgstr "sekcja [%2d] „%s”: wpis %d ma powtórzoną nazwę wersji „%s”\n"
+
+#: src/elflint.c:3395
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %d ma nieprawidłowe odniesienie do nazwy w danych "
+"dodatkowych\n"
+
+#: src/elflint.c:3412
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"
+msgstr ""
+"sekcja [%2d] „%s”: wpis %d ma błędne następne pole w danych dodatkowych\n"
+
+#: src/elflint.c:3445
+#, c-format
+msgid "section [%2d] '%s': no BASE definition\n"
+msgstr "sekcja [%2d] „%s”: brak definicji BASE\n"
+
+#: src/elflint.c:3461
+#, c-format
+msgid "section [%2d] '%s': unknown parent version '%s'\n"
+msgstr "sekcja [%2d] „%s”: nieznana wersja rodzica „%s”\n"
+
+#: src/elflint.c:3486
+#, c-format
+msgid "section [%2d] '%s': empty object attributes section\n"
+msgstr "sekcja [%2d] „%s”: pusta sekcja atrybutów obiektu\n"
+
+#: src/elflint.c:3502
+#, c-format
+msgid "section [%2d] '%s': unrecognized attribute format\n"
+msgstr "sekcja [%2d] „%s”: nierozpoznany format atrybutu\n"
+
+#: src/elflint.c:3513
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute section\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: pole o zerowej długości w sekcji atrybutów\n"
+
+#: src/elflint.c:3522
+#, c-format
+msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: nieprawidłowa długość w sekcji atrybutów\n"
+
+#: src/elflint.c:3534
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n"
+msgstr "sekcja [%2d] „%s”: offset %zu: niezakończony ciąg nazwy producenta\n"
+
+#: src/elflint.c:3551
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: niekończące się ULEB128 w znaczniku podsekcji "
+"atrybutów\n"
+
+#: src/elflint.c:3560
+#, c-format
+msgid "section [%2d] '%s': offset %zu: truncated attribute section\n"
+msgstr "sekcja [%2d] „%s”: offset %zu: skrócona sekcja atrybutów\n"
+
+#: src/elflint.c:3569
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: zerowej długości pole w podsekcji atrybutów\n"
+
+#: src/elflint.c:3584
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: nieprawidłowa długość w podsekcji atrybutów\n"
+
+#. Tag_File
+#: src/elflint.c:3595
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: podsekcja atrybutów ma nieoczekiwany znacznik "
+"%u\n"
+
+#: src/elflint.c:3616
+#, c-format
+msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: niekończące się ULEB128 w znaczniku atrybutu\n"
+
+#: src/elflint.c:3627
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n"
+msgstr "sekcja [%2d] „%s”: offset %zu: niezakończony ciąg w atrybucie\n"
+
+#: src/elflint.c:3640
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"
+msgstr "sekcja [%2d] „%s”: offset %zu: nierozpoznany znacznik atrybutu %u\n"
+
+#: src/elflint.c:3644
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: unrecognized %s attribute value %<PRIu64>\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: atrybut %s ma nierozpoznaną wartość "
+"%<PRIu64>\n"
+
+#: src/elflint.c:3654
+#, c-format
+msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n"
+msgstr "sekcja [%2d] „%s”: offset %zu: producent „%s” jest nieznany\n"
+
+#: src/elflint.c:3660
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"
+msgstr ""
+"sekcja [%2d] „%s”: offset %zu: dodatkowe bajty po ostatniej sekcji "
+"atrybutów\n"
+
+#: src/elflint.c:3758
+#, c-format
+msgid "cannot get section header of zeroth section\n"
+msgstr "nie można uzyskać nagłówka sekcji zerowej\n"
+
+#: src/elflint.c:3762
+#, c-format
+msgid "zeroth section has nonzero name\n"
+msgstr "sekcja zerowa ma niezerową nazwę\n"
+
+#: src/elflint.c:3764
+#, c-format
+msgid "zeroth section has nonzero type\n"
+msgstr "sekcja zerowa ma niezerowy typ\n"
+
+#: src/elflint.c:3766
+#, c-format
+msgid "zeroth section has nonzero flags\n"
+msgstr "sekcja zerowa ma niezerowe flagi\n"
+
+#: src/elflint.c:3768
+#, c-format
+msgid "zeroth section has nonzero address\n"
+msgstr "sekcja zerowa ma niezerowy adres\n"
+
+#: src/elflint.c:3770
+#, c-format
+msgid "zeroth section has nonzero offset\n"
+msgstr "sekcja zerowa ma niezerowy offset\n"
+
+#: src/elflint.c:3772
+#, c-format
+msgid "zeroth section has nonzero align value\n"
+msgstr "sekcja zerowa ma niezerową wartość wyrównania\n"
+
+#: src/elflint.c:3774
+#, c-format
+msgid "zeroth section has nonzero entry size value\n"
+msgstr "sekcja zerowa ma niezerową wartość rozmiaru wpisu\n"
+
+#: src/elflint.c:3777
+#, c-format
+msgid ""
+"zeroth section has nonzero size value while ELF header has nonzero shnum "
+"value\n"
+msgstr ""
+"sekcja zerowa ma niezerową wartość rozmiaru, a nagłówek ELF ma niezerową "
+"wartość shnum\n"
+
+#: src/elflint.c:3781
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in shstrndx\n"
+msgstr ""
+"sekcja zerowa ma niezerową wartość dowiązań, a nagłówek ELF nie wskazuje "
+"przepełnienia w shstrndx\n"
+
+#: src/elflint.c:3785
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in phnum\n"
+msgstr ""
+"sekcja zerowa ma niezerową wartość dowiązań, a nagłówek ELF nie wskazuje "
+"przepełnienia w phnum\n"
+
+#: src/elflint.c:3803
+#, c-format
+msgid "cannot get section header for section [%2zu] '%s': %s\n"
+msgstr "nie można uzyskać nagłówka sekcji dla sekcji [%2zu] „%s”: %s\n"
+
+#: src/elflint.c:3812
+#, c-format
+msgid "section [%2zu]: invalid name\n"
+msgstr "sekcja [%2zu]: nieprawidłowa nazwa\n"
+
+#: src/elflint.c:3839
+#, c-format
+msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n"
+msgstr "sekcja [%2d] „%s” ma błędny typ: oczekiwano %s, jest %s\n"
+
+#: src/elflint.c:3856
+#, c-format
+msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n"
+msgstr "sekcja [%2zu] „%s” ma błędne flagi: oczekiwano %s, jest %s\n"
+
+#: src/elflint.c:3874
+#, c-format
+msgid ""
+"section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"
+msgstr ""
+"sekcja [%2zu] „%s” ma błędne flagi: oczekiwano %s i być może %s, jest %s\n"
+
+#: src/elflint.c:3891
+#, c-format
+msgid "section [%2zu] '%s' present in object file\n"
+msgstr "sekcja [%2zu] „%s” jest obecna w pliku obiektu\n"
+
+#: src/elflint.c:3897 src/elflint.c:3929
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"
+msgstr ""
+"sekcja [%2zu] „%s” ma flagę SHF_ALLOC, ale nie ma segmentu wczytywalnego\n"
+
+#: src/elflint.c:3902 src/elflint.c:3934
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable "
+"segments\n"
+msgstr ""
+"sekcja [%2zu] „%s” nie ma flagi SHF_ALLOC, ale są segmenty wczytywalne\n"
+
+#: src/elflint.c:3910
+#, c-format
+msgid ""
+"section [%2zu] '%s' is extension section index table in non-object file\n"
+msgstr ""
+"sekcja [%2zu] „%s” jest tabelą indeksów sekcji rozszerzeń w pliku "
+"nieobiektowym\n"
+
+#: src/elflint.c:3953
+#, c-format
+msgid "section [%2zu] '%s': size not multiple of entry size\n"
+msgstr "sekcja [%2zu] „%s”: rozmiar nie jest wielokrotnością rozmiaru wpisu\n"
+
+#: src/elflint.c:3958
+#, c-format
+msgid "cannot get section header\n"
+msgstr "nie można uzyskać nagłówka sekcji\n"
+
+#: src/elflint.c:3968
+#, c-format
+msgid "section [%2zu] '%s' has unsupported type %d\n"
+msgstr "sekcja [%2zu] „%s” ma nieobsługiwany typ %d\n"
+
+#: src/elflint.c:3988
+#, c-format
+msgid ""
+"section [%2zu] '%s' contains invalid processor-specific flag(s) %#<PRIx64>\n"
+msgstr ""
+"sekcja [%2zu] „%s” zawiera nieprawidłowe flagi dla konkretnego procesora "
+"%#<PRIx64>\n"
+
+#: src/elflint.c:3998
+#, c-format
+msgid "section [%2zu] '%s' contains unknown flag(s) %#<PRIx64>\n"
+msgstr "sekcja [%2zu] „%s” zawiera nieznane flagi %#<PRIx64>\n"
+
+#: src/elflint.c:4006
+#, c-format
+msgid "section [%2zu] '%s': thread-local data sections address not zero\n"
+msgstr ""
+"sekcja [%2zu] „%s”: adres sekcji danych lokalnych dla wątków nie jest zerem\n"
+
+#: src/elflint.c:4016
+#, c-format
+msgid "section [%2zu] '%s': allocated section cannot be compressed\n"
+msgstr "sekcja [%2zu] „%s”: nie można skompresować przydzielonej sekcji\n"
+
+#: src/elflint.c:4021
+#, c-format
+msgid "section [%2zu] '%s': nobits section cannot be compressed\n"
+msgstr "sekcja [%2zu] „%s”: nie można skompresować sekcji „nobits”\n"
+
+#: src/elflint.c:4027
+#, c-format
+msgid ""
+"section [%2zu] '%s': compressed section with no compression header: %s\n"
+msgstr "sekcja [%2zu] „%s”: skompresowana sekcja bez nagłówka kompresji: %s\n"
+
+#: src/elflint.c:4033
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in link value\n"
+msgstr ""
+"sekcja [%2zu] „%s”: nieprawidłowe odwołanie do sekcji w wartości dowiązania\n"
+
+#: src/elflint.c:4038
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in info value\n"
+msgstr ""
+"sekcja [%2zu] „%s”: nieprawidłowe odwołanie do sekcji w wartości "
+"informacyjnej\n"
+
+#: src/elflint.c:4045
+#, c-format
+msgid "section [%2zu] '%s': strings flag set without merge flag\n"
+msgstr "sekcja [%2zu] „%s”: flaga ciągów jest ustawiona bez flagi merge\n"
+
+#: src/elflint.c:4050
+#, c-format
+msgid "section [%2zu] '%s': merge flag set but entry size is zero\n"
+msgstr ""
+"sekcja [%2zu] „%s”: flaga merge jest ustawiona, ale rozmiar wpisu jest "
+"zerowy\n"
+
+#: src/elflint.c:4069
+#, c-format
+msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n"
+msgstr "sekcja [%2zu] „%s” ma nieoczekiwany typ %d dla sekcji wykonywalnej\n"
+
+#: src/elflint.c:4078
+#, c-format
+msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"
+msgstr "sekcja [%2zu] „%s” musi być typu NOBITS w plikach debuginfo\n"
+
+#: src/elflint.c:4085
+#, c-format
+msgid "section [%2zu] '%s' is both executable and writable\n"
+msgstr "sekcja [%2zu] „%s” jest wykonywalne i zapisywalne\n"
+
+#: src/elflint.c:4116
+#, c-format
+msgid ""
+"section [%2zu] '%s' not fully contained in segment of program header entry "
+"%d\n"
+msgstr ""
+"sekcja [%2zu] „%s” nie jest w całości zawarta w segmencie wpisu %d nagłówka "
+"programu\n"
+
+#: src/elflint.c:4126
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d\n"
+msgstr ""
+"sekcja [%2zu] „%s” ma typ NOBITS, a jest odczytywana z pliku w segmencie "
+"wpisu %d nagłówka programu\n"
+
+#: src/elflint.c:4152
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d and file contents is non-zero\n"
+msgstr ""
+"sekcja [%2zu] „%s” ma typ NOBITS, ale jest odczytywana z pliku w segmencie "
+"wpisu %d nagłówka programu, a zawartość pliku jest niezerowa\n"
+
+#: src/elflint.c:4163
+#, c-format
+msgid ""
+"section [%2zu] '%s' has not type NOBITS but is not read from the file in "
+"segment of program header entry %d\n"
+msgstr ""
+"sekcja [%2zu] „%s” nie ma typu NOBITS, a nie jest odczytywana z pliku "
+"w segmencie wpisu %d nagłówka programu\n"
+
+#: src/elflint.c:4174
+#, c-format
+msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n"
+msgstr "sekcja [%2zu] „%s” jest wykonywalne w segmencie niewykonywalnym %d\n"
+
+#: src/elflint.c:4184
+#, c-format
+msgid "section [%2zu] '%s' is writable in unwritable segment %d\n"
+msgstr "sekcja [%2zu] „%s” jest zapisywalne w niezapisywalnym segmencie %d\n"
+
+#: src/elflint.c:4194
+#, c-format
+msgid ""
+"section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"
+msgstr ""
+"sekcja [%2zu] „%s”: ma flagę alloc, ale sekcja nie jest w żadnym segmencie "
+"wczytywalnym\n"
+
+#: src/elflint.c:4200
+#, c-format
+msgid ""
+"section [%2zu] '%s': ELF header says this is the section header string table "
+"but type is not SHT_TYPE\n"
+msgstr ""
+"sekcja [%2zu] „%s”: według nagłówka ELF to jest tabela ciągów nagłówków "
+"sekcji, ale typ nie jest SHT_TYPE\n"
+
+#: src/elflint.c:4208
+#, c-format
+msgid ""
+"section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"
+msgstr ""
+"sekcja [%2zu] „%s”: pliki relokowalne nie mogą mieć tabeli symboli "
+"dynamicznych\n"
+
+#: src/elflint.c:4263
+#, c-format
+msgid "more than one version symbol table present\n"
+msgstr "obecna jest więcej niż jedna tabela symboli wersji\n"
+
+#: src/elflint.c:4286
+#, c-format
+msgid "INTERP program header entry but no .interp section\n"
+msgstr "jest wpis nagłówka programu INTERP, ale nie ma sekcji .interp\n"
+
+#: src/elflint.c:4297
+#, c-format
+msgid ""
+"loadable segment [%u] is executable but contains no executable sections\n"
+msgstr ""
+"wczytywalny segment [%u] jest wykonywalny, ale nie zawiera wykonywalnych "
+"sekcji\n"
+
+#: src/elflint.c:4303
+#, c-format
+msgid "loadable segment [%u] is writable but contains no writable sections\n"
+msgstr ""
+"wczytywalny segment [%u] jest zapisywalny, ale nie zawiera zapisywalnych "
+"sekcji\n"
+
+#: src/elflint.c:4314
+#, c-format
+msgid ""
+"no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section "
+"exist\n"
+msgstr ""
+"brak sekcji .gnu.versym, ale istnieje sekcja .gnu.versym_d lub .gnu."
+"versym_r\n"
+
+#: src/elflint.c:4327
+#, c-format
+msgid "duplicate version index %d\n"
+msgstr "powtórzony indeks wersji %d\n"
+
+#: src/elflint.c:4341
+#, c-format
+msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"
+msgstr "sekcja .gnu.versym istnieje bez .gnu.versym_d lub .gnu.versym_r\n"
+
+#: src/elflint.c:4390
+#, c-format
+msgid "phdr[%d]: unknown core file note type %<PRIu32> at offset %<PRIu64>\n"
+msgstr ""
+"phdr[%d]: nieznany typ notatki pliku core %<PRIu32> pod offsetem %<PRIu64>\n"
+
+#: src/elflint.c:4394
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown core file note type %<PRIu32> at offset %zu\n"
+msgstr ""
+"sekcja [%2d]: „%s”: nieznany typ notatki pliku core %<PRIu32> pod offsetem "
+"%zu\n"
+
+#: src/elflint.c:4450
+#, c-format
+msgid ""
+"phdr[%d]: unknown object file note type %<PRIu32> with owner name '%s' at "
+"offset %zu\n"
+msgstr ""
+"phdr[%d]: nieznany typ notatki pliku obiektu %<PRIu32> o nazwie właściciela "
+"„%s” pod offsetem %zu\n"
+
+#: src/elflint.c:4455
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown object file note type %<PRIu32> with owner name "
+"'%s' at offset %zu\n"
+msgstr ""
+"sekcja [%2d] „%s”: nieznany typ notatki pliku obiektu %<PRIu32> o nazwie "
+"właściciela „%s” pod offsetem %zu\n"
+
+#: src/elflint.c:4474
+#, c-format
+msgid "phdr[%d]: no note entries defined for the type of file\n"
+msgstr "phdr[%d]: brak określonych wpisów notatek dla typu pliku\n"
+
+#: src/elflint.c:4494
+#, c-format
+msgid "phdr[%d]: cannot get content of note section: %s\n"
+msgstr "phdr[%d]: nie można uzyskać zawartości sekcji notatki: %s\n"
+
+#: src/elflint.c:4497
+#, c-format
+msgid "phdr[%d]: extra %<PRIu64> bytes after last note\n"
+msgstr "phdr[%d]: dodatkowe %<PRIu64> B po ostatniej notatce\n"
+
+#: src/elflint.c:4518
+#, c-format
+msgid "section [%2d] '%s': no note entries defined for the type of file\n"
+msgstr "sekcja [%2d] „%s”: brak określonych wpisów notatek dla typu pliku\n"
+
+#: src/elflint.c:4525
+#, c-format
+msgid "section [%2d] '%s': cannot get content of note section\n"
+msgstr "sekcja [%2d] „%s”: nie można uzyskać zawartości sekcji notatek\n"
+
+#: src/elflint.c:4528
+#, c-format
+msgid "section [%2d] '%s': extra %<PRIu64> bytes after last note\n"
+msgstr "sekcja [%2d] „%s”: dodatkowe %<PRIu64> B po ostatniej notatce\n"
+
+#: src/elflint.c:4546
+#, c-format
+msgid ""
+"only executables, shared objects, and core files can have program headers\n"
+msgstr ""
+"tylko pliki wykonywalne, obiekty współdzielone i pliki core mogą mieć "
+"nagłówki programu\n"
+
+#: src/elflint.c:4561
+#, c-format
+msgid "cannot get program header entry %d: %s\n"
+msgstr "nie można uzyskać wpisu nagłówka programu %d: %s\n"
+
+#: src/elflint.c:4571
+#, c-format
+msgid "program header entry %d: unknown program header entry type %#<PRIx64>\n"
+msgstr ""
+"wpis nagłówka programu %d: nieznany typ wpisu nagłówka programu %#<PRIx64>\n"
+
+#: src/elflint.c:4582
+#, c-format
+msgid "more than one INTERP entry in program header\n"
+msgstr "więcej niż jeden wpis INTERP w nagłówku programu\n"
+
+#: src/elflint.c:4590
+#, c-format
+msgid "more than one TLS entry in program header\n"
+msgstr "więcej niż jeden wpis TLS w nagłówku programu\n"
+
+#: src/elflint.c:4597
+#, c-format
+msgid "static executable cannot have dynamic sections\n"
+msgstr "statyczny plik wykonywalny nie może mieć sekcji dynamicznych\n"
+
+#: src/elflint.c:4611
+#, c-format
+msgid "dynamic section reference in program header has wrong offset\n"
+msgstr "odniesienie sekcji dynamicznej w nagłówku programu ma błędny offset\n"
+
+#: src/elflint.c:4614
+#, c-format
+msgid "dynamic section size mismatch in program and section header\n"
+msgstr "różne rozmiary sekcji dynamicznej w nagłówku programu i sekcji\n"
+
+#: src/elflint.c:4624
+#, c-format
+msgid "more than one GNU_RELRO entry in program header\n"
+msgstr "więcej niż jeden wpis GNU_RELRO w nagłówku programu\n"
+
+#: src/elflint.c:4645
+#, c-format
+msgid "loadable segment GNU_RELRO applies to is not writable\n"
+msgstr "wczytywalny segment wskazywany przez GNU_RELRO nie jest zapisywalny\n"
+
+#: src/elflint.c:4656
+#, c-format
+msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"
+msgstr "flagi wczytywalnego segmentu [%u] nie pasują do flag GNU_RELRO [%u]\n"
+
+#: src/elflint.c:4663
+#, c-format
+msgid ""
+"GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"
+msgstr ""
+"flagi GNU_RELRO [%u] nie są podzbiorem flag wczytywalnego segmentu [%u]\n"
+
+#: src/elflint.c:4672 src/elflint.c:4695
+#, c-format
+msgid "%s segment not contained in a loaded segment\n"
+msgstr "segment %s nie zawiera się we wczytywalnym segmencie\n"
+
+#: src/elflint.c:4701
+#, c-format
+msgid "program header offset in ELF header and PHDR entry do not match"
+msgstr ""
+"offsety nagłówka programu w nagłówku ELF i wpisie PHDR nie zgadzają się"
+
+#: src/elflint.c:4728
+#, c-format
+msgid "call frame search table reference in program header has wrong offset\n"
+msgstr ""
+"odniesienie tabeli wyszukiwania ramki wywołania w nagłówku programu ma "
+"błędny offset\n"
+
+#: src/elflint.c:4731
+#, c-format
+msgid "call frame search table size mismatch in program and section header\n"
+msgstr ""
+"różne rozmiary tabel wyszukiwania ramki wywołania w nagłówku programu "
+"i sekcji\n"
+
+#: src/elflint.c:4744
+#, c-format
+msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"
+msgstr "PT_GNU_EH_FRAME jest obecne, ale brak sekcji .eh_frame_hdr\n"
+
+#: src/elflint.c:4752
+#, c-format
+msgid "call frame search table must be allocated\n"
+msgstr "tabela wyszukiwania ramki wywołania musi być przydzielona\n"
+
+#: src/elflint.c:4755
+#, c-format
+msgid "section [%2zu] '%s' must be allocated\n"
+msgstr "sekcja [%2zu] „%s”: musi być przydzielona\n"
+
+#: src/elflint.c:4759
+#, c-format
+msgid "call frame search table must not be writable\n"
+msgstr "tabela wyszukiwania ramki wywołania nie może być zapisywalna\n"
+
+#: src/elflint.c:4762
+#, c-format
+msgid "section [%2zu] '%s' must not be writable\n"
+msgstr "sekcja [%2zu] „%s” nie może być zapisywalna\n"
+
+#: src/elflint.c:4767
+#, c-format
+msgid "call frame search table must not be executable\n"
+msgstr "tabela wyszukiwania ramki wywołania nie może być wykonywalna\n"
+
+#: src/elflint.c:4770
+#, c-format
+msgid "section [%2zu] '%s' must not be executable\n"
+msgstr "sekcja [%2zu] „%s” nie może być wykonywalna\n"
+
+#: src/elflint.c:4784
+#, c-format
+msgid "program header entry %d: file size greater than memory size\n"
+msgstr "wpis nagłówka programu %d: rozmiar pliku większy niż rozmiar pamięci\n"
+
+#: src/elflint.c:4791
+#, c-format
+msgid "program header entry %d: alignment not a power of 2\n"
+msgstr "wpis nagłówka programu %d: wyrównanie nie jest potęgą 2\n"
+
+#: src/elflint.c:4794
+#, c-format
+msgid ""
+"program header entry %d: file offset and virtual address not module of "
+"alignment\n"
+msgstr ""
+"wpis nagłówka programu %d: offset w pliku i adres wirtualny nie są "
+"wielokrotnością wyrównania\n"
+
+#: src/elflint.c:4807
+#, c-format
+msgid ""
+"executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME "
+"program header entry"
+msgstr ""
+"plik wykonywalny/DSO z sekcją .eh_frame_hdr nie ma wpisu nagłówka programu "
+"PT_GNU_EH_FRAME"
+
+#: src/elflint.c:4841
+#, c-format
+msgid "cannot read ELF header: %s\n"
+msgstr "nie można odczytać nagłówka ELF: %s\n"
+
+#: src/elflint.c:4853
+#, c-format
+msgid "cannot create backend for ELF file\n"
+msgstr "nie można utworzyć zaplecza dla pliku ELF\n"
+
+#: src/elflint.c:4874
+#, c-format
+msgid "text relocation flag set but not needed\n"
+msgstr "flaga relokacji tekstu jest ustawiona, ale niepotrzebna\n"
+
+#: src/findtextrel.c:60
+msgid "Input Selection:"
+msgstr "Wybór wejścia:"
+
+#: src/findtextrel.c:61
+msgid "Prepend PATH to all file names"
+msgstr "Dołącza ŚCIEŻKĘ do wszystkich nazw plików"
+
+#: src/findtextrel.c:63
+msgid "Use PATH as root of debuginfo hierarchy"
+msgstr "Używa ŚCIEŻKI jako korzenia dla hierarchii debuginfo"
+
+#. Short description of program.
+#: src/findtextrel.c:70
+msgid "Locate source of text relocations in FILEs (a.out by default)."
+msgstr "Odnajduje źródło relokacji tekstu w PLIKACH (domyślnie a.out)."
+
+#. Strings for arguments in help texts.
+#: src/findtextrel.c:74 src/nm.c:107 src/objdump.c:70 src/size.c:79
+#: src/strings.c:86 src/strip.c:100
+msgid "[FILE...]"
+msgstr "[PLIK…]"
+
+#: src/findtextrel.c:223
+#, c-format
+msgid "cannot get ELF header '%s': %s"
+msgstr "nie można uzyskać nagłówka ELF „%s”: %s"
+
+#: src/findtextrel.c:234
+#, c-format
+msgid "'%s' is not a DSO or PIE"
+msgstr "„%s” nie jest DSO ani PIE"
+
+#: src/findtextrel.c:254
+#, c-format
+msgid "getting get section header of section %zu: %s"
+msgstr "uzyskiwanie nagłówka sekcji dla sekcji %zu: %s"
+
+#: src/findtextrel.c:278
+#, c-format
+msgid "cannot read dynamic section: %s"
+msgstr "nie można odczytać sekcji dynamicznej: %s"
+
+#: src/findtextrel.c:299
+#, c-format
+msgid "no text relocations reported in '%s'"
+msgstr "brak relokacji tekstu w „%s”"
+
+#: src/findtextrel.c:310
+#, c-format
+msgid "while reading ELF file"
+msgstr "podczas odczytywania pliku ELF"
+
+#: src/findtextrel.c:314
+#, c-format
+msgid "cannot get program header count: %s"
+msgstr "nie można uzyskać liczby nagłówków programu: %s"
+
+#: src/findtextrel.c:325 src/findtextrel.c:340
+#, c-format
+msgid "cannot get program header index at offset %zd: %s"
+msgstr "nie można uzyskać indeksu nagłówka programu pod offsetem %zd: %s"
+
+#: src/findtextrel.c:396
+#, c-format
+msgid "cannot get symbol table section %zu in '%s': %s"
+msgstr "nie można uzyskać sekcji tabeli symboli %zu w „%s”: %s"
+
+#: src/findtextrel.c:417 src/findtextrel.c:440
+#, c-format
+msgid "cannot get relocation at index %d in section %zu in '%s': %s"
+msgstr "nie można uzyskać relokacji pod indeksem %d w sekcji %zu w „%s”: %s"
+
+#: src/findtextrel.c:506
+#, c-format
+msgid "%s not compiled with -fpic/-fPIC\n"
+msgstr "%s nie został skompilowany z -fpic/-fPIC\n"
+
+#: src/findtextrel.c:560
+#, c-format
+msgid ""
+"the file containing the function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr "plik zawierający funkcję „%s” nie został skompilowany z -fpic/-fPIC\n"
+
+#: src/findtextrel.c:567 src/findtextrel.c:587
+#, c-format
+msgid ""
+"the file containing the function '%s' might not be compiled with -fpic/-"
+"fPIC\n"
+msgstr ""
+"plik zawierający funkcję „%s” mógł nie zostać skompilowany z -fpic/-fPIC\n"
+
+#: src/findtextrel.c:575
+#, c-format
+msgid ""
+"either the file containing the function '%s' or the file containing the "
+"function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"plik zawierający funkcję „%s” lub plik zawierający funkcję „%s” nie został "
+"skompilowany z -fpic/-fPIC\n"
+
+#: src/findtextrel.c:595
+#, c-format
+msgid ""
+"a relocation modifies memory at offset %llu in a write-protected segment\n"
+msgstr ""
+"relokacja modyfikuje pamięć pod offsetem %llu w segmencie zabezpieczonym "
+"przed zapisem\n"
+
+#: src/nm.c:65 src/strip.c:69
+msgid "Output selection:"
+msgstr "Wybór wyjścia:"
+
+#: src/nm.c:66
+msgid "Display debugger-only symbols"
+msgstr "Wyświetla symbole wyłącznie debugowania"
+
+#: src/nm.c:67
+msgid "Display only defined symbols"
+msgstr "Wyświetla tylko określone symbole"
+
+#: src/nm.c:70
+msgid "Display dynamic symbols instead of normal symbols"
+msgstr "Wyświetla symbole dynamiczne zamiast zwykłych"
+
+#: src/nm.c:71
+msgid "Display only external symbols"
+msgstr "Wyświetla tylko symbole zewnętrzne"
+
+#: src/nm.c:72
+msgid "Display only undefined symbols"
+msgstr "Wyświetla tylko nieokreślone symbole"
+
+#: src/nm.c:74
+msgid "Include index for symbols from archive members"
+msgstr "Dołącza indeks dla symboli z elementów archiwum"
+
+#: src/nm.c:76 src/size.c:53
+msgid "Output format:"
+msgstr "Format wyjścia:"
+
+#: src/nm.c:78
+msgid "Print name of the input file before every symbol"
+msgstr "Wyświetla nazwę pliku wejściowego przed każdym symbolem"
+
+#: src/nm.c:81
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The "
+"default is `sysv'"
+msgstr ""
+"Używa FORMATU wyjściowego. Może to być „bsd”, „sysv” lub „posix”. Domyślny "
+"jest format „sysv”"
+
+#: src/nm.c:83
+msgid "Same as --format=bsd"
+msgstr "To samo, co --format=bsd"
+
+#: src/nm.c:84
+msgid "Same as --format=posix"
+msgstr "To samo co, --format=posix"
+
+#: src/nm.c:85 src/size.c:59
+msgid "Use RADIX for printing symbol values"
+msgstr "Używa BAZY do wypisywania wartości symboli"
+
+#: src/nm.c:86
+msgid "Mark special symbols"
+msgstr "Oznacza specjalne symbole"
+
+#: src/nm.c:88
+msgid "Print size of defined symbols"
+msgstr "Wyświetla rozmiar określonych symboli"
+
+#: src/nm.c:90 src/size.c:67 src/strip.c:74 src/unstrip.c:68
+msgid "Output options:"
+msgstr "Opcje wyjścia:"
+
+#: src/nm.c:91
+msgid "Sort symbols numerically by address"
+msgstr "Porządkuje symbole numerycznie według adresu"
+
+#: src/nm.c:93
+msgid "Do not sort the symbols"
+msgstr "Bez porządkowania symboli"
+
+#: src/nm.c:94
+msgid "Reverse the sense of the sort"
+msgstr "Odwraca kierunek porządkowania"
+
+#: src/nm.c:97
+msgid "Decode low-level symbol names into source code names"
+msgstr "Dekoduje niskopoziomowe nazwy symboli na nazwy kodu źródłowego"
+
+#. Short description of program.
+#: src/nm.c:104
+msgid "List symbols from FILEs (a.out by default)."
+msgstr "Wyświetla listę symboli z PLIKU (domyślnie a.out)."
+
+#: src/nm.c:115 src/objdump.c:78
+msgid "Output formatting"
+msgstr "Formatowanie wyjścia"
+
+#: src/nm.c:139 src/objdump.c:102 src/size.c:104 src/strip.c:132
+#, c-format
+msgid "%s: INTERNAL ERROR %d (%s): %s"
+msgstr "%s: BŁĄD WEWNĘTRZNY %d (%s): %s"
+
+#: src/nm.c:380 src/nm.c:392 src/size.c:287 src/size.c:296 src/size.c:307
+#: src/strip.c:2763
+#, c-format
+msgid "while closing '%s'"
+msgstr "podczas zamykania „%s”"
+
+#: src/nm.c:402 src/objdump.c:279 src/strip.c:827
+#, c-format
+msgid "%s: File format not recognized"
+msgstr "%s: nie rozpoznano formatu pliku"
+
+#. Note: 0 is no valid offset.
+#: src/nm.c:442
+msgid ""
+"\n"
+"Archive index:\n"
+msgstr ""
+"\n"
+"Indeks archiwum:\n"
+
+#: src/nm.c:451
+#, c-format
+msgid "invalid offset %zu for symbol %s"
+msgstr "nieprawidłowy offset %zu dla symbolu %s"
+
+#: src/nm.c:456
+#, c-format
+msgid "%s in %s\n"
+msgstr "%s w %s\n"
+
+#: src/nm.c:464
+#, c-format
+msgid "cannot reset archive offset to beginning"
+msgstr "nie można przywrócić offsetu w archiwum na początek"
+
+#: src/nm.c:489 src/objdump.c:327
+#, c-format
+msgid "%s%s%s: file format not recognized"
+msgstr "%s%s%s: nie rozpoznano formatu pliku"
+
+#: src/nm.c:702
+msgid "cannot create search tree"
+msgstr "nie można utworzyć drzewa wyszukiwania"
+
+#: src/nm.c:742 src/nm.c:1234 src/objdump.c:778 src/readelf.c:685
+#: src/readelf.c:1506 src/readelf.c:1655 src/readelf.c:1882 src/readelf.c:2123
+#: src/readelf.c:2312 src/readelf.c:2482 src/readelf.c:2604 src/readelf.c:2854
+#: src/readelf.c:3140 src/readelf.c:3215 src/readelf.c:3301 src/readelf.c:3897
+#: src/readelf.c:3945 src/readelf.c:4014 src/readelf.c:12030
+#: src/readelf.c:13213 src/readelf.c:13423 src/readelf.c:13491 src/size.c:396
+#: src/size.c:467 src/strip.c:1093
+#, c-format
+msgid "cannot get section header string table index"
+msgstr "nie można uzyskać indeksu tabeli ciągów nagłówków sekcji"
+
+#. We always print this prolog.
+#: src/nm.c:767
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s:\n"
+"\n"
+msgstr ""
+"\n"
+"\n"
+"Symbole z %s:\n"
+"\n"
+
+#. The header line.
+#: src/nm.c:770
+#, c-format
+msgid ""
+"%*s%-*s %-*s Class  Type     %-*s %*s Section\n"
+"\n"
+msgstr ""
+"%*s%-*s %-*s Klasa  Typ      %-*s %*s Sekcja\n"
+"\n"
+
+#: src/nm.c:772
+#, fuzzy
+#| msgid " Name: "
+msgctxt "sysv"
+msgid "Name"
+msgstr " Nazwa: "
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:774
+msgctxt "sysv"
+msgid "Value"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:776
+msgctxt "sysv"
+msgid "Size"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:778
+msgctxt "sysv"
+msgid "Line"
+msgstr ""
+
+#: src/nm.c:1245
+#, c-format
+msgid "%s: entry size in section %zd `%s' is not what we expect"
+msgstr "%s: rozmiar wpisu w sekcji %zd „%s” nie jest tym, czego oczekiwano"
+
+#: src/nm.c:1250
+#, c-format
+msgid "%s: size of section %zd `%s' is not multiple of entry size"
+msgstr "%s: rozmiar sekcji %zd „%s” nie jest wielokrotnością rozmiaru wpisu"
+
+#: src/nm.c:1330
+#, c-format
+msgid "%s: entries (%zd) in section %zd `%s' is too large"
+msgstr "%s: wpisy (%zd) w sekcji %zd „%s” są za duże"
+
+#. XXX Add machine specific object file types.
+#: src/nm.c:1566
+#, c-format
+msgid "%s%s%s%s: Invalid operation"
+msgstr "%s%s%s%s: nieprawidłowe działanie"
+
+#: src/nm.c:1616
+#, c-format
+msgid "%s%s%s: no symbols"
+msgstr "%s%s%s: brak symboli"
+
+#: src/objdump.c:51
+msgid "Mode selection:"
+msgstr "Wybór trybu:"
+
+#: src/objdump.c:52
+msgid "Display relocation information."
+msgstr "Wyświetla informacje o relokacji."
+
+#: src/objdump.c:54
+msgid "Display the full contents of all sections requested"
+msgstr "Wyświetla pełną zawartość żądanych sekcji"
+
+#: src/objdump.c:56
+msgid "Display assembler code of executable sections"
+msgstr "Wyświetla kod asemblera sekcji wykonywalnych"
+
+#: src/objdump.c:58
+msgid "Output content selection:"
+msgstr "Wybór zawartości wyjścia:"
+
+#: src/objdump.c:60
+msgid "Only display information for section NAME."
+msgstr "Wyświetla tylko informacje o sekcji NAZWA."
+
+#. Short description of program.
+#: src/objdump.c:66
+msgid "Show information from FILEs (a.out by default)."
+msgstr "Wyświetla informacje z PLIKÓW (domyślnie a.out)."
+
+#: src/objdump.c:217 src/readelf.c:630
+msgid "No operation specified.\n"
+msgstr "Nie podano działania.\n"
+
+#: src/objdump.c:257 src/objdump.c:269
+#, c-format
+msgid "while close `%s'"
+msgstr "podczas zamykania „%s”"
+
+#: src/objdump.c:362 src/readelf.c:2218 src/readelf.c:2409
+msgid "INVALID SYMBOL"
+msgstr "NIEPRAWIDŁOWY SYMBOL"
+
+#: src/objdump.c:377 src/readelf.c:2252 src/readelf.c:2445
+msgid "INVALID SECTION"
+msgstr "NIEPRAWIDŁOWA SEKCJA"
+
+#: src/objdump.c:497
+#, c-format
+msgid ""
+"\n"
+"RELOCATION RECORDS FOR [%s]:\n"
+"%-*s TYPE                 VALUE\n"
+msgstr ""
+"\n"
+"PISY RELOKACJI DLA [%s]:\n"
+"%-*s TYP                  WARTOŚĆ\n"
+
+#: src/objdump.c:500
+msgid "OFFSET"
+msgstr "OFFSET"
+
+#: src/objdump.c:565
+#, c-format
+msgid "Contents of section %s:\n"
+msgstr "Zawartość sekcji %s:\n"
+
+#: src/objdump.c:686
+msgid "cannot disassemble"
+msgstr "nie można deasemblować"
+
+#: src/objdump.c:757
+msgid "cannot create backend for elf file"
+msgstr "nie można utworzyć zaplecza dla pliku ELF"
+
+#. Short description of program.
+#: src/ranlib.c:62
+msgid "Generate an index to speed access to archives."
+msgstr "Tworzenie indeksu w celu przyspieszenia dostępu do archiwów."
+
+#. Strings for arguments in help texts.
+#: src/ranlib.c:65
+msgid "ARCHIVE"
+msgstr "ARCHIWUM"
+
+#: src/ranlib.c:101
+#, c-format
+msgid "Archive name required"
+msgstr "Wymagana jest nazwa archiwum"
+
+#: src/ranlib.c:165
+#, c-format
+msgid "'%s' is no archive"
+msgstr "„%s” nie jest archiwum"
+
+#: src/ranlib.c:200
+#, c-format
+msgid "error while freeing sub-ELF descriptor: %s"
+msgstr "błąd podczas zwalniania deskryptora pod-ELF: %s"
+
+#: src/readelf.c:97
+msgid "ELF input selection:"
+msgstr "Wybór wyjścia ELF:"
+
+#: src/readelf.c:99
+msgid ""
+"Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data"
+msgstr ""
+"Używa podanej SEKCJI (domyślnie .gnu_debugdata) jako (skompresowanych) "
+"danych wejściowych ELF"
+
+#: src/readelf.c:102
+msgid ""
+"Used with -w to find the skeleton Compile Units in FILE associated with the "
+"Split Compile units in a .dwo input file"
+msgstr ""
+"Używane z opcją -w do wyszukiwania szkieletów jednostek kompilacji w PLIKU "
+"powiązanych z jednostkami podzielonej kompilacji w pliku wejściowym .dwo"
+
+#: src/readelf.c:104
+msgid "ELF output selection:"
+msgstr "Wybór wyjścia ELF:"
+
+#: src/readelf.c:106
+msgid "All these plus -p .strtab -p .dynstr -p .comment"
+msgstr "Wszystkie te plus -p .strtab -p .dynstr -p .comment"
+
+#: src/readelf.c:107
+msgid "Display the dynamic segment"
+msgstr "Wyświetla segment dynamiczny"
+
+#: src/readelf.c:108
+msgid "Display the ELF file header"
+msgstr "Wyświetla nagłówek pliku ELF"
+
+#: src/readelf.c:110
+msgid "Display histogram of bucket list lengths"
+msgstr "Wyświetla histogram długości list kubełków"
+
+#: src/readelf.c:111
+msgid "Display the program headers"
+msgstr "Wyświetla nagłówki programu"
+
+#: src/readelf.c:113
+msgid "Display relocations"
+msgstr "Wyświetla relokacje"
+
+#: src/readelf.c:114
+msgid "Display the section groups"
+msgstr "Wyświetla grupy sekcji"
+
+#: src/readelf.c:115
+msgid "Display the sections' headers"
+msgstr "Wyświetla nagłówki sekcji"
+
+#: src/readelf.c:118
+msgid "Display the symbol table sections"
+msgstr "Wyświetla sekcje tabeli symboli"
+
+#: src/readelf.c:121
+msgid "Display (only) the dynamic symbol table"
+msgstr "Wyświetla (tylko) tabelę symboli dynamicznych"
+
+#: src/readelf.c:122
+msgid "Display versioning information"
+msgstr "Wyświetla informacje o wersji"
+
+#: src/readelf.c:123
+msgid "Display the ELF notes"
+msgstr "Wyświetla notatki ELF"
+
+#: src/readelf.c:125
+msgid "Display architecture specific information, if any"
+msgstr "Wyświetla informacje dla konkretnej architektury, jeśli są"
+
+#: src/readelf.c:127
+msgid "Display sections for exception handling"
+msgstr "Wyświetla sekcje do obsługi wyjątków"
+
+#: src/readelf.c:129
+msgid "Additional output selection:"
+msgstr "Dodatkowy wybór wyjścia:"
+
+#: src/readelf.c:131
+msgid ""
+"Display DWARF section content.  SECTION can be one of abbrev, addr, aranges, "
+"decodedaranges, frame, gdb_index, info, info+, loc, line, decodedline, "
+"ranges, pubnames, str, macinfo, macro or exception"
+msgstr ""
+"Wyświetla zawartość sekcji DWARF. SEKCJA może być jednym z abbrev, addr, "
+"aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
+"decodedline, ranges, pubnames, str, macinfo, macro lub exception"
+
+#: src/readelf.c:135
+msgid "Dump the uninterpreted contents of SECTION, by number or name"
+msgstr "Zrzuca niezinterpretowaną zawartość SEKCJI, według liczny lub nazwy"
+
+#: src/readelf.c:137
+msgid "Print string contents of sections"
+msgstr "Wyświetla zawartość ciągów sekcji"
+
+#: src/readelf.c:140
+msgid "Display the symbol index of an archive"
+msgstr "Wyświetla indeks symboli archiwum"
+
+#: src/readelf.c:142
+msgid "Use the dynamic segment when possible for displaying info"
+msgstr ""
+
+#: src/readelf.c:144
+msgid "Output control:"
+msgstr "Kontrola wyjścia:"
+
+#: src/readelf.c:146
+msgid "Do not find symbol names for addresses in DWARF data"
+msgstr "Bez odnajdywania nazw symboli dla adresów w danych DWARF"
+
+#: src/readelf.c:148
+msgid ""
+"Display just offsets instead of resolving values to addresses in DWARF data"
+msgstr ""
+"Wyświetla tylko offsety zamiast rozwiązywania wartości na adresy w danych "
+"DWARF"
+
+#: src/readelf.c:150
+msgid "Ignored for compatibility (lines always wide)"
+msgstr "Ignorowane dla zgodności (wiersze są zawsze szerokie)"
+
+#: src/readelf.c:152
+msgid ""
+"Show compression information for compressed sections (when used with -S); "
+"decompress section before dumping data (when used with -p or -x)"
+msgstr ""
+"Wyświetla informacje o kompresji dla skompresowanych sekcji (kiedy jest "
+"używane z opcją -S); dekompresuje sekcję przed zrzuceniem danych (kiedy jest "
+"używane z opcją -p lub -x)"
+
+#. Short description of program.
+#: src/readelf.c:157
+msgid "Print information from ELF file in human-readable form."
+msgstr "Wyświetla informacje z pliku ELF w postaci czytelnej dla człowieka."
+
+#. Look up once.
+#: src/readelf.c:395
+msgid "yes"
+msgstr "tak"
+
+#: src/readelf.c:396
+msgid "no"
+msgstr "nie"
+
+#: src/readelf.c:598
+#, c-format
+msgid "Unknown DWARF debug section `%s'.\n"
+msgstr "Nieznana sekcja debugowania DWARF „%s”.\n"
+
+#: src/readelf.c:669 src/readelf.c:780
+#, c-format
+msgid "cannot generate Elf descriptor: %s"
+msgstr "nie można utworzyć deskryptora ELF: %s"
+
+#: src/readelf.c:676 src/readelf.c:1002 src/strip.c:1188
+#, c-format
+msgid "cannot determine number of sections: %s"
+msgstr "nie można określić liczby sekcji: %s"
+
+#: src/readelf.c:694 src/readelf.c:1322 src/readelf.c:1530
+#, c-format
+msgid "cannot get section: %s"
+msgstr "nie można uzyskać sekcji: %s"
+
+#: src/readelf.c:703 src/readelf.c:1329 src/readelf.c:1537 src/readelf.c:13443
+#: src/unstrip.c:396 src/unstrip.c:427 src/unstrip.c:490 src/unstrip.c:622
+#: src/unstrip.c:640 src/unstrip.c:680 src/unstrip.c:897 src/unstrip.c:1263
+#: src/unstrip.c:1390 src/unstrip.c:1414 src/unstrip.c:1470 src/unstrip.c:1511
+#: src/unstrip.c:1703 src/unstrip.c:1854 src/unstrip.c:1998 src/unstrip.c:2106
+#, c-format
+msgid "cannot get section header: %s"
+msgstr "nie można uzyskać nagłówka sekcji: %s"
+
+#: src/readelf.c:711
+#, c-format
+msgid "cannot get section name"
+msgstr "nie można uzyskać nazwy sekcji"
+
+#: src/readelf.c:720 src/readelf.c:7177 src/readelf.c:11231 src/readelf.c:11333
+#: src/readelf.c:11517
+#, c-format
+msgid "cannot get %s content: %s"
+msgstr "nie można uzyskać zwartości %s: %s"
+
+#: src/readelf.c:736
+#, c-format
+msgid "cannot create temp file '%s'"
+msgstr "nie można utworzyć pliku tymczasowego „%s”"
+
+#: src/readelf.c:745
+#, c-format
+msgid "cannot write section data"
+msgstr "nie można zapisać danych sekcji"
+
+#: src/readelf.c:751 src/readelf.c:768 src/readelf.c:797
+#, c-format
+msgid "error while closing Elf descriptor: %s"
+msgstr "błąd podczas zamykania deskryptora ELF: %s"
+
+#: src/readelf.c:758
+#, c-format
+msgid "error while rewinding file descriptor"
+msgstr "błąd podczas przewijania deskryptora pliku"
+
+#: src/readelf.c:792
+#, c-format
+msgid "'%s' is not an archive, cannot print archive index"
+msgstr "„%s” nie jest archiwum, nie można wyświetlić indeksu archiwum"
+
+#: src/readelf.c:896
+#, c-format
+msgid "cannot stat input file"
+msgstr "nie można wykonać stat na pliku wejściowym"
+
+#: src/readelf.c:898
+#, c-format
+msgid "input file is empty"
+msgstr "plik wejściowy jest pusty"
+
+#: src/readelf.c:900
+#, c-format
+msgid "failed reading '%s': %s"
+msgstr "odczytanie „%s” się nie powiodło: %s"
+
+#: src/readelf.c:929
+#, c-format
+msgid "No such section '%s' in '%s'"
+msgstr "Brak sekcji „%s” w „%s”"
+
+#: src/readelf.c:988
+#, c-format
+msgid "cannot read ELF header: %s"
+msgstr "nie można odczytać nagłówka ELF: %s"
+
+#: src/readelf.c:996
+#, c-format
+msgid "cannot create EBL handle"
+msgstr "nie można utworzyć uchwytu EBL"
+
+#: src/readelf.c:1007
+#, c-format
+msgid "cannot determine number of program headers: %s"
+msgstr "nie można określić liczby nagłówków programu: %s"
+
+#: src/readelf.c:1039
+#, c-format
+msgid "cannot read ELF: %s"
+msgstr "nie można odczytać danych ELF: %s"
+
+#: src/readelf.c:1072
+#, fuzzy
+#| msgid "cannot get section: %s"
+msgid "cannot find section"
+msgstr "nie można uzyskać sekcji: %s"
+
+#: src/readelf.c:1109
+msgid "NONE (None)"
+msgstr "NONE (żaden)"
+
+#: src/readelf.c:1110
+msgid "REL (Relocatable file)"
+msgstr "REL (plik relokowalny)"
+
+#: src/readelf.c:1111
+msgid "EXEC (Executable file)"
+msgstr "EXEC (plik wykonywalny)"
+
+#: src/readelf.c:1112
+msgid "DYN (Shared object file)"
+msgstr "DYN (plik obiektu współdzielonego)"
+
+#: src/readelf.c:1113
+msgid "CORE (Core file)"
+msgstr "CORE (plik core)"
+
+#: src/readelf.c:1118
+#, c-format
+msgid "OS Specific: (%x)\n"
+msgstr "Zależny od systemu: (%x)\n"
+
+#. && e_type <= ET_HIPROC always true
+#: src/readelf.c:1120
+#, c-format
+msgid "Processor Specific: (%x)\n"
+msgstr "Zależny od procesora: (%x)\n"
+
+#: src/readelf.c:1130
+msgid ""
+"ELF Header:\n"
+"  Magic:  "
+msgstr ""
+"Nagłówek ELF:\n"
+"  Magic:  "
+
+#: src/readelf.c:1134
+#, c-format
+msgid ""
+"\n"
+"  Class:                             %s\n"
+msgstr ""
+"\n"
+"  Klasa:                             %s\n"
+
+#: src/readelf.c:1139
+#, c-format
+msgid "  Data:                              %s\n"
+msgstr "  Dane:                              %s\n"
+
+#: src/readelf.c:1145
+#, c-format
+msgid "  Ident Version:                     %hhd %s\n"
+msgstr "  Wersja Ident:                      %hhd %s\n"
+
+#: src/readelf.c:1147 src/readelf.c:1169
+msgid "(current)"
+msgstr "(bieżąca)"
+
+#: src/readelf.c:1151
+#, c-format
+msgid "  OS/ABI:                            %s\n"
+msgstr "  System operacyjny/ABI:             %s\n"
+
+#: src/readelf.c:1154
+#, c-format
+msgid "  ABI Version:                       %hhd\n"
+msgstr "  Wersja ABI:                        %hhd\n"
+
+#: src/readelf.c:1157
+msgid "  Type:                              "
+msgstr "  Typ:                               "
+
+#: src/readelf.c:1162
+#, c-format
+msgid "  Machine:                           %s\n"
+msgstr "  Komputer:                          %s\n"
+
+#: src/readelf.c:1164
+#, c-format
+msgid "  Machine:                           <unknown>: 0x%x\n"
+msgstr "  Komputer:                          <nieznany>: 0x%x\n"
+
+#: src/readelf.c:1167
+#, c-format
+msgid "  Version:                           %d %s\n"
+msgstr "  Wersja:                            %d %s\n"
+
+#: src/readelf.c:1171
+#, c-format
+msgid "  Entry point address:               %#<PRIx64>\n"
+msgstr "  Adres punktu wejściowego:          %#<PRIx64>\n"
+
+#: src/readelf.c:1174
+#, c-format
+msgid "  Start of program headers:          %<PRId64> %s\n"
+msgstr "  Początek nagłówków programu:       %<PRId64> %s\n"
+
+#: src/readelf.c:1175 src/readelf.c:1178
+msgid "(bytes into file)"
+msgstr "(bajtów w pliku)"
+
+#: src/readelf.c:1177
+#, c-format
+msgid "  Start of section headers:          %<PRId64> %s\n"
+msgstr "  Początek nagłówków sekcji:         %<PRId64> %s\n"
+
+#: src/readelf.c:1180
+#, c-format
+msgid "  Flags:                             %s\n"
+msgstr "  Flagi:                             %s\n"
+
+#: src/readelf.c:1183
+#, c-format
+msgid "  Size of this header:               %<PRId16> %s\n"
+msgstr "  Rozmiar tego nagłówka:             %<PRId16> %s\n"
+
+#: src/readelf.c:1184 src/readelf.c:1187 src/readelf.c:1204
+msgid "(bytes)"
+msgstr "(bajtów)"
+
+#: src/readelf.c:1186
+#, c-format
+msgid "  Size of program header entries:    %<PRId16> %s\n"
+msgstr "  Rozmiar wpisów nagłówka programu:  %<PRId16> %s\n"
+
+#: src/readelf.c:1189
+#, c-format
+msgid "  Number of program headers entries: %<PRId16>"
+msgstr "  Liczba wpisów nagłówków programu: %<PRId16>"
+
+#: src/readelf.c:1196
+#, c-format
+msgid " (%<PRIu32> in [0].sh_info)"
+msgstr " (%<PRIu32> w [0].sh_info)"
+
+#: src/readelf.c:1199 src/readelf.c:1216 src/readelf.c:1230
+msgid " ([0] not available)"
+msgstr " ([0] niedostępny)"
+
+#: src/readelf.c:1203
+#, c-format
+msgid "  Size of section header entries:    %<PRId16> %s\n"
+msgstr "  Rozmiar wpisów nagłówka sekcji:    %<PRId16> %s\n"
+
+#: src/readelf.c:1206
+#, c-format
+msgid "  Number of section headers entries: %<PRId16>"
+msgstr "  Liczba wpisów nagłówków sekcji:    %<PRId16>"
+
+#: src/readelf.c:1213
+#, c-format
+msgid " (%<PRIu32> in [0].sh_size)"
+msgstr " (%<PRIu32> w [0].sh_size)"
+
+#. We managed to get the zeroth section.
+#: src/readelf.c:1226
+#, c-format
+msgid " (%<PRIu32> in [0].sh_link)"
+msgstr " (%<PRIu32> w [0].sh_link)"
+
+#: src/readelf.c:1234
+#, c-format
+msgid ""
+"  Section header string table index: XINDEX%s\n"
+"\n"
+msgstr ""
+"  Indeks tabeli ciągów nagłówków sekcji: XINDEX%s\n"
+"\n"
+
+#: src/readelf.c:1238
+#, c-format
+msgid ""
+"  Section header string table index: %<PRId16>\n"
+"\n"
+msgstr ""
+"  Indeks tabeli ciągów nagłówków sekcji: %<PRId16>\n"
+"\n"
+
+#: src/readelf.c:1288 src/readelf.c:1496
+#, c-format
+msgid "cannot get number of sections: %s"
+msgstr "nie można uzyskać liczby sekcji: %s"
+
+#: src/readelf.c:1291
+#, c-format
+msgid ""
+"There are %zd section headers, starting at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"Liczba nagłówków sekcji: %zd, rozpoczynających się od offsetu %#<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:1299
+#, c-format
+msgid "cannot get section header string table index: %s"
+msgstr "nie można uzyskać indeksu tabeli ciągów nagłówków sekcji: %s"
+
+#: src/readelf.c:1302
+msgid "Section Headers:"
+msgstr "Nagłówki sekcji:"
+
+#: src/readelf.c:1305
+msgid ""
+"[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk "
+"Inf Al"
+msgstr ""
+"[Nr] Nazwa                Typ          Adres    Offset Rozm.  ES Flagi Lk "
+"Inf Al"
+
+#: src/readelf.c:1307
+msgid ""
+"[Nr] Name                 Type         Addr             Off      Size     ES "
+"Flags Lk Inf Al"
+msgstr ""
+"[Nr] Nazwa                Typ          Adres            Offset   Rozmiar  ES "
+"Flagi Lk Inf Al"
+
+#: src/readelf.c:1312
+msgid "     [Compression  Size   Al]"
+msgstr "     [Kompresja  Rozmiar   Al]"
+
+#: src/readelf.c:1314
+msgid "     [Compression  Size     Al]"
+msgstr "     [Kompresja  Rozmiar     Al]"
+
+#: src/readelf.c:1392
+#, c-format
+msgid "bad compression header for section %zd: %s"
+msgstr "błędny nagłówek kompresji dla sekcji %zd: %s"
+
+#: src/readelf.c:1403
+#, c-format
+msgid "bad gnu compressed size for section %zd: %s"
+msgstr "błędny rozmiar kompresji gnu dla sekcji %zd: %s"
+
+#: src/readelf.c:1421
+msgid "Program Headers:"
+msgstr "Nagłówki programu:"
+
+#: src/readelf.c:1423
+msgid ""
+"  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"
+msgstr ""
+"  Typ            Offset   AdresWirt  AdresFiz   RozmPlik RozmPam  Flg "
+"Wyrównanie"
+
+#: src/readelf.c:1426
+msgid ""
+"  Type           Offset   VirtAddr           PhysAddr           FileSiz  "
+"MemSiz   Flg Align"
+msgstr ""
+"  Typ            Offset   AdresWirtualny     AdresFizyczny      RozmPlik "
+"RozmPam  Flg Wyrównanie"
+
+#: src/readelf.c:1483
+#, c-format
+msgid "\t[Requesting program interpreter: %s]\n"
+msgstr "\t[Wywołanie interpretera programu: %s]\n"
+
+#: src/readelf.c:1508
+msgid ""
+"\n"
+" Section to Segment mapping:\n"
+"  Segment Sections..."
+msgstr ""
+"\n"
+" Mapowanie sekcji do segmentów:\n"
+"  Segment sekcji…"
+
+#: src/readelf.c:1519 src/unstrip.c:2165 src/unstrip.c:2207 src/unstrip.c:2214
+#, c-format
+msgid "cannot get program header: %s"
+msgstr "nie można uzyskać nagłówka programu: %s"
+
+#: src/readelf.c:1663
+#, c-format
+msgid ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Grupa sekcji COMDAT [%2zu] „%s” z podpisem „%s” zawiera %zu wpis:\n"
+msgstr[1] ""
+"\n"
+"Grupa sekcji COMDAT [%2zu] „%s” z podpisem „%s” zawiera %zu wpisy:\n"
+msgstr[2] ""
+"\n"
+"Grupa sekcji COMDAT [%2zu] „%s” z podpisem „%s” zawiera %zu wpisów:\n"
+
+#: src/readelf.c:1668
+#, c-format
+msgid ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Grupa sekcji [%2zu] „%s” z podpisem „%s” zawiera %zu wpis:\n"
+msgstr[1] ""
+"\n"
+"Grupa sekcji [%2zu] „%s” z podpisem „%s” zawiera %zu wpisy:\n"
+msgstr[2] ""
+"\n"
+"Grupa sekcji [%2zu] „%s” z podpisem „%s” zawiera %zu wpisów:\n"
+
+#: src/readelf.c:1676
+msgid "<INVALID SYMBOL>"
+msgstr "<NIEPRAWIDŁOWY SYMBOL>"
+
+#: src/readelf.c:1690
+msgid "<INVALID SECTION>"
+msgstr "<NIEPRAWIDŁOWY SEKCJA>"
+
+#: src/readelf.c:1713 src/readelf.c:2614 src/readelf.c:3913 src/readelf.c:4213
+#: src/readelf.c:13315 src/readelf.c:13322 src/readelf.c:13366
+#: src/readelf.c:13373
+msgid "Couldn't uncompress section"
+msgstr "Nie można dekompresować sekcji"
+
+#: src/readelf.c:1717 src/readelf.c:2619 src/readelf.c:3917
+#, c-format
+msgid "cannot get section [%zd] header: %s"
+msgstr "nie można uzyskać nagłówka sekcji [%zd]: %s"
+
+#: src/readelf.c:1886 src/readelf.c:2860 src/readelf.c:3146 src/readelf.c:3221
+#: src/readelf.c:3524 src/readelf.c:3598 src/readelf.c:5963
+#, c-format
+msgid "invalid sh_link value in section %zu"
+msgstr "nieprawidłowa wartość sh_link w sekcji %zu"
+
+#: src/readelf.c:1889
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Segment dynamiczny zawiera %lu wpis:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"'%s'\n"
+msgstr[1] ""
+"\n"
+"Segment dynamiczny zawiera %lu wpisy:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"'%s'\n"
+msgstr[2] ""
+"\n"
+"Segment dynamiczny zawiera %lu wpisów:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"'%s'\n"
+
+#: src/readelf.c:1902
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "Dynamic segment contains %lu entry:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+#| msgid_plural ""
+#| "\n"
+#| "Dynamic segment contains %lu entries:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgstr[0] ""
+"\n"
+"Segment dynamiczny zawiera %lu wpis:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"'%s'\n"
+msgstr[1] ""
+"\n"
+"Segment dynamiczny zawiera %lu wpisy:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"'%s'\n"
+msgstr[2] ""
+"\n"
+"Segment dynamiczny zawiera %lu wpisów:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"'%s'\n"
+
+#: src/readelf.c:1912
+msgid "  Type              Value\n"
+msgstr "  Typ               Wartość\n"
+
+#: src/readelf.c:1921
+#, fuzzy
+#| msgid "cannot get string section data: %s"
+msgid "cannot get string table by using dynamic segment"
+msgstr "nie można uzyskać danych sekcji ciągów: %s"
+
+#: src/readelf.c:1960
+#, c-format
+msgid "Shared library: [%s]\n"
+msgstr "Biblioteka współdzielona: [%s]\n"
+
+#: src/readelf.c:1964
+#, c-format
+msgid "Library soname: [%s]\n"
+msgstr "soname biblioteki: [%s]\n"
+
+#: src/readelf.c:1968
+#, c-format
+msgid "Library rpath: [%s]\n"
+msgstr "rpath biblioteki: [%s]\n"
+
+#: src/readelf.c:1972
+#, c-format
+msgid "Library runpath: [%s]\n"
+msgstr "runpath biblioteki: [%s]\n"
+
+#: src/readelf.c:1993
+#, c-format
+msgid "%<PRId64> (bytes)\n"
+msgstr "%<PRId64> (bajtów)\n"
+
+#: src/readelf.c:2109 src/readelf.c:2298
+#, c-format
+msgid ""
+"\n"
+"Invalid symbol table at offset %#0<PRIx64>\n"
+msgstr ""
+"\n"
+"Nieprawidłowa tabela symboli pod offsetem %#0<PRIx64>\n"
+
+#: src/readelf.c:2126 src/readelf.c:2315
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Sekcja relokacji [%2zu] „%s” dla sekcji [%2u] „%s” pod offsetem %#0<PRIx64> "
+"zawiera %d wpis:\n"
+msgstr[1] ""
+"\n"
+"Sekcja relokacji [%2zu] „%s” dla sekcji [%2u] „%s” pod offsetem %#0<PRIx64> "
+"zawiera %d wpisy:\n"
+msgstr[2] ""
+"\n"
+"Sekcja relokacji [%2zu] „%s” dla sekcji [%2u] „%s” pod offsetem %#0<PRIx64> "
+"zawiera %d wpisów:\n"
+
+#. The .rel.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. The .rela.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. A .relr.dyn section does not refer to a specific section.
+#: src/readelf.c:2141 src/readelf.c:2330 src/readelf.c:2485
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Sekcja relokacji [%2u] „%s” pod offsetem %#0<PRIx64> zawiera %d wpis:\n"
+msgstr[1] ""
+"\n"
+"Sekcja relokacji [%2u] „%s” pod offsetem %#0<PRIx64> zawiera %d wpisy:\n"
+msgstr[2] ""
+"\n"
+"Sekcja relokacji [%2u] „%s” pod offsetem %#0<PRIx64> zawiera %d wpisów:\n"
+
+#: src/readelf.c:2151
+msgid "  Offset      Type                 Value       Name\n"
+msgstr "  Offset      Typ                  Wartość     Nazwa\n"
+
+#: src/readelf.c:2153
+msgid "  Offset              Type                 Value               Name\n"
+msgstr "  Offset              Typ                  Wartość             Nazwa\n"
+
+#: src/readelf.c:2206 src/readelf.c:2217 src/readelf.c:2230 src/readelf.c:2251
+#: src/readelf.c:2263 src/readelf.c:2396 src/readelf.c:2408 src/readelf.c:2422
+#: src/readelf.c:2444 src/readelf.c:2457
+msgid "<INVALID RELOC>"
+msgstr "<NIEPRAWIDŁOWA RELOKACJA>"
+
+#: src/readelf.c:2340
+msgid "  Offset      Type            Value       Addend Name\n"
+msgstr "  Offset      Typ             Wartość     Koniec Nazwa\n"
+
+#: src/readelf.c:2342
+msgid "  Offset              Type            Value               Addend Name\n"
+msgstr ""
+"  Offset              Typ             Wartość             Koniec Nazwa\n"
+
+#: src/readelf.c:2654
+#, c-format
+msgid "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+msgstr "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+
+#: src/readelf.c:2750
+#, c-format
+msgid "bad dynamic symbol"
+msgstr "błędny symbol dynamiczny"
+
+#: src/readelf.c:2868
+#, c-format
+msgid ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entry:\n"
+msgid_plural ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entries:\n"
+msgstr[0] ""
+"\n"
+"Tabela symboli [%2u] „%s” zawiera %u wpis:\n"
+msgstr[1] ""
+"\n"
+"Tabela symboli [%2u] „%s” zawiera %u wpisy:\n"
+msgstr[2] ""
+"\n"
+"Tabela symboli [%2u] „%s” zawiera %u wpisów:\n"
+
+#: src/readelf.c:2873
+#, c-format
+msgid " %lu local symbol  String table: [%2u] '%s'\n"
+msgid_plural " %lu local symbols  String table: [%2u] '%s'\n"
+msgstr[0] " %lu symbol lokalny     Tabela ciągów: [%2u] „%s”\n"
+msgstr[1] " %lu symbole lokalne    Tabela ciągów: [%2u] „%s”\n"
+msgstr[2] " %lu symboli lokalnych  Tabela ciągów: [%2u] „%s”\n"
+
+#: src/readelf.c:2881
+msgid "  Num:    Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  Numer:  Wartość Rozm Typ     Bind   Widoczność   Ndx Nazwa\n"
+
+#: src/readelf.c:2883
+msgid "  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  Numer:          Wartość Rozm Typ     Bind   Widoczność   Ndx Nazwa\n"
+
+#: src/readelf.c:3002
+msgid "Dynamic symbol information is not available for displaying symbols."
+msgstr ""
+
+#: src/readelf.c:3102
+msgid "none"
+msgstr "brak"
+
+#: src/readelf.c:3119
+msgid "| <unknown>"
+msgstr "| <nieznany>"
+
+#: src/readelf.c:3149
+#, c-format
+msgid ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Sekcja wymaganych wersji [%2u] „%s” zawiera %d wpis:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+msgstr[1] ""
+"\n"
+"Sekcja wymaganych wersji [%2u] „%s” zawiera %d wpisy:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+msgstr[2] ""
+"\n"
+"Sekcja wymaganych wersji [%2u] „%s” zawiera %d wpisów:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+
+#: src/readelf.c:3170
+#, c-format
+msgid "  %#06x: Version: %hu  File: %s  Cnt: %hu\n"
+msgstr "  %#06x: Wersja: %hu  Plik: %s  Licznik: %hu\n"
+
+#: src/readelf.c:3183
+#, c-format
+msgid "  %#06x: Name: %s  Flags: %s  Version: %hu\n"
+msgstr "  %#06x: Nazwa: %s  Flagi: %s  Wersja: %hu\n"
+
+#: src/readelf.c:3225
+#, c-format
+msgid ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Sekcja definicji wersji [%2u] „%s” zawiera %d wpis:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+msgstr[1] ""
+"\n"
+"Sekcja definicji wersji [%2u] „%s” zawiera %d wpisy:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+msgstr[2] ""
+"\n"
+"Sekcja definicji wersji [%2u] „%s” zawiera %d wpisów:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+
+#: src/readelf.c:3253
+#, c-format
+msgid "  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"
+msgstr ""
+"  %#06x: Wersja: %hd  Flagi: %s  Indeks: %hd  Licznik: %hd  Nazwa: %s\n"
+
+#: src/readelf.c:3268
+#, c-format
+msgid "  %#06x: Parent %d: %s\n"
+msgstr "  %#06x: Rodzic %d: %s\n"
+
+#. Print the header.
+#: src/readelf.c:3528
+#, c-format
+msgid ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgid_plural ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgstr[0] ""
+"\n"
+"Sekcja symboli wersji [%2u] „%s” zawiera %d wpis:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] „%s”"
+msgstr[1] ""
+"\n"
+"Sekcja symboli wersji [%2u] „%s” zawiera %d wpisy:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] „%s”"
+msgstr[2] ""
+"\n"
+"Sekcja symboli wersji [%2u] „%s” zawiera %d wpisów:\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] „%s”"
+
+#: src/readelf.c:3556
+msgid "   0 *local*                     "
+msgstr "   0 *lokalny*                   "
+
+#: src/readelf.c:3561
+msgid "   1 *global*                    "
+msgstr "   1 *globalny*                  "
+
+#: src/readelf.c:3603
+#, c-format
+msgid ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"bucket):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"buckets):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Histogram dla długości listy kubełków w sekcji [%2u] „%s” (w sumie %d "
+"kubełek):\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+msgstr[1] ""
+"\n"
+"Histogram dla długości listy kubełków w sekcji [%2u] „%s” (w sumie %d "
+"kubełki):\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+msgstr[2] ""
+"\n"
+"Histogram dla długości listy kubełków w sekcji [%2u] „%s” (w sumie %d "
+"kubełków):\n"
+" Adres: %#0*<PRIx64>  Offset: %#08<PRIx64>  Dowiązanie do sekcji: [%2u] "
+"„%s”\n"
+
+#: src/readelf.c:3625
+#, no-c-format
+msgid " Length  Number  % of total  Coverage\n"
+msgstr " Długość Liczba  % całości   Pokrycie\n"
+
+#: src/readelf.c:3627
+#, c-format
+msgid "      0  %6<PRIu32>      %5.1f%%\n"
+msgstr "      0  %6<PRIu32>      %5.1f%%\n"
+
+#: src/readelf.c:3634
+#, c-format
+msgid "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+msgstr "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+
+#: src/readelf.c:3648
+#, c-format
+msgid ""
+" Average number of tests:   successful lookup: %f\n"
+"\t\t\t  unsuccessful lookup: %f\n"
+msgstr ""
+" Średnia liczba testów:   udane wyszukania: %f\n"
+"\t\t\t  nieudane wyszukania: %f\n"
+
+#: src/readelf.c:3666 src/readelf.c:3730 src/readelf.c:3796
+#, c-format
+msgid "cannot get data for section %d: %s"
+msgstr "nie można uzyskać danych dla sekcji %d: %s"
+
+#: src/readelf.c:3674
+#, c-format
+msgid "invalid data in sysv.hash section %d"
+msgstr "nieprawidłowe dane w sekcji sysv.hash %d"
+
+#: src/readelf.c:3703
+#, c-format
+msgid "invalid chain in sysv.hash section %d"
+msgstr "nieprawidłowy łańcuch w sekcji sysv.hash %d"
+
+#: src/readelf.c:3738
+#, c-format
+msgid "invalid data in sysv.hash64 section %d"
+msgstr "nieprawidłowe dane w sekcji sysv.hash64 %d"
+
+#: src/readelf.c:3769
+#, c-format
+msgid "invalid chain in sysv.hash64 section %d"
+msgstr "nieprawidłowy łańcuch w sekcji sysv.hash64 %d"
+
+#: src/readelf.c:3805
+#, c-format
+msgid "invalid data in gnu.hash section %d"
+msgstr "nieprawidłowe dane w sekcji gnu.hash %d"
+
+#: src/readelf.c:3871
+#, c-format
+msgid ""
+" Symbol Bias: %u\n"
+" Bitmask Size: %zu bytes  %<PRIuFAST32>%% bits set  2nd hash shift: %u\n"
+msgstr ""
+" Przesunięcie symboli: %u\n"
+" Rozmiar maski bitowej: %zu B  %<PRIuFAST32>%% b ustawionych  drugie "
+"przesunięcie skrótu: %u\n"
+
+#: src/readelf.c:3956
+#, c-format
+msgid ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Sekcja listy bibliotek [%2zu] „%s” pod offsetem %#0<PRIx64> zawiera %d "
+"wpis:\n"
+msgstr[1] ""
+"\n"
+"Sekcja listy bibliotek [%2zu] „%s” pod offsetem %#0<PRIx64> zawiera %d "
+"wpisy:\n"
+msgstr[2] ""
+"\n"
+"Sekcja listy bibliotek [%2zu] „%s” pod offsetem %#0<PRIx64> zawiera %d "
+"wpisów:\n"
+
+#: src/readelf.c:3970
+msgid ""
+"       Library                       Time Stamp          Checksum Version "
+"Flags"
+msgstr ""
+"       Biblioteka                    Czas                Suma k.  Wersja  "
+"Flagi"
+
+#: src/readelf.c:4030
+#, c-format
+msgid ""
+"\n"
+"Object attributes section [%2zu] '%s' of %<PRIu64> bytes at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sekcja atrybutów obiektu [%2zu] „%s” %<PRIu64> B pod offsetem %#0<PRIx64>:\n"
+
+#: src/readelf.c:4047
+msgid "  Owner          Size\n"
+msgstr "  Właściciel          Rozmiar\n"
+
+#: src/readelf.c:4071
+#, c-format
+msgid "  %-13s  %4<PRIu32>\n"
+msgstr "  %-13s  %4<PRIu32>\n"
+
+#. Unknown subsection, print and skip.
+#: src/readelf.c:4110
+#, c-format
+msgid "    %-4u %12<PRIu32>\n"
+msgstr "    %-4u %12<PRIu32>\n"
+
+#. Tag_File
+#: src/readelf.c:4115
+#, c-format
+msgid "    File: %11<PRIu32>\n"
+msgstr "    Plik: %11<PRIu32>\n"
+
+#: src/readelf.c:4165
+#, c-format
+msgid "      %s: %<PRId64>, %s\n"
+msgstr "      %s: %<PRId64>, %s\n"
+
+#: src/readelf.c:4168
+#, c-format
+msgid "      %s: %<PRId64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:4171
+#, c-format
+msgid "      %s: %s\n"
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:4181
+#, c-format
+msgid "      %u: %<PRId64>\n"
+msgstr "      %u: %<PRId64>\n"
+
+#: src/readelf.c:4184
+#, c-format
+msgid "      %u: %s\n"
+msgstr "      %u: %s\n"
+
+#: src/readelf.c:4222
+#, fuzzy
+#| msgid "couldn't get shdr for group section: %s"
+msgid "Couldn't get data from section"
+msgstr "nie można uzyskać shdr dla sekcji grupy: %s"
+
+#: src/readelf.c:4287
+msgid "sprintf failure"
+msgstr "sprintf się nie powiodło"
+
+#: src/readelf.c:4771
+msgid "empty block"
+msgstr "pusty blok"
+
+#: src/readelf.c:4774
+#, c-format
+msgid "%zu byte block:"
+msgstr "blok o %zu B:"
+
+#: src/readelf.c:5252
+#, c-format
+msgid "%*s[%2<PRIuMAX>] %s  <TRUNCATED>\n"
+msgstr "%*s[%2<PRIuMAX>] %s  <SKRÓCONE>\n"
+
+#: src/readelf.c:5424
+#, c-format
+msgid "%s %#<PRIx64> used with different address sizes"
+msgstr "%s %#<PRIx64> zostało użyte z różnymi rozmiarami adresu"
+
+#: src/readelf.c:5431
+#, c-format
+msgid "%s %#<PRIx64> used with different offset sizes"
+msgstr "%s %#<PRIx64> zostało użyte z różnymi rozmiarami offsetu"
+
+#: src/readelf.c:5438
+#, c-format
+msgid "%s %#<PRIx64> used with different base addresses"
+msgstr "%s %#<PRIx64> zostało użyte z różnymi adresami podstawowymi"
+
+#: src/readelf.c:5445
+#, c-format
+msgid "%s %#<PRIx64> used with different attribute %s and %s"
+msgstr "%s %#<PRIx64> zostało użyte z różnymi atrybutami %s i %s"
+
+#: src/readelf.c:5545
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"
+msgstr " [%6tx]  <NIEUŻYWANE ŚMIECIE W RESZCIE SEKCJI>\n"
+
+#: src/readelf.c:5553
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE> ... %<PRIu64> bytes ...\n"
+msgstr " [%6tx]  <NIEUŻYWANE ŚMIECIE>… %<PRIu64> B…\n"
+
+#: src/readelf.c:5659
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [ Code]\n"
+msgstr ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64>:\n"
+" [ Kod]\n"
+
+#: src/readelf.c:5667
+#, c-format
+msgid ""
+"\n"
+"Abbreviation section at offset %<PRIu64>:\n"
+msgstr ""
+"\n"
+"Sekcja skrótów pod offsetem %<PRIu64>:\n"
+
+#: src/readelf.c:5680
+#, c-format
+msgid " *** error while reading abbreviation: %s\n"
+msgstr " *** błąd podczas odczytywania skrótu: %s\n"
+
+#: src/readelf.c:5696
+#, c-format
+msgid " [%5u] offset: %<PRId64>, children: %s, tag: %s\n"
+msgstr " [%5u] offset: %<PRId64>, potomek: %s, znacznik: %s\n"
+
+#: src/readelf.c:5733 src/readelf.c:6026 src/readelf.c:6197 src/readelf.c:6568
+#: src/readelf.c:7194 src/readelf.c:8963 src/readelf.c:9705 src/readelf.c:10173
+#: src/readelf.c:10428 src/readelf.c:10590 src/readelf.c:10971
+#: src/readelf.c:11042
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64>:\n"
+
+#: src/readelf.c:5836 src/readelf.c:5860 src/readelf.c:6233 src/readelf.c:9741
+#, c-format
+msgid " Length:         %8<PRIu64>\n"
+msgstr " Długość:          %8<PRIu64>\n"
+
+#: src/readelf.c:5838 src/readelf.c:5875 src/readelf.c:6246 src/readelf.c:9754
+#, c-format
+msgid " DWARF version:  %8<PRIu16>\n"
+msgstr " Wersja DWARF:     %8<PRIu16>\n"
+
+#: src/readelf.c:5839 src/readelf.c:5884 src/readelf.c:6255 src/readelf.c:9763
+#, c-format
+msgid " Address size:   %8<PRIu64>\n"
+msgstr " Rozmiar adresu:   %8<PRIu64>\n"
+
+#: src/readelf.c:5841 src/readelf.c:5894 src/readelf.c:6265 src/readelf.c:9773
+#, c-format
+msgid " Segment size:   %8<PRIu64>\n"
+msgstr " Rozmiar segmentu: %8<PRIu64>\n"
+
+#: src/readelf.c:5879 src/readelf.c:6250 src/readelf.c:9758 src/readelf.c:11164
+#, c-format
+msgid "Unknown version"
+msgstr "Nieznana wersja"
+
+#: src/readelf.c:5889 src/readelf.c:6096 src/readelf.c:6260 src/readelf.c:9768
+#, c-format
+msgid "unsupported address size"
+msgstr "nieobsługiwany rozmiar adresu"
+
+#: src/readelf.c:5900 src/readelf.c:6107 src/readelf.c:6270 src/readelf.c:9778
+#, c-format
+msgid "unsupported segment size"
+msgstr "nieobsługiwany rozmiar segmentu"
+
+#: src/readelf.c:5953
+#, c-format
+msgid "cannot get .debug_aranges content: %s"
+msgstr "nie można uzyskać zawartości .debug_aranges: %s"
+
+#: src/readelf.c:5968
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64> zawiera %zu wpis:\n"
+msgstr[1] ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64> zawiera %zu wpisy:\n"
+msgstr[2] ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64> zawiera %zu wpisów:\n"
+
+#: src/readelf.c:5999
+#, c-format
+msgid " [%*zu] ???\n"
+msgstr " [%*zu] ???\n"
+
+#: src/readelf.c:6001
+#, c-format
+msgid ""
+" [%*zu] start: %0#*<PRIx64>, length: %5<PRIu64>, CU DIE offset: %6<PRId64>\n"
+msgstr ""
+" [%*zu] początek: %0#*<PRIx64>, długość: %5<PRIu64>, offset CU DIE: "
+"%6<PRId64>\n"
+
+#: src/readelf.c:6039 src/readelf.c:8982
+#, c-format
+msgid ""
+"\n"
+"Table at offset %zu:\n"
+msgstr ""
+"\n"
+"Tabela pod offsetem %zu:\n"
+
+#: src/readelf.c:6043 src/readelf.c:6214 src/readelf.c:7218 src/readelf.c:8993
+#: src/readelf.c:9722
+#, c-format
+msgid "invalid data in section [%zu] '%s'"
+msgstr "nieprawidłowe dane w sekcji [%zu] „%s”"
+
+#: src/readelf.c:6059
+#, c-format
+msgid ""
+"\n"
+" Length:        %6<PRIu64>\n"
+msgstr ""
+"\n"
+" Długość:        %6<PRIu64>\n"
+
+#: src/readelf.c:6071
+#, c-format
+msgid " DWARF version: %6<PRIuFAST16>\n"
+msgstr " Wersja DWARF: %6<PRIuFAST16>\n"
+
+#: src/readelf.c:6075
+#, c-format
+msgid "unsupported aranges version"
+msgstr "nieobsługiwana wersja aranges"
+
+#: src/readelf.c:6086
+#, c-format
+msgid " CU offset:     %6<PRIx64>\n"
+msgstr " Offset CU:     %6<PRIx64>\n"
+
+#: src/readelf.c:6092
+#, c-format
+msgid " Address size:  %6<PRIu64>\n"
+msgstr " Offset adresu:  %6<PRIu64>\n"
+
+#: src/readelf.c:6103
+#, c-format
+msgid ""
+" Segment size:  %6<PRIu64>\n"
+"\n"
+msgstr ""
+" Rozmiar segmentu:  %6<PRIu64>\n"
+"\n"
+
+#: src/readelf.c:6158
+#, c-format
+msgid "   %zu padding bytes\n"
+msgstr "   %zu B wypełnienia\n"
+
+#: src/readelf.c:6220 src/readelf.c:9728
+#, c-format
+msgid ""
+"Table at Offset 0x%<PRIx64>:\n"
+"\n"
+msgstr ""
+"Tabela pod offsetem 0x%<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:6275 src/readelf.c:9783
+#, c-format
+msgid " Offset entries: %8<PRIu64>\n"
+msgstr " Wpisy offsetu: %8<PRIu64>\n"
+
+#: src/readelf.c:6291 src/readelf.c:9799
+#, c-format
+msgid " Unknown CU base: "
+msgstr " Nieznana podstawa CU: "
+
+#: src/readelf.c:6293 src/readelf.c:9801
+#, c-format
+msgid " CU [%6<PRIx64>] base: "
+msgstr " Podstawa CU [%6<PRIx64>]: "
+
+#: src/readelf.c:6299 src/readelf.c:9807
+#, c-format
+msgid " Not associated with a CU.\n"
+msgstr " Brak powiązania z CU.\n"
+
+#: src/readelf.c:6310 src/readelf.c:9818
+#, c-format
+msgid "too many offset entries for unit length"
+msgstr "za dużo wpisów offsetu dla długości jednostki"
+
+#: src/readelf.c:6314 src/readelf.c:9822
+#, c-format
+msgid "  Offsets starting at 0x%<PRIx64>:\n"
+msgstr "  Offsety zaczynające się w 0x%<PRIx64>:\n"
+
+#: src/readelf.c:6366
+#, c-format
+msgid "invalid range list data"
+msgstr "nieprawidłowe dane listy zakresów"
+
+#: src/readelf.c:6551 src/readelf.c:10157
+#, c-format
+msgid ""
+"   %zu padding bytes\n"
+"\n"
+msgstr ""
+"   %zu B wypełnienia\n"
+"\n"
+
+#: src/readelf.c:6599 src/readelf.c:10206
+#, c-format
+msgid ""
+"\n"
+" Unknown CU base: "
+msgstr ""
+"\n"
+" Nieznana podstawa CU: "
+
+#: src/readelf.c:6601 src/readelf.c:10208
+#, c-format
+msgid ""
+"\n"
+" CU [%6<PRIx64>] base: "
+msgstr ""
+"\n"
+" Podstawa CU [%6<PRIx64>]: "
+
+#: src/readelf.c:6610 src/readelf.c:10234 src/readelf.c:10260
+#, c-format
+msgid " [%6tx]  <INVALID DATA>\n"
+msgstr " [%6tx]  <NIEPRAWIDŁOWE DANE>\n"
+
+#: src/readelf.c:6635 src/readelf.c:10344
+msgid "base address"
+msgstr "adres podstawowy"
+
+#: src/readelf.c:6645 src/readelf.c:10354
+#, c-format
+msgid " [%6tx] empty list\n"
+msgstr " [%6tx] pusta lista\n"
+
+#: src/readelf.c:6909
+msgid "         <INVALID DATA>\n"
+msgstr "         <NIEPRAWIDŁOWE DANE>\n"
+
+#: src/readelf.c:7166
+#, c-format
+msgid "cannot get ELF: %s"
+msgstr "nie można uzyskać ELF: %s"
+
+#: src/readelf.c:7190
+#, c-format
+msgid ""
+"\n"
+"Call frame information section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sekcja informacji o ramce wywołania [%2zu] „%s” pod offsetem %#<PRIx64>:\n"
+
+#: src/readelf.c:7240
+#, c-format
+msgid ""
+"\n"
+" [%6tx] Zero terminator\n"
+msgstr ""
+"\n"
+" [%6tx] Zerowy koniec\n"
+
+#: src/readelf.c:7344 src/readelf.c:7498
+#, c-format
+msgid "invalid augmentation length"
+msgstr "nieprawidłowa długość powiększenia"
+
+#: src/readelf.c:7359
+msgid "FDE address encoding: "
+msgstr "Kodowanie adresu FDE: "
+
+#: src/readelf.c:7365
+msgid "LSDA pointer encoding: "
+msgstr "Kodowanie wskaźnika LSDA: "
+
+#: src/readelf.c:7475
+#, c-format
+msgid " (offset: %#<PRIx64>)"
+msgstr " (offset: %#<PRIx64>)"
+
+#: src/readelf.c:7482
+#, c-format
+msgid " (end offset: %#<PRIx64>)"
+msgstr " (kończący offset: %#<PRIx64>)"
+
+#: src/readelf.c:7519
+#, c-format
+msgid "   %-26sLSDA pointer: %#<PRIx64>\n"
+msgstr "   %-26sWskaźnik LSDA: %#<PRIx64>\n"
+
+#: src/readelf.c:7604
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute code: %s"
+msgstr "DIE [%<PRIx64>] nie można uzyskać kodu atrybutu: %s"
+
+#: src/readelf.c:7614
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute form: %s"
+msgstr "DIE [%<PRIx64>] nie można uzyskać formy atrybutu: %s"
+
+#: src/readelf.c:7636
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute '%s' (%s) value: %s"
+msgstr "DIE [%<PRIx64>] nie można uzyskać wartości atrybutu „%s” (%s): %s"
+
+#: src/readelf.c:7966
+#, c-format
+msgid "invalid file (%<PRId64>): %s"
+msgstr "nieprawidłowy plik (%<PRId64>): %s"
+
+#: src/readelf.c:7970
+#, c-format
+msgid "no srcfiles for CU [%<PRIx64>]"
+msgstr "brak plików źródłowych dla CU [%<PRIx64>]"
+
+#: src/readelf.c:7974
+#, c-format
+msgid "couldn't get DWARF CU: %s"
+msgstr "nie można uzyskać CU DWARF: %s"
+
+#: src/readelf.c:8296
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [Offset]\n"
+msgstr ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64>:\n"
+" [Offset]\n"
+
+#: src/readelf.c:8346
+#, c-format
+msgid "cannot get next unit: %s"
+msgstr "nie można uzyskać następnej jednostki: %s"
+
+#: src/readelf.c:8366
+#, c-format
+msgid ""
+" Type unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+" Type signature: %#<PRIx64>, Type offset: %#<PRIx64> [%<PRIx64>]\n"
+msgstr ""
+" Jednostka typu pod offsetem %<PRIu64>:\n"
+" Wersja: %<PRIu16>, offset sekcji skrótów: %<PRIu64>, rozmiar adresu: "
+"%<PRIu8>, rozmiar offsetu: %<PRIu8>\n"
+" Podpis typu: %#<PRIx64>, offset typu: %#<PRIx64> [%<PRIx64>]\n"
+
+#: src/readelf.c:8378
+#, c-format
+msgid ""
+" Compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+" Jednostka kompilacji pod offsetem %<PRIu64>:\n"
+" Wersja: %<PRIu16>, offset sekcji skrótów: %<PRIu64>, rozmiar adresu: "
+"%<PRIu8>, rozmiar offsetu: %<PRIu8>\n"
+
+#: src/readelf.c:8388 src/readelf.c:8549
+#, c-format
+msgid " Unit type: %s (%<PRIu8>)"
+msgstr " Typ jednostki: %s (%<PRIu8>)"
+
+#: src/readelf.c:8415
+#, c-format
+msgid "unknown version (%d) or unit type (%d)"
+msgstr "nieznana wersja (%d) lub typ jednostki (%d)"
+
+#: src/readelf.c:8444
+#, c-format
+msgid "cannot get DIE offset: %s"
+msgstr "nie można uzyskać offsetu DIE: %s"
+
+#: src/readelf.c:8453
+#, c-format
+msgid "cannot get tag of DIE at offset [%<PRIx64>] in section '%s': %s"
+msgstr ""
+"nie można uzyskać znacznika DIE pod offsetem [%<PRIx64>] w sekcji „%s”: %s"
+
+#: src/readelf.c:8489
+#, c-format
+msgid "cannot get next DIE: %s\n"
+msgstr "nie można uzyskać następnego DIE: %s\n"
+
+#: src/readelf.c:8497
+#, c-format
+msgid "cannot get next DIE: %s"
+msgstr "nie można uzyskać następnego DIE: %s"
+
+#: src/readelf.c:8541
+#, c-format
+msgid ""
+" Split compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+" Jednostka podzielonej kompilacji pod offsetem %<PRIu64>:\n"
+" Wersja: %<PRIu16>, offset sekcji skrótów: %<PRIu64>, rozmiar adresu: "
+"%<PRIu8>, rozmiar offsetu: %<PRIu8>\n"
+
+#: src/readelf.c:8593
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:8925
+#, c-format
+msgid "unknown form: %s"
+msgstr "nieznana forma: %s"
+
+#. Print what we got so far.
+#: src/readelf.c:9073
+#, c-format
+msgid ""
+"\n"
+" Length:                         %<PRIu64>\n"
+" DWARF version:                  %<PRIuFAST16>\n"
+" Prologue length:                %<PRIu64>\n"
+" Address size:                   %zd\n"
+" Segment selector size:          %zd\n"
+" Min instruction length:         %<PRIuFAST8>\n"
+" Max operations per instruction: %<PRIuFAST8>\n"
+" Initial value if 'is_stmt':     %<PRIuFAST8>\n"
+" Line base:                      %<PRIdFAST8>\n"
+" Line range:                     %<PRIuFAST8>\n"
+" Opcode base:                    %<PRIuFAST8>\n"
+"\n"
+"Opcodes:\n"
+msgstr ""
+"\n"
+" Długość:                             %<PRIu64>\n"
+" Wersja DWARF:                        %<PRIuFAST16>\n"
+" Długość prologu:                     %<PRIu64>\n"
+" Rozmiar adresu:                      %zd\n"
+" Rozmiar selektora segmentu:          %zd\n"
+" Minimalna długość instrukcji:        %<PRIuFAST8>\n"
+" Maks. liczba działań na instrukcję:  %<PRIuFAST8>\n"
+" Wartość początkowa, jeśli „is_stmt”: %<PRIuFAST8>\n"
+" Podstawa wiersza:                    %<PRIdFAST8>\n"
+" Zakres wiersza:                      %<PRIuFAST8>\n"
+" Podstawa instrukcji:                 %<PRIuFAST8>\n"
+"\n"
+"Instrukcje:\n"
+
+#: src/readelf.c:9095
+#, c-format
+msgid "cannot handle .debug_line version: %u\n"
+msgstr "nie można obsłużyć wersji .debug_line: %u\n"
+
+#: src/readelf.c:9103
+#, c-format
+msgid "cannot handle address size: %u\n"
+msgstr "nie można obsłużyć rozmiaru adresu: %u\n"
+
+#: src/readelf.c:9111
+#, c-format
+msgid "cannot handle segment selector size: %u\n"
+msgstr "nie można obsłużyć rozmiaru selektora segmentu: %u\n"
+
+#: src/readelf.c:9121
+#, c-format
+msgid "invalid data at offset %tu in section [%zu] '%s'"
+msgstr "nieprawidłowe dane pod offsetem %tu w sekcji [%zu] „%s”"
+
+#: src/readelf.c:9136
+#, c-format
+msgid "  [%*<PRIuFAST8>]  %hhu argument\n"
+msgid_plural "  [%*<PRIuFAST8>]  %hhu arguments\n"
+msgstr[0] "  [%*<PRIuFAST8>]  %hhu parametr\n"
+msgstr[1] "  [%*<PRIuFAST8>]  %hhu parametry\n"
+msgstr[2] "  [%*<PRIuFAST8>]  %hhu parametrów\n"
+
+#: src/readelf.c:9147
+msgid ""
+"\n"
+"Directory table:"
+msgstr ""
+"\n"
+"Tabela katalogu:"
+
+#: src/readelf.c:9153 src/readelf.c:9230
+#, c-format
+msgid "      ["
+msgstr "      ["
+
+#: src/readelf.c:9224
+msgid ""
+"\n"
+"File name table:"
+msgstr ""
+"\n"
+"Tabela nazw plików:"
+
+#: src/readelf.c:9285
+msgid " Entry Dir   Time      Size      Name"
+msgstr " Wpis  Kat   Czas      Rozmiar   Nazwa"
+
+#: src/readelf.c:9331
+msgid ""
+"\n"
+"No line number statements."
+msgstr ""
+"\n"
+"Brak instrukcji numerów wierszy."
+
+#: src/readelf.c:9335
+msgid ""
+"\n"
+"Line number statements:"
+msgstr ""
+"\n"
+"Instrukcje numerów wierszy:"
+
+#: src/readelf.c:9350
+#, c-format
+msgid "invalid maximum operations per instruction is zero"
+msgstr "nieprawidłowe maksimum operacji na instrukcję wynosi zero"
+
+#: src/readelf.c:9384
+#, c-format
+msgid " special opcode %u: address+%u = "
+msgstr " instrukcja specjalna %u: adres+%u = "
+
+#: src/readelf.c:9388
+#, c-format
+msgid ", op_index = %u, line%+d = %zu\n"
+msgstr ", op_index = %u, wiersz%+d = %zu\n"
+
+#: src/readelf.c:9391
+#, c-format
+msgid ", line%+d = %zu\n"
+msgstr ", wiersz%+d = %zu\n"
+
+#: src/readelf.c:9409
+#, c-format
+msgid " extended opcode %u: "
+msgstr " instrukcja rozszerzona %u: "
+
+#: src/readelf.c:9414
+msgid " end of sequence"
+msgstr " koniec sekwencji"
+
+#: src/readelf.c:9432
+#, c-format
+msgid " set address to "
+msgstr " ustawienie adresu na "
+
+#: src/readelf.c:9460
+#, c-format
+msgid " define new file: dir=%u, mtime=%<PRIu64>, length=%<PRIu64>, name=%s\n"
+msgstr ""
+" definicja nowego pliku: dir=%u, mtime=%<PRIu64>, długość=%<PRIu64>, "
+"nazwa=%s\n"
+
+#: src/readelf.c:9474
+#, c-format
+msgid " set discriminator to %u\n"
+msgstr " ustawienie dyskryminatora na %u\n"
+
+#: src/readelf.c:9501
+#, c-format
+msgid " set inlined context %u, function name %s (0x%x)\n"
+msgstr ""
+
+#: src/readelf.c:9525
+#, fuzzy, c-format
+#| msgid "Also show function names"
+msgid " set function name %s (0x%x)\n"
+msgstr "Wyświetla także nazwy funkcji"
+
+#. Unknown, ignore it.
+#: src/readelf.c:9532
+msgid " unknown opcode"
+msgstr " nieznana instrukcja"
+
+#. Takes no argument.
+#: src/readelf.c:9544
+msgid " copy"
+msgstr " kopiowanie"
+
+#: src/readelf.c:9555
+#, c-format
+msgid " advance address by %u to "
+msgstr " zwiększenie adresu o %u do "
+
+#: src/readelf.c:9559 src/readelf.c:9620
+#, c-format
+msgid ", op_index to %u"
+msgstr ", op_index do %u"
+
+#: src/readelf.c:9571
+#, c-format
+msgid " advance line by constant %d to %<PRId64>\n"
+msgstr " zwiększenie wiersza o stałą %d do %<PRId64>\n"
+
+#: src/readelf.c:9581
+#, c-format
+msgid " set file to %<PRIu64>\n"
+msgstr " ustawienie pliku na %<PRIu64>\n"
+
+#: src/readelf.c:9592
+#, c-format
+msgid " set column to %<PRIu64>\n"
+msgstr " ustawienie kolumny na %<PRIu64>\n"
+
+#: src/readelf.c:9599
+#, c-format
+msgid " set '%s' to %<PRIuFAST8>\n"
+msgstr " ustawienie „%s” na %<PRIuFAST8>\n"
+
+#. Takes no argument.
+#: src/readelf.c:9605
+msgid " set basic block flag"
+msgstr " ustawienie podstawowej flagi bloku"
+
+#: src/readelf.c:9616
+#, c-format
+msgid " advance address by constant %u to "
+msgstr " zwiększenie adresu o stałą %u do "
+
+#: src/readelf.c:9636
+#, c-format
+msgid " advance address by fixed value %u to \n"
+msgstr " zwiększenie adresu o stałą wartość %u do \n"
+
+#. Takes no argument.
+#: src/readelf.c:9646
+msgid " set prologue end flag"
+msgstr " ustawienie flagi końca prologu"
+
+#. Takes no argument.
+#: src/readelf.c:9651
+msgid " set epilogue begin flag"
+msgstr " ustawienie flagi początku epilogu"
+
+#: src/readelf.c:9661
+#, c-format
+msgid " set isa to %u\n"
+msgstr " ustawienie isa na %u\n"
+
+#. This is a new opcode the generator but not we know about.
+#. Read the parameters associated with it but then discard
+#. everything.  Read all the parameters for this opcode.
+#: src/readelf.c:9670
+#, c-format
+msgid " unknown opcode with %<PRIu8> parameter:"
+msgid_plural " unknown opcode with %<PRIu8> parameters:"
+msgstr[0] " nieznana instrukcja z %<PRIu8> parametrem:"
+msgstr[1] " nieznana instrukcja z %<PRIu8> parametrami:"
+msgstr[2] " nieznana instrukcja z %<PRIu8> parametrami:"
+
+#: src/readelf.c:9871
+#, c-format
+msgid "    <INVALID DATA>\n"
+msgstr "    <NIEPRAWIDŁOWE DANE>\n"
+
+#: src/readelf.c:9911
+#, c-format
+msgid "invalid loclists data"
+msgstr "nieprawidłowe dane loclists"
+
+#: src/readelf.c:10381 src/readelf.c:11426
+msgid "   <INVALID DATA>\n"
+msgstr "   <NIEPRAWIDŁOWE DANE>\n"
+
+#: src/readelf.c:10512
+#, c-format
+msgid "%*s*** non-terminated string at end of section"
+msgstr "%*s*** niezakończony ciąg na końcu sekcji"
+
+#: src/readelf.c:10535
+#, c-format
+msgid "%*s*** missing DW_MACINFO_start_file argument at end of section"
+msgstr "%*s*** brak parametru DW_MACINFO_start_file na końcu sekcji"
+
+#: src/readelf.c:10630
+#, c-format
+msgid " Offset:             0x%<PRIx64>\n"
+msgstr " Offset:             0x%<PRIx64>\n"
+
+#: src/readelf.c:10642
+#, c-format
+msgid " Version:            %<PRIu16>\n"
+msgstr " Wersja:             %<PRIu16>\n"
+
+#: src/readelf.c:10648 src/readelf.c:11547
+#, c-format
+msgid "  unknown version, cannot parse section\n"
+msgstr "  nieznana wersja, nie można przetworzyć sekcji\n"
+
+#: src/readelf.c:10655
+#, c-format
+msgid " Flag:               0x%<PRIx8>"
+msgstr " Flaga:              0x%<PRIx8>"
+
+#: src/readelf.c:10684
+#, c-format
+msgid " Offset length:      %<PRIu8>\n"
+msgstr " Długość offsetu:    %<PRIu8>\n"
+
+#: src/readelf.c:10692
+#, c-format
+msgid " .debug_line offset: 0x%<PRIx64>\n"
+msgstr " Offset .debug_line: 0x%<PRIx64>\n"
+
+#: src/readelf.c:10717
+#, c-format
+msgid "  extension opcode table, %<PRIu8> items:\n"
+msgstr "  tabela instrukcji rozszerzenia, %<PRIu8> elementów:\n"
+
+#: src/readelf.c:10724
+#, c-format
+msgid "    [%<PRIx8>]"
+msgstr "    [%<PRIx8>]"
+
+#: src/readelf.c:10736
+#, c-format
+msgid " %<PRIu8> arguments:"
+msgstr " Parametry %<PRIu8>:"
+
+#: src/readelf.c:10751
+#, c-format
+msgid " no arguments."
+msgstr " brak parametrów."
+
+#: src/readelf.c:10952
+#, c-format
+msgid " [%5d] DIE offset: %6<PRId64>, CU DIE offset: %6<PRId64>, name: %s\n"
+msgstr " [%5d] offset DIE: %6<PRId64>, offset CU DIE: %6<PRId64>, nazwa: %s\n"
+
+#: src/readelf.c:11007
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" %*s  String\n"
+msgstr ""
+"\n"
+"Sekcja DWARF [%2zu] „%s” pod offsetem %#<PRIx64>:\n"
+" %*s  Ciąg\n"
+
+#. TRANS: the debugstr| prefix makes the string unique.
+#: src/readelf.c:11012
+msgctxt "debugstr"
+msgid "Offset"
+msgstr ""
+
+#: src/readelf.c:11022
+#, c-format
+msgid " *** error, missing string terminator\n"
+msgstr " *** błąd, brak znaku kończącego ciąg\n"
+
+#: src/readelf.c:11144
+#, c-format
+msgid " Length:        %8<PRIu64>\n"
+msgstr " Długość:         %8<PRIu64>\n"
+
+#: src/readelf.c:11146
+#, c-format
+msgid " Offset size:   %8<PRIu8>\n"
+msgstr " Rozmiar offsetu: %8<PRIu8>\n"
+
+#: src/readelf.c:11160
+#, c-format
+msgid " DWARF version: %8<PRIu16>\n"
+msgstr " Wersja DWARF:    %8<PRIu16>\n"
+
+#: src/readelf.c:11169
+#, c-format
+msgid " Padding:       %8<PRIx16>\n"
+msgstr " Wypełnienie:     %8<PRIx16>\n"
+
+#: src/readelf.c:11223
+#, c-format
+msgid ""
+"\n"
+"Call frame search table section [%2zu] '.eh_frame_hdr':\n"
+msgstr ""
+"\n"
+"Sekcja tabeli wyszukiwania ramki wywołania [%2zu] „.eh_frame_hdr”:\n"
+
+#: src/readelf.c:11325
+#, c-format
+msgid ""
+"\n"
+"Exception handling table section [%2zu] '.gcc_except_table':\n"
+msgstr ""
+"\n"
+"Sekcja tabeli obsługiwania wyjątków [%2zu] „.gcc_except_table”:\n"
+
+#: src/readelf.c:11348
+#, c-format
+msgid " LPStart encoding:    %#x "
+msgstr " Kodowanie LPStart:    %#x "
+
+#: src/readelf.c:11360
+#, c-format
+msgid " TType encoding:      %#x "
+msgstr " Kodowanie TType:      %#x "
+
+#: src/readelf.c:11377
+#, c-format
+msgid " Call site encoding:  %#x "
+msgstr " Kodowanie strony wywołania:  %#x "
+
+#: src/readelf.c:11392
+msgid ""
+"\n"
+" Call site table:"
+msgstr ""
+"\n"
+" Tabela strony wywołania:"
+
+#: src/readelf.c:11408
+#, c-format
+msgid ""
+" [%4u] Call site start:   %#<PRIx64>\n"
+"        Call site length:  %<PRIu64>\n"
+"        Landing pad:       %#<PRIx64>\n"
+"        Action:            %u\n"
+msgstr ""
+" [%4u] Początek strony wywołania: %#<PRIx64>\n"
+"        Długość strony wywołania:  %<PRIu64>\n"
+"        Lądowisko:                 %#<PRIx64>\n"
+"        Działanie:                 %u\n"
+
+#: src/readelf.c:11481
+#, c-format
+msgid "invalid TType encoding"
+msgstr "nieprawidłowe kodowanie TType"
+
+#: src/readelf.c:11508
+#, c-format
+msgid ""
+"\n"
+"GDB section [%2zu] '%s' at offset %#<PRIx64> contains %<PRId64> bytes :\n"
+msgstr ""
+"\n"
+"Sekcja GDB [%2zu] „%s” pod offsetem %#<PRIx64> zawiera %<PRId64> B:\n"
+
+#: src/readelf.c:11537
+#, c-format
+msgid " Version:         %<PRId32>\n"
+msgstr " Wersja:         %<PRId32>\n"
+
+#: src/readelf.c:11556
+#, c-format
+msgid " CU offset:       %#<PRIx32>\n"
+msgstr " offset CU:       %#<PRIx32>\n"
+
+#: src/readelf.c:11563
+#, c-format
+msgid " TU offset:       %#<PRIx32>\n"
+msgstr " offset TU:       %#<PRIx32>\n"
+
+#: src/readelf.c:11570
+#, c-format
+msgid " address offset:  %#<PRIx32>\n"
+msgstr " offset adresu:  %#<PRIx32>\n"
+
+#: src/readelf.c:11577
+#, c-format
+msgid " symbol offset:   %#<PRIx32>\n"
+msgstr " offset symbolu:   %#<PRIx32>\n"
+
+#: src/readelf.c:11587
+#, fuzzy, c-format
+#| msgid " constant offset: %#<PRIx32>\n"
+msgid " shortcut offset: %#<PRIx32>\n"
+msgstr " offset stałej: %#<PRIx32>\n"
+
+#: src/readelf.c:11595
+#, c-format
+msgid " constant offset: %#<PRIx32>\n"
+msgstr " offset stałej: %#<PRIx32>\n"
+
+#: src/readelf.c:11609
+#, c-format
+msgid ""
+"\n"
+" CU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+" Lista CU pod offsetem %#<PRIx32> zawiera %zu wpisów:\n"
+
+#: src/readelf.c:11634
+#, c-format
+msgid ""
+"\n"
+" TU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+" Lista TU pod offsetem %#<PRIx32> zawiera %zu wpisów:\n"
+
+#: src/readelf.c:11663
+#, c-format
+msgid ""
+"\n"
+" Address list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+" Lista adresów pod offsetem %#<PRIx32> zawiera %zu wpisów:\n"
+
+#: src/readelf.c:11706
+#, c-format
+msgid ""
+"\n"
+" Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+" Tabela symboli pod offsetem %#<PRIx32> zawiera %zu gniazd:\n"
+
+#: src/readelf.c:11791
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| " Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgid ""
+"\n"
+"Shortcut table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+" Tabela symboli pod offsetem %#<PRIx32> zawiera %zu gniazd:\n"
+
+#: src/readelf.c:11803
+#, c-format
+msgid "Language of main: %s\n"
+msgstr ""
+
+#: src/readelf.c:11804
+#, c-format
+msgid "Name of main: "
+msgstr ""
+
+#: src/readelf.c:11887
+#, c-format
+msgid "cannot get debug context descriptor: %s"
+msgstr "nie można uzyskać deskryptora kontekstu debugowania: %s"
+
+#: src/readelf.c:12253 src/readelf.c:12873 src/readelf.c:12983
+#: src/readelf.c:13040
+#, c-format
+msgid "cannot convert core note data: %s"
+msgstr "nie można konwertować danych notatki core: %s"
+
+#: src/readelf.c:12617
+#, c-format
+msgid ""
+"\n"
+"%*s... <repeats %u more times> ..."
+msgstr ""
+"\n"
+"%*s… <powtarza się jeszcze %u razy>…"
+
+#: src/readelf.c:13119
+msgid "  Owner          Data size  Type\n"
+msgstr "  Właściciel     Rozmiar danych  Typ\n"
+
+#: src/readelf.c:13147
+#, c-format
+msgid "  %-13.*s  %9<PRId32>  %s\n"
+msgstr "  %-13.*s  %9<PRId32>  %s\n"
+
+#: src/readelf.c:13199
+#, c-format
+msgid "cannot get content of note: %s"
+msgstr "nie można uzyskać zawartości notatki: %s"
+
+#: src/readelf.c:13232
+#, c-format
+msgid ""
+"\n"
+"Note section [%2zu] '%s' of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Segment notatki [%2zu] „%s” o długości %<PRIu64> B pod offsetem "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13255
+#, c-format
+msgid ""
+"\n"
+"Note segment of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Segment notatki o długości %<PRIu64> B pod offsetem %#0<PRIx64>:\n"
+
+#: src/readelf.c:13302
+#, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no data to dump.\n"
+msgstr ""
+"\n"
+"Sekcja [%zu] „%s” nie ma danych do zrzucenia.\n"
+
+#: src/readelf.c:13329 src/readelf.c:13380
+#, c-format
+msgid "cannot get data for section [%zu] '%s': %s"
+msgstr "nie można uzyskać danych dla sekcji [%zu] „%s”: %s"
+
+#: src/readelf.c:13334
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Segment zrzutu szesnastkowego [%zu] „%s”, %<PRIu64> B pod offsetem "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13339
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes (%zd uncompressed) at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Zrzut szesnastkowy sekcji [%zu] „%s”, %<PRIu64> B (%zd nieskompresowanych) "
+"pod offsetem %#0<PRIx64>:\n"
+
+#: src/readelf.c:13353
+#, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no strings to dump.\n"
+msgstr ""
+"\n"
+"Sekcja [%zu] „%s” nie ma ciągów do zrzucenia.\n"
+
+#: src/readelf.c:13385
+#, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sekcja ciągów [%zu] „%s” zawiera %<PRIu64> B pod offsetem %#0<PRIx64>:\n"
+
+#: src/readelf.c:13390
+#, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes (%zd uncompressed) at "
+"offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Sekcja ciągów [%zu] „%s” zawiera %<PRIu64> B (%zd nieskompresowanych) pod "
+"offsetem %#0<PRIx64>:\n"
+
+#: src/readelf.c:13438
+#, c-format
+msgid ""
+"\n"
+"section [%lu] does not exist"
+msgstr ""
+"\n"
+"sekcja [%lu] nie istnieje"
+
+#: src/readelf.c:13468
+#, c-format
+msgid ""
+"\n"
+"section '%s' does not exist"
+msgstr ""
+"\n"
+"sekcja „%s” nie istnieje"
+
+#: src/readelf.c:13523
+#, c-format
+msgid "cannot get symbol index of archive '%s': %s"
+msgstr "nie można uzyskać indeksu symboli archiwum „%s”: %s"
+
+#: src/readelf.c:13526
+#, c-format
+msgid ""
+"\n"
+"Archive '%s' has no symbol index\n"
+msgstr ""
+"\n"
+"Archiwum „%s” nie ma indeksu symboli\n"
+
+#: src/readelf.c:13530
+#, c-format
+msgid ""
+"\n"
+"Index of archive '%s' has %zu entries:\n"
+msgstr ""
+"\n"
+"Indeks archiwum „%s” ma %zu wpisów:\n"
+
+#: src/readelf.c:13548
+#, c-format
+msgid "cannot extract member at offset %zu in '%s': %s"
+msgstr "nie można wydobyć elementów pod offsetem %zu w „%s”: %s"
+
+#: src/readelf.c:13553
+#, c-format
+msgid "Archive member '%s' contains:\n"
+msgstr "Element archiwum „%s” zawiera:\n"
+
+#: src/size.c:55
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  The default "
+"is `bsd'"
+msgstr ""
+"Używa FORMATU wyjścia. Może to być „bsd” lub „sysv”. Domyślny jest „bsd”"
+
+#: src/size.c:57
+msgid "Same as `--format=sysv'"
+msgstr "To samo, co „--format=sysv”"
+
+#: src/size.c:58
+msgid "Same as `--format=bsd'"
+msgstr "To samo, co „--format=bsd”"
+
+#: src/size.c:61
+msgid "Same as `--radix=10'"
+msgstr "To samo, co „--radix=10”"
+
+#: src/size.c:62
+msgid "Same as `--radix=8'"
+msgstr "To samo, co „--radix=8”"
+
+#: src/size.c:63
+msgid "Same as `--radix=16'"
+msgstr "To samo, co „--radix=16”"
+
+#: src/size.c:65
+msgid "Similar to `--format=sysv' output but in one line"
+msgstr "Podobne do wyjścia „--format=sysv”, ale w jednym wierszu"
+
+#: src/size.c:69
+msgid "Print size and permission flags for loadable segments"
+msgstr "Wyświetla rozmiar i flagi uprawnień dla segmentów wczytywalnych"
+
+#: src/size.c:70
+msgid "Display the total sizes (bsd only)"
+msgstr "Wyświetla całkowite rozmiary (tylko bsd)"
+
+#. Short description of program.
+#: src/size.c:75
+msgid "List section sizes of FILEs (a.out by default)."
+msgstr "Wyświetla listę rozmiarów sekcji PLIKU (domyślnie a.out)."
+
+#: src/size.c:239
+#, c-format
+msgid "Invalid format: %s"
+msgstr "Nieprawidłowy format: %s"
+
+#: src/size.c:250
+#, c-format
+msgid "Invalid radix: %s"
+msgstr "Nieprawidłowa baza: %s"
+
+#: src/size.c:309
+#, c-format
+msgid "%s: file format not recognized"
+msgstr "%s: nie rozpoznano formatu pliku"
+
+#: src/size.c:327
+msgctxt "bsd"
+msgid "text"
+msgstr ""
+
+#: src/size.c:328
+msgctxt "bsd"
+msgid "data"
+msgstr ""
+
+#: src/size.c:329
+msgctxt "bsd"
+msgid "bss"
+msgstr ""
+
+#: src/size.c:330
+msgctxt "bsd"
+msgid "dec"
+msgstr ""
+
+#: src/size.c:331
+msgctxt "bsd"
+msgid "hex"
+msgstr ""
+
+#: src/size.c:332
+msgctxt "bsd"
+msgid "filename"
+msgstr ""
+
+#: src/size.c:416 src/size.c:557
+#, c-format
+msgid " (ex %s)"
+msgstr " (ex %s)"
+
+#: src/size.c:418
+#, fuzzy
+#| msgid "invalid section"
+msgctxt "sysv"
+msgid "section"
+msgstr "nieprawidłowa sekcja"
+
+#: src/size.c:419
+msgctxt "sysv"
+msgid "size"
+msgstr ""
+
+#: src/size.c:420
+msgctxt "sysv"
+msgid "addr"
+msgstr ""
+
+#: src/size.c:449 src/size.c:452 src/size.c:455
+msgctxt "sysv"
+msgid "Total"
+msgstr ""
+
+#: src/size.c:479
+msgid "cannot get section header"
+msgstr "nie można uzyskać nagłówka sekcji"
+
+#: src/size.c:582
+msgid "(TOTALS)\n"
+msgstr "(CAŁKOWITE)\n"
+
+#: src/stack.c:487
+#, c-format
+msgid "-p PID should be a positive process id."
+msgstr "-p PID musi być dodatnim identyfikatorem procesu."
+
+#: src/stack.c:493
+#, c-format
+msgid "Cannot open core file '%s'"
+msgstr "Nie można otworzyć pliku core „%s”"
+
+#: src/stack.c:553
+#, c-format
+msgid "-n MAXFRAMES should be 0 or higher."
+msgstr "-n MAKSYMALNA-LICZBA-RAMEK musi wynosić 0 lub więcej."
+
+#: src/stack.c:565
+#, c-format
+msgid "-e EXEC needs a core given by --core."
+msgstr "-e PLIK-WYKONYWALNY wymaga pliku core podanego za pomocą opcji --core."
+
+#: src/stack.c:569
+#, c-format
+msgid "-1 needs a thread id given by -p."
+msgstr "-1 wymaga identyfikatora wątku podanego za pomocą opcji -p."
+
+#: src/stack.c:573
+#, c-format
+msgid "One of -p PID or --core COREFILE should be given."
+msgstr "Tylko jedna z opcji -p PID lub --core PLIK-CORE może zostać podana."
+
+#: src/stack.c:645
+msgid "Show stack of process PID"
+msgstr "Wyświetla stos numeru PID procesu"
+
+#: src/stack.c:647
+msgid "Show stack found in COREFILE"
+msgstr "Wyświetla stos odnaleziony w PLIKU-CORE"
+
+#: src/stack.c:648
+msgid "(optional) EXECUTABLE that produced COREFILE"
+msgstr "(opcjonalnie) PLIK-WYKONYWALNY, który utworzył PLIK-CORE"
+
+#: src/stack.c:652
+msgid "Output selection options:"
+msgstr "Opcje wyboru wyjścia:"
+
+#: src/stack.c:654
+msgid "Additionally show frame activation"
+msgstr "Dodatkowo wyświetla aktywację ramki"
+
+#: src/stack.c:656
+msgid "Additionally try to lookup DWARF debuginfo name for frame address"
+msgstr "Dodatkowo próbuje wyszukać nazwy debuginfo DWARF dla adresu ramki"
+
+#: src/stack.c:659
+msgid ""
+"Additionally show inlined function frames using DWARF debuginfo if available "
+"(implies -d)"
+msgstr ""
+"Dodatkowo wyświetla wstawione ramki używając debuginfo DWARF, jeśli jest "
+"dostępne (zakłada opcję -d)"
+
+#: src/stack.c:661
+msgid "Additionally show module file information"
+msgstr "Dodatkowo wyświetla informacje o pliku modułu"
+
+#: src/stack.c:663
+msgid "Additionally show source file information"
+msgstr "Dodatkowo wyświetla informacje o pliku źródłowym"
+
+#: src/stack.c:665
+msgid ""
+"Show all additional information (activation, debugname, inlines, module and "
+"source)"
+msgstr ""
+"Wyświetla wszystkie dodatkowe informacje (aktywację, nazwę debugowania, "
+"wstawki, moduł i źródło)"
+
+#: src/stack.c:667
+msgid "Do not resolve address to function symbol name"
+msgstr "Nie rozwiązuje nazw symboli adresów do funkcji"
+
+#: src/stack.c:669
+msgid "Show raw function symbol names, do not try to demangle names"
+msgstr ""
+"Wyświetla surowe nazwy symboli funkcji, nie próbuje usuwać dekoracji z nazw"
+
+#: src/stack.c:671
+msgid "Show module build-id, load address and pc offset"
+msgstr "Wyświetla identyfikator kopii modułu, wczytuje adres i offset pc"
+
+#: src/stack.c:673
+msgid "Show the backtrace of only one thread"
+msgstr "Wyświetla ślad stosu, jeśli jest tylko jeden wątek"
+
+#: src/stack.c:675
+msgid "Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"
+msgstr ""
+"Wyświetla najwyżej MAKSYMALNĄ-LICZBĘ-KLATEK na wątek (domyślnie 256, 0 "
+"oznacza brak ograniczenia)"
+
+#: src/stack.c:677
+msgid "Show module memory map with build-id, elf and debug files detected"
+msgstr ""
+"Wyświetla mapę pamięci modułu z identyfikatorem kopii, wykryte pliki elf "
+"i debug"
+
+#: src/stack.c:685
+msgid ""
+"Print a stack for each thread in a process or core file.\n"
+"\n"
+"Program exits with return code 0 if all frames were shown without any "
+"errors.  If some frames were shown, but there were some non-fatal errors, "
+"possibly causing an incomplete backtrace, the program exits with return code "
+"1.  If no frames could be shown, or a fatal error occurred the program exits "
+"with return code 2.  If the program was invoked with bad or missing "
+"arguments it will exit with return code 64."
+msgstr ""
+"Wyświetla stos dla każdego wątku w procesie lub pliku core.\n"
+"\n"
+"Program kończy działanie z kodem zwrotnym 0, jeśli wszystkie ramki zostały "
+"wyświetlone bez żadnych błędów. Jeśli niektóre ramki zostały wyświetlone, "
+"ale wystąpiły niekrytyczne błędy, które mogą spowodować niepełny ślad stosu, "
+"to program kończy działanie z kodem zwrotnym 1. Jeśli żadne ramki nie mogły "
+"zostać wyświetlone lub wystąpił krytyczny błąd, to program kończy działanie "
+"z kodem zwrotnym 2. Jeśli program został wywołany za pomocą błędnych lub "
+"brakujących parametrów, to zakończy on działanie z kodem zwrotnym 64."
+
+#: src/stack.c:760
+#, c-format
+msgid "Couldn't show any frames."
+msgstr "Nie można wyświetlić żadnych ramek."
+
+#: src/strings.c:64
+msgid "Output Selection:"
+msgstr "Wybór wyjścia:"
+
+#: src/strings.c:65
+msgid "Scan entire file, not only loaded sections"
+msgstr "Przeszukuje cały plik, nie tylko wczytane sekcje"
+
+#: src/strings.c:67
+msgid "Only NUL-terminated sequences of MIN-LEN characters or more are printed"
+msgstr ""
+"Wyświetlane są tylko zakończone NUL sekwencje o MIN-LEN lub większej liczbie "
+"znaków"
+
+#: src/strings.c:68
+msgid ""
+"Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, "
+"{B,L} = 32-bit"
+msgstr ""
+"Wybór rozmiaru i kolejności znaków: s = 7 bitów, S = 8 bitów, {b,l} = 16 "
+"bitów, {B,L} = 32 bity"
+
+#: src/strings.c:72
+msgid "Print name of the file before each string."
+msgstr "Wyświetla nazwę pliku przed każdym ciągiem."
+
+#: src/strings.c:74
+msgid "Print location of the string in base 8, 10, or 16 respectively."
+msgstr "Wyświetla położenie ciągu z podstawą odpowiednio 8, 10 lub 16."
+
+#: src/strings.c:75
+msgid "Alias for --radix=o"
+msgstr "Alias dla --radix=o"
+
+#. Short description of program.
+#: src/strings.c:82
+msgid "Print the strings of printable characters in files."
+msgstr "Wyświetla ciągi znaków drukowalnych w plikach."
+
+#: src/strings.c:255 src/strings.c:290
+#, c-format
+msgid "invalid value '%s' for %s parameter"
+msgstr "nieprawidłowa wartość „%s” dla parametru %s"
+
+#: src/strings.c:300
+msgid "invalid minimum length of matched string size"
+msgstr "nieprawidłowa minimalna długość dopasowanego rozmiaru ciągu"
+
+#: src/strings.c:583
+msgid "lseek failed"
+msgstr "lseek się nie powiodło"
+
+#: src/strings.c:600 src/strings.c:664
+msgid "re-mmap failed"
+msgstr "ponowne mmap się nie powiodło"
+
+#: src/strings.c:637
+msgid "mprotect failed"
+msgstr "mprotect się nie powiodło"
+
+#: src/strings.c:726
+#, c-format
+msgid "Skipping section %zd '%s' data outside file"
+msgstr "Pomijanie sekcji %zd „%s” dane poza plikiem"
+
+#: src/strip.c:70
+msgid "Place stripped output into FILE"
+msgstr "Umieszcza okrojone wyjście w PLIKU"
+
+#: src/strip.c:71
+msgid "Extract the removed sections into FILE"
+msgstr "Wydobywa usunięte sekcje do PLIKU"
+
+#: src/strip.c:72
+msgid "Embed name FILE instead of -f argument"
+msgstr "Osadza nazwę PLIKU zamiast parametru -f"
+
+#: src/strip.c:76
+msgid "Remove all debugging symbols"
+msgstr "Usuwa wszystkie symbole debugowania"
+
+#: src/strip.c:80
+msgid "Remove section headers (not recommended)"
+msgstr "Usuwa nagłówki sekcji (niezalecane)"
+
+#: src/strip.c:82
+msgid "Copy modified/access timestamps to the output"
+msgstr "Kopiuje czasy modyfikacji/dostępu do wyjścia"
+
+#: src/strip.c:84
+msgid ""
+"Resolve all trivial relocations between debug sections if the removed "
+"sections are placed in a debug file (only relevant for ET_REL files, "
+"operation is not reversible, needs -f)"
+msgstr ""
+"Rozwiązuje wszystkie proste relokacje między sekcjami debugowania, jeśli "
+"usunięte sekcje zostały umieszczone w pliku debugowania (ma znaczenie tylko "
+"dla plików ET_REL, działanie jest nieodwracalne, wymaga użycia opcji -f)"
+
+#: src/strip.c:86
+msgid ""
+"Similar to --reloc-debug-sections, but resolve all trivial relocations "
+"between debug sections in place.  No other stripping is performed (operation "
+"is not reversible, incompatible with -f, -g, --remove-comment and --remove-"
+"section)"
+msgstr ""
+"Podobne do opcji --reloc-debug-sections, ale rozwiązuje wszystkie proste "
+"relokacje między sekcjami debugowania na miejscu. Żadne inne okrajanie nie "
+"jest wykonywane (działania nie jest odwracalne, nie jest zgodne z opcjami -"
+"f, -g, --remove-comment i --remove-section)"
+
+#: src/strip.c:88
+msgid "Remove .comment section"
+msgstr "Usuwa sekcję .comment"
+
+#: src/strip.c:89
+msgid ""
+"Remove the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once.  Only non-allocated sections can be removed."
+msgstr ""
+"Usuwa podaną sekcję. SEKCJA jest rozszerzonym wzorem. Może być podane więcej "
+"niż raz. Można usuwać tylko nieprzydzielone sekcje."
+
+#: src/strip.c:90
+msgid ""
+"Keep the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once."
+msgstr ""
+"Zachowuje podaną sekcję. SEKCJA jest rozszerzonym wzorem. Może być podane "
+"więcej niż raz."
+
+#. Short description of program.
+#: src/strip.c:97
+msgid "Discard symbols from object files."
+msgstr "Odrzuca symbole z plików obiektów."
+
+#: src/strip.c:245
+msgid "--reloc-debug-sections used without -f"
+msgstr "Użyto --reloc-debug-sections bez opcji -f"
+
+#: src/strip.c:251
+msgid ""
+"--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --"
+"remove-section"
+msgstr ""
+"Opcja --reloc-debug-sections-only jest niezgodna z -f, -g, --remove-comment "
+"i --remove-section"
+
+#: src/strip.c:265
+msgid "Only one input file allowed together with '-o' and '-f'"
+msgstr "Tylko jeden plik wejściowy jest dozwolony z „-o” i „-f”"
+
+#: src/strip.c:287
+#, c-format
+msgid "-f option specified twice"
+msgstr "Opcję -f podano dwukrotnie"
+
+#: src/strip.c:296
+#, c-format
+msgid "-F option specified twice"
+msgstr "Opcję -F podano dwukrotnie"
+
+#: src/strip.c:359
+#, c-format
+msgid "cannot both keep and remove .comment section"
+msgstr "nie można jednocześnie zachować i usunąć sekcji .comment"
+
+#: src/strip.c:478
+msgid "bad relocation"
+msgstr "błędna relokacja"
+
+#: src/strip.c:756 src/strip.c:780
+#, c-format
+msgid "cannot stat input file '%s'"
+msgstr "nie można wykonać stat na pliku wejściowym „%s”"
+
+#: src/strip.c:770
+#, c-format
+msgid "while opening '%s'"
+msgstr "podczas otwierania „%s”"
+
+#: src/strip.c:808
+#, c-format
+msgid "%s: cannot use -o or -f when stripping archive"
+msgstr "%s: nie można używać -o lub -f podczas okrajania archiwum"
+
+#. We would like to support ar archives, but currently it just
+#. doesn't work at all since we call elf_clone on the members
+#. which doesn't really support ar members.
+#. result = handle_ar (fd, elf, NULL, fname,
+#. preserve_dates ? tv : NULL);
+#.
+#: src/strip.c:820
+#, c-format
+msgid "%s: no support for stripping archive"
+msgstr "%s: brak obsługi okrajania archiwum"
+
+#: src/strip.c:1057
+#, c-format
+msgid "cannot open EBL backend"
+msgstr "nie można otworzyć zaplecza EBL"
+
+#: src/strip.c:1101
+msgid "cannot get number of phdrs"
+msgstr "nie można uzyskać liczby phdr"
+
+#: src/strip.c:1115 src/strip.c:1158
+#, c-format
+msgid "cannot create new ehdr for file '%s': %s"
+msgstr "nie można utworzyć nowego ehdr dla pliku „%s”: %s"
+
+#: src/strip.c:1125 src/strip.c:1168
+#, c-format
+msgid "cannot create new phdr for file '%s': %s"
+msgstr "nie można utworzyć nowego phdr dla pliku „%s”: %s"
+
+#: src/strip.c:1248
+#, c-format
+msgid "illformed file '%s'"
+msgstr "plik „%s” ma błędny format"
+
+#: src/strip.c:1258
+#, c-format
+msgid "Cannot remove allocated section '%s'"
+msgstr "Nie można usunąć przydzielonej sekcji „%s”"
+
+#: src/strip.c:1267
+#, c-format
+msgid "Cannot both keep and remove section '%s'"
+msgstr "Nie można jednocześnie zachować i usunąć sekcji „%s”"
+
+#: src/strip.c:1631 src/strip.c:1746
+#, c-format
+msgid "while generating output file: %s"
+msgstr "podczas tworzenia pliku wyjściowego: %s"
+
+#: src/strip.c:1695
+#, c-format
+msgid "%s: error while updating ELF header: %s"
+msgstr "%s: błąd podczas aktualizowania nagłówka ELF: %s"
+
+#: src/strip.c:1704
+#, c-format
+msgid "%s: error while getting shdrstrndx: %s"
+msgstr "%s: błąd podczas uzyskiwania shdrstrndx: %s"
+
+#: src/strip.c:1712 src/strip.c:2552
+#, c-format
+msgid "%s: error updating shdrstrndx: %s"
+msgstr "%s: błąd podczas aktualizowania shdrstrndx: %s"
+
+#: src/strip.c:1729
+#, c-format
+msgid "while preparing output for '%s'"
+msgstr "podczas przygotowywania wyjścia dla „%s”"
+
+#: src/strip.c:1790 src/strip.c:1852
+#, c-format
+msgid "while create section header section: %s"
+msgstr "podczas tworzenia sekcji nagłówka sekcji: %s"
+
+#: src/strip.c:1799
+#, c-format
+msgid "cannot allocate section data: %s"
+msgstr "nie można przydzielić danych sekcji: %s"
+
+#: src/strip.c:1863
+#, c-format
+msgid "while create section header string table: %s"
+msgstr "podczas tworzenia tabeli ciągów nagłówka sekcji: %s"
+
+#: src/strip.c:1869
+msgid "no memory to create section header string table"
+msgstr "brak pamięci do utworzenia tabeli ciągów nagłówka sekcji"
+
+#: src/strip.c:2082
+#, c-format
+msgid "Cannot remove symbol [%zd] from allocated symbol table [%zd]"
+msgstr "Nie można usunąć symbolu [%zd] z przydzielonej tabeli symboli [%zd]"
+
+#: src/strip.c:2469 src/strip.c:2574
+#, c-format
+msgid "while writing '%s': %s"
+msgstr "podczas zapisywania „%s”: %s"
+
+#: src/strip.c:2480
+#, c-format
+msgid "while creating '%s'"
+msgstr "podczas tworzenia „%s”"
+
+#: src/strip.c:2503
+#, c-format
+msgid "while computing checksum for debug information"
+msgstr "podczas obliczania sumy kontrolnej dla informacji debugowania"
+
+#: src/strip.c:2544
+#, c-format
+msgid "%s: error while creating ELF header: %s"
+msgstr "%s: błąd podczas tworzenia nagłówka ELF: %s"
+
+#: src/strip.c:2560
+#, c-format
+msgid "%s: error while reading the file: %s"
+msgstr "%s: błąd podczas odczytywania pliku: %s"
+
+#: src/strip.c:2599 src/strip.c:2619
+#, c-format
+msgid "while writing '%s'"
+msgstr "podczas zapisywania „%s”"
+
+#: src/strip.c:2656 src/strip.c:2663
+#, c-format
+msgid "error while finishing '%s': %s"
+msgstr "błąd podczas kończenia „%s”: %s"
+
+#: src/strip.c:2680 src/strip.c:2756
+#, c-format
+msgid "cannot set access and modification date of '%s'"
+msgstr "nie można ustawić czasu dostępu i modyfikacji „%s”"
+
+#: src/unstrip.c:65
+msgid "Match MODULE against file names, not module names"
+msgstr "Dopasowuje MODUŁY do nazw plików, a nie nazwy modułów"
+
+#: src/unstrip.c:66
+msgid "Silently skip unfindable files"
+msgstr "Pomija nieodnalezione pliki bez zgłaszania tego"
+
+#: src/unstrip.c:69
+msgid "Place output into FILE"
+msgstr "Umieszcza wyjście w PLIKU"
+
+#: src/unstrip.c:71
+msgid "Create multiple output files under DIRECTORY"
+msgstr "Tworzy wiele plików wyjściowych w KATALOGU"
+
+#: src/unstrip.c:72
+msgid "Use module rather than file names"
+msgstr "Używa nazw modułów zamiast nazw plików"
+
+#: src/unstrip.c:74
+msgid "Create output for modules that have no separate debug information"
+msgstr ""
+"Tworzy wyjście dla modułów niemających oddzielnych informacji debugowania"
+
+#: src/unstrip.c:77
+msgid "Apply relocations to section contents in ET_REL files"
+msgstr "Zastosowuje relokacje do zawartości sekcji w plikach ET_REL"
+
+#: src/unstrip.c:79
+msgid "Only list module and file names, build IDs"
+msgstr "Wyświetla tylko nazwy modułów i plików, identyfikatory kopii"
+
+#: src/unstrip.c:81
+msgid "Force combining files even if some ELF headers don't seem to match"
+msgstr ""
+"Wymusza łączenie plików, nawet jeśli niektóre nagłówki ELF się nie zgadzają"
+
+#: src/unstrip.c:125
+#, c-format
+msgid "-d option specified twice"
+msgstr "opcję -d podano dwukrotnie"
+
+#: src/unstrip.c:160
+#, c-format
+msgid "only one of -o or -d allowed"
+msgstr "dozwolona jest tylko jedna z opcji -o lub -d"
+
+#: src/unstrip.c:169
+#, c-format
+msgid "-n cannot be used with explicit files or -o or -d"
+msgstr "opcja -n nie może być używana z jawnymi plikami albo z opcją -o lub -d"
+
+#: src/unstrip.c:184
+#, c-format
+msgid "output directory '%s'"
+msgstr "katalog wyjściowy „%s”"
+
+#: src/unstrip.c:193
+#, c-format
+msgid "exactly two file arguments are required"
+msgstr "wymagane są dokładnie dwa parametry plików"
+
+#: src/unstrip.c:199
+#, c-format
+msgid "-m, -a, -R, and -i options not allowed with explicit files"
+msgstr "opcje -m, -a, -R oraz -i nie są dozwolone z jawnymi plikami"
+
+#: src/unstrip.c:212
+#, c-format
+msgid "-o or -d is required when using implicit files"
+msgstr "opcja -o lub -d jest wymagana podczas używania ukrytych plików"
+
+#: src/unstrip.c:235
+#, c-format
+msgid "cannot create ELF header: %s"
+msgstr "nie można utworzyć nagłówka ELF: %s"
+
+#: src/unstrip.c:239
+#, c-format
+msgid "cannot get shdrstrndx:%s"
+msgstr "nie można uzyskać shdrstrndx: %s"
+
+#: src/unstrip.c:243 src/unstrip.c:2136
+#, c-format
+msgid "cannot get ELF header: %s"
+msgstr "nie można uzyskać nagłówka ELF: %s"
+
+#: src/unstrip.c:253
+#, c-format
+msgid "cannot get new zero section: %s"
+msgstr "nie można uzyskać nowej sekcji zerowej: %s"
+
+#: src/unstrip.c:256
+#, c-format
+msgid "cannot update new zero section: %s"
+msgstr "nie można zaktualizować nowej sekcji zerowej: %s"
+
+#: src/unstrip.c:260
+#, c-format
+msgid "cannot copy ELF header: %s"
+msgstr "nie można skopiować nagłówka ELF: %s"
+
+#: src/unstrip.c:264 src/unstrip.c:2154 src/unstrip.c:2197
+#, c-format
+msgid "cannot get number of program headers: %s"
+msgstr "nie można uzyskać liczby nagłówków programu: %s"
+
+#: src/unstrip.c:269 src/unstrip.c:2158
+#, c-format
+msgid "cannot create program headers: %s"
+msgstr "nie można utworzyć nagłówków programu: %s"
+
+#: src/unstrip.c:275
+#, c-format
+msgid "cannot copy program header: %s"
+msgstr "nie można skopiować nagłówka programu: %s"
+
+#: src/unstrip.c:285
+#, c-format
+msgid "cannot copy section header: %s"
+msgstr "nie można skopiować nagłówka sekcji: %s"
+
+#: src/unstrip.c:288 src/unstrip.c:1748
+#, c-format
+msgid "cannot get section data: %s"
+msgstr "nie można uzyskać danych sekcji: %s"
+
+#: src/unstrip.c:290 src/unstrip.c:1750
+#, c-format
+msgid "cannot copy section data: %s"
+msgstr "nie można skopiować danych sekcji: %s"
+
+#: src/unstrip.c:318
+#, c-format
+msgid "cannot create directory '%s'"
+msgstr "nie można utworzyć katalogu „%s”"
+
+#: src/unstrip.c:392 src/unstrip.c:666 src/unstrip.c:700 src/unstrip.c:868
+#: src/unstrip.c:1790
+#, c-format
+msgid "cannot get symbol table entry: %s"
+msgstr "nie można uzyskać wpisu tabeli symboli: %s"
+
+#: src/unstrip.c:408 src/unstrip.c:669 src/unstrip.c:690 src/unstrip.c:703
+#: src/unstrip.c:1811 src/unstrip.c:2007 src/unstrip.c:2031
+#, c-format
+msgid "cannot update symbol table: %s"
+msgstr "nie można zaktualizować tabeli symboli: %s"
+
+#: src/unstrip.c:418
+#, c-format
+msgid "cannot update section header: %s"
+msgstr "nie można zaktualizować nagłówka sekcji: %s"
+
+#: src/unstrip.c:464
+#, c-format
+msgid "gelf_getrel failed: %s"
+msgstr ""
+
+#: src/unstrip.c:467 src/unstrip.c:482
+#, c-format
+msgid "cannot update relocation: %s"
+msgstr "nie można zaktualizować relokacji: %s"
+
+#: src/unstrip.c:479
+#, c-format
+msgid "gelf_getrela failed: %s"
+msgstr ""
+
+#: src/unstrip.c:580
+#, c-format
+msgid "cannot get symbol version: %s"
+msgstr "nie można uzyskać wersji symbolu: %s"
+
+#: src/unstrip.c:593
+#, c-format
+msgid "unexpected section type in [%zu] with sh_link to symtab"
+msgstr "nieoczekiwany typ sekcji w [%zu] z sh_link do tabeli symboli"
+
+#: src/unstrip.c:857
+#, c-format
+msgid "cannot get symbol section data: %s"
+msgstr "nie można uzyskać danych sekcji symboli: %s"
+
+#: src/unstrip.c:859
+#, c-format
+msgid "cannot get string section data: %s"
+msgstr "nie można uzyskać danych sekcji ciągów: %s"
+
+#: src/unstrip.c:876
+#, c-format
+msgid "invalid string offset in symbol [%zu]"
+msgstr "nieprawidłowy offset ciągu w symbolu [%zu]"
+
+#: src/unstrip.c:939
+msgid "found two identical index map positions."
+msgstr ""
+
+#: src/unstrip.c:990
+msgid "section symbols in unexpected order"
+msgstr ""
+
+#: src/unstrip.c:996
+#, fuzzy
+#| msgid "Show demangled symbols (ARG is always ignored)"
+msgid "found two identical symbols"
+msgstr ""
+"Wyświetla symbole z usuniętym dekorowaniem (PARAMETR jest zawsze ignorowany)"
+
+#: src/unstrip.c:1066 src/unstrip.c:1474
+#, c-format
+msgid "cannot read section [%zu] name: %s"
+msgstr "nie można odczytać nazwy sekcji [%zu]: %s"
+
+#: src/unstrip.c:1081
+#, c-format
+msgid "bad sh_link for group section: %s"
+msgstr "błędne sh_link dla sekcji grupy: %s"
+
+#: src/unstrip.c:1087
+#, c-format
+msgid "couldn't get shdr for group section: %s"
+msgstr "nie można uzyskać shdr dla sekcji grupy: %s"
+
+#: src/unstrip.c:1092
+#, c-format
+msgid "bad data for group symbol section: %s"
+msgstr "błędne dane dla sekcji symboli grupy: %s"
+
+#: src/unstrip.c:1098
+#, c-format
+msgid "couldn't get symbol for group section: %s"
+msgstr "nie można uzyskać symbolu dla sekcji grupy: %s"
+
+#: src/unstrip.c:1103
+#, c-format
+msgid "bad symbol name for group section: %s"
+msgstr "błędna nazwa symbolu dla sekcji grupy: %s"
+
+#: src/unstrip.c:1114 src/unstrip.c:1594
+#, c-format
+msgid "cannot find matching section for [%zu] '%s'"
+msgstr "nie można odnaleźć pasującej sekcji dla [%zu] „%s”"
+
+#: src/unstrip.c:1159 src/unstrip.c:1178 src/unstrip.c:1216
+#, c-format
+msgid "cannot read '.gnu.prelink_undo' section: %s"
+msgstr "nie można odczytać sekcji „.gnu.prelink_undo”: %s"
+
+#: src/unstrip.c:1196
+#, c-format
+msgid "overflow with shnum = %zu in '%s' section"
+msgstr "przepełnienie z shnum = %zu w sekcji „%s”"
+
+#: src/unstrip.c:1207
+#, c-format
+msgid "invalid contents in '%s' section"
+msgstr "nieprawidłowa zawartość w sekcji „%s”"
+
+#: src/unstrip.c:1378 src/unstrip.c:1394 src/unstrip.c:1674 src/unstrip.c:1966
+#, c-format
+msgid "cannot add section name to string table: %s"
+msgstr "nie można nazwy sekcji do tabeli ciągów: %s"
+
+#: src/unstrip.c:1403
+#, c-format
+msgid "cannot update section header string table data: %s"
+msgstr "nie można zaktualizować danych tabeli ciągów nagłówków sekcji: %s"
+
+#: src/unstrip.c:1432 src/unstrip.c:1436
+#, c-format
+msgid "cannot get section header string table section index: %s"
+msgstr "nie można uzyskać indeksu sekcji tabeli ciągów nagłówków sekcji: %s"
+
+#: src/unstrip.c:1440 src/unstrip.c:1444 src/unstrip.c:1689
+#, c-format
+msgid "cannot get section count: %s"
+msgstr "nie można uzyskać licznika sekcji: %s"
+
+#: src/unstrip.c:1447
+msgid "more sections in stripped file than debug file -- arguments reversed?"
+msgstr ""
+"więcej sekcji w okrojonym pliku niż w pliku debugowania — odwrócono "
+"parametry?"
+
+#: src/unstrip.c:1451
+msgid "no sections in stripped file"
+msgstr "brak sekcji w okrojonym pliku"
+
+#: src/unstrip.c:1499 src/unstrip.c:1609
+#, c-format
+msgid "cannot read section header string table: %s"
+msgstr "nie można odczytać tabeli ciągów nagłówków sekcji: %s"
+
+#: src/unstrip.c:1668
+#, c-format
+msgid "cannot add new section: %s"
+msgstr "nie można dodać nowej sekcji: %s"
+
+#: src/unstrip.c:1798
+#, c-format
+msgid "symbol [%zu] has invalid section index"
+msgstr "symbol [%zu] ma nieprawidłowy indeks sekcji"
+
+#: src/unstrip.c:1830
+#, c-format
+msgid "group has invalid section index [%zd]"
+msgstr "grupa ma nieprawidłowy indeks sekcji [%zd]"
+
+#: src/unstrip.c:2115
+#, c-format
+msgid "cannot read section data: %s"
+msgstr "nie można odczytać danych sekcji: %s"
+
+#: src/unstrip.c:2144
+#, c-format
+msgid "cannot update ELF header: %s"
+msgstr "nie można zaktualizować nagłówka ELF: %s"
+
+#: src/unstrip.c:2168
+#, c-format
+msgid "cannot update program header: %s"
+msgstr "nie można zaktualizować nagłówka programu: %s"
+
+#: src/unstrip.c:2173 src/unstrip.c:2256
+#, c-format
+msgid "cannot write output file: %s"
+msgstr "nie można zapisać pliku wyjściowego: %s"
+
+#: src/unstrip.c:2224
+#, c-format
+msgid "DWARF data not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+"Dane DWARF nie zostały dostosowane do przesunięcia wczesnego konsolidowania; "
+"proszę rozważyć polecenie prelink -u"
+
+#: src/unstrip.c:2227
+#, c-format
+msgid ""
+"DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+"Dane DWARF w „%s” nie zostały dostosowane do przesunięcia wczesnego "
+"konsolidowania; proszę rozważyć polecenie prelink -u"
+
+#: src/unstrip.c:2247 src/unstrip.c:2299 src/unstrip.c:2311 src/unstrip.c:2401
+#, c-format
+msgid "cannot create ELF descriptor: %s"
+msgstr "nie można utworzyć deskryptora ELF: %s"
+
+#: src/unstrip.c:2285
+msgid "WARNING: "
+msgstr "OSTRZEŻENIE: "
+
+#: src/unstrip.c:2287
+msgid ", use --force"
+msgstr ", należy użyć opcji --force"
+
+#: src/unstrip.c:2315
+msgid "ELF header identification (e_ident) different"
+msgstr "Różna identyfikacja nagłówka ELF (e_ident)"
+
+#: src/unstrip.c:2319
+msgid "ELF header type (e_type) different"
+msgstr "Różne typy nagłówka ELF (e_type)"
+
+#: src/unstrip.c:2323
+msgid "ELF header machine type (e_machine) different"
+msgstr "Różne typy maszyny nagłówka ELF (e_machine)"
+
+#: src/unstrip.c:2327
+msgid "stripped program header (e_phnum) smaller than unstripped"
+msgstr "okrojony nagłówek programu (e_phnum) jest mniejszy niż nieokrojony"
+
+#: src/unstrip.c:2358
+#, c-format
+msgid "cannot find stripped file for module '%s': %s"
+msgstr "nie można odnaleźć okrojonego pliku dla modułu „%s”: %s"
+
+#: src/unstrip.c:2362
+#, c-format
+msgid "cannot open stripped file '%s' for module '%s': %s"
+msgstr "nie można otworzyć okrojonego pliku „%s” dla modułu „%s”: %s"
+
+#: src/unstrip.c:2377
+#, c-format
+msgid "cannot find debug file for module '%s': %s"
+msgstr "nie można odnaleźć pliku debugowania dla modułu „%s”: %s"
+
+#: src/unstrip.c:2381
+#, c-format
+msgid "cannot open debug file '%s' for module '%s': %s"
+msgstr "nie można otworzyć pliku debugowania „%s” dla modułu „%s”: %s"
+
+#: src/unstrip.c:2394
+#, c-format
+msgid "module '%s' file '%s' is not stripped"
+msgstr "moduł „%s” pliku „%s” nie został okrojony"
+
+#: src/unstrip.c:2425
+#, c-format
+msgid "cannot cache section addresses for module '%s': %s"
+msgstr ""
+"nie można utworzyć pamięci podręcznej adresów sekcji dla modułu „%s”: %s"
+
+#: src/unstrip.c:2553
+msgid "no matching modules found"
+msgstr "nie odnaleziono pasujących modułów"
+
+#: src/unstrip.c:2563
+msgid "matched more than one module"
+msgstr "pasuje więcej niż jeden moduł"
+
+#: src/unstrip.c:2608
+msgid ""
+"STRIPPED-FILE DEBUG-FILE\n"
+"[MODULE...]"
+msgstr ""
+"OKROJONY-PLIK PLIK-DEBUGOWANIA\n"
+"[MODUŁ…]"
+
+#: src/unstrip.c:2609
+msgid ""
+"Combine stripped files with separate symbols and debug information.\n"
+"\n"
+"The first form puts the result in DEBUG-FILE if -o was not given.\n"
+"\n"
+"MODULE arguments give file name patterns matching modules to process.\n"
+"With -f these match the file name of the main (stripped) file (slashes are "
+"never special), otherwise they match the simple module names.  With no "
+"arguments, process all modules found.\n"
+"\n"
+"Multiple modules are written to files under OUTPUT-DIRECTORY, creating "
+"subdirectories as needed.  With -m these files have simple module names, "
+"otherwise they have the name of the main file complete with directory "
+"underneath OUTPUT-DIRECTORY.\n"
+"\n"
+"With -n no files are written, but one line to standard output for each "
+"module:\n"
+"\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n"
+"START and SIZE are hexadecimal giving the address bounds of the module.  "
+"BUILDID is hexadecimal for the build ID bits, or - if no ID is known; the "
+"hexadecimal may be followed by @0xADDR giving the address where the ID "
+"resides if that is known.  FILE is the file name found for the module, or - "
+"if none was found, or . if an ELF image is available but not from any named "
+"file.  DEBUGFILE is the separate debuginfo file name, or - if no debuginfo "
+"was found, or . if FILE contains the debug information."
+msgstr ""
+"Łączy okrojone pliki z oddzielnymi symbolami i informacjami debugowania.\n"
+"\n"
+"Pierwsza forma umieszcza wynik w PLIKU-DEBUGOWANIA, jeśli nie podano opcji -"
+"o.\n"
+"\n"
+"Parametry MODUŁ podają wzorce nazw plików dopasowujące moduły do procesów.\n"
+"Za pomocą opcji -f dopasowuje nazwę głównego (okrojonego) pliku (ukośniki "
+"nigdy nie są specjalne), w innym przypadku dopasowują proste nazwy modułów. "
+"Jeśli nie podano parametrów, przetwarza wszystkie odnalezione moduły.\n"
+"\n"
+"Wiele modułów zostaje zapisanych do plików w KATALOGU-WYJŚCIOWYM, tworząc "
+"podkatalogi, jeśli są wymagane. Używając opcji -m te pliki mają proste nazwy "
+"modułów, w innym przypadku mają nazwy głównego pliku uzupełnione katalogiem "
+"w KATALOGU-WYJŚCIOWYM.\n"
+"\n"
+"Używając opcji -n żadne pliki nie zostają zapisane, a jeden wiersz do "
+"standardowego wyjścia dla każdego modułu:\n"
+"\tPOCZĄTEK+ROZMIAR IDENTYFIKATOR-KOPII PLIK PLIK-DEBUGOWANIA NAZWA-MODUŁU\n"
+"POCZĄTEK i ROZMIAR są liczbami szesnastkowymi podającymi zakres adresów "
+"modułu. IDENTYFIKATOR-KOPII jest liczbą szesnastkową dla bitów "
+"identyfikatora kopii lub „-”, jeśli identyfikator jest nieznany; liczba "
+"szesnastkowa może być uzupełniona @0xADRES podającym adres, gdzie znajduje "
+"się identyfikator, jeśli jest to wiadome. PLIK jest nazwą pliku "
+"odnalezionego dla modułu lub „-”, jeśli go nie odnaleziono lub „.”, jeśli "
+"obraz ELF jest dostępny, ale nie z żadnego nazwanego pliku. PLIK-DEBUGOWANIA "
+"jest nazwą oddzielnego pliku debuginfo lub „-”, jeśli nie odnaleziono "
+"debuginfo lub „.”, jeśli PLIK zawiera informacje debugowania."
+
+#. Short description of program.
+#: debuginfod/debuginfod-find.c:42
+msgid "Request debuginfo-related content from debuginfods listed in $"
+msgstr "Żąda zawartość powiązaną z debuginfo z debuginfod wymienionych w $"
+
+#. Strings for arguments in help texts.
+#: debuginfod/debuginfod-find.c:46
+#, fuzzy
+#| msgid ""
+#| "debuginfo BUILDID\n"
+#| "debuginfo PATH\n"
+#| "executable BUILDID\n"
+#| "executable PATH\n"
+#| "source BUILDID /FILENAME\n"
+#| "source PATH /FILENAME\n"
+msgid ""
+"debuginfo BUILDID\n"
+"debuginfo PATH\n"
+"executable BUILDID\n"
+"executable PATH\n"
+"source BUILDID /FILENAME\n"
+"source PATH /FILENAME\n"
+"section BUILDID SECTION-NAME\n"
+"section PATH SECTION-NAME\n"
+msgstr ""
+"debuginfo IDENTYFIKATOR-KOPII\n"
+"debuginfo ŚCIEŻKA\n"
+"executable IDENTYFIKATOR-KOPII\n"
+"executable ŚCIEŻKA\n"
+"source IDENTYFIKATOR-KOPII /NAZWA-PLIKU\n"
+"source ŚCIEŻKA /NAZWA-PLIKU\n"
+
+#: tests/backtrace.c:491
+msgid "Run executable"
+msgstr "Uruchamia plik wykonywalny"
+
+#: tests/dwflmodtest.c:209
+msgid "Additionally show function names"
+msgstr "Dodatkowo wyświetla nazwy funkcji"
+
+#: tests/dwflmodtest.c:210
+msgid "Show instances of inlined functions"
+msgstr "Wyświetla wystąpienia wstawionych funkcji"
+
+#, c-format
+#~ msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n"
+#~ msgstr ""
+#~ "sekcja [%2d] „%s”: rozmiar wpisu sekcji nie zgadza się z ElfXX_Rela\n"
+
+#, c-format
+#~ msgid "cannot get .debug_addr section data: %s"
+#~ msgstr "nie można uzyskać danych sekcji .debug_addr: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_rnglists content: %s"
+#~ msgstr "nie można uzyskać zawartości .debug_rnglists: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_ranges content: %s"
+#~ msgstr "nie można uzyskać zawartości .debug_ranges: %s"
+
+#, c-format
+#~ msgid "cannot get line data section data: %s"
+#~ msgstr "nie można uzyskać danych sekcji danych wiersza: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loclists content: %s"
+#~ msgstr "nie można uzyskać zawartości .debug_loclists: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loc content: %s"
+#~ msgstr "nie można uzyskać zawartości .debug_log: %s"
+
+#, c-format
+#~ msgid "cannot get macro information section data: %s"
+#~ msgstr "nie można uzyskać danych sekcji informacji o makrach: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_str_offsets section data: %s"
+#~ msgstr "nie można uzyskać danych sekcji .debug_str_offsets: %s"
+
+#, c-format
+#~ msgid "cannot allocate memory"
+#~ msgstr "nie można przydzielić pamięci"
diff --git a/po/uk.po b/po/uk.po
new file mode 100644
index 0000000..f700756
--- /dev/null
+++ b/po/uk.po
@@ -0,0 +1,8231 @@
+# Ukrainian translation of elfutils
+# Copyright (C) 2010 Free Software Foundation, Inc.
+# This file is distributed under the same license as the elfutils package.
+#
+# Yuri Chornoivan <yurchor@ukr.net>, 2010, 2011, 2012, 2013, 2014, 2015, 2020.
+msgid ""
+msgstr ""
+"Project-Id-Version: elfutils\n"
+"Report-Msgid-Bugs-To: https://sourceware.org/bugzilla/\n"
+"POT-Creation-Date: 2024-03-01 10:22-0500\n"
+"PO-Revision-Date: 2020-03-28 14:59+0200\n"
+"Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n"
+"Language-Team: Ukrainian <kde-i18n-uk@kde.org>\n"
+"Language: uk\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
+"X-Generator: Lokalize 20.03.70\n"
+
+#: lib/color.c:51
+msgid ""
+"colorize the output.  WHEN defaults to 'always' or can be 'auto' or 'never'"
+msgstr ""
+"розфарбовувати виведене. Типові значення «always» (завжди), «auto» (авто) "
+"або «never» (ніколи)"
+
+#: lib/color.c:127
+#, c-format
+msgid ""
+"%s: invalid argument '%s' for '--color'\n"
+"valid arguments are:\n"
+"  - 'always', 'yes', 'force'\n"
+"  - 'never', 'no', 'none'\n"
+"  - 'auto', 'tty', 'if-tty'\n"
+msgstr ""
+"%s: некоректний аргумент «%s» до «--color»\n"
+"коректними аргументами є такі:\n"
+"  - «always», «yes», «force»\n"
+"  - «never», «no», «none»\n"
+"  - «auto», «tty», «if-tty»\n"
+
+#: lib/printversion.c:39
+#, c-format
+msgid ""
+"Copyright (C) %s The elfutils developers <%s>.\n"
+"This is free software; see the source for copying conditions.  There is NO\n"
+"warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+msgstr ""
+"© Розробники elfutils, %s <%s>.\n"
+"Це програмне забезпечення є вільним, умови копіювання викладено у його "
+"початкових кодах. Умовами ліцензування програми НЕ передбачено жодних "
+"гарантій, зокрема гарантій працездатності або придатності для певної мети.\n"
+
+#: lib/xmalloc.c:47 lib/xmalloc.c:60 lib/xmalloc.c:72 src/readelf.c:12203
+#: src/unstrip.c:311
+#, c-format
+msgid "memory exhausted"
+msgstr "пам’ять вичерпано"
+
+#: libasm/asm_error.c:64 libdw/dwarf_error.c:57 libdwfl/libdwflP.h:47
+#: libelf/elf_error.c:59
+msgid "no error"
+msgstr "без помилок"
+
+#: libasm/asm_error.c:65 libdw/dwarf_error.c:67 libdwfl/libdwflP.h:49
+#: libelf/elf_error.c:90
+msgid "out of memory"
+msgstr "нестача пам'яті"
+
+#: libasm/asm_error.c:66
+msgid "cannot create output file"
+msgstr "не вдалося створити файл виводу даних"
+
+#: libasm/asm_error.c:67
+msgid "invalid parameter"
+msgstr "некоректний параметр"
+
+#: libasm/asm_error.c:68
+msgid "cannot change mode of output file"
+msgstr "не вдалося змінити права доступу до файла виводу даних"
+
+#: libasm/asm_error.c:69
+msgid "cannot rename output file"
+msgstr "не вдалося перейменувати файл виводу даних"
+
+#: libasm/asm_error.c:70
+msgid "duplicate symbol"
+msgstr "дублювання символів"
+
+#: libasm/asm_error.c:71
+msgid "invalid section type for operation"
+msgstr "некоректний тип розділу для дії"
+
+#: libasm/asm_error.c:72
+msgid "error during output of data"
+msgstr "помилка під час спроби виведення даних"
+
+#: libasm/asm_error.c:73
+msgid "no backend support available"
+msgstr "підтримки серверів не передбачено"
+
+#: libasm/asm_error.c:82 libdw/dwarf_error.c:58 libdwfl/libdwflP.h:48
+#: libelf/elf_error.c:62
+msgid "unknown error"
+msgstr "невідома помилка"
+
+#: libcpu/i386_lex.l:121
+#, fuzzy, c-format
+#| msgid "invalid page size value '%s': ignored"
+msgid "invalid character '%c' at line %d; ignored"
+msgstr "некоректне значення розміру сторінки «%s»: проігноровано"
+
+#: libcpu/i386_lex.l:122
+#, fuzzy, c-format
+#| msgid "invalid page size value '%s': ignored"
+msgid "invalid character '\\%o' at line %d; ignored"
+msgstr "некоректне значення розміру сторінки «%s»: проігноровано"
+
+#: libcpu/i386_parse.y:555
+#, fuzzy, c-format
+#| msgid "while reading linker script '%s': %s at line %d"
+msgid "while reading i386 CPU description: %s at line %d"
+msgstr "під час читання скрипту компонування «%s»: %s у рядку %d"
+
+#: libdw/dwarf_error.c:59
+msgid "invalid access"
+msgstr "некоректний доступ"
+
+#: libdw/dwarf_error.c:60
+msgid "no regular file"
+msgstr "не є звичайним файлом"
+
+#: libdw/dwarf_error.c:61
+msgid "I/O error"
+msgstr "помилка вводу/виводу"
+
+#: libdw/dwarf_error.c:62
+msgid "invalid ELF file"
+msgstr "некоректний файл ELF"
+
+#: libdw/dwarf_error.c:63
+msgid "no DWARF information"
+msgstr "немає відомостей DWARF"
+
+#: libdw/dwarf_error.c:64
+msgid "cannot decompress DWARF"
+msgstr "не вдалося розпакувати DWARF"
+
+#: libdw/dwarf_error.c:65
+msgid "no ELF file"
+msgstr "немає файла ELF"
+
+#: libdw/dwarf_error.c:66
+msgid "cannot get ELF header"
+msgstr "не вдалося отримати заголовок ELF"
+
+#: libdw/dwarf_error.c:68
+msgid "not implemented"
+msgstr "не реалізовано"
+
+#: libdw/dwarf_error.c:69 libelf/elf_error.c:110 libelf/elf_error.c:158
+msgid "invalid command"
+msgstr "некоректна команда"
+
+#: libdw/dwarf_error.c:70
+msgid "invalid version"
+msgstr "некоректна версія"
+
+#: libdw/dwarf_error.c:71
+msgid "invalid file"
+msgstr "некоректний файл"
+
+#: libdw/dwarf_error.c:72
+msgid "no entries found"
+msgstr "запис не знайдено"
+
+#: libdw/dwarf_error.c:73
+msgid "invalid DWARF"
+msgstr "некоректний запис DWARF"
+
+#: libdw/dwarf_error.c:74
+msgid "no string data"
+msgstr "немає рядкових даних"
+
+#: libdw/dwarf_error.c:75
+msgid ".debug_str section missing"
+msgstr "пропущено розділ .debug_str"
+
+#: libdw/dwarf_error.c:76
+msgid ".debug_line_str section missing"
+msgstr "пропущено розділ .debug_line_str"
+
+#: libdw/dwarf_error.c:77
+msgid ".debug_str_offsets section missing"
+msgstr "пропущено розділ .debug_str_offsets"
+
+#: libdw/dwarf_error.c:78
+msgid "no address value"
+msgstr "немає значення адреси"
+
+#: libdw/dwarf_error.c:79
+msgid "no constant value"
+msgstr "немає значення сталої"
+
+#: libdw/dwarf_error.c:80
+msgid "no reference value"
+msgstr "немає значення для порівняння"
+
+#: libdw/dwarf_error.c:81
+msgid "invalid reference value"
+msgstr "некоректне значення для порівняння"
+
+#: libdw/dwarf_error.c:82
+msgid ".debug_line section missing"
+msgstr "немає розділу .debug_line"
+
+#: libdw/dwarf_error.c:83
+msgid "invalid .debug_line section"
+msgstr "некоректний розділ .debug_line"
+
+#: libdw/dwarf_error.c:84
+msgid "debug information too big"
+msgstr "занадто великі відомості для діагностики"
+
+#: libdw/dwarf_error.c:85
+msgid "invalid DWARF version"
+msgstr "некоректна версія DWARF"
+
+#: libdw/dwarf_error.c:86
+msgid "invalid directory index"
+msgstr "некоректний покажчик каталогу"
+
+#: libdw/dwarf_error.c:87 libdwfl/libdwflP.h:69
+msgid "address out of range"
+msgstr "некоректна адреса"
+
+#: libdw/dwarf_error.c:88
+msgid ".debug_loc section missing"
+msgstr "пропущено розділ .debug_loc"
+
+#: libdw/dwarf_error.c:89
+msgid ".debug_loclists section missing"
+msgstr "пропущено розділ .debug_loclists"
+
+#: libdw/dwarf_error.c:90
+msgid "not a location list value"
+msgstr "не є значенням списку адрес"
+
+#: libdw/dwarf_error.c:91
+msgid "no block data"
+msgstr "немає блокових даних"
+
+#: libdw/dwarf_error.c:92
+msgid "invalid line index"
+msgstr "некоректний номер рядка"
+
+#: libdw/dwarf_error.c:93
+msgid "invalid address range index"
+msgstr "некоректний індекс діапазону адрес"
+
+#: libdw/dwarf_error.c:94 libdwfl/libdwflP.h:70
+msgid "no matching address range"
+msgstr "не виявлено відповідного діапазону адрес"
+
+#: libdw/dwarf_error.c:95
+msgid "no flag value"
+msgstr "немає значення прапорця"
+
+#: libdw/dwarf_error.c:96 libelf/elf_error.c:235
+msgid "invalid offset"
+msgstr "некоректне значення зміщення"
+
+#: libdw/dwarf_error.c:97
+msgid ".debug_ranges section missing"
+msgstr "немає розділу .debug_ranges"
+
+#: libdw/dwarf_error.c:98
+msgid ".debug_rnglists section missing"
+msgstr "пропущено розділ .debug_rnglists"
+
+#: libdw/dwarf_error.c:99
+msgid "invalid CFI section"
+msgstr "некоректний розділ CFI"
+
+#: libdw/dwarf_error.c:100
+msgid "no alternative debug link found"
+msgstr "альтернативного діагностичного посилання не знайдено"
+
+#: libdw/dwarf_error.c:101
+msgid "invalid opcode"
+msgstr "некоректний код операції"
+
+#: libdw/dwarf_error.c:102
+msgid "not a CU (unit) DIE"
+msgstr "не є DIE CU (модуля)"
+
+#: libdw/dwarf_error.c:103
+msgid "unknown language code"
+msgstr "невідомий код мови"
+
+#: libdw/dwarf_error.c:104
+msgid ".debug_addr section missing"
+msgstr "пропущено розділ .debug_addr"
+
+#: libdw/dwarf_error.c:105
+#, fuzzy
+#| msgid "unknown version"
+msgid "unknown section"
+msgstr "невідома версія"
+
+#: libdwfl/argp-std.c:45 src/stack.c:643 src/unstrip.c:2598
+msgid "Input selection options:"
+msgstr "Вибір параметрів виведення даних:"
+
+#: libdwfl/argp-std.c:46
+msgid "Find addresses in FILE"
+msgstr "Знайти адреси у ФАЙЛІ"
+
+#: libdwfl/argp-std.c:48
+msgid "Find addresses from signatures found in COREFILE"
+msgstr "Знайти адреси за сигнатурами з файла COREFILE"
+
+#: libdwfl/argp-std.c:50
+msgid "Find addresses in files mapped into process PID"
+msgstr "Знайти адреси у файлах, відображених на процес з PID"
+
+#: libdwfl/argp-std.c:52
+msgid ""
+"Find addresses in files mapped as read from FILE in Linux /proc/PID/maps "
+"format"
+msgstr ""
+"Знайти адреси у файлах, відображених як read за ФАЙЛОМ у форматі /proc/PID/"
+"maps Linux"
+
+#: libdwfl/argp-std.c:54
+msgid "Find addresses in the running kernel"
+msgstr "Знайти адреси у запущеному ядрі"
+
+#: libdwfl/argp-std.c:56
+msgid "Kernel with all modules"
+msgstr "Ядро з усіма модулями"
+
+#: libdwfl/argp-std.c:58 src/stack.c:650
+msgid "Search path for separate debuginfo files"
+msgstr "Шукати у вказаному каталозі окремі файли debuginfo"
+
+#: libdwfl/argp-std.c:159
+msgid "only one of -e, -p, -k, -K, or --core allowed"
+msgstr ""
+"можна використовувати лише один за параметрів: -e, -p, -k, -K або --core"
+
+#: libdwfl/argp-std.c:232
+msgid "cannot load kernel symbols"
+msgstr "не вдалося завантажити символи ядра"
+
+#. Non-fatal to have no modules since we do have the kernel.
+#: libdwfl/argp-std.c:236
+msgid "cannot find kernel modules"
+msgstr "не вдалося виявити модулі ядра"
+
+#: libdwfl/argp-std.c:253
+msgid "cannot find kernel or modules"
+msgstr "не вдалося виявити ядро або модулі"
+
+#: libdwfl/argp-std.c:292
+#, c-format
+msgid "cannot read ELF core file: %s"
+msgstr "не вдалося прочитати файл core ELF: %s"
+
+#: libdwfl/argp-std.c:315
+msgid "Not enough memory"
+msgstr "Бракує пам'яті"
+
+#: libdwfl/argp-std.c:325
+msgid "No modules recognized in core file"
+msgstr "Не вдалося виявити модулі у файлі core"
+
+#: libdwfl/libdwflP.h:50
+msgid "See errno"
+msgstr "Див. errno"
+
+#: libdwfl/libdwflP.h:51
+msgid "See elf_errno"
+msgstr "Див. elf_errno"
+
+#: libdwfl/libdwflP.h:52
+msgid "See dwarf_errno"
+msgstr "Див. dwarf_errno"
+
+#: libdwfl/libdwflP.h:53
+msgid "See ebl_errno (XXX missing)"
+msgstr "Див. ebl_errno (не виявлено XXX)"
+
+#: libdwfl/libdwflP.h:54
+msgid "gzip decompression failed"
+msgstr "Помилка під час спроби видобування з gzip"
+
+#: libdwfl/libdwflP.h:55
+msgid "bzip2 decompression failed"
+msgstr "Помилка під час спроби видобування з bzip2"
+
+#: libdwfl/libdwflP.h:56
+msgid "LZMA decompression failed"
+msgstr "Помилка під час спроби видобування з LZMA"
+
+#: libdwfl/libdwflP.h:57
+#, fuzzy
+msgid "zstd decompression failed"
+msgstr "Помилка під час спроби видобування з gzip"
+
+#: libdwfl/libdwflP.h:58
+msgid "no support library found for machine"
+msgstr "у системі не виявлено бібліотеки підтримки"
+
+#: libdwfl/libdwflP.h:59
+msgid "Callbacks missing for ET_REL file"
+msgstr "Немає зворотних викликів для файла ET_REL"
+
+#: libdwfl/libdwflP.h:60
+msgid "Unsupported relocation type"
+msgstr "Непідтримуваний тип пересування"
+
+#: libdwfl/libdwflP.h:61
+msgid "r_offset is bogus"
+msgstr "r_offset є фіктивним"
+
+#: libdwfl/libdwflP.h:62 libelf/elf_error.c:114 libelf/elf_error.c:174
+msgid "offset out of range"
+msgstr "перевищення можливого зміщення"
+
+#: libdwfl/libdwflP.h:63
+msgid "relocation refers to undefined symbol"
+msgstr "пересування посилається на невизначений символ."
+
+#: libdwfl/libdwflP.h:64
+msgid "Callback returned failure"
+msgstr "Зворотним викликом повернуто помилку"
+
+#: libdwfl/libdwflP.h:65
+msgid "No DWARF information found"
+msgstr "Не виявлено відомостей DWARF"
+
+#: libdwfl/libdwflP.h:66
+msgid "No symbol table found"
+msgstr "Не виявлено таблиці символів"
+
+#: libdwfl/libdwflP.h:67
+msgid "No ELF program headers"
+msgstr "Немає заголовків програми ELF"
+
+#: libdwfl/libdwflP.h:68
+msgid "address range overlaps an existing module"
+msgstr "діапазон адрес перекриває існуючий модуль"
+
+#: libdwfl/libdwflP.h:71
+msgid "image truncated"
+msgstr "образ обрізано"
+
+#: libdwfl/libdwflP.h:72
+msgid "ELF file opened"
+msgstr "Відкритий файл ELF"
+
+#: libdwfl/libdwflP.h:73
+msgid "not a valid ELF file"
+msgstr "не є коректним файлом ELF"
+
+#: libdwfl/libdwflP.h:74
+msgid "cannot handle DWARF type description"
+msgstr "не вдалося обробити опис типу DWARF"
+
+#: libdwfl/libdwflP.h:75
+msgid "ELF file does not match build ID"
+msgstr "Файл ELF не відповідає ідентифікатору збирання"
+
+#: libdwfl/libdwflP.h:76
+msgid "corrupt .gnu.prelink_undo section data"
+msgstr "дані розділу «.gnu.prelink_undo» пошкоджено"
+
+#: libdwfl/libdwflP.h:77
+msgid "Internal error due to ebl"
+msgstr "Внутрішня помилка через ebl"
+
+#: libdwfl/libdwflP.h:78
+msgid "Missing data in core file"
+msgstr "У файлі ядра не вистачає даних"
+
+#: libdwfl/libdwflP.h:79
+msgid "Invalid register"
+msgstr "Некоректний регістр"
+
+#: libdwfl/libdwflP.h:80
+#, fuzzy
+#| msgid "no reference value"
+msgid "Unknown register value"
+msgstr "немає значення для порівняння"
+
+#: libdwfl/libdwflP.h:81
+msgid "Error reading process memory"
+msgstr "Помилка під час спроби читання пам’яті процесу"
+
+#: libdwfl/libdwflP.h:82
+msgid "Couldn't find architecture of any ELF"
+msgstr "Не вдалося знайти хоч якусь архітектуру ELF"
+
+#: libdwfl/libdwflP.h:83
+msgid "Error parsing /proc filesystem"
+msgstr "Помилка під час спроби обробки файлової системи /proc"
+
+#: libdwfl/libdwflP.h:84
+msgid "Invalid DWARF"
+msgstr "Некоректний запис DWARF"
+
+#: libdwfl/libdwflP.h:85
+msgid "Unsupported DWARF"
+msgstr "Непідтримуваний запис DWARF"
+
+#: libdwfl/libdwflP.h:86
+msgid "Unable to find more threads"
+msgstr "Не вдалося знайти додаткові потоки"
+
+#: libdwfl/libdwflP.h:87
+msgid "Dwfl already has attached state"
+msgstr "Dwfl уже перебуває у стані долучення до процесу"
+
+#: libdwfl/libdwflP.h:88
+msgid "Dwfl has no attached state"
+msgstr "Dwfl не перебуває у стані долучення до процесу"
+
+#: libdwfl/libdwflP.h:89
+msgid "Unwinding not supported for this architecture"
+msgstr "Для цієї архітектури розгортання не передбачено"
+
+#: libdwfl/libdwflP.h:90
+msgid "Invalid argument"
+msgstr "Некоректний аргумент"
+
+#: libdwfl/libdwflP.h:91
+msgid "Not an ET_CORE ELF file"
+msgstr "Не є файлом ET_CORE ELF"
+
+#: libebl/eblbackendname.c:41
+msgid "No backend"
+msgstr "Немає сервера"
+
+#: libebl/eblcorenotetypename.c:100 libebl/eblobjnotetypename.c:79
+#: libebl/eblobjnotetypename.c:113 libebl/eblobjnotetypename.c:134
+#: libebl/eblosabiname.c:73 libebl/eblsectionname.c:83
+#: libebl/eblsectiontypename.c:116 libebl/eblsegmenttypename.c:81
+msgid "<unknown>"
+msgstr "<невідомо>"
+
+#: libebl/ebldynamictagname.c:103
+#, c-format
+msgid "<unknown>: %#<PRIx64>"
+msgstr "<невідомо>: %#<PRIx64>"
+
+#: libebl/eblobjnote.c:58
+#, c-format
+msgid "unknown SDT version %u\n"
+msgstr "невідома версія SDT, %u\n"
+
+#: libebl/eblobjnote.c:76
+#, c-format
+msgid "invalid SDT probe descriptor\n"
+msgstr "некоректний дескриптор зондування SDT\n"
+
+#: libebl/eblobjnote.c:126
+#, c-format
+msgid "    PC: "
+msgstr "    PC: "
+
+#: libebl/eblobjnote.c:128
+#, c-format
+msgid " Base: "
+msgstr "Основа: "
+
+#: libebl/eblobjnote.c:130
+#, c-format
+msgid " Semaphore: "
+msgstr " Семафор:   "
+
+#: libebl/eblobjnote.c:132
+#, c-format
+msgid "    Provider: "
+msgstr " Постачальник: "
+
+#: libebl/eblobjnote.c:134
+#, c-format
+msgid " Name: "
+msgstr "Назва: "
+
+#: libebl/eblobjnote.c:136
+#, c-format
+msgid " Args: "
+msgstr " Арг.: "
+
+#: libebl/eblobjnote.c:304
+#, c-format
+msgid "    Build ID: "
+msgstr "    Ід. збирання: "
+
+#. A non-null terminated version string.
+#: libebl/eblobjnote.c:315
+#, c-format
+msgid "    Linker version: %.*s\n"
+msgstr "    Версія компонувальника: %.*s\n"
+
+#: libebl/eblobjnote.c:642
+#, c-format
+msgid "    OS: %s, ABI: "
+msgstr "    ОС: %s, ABI: "
+
+#: libebl/eblosabiname.c:70
+msgid "Stand alone"
+msgstr "Окремий"
+
+#: libebl/eblsymbolbindingname.c:68 libebl/eblsymboltypename.c:74
+#, c-format
+msgid "<unknown>: %d"
+msgstr "<невідомий>: %d"
+
+#: libelf/elf_error.c:66
+msgid "unknown version"
+msgstr "невідома версія"
+
+#: libelf/elf_error.c:70
+msgid "unknown type"
+msgstr "невизначений тип"
+
+#: libelf/elf_error.c:74
+msgid "invalid `Elf' handle"
+msgstr "некоректний дескриптор «Elf»"
+
+#: libelf/elf_error.c:78
+msgid "invalid size of source operand"
+msgstr "некоректна розмірність вхідного параметра"
+
+#: libelf/elf_error.c:82
+msgid "invalid size of destination operand"
+msgstr "некоректна розмірність вихідного параметра"
+
+#: libelf/elf_error.c:86 src/readelf.c:6759
+#, c-format
+msgid "invalid encoding"
+msgstr "некоректне кодування"
+
+#: libelf/elf_error.c:94
+msgid "invalid file descriptor"
+msgstr "некоректний дескриптор файла"
+
+#: libelf/elf_error.c:98
+msgid "invalid ELF file data"
+msgstr "некоректні дані щодо файла ELF"
+
+#: libelf/elf_error.c:102
+msgid "invalid operation"
+msgstr "недійсна дія"
+
+#: libelf/elf_error.c:106
+msgid "ELF version not set"
+msgstr "версію ELF не вказано"
+
+#: libelf/elf_error.c:118
+msgid "invalid fmag field in archive header"
+msgstr "некоректне поле fmag у заголовку архіву"
+
+#: libelf/elf_error.c:122
+msgid "invalid archive file"
+msgstr "некоректний файл архіву"
+
+#: libelf/elf_error.c:126
+msgid "descriptor is not for an archive"
+msgstr "дескриптор не належить архіву"
+
+#: libelf/elf_error.c:130
+msgid "no index available"
+msgstr "такого номера немає"
+
+#: libelf/elf_error.c:134
+msgid "cannot read data from file"
+msgstr "не вдалося прочитати дані з файла"
+
+#: libelf/elf_error.c:138
+msgid "cannot write data to file"
+msgstr "не вдалося записати дані до файла"
+
+#: libelf/elf_error.c:142
+msgid "invalid binary class"
+msgstr "некоректний бінарний клас"
+
+#: libelf/elf_error.c:146
+msgid "invalid section index"
+msgstr "некоректний номер розділу"
+
+#: libelf/elf_error.c:150
+msgid "invalid operand"
+msgstr "некоректний параметр"
+
+#: libelf/elf_error.c:154
+msgid "invalid section"
+msgstr "некоректний розділ"
+
+#: libelf/elf_error.c:162
+msgid "executable header not created first"
+msgstr "заголовок виконуваного файла не було створено першим"
+
+#: libelf/elf_error.c:166
+msgid "file descriptor disabled"
+msgstr "дескриптор файла вимкнено"
+
+#: libelf/elf_error.c:170
+msgid "archive/member file descriptor mismatch"
+msgstr "невідповідність дескрипторів файлів архіву/елемента"
+
+#: libelf/elf_error.c:178
+msgid "cannot manipulate null section"
+msgstr "не можна оперувати нульовим розділом"
+
+#: libelf/elf_error.c:182
+msgid "data/scn mismatch"
+msgstr "невідповідність полів data/scn"
+
+#: libelf/elf_error.c:186
+msgid "invalid section header"
+msgstr "некоректний заголовок розділу"
+
+#: libelf/elf_error.c:190 src/readelf.c:10638 src/readelf.c:11243
+#: src/readelf.c:11344 src/readelf.c:11532
+#, c-format
+msgid "invalid data"
+msgstr "некоректні дані"
+
+#: libelf/elf_error.c:194
+msgid "unknown data encoding"
+msgstr "невідоме кодування даних"
+
+#: libelf/elf_error.c:198
+msgid "section `sh_size' too small for data"
+msgstr "розділ «sh_size» є замалим для даних"
+
+#: libelf/elf_error.c:202
+msgid "invalid section alignment"
+msgstr "некоректне вирівнювання розділу"
+
+#: libelf/elf_error.c:206
+msgid "invalid section entry size"
+msgstr "некоректна розмірність запису розділу"
+
+#: libelf/elf_error.c:210
+msgid "update() for write on read-only file"
+msgstr "update() для запису придатного лише для читання файла"
+
+#: libelf/elf_error.c:214
+msgid "no such file"
+msgstr "такого файла не виявлено"
+
+#: libelf/elf_error.c:218
+msgid "only relocatable files can contain section groups"
+msgstr "містити групи розділів можуть лише придатні до пересування файли"
+
+#: libelf/elf_error.c:223
+msgid ""
+"program header only allowed in executables, shared objects, and core files"
+msgstr ""
+"заголовок програми можна використовувати лише у виконуваних файлах, об’єктах "
+"спільного використання та файлах ядра"
+
+#: libelf/elf_error.c:230
+msgid "file has no program header"
+msgstr "у файлі немає заголовка програми"
+
+#: libelf/elf_error.c:240
+msgid "invalid section type"
+msgstr "некоректний тип розділу"
+
+#: libelf/elf_error.c:245
+msgid "invalid section flags"
+msgstr "некоректні прапорці розділу"
+
+#: libelf/elf_error.c:250
+msgid "section does not contain compressed data"
+msgstr "розділ не містить стиснутих даних"
+
+#: libelf/elf_error.c:255
+msgid "section contains compressed data"
+msgstr "розділ містить стиснені дані"
+
+#: libelf/elf_error.c:260
+msgid "unknown compression type"
+msgstr "невідомий тип стиснення"
+
+#: libelf/elf_error.c:265
+msgid "cannot compress data"
+msgstr "неможливо стиснути дані"
+
+#: libelf/elf_error.c:270
+msgid "cannot decompress data"
+msgstr "неможливо розпакувати дані"
+
+#: src/addr2line.c:58
+msgid "Input format options:"
+msgstr "Параметри форматування вхідних даних:"
+
+#: src/addr2line.c:60
+msgid "Treat addresses as offsets relative to NAME section."
+msgstr "Вважати адреси зміщеннями відносно розділу НАЗВА."
+
+#: src/addr2line.c:62
+msgid "Output format options:"
+msgstr "Параметри форматування результатів:"
+
+#: src/addr2line.c:63
+msgid "Print address before each entry"
+msgstr "Виводити адресу перед кожним записом"
+
+#: src/addr2line.c:64
+msgid "Show only base names of source files"
+msgstr "Показувати лише базові назви файлів коду програми"
+
+#: src/addr2line.c:66
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show absolute file names using compilation directory (default)"
+msgstr "Показувати абсолютні назви файлів з використанням каталогу збирання"
+
+#: src/addr2line.c:67
+msgid "Also show function names"
+msgstr "Показувати також назви функцій"
+
+#: src/addr2line.c:68
+msgid "Also show symbol or section names"
+msgstr "Показувати також назви символів та розділів"
+
+#: src/addr2line.c:69
+msgid "Also show symbol and the section names"
+msgstr "Показувати також назви символів та розділів"
+
+#: src/addr2line.c:70
+msgid "Also show line table flags"
+msgstr "Показувати також прапорці рядків таблиці"
+
+#: src/addr2line.c:72
+msgid ""
+"Show all source locations that caused inline expansion of subroutines at the "
+"address."
+msgstr ""
+"Показати усі місця у початковому коді, у яких було виявлено вбудоване "
+"розгортання підпрограм за вказаною адресою."
+
+#: src/addr2line.c:75
+msgid "Show demangled symbols (ARG is always ignored)"
+msgstr "Виводити розшифровані символи (АРГ завжди ігнорується)"
+
+#: src/addr2line.c:76
+#, fuzzy
+#| msgid "Show demangled symbols (ARG is always ignored)"
+msgid "Show demangled symbols"
+msgstr "Виводити розшифровані символи (АРГ завжди ігнорується)"
+
+#: src/addr2line.c:78
+msgid "Print all information on one line, and indent inlines"
+msgstr "Вивести усі дані у один рядок і додати відступи до перенесених рядків"
+
+#: src/addr2line.c:80
+#, fuzzy
+#| msgid "Show absolute file names using compilation directory"
+msgid "Show relative file names without compilation directory"
+msgstr "Показувати абсолютні назви файлів з використанням каталогу збирання"
+
+#: src/addr2line.c:82 src/elfcmp.c:69 src/findtextrel.c:65 src/nm.c:99
+#: src/strings.c:77
+msgid "Miscellaneous:"
+msgstr "Інше:"
+
+#. Short description of program.
+#: src/addr2line.c:90
+msgid ""
+"Locate source files and line information for ADDRs (in a.out by default)."
+msgstr "Шукати АДРЕСИ у файлах кодів та даних про рядки (типово, у a.out)."
+
+#. Strings for arguments in help texts.
+#: src/addr2line.c:94
+msgid "[ADDR...]"
+msgstr "[АДРЕСА...]"
+
+#: src/addr2line.c:530
+msgid "Section syntax requires exactly one module"
+msgstr "Синтаксис розділів вимагає точного одного модуля"
+
+#: src/addr2line.c:552
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside section '%s'"
+msgstr "зміщення %#<PRIxMAX> розташовано поза межами розділу «%s»"
+
+#: src/addr2line.c:662
+#, c-format
+msgid "cannot find symbol '%s'"
+msgstr "не вдалося знайти символ «%s»"
+
+#: src/addr2line.c:667
+#, c-format
+msgid "offset %#<PRIxMAX> lies outside contents of '%s'"
+msgstr "зміщення %#<PRIxMAX> розташовано поза межами вмісту «%s»"
+
+#: src/ar.c:66
+msgid "Commands:"
+msgstr "Команди:"
+
+#: src/ar.c:67
+msgid "Delete files from archive."
+msgstr "Вилучити файли з архіву."
+
+#: src/ar.c:68
+msgid "Move files in archive."
+msgstr "Пересунути файли до архіву."
+
+#: src/ar.c:69
+msgid "Print files in archive."
+msgstr "Надрукувати список файлів у архіві."
+
+#: src/ar.c:70
+msgid "Quick append files to archive."
+msgstr "Швидко додати файли до архіву."
+
+#: src/ar.c:72
+msgid "Replace existing or insert new file into archive."
+msgstr "Замінити поточний або вставити новий файл до архіву."
+
+#: src/ar.c:73
+msgid "Display content of archive."
+msgstr "Показати вміст архіву."
+
+#: src/ar.c:74
+msgid "Extract files from archive."
+msgstr "Видобути файли з архіву."
+
+#: src/ar.c:76
+msgid "Command Modifiers:"
+msgstr "Модифікатори команд:"
+
+#: src/ar.c:77
+msgid "Preserve original dates."
+msgstr "Зберігати початкові часові мітки."
+
+#: src/ar.c:78
+msgid "Use instance [COUNT] of name."
+msgstr "Використовувати екземпляр [НОМЕР] назви."
+
+#: src/ar.c:80
+msgid "Do not replace existing files with extracted files."
+msgstr "Не замінювати поточні файли видобутими."
+
+#: src/ar.c:81
+msgid "Allow filename to be truncated if necessary."
+msgstr "Уможливити, за потреби, обрізання назв файлів."
+
+#: src/ar.c:83
+msgid "Provide verbose output."
+msgstr "Докладний вивід даних."
+
+#: src/ar.c:84
+msgid "Force regeneration of symbol table."
+msgstr "Примусове повторне створення таблиці символів."
+
+#: src/ar.c:85
+msgid "Insert file after [MEMBER]."
+msgstr "Вставити файл після [ЕЛЕМЕНТ]."
+
+#: src/ar.c:86
+msgid "Insert file before [MEMBER]."
+msgstr "Вставити файл перед [ЕЛЕМЕНТ]."
+
+#: src/ar.c:87
+msgid "Same as -b."
+msgstr "Те саме, що і -b."
+
+#: src/ar.c:88
+msgid "Suppress message when library has to be created."
+msgstr "Придушити повідомлення, якщо має бути створено бібліотеку."
+
+#: src/ar.c:90
+msgid "Use full path for file matching."
+msgstr "Використовувати для порівняння повний шлях до файла."
+
+#: src/ar.c:91
+msgid "Update only older files in archive."
+msgstr "Оновлювати у архіві лише старіші файли."
+
+#. Short description of program.
+#: src/ar.c:97
+msgid "Create, modify, and extract from archives."
+msgstr "Створення, зміна архівів і видобування даних з архівів."
+
+#. Strings for arguments in help texts.
+#: src/ar.c:100
+msgid "[MEMBER] [COUNT] ARCHIVE [FILE...]"
+msgstr "[ЕЛЕМЕНТ] [НОМЕР] АРХІВ [ФАЙЛ...]"
+
+#: src/ar.c:179
+#, c-format
+msgid "'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"
+msgstr ""
+"модифікатори «a», «b» і «i» можна використовувати лише разом з параметрами "
+"«m» і «r»"
+
+#: src/ar.c:184
+#, c-format
+msgid "MEMBER parameter required for 'a', 'b', and 'i' modifiers"
+msgstr ""
+"Для модифікаторів «a», «b» та «i» слід використовувати параметр ЕЛЕМЕНТ"
+
+#: src/ar.c:200
+#, c-format
+msgid "'N' is only meaningful with the 'x' and 'd' options"
+msgstr "«N» має значення лише разом з параметрами «x» і «d»"
+
+#: src/ar.c:205
+#, c-format
+msgid "COUNT parameter required"
+msgstr "потрібен параметр НОМЕР"
+
+#: src/ar.c:217
+#, c-format
+msgid "invalid COUNT parameter %s"
+msgstr "некоректний параметр НОМЕР %s"
+
+#: src/ar.c:224
+#, c-format
+msgid "'%c' is only meaningful with the 'x' option"
+msgstr "«%c» має сенс лише у разі використання параметра «x»"
+
+#: src/ar.c:230
+#, c-format
+msgid "archive name required"
+msgstr "слід вказати назву архіву"
+
+#: src/ar.c:243
+#, c-format
+msgid "command option required"
+msgstr "має бути вказано параметр команди"
+
+#: src/ar.c:294
+#, c-format
+msgid "More than one operation specified"
+msgstr "Вказано більше за одну дію"
+
+#: src/ar.c:388
+#, c-format
+msgid "cannot open archive '%s'"
+msgstr "не вдалося відкрити архів «%s»"
+
+#: src/ar.c:398
+#, c-format
+msgid "cannot open archive '%s': %s"
+msgstr "не вдалося відкрити архів «%s»: %s"
+
+#: src/ar.c:402
+#, c-format
+msgid "%s: not an archive file"
+msgstr "%s: не є файлом архіву"
+
+#: src/ar.c:406
+#, c-format
+msgid "cannot stat archive '%s'"
+msgstr "не вдалося отримати дані архіву «%s» за допомогою stat"
+
+#: src/ar.c:418
+#, c-format
+msgid "no entry %s in archive\n"
+msgstr "у архіві немає запису %s\n"
+
+#: src/ar.c:471 src/ar.c:925 src/ar.c:1131
+msgid "cannot create hash table"
+msgstr "не вдалося створити таблицю хешів"
+
+#: src/ar.c:477 src/ar.c:931 src/ar.c:1139
+msgid "cannot insert into hash table"
+msgstr "не вдалося вставити запис до таблиці хешів"
+
+#: src/ar.c:485 src/ranlib.c:147
+#, c-format
+msgid "cannot stat '%s'"
+msgstr "не вдалося отримати дані з «%s» за допомогою stat"
+
+#: src/ar.c:587
+#, c-format
+msgid "cannot read content of %s: %s"
+msgstr "не вдалося прочитати вміст з %s: %s"
+
+#: src/ar.c:630
+#, c-format
+msgid "cannot open %.*s"
+msgstr "не вдалося відкрити %.*s"
+
+#: src/ar.c:652
+#, c-format
+msgid "failed to write %s"
+msgstr "не вдалося записати %s"
+
+#: src/ar.c:664
+#, c-format
+msgid "cannot change mode of %s"
+msgstr "не вдалося змінити права доступу до %s"
+
+#: src/ar.c:680
+#, c-format
+msgid "cannot change modification time of %s"
+msgstr "не вдалося змінити часову мітку зміни %s"
+
+#: src/ar.c:726
+#, c-format
+msgid "cannot rename temporary file to %.*s"
+msgstr "не вдалося перейменувати файл тимчасових даних на %.*s"
+
+#: src/ar.c:762 src/ar.c:1016 src/ar.c:1419 src/ranlib.c:221
+#, c-format
+msgid "cannot create new file"
+msgstr "не вдалося створити файл"
+
+#: src/ar.c:1221
+#, c-format
+msgid "position member %s not found"
+msgstr "не виявлено елемента позиції %s"
+
+#: src/ar.c:1231
+#, c-format
+msgid "%s: no entry %s in archive!\n"
+msgstr "%s: у архіві немає запису %s!\n"
+
+#: src/ar.c:1260 src/objdump.c:240
+#, c-format
+msgid "cannot open %s"
+msgstr "не вдалося відкрити %s"
+
+#: src/ar.c:1265
+#, c-format
+msgid "cannot stat %s"
+msgstr "не вдалося отримати дані %s за допомогою stat"
+
+#: src/ar.c:1271
+#, c-format
+msgid "%s is no regular file"
+msgstr "%s не є звичайним файлом"
+
+#: src/ar.c:1284
+#, c-format
+msgid "cannot get ELF descriptor for %s: %s\n"
+msgstr "не вдалося отримати дескриптор ELF для %s: %s\n"
+
+#: src/ar.c:1304
+#, c-format
+msgid "cannot read %s: %s"
+msgstr "не вдалося прочитати %s: %s"
+
+#: src/ar.c:1479
+#, c-format
+msgid "cannot represent ar_date"
+msgstr "неможливо представити ar_date"
+
+#: src/ar.c:1485
+#, c-format
+msgid "cannot represent ar_uid"
+msgstr "неможливо представити ar_uid"
+
+#: src/ar.c:1491
+#, c-format
+msgid "cannot represent ar_gid"
+msgstr "неможливо представити ar_gid"
+
+#: src/ar.c:1497
+#, c-format
+msgid "cannot represent ar_mode"
+msgstr "неможливо представити ar_mode"
+
+#: src/ar.c:1503
+#, c-format
+msgid "cannot represent ar_size"
+msgstr "неможливо представити ar_size"
+
+#: src/arlib-argp.c:31
+msgid "Use zero for uid, gid, and date in archive members."
+msgstr ""
+"Використовувати нульове значення для uid, gid, та дати у елементах архіву."
+
+#: src/arlib-argp.c:33
+msgid "Use actual uid, gid, and date in archive members."
+msgstr ""
+"Використовувати поточні значення для uid, gid, та дати у елементах архіву."
+
+#: src/arlib-argp.c:62
+#, c-format
+msgid "%s (default)"
+msgstr "%s (типово)"
+
+#. The archive is too big.
+#: src/arlib.c:212
+#, c-format
+msgid "the archive '%s' is too large"
+msgstr "розмір архіву «%s» є занадто великим"
+
+#: src/arlib.c:225
+#, c-format
+msgid "cannot read ELF header of %s(%s): %s"
+msgstr "не вдалося прочитати заголовок ELF з %s(%s): %s"
+
+#: src/elfclassify.c:91
+msgid "opening"
+msgstr ""
+
+#: src/elfclassify.c:98
+msgid "reading"
+msgstr ""
+
+#: src/elfclassify.c:244
+#, fuzzy
+#| msgid "cannot get ELF header"
+msgid "ELF header"
+msgstr "не вдалося отримати заголовок ELF"
+
+#: src/elfclassify.c:255
+#, fuzzy
+#| msgid "Program Headers:"
+msgid "program headers"
+msgstr "Заголовки програми:"
+
+#: src/elfclassify.c:264
+#, fuzzy
+#| msgid "Program Headers:"
+msgid "program header"
+msgstr "Заголовки програми:"
+
+#: src/elfclassify.c:284
+#, fuzzy
+#| msgid "Section Headers:"
+msgid "section headers"
+msgstr "Заголовки розділів:"
+
+#: src/elfclassify.c:295
+#, fuzzy
+#| msgid "cannot get section header string table index"
+msgid "section header string table index"
+msgstr "не вдалося визначити індекс заголовка розділу у таблиці рядків"
+
+#: src/elfclassify.c:309
+#, fuzzy
+#| msgid "cannot get section header"
+msgid "could not obtain section header"
+msgstr "не вдалося отримати заголовок розділу"
+
+#: src/elfclassify.c:315
+#, fuzzy
+#| msgid "cannot get section name"
+msgid "could not obtain section name"
+msgstr "не вдалося отримати назву розділу"
+
+#: src/elfclassify.c:828
+msgid "writing to standard output"
+msgstr ""
+
+#: src/elfclassify.c:855
+msgid "reading from standard input"
+msgstr ""
+
+#: src/elfclassify.c:876
+#, fuzzy
+#| msgid "Input selection options:"
+msgid "Classification options"
+msgstr "Вибір параметрів виведення даних:"
+
+#: src/elfclassify.c:878
+msgid "File looks like an ELF object or archive/static library (default)"
+msgstr ""
+
+#: src/elfclassify.c:881
+msgid "File is an regular ELF object (not an archive/static library)"
+msgstr ""
+
+#: src/elfclassify.c:884
+msgid "File is an ELF archive or static library"
+msgstr ""
+
+#: src/elfclassify.c:887
+msgid "File is an ELF core dump file"
+msgstr ""
+
+#: src/elfclassify.c:890
+msgid ""
+"File is an ELF file with symbol table or .debug_* sections and can be "
+"stripped further"
+msgstr ""
+
+#: src/elfclassify.c:893
+msgid "File is (primarily) an ELF program executable (not primarily a DSO)"
+msgstr ""
+
+#: src/elfclassify.c:896
+msgid "File is an ELF program executable (might also be a DSO)"
+msgstr ""
+
+#: src/elfclassify.c:899
+msgid ""
+"File is (primarily) an ELF shared object (DSO) (not primarily an executable)"
+msgstr ""
+
+#: src/elfclassify.c:902
+msgid "File is an ELF shared object (DSO) (might also be an executable)"
+msgstr ""
+
+#: src/elfclassify.c:906
+#, fuzzy
+#| msgid "cannot find kernel modules"
+msgid "File is a linux kernel module"
+msgstr "не вдалося виявити модулі ядра"
+
+#: src/elfclassify.c:908
+msgid "File is a debug only ELF file (separate .debug, .dwo or dwz multi-file)"
+msgstr ""
+
+#: src/elfclassify.c:911
+msgid "File is a loadable ELF object (program or shared object)"
+msgstr ""
+
+#: src/elfclassify.c:940
+msgid "Input flags"
+msgstr ""
+
+#: src/elfclassify.c:942
+msgid "Only classify regular (not symlink nor special device) files"
+msgstr ""
+
+#: src/elfclassify.c:944
+msgid ""
+"Also read file names to process from standard input, separated by newlines"
+msgstr ""
+
+#: src/elfclassify.c:947
+msgid ""
+"Also read file names to process from standard input, separated by ASCII NUL "
+"bytes"
+msgstr ""
+
+#: src/elfclassify.c:950
+msgid "Do not read files from standard input (default)"
+msgstr ""
+
+#: src/elfclassify.c:952
+msgid "Try to open compressed files or embedded (kernel) ELF images"
+msgstr ""
+
+#: src/elfclassify.c:955
+#, fuzzy
+#| msgid "Output format:"
+msgid "Output flags"
+msgstr "Формат виводу:"
+
+#: src/elfclassify.c:957
+msgid "Output names of files, separated by newline"
+msgstr ""
+
+#: src/elfclassify.c:959
+msgid "Output names of files, separated by ASCII NUL"
+msgstr ""
+
+#: src/elfclassify.c:961
+#, fuzzy
+#| msgid "More than one output file name given."
+msgid "Do not output file names"
+msgstr "Вказано декілька назв файлів виведення даних."
+
+#: src/elfclassify.c:963
+msgid "If printing file names, print matching files (default)"
+msgstr ""
+
+#: src/elfclassify.c:965
+msgid "If printing file names, print files that do not match"
+msgstr ""
+
+#: src/elfclassify.c:967
+msgid "Additional flags"
+msgstr ""
+
+#: src/elfclassify.c:969
+msgid "Output additional information (can be specified multiple times)"
+msgstr ""
+
+#: src/elfclassify.c:971
+msgid "Suppress some error output (counterpart to --verbose)"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: src/elfclassify.c:979 src/elfcompress.c:1436 src/elflint.c:77
+#: src/readelf.c:161
+msgid "FILE..."
+msgstr "ФАЙЛ..."
+
+#: src/elfclassify.c:980
+msgid ""
+"Determine the type of an ELF file.\n"
+"\n"
+"All of the classification options must apply at the same time to a "
+"particular file.  Classification options can be negated using a \"--not-\" "
+"prefix.\n"
+"\n"
+"Since modern ELF does not clearly distinguish between programs and dynamic "
+"shared objects, you should normally use either --executable or --shared to "
+"identify the primary purpose of a file.  Only one of the --shared and --"
+"executable checks can pass for a file.\n"
+"\n"
+"If you want to know whether an ELF object might a program or a shared "
+"library (but could be both), then use --program or --library. Some ELF files "
+"will classify as both a program and a library.\n"
+"\n"
+"If you just want to know whether an ELF file is loadable (as program or "
+"library) use --loadable.  Note that files that only contain (separate) debug "
+"information (--debug-only) are never --loadable (even though they might "
+"contain program headers).  Linux kernel modules are also not --loadable (in "
+"the normal sense).\n"
+"\n"
+"Without any of the --print options, the program exits with status 0 if the "
+"requested checks pass for all input files, with 1 if a check fails for any "
+"file, and 2 if there is an environmental issue (such as a file read error or "
+"a memory allocation error).\n"
+"\n"
+"When printing file names, the program exits with status 0 even if no file "
+"names are printed, and exits with status 2 if there is an environmental "
+"issue.\n"
+"\n"
+"On usage error (e.g. a bad option was given), the program exits with a "
+"status code larger than 2.\n"
+"\n"
+"The --quiet or -q option suppresses some error warning output, but doesn't "
+"change the exit status."
+msgstr ""
+
+#: src/elfcmp.c:59
+msgid "Control options:"
+msgstr "Параметри керування:"
+
+#: src/elfcmp.c:61
+msgid "Output all differences, not just the first"
+msgstr "Показати всі відмінності, не лише першу з них"
+
+#: src/elfcmp.c:62
+msgid ""
+"Control treatment of gaps in loadable segments [ignore|match] (default: "
+"ignore)"
+msgstr ""
+"Керування обробкою проміжків у придатних до завантаження сегментах [ignore|"
+"match] (типово, ignore)"
+
+#: src/elfcmp.c:64
+msgid "Ignore permutation of buckets in SHT_HASH section"
+msgstr "Ігнорувати переставляння блоків у розділі SHT_HASH"
+
+#: src/elfcmp.c:66
+msgid "Ignore differences in build ID"
+msgstr "Ігнорувати відмінності у ідентифікаторі збирання"
+
+#: src/elfcmp.c:67
+msgid "Output nothing; yield exit status only"
+msgstr "Нічого не виводити; визначити лише стан виходу"
+
+#. Short description of program.
+#: src/elfcmp.c:74
+msgid "Compare relevant parts of two ELF files for equality."
+msgstr "Порівнює відповідні частини двох файлів ELF."
+
+#. Strings for arguments in help texts.
+#: src/elfcmp.c:78
+msgid "FILE1 FILE2"
+msgstr "ФАЙЛ1 ФАЙЛ2"
+
+#: src/elfcmp.c:140
+msgid "Invalid number of parameters.\n"
+msgstr "Некоректна кількість параметрів.\n"
+
+#: src/elfcmp.c:171 src/elfcmp.c:176
+#, c-format
+msgid "cannot get ELF header of '%s': %s"
+msgstr "не вдалося отримати заголовок ELF «%s»: %s"
+
+#: src/elfcmp.c:202
+#, c-format
+msgid "%s %s diff: ELF header"
+msgstr "%s %s diff: заголовок ELF"
+
+#: src/elfcmp.c:209 src/elfcmp.c:212
+#, c-format
+msgid "cannot get section count of '%s': %s"
+msgstr "не вдалося отримати даних щодо кількості розділів «%s»: %s"
+
+#: src/elfcmp.c:217
+#, c-format
+msgid "%s %s diff: section count"
+msgstr "%s %s diff: кількість розділів"
+
+#: src/elfcmp.c:224 src/elfcmp.c:227
+#, c-format
+msgid "cannot get program header count of '%s': %s"
+msgstr ""
+"не вдалося отримати даних щодо кількості заголовків програми у «%s»: %s"
+
+#: src/elfcmp.c:232
+#, c-format
+msgid "%s %s diff: program header count"
+msgstr "%s %s diff: кількість заголовків програми"
+
+#: src/elfcmp.c:240 src/elfcmp.c:243
+#, c-format
+msgid "cannot get hdrstrndx of '%s': %s"
+msgstr "не вдалося отримати hdrstrndx «%s»: %s"
+
+#: src/elfcmp.c:248
+#, c-format
+msgid "%s %s diff: shdr string index"
+msgstr "різниця між %s і %s: індекс рядків shdr"
+
+#: src/elfcmp.c:306
+#, c-format
+msgid "%s %s differ: section [%zu], [%zu] name"
+msgstr "%s %s diff: розділ [%zu], назва [%zu]"
+
+#: src/elfcmp.c:329
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' header"
+msgstr "%s %s diff: розділ [%zu] заголовок «%s»"
+
+#: src/elfcmp.c:337 src/elfcmp.c:343
+#, c-format
+msgid "cannot get content of section %zu in '%s': %s"
+msgstr "не вдалося отримати вміст розділу %zu у «%s»: %s"
+
+#: src/elfcmp.c:352
+#, c-format
+msgid "symbol table [%zu] in '%s' has zero sh_entsize"
+msgstr "таблиця символів [%zu] у «%s» містить нульове значення sh_entsize"
+
+#: src/elfcmp.c:364 src/elfcmp.c:370
+#, c-format
+msgid "cannot get symbol in '%s': %s"
+msgstr "не вдалося отримати символ у «%s»: %s"
+
+#: src/elfcmp.c:392
+#, c-format
+msgid "%s %s differ: symbol table [%zu]"
+msgstr "%s %s diff: таблиця символів [%zu]"
+
+#: src/elfcmp.c:395
+#, c-format
+msgid "%s %s differ: symbol table [%zu,%zu]"
+msgstr "%s %s diff: таблиця символів [%zu,%zu]"
+
+#: src/elfcmp.c:442 src/elfcmp.c:512
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' number of notes"
+msgstr "%s %s diff: розділ [%zu] кількість нотаток «%s»"
+
+#: src/elfcmp.c:450
+#, c-format
+msgid "cannot read note section [%zu] '%s' in '%s': %s"
+msgstr "не вдалося прочитати розділ нотаток [%zu] «%s» у «%s»: %s"
+
+#: src/elfcmp.c:461
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note name"
+msgstr "%s %s diff: розділ [%zu] назва нотатки «%s»"
+
+#: src/elfcmp.c:469
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' type"
+msgstr "%s %s diff: розділ [%zu] нотатка «%s» тип «%s»"
+
+#: src/elfcmp.c:484
+#, c-format
+msgid "%s %s differ: build ID length"
+msgstr "%s %s diff: довжина ідентифікатора збирання"
+
+#: src/elfcmp.c:492
+#, c-format
+msgid "%s %s differ: build ID content"
+msgstr "%s %s diff: вміст ідентифікатора збирання"
+
+#: src/elfcmp.c:501
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' note '%s' content"
+msgstr "%s %s diff: розділ [%zu] нотатка «%s» вміст «%s»"
+
+#: src/elfcmp.c:542
+#, c-format
+msgid "%s %s differ: section [%zu] '%s' content"
+msgstr "%s %s diff: розділ [%zu] «%s», вміст"
+
+#: src/elfcmp.c:546
+#, c-format
+msgid "%s %s differ: section [%zu,%zu] '%s' content"
+msgstr "%s %s diff: розділ [%zu,%zu] «%s», вміст"
+
+#: src/elfcmp.c:561
+#, c-format
+msgid "%s %s differ: unequal amount of important sections"
+msgstr "%s %s diff: невідповідність об’ємів важливих розділів"
+
+#: src/elfcmp.c:594 src/elfcmp.c:599
+#, c-format
+msgid "cannot load data of '%s': %s"
+msgstr "не вдалося завантажити дані «%s»: %s"
+
+#: src/elfcmp.c:618 src/elfcmp.c:624
+#, c-format
+msgid "cannot get program header entry %d of '%s': %s"
+msgstr "не вдалося отримати запис заголовка програми %d «%s»: %s"
+
+#: src/elfcmp.c:630
+#, c-format
+msgid "%s %s differ: program header %d"
+msgstr "%s %s diff: заголовок програми %d"
+
+#: src/elfcmp.c:654
+#, c-format
+msgid "%s %s differ: gap"
+msgstr "%s %s diff: проміжок"
+
+#: src/elfcmp.c:705
+#, c-format
+msgid "Invalid value '%s' for --gaps parameter."
+msgstr "Некоректне значення «%s» параметра --gaps."
+
+#: src/elfcmp.c:733 src/findtextrel.c:194 src/nm.c:363 src/ranlib.c:140
+#: src/size.c:271 src/strings.c:184 src/strip.c:1040 src/strip.c:1077
+#: src/unstrip.c:2245 src/unstrip.c:2274
+#, c-format
+msgid "cannot open '%s'"
+msgstr "не вдалося відкрити «%s»"
+
+#: src/elfcmp.c:737 src/findtextrel.c:213 src/ranlib.c:157
+#, c-format
+msgid "cannot create ELF descriptor for '%s': %s"
+msgstr "не вдалося створити дескриптор ELF для «%s»: %s"
+
+#: src/elfcmp.c:742
+#, c-format
+msgid "cannot create EBL descriptor for '%s'"
+msgstr "не вдалося створити дескриптор EBL для «%s»"
+
+#: src/elfcmp.c:760 src/findtextrel.c:384
+#, c-format
+msgid "cannot get section header of section %zu: %s"
+msgstr "не вдалося отримати заголовок розділу %zu: %s"
+
+#: src/elfcmp.c:770
+#, c-format
+msgid "cannot get content of section %zu: %s"
+msgstr "не вдалося отримати вміст розділу %zu: %s"
+
+#: src/elfcmp.c:780 src/elfcmp.c:794
+#, c-format
+msgid "cannot get relocation: %s"
+msgstr "не вдалося отримати пересування: %s"
+
+#: src/elfcompress.c:128 src/strip.c:305 src/unstrip.c:116
+#, c-format
+msgid "-o option specified twice"
+msgstr "параметр -o вказано двічі"
+
+#: src/elfcompress.c:135
+#, c-format
+msgid "-t option specified twice"
+msgstr "параметр -t вказано двічі"
+
+#: src/elfcompress.c:147
+#, c-format
+msgid "ZSTD support is not enabled"
+msgstr ""
+
+#: src/elfcompress.c:150
+#, c-format
+msgid "unknown compression type '%s'"
+msgstr "невідомий тип стиснення «%s»"
+
+#. We need at least one input file.
+#: src/elfcompress.c:162 src/elfcompress.c:1447
+#, c-format
+msgid "No input file given"
+msgstr "Не надано файла вхідних даних"
+
+#: src/elfcompress.c:168 src/elfcompress.c:1451
+#, c-format
+msgid "Only one input file allowed together with '-o'"
+msgstr "З параметром «-o» можна використовувати лише один файл вхідних даних"
+
+#: src/elfcompress.c:1408
+msgid "Place (de)compressed output into FILE"
+msgstr "Помістити результати розпакування або стискання до ФАЙЛа"
+
+#: src/elfcompress.c:1411
+#, fuzzy
+#| msgid ""
+#| "What type of compression to apply. TYPE can be 'none' (decompress), "
+#| "'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias) or "
+#| "'zlib-gnu' (.zdebug GNU style compression, 'gnu' is an alias)"
+msgid ""
+"What type of compression to apply. TYPE can be 'none' (decompress), "
+"'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), 'zlib-"
+"gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD "
+"compression)"
+msgstr ""
+"Визначає тип стискання, який слід застосувати. ТИПом може бути "
+"«none» (розпакувати), «zlib» (стискання ELF ZLIB, типовий варіант, інша "
+"назва — «zlib-gabi») або «zlib-gnu» (стискання у стилі GNU .zdebug, інша "
+"назва — «gnu»)"
+
+#: src/elfcompress.c:1415
+msgid ""
+"SECTION name to (de)compress, SECTION is an extended wildcard pattern "
+"(defaults to '.?(z)debug*')"
+msgstr ""
+"назва РОЗДІЛу для розпакування або стискання, РОЗДІЛ є розширеним взірцем із "
+"замінниками (типове значення -- «.?(z)debug*»)"
+
+#: src/elfcompress.c:1418
+msgid "Print a message for each section being (de)compressed"
+msgstr ""
+"Вивести повідомлення для кожного розділу, який розпаковується чи стискається"
+
+#: src/elfcompress.c:1421
+msgid ""
+"Force compression of section even if it would become larger or update/"
+"rewrite the file even if no section would be (de)compressed"
+msgstr ""
+"Примусове стискання розділу, навіть якщо він стане більшим, або оновлення чи "
+"перезапис файла, навіть якщо жодного розділу не буде розпаковано або стиснено"
+
+#: src/elfcompress.c:1424 src/strip.c:92
+msgid "Relax a few rules to handle slightly broken ELF files"
+msgstr ""
+"Знехтувати декількома правилами для обробки трохи пошкоджених файлів ELF"
+
+#: src/elfcompress.c:1427
+msgid "Be silent when a section cannot be compressed"
+msgstr "Не сповіщати, якщо розділ неможливо стиснути"
+
+#: src/elfcompress.c:1437
+msgid "Compress or decompress sections in an ELF file."
+msgstr "Стиснути або розпакувати розділи у файлі ELF."
+
+#: src/elflint.c:63
+msgid "Be extremely strict, flag level 2 features."
+msgstr "Висока строгість, увімкнути можливості рівня 2."
+
+#: src/elflint.c:64
+msgid "Do not print anything if successful"
+msgstr "Не виводити ніяких даних у разі успіху"
+
+#: src/elflint.c:65
+msgid "Binary is a separate debuginfo file"
+msgstr "Бінарний файл є окремим файлом debuginfo"
+
+#: src/elflint.c:67
+msgid ""
+"Binary has been created with GNU ld and is therefore known to be broken in "
+"certain ways"
+msgstr ""
+"Бінарний файл було створено за допомогою GNU ld, тому він, очевидно, є до "
+"певної міри неправильним"
+
+#. Short description of program.
+#: src/elflint.c:73
+msgid "Pedantic checking of ELF files compliance with gABI/psABI spec."
+msgstr ""
+"Педантична перевірка файлів ELF на сумісність зі специфікаціями gABI/psABI."
+
+#: src/elflint.c:154 src/readelf.c:413
+#, c-format
+msgid "cannot open input file '%s'"
+msgstr "не вдалося відкрити вхідний файл «%s»"
+
+#: src/elflint.c:161
+#, c-format
+msgid "cannot generate Elf descriptor for '%s': %s\n"
+msgstr "не вдалося створити дескриптор Elf для «%s»: %s\n"
+
+#: src/elflint.c:180
+#, c-format
+msgid "error while closing Elf descriptor: %s\n"
+msgstr "помилка під час спроби закриття дескриптора Elf: %s\n"
+
+#: src/elflint.c:184
+msgid "No errors"
+msgstr "Без помилок"
+
+#: src/elflint.c:219 src/readelf.c:625
+msgid "Missing file name.\n"
+msgstr "Не вказано назви файла.\n"
+
+#: src/elflint.c:284
+#, c-format
+msgid " error while freeing sub-ELF descriptor: %s\n"
+msgstr " помилка під час спроби вивільнення дескриптора суб-ELF: %s\n"
+
+#. We cannot do anything.
+#: src/elflint.c:292
+#, c-format
+msgid "Not an ELF file - it has the wrong magic bytes at the start\n"
+msgstr "Не є файлом ELF. Виявлено помилкові магічні байти на початку файла\n"
+
+#: src/elflint.c:358
+#, c-format
+msgid "e_ident[%d] == %d is no known class\n"
+msgstr "e_ident[%d] == %d не є відомим класом\n"
+
+#: src/elflint.c:363
+#, c-format
+msgid "e_ident[%d] == %d is no known data encoding\n"
+msgstr "e_ident[%d] == %d не є відомим кодуванням даних\n"
+
+#: src/elflint.c:367
+#, c-format
+msgid "unknown ELF header version number e_ident[%d] == %d\n"
+msgstr "невідомий номер версії заголовка ELF e_ident[%d] == %d\n"
+
+#: src/elflint.c:375
+#, c-format
+msgid "unsupported OS ABI e_ident[%d] == '%s'\n"
+msgstr "непідтримуване ABI ОС e_ident[%d] == «%s»\n"
+
+#: src/elflint.c:381
+#, c-format
+msgid "unsupported ABI version e_ident[%d] == %d\n"
+msgstr "непідтримувана версія ABI e_ident[%d] == %d\n"
+
+#: src/elflint.c:386
+#, c-format
+msgid "e_ident[%zu] is not zero\n"
+msgstr "e_ident[%zu] не дорівнює нулеві\n"
+
+#: src/elflint.c:391
+#, c-format
+msgid "unknown object file type %d\n"
+msgstr "невідомий тип об’єктних файлів %d\n"
+
+#: src/elflint.c:398
+#, c-format
+msgid "unknown machine type %d\n"
+msgstr "невідомий тип архітектури %d\n"
+
+#: src/elflint.c:402
+#, c-format
+msgid "unknown object file version\n"
+msgstr "невідома версія об’єктних файлів\n"
+
+#: src/elflint.c:408
+#, c-format
+msgid "invalid program header offset\n"
+msgstr "некоректне зміщення заголовка програми\n"
+
+#: src/elflint.c:410
+#, c-format
+msgid "executables and DSOs cannot have zero program header offset\n"
+msgstr ""
+"виконувані файли і DSO не можуть містити заголовка програми з нульовим "
+"зміщенням\n"
+
+#: src/elflint.c:414
+#, c-format
+msgid "invalid number of program header entries\n"
+msgstr "некоректна кількість записів заголовків програми\n"
+
+#: src/elflint.c:422
+#, c-format
+msgid "invalid section header table offset\n"
+msgstr "некоректне зміщення таблиці заголовків розділів\n"
+
+#: src/elflint.c:425
+#, c-format
+msgid "section header table must be present\n"
+msgstr "має бути вказано таблицю заголовків розділів\n"
+
+#: src/elflint.c:439
+#, c-format
+msgid "invalid number of section header table entries\n"
+msgstr "некоректна кількість записів таблиці заголовків розділів\n"
+
+#: src/elflint.c:456
+#, c-format
+msgid "invalid section header index\n"
+msgstr "некоректний індекс заголовка розділу\n"
+
+#: src/elflint.c:474
+#, c-format
+msgid "Can only check %u headers, shnum was %u\n"
+msgstr "Можна перевірити лише %u заголовків, значенням же shnum було %u\n"
+
+#: src/elflint.c:488
+#, c-format
+msgid "invalid number of program header table entries\n"
+msgstr "некоректна кількість записів таблиці заголовків програми\n"
+
+#: src/elflint.c:505
+#, c-format
+msgid "Can only check %u headers, phnum was %u\n"
+msgstr "Можна перевірити лише %u заголовків, значенням же phnum було %u\n"
+
+#: src/elflint.c:510
+#, c-format
+msgid "invalid machine flags: %s\n"
+msgstr "некоректні прапорці архітектури: %s\n"
+
+#: src/elflint.c:517 src/elflint.c:534
+#, c-format
+msgid "invalid ELF header size: %hd\n"
+msgstr "некоректний розмір заголовка ELF: %hd\n"
+
+#: src/elflint.c:520 src/elflint.c:537
+#, c-format
+msgid "invalid program header size: %hd\n"
+msgstr "некоректний розмір заголовка програми: %hd\n"
+
+#: src/elflint.c:523 src/elflint.c:540
+#, c-format
+msgid "invalid program header position or size\n"
+msgstr "некоректне розташування або розмір заголовка програми\n"
+
+#: src/elflint.c:526 src/elflint.c:543
+#, c-format
+msgid "invalid section header size: %hd\n"
+msgstr "некоректний розмір заголовка розділу: %hd\n"
+
+#: src/elflint.c:529 src/elflint.c:546
+#, c-format
+msgid "invalid section header position or size\n"
+msgstr "некоректне розташування або розмір заголовка розділу\n"
+
+#: src/elflint.c:591
+#, c-format
+msgid ""
+"section [%2d] '%s': section with SHF_GROUP flag set not part of a section "
+"group\n"
+msgstr ""
+"розділ [%2d] «%s»: розділ з встановленим прапорцем SHF_GROUP не є частиною "
+"групи розділів\n"
+
+#: src/elflint.c:595
+#, c-format
+msgid ""
+"section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"
+msgstr ""
+"розділ [%2d] «%s»: групу розділів [%2zu] «%s» мало бути визначено до розділу-"
+"елемента цієї групи\n"
+
+#: src/elflint.c:611 src/elflint.c:1509 src/elflint.c:1560 src/elflint.c:1610
+#: src/elflint.c:1692 src/elflint.c:2029 src/elflint.c:2355 src/elflint.c:2981
+#: src/elflint.c:3144 src/elflint.c:3292 src/elflint.c:3494 src/elflint.c:4511
+#, c-format
+msgid "section [%2d] '%s': cannot get section data\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати дані розділу\n"
+
+#: src/elflint.c:624 src/elflint.c:1699
+#, c-format
+msgid ""
+"section [%2d] '%s': referenced as string table for section [%2d] '%s' but "
+"type is not SHT_STRTAB\n"
+msgstr ""
+"розділ [%2d] «%s»: надано посилання на таблицю рядків розділу [%2d] «%s», "
+"але типом даних не є SHT_STRTAB\n"
+
+#: src/elflint.c:647
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol table cannot have more than one extended index "
+"section\n"
+msgstr ""
+"розділ [%2d] «%s»: у таблиці символів не може бути більше одного розширеного "
+"розділу покажчика\n"
+
+#: src/elflint.c:659
+#, c-format
+msgid "section [%2u] '%s': entry size is does not match ElfXX_Sym\n"
+msgstr "розділ [%2u] «%s»: розмірність запису не відповідає ElfXX_Sym\n"
+
+#: src/elflint.c:663
+#, c-format
+msgid ""
+"section [%2u] '%s': number of local entries in 'st_info' larger than table "
+"size\n"
+msgstr ""
+"розділ [%2u] «%s»: кількість локальних записів у «st_info» перевищує розмір "
+"таблиці\n"
+
+#: src/elflint.c:672
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %d: %s\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати символ %d: %s\n"
+
+#: src/elflint.c:677 src/elflint.c:680 src/elflint.c:683 src/elflint.c:686
+#: src/elflint.c:689 src/elflint.c:692
+#, c-format
+msgid "section [%2d] '%s': '%s' in zeroth entry not zero\n"
+msgstr "розділ [%2d] «%s»: «%s» у нульовому записі не є нулем\n"
+
+#: src/elflint.c:695
+#, c-format
+msgid "section [%2d] '%s': XINDEX for zeroth entry not zero\n"
+msgstr "розділ [%2d] «%s»: XINDEX для нульового запису не є нулем\n"
+
+#: src/elflint.c:705
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol %zu: %s\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати символ %zu: %s\n"
+
+#: src/elflint.c:714
+#, c-format
+msgid "section [%2d] '%s': symbol %zu: invalid name value\n"
+msgstr "розділ [%2d] «%s»: символ %zu: некоректне значення назви\n"
+
+#: src/elflint.c:729
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): too large section index but no extended "
+"section index section\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: занадто великий покажчик розділу за умови, що "
+"не визначено розділу розширеного покажчика розділів\n"
+
+#: src/elflint.c:735
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit "
+"in st_shndx (%<PRIu32>)\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: XINDEX використано для індексування, яке не "
+"відповідає st_shndx (%<PRIu32>)\n"
+
+#. || sym->st_shndx > SHN_HIRESERVE  always false
+#: src/elflint.c:747
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): invalid section index\n"
+msgstr "розділ [%2d] «%s»: символ %zu: некоректний індекс розділу\n"
+
+#: src/elflint.c:755
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown type\n"
+msgstr "розділ [%2d] «%s»: символ %zu: невідомий тип\n"
+
+#: src/elflint.c:761
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"
+msgstr "розділ [%2d] «%s»: символ %zu: невідома прив’язка символу\n"
+
+#: src/elflint.c:766
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: унікальний символ, що не належить до типу "
+"об’єктів\n"
+
+#: src/elflint.c:774
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable "
+"files\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: COMMON можна використовувати лише у файлах, "
+"придатних до пересування\n"
+
+#: src/elflint.c:778
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: використання локальних символів COMMON "
+"позбавлене сенсу\n"
+
+#: src/elflint.c:782
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: використання функції у розділі COMMON "
+"позбавлене сенсу\n"
+
+#: src/elflint.c:833
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: значення st_value поза можливим діапазоном\n"
+
+#: src/elflint.c:839 src/elflint.c:864 src/elflint.c:913
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu не повністю відповідає розділу, на який "
+"посилається, [%2d] «%s»\n"
+
+#: src/elflint.c:848
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not "
+"have SHF_TLS flag set\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: для розділу посилання [%2d] «%s» не "
+"встановлено прапорець SHF_TLS\n"
+
+#: src/elflint.c:858 src/elflint.c:906
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced "
+"section [%2d] '%s'\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: значення st_value поза межами розділу "
+"посилання, [%2d] «%s»\n"
+
+#: src/elflint.c:885
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header "
+"entry\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: символ TLS без запису заголовка програми TLS\n"
+
+#: src/elflint.c:891
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program "
+"header entry\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: маємо символ TLS, але не вдалося отримати "
+"запис заголовка програми TLS\n"
+
+#: src/elflint.c:899
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): st_value short of referenced section "
+"[%2d] '%s'\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: значення st_value перед розділом посилання, "
+"[%2d] «%s»\n"
+
+#: src/elflint.c:926
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): local symbol outside range described in "
+"sh_info\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: у sh_info описано локальний символ поза "
+"діапазоном\n"
+
+#: src/elflint.c:933
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): non-local symbol outside range "
+"described in sh_info\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: у sh_info описано нелокальний символ поза "
+"діапазоном\n"
+
+#: src/elflint.c:940
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"
+msgstr "розділ [%2d] «%s»: символ %zu: нелокальний символ розділу\n"
+
+#: src/elflint.c:990
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to bad section "
+"[%2d]\n"
+msgstr ""
+"розділ [%2d] «%s»: символ _GLOBAL_OFFSET_TABLE_  посилається на помилковий "
+"розділ, [%2d]\n"
+
+#: src/elflint.c:997
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to section [%2d] "
+"'%s'\n"
+msgstr ""
+"розділ [%2d] «%s»: символ _GLOBAL_OFFSET_TABLE_  посилається на розділ [%2d] "
+"'%s'\n"
+
+#. This test is more strict than the psABIs which
+#. usually allow the symbol to be in the middle of
+#. the .got section, allowing negative offsets.
+#: src/elflint.c:1013
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#<PRIx64> does not "
+"match %s section address %#<PRIx64>\n"
+msgstr ""
+"розділ [%2d] «%s»: значення символу _GLOBAL_OFFSET_TABLE_ %#<PRIx64> не "
+"відповідає адресі розділу %s %#<PRIx64>\n"
+
+#: src/elflint.c:1020
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %<PRIu64> does not "
+"match %s section size %<PRIu64>\n"
+msgstr ""
+"розділ [%2d] «%s»: розмір символу _GLOBAL_OFFSET_TABLE_ %<PRIu64> не "
+"відповідає розміру розділу %s %<PRIu64>\n"
+
+#: src/elflint.c:1028
+#, c-format
+msgid ""
+"section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got "
+"section\n"
+msgstr ""
+"розділ [%2d] «%s»: виявлено символ _GLOBAL_OFFSET_TABLE_, але не виявлено "
+"розділу .got\n"
+
+#: src/elflint.c:1044
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC_ symbol value %#<PRIx64> does not match dynamic "
+"segment address %#<PRIx64>\n"
+msgstr ""
+"розділ [%2d] «%s»: значення символу _DYNAMIC_ %#<PRIx64> не відповідає "
+"адресі динамічного сегмента %#<PRIx64>\n"
+
+#: src/elflint.c:1051
+#, c-format
+msgid ""
+"section [%2d] '%s': _DYNAMIC symbol size %<PRIu64> does not match dynamic "
+"segment size %<PRIu64>\n"
+msgstr ""
+"розділ [%2d] «%s»: розмір символу _DYNAMIC %<PRIu64> не відповідає розміру "
+"динамічного сегмента %<PRIu64>\n"
+
+#: src/elflint.c:1064
+#, fuzzy, c-format
+msgid ""
+"section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-"
+"default visibility\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %zu: символ у динамічній таблиці символів з "
+"нетиповою видимістю\n"
+
+#: src/elflint.c:1068
+#, fuzzy, c-format
+msgid "section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"
+msgstr "розділ [%2d] «%s»: символ %zu: невідомий набір бітів у st_other\n"
+
+#: src/elflint.c:1106
+#, c-format
+msgid "section [%2d] '%s': cannot get section data.\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати дані розділу.\n"
+
+#: src/elflint.c:1122
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"
+msgstr "розділ [%2d] «%s»: для цього розділу RELA використано DT_RELCOUNT\n"
+
+#: src/elflint.c:1133 src/elflint.c:1186
+#, c-format
+msgid "section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"
+msgstr ""
+"розділ [%2d] «%s»: значення DT_RELCOUNT %d є занадто високим для цього "
+"розділу\n"
+
+#: src/elflint.c:1158 src/elflint.c:1211
+#, c-format
+msgid ""
+"section [%2d] '%s': relative relocations after index %d as specified by "
+"DT_RELCOUNT\n"
+msgstr ""
+"розділ [%2d] «%s»: відносні пересування після позиції %d, вказаної за "
+"допомогою DT_RELCOUNT\n"
+
+#: src/elflint.c:1164 src/elflint.c:1217
+#, c-format
+msgid ""
+"section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT "
+"specified %d relative relocations\n"
+msgstr ""
+"розділ [%2d] «%s»: безвідносне пересування на позиції %zu; DT_RELCOUNT "
+"визначено %d відносних пересування\n"
+
+#: src/elflint.c:1176
+#, c-format
+msgid "section [%2d] '%s': DT_RELACOUNT used for this REL section\n"
+msgstr "розділ [%2d] «%s»: для цього розділу REL використано DT_RELACOUNT\n"
+
+#: src/elflint.c:1259
+#, c-format
+msgid "section [%2d] '%s': invalid destination section index\n"
+msgstr "розділ [%2d] «%s»: некоректний індекс розділу призначення\n"
+
+#: src/elflint.c:1271
+#, c-format
+msgid "section [%2d] '%s': invalid destination section type\n"
+msgstr "розділ [%2d] «%s»: некоректний тип розділу призначення\n"
+
+#: src/elflint.c:1279
+#, c-format
+msgid "section [%2d] '%s': sh_info should be zero\n"
+msgstr "розділ [%2d] «%s»: sh_info має бути нульовим\n"
+
+#: src/elflint.c:1287
+#, c-format
+msgid ""
+"section [%2d] '%s': no relocations for merge-able string sections possible\n"
+msgstr ""
+"розділ [%2d] «%s»: неможливі пересування для розділів рядків, які непридатні "
+"до об'єднання\n"
+
+#: src/elflint.c:1365
+#, c-format
+msgid "text relocation flag set but there is no read-only segment\n"
+msgstr ""
+"встановлено прапорець пересування тексту, але сегмент придатний лише до "
+"читання\n"
+
+#: src/elflint.c:1392
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid type\n"
+msgstr "розділ [%2d] «%s»: пересування %zu: некоректний тип\n"
+
+#: src/elflint.c:1400
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: relocation type invalid for the file "
+"type\n"
+msgstr ""
+"розділ [%2d] «%s»: пересування %zu: некоректний тип пересування для типу "
+"файла\n"
+
+#: src/elflint.c:1408
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: invalid symbol index\n"
+msgstr "розділ [%2d] «%s»: пересування %zu: некоректний індекс символу\n"
+
+#: src/elflint.c:1426
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can "
+"be used with %s\n"
+msgstr ""
+"розділ [%2d] «%s»: пересування %zu: з %s можна використовувати лише символ "
+"«_GLOBAL_OFFSET_TABLE_»\n"
+
+#: src/elflint.c:1443
+#, c-format
+msgid "section [%2d] '%s': relocation %zu: offset out of bounds\n"
+msgstr "розділ [%2d] «%s»: пересування %zu: зміщення за межі діапазону\n"
+
+#: src/elflint.c:1458
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: copy relocation against symbol of type "
+"%s\n"
+msgstr ""
+"розділ [%2d] «%s»: пересування %zu: пересування копіювання для символу типу "
+"%s\n"
+
+#: src/elflint.c:1479
+#, c-format
+msgid ""
+"section [%2d] '%s': relocation %zu: read-only section modified but text "
+"relocation flag not set\n"
+msgstr ""
+"розділ [%2d] «%s»: пересування %zu: змінено придатний лише для читання "
+"розділ, але не встановлено прапорець пересування тексту\n"
+
+#: src/elflint.c:1494
+#, c-format
+msgid "section [%2d] '%s': relocations are against loaded and unloaded data\n"
+msgstr "розділ [%2d] «%s»: пересування завантажених і незавантажених даних\n"
+
+#: src/elflint.c:1534 src/elflint.c:1585
+#, c-format
+msgid "section [%2d] '%s': cannot get relocation %zu: %s\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати зміщення %zu: %s\n"
+
+#: src/elflint.c:1687
+#, c-format
+msgid "more than one dynamic section present\n"
+msgstr "вказано більше одного динамічного розділу\n"
+
+#: src/elflint.c:1705
+#, c-format
+msgid ""
+"section [%2d]: referenced as string table for section [%2d] '%s' but section "
+"link value is invalid\n"
+msgstr ""
+"розділ [%2d]: надано посилання на таблицю рядків розділу [%2d] «%s», але "
+"значення посилання на розділ є некоректним\n"
+
+#: src/elflint.c:1713
+#, c-format
+msgid "section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"
+msgstr ""
+"розділ [%2d] «%s»: розмірність запису розділу не відповідає ElfXX_Dyn\n"
+
+#: src/elflint.c:1718 src/elflint.c:2008
+#, c-format
+msgid "section [%2d] '%s': sh_info not zero\n"
+msgstr "розділ [%2d] «%s»: sh_info не є нульовим\n"
+
+#: src/elflint.c:1728
+#, c-format
+msgid "section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"
+msgstr ""
+"розділ [%2d] «%s»: не вдалося отримати запис динамічного розділу %zu: %s\n"
+
+#: src/elflint.c:1736
+#, c-format
+msgid "section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"
+msgstr ""
+"розділ [%2d] «%s»: за записом DT_NULL вказано записи, що не належать до "
+"DT_NULL\n"
+
+#: src/elflint.c:1743
+#, c-format
+msgid "section [%2d] '%s': entry %zu: unknown tag\n"
+msgstr "розділ [%2d] «%s»: запис %zu: невідома мітка\n"
+
+#: src/elflint.c:1754
+#, c-format
+msgid "section [%2d] '%s': entry %zu: more than one entry with tag %s\n"
+msgstr "розділ [%2d] «%s»: запис %zu: декілька записів з міткою %s\n"
+
+#: src/elflint.c:1764
+#, c-format
+msgid "section [%2d] '%s': entry %zu: level 2 tag %s used\n"
+msgstr "розділ [%2d] «%s»: запис %zu: використано мітку рівня 2 %s\n"
+
+#: src/elflint.c:1782
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %zu: значенням DT_PLTREL має бути DT_REL або "
+"DT_RELA\n"
+
+#: src/elflint.c:1795
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: pointer does not match address of section "
+"[%2d] '%s' referenced by sh_link\n"
+msgstr ""
+"розділ [%2d] «%s»: розділ %zu: вказівник не відповідає адресі розділу [%2d] "
+"«%s», на яку посилається sh_link\n"
+
+#: src/elflint.c:1839
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %zu: значення %s має вказувати на завантажений "
+"сегмент\n"
+
+#: src/elflint.c:1854
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %zu: %s value must be valid offset in section "
+"[%2d] '%s'\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %zu: значенням %s має бути коректне зміщення у "
+"розділі [%2d] «%s»\n"
+
+#: src/elflint.c:1874 src/elflint.c:1902
+#, c-format
+msgid "section [%2d] '%s': contains %s entry but not %s\n"
+msgstr "розділ [%2d] «%s»: містить запис %s, але не %s\n"
+
+#: src/elflint.c:1886
+#, c-format
+msgid "section [%2d] '%s': mandatory tag %s not present\n"
+msgstr "розділ [%2d] «%s»: немає обов’язкової мітки %s\n"
+
+#: src/elflint.c:1895
+#, c-format
+msgid "section [%2d] '%s': no hash section present\n"
+msgstr "розділ [%2d] «%s»: не виявлено розділу хешів\n"
+
+#: src/elflint.c:1910 src/elflint.c:1917
+#, c-format
+msgid "section [%2d] '%s': not all of %s, %s, and %s are present\n"
+msgstr "розділ [%2d] «%s»: вказано не всі зі значень %s, %s і %s\n"
+
+#: src/elflint.c:1927 src/elflint.c:1931
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"
+msgstr ""
+"розділ [%2d] «%s»: у DSO, позначеному на кроці попереднього компонування, "
+"немає мітки %s\n"
+
+#: src/elflint.c:1937
+#, c-format
+msgid "section [%2d] '%s': non-DSO file marked as dependency during prelink\n"
+msgstr ""
+"розділ [%2d] «%s»: під час попереднього компонування як залежність позначено "
+"файл, який не є файлом DSO\n"
+
+#: src/elflint.c:1948 src/elflint.c:1952 src/elflint.c:1956 src/elflint.c:1960
+#, c-format
+msgid "section [%2d] '%s': %s tag missing in prelinked executable\n"
+msgstr ""
+"розділ [%2d] «%s»: у попередньо скомпонованому виконуваному файлі не "
+"міститься мітки %s\n"
+
+#: src/elflint.c:1972
+#, c-format
+msgid ""
+"section [%2d] '%s': only relocatable files can have extended section index\n"
+msgstr ""
+"розділ [%2d] «%s»: розширений розділ покажчика можуть мати лише файли, "
+"придатні до пересування\n"
+
+#: src/elflint.c:1982
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index section not for symbol table\n"
+msgstr ""
+"розділ [%2d] «%s»: розділ розширеного покажчика розділів не призначено для "
+"таблиць символів\n"
+
+#: src/elflint.c:1986
+#, c-format
+msgid "section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"
+msgstr ""
+"розділ [%2d] «%s»: індекс розширеного розділу sh_link [%2d] є некоректним\n"
+
+#: src/elflint.c:1991
+#, c-format
+msgid "cannot get data for symbol section\n"
+msgstr "не вдалося отримати дані для розділу символів\n"
+
+#: src/elflint.c:1994
+#, c-format
+msgid "section [%2d] '%s': entry size does not match Elf32_Word\n"
+msgstr "розділ [%2d] «%s»: розмірність запису не відповідає Elf32_Word\n"
+
+#: src/elflint.c:2003
+#, c-format
+msgid "section [%2d] '%s': extended index table too small for symbol table\n"
+msgstr ""
+"розділ [%2d] «%s»: розширена таблиця покажчика замала для таблиці символів\n"
+
+#: src/elflint.c:2018
+#, c-format
+msgid ""
+"section [%2d] '%s': extended section index in section [%2zu] '%s' refers to "
+"same symbol table\n"
+msgstr ""
+"розділ [%2d] «%s»: розширений покажчик розділів у розділі [%2zu] «%s» "
+"посилається на ту саму таблицю розділів\n"
+
+#: src/elflint.c:2036
+#, c-format
+msgid "symbol 0 should have zero extended section index\n"
+msgstr "символу 0 має відповідати нульовий індекс розширеного розділу\n"
+
+#: src/elflint.c:2048
+#, c-format
+msgid "cannot get data for symbol %zu\n"
+msgstr "не вдалося отримати дані для символу %zu\n"
+
+#: src/elflint.c:2053
+#, c-format
+msgid "extended section index is %<PRIu32> but symbol index is not XINDEX\n"
+msgstr ""
+"індекс розширеного розділу дорівнює %<PRIu32>, але індекс символу не є "
+"XINDEX\n"
+
+#: src/elflint.c:2070 src/elflint.c:2127
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"
+msgstr ""
+"розділ [%2d] «%s»: розділ таблиці хешів занадто малий (розмір %ld, мало бути "
+"— %ld)\n"
+
+#: src/elflint.c:2084 src/elflint.c:2141
+#, c-format
+msgid "section [%2d] '%s': chain array too large\n"
+msgstr "розділ [%2d] «%s»: масив ланцюжка занадто великий\n"
+
+#: src/elflint.c:2098 src/elflint.c:2155
+#, c-format
+msgid "section [%2d] '%s': hash bucket reference %zu out of bounds\n"
+msgstr ""
+"розділ [%2d] «%s»: посилання на хеш блоку %zu лежить поза межами діапазону\n"
+
+#: src/elflint.c:2108
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %zu out of bounds\n"
+msgstr ""
+"розділ [%2d] «%s»: посилання ланцюжка хешів %zu лежить поза межами "
+"діапазону\n"
+
+#: src/elflint.c:2165
+#, c-format
+msgid "section [%2d] '%s': hash chain reference %<PRIu64> out of bounds\n"
+msgstr ""
+"розділ [%2d] «%s»: посилання ланцюжка хешів %<PRIu64> лежить поза межами "
+"діапазону\n"
+
+#: src/elflint.c:2178
+#, c-format
+msgid "section [%2d] '%s': not enough data\n"
+msgstr "розділ [%2d] «%s»: недостатньо даних\n"
+
+#: src/elflint.c:2190
+#, c-format
+msgid "section [%2d] '%s': bitmask size zero or not power of 2: %u\n"
+msgstr ""
+"розділ [%2d] «%s»: розмір бітової маски є нульовим або не є степенем 2: %u\n"
+
+#: src/elflint.c:2206
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table section is too small (is %ld, expected at "
+"least %ld)\n"
+msgstr ""
+"розділ [%2d] «%s»: розділ таблиці хешів є надто малим (маємо %ld, мало бути "
+"принаймні %ld)\n"
+
+#: src/elflint.c:2215
+#, c-format
+msgid "section [%2d] '%s': 2nd hash function shift too big: %u\n"
+msgstr "розділ [%2d] «%s»: зсув 2-ої функції хешування занадто великий: %u\n"
+
+#: src/elflint.c:2249
+#, c-format
+msgid ""
+"section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"
+msgstr ""
+"розділ [%2d] '%s': ланцюжок хешів для блоку %zu розташовано нижче за позицію "
+"відхилення індексу символу\n"
+
+#: src/elflint.c:2270
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %u referenced in chain for bucket %zu is "
+"undefined\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %u, на який посилається ланцюжок у блоці %zu не "
+"визначено\n"
+
+#: src/elflint.c:2283
+#, c-format
+msgid ""
+"section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+"розділ [%2d] «%s»: значення хешу для символу %u у ланцюжку для блоку %zu є "
+"помилковим\n"
+
+#: src/elflint.c:2292
+#, c-format
+msgid ""
+"section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"
+msgstr ""
+"розділ [%2d] «%s»: індекс маски для символу %u у ланцюжку для блоку %zu є "
+"помилковим\n"
+
+#: src/elflint.c:2322
+#, c-format
+msgid "section [%2d] '%s': hash chain for bucket %zu out of bounds\n"
+msgstr ""
+"розділ [%2d] «%s»: ланцюжок хешів для блоку %zu лежить поза межами "
+"діапазону\n"
+
+#: src/elflint.c:2327
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"
+msgstr ""
+"розділ [%2d] «%s»: посилання на символ у ланцюжку для блоку %zu лежить поза "
+"межами діапазону\n"
+
+#: src/elflint.c:2333
+#, c-format
+msgid "section [%2d] '%s': bitmask does not match names in the hash table\n"
+msgstr "розділ [%2d] «%s»: бітова маска не відповідає назвам у таблиці хешів\n"
+
+#: src/elflint.c:2346
+#, c-format
+msgid "section [%2d] '%s': relocatable files cannot have hash tables\n"
+msgstr ""
+"розділ [%2d] «%s»: придатні до пересування файли не можуть містити таблиць "
+"хешів\n"
+
+#: src/elflint.c:2364
+#, c-format
+msgid "section [%2d] '%s': hash table not for dynamic symbol table\n"
+msgstr ""
+"розділ [%2d] «%s»: таблицю хешів не призначено для зберігання таблиці "
+"динамічних символів\n"
+
+#: src/elflint.c:2368
+#, c-format
+msgid "section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"
+msgstr ""
+"розділ [%2d] «%s»: некоректний індекс розділу таблиці символів sh_link "
+"[%2d]\n"
+
+#: src/elflint.c:2378
+#, c-format
+msgid "section [%2d] '%s': hash table entry size incorrect\n"
+msgstr "розділ [%2d] «%s»: розмірність запису таблиці хешів є некоректною\n"
+
+#: src/elflint.c:2383
+#, c-format
+msgid "section [%2d] '%s': not marked to be allocated\n"
+msgstr "розділ [%2d] «%s»: не позначено для пересування\n"
+
+#: src/elflint.c:2388
+#, c-format
+msgid ""
+"section [%2d] '%s': hash table has not even room for initial administrative "
+"entries\n"
+msgstr ""
+"розділ [%2d] «%s»: у таблиці хешів виявлено незвичайне розташування "
+"початкових адміністративних записів\n"
+
+#: src/elflint.c:2437
+#, c-format
+msgid "sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"
+msgstr "sh_link у розділах хешів [%2zu] «%s» і [%2zu] «%s» не збігаються\n"
+
+#: src/elflint.c:2461 src/elflint.c:2526 src/elflint.c:2561
+#, c-format
+msgid "hash section [%2zu] '%s' does not contain enough data\n"
+msgstr "розділ хешу [%2zu] «%s» містить недостатньо даних\n"
+
+#: src/elflint.c:2482
+#, c-format
+msgid "hash section [%2zu] '%s' has zero bit mask words\n"
+msgstr "розділ хешу [%2zu] «%s» містить нульові слова бітової маски\n"
+
+#: src/elflint.c:2493 src/elflint.c:2537 src/elflint.c:2574
+#, c-format
+msgid "hash section [%2zu] '%s' uses too much data\n"
+msgstr "розділ хешу [%2zu] «%s» використовує надто багато даних\n"
+
+#: src/elflint.c:2508
+#, c-format
+msgid ""
+"hash section [%2zu] '%s' invalid symbol index %<PRIu32> (max_nsyms: "
+"%<PRIu32>, nentries: %<PRIu32>\n"
+msgstr ""
+"розділ хешу [%2zu] «%s» некоректний індекс символу %<PRIu32> (макс. к-ть "
+"символів: %<PRIu32>, кількість записів: %<PRIu32>\n"
+
+#: src/elflint.c:2595
+#, c-format
+msgid "hash section [%2zu] '%s' invalid sh_entsize\n"
+msgstr "розділ хешу [%2zu] «%s» некоректне значення sh_entsize\n"
+
+#: src/elflint.c:2605 src/elflint.c:2609
+#, c-format
+msgid "section [%2zu] '%s': reference to symbol index 0\n"
+msgstr "розділ [%2zu] «%s»: посилання на індекс символів 0\n"
+
+#: src/elflint.c:2616
+#, c-format
+msgid ""
+"symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+"виявлено посилання на символ %d у новій таблиці хешів у [%2zu] «%s», але "
+"його немає у старій таблиці хешів у [%2zu] «%s»\n"
+
+#: src/elflint.c:2628
+#, c-format
+msgid ""
+"symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash "
+"table in [%2zu] '%s'\n"
+msgstr ""
+"виявлено посилання на символ %d у старій таблиці хешів у [%2zu] «%s», але "
+"його немає у новій таблиці хешів у [%2zu] «%s»\n"
+
+#: src/elflint.c:2644
+#, c-format
+msgid "section [%2d] '%s': nonzero sh_%s for NULL section\n"
+msgstr "розділ [%2d] «%s»: ненульове значення sh_%s для розділу NULL\n"
+
+#: src/elflint.c:2664
+#, c-format
+msgid ""
+"section [%2d] '%s': section groups only allowed in relocatable object files\n"
+msgstr ""
+"розділ [%2d] «%s»: групи розділів передбачено лише для придатних до "
+"пересування об’єктних файлах\n"
+
+#: src/elflint.c:2675
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol table: %s\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати таблицю символів: %s\n"
+
+#: src/elflint.c:2680
+#, c-format
+msgid "section [%2d] '%s': section reference in sh_link is no symbol table\n"
+msgstr ""
+"розділ [%2d] «%s»: посилання на розділ у sh_link не має таблиці символів\n"
+
+#: src/elflint.c:2686
+#, c-format
+msgid "section [%2d] '%s': invalid symbol index in sh_info\n"
+msgstr "розділ [%2d] «%s»: некоректний індекс символу у sh_info\n"
+
+#: src/elflint.c:2691
+#, c-format
+msgid "section [%2d] '%s': sh_flags not zero\n"
+msgstr "розділ [%2d] «%s»: sh_flags не є нульовим\n"
+
+#: src/elflint.c:2698
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol for signature\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати символ для підпису\n"
+
+#: src/elflint.c:2702
+#, c-format
+msgid "section [%2d] '%s': cannot get symbol name for signature\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати назву символу для підпису\n"
+
+#: src/elflint.c:2707
+#, c-format
+msgid "section [%2d] '%s': signature symbol cannot be empty string\n"
+msgstr "розділ [%2d] «%s»: символ підпису не може бути порожнім рядком\n"
+
+#: src/elflint.c:2713
+#, c-format
+msgid "section [%2d] '%s': sh_flags not set correctly\n"
+msgstr "розділ [%2d] «%s»: для sh_flags встановлено помилкове значення\n"
+
+#: src/elflint.c:2719
+#, c-format
+msgid "section [%2d] '%s': cannot get data: %s\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати дані: %s\n"
+
+#: src/elflint.c:2728
+#, c-format
+msgid "section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"
+msgstr "розділ [%2d] «%s»: розмір розділу не є кратним до sizeof(Elf32_Word)\n"
+
+#: src/elflint.c:2734
+#, c-format
+msgid "section [%2d] '%s': section group without flags word\n"
+msgstr "розділ [%2d] «%s»: група розділів без значення типу word прапорців\n"
+
+#: src/elflint.c:2742
+#, c-format
+msgid "section [%2d] '%s': section group without member\n"
+msgstr "розділ [%2d] «%s»: група розділів без елементів\n"
+
+#: src/elflint.c:2746
+#, c-format
+msgid "section [%2d] '%s': section group with only one member\n"
+msgstr "розділ [%2d] «%s»: група розділів, що містить лише один елемент\n"
+
+#: src/elflint.c:2757
+#, c-format
+msgid "section [%2d] '%s': unknown section group flags\n"
+msgstr "розділ [%2d] «%s»: невідомі прапорці групи розділів\n"
+
+#: src/elflint.c:2769
+#, c-format
+msgid "section [%2d] '%s': section index %zu out of range\n"
+msgstr "розділ [%2d] «%s»: індекс розділу %zu поза межами діапазону\n"
+
+#: src/elflint.c:2778
+#, c-format
+msgid "section [%2d] '%s': cannot get section header for element %zu: %s\n"
+msgstr ""
+"розділ [%2d] «%s»: не вдалося отримати заголовок розділу для елемента %zu: "
+"%s\n"
+
+#: src/elflint.c:2785
+#, c-format
+msgid "section [%2d] '%s': section group contains another group [%2d] '%s'\n"
+msgstr "розділ [%2d] «%s»: група розділів містить іншу групу [%2d] «%s»\n"
+
+#: src/elflint.c:2791
+#, c-format
+msgid ""
+"section [%2d] '%s': element %zu references section [%2d] '%s' without "
+"SHF_GROUP flag set\n"
+msgstr ""
+"розділ [%2d] «%s»: елемент %zu посилається на розділ [%2d] «%s» без "
+"встановленого прапорця SHF_GROUP\n"
+
+#: src/elflint.c:2798
+#, c-format
+msgid "section [%2d] '%s' is contained in more than one section group\n"
+msgstr "розділ [%2d] «%s» міститься у більше ніж одній групі розділів\n"
+
+#: src/elflint.c:2995
+#, c-format
+msgid ""
+"section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no "
+"dynamic symbol table\n"
+msgstr ""
+"розділ [%2d] «%s» посилається у sh_link на розділ [%2d] «%s», який не має "
+"динамічної таблиці символів\n"
+
+#: src/elflint.c:3007
+#, c-format
+msgid ""
+"section [%2d] '%s' has different number of entries than symbol table [%2d] "
+"'%s'\n"
+msgstr ""
+"кількість записів у розділі [%2d] «%s» відрізняється від кількості у таблиці "
+"символів [%2d] «%s»\n"
+
+#: src/elflint.c:3023
+#, c-format
+msgid "section [%2d] '%s': symbol %d: cannot read version data\n"
+msgstr "розділ [%2d] «%s»: символ %d: не вдалося прочитати дані щодо версії\n"
+
+#: src/elflint.c:3039
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with global scope\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %d: локальний символ у загальному контексті\n"
+
+#: src/elflint.c:3047
+#, c-format
+msgid "section [%2d] '%s': symbol %d: local symbol with version\n"
+msgstr "розділ [%2d] «%s»: символ %d: локальний символ з версією\n"
+
+#: src/elflint.c:3061
+#, c-format
+msgid "section [%2d] '%s': symbol %d: invalid version index %d\n"
+msgstr "розділ [%2d] «%s»: символ %d: некоректний індекс версії %d\n"
+
+#: src/elflint.c:3066
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for defined version\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %d: індекси версії %d призначено до визначеної "
+"версії\n"
+
+#: src/elflint.c:3076
+#, c-format
+msgid ""
+"section [%2d] '%s': symbol %d: version index %d is for requested version\n"
+msgstr ""
+"розділ [%2d] «%s»: символ %d: індекс версії %d призначено для версії, на яку "
+"надійшов запит\n"
+
+#: src/elflint.c:3129
+#, c-format
+msgid "more than one version reference section present\n"
+msgstr "виявлено більше за один розділ посилань на версії\n"
+
+#: src/elflint.c:3137 src/elflint.c:3284
+#, c-format
+msgid "section [%2d] '%s': sh_link does not link to string table\n"
+msgstr "розділ [%2d] «%s»: sh_link не посилається на таблицю рядків\n"
+
+#: src/elflint.c:3162 src/elflint.c:3338
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong version %d\n"
+msgstr "розділ [%2d] «%s»: запис %d має помилкову версію %d\n"
+
+#: src/elflint.c:3169 src/elflint.c:3345
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %d містить помилкове зміщення у допоміжних даних\n"
+
+#: src/elflint.c:3179
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid file reference\n"
+msgstr "розділ [%2d] «%s»: запис %d містить некоректне посилання на файл\n"
+
+#: src/elflint.c:3187
+#, c-format
+msgid "section [%2d] '%s': entry %d references unknown dependency\n"
+msgstr "розділ [%2d] «%s»: запис %d посилається на невідому залежність\n"
+
+#: src/elflint.c:3199
+#, c-format
+msgid "section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"
+msgstr ""
+"розділ [%2d] «%s»: допоміжний запис %d запису %d позначено невідомим "
+"прапорцем\n"
+
+#: src/elflint.c:3207
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has invalid name "
+"reference\n"
+msgstr ""
+"розділ [%2d] «%s»: допоміжний запис %d запису %d містить некоректне "
+"посилання на назву\n"
+
+#: src/elflint.c:3216
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: "
+"%#x, expected %#x\n"
+msgstr ""
+"розділ [%2d] «%s»: допоміжний запис %d запису %d має помилкове значення "
+"хешу: %#x, мало бути %#x\n"
+
+#: src/elflint.c:3225
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version "
+"name '%s'\n"
+msgstr ""
+"розділ [%2d] «%s»: допоміжний запис %d запису %d містить дублікати назви "
+"версії «%s»\n"
+
+#: src/elflint.c:3236
+#, c-format
+msgid ""
+"section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"
+msgstr ""
+"розділ [%2d] «%s»: допоміжний запис %d запису %d має помилкове наступне "
+"поле\n"
+
+#: src/elflint.c:3253 src/elflint.c:3429
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid offset to next entry\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %d має некоректне зміщення щодо наступного запису\n"
+
+#: src/elflint.c:3261 src/elflint.c:3437
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says "
+"there are more entries\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %d має нульове зміщення щодо наступного запису, але "
+"за sh_info можна зрозуміти, що записів більше\n"
+
+#: src/elflint.c:3276
+#, c-format
+msgid "more than one version definition section present\n"
+msgstr "виявлено більше за один розділ визначення версій\n"
+
+#: src/elflint.c:3323
+#, c-format
+msgid "section [%2d] '%s': more than one BASE definition\n"
+msgstr "розділ [%2d] «%s»: повторне визначення BASE\n"
+
+#: src/elflint.c:3327
+#, c-format
+msgid "section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"
+msgstr ""
+"розділ [%2d] «%s»: визначення BASE повинно мати індекс VER_NDX_GLOBAL\n"
+
+#: src/elflint.c:3333
+#, c-format
+msgid "section [%2d] '%s': entry %d has unknown flag\n"
+msgstr "розділ [%2d] «%s»: невідомий прапорець запису %d\n"
+
+#: src/elflint.c:3360
+#, c-format
+msgid "section [%2d] '%s': entry %d has invalid name reference\n"
+msgstr "розділ [%2d] «%s»: запис %d містить некоректне посилання на назву\n"
+
+#: src/elflint.c:3367
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %d має помилкове значення хешу: %#x, мало бути %#x\n"
+
+#: src/elflint.c:3375
+#, c-format
+msgid "section [%2d] '%s': entry %d has duplicate version name '%s'\n"
+msgstr "розділ [%2d] «%s»: запис %d містить дублікати назви версії «%s»\n"
+
+#: src/elflint.c:3395
+#, c-format
+msgid ""
+"section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"
+msgstr ""
+"розділ [%2d] «%s»: запис %d містить некоректне посилання на назву у "
+"допоміжних даних\n"
+
+#: src/elflint.c:3412
+#, c-format
+msgid "section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"
+msgstr ""
+"розділ [%2d] «%s»: у допоміжних даних запису %d міститься помилкове поле "
+"наступного запису\n"
+
+#: src/elflint.c:3445
+#, c-format
+msgid "section [%2d] '%s': no BASE definition\n"
+msgstr "розділ [%2d] «%s»: немає визначення BASE\n"
+
+#: src/elflint.c:3461
+#, c-format
+msgid "section [%2d] '%s': unknown parent version '%s'\n"
+msgstr "розділ [%2d] «%s»: невідома основна версія «%s»\n"
+
+#: src/elflint.c:3486
+#, c-format
+msgid "section [%2d] '%s': empty object attributes section\n"
+msgstr "розділ [%2d] «%s»: порожній розділ атрибутів об’єкта\n"
+
+#: src/elflint.c:3502
+#, c-format
+msgid "section [%2d] '%s': unrecognized attribute format\n"
+msgstr "розділ [%2d] «%s»: не вдалося визначити формат атрибутів\n"
+
+#: src/elflint.c:3513
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute section\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: поле нульового розміру у розділі атрибутів\n"
+
+#: src/elflint.c:3522
+#, c-format
+msgid "section [%2d] '%s': offset %zu: invalid length in attribute section\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: некоректна довжина у розділі атрибутів\n"
+
+#: src/elflint.c:3534
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated vendor name string\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: незавершений рядок назви постачальника\n"
+
+#: src/elflint.c:3551
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: незавершене поле ULEB128 у тезі підрозділу "
+"атрибутів\n"
+
+#: src/elflint.c:3560
+#, c-format
+msgid "section [%2d] '%s': offset %zu: truncated attribute section\n"
+msgstr "розділ [%2d] «%s»: зміщення %zu: обрізаний розділ атрибутів\n"
+
+#: src/elflint.c:3569
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: поле нульового розміру у підрозділі "
+"атрибутів\n"
+
+#: src/elflint.c:3584
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: некоректна довжина у підрозділі атрибутів\n"
+
+#. Tag_File
+#: src/elflint.c:3595
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: підрозділ атрибутів містить неочікуваний "
+"теґ %u\n"
+
+#: src/elflint.c:3616
+#, c-format
+msgid "section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: незавершене поле ULEB128 у тезі атрибуту\n"
+
+#: src/elflint.c:3627
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unterminated string in attribute\n"
+msgstr "розділ [%2d] «%s»: зміщення %zu: незавершений рядок у атрибуті\n"
+
+#: src/elflint.c:3640
+#, c-format
+msgid "section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"
+msgstr "розділ [%2d] «%s»: зміщення %zu: незавершений теґ атрибуту %u\n"
+
+#: src/elflint.c:3644
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: unrecognized %s attribute value %<PRIu64>\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: невідоме значення %s атрибуту %<PRIu64>\n"
+
+#: src/elflint.c:3654
+#, c-format
+msgid "section [%2d] '%s': offset %zu: vendor '%s' unknown\n"
+msgstr "розділ [%2d] «%s»: зміщення %zu: невідомий постачальник «%s»\n"
+
+#: src/elflint.c:3660
+#, c-format
+msgid ""
+"section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"
+msgstr ""
+"розділ [%2d] «%s»: зміщення %zu: зайві байти після останнього розділу "
+"атрибутів\n"
+
+#: src/elflint.c:3758
+#, c-format
+msgid "cannot get section header of zeroth section\n"
+msgstr "не вдалося отримати заголовок нульового розділу\n"
+
+#: src/elflint.c:3762
+#, c-format
+msgid "zeroth section has nonzero name\n"
+msgstr "нульовий розділ має ненульову назву\n"
+
+#: src/elflint.c:3764
+#, c-format
+msgid "zeroth section has nonzero type\n"
+msgstr "нульовий розділ має ненульовий тип\n"
+
+#: src/elflint.c:3766
+#, c-format
+msgid "zeroth section has nonzero flags\n"
+msgstr "нульовий розділ має ненульові прапорці\n"
+
+#: src/elflint.c:3768
+#, c-format
+msgid "zeroth section has nonzero address\n"
+msgstr "нульовий розділ має ненульову адресу\n"
+
+#: src/elflint.c:3770
+#, c-format
+msgid "zeroth section has nonzero offset\n"
+msgstr "нульовий розділ має ненульове зміщення\n"
+
+#: src/elflint.c:3772
+#, c-format
+msgid "zeroth section has nonzero align value\n"
+msgstr "нульовий розділ має ненульове значення вирівнювання\n"
+
+#: src/elflint.c:3774
+#, c-format
+msgid "zeroth section has nonzero entry size value\n"
+msgstr "нульовий розділ має ненульове значення розміру запису\n"
+
+#: src/elflint.c:3777
+#, c-format
+msgid ""
+"zeroth section has nonzero size value while ELF header has nonzero shnum "
+"value\n"
+msgstr ""
+"нульовий розділ має ненульове значення розміру, хоча заголовок ELF ман "
+"ненульове значення shnum\n"
+
+#: src/elflint.c:3781
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in shstrndx\n"
+msgstr ""
+"нульовий розділ має ненульове значення компонування, хоча у заголовку ELF "
+"немає сигналу переповнення у shstrndx\n"
+
+#: src/elflint.c:3785
+#, c-format
+msgid ""
+"zeroth section has nonzero link value while ELF header does not signal "
+"overflow in phnum\n"
+msgstr ""
+"нульовий розділ має ненульове значення компонування, хоча у заголовку ELF "
+"немає сигналу переповнення у phnum\n"
+
+#: src/elflint.c:3803
+#, c-format
+msgid "cannot get section header for section [%2zu] '%s': %s\n"
+msgstr "не вдалося отримати заголовок розділу [%2zu] «%s»: %s\n"
+
+#: src/elflint.c:3812
+#, c-format
+msgid "section [%2zu]: invalid name\n"
+msgstr "розділ [%2zu]: некоректна назва\n"
+
+#: src/elflint.c:3839
+#, c-format
+msgid "section [%2d] '%s' has wrong type: expected %s, is %s\n"
+msgstr ""
+"розділ [%2d] «%s» належить до помилкового типу: мав бути %s, маємо %s\n"
+
+#: src/elflint.c:3856
+#, c-format
+msgid "section [%2zu] '%s' has wrong flags: expected %s, is %s\n"
+msgstr "розділ [%2zu] «%s» має помилкові прапорці: мало бути %s, маємо %s\n"
+
+#: src/elflint.c:3874
+#, c-format
+msgid ""
+"section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"
+msgstr ""
+"розділ [%2zu] «%s» має помилкові прапорці: мало бути %s, можливо, %s, але "
+"маємо %s\n"
+
+#: src/elflint.c:3891
+#, c-format
+msgid "section [%2zu] '%s' present in object file\n"
+msgstr "у об’єктному файлі виявлено розділ [%2zu] «%s»\n"
+
+#: src/elflint.c:3897 src/elflint.c:3929
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"
+msgstr ""
+"у розділ [%2zu] «%s» встановлено прапорець SHF_ALLOC, але немає придатного "
+"до завантаження сегмента\n"
+
+#: src/elflint.c:3902 src/elflint.c:3934
+#, c-format
+msgid ""
+"section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable "
+"segments\n"
+msgstr ""
+"у розділі [%2zu] «%s» не встановлено прапорець SHF_ALLOC, але є придатні до "
+"завантаження сегменти\n"
+
+#: src/elflint.c:3910
+#, c-format
+msgid ""
+"section [%2zu] '%s' is extension section index table in non-object file\n"
+msgstr ""
+"розділ [%2zu] «%s» є таблицею-покажчиком розділу розширень у файлі, який не "
+"є об’єктним\n"
+
+#: src/elflint.c:3953
+#, c-format
+msgid "section [%2zu] '%s': size not multiple of entry size\n"
+msgstr "розділ [%2zu] «%s»: розмір не є кратним до розміру запису\n"
+
+#: src/elflint.c:3958
+#, c-format
+msgid "cannot get section header\n"
+msgstr "не вдалося отримати заголовок розділу\n"
+
+#: src/elflint.c:3968
+#, c-format
+msgid "section [%2zu] '%s' has unsupported type %d\n"
+msgstr "розділ [%2zu] «%s» належить до непідтримуваного типу %d\n"
+
+#: src/elflint.c:3988
+#, c-format
+msgid ""
+"section [%2zu] '%s' contains invalid processor-specific flag(s) %#<PRIx64>\n"
+msgstr ""
+"розділ [%2zu] «%s» містить некоректні специфічні для процесора прапорці "
+"%#<PRIx64>\n"
+
+#: src/elflint.c:3998
+#, c-format
+msgid "section [%2zu] '%s' contains unknown flag(s) %#<PRIx64>\n"
+msgstr "розділ [%2zu] «%s» містить невідомі прапорці %#<PRIx64>\n"
+
+#: src/elflint.c:4006
+#, c-format
+msgid "section [%2zu] '%s': thread-local data sections address not zero\n"
+msgstr ""
+"розділ [%2zu] «%s»: адреса розділів локальних даних потоків не є нульовою\n"
+
+#: src/elflint.c:4016
+#, c-format
+msgid "section [%2zu] '%s': allocated section cannot be compressed\n"
+msgstr ""
+"розділ [%2zu] «%s»: розміщений у пам'яті розділ не може бути стиснений\n"
+
+#: src/elflint.c:4021
+#, c-format
+msgid "section [%2zu] '%s': nobits section cannot be compressed\n"
+msgstr "розділ [%2zu] «%s»: розділ nobits не може бути стиснений\n"
+
+#: src/elflint.c:4027
+#, c-format
+msgid ""
+"section [%2zu] '%s': compressed section with no compression header: %s\n"
+msgstr "розділ [%2zu] «%s»: стиснений розділ без заголовка стиснення: %s\n"
+
+#: src/elflint.c:4033
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in link value\n"
+msgstr ""
+"розділ [%2zu] «%s»: некоректне посилання на розділ у значенні компонування\n"
+
+#: src/elflint.c:4038
+#, c-format
+msgid "section [%2zu] '%s': invalid section reference in info value\n"
+msgstr ""
+"розділ [%2zu] «%s»: некоректне посилання на розділ у значенні відомостей\n"
+
+#: src/elflint.c:4045
+#, c-format
+msgid "section [%2zu] '%s': strings flag set without merge flag\n"
+msgstr "розділ [%2zu] «%s»: встановлено прапорець strings без прапорця merge\n"
+
+#: src/elflint.c:4050
+#, c-format
+msgid "section [%2zu] '%s': merge flag set but entry size is zero\n"
+msgstr ""
+"розділ [%2zu] «%s»: встановлено прапорець merge, але розмір запису є "
+"нульовим\n"
+
+#: src/elflint.c:4069
+#, c-format
+msgid "section [%2zu] '%s' has unexpected type %d for an executable section\n"
+msgstr "розділ [%2zu] «%s» має неочікуваний тип %d для виконуваного розділу\n"
+
+#: src/elflint.c:4078
+#, c-format
+msgid "section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"
+msgstr "розділ [%2zu] «%s» у файлах debuginfo має належати до типу NOBITS\n"
+
+#: src/elflint.c:4085
+#, c-format
+msgid "section [%2zu] '%s' is both executable and writable\n"
+msgstr "розділ [%2zu] «%s» є одночасно виконуваним і придатним до запису\n"
+
+#: src/elflint.c:4116
+#, c-format
+msgid ""
+"section [%2zu] '%s' not fully contained in segment of program header entry "
+"%d\n"
+msgstr ""
+"розділ [%2zu] «%s» не повністю міститься у сегменті запису заголовка "
+"програми %d\n"
+
+#: src/elflint.c:4126
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d\n"
+msgstr ""
+"розділ [%2zu] «%s» належить до типу NOBITS, але його читання виконується з "
+"файла у сегментів запису заголовка програми %d\n"
+
+#: src/elflint.c:4152
+#, c-format
+msgid ""
+"section [%2zu] '%s' has type NOBITS but is read from the file in segment of "
+"program header entry %d and file contents is non-zero\n"
+msgstr ""
+"розділ [%2zu] «%s» належить до типу NOBITS, але його читання виконується з "
+"файла у сегментів запису заголовка програми %d, а вміст файла є ненульовим\n"
+
+#: src/elflint.c:4163
+#, c-format
+msgid ""
+"section [%2zu] '%s' has not type NOBITS but is not read from the file in "
+"segment of program header entry %d\n"
+msgstr ""
+"розділ [%2zu] «%s» не належить до типу NOBITS, але його читання не "
+"виконується з файла у сегментів запису заголовка програми %d\n"
+
+#: src/elflint.c:4174
+#, c-format
+msgid "section [%2zu] '%s' is executable in nonexecutable segment %d\n"
+msgstr "розділ [%2zu] «%s» є виконуваним у невиконуваному сегменті %d\n"
+
+#: src/elflint.c:4184
+#, c-format
+msgid "section [%2zu] '%s' is writable in unwritable segment %d\n"
+msgstr ""
+"розділ [%2zu] «%s» є придатним до запису у непридатному до запису сегменті "
+"%d\n"
+
+#: src/elflint.c:4194
+#, c-format
+msgid ""
+"section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"
+msgstr ""
+"розділ [%2zu] «%s»: встановлено прапорець alloc, але розділ не перебуває у "
+"жодному завантаженому сегменті\n"
+
+#: src/elflint.c:4200
+#, c-format
+msgid ""
+"section [%2zu] '%s': ELF header says this is the section header string table "
+"but type is not SHT_TYPE\n"
+msgstr ""
+"розділ [%2zu] «%s»: заголовок ELF повідомляє про те, що це таблиця рядків "
+"заголовка розділу, але ця таблиця не належить до типу SHT_TYPE\n"
+
+#: src/elflint.c:4208
+#, c-format
+msgid ""
+"section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"
+msgstr ""
+"розділ [%2zu] «%s»: придатні до пересування файли не можуть містити "
+"динамічних таблиць символів\n"
+
+#: src/elflint.c:4263
+#, c-format
+msgid "more than one version symbol table present\n"
+msgstr "виявлено більше за одну таблицю символів версій\n"
+
+#: src/elflint.c:4286
+#, c-format
+msgid "INTERP program header entry but no .interp section\n"
+msgstr "існує запис заголовка програми INTERP, але не розділ .interp\n"
+
+#: src/elflint.c:4297
+#, c-format
+msgid ""
+"loadable segment [%u] is executable but contains no executable sections\n"
+msgstr ""
+"придатний до завантаження сегмент [%u] є виконуваним, але не містить "
+"виконуваних розділів\n"
+
+#: src/elflint.c:4303
+#, c-format
+msgid "loadable segment [%u] is writable but contains no writable sections\n"
+msgstr ""
+"придатний до завантаження розділ [%u] є придатним до запису, але не містить "
+"придатних до запису розділів\n"
+
+#: src/elflint.c:4314
+#, c-format
+msgid ""
+"no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section "
+"exist\n"
+msgstr ""
+"немає розділу .gnu.versym, хоча існує розділ .gnu.versym_d або .gnu."
+"versym_r\n"
+
+#: src/elflint.c:4327
+#, c-format
+msgid "duplicate version index %d\n"
+msgstr "дублікат індексу версії %d\n"
+
+#: src/elflint.c:4341
+#, c-format
+msgid ".gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"
+msgstr ""
+"існує розділ .gnu.versym, але немає розділу .gnu.versym_d або .gnu.versym_r\n"
+
+#: src/elflint.c:4390
+#, c-format
+msgid "phdr[%d]: unknown core file note type %<PRIu32> at offset %<PRIu64>\n"
+msgstr ""
+"phdr[%d]: невідомий тип нотатки файла core %<PRIu32> за зміщенням %<PRIu64>\n"
+
+#: src/elflint.c:4394
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown core file note type %<PRIu32> at offset %zu\n"
+msgstr ""
+"розділ [%2d] «%s»: невідомий тип нотатки файла core %<PRIu32> за зміщенням "
+"%zu\n"
+
+#: src/elflint.c:4450
+#, c-format
+msgid ""
+"phdr[%d]: unknown object file note type %<PRIu32> with owner name '%s' at "
+"offset %zu\n"
+msgstr ""
+"phdr[%d]: невідомий тип нотатки у файлі об'єктів, %<PRIu32>, із іменем "
+"власника «%s» за зміщенням %zu\n"
+
+#: src/elflint.c:4455
+#, c-format
+msgid ""
+"section [%2d] '%s': unknown object file note type %<PRIu32> with owner name "
+"'%s' at offset %zu\n"
+msgstr ""
+"розділ [%2d] «%s»: невідомий тип нотатки у файлі об'єктів, %<PRIu32>, із "
+"іменем власника «%s» за зміщенням %zu\n"
+
+#: src/elflint.c:4474
+#, c-format
+msgid "phdr[%d]: no note entries defined for the type of file\n"
+msgstr "phdr[%d]: для цього типу файлів не визначено записів нотаток\n"
+
+#: src/elflint.c:4494
+#, c-format
+msgid "phdr[%d]: cannot get content of note section: %s\n"
+msgstr "phdr[%d]: не вдалося отримати вміст розділу нотаток: %s\n"
+
+#: src/elflint.c:4497
+#, c-format
+msgid "phdr[%d]: extra %<PRIu64> bytes after last note\n"
+msgstr "phdr[%d]: зайві %<PRIu64> байтів після останнього запису нотатки\n"
+
+#: src/elflint.c:4518
+#, c-format
+msgid "section [%2d] '%s': no note entries defined for the type of file\n"
+msgstr ""
+"розділ [%2d] «%s»: для цього типу файлів не визначено записів нотаток\n"
+
+#: src/elflint.c:4525
+#, c-format
+msgid "section [%2d] '%s': cannot get content of note section\n"
+msgstr "розділ [%2d] «%s»: не вдалося отримати вміст розділу нотаток\n"
+
+#: src/elflint.c:4528
+#, c-format
+msgid "section [%2d] '%s': extra %<PRIu64> bytes after last note\n"
+msgstr ""
+"розділ [%2d] «%s»: додаткові %<PRIu64> байтів після останньої нотатки\n"
+
+#: src/elflint.c:4546
+#, c-format
+msgid ""
+"only executables, shared objects, and core files can have program headers\n"
+msgstr ""
+"заголовки програм можуть бути лише у виконуваних файлів, об’єктних файлів "
+"спільного використання або файлів core\n"
+
+#: src/elflint.c:4561
+#, c-format
+msgid "cannot get program header entry %d: %s\n"
+msgstr "не вдалося отримати запис заголовка програми %d: %s\n"
+
+#: src/elflint.c:4571
+#, c-format
+msgid "program header entry %d: unknown program header entry type %#<PRIx64>\n"
+msgstr ""
+"запис заголовка програми %d: невідомий тип запису заголовка програми "
+"%#<PRIx64>\n"
+
+#: src/elflint.c:4582
+#, c-format
+msgid "more than one INTERP entry in program header\n"
+msgstr "більше за один запис INTERP у заголовку програми\n"
+
+#: src/elflint.c:4590
+#, c-format
+msgid "more than one TLS entry in program header\n"
+msgstr "більше за один запис TLS у заголовку програми\n"
+
+#: src/elflint.c:4597
+#, c-format
+msgid "static executable cannot have dynamic sections\n"
+msgstr "у статичному виконуваному файлі не може бути динамічних розділів\n"
+
+#: src/elflint.c:4611
+#, c-format
+msgid "dynamic section reference in program header has wrong offset\n"
+msgstr ""
+"посилання на динамічний розділ у заголовку програми має помилкове зміщення\n"
+
+#: src/elflint.c:4614
+#, c-format
+msgid "dynamic section size mismatch in program and section header\n"
+msgstr ""
+"розміри динамічного розділу у заголовку програми та у заголовку розділу не "
+"збігаються\n"
+
+#: src/elflint.c:4624
+#, c-format
+msgid "more than one GNU_RELRO entry in program header\n"
+msgstr "більше за один запис GNU_RELRO у заголовку програми\n"
+
+#: src/elflint.c:4645
+#, c-format
+msgid "loadable segment GNU_RELRO applies to is not writable\n"
+msgstr ""
+"придатний до завантаження сегмент, до якого звертається GNU_RELRO, "
+"непридатний до запису\n"
+
+#: src/elflint.c:4656
+#, c-format
+msgid "loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"
+msgstr ""
+"прапорці придатного до завантаження сегмента [%u] не відповідають прапорцям "
+"GNU_RELRO [%u]\n"
+
+#: src/elflint.c:4663
+#, c-format
+msgid ""
+"GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"
+msgstr ""
+"прапорці GNU_RELRO [%u] не є підмножиною прапорців завантажуваного сегмента "
+"[%u]\n"
+
+#: src/elflint.c:4672 src/elflint.c:4695
+#, c-format
+msgid "%s segment not contained in a loaded segment\n"
+msgstr "сегмент %s не міститься у завантаженому сегменті\n"
+
+#: src/elflint.c:4701
+#, c-format
+msgid "program header offset in ELF header and PHDR entry do not match"
+msgstr "зміщення заголовка програми у заголовку ELF і запис PHDR не збігаються"
+
+#: src/elflint.c:4728
+#, c-format
+msgid "call frame search table reference in program header has wrong offset\n"
+msgstr ""
+"посилання на таблицю вікон викликів у заголовку програми має помилкове "
+"зміщення\n"
+
+#: src/elflint.c:4731
+#, c-format
+msgid "call frame search table size mismatch in program and section header\n"
+msgstr ""
+"розміри таблиці пошуку вікон виклику у заголовку програми та у заголовку "
+"розділу не збігаються\n"
+
+#: src/elflint.c:4744
+#, c-format
+msgid "PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"
+msgstr "існує PT_GNU_EH_FRAME, хоча немає розділу .eh_frame_hdr\n"
+
+#: src/elflint.c:4752
+#, c-format
+msgid "call frame search table must be allocated\n"
+msgstr "таблицю пошуку вікон викликів має бути розміщено у пам’яті\n"
+
+#: src/elflint.c:4755
+#, c-format
+msgid "section [%2zu] '%s' must be allocated\n"
+msgstr "розділ [%2zu] «%s» має бути розміщено у пам’яті\n"
+
+#: src/elflint.c:4759
+#, c-format
+msgid "call frame search table must not be writable\n"
+msgstr "таблиця пошуку вікон викликів не повинна бути придатною до запису\n"
+
+#: src/elflint.c:4762
+#, c-format
+msgid "section [%2zu] '%s' must not be writable\n"
+msgstr "розділ [%2zu] «%s» не повинен бути придатним до запису\n"
+
+#: src/elflint.c:4767
+#, c-format
+msgid "call frame search table must not be executable\n"
+msgstr "таблиця пошуку вікон викликів не повинна бути придатною до виконання\n"
+
+#: src/elflint.c:4770
+#, c-format
+msgid "section [%2zu] '%s' must not be executable\n"
+msgstr "розділ [%2zu] «%s» не повинен бути придатним до виконання\n"
+
+#: src/elflint.c:4784
+#, c-format
+msgid "program header entry %d: file size greater than memory size\n"
+msgstr "запис заголовка програми %d: розмір файла перевищує об’єм пам’яті\n"
+
+#: src/elflint.c:4791
+#, c-format
+msgid "program header entry %d: alignment not a power of 2\n"
+msgstr "запис заголовка програми %d: значення вирівнювання не є степенем 2\n"
+
+#: src/elflint.c:4794
+#, c-format
+msgid ""
+"program header entry %d: file offset and virtual address not module of "
+"alignment\n"
+msgstr ""
+"запис заголовка програми %d: зміщення у файлі і віртуальна адреса не "
+"співвідносяться з вирівнюванням\n"
+
+#: src/elflint.c:4807
+#, c-format
+msgid ""
+"executable/DSO with .eh_frame_hdr section does not have a PT_GNU_EH_FRAME "
+"program header entry"
+msgstr ""
+"виконуваний модуль/DSO з розділом .eh_frame_hdr не містить запису заголовка "
+"програми PT_GNU_EH_FRAME"
+
+#: src/elflint.c:4841
+#, c-format
+msgid "cannot read ELF header: %s\n"
+msgstr "не вдалося прочитати заголовок ELF: %s\n"
+
+#: src/elflint.c:4853
+#, fuzzy, c-format
+msgid "cannot create backend for ELF file\n"
+msgstr "не вдалося створити файл"
+
+#: src/elflint.c:4874
+#, c-format
+msgid "text relocation flag set but not needed\n"
+msgstr ""
+"встановлено прапорець пересування тексту, але такий прапорець не потрібен\n"
+
+#: src/findtextrel.c:60
+msgid "Input Selection:"
+msgstr "Вибір параметрів виводу даних:"
+
+#: src/findtextrel.c:61
+msgid "Prepend PATH to all file names"
+msgstr "Додавати ШЛЯХ до всіх назв файлів"
+
+#: src/findtextrel.c:63
+msgid "Use PATH as root of debuginfo hierarchy"
+msgstr "Використовувати ШЛЯХ як кореневий каталог для ієрархії debuginfo"
+
+#. Short description of program.
+#: src/findtextrel.c:70
+msgid "Locate source of text relocations in FILEs (a.out by default)."
+msgstr "Шукає джерело пересуваного тексту у ФАЙЛАХ (типово, a.out)."
+
+#. Strings for arguments in help texts.
+#: src/findtextrel.c:74 src/nm.c:107 src/objdump.c:70 src/size.c:79
+#: src/strings.c:86 src/strip.c:100
+msgid "[FILE...]"
+msgstr "[ФАЙЛ...]"
+
+#: src/findtextrel.c:223
+#, c-format
+msgid "cannot get ELF header '%s': %s"
+msgstr "не вдалося отримати заголовок ELF «%s»: %s"
+
+#: src/findtextrel.c:234
+#, c-format
+msgid "'%s' is not a DSO or PIE"
+msgstr "«%s» не є DSO або PIE"
+
+#: src/findtextrel.c:254
+#, c-format
+msgid "getting get section header of section %zu: %s"
+msgstr "отримання заголовка розділу get розділу %zu: %s"
+
+#: src/findtextrel.c:278
+#, c-format
+msgid "cannot read dynamic section: %s"
+msgstr "не вдалося прочитати динамічний розділ: %s"
+
+#: src/findtextrel.c:299
+#, c-format
+msgid "no text relocations reported in '%s'"
+msgstr "у «%s» не виявлено пересувань тексту"
+
+#: src/findtextrel.c:310
+#, c-format
+msgid "while reading ELF file"
+msgstr "під час спроби читання файла ELF"
+
+#: src/findtextrel.c:314
+#, c-format
+msgid "cannot get program header count: %s"
+msgstr "не вдалося отримати кількість заголовків програми: %s"
+
+#: src/findtextrel.c:325 src/findtextrel.c:340
+#, c-format
+msgid "cannot get program header index at offset %zd: %s"
+msgstr "не вдалося отримати індекс заголовка програми за зміщенням %zd: %s"
+
+#: src/findtextrel.c:396
+#, c-format
+msgid "cannot get symbol table section %zu in '%s': %s"
+msgstr "не вдалося отримати таблицю символів розділу %zu у «%s»: %s"
+
+#: src/findtextrel.c:417 src/findtextrel.c:440
+#, c-format
+msgid "cannot get relocation at index %d in section %zu in '%s': %s"
+msgstr ""
+"не вдалося отримати пересування за індексом %d у розділі %zu у «%s»: %s"
+
+#: src/findtextrel.c:506
+#, c-format
+msgid "%s not compiled with -fpic/-fPIC\n"
+msgstr "%s не зібрано з -fpic/-fPIC\n"
+
+#: src/findtextrel.c:560
+#, c-format
+msgid ""
+"the file containing the function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"файл, що містить функцію «%s», не було зібрано з параметрами -fpic/-fPIC\n"
+
+#: src/findtextrel.c:567 src/findtextrel.c:587
+#, c-format
+msgid ""
+"the file containing the function '%s' might not be compiled with -fpic/-"
+"fPIC\n"
+msgstr ""
+"файл, що містить функцію «%s», ймовірно, не було зібрано з параметрами -"
+"fpic/-fPIC\n"
+
+#: src/findtextrel.c:575
+#, c-format
+msgid ""
+"either the file containing the function '%s' or the file containing the "
+"function '%s' is not compiled with -fpic/-fPIC\n"
+msgstr ""
+"файл, що містить функцію «%s», або файл, що містить функцію «%s», зібрано "
+"без параметрів -fpic/-fPIC\n"
+
+#: src/findtextrel.c:595
+#, c-format
+msgid ""
+"a relocation modifies memory at offset %llu in a write-protected segment\n"
+msgstr ""
+"пересування призводить до зміни запису пам’яті за зміщенням %llu у "
+"захищеному від запису сегменті\n"
+
+#: src/nm.c:65 src/strip.c:69
+msgid "Output selection:"
+msgstr "Вибір виводу:"
+
+#: src/nm.c:66
+msgid "Display debugger-only symbols"
+msgstr "Показувати лише діагностичні символи"
+
+#: src/nm.c:67
+msgid "Display only defined symbols"
+msgstr "Показувати лише визначені символи"
+
+#: src/nm.c:70
+msgid "Display dynamic symbols instead of normal symbols"
+msgstr "Показувати динамічні символи замість звичайних символів"
+
+#: src/nm.c:71
+msgid "Display only external symbols"
+msgstr "Показувати лише зовнішні символи"
+
+#: src/nm.c:72
+msgid "Display only undefined symbols"
+msgstr "Показувати лише невизначені символи"
+
+#: src/nm.c:74
+msgid "Include index for symbols from archive members"
+msgstr "Включити покажчик для символів з елементів архіву"
+
+#: src/nm.c:76 src/size.c:53
+msgid "Output format:"
+msgstr "Формат виводу:"
+
+#: src/nm.c:78
+msgid "Print name of the input file before every symbol"
+msgstr "Виводити перед кожним символом назву вхідного файла"
+
+#: src/nm.c:81
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The "
+"default is `sysv'"
+msgstr ""
+"Використовувати формат виводу ФОРМАТ. ФОРМАТом може бути «bsd», «sysv» або "
+"«posix». Типовим форматом є «sysv»"
+
+#: src/nm.c:83
+msgid "Same as --format=bsd"
+msgstr "Те саме, що і --format=bsd"
+
+#: src/nm.c:84
+msgid "Same as --format=posix"
+msgstr "Те саме, що і --format=posix"
+
+#: src/nm.c:85 src/size.c:59
+msgid "Use RADIX for printing symbol values"
+msgstr "Використовувати ОСНОВУ числення для виводу символьних значень"
+
+#: src/nm.c:86
+msgid "Mark special symbols"
+msgstr "Позначати спеціальні символи"
+
+#: src/nm.c:88
+msgid "Print size of defined symbols"
+msgstr "Вивести розмір визначених символів"
+
+#: src/nm.c:90 src/size.c:67 src/strip.c:74 src/unstrip.c:68
+msgid "Output options:"
+msgstr "Параметри виводу:"
+
+#: src/nm.c:91
+msgid "Sort symbols numerically by address"
+msgstr "Числове впорядкування символів за адресою"
+
+#: src/nm.c:93
+msgid "Do not sort the symbols"
+msgstr "Не впорядковувати символи"
+
+#: src/nm.c:94
+msgid "Reverse the sense of the sort"
+msgstr "Змінити порядок на протилежний"
+
+#: src/nm.c:97
+msgid "Decode low-level symbol names into source code names"
+msgstr "Визначати за низькорівневими назвами символів назви у початковому коді"
+
+#. Short description of program.
+#: src/nm.c:104
+msgid "List symbols from FILEs (a.out by default)."
+msgstr "Показати список символів з ФАЙЛів (типово з a.out)."
+
+#: src/nm.c:115 src/objdump.c:78
+msgid "Output formatting"
+msgstr "Форматування виводу"
+
+#: src/nm.c:139 src/objdump.c:102 src/size.c:104 src/strip.c:132
+#, c-format
+msgid "%s: INTERNAL ERROR %d (%s): %s"
+msgstr "%s: ВНУТРІШНЯ ПОМИЛКА %d (%s): %s"
+
+#: src/nm.c:380 src/nm.c:392 src/size.c:287 src/size.c:296 src/size.c:307
+#: src/strip.c:2763
+#, c-format
+msgid "while closing '%s'"
+msgstr "під час закриття «%s»"
+
+#: src/nm.c:402 src/objdump.c:279 src/strip.c:827
+#, c-format
+msgid "%s: File format not recognized"
+msgstr "%s: не вдалося розпізнати формат файла"
+
+#. Note: 0 is no valid offset.
+#: src/nm.c:442
+msgid ""
+"\n"
+"Archive index:\n"
+msgstr ""
+"\n"
+"Покажчик архіву:\n"
+
+#: src/nm.c:451
+#, c-format
+msgid "invalid offset %zu for symbol %s"
+msgstr "некоректне зміщення %zu для символу %s"
+
+#: src/nm.c:456
+#, c-format
+msgid "%s in %s\n"
+msgstr "%s у %s\n"
+
+#: src/nm.c:464
+#, c-format
+msgid "cannot reset archive offset to beginning"
+msgstr "не вдалося відновити зміщення початку архіву"
+
+#: src/nm.c:489 src/objdump.c:327
+#, c-format
+msgid "%s%s%s: file format not recognized"
+msgstr "%s%s%s: не вдалося розпізнати формат файла"
+
+#: src/nm.c:702
+msgid "cannot create search tree"
+msgstr "не вдалося створити дерево пошуку"
+
+#: src/nm.c:742 src/nm.c:1234 src/objdump.c:778 src/readelf.c:685
+#: src/readelf.c:1506 src/readelf.c:1655 src/readelf.c:1882 src/readelf.c:2123
+#: src/readelf.c:2312 src/readelf.c:2482 src/readelf.c:2604 src/readelf.c:2854
+#: src/readelf.c:3140 src/readelf.c:3215 src/readelf.c:3301 src/readelf.c:3897
+#: src/readelf.c:3945 src/readelf.c:4014 src/readelf.c:12030
+#: src/readelf.c:13213 src/readelf.c:13423 src/readelf.c:13491 src/size.c:396
+#: src/size.c:467 src/strip.c:1093
+#, c-format
+msgid "cannot get section header string table index"
+msgstr "не вдалося визначити індекс заголовка розділу у таблиці рядків"
+
+#. We always print this prolog.
+#: src/nm.c:767
+#, c-format
+msgid ""
+"\n"
+"\n"
+"Symbols from %s:\n"
+"\n"
+msgstr ""
+"\n"
+"\n"
+"Символи з %s:\n"
+"\n"
+
+#. The header line.
+#: src/nm.c:770
+#, c-format
+msgid ""
+"%*s%-*s %-*s Class  Type     %-*s %*s Section\n"
+"\n"
+msgstr ""
+"%*s%-*s %-*s Клас   Тип      %-*s %*s Розділ\n"
+"\n"
+
+#: src/nm.c:772
+#, fuzzy
+#| msgid " Name: "
+msgctxt "sysv"
+msgid "Name"
+msgstr "Назва: "
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:774
+msgctxt "sysv"
+msgid "Value"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:776
+msgctxt "sysv"
+msgid "Size"
+msgstr ""
+
+#. TRANS: the "sysv|" parts makes the string unique.
+#: src/nm.c:778
+msgctxt "sysv"
+msgid "Line"
+msgstr ""
+
+#: src/nm.c:1245
+#, c-format
+msgid "%s: entry size in section %zd `%s' is not what we expect"
+msgstr "%s: розмір запису у розділі %zd «%s» не є очікуваним"
+
+#: src/nm.c:1250
+#, c-format
+msgid "%s: size of section %zd `%s' is not multiple of entry size"
+msgstr "%s: розмір розділу %zd «%s» не є кратним до розміру запису"
+
+#: src/nm.c:1330
+#, c-format
+msgid "%s: entries (%zd) in section %zd `%s' is too large"
+msgstr "%s: записи (%zd) у розділі %zd, «%s» є завеликим"
+
+#. XXX Add machine specific object file types.
+#: src/nm.c:1566
+#, c-format
+msgid "%s%s%s%s: Invalid operation"
+msgstr "%s%s%s%s: некоректна дія"
+
+#: src/nm.c:1616
+#, c-format
+msgid "%s%s%s: no symbols"
+msgstr "%s%s%s: немає символів"
+
+#: src/objdump.c:51
+msgid "Mode selection:"
+msgstr "Вибір режиму:"
+
+#: src/objdump.c:52
+msgid "Display relocation information."
+msgstr "Показати інформацію про пересування."
+
+#: src/objdump.c:54
+msgid "Display the full contents of all sections requested"
+msgstr "Показати весь вміст всіх вказаних розділів"
+
+#: src/objdump.c:56
+msgid "Display assembler code of executable sections"
+msgstr "Показати код асемблера виконуваних розділів"
+
+#: src/objdump.c:58
+msgid "Output content selection:"
+msgstr "Вибір виведених даних:"
+
+#: src/objdump.c:60
+msgid "Only display information for section NAME."
+msgstr "Показати інформацію лише з розділу НАЗВА."
+
+#. Short description of program.
+#: src/objdump.c:66
+msgid "Show information from FILEs (a.out by default)."
+msgstr "Показати інформацію з ФАЙЛів (типово a.out)."
+
+#: src/objdump.c:217 src/readelf.c:630
+msgid "No operation specified.\n"
+msgstr "Не вказано дії.\n"
+
+#: src/objdump.c:257 src/objdump.c:269
+#, c-format
+msgid "while close `%s'"
+msgstr "під час закриття «%s»"
+
+#: src/objdump.c:362 src/readelf.c:2218 src/readelf.c:2409
+msgid "INVALID SYMBOL"
+msgstr "НЕКОРЕКТНИЙ СИМВОЛ"
+
+#: src/objdump.c:377 src/readelf.c:2252 src/readelf.c:2445
+msgid "INVALID SECTION"
+msgstr "НЕКОРЕКТНИЙ РОЗДІЛ"
+
+#: src/objdump.c:497
+#, c-format
+msgid ""
+"\n"
+"RELOCATION RECORDS FOR [%s]:\n"
+"%-*s TYPE                 VALUE\n"
+msgstr ""
+"\n"
+"ЗАПИСИ ПЕРЕМІЩЕННЯ ДЛЯ [%s]:\n"
+"%-*s ТИП                  ЗНАЧЕННЯ\n"
+
+#: src/objdump.c:500
+msgid "OFFSET"
+msgstr "ЗМІЩЕННЯ"
+
+#: src/objdump.c:565
+#, c-format
+msgid "Contents of section %s:\n"
+msgstr "Вміст розділу %s:\n"
+
+#: src/objdump.c:686
+msgid "cannot disassemble"
+msgstr "не вдалося дизасемблювати"
+
+#: src/objdump.c:757
+#, fuzzy
+msgid "cannot create backend for elf file"
+msgstr "не вдалося створити файл"
+
+#. Short description of program.
+#: src/ranlib.c:62
+msgid "Generate an index to speed access to archives."
+msgstr "Створювати покажчик для пришвидшення доступу до архівів."
+
+#. Strings for arguments in help texts.
+#: src/ranlib.c:65
+msgid "ARCHIVE"
+msgstr "АРХІВ"
+
+#: src/ranlib.c:101
+#, c-format
+msgid "Archive name required"
+msgstr "Слід вказати назву архіву"
+
+#: src/ranlib.c:165
+#, c-format
+msgid "'%s' is no archive"
+msgstr "«%s» не є архівом"
+
+#: src/ranlib.c:200
+#, c-format
+msgid "error while freeing sub-ELF descriptor: %s"
+msgstr "помилка під час спроби вивільнення дескриптора під-ELF: %s"
+
+#: src/readelf.c:97
+msgid "ELF input selection:"
+msgstr "Вибір вихідних даних ELF:"
+
+#: src/readelf.c:99
+msgid ""
+"Use the named SECTION (default .gnu_debugdata) as (compressed) ELF input data"
+msgstr ""
+"Використовувати вказаний за іменем РОЗДІЛ (типово .gnu_debugdata) як "
+"(стиснені) вхідні дані ELF"
+
+#: src/readelf.c:102
+msgid ""
+"Used with -w to find the skeleton Compile Units in FILE associated with the "
+"Split Compile units in a .dwo input file"
+msgstr ""
+"Використовується з -w для пошуку основи компільованих модулів у ФАЙЛі, "
+"пов'язаному із модулями розділеної компіляції у вхідному файлі .dwo"
+
+#: src/readelf.c:104
+msgid "ELF output selection:"
+msgstr "Вибір виводу ELF:"
+
+#: src/readelf.c:106
+msgid "All these plus -p .strtab -p .dynstr -p .comment"
+msgstr "Все це плюс -p .strtab -p .dynstr -p .comment"
+
+#: src/readelf.c:107
+msgid "Display the dynamic segment"
+msgstr "Показувати динамічний сегмент"
+
+#: src/readelf.c:108
+msgid "Display the ELF file header"
+msgstr "Показувати заголовок файла ELF"
+
+#: src/readelf.c:110
+msgid "Display histogram of bucket list lengths"
+msgstr "Показати гістограму довжин списку блоків"
+
+#: src/readelf.c:111
+msgid "Display the program headers"
+msgstr "Показувати заголовки програми"
+
+#: src/readelf.c:113
+msgid "Display relocations"
+msgstr "Показувати пересування"
+
+#: src/readelf.c:114
+msgid "Display the section groups"
+msgstr "Показувати групи розділів"
+
+#: src/readelf.c:115
+msgid "Display the sections' headers"
+msgstr "Показувати заголовки розділів"
+
+#: src/readelf.c:118
+msgid "Display the symbol table sections"
+msgstr "Показати розділи таблиці символів"
+
+#: src/readelf.c:121
+msgid "Display (only) the dynamic symbol table"
+msgstr "Показувати (лише) динамічну таблицю символів"
+
+#: src/readelf.c:122
+msgid "Display versioning information"
+msgstr "Показувати відомості щодо версії"
+
+#: src/readelf.c:123
+msgid "Display the ELF notes"
+msgstr "Показувати нотатки ELF"
+
+#: src/readelf.c:125
+msgid "Display architecture specific information, if any"
+msgstr "Показувати специфічні для архітектури дані, якщо такі буде виявлено"
+
+#: src/readelf.c:127
+msgid "Display sections for exception handling"
+msgstr "Показувати розділи для обробки виключень"
+
+#: src/readelf.c:129
+msgid "Additional output selection:"
+msgstr "Додатковий вибір виводу:"
+
+#: src/readelf.c:131
+msgid ""
+"Display DWARF section content.  SECTION can be one of abbrev, addr, aranges, "
+"decodedaranges, frame, gdb_index, info, info+, loc, line, decodedline, "
+"ranges, pubnames, str, macinfo, macro or exception"
+msgstr ""
+"Показати вміст розділу DWARF. Значенням РОЗДІЛ може бути abbrev, addr, "
+"aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
+"decodedline, ranges, pubnames, str, macinfo, macro або exception"
+
+#: src/readelf.c:135
+msgid "Dump the uninterpreted contents of SECTION, by number or name"
+msgstr ""
+"Створити дамп даних РОЗДІЛ, які не вдалося інтерпретувати, за номером або "
+"назвами"
+
+#: src/readelf.c:137
+msgid "Print string contents of sections"
+msgstr "Виводити вміст рядків розділів"
+
+#: src/readelf.c:140
+msgid "Display the symbol index of an archive"
+msgstr "Показувати покажчик символів архіву"
+
+#: src/readelf.c:142
+msgid "Use the dynamic segment when possible for displaying info"
+msgstr ""
+
+#: src/readelf.c:144
+msgid "Output control:"
+msgstr "Керування виводом:"
+
+#: src/readelf.c:146
+msgid "Do not find symbol names for addresses in DWARF data"
+msgstr "Не шукати назви символів для адрес у даних DWARF"
+
+#: src/readelf.c:148
+msgid ""
+"Display just offsets instead of resolving values to addresses in DWARF data"
+msgstr "Показати лише зміщення, а не визначені значення адреси у даних DWARF"
+
+#: src/readelf.c:150
+msgid "Ignored for compatibility (lines always wide)"
+msgstr "Ігнорується з міркувань сумісності (рядки завжди широкі)"
+
+#: src/readelf.c:152
+msgid ""
+"Show compression information for compressed sections (when used with -S); "
+"decompress section before dumping data (when used with -p or -x)"
+msgstr ""
+"Показати дані щодо стискання для стиснених розділів (якщо використано з -S); "
+"розпакувати розділ до створення дампу даних (якщо використано з -p або -x)"
+
+#. Short description of program.
+#: src/readelf.c:157
+msgid "Print information from ELF file in human-readable form."
+msgstr "Виводити відомості з файла ELF у придатному для читання форматі."
+
+#. Look up once.
+#: src/readelf.c:395
+msgid "yes"
+msgstr "так"
+
+#: src/readelf.c:396
+msgid "no"
+msgstr "ні"
+
+#: src/readelf.c:598
+#, c-format
+msgid "Unknown DWARF debug section `%s'.\n"
+msgstr "Невідомий діагностичний розділ DWARF «%s».\n"
+
+#: src/readelf.c:669 src/readelf.c:780
+#, c-format
+msgid "cannot generate Elf descriptor: %s"
+msgstr "не вдалося створити дескриптор Elf: %s"
+
+#: src/readelf.c:676 src/readelf.c:1002 src/strip.c:1188
+#, c-format
+msgid "cannot determine number of sections: %s"
+msgstr "не вдалося визначити кількість розділів: %s"
+
+#: src/readelf.c:694 src/readelf.c:1322 src/readelf.c:1530
+#, c-format
+msgid "cannot get section: %s"
+msgstr "не вдалося отримати розділ: %s"
+
+#: src/readelf.c:703 src/readelf.c:1329 src/readelf.c:1537 src/readelf.c:13443
+#: src/unstrip.c:396 src/unstrip.c:427 src/unstrip.c:490 src/unstrip.c:622
+#: src/unstrip.c:640 src/unstrip.c:680 src/unstrip.c:897 src/unstrip.c:1263
+#: src/unstrip.c:1390 src/unstrip.c:1414 src/unstrip.c:1470 src/unstrip.c:1511
+#: src/unstrip.c:1703 src/unstrip.c:1854 src/unstrip.c:1998 src/unstrip.c:2106
+#, c-format
+msgid "cannot get section header: %s"
+msgstr "не вдалося отримати заголовок розділу: %s"
+
+#: src/readelf.c:711
+#, c-format
+msgid "cannot get section name"
+msgstr "не вдалося отримати назву розділу"
+
+#: src/readelf.c:720 src/readelf.c:7177 src/readelf.c:11231 src/readelf.c:11333
+#: src/readelf.c:11517
+#, c-format
+msgid "cannot get %s content: %s"
+msgstr "не вдалося отримати дані %s: %s"
+
+#: src/readelf.c:736
+#, c-format
+msgid "cannot create temp file '%s'"
+msgstr "не вдалося створити файл тимчасових даних «%s»"
+
+#: src/readelf.c:745
+#, c-format
+msgid "cannot write section data"
+msgstr "не вдалося записати дані розділу"
+
+#: src/readelf.c:751 src/readelf.c:768 src/readelf.c:797
+#, c-format
+msgid "error while closing Elf descriptor: %s"
+msgstr "помилка під час спроби закриття дескриптора Elf: %s"
+
+#: src/readelf.c:758
+#, c-format
+msgid "error while rewinding file descriptor"
+msgstr "помилка під час повернення до початкового значення дескриптора файла"
+
+#: src/readelf.c:792
+#, c-format
+msgid "'%s' is not an archive, cannot print archive index"
+msgstr "«%s» не є архівом, виведення покажчика архіву неможливе"
+
+#: src/readelf.c:896
+#, c-format
+msgid "cannot stat input file"
+msgstr "не вдалося отримати дані з вхідного файла за допомогою stat"
+
+#: src/readelf.c:898
+#, c-format
+msgid "input file is empty"
+msgstr "вхідний файл є порожнім"
+
+#: src/readelf.c:900
+#, c-format
+msgid "failed reading '%s': %s"
+msgstr "не вдалося прочитати «%s»: %s"
+
+#: src/readelf.c:929
+#, c-format
+msgid "No such section '%s' in '%s'"
+msgstr "У «%2$s» немає розділу «%1$s»"
+
+#: src/readelf.c:988
+#, c-format
+msgid "cannot read ELF header: %s"
+msgstr "не вдалося прочитати заголовок ELF: %s"
+
+#: src/readelf.c:996
+#, c-format
+msgid "cannot create EBL handle"
+msgstr "не вдалося створити дескриптор EBL"
+
+#: src/readelf.c:1007
+#, c-format
+msgid "cannot determine number of program headers: %s"
+msgstr "не вдалося визначити кількість заголовків програми: %s"
+
+#: src/readelf.c:1039
+#, c-format
+msgid "cannot read ELF: %s"
+msgstr "не вдалося прочитати ELF: %s"
+
+#: src/readelf.c:1072
+#, fuzzy
+#| msgid "cannot get section: %s"
+msgid "cannot find section"
+msgstr "не вдалося отримати розділ: %s"
+
+#: src/readelf.c:1109
+msgid "NONE (None)"
+msgstr "NONE (Немає)"
+
+#: src/readelf.c:1110
+msgid "REL (Relocatable file)"
+msgstr "REL (Придатний до пересування файл)"
+
+#: src/readelf.c:1111
+msgid "EXEC (Executable file)"
+msgstr "EXEC (Виконуваний файл)"
+
+#: src/readelf.c:1112
+msgid "DYN (Shared object file)"
+msgstr "DYN (Файл об’єктів спільного використання)"
+
+#: src/readelf.c:1113
+msgid "CORE (Core file)"
+msgstr "CORE (Файл ядра)"
+
+#: src/readelf.c:1118
+#, c-format
+msgid "OS Specific: (%x)\n"
+msgstr "ОС-специфічне: (%x)\n"
+
+#. && e_type <= ET_HIPROC always true
+#: src/readelf.c:1120
+#, c-format
+msgid "Processor Specific: (%x)\n"
+msgstr "Специфічне для процесора: (%x)\n"
+
+#: src/readelf.c:1130
+msgid ""
+"ELF Header:\n"
+"  Magic:  "
+msgstr ""
+"Заголовок ELF:\n"
+"  Magic:  "
+
+#: src/readelf.c:1134
+#, c-format
+msgid ""
+"\n"
+"  Class:                             %s\n"
+msgstr ""
+"\n"
+"  Клас:                              %s\n"
+
+#: src/readelf.c:1139
+#, c-format
+msgid "  Data:                              %s\n"
+msgstr "  Дані:                              %s\n"
+
+#: src/readelf.c:1145
+#, c-format
+msgid "  Ident Version:                     %hhd %s\n"
+msgstr "   Версія Ident:                     %hhd %s\n"
+
+#: src/readelf.c:1147 src/readelf.c:1169
+msgid "(current)"
+msgstr "(поточний)"
+
+#: src/readelf.c:1151
+#, c-format
+msgid "  OS/ABI:                            %s\n"
+msgstr "  ОС/ABI:                            %s\n"
+
+#: src/readelf.c:1154
+#, c-format
+msgid "  ABI Version:                       %hhd\n"
+msgstr "  Версія ABI:                       %hhd\n"
+
+#: src/readelf.c:1157
+msgid "  Type:                              "
+msgstr "  Тип:                                "
+
+#: src/readelf.c:1162
+#, c-format
+msgid "  Machine:                           %s\n"
+msgstr "  Архітектура:                       %s\n"
+
+#: src/readelf.c:1164
+#, c-format
+msgid "  Machine:                           <unknown>: 0x%x\n"
+msgstr "  Архітектура:                       <невідома>: 0x%x\n"
+
+#: src/readelf.c:1167
+#, c-format
+msgid "  Version:                           %d %s\n"
+msgstr "  Версія:                            %d %s\n"
+
+#: src/readelf.c:1171
+#, c-format
+msgid "  Entry point address:               %#<PRIx64>\n"
+msgstr "  Адреса вхідної точки:              %#<PRIx64>\n"
+
+#: src/readelf.c:1174
+#, c-format
+msgid "  Start of program headers:          %<PRId64> %s\n"
+msgstr "  Початок заголовків програм:      %<PRId64> %s\n"
+
+#: src/readelf.c:1175 src/readelf.c:1178
+msgid "(bytes into file)"
+msgstr "(байтів у файл)"
+
+#: src/readelf.c:1177
+#, c-format
+msgid "  Start of section headers:          %<PRId64> %s\n"
+msgstr "  Початок заголовків розділів:     %<PRId64> %s\n"
+
+#: src/readelf.c:1180
+#, c-format
+msgid "  Flags:                             %s\n"
+msgstr "  Прапорці:                          %s\n"
+
+#: src/readelf.c:1183
+#, c-format
+msgid "  Size of this header:               %<PRId16> %s\n"
+msgstr "  Розмір цього заголовка:            %<PRId16> %s\n"
+
+#: src/readelf.c:1184 src/readelf.c:1187 src/readelf.c:1204
+msgid "(bytes)"
+msgstr "(байтів)"
+
+#: src/readelf.c:1186
+#, c-format
+msgid "  Size of program header entries:    %<PRId16> %s\n"
+msgstr "  Розмір записів заголовка програми:  %<PRId16> %s\n"
+
+#: src/readelf.c:1189
+#, c-format
+msgid "  Number of program headers entries: %<PRId16>"
+msgstr "  Кількість записів заголовків програми: %<PRId16>"
+
+#: src/readelf.c:1196
+#, c-format
+msgid " (%<PRIu32> in [0].sh_info)"
+msgstr " (%<PRIu32> у [0].sh_info)"
+
+#: src/readelf.c:1199 src/readelf.c:1216 src/readelf.c:1230
+msgid " ([0] not available)"
+msgstr " ([0] недоступний)"
+
+#: src/readelf.c:1203
+#, c-format
+msgid "  Size of section header entries:    %<PRId16> %s\n"
+msgstr "  Розмір записів заголовків розділів:  %<PRId16> %s\n"
+
+#: src/readelf.c:1206
+#, c-format
+msgid "  Number of section headers entries: %<PRId16>"
+msgstr "  Кількість записів заголовків розділів: %<PRId16>"
+
+#: src/readelf.c:1213
+#, c-format
+msgid " (%<PRIu32> in [0].sh_size)"
+msgstr " (%<PRIu32> у [0].sh_size)"
+
+#. We managed to get the zeroth section.
+#: src/readelf.c:1226
+#, c-format
+msgid " (%<PRIu32> in [0].sh_link)"
+msgstr " (%<PRIu32> у [0].sh_link)"
+
+#: src/readelf.c:1234
+#, c-format
+msgid ""
+"  Section header string table index: XINDEX%s\n"
+"\n"
+msgstr ""
+"  Індекс заголовка розділу у таблиці рядків: XINDEX%s\n"
+"\n"
+
+#: src/readelf.c:1238
+#, c-format
+msgid ""
+"  Section header string table index: %<PRId16>\n"
+"\n"
+msgstr ""
+"  Індекс заголовка розділу у таблиці рядків: %<PRId16>\n"
+"\n"
+
+#: src/readelf.c:1288 src/readelf.c:1496
+#, c-format
+msgid "cannot get number of sections: %s"
+msgstr "не вдалося отримати кількість розділів: %s"
+
+#: src/readelf.c:1291
+#, c-format
+msgid ""
+"There are %zd section headers, starting at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"Виявлено %zd заголовків розділів, зміщення початку — %#<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:1299
+#, c-format
+msgid "cannot get section header string table index: %s"
+msgstr "не вдалося визначити індекс заголовка розділу у таблиці рядків: %s"
+
+#: src/readelf.c:1302
+msgid "Section Headers:"
+msgstr "Заголовки розділів:"
+
+#: src/readelf.c:1305
+msgid ""
+"[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk "
+"Inf Al"
+msgstr ""
+"[№ ] Назва                Тип          Адр      Змі    Розмір ES Прап  Lk "
+"Інф Al"
+
+#: src/readelf.c:1307
+msgid ""
+"[Nr] Name                 Type         Addr             Off      Size     ES "
+"Flags Lk Inf Al"
+msgstr ""
+"[№ ] Назва                Тип          Адр              Змі      Розмір   ES "
+"Прап  Lk Інф Al"
+
+#: src/readelf.c:1312
+msgid "     [Compression  Size   Al]"
+msgstr "     [Стискання    Розмір Ал]"
+
+#: src/readelf.c:1314
+msgid "     [Compression  Size     Al]"
+msgstr "     [Стискання    Розмір   Ал]"
+
+#: src/readelf.c:1392
+#, c-format
+msgid "bad compression header for section %zd: %s"
+msgstr "помилковий заголовок стиснення для розділу %zd: %s"
+
+#: src/readelf.c:1403
+#, c-format
+msgid "bad gnu compressed size for section %zd: %s"
+msgstr "помилкове значення стисненого розміру gnu для розділу %zd: %s"
+
+#: src/readelf.c:1421
+msgid "Program Headers:"
+msgstr "Заголовки програми:"
+
+#: src/readelf.c:1423
+msgid ""
+"  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"
+msgstr ""
+"  Тип            Зміщен   ВіртАдр    ФізАдр     РозмФайл РозмПам  Пра Вирів"
+
+#: src/readelf.c:1426
+msgid ""
+"  Type           Offset   VirtAddr           PhysAddr           FileSiz  "
+"MemSiz   Flg Align"
+msgstr ""
+"  Тип           Зміщен   ВіртАдр            ФізАдр             "
+"РозмФайлРозмПам  Пра Вирів"
+
+#: src/readelf.c:1483
+#, c-format
+msgid "\t[Requesting program interpreter: %s]\n"
+msgstr "\t[Запит щодо інтерпретатора програми: %s]\n"
+
+#: src/readelf.c:1508
+msgid ""
+"\n"
+" Section to Segment mapping:\n"
+"  Segment Sections..."
+msgstr ""
+"\n"
+" Відображення розділів на сегмент:\n"
+"  Розділи сегмента..."
+
+#: src/readelf.c:1519 src/unstrip.c:2165 src/unstrip.c:2207 src/unstrip.c:2214
+#, c-format
+msgid "cannot get program header: %s"
+msgstr "не вдалося отримати заголовок програми: %s"
+
+#: src/readelf.c:1663
+#, c-format
+msgid ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"COMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Група розділів COMDAT [%2zu] «%s» з підписом «%s» містить %zu запис:\n"
+msgstr[1] ""
+"\n"
+"Група розділів COMDAT [%2zu] «%s» з підписом «%s» містить %zu записи:\n"
+msgstr[2] ""
+"\n"
+"Група розділів COMDAT [%2zu] «%s» з підписом «%s» містить %zu записів:\n"
+
+#: src/readelf.c:1668
+#, c-format
+msgid ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"Section group [%2zu] '%s' with signature '%s' contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Група розділів [%2zu] «%s» з підписом «%s» містить %zu запис:\n"
+msgstr[1] ""
+"\n"
+"Група розділів [%2zu] «%s» з підписом «%s» містить %zu записи:\n"
+msgstr[2] ""
+"\n"
+"Група розділів [%2zu] «%s» з підписом «%s» містить %zu записів:\n"
+
+#: src/readelf.c:1676
+msgid "<INVALID SYMBOL>"
+msgstr "<НЕКОРЕКТНИЙ СИМВОЛ>"
+
+#: src/readelf.c:1690
+msgid "<INVALID SECTION>"
+msgstr "<НЕКОРЕКТНИЙ РОЗДІЛ>"
+
+#: src/readelf.c:1713 src/readelf.c:2614 src/readelf.c:3913 src/readelf.c:4213
+#: src/readelf.c:13315 src/readelf.c:13322 src/readelf.c:13366
+#: src/readelf.c:13373
+msgid "Couldn't uncompress section"
+msgstr "Не вдалося розпакувати розділ"
+
+#: src/readelf.c:1717 src/readelf.c:2619 src/readelf.c:3917
+#, c-format
+msgid "cannot get section [%zd] header: %s"
+msgstr "не вдалося отримати заголовок розділу [%zd]: %s"
+
+#: src/readelf.c:1886 src/readelf.c:2860 src/readelf.c:3146 src/readelf.c:3221
+#: src/readelf.c:3524 src/readelf.c:3598 src/readelf.c:5963
+#, c-format
+msgid "invalid sh_link value in section %zu"
+msgstr "некоректне значення sh_link у розділі %zu"
+
+#: src/readelf.c:1889
+#, c-format
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Динамічний сегмент містить %lu запис:\n"
+" Адр: %#0*<PRIx64>  Зміщення: %#08<PRIx64>  Пос. на розділ: [%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Динамічний сегмент містить %lu записи:\n"
+" Адр: %#0*<PRIx64>  Зміщення: %#08<PRIx64>  Пос. на розділ: [%2u] '%s'\n"
+msgstr[2] ""
+"\n"
+"Динамічний сегмент містить %lu записів:\n"
+" Адр: %#0*<PRIx64>  Зміщення: %#08<PRIx64>  Пос. на розділ: [%2u] '%s'\n"
+
+#: src/readelf.c:1902
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| "Dynamic segment contains %lu entry:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+#| msgid_plural ""
+#| "\n"
+#| "Dynamic segment contains %lu entries:\n"
+#| " Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid ""
+"\n"
+"Dynamic segment contains %lu entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgid_plural ""
+"\n"
+"Dynamic segment contains %lu entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>\n"
+msgstr[0] ""
+"\n"
+"Динамічний сегмент містить %lu запис:\n"
+" Адр: %#0*<PRIx64>  Зміщення: %#08<PRIx64>  Пос. на розділ: [%2u] '%s'\n"
+msgstr[1] ""
+"\n"
+"Динамічний сегмент містить %lu записи:\n"
+" Адр: %#0*<PRIx64>  Зміщення: %#08<PRIx64>  Пос. на розділ: [%2u] '%s'\n"
+msgstr[2] ""
+"\n"
+"Динамічний сегмент містить %lu записів:\n"
+" Адр: %#0*<PRIx64>  Зміщення: %#08<PRIx64>  Пос. на розділ: [%2u] '%s'\n"
+
+#: src/readelf.c:1912
+msgid "  Type              Value\n"
+msgstr "  Тип              Значення\n"
+
+#: src/readelf.c:1921
+#, fuzzy
+#| msgid "cannot get string section data: %s"
+msgid "cannot get string table by using dynamic segment"
+msgstr "не вдалося отримати дані розділу рядків: %s"
+
+#: src/readelf.c:1960
+#, c-format
+msgid "Shared library: [%s]\n"
+msgstr "Спільна бібліотека: [%s]\n"
+
+#: src/readelf.c:1964
+#, c-format
+msgid "Library soname: [%s]\n"
+msgstr "Назва so бібліотеки: [%s]\n"
+
+#: src/readelf.c:1968
+#, c-format
+msgid "Library rpath: [%s]\n"
+msgstr "Rpath бібліотеки: [%s]\n"
+
+#: src/readelf.c:1972
+#, c-format
+msgid "Library runpath: [%s]\n"
+msgstr "Runpath бібліотеки: [%s]\n"
+
+#: src/readelf.c:1993
+#, c-format
+msgid "%<PRId64> (bytes)\n"
+msgstr "%<PRId64> (байт)\n"
+
+#: src/readelf.c:2109 src/readelf.c:2298
+#, c-format
+msgid ""
+"\n"
+"Invalid symbol table at offset %#0<PRIx64>\n"
+msgstr ""
+"\n"
+"Некоректна таблиця символів за зміщенням %#0<PRIx64>\n"
+
+#: src/readelf.c:2126 src/readelf.c:2315
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0<PRIx64> "
+"contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Розділ пересування [%2zu] «%s» для розділу [%2u] «%s» за зміщенням "
+"%#0<PRIx64> містить %d запис:\n"
+msgstr[1] ""
+"\n"
+"Розділ пересування [%2zu] «%s» для розділу [%2u] «%s» за зміщенням "
+"%#0<PRIx64> містить %d записи:\n"
+msgstr[2] ""
+"\n"
+"Розділ пересування [%2zu] «%s» для розділу [%2u] «%s» за зміщенням "
+"%#0<PRIx64> містить %d записів:\n"
+
+#. The .rel.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. The .rela.dyn section does not refer to a specific section but
+#. instead of section index zero.  Do not try to print a section
+#. name.
+#. A .relr.dyn section does not refer to a specific section.
+#: src/readelf.c:2141 src/readelf.c:2330 src/readelf.c:2485
+#, c-format
+msgid ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Relocation section [%2u] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Розділ пересування [%2u] «%s» за зміщенням %#0<PRIx64> містить %d запис:\n"
+msgstr[1] ""
+"\n"
+"Розділ пересування [%2u] «%s» за зміщенням %#0<PRIx64> містить %d записи:\n"
+msgstr[2] ""
+"\n"
+"Розділ пересування [%2u] «%s» за зміщенням %#0<PRIx64> містить %d записів:\n"
+
+#: src/readelf.c:2151
+msgid "  Offset      Type                 Value       Name\n"
+msgstr "  Зміщення     Тип                  Значення    Назва\n"
+
+#: src/readelf.c:2153
+msgid "  Offset              Type                 Value               Name\n"
+msgstr "  Зміщення            Тип                  Значення            Назва\n"
+
+#: src/readelf.c:2206 src/readelf.c:2217 src/readelf.c:2230 src/readelf.c:2251
+#: src/readelf.c:2263 src/readelf.c:2396 src/readelf.c:2408 src/readelf.c:2422
+#: src/readelf.c:2444 src/readelf.c:2457
+msgid "<INVALID RELOC>"
+msgstr "<НЕКОРЕКТНЕ ПЕРЕМІЩЕННЯ>"
+
+#: src/readelf.c:2340
+msgid "  Offset      Type            Value       Addend Name\n"
+msgstr "  Зміщення    Тип             Значення    Назва додатка\n"
+
+#: src/readelf.c:2342
+msgid "  Offset              Type            Value               Addend Name\n"
+msgstr ""
+"  Зміщення            Тип             Значення            Назва додатка\n"
+
+#: src/readelf.c:2654
+#, c-format
+msgid "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+msgstr "%5u: %0*<PRIx64> %6<PRId64> %-7s %-6s %-9s %6s %s"
+
+#: src/readelf.c:2750
+#, c-format
+msgid "bad dynamic symbol"
+msgstr "помилковий динамічний символ"
+
+#: src/readelf.c:2868
+#, c-format
+msgid ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entry:\n"
+msgid_plural ""
+"\n"
+"Symbol table [%2u] '%s' contains %u entries:\n"
+msgstr[0] ""
+"\n"
+"Таблиця символів [%2u] «%s» містить %u запис:\n"
+msgstr[1] ""
+"\n"
+"Таблиця символів [%2u] «%s» містить %u записи:\n"
+msgstr[2] ""
+"\n"
+"Таблиця символів [%2u] «%s» містить %u записів:\n"
+
+#: src/readelf.c:2873
+#, c-format
+msgid " %lu local symbol  String table: [%2u] '%s'\n"
+msgid_plural " %lu local symbols  String table: [%2u] '%s'\n"
+msgstr[0] " %lu лок. символ   Таблиця символів: [%2u] «%s»\n"
+msgstr[1] " %lu лок. символи  Таблиця символів: [%2u] «%s»\n"
+msgstr[2] " %lu лок. символів Таблиця символів: [%2u] «%s»\n"
+
+#: src/readelf.c:2881
+msgid "  Num:    Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  №№      Знач.   Роз. Тип     Зв’яз  Вид.         Інд Назва\n"
+
+#: src/readelf.c:2883
+msgid "  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"
+msgstr "  №№              Знач.   Роз. Тип     Зв’яз  Вид.         Інд Назва\n"
+
+#: src/readelf.c:3002
+msgid "Dynamic symbol information is not available for displaying symbols."
+msgstr ""
+
+#: src/readelf.c:3102
+msgid "none"
+msgstr "немає"
+
+#: src/readelf.c:3119
+msgid "| <unknown>"
+msgstr "| <невідомо>"
+
+#: src/readelf.c:3149
+#, c-format
+msgid ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version needs section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Розділ потреби у версіях [%2u] «%s», що містить %d запис:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+msgstr[1] ""
+"\n"
+"Розділ потреби у версіях [%2u] «%s», що містить %d записи:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+msgstr[2] ""
+"\n"
+"Розділ потреби у версіях [%2u] «%s», що містить %d записів:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+
+#: src/readelf.c:3170
+#, c-format
+msgid "  %#06x: Version: %hu  File: %s  Cnt: %hu\n"
+msgstr "  %#06x: Версія: %hu  Файл: %s  Кть: %hu\n"
+
+#: src/readelf.c:3183
+#, c-format
+msgid "  %#06x: Name: %s  Flags: %s  Version: %hu\n"
+msgstr "  %#06x: Назва: %s  Прап: %s  Версія: %hu\n"
+
+#: src/readelf.c:3225
+#, c-format
+msgid ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Version definition section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Розділ визначення версії [%2u] «%s», що містить %d запис:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+msgstr[1] ""
+"\n"
+"Розділ визначення версії [%2u] «%s», що містить %d записи:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+msgstr[2] ""
+"\n"
+"Розділ визначення версії [%2u] «%s», що містить %d записів:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+
+#: src/readelf.c:3253
+#, c-format
+msgid "  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"
+msgstr "  %#06x: Версія:  %hd  Прап.: %s  Індекс: %hd К-ть: %hd Назва: %s\n"
+
+#: src/readelf.c:3268
+#, c-format
+msgid "  %#06x: Parent %d: %s\n"
+msgstr "  %#06x: батьківський %d: %s\n"
+
+#. Print the header.
+#: src/readelf.c:3528
+#, c-format
+msgid ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entry:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgid_plural ""
+"\n"
+"Version symbols section [%2u] '%s' contains %d entries:\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'"
+msgstr[0] ""
+"\n"
+"Розділ символів версій [%2u] «%s», що містить %d запис:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»"
+msgstr[1] ""
+"\n"
+"Розділ символів версій [%2u] «%s», що містить %d записи:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»"
+msgstr[2] ""
+"\n"
+"Розділ символів версій [%2u] «%s», що містить %d записів:\n"
+" Адр.: %#0*<PRIx64>  Зміщ.:  %#08<PRIx64>  Посилання на розділ: [%2u] «%s»"
+
+#: src/readelf.c:3556
+msgid "   0 *local*                     "
+msgstr "   0 *локальний*                 "
+
+#: src/readelf.c:3561
+msgid "   1 *global*                    "
+msgstr "   1 *загальний*                 "
+
+#: src/readelf.c:3603
+#, c-format
+msgid ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"bucket):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgid_plural ""
+"\n"
+"Histogram for bucket list length in section [%2u] '%s' (total of %d "
+"buckets):\n"
+" Addr: %#0*<PRIx64>  Offset: %#08<PRIx64>  Link to section: [%2u] '%s'\n"
+msgstr[0] ""
+"\n"
+"Гістограма довжин списків блоків у розділі [%2u] «%s» (загальні дані за %d "
+"блоком):\n"
+" Адр.: %#0*<PRIx64>  Зміщ.: %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+msgstr[1] ""
+"\n"
+"Гістограма довжин списків блоків у розділі [%2u] «%s» (загальні дані за %d "
+"блоками):\n"
+" Адр.: %#0*<PRIx64>  Зміщ.: %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+msgstr[2] ""
+"\n"
+"Гістограма довжин списків блоків у розділі [%2u] «%s» (загальні дані за %d "
+"блоками):\n"
+" Адр.: %#0*<PRIx64>  Зміщ.: %#08<PRIx64>  Посилання на розділ: [%2u] «%s»\n"
+
+#: src/readelf.c:3625
+#, no-c-format
+msgid " Length  Number  % of total  Coverage\n"
+msgstr " Довжина Номер   % від загал. Покриття\n"
+
+#: src/readelf.c:3627
+#, c-format
+msgid "      0  %6<PRIu32>      %5.1f%%\n"
+msgstr "      0  %6<PRIu32>      %5.1f%%\n"
+
+#: src/readelf.c:3634
+#, c-format
+msgid "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+msgstr "%7d  %6<PRIu32>      %5.1f%%    %5.1f%%\n"
+
+#: src/readelf.c:3648
+#, c-format
+msgid ""
+" Average number of tests:   successful lookup: %f\n"
+"\t\t\t  unsuccessful lookup: %f\n"
+msgstr ""
+" Середня кількість тестів:   успішний пошук: %f\n"
+"\t\t\t  неуспішний пошук: %f\n"
+
+#: src/readelf.c:3666 src/readelf.c:3730 src/readelf.c:3796
+#, c-format
+msgid "cannot get data for section %d: %s"
+msgstr "не вдалося отримати дані для розділу %d: %s"
+
+#: src/readelf.c:3674
+#, c-format
+msgid "invalid data in sysv.hash section %d"
+msgstr "некоректні дані у розділі sysv.hash %d"
+
+#: src/readelf.c:3703
+#, c-format
+msgid "invalid chain in sysv.hash section %d"
+msgstr "некоректний ланцюжок у розділі sysv.hash %d"
+
+#: src/readelf.c:3738
+#, c-format
+msgid "invalid data in sysv.hash64 section %d"
+msgstr "некоректні дані у розділі sysv.hash64 %d"
+
+#: src/readelf.c:3769
+#, c-format
+msgid "invalid chain in sysv.hash64 section %d"
+msgstr "некоректний ланцюжок у розділі sysv.hash64 %d"
+
+#: src/readelf.c:3805
+#, c-format
+msgid "invalid data in gnu.hash section %d"
+msgstr "некоректні дані у розділі gnu.hash %d"
+
+#: src/readelf.c:3871
+#, c-format
+msgid ""
+" Symbol Bias: %u\n"
+" Bitmask Size: %zu bytes  %<PRIuFAST32>%% bits set  2nd hash shift: %u\n"
+msgstr ""
+" Відхилення символу: %u\n"
+" Розмір бітової маски: %zu байтів  %<PRIuFAST32>%% встановлених бітів  зсув "
+"2-го хешу: %u\n"
+
+#: src/readelf.c:3956
+#, c-format
+msgid ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entry:\n"
+msgid_plural ""
+"\n"
+"Library list section [%2zu] '%s' at offset %#0<PRIx64> contains %d entries:\n"
+msgstr[0] ""
+"\n"
+"Розділ списку бібліотек [%2zu] «%s» за зміщенням %#0<PRIx64> містить %d "
+"запис:\n"
+msgstr[1] ""
+"\n"
+"Розділ списку бібліотек [%2zu] «%s» за зміщенням %#0<PRIx64> містить %d "
+"записи:\n"
+msgstr[2] ""
+"\n"
+"Розділ списку бібліотек [%2zu] «%s» за зміщенням %#0<PRIx64> містить %d "
+"записів:\n"
+
+#: src/readelf.c:3970
+msgid ""
+"       Library                       Time Stamp          Checksum Version "
+"Flags"
+msgstr ""
+"       Бібліотека                    Часовий штамп       Версія суми      "
+"Прапорці"
+
+#: src/readelf.c:4030
+#, c-format
+msgid ""
+"\n"
+"Object attributes section [%2zu] '%s' of %<PRIu64> bytes at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Розділ атрибутів об’єктів [%2zu] «%s» з %<PRIu64> байтів за зміщенням "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:4047
+msgid "  Owner          Size\n"
+msgstr "  Власник        Розмір\n"
+
+#: src/readelf.c:4071
+#, c-format
+msgid "  %-13s  %4<PRIu32>\n"
+msgstr "  %-13s  %4<PRIu32>\n"
+
+#. Unknown subsection, print and skip.
+#: src/readelf.c:4110
+#, c-format
+msgid "    %-4u %12<PRIu32>\n"
+msgstr "    %-4u %12<PRIu32>\n"
+
+#. Tag_File
+#: src/readelf.c:4115
+#, c-format
+msgid "    File: %11<PRIu32>\n"
+msgstr "    Файл: %11<PRIu32>\n"
+
+#: src/readelf.c:4165
+#, c-format
+msgid "      %s: %<PRId64>, %s\n"
+msgstr "      %s: %<PRId64>, %s\n"
+
+#: src/readelf.c:4168
+#, c-format
+msgid "      %s: %<PRId64>\n"
+msgstr "      %s: %<PRId64>\n"
+
+#: src/readelf.c:4171
+#, c-format
+msgid "      %s: %s\n"
+msgstr "      %s: %s\n"
+
+#: src/readelf.c:4181
+#, c-format
+msgid "      %u: %<PRId64>\n"
+msgstr "      %u: %<PRId64>\n"
+
+#: src/readelf.c:4184
+#, c-format
+msgid "      %u: %s\n"
+msgstr "      %u: %s\n"
+
+#: src/readelf.c:4222
+#, fuzzy
+#| msgid "couldn't get shdr for group section: %s"
+msgid "Couldn't get data from section"
+msgstr "не вдалося отримати shdr для розділу груп: %s"
+
+#: src/readelf.c:4287
+msgid "sprintf failure"
+msgstr "помилка sprintf"
+
+#: src/readelf.c:4771
+msgid "empty block"
+msgstr "порожній блок"
+
+#: src/readelf.c:4774
+#, c-format
+msgid "%zu byte block:"
+msgstr "%zu-байтовий блок:"
+
+#: src/readelf.c:5252
+#, c-format
+msgid "%*s[%2<PRIuMAX>] %s  <TRUNCATED>\n"
+msgstr "%*s[%2<PRIuMAX>] %s  <ОБРІЗАНО>\n"
+
+#: src/readelf.c:5424
+#, c-format
+msgid "%s %#<PRIx64> used with different address sizes"
+msgstr "%s %#<PRIx64> використано з різними розмірами адрес"
+
+#: src/readelf.c:5431
+#, c-format
+msgid "%s %#<PRIx64> used with different offset sizes"
+msgstr "%s %#<PRIx64> використано з різними розмірами зміщень"
+
+#: src/readelf.c:5438
+#, c-format
+msgid "%s %#<PRIx64> used with different base addresses"
+msgstr "%s %#<PRIx64> використано з різними базовими адресами"
+
+#: src/readelf.c:5445
+#, c-format
+msgid "%s %#<PRIx64> used with different attribute %s and %s"
+msgstr "%s %#<PRIx64> використано з різними атрибутами, %s і %s"
+
+#: src/readelf.c:5545
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"
+msgstr " [%6tx]  <НЕВИКОРИСТОВУВАНІ ДАНІ У РЕШТІ РОЗДІЛУ>\n"
+
+#: src/readelf.c:5553
+#, c-format
+msgid " [%6tx]  <UNUSED GARBAGE> ... %<PRIu64> bytes ...\n"
+msgstr " [%6tx]  <НЕВИКОРИСТОВУВАНІ ДАНІ> ... %<PRIu64> байтів ...\n"
+
+#: src/readelf.c:5659
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [ Code]\n"
+msgstr ""
+"\n"
+"Розділ DWARF [%2zu] «%s» зі зміщенням %#<PRIx64>:\n"
+" [ Код]\n"
+
+#: src/readelf.c:5667
+#, c-format
+msgid ""
+"\n"
+"Abbreviation section at offset %<PRIu64>:\n"
+msgstr ""
+"\n"
+"Розділ скорочень за зміщенням %<PRIu64>:\n"
+
+#: src/readelf.c:5680
+#, c-format
+msgid " *** error while reading abbreviation: %s\n"
+msgstr " *** помилка під час читання скорочення: %s\n"
+
+#: src/readelf.c:5696
+#, c-format
+msgid " [%5u] offset: %<PRId64>, children: %s, tag: %s\n"
+msgstr " [%5u] зміщення: %<PRId64>, дочірній: %s, мітка: %s\n"
+
+#: src/readelf.c:5733 src/readelf.c:6026 src/readelf.c:6197 src/readelf.c:6568
+#: src/readelf.c:7194 src/readelf.c:8963 src/readelf.c:9705 src/readelf.c:10173
+#: src/readelf.c:10428 src/readelf.c:10590 src/readelf.c:10971
+#: src/readelf.c:11042
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"Розділ DWARF [%2zu] «%s» зі зміщенням %#<PRIx64>:\n"
+
+#: src/readelf.c:5836 src/readelf.c:5860 src/readelf.c:6233 src/readelf.c:9741
+#, c-format
+msgid " Length:         %8<PRIu64>\n"
+msgstr " Довжина:        %8<PRIu64>\n"
+
+#: src/readelf.c:5838 src/readelf.c:5875 src/readelf.c:6246 src/readelf.c:9754
+#, c-format
+msgid " DWARF version:  %8<PRIu16>\n"
+msgstr " версія DWARF:   %8<PRIu16>\n"
+
+#: src/readelf.c:5839 src/readelf.c:5884 src/readelf.c:6255 src/readelf.c:9763
+#, c-format
+msgid " Address size:   %8<PRIu64>\n"
+msgstr " Розмір адреси:  %8<PRIu64>\n"
+
+#: src/readelf.c:5841 src/readelf.c:5894 src/readelf.c:6265 src/readelf.c:9773
+#, c-format
+msgid " Segment size:   %8<PRIu64>\n"
+msgstr ""
+" Розмір сегмента: %8<PRIu64>\n"
+"\n"
+
+#: src/readelf.c:5879 src/readelf.c:6250 src/readelf.c:9758 src/readelf.c:11164
+#, c-format
+msgid "Unknown version"
+msgstr "Невідома версія"
+
+#: src/readelf.c:5889 src/readelf.c:6096 src/readelf.c:6260 src/readelf.c:9768
+#, c-format
+msgid "unsupported address size"
+msgstr "непідтримуваний розмір адреси"
+
+#: src/readelf.c:5900 src/readelf.c:6107 src/readelf.c:6270 src/readelf.c:9778
+#, c-format
+msgid "unsupported segment size"
+msgstr "непідтримуваний розмір сегмента"
+
+#: src/readelf.c:5953
+#, c-format
+msgid "cannot get .debug_aranges content: %s"
+msgstr "не вдалося отримати дані get .debug_aranges: %s"
+
+#: src/readelf.c:5968
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entry:\n"
+msgid_plural ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64> contains %zu entries:\n"
+msgstr[0] ""
+"\n"
+"Розділ DWARF [%2zu] «%s» за зміщенням %#<PRIx64> містить %zu запис:\n"
+msgstr[1] ""
+"\n"
+"Розділ DWARF [%2zu] «%s» за зміщенням %#<PRIx64> містить %zu записи:\n"
+msgstr[2] ""
+"\n"
+"Розділ DWARF [%2zu] «%s» за зміщенням %#<PRIx64> містить %zu записів:\n"
+
+#: src/readelf.c:5999
+#, c-format
+msgid " [%*zu] ???\n"
+msgstr " [%*zu] ???\n"
+
+#: src/readelf.c:6001
+#, c-format
+msgid ""
+" [%*zu] start: %0#*<PRIx64>, length: %5<PRIu64>, CU DIE offset: %6<PRId64>\n"
+msgstr ""
+" [%*zu] початок: %0#*<PRIx64>, довжина: %5<PRIu64>, зміщення CU DIE: "
+"%6<PRId64>\n"
+
+#: src/readelf.c:6039 src/readelf.c:8982
+#, c-format
+msgid ""
+"\n"
+"Table at offset %zu:\n"
+msgstr ""
+"\n"
+"Таблиця за зміщенням %zu:\n"
+
+#: src/readelf.c:6043 src/readelf.c:6214 src/readelf.c:7218 src/readelf.c:8993
+#: src/readelf.c:9722
+#, c-format
+msgid "invalid data in section [%zu] '%s'"
+msgstr "некоректні дані у розділі [%zu] «%s»"
+
+#: src/readelf.c:6059
+#, c-format
+msgid ""
+"\n"
+" Length:        %6<PRIu64>\n"
+msgstr ""
+"\n"
+" Довжина:       %6<PRIu64>\n"
+
+#: src/readelf.c:6071
+#, c-format
+msgid " DWARF version: %6<PRIuFAST16>\n"
+msgstr " версія DWARF:  %6<PRIuFAST16>\n"
+
+#: src/readelf.c:6075
+#, c-format
+msgid "unsupported aranges version"
+msgstr "непідтримувана версія aranges"
+
+#: src/readelf.c:6086
+#, c-format
+msgid " CU offset:     %6<PRIx64>\n"
+msgstr " зміщення CU:     %6<PRIx64>\n"
+
+#: src/readelf.c:6092
+#, c-format
+msgid " Address size:  %6<PRIu64>\n"
+msgstr " Розмір адреси:  %6<PRIu64>\n"
+
+#: src/readelf.c:6103
+#, c-format
+msgid ""
+" Segment size:  %6<PRIu64>\n"
+"\n"
+msgstr ""
+" Розмір сегмента:  %6<PRIu64>\n"
+"\n"
+
+#: src/readelf.c:6158
+#, c-format
+msgid "   %zu padding bytes\n"
+msgstr "   %zu байтів доповнення\n"
+
+#: src/readelf.c:6220 src/readelf.c:9728
+#, c-format
+msgid ""
+"Table at Offset 0x%<PRIx64>:\n"
+"\n"
+msgstr ""
+"Таблиця за зміщенням 0x%<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:6275 src/readelf.c:9783
+#, c-format
+msgid " Offset entries: %8<PRIu64>\n"
+msgstr " Записи зміщення: %8<PRIu64>\n"
+
+#: src/readelf.c:6291 src/readelf.c:9799
+#, c-format
+msgid " Unknown CU base: "
+msgstr " Невідома основа CU: "
+
+#: src/readelf.c:6293 src/readelf.c:9801
+#, c-format
+msgid " CU [%6<PRIx64>] base: "
+msgstr " Основа CU [%6<PRIx64>]: "
+
+#: src/readelf.c:6299 src/readelf.c:9807
+#, c-format
+msgid " Not associated with a CU.\n"
+msgstr " Не пов'язано із CU.\n"
+
+#: src/readelf.c:6310 src/readelf.c:9818
+#, c-format
+msgid "too many offset entries for unit length"
+msgstr "забагато записів зсуву для довжини модуля"
+
+#: src/readelf.c:6314 src/readelf.c:9822
+#, c-format
+msgid "  Offsets starting at 0x%<PRIx64>:\n"
+msgstr "  Зміщення, що починаються з 0x%<PRIx64>:\n"
+
+#: src/readelf.c:6366
+#, c-format
+msgid "invalid range list data"
+msgstr "некоректні дані списку діапазонів"
+
+#: src/readelf.c:6551 src/readelf.c:10157
+#, c-format
+msgid ""
+"   %zu padding bytes\n"
+"\n"
+msgstr ""
+"   %zu байтів доповнення\n"
+"\n"
+
+#: src/readelf.c:6599 src/readelf.c:10206
+#, c-format
+msgid ""
+"\n"
+" Unknown CU base: "
+msgstr ""
+"\n"
+" Невідома основа CU: "
+
+#: src/readelf.c:6601 src/readelf.c:10208
+#, c-format
+msgid ""
+"\n"
+" CU [%6<PRIx64>] base: "
+msgstr ""
+"\n"
+" Основа CU [%6<PRIx64>]: "
+
+#: src/readelf.c:6610 src/readelf.c:10234 src/readelf.c:10260
+#, c-format
+msgid " [%6tx]  <INVALID DATA>\n"
+msgstr " [%6tx]  <НЕКОРЕКТНІ ДАНІ>\n"
+
+#: src/readelf.c:6635 src/readelf.c:10344
+#, fuzzy
+msgid "base address"
+msgstr " встановити адресу у значення "
+
+#: src/readelf.c:6645 src/readelf.c:10354
+#, c-format
+msgid " [%6tx] empty list\n"
+msgstr " [%6tx] порожній список\n"
+
+#: src/readelf.c:6909
+msgid "         <INVALID DATA>\n"
+msgstr "         <НЕКОРЕКТНІ ДАНІ>\n"
+
+#: src/readelf.c:7166
+#, c-format
+msgid "cannot get ELF: %s"
+msgstr "не вдалося отримати ELF: %s"
+
+#: src/readelf.c:7190
+#, c-format
+msgid ""
+"\n"
+"Call frame information section [%2zu] '%s' at offset %#<PRIx64>:\n"
+msgstr ""
+"\n"
+"Розділ відомостей щодо вікна викликів [%2zu] «%s» за зміщенням %#<PRIx64>:\n"
+
+#: src/readelf.c:7240
+#, c-format
+msgid ""
+"\n"
+" [%6tx] Zero terminator\n"
+msgstr ""
+"\n"
+" [%6tx] нульовий переривач\n"
+
+#: src/readelf.c:7344 src/readelf.c:7498
+#, c-format
+msgid "invalid augmentation length"
+msgstr "некоректна довжина збільшення"
+
+#: src/readelf.c:7359
+msgid "FDE address encoding: "
+msgstr "Кодування адреси FDE: "
+
+#: src/readelf.c:7365
+msgid "LSDA pointer encoding: "
+msgstr "Кодування вказівника LSDA: "
+
+#: src/readelf.c:7475
+#, c-format
+msgid " (offset: %#<PRIx64>)"
+msgstr " (зміщення: %#<PRIx64>)"
+
+#: src/readelf.c:7482
+#, c-format
+msgid " (end offset: %#<PRIx64>)"
+msgstr " (зміщення від кінця: %#<PRIx64>)"
+
+#: src/readelf.c:7519
+#, c-format
+msgid "   %-26sLSDA pointer: %#<PRIx64>\n"
+msgstr "   %-26sвказівник LSDA: %#<PRIx64>\n"
+
+#: src/readelf.c:7604
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute code: %s"
+msgstr "DIE [%<PRIx64>] не вдалося отримати код атрибута: %s"
+
+#: src/readelf.c:7614
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute form: %s"
+msgstr "DIE [%<PRIx64>] не вдалося отримати форму атрибута: %s"
+
+#: src/readelf.c:7636
+#, c-format
+msgid "DIE [%<PRIx64>] cannot get attribute '%s' (%s) value: %s"
+msgstr "DIE [%<PRIx64>] не вдалося отримати значення атрибута «%s» (%s): %s"
+
+#: src/readelf.c:7966
+#, c-format
+msgid "invalid file (%<PRId64>): %s"
+msgstr "некоректний файл (%<PRId64>): %s"
+
+#: src/readelf.c:7970
+#, c-format
+msgid "no srcfiles for CU [%<PRIx64>]"
+msgstr "немає srcfiles для CU [%<PRIx64>]"
+
+#: src/readelf.c:7974
+#, c-format
+msgid "couldn't get DWARF CU: %s"
+msgstr "не вдалося отримати CU DWARF: %s"
+
+#: src/readelf.c:8296
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" [Offset]\n"
+msgstr ""
+"\n"
+"Розділ DWARF [%2zu] «%s» за зміщенням %#<PRIx64>:\n"
+" [Зміщення]\n"
+
+#: src/readelf.c:8346
+#, c-format
+msgid "cannot get next unit: %s"
+msgstr "не вдалося отримати наступний модуль: %s"
+
+#: src/readelf.c:8366
+#, c-format
+msgid ""
+" Type unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+" Type signature: %#<PRIx64>, Type offset: %#<PRIx64> [%<PRIx64>]\n"
+msgstr ""
+" Модуль типів за зміщенням %<PRIu64>:\n"
+" Версія: %<PRIu16>, Зміщення розділу скорочень: %<PRIu64>, Розмір адреси: "
+"%<PRIu8>, Розмір зміщення: %<PRIu8>\n"
+" Підпис типу: %#<PRIx64>, Зміщення типу: %#<PRIx64> [%<PRIx64>]\n"
+
+#: src/readelf.c:8378
+#, c-format
+msgid ""
+" Compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+" Модуль компіляції за зміщенням %<PRIu64>:\n"
+" Версія: %<PRIu16>, Зміщення розділу скорочень: %<PRIu64>, Адреса: %<PRIu8>, "
+"Зміщення: %<PRIu8>\n"
+
+#: src/readelf.c:8388 src/readelf.c:8549
+#, c-format
+msgid " Unit type: %s (%<PRIu8>)"
+msgstr " Тип модуля: %s (%<PRIu8>)"
+
+#: src/readelf.c:8415
+#, c-format
+msgid "unknown version (%d) or unit type (%d)"
+msgstr "невідома версія (%d) або тип модуля (%d)"
+
+#: src/readelf.c:8444
+#, c-format
+msgid "cannot get DIE offset: %s"
+msgstr "не вдалося отримати зміщення DIE: %s"
+
+#: src/readelf.c:8453
+#, c-format
+msgid "cannot get tag of DIE at offset [%<PRIx64>] in section '%s': %s"
+msgstr ""
+"не вдалося отримати мітку DIE за зміщенням [%<PRIu64>] у розділі «%s»: %s"
+
+#: src/readelf.c:8489
+#, c-format
+msgid "cannot get next DIE: %s\n"
+msgstr "не вдалося визначити наступний DIE: %s\n"
+
+#: src/readelf.c:8497
+#, c-format
+msgid "cannot get next DIE: %s"
+msgstr "не вдалося визначити наступний DIE: %s"
+
+#: src/readelf.c:8541
+#, c-format
+msgid ""
+" Split compilation unit at offset %<PRIu64>:\n"
+" Version: %<PRIu16>, Abbreviation section offset: %<PRIu64>, Address size: "
+"%<PRIu8>, Offset size: %<PRIu8>\n"
+msgstr ""
+" Модуль розділеної компіляції за зміщенням %<PRIu64>:\n"
+" Версія: %<PRIu16>, Зміщення розділу скорочень: %<PRIu64>, Адреса: %<PRIu8>, "
+"Зміщення: %<PRIu8>\n"
+
+#: src/readelf.c:8593
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+"\n"
+msgstr ""
+"\n"
+"Розділ DWARF [%2zu] «%s» зі зміщенням %#<PRIx64>:\n"
+"\n"
+
+#: src/readelf.c:8925
+#, c-format
+msgid "unknown form: %s"
+msgstr "невідома форма: %s"
+
+#. Print what we got so far.
+#: src/readelf.c:9073
+#, c-format
+msgid ""
+"\n"
+" Length:                         %<PRIu64>\n"
+" DWARF version:                  %<PRIuFAST16>\n"
+" Prologue length:                %<PRIu64>\n"
+" Address size:                   %zd\n"
+" Segment selector size:          %zd\n"
+" Min instruction length:         %<PRIuFAST8>\n"
+" Max operations per instruction: %<PRIuFAST8>\n"
+" Initial value if 'is_stmt':     %<PRIuFAST8>\n"
+" Line base:                      %<PRIdFAST8>\n"
+" Line range:                     %<PRIuFAST8>\n"
+" Opcode base:                    %<PRIuFAST8>\n"
+"\n"
+"Opcodes:\n"
+msgstr ""
+"\n"
+" Довжина:                    %<PRIu64>\n"
+" Версія DWARF:               %<PRIuFAST16>\n"
+" Довжина вступу:             %<PRIu64>\n"
+" Розмір адреси:                  %zd\n"
+" Розмір селектора сегментів:     %zd\n"
+" Мінімальна довж. інстр.:    %<PRIuFAST8>\n"
+" Макс. к-ть операцій на інструкцію: %<PRIuFAST8>\n"
+" Поч. значення, якщо «is_stmt»: %<PRIuFAST8>\n"
+" Основа рядків:              %<PRIdFAST8>\n"
+" Діапазон рядків:            %<PRIuFAST8>\n"
+" Основа кодів операцій:      %<PRIuFAST8>\n"
+"\n"
+"Коди операцій:\n"
+
+#: src/readelf.c:9095
+#, c-format
+msgid "cannot handle .debug_line version: %u\n"
+msgstr "не вдалося обробити версію .debug_line: %u\n"
+
+#: src/readelf.c:9103
+#, c-format
+msgid "cannot handle address size: %u\n"
+msgstr "не вдалося обробити розмір адреси: %u\n"
+
+#: src/readelf.c:9111
+#, c-format
+msgid "cannot handle segment selector size: %u\n"
+msgstr "не вдалося обробити розмір селектора сегментів: %u\n"
+
+#: src/readelf.c:9121
+#, c-format
+msgid "invalid data at offset %tu in section [%zu] '%s'"
+msgstr "некоректні дані зі зміщенням %tu у розділі [%zu] «%s»"
+
+#: src/readelf.c:9136
+#, c-format
+msgid "  [%*<PRIuFAST8>]  %hhu argument\n"
+msgid_plural "  [%*<PRIuFAST8>]  %hhu arguments\n"
+msgstr[0] "  [%*<PRIuFAST8>]  %hhu аргумент\n"
+msgstr[1] "  [%*<PRIuFAST8>]  %hhu аргументи\n"
+msgstr[2] "  [%*<PRIuFAST8>]  %hhu аргументів\n"
+
+#: src/readelf.c:9147
+msgid ""
+"\n"
+"Directory table:"
+msgstr ""
+"\n"
+"Таблиця каталогу:"
+
+#: src/readelf.c:9153 src/readelf.c:9230
+#, c-format
+msgid "      ["
+msgstr "      ["
+
+#: src/readelf.c:9224
+msgid ""
+"\n"
+"File name table:"
+msgstr ""
+"\n"
+" Таблиця назв файлів:"
+
+#: src/readelf.c:9285
+msgid " Entry Dir   Time      Size      Name"
+msgstr " Запис Кат   Час       Розмір    Назва"
+
+#: src/readelf.c:9331
+#, fuzzy
+msgid ""
+"\n"
+"No line number statements."
+msgstr ""
+"\n"
+"Оператори номерів рядків:"
+
+#: src/readelf.c:9335
+msgid ""
+"\n"
+"Line number statements:"
+msgstr ""
+"\n"
+"Оператори номерів рядків:"
+
+#: src/readelf.c:9350
+#, c-format
+msgid "invalid maximum operations per instruction is zero"
+msgstr "некоректну кількість операцій на інструкцію прирівняно до нуля"
+
+#: src/readelf.c:9384
+#, c-format
+msgid " special opcode %u: address+%u = "
+msgstr " спеціальний код операції %u: адреса+%u = "
+
+#: src/readelf.c:9388
+#, c-format
+msgid ", op_index = %u, line%+d = %zu\n"
+msgstr ", індекс_оп = %u, рядок%+d = %zu\n"
+
+#: src/readelf.c:9391
+#, c-format
+msgid ", line%+d = %zu\n"
+msgstr ", рядок%+d = %zu\n"
+
+#: src/readelf.c:9409
+#, c-format
+msgid " extended opcode %u: "
+msgstr " розширений код операції %u: "
+
+#: src/readelf.c:9414
+msgid " end of sequence"
+msgstr " кінець послідовності"
+
+#: src/readelf.c:9432
+#, c-format
+msgid " set address to "
+msgstr " встановити адресу у значення "
+
+#: src/readelf.c:9460
+#, c-format
+msgid " define new file: dir=%u, mtime=%<PRIu64>, length=%<PRIu64>, name=%s\n"
+msgstr ""
+" визначення нового файла: dir=%u, mtime=%<PRIu64>, довжина=%<PRIu64>, "
+"назва=%s\n"
+
+#: src/readelf.c:9474
+#, c-format
+msgid " set discriminator to %u\n"
+msgstr " встановити розрізнення для %u\n"
+
+#: src/readelf.c:9501
+#, c-format
+msgid " set inlined context %u, function name %s (0x%x)\n"
+msgstr ""
+
+#: src/readelf.c:9525
+#, fuzzy, c-format
+#| msgid "Also show function names"
+msgid " set function name %s (0x%x)\n"
+msgstr "Показувати також назви функцій"
+
+#. Unknown, ignore it.
+#: src/readelf.c:9532
+msgid " unknown opcode"
+msgstr " невідомий код операції"
+
+#. Takes no argument.
+#: src/readelf.c:9544
+msgid " copy"
+msgstr " копія"
+
+#: src/readelf.c:9555
+#, c-format
+msgid " advance address by %u to "
+msgstr " збільшення адреси на %u до "
+
+#: src/readelf.c:9559 src/readelf.c:9620
+#, c-format
+msgid ", op_index to %u"
+msgstr ", op_index до %u"
+
+#: src/readelf.c:9571
+#, c-format
+msgid " advance line by constant %d to %<PRId64>\n"
+msgstr " просувати рядок на сталу %d до %<PRId64>\n"
+
+#: src/readelf.c:9581
+#, c-format
+msgid " set file to %<PRIu64>\n"
+msgstr " встановити файл у %<PRIu64>\n"
+
+#: src/readelf.c:9592
+#, c-format
+msgid " set column to %<PRIu64>\n"
+msgstr " встановити значення стовпчика %<PRIu64>\n"
+
+#: src/readelf.c:9599
+#, c-format
+msgid " set '%s' to %<PRIuFAST8>\n"
+msgstr " встановити «%s» у %<PRIuFAST8>\n"
+
+#. Takes no argument.
+#: src/readelf.c:9605
+msgid " set basic block flag"
+msgstr " встановити прапорець базового блоку"
+
+#: src/readelf.c:9616
+#, c-format
+msgid " advance address by constant %u to "
+msgstr " збільшити адресу на сталу величину %u до "
+
+#: src/readelf.c:9636
+#, c-format
+msgid " advance address by fixed value %u to \n"
+msgstr " збільшити адресу на фіксовану величину %u до \n"
+
+#. Takes no argument.
+#: src/readelf.c:9646
+msgid " set prologue end flag"
+msgstr " встановити прапорець кінця вступу"
+
+#. Takes no argument.
+#: src/readelf.c:9651
+msgid " set epilogue begin flag"
+msgstr " встановити прапорець початку епілогу"
+
+#: src/readelf.c:9661
+#, c-format
+msgid " set isa to %u\n"
+msgstr " встановити isa у %u\n"
+
+#. This is a new opcode the generator but not we know about.
+#. Read the parameters associated with it but then discard
+#. everything.  Read all the parameters for this opcode.
+#: src/readelf.c:9670
+#, c-format
+msgid " unknown opcode with %<PRIu8> parameter:"
+msgid_plural " unknown opcode with %<PRIu8> parameters:"
+msgstr[0] " невідомий код операції з %<PRIu8> параметром:"
+msgstr[1] " невідомий код операції з %<PRIu8> параметрами:"
+msgstr[2] " невідомий код операції з %<PRIu8> параметрами:"
+
+#: src/readelf.c:9871
+#, fuzzy, c-format
+msgid "    <INVALID DATA>\n"
+msgstr "   <НЕКОРЕКТНІ ДАНІ>\n"
+
+#: src/readelf.c:9911
+#, c-format
+msgid "invalid loclists data"
+msgstr "некоректні дані loclists"
+
+#: src/readelf.c:10381 src/readelf.c:11426
+msgid "   <INVALID DATA>\n"
+msgstr "   <НЕКОРЕКТНІ ДАНІ>\n"
+
+#: src/readelf.c:10512
+#, c-format
+msgid "%*s*** non-terminated string at end of section"
+msgstr "%*s*** незавершений рядок наприкінці розділу"
+
+#: src/readelf.c:10535
+#, c-format
+msgid "%*s*** missing DW_MACINFO_start_file argument at end of section"
+msgstr "%*s*** пропущено аргумент DW_MACINFO_start_file наприкінці розділу"
+
+#: src/readelf.c:10630
+#, c-format
+msgid " Offset:             0x%<PRIx64>\n"
+msgstr " Зміщення:           0x%<PRIx64>\n"
+
+#: src/readelf.c:10642
+#, c-format
+msgid " Version:            %<PRIu16>\n"
+msgstr " Версія:             %<PRIu16>\n"
+
+#: src/readelf.c:10648 src/readelf.c:11547
+#, c-format
+msgid "  unknown version, cannot parse section\n"
+msgstr "  невідома версія, не вдалося обробити розділ\n"
+
+#: src/readelf.c:10655
+#, c-format
+msgid " Flag:               0x%<PRIx8>"
+msgstr " Прапорець:          0x%<PRIx8>"
+
+#: src/readelf.c:10684
+#, c-format
+msgid " Offset length:      %<PRIu8>\n"
+msgstr " Довжина зміщення:   %<PRIu8>\n"
+
+#: src/readelf.c:10692
+#, c-format
+msgid " .debug_line offset: 0x%<PRIx64>\n"
+msgstr " зміщення .debug_line: 0x%<PRIx64>\n"
+
+#: src/readelf.c:10717
+#, c-format
+msgid "  extension opcode table, %<PRIu8> items:\n"
+msgstr "  таблиця кодів операцій розширень, записів — %<PRIu8>:\n"
+
+#: src/readelf.c:10724
+#, c-format
+msgid "    [%<PRIx8>]"
+msgstr "    [%<PRIx8>]"
+
+#: src/readelf.c:10736
+#, c-format
+msgid " %<PRIu8> arguments:"
+msgstr " %<PRIu8> аргументів:"
+
+#: src/readelf.c:10751
+#, c-format
+msgid " no arguments."
+msgstr " немає аргументів."
+
+#: src/readelf.c:10952
+#, c-format
+msgid " [%5d] DIE offset: %6<PRId64>, CU DIE offset: %6<PRId64>, name: %s\n"
+msgstr ""
+" [%5d] зміщення DIE: %6<PRId64>, зміщення CU DIE: %6<PRId64>, назва: %s\n"
+
+#: src/readelf.c:11007
+#, c-format
+msgid ""
+"\n"
+"DWARF section [%2zu] '%s' at offset %#<PRIx64>:\n"
+" %*s  String\n"
+msgstr ""
+"\n"
+"Розділ DWARF [%2zu] «%s» зі зміщенням %#<PRIx64>:\n"
+" %*s  Рядок\n"
+
+#. TRANS: the debugstr| prefix makes the string unique.
+#: src/readelf.c:11012
+msgctxt "debugstr"
+msgid "Offset"
+msgstr ""
+
+#: src/readelf.c:11022
+#, c-format
+msgid " *** error, missing string terminator\n"
+msgstr " *** помилка, пропущено роздільник рядків\n"
+
+#: src/readelf.c:11144
+#, c-format
+msgid " Length:        %8<PRIu64>\n"
+msgstr " Довжина:       %8<PRIu64>\n"
+
+#: src/readelf.c:11146
+#, c-format
+msgid " Offset size:   %8<PRIu8>\n"
+msgstr " Розмір зсуву:   %8<PRIu8>\n"
+
+#: src/readelf.c:11160
+#, c-format
+msgid " DWARF version: %8<PRIu16>\n"
+msgstr " версія DWARF:  %8<PRIu16>\n"
+
+#: src/readelf.c:11169
+#, c-format
+msgid " Padding:       %8<PRIx16>\n"
+msgstr " Заповнення:     %8<PRIx16>\n"
+
+#: src/readelf.c:11223
+#, c-format
+msgid ""
+"\n"
+"Call frame search table section [%2zu] '.eh_frame_hdr':\n"
+msgstr ""
+"\n"
+"Розділ таблиці пошуку вікон виклику [%2zu] '.eh_frame_hdr':\n"
+
+#: src/readelf.c:11325
+#, c-format
+msgid ""
+"\n"
+"Exception handling table section [%2zu] '.gcc_except_table':\n"
+msgstr ""
+"\n"
+"Розділ таблиці обробки виключень [%2zu] '.gcc_except_table':\n"
+
+#: src/readelf.c:11348
+#, c-format
+msgid " LPStart encoding:    %#x "
+msgstr " Кодування LPStart:   %#x "
+
+#: src/readelf.c:11360
+#, c-format
+msgid " TType encoding:      %#x "
+msgstr " Кодування TType:     %#x "
+
+#: src/readelf.c:11377
+#, c-format
+msgid " Call site encoding:  %#x "
+msgstr " Кодування місця виклику:%#x "
+
+#: src/readelf.c:11392
+msgid ""
+"\n"
+" Call site table:"
+msgstr ""
+"\n"
+" Таблиця місця виклику:"
+
+#: src/readelf.c:11408
+#, c-format
+msgid ""
+" [%4u] Call site start:   %#<PRIx64>\n"
+"        Call site length:  %<PRIu64>\n"
+"        Landing pad:       %#<PRIx64>\n"
+"        Action:            %u\n"
+msgstr ""
+" [%4u] Поч. місця виклику:   %#<PRIx64>\n"
+"        Довж. місця виклику:  %<PRIu64>\n"
+"        Місце застосування:   %#<PRIx64>\n"
+"        Дія:                  %u\n"
+
+#: src/readelf.c:11481
+#, c-format
+msgid "invalid TType encoding"
+msgstr "некоректне кодування TType"
+
+#: src/readelf.c:11508
+#, c-format
+msgid ""
+"\n"
+"GDB section [%2zu] '%s' at offset %#<PRIx64> contains %<PRId64> bytes :\n"
+msgstr ""
+"\n"
+"Розділ GDB [%2zu] «%s» за зміщенням %#<PRIx64> містить %<PRId64> байтів:\n"
+
+#: src/readelf.c:11537
+#, c-format
+msgid " Version:         %<PRId32>\n"
+msgstr " Версія:          %<PRId32>\n"
+
+#: src/readelf.c:11556
+#, c-format
+msgid " CU offset:       %#<PRIx32>\n"
+msgstr " зміщення CU:     %#<PRIx32>\n"
+
+#: src/readelf.c:11563
+#, c-format
+msgid " TU offset:       %#<PRIx32>\n"
+msgstr " зміщення TU:      %#<PRIx32>\n"
+
+#: src/readelf.c:11570
+#, c-format
+msgid " address offset:  %#<PRIx32>\n"
+msgstr " зміщення адреси: %#<PRIx32>\n"
+
+#: src/readelf.c:11577
+#, c-format
+msgid " symbol offset:   %#<PRIx32>\n"
+msgstr " зміщення символу: %#<PRIx32>\n"
+
+#: src/readelf.c:11587
+#, fuzzy, c-format
+#| msgid " constant offset: %#<PRIx32>\n"
+msgid " shortcut offset: %#<PRIx32>\n"
+msgstr " стале зміщення:  %#<PRIx32>\n"
+
+#: src/readelf.c:11595
+#, c-format
+msgid " constant offset: %#<PRIx32>\n"
+msgstr " стале зміщення:  %#<PRIx32>\n"
+
+#: src/readelf.c:11609
+#, c-format
+msgid ""
+"\n"
+" CU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+" Список CU зі зміщенням %#<PRIx32> містить %zu записів:\n"
+
+#: src/readelf.c:11634
+#, c-format
+msgid ""
+"\n"
+" TU list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+" Список TU зі зміщенням %#<PRIx32> містить %zu записів:\n"
+
+#: src/readelf.c:11663
+#, c-format
+msgid ""
+"\n"
+" Address list at offset %#<PRIx32> contains %zu entries:\n"
+msgstr ""
+"\n"
+" Список адрес зі зміщенням %#<PRIx32> містить %zu записів:\n"
+
+#: src/readelf.c:11706
+#, c-format
+msgid ""
+"\n"
+" Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+" Таблиця символів за зміщенням %#<PRIx32> містить %zu позицій:\n"
+
+#: src/readelf.c:11791
+#, fuzzy, c-format
+#| msgid ""
+#| "\n"
+#| " Symbol table at offset %#<PRIx32> contains %zu slots:\n"
+msgid ""
+"\n"
+"Shortcut table at offset %#<PRIx32> contains %zu slots:\n"
+msgstr ""
+"\n"
+" Таблиця символів за зміщенням %#<PRIx32> містить %zu позицій:\n"
+
+#: src/readelf.c:11803
+#, c-format
+msgid "Language of main: %s\n"
+msgstr ""
+
+#: src/readelf.c:11804
+#, c-format
+msgid "Name of main: "
+msgstr ""
+
+#: src/readelf.c:11887
+#, c-format
+msgid "cannot get debug context descriptor: %s"
+msgstr "не вдалося отримати дескриптор контексту зневаджування: %s"
+
+#: src/readelf.c:12253 src/readelf.c:12873 src/readelf.c:12983
+#: src/readelf.c:13040
+#, c-format
+msgid "cannot convert core note data: %s"
+msgstr "не вдалося перетворити дані запису ядра: %s"
+
+#: src/readelf.c:12617
+#, c-format
+msgid ""
+"\n"
+"%*s... <repeats %u more times> ..."
+msgstr ""
+"\n"
+"%*s... <повторюється %u разів> ..."
+
+#: src/readelf.c:13119
+msgid "  Owner          Data size  Type\n"
+msgstr "  Власник        Розм. даних Тип\n"
+
+#: src/readelf.c:13147
+#, c-format
+msgid "  %-13.*s  %9<PRId32>  %s\n"
+msgstr "  %-13.*s  %9<PRId32>  %s\n"
+
+#: src/readelf.c:13199
+#, c-format
+msgid "cannot get content of note: %s"
+msgstr "не вдалося отримати вміст нотатки: %s"
+
+#: src/readelf.c:13232
+#, c-format
+msgid ""
+"\n"
+"Note section [%2zu] '%s' of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Розділ записів (note) [%2zu] «%s» з %<PRIu64> байтів за зміщенням "
+"%#0<PRIx64>:\n"
+
+#: src/readelf.c:13255
+#, c-format
+msgid ""
+"\n"
+"Note segment of %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Сегмент записів з %<PRIu64> байтів за зміщенням %#0<PRIx64>:\n"
+
+#: src/readelf.c:13302
+#, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no data to dump.\n"
+msgstr ""
+"\n"
+"У розділі [%zu] «%s» не міститься даних для створення дампу.\n"
+
+#: src/readelf.c:13329 src/readelf.c:13380
+#, c-format
+msgid "cannot get data for section [%zu] '%s': %s"
+msgstr "не вдалося отримати дані для розділу [%zu] «%s»: %s"
+
+#: src/readelf.c:13334
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Шіст. дамп розділу [%zu] «%s», %<PRIu64> байтів за зміщенням %#0<PRIx64>:\n"
+
+#: src/readelf.c:13339
+#, c-format
+msgid ""
+"\n"
+"Hex dump of section [%zu] '%s', %<PRIu64> bytes (%zd uncompressed) at offset "
+"%#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Шіст. дамп розділу [%zu] «%s», %<PRIu64> байтів (%zd нестиснено) за "
+"зміщенням %#0<PRIx64>:\n"
+
+#: src/readelf.c:13353
+#, c-format
+msgid ""
+"\n"
+"Section [%zu] '%s' has no strings to dump.\n"
+msgstr ""
+"\n"
+"У розділі [%zu] «%s» не міститься рядків для створення дампу.\n"
+
+#: src/readelf.c:13385
+#, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes at offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Розділ рядків [%zu] «%s» містить %<PRIu64> байтів за зміщенням %#0<PRIx64>:\n"
+
+#: src/readelf.c:13390
+#, c-format
+msgid ""
+"\n"
+"String section [%zu] '%s' contains %<PRIu64> bytes (%zd uncompressed) at "
+"offset %#0<PRIx64>:\n"
+msgstr ""
+"\n"
+"Рядок розділу [%zu] «%s» містить %<PRIu64> байти (%zd нестиснено) на "
+"зміщенні %#0<PRIx64>:\n"
+
+#: src/readelf.c:13438
+#, c-format
+msgid ""
+"\n"
+"section [%lu] does not exist"
+msgstr ""
+"\n"
+"розділу [%lu] не існує"
+
+#: src/readelf.c:13468
+#, c-format
+msgid ""
+"\n"
+"section '%s' does not exist"
+msgstr ""
+"\n"
+"розділу «%s» не існує"
+
+#: src/readelf.c:13523
+#, c-format
+msgid "cannot get symbol index of archive '%s': %s"
+msgstr "не вдалося отримати покажчик символів архіву «%s»: %s"
+
+#: src/readelf.c:13526
+#, c-format
+msgid ""
+"\n"
+"Archive '%s' has no symbol index\n"
+msgstr ""
+"\n"
+"У архіві «%s» немає покажчика символів\n"
+
+#: src/readelf.c:13530
+#, c-format
+msgid ""
+"\n"
+"Index of archive '%s' has %zu entries:\n"
+msgstr ""
+"\n"
+"Покажчик архіву «%s» містить %zu записів:\n"
+
+#: src/readelf.c:13548
+#, c-format
+msgid "cannot extract member at offset %zu in '%s': %s"
+msgstr "не вдалося видобути елемент за зміщенням %zu у «%s»: %s"
+
+#: src/readelf.c:13553
+#, c-format
+msgid "Archive member '%s' contains:\n"
+msgstr "Елемент архіву «%s» містить:\n"
+
+#: src/size.c:55
+msgid ""
+"Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  The default "
+"is `bsd'"
+msgstr ""
+"Використовувати формат виводу ФОРМАТ. ФОРМАТом може бути «bsd» або «sysv». "
+"Типовим є значення «bsd»"
+
+#: src/size.c:57
+msgid "Same as `--format=sysv'"
+msgstr "Те саме, що і «--format=sysv»"
+
+#: src/size.c:58
+msgid "Same as `--format=bsd'"
+msgstr "Те саме, що і «--format=bsd»"
+
+#: src/size.c:61
+msgid "Same as `--radix=10'"
+msgstr "Те саме, що і «--radix=10»"
+
+#: src/size.c:62
+msgid "Same as `--radix=8'"
+msgstr "Те саме, що і «--radix=8»"
+
+#: src/size.c:63
+msgid "Same as `--radix=16'"
+msgstr "Те саме, що і «--radix=16»"
+
+#: src/size.c:65
+msgid "Similar to `--format=sysv' output but in one line"
+msgstr "Вивід даних у форматі, подібному до «--format=sysv», але у один рядок"
+
+#: src/size.c:69
+msgid "Print size and permission flags for loadable segments"
+msgstr ""
+"Вивести розмір і прапорці прав доступу для придатних до завантаження "
+"сегментів"
+
+#: src/size.c:70
+msgid "Display the total sizes (bsd only)"
+msgstr "Показувати загальні розміри (лише bsd)"
+
+#. Short description of program.
+#: src/size.c:75
+msgid "List section sizes of FILEs (a.out by default)."
+msgstr "Показати розміри розділів ФАЙЛів (типово a.out)."
+
+#: src/size.c:239
+#, c-format
+msgid "Invalid format: %s"
+msgstr "Некоректний формат: %s"
+
+#: src/size.c:250
+#, c-format
+msgid "Invalid radix: %s"
+msgstr "Некоректна основа числення: %s"
+
+#: src/size.c:309
+#, c-format
+msgid "%s: file format not recognized"
+msgstr "%s: не вдалося розпізнати формат файла"
+
+#: src/size.c:327
+msgctxt "bsd"
+msgid "text"
+msgstr ""
+
+#: src/size.c:328
+msgctxt "bsd"
+msgid "data"
+msgstr ""
+
+#: src/size.c:329
+msgctxt "bsd"
+msgid "bss"
+msgstr ""
+
+#: src/size.c:330
+msgctxt "bsd"
+msgid "dec"
+msgstr ""
+
+#: src/size.c:331
+msgctxt "bsd"
+msgid "hex"
+msgstr ""
+
+#: src/size.c:332
+msgctxt "bsd"
+msgid "filename"
+msgstr ""
+
+#: src/size.c:416 src/size.c:557
+#, c-format
+msgid " (ex %s)"
+msgstr " (прикл. %s)"
+
+#: src/size.c:418
+#, fuzzy
+#| msgid "invalid section"
+msgctxt "sysv"
+msgid "section"
+msgstr "некоректний розділ"
+
+#: src/size.c:419
+msgctxt "sysv"
+msgid "size"
+msgstr ""
+
+#: src/size.c:420
+msgctxt "sysv"
+msgid "addr"
+msgstr ""
+
+#: src/size.c:449 src/size.c:452 src/size.c:455
+msgctxt "sysv"
+msgid "Total"
+msgstr ""
+
+#: src/size.c:479
+msgid "cannot get section header"
+msgstr "не вдалося отримати заголовок розділу"
+
+#: src/size.c:582
+msgid "(TOTALS)\n"
+msgstr "(ЗАГАЛОМ)\n"
+
+#: src/stack.c:487
+#, c-format
+msgid "-p PID should be a positive process id."
+msgstr "PID у -p PID має бути додатним значенням ідентифікатора процесу."
+
+#: src/stack.c:493
+#, c-format
+msgid "Cannot open core file '%s'"
+msgstr "Не вдалося відкрити файл дампу ядра «%s»"
+
+#: src/stack.c:553
+#, c-format
+msgid "-n MAXFRAMES should be 0 or higher."
+msgstr "MAXFRAMES у -n має бути значенням рівним 0 або більшим."
+
+#: src/stack.c:565
+#, c-format
+msgid "-e EXEC needs a core given by --core."
+msgstr "Для -e EXEC слід вказати ядро за допомогою --core."
+
+#: src/stack.c:569
+#, c-format
+msgid "-1 needs a thread id given by -p."
+msgstr "-1 слід передати ідентифікатор потоку виконання, заданого -p."
+
+#: src/stack.c:573
+#, c-format
+msgid "One of -p PID or --core COREFILE should be given."
+msgstr "Слід вказати -p PID або --core COREFILE."
+
+#: src/stack.c:645
+msgid "Show stack of process PID"
+msgstr "Вивести стек PID процесу"
+
+#: src/stack.c:647
+msgid "Show stack found in COREFILE"
+msgstr "Вивести стек, знайдений у COREFILE"
+
+#: src/stack.c:648
+msgid "(optional) EXECUTABLE that produced COREFILE"
+msgstr "(необов’язковий) EXECUTABLE, яким створено COREFILE"
+
+#: src/stack.c:652
+msgid "Output selection options:"
+msgstr "Параметри вибору виведених даних:"
+
+#: src/stack.c:654
+msgid "Additionally show frame activation"
+msgstr "Додатково вивести активацію вікна"
+
+#: src/stack.c:656
+msgid "Additionally try to lookup DWARF debuginfo name for frame address"
+msgstr ""
+"Додатково спробувати визначити назву файла даних діагностики DWARF для "
+"адреси вікна"
+
+#: src/stack.c:659
+msgid ""
+"Additionally show inlined function frames using DWARF debuginfo if available "
+"(implies -d)"
+msgstr ""
+"Додатково вивести вікна вбудованих функцій за допомогою даних діагностики "
+"DWARF, якщо такі є (використовується і -d)"
+
+#: src/stack.c:661
+msgid "Additionally show module file information"
+msgstr "Додатково вивести дані щодо файла модуля"
+
+#: src/stack.c:663
+msgid "Additionally show source file information"
+msgstr "Додатково вивести дані щодо файла початкового коду"
+
+#: src/stack.c:665
+msgid ""
+"Show all additional information (activation, debugname, inlines, module and "
+"source)"
+msgstr ""
+"Вивести усі додаткові дані (активацію, назву у системі діагностики, "
+"вбудовані функції, модуль і початковий файл)"
+
+#: src/stack.c:667
+msgid "Do not resolve address to function symbol name"
+msgstr "Не розгортати адресу до назви символу функції"
+
+#: src/stack.c:669
+msgid "Show raw function symbol names, do not try to demangle names"
+msgstr ""
+"Вивести назви символів функцій без обробки, не намагатися розшифрувати назви"
+
+#: src/stack.c:671
+msgid "Show module build-id, load address and pc offset"
+msgstr "Виводити ідентифікатор збирання, адресу завантаження та зсув модуля"
+
+#: src/stack.c:673
+msgid "Show the backtrace of only one thread"
+msgstr "Виводити зворотне трасування лише одного потоку"
+
+#: src/stack.c:675
+msgid "Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"
+msgstr ""
+"Виводити не більше MAXFRAMES на потік виконання (типове значення 256, 0 — не "
+"обмежувати)"
+
+#: src/stack.c:677
+msgid "Show module memory map with build-id, elf and debug files detected"
+msgstr ""
+"Вивести карту пам’яті модуля із виявленими ідентифікатором збирання, elf та "
+"файлами діагностичних даних"
+
+#: src/stack.c:685
+msgid ""
+"Print a stack for each thread in a process or core file.\n"
+"\n"
+"Program exits with return code 0 if all frames were shown without any "
+"errors.  If some frames were shown, but there were some non-fatal errors, "
+"possibly causing an incomplete backtrace, the program exits with return code "
+"1.  If no frames could be shown, or a fatal error occurred the program exits "
+"with return code 2.  If the program was invoked with bad or missing "
+"arguments it will exit with return code 64."
+msgstr ""
+"Вивести стек для кожного потоку у процесі або файлі дампу ядра.\n"
+"\n"
+"Програма завершує роботу з кодом виходу 0, якщо усі вікна було виведено без "
+"помилок. Якщо деякі вікна було показано, але сталися некритичні помилки, "
+"ймовірно спричинені неповними даними зворотного трасування, програма "
+"завершує роботу з кодом повернення 1. Якщо не вдалося вивести жодного вікна "
+"або сталася критична помилка, програма виходить з кодом повернення 2. Якщо "
+"програму було викликано з помилковими або пропущеними аргументами, програма "
+"завершить роботу з кодом виходу 64."
+
+#: src/stack.c:760
+#, c-format
+msgid "Couldn't show any frames."
+msgstr "Не вдалося вивести жодного вікна."
+
+#: src/strings.c:64
+msgid "Output Selection:"
+msgstr "Вибір виводу:"
+
+#: src/strings.c:65
+msgid "Scan entire file, not only loaded sections"
+msgstr "Шукати у всьому файлі, а не лише у завантажених розділах"
+
+#: src/strings.c:67
+msgid "Only NUL-terminated sequences of MIN-LEN characters or more are printed"
+msgstr ""
+"Буде виведено лише послідовності з не менше, ніж MIN-LEN символів, що "
+"завершуються на NUL"
+
+#: src/strings.c:68
+msgid ""
+"Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, "
+"{B,L} = 32-bit"
+msgstr ""
+"Визначення розмірності та порядку бітів символів: s = 7-бітові, S = 8-"
+"бітові, {b,l} = 16-бітові, {B,L} = 32-бітові"
+
+#: src/strings.c:72
+msgid "Print name of the file before each string."
+msgstr "Виводити назву файла перед кожним рядком."
+
+#: src/strings.c:74
+msgid "Print location of the string in base 8, 10, or 16 respectively."
+msgstr "Виводити адресу рядка за основами 8, 10 та 16, відповідно."
+
+#: src/strings.c:75
+msgid "Alias for --radix=o"
+msgstr "Замінник --radix=o"
+
+#. Short description of program.
+#: src/strings.c:82
+msgid "Print the strings of printable characters in files."
+msgstr "Вивести рядки файлів з символів, придатних для друку."
+
+#: src/strings.c:255 src/strings.c:290
+#, c-format
+msgid "invalid value '%s' for %s parameter"
+msgstr "некоректне значення «%s» параметра %s"
+
+#: src/strings.c:300
+msgid "invalid minimum length of matched string size"
+msgstr "некоректна мінімальна довжина розмірності рядка для порівняння"
+
+#: src/strings.c:583
+msgid "lseek failed"
+msgstr "помилка lseek"
+
+#: src/strings.c:600 src/strings.c:664
+msgid "re-mmap failed"
+msgstr "помилка повторного використання mmap"
+
+#: src/strings.c:637
+msgid "mprotect failed"
+msgstr "помилка mprotect"
+
+#: src/strings.c:726
+#, c-format
+msgid "Skipping section %zd '%s' data outside file"
+msgstr "Пропускаємо дані %zd «%s» поза файлом"
+
+#: src/strip.c:70
+msgid "Place stripped output into FILE"
+msgstr "Вивести дані після вилучення до ФАЙЛа"
+
+#: src/strip.c:71
+msgid "Extract the removed sections into FILE"
+msgstr "Видобути вилучені розділи до ФАЙЛа"
+
+#: src/strip.c:72
+msgid "Embed name FILE instead of -f argument"
+msgstr "Вбудувати назву ФАЙЛа замість аргументу -f"
+
+#: src/strip.c:76
+msgid "Remove all debugging symbols"
+msgstr "Вилучити всі символи зневаджування"
+
+#: src/strip.c:80
+msgid "Remove section headers (not recommended)"
+msgstr "Вилучити заголовки розділів (не рекомендовано)"
+
+#: src/strip.c:82
+msgid "Copy modified/access timestamps to the output"
+msgstr "Скопіювати часові позначки зміни/доступу до виведених даних"
+
+#: src/strip.c:84
+msgid ""
+"Resolve all trivial relocations between debug sections if the removed "
+"sections are placed in a debug file (only relevant for ET_REL files, "
+"operation is not reversible, needs -f)"
+msgstr ""
+"Розв’язати всі очевидні пересування між діагностичними розділами, якщо "
+"вилучені розділи було розташовано у діагностичному файлі (стосується лише "
+"файлів ET_REL, скасувати дію неможливо, потребує параметра -f)"
+
+#: src/strip.c:86
+msgid ""
+"Similar to --reloc-debug-sections, but resolve all trivial relocations "
+"between debug sections in place.  No other stripping is performed (operation "
+"is not reversible, incompatible with -f, -g, --remove-comment and --remove-"
+"section)"
+msgstr ""
+"Подібний до --reloc-debug-sections, або усі тривіальні переміщення між "
+"розділами діагностики вирішуються на місці. Додаткове очищення не "
+"виконується (дію неможливо скасувати, параметр несумісний із -f, -g, --"
+"remove-comment та --remove-section)"
+
+#: src/strip.c:88
+msgid "Remove .comment section"
+msgstr "Вилучити розділ .comment"
+
+#: src/strip.c:89
+msgid ""
+"Remove the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once.  Only non-allocated sections can be removed."
+msgstr ""
+"Вилучити іменований розділ. РОЗДІЛ є розширеним взірцем із символами-"
+"замінниками. Можна вказувати декілька розділів. Може бути вилучено лише "
+"нерозміщені у пам'яті розділи."
+
+#: src/strip.c:90
+msgid ""
+"Keep the named section.  SECTION is an extended wildcard pattern.  May be "
+"given more than once."
+msgstr ""
+"Зберегти іменований розділ. РОЗДІЛ є розширеним взірцем із символами-"
+"замінниками. Можна вказувати декілька розділів."
+
+#. Short description of program.
+#: src/strip.c:97
+msgid "Discard symbols from object files."
+msgstr "Відкинути символи з об’єктних файлів"
+
+#: src/strip.c:245
+msgid "--reloc-debug-sections used without -f"
+msgstr "--reloc-debug-sections використано без -f"
+
+#: src/strip.c:251
+msgid ""
+"--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --"
+"remove-section"
+msgstr ""
+"--reloc-debug-sections-only є несумісним із -f, -g, --remove-comment та --"
+"remove-section"
+
+#: src/strip.c:265
+msgid "Only one input file allowed together with '-o' and '-f'"
+msgstr ""
+"Разом з «-o» або «-f» можна використовувати лише один файл вхідних даних"
+
+#: src/strip.c:287
+#, c-format
+msgid "-f option specified twice"
+msgstr "параметр -f вказано двічі"
+
+#: src/strip.c:296
+#, c-format
+msgid "-F option specified twice"
+msgstr "параметр -F вказано двічі"
+
+#: src/strip.c:359
+#, c-format
+msgid "cannot both keep and remove .comment section"
+msgstr "неможливо одночасно зберегти і вилучити розділ .comment"
+
+#: src/strip.c:478
+msgid "bad relocation"
+msgstr "помилкове пересування"
+
+#: src/strip.c:756 src/strip.c:780
+#, c-format
+msgid "cannot stat input file '%s'"
+msgstr "не вдалося отримати дані з вхідного файла «%s» за допомогою stat"
+
+#: src/strip.c:770
+#, c-format
+msgid "while opening '%s'"
+msgstr "під час спроби відкриття «%s»"
+
+#: src/strip.c:808
+#, c-format
+msgid "%s: cannot use -o or -f when stripping archive"
+msgstr ""
+"%s: не можна використовувати -o або -f під час вилучення додаткового вмісту "
+"архіву"
+
+#. We would like to support ar archives, but currently it just
+#. doesn't work at all since we call elf_clone on the members
+#. which doesn't really support ar members.
+#. result = handle_ar (fd, elf, NULL, fname,
+#. preserve_dates ? tv : NULL);
+#.
+#: src/strip.c:820
+#, c-format
+msgid "%s: no support for stripping archive"
+msgstr "%s: підтримки вилучення додаткового вмісту з архіву не передбачено"
+
+#: src/strip.c:1057
+#, c-format
+msgid "cannot open EBL backend"
+msgstr "не вдалося відкрити канал сервера EBL"
+
+#: src/strip.c:1101
+msgid "cannot get number of phdrs"
+msgstr "не вдалося отримати кількість phdr"
+
+#: src/strip.c:1115 src/strip.c:1158
+#, c-format
+msgid "cannot create new ehdr for file '%s': %s"
+msgstr "не вдалося створити ehdr для файла «%s»: %s"
+
+#: src/strip.c:1125 src/strip.c:1168
+#, c-format
+msgid "cannot create new phdr for file '%s': %s"
+msgstr "не вдалося створити phdr для файла «%s»: %s"
+
+#: src/strip.c:1248
+#, c-format
+msgid "illformed file '%s'"
+msgstr "помилкове форматування файла «%s»"
+
+#: src/strip.c:1258
+#, c-format
+msgid "Cannot remove allocated section '%s'"
+msgstr "Неможливо вилучити розміщений у пам'яті розділ «%s»"
+
+#: src/strip.c:1267
+#, c-format
+msgid "Cannot both keep and remove section '%s'"
+msgstr "Неможливо одночасно зберегти та вилучити розділ «%s»"
+
+#: src/strip.c:1631 src/strip.c:1746
+#, c-format
+msgid "while generating output file: %s"
+msgstr "під час спроби створення файла з виведеними даними: %s"
+
+#: src/strip.c:1695
+#, c-format
+msgid "%s: error while updating ELF header: %s"
+msgstr "%s: помилка під час оновлення заголовка ELF: %s"
+
+#: src/strip.c:1704
+#, c-format
+msgid "%s: error while getting shdrstrndx: %s"
+msgstr "%s: помилка під час отримання shdrstrndx: %s"
+
+#: src/strip.c:1712 src/strip.c:2552
+#, c-format
+msgid "%s: error updating shdrstrndx: %s"
+msgstr "%s: помилка під час оновлення shdrstrndx: %s"
+
+#: src/strip.c:1729
+#, c-format
+msgid "while preparing output for '%s'"
+msgstr "під час приготування виведених даних для «%s»"
+
+#: src/strip.c:1790 src/strip.c:1852
+#, c-format
+msgid "while create section header section: %s"
+msgstr "під час створення розділу заголовка розділу: %s"
+
+#: src/strip.c:1799
+#, c-format
+msgid "cannot allocate section data: %s"
+msgstr "не вдалося розмістити дані розділу: %s"
+
+#: src/strip.c:1863
+#, c-format
+msgid "while create section header string table: %s"
+msgstr "під час створення таблиці рядків заголовка розділу: %s"
+
+#: src/strip.c:1869
+msgid "no memory to create section header string table"
+msgstr "недостатньо пам'яті для створення таблиці рядків заголовка розділу"
+
+#: src/strip.c:2082
+#, c-format
+msgid "Cannot remove symbol [%zd] from allocated symbol table [%zd]"
+msgstr ""
+"Неможливо вилучити символ [%zd] з розміщеної у пам'яті таблиці символів [%zd]"
+
+#: src/strip.c:2469 src/strip.c:2574
+#, c-format
+msgid "while writing '%s': %s"
+msgstr "під час запису «%s»: %s"
+
+#: src/strip.c:2480
+#, c-format
+msgid "while creating '%s'"
+msgstr "під час спроби створення «%s»"
+
+#: src/strip.c:2503
+#, c-format
+msgid "while computing checksum for debug information"
+msgstr "під час обчислення контрольної суми для діагностичних даних"
+
+#: src/strip.c:2544
+#, c-format
+msgid "%s: error while creating ELF header: %s"
+msgstr "%s: помилка під час створення заголовка ELF: %s"
+
+#: src/strip.c:2560
+#, c-format
+msgid "%s: error while reading the file: %s"
+msgstr "%s: помилка під час читання файла: %s"
+
+#: src/strip.c:2599 src/strip.c:2619
+#, c-format
+msgid "while writing '%s'"
+msgstr "під час спроби запису «%s»"
+
+#: src/strip.c:2656 src/strip.c:2663
+#, c-format
+msgid "error while finishing '%s': %s"
+msgstr "помилка під час завершення «%s»: %s"
+
+#: src/strip.c:2680 src/strip.c:2756
+#, c-format
+msgid "cannot set access and modification date of '%s'"
+msgstr "не вдалося встановити права доступу та дату зміни «%s»"
+
+#: src/unstrip.c:65
+msgid "Match MODULE against file names, not module names"
+msgstr ""
+"Встановити відповідність МОДУЛЯ назвам файлів, а не назвам модулів names"
+
+#: src/unstrip.c:66
+msgid "Silently skip unfindable files"
+msgstr "Пропустити незнайдені файли без додаткових повідомлень"
+
+#: src/unstrip.c:69
+msgid "Place output into FILE"
+msgstr "Вивести дані у ФАЙЛ"
+
+#: src/unstrip.c:71
+msgid "Create multiple output files under DIRECTORY"
+msgstr "Створити декілька файлів виведених даних у КАТАЛОЗІ"
+
+#: src/unstrip.c:72
+msgid "Use module rather than file names"
+msgstr "Використовувати назви модулів, а не файлів"
+
+#: src/unstrip.c:74
+msgid "Create output for modules that have no separate debug information"
+msgstr ""
+"Вивести дані для модулів, які не містять окремих діагностичних відомостей"
+
+#: src/unstrip.c:77
+msgid "Apply relocations to section contents in ET_REL files"
+msgstr "Застосувати пересування до вмісту розділів у файлах ET_REL"
+
+#: src/unstrip.c:79
+msgid "Only list module and file names, build IDs"
+msgstr "Вивести лише список назв модулів, файлів, побудувати ідентифікатори"
+
+#: src/unstrip.c:81
+msgid "Force combining files even if some ELF headers don't seem to match"
+msgstr ""
+"Примусово поєднати файли, навіть якщо буде встановлено невідповідність "
+"якихось із заголовків ELF"
+
+#: src/unstrip.c:125
+#, c-format
+msgid "-d option specified twice"
+msgstr "параметр -d вказано двічі"
+
+#: src/unstrip.c:160
+#, c-format
+msgid "only one of -o or -d allowed"
+msgstr "можна використовувати лише один з параметрів: -o або -d"
+
+#: src/unstrip.c:169
+#, c-format
+msgid "-n cannot be used with explicit files or -o or -d"
+msgstr ""
+"-n не можна використовувати з файлами, заданими явно, або параметрами -o і -d"
+
+#: src/unstrip.c:184
+#, c-format
+msgid "output directory '%s'"
+msgstr "каталог виведення даних «%s»"
+
+#: src/unstrip.c:193
+#, c-format
+msgid "exactly two file arguments are required"
+msgstr "як аргументи має бути вказано точно два файла"
+
+#: src/unstrip.c:199
+#, c-format
+msgid "-m, -a, -R, and -i options not allowed with explicit files"
+msgstr ""
+"для файлів, заданих явно, не можна використовувати параметри -m, -a, -R і -i"
+
+#: src/unstrip.c:212
+#, c-format
+msgid "-o or -d is required when using implicit files"
+msgstr ""
+"якщо використовуються файли, задані неявно, слід додавати параметр -o або -d"
+
+#: src/unstrip.c:235
+#, c-format
+msgid "cannot create ELF header: %s"
+msgstr "не вдалося створити заголовок ELF: %s"
+
+#: src/unstrip.c:239
+#, c-format
+msgid "cannot get shdrstrndx:%s"
+msgstr "не вдалося отримати shdrstrndx:%s"
+
+#: src/unstrip.c:243 src/unstrip.c:2136
+#, c-format
+msgid "cannot get ELF header: %s"
+msgstr "не вдалося отримати заголовок ELF: %s"
+
+#: src/unstrip.c:253
+#, c-format
+msgid "cannot get new zero section: %s"
+msgstr "не вдалося отримати новий нульовий розділ: %s"
+
+#: src/unstrip.c:256
+#, c-format
+msgid "cannot update new zero section: %s"
+msgstr "неможливо оновити новий нульовий розділ: %s"
+
+#: src/unstrip.c:260
+#, c-format
+msgid "cannot copy ELF header: %s"
+msgstr "не вдалося скопіювати заголовок ELF: %s"
+
+#: src/unstrip.c:264 src/unstrip.c:2154 src/unstrip.c:2197
+#, c-format
+msgid "cannot get number of program headers: %s"
+msgstr "не вдалося отримати кількість заголовків програми: %s"
+
+#: src/unstrip.c:269 src/unstrip.c:2158
+#, c-format
+msgid "cannot create program headers: %s"
+msgstr "не вдалося створити заголовки програми: %s"
+
+#: src/unstrip.c:275
+#, c-format
+msgid "cannot copy program header: %s"
+msgstr "не вдалося скопіювати заголовок програми: %s"
+
+#: src/unstrip.c:285
+#, c-format
+msgid "cannot copy section header: %s"
+msgstr "не вдалося скопіювати заголовок розділу: %s"
+
+#: src/unstrip.c:288 src/unstrip.c:1748
+#, c-format
+msgid "cannot get section data: %s"
+msgstr "не вдалося отримати дані розділу: %s"
+
+#: src/unstrip.c:290 src/unstrip.c:1750
+#, c-format
+msgid "cannot copy section data: %s"
+msgstr "не вдалося скопіювати дані розділу: %s"
+
+#: src/unstrip.c:318
+#, c-format
+msgid "cannot create directory '%s'"
+msgstr "не вдалося створити каталог «%s»"
+
+#: src/unstrip.c:392 src/unstrip.c:666 src/unstrip.c:700 src/unstrip.c:868
+#: src/unstrip.c:1790
+#, c-format
+msgid "cannot get symbol table entry: %s"
+msgstr "не вдалося отримати запис таблиці символів: %s"
+
+#: src/unstrip.c:408 src/unstrip.c:669 src/unstrip.c:690 src/unstrip.c:703
+#: src/unstrip.c:1811 src/unstrip.c:2007 src/unstrip.c:2031
+#, c-format
+msgid "cannot update symbol table: %s"
+msgstr "не вдалося оновити таблицю символів: %s"
+
+#: src/unstrip.c:418
+#, c-format
+msgid "cannot update section header: %s"
+msgstr "не вдалося оновити заголовок розділу: %s"
+
+#: src/unstrip.c:464
+#, c-format
+msgid "gelf_getrel failed: %s"
+msgstr ""
+
+#: src/unstrip.c:467 src/unstrip.c:482
+#, c-format
+msgid "cannot update relocation: %s"
+msgstr "не вдалося оновити пересування: %s"
+
+#: src/unstrip.c:479
+#, c-format
+msgid "gelf_getrela failed: %s"
+msgstr ""
+
+#: src/unstrip.c:580
+#, c-format
+msgid "cannot get symbol version: %s"
+msgstr "не вдалося отримати версію символу: %s"
+
+#: src/unstrip.c:593
+#, c-format
+msgid "unexpected section type in [%zu] with sh_link to symtab"
+msgstr "неочікуваний тип розділу у [%zu] з посиланням sh_link на symtab"
+
+#: src/unstrip.c:857
+#, c-format
+msgid "cannot get symbol section data: %s"
+msgstr "не вдалося отримати дані розділу символів: %s"
+
+#: src/unstrip.c:859
+#, c-format
+msgid "cannot get string section data: %s"
+msgstr "не вдалося отримати дані розділу рядків: %s"
+
+#: src/unstrip.c:876
+#, c-format
+msgid "invalid string offset in symbol [%zu]"
+msgstr "некоректне зміщення рядка у символі [%zu]"
+
+#: src/unstrip.c:939
+msgid "found two identical index map positions."
+msgstr ""
+
+#: src/unstrip.c:990
+msgid "section symbols in unexpected order"
+msgstr ""
+
+#: src/unstrip.c:996
+#, fuzzy
+#| msgid "Show demangled symbols (ARG is always ignored)"
+msgid "found two identical symbols"
+msgstr "Виводити розшифровані символи (АРГ завжди ігнорується)"
+
+#: src/unstrip.c:1066 src/unstrip.c:1474
+#, c-format
+msgid "cannot read section [%zu] name: %s"
+msgstr "не вдалося прочитати назву розділу [%zu]: %s"
+
+#: src/unstrip.c:1081
+#, c-format
+msgid "bad sh_link for group section: %s"
+msgstr "помилкове значення sh_link для розділу груп: %s"
+
+#: src/unstrip.c:1087
+#, c-format
+msgid "couldn't get shdr for group section: %s"
+msgstr "не вдалося отримати shdr для розділу груп: %s"
+
+#: src/unstrip.c:1092
+#, c-format
+msgid "bad data for group symbol section: %s"
+msgstr "помилкові дані для розділу символів груп: %s"
+
+#: src/unstrip.c:1098
+#, c-format
+msgid "couldn't get symbol for group section: %s"
+msgstr "не вдалося отримати символ для розділу груп: %s"
+
+#: src/unstrip.c:1103
+#, c-format
+msgid "bad symbol name for group section: %s"
+msgstr "помилкова назва символу для розділу груп: %s"
+
+#: src/unstrip.c:1114 src/unstrip.c:1594
+#, c-format
+msgid "cannot find matching section for [%zu] '%s'"
+msgstr "не вдалося знайти відповідний розділ для [%zu] «%s»"
+
+#: src/unstrip.c:1159 src/unstrip.c:1178 src/unstrip.c:1216
+#, c-format
+msgid "cannot read '.gnu.prelink_undo' section: %s"
+msgstr "не вдалося прочитати розділ «.gnu.prelink_undo»: %s"
+
+#: src/unstrip.c:1196
+#, c-format
+msgid "overflow with shnum = %zu in '%s' section"
+msgstr "переповнення з shnum = %zu у розділі «%s»"
+
+#: src/unstrip.c:1207
+#, c-format
+msgid "invalid contents in '%s' section"
+msgstr "некоректний вміст розділу «%s»"
+
+#: src/unstrip.c:1378 src/unstrip.c:1394 src/unstrip.c:1674 src/unstrip.c:1966
+#, c-format
+msgid "cannot add section name to string table: %s"
+msgstr "не вдалося додати назву розділу до таблиці рядків: %s"
+
+#: src/unstrip.c:1403
+#, c-format
+msgid "cannot update section header string table data: %s"
+msgstr "не вдалося оновити дані заголовка розділу у таблиці рядків: %s"
+
+#: src/unstrip.c:1432 src/unstrip.c:1436
+#, c-format
+msgid "cannot get section header string table section index: %s"
+msgstr ""
+"не вдалося визначити індекс розділу заголовка розділу у таблиці рядків: %s"
+
+#: src/unstrip.c:1440 src/unstrip.c:1444 src/unstrip.c:1689
+#, c-format
+msgid "cannot get section count: %s"
+msgstr "не вдалося отримати кількість розділів: %s"
+
+#: src/unstrip.c:1447
+msgid "more sections in stripped file than debug file -- arguments reversed?"
+msgstr ""
+"у очищеному файлі більше розділів ніж у файлі з даними для зневаджування — "
+"помилковий порядок параметрів?"
+
+#: src/unstrip.c:1451
+msgid "no sections in stripped file"
+msgstr "у очищеному файлі немає розділів"
+
+#: src/unstrip.c:1499 src/unstrip.c:1609
+#, c-format
+msgid "cannot read section header string table: %s"
+msgstr "не вдалося прочитати таблицю рядків заголовка розділу: %s"
+
+#: src/unstrip.c:1668
+#, c-format
+msgid "cannot add new section: %s"
+msgstr "не вдалося додати новий розділ: %s"
+
+#: src/unstrip.c:1798
+#, c-format
+msgid "symbol [%zu] has invalid section index"
+msgstr "символ [%zu] має некоректний індекс розділу"
+
+#: src/unstrip.c:1830
+#, c-format
+msgid "group has invalid section index [%zd]"
+msgstr "група містить некоректний індекс розділу [%zd]"
+
+#: src/unstrip.c:2115
+#, c-format
+msgid "cannot read section data: %s"
+msgstr "не вдалося прочитати дані розділу: %s"
+
+#: src/unstrip.c:2144
+#, c-format
+msgid "cannot update ELF header: %s"
+msgstr "не вдалося оновити заголовок ELF: %s"
+
+#: src/unstrip.c:2168
+#, c-format
+msgid "cannot update program header: %s"
+msgstr "не вдалося оновити заголовок програми: %s"
+
+#: src/unstrip.c:2173 src/unstrip.c:2256
+#, c-format
+msgid "cannot write output file: %s"
+msgstr "не вдалося записати файл виведених даних: %s"
+
+#: src/unstrip.c:2224
+#, c-format
+msgid "DWARF data not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+"Дані DWARF не скориговано відповідно до відхилення перед компонуванням; "
+"спробуйте виправити це командою prelink -u"
+
+#: src/unstrip.c:2227
+#, c-format
+msgid ""
+"DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"
+msgstr ""
+"Дані DWARF у «%s» не скориговано відповідно до відхилення перед "
+"компонуванням; спробуйте виправити це командою prelink -u"
+
+#: src/unstrip.c:2247 src/unstrip.c:2299 src/unstrip.c:2311 src/unstrip.c:2401
+#, c-format
+msgid "cannot create ELF descriptor: %s"
+msgstr "не вдалося створити дескриптор ELF: %s"
+
+#: src/unstrip.c:2285
+msgid "WARNING: "
+msgstr "УВАГА: "
+
+#: src/unstrip.c:2287
+msgid ", use --force"
+msgstr ", скористайтеся --force"
+
+#: src/unstrip.c:2315
+msgid "ELF header identification (e_ident) different"
+msgstr "Різні ідентифікатори заголовків ELF (e_ident)"
+
+#: src/unstrip.c:2319
+msgid "ELF header type (e_type) different"
+msgstr "Різні типи заголовків ELF (e_type)"
+
+#: src/unstrip.c:2323
+msgid "ELF header machine type (e_machine) different"
+msgstr "Різні типи архітектур заголовків ELF (e_machine)"
+
+#: src/unstrip.c:2327
+msgid "stripped program header (e_phnum) smaller than unstripped"
+msgstr "очищений заголовок програми (e_phnum) є меншим за неочищений"
+
+#: src/unstrip.c:2358
+#, c-format
+msgid "cannot find stripped file for module '%s': %s"
+msgstr "не вдалося знайти очищений файл для модуля «%s»: %s"
+
+#: src/unstrip.c:2362
+#, c-format
+msgid "cannot open stripped file '%s' for module '%s': %s"
+msgstr "не вдалося відкрити очищений файл «%s» для модуля «%s»: %s"
+
+#: src/unstrip.c:2377
+#, c-format
+msgid "cannot find debug file for module '%s': %s"
+msgstr "не вдалося знайти файл діагностичних даних для модуля «%s»: %s"
+
+#: src/unstrip.c:2381
+#, c-format
+msgid "cannot open debug file '%s' for module '%s': %s"
+msgstr "не вдалося відкрити файл діагностичних даних «%s» для модуля «%s»: %s"
+
+#: src/unstrip.c:2394
+#, c-format
+msgid "module '%s' file '%s' is not stripped"
+msgstr "у модулі «%s» файл «%s» не очищено strip"
+
+#: src/unstrip.c:2425
+#, c-format
+msgid "cannot cache section addresses for module '%s': %s"
+msgstr "не вдалося кешувати адреси розділів для модуля «%s»: %s"
+
+#: src/unstrip.c:2553
+msgid "no matching modules found"
+msgstr "відповідних модулів не виявлено"
+
+#: src/unstrip.c:2563
+msgid "matched more than one module"
+msgstr "встановлено відповідність декількох модулів"
+
+#: src/unstrip.c:2608
+msgid ""
+"STRIPPED-FILE DEBUG-FILE\n"
+"[MODULE...]"
+msgstr ""
+"ОЧИЩЕНИЙ-ФАЙЛ ФАЙЛ-DEBUG\n"
+"[МОДУЛЬ...]"
+
+#: src/unstrip.c:2609
+msgid ""
+"Combine stripped files with separate symbols and debug information.\n"
+"\n"
+"The first form puts the result in DEBUG-FILE if -o was not given.\n"
+"\n"
+"MODULE arguments give file name patterns matching modules to process.\n"
+"With -f these match the file name of the main (stripped) file (slashes are "
+"never special), otherwise they match the simple module names.  With no "
+"arguments, process all modules found.\n"
+"\n"
+"Multiple modules are written to files under OUTPUT-DIRECTORY, creating "
+"subdirectories as needed.  With -m these files have simple module names, "
+"otherwise they have the name of the main file complete with directory "
+"underneath OUTPUT-DIRECTORY.\n"
+"\n"
+"With -n no files are written, but one line to standard output for each "
+"module:\n"
+"\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n"
+"START and SIZE are hexadecimal giving the address bounds of the module.  "
+"BUILDID is hexadecimal for the build ID bits, or - if no ID is known; the "
+"hexadecimal may be followed by @0xADDR giving the address where the ID "
+"resides if that is known.  FILE is the file name found for the module, or - "
+"if none was found, or . if an ELF image is available but not from any named "
+"file.  DEBUGFILE is the separate debuginfo file name, or - if no debuginfo "
+"was found, or . if FILE contains the debug information."
+msgstr ""
+"Комбінувати очищені файли з окремими даними щодо символів та діагностичними "
+"даними.\n"
+"\n"
+"За використання першої форми команди, результати буде виведено до ФАЙЛА-"
+"DEBUG, якщо не файл виведених даних не вказано параметром -o.\n"
+"\n"
+"За допомогою аргументів МОДУЛЬ можна вказати шаблони назв файлів модулів, "
+"які слід обробити.\n"
+"З -f ці назви модулів відповідатимуть назві основного (очищеного strip) "
+"файла (похилі риски не є спеціальними символами), якщо ж -f не вказано, "
+"назви вважатимуться простими назвами модулів. Якщо аргументів не буде "
+"вказано, програма обробить всі знайдені модулі.\n"
+"\n"
+"Вказані модулі буде записано до файлів у КАТАЛОЗІ-ВИВОДУ, зі створенням, за "
+"потреби, підкаталогів. З параметром -m файли виведених даних "
+"створюватимуться за назвами модулів, якщо ж цього параметра вказано не буде, "
+"програма створюватиме файл з назвою основного файла у основному КАТАЛОЗІ-"
+"ВИВОДУ.\n"
+"\n"
+"Якщо буде вказано параметр -n, дані до файлів не виводитимуться, програма "
+"виведе для кожного модуля до стандартного виводу такі дані:\n"
+"\tПОЧАТОК+РОЗМІР ІДЕНТИФІКАТОР-ЗБИРАННЯ ФАЙЛ ФАЙЛ-DEBUG НАЗВА-МОДУЛЯ\n"
+"ПОЧАТОК і РОЗМІР буде виведено як шістнадцяткові числа у межах адресного "
+"простору модуля. ІДЕНТИФІКАТОР-ЗБИРАННЯ — це шістнадцяткове число, що "
+"відповідає бітам ідентифікатора збирання, або «-», якщо ідентифікатор "
+"невідомий; за шістнадцятковим числом може слідувати @0xАДРЕСА, яка вказує "
+"місце розташування ідентифікатора, якщо воно відоме. ФАЙЛ відповідає назві "
+"файла, знайденого для модуля, або «-», якщо файл не знайдено, і «.», якщо "
+"вдалося знайти образ ELF, але без жодного файла з назвою. ФАЙЛ-DEBUG — назва "
+"окремого файла діагностичних даних або «-», якщо файла діагностичних даних "
+"не вдалося знайти, і «.», якщо ФАЙЛ сам містить діагностичні дані."
+
+#. Short description of program.
+#: debuginfod/debuginfod-find.c:42
+msgid "Request debuginfo-related content from debuginfods listed in $"
+msgstr ""
+
+#. Strings for arguments in help texts.
+#: debuginfod/debuginfod-find.c:46
+msgid ""
+"debuginfo BUILDID\n"
+"debuginfo PATH\n"
+"executable BUILDID\n"
+"executable PATH\n"
+"source BUILDID /FILENAME\n"
+"source PATH /FILENAME\n"
+"section BUILDID SECTION-NAME\n"
+"section PATH SECTION-NAME\n"
+msgstr ""
+
+#: tests/backtrace.c:491
+msgid "Run executable"
+msgstr "Запустити виконуваний файл"
+
+#: tests/dwflmodtest.c:209
+msgid "Additionally show function names"
+msgstr "Додатково вивести назви функцій"
+
+#: tests/dwflmodtest.c:210
+msgid "Show instances of inlined functions"
+msgstr "Вивести екземпляри вбудованих функцій"
+
+#, c-format
+#~ msgid "section [%2d] '%s': section entry size does not match ElfXX_Rela\n"
+#~ msgstr ""
+#~ "розділ [%2d] «%s»: розмірність запису розділу не відповідає ElfXX_Rela\n"
+
+#, c-format
+#~ msgid "cannot get .debug_addr section data: %s"
+#~ msgstr "не вдалося отримати дані розділу .debug_addr: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_rnglists content: %s"
+#~ msgstr "не вдалося отримати вміст .debug_rnglists: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_ranges content: %s"
+#~ msgstr "не вдалося отримати дані .debug_ranges: %s"
+
+#, c-format
+#~ msgid "cannot get line data section data: %s"
+#~ msgstr "не вдалося отримати дані розділу лінійних даних: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loclists content: %s"
+#~ msgstr "не вдалося отримати вміст .debug_loclists: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_loc content: %s"
+#~ msgstr "не вдалося отримати вміст .debug_loc: %s"
+
+#, c-format
+#~ msgid "cannot get macro information section data: %s"
+#~ msgstr "не вдалося отримати дані розділу відомостей щодо макросів: %s"
+
+#, c-format
+#~ msgid "cannot get .debug_str_offsets section data: %s"
+#~ msgstr "не вдалося отримати дані розділу .debug_str_offsets: %s"
+
+#, c-format
+#~ msgid "cannot allocate memory"
+#~ msgstr "не вдалося розподілити пам’ять"
+
+#~ msgid ""
+#~ " [%6tx] base address\n"
+#~ "          "
+#~ msgstr ""
+#~ " [%6tx] базова адреса\n"
+#~ "          "
+
+#, fuzzy
+#~ msgid "%s: error getting zero section: %s"
+#~ msgstr "%s: помилка під час читання файла: %s"
+
+#, fuzzy
+#~ msgid "%s: error while updating zero section: %s"
+#~ msgstr "%s: помилка під час читання файла: %s"
+
+#~ msgid "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%s+%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%#0*<PRIx64> <%s+%#<PRIx64>>"
+#~ msgstr "%#0*<PRIx64> <%s+%#<PRIx64>>"
+
+#~ msgid "%s+%#<PRIx64> <%s>"
+#~ msgstr "%s+%#<PRIx64> <%s>"
+
+#~ msgid "%s+%#0*<PRIx64> <%s>"
+#~ msgstr "%s+%#0*<PRIx64> <%s>"
+
+#~ msgid "%#<PRIx64> <%s>"
+#~ msgstr "%#<PRIx64> <%s>"
+
+#~ msgid "%#0*<PRIx64> <%s>"
+#~ msgstr "%#0*<PRIx64> <%s>"
+
+#~ msgid "%s+%#<PRIx64>"
+#~ msgstr "%s+%#<PRIx64>"
+
+#~ msgid "%s+%#0*<PRIx64>"
+#~ msgstr "%s+%#0*<PRIx64>"
+
+#~ msgid "   %s..%s (%<PRIx64>)\n"
+#~ msgstr "   %s..%s (%<PRIx64>)\n"
+
+#~ msgid "   %s..%s\n"
+#~ msgstr "   %s..%s\n"
+
+#~ msgid " advance address by %u to %s, op_index to %u\n"
+#~ msgstr " збільшення адреси на %u до %s, індекс_оп до %u\n"
+
+#~ msgid " advance address by constant %u to %s, op_index to %u\n"
+#~ msgstr " збільшити адресу на сталу величину %u до %s, індекс_оп до %u\n"
+
+#~ msgid " [%6tx]  %s..%s\n"
+#~ msgstr " [%6tx]  %s..%s\n"
+
+#~ msgid "           %s..%s\n"
+#~ msgstr "           %s..%s\n"
+
+#~ msgid "cannot get DIE at offset %<PRIu64> in section '%s': %s"
+#~ msgstr "не вдалося отримати DIE за зміщенням %<PRIu64> у розділі «%s»: %s"
+
+#~ msgid " [%6tx]  %s..%s"
+#~ msgstr " [%6tx]  %s..%s"
+
+#~ msgid "           %s..%s"
+#~ msgstr "           %s..%s"
+
+#~ msgid "vendor opcode not verified?"
+#~ msgstr "код операції постачальника не перевірено?"
+
+#~ msgid "-R option supports only .comment section"
+#~ msgstr "Для параметра -R передбачено підтримку лише розділу .comment"
+
+#~ msgid "Written by %s.\n"
+#~ msgstr "Автор — %s.\n"
+
+#~ msgid "cannot allocate PLTREL section: %s"
+#~ msgstr "не вдалося розмістити розділ PLTREL: %s"
+
+#~ msgid "cannot allocate GOT section: %s"
+#~ msgstr "не вдалося розмістити розділ GOT: %s"
+
+#~ msgid "cannot allocate GOTPLT section: %s"
+#~ msgstr "не вдалося розмістити розділ GOTPLT: %s"
+
+#~ msgid "initial-executable TLS relocation cannot be used "
+#~ msgstr ""
+#~ "не можна використовувати пересування TLS у початковому виконуваному файлі"
+
+#~ msgid "Input File Control:"
+#~ msgstr "Керування файлом вхідних даних:"
+
+#~ msgid "Include whole archives in the output from now on."
+#~ msgstr "Відтепер включати цілі архіви до виведених даних."
+
+#~ msgid "Stop including the whole archives in the output."
+#~ msgstr "Припинити включення цілих архівів до вихідних даних."
+
+#~ msgid "FILE"
+#~ msgstr "ФАЙЛ"
+
+#~ msgid "Start a group."
+#~ msgstr "Почати групу."
+
+#~ msgid "End a group."
+#~ msgstr "Завершити групу."
+
+#~ msgid "PATH"
+#~ msgstr "ШЛЯХ"
+
+#~ msgid "Add PATH to list of directories files are searched in."
+#~ msgstr "Додати ШЛЯХ до списку каталогів, у яких слід шукати файли."
+
+#~ msgid "Only set DT_NEEDED for following dynamic libs if actually used"
+#~ msgstr ""
+#~ "Встановлювати DT_NEEDED лише для наступних динамічних бібліотек, якщо він "
+#~ "справді використовується"
+
+#~ msgid "Always set DT_NEEDED for following dynamic libs"
+#~ msgstr "Завжди встановлювати DT_NEEDED для наступних динамічних бібліотек"
+
+#~ msgid "Ignore LD_LIBRARY_PATH environment variable."
+#~ msgstr "Ігнорувати змінну середовища LD_LIBRARY_PATH."
+
+#~ msgid "Output File Control:"
+#~ msgstr "Керування файлом виведених даних:"
+
+#~ msgid "Place output in FILE."
+#~ msgstr "Вивести дані до ФАЙЛА."
+
+#~ msgid "Object is marked to not use default search path at runtime."
+#~ msgstr ""
+#~ "Об’єкт позначено, як таких, який не використовує типовий шлях пошуку під "
+#~ "час запуску."
+
+#~ msgid "Same as --whole-archive."
+#~ msgstr "Те саме, що --whole-archive."
+
+#~ msgid ""
+#~ "Default rules of extracting from archive; weak references are not enough."
+#~ msgstr ""
+#~ "Типові правила видобування з архівів; слабкого посилання недостатньо."
+
+#~ msgid "Weak references cause extraction from archive."
+#~ msgstr "Слабкі посилання спричиняють видобування з архіву."
+
+#~ msgid "Allow multiple definitions; first is used."
+#~ msgstr "Дозволити декілька визначень. Використовуватиметься лише перше."
+
+#~ msgid "Disallow/allow undefined symbols in DSOs."
+#~ msgstr "Заборонити/Дозволити невизначені символи у DSO."
+
+#~ msgid "Object requires immediate handling of $ORIGIN."
+#~ msgstr "Об’єкт вимагає негайної обробки $ORIGIN."
+
+#~ msgid "Relocation will not be processed lazily."
+#~ msgstr "Переміщення не буде оброблятися у лінивому режимі."
+
+#~ msgid "Object cannot be unloaded at runtime."
+#~ msgstr "Об’єкт не можна вивантажувати під час запуску."
+
+#~ msgid "Mark object to be initialized first."
+#~ msgstr "Позначити об’єкт, як такий, що потребує ініціалізації."
+
+#~ msgid "Enable/disable lazy-loading flag for following dependencies."
+#~ msgstr ""
+#~ "Увімкнути/Вимкнути прапорець лінивого завантаження для наведених нижче "
+#~ "залежностей."
+
+#~ msgid "Mark object as not loadable with 'dlopen'."
+#~ msgstr ""
+#~ "Позначити об’єкт, як непридатний для завантаження за допомогою «dlopen»."
+
+#~ msgid "Ignore/record dependencies on unused DSOs."
+#~ msgstr "Ігнорувати/Записувати залежності невикористаних DSO."
+
+#~ msgid "Generated DSO will be a system library."
+#~ msgstr "Створена DSO буде системною бібліотекою."
+
+#~ msgid "ADDRESS"
+#~ msgstr "АДРЕСА"
+
+#~ msgid "Set entry point address."
+#~ msgstr "Встановити адресу точки входу."
+
+#~ msgid "Do not link against shared libraries."
+#~ msgstr "Не компонувати з бібліотеками спільного використання."
+
+#~ msgid "Prefer linking against shared libraries."
+#~ msgstr ""
+#~ "Надавати перевагу компонуванню з бібліотеками спільного використання."
+
+#~ msgid "Export all dynamic symbols."
+#~ msgstr "Експортувати всі динамічні символи."
+
+#~ msgid "Strip all symbols."
+#~ msgstr "Вилучити всі символи."
+
+#~ msgid "Strip debugging symbols."
+#~ msgstr "Вилучити символи зневаджування."
+
+#~ msgid "Assume pagesize for the target system to be SIZE."
+#~ msgstr ""
+#~ "Вважати розмір сторінки для системи призначення рівним значенню РОЗМІР."
+
+#~ msgid "Set runtime DSO search path."
+#~ msgstr "Встановити шлях пошуку DSO під час запуску."
+
+#~ msgid "Set link time DSO search path."
+#~ msgstr "Встановити шлях пошуку DSO під час компонування."
+
+#~ msgid "Generate dynamic shared object."
+#~ msgstr "Створити динамічний об’єкт спільного використання."
+
+#~ msgid "Generate relocatable object."
+#~ msgstr "Створити придатний для пересування об’єкт."
+
+#~ msgid "Causes symbol not assigned to a version be reduced to local."
+#~ msgstr ""
+#~ "Спричиняє перетворення символів, не прив’язаних до версії, на локальні."
+
+#~ msgid "Remove unused sections."
+#~ msgstr "Вилучити невикористані розділи."
+
+#~ msgid "Don't remove unused sections."
+#~ msgstr "Не вилучати невикористані розділи."
+
+#~ msgid "Set soname of shared object."
+#~ msgstr "Встановити soname об’єкта спільного використання."
+
+#~ msgid "Set the dynamic linker name."
+#~ msgstr "Встановити назву динамічного компонувальника."
+
+#~ msgid "Add/suppress addition indentifying link-editor to .comment section."
+#~ msgstr ""
+#~ "Додати/Придушити додавання ідентифікації редактора компонування до "
+#~ "розділу .comment."
+
+#~ msgid "Create .eh_frame_hdr section"
+#~ msgstr "Створити розділ .eh_frame_hdr"
+
+#~ msgid "Set hash style to sysv, gnu or both."
+#~ msgstr "Встановити формат хешування у значення sysv, gnu або both."
+
+#~ msgid "Generate build ID note (md5, sha1 (default), uuid)."
+#~ msgstr ""
+#~ "Створити запису ідентифікатора збирання (md5, sha1 (типовий), uuid)."
+
+#~ msgid "Linker Operation Control:"
+#~ msgstr "Керування роботою компонувальника:"
+
+#~ msgid "Verbose messages."
+#~ msgstr "Докладні повідомлення."
+
+#~ msgid "Trace file opens."
+#~ msgstr "Спостерігати за відкриттями файлів."
+
+#~ msgid "Trade speed for less memory usage"
+#~ msgstr "Зменшити споживання пам’яті за рахунок швидкості"
+
+#~ msgid "LEVEL"
+#~ msgstr "РІВЕНЬ"
+
+#~ msgid "Set optimization level to LEVEL."
+#~ msgstr "Встановити рівень оптимізації РІВЕНЬ."
+
+#~ msgid "Use linker script in FILE."
+#~ msgstr "Використати скрипт компонування у ФАЙЛі."
+
+#~ msgid "Select to get parser debug information"
+#~ msgstr "Позначте, щоб отримати діагностичні дані обробника"
+
+#~ msgid "Read version information from FILE."
+#~ msgstr "Прочитати відомості щодо версії з ФАЙЛа."
+
+#~ msgid "Set emulation to NAME."
+#~ msgstr "Встановити режим емуляції на основі НАЗВИ."
+
+#~ msgid "Combine object and archive files."
+#~ msgstr "Комбінує об’єктні файли і файли архівів."
+
+#~ msgid "[FILE]..."
+#~ msgstr "[ФАЙЛ]..."
+
+#~ msgid "At least one input file needed"
+#~ msgstr "Потрібен принаймні один файл вхідних даних"
+
+#~ msgid "error while preparing linking"
+#~ msgstr "помилка під час приготування до компонування"
+
+#~ msgid "cannot open linker script '%s'"
+#~ msgstr "не вдалося відкрити скрипт компонування «%s»"
+
+#~ msgid "-( without matching -)"
+#~ msgstr "-( без відповідника -)"
+
+#~ msgid "only one option of -G and -r is allowed"
+#~ msgstr "можна використовувати лише один з параметрів -G або -r"
+
+#~ msgid "more than one '-m' parameter"
+#~ msgstr "декілька параметрів «-m»"
+
+#~ msgid "unknown option `-%c %s'"
+#~ msgstr "невідомий параметр «-%c %s»"
+
+#~ msgid "invalid hash style '%s'"
+#~ msgstr "некоректний формат хешування «%s»"
+
+#~ msgid "invalid build-ID style '%s'"
+#~ msgstr "некоректний формат ідентифікатора збирання «%s»"
+
+#~ msgid "Invalid optimization level `%s'"
+#~ msgstr "Некоректний рівень оптимізації «%s»"
+
+#~ msgid "nested -( -) groups are not allowed"
+#~ msgstr "підтримки вкладених груп -( -) не передбачено"
+
+#~ msgid "-) without matching -("
+#~ msgstr "-) без відповідника -("
+
+#~ msgid "unknown option '-%c %s'"
+#~ msgstr "невідомий параметр «-%c %s»"
+
+#~ msgid "could not find input file to determine output file format"
+#~ msgstr ""
+#~ "не вдалося виявити файл вхідних даних для визначення формату файла "
+#~ "вихідних даних"
+
+#~ msgid "try again with an appropriate '-m' parameter"
+#~ msgstr "повторіть спробу з належним параметром «-m»"
+
+#~ msgid "cannot read version script '%s'"
+#~ msgstr "не вдалося прочитати скрипт версій «%s»"
+
+#~ msgid "duplicate definition of '%s' in linker script"
+#~ msgstr "повторне визначення «%s» у скрипті компонування"
+
+#~ msgid "cannot create string table"
+#~ msgstr "не вдалося створити таблицю рядків"
+
+#~ msgid "cannot load ld backend library '%s': %s"
+#~ msgstr "не вдалося завантажити бібліотеку сервера ld «%s»: %s"
+
+#~ msgid "cannot find init function in ld backend library '%s': %s"
+#~ msgstr "не вдалося виявити функцію init у бібліотеці сервера ld «%s»: %s"
+
+#~ msgid "%s listed more than once as input"
+#~ msgstr "%s вказано декілька разів як джерело даних"
+
+#~ msgid "%s (for -l%s)\n"
+#~ msgstr "%s (для -l%s)\n"
+
+#~ msgid "%s (for DT_NEEDED %s)\n"
+#~ msgstr "%s (для DT_NEEDED %s)\n"
+
+#~ msgid "Warning: type of `%s' changed from %s in %s to %s in %s"
+#~ msgstr "Попередження: тип «%s» змінився з %s у %s на %s у %s"
+
+#~ msgid ""
+#~ "Warning: size of `%s' changed from %<PRIu64> in %s to %<PRIu64> in %s"
+#~ msgstr ""
+#~ "Попередження: розмір «%s» змінено з %<PRIu64> у %s на %<PRIu64> у %s"
+
+#~ msgid "(%s+%#<PRIx64>): multiple definition of %s `%s'\n"
+#~ msgstr "(%s+%#<PRIx64>): повторне визначення %s «%s»\n"
+
+#~ msgid "(%s+%#<PRIx64>): first defined here\n"
+#~ msgstr "(%s+%#<PRIx64>): вперше визначено тут\n"
+
+#~ msgid "%s: cannot get section group data: %s"
+#~ msgstr "%s: не вдалося отримати дані групи розділів: %s"
+
+#~ msgid "%s: section '%s' with group flag set does not belong to any group"
+#~ msgstr ""
+#~ "%s: розділ «%s» з встановленим прапорцем групи не належить жодній групі"
+
+#~ msgid "%s: section [%2d] '%s' is not in the correct section group"
+#~ msgstr "%s: розділ [%2d] «%s» не належить до відповідної групи розділів"
+
+#~ msgid "%s: invalid ELF file (%s:%d)\n"
+#~ msgstr "%s: некоректний файл ELF (%s:%d)\n"
+
+#~ msgid "%s: only files of type ET_REL might contain section groups"
+#~ msgstr "%s: групи розділів можуть містити лише файли типу ET_REL"
+
+#~ msgid "%s: cannot determine signature of section group [%2zd] '%s': %s"
+#~ msgstr "%s: не вдалося визначити підпис групи розділів [%2zd] «%s»: %s"
+
+#~ msgid "%s: cannot get content of section group [%2zd] '%s': %s'"
+#~ msgstr "%s: не вдалося отримати вміст групи розділів [%2zd] «%s»: %s'"
+
+#~ msgid ""
+#~ "%s: group member %zu of section group [%2zd] '%s' has too high index: "
+#~ "%<PRIu32>"
+#~ msgstr ""
+#~ "%s: елемент групи %zu групи розділів [%2zd] «%s» має надто високий "
+#~ "індекс: %<PRIu32>"
+
+#~ msgid "%s: section '%s' has unknown type: %d"
+#~ msgstr "%s: розділ «%s» належить до невідомого типу: %d"
+
+#~ msgid "cannot get descriptor for ELF file (%s:%d): %s\n"
+#~ msgstr "не вдалося отримати дескриптор файла ELF (%s:%d): %s\n"
+
+#~ msgid "cannot read archive `%s': %s"
+#~ msgstr "не вдалося прочитати архів «%s»: %s"
+
+#~ msgid "file of type %s cannot be linked in\n"
+#~ msgstr "файл типу %s не можна скомпонувати у\n"
+
+#~ msgid "%s: input file incompatible with ELF machine type %s\n"
+#~ msgstr "%s: файл вхідних даних несумісний з типом архітектури ELF %s\n"
+
+#~ msgid "%s: cannot get section header string table index: %s\n"
+#~ msgstr ""
+#~ "%s: не вдалося отримати покажчик таблиці рядків заголовка розділу: %s\n"
+
+#~ msgid "cannot use DSO '%s' when generating relocatable object file"
+#~ msgstr ""
+#~ "не вдалося використати DSO «%s» під час створення придатного до "
+#~ "пересування об’єктного файла"
+
+#~ msgid "input file '%s' ignored"
+#~ msgstr "файл вхідних даних «%s» проігноровано"
+
+#~ msgid "undefined symbol `%s' in %s"
+#~ msgstr "невизначений символ «%s» у %s"
+
+#~ msgid "cannot create ELF descriptor for output file: %s"
+#~ msgstr "не вдалося створити дескриптор ELF для файла вихідних даних: %s"
+
+#~ msgid "could not create ELF header for output file: %s"
+#~ msgstr "не вдалося створити заголовок ELF для файла виведених даних: %s"
+
+#~ msgid "cannot create section for output file: %s"
+#~ msgstr "не вдалося створити розділ для файла вихідних даних: %s"
+
+#~ msgid "address computation expression contains variable '%s'"
+#~ msgstr "вираз обчислення адреси містить змінну «%s»"
+
+#~ msgid ""
+#~ "argument '%<PRIuMAX>' of ALIGN in address computation expression is no "
+#~ "power of two"
+#~ msgstr ""
+#~ "значення «%<PRIuMAX>» ALIGN у виразі обчислення адреси не є степенем "
+#~ "двійки"
+
+#~ msgid "cannot find entry symbol '%s': defaulting to %#0*<PRIx64>"
+#~ msgstr ""
+#~ "не вдалося знайти символ запису «%s»: встановлено типове значення "
+#~ "%#0*<PRIx64>"
+
+#~ msgid "no entry symbol specified: defaulting to %#0*<PRIx64>"
+#~ msgstr "не вказано символу запису: встановлено типове значення %#0*<PRIx64>"
+
+#~ msgid "cannot create GNU hash table section for output file: %s"
+#~ msgstr ""
+#~ "не вдалося створити розділ таблиці хешів GNU для файла вихідних даних: %s"
+
+#~ msgid "cannot create hash table section for output file: %s"
+#~ msgstr ""
+#~ "не вдалося створити розділ таблиці хешів для файла вихідних даних: %s"
+
+#~ msgid "cannot create build ID section: %s"
+#~ msgstr "не вдалося створити розділу ідентифікатора збирання: %s"
+
+#~ msgid "cannot convert section data to file format: %s"
+#~ msgstr "не вдалося перетворити дані розділу у формат файла: %s"
+
+#~ msgid "cannot convert section data to memory format: %s"
+#~ msgstr "не вдалося перетворити дані розділу у формат вмісту пам’яті: %s"
+
+#~ msgid "cannot read enough data for UUID"
+#~ msgstr "не вдалося прочитати достатньо даних для встановлення UUID"
+
+#~ msgid "cannot create symbol table for output file: %s"
+#~ msgstr "не вдалося створити таблицю символів для файла вихідних даних: %s"
+
+#~ msgid "section index too large in dynamic symbol table"
+#~ msgstr "у таблиці динамічних символів покажчик є занадто великим"
+
+#~ msgid "cannot create versioning section: %s"
+#~ msgstr "не вдалося створити розділ версій: %s"
+
+#~ msgid "cannot create dynamic symbol table for output file: %s"
+#~ msgstr ""
+#~ "не вдалося створити динамічну таблицю символів для файла вихідних даних: "
+#~ "%s"
+
+#~ msgid "cannot create versioning data: %s"
+#~ msgstr "не вдалося створити даних версії: %s"
+
+#~ msgid "cannot create section header string section: %s"
+#~ msgstr "не вдалося створити розділ рядків заголовка розділу: %s"
+
+#~ msgid "cannot create section header string section"
+#~ msgstr "не вдалося створити розділ рядків заголовка розділу"
+
+#~ msgid "cannot create program header: %s"
+#~ msgstr "не вдалося створити заголовок програми: %s"
+
+#~ msgid "while determining file layout: %s"
+#~ msgstr "під час визначення компонування файла: %s"
+
+#~ msgid "internal error: non-nobits section follows nobits section"
+#~ msgstr ""
+#~ "внутрішня помилка: небезбітовий розділ слідом за безбітовим розділом"
+
+#~ msgid "linker backend didn't specify function to relocate section"
+#~ msgstr "у сервері компонування не визначено функції для розділу пересування"
+
+#~ msgid "while writing output file: %s"
+#~ msgstr "під час запису файла вихідних даних: %s"
+
+#~ msgid "while finishing output file: %s"
+#~ msgstr "під час закриття файла вихідних даних: %s"
+
+#~ msgid "cannot stat output file"
+#~ msgstr "не вдалося обробити stat файл виводу даних"
+
+#~ msgid "WARNING: temporary output file overwritten before linking finished"
+#~ msgstr ""
+#~ "ПОПЕРЕДЖЕННЯ: файл тимчасового виводу даних було перезаписано до "
+#~ "завершення компонування"
+
+#~ msgid "no machine specific '%s' implementation"
+#~ msgstr "не специфічна для архітектури реалізація «%s»"
+
+#~ msgid "mode for segment invalid\n"
+#~ msgstr "режим сегмента є некоректним\n"
+
+#~ msgid "while reading version script '%s': %s at line %d"
+#~ msgstr "під час читання скрипту версій «%s»: %s у рядку %d"
+
+#~ msgid ""
+#~ "symbol '%s' is declared both local and global for unnamed version '%s'"
+#~ msgstr ""
+#~ "символ «%s» оголошено локально і на загальному рівні для версії без назви "
+#~ "«%s»"
+
+#~ msgid "symbol '%s' is declared both local and global for version '%s'"
+#~ msgstr ""
+#~ "символ «%s» оголошено локально і на загальному рівні для версії «%s»"
+
+#~ msgid "default visibility set as local and global"
+#~ msgstr "типову видимість визначено як локальну і загальну"
+
+#~ msgid "cannot get section header of section %Zu: %s"
+#~ msgstr "не вдалося отримати заголовок розділу %Zu: %s"
+
+#, fuzzy
+#~ msgid "cannot attach to core"
+#~ msgstr "не вдалося створити дерево пошуку"
+
+#~ msgid "'%s' and '%s' do not seem to match"
+#~ msgstr "«%s» і «%s» не відповідають одне одному"
+
+#~ msgid "unknown tag %hx"
+#~ msgstr "невідомий теґ %hx"
+
+#~ msgid "unknown user tag %hx"
+#~ msgstr "невідомий теґ користувача %hx"
+
+#~ msgid "unknown attribute %hx"
+#~ msgstr "невідомий атрибут %hx"
+
+#~ msgid "unknown user attribute %hx"
+#~ msgstr "невідомий атрибут користувача %hx"
+
+#~ msgid ""
+#~ "\n"
+#~ "\n"
+#~ "Symbols from %s[%s]:\n"
+#~ "\n"
+#~ msgstr ""
+#~ "\n"
+#~ "\n"
+#~ "Символи з %s[%s]:\n"
+#~ "\n"
+
+#~ msgid "%s %s differ: section header"
+#~ msgstr "%s %s diff: заголовок розділу"
diff --git a/src/ChangeLog b/src/ChangeLog
new file mode 100644
index 0000000..ae62f4e
--- /dev/null
+++ b/src/ChangeLog
@@ -0,0 +1,5513 @@
+2023-03-27  Di Chen  <dichen@redhat.com>
+
+	* readelf.c (options): Support dynamic symtab print with '-Ds'.
+	(process_symtab): New function.
+	(handle_dynamic_symtab): Likewise.
+	(handle_symtab): Return true if symtab was printed. Move printing
+	code to process_symtab and call that function.
+	(print_symtab): Call handle_dynamic_symtab for SHT_DYNSYM when
+	using dynamic segment.
+	(enum dyn_idx): Include i_symtab_shndx, i_verneednum and
+	i_verdefnum.
+	(process_elf_file): Only call print_symtab for SHT_SYMTAB when not
+	use_dynamic_segment.
+	(get_dynscn_addrs): Handle DT_VERDEFNUM, DT_VERNEEDNUM and
+	DT_SYMTAB_SHNDX.
+
+2023-03-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf (process_elf_file): ebl_closebackend only after
+	comparing ebl pointer.
+
+2023-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_attributes): Add comment about check.
+	(read_encoded): Check readp >= endp before reading
+	DW_EH_PE_uleb128 and DW_EH_PE_sleb128.
+	* elflint.c (check_attributes): Check r >= q before reading
+	uleb128.
+	(print_debug_frame_section): Check augmentation length can be read
+	as uleb128.
+	(print_debug_exception_table): Likewise for ttype_base_offset,
+	call_site_table_len and action.
+
+2023-01-22  Mark Wielaard  <mark@klomp.org>
+
+	* addr2line.c (options): Separate --demangle and -C.
+	(parse_opt): Ignore 'b'.
+
+2023-01-10  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (get_debug_elf_data): New function.
+	(print_debug_abbrev_section): Use get_debug_elf_data.
+	(print_debug_addr_section): Likewise.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_rnglists_section): Likewise.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_frame_section): Likewise.
+	(print_debug_units): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loclists_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_macro_section): Likewise.
+	(print_debug_str_section): Likewise.
+	(print_debug_str_offsets_section): Likewise.
+	(print_debug_pubnames_section): Likewise.
+
+2022-12-21  Shahab Vahedi  <shahab@synopsys.email>
+
+	* elflint.c (valid_e_machine): Add EM_ARCV2.
+
+2022-12-02  Hengqi Chen  <hengqi.chen@gmail.com>
+
+	* elflint.c (valid_e_machine): Add EM_LOONGARCH.
+
+2022-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (get_dynscn_addrs): Check gelf_getdyn doesn't
+	return NULL.
+
+2022-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_dynamic): Check phdr != NULL when
+	use_dynamic_segment, otherwise check shdr != NULL.
+
+2022-10-28  Arsen Arsenović  <arsen@aarsen.me>
+
+	* readelf.c (options): Add Binutils-style --syms alias.
+
+2022-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (dwarf_loc_list_encoding_string): Handle
+	DW_LLE_GNU_view_pair.
+	(print_debug_loclists_section): Likewise.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* arlib.h: Use BYTE_ORDER, LITTLE_ENDIAN and BIG_ENDIAN.
+
+2022-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* ar.c (do_oper_extract): Predecrement instance before compare
+	to zero.
+	(do_oper_delete): Likewise.
+
+2022-08-10  Andreas Schwab  <schwab@suse.de>
+
+	* readelf.c (print_attributes): Also handle SHT_RISCV_ATTRIBUTES.
+
+2022-08-09  Andreas Schwab  <schwab@suse.de>
+
+	* elflint.c (check_program_header): Don't complain about p_filesz
+	> p_memsz if p_memsz is zero and p_type is PT_RISCV_ATTRIBUTES.
+
+2022-08-01  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_dynamic): Pass start of buffer to memrchr.
+	Use dyn->d_un.d_val for offsets instead of d_ptr.
+
+2022-04-28  Di Chen  <dichen@redhat.com>
+
+	* readelf.c (options): Add use-dynamic 'D'.
+	(use_dynamic_segment): New static bool.
+	(enum dyn_idx): New.
+	(get_dynscn_strtab): New function.
+	(get_dynscn_addrs): Likewise.
+	(find_offsets): Likewise.
+	(parse_opt): Handle 'D'.
+	(handle_dynamic): New argument phdr. Get data either through the shdr
+	or phdr.  Print segment info when use_dynamic_segment. Use
+	get_dynscn_strtab. Get library name and paths through strtab_data.
+
+2022-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (remove_debug_relocations): Check gelf_getshdr, gelf_getrela,
+	gelf_getrel and gelf_getsymshndx don't return NULL.
+
+2022-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* elfcompress.c (process_file): Sanity check shstrtab_name,
+	shstrtab_newname and symstrents are only set once.
+
+2022-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* elfclassify.c (main): Use classify_flag_no_stdin for no-std in options.
+
+2022-04-19  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (get_dyn_ents): Define dyn_mem outside the while loop.
+
+2022-03-01  Di Chen  <dichen@redhat.com>
+
+	* readelf.c (get_dyn_ents): New function.
+	(handle_dynamic): Use get_dyn_ents to get the actual number of
+	Dynamic entries in the section.
+
+2022-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* addr2line.c: Replace error (EXIT_FAILURE, ...) with error_exit(...).
+	* ar.c: Likewise.
+	* arlib.c: Likewise.
+	* elfcompress.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2022-03-24  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_note_data): Recognize NT_FDO_PACKAGING_METADATA.
+
+2022-03-11  Mark Wielaard  <mark@klomp.org>
+
+	* addr2line.c (OPT_RELATIVE): New constant.
+	(options): Add --relative.
+	(use_comp_dir): Initialize to true.
+	(parse_opt): Handle OPT_RELATIVE.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ehdr): Pass sizeof (buf) - 1 to strncpy.
+
+2021-10-20  John M Mellor-Crummey  <johnmc@rice.edu>
+
+	* readelf.c (print_debug_line_section): Try to read
+	debug_str_offset if available.  Handle DW_LNE_NVIDIA_inlined_call
+	and DW_LNE_NVIDIA_set_function_name.
+
+2021-10-06  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_sections): Don't dereference databits if bad.
+
+2021-09-09  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* findtextrel.c: Include "libeu.h".
+	(open_rootdir_file): New function.
+	(process_file): Use it to open file inside rootdir.
+	* Makefile.am (findtextrel_no_Wstack_usage): Remove.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* objdump.c (show_disasm): Replace asprintf followed by
+	error(EXIT_FAILURE) with xasprintf.
+	* readelf.c (handle_gnu_hash): Likewise.
+	* unstrip.c (handle_output_dir_module, main): Likewise.
+
+	* elflint.c (check_sections): Remove cast of xcalloc return value.
+	* findtextrel.c (process_file): Remove casts of malloc and realloc
+	return values.
+	* nm.c (get_local_names, show_symbols_sysv, show_symbols): Remove
+	casts of xmalloc return values.
+	* readelf.c (print_hash_info, handle_sysv_hash, handle_sysv_hash64,
+	handle_gnu_hash): Remove cast of xcalloc return value.
+	(print_debug_units): Remove casts of xmalloc return values.
+	* strip.c (handle_elf): Remove casts of xcalloc and xmalloc return
+	values.
+
+2021-09-05  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* Makefile.am (AM_LDFLAGS): Add $(STACK_USAGE_NO_ERROR).
+
+2021-08-20  Saleem Abdulrasool  <abdulras@google.com>
+
+	* elfclassify.c: Remove error.h include.
+
+2021-03-18  Timm Bäder  <tbaeder@redhat.com>
+
+	* readelf.c (run_advance_pc): New static inline function
+	lifted from...
+	(print_debug_line_section): ... here. Define advance_pc
+	using run_advance_pc.
+
+2021-07-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (compare_listptr): Fix dwarf_attr_name argument.
+
+2021-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (adjust_relocs): Check gelf_getrel and geld_getrela.
+
+2021-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (remove_debug_relocations): Check gelf_update results.
+	(update_section_size): Likewise.
+
+2021-06-06  Sergei Trofimovich  <slyfox@gentoo.org>
+
+	* elflint.c (buffer_left): Mark as 'static' to avoid external linkage
+	failure.
+
+2021-05-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* elfcompress.c (process_file): Return 1 instead of -1 in case of an
+	error.
+
+	* elfcompress.c (process_file): Remove redundant assignment in case of
+	"Nothing to do".
+
+	* elfcompress.c (process_file): Set res to 0 in case of "Nothing to do".
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* elfclassify.c (run_classify): Use startswith.
+	* elfcompress.c (process_file): Likewise.
+	* nm.c (show_symbols_sysv): Likewise.
+	* readelf.c (print_debug): Likewise.
+	(handle_notes_data): Likewise.
+	(dump_data_section): Likewise.
+	(print_string_section): Likewise.
+	* strip.c (remove_debug_relocations): Likewise.
+
+2021-04-03  Mark Wielaard  <mark@klomp.org>
+
+	* nm.c (show_symbols): close dwfl_fd if dwfl_begin fails.
+
+2021-04-03  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (handle_output_dir_module): Free output_file when done.
+
+2021-04-03  Mark Wielaard  <mark@klomp.org>
+
+	* ar.c (do_oper_insert): Always close newfd.
+
+2021-03-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_symtab): Sanity check verneed vna_next,
+	vn_next and verdef vd_next offsets.
+
+2021-03-02  Timm Bäder  <tbaeder@redhat.com>
+
+	* elfcompress.c (process_file): Remove cleanup() function and
+	replace it with a cleanup label at the end of the function.
+	Initialize res to -1.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elfcompress.c (process_file): Move get_sections function...
+	(get_section): ...to top-level static function taking an
+	sections array and shnum.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elfcompress.c (process_file): Move get_section function...
+	(get_section): ...to top-level static function taking an
+	sections array.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elfcompress.c (process_file): Move set_section function...
+	(set_section): ...to top-level static function taking a
+	section array.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* unstrip.c (handle_implicit_modules): Inline the next function
+	in three places. This is simply dwfl_getmodules with match_module
+	callback providing mmi.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* unstrip.c (handle_explicit_files): Move warn function...
+	(warn): ...here as top-level static function taking stripped,
+	unstripped files and force flag as extra arguments.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Inline find_unalloc_section
+	function into calling location. The sec pointer is set to NULL
+	before the if-else statement and only set when match is found.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* unstrip.c (find_alloc_sections_prelink): Move check_match to...
+	(check_match): Adjusted to return whether there was no match,
+	which indicates a failure. So callers are adjusted to or the
+	result into a local fail boolean.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* unstrip.c (adjust_relocs): Move adjust_reloc function to...
+	(adjust_reloc): ... here as static top-level function taking
+	a map array and size as extra arguments.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elflint.c (check_attributes): Rename and move left function...
+	(buffer_left): ...as static toplevel function taking both an
+	Elf_Data pointer argument and the unsigned char pointer p.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elflint.c (check_attributes): Rename and move pos function...
+	(buffer_pos): ...as static toplevel function taking an extra
+	Elf_Data pointer argument.
+
+2021-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Type DIE offset is from start CU.
+
+2021-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Don't handle blocks as expression
+	blocks for DWARF version 4 or higher.
+
+2021-02-03 Timm Bäder <tbaeder@redhat.com>
+
+	* ar.c (do_oper_extract): Extract should_truncate_fname function
+	to...
+	(should_truncate_fname): ...here. New file scope function taking
+	size_t pointer to be read and/or set.
+
+2021-02-02 Timm Bäder <tbaeder@redhat.com>
+
+	* readelf.c (print_debug_line_section): Remove unnecessary
+	show_op_index variable, replace with (op_index > 0).
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* readelf.c (print_cfa_program): Lift regname function to...
+	(regname): ...here. New file scope function add ebl and regnamebuf
+	as arguments.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* readelf.c (print_attributes): Lift left function to...
+	(left): ...here. New file scope function taking Elf_Data and char
+	pointers.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* readelf.c (handle_core_registers): Lift same_set function to...
+	(same_set): ...here. New file scope function adding regs and
+	maxnreg arguments.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* readelf.c (parse_opt): Lift add_dump_section function to...
+	(add_dump_section): ...here. New top level function. Added key
+	argument.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* arlib-argp.c (help_filter): Lift text_for_default function to...
+	(text_for_default): ... here. New file scope function taking text
+	as argument.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* addr2line.c (handle_address): Move show_note and show_int up to
+	file scope.
+	(show_note: New static inline function.
+	(show_int): Likewise.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* strip.c (handle_elf): Remove no_symtab_updates function and
+	calls inside the switch statement. Add checks and (possibly)
+	continue, before switch statement is called.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* strip.c (handle_elf): Move inlined update_section_size function
+	to...
+	(update_section_size): ...here. New static function that takes as
+	extra arguments the Elf_Scn, debug_elf, section cnt and fname.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* strip.c (remove_debug_relocations): Rewrite inlined relocate
+	function to file static. Do R_*_NONE, reloc_simple_type and
+	ebl_debug_scn_p checks before calling new relocate function.
+	(relocate): New file static function from
+	remove_debug_relocate. Remove R_*_NONE, reloc_simple_type and
+	ebl_debugscn_p checks.
+
+2021-01-08  Timm Bäder  <tbaeder@redhat.com>
+
+	* strip.c (handle_elf): Expand inlined function check_preserved.
+
+2021-01-12  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (EXTRA_SHFLAGS): New define.
+	(check_sections): Use EXTRA_SHFLAGS. Add SHF_GNU_RETAIN to
+	ALL_SH_FLAGS.
+
+2020-12-31  Sergei Trofimovich  <slyfox@gentoo.org>
+
+	* elflint.c (section_flags_string): Add NEWFLAG for GNU_RETAIN,
+	ORDERED and EXCLUDE.
+
+2020-12-31  Sergei Trofimovich  <slyfox@gentoo.org>
+
+	* elflint.c (section_flags_string): Update cp pointer after
+	snprintf for unknown flags.
+
+2020-12-16  Érico Nogueira  <ericonr@disroot.org>
+
+	* readelf.c (qsort_r): Use qsort for improved portability.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+2020-12-12  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_sections): Handle SHF_GNU_RETAIN.
+	* readelf.c (print_shdr): Likewise.
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* *.c: Replace gettext(...) with _(...).
+
+	* unstrip.c (_): Remove.
+
+2020-12-15  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_symtab): Always print symbol name (if known)
+	in error messages.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* ar.c (write_member, do_oper_insert): Fix spelling typo in comment.
+	* elfclassify.c (issue, elf_issue, is_unstripped): Likewise.
+	* elfcompress.c (process_file): Likewise.
+	* elflint.c (be_quiet, check_gnu_hash): Likewise.
+	* readelf.c (print_phdr, handle_gnu_hash,
+	dwarf_locexpr_opcode_string): Likewise.
+	* size.c (totals_class): Likewise.
+	* strings.c (read_elf): Likewise.
+	* strip.c (handle_elf): Likewise.
+
+	* readelf.c (print_debug_addr_section): Fix spelling typo in error
+	diagnostics.
+	* strip.c (options): Fix spelling typos in argp help text.
+	* strings.c (options): Likewise.
+	* stack.c (options): Likewise.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* unstrip.c (make_directories): Use ACCESSPERMS for mkdir.
+	(handle_file): Use DEFFILEMODE for open with O_CREAT for ET_REL
+	files, ACCESSPERMS otherwise.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* Makefile.am (nm_LDADD): Add obstack_LIBS.
+	(ranlib_LDADD): Likewise.
+	(ar_LDADD): Likewise.
+
+2020-10-27  Érico N. Rolim  <erico.erc@gmail.com>
+
+	* unstrip.c (make_directories): Use strndup, not strndupa.
+
+2020-09-28  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (next_listptr_offset): Take idx as pointer, to be updated
+	and use new Dwarf_Off as offset to match.
+	(listptr_attr): New function.
+	(print_debug_loclists_section): Check for DW_AT_GNU_locviews to show
+	view pairs.
+	(print_debug_loc_section): Adjust next_listptr_offset call.
+
+2020-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_cfa_program): Take ehdr as argument. Use it to
+	recognize DW_CFA_AARCH64_negate_ra_state.
+	(print_debug_frame_section): Pass ehdr to print_cfa_program.
+	(print_debug): Don't warn if we dump frames, but cannot get dbg.
+
+2020-09-01  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_ranges_section): Base address entry can
+	be first.
+	(print_debug_loc_section): Likewise.
+
+2020-09-04  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (special_sections): Add .debug_line_str.
+
+2020-08-26  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_line_section): It is not an error if there
+	are no line number statements at the end of a debug line section.
+
+2020-07-19  Mark Wielaard  <mark@klomp.org>
+
+	* elfclassify.c (process_current_path): Handle fwrite failing.
+
+2020-07-05  Mark Wielaard  <mark@klomp.org>
+
+	* stack.c (module_callback): Don't assert if dwfl_module_info fails.
+	* unstrip.c (adjust_relocs): Produce a proper error when HAS
+	section has inconsistent size or entsize.
+	(match_module): Don't assert if dwfl_module_info fails.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* ar.c (do_oper_extract): Split large if statement. Call fchown
+	before fchmod and explicitly ignore the return value.
+	(do_oper_delete): Likewise.
+	(do_oper_insert): Likewise.
+	* ranlib.c (handle_file): Likewise.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_elf_header): Explicitly check and ignore
+	any error from elf_compress.
+
+2020-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* nm.c (sort_by_name_strtab): Replace by...
+	(sort_by_name_elf): New static Elf pointer and ...
+	(sort_by_name_ndx): New static size_t index.
+	(sort_by_name): Use elf_strptr to get symbol string.
+	(show_symbols): Set sort_by_name_elf and sort_by_name_ndx.
+
+2020-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* nm.c (show_symbols_sysv): Skip no name and STT_FILE symbols.
+	When not printing address and size pad strings. Strip "GNU_"
+	prefix from binding name.
+	(class_type_char): Use 'V' for weak symbols, 'C' for common
+	symbols and 'T' for weak functions.
+	(show_symbols_posix): Skip STT_FILE symbols. Don't print value and
+	size when undefined.
+
+2020-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_program_header): Remove PT_GNU_PROPERTY define.
+
+2020-05-14  Mark Wielaard  <mark@klomp.org>
+
+	* size.c (show_bsd): Set printf format based on radix.
+
+2020-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (process_elf_file): Error out if ebl_openbackend fails.
+	* objdump.c (handle_elf): Likewise.
+	* nm.c (handle_elf): Likewise. Move full name string construction
+	forward, so it can be used in the error message.
+
+2020-04-17  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug): Check .gnu.debuglto_ prefix.
+
+2020-04-16  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_sections): Mask out SHF_EXCLUDE from processor
+	specific section flags when --gnu is given.
+
+2020-02-08  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_program_header): Handle PT_GNU_PROPERTY.
+
+2020-02-07  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_symtab): Check st_info isn't too big.
+
+2020-01-16  Mark Wielaard  <mark@klomp.org>
+
+	* nm.c (show_symbols_sysv): Iterate over all symbols starting
+	at index zero.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (BUILD_STATIC): Add libraries needed for libdw.
+
+2019-10-26  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (collect_symbols): Check symbol strings are
+	terminated.
+
+2019-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (adjust_relocs): Set versym data d_size to the actual
+	size allocated.
+
+2019-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (copy_elided_sections): Set and check max_off.
+
+2019-10-21  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (adjust_relocs): Add map_size argument and check ndx
+	against it.
+	(adjust_all_relocs): Add map_size argument and pass it to
+	adjust_relocs.
+	(add_new_section_symbols): Call adjust_all_relocs with symndx_map
+	size.
+	(collect)symbols): Check sym and string data can be found.
+	(compare_symbols_output): Call error when (different) symbols are
+	equal.
+	(new_shstrtab): Make unstripped_strent array one larger. Check
+	stripped_shnum isn't zero.
+	(copy_elided_sections): Add ndx_sec_num as size of ndx_section
+	array. Check sh_link and sh_info are not larger than ndx_sec_num.
+	Allocate symbols and symndx_map arrays on heap, not stack. Pass
+	map sizes to adjust_all_relocs.
+
+2019-09-28  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* elflint.c (main): When an input file cannot be opened,
+	include its name into the error diagnostics.
+	* readelf.c (main): Likewise.
+
+2019-09-02  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (PRINT_DYNSYM_TABLE): New argp key value.
+	(argp_opt): Add syn-sym.
+	(print_dynsym_table): New static bool.
+	(parse_opt): Handle PRINT_DYNSYM_TABLE.
+	(process_elf_file): Check print_dynsym_table.
+
+2019-08-27  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (for_each_section_argument): Call (*dump) also for
+	section numbers.
+
+2019-08-26  Mark Wielaard  <mark@klomp.org>
+
+	* nm.c (show_symbols): Remember nentries_orig and check before
+	freeing sym_mem.
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Remove -ldl.
+	(elflint_LDADD): Add $(libdw).
+	(elfcmp_LDADD): Add $(libdw).
+	(objdump_LDADD): Add $(libdw).
+
+2019-08-26  Mark Wielaard  <mark@klomp.org>
+
+	* readelf (options): Add OPTION_ARG_OPTIONAL "SECTION" for notes.
+	(notes_section): New global variable.
+	(parse_opt): Set notes_section.
+	(handle_notes): Check if notes_section is set.
+
+2019-07-26  Florian Weimer  <fweimer@redhat.com>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (bin_PROGRAMS): Add elfclassify.
+	(elfclassify_LDADD): New variable.
+	* elfclassify.c: New tool.
+
+2019-07-13  Mao Han  <han_mao@c-sky.com>
+
+	* elflint.c: Add C-SKY.
+
+2019-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ehdr): Use dwelf_elf_e_machine_string instead of
+	ebl->name. If unknown print hex value.
+
+2019-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* stack.c (parse_opt): Fix dwfl_core_file_attach error message.
+
+2019-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Use elf_begin ELF_C_WRITE, instead of
+	ELF_C_WRITE_MMAP.
+
+2019-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (struct attrcb_args): Rename die to dies.
+	(attr_callback): Get current current die using dies[level].
+	Handle DW_AT_discr_list as block, not as constant.
+	(print_debug_units): pass dies, not dies[level] as args.
+
+2019-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (cleanup_list): New function.
+	(main): Call cleanup_list for dump_data_sections and string_sections.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (add_new_section_symbols): Call ELF_CHECK after
+	gelf_getsymshndx.
+	(new_shstrtab): Call ELF_CHECK after gelf_getshdr.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* size.c (show_sysv): Call INTERNAL_ERROR if gelf_getshdr
+	returns NULL.
+	(show_sysv_one_line): Call error with EXIT_FAILURE if
+	gelf_getshdr returns NULL.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* nm.c (show_symbols_sysv): Check gelf_getshdr doesn't return
+	NULL. Simplify naming of invalid sections, don't use alloca.
+
+2019-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* elfcmp.c (main): Check shdr1 and shdr2 are not NULL.
+
+2019-04-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Print DW_AT_data_member_location as
+	decimal offset, not hex number.
+
+2019-03-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_macinfo_section): Check cus[0] is not the
+	sentinel.
+
+2019-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Assert that symbol section number exists.
+
+2019-01-24  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Fix check test for SHN_XINDEX symbol.
+
+2019-01-22  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_line_section): Check we are not at end of
+	line data when reading parameters for unknown opcodes.
+
+2019-01-20  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_line_section): Check terminating NUL byte
+	for dir and file tables.
+
+2019-01-16  Mark Wielaard  <mark@klomp.org>
+
+	* readelf (handle_core_note): Pass desc to ebl_core_note.
+
+2018-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_program_header): Allow PT_GNU_EH_FRAME segment
+	to be matched against SHT_X86_64_UNWIND section.
+
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (remove_debug_relocations): Check if section is gnu
+	compressed and decompress and recompress it.
+
+2018-11-12  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_note_data): Recognize NT_GNU_BUILD_ATTRIBUTE_OPEN
+	and NT_GNU_BUILD_ATTRIBUTE_OPEN.
+	* readelf.c (handle_notes_data): Handle
+	ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX. Pass nhdr.n_namesz to
+	ebl_object_note.
+
+2018-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_notes_data): Pass n_descsz to
+	ebl_object_note_type_name.
+	* elflint.c (check_note_data): Recognize NT_VERSION, add owner
+	name to unknown note error.
+
+2018-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (process_elf_file): Use dwelf_elf_begin to open pure_elf.
+
+2018-10-26  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (OPT_RELOC_DEBUG_ONLY): New define.
+	(options): Add reloc-debug-sections-only.
+	(reloc_debug_only): New static bool.
+	(main): Check reloc_debug_only is the only strip option used.
+	(parse_opt): Handle OPT_RELOC_DEBUG_ONLY.
+	(handle_debug_relocs): New function.
+	(handle_elf): Add local variables lastsec_offset and lastsec_size.
+	Handle reloc_debug_only.
+
+2018-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Extract code to update shdrstrndx into...
+	(update_shdrstrndx): ... this new function.
+
+2018-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Extract code into separate functions...
+	(secndx_name): ... new function.
+	(get_xndxdata): Likewise.
+	(remove_debug_relocations): Likewise.
+
+2018-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Always copy over phdrs if there are any
+	and check phnum instead of e_type to determine whether to move
+	allocated sections.
+
+2018-11-02  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (copy_elf): Add ELF_CHECK to make sure gelf_getehdr ()
+	doesn't return NULL.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_note_data): Recognize NT_GNU_PROPERTY_TYPE_0.
+	(check_note): Use p_align to pass either ELF_T_NHDR or ELF_T_NHDR8 to
+	elf_getdata_rawchunk.
+	* readelf (handle_notes): Likewise.
+
+2018-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* addr2line.c (print_addrsym): Use elf_getshdrstrndx instead of
+	Ehdr field.
+
+2018-10-24  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (section_name): Remove ehdr argument, lookup shstrndx.
+	(print_debug_abbrev_section): Don't pass ehdr.
+	(print_debug_addr_section): Likewise.
+	(print_decoded_aranges_section): Likewise.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_rnglists_section): Likewise.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_units): Likewise.
+	(print_decoded_line_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loclists_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_macro_section): Likewise.
+	(print_debug_pubnames_section): Likewise.
+	(print_debug_str_section): Liekwise.
+	(print_debug_str_offsets_section): Likewise.
+	(print_gdb_index_section): Likewise.
+
+2018-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_frame_section): Make sure readp is never
+	greater than cieend.
+
+2018-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl_module_getdwarf.c (adjust_relocs): Check sh_entsize is not
+	zero.
+	(add_new_section_symbols): Likewise.
+	(copy_elided_sections): Likewise.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* size.c (handle_ar): Only close elf if prefix was NULL.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* arlib.c (arlib_add_symbols): Check that sh_entsize is not zero.
+
+2018-10-14  Mark Wielaard  <mark@klomp.org>
+
+	* ar.c (do_oper_extract): Assume epoch if ar_date is bogus.
+
+2018-10-14  Mark Wielaard  <mark@klomp.org>
+
+	* findtextrel.c (process_file): Check that sh_entsize is not zero.
+
+2018-10-13  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_macro_section): Use elf_getdata. Print
+	decoded flag string.
+
+2018-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (copy_elided_sections): Renumber group section indexes.
+
+2018-10-12  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Don't remove SHF_GROUP flag from sections.
+	Skip group section flag when renumbering section indexes.
+	* unstrip.c (struct section): Add sig field.
+	(compare_unalloc_sections): Take and use sig1 and sig2 as arguments.
+	(compare_sections): Pass signatures to compare_unalloc_sections.
+	(get_group_sig): New function.
+	(find_alloc_sections_prelink): Set signature.
+	(copy_elided_sections): Likewise and pass them on.
+	(find_unalloc_section): Take and pass signatures.
+
+2018-10-02  Andreas Schwab  <schwab@suse.de>
+
+	* strip.c (handle_elf): Handle ADD/SUB relocation.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_shdr): Get number of section with elf_getshdrnum.
+	(print_phdr): Likewise.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Check against shstrndx, not e_shstrndx.
+	Explicitly set shdrstrndx for debug file.
+	* unstrip.c (copy_elf): Explicitly copy shstrndx.
+	(find_alloc_sections_prelink): Document shnum usage.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_elf_header): Use shnum instead of e_shnum for all
+	checks.
+	(check_symtab): Use shstrndx instead of e_shstrndx to get section
+	names.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* elfcmp.c (main): Get, check and shdrstrndx for section names.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* elfcmp.c (main): Call ebl_section_strip_p without ehdr.
+	* strip.c (handle_elf): Likewise.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_symtab): Call ebl_check_special_symbol without
+	ehdr.
+
+2018-07-30  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Track allocated/unallocated sections seen. Set
+	section offset of unallocated sections after handling all allocated
+	sections.
+
+2018-08-18  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_aranges_section): Make sure there is enough
+	data to read the header segment size.
+
+2018-08-18  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_sysv_hash): Calculate needed size using unsigned
+	long long int to prevent overflow.
+	(check_sysv_hash64): Calculate maxwords used separately before
+	comparison to prevent overflow.
+
+2018-07-24  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (compare_unalloc_sections): Also compare sh_size.
+
+2018-07-21  Mark Wielaard  <mark@klomp.org>
+
+	* unstrip.c (adjust_all_relocs): Skip SHT_GROUP sections.
+
+2018-07-21  Mark Wielaard  <mark@klomp.org>
+
+	* elfcompress.c (get_sections): New function.
+	(process_file): Check whether section needs to change. Don't rewrite
+	file if no section data needs changing.
+	(main): Update 'force' help text.
+
+2018-07-21  Mark Wielaard  <mark@klomp.org>
+
+	* elfcompress.c (process_file): Swap fchmod and fchown calls.
+
+2018-07-04  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_addr_section): Rename index var to uidx.
+	(attr_callback): Rename index var to word.
+	(print_debug_str_offsets_section): Rename index var to uidx.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* addr2line.c: Remove error.h include.
+	* ar.c: Likewise.
+	* arlib.c: Likewise and add system.h include.
+	* arlib2.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elfcompress.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* stack.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2018-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_decoded_line_section): Use dwarf_next_lines
+	instead of dwarf_nextcu.
+	(print_debug_line_section): Don't explicitly lookup CU.
+
+2018-06-15  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Only print block as expressions if it
+	isn't DW_FORM_data16.
+
+2018-06-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_form_data): Check we have 4, not 2, bytes
+	available for DW_FORM_block4.
+
+2018-06-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_form_data): Don't increase strreadp after use.
+	Do increase readp for DW_FORM_strx[1234].
+
+2018-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_loc_section): Make sure next_off doesn't
+	overflow d_buf.
+
+2018-06-13  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (die_type_sign_bytes): New function.
+	(attr_callback): Recognized DW_FORM_implicit_cost as signed. Use
+	die_type_sign_bytes to lookup the signedness and size of const
+	values.
+
+2018-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_form_data): Don't reuse readp and readendp when
+	reading str_offsets section.
+
+2018-06-10  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_form_data): Don't cast value to ptrdiff_t, cast
+	ptrdiff_t to size_t.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_rnglists_section): Calculate max_entries
+	instead of needed bytes to prevent overflowing. Always print
+	max_entries (but not more).
+	(print_debug_loclists_section): Likewise.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_line_section): Stop printing directories
+	and files when we are at the end of the unit data.
+
+2018-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (format_result): Removed.
+	(format_result_size): Removed.
+	(format_dwarf_addr): Renamed to...
+	(print_dwarf_addr): ...this. Simply call printf, don't setup buffer,
+	don't call sprintf.
+	(print_ops): Use print_dwarf_addr instead of format_dwarf_addr.
+	(print_debug_addr_section): Likewise.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_rnglists_section): Likewise.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_frame_section): Likewise.
+	(attr_callback): Likewise.
+	(print_decoded_line_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loclists_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_gdb_index_section): Likewsie.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_addr_section): Set unit_length always to
+	(next_unitp - readp) in case we don't have a real header.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_loc_section): Set begin to idx when failing
+	to read the start address if DW_LLE_GNU_start_end_entry.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_sysv_hash): Don't leak lengths array when
+	detecting an invalid chain.
+	(handle_sysv_hash64): Likewise.
+
+2018-06-05  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_macro_section): Extend vendor array by one
+	to include max DW_MACRO_hi_user opcode.
+
+2018-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (main): Lookup "no" for no_str.
+	(print_debug_abbrev_section): Use yes_str and no_str.
+	(print_form_data): Likewise.
+
+2018-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* readelf (format_result): New static char pointer.
+	(format_result_size): New static size_t.
+	(format_dwarf_addr): Calculate max string size, reuse format_result
+	if possible, otherwise realloc. Use sprintf on result, not asprintf.
+	(print_ops): Don't free format_dwarf_addr, make sure result is
+	printed before calling format_dwarf_addr again.
+	(print_debug_addr_section): Likewise.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_rnglists_section): Likewise.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_frame_section): Likewise.
+	(attr_callback): Likewise.
+	(print_decoded_line_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loclists_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_gdb_index_section): Likewsie.
+
+2018-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (yes_str): New static char pointer.
+	(no_str): Likewise.
+	(main): Set yes_str and no_str using gettext.
+	(attr_callback): Use yes_str and no_str instead of calling gettext.
+
+2018-06-04  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (main): Call __fsetlocking (stdout, FSETLOCKING_BYCALLER).
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Print the dwo name and id when
+	unable to find a .dwo file.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (enum section_e): Make section_types not an alias of
+	section_info.
+	(section_all): Add section_types.
+	(parse_opt): Add both section_info and section_types for "info"
+	and "info+".
+	(print_debug_units): Don't be silent for debug_types.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Only register section_loc when not
+	looking at a split dwarf from a skeleton.
+
+2018-05-30  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_loc_section): Use correct listptr for
+	locview attribute.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Check offset against -1 not ~0ul.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_loc_section): Handle GNU DebugFission list
+	entries.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug): Record and reset section_info status in
+	implicit_debug_sections and print_debug_sections.
+
+2018-05-28  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Turn "Could not find split compile
+	unit" into an Warning instead of an error.
+
+2018-04-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (parse_opt): Request implicit section_info for "str".
+	(known_stroffbases): New static variable.
+	(attr_callbackattr_callback): Handle DW_AT_str_offets_base.
+	(print_debug_str_offsets_section): New function.
+	(print_debug): Handle .debug_str_offsets as section_str. Reset
+	known_stroffbases.
+
+2018-04-27  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (options): Add addr.
+	(enum section_e): Add section_addr.
+	(section_all): Add section_addr.
+	(parse_opt): Parse "addr".
+	(known_addrbases): New static variable.
+	(get_listptr): New function.
+	(print_debug_addr_section): Likewise.
+	(attr_callback): Handle DW_AT_addr_base and DW_AT_GNU_addr_base.
+	(print_debug): Add NEW_SECTION (addr). Reset known_addrbases.
+
+2018-04-07  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Handle DW_FORM_loclistx and
+	DW_AT_segment.
+
+2018-04-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (dwarf_loc_list_encoding_string): New functions.
+	(dwarf_loc_list_encoding_name): Likewise.
+	(known_loclistptr): Renamed and split in two...
+	(known_locsptr): this and ...
+	(known_loclistsptr): this.
+	(listptr_base): Split out...
+	(cudie_base): ...this.
+	(is_split_dwarf): New function.
+	(attr_callback): Handle DW_AT_loclists_base and notice sec_offset
+	in correct list.
+	(print_debug_rnglists_section): Use spit_dwarf_cu_base.
+	(print_debug_loclists_section): New function.
+	(print_debug_loc_section): Use known_locsptr instead of
+	known_loclistptr.
+	(print_debug): Recognize .debug_loclists. Reset known_locsptr and
+	known_loclistsptr.
+
+2018-05-25  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (DWARF_SKELETON): New constant.
+	(do_not_close_dwfl): New bool.
+	(options): Add dwarf-skeleton.
+	(dwarf_skeleton): New static variable.
+	(parse_opt): Handle DWARF_SKELETON, set dwarf_skeleton.
+	(create_dwfl): New function, with code extracted from...
+	(process_file): ...here. Check do_not_close_dwfl.
+	(is_split_darf): New function.
+	(getone_dwflmod): Likewise.
+	(print_debug): Use new functions to find skeleton DWARF file to use
+	when inspecting .dwo split DWARF file.
+
+2018-04-11  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (dwarf_range_list_encoding_string): New function.
+	(dwarf_range_list_encoding_name): Likewise.
+	(known_rnglistptr): New static variable.
+	(listptr_cu): New function.
+	(print_debug_rnglists_section): Likewise.
+	(attr_callback): Call notice_listptr for DW_AT_ranges. Handle
+	DW_AT_rnglists_base. Handle DW_FORM_rnglistx. DW_AT_start_scope
+	can also have a rnglist.
+	(print_debug_units): Do (silently) scan split DWARF also for
+	debug_ranges before DWARF5 to catch all rangelistptrs.
+	(print_debug): Recognize .debug_rnglists. Reset known_rnglistptr.
+
+2018-01-21  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (get_indexed_addr): New function.
+	(print_ops): Handle DW_OP_addrx, DW_OP_GNU_addr_index,
+	DW_OP_constx, DW_OP_GNU_const_index separately and resolve
+	address.
+	(attr_callback): Print index and address for
+	DW_FORM_GNU_addr_index and DW_FORM_addrx[1234].
+
+2018-01-19  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (options): Add info+.
+	(show_split_units): New static boolean defaulting to false.
+	(parse_opt): For all (no arg) --debug-dump set show_split_units
+	to yes. For "info+" enable section_info and show_split_units.
+	(attrcb_args): Add is_split field.
+	(attr_callback): Use is_split to format DIE offsets differently.
+	(print_debug_units): Likewise. Get subdie (type or split) only
+	when needed. When not silent reiterate over split DIEs when
+	found.
+
+2018-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Print unit type and id for any
+	unit type that has it even when version < 5.
+
+2018-05-14  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ops): Handle DW_OP_GNU_addr_index and
+	DW_OP_GNU_const_index.
+	(attr_callback): Handle DW_FORM_GNU_addr_index as DW_FORM_addrx.
+	Handle DW_FORM_GNU_str_index as DW_FORM_constx. Add as_hex_id.
+	Handle DW_AT_GNU_dwo_id as_hex_id.
+	(print_form_data): Handle DW_FORM_GNU_str_index as DW_FORM_strx.
+
+2018-05-12  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug): Also recognize .dwo section name variants.
+
+2018-05-15  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* elflint.c (check_elf_header): Fix typo in error diagnostics.
+
+2018-05-15  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_form_data): Cast comparisons against offset_len to
+	ptrdiff_t.
+	(print_debug_line_section): Print uint64_t as PRIu64.
+
+2018-05-11  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_macro_section): Use libdw_valid_user_form.
+	Use print_form_data for strx and sup strings.
+
+2018-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (dwarf_line_content_description_string): New function.
+	(dwarf_line_content_description_name): Likewise.
+	(print_bytes): Likewise.
+	(print_form_data): Likewise. Based on code taken from...
+	(print_debug_macro_section): ...here. Now calls print_form_data
+	and str_offsets_base_off.
+	(print_debug_line_section): Parse DWARF5 header, directory and file
+	name tables.
+
+2018-05-12  Mark Wielaard  <mark@klomp.org>
+
+	* addr2line.c (main): Add fflush (stdout) after handle_address ()
+	when reading from stdin.
+
+2018-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_aranges_section): Try elf_rawdata if no
+	sectiondata.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_frame_section): Likewise.
+	(print_debug_line_section): Likewise. Check for data == NULL.
+	(print_debug_loc_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_macro_section): Likewise.
+
+2018-04-28  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug): If .debug_info is needed implicitly by
+	then handle it first before handling any other debug section.
+	(parse_opt): Set implicit_debug_sections to section_info when
+	showing all debug sections.
+
+2018-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Handle DW_FORM_ref_sup4 and
+	DW_FORM_ref_sup8 as references.
+
+2018-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_str_section): Take raw section data. Don't
+	use dwarf_getstring, but determine start and end of string from
+	offset and section data directly.
+	(print_debug): Handle ".debug_line_str" like ".debug_str".
+
+2018-04-19  Andreas Schwab  <schwab@suse.de>
+
+	* elflint.c (valid_e_machine): Add EM_RISCV.
+
+2018-04-16  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_line_section). In advance_pc, advance
+	using op_addr_advance, not op_advance.
+
+2018-04-14  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Only show errors when not silent.
+
+2018-03-23  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Handle DW_FORM_strx[1234].
+
+2018-03-22  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Handle DW_FORM_addrx[1234].
+
+2018-03-28  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_sysv_hash): Break bucket chain after nchain
+	entries are found.
+	(handle_sysv_hash64): Likewise.
+
+2018-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Print dwarf_dieoffset as %PRIx64,
+	not %zx.
+
+2018-03-20  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Report error when DW_AT_decl_file or
+	DW_AT_call_file cannot be resolved.
+
+2018-03-06  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ops): Handle DW_OP_addrx, DW_OP_constx,
+	DW_OP_implicit_pointer, DW_OP_entry_value, DW_OP_const_type,
+	DW_OP_regval_type, DW_OP_deref_type, DW_OP_xderef_type,
+	DW_OP_convert, DW_OP_reinterpret.
+
+2018-03-01  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (struct listptr): Add attr field.
+	(compare_listptr): Warn when two listptrs for the same offset have
+	different attributes.
+	(notice_listptr): Take attr as argument and add it to listptr.
+	(skip_listptr_hole): New attr argument.
+	(next_listptr_offset): New function.
+	(print_debug_ranges_section): Pass NULL attr to skip_listptr_hole.
+	(attr_callback): Handle DW_AT_GNU_locviews. Call notice_listptr with
+	attr.
+	(print_debug_loc_section): Keep track of which attr is associated with
+	a listptr. If the attr is DW_AT_GNU_locview print view pairs till the
+	next listptr offset.
+
+2018-02-09  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_group): Make sure we can read a complete
+	element when iterating over the group.
+
+2018-02-09  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Handle DW_FORM_data16 as Dwarf_Block.
+
+2018-02-09  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_abbrev_section): Print the value of a
+	DW_FORM_implicit_const using dwarf_getabbrevattr_data.
+	(attr_callback): Handle DW_FORM_implicit_const.
+
+2018-01-30  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (dwarf_unit_string): New function.
+	(dwarf_unit_name): Likewise.
+	(print_debug_units): Use dwarf_get_units and dwarf_cu_die instead
+	of dwarf_next_unit. Print unit type, id and subdie if available.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* addr2line.c (handle_address): Use FALLTHROUGH macro instead of
+	comment.
+	* elfcompress.c (parse_opt): Likewise.
+	* elflint.c (check_dynamic): Likewise.
+	(check_sections): Likewise.
+	(check_note_data): Likewise.
+	* objdump.c (parse_opt): Likewise.
+	* readelf.c (parse_opt): Likewise.
+	(attr_callback): Likewise.
+	(handle_auxv_note): Likewise.
+	* strings.c (parse_opt): Likewise.
+	* backtrace.c (callback_verify): Likewise.
+
+2018-01-25  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_ranges_section): Initialize cu to last_cu.
+	(print_debug_loc_section): Likewise.
+
+2018-01-01  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Use dwarf_form_name for unknown forms.
+	(print_debug_macro_section): Print form using dwarf_form_name.
+
+2017-12-28  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Print DIE offset in error message
+	as hex.
+
+2017-12-18  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (handle_notes_data): Don't use EXIT_FAILURE in error.
+	Adjust error message depending on whether or not we got data.
+
+2017-12-07  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ops): Update data pointer and print arguments
+	to DW_OP_call2 and DW_OP_call4 as DIE offsets.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (argp_options): Add "section-groups", 'g'.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_loc_section): Print CU base and unresolved
+	addresses. Adjust formatting.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_ranges_section): Print CU base and unresolved
+	addresses. Adjust formatting.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Set valuestr to resolved file name
+	for DW_AT_decl_file and DW_AT_call_file.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_units): Print abbrev code after DIE tag.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ops): Use only2 space for index. re-indent +5
+	for DW_OP_GNU_entry_value.
+
+2017-11-21  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Print attribute name and form in error
+	message. If only the value cannot be retrieved/resolved don't abort.
+
+2017-10-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (attr_callback): Print DIE offset in error messages.
+
+2017-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_ops): Handle DW_OP_GNU_variable_value. Print
+	referenced DIE as offset.
+
+2017-09-10  Mark Wielaard  <mark@klomp.org>
+
+	* ar.c (do_oper_delete): Remove DEBUG conditional check.
+	(no0print): Return bool. Check snprintf return value.
+	(do_oper_insert): Initialize elf. Remove DEBUG conditional check.
+	Check no0print calls succeed. Explicitly elf_end found elfs.
+	(do_oper_extract): Make sure we don't create an empty variable
+	length array.
+
+2017-09-01  Mark Wielaard  <mark@klomp.org>
+
+	* stack.c (main): Replace \v in doc string with \n\n.
+	* unstrip.c (main): Likewise.
+
+2017-05-04  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* stack.c: Print pid_t using %lld.
+
+2017-08-18  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* readelf.c: Hardcode the signal numbers for non-linux systems.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (print_debug_macro_section): Accept either version 4 or
+	version 5. Use DW_MACRO names instead of DW_MACRO_GNU names. Add
+	minimal support for DW_MACRO_define_sup, DW_MACRO_undef_sup,
+	DW_MACRO_import_sup, DW_MACRO_define_strx and DW_MACRO_undef_strx.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* readelf.c (dwarf_defaulted_string): New function.
+	(dwarf_defaulted_name): Likewise.
+	(attr_callback): Use dwarf_defaulted_name to get value of
+	DW_AT_defaulted.
+
+2017-07-20  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Deal with data marker symbols pointing to
+	debug sections (they can be removed).
+
+2017-07-14  Mark Wielaard  <mark@klomp.org>
+
+	* strip (OPT_KEEP_SECTION): New define.
+	(options): Add documentation for remove-section. Add keep-section.
+	(struct section_pattern): New data type.
+	(keep_secs, remove_secs): New globals.
+	(add_pattern, free_sec_patterns, free_patterns, section_name_matches):
+	New functions.
+	(main): Call free_patterns.
+	(parse_opt): Handle 'R' and OPT_KEEP_SECTION. Check remove_comment
+	on ARGP_KEY_SUCCESS.
+	(handle_elf): Handle and sanity check keep_secs and remove_secs.
+
+2017-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Introduce new handle_elf boolean. Use it to
+	determine whether to create an output and/or debug file. Remove new
+	output file on error.
+
+2017-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* strip.c (handle_elf): Assume e_shstrndx section can be removed.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* readelf.c: Include strings.h.
+
+2017-04-20  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* unstrip.c: Check shnum for 0 before subtracting from it.
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* readelf.c: Replace YESSTR and NOSTR with gettext ("yes") and
+	gettext ("no"), respectively.
+
+2017-04-05  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_elf_header): Decompress all sections.
+
+2017-03-28  Mark Wielaard  <mark@klomp.org>
+
+	* elflint (check_group): Don't check if there is no flag word.
+
+2017-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_elf_header): Sanity check phnum and shnum.
+
+2017-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_sysv_hash): Return early if section size is
+	too small.
+	(check_sysv_hash64): Likewise.
+	(check_hash): Calculate expect_entsize to check section size.
+
+2017-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* elflint.c (check_symtab_shndx): Check data->d_size.
+
+2017-03-24  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcmp.c (main): If n_namesz == 0 then the note name data is the
+	empty string.
+	* readelf.c (handle_notes_data): Likewise.
+
+2017-03-24  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_gnu_hash): Check inner < max_nsyms before
+	indexing into chain array.
+
+2017-02-16  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* addr2line.c: Include printversion.h
+	* ar.c: Likewise.
+	* elflint.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* stack.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* elfcmp.c: Include printversion.h, remove system.h include.
+	* elfcompress.c: Likewise.
+	* findtextrel.c: Likewise.
+	* unstrip.c: Likewise.
+
+2017-02-14  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* nm.c: Include color.h.
+	* objdump.c: Likewise.
+
+2016-12-24  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (findtextrel_LDADD): Add $(libeu).
+	(addr2line_LDADD): Likewise.
+	(elfcmp_LDADD): Likewise.
+	* addr2line.c (print_version): Removed.
+	* ar.c (print_version): Likewise.
+	* elfcmp.c (print_version): Likewise.
+	* elfcompress.c (print_version): Likewise.
+	* elflint.c (print_version): Likewise.
+	* findtextrel.c (print_version): Likewise.
+	* nm.c (print_version): Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* stack.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2016-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (options): Add optional arg SECTION for symbols.
+	(symbol_table_section): New static variable.
+	(parse_opt): Set symbol_table_section on 's'.
+	(print_symtab): Filter on symbol_table_section name is set.
+
+2016-11-10  Mark Wielaard  <mjw@redhat.com>
+
+	* ar.c (write_member): Make sure tmpbuf is large enough to contain
+	a starting '/' and ending '\0' char.
+	(do_oper_insert): Likewise.
+	* arlib.c (arlib_finalize): Format tmpbuf as PRId32 decimal.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (handle_address): Add fallthrough comment.
+	* elfcompress.c (parse_opt): Adjust fallthrough comment.
+	* elflint.c (parse_opt): Add missing break after 'd' case.
+	(check_sections): Add fallthrough comments.
+	* objdump.c (parse_opt): Add explantion for fallthrough comment.
+
+2016-10-22  Kevin Cernekee  <cernekee@chromium.org>
+
+	* unstrip.c: Fix "invalid string offset" error caused by using the
+	  unstripped .symtab with the stripped .strtab.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* arlib.c: Remove system.h include, add libeu.h include.
+	* arlib2.c: Remove sys/param.h include.
+	* elfcompress.c: Add libeu.h include.
+	* elflint.c: Remove sys/param.h include, add libeu.h include.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Remove sys/param.h include.
+	* strings.c: Likewise, add libeu.h include.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2016-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Don't remove real symbols from allocated
+	symbol tables.
+
+2016-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Recompress with ELF_CHF_FORCE.
+
+2016-08-06  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Uncompress and recompress relocation target
+	section if necessary.
+
+2016-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (strip_LDADD): Add libdw.
+	* elfcompress.c (process_file): Use dwelf_strtab functions instead of
+	ebl_strtab.
+	* strip.c (handle_elf): Likewise.
+	* unstrip.c (new_shstrtab): Likewise.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elf32-i386.script, i386_ld.c, ld.c, ld.h, ldgeneric.c, ldlex.l,
+	ldscript.y, libld_elf_i386.map, none_ld.c, sectionhash.c,
+	sectionhash.h, symbolhash.c, symbolhash.h, unaligned.h,
+	versionhash.c, versionhash.h, xelf.h: Removed.
+	* Makefile.am (YACC): Removed.
+	(AM_YFLAGS): Removed.
+	(AM_LFLAGS): Removed.
+	(native_ld): Removed.
+	(base_cpu): Removed.
+	(bin_PROGRAMS): Removed ld.
+	(ld_dsos): Removed.
+	(ld_SOURCES): Removed.
+	(noinst_LIBRARIES): Only libar.a.
+	(EXTRA_DIST): Just arlib.h and debugpred.h.
+	(ld_LDADD): Removed.
+	(ld_LDFLAGS): Removed.
+	(ldlex.o): Removed.
+	(ldscript.h): Removed.
+	(libld*): Removed.
+	(CLEANFILES): Just *.gconv.
+	(MAINTAINERCLEANFILES): Removed.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Use unstripped_strent[] from
+	index zero, instead of one.
+
+2016-06-28  Richard Henderson <rth@redhat.com>
+
+	* elflint.c (valid_e_machine): Add EM_BPF.
+
+2016-04-11  David Abdurachmanov  <davidlt@cern.ch>
+
+	* elfcmp.c (main): Fix self-comparison error with GCC 6.
+
+2016-03-21  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (show_symbols): Check for malloc size argument overflow.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_scngrp): Call error when gelf_getshdr fails.
+	(print_symtab): Likewise.
+	(handle_hash): Likewise.
+	(dump_data_section): Print a warning if decompressing fails.
+	(print_string_section): Likewise.
+
+2016-02-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcompress.c (parse_opt): Don't fallthrough after processing -q.
+
+2016-02-12  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Correct elf_assert shndxdata check.
+
+2016-02-09  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (read_encoded): Move up.
+	(print_cfa_program): Add encoding argument. Use it for read_encoded
+	when reading DW_CFA_set_loc op.
+	(print_debug_frame_section): Pass fde_encoding to print_cfa_program.
+
+2016-02-09  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (compare_hash_gnu_hash): Check hash sh_entsize against
+	sizeof (Elf64_Xword). Correct invalid sh_entsize error message
+	section idx and name.
+
+2016-01-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_elf_header): Recognize ELFOSABI_FREEBSD.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcompress.c (compress_section): Use %zu to print size_t.
+	* readelf.c (print_shdr): Use %zx to print size_t.
+
+2015-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcompress.c: New file.
+	* Makefile.am (bin_PROGRAMS): Add elfcompress.
+	(elfcompress_LDADD): New variable.
+
+2015-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (section_flags_string): Add NEWFLAG COMPRESSED.
+	(check_sections): SHF_COMPRESSED can be on any special section.
+	SHF_COMPRESSED is a valid section flag. SHF_COMPRESSED cannot
+	be used together with SHF_ALLOC or with SHT_NOBITS. Should have
+	a valid Chdr.
+
+2015-10-20  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (options): Expand -z help text.
+	(dump_data_section): Check whether we need and can decompress section
+	data and call elf_rawzdata if so,
+	(print_string_section): Likewise.
+	(elf_contains_chdrs): New function.
+	(process_elf_file): Rename print_unrelocated to print_unchanged,
+	use elf_contains_chdrs.
+	(print_scngrp): Check whether section is compressed before use.
+	(print_symtab): Likewise.
+	(handle_hash): Likewise.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (argp_option): Describe --decompress,-z.
+	(print_decompress): New bool.
+	(parse_opt): Handle -z.
+	(elf_ch_type_name): New function.
+	(print_shdr): Print section compress information.
+
+2015-12-31  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_symtab): Add _edata and _end (plus extra underscore
+	variants) to to the list of possibly dangling symbols.
+
+2015-12-02  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (process_file): Accept fd and pass it on.
+	(handle_elf): Likewise.
+	(find_no_debuginfo): New.
+	(struct getdbg): Likewise.
+	(getdbg_dwflmod): Likewise.
+	(show_symbols): Take fd. If the file is ET_REL use libdwfl to get
+	the relocated Dwarf.
+
+2015-12-02  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (get_local_names): Check for duplicates in local_root tree.
+
+2015-12-02  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (struct data_list): New.
+	(new_data_list): Likewise.
+	(record_new_data): Likewise.
+	(free_new_data): Likewise.
+	(adjust_relocs): Call record_new_data.
+	(add_new_section_symbols): Likewise.
+	(copy_elided_sections): Call free_new_data.
+
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcmp.c (main): Close ebl1 and ebl2 backends.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am [BUILD_STATIC](libdw): Add -lz.
+	[BUILD_STATIC](libelf): Likewise.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_symtab): Don't check TLS symbol value against TLS
+	phdr offset in debuginfo files.
+	(check_sections): Don't try to match section offsets to phdrs offsets
+	in debuginfo files.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_reloc_shdr): Reject only desthdrs if they have both
+	SHF_MERGE and SHF_STRINGS set.
+
+2015-10-13  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* elflint.c (check_sections): Do not rely on
+	ebl_check_special_section when checking debuginfo files.  Also
+	check that the type of WE sections in debuginfo files is NOBITS.
+
+2015-10-13  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_program_header): Check relro flags are a subset
+	of the load segment if they don't fully overlap.
+
+2015-10-07  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (ldlex_no_Wstack_usage): New.
+	* ldlex.l ([RWX]): Make cnt unsigned.
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* elflint.c (main): Replace stat64 and fstat64 with stat and fstat.
+	* readelf.c (process_file): Likewise.
+	(process_elf_file): Replace off64_t with off_t.
+	* findtextrel.c (process_file): Replace open64 with open.
+	* ld.c (main): Replace sizeof (off64_t) with 8.
+	* strings.c: Replace off64_t with off_t throughout.
+	(main): Replace stat64 and fstat64 with stat and fstat.
+	(map_file): Replace mmap64 with mmap.
+	(read_block): Likewise, and replace lseek64 with lseek.
+	* strip.c (handle_elf): Replace ftruncate64 with ftruncate.
+	(process_file): Replace stat64 and fstat64 with stat and fstat.
+	* unstrip.c (parse_opt): Replace stat64 with stat.
+	(handle_file): Replace open64 with open.
+	(open_file): Likewise.
+
+2015-10-08  Chih-Hung Hsieh  <chh@google.com>
+
+	* ld.c (determine_output_format): Move recursive nested
+	function "try" to file scope.
+
+2015-10-04  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Only sanity check section symbols to not
+	kept discarded sections if we are creating a debug file.
+
+2015-10-07  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (MAX): Removed.
+	(find_alloc_sections_prelink): Allocate exact amount of bytes for
+	shdrs.
+
+2015-10-05  Chih-Hung Hsieh <chh@google.com>
+
+	* unstrip.c (find_alloc_sections_prelink): Do not allocate
+	on stack union types with variable length arrays; use xmalloc
+	for such dynamic sized objects.
+	* readelf.c (handle_core_item): Likewise, but use alloca
+	for small variable size data object and add assert(count < 128).
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (libld_elf_i386.so): Add AM_V_CCLD silencer.
+	(.deps/none_ld.Po): Always silence the dummy command.
+	(make-debug-archive): Add AM_V_GEN and AM_V_at silencers.
+
+2015-10-02  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Use SH_INFO_LINK_P, not just
+	SHF_INFO_LINK.
+
+2015-10-02  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Don't move around allocated NOBITS sections.
+	Don't just mark the section header string table as unused.
+	* unstrip.c (copy_elided_sections): Add header names to strtab if
+	shstrndx equals the symtab strtabndx.
+
+2015-09-22  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (cleanup_debug): Remove old-style function definitions.
+
+2015-09-09  Chih-Hung Hsieh  <chh@google.com>
+
+	* readelf.c (print_debug_exception_table): Initialize variable before
+	it is used, because compiler does not know that error never returns.
+	(dump_arhive_index): Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* elflint.c (check_group): Replace %Z length modifier with %z.
+	(check_note_data): Likewise.
+	* findtextrel.c (process_file): Likewise.
+	* readelf.c (handle_dynamic): Likewise.
+	(handle_symtab): Likewise.
+	(handle_verneed): Likewise.
+	(handle_verdef): Likewise.
+	(handle_versym): Likewise.
+	(print_hash_info): Likewise.
+	(print_decoded_aranges_section): Likewise.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(hex_dump): Likewise.
+	(dump_data_section): Likewise.
+	(print_string_section): Likewise.
+	(dump_archive_index): Likewise.
+	* unstrip.c (adjust_relocs): Likewise.
+	(collect_symbols): likewise.
+	(get_section_name): Likewise.
+	(find_alloc_sections_prelink): Likewise.
+	(copy_elided_sections): Likewise.
+	* ldscript.y (add_id_list): Add missing '%s'.
+
+2015-09-03  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_core_item): Handle right shift >= 32 bits.
+
+2015-08-11  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_sections): When gnuld and a NOBITS section falls
+	inside a segment make sure any ELF file contents is zero.
+
+2015-07-29  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (sections_flags_match): New function.
+	(sections_match): Use sections_flags_match.
+	(find_alloc_sections_prelink): Only clear matched sections if there
+	is an undo section.
+	(copy_elided_sections): Add SHF_INFO_LINK to shdr_mem.sh_flags if
+	necessary.
+
+2015-06-27  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* src/strings.c: Define MAP_POPULATE if not defined already.
+
+2015-06-27  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (show_symbols): First call elf_getdata, then allocate memory.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* findtextrel.c (process_file): Free segments after use.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_phdr): Make sure phdr2_mem lifetime/scope equals
+	phdr2 pointer.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_gnu_hash): Free lengths on invalid_data.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_symtab): Only check the PT_TLS phdr if it actually
+	exists. Warn otherwise.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (show_symbols): Check sizeof (sym_mem[0]), not GElf_Sym to
+	known whether or not we stack allocated memory.
+
+2015-06-18  Mark Wielaard  <mjw@redhat.com>
+
+	* strings.c (readelf): Use "<unknown>" if we cannot retrieve section
+	name.
+
+2015-06-09  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (print_dwarf_function): Always free scopes before
+	returning.
+
+2015-06-09  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_ar): Mark as unused.
+	(process_file): Produce an error when trying to handle an ar.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcmp.c (main): Only call memcmp when d_size != 0.
+
+2015-05-23  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Define ldgeneric, readelf, nm, size, strip, elflint,
+	findtextrel, elfcmp objdump, ranlib, ar and unstrip no_Wstack_usage.
+
+2015-05-21  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (handle_address): Set scopes to NULL after free.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (OPT_PRETTY): New constant define.
+	(argp_option): Add "pretty-print".
+	(pretty): New static bool.
+	(parse_opt): Set pretty.
+	(print_dwarf_function): Adjust output when pretty is set.
+	(print_addrsym): Likewise.
+	(handle_address): Likewise.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (addr2line_LDADD): Add demanglelib.
+	* addr2line.c (argp_option): Move demangle under output format.
+	(demangle): New static bool.
+	(demangle_buffer_len): New static size_t.
+	(demangle_buffer): New static char *.
+	(main): free demangle_buffer.
+	(parse_opt): Set demangle.
+	(symname): New static function.
+	(get_diename): Use symname.
+	(print_dwarf_function): Likewise.
+	(print_addrsym): Likewise.
+	(handle_address): Likewise.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (argp_option): Add "addresses", 'a'.
+	(print_addresses): New static bool.
+	(parse_opt): Set print_addresses.
+	(get_addr_width): New static function.
+	(handle_address): Print address if print_addresses is true.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (handle_address): Call strtoumax with base 16. Make
+	sure all input has been processed.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line (argp_option): Group 'section' under "Input format
+	options".
+
+2015-05-12  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (debug_fd): New static variable.
+	(tmp_debug_fname): Likewise.
+	(cleanup_debug): New function using the above to clean up temporary
+	debug file.
+	(INTERNAL_ERROR): Call cleanup_debug.
+	(handle_elf): Use debug_fd and tmp_debug_fname statics and call
+	cleanup_debug before any error. Use output_fname instead of fname in
+	error messages when it exists (-o was given). SHT_NOBITS sections
+	can also be moved freely even if SHF_ALLOC is set. Add various
+	sanity checks. Use elf_assert instead of plain assert.
+
+2015-05-08  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (show_symbols): Call gelf_fsize with EV_CURRENT.
+	* strip.c (handle_elf): Likewise.
+
+2015-05-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_gnu_hash): Return early when 2nd hash function
+	shift too big. Check there is enough data available. Make sure
+	bitmask_words is not zero.
+	(check_verdef): Use Elf64_Word for shdr->sh_info cnt.
+	(check_verneed): Likewise.
+	(check_attributes): Break when vendor name isn't terminated.
+	Add overflow check for subsection_len.
+
+2015-05-05  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (show_symbols): Handle dwarf_linesrc returning NULL.
+
+2015-05-04  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* ar.c (do_oper_extract): Replace struct timeval with struct timespec
+	and futimes with futimens.
+	* strip.c (process_file): Replace struct timeval with struct timespec.
+	(handle_elf, handle_ar): Replace struct timeval with struct timespec
+	in prototype. Replace futimes with futimens.
+
+2015-05-04  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* addr2line.c (main): Drop mtrace() call and #include <mcheck.h>.
+	* ar.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* size.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2015-05-04  Anthony G. Basile  <blueness@gentoo.org>
+
+	* Makefile.am (readelf_LDADD, nm_LDADD, size_LDADD, strip_LDADD)
+	(ld_LDADD, elflint_LDADD, findtextrel_LDADD, addr2line_LDADD)
+	(elfcmp_LDADD, objdump_LDADD, ranlib_LDADD, strings_LDADD)
+	(ar_LDADD, unstrip_LDADD, stack_LDADD): Append $(argp_LDADD).
+
+2015-03-22  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Cast start to Dwarf_Off
+	before subtracting cie_id. And cast cie_offset to Dwarf_Off before
+	comparison.
+
+2015-03-22  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Check all offsets used
+	against section d_size.
+
+2015-03-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug): Don't return, but always use dummy_dbg.
+
+2015-03-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Add overflow checking for
+	dataend checks.
+
+2015-03-14  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (INTERNAL_ERROR): Remove __DATE__.
+	* objdump.c (INTERNAL_ERROR): Likewise.
+	* size.c (INTERNAL_ERROR): Likewise.
+	* strip.c (INTERNAL_ERROR): Likewise.
+
+2015-03-18  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (dwarf_tag_string, dwarf_attr_string)
+	(dwarf_form_string, dwarf_lang_string, dwarf_inline_string)
+	(dwarf_encoding_string, dwarf_access_string)
+	(dwarf_visibility_string, dwarf_virtuality_string)
+	(dwarf_identifier_case_string, dwarf_calling_convention_string)
+	(dwarf_ordering_string, dwarf_discr_list_string)
+	(dwarf_locexpr_opcode_string): Adjust uses of know-dwarf.h macros
+	to match the API changes.
+
+2015-03-09  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (compare_hash_gnu_hash): Correct gnu_symbias usage.
+
+2015-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcmp (main): Check section name is not NULL. Check sh_entsize
+	is not zero for symbol tables. Check phdrs are not NULL.
+	(search_for_copy_reloc): Check sh_entsize is not zero.
+
+2014-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_scn_group): Check d_buf and name are not NULL.
+	(is_rel_dyn): Check d is not NULL. Check shdr->sh_entsize is not
+	zero.
+	(check_dynamic): Check strshdr is not NULL. Check d_tag is positive.
+	(check_symtab_shndx): Check symshdr and data->d_buf are not NULL.
+	Check shdr and symshdr sh_entsize are not zero.
+	(check_gnu_hash): Make sure maskidx is smaller than bitmask_words.
+	Check symshdr->sh_entsize is not zero. Check data->d_buf is not
+	NULL.
+	(compare_hash_gnu_hash): Check sections d_buf are not NULL.
+	Check section data is large enough. Use gnu_symbias.
+	(check_group): Check section val is valid.
+	(has_copy_reloc): Check sh_entsize is not zero.
+	(check_versym): Likewise.
+	(unknown_dependency_p): Likewise.
+	(check_verneed): Break on invalid ref or offset. Don't assert.
+	Report error when next offset is zero, but more vers expected.
+	(check_verdef): Likewise.
+	(check_attributes): Make sure d_buf is not NULL.
+	(check_note): Likewise.
+	(check_note_section): Likewise.
+	(check_program_header): Make sure section name is not NULL.
+
+2014-12-26  Mark Wielaard  <mjw@redhat.com>
+
+	* strings.c (read_elf): Produce error when section data falls outside
+	file.
+
+2014-12-26  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (show_symbols): Guard against divide by zero in error check.
+	Add section index number in error message.
+
+2014-12-26  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (handle_ar): Skip over /SYM64/ entries.
+
+2014-12-26  Mark Wielaard  <mjw@redhat.com>
+
+	* nm.c (handle_ar): Break on arsym with invalid offset.
+
+2014-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_macinfo_section): Mark cus sentinel files
+	as -1 non-existent. Check macoff against sentinel cus.
+
+2014-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_exception_table): Add max_action overflow
+	check. Check action_table_end before reading slib128. Check
+	max_ar_filter underflow.
+
+2014-12-18  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am: Suppress output of textrel_check command.
+
+2014-12-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_cfa_program): Add bounds check before each op that
+	takes at least one argument.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_decoded_line_section): Print dwarf_errmsg if
+	dwarf_onesrcline or dwarf_linesrc fails.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_line_section): Correct overflow check for
+	unit_length.
+	(print_debug_aranges_section): Correct overflow check for length.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (notice_listptr): Return false if offset doesn't fit
+	in 61-bits.
+	(attr_callback): Warn if loclist or rangelist offset doesn't fit.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Don't assert when addr_size or ref_size
+	is not 4 or 8, just report invalid data.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Add more bounds checks.
+
+2014-12-15  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_line_section): Check there is enough room
+	for DW_LNE_set_address argument. Make sure there is enough room
+	for the the initial unit_length.
+
+2014-12-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_attributes): Call get_uleb128 with end pointer.
+	* readelf.c (print_attributes): Likewise.
+	(print_ops): Likewise and also for get_sleb128.
+	(print_cfa_program): Likewise and add more readp bounds checks.
+	(read_encoded): Likewise.
+	(print_debug_frame_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_macro_section): Likewise.
+	(print_debug_exception_table): Likewise.
+
+2014-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcmp.c (compare_Elf32_Word): Make sure (unsigned) Elf32_Word
+	difference doesn't wrap around before returning as int.
+
+2014-12-11  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_exception_table): Check TType base offset
+	and Action table are sane.
+
+2014-12-11  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Check number of augmentation
+	chars to print.
+
+2014-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_file_note): Check count fits data section and
+	doesn't overflow fptr.
+
+2014-12-08  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_exception_table): Report invalid data if
+	action table doesn't immediately follow call site table.
+
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+	* addr2line.c (get_diename): New, get linkage_name or name.
+	* addr2line.c (print_dwarf_function): Use get_diename.
+	* addr2line.c (handle_address): Likewise.
+	* addr2line.c (print_diesym): Removed.
+
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+	* addr2line.c (handle_address): Find the proper inline parents.
+
+2014-12-07  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_line_section): max_ops_per_instr cannot
+	be zero.
+
+2014-12-07  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Handle zero ref_size for DW_OP_call_ref
+	and DW_OP_GNU_implicit_pointer.
+
+2014-12-04  Mark Wielaard  <mjw@redhat.com>
+
+	* objdump.c (show_relocs_x): Make sure destshdr exists.
+	(show_relocs_rel): Don't rely on shdr->sh_entsize, use gelf_fsize.
+	(show_relocs_rela): Likewise.
+	(show_relocs): Make sure destshdr, symshdr and symdata exists.
+
+2014-11-30  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_sysv_hash64): Fix overflow check.
+
+2014-11-28  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_relocs_rel): Don't reuse destshdr to store
+	section header of a relocation against a STT_SECTION symbol. Use
+	a new local variable secshdr.
+	(handle_relocs_rela): Likewise.
+
+2014-11-26  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_aranges_section): Cast Dwarf_Word length
+	to ptrdiff_t for comparison.
+
+2014-11-24  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_line_section): Check line_range is not zero
+	before usage.
+
+2014-11-23  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_aranges_section): Check length to catch
+	nexthdr overflow.
+
+2014-11-21  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_attributes): Guard against empty section.
+	Document attribute format. Break when vendor name isn't terminated.
+	Add overflow check for subsection_len. Handle both gnu and non-gnu
+	attribute tags.
+
+2014-11-22  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_sections): Call ebl_bss_plt_p without ehdr.
+	* findtextrel.c (process_file): Use elf_getphdrnum.
+	* readelf.c (process_elf_file): Remove redundant ehdr->e_phoff check.
+	(print_phdr): Check phnum.
+	* size.c (show_segments): Use elf_getphdrnum.
+	* strip.c (handle_elf): Likewise.
+	* unstrip.c (copy_elf): Likewise.
+	(copy_elided_sections): Likewise.
+	(handle_file): Likewise.
+
+2014-11-18  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_cfa_program): Fix sanity check of DW_FORM_block
+	length.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_verneed): Check vna_next and vn_next exist.
+	(handle_verdef): Check vda_next and vd_next exist.
+	(handle_versym): Check vd_next, vna_next and vn_next exist.
+	Check vername and filename are not NULL before use.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* elfcmp.c (main): Check section names are NULL before use.
+	* objdump.c (section_match): Likewise.
+	* size.c (show_sysv): Likewise.
+
+2014-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Warn if ptr_size is not 4
+	or 8 instead of just calling print_cfa_program.
+
+2014-11-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf (process_elf_file): Set phnum to zero if there aren't
+	actually any pheaders.
+	(print_phdr): Check there actually is a phdr.
+
+2014-11-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_cfa_program): Check block len before calling
+	print_ops.
+
+2014-11-14  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Sanity Check CIE
+	unit_length and augmentationlen.
+
+2014-11-14  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_versym): Check def == NULL before use.
+
+2014-11-08  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_versym): Initialize vername and filename array
+	elements.
+
+2014-11-07  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_sysv_hash): Sanity check section contents.
+	(handle_sysv_hash64): Likewise.
+	(handle_gnu_hash): Likewise.
+
+2014-09-14  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (handle_relocs_rela): Typo fix, test DESTSHDR properly.
+
+2014-09-12  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (encoded_ptr_size): In the switch statement, change
+	magic constants 3 and 4 to DW_EH_PE_* counterparts.  Still accept
+	0.  Print diagnostic for anything else.
+
+2014-08-25  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am: Prevent premature @AR@ replacement in a sed expression.
+
+2014-07-04  Menanteau Guy  <menantea@linux.vnet.ibm.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* elflint (check_symtab): Add ".TOC." to the list of possibly
+	dangling symbols because of sourceware PR13621.
+
+2014-06-14  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint (check_symtab): Use ebl_func_addr_mask on st_value.
+
+2014-05-27  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug): Skip section if name is NULL.
+
+2014-05-26  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_relocs_rela): Print header like handle_relocs_rel
+	does, when sh_info == 0.
+
+2014-05-26  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (find_alloc_sections_prelink): Allow non-split .bss
+	section when sh_size of the original and undo .bss section are equal.
+
+2014-05-26  Mark Wielaard  <mjw@redhat.com>
+
+	* unstrip.c (options): Add --force, -F.
+	(struct arg_info): Add bool force.
+	(parse_opt): Handle 'F', set force.
+	(handle_explicit_files): Add force argument, add warn function,
+	separate check ehdr field checks, use warn.
+	(handle_dwfl_module): Add force argument, pass on to
+	handle_explicit_files.
+	(handle_output_dir_module): Add force argument, pass on to
+	handle_dwfl_module.
+	(handle_implicit_modules): Pass info->force to handle_dwfl_module and
+	handle_output_dir_module.
+	(main): Pass info.force to handle_explicit_files.
+
+2014-05-19  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_reloc_shdr): Check ebl_check_reloc_target_type.
+
+2014-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (find_no_debuginfo): Call dwfl_standard_find_debuginfo
+	if looking for alternate debug file.
+
+2014-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (AM_CPPFLAGS): Add -I libdwelf.
+
+2014-04-22  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_core_item): Make sure variable length array
+	contains at least enough space for terminating zero char.
+
+2014-04-22  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Use unsigned int for 31 bits
+	left shift.
+
+2014-03-13  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove no_mudflap.os. Remove libmudflap from all
+	LDADD lines.
+	* strings.c (process_chunk): Remove _MUDFLAP condition.
+
+2014-04-09  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_aranges_section): Don't get the raw section
+	data, use the possibly decompressed .[z]debug sectiondata.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_frame_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_macro_section): Likewise.
+
+2014-04-10  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (buf_read_ulong): Pass actual long size to convert.
+
+2014-03-05  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (attr_callback): Print DW_FORM_sdata values as signed
+	numbers.
+
+2014-02-24  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf (print_phdr): Check there is a SHT_PROGBITS section at the
+	offset given by p_offsets for a PT_INTERP segment before trying to
+	display the interpreter string.
+
+2014-02-07  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_phdr): Check phdr->p_filesz and make sure
+	interpreter string is zero terminated before calling printf.
+
+2014-01-22  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (nm_no_Wformat): Removed.
+	(size_no_Wformat): Likewise.
+	(strings_no_Wformat): Likewise.
+	(addr2line_no_Wformat): Likewise.
+	* size.c (show_sysv): Use fmtstr directly as literal in printf.
+	(show_sysv_one_line): Likewise.
+	* strings.c (locfmt): Removed.
+	(radix): New static enum.
+	(parse_opt): Set radix, not locfmt.
+	(process_chunk_mb): Use fmtstr directly as literal in printf based
+	on radix.
+	(process_chunk): Likewise.
+	* nm.c (show_symbols_sysv): Use fmtstr directly as literal in printf.
+	(show_symbols_bsd): Likewise.
+	(show_symbols_posix): Likewise.
+
+2014-01-21  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (show_inlines): New static boolean.
+	(print_frame): New function split out from...
+	(print_frames): ..here. If show_inlines is true and we found a
+	DIE for the frame address, call print_inline_frames otherwise
+	call print_frame. Keep track of and track frame_nr.
+	(print_inline_frames): New function.
+	(parse_opt): Handle '-i'.
+	(main): Add 'i' to options.
+
+2014-01-27  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (maxframes): Initialize to 256.
+	(main): Document new default in options. Document magic number
+	used in frames.allocated initialization.
+
+2014-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (show_debugname): New static boolean.
+	(die_name): New function.
+	(print_frames): If show_debugname is true set symname to the
+	first function-like DIE with a name in scope for the address in
+	the debuginfo.
+	(parse_opt): Handle '-d'.
+	(main): Add 'd' to options.
+
+2014-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (handle_address): Initialize scopes to NULL.
+
+2014-01-17  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Check for bogus values in sh_link, sh_info,
+	st_shndx, e_shstrndx, and SHT_GROUP or SHT_SYMTAB_SHNDX data.
+	Don't use assert on input values, instead bail with "illformed" error.
+
+2014-01-17  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_dynamic, handle_symtab): Check for bogus sh_link.
+	(handle_verneed, handle_verdef, handle_versym, handle_hash): Likewise.
+	(handle_scngrp): Check for bogus sh_info.
+
+2014-01-17  Jakub Jelinek  <jakub@redhat.com>
+
+	* elflint.c (section_name): Return "<invalid>" instead of
+	crashing on invalid section name.
+	(check_symtab, is_rel_dyn, check_rela, check_rel, check_dynamic,
+	check_symtab_shndx, check_hash, check_versym): Robustify.
+	(check_hash): Don't check entries beyond end of section.
+	(check_note): Don't crash if gelf_rawchunk fails.
+
+2014-01-17  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (handle_dynamic, handle_relocs_rel)
+	(handle_relocs_rela, handle_versym, print_liblist):
+	Use gelf_fsize instead of relying on shdr->sh_entsize.
+
+2014-01-14  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_macro_section): Clear vendor array before
+	use.
+
+2014-01-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix corruption of non-C++ symbols by the demangler.
+	* nm.c (show_symbols_sysv, show_symbols_bsd, show_symbols_posix)
+	(show_symbols): Check for _Z.
+	* stack.c (print_frames) <USE_DEMANGLE>: Check for _Z.
+
+2014-01-02  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (show_raw): Declare unconditionally.
+	(parse_opt): Handle '-r' unconditionally.
+	(main): Show "raw" option even without USE_DEMANGLE.
+
+2014-01-02  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (print_frames): Print 0x before build-id hex-offset.
+
+2014-01-02  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (maxframes): Increase to 2048.
+	(struct frames): Add allocated field.
+	(frame_callback): If frames used is frames allocated, realloc.
+	(print_frames): Show an error if maxframes has been reached.
+	(parse_opt): Allow -n 0 for unlimited frames.
+	(main): Document -n 0 and new default 2048 frames. Allocate initial
+	number of frames with malloc.
+
+2013-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (parse_opt): Explicitly call dwfl_linux_proc_attach
+	or dwfl_core_file_attach and check for errors.
+
+2013-12-28  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (print_frames): Remove address width code and use...
+	(get_addr_width): ...this new function.
+	(show_modules): New static boolean.
+	(module_callback): New static function.
+	(parse_opt): Handle '-l'.
+	(main): Add 'l' to options. If show_modules then use dwfl_getmodules
+	with module_callback to show all detected modules and possible
+	build_id, elf and dwarf files.
+
+2013-12-27  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (frames_shown): New static boolean.
+	(EXIT_OK,EXIT_ERROR,EXIT_BAD,EXIT_USAGES): New defines.
+	(frame_callback): Return -1 on error. Don't print error.
+	(print_frames): Add arguments, tid, dwflerr and what. Print tid.
+	If there was an error report it with address and module if possible.
+	Record whether any frames were actually printed.
+	(thread_callback): Collect tid and err, pass it to print_frames.
+	(parse_opt): Use EXIT_BAD for errors. On ARGP_KEY_END print errno
+	if dwfl_linux_proc_report returned it. Check whether we are properly
+	attached with dwfl_pid.
+	(main): Document exit status. Don't report DWARF_CB_ABORT from
+	callbacks as error. Pass real errors to print_frames. Return
+	EXIT_BAD if no frames could be shown. Return EXIT_ERROR if there
+	were any non-fatal errors.
+
+2013-12-23  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (stack_LDADD): Add demanglelib.
+	* stack.c (show_quiet): New static boolean, default false.
+	(show_raw): Likewise.
+	(demangle_buffer_len): New static size_t.
+	(demangle_buffer): New static char *.
+	(print_frames): Don't resolve pc name if show_quiet. Demangle name
+	unless show_raw.
+	(parse_opt): Handle '-q' and '-r'.
+	(main): Add 'q' and 'r' to options. Free demangle_buffer.
+
+2013-12-23  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (OPT_DEBUGINFO): New define.
+	(OPT_COREFILE): Likewise.
+	(pid): New static.
+	(core_fd): Likewise.
+	(core): Likewise.
+	(exec): Likewise.
+	(debuginfo_path): Likewise.
+	(parse_opt): Handle '-p', '--core', '-e' and '--debuginfo-path'.
+	Do argument sanity checking. Setup Dwfl.
+	(main): Add 'p', 'core', 'e' and 'debuginfo-path' to options.
+	Remove argp_child children, simplify argp doc, remove custom
+	usage message and construction of dwfl with dwfl_standard_argp.
+	Use pid directly as tid. close core and core_fd if opened. Print
+	pid of process or core.
+
+2013-12-23  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (show_build_id): New static boolean.
+	(print_frames): Print module build-id, load address and pc offset
+	if show_build_id is true.
+	(parse_opt): Handle '-b'.
+	(main): Add -b to options.
+
+2013-12-22  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (maxframes): New static unsigned. Initialize to 64.
+	(struct frame): New struct.
+	(struct frames): Likewise.
+	(dwfl): New static Dwfl pointer.
+	(frame_callback): Use arg as struct frames and fill it next frame.
+	Return DWARF_CB_ABORT when maxframes has been reached. Move
+	printing of frame to...
+	(print_frames): ...here. New function.
+	(thread_callback): Use arg as struct frames and set frames to zero.
+	Call print_frames.
+	(parse_opt): Handle '-n'.
+	(main): Add -n to options. Allocate frames using maxframes. Pass
+	frames to frame_callback and thread_callback.
+
+2013-12-20  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (show_one_tid): New static boolean.
+	(parse_opt): Handle '-1'.
+	(main): Add -1 to options. Call dwfl_getthread_frames when
+	show_one_tid is true.
+
+2013-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (options): Add symbol-sections, 'x'.
+	(show_symbol_sections): New static bool.
+	(parse_opt): Handle 'x'.
+	(print_addrsym): Use dwfl_module_addrinfo value.r
+	Also show section of address with show_symbol_sections.
+	(find_symbol): Use dwfl_module_getsym_info and set value.
+	(handle_address): Request value and use it instead of sym.st_value.
+	* readelf.c (format_dwarf_addr): Use dwfl_module_addrinfo to get
+	name and offset.
+
+2013-12-17  Masatake YAMATO  <yamato@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c (show_activation, show_module, show_source): New variables.
+	(parse_opt): Set show_activation if -a option is given.
+	Set show_module if -m option is given. Set show_source if -s option
+	is given. Set all show booleans when -v option is given.
+	(main): Added `-a', `-m', `-s', and `-v' to the help message.
+	(frame_callback): Print module and source file information.
+
+2013-11-25  Petr Machata  <pmachata@redhat.com>
+
+	* elflint.c (valid_e_machine): Add EM_AARCH64.
+
+2013-11-14  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (handle_core_item) <'h'>: New branch for handling
+	fields that shouldn't be displayed.
+
+2013-11-10  Mark Wielaard  <mjw@redhat.com>
+
+	* stack.c: Use ARGP_PROGRAM_VERSION_HOOK_DEF and
+	ARGP_PROGRAM_BUG_ADDRESS_DEF.
+	(print_version): New function.
+
+2013-11-09  Mark Wielaard  <mjw@redhat.com>
+
+	* arlib.c (arlib_init): Call snprintf before using the result
+	with memcpy.
+	(arlib_finalize): Likewise.
+	* nm.c (show_symbols_sysv): Don't modify cnt inside assert.
+
+2013-11-07  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (bin_PROGRAMS): Add stack.
+	(stack_LDADD): New.
+	* stack.c: New file.
+
+2013-11-05  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_ranges_section): Cast address to size_t
+	before comparison.
+	(print_debug_loc_section): Likewise.
+
+2013-10-18  Mark Wielaard  <mjw@redhat.com>
+
+	* ar.c (main): Correct operation check when instance_specifed is set.
+
+2013-09-26  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (handle_file_note): New function.
+	(handle_notes_data): Call it to handle NT_FILE notes.
+
+2013-09-26  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (handle_siginfo_note): New function.
+	(handle_notes_data): Call it to handle NT_SIGINFO notes.
+	(buf_read_int, buf_read_ulong, buf_has_data): New functions.
+
+2013-08-13  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (options): Add "inlines", 'i'.
+	(show_inlines): New bool.
+	(parse_opt): Handle 'i'.
+	(print_diesym): New static function.
+	(print_src): New function taking code from...
+	(handle_address): here. Call print_src. Print inlines.
+
+2013-08-12  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (main): If there is a newline char at end of buf,
+	then remove it.
+
+2013-07-05  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Take CU as argument, use it to print
+	parameter_ref DIE offset.
+	(struct listptr): Replace base field with cu.
+	(listptr_base): New function.
+	(compare_listptr): Use listptr_base.
+	(notice_listptr): Take CU as argument.
+	(skip_listptr_hole): Likewise.
+	(print_debug_ranges_section): Pass NULL as CU to skip_listptr_hole.
+	(print_cfa_program): Pass NULL as CU to print_ops.
+	(struct attrcb_args): Replace cu_base field with cu.
+	(attr_callback): Pass cu not cu_base to notice_listptr.
+	(print_debug_units): Don't calculate base, just set cu.
+	(print_debug_loc_section): Pass cu to skip_listptr_hole and
+	print_ops.
+
+2013-05-06  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Format first DW_OP_GNU_implicit_pointer
+	argument as DIE offset.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2013-03-25  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (argp_options): Add decodedline.
+	(decodedline): New boolean initialized to false.
+	(parse_opt): Set decodedline when arg is decodedline.
+	(print_decoded_line_section): New function.
+	(print_debug_line_section): Call print_decoded_line_section when
+	decodedline is true.
+
+2013-03-25  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (argp_option): Add decodedaranges.
+	(decodedaranges): New boolean initialized to false.
+	(parse_opt): Set decodedaranges when arg is decodedaranges.
+	(print_debug_aranges_section): Reimplemented and original
+	implementation renamed to...
+	(print_decoded_aranges_section): this.
+
+2013-03-25  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (attrcb_args): Add Dwarf_Die.
+	(attr_callback): When highpc is in constant form also print as
+	address.
+	(print_debug_units): Set args.die.
+
+2013-03-19  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Free format_dwarf_addr results.
+
+2013-03-18  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Accept version 8.
+
+2013-03-01  Mark Wielaard  <mjw@redhat.com>
+
+	* findtextrel.c (process_file): Release ELF and close file when not
+	text relocations are found.
+	* strip.c (handle_elf): Track memory used for .debuglink section data
+	and free when done.
+
+2013-02-24  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_symtab): Add __bss_start__ to the list of symbols
+	allowed to have out of section values because of GNU ld bugs.
+
+2013-02-06  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_symtab): Add __bss_start and __TMC_END__ to the
+	list of symbols allowed to have out of section values because of
+	GNU ld bugs in either .symtab or .dynsym, but only when they are
+	zero sized.
+
+2013-01-24  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (argp_option): Add unresolved-address-offsets, U.
+	(print_unresolved_addresses): New static.
+	(parse_opt): Handle 'U', set print_unprocessed_values.
+	(format_dwarf_addr): Take and handle new raw argument.
+	(print_ops): Call format_dwarf_addr with raw offset values.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_frame_section): Likewise.
+	(attr_callback): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_gdb_index_section): Likewise.
+
+2013-01-18  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (struct listptr): Add base Dwarf_Addr field.
+	(compare_listptr): Warn for same offset with different base.
+	(notice_listptr): Take base argument and set it.
+	(skip_listptr_hole): Likewise.
+	(struct attrcb_args): Removed unused cu_offset field.
+	Add cu_base Dwarf_Addr field.
+	(attr_callback): Call notice_listptr with cbargs->cu_base.
+	(print_debug_units): Set args.cu_base.
+	(print_debug_ranges_section): Get base and use for format_dwarf_addr.
+	(print_debug_loc_section): Likewise.
+
+2013-01-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* readelf.c (handle_core_items): Limit special repeated items handling
+	to single-item formats '\n', 'b' and 'B', assert OFFSET 0 there.
+
+2012-12-18  Mark Wielaard  <mark@bordewijk.wildebeest.org>
+
+	* readelf.c (ELF_INPUT_SECTION): New argp key value.
+	(argp_option): Add elf-section.
+	(elf_input_section): New static.
+	(parse_opt): Handle ELF_INPUT_SECTION and set elf_input_section.
+	(open_input_section): New function.
+	(process_file): Call open_input_section if elf_input_section set.
+
+2013-01-13  David Abdurachmanov  <David.Abdurachmanov@cern.ch>
+
+	ar.c (do_oper_delete): Fix num passed to memset.
+
+2012-12-21  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Adjust FDE start address
+	if pcrel before feeding it to format_dwarf_addr.
+
+2012-12-21  Mark Wielaard  <mjw@redhat.com>
+
+	* addr2line.c (main): Call dwfl_end.
+
+2012-12-11  Roland McGrath  <roland@hack.frob.com>
+
+	* nm.c (show_symbols_sysv): Fix size passed to snprintf for invalid
+	sh_name case.
+	Reported by David Abdurachmanov <David.Abdurachmanov@cern.ch>.
+
+2012-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): DW_OP_skip and DW_OP_bra targets are
+	calculated beginning after the operand and 2-byte constant.
+
+2012-10-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* readelf.c (ITEM_WRAP_COLUMN, REGISTER_WRAP_COLUMN): Merge to ...
+	(WRAP_COLUMN): ... here.
+	(print_core_item): Remove parameter format_max.  Update function
+	comment.  Replace FORMAT_MAX by the real output width.
+	(handle_core_item): Remove the FORMAT_MAX values in TYPES, DO_TYPE,
+	calls of print_core_item, remove variable maxfmt, change
+	ITEM_WRAP_COLUMN to WRAP_COLUMN.
+	(handle_core_register): Remove the FORMAT_MAX values in TYPES, BITS,
+	calls of print_core_item, change REGISTER_WRAP_COLUMN to WRAP_COLUMN.
+
+2012-10-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* readelf.c (handle_core_item) <b>: Make run an outer block variable.
+	Increase run only if LASTBIT != 0.  Print last element only if RUN > 0.
+
+2012-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_macro_section): Print offset as PRIx64.
+
+2012-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (register_info): Handle loc == NULL.
+
+2012-08-22  Jeff Kenton  <jkenton@tilera.com>
+
+	* elflint.c (valid_e_machine): Add EM_TILEGX and EM_TILEPRO.
+
+2012-08-16  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_tag_name): Renamed from dwarf_tag_string.
+	Uses new dwarf_tag_string or adds ??? or lo_user+%#x when
+	appropriate.
+	(dwarf_attr_name): Likewise.
+	(dwarf_form_name): Likewise.
+	(dwarf_lang_name): Likewise.
+	(dwarf_inline_name): Likewise.
+	(dwarf_encoding_name): Likewise.
+	(dwarf_access_name): Likewise.
+	(dwarf_visibility_name): Likewise.
+	(dwarf_virtuality_name): Likewise.
+	(dwarf_identifier_case_name): Likewise.
+	(dwarf_calling_convention_name): Likewise.
+	(dwarf_ordering_name): Likewise.
+	(dwarf_discr_list_name): Likewise.
+	(print_ops): Remove KNOWN.  Use dwarf_locexpr_opcode_string.
+	(attr_callback): Call new dwarf_foobar_name instead of old
+	dwarf_foobar_string functions.
+	(dwarf_tag_string): New function using known-dwarf.h macros.
+	(dwarf_attr_string): Likewise.
+	(dwarf_form_string): Likewise.
+	(dwarf_lang_string): Likewise.
+	(dwarf_inline_string): Likewise.
+	(dwarf_encoding_string): Likewise.
+	(dwarf_access_string): Likewise.
+	(dwarf_visibility_string): Likewise.
+	(dwarf_virtuality_string): Likewise.
+	(dwarf_identifier_case_string): Likewise.
+	(dwarf_calling_convention_string): Likewise.
+	(dwarf_ordering_string): Likewise.
+	(dwarf_discr_list_string): Likewise.
+	(dwarf_locexpr_opcode_string): Likewise.
+
+2012-06-27  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_form_string): Handle DW_FORM_GNU_ref_alt and
+	DW_FORM_GNU_strp_alt.
+	(attr_callback): Likewise.
+
+2012-07-30  Petr Machata  <pmachata@redhat.com>
+
+	* nm.c (show_symbols_bsd): Reorder arguments in {S,}FMTSTRS (and
+	corresponding printf) so that those that are referenced by only
+	one of the formatting strings are at the end.
+
+2012-07-29  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_lang_string): Use DW_LANG_ObjC, not DW_LANG_Objc.
+	(print_ops): Use known[op], not op_name, for DW_OP_GNU_parameter_ref.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Handle DW_OP_GNU_parameter_ref.
+
+2012-07-11  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (options): Add macro to help of debug-dump.
+	(section_e): Add section_macro.
+	(section_all): Add section_macro.
+	(parse_opt): Handle macro.
+	(print_debug_macro_section): New function.
+	(print_debug): Add NEW_SECTION (macro).
+
+2012-07-10  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Add version 7 support.
+	Keep track of cu_nr. Print kind and static/global flag for each
+	symbol. When a symbol is in the TU list add 'T'.
+
+2012-06-26  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_attr_string): Add DW_AT_GNU_macros.
+
+2012-06-22  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Cast printf PRIu/x64 arguments to uint64_t
+	for gcc 4.7 -Wformat.
+
+2012-05-09  Roland McGrath  <roland@hack.frob.com>
+
+	* elflint (check_sections): Allow zero sized sections at (filesz) end
+	of segment. And make check overflow-proofed.
+
+2012-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Add DW_OP_GNU_push_tls_address,
+	DW_OP_GNU_uinit and DW_OP_GNU_encoded_addr.
+
+2012-03-28  Roland McGrath  <roland@hack.frob.com>
+
+	* elflint.c (special_sections): Accept SHF_INFO_LINK for reloc sections.
+
+2012-03-28  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_debug_abbrev_section): Check there is Dwarf
+	section data.
+	(print_debug_str_section): Likewise.
+
+2012-03-21  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_gdb_index_section): Accept version 6.
+
+2012-01-31  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (attr_callback): Don't special case DW_FORM_sec_offset.
+
+2012-01-21  Ulrich Drepper  <drepper@gmail.com>
+
+	* addr2line.c: Update copyright year.
+	* ar.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+	* nm.c (argp_children): Define.
+	(argp): Hook up argp_children.
+	(handle_ar): Optimize puts call.
+	(show_symbols_bsd): Use positional parameters to also print color
+	codes.  Don't print STT_FILE symbols.
+	* objdump.c (options): Improve help text.
+	(argp_children): Define.
+	(argp): Hook up argp_children.
+	(disasm_info): Add elements for color codes.
+	(disasm_output): Print color codes as well.
+	(show_disasm): Set up disasm_info data for callback.
+
+2012-01-20  Roland McGrath  <roland@hack.frob.com>
+
+	* arlib-argp.c (arlib_deterministic_output): Initialize from
+	configured value.
+	(help_filter): New function.
+	(argp): Use it.
+
+	* ar.c (main): Handle oper_none as usage error.
+
+	* arlib-argp.c (options, parse_opt): Grok -U as inverse of -D.
+
+	* ranlib.c (argp): Use arlib_argp_children.
+
+	* arlib.c (arlib_init): Obey arlib_deterministic_output.
+
+	* arlib-argp.c: New file.
+	* Makefile.am (libar_a_SOURCES): Add it.
+	* arlib.h (arlib_deterministic_output, arlib_argp_children):
+	Declare new variables.
+	* ar.c (deterministic_output): Variable removed.
+	(do_oper_insert): Use arlib_deterministic_output instead.
+	(options, parse_opt): Don't handle -D here.  Add group numbers.
+	(argp): Use arlib_argp_children.
+
+2011-12-20  Roland McGrath  <roland@hack.frob.com>
+
+	* readelf.c (print_debug): Initialize DUMMY_DBG.elf.
+	Reported by Karel Klic <kklic@redhat.com>.
+
+2011-11-05  Roland McGrath  <roland@hack.frob.com>
+
+	* ar.c (deterministic_output): New flag variable.
+	(options, parse_opt): Grok -D to set it.
+	(do_oper_insert): When set, use zero from mtime, uid, and gid.
+
+	* ar.c (do_oper_insert): Fix check on elf_rawfile return value.
+
+2011-10-04  Marek Polacek  <mpolacek@redhat.com>
+
+	* readelf.c (register_info): Assume the right size of an array.
+
+2011-10-03  Ulrich Drepper  <drepper@gmail.com>
+
+	* nm.c: Recognize option --mark-special.  Still recognize --mark-weak
+	but don't show it in help anymore.
+	(mark_special): Renamed from mark_weak.
+	(parse_opt): Adjust.
+	(class_type_char): Take additional parameters for ELF file and ELF
+	header.  Treat TLS symbols like objects.
+	In case of D symbols, show u for unique symbols, R for symbols in
+	read-only sections, B for symbols in BSS sections.
+	(show_symbols_bsd): Take additional parameters for ELF file and ELF
+	header.  Adjust for class_type_char change.  Show TLS symbols with
+	@ after them in case --mark-special is selected.
+	(show_symbols_posix): Likewise.
+	(show_symbols): Adjust calls to show_symbols_bsd and
+	show_symbols_posix.
+	(show_symbols_sysv): Avoid printing address and size for undefined
+	symbols.  Don't print initial special entry and section entries.
+
+2011-10-02  Ulrich Drepper  <drepper@gmail.com>
+
+	* Makefile.am (demanglelib): Define.
+	(nm_LDADD): Add demanglelib.
+	* nm.c (options): Add -C option.
+	(demangle): Define as global variable.
+	(parse_opt): Recognize -C.
+	(show_symbols_sysv): Handle demangling.
+	(show_symbols_bad): Likewise.
+	(show_symbols_posix): Likewise.
+	(show_symbols): Likewise.
+
+2011-07-09  Roland McGrath  <roland@hack.frob.com>
+
+	* readelf.c (options, parse_opt): Grok -W/--wide and ignore it.
+
+	* ar.c (parse_opt): Grok -u.
+
+2011-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (relocate): Make offset check overflow-proof.
+
+2011-05-23  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (relocate): Take new arguments is_rela to indicate
+	whether the relocation is from a SHT_REL or SHT_RELA section.
+	Relocate against any debug section symbol, not just STT_SECTION
+	symbols. For SHT_REL relocations, fetch addend from offset and
+	add it to symbol value if not zero.
+
+2011-05-23  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (OPT_RELOC_DEBUG): New option.
+	(argp_option): Add new --reloc-debug-sections option.
+	(main): Check new option.
+	(parse_opt): Likewise.
+	(handle_elf): Remove any relocations between debug sections
+	in ET_REL for the debug file when requested.
+
+2011-05-18  Mark Wielaard  <mjw@redhat.com>
+
+	* strip.c (handle_elf): Make sure all sections of a removed group
+	section are removed too. Don't discard SHT_GROUP sections, copy
+	section table before it gets modified. Section group signature
+	symbols don't have to be retained.
+
+2011-05-16  Jakub Jelinek  <jakub@redhat.com>
+
+	* readelf.c (print_ops): Handle DW_OP_GNU_const_type,
+	DW_OP_GNU_regval_type, DW_OP_GNU_deref_type, DW_OP_GNU_convert
+	and DW_OP_GNU_reinterpret.
+
+2011-05-17  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_tag_string): Fixup DW_TAG_GNU_call_site and
+	DW_TAG_GNU_call_site_parameter return strings.
+
+2011-05-11  Marek Polacek  <mpolacek@redhat.com>
+
+	* nm.c (show_symbols_sysv): Remove unused if/else, remove
+	unused `prefix' and `fname' parameters.
+
+2011-05-07  Marek Polacek  <mpolacek@redhat.com>
+
+	* unstrip.c (compare_sections_nonrel): Mark this function as static.
+
+2011-04-26  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (handle_notes_data): Call ebl_object_note_type_name
+	with note name.
+
+2011-04-14  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (options): Add gdb_index.
+	(section_e): Define section_gdb_index.
+	(parse_opt): Recognize gdb_index debug-dump argument.
+	(print_gdb_index_section): New function.
+	(print_debug): Add gdb_index to debug_sections.
+
+2011-03-24  Petr Machata  <pmachata@redhat.com>
+
+	* readelf.c (print_debug_line_section): Emit initial space for all
+	opcode lines.  Print offset in front of each opcode.
+
+2011-03-22  Marek Polacek  <mpolacek@redhat.com>
+
+	* readelf.c (handle_dynamic): Don't segfault at DT_PLTREL case.
+
+2011-03-22  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_tag_string): Support DW_TAG_GNU_call_site
+	and DW_TAG_GNU_call_site_parameter.
+	(dwarf_attr_string): Support DW_AT_GNU_call_site_value,
+	DW_AT_GNU_call_site_data_value,
+	DW_AT_GNU_call_site_target,
+	DW_AT_GNU_call_site_target_clobbered,
+	DW_AT_GNU_tail_call,
+	DW_AT_GNU_all_tail_call_sites,
+	DW_AT_GNU_all_call_sites,
+	and DW_AT_GNU_all_source_call_sites.
+	(print_ops): Handle DW_OP_GNU_entry_value.
+	(attr_callback): Handle DW_AT_GNU_call_site_value,
+	DW_AT_GNU_call_site_data_value,
+	DW_AT_GNU_call_site_target,
+	and DW_AT_GNU_call_site_target_clobbered.
+
+2011-03-10  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_symtab): Use ebl_check_st_other_bits.
+
+2011-02-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* readelf.c (reset_listptr): Clear TABLE->TABLE.
+
+2011-02-25  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (dwarf_attr_string): Add DW_AT_GNU_* handling.
+	(dwarf_form_string): Properly format and return unknown form.
+
+2011-02-23  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (section_name): New function.
+	(print_debug_abbrev_section): Use it instead of constant.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_units): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_pubnames_section): Likewise.
+	(print_debug_str_section): Likewise.
+	(print_debug) [USE_ZLIB]: Match .zdebug_* sections too.
+	(print_debug_abbrev_section): Use decoded d_size, not sh_size.
+	(print_debug_str_section): Likewise.
+
+	* readelf.c (dwarf_attr_string): Grok DW_AT_GNU_odr_signature.
+
+2011-02-11  Roland McGrath  <roland@redhat.com>
+
+	* elfcmp.c (verbose): New variable.
+	(options, parse_opt): Grok -l/--verbose to set it.
+	(main): Under -l, keep going after first difference.
+
+	* elfcmp.c (ignore_build_id): New variable.
+	(options, parse_opt): Grok --ignore-build-id to set it.
+	(main): For SHT_NOTE sections, compare note details rather than raw
+	bytes.  Under --ignore-build-id, don't complain about differing build
+	ID contents if lengths match.
+
+2011-02-08  Roland McGrath  <roland@redhat.com>
+
+	* ldscript.y (filename_id_star): Remove unused variable.
+
+	* unstrip.c (copy_elided_sections): Remove unused variable.
+
+	* elflint.c (check_dynamic): Remove unused variables.
+
+	* elflint.c (check_symtab): Warn about missing xndx section only once.
+
+	* ldgeneric.c (check_for_duplicate2): Remove unused variable.
+
+2011-01-06  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Under --strip-sections, remove all
+	non-allocated sections and never generate .gnu_debuglink.
+
+2011-01-04  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (remove_shdrs): New variable.
+	(options, parse_opt): Grok --strip-sections to set it.
+	(handle_elf): When that's set, truncate off .shstrtab and shdrs.
+
+2010-11-10  Roland McGrath  <roland@redhat.com>
+
+	* findtextrel.c (process_file): Don't assume order of sections.
+	Reported by Mike Hommey <mh@glandium.org>.
+
+2010-07-26  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ops): Handle DW_OP_GNU_implicit_pointer.
+
+2010-08-30  Roland McGrath  <roland@redhat.com>
+
+	Print .debug_loc/.debug_ranges with cognizance of actual DIE uses.
+	* readelf.c (parse_opt): Add section_info to implicit_debug_sections
+	for ranges, loc.
+	(struct listptr, struct listptr_table): New types.
+	(compare_listptr, reset_listptr, sort_listptr): New functions.
+	(notice_listptr, skip_listptr_hole): New functions.
+	(struct attrcb_args): Add silent member.
+	(attr_callback): Call notice_listptr for loclistptr and rangelistptr.
+	Suppress output if silent, but still call notice_listptr.
+	(print_debug_units): Suppress output if section_info not requested.
+	(print_debug_loc_section): Call sort_listptr, skip_listptr_hole.
+	(print_debug_ranges_section): Likewise.
+	(print_debug): Call reset_listptr on both tables.
+
+	* readelf.c (print_debug_ranges_section): Print empty list.
+	(print_debug_loc_section): Likewise.
+
+	* readelf.c (print_debug_loc_section): Check for bogus length
+	before calling print_ops.
+	(print_ops): Check harder for bogus data that would read off end.
+
+2010-08-11  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (for_each_section_argument): Process all sections with
+	matching name, not just the first.
+
+2010-07-26  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ops): Take new argument for CU version.
+	Fix DW_OP_call_ref decoding to depend on it.
+	(print_debug_loc_section): Update caller.
+	(print_cfa_program): Take new argument, pass it down.
+	(print_debug_frame_section): Update caller.
+	(struct attrcb_args): New member version.
+	(print_debug_units): Initialize it.
+
+2010-07-02  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Use format_dwarf_addr for
+	initial_location.
+
+2010-06-30  Roland McGrath  <roland@redhat.com>
+
+	* strings.c (main): Use STDIN_FILENO, not STDOUT_FILENO.
+	Ignore st_size for a non-S_ISREG file descriptor.
+	(read_block): Move assert after no-mmap bail-out.
+	(read_block_no_mmap): Fix size calculations for moving buffer remnant.
+
+2010-06-22  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_line_section): Fix braino in DW_LNS_set_isa.
+
+2010-06-21  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (dwarf_tag_string): Handle new v4 tags.
+	(dwarf_attr_string): Add new attributes.
+	(dwarf_tag_string): Handle DW_TAG_GNU_*.
+
+	* readelf.c (print_ops): Use 64-bit types for LEB128 operands.
+	(print_cfa_program): Likewise.
+
+2010-06-20  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_units): New function, broken out of ...
+	(print_debug_info_section): ... here.  Call it.
+	(print_debug_types_section): New function.
+	(enum section_e): Add section_types alias for section_info.
+	(print_debug): Add types to the sections table.
+
+	* readelf.c (print_debug_frame_section): Handle version 4 format.
+
+	* readelf.c (print_debug_line_section): Handle version 4 format.
+
+2010-06-14  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Make sure all sections' data have
+	been read in before we write anything out.
+
+2010-06-04  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (update_shdr): New function.
+	(update_sh_size): Call it instead of gelf_update_shdr.
+	(adjust_relocs, add_new_section_symbols): Likewise.
+	(new_shstrtab, copy_elided_sections): Likewise.
+
+	* unstrip.c (copy_elided_sections): Bail if stripped file has more
+	sections than unstripped file, rather than getting confused later.
+
+2010-06-01  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (dwarf_form_string): Handle DWARF 4 forms.
+	(attr_callback): Handle DW_FORM_flag_present, DW_FORM_exprloc,
+	DW_FORM_sec_offset, DW_FORM_ref_sig8.
+
+	* readelf.c (print_debug): Don't bail if libdw setup fails.
+	Suppress complaint if we only want .eh_frame anyway.
+
+2010-05-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (attr_callback): Also print form information.
+
+2010-05-19  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (find_symbol): Short-circuit on empty name.
+	(handle_address): Handle SYMBOL with no +OFFSET.
+
+2010-05-08  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ops): Take new arg OFFSET_SIZE.
+	Use that for DW_OP_call_ref, not ADDRSIZE.
+	(print_cfa_program): Update caller.
+	(struct attrcb_args): Add offset_size field.
+	(attr_callback): Use it for print_ops call.
+	(print_debug_info_section): Initialize it.
+	(print_ops): Likewise.
+
+2010-04-14  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_core_item): Fix bitmask printing.
+
+2010-04-06  Roland McGrath  <roland@redhat.com>
+
+	* ld.c (options): Fix some typos in messages.
+	* elflint.c (check_scn_group, check_group): Likewise.
+	* ldscript.y (add_id_list): Likewise.
+	* readelf.c (print_hash_info): Add xgettext:no-c-format magic comment
+	before translated string containing a literal %.
+
+2010-02-26  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (process_file): Don't leak an fd in failure case.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+	* readelf.c (print_debug_frame_section): Add a cast to avoid sign
+	mismatch in comparison.
+
+2010-02-02  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_encoding_base): Handle DW_EH_PE_absptr (zero).
+	(read_encoded): Likewise.
+	(print_debug_frame_section): Check for bogus augmentation length.
+	For P augmentation, use read_encoded, print the encoding description,
+	and use hex for unsigned values.
+
+2010-01-15  Roland McGrath  <roland@redhat.com>
+
+	* ar.c: Include <sys/stat.h>.
+	* elflint.c: Likewise.
+	* readelf.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise
+
+2010-01-07  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ehdr): Handle PN_XNUM.
+	(phnum): New static variable.
+	(process_elf_file): Set it with elf_getphdrnum.
+	(print_phdr): Use phnum instead of EHDR->e_phnum.
+	(print_dynamic, handle_notes): Likewise.
+	(handle_relocs_rel, handle_relocs_rela): Likewise.
+
+	* elfcmp.c (main): Use elf_getshdrnum and elf_getphdrnum.
+
+	* elflint.c (phnum): New static variable.
+	(check_elf_header): Set it, handling PN_XNUM.
+	Use that in place of EHDR->e_phnum throughout.
+	(check_symtab, check_reloc_shdr, check_dynamic): Likewise.
+	(unknown_dependency_p, check_sections, check_program_header): Likewise.
+
+2010-01-05  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (dwarf_attr_string): Match DW_AT_GNU_vector and
+	DW_AT_GNU_template_name.
+
+2010-01-04  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_notes_data): Grab NT_AUXV only for name "CORE".
+	(handle_core_note): Pass NHDR and NAME to ebl_core_note.
+	(handle_core_item): Handle .format of '\n' as \n-separated strings.
+
+	* readelf.c (implicit_debug_sections): New variable.
+	(parse_opt): Set it instead of print_debug_sections for -a.
+	OR them together for print_debug check.
+	(print_debug): OR them together for section check.
+
+	* readelf.c (options): Repartition into set implied by -a and others.
+	Correct -a text to match reality.
+
+	* readelf.c (struct section_argument): Add bool member 'implicit'.
+	(parse_opt): Set it for -a cases, clear it for -x args.
+	(for_each_section_argument): Don't complain about a missing section by
+	name if it's implicit.
+
+2009-11-16  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_string_section): Punt SHT_NOBITS like empty
+	sections, just as dump_data_section already does.
+
+2009-09-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (special_sections): Allow MERGE and STRINGS flags to be
+	set for .comment section.
+	Patch by Mark Wielaard <mjw@redhat.com>.
+
+2009-09-08  Roland McGrath  <roland@redhat.com>
+
+	* ar.c (main): Fix typo in message format.
+
+2009-08-21  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (attr_callback): Use print_block only when we don't use
+	print_ops.
+
+2009-08-14  Roland McGrath  <roland@redhat.com>
+
+	* ar.c (do_oper_extract): Use pathconf instead of statfs.
+
+2009-08-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* debugpred.h: Add two most const.
+
+2009-07-26  Mark Wielaard  <mjw@redhat.com>
+
+	* elflint.c (check_note_data): Recognize NT_GNU_GOLD_VERSION.
+
+2009-07-25  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (addr2line_LDADD): Add $(libelf).
+
+2009-07-24  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_block): New function.
+	(print_ops): Use it.
+	(attr_callback): Use it for DW_FORM_block* forms.
+
+2009-07-20  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (print_ops): Add handling of DW_OP_implicit_value
+	and DW_OP_stack_value.
+
+2009-07-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_elf_header): Allow Linux ABI.
+	(check_symtab): Handle STB_GNU_UNIQUE.
+
+2009-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* readelf.c (attr_callback): Handle DW_Form constants for
+	DW_AT_data_member_location.
+
+2009-07-06  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (register_info): New function.  Handle unknown register #s.
+	(print_cfa_program): Use it.
+	(handle_core_register, handle_core_registers): Likewise.
+
+2009-06-28  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_address_names): New static variable.
+	(options, parse_opt): Grok -N/--numeric-addresses to clear it.
+	(format_dwarf_addr): Don't look up name if !print_address_names.
+
+2009-06-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldgeneric.c: Don't use deprecated libelf functions.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+	* ld.h: Fix up comment.
+
+2009-06-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_relocs): Expect ELF header argument and pass on
+	to handle_relocs_rel* functions. Adjust caller.
+	(handle_relocs_rel): Add ELF header argument.  Add special case for
+	the IRELATIVE relocations in statically linked executables.
+	(handle_relocs_rela): Likewise.
+
+2009-04-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_symtab): Add tests of st_other field.
+
+2009-04-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile [BUILD_STATIC] (libdw): Add $(zip_LIBS).
+
+2009-04-20  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (print_dwarf_function): Honor -s and -A for file names
+	of inline call sites.
+
+	* addr2line.c (just_section): New variable.
+	(adjust_to_section): New function, broken out of ...
+	(handle_address): ... here.
+	(options, parse_opt): Add -j/--section=NAME to set it.
+
+2009-04-15  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Check for DW_CIE_ID_64 in
+	64-bit format header, DW_CIE_ID_32 in 32-bit format header.
+
+2009-04-14  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_attributes): Treat SHT_ARM_ATTRIBUTES on EM_ARM
+	like SHT_GNU_ATTRIBUTES.
+
+	* readelf.c (handle_core_registers): Fix error message.
+
+	* strip.c (handle_elf: check_preserved): Don't note any change when
+	.debug_data is already filled from a previous pass.
+
+2009-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* objdump.c (show_relocs_x): Minor cleanups.
+
+	* readelf.c (print_cfa_program): Correct a few labels.
+	Print first DW_CFA_expression and DW_CFA_val_expression parameter
+	as register.
+
+2009-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* objdump.c (show_relocs_rel, show_relocs_rela): Split common parts
+	into ...
+	(show_relocs_x): ...here.  New function.
+	(show_relocs): Better spacing in output.
+
+	* objdump.c (show_relocs_rela): Show offsets as signed values.
+
+	* ar.c (main): Fix recognition of invalid modes for a, b, i modifiers.
+	Improve some error messages.
+	Use program_invocation_short_name instead of AR macro.
+	* Makefile.am (CFLAGS_ar): Remove.
+	* elflint.c (parse_opt): ARGP_HELP_EXIT_ERR does nothing for argp_help.
+	* objdump.c (parse_opt): Likewise.
+	* readelf.c (parse_opt): Likewise.
+
+2009-01-27  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ops): Notice short length, don't overrun buffer
+	(still need to fix LEB128).
+
+	* readelf.c (print_ops): Fix DW_OP_call[24] decoding.
+
+	* readelf.c (print_ops): Print (empty)\n when LEN == 0.
+
+2009-01-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_debug_frame_section): Fix computation of vma_base
+	for PC-relative mode.
+
+2009-01-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* size.c (process_file): When handling archive, close file descriptor
+	here.  For unknown file format also close file descriptor.
+	(handle_ar): Don't close file descriptor here.
+
+	* readelf.c (parse_opt): Move code to add to dump_data_sections and
+	string_sections list in local function add_dump_section.  Adjust 'x'
+	key handling.  For 'a' key add .strtab, .dynstr, and .comment section
+	to string_sections list.
+
+2009-01-22  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_phdr): Don't print section mapping when no sections.
+
+	* Makefile.am (AM_CFLAGS): Pass -Wno-format for *_no_Wformat.
+
+	* readelf.c (print_debug_frame_section): Initialize IS_SIGNED to false
+	and reset it only for the 'true' cases.
+
+	* Makefile.am (addr2line_no_Wformat): New variable.
+
+	* readelf.c (print_debug_frame_section): Use t instead of j formats
+	for ptrdiff_t OFFSET.
+
+2009-01-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_program_header): Fix typo in .eh_frame_hdr section
+	test.  Handle debuginfo files.
+	(check_exception_data): First sanity test.
+
+2009-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_debug_exception_table): Show target of ar_disp
+	field.
+
+	* elflint.c (check_program_header): Add most consistency checks for
+	PT_GNU_EH_FRAME entry.
+
+	* addr2line.c: Use ARGP_PROGRAM_VERSION_HOOK_DEF and
+	ARGP_PROGRAM_BUG_ADDRESS_DEF.
+	* ar.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2009-01-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_program_header): Check that PT_GNU_EH_FRAME entry
+	matches .eh_frame_hdr section, if it is available.  Also check that
+	the segment is allocated, not writable, not executable.
+
+	* readelf.c: Add -e option.  Dump exception and unwind related
+	sections.  Add -e to -a.
+	(print_encoding_base): Handle DW_EH_PE_omit.
+	(print_debug_exception_table): Beginning of support.
+	(print_debug): Hook up print_debug_exception_table for
+	.gcc_except_table sections.
+
+	* readelf.c (print_debug_frame_section): Some fixes for last change.
+
+2009-01-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_encoding): Now a toplevel function.
+	(print_relinfo): Likewise.
+	(print_encoding_base): Broken out of print_debug_frame_section.
+	(print_debug_frame_section): Print different header for .eh_frame
+	sections.  Fix recognition of matching CIEs in .debug_frame sections.
+	Print absolute offset for PC-relative FDE locations.  Don't print
+	table header for FDEs if the table is empty.
+	(read_encoded): New function.
+	(print_debug_frame_hdr_section): New function.
+	(print_debug): Hook up print_debug_frame_hdr_section for .eh_frame_hdr
+	sections.
+
+	* readelf.c (handle_relocs_rel): Print section number.
+	(print_debug_abbrev_section): Likewise.
+	(print_debug_aranges_section): Likewise.
+	(print_debug_ranges_section): Likewise.
+	(print_debug_info_section): Likewise.
+	(print_debug_line_section): Likewise.
+	(print_debug_loc_section): Likewise.
+	(print_debug_macinfo_section): Likewise.
+	(print_debug_pubnames_section): Likewise.
+	(print_debug_str_section): Likewise.
+
+2009-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* strings.c (read_block): Fix typo in error message string.
+
+2009-01-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c (ld_new_searchdir): Fix adding to search path list.
+
+2009-01-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c: Implement call frame debug section dumping.
+
+2009-01-05  Roland McGrath  <roland@redhat.com>
+
+	* elfcmp.c: Exit with status 2 for errors (like cmp, diff, grep).
+	Status 1 (aka EXIT_FAILURE) is only for completed OK but not equal.
+
+2009-01-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: Update copyright year.
+	* ar.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2008-12-11  Roland McGrath  <roland@redhat.com>
+
+	* nm.c (sym_name): New function.
+	(show_symbols_sysv): Use it in place of elf_strptr.
+	(show_symbols_bsd, show_symbols_posix): Likewise.
+	Fixes RHBZ#476136.
+
+	* nm.c (show_symbols_sysv): Use an alloca'd backup section name when
+	elf_strptr fails.
+
+2008-12-02  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (count_dwflmod, process_file): Don't presume encoding of
+	nonzero OFFSET argument to dwfl_getmodules.
+
+2008-08-07  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (main): Pass string to handle_address.
+	(see_one_module): New function, subroutine of handle_address.
+	(find_symbol): Likewise.
+	(handle_address): Take string argument rather than address.
+	Convert plain number, or handle strings like "(section)+offset"
+	or "symbol+offset".
+
+2008-08-01  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_core_item): Handle 'B' type for 1-origin bitset.
+	For 'b' and 'B', print <x-y,z> or ~<x,y-z> rather than 1/0 string.
+
+	* readelf.c (convert): Take new argument SIZE.
+	(handle_core_register, handle_core_item): Update callers.
+	(handle_core_item): Take new arg REPEATED_SIZE.
+	(handle_core_items): Special case for a singleton item,
+	let handle_core_item handle repeats if it wants to.
+
+	* readelf.c (handle_core_items): Give abridged output
+	for identical groups repeated more than twice.
+
+2008-07-04  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_core_items): Handle ELF_T_ADDR.
+
+2008-04-10  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Don't keep sections that kept symbol tables
+	refer to.  Instead, just be sure to preserve the original symbol
+	table in the debug file so those symbols go with their sections and
+	can be elided from the stripped version of the symbol table.
+
+	* strip.c (handle_elf): When a discarded section kept in the debug
+	file refers to a nondiscard section via sh_link/sh_info, preserve
+	that nondiscarded section unmodified in the debug file as well.
+	Skip adjustment of discarded sections symbol table references when
+	that symbol table is copied in this way.
+
+	* elflint.c (check_symtab): Don't crash from missing symbol names
+	after diagnosing bogus strtab.
+
+	* strip.c (handle_elf): Cosmetic cleanup in special section contents
+	adjustment for symtab changes.
+
+2008-03-31  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_sections): Add checks on SHF_EXECINSTR sections:
+	must be SHT_PROGBITS, must not be SHF_WRITE.  Let backend hook
+	excuse a special section.
+
+2008-03-27  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_sections): Check that executability and writability
+	of sections is reflected in segment p_flags.
+
+2008-03-26  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_program_header): Accept PT_GNU_RELRO p_flags
+	that matches its PT_LOAD's p_flags &~ PF_W.  On sparc, PF_X really
+	is valid in RELRO.
+
+2008-02-29  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_attributes): Add a cast.
+	* elflint.c (check_attributes): Likewise.
+
+	* unaligned.h (add_8ubyte_unaligned): Cast PTR argument for parity
+	with [UNALIGNED_ACCESS_CLASS == BYTE_ORDER] definition.
+	(add_4ubyte_unaligned, add_2ubyte_unaligned): Likewise.
+
+2008-02-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_ld.c (elf_i386_count_relocations): Implement R_386_TLS_GD
+	when linked into executable.
+	(elf_i386_create_relocations): Likewise.
+
+2008-02-20  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_attributes): New function.
+	(process_elf_file): Call it under -A.
+
+	* elflint.c (check_attributes): Implement it for real.
+
+2008-02-19  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (special_sections): Handle .gnu.attributes section.
+	(check_sections): Likewise.
+	(check_attributes): New function.
+
+2008-02-10  Roland McGrath  <roland@redhat.com>
+
+	* elfcmp.c (main): Ignore sh_offset differences in non-SHF_ALLOC
+	sections and ET_REL files.
+
+2008-02-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32-i386.script: Add .eh_frame_hdr, .tdata, and .tbss sections.
+	* i386_ld.c (elf_i386_count_relocations): Handle R_386_TLS_LDO_32
+	and R_386_TLS_LE.
+	(elf_i386_create_relocations): Likewise.
+	* ld.h (struct ld_state): Add need_tls, tls_start, and tls_tcb
+	elements.
+	* ldgeneric.c (add_section): If TLS section is used, set need_tls flag.
+	(ld_generic_create_outfile): Add PT_TLS entry to program  header.
+	Fix generation of PT_GNU_STACK entry.
+
+2008-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c (replace_args): Prevent loop over replacements if the parameter
+	is only two characters long.
+
+	* ld.c: Recognize sha1 argument for --build-id parameter.
+	* ldgeneric.c (create_build_id_section): Handle sha1.
+	(compute_hash_sum): New function.  Broken out of compute_build_id.
+	Take hash function and context as parameters.
+	(compute_build_id): Use compute_hash_sum for md5 and the new sha1
+	implementation.
+
+2008-01-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* elf32-i386.script: Add .note.ABI-tag and .note.gnu.build-id sections.
+	* ld.c: Recognize --build-id command line parameter.
+	* ld.h: Define scn_dot_note_gnu_build_id.
+	(struct ld_state): Add build_id and buildidscnidx elements.
+	* ldgeneric.c: Implement --build-id command line parameter.
+	* ldlex.l (ID): Recognize - as valid character after the first one.
+
+2008-01-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c (replace_args): New function.
+	(main): Use it to rewrite old-style parameters.
+
+	* elf32-i386.script: Add .gnu.hash section.
+	* ldgeneric.c (optimal_bucket_size): A tiny bit more efficient.
+	(fillin_special_symbol): Initialize st_size.
+	(sortfct_hashval): New function.
+	(create_gnu_hash): New function.
+	(create_hash): New function.
+	(ld_generic_create_outfile): Use the new functions to create the
+	hash tables.
+
+	* elflint.c (check_gnu_hash): Fix index value printed in error message.
+
+2008-01-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_group): Check that signature symbol for section
+	group is not an empty string.
+	* ldgeneric.c: Remove magic assignment of indices in the dynsym
+	section.  Start implementation of --hash-style.
+	* i386_ld.c: Likewise.
+	* ld.c: Recognize --hash-style.
+	* ld.h (struct scninfo): Add comdat_group.
+	Add additional parameter to finalize_plt callback.
+
+2008-01-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.h (struct callbacks): Add initialize_gotplt.
+	(struct scnhead): Add scn_dot_gotplt.
+	(struct ld_state): Add gotpltscnidx.
+	* i386_ld.c (elf_i386_initialize_plt): Minor optimization.
+	(elf_i386_initialize_pltrel): Likewise.
+	(elf_i386_initialize_got): There is now a separate .got.plt, so
+	don't do the PLT-related work here.  Initialize d_type.
+	(elf_i386_initialize_gotplt): New function.
+	(elf_i386_plt0): Use ud2a after indirect jump.
+	(elf_i386_pic_plt0_entry): Likewise.
+	(elf_i386_finalize_plt): Reference now .got.plt.
+	(elf_i386_count_relocations): For GOT entries which need no relocation
+	don't bump nrel_got.
+	(elf_i386_create_relocations): Also get .got.plt.  Rewrite R-386_GOT32
+	handling for split .got/.got.plt.
+	(elf_i386_ld_init): Initialize callbacks.initialize_gotplt.
+	* elf32-i386.script: Sort sections for security.  There are no .got
+	input sections.  Add .got.plt.
+	* ldgeneric.c (ld_generic_generate_sections): Add .got.plt section.
+	(ld_generic_create_outfile): Initialize .got.plt section.
+	Use .got.plt address for _GLOBAL_OFFSET_TABLE_ symbol and DT_PLTGOT.
+
+2008-01-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_ld.c (elf_i386_count_relocations): PLT relocations for undefined
+	symbols are not carried over into statically linked output files.
+	Add dummy entries for more TLS relocations.
+
+	* ld.c (options): Add long names for -( and -).
+
+	* ldgeneric.c (check_definition): For newly found definitions don't
+	mark section as used if symbol is absolute.
+	(extract_from_archive): Only assign archive sequence number the first
+	time the archive is handled.  Update ld_state.last_archive_used
+	if any symbol was used.  Remove nround variable.
+	(file_process2): When using symbol from an archive, update
+	ld_state.group_start_archive, ld_state.archives, and
+	ld_state.tailarchives.
+	(ld_generic_file_process): If group is not handled anymore, after
+	freeing ELF handles for the archives, clear ld_state.archives and
+	*nextp.  Fix wrong logic in recognizing first iteration of group
+	loop.  When clearing flags, also clear ld_state.group_start_archive.
+
+2008-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* objdump.c (show_disasm): Adjust disassembler format string for
+	removal of %e.
+
+2008-01-04  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_core_items): Take new arg DESCSZ; if nonzero,
+	a size greater than the items cover means multiple sets of items.
+	(handle_core_note): Update caller.
+
+2008-01-04  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Move SHDRIDX defn to silence gcc warning.
+
+2008-01-03  Roland McGrath  <roland@redhat.com>
+
+	* ld.h (linked_from_dso_p): Use __attribute__ ((__gnu_inline__)).
+
+	* elflint.c (check_dynamic): Remove duplicate initializer.
+
+2008-01-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: Update copyright year.
+	* ar.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2007-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* objdump (show_disasm): Use %e after third parameter.
+
+2007-12-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c: Fix wrong parenthesis in a few branch predictions.
+	* strings.c: Likewise.
+
+2007-12-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (DEFS): Add DEBUGPRED.
+	* addr2line.c: Include debugpred.h.
+	* ar.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+	* debugpred.h: New file.
+
+	* readelf.c (handle_relocs_rel): Use elf_scnshndx.
+	(handle_relocs_rela): Likewise.
+
+	* readelf.c: Add lots of likely/unlikely.
+
+	* elflint.c: Minor cleanups.
+
+2007-11-19  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ops): Handle all bad op codes gracefully.
+	Print their numbers instead of just ???.
+
+2007-11-09  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (attr_callback): Handle DW_AT_data_location.
+	Handle block forms to mean a DWARF expression for DW_AT_allocated,
+	DW_AT_associated, DW_AT_bit_size, DW_AT_bit_offset, DW_AT_bit_stride,
+	DW_AT_byte_size, DW_AT_byte_stride, DW_AT_count, DW_AT_lower_bound,
+	DW_AT_upper_bound.
+
+2007-10-20  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (options): Update -R description.
+	(struct symbol): Put symbol details a union with a size_t pointer
+	`duplicate'.
+	(compare_symbols_output): Use null ->name as marker for discard
+	symbols, not zero *->map.
+	(copy_elided_sections): Record forwarding pointers for discarded
+	duplicates and fill SYMNDX_MAP elements through them.
+
+	* readelf.c (process_file): Set offline_next_address to 0 at start.
+	(struct process_dwflmod_args): New type.
+	(process_dwflmod): Take args in it, pass fd to process_elf_file.
+	(process_file): Update caller; dup FD for passing to libdwfl.
+	(process_elf_file): Take new arg FD.  For ET_REL file when
+	displaying data affected by libdwfl relocation, open a new Elf handle.
+
+2007-10-17  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_line_section): For invalid data inside a
+	unit with plausible length, keep printing at the next unit boundary.
+
+	* readelf.c (attr_callback): Use dwarf_formref_die, not dwarf_formref.
+
+2007-10-16  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (hex_dump): Fix rounding error in whitespace calculation.
+
+2007-10-15  Roland McGrath  <roland@redhat.com>
+
+	* make-debug-archive.in: New file.
+	* Makefile.am (EXTRA_DIST): Add it.
+	(make-debug-archive): New target.
+	(bin_SCRIPTS, CLEANFILES): Add it.
+
+2007-10-10  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (special_sections): Add new attrflag value exact_or_gnuld.
+	Use it to check MERGE|STRINGS for .debug_str.
+	(check_sections): Handle exact_or_gnuld.
+
+2007-10-08  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_core_item): Handle 'T'|0x80 to indicate
+	64-bit struct timeval with 32-bit tv_usec.
+
+2007-10-07  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (check_archive_index): New function.
+	(process_file): Call it.  Change signature to take only fd and name.
+	Use libdwfl to open the file, then iterate on its modules (multiple
+	for an archive) to print file name and call process_elf_file.
+	(main): Update caller.  Let process_file do elf_begin.
+	(count_dwflmod, process_dwflmod, find_no_debuginfo): New functions.
+	(process_elf_file): Take only Dwfl_Module * argument.
+	Don't print the file name here.
+	(print_debug_*_section): Take Dwfl_Module * argument.
+	(print_debug): Likewise.  Update caller.
+	(format_dwarf_addr): New function.
+	(print_debug_ranges_section): Use it.
+	(attr_callback): Likewise.
+	(print_debug_line_section, print_debug_loc_section): Likewise.
+
+	* readelf.c (print_debug_ranges_section): Translate all strings.
+	(print_debug_loc_section): Likewise.
+
+	* unstrip.c (copy_elided_sections): Initialize SEC.
+
+	* ar.c (do_oper_insert): Put trailing / on short names.
+
+	* arlib.h (MAX_AR_NAME_LEN): Decrease by one.
+
+	* arlib2.c (arlib_add_long_name): Adjust for header size.
+
+	* arlib.c (arlib_finalize): Pad long name table to keep size even.
+
+	* ar.c (do_oper_insert): Use write_retry for padding write.
+
+	* ar.c (do_oper_insert): Initialize CUR_OFF in no_old case.
+	Unconditionally set FOUND[CNT]->elf when setting ->mem.
+	(remember_long_name): New function.
+	(do_oper_insert): Call it.  Correctly use length of basename,
+	not original name.  Don't store long name twice for new member.
+
+2007-10-06  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_note): Skip empty segment.
+	(check_note_section): Skip empty section.
+
+	* unstrip.c (options, parse_opt, struct arg_info): Grok -R/--relocate.
+	(handle_output_dir_module, handle_implicit_modules): Pass it down.
+	(handle_dwfl_module): When set, use ET_REL already loaded by Dwfl.
+	(compare_alloc_sections): Take new arg REL, ignore address if true.
+	(compare_sections): Likewise, pass it down.
+	(compare_sections_rel, compare_sections_nonrel): New functions.
+	(find_alloc_sections_prelink, copy_elided_sections): Use them
+	instead of compare_sections.
+	(sections_match): New function, broken out of ...
+	(find_alloc_section): ... here.
+	(copy_elided_sections): Reorganize section match-up logic.
+	Use sections_match for SHF_ALLOC in ET_REL.
+	For ET_REL, let the nonzero sh_addr from the debug file dominate.
+
+	* unstrip.c (add_new_section_symbols): Take new arg REL.
+	When true, do not update section symbol values.
+	(collect_symbols): Likewise.  Update section symbols with address
+	of chosen output section, not original section.
+	(check_symtab_section_symbols, copy_elided_sections): Update callers.
+
+	* unstrip.c (compare_alloc_sections): At the same address, preserve
+	original section order.
+
+	* elflint.c (special_sections): Don't require MERGE|STRINGS for
+	.debug_str, it didn't always have them with older tools.
+
+	* elflint.c (check_symtab, check_one_reloc): Ignore sh_addr in ET_REL.
+
+2007-10-05  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_symtab): Allow SHN_UNDEF _GLOBAL_OFFSET_TABLE_ in
+	ET_REL file.
+
+	* elflint.c (check_symtab): For _GLOBAL_OFFSET_TABLE_, diagnose
+	SHN_UNDEF as "bad section".  Use shndx value in messages.
+
+	* elflint.c (special_sections): Add ".debug_str".  Decrement namelen
+	for ".debug" so it matches as a prefix.
+	(IS_KNOWN_SPECIAL): New macro.
+	(check_sections): Use it for ".plt" match.  Cite wrong SHT_NOBITS
+	type even under -d, for a .debug* or .shstrtab section.
+
+	* readelf.c (print_ops): Use hex for address operand.
+
+2007-10-04  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Initialize NDX_SECTION element for
+	.gnu_debuglink section to SHN_UNDEF.  Drop STT_SECTION symbols for
+	sections mapped to SHN_UNDEF.
+
+2007-10-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (dump_archive_index): Avoid warning about uninitialized
+	variable with older glibc versions.
+	Add some branch prediction.
+
+2007-10-04  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_archive_index): New variable.
+	(options, parse_opt): Accept -c/--archive-index to set it.
+	(dump_archive_index): New function.
+	(process_file): Take new arg WILL_PRINT_ARCHIVE_INDEX.
+	Call dump_archive_index on archives if set.
+	(main): Update caller.
+	(any_control_option): Give it file scope, moved out of ...
+	(parse_opt): ... here.
+
+2007-10-03  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (struct arg_info): Add `list' flag.
+	(options, parse_opt): Grok -n/--list to set it.
+	(list_module): New function.
+	(handle_implicit_modules): Call it under -n.
+
+	* elflint.c (check_note_section): New function.
+	(check_sections): Call it for SHT_NOTE.
+
+	* readelf.c (handle_notes): Use sections when available.
+
+	* elflint.c (check_note_data): New function, broken out of ...
+	(check_note): ... here.  Call it and elf_getdata_rawchunk.
+
+	* readelf.c (handle_auxv_note): Take offset as argument, not buffer.
+	Use elf_getdata_rawchunk and gelf_getauxv.
+	(handle_notes_data): New function, broken out of ...
+	(handle_notes): ... here.  Call it and elf_getdata_rawchunk.
+
+2007-10-01  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (hex_dump): Fix transposed subtraction generating spaces.
+
+	* readelf.c (hex_dump): Fix line header to be hex instead of decimal.
+
+2007-09-10  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (options): Give -p optional argument, alias --string-dump.
+	(string_sections, string_sections_tail): New static variables.
+	(parse_opt): Set them when -p has an argument.
+	(print_string_section): New function, broken out of ...
+	(print_strings): ... here.  Call it.
+	(dump_data_section): New function, broken out of ...
+	(dump_data): ... here.  Call it.
+	(for_each_section_argument): New function, broken out of ...
+	(dump_data): ... here.  Call it.
+	(dump_strings): New function.
+
+2007-08-31  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_strings): Typo fix.
+
+2007-08-23  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (printf_with_wrap): Function removed.
+	(REGISTER_WRAP_COLUMN): New macro.
+	(handle_core_register): Use print_core_item instead.
+	(struct register_info): New type.
+	(compare_registers, compare_register_sets): New functions.
+	(register_bitpos, compare_sets_by_info): New functions.
+	(handle_core_registers): Use those to segregate and sort registers
+	for display.
+
+	* readelf.c (ITEM_WRAP_COLUMN): New macro.
+	(print_core_item): New function.
+	(handle_core_item): Use it instead of printf_with_wrap.
+	(compare_core_items, compare_core_item_groups): New functions.
+	(handle_core_items): Use them.  Sort by group and force line breaks
+	between groups.
+
+	* readelf.c (handle_core_registers, handle_core_items): New functions,
+	broken out of ...
+	(handle_core_note): ... here.   Call them.
+
+2007-08-22  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (new_shstrtab): New function, broken out of ...
+	(copy_elided_sections): ... here.
+
+2007-08-20  Roland McGrath  <roland@redhat.com>
+
+	Avoid local function trampolines in nm binary.
+	* nm.c (sort_by_address): Move to a static function instead of local
+	inside show_symbols.
+	(sort_by_name_strtab): New static variable.
+	(sort_by_name): Use it.  Move to a static function instead of local
+	inside show_symbols.
+	(show_symbols): Set sort_by_name_strtab.
+
+2007-08-19  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_auxv_note): New function.
+	(handle_notes): Call it.
+
+	* readelf.c (printf_with_wrap, convert): New functions.
+	(handle_core_item, (handle_core_register): New functions.
+	(handle_notes): Call those with details from ebl_core_note.
+
+2007-08-12  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_note): Accept type 0 with name "Linux".
+
+	* elflint.c (special_sections): Accept SHF_ALLOC for ".note".
+
+	* elflint.c (section_flags_string): Return "none" for 0, not "".
+
+2007-08-11  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_note): Accept NT_GNU_HWCAP, NT_GNU_BUILD_ID.
+
+2007-08-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (hex_dump): Use isprint to determine whether to print
+	character itself or full stop character.
+	(dump_data): No need to check endp for NULL after strtol call.
+
+2007-08-03  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_string_sections): New variable.
+	(options, parse_opt): Handle --strings/-p to set it.
+	(print_strings): New function.
+	(process_elf_file): Call it under -p.
+
+	* readelf.c (options): Add hidden aliases --segments, --sections,
+	as taken by binutils readelf.
+
+2007-08-01  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (dump_data_sections, dump_data_sections_tail):
+	New variables.
+	(options, parse_opt): Handle --hex-dump/-x, set them.
+	(hex_dump): New function.
+	(dump_data): New function, call it.
+	(process_elf_file): Call it.
+
+2007-07-25  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (show_symbols): New variable.
+	(print_addrsym): New function.
+	(handle_address): Call it.
+	(options, parse_opt): Handle -S/--symbols.
+
+2007-06-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: Update for latest autoconf header.
+	* ar.c: Likewise.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* ldgeneric.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+	* unstrip.c: Likewise.
+
+2007-05-18  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Match up non-NOBITS sections with
+	stripped file, so as not to duplicate a section copied in both.
+
+	* strip.c (handle_elf): Keep SHT_NOTE section copies in the debug file.
+
+2007-05-17  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c (copy_elided_sections): Don't call gelf_newphdr for 0.
+
+	* unstrip.c (handle_file): Tweak BIAS != 0 warning.
+
+	* unstrip.c (handle_file): Take new arg CREATE_DIRS.  If set,
+	call make_directories here.
+	(handle_explicit_files): Take new arg CREATE_DIRS, pass it down.
+	(handle_dwfl_module): Likewise.
+	(handle_implicit_modules): Update callers.
+	(handle_output_dir_module): Likewise.  Don't do make_directories here.
+
+	* unstrip.c (get_section_name): New function, broken out of ...
+	(copy_elided_sections): here.  Update callers.
+	(find_alloc_section): Broken out of ...
+	(copy_elided_sections): ... here.  Update caller.
+	(symtab_count_leading_section_symbols): Take new arg NEWSYMDATA,
+	update STT_SECTION symbols' st_value fields as a side effect.
+	(check_symtab_section_symbols): Update caller.
+	(add_new_section_symbols): Set st_value in symbols added.
+	(collect_symbols): Reset S->value for STT_SECTION symbols recorded.
+	Take new arg SPLIT_BSS.  Adjust S->shndx recorded for symbols moved
+	from .bss to .dynbss.
+	(find_alloc_sections_prelink): New function.  Associate debug file
+	allocated SHT_NOBITS shdrs with stripped moved by prelink via
+	.gnu.prelink_undo information.
+	(copy_elided_sections): Call it when we couldn't find every allocated
+	section.  Don't use a debug file non-NOBITS section if SHF_ALLOC.
+	Take STRIPPED_EHDR arg instead of E_TYPE and PHNUM.
+	(handle_file): Update callers.
+
+	* unstrip.c (copy_elided_sections): Ignore unfound unallocated section
+	named ".comment".
+
+	* elflint.c (check_sections): Fix association of segments with
+	sections when p_memsz > p_filesz.
+
+2007-04-29  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (options, main): Tweak argp group settings to fix
+	usage output.
+
+2007-04-28  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Update debug file's SHT_NOBITS sections'
+	sizes to match sections adjusted in the stripped file.
+
+2007-04-24  Roland McGrath  <roland@redhat.com>
+
+	* elfcmp.c (OPT_HASH_INEXACT): New macro.
+	(hash_inexact): New variable.
+	(options, parse_opt): Add --hash-inexact option to set it.
+	(hash_content_equivalent): New function.
+	(main): Call it for differing SHT_HASH sections under --hash-inexact.
+
+2007-04-23  Roland McGrath  <roland@redhat.com>
+
+	* unstrip.c: New file.
+	* Makefile.am (bin_PROGRAMS): Add it.
+	(unstrip_LDADD): New variable.
+
+	* strip.c (options): Allow --output for -o.
+
+2007-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c: Remove unused code.  Add a few consts.
+
+2007-02-15  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug): Fix brainos in SHDR test.
+
+2007-02-05  Roland McGrath  <roland@redhat.com>
+
+	* ar.c: Include <limits.h>, since we use LONG_MAX.
+
+2007-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* ar.c: Add ugly hack to work around gcc complaining that we
+	ignore fchown's return value.
+	(do_oper_insert): Handle error when writing padding.
+	* ranlib.c: Add fchown complain work around.
+
+	* arlib.c: Make symtab a global variable.  Change all users.
+	* arlib2.c: Likewise.
+	* ranlib.c: Likewise.
+	* ar.c: Likewise.
+	* arlib.h: Declare it.
+
+2007-01-11  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_sections): Use ebl_machine_section_flag_check on
+	SHF_MASKPROC bits separately from generic sh_flags validation.
+
+2007-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* ar.c: New file.
+	* arlib.c: New file.
+	* arlib2.c: New file.
+	* arlib.h: New file.
+	* Makefile (noinst_LIBRARIES): Add libar.
+	(libar_a_SOURCES): Define.
+	(ar_LDADD): Define.
+	(CFLAGS_ar): Define.
+	* ranlib.c: Change to use arlib.
+
+	* elflint.c (check_symtab): Work around GNU ld bug which omits
+	sections but not symbols in those sections.
+
+2007-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: Update copyright year.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c:  Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+
+2006-12-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (compare_hash_gnu_hash): New function.  Report if the
+	two hash tables have different content (module expected omission
+	of undefined symbols).
+
+2006-10-31  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_program_header): Don't complain about
+	p_filesz > p_memsz if p_memsz is zero and p_type is PT_NOTE.
+
+2006-09-19  Jakub Jelinek  <jakub@redhat.com>
+
+	* strip.c (process_file): Disallow -f on archives.
+
+2006-10-09  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (libld_elf_i386.so): Use $(LINK), not $(CC).
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (MAINTAINERCLEANFILES): New variable.
+
+	* readelf.c (handle_relocs_rel): Typo fix, test DESTSHDR properly.
+	Reported by Christian Aichinger <Greek0@gmx.net>.
+
+	* elflint.c (valid_e_machine): Add EM_ALPHA.
+	Reported by Christian Aichinger <Greek0@gmx.net>.
+
+2006-08-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_dynamic): Don't require DT_HASH for DT_SYMTAB.
+	Keep track of which "high DT" entries are present.
+	Check that either old or GNU-style hash table is present.
+	If GNU-style hash table is used a symbol table is mandatory.
+	Check that if any prelink entry is present all of them are.
+	(check_gnu_hash): Only fail for undefined symbols in GNU-style hash
+	table if they don't refer to functions.
+
+2006-07-17  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (struct version_namelist): Use GElf_Versym for `ndx' field.
+	(add_version): Likewise for argument.
+	(check_versym): Cast constant to GElf_Versym for comparison.
+
+2006-07-12  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (handle_gnu_hash): Add casts for machines where
+	Elf32_Word != unsigned int.
+
+2006-07-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_sysv_hash64): Fix printf format.
+
+2006-07-11  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (options): English fix in -f doc string.
+
+	* addr2line.c (use_comp_dir): New variable.
+	(options, parse_opt): Grok -A/--absolute to set it.
+	(handle_address): If set, prepend dwfl_line_comp_dir results to
+	relative file names.
+
+2006-07-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c: Adjust for latest new hash table format.
+	* readelf.c: Likewise.
+
+	* elflint.c (check_versym): Ignore hidden bit when comparing version
+	numbers.
+
+2006-07-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldgeneric.c (ld_generic_create_outfile): Correctly recognize
+	discarded COMDAT symbols.
+
+	* i386_ld.c (elf_i386_count_relocations): Lot of corrections.
+	(elf_i386_create_relocations): Likewise.
+	* ld.h (struct symbol): Add local and hidden bits.
+	* ld.c (create_special_section_symbol): These synthsized symbols
+	are local and hidden.
+	* ldgeneric.c (file_process2): Check whether input file matches
+	the emulation.
+	(fillin_special_symbol): Create symbols as local and/or hidden
+	if requested.
+	(ld_generic_create_outfile): Make local copy of symbol.
+	Don't hide global, defined symbols in dynamic symbol table unless
+	requested.  Synthetic symbols have no version information.
+
+	* elflint.c: Add support for checking 64-bit SysV-style hash tables.
+	* readelf.c: Add support for printing 64-bit SysV-style hash tables.
+
+2006-07-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (is_rel_dyn): Fix and extend DT_RELCOUNT/DT_RELACOUNT
+	testing.
+
+2006-07-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c: Add testing of DT_GNU_HASH.
+	* readelf.c: Implement showing histogram for DT_GNU_HASH section.
+
+	* Makefile.am: Add hacks to create dependency files for non-generic
+	linker.
+
+2006-06-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldgeneric.c (ld_generic_generate_sections): Don't create .interp
+	section if creating a DSO and no interpreter is given.
+	(ld_generic_create_outfile): Don't store reference to symbols in
+	discarded COMDAT groups.  Don't create PHDR and INTERP program header
+	for DSO if no interpreter is specified.
+	(create_verneed_data): Pretty printing.
+
+	* ldscript.y (content): If a DSO is created don't set default
+	interpreter from linker script.
+
+	* i386_ld.c (elf_i386_count_relocations): Do not add relocations
+	for symbols in discarded COMDAT groups.
+	(elf_i386_create_relocations): Likewise.
+	* ld.h (struct scninfo): Add unused_comdat.
+	* ldgeneric.c (add_section): Also check group signature when
+	matching COMDAT sections.
+	(add_relocatable_file): Ignore symbols in COMDAT group which are
+	discarded.
+
+	* elflint.c (check_one_reloc): For *_NONE relocs only check type
+	and symbol reference.
+
+2006-06-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_dynamic): Fix checking value of tags which are
+	offsets in the string section.  Make sure DT_STRTAB points to the
+	section referenced in sh_link.
+
+	* ld.c (options): Add headers.  Add short option 'R' for '--rpath'.
+
+	* ld.c: Recognize --eh-frame-hdr option.
+	* ld.h (struct ld_state): Add eh_frame_hdr field.
+	* ldgeneric.c (struct unw_eh_frame_hdr): Define.
+
+	* ldgeneric.c (add_section): Use ebl_sh_flags_combine instead of
+	SH_FLAGS_COMBINE.
+	(add_relocatable_file): Minor optimization of last change.
+	(match_section): Don't preserve SHF_GROUP flag any longer.
+
+2006-06-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c (parse_z_option): Recognize execstack and noexecstack.
+	Handle record and ignore as position dependent options.
+	(parse_z_option_2): Handle ignore and record here.
+	* ld.h (struct ld_state): Add execstack field.
+	* ldgeneric.c (add_relocatable_file): Recognize .note.GNU-stack
+	sections.
+	(ld_generic_create_outfile): Fix program header creation in native
+	linker.  Add PT_GNU_STACK program header.
+
+2006-06-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_ld.c (elf_i386_finalize_plt): Don't change symbol table entries
+	for PLT entries if there is no local definition.
+
+	* ld.c (parse_option): Handle -z ignore like --as-needed and
+	-z record like --no-as-needed.
+	* ld.h (struct ld_state): Remove ignore_unused_dsos field.
+	* ldgeneric.c (new_generated_scn): Always compute ndt_needed by
+	looping over DSOs.  When deciding about adding DT_NEEDED entries
+	use ->as_needed instead of ignore_unused_dsos.
+
+2006-05-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c: Recognize --as-needed and --no-as-needed options.
+	* ld.h (struct usedfile): Add as_needed field.
+	(struct ld_state): Likewise.
+	* ldgeneric.c (ld_handle_filename_list): Copy as_needed flag from
+	the list.
+	* ldscript.y (filename_id_list): Split to correctly parse all
+	combinations.
+	(mark_as_needed): Fix loop.
+
+2006-05-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c (print_dwarf_function): Use unsigned type for lineno
+	and colno.
+
+2006-05-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (handle_relocs_rela): Better notations for addon value.
+	(print_ehdr): Distinguish e_ident[EI_VERSION] from e_version.
+
+2006-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: Update copyright year.
+	* elfcmp.c: Likewise.
+	* elflint.c: Likewise.
+	* findtextrel.c: Likewise.
+	* ld.c: Likewise.
+	* nm.c: Likewise.
+	* objdump.c: Likewise.
+	* ranlib.c: Likewise.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strings.c: Likewise.
+	* strip.c: Likewise.
+
+2006-03-09  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (AM_LDFLAGS): New variable.
+
+2006-03-01  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (dwarf_tag_string, dwarf_attr_string): Update name tables
+	for dwarf.h changes matching 3.0 spec.
+	(dwarf_encoding_string, dwarf_lang_string, print_ops): Likewise.
+
+2005-12-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_one_reloc): If relocation section is not loaded,
+	don't check whether the relocations modify read-only sections or
+	loaded and unloaded sections.
+
+2005-11-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_one_reloc): Take additional parameters.  Use
+	them to determine whether relocation is valid in this type of
+	file.  DSOs and executables can contain relocation sections in
+	unloaded sections which just show the relocations the linker
+	applied.  Adjust all callers.
+	(check_program_header): Check that PT_PHDR is loaded and that offset
+	matches the one in the ELF header.
+
+2005-10-26  Roland McGrath  <roland@redhat.com>
+
+	* nm.c (get_var_range): dwarf_getloclist -> dwarf_getlocation.
+
+2005-09-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c (handle_elf): Unify some error messages.
+	* ld.c (main): Likewise.
+	* ldgeneric.c (open_elf): Likewise.
+	* elfcmp.c (main): Likewise.
+	* elflint.c (check_elf_header): Likewise.
+
+	* size.c (process_file): Fix typo in error message.
+
+	* readelf.c: Lots of little cleanups.  Use _unlocked functions.
+
+2005-09-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* strings.c (main): Reset elfmap variable after munmap call.
+	[_MUDFLAP] (map_file): Simplify mudflap debugging by not using mmap.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* ranlib.c: Don't define pread_retry and write_retry here.
+
+	* Makefile.an [BUILD_STATIC] (libdw): Add -ldl.
+	(CLEANFILES): Add *.gcno *.gcda *.gconv.
+
+	* strings.c (process_chunk): Reorder expressions in conditional
+	(process_chunk_mb): Likewise.
+
+	* strings.c: New file.
+	* Makefile.am (bin_PROGRAMS): Add strings.
+	(strings_no_Wstring): Define.
+	(strings_LDADD): Define.
+
+2005-08-27  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (dwarf_diename_integrate): Function removed.
+	(print_dwarf_function): Use plain dwarf_diename.
+
+2005-08-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_versym): Versioned symbols should not have
+	local binding.
+
+2005-08-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_versym): Allow VER_NDX_LOCAL symbols to be
+	undefined.
+
+	* Makefile.am: Add rules to build ranlib.
+	* ranlib.c: New file.
+
+2005-08-14  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_sections): Use ebl_section_type_name and allow any
+	sh_type it recognizes.
+
+	* elflint.c (check_sections): Print unknown flags in hex, don't
+	truncate high bits.  Print section number and name for unknown type.
+
+2005-08-13  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_program_header): Use ebl_segment_type_name and
+	allow any p_type it recognizes.  Include p_type value in error
+	message for unknown type.
+
+2005-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_symtab): Simplify last change a bit.  Pass ehdr
+	to ebl_check_special_symbol.
+	(check_sections): Pass ehdr to ebl_bss_plt_p.
+
+2005-08-12  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (check_symtab): Check that _GLOBAL_OFFSET_TABLE_ st_shndx
+	refers to the right section if it's not SHN_ABS.
+	Let ebl_check_special_symbol override _G_O_T_ value and size checks.
+
+	* elflint.c (check_sections): Don't complain about a non-NOBITS
+	section taking no segment space, if it's sh_size is 0.
+
+	* elflint.c (check_sections): Use ebl_bss_plt_p to see if .plt should
+	be PROGBITS or NOBITS.
+
+	* elflint.c (check_symtab): Use ebl_check_special_symbol to override
+	standard st_value and st_size checks.
+
+2005-07-28  Roland McGrath  <roland@redhat.com>
+
+	* addr2line.c (options, parse_opt): Don't handle -e here.
+	(executable): Variable removed.
+	(argp_children): New static variable.
+	(argp): Use it.  Make const.
+	(main): Fill in argp_children from dwfl_standard_argp ().
+	Let libdwfl handle file selection, pass Dwfl handle to handle_address.
+	(print_dwarf_function): New function.  Try to figure out inline chain.
+	(elf_getname): Function removed, libdwfl does it for us.
+	(handle_address): Take Dwfl handle instead of Elf, Dwarf handles.
+	Use dwfl_module_addrname instead of elf_getname.
+	Use dwfl_module_getsrc and dwfl_lineinfo instead of libdw calls.
+	* Makefile.am (INCLUDES): Add libdwfl directory to path.
+
+2005-08-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c (parse_opt): STATE parameter is now used.
+	Various little cleanups.
+
+	* readelf.c (print_debug_line_section): Correct fallout of renaming
+	of DW_LNS_set_epilog_begin.
+
+2005-08-08  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (options, parse_opt): Grok -R .comment for compatibility
+	with binutils strip.  Likewise -d, -S, as aliases for -g.
+	Likewise ignore -s/--strip-all.
+
+2005-08-07  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (process_file): Open read-only when using a different output
+	file.
+
+2005-08-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (in_nobits_scn): New function.
+	(check_versym): Allow references for defined symbols against versions
+	of other DSOs also for symbols in nobits sections.
+	Move a few variables around.
+
+	* Makefile.am (AM_CFLAGS): Avoid duplication.
+	Link with statis libs if BUILD_STATIC.
+
+2005-08-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c: Many, many more tests.  Mostly related to symbol
+	versioning.  Those sections should now be completely checked.
+
+	* readelf.c (print_dynamic): Use gelf_offscn.
+
+2005-08-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c: Add lots more tests: more extension symbol table sanity,
+	versioning section tests, hash table tests.  General cleanup.
+
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* objdump.c: New file.
+	* Makefile.am (bin_PROGRAMS): Add objdump.
+	(objdump_LDADD): Define.
+
+	* elflint.c (check_reloc_shdr): New function split out from check_rela
+	and check_rel.
+	(check_one_reloc): New function.  Likewise.
+	(check_rela): Use check_reloc_shdr and check_one_reloc.
+	(check_rel): Likewise.
+	(check_program_header): Check that PT_DYNAMIC entry matches .dynamic
+	section.
+	Add checks that relocations against read-only segments are flagged,
+	that the text relocation flag is not set unnecessarily, and that
+	relocations in one section are either against loaded or not-loaded
+	segments.
+
+2005-08-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfcmp.c (main): Ignore section count and section name string table
+	section index.
+
+2005-07-27  Roland McGrath  <roland@redhat.com>
+
+	* elfcmp.c: Include <locale.h>.
+
+2005-07-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfcmp.c: Print name and index of differing section.
+
+2005-07-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfcmp.c: Implement comparing gaps between sections.
+
+2005-07-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c: Include libeblP.h instead of libebl.h.
+	* nm.c: Likewise.
+	* readelf.c: Likewise.
+	* elfcmp.c: Likewise.
+
+	* elfcmp.c (main): Compare individual ELF header fields, excluding
+	e_shoff instead of the whole struct at once.
+	Use ebl_section_strip_p instead of SECTION_STRIP_P.
+	* strip.c: Use ebl_section_strip_p instead of SECTION_STRIP_P.
+
+2005-07-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfcmp.c (main): Take empty section into account when comparing
+	section content.
+
+	* elflint.c (check_dynamic): Check that d_tag value is >= 0 before
+	using it.
+
+2005-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* elfcmp.c: New file.
+	* Makefile.am (bin_PROGRAMS): Add elfcmp.
+	(elfcmp_LDADD): Define.
+
+	* elflint.c (check_rela): Check that copy relocations only reference
+	object symbols or symbols with unknown type.
+	(check_rel): Likewise.
+
+2005-06-08  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_ops): Add consts.
+
+2005-05-31  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_abbrev_section): Don't bail after first CU's
+	abbreviations.  Print a header line before each CU section.
+
+	* readelf.c (print_debug_loc_section): Fix indentation for larger
+	address size.
+
+2005-05-30  Roland McGrath  <roland@redhat.com>
+
+	* readelf.c (print_debug_line_section): Print section offset of each
+	CU's table, so they are easy to find from seeing the stmt_list value.
+
+	* readelf.c (dwarf_attr_string): Add all attributes in <dwarf.h>.
+	(attr_callback): Grok DW_AT_ranges and print offset in hex.
+
+	* readelf.c (attr_callback): Add 2 to addrsize * 2 for %#0* format.
+	(print_debug_ranges_section, print_debug_loc_section): Likewise.
+
+	* readelf.c (print_ops): Take different args for indentation control.
+	(attr_callback): Caller updated.
+	Grok several more block-form attributes as being location expressions.
+	For those same attributes with udata forms, format output differently
+	for location list offset.
+	(print_debug_loc_section): Implement it for real.
+
+	* readelf.c (options): Mention ranges for --debug-dump.
+	(enum section_e): Add section_ranges.
+	(parse_opt): Grok "ranges" for -w/--debug-dump.
+	(print_debug_ranges_section): New function.
+	(print_debug): Handle .debug_ranges section.
+
+2005-05-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (handle_notes): At least x86-64 need not have the note
+	section values aligned to 8 bytes.
+
+2005-05-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (dwarf_tag_string): Add new tags.
+
+2005-05-08  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Don't translate hash and versym data formats,
+	elf_getdata already did it for us.
+
+2005-05-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (findtextrel_LDADD): Add $(libmudflap).
+	(addr2line_LDADD): Likewise.
+
+2005-05-03  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (handle_elf): Apply symbol table fixups to discarded
+	relocation sections when they are being saved in the debug file.
+
+	* strip.c (handle_elf): Pass EHDR->e_ident[EI_DATA] to gelf_xlatetom
+	and gelf_xlatetof, not the native byte order.
+
+	* strip.c (parse_opt): Give error if -f or -o is repeated.
+	(main): Exit if argp_parse returns nonzero.
+
+	* strip.c (debug_fname_embed): New variable.
+	(options, parse_opt): New option -F to set it.
+
+2005-05-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (parse_opt): Make any_control_option variable
+	local.  Simplify some tests.
+
+2005-05-03  Roland McGrath  <roland@redhat.com>
+
+	* strip.c (crc32_file): Function removed (now in ../lib).
+
+2005-05-03  Roland McGrath  <roland@redhat.com>
+
+	* elflint.c (is_debuginfo): New variable.
+	(options, parse_opt): New option --debuginfo/-d to set it.
+	(check_sections): If is_debuginfo, don't complain about SHT_NOBITS.
+	(check_note): If is_debuginfo, don't try to get note contents.
+
+2005-04-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_debug_abbrev_section): Don't print error when end of
+	section reached.
+
+2005-04-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (dwarf_encoding_string): New function.
+	(dwarf_inline_string): New function.
+	(dwarf_access_string): New function.
+	(dwarf_visibility_string): New function.
+	(dwarf_virtuality_string): New function.
+	(dwarf_identifier_case_string): New function.
+	(dwarf_calling_convention_string): New function.
+	(dwarf_ordering_string): New function.
+	(dwarf_discr_list_string): New function.
+	(attr_callback): Decode man more attribute values.
+
+2005-04-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: Finish implementation of -f option.
+
+2005-03-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* addr2line.c: New file.
+	* Makefile.am (bin_PROGRAMS): Add addr2line.
+	Define addr2line_LDADD.
+
+	* findtextrel.c: Use new dwarf_addrdie function.
+
+	* findtextrel.c: Fix usage message and re-add accidentally removed
+	line.
+
+2005-03-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* findtextrel.c: New file.
+	* Makefile: Add rules to build findtextrel.
+
+2005-02-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldlex.l: Provide ECHO definition to avoid warning.
+
+	* elflint.c (check_program_header): Fix typo in RELRO test.
+
+	* Makefile.am (AM_CFLAGS): Add more warning options.
+	* elflint.c: Fix warnings introduced by the new warning options.
+	* i386_ld.c: Likewise.
+	* ld.c: Likewise.
+	* ld.h: Likewise.
+	* ldgeneric.c: Likewise.
+	* nm.c: Likewise.
+	* readelf.c: Likewise.
+	* sectionhash.c: Likewise.
+	* size.c: Likewise.
+	* string.c: Likewise.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Check for text relocations in constructed DSOs.
+
+	* Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fmudflap.  Link all apps
+	with -lmudflap.
+
+	* ldscript.y: Add as_needed handling.
+	* ldlex.l: Recognize AS_NEEDED token.
+	* ld.h (struct filename_list): Add as_needed flag.
+
+2005-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* elflint.c (check_symtab): Correctly determine size of GOT section.
+
+2005-01-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c: Remove unnecessary more_help function.  Print bug report
+	address using argp.
+	* strip.c: Likewise.
+	* size.c: Likewise.
+	* nm.c: Likewise.
+	* readelf.c: Likewise.
+	* elflint.c: Likewise.
+
+	* elflint.c (main): Don't check for parameter problems here.
+	(parse_opt): Do it here, where we get informed about some of them
+	anyway.
+
+	* readelf.c (main): Don't check for parameter problems here.
+	(parse_opt): Do it here, where we get informed about some of them
+	anyway.
+
+2005-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c: Update copyright year.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* nm.c: Likewise.
+	* ld.c: Likewise.
+	* elflint.c: Likewise.
+
+	* elflint.c (check_symtab): Don't warn about wrong size for
+	_DYNAMIC and __GLOBAL_OFFSET_TABLE__ for --gnu-ld.
+
+2004-10-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_phdr): In section mapping, also indicate
+	sections in read-only segments.
+
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c: Make compile with gcc 4.0.
+	* strip.c: Likewise.
+
+2004-08-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c (handle_elf): Rewrite dynamic memory handling to use of
+	allocate to work around gcc 3.4 bug.
+
+2004-01-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldlex.l (invalid_char): Better error message.
+
+2004-01-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c: Print SHT_GNU_LIBLIST sections.
+
+	* none_ld.c: New file.
+
+2004-01-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Enable building of machine specific linker.
+
+2004-01-20  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+	* i386_ld.c: Fix warnings gcc 3.4 spits out.
+	* ldgeneric.c: Likewise.
+	* ldscript.y: Likewise.
+	* readelf.c: Likewise.
+	* strip.c: Likewise.
+
+	* readelf.c (print_debug_line_section): Determine address size
+	correctly.
+
+2004-01-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_phdr): Show which sections are covered by the
+	PT_GNU_RELRO entry.
+
+	* elflint.c (check_program_header): Check PT_GNU_RELRO entry.
+
+	* readelf.c (print_debug_macinfo_section): Implement.
+
+2004-01-18  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_debug_line_section): Implement.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* src/elflint.c: Use PACKAGE_NAME instead of PACKAGE.
+	* src/ld.c: Likewise.
+	* src/nm.c: Likewise.
+	* src/readelf.c: Likewise.
+	* src/size.c: Likewise.
+	* src/strip.c: Likewise.
+
+	* strip.c: Add a few more unlikely.  Reduce scope of some variables.
+
+	* Makefile.am: Support building with mudflap.
+
+2004-01-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_debug_info_section): Free dies memory.
+
+	* readelf.c: Print .debug_info section content.
+
+2004-01-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_shdr): Add support for SHF_ORDERED and SHF_EXCLUDE.
+
+2004-01-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (print_debug_aranges): Implement using libdw.
+
+2004-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* nm.c: Adjust for Dwarf_Files type and dwarf_lineno interface change.
+
+	* readelf.c: Use libdw instead of libdwarf.  Not all of the old
+	behavior is available yet.
+	* Makefile.am: Link readelf with libdw.  Remove libdwarf include path.
+
+2004-01-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* nm.c (get_local_names): Adjust call to dwarf_nextcu.
+
+	* nm.c: Implement getting information about local variables.
+
+2004-01-07  Ulrich Drepper  <drepper@redhat.com>
+
+	* nm.c: Read also debug information for local symbols.
+
+2004-01-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* nm.c: Shuffle dwarf handling code around so the maximum column
+	width can be computed ahead of printing.  Avoid collection symbols
+	which are not printed anyway.
+
+	* nm.c: Rewrite dwarf handling to use libdw.
+	* Makefile.am (AM_CFLAGS): Add -std parameter.
+	(INCLUDES): Find header in libdw subdir.
+	(nm_LDADD): Replace libdwarf with libdw.
+
+	* elflint.c: Update copyright year.
+	* readelf.c: Likewise.
+	* size.c: Likewise.
+	* strip.c: Likewise.
+	* nm.c: Likewise.
+
+2003-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c (process_file): Close file before returning.
+
+2003-11-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (handle_dynamic): Make column for tag name wider.
+
+2003-09-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* readelf.c (handle_dynamic): Always terminate tag name with a space.
+
+2003-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* strip.c (process_file): Don't mmap the input file, we modify the
+	data structures and don't want the change end up on disk.
+
+2003-09-23  Jakub Jelinek  <jakub@redhat.com>
+
+	* unaligned.h (union u_2ubyte_unaligned,
+	union u_4ubyte_unaligned, union u_8ubyte_unaligned): Add
+	packed attribute.
+	(add_2ubyte_unaligned, add_4ubyte_unaligned,
+	add_8ubyte_unaligned): Avoid nesting bswap_NN macros.
+	Read/store value through _ptr->u instead of *_ptr.
+
+2003-09-22  Ulrich Drepper  <drepper@redhat.com>
+
+	* size.c (show_sysv): Change type of maxlen to int.
+
+	* strip.c (handle_elf): Handle the 64-bit archs which is 64-bit
+	buckets.
+
+	* i386_ld.c: Many many fixes and extensions.
+	* ld.c: Likewise.
+	* ldgeneric.c: Likewise.
+
+2003-08-16  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldgeneric.c (check_definition): Don't add symbol on dso_list if
+	the reference is from another DSO.
+
+2003-08-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* ldgeneric.c (find_entry_point): It is no fatal error if no entry
+	point is found when creating a DSO.
+
+2003-08-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* ld.c (main): Always call FLAG_UNRESOLVED.
+	* ldgeneric.c (ld_generic_flag_unresolved): Only complain about
+	undefined symbols if not creating DSO or ld_state.nodefs is not set.
+
+2003-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in: Depend on libebl.a, not libebl.so.
+
+	* ld.c (main): Mark stream for linker script as locked by caller.
+	(read_version_script): Likewise.
+	* ldlex.c: Define fread and fwrite to _unlocked variant.
+
+	* i386_ld.c (elf_i386_finalize_plt): Replace #ifdefs with uses of
+	target_bswap_32.
+	* unaligned.h: Define target_bswap_16, target_bswap_32, and
+	target_bswap_64.
+	(store_2ubyte_unaligned, store_4ubyte_unaligned,
+	store_8ubyte_unaligned): Define using new macros.
+
+2003-08-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* i386_ld.c (elf_i386_finalize_plt): Use packed structs to access
+	possibly unaligned memory.  Support use of big endian machines.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..1d592d4
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,126 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 1996-2014, 2016 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+DEFS += $(YYDEBUG) -DDEBUGPRED=@DEBUGPRED@ \
+	-DSRCDIR=\"$(shell cd $(srcdir);pwd)\" -DOBJDIR=\"$(shell pwd)\"
+AM_CPPFLAGS += -I$(srcdir)/../libelf -I$(srcdir)/../libebl \
+	    -I$(srcdir)/../libdw -I$(srcdir)/../libdwelf \
+	    -I$(srcdir)/../libdwfl -I$(srcdir)/../libasm -I../debuginfod
+
+AM_LDFLAGS = -Wl,-rpath-link,../libelf:../libdw $(STACK_USAGE_NO_ERROR)
+
+bin_PROGRAMS = readelf nm size strip elflint findtextrel addr2line \
+	       elfcmp objdump ranlib strings ar unstrip stack elfcompress \
+	       elfclassify srcfiles
+
+noinst_LIBRARIES = libar.a
+
+libar_a_SOURCES = arlib.c arlib2.c arlib-argp.c
+
+EXTRA_DIST = arlib.h debugpred.h
+
+bin_SCRIPTS = make-debug-archive
+EXTRA_DIST += make-debug-archive.in
+CLEANFILES += make-debug-archive
+
+if BUILD_STATIC
+libasm = ../libasm/libasm.a
+libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) -ldl -lpthread
+libelf = ../libelf/libelf.a -lz $(zstd_LIBS)
+if LIBDEBUGINFOD
+libdebuginfod = ../debuginfod/libdebuginfod.a -lpthread $(libcurl_LIBS)
+else
+libdebuginfod =
+endif
+else
+libasm = ../libasm/libasm.so
+libdw = ../libdw/libdw.so
+libelf = ../libelf/libelf.so
+if LIBDEBUGINFOD
+libdebuginfod = ../debuginfod/libdebuginfod.so
+else
+libdebuginfod =
+endif
+endif
+libebl = ../libebl/libebl.a ../backends/libebl_backends.a ../libcpu/libcpu.a
+libeu = ../lib/libeu.a
+
+if DEMANGLE
+demanglelib = -lstdc++
+endif
+
+# Bad, bad stack usage...
+readelf_no_Wstack_usage = yes
+nm_no_Wstack_usage = yes
+size_no_Wstack_usage = yes
+strip_no_Wstack_usage = yes
+elflint_no_Wstack_usage = yes
+elfcmp_no_Wstack_usage = yes
+objdump_no_Wstack_usage = yes
+ranlib_no_Wstack_usage = yes
+ar_no_Wstack_usage = yes
+unstrip_no_Wstack_usage = yes
+
+readelf_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD)
+nm_LDADD = $(libdw) $(libebl) $(libelf) $(libeu) $(argp_LDADD) $(obstack_LIBS) \
+	   $(demanglelib)
+size_LDADD = $(libelf) $(libeu) $(argp_LDADD)
+strip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
+elflint_LDADD  = $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)
+findtextrel_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD)
+addr2line_LDADD = $(libdw) $(libelf) $(libeu) $(argp_LDADD) $(demanglelib)
+elfcmp_LDADD = $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)
+objdump_LDADD  = $(libasm) $(libebl) $(libdw) $(libelf) $(libeu) $(argp_LDADD)
+ranlib_LDADD = libar.a $(libelf) $(libeu) $(argp_LDADD) $(obstack_LIBS)
+strings_LDADD = $(libelf) $(libeu) $(argp_LDADD)
+ar_LDADD = libar.a $(libelf) $(libeu) $(argp_LDADD) $(obstack_LIBS)
+unstrip_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
+stack_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD) $(demanglelib)
+elfcompress_LDADD = $(libebl) $(libelf) $(libdw) $(libeu) $(argp_LDADD)
+elfclassify_LDADD = $(libelf) $(libdw) $(libeu) $(argp_LDADD)
+srcfiles_SOURCES = srcfiles.cxx
+srcfiles_LDADD = $(libdw) $(libelf) $(libeu)  $(argp_LDADD) $(libarchive_LIBS) $(libdebuginfod)
+
+installcheck-binPROGRAMS: $(bin_PROGRAMS)
+	bad=0; pid=$$$$; list="$(bin_PROGRAMS)"; for p in $$list; do \
+	  case ' $(AM_INSTALLCHECK_STD_OPTIONS_EXEMPT) ' in \
+	   *" $$p "* | *" $(srcdir)/$$p "*) continue;; \
+	  esac; \
+	  f=`echo "$$p" | \
+	     sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+	  for opt in --help --version; do \
+	    if LD_LIBRARY_PATH=$(DESTDIR)$(libdir) \
+	       $(DESTDIR)$(bindir)/$$f $$opt > c$${pid}_.out 2> c$${pid}_.err \
+		 && test -n "`cat c$${pid}_.out`" \
+		 && test -z "`cat c$${pid}_.err`"; then :; \
+	    else echo "$$f does not support $$opt" 1>&2; bad=1; fi; \
+	  done; \
+	done; rm -f c$${pid}_.???; exit $$bad
+
+CLEANFILES += *.gconv
+
+make-debug-archive: $(srcdir)/make-debug-archive.in
+	$(AM_V_GEN)UNSTRIP=$(bindir)/`echo unstrip | sed '$(transform)'`; \
+	AR=$(bindir)/`echo ar | sed '$(transform)'`; \
+	sed -e "s,[@]UNSTRIP[@],$$UNSTRIP,g" -e "s,[@]AR[@],$$AR,g" \
+	    -e "s%[@]PACKAGE_NAME[@]%$(PACKAGE_NAME)%g" \
+	    -e "s%[@]PACKAGE_VERSION[@]%$(PACKAGE_VERSION)%g" \
+	    $(srcdir)/make-debug-archive.in > $@.new
+	$(AM_V_at)chmod +x $@.new
+	$(AM_V_at)mv -f $@.new $@
diff --git a/src/addr2line.c b/src/addr2line.c
new file mode 100644
index 0000000..d87e5b4
--- /dev/null
+++ b/src/addr2line.c
@@ -0,0 +1,829 @@
+/* Locate source files and line information for given addresses
+   Copyright (C) 2005-2010, 2012, 2013, 2015 Red Hat, Inc.
+   Copyright (C) 2022, 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libdwfl.h>
+#include <dwarf.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <system.h>
+#include <printversion.h>
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Values for the parameters which have no short form.  */
+#define OPT_DEMANGLER 0x100
+#define OPT_PRETTY    0x101  /* 'p' is already used to select the process.  */
+#define OPT_RELATIVE  0x102  /* 'r' is something else in binutils addr2line.  */
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Input format options:"), 2 },
+  { "section", 'j', "NAME", 0,
+    N_("Treat addresses as offsets relative to NAME section."), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output format options:"), 3 },
+  { "addresses", 'a', NULL, 0, N_("Print address before each entry"), 0 },
+  { "basenames", 's', NULL, 0, N_("Show only base names of source files"), 0 },
+  { "absolute", 'A', NULL, 0,
+    N_("Show absolute file names using compilation directory (default)"), 0 },
+  { "functions", 'f', NULL, 0, N_("Also show function names"), 0 },
+  { "symbols", 'S', NULL, 0, N_("Also show symbol or section names"), 0 },
+  { "symbols-sections", 'x', NULL, 0, N_("Also show symbol and the section names"), 0 },
+  { "flags", 'F', NULL, 0, N_("Also show line table flags"), 0 },
+  { "inlines", 'i', NULL, 0,
+    N_("Show all source locations that caused inline expansion of subroutines at the address."),
+    0 },
+  { "demangle", OPT_DEMANGLER, "ARG", OPTION_ARG_OPTIONAL,
+    N_("Show demangled symbols (ARG is always ignored)"), 0 },
+  { NULL, 'C', NULL, 0, N_("Show demangled symbols"), 0 },
+  { "pretty-print", OPT_PRETTY, NULL, 0,
+    N_("Print all information on one line, and indent inlines"), 0 },
+  { "relative", OPT_RELATIVE, NULL, 0,
+    N_("Show relative file names without compilation directory"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
+  /* Unsupported options.  */
+  { "target", 'b', "ARG", OPTION_HIDDEN, NULL, 0 },
+  { "demangler", OPT_DEMANGLER, "ARG", OPTION_HIDDEN, NULL, 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Locate source files and line information for ADDRs (in a.out by default).");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[ADDR...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+static struct argp_child argp_children[2]; /* [0] is set in main.  */
+
+/* Data structure to communicate with argp functions.  */
+static const struct argp argp =
+{
+  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
+};
+
+
+/* Handle ADDR.  */
+static int handle_address (const char *addr, Dwfl *dwfl);
+
+/* True when we should print the address for each entry.  */
+static bool print_addresses;
+
+/* True if only base names of files should be shown.  */
+static bool only_basenames;
+
+/* True if absolute file names based on DW_AT_comp_dir should be shown.  */
+static bool use_comp_dir = true;
+
+/* True if line flags should be shown.  */
+static bool show_flags;
+
+/* True if function names should be shown.  */
+static bool show_functions;
+
+/* True if ELF symbol or section info should be shown.  */
+static bool show_symbols;
+
+/* True if section associated with a symbol address should be shown.  */
+static bool show_symbol_sections;
+
+/* If non-null, take address parameters as relative to named section.  */
+static const char *just_section;
+
+/* True if all inlined subroutines of the current address should be shown.  */
+static bool show_inlines;
+
+/* True if all names need to be demangled.  */
+static bool demangle;
+
+/* True if all information should be printed on one line.  */
+static bool pretty;
+
+#ifdef USE_DEMANGLE
+static size_t demangle_buffer_len = 0;
+static char *demangle_buffer = NULL;
+#endif
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+  int result = 0;
+
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  This includes opening the modules.  */
+  argp_children[0].argp = dwfl_standard_argp ();
+  argp_children[0].group = 1;
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+
+  /* Now handle the addresses.  In case none are given on the command
+     line, read from stdin.  */
+  if (remaining == argc)
+    {
+      /* We use no threads here which can interfere with handling a stream.  */
+      (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+
+      char *buf = NULL;
+      size_t len = 0;
+      ssize_t chars;
+      while (!feof_unlocked (stdin))
+	{
+	  if ((chars = getline (&buf, &len, stdin)) < 0)
+	    break;
+
+	  if (buf[chars - 1] == '\n')
+	    buf[chars - 1] = '\0';
+
+	  result = handle_address (buf, dwfl);
+	  fflush (stdout);
+	}
+
+      free (buf);
+    }
+  else
+    {
+      do
+	result = handle_address (argv[remaining], dwfl);
+      while (++remaining < argc);
+    }
+
+  dwfl_end (dwfl);
+
+#ifdef USE_DEMANGLE
+  free (demangle_buffer);
+#endif
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case ARGP_KEY_INIT:
+      state->child_inputs[0] = state->input;
+      break;
+
+    case 'a':
+      print_addresses = true;
+      break;
+
+    /* Ignore --target=bfdname.  */
+    case 'b':
+      break;
+
+    case 'C':
+    case OPT_DEMANGLER:
+      demangle = true;
+      break;
+
+    case 's':
+      only_basenames = true;
+      break;
+
+    case 'A':
+      use_comp_dir = true;
+      break;
+
+    case OPT_RELATIVE:
+      use_comp_dir = false;
+      break;
+
+    case 'f':
+      show_functions = true;
+      break;
+
+    case 'F':
+      show_flags = true;
+      break;
+
+    case 'S':
+      show_symbols = true;
+      break;
+
+    case 'x':
+      show_symbols = true;
+      show_symbol_sections = true;
+      break;
+
+    case 'j':
+      just_section = arg;
+      break;
+
+    case 'i':
+      show_inlines = true;
+      break;
+
+    case OPT_PRETTY:
+      pretty = true;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static const char *
+symname (const char *name)
+{
+#ifdef USE_DEMANGLE
+  // Require GNU v3 ABI by the "_Z" prefix.
+  if (demangle && name[0] == '_' && name[1] == 'Z')
+    {
+      int status = -1;
+      char *dsymname = __cxa_demangle (name, demangle_buffer,
+				       &demangle_buffer_len, &status);
+      if (status == 0)
+	name = demangle_buffer = dsymname;
+    }
+#endif
+  return name;
+}
+
+static const char *
+get_diename (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr;
+  const char *name;
+
+  name = dwarf_formstring (dwarf_attr_integrate (die, DW_AT_MIPS_linkage_name,
+						 &attr)
+			   ?: dwarf_attr_integrate (die, DW_AT_linkage_name,
+						    &attr));
+
+  if (name == NULL)
+    name = dwarf_diename (die) ?: "??";
+
+  return name;
+}
+
+static bool
+print_dwarf_function (Dwfl_Module *mod, Dwarf_Addr addr)
+{
+  Dwarf_Addr bias = 0;
+  Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
+
+  Dwarf_Die *scopes;
+  int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
+  if (nscopes <= 0)
+    return false;
+
+  bool res = false;
+  for (int i = 0; i < nscopes; ++i)
+    switch (dwarf_tag (&scopes[i]))
+      {
+      case DW_TAG_subprogram:
+	{
+	  const char *name = get_diename (&scopes[i]);
+	  if (name == NULL)
+	    goto done;
+	  printf ("%s%c", symname (name), pretty ? ' ' : '\n');
+	  res = true;
+	  goto done;
+	}
+
+      case DW_TAG_inlined_subroutine:
+	{
+	  const char *name = get_diename (&scopes[i]);
+	  if (name == NULL)
+	    goto done;
+
+	  /* When using --pretty-print we only show inlines on their
+	     own line.  Just print the first subroutine name.  */
+	  if (pretty)
+	    {
+	      printf ("%s ", symname (name));
+	      res = true;
+	      goto done;
+	    }
+	  else
+	    printf ("%s inlined", symname (name));
+
+	  Dwarf_Files *files;
+	  if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
+	    {
+	      Dwarf_Attribute attr_mem;
+	      Dwarf_Word val;
+	      if (dwarf_formudata (dwarf_attr (&scopes[i],
+					       DW_AT_call_file,
+					       &attr_mem), &val) == 0)
+		{
+		  const char *file = dwarf_filesrc (files, val, NULL, NULL);
+		  unsigned int lineno = 0;
+		  unsigned int colno = 0;
+		  if (dwarf_formudata (dwarf_attr (&scopes[i],
+						   DW_AT_call_line,
+						   &attr_mem), &val) == 0)
+		    lineno = val;
+		  if (dwarf_formudata (dwarf_attr (&scopes[i],
+						   DW_AT_call_column,
+						   &attr_mem), &val) == 0)
+		    colno = val;
+
+		  const char *comp_dir = "";
+		  const char *comp_dir_sep = "";
+
+		  if (file == NULL)
+		    file = "???";
+		  else if (only_basenames)
+		    file = xbasename (file);
+		  else if (use_comp_dir && file[0] != '/')
+		    {
+		      const char *const *dirs;
+		      size_t ndirs;
+		      if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0
+			  && dirs[0] != NULL)
+			{
+			  comp_dir = dirs[0];
+			  comp_dir_sep = "/";
+			}
+		    }
+
+		  if (lineno == 0)
+		    printf (" from %s%s%s",
+			    comp_dir, comp_dir_sep, file);
+		  else if (colno == 0)
+		    printf (" at %s%s%s:%u",
+			    comp_dir, comp_dir_sep, file, lineno);
+		  else
+		    printf (" at %s%s%s:%u:%u",
+			    comp_dir, comp_dir_sep, file, lineno, colno);
+		}
+	    }
+	  printf (" in ");
+	  continue;
+	}
+      }
+
+done:
+  free (scopes);
+  return res;
+}
+
+static void
+print_addrsym (Dwfl_Module *mod, GElf_Addr addr)
+{
+  GElf_Sym s;
+  GElf_Off off;
+  const char *name = dwfl_module_addrinfo (mod, addr, &off, &s,
+					   NULL, NULL, NULL);
+  if (name == NULL)
+    {
+      /* No symbol name.  Get a section name instead.  */
+      int i = dwfl_module_relocate_address (mod, &addr);
+      if (i >= 0)
+	name = dwfl_module_relocation_info (mod, i, NULL);
+      if (name == NULL)
+	printf ("??%c", pretty ? ' ': '\n');
+      else
+	printf ("(%s)+%#" PRIx64 "%c", name, addr, pretty ? ' ' : '\n');
+    }
+  else
+    {
+      name = symname (name);
+      if (off == 0)
+	printf ("%s", name);
+      else
+	printf ("%s+%#" PRIx64 "", name, off);
+
+      // Also show section name for address.
+      if (show_symbol_sections)
+	{
+	  Dwarf_Addr ebias;
+	  Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
+	  if (scn != NULL)
+	    {
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL)
+		{
+		  Elf *elf = dwfl_module_getelf (mod, &ebias);
+		  size_t shstrndx;
+		  if (elf_getshdrstrndx (elf, &shstrndx) >= 0)
+		    printf (" (%s)", elf_strptr (elf, shstrndx,
+						 shdr->sh_name));
+		}
+	    }
+	}
+      printf ("%c", pretty ? ' ' : '\n');
+    }
+}
+
+static int
+see_one_module (Dwfl_Module *mod,
+		void **userdata __attribute__ ((unused)),
+		const char *name __attribute__ ((unused)),
+		Dwarf_Addr start __attribute__ ((unused)),
+		void *arg)
+{
+  Dwfl_Module **result = arg;
+  if (*result != NULL)
+    return DWARF_CB_ABORT;
+  *result = mod;
+  return DWARF_CB_OK;
+}
+
+static int
+find_symbol (Dwfl_Module *mod,
+	     void **userdata __attribute__ ((unused)),
+	     const char *name __attribute__ ((unused)),
+	     Dwarf_Addr start __attribute__ ((unused)),
+	     void *arg)
+{
+  const char *looking_for = ((void **) arg)[0];
+  GElf_Sym *symbol = ((void **) arg)[1];
+  GElf_Addr *value = ((void **) arg)[2];
+
+  int n = dwfl_module_getsymtab (mod);
+  for (int i = 1; i < n; ++i)
+    {
+      const char *symbol_name = dwfl_module_getsym_info (mod, i, symbol,
+							 value, NULL, NULL,
+							 NULL);
+      if (symbol_name == NULL || symbol_name[0] == '\0')
+	continue;
+      switch (GELF_ST_TYPE (symbol->st_info))
+	{
+	case STT_SECTION:
+	case STT_FILE:
+	case STT_TLS:
+	  break;
+	default:
+	  if (!strcmp (symbol_name, looking_for))
+	    {
+	      ((void **) arg)[0] = NULL;
+	      return DWARF_CB_ABORT;
+	    }
+	}
+    }
+
+  return DWARF_CB_OK;
+}
+
+static bool
+adjust_to_section (const char *name, uintmax_t *addr, Dwfl *dwfl)
+{
+  /* It was (section)+offset.  This makes sense if there is
+     only one module to look in for a section.  */
+  Dwfl_Module *mod = NULL;
+  if (dwfl_getmodules (dwfl, &see_one_module, &mod, 0) != 0
+      || mod == NULL)
+    error_exit (0, _("Section syntax requires exactly one module"));
+
+  int nscn = dwfl_module_relocations (mod);
+  for (int i = 0; i < nscn; ++i)
+    {
+      GElf_Word shndx;
+      const char *scn = dwfl_module_relocation_info (mod, i, &shndx);
+      if (unlikely (scn == NULL))
+	break;
+      if (!strcmp (scn, name))
+	{
+	  /* Found the section.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Addr shdr_bias;
+	  GElf_Shdr *shdr = gelf_getshdr
+	    (elf_getscn (dwfl_module_getelf (mod, &shdr_bias), shndx),
+	     &shdr_mem);
+	  if (unlikely (shdr == NULL))
+	    break;
+
+	  if (*addr >= shdr->sh_size)
+	    error (0, 0,
+		   _("offset %#" PRIxMAX " lies outside"
+			    " section '%s'"),
+		   *addr, scn);
+
+	  *addr += shdr->sh_addr + shdr_bias;
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+static void
+print_src (const char *src, int lineno, int linecol, Dwarf_Die *cu)
+{
+  const char *comp_dir = "";
+  const char *comp_dir_sep = "";
+
+  if (only_basenames)
+    src = xbasename (src);
+  else if (use_comp_dir && src[0] != '/')
+    {
+      Dwarf_Attribute attr;
+      comp_dir = dwarf_formstring (dwarf_attr (cu, DW_AT_comp_dir, &attr));
+      if (comp_dir != NULL)
+	comp_dir_sep = "/";
+    }
+
+  if (linecol != 0)
+    printf ("%s%s%s:%d:%d",
+	    comp_dir, comp_dir_sep, src, lineno, linecol);
+  else
+    printf ("%s%s%s:%d",
+	    comp_dir, comp_dir_sep, src, lineno);
+}
+
+static int
+get_addr_width (Dwfl_Module *mod)
+{
+  // Try to find the address width if possible.
+  static int width = 0;
+  if (width == 0 && mod != NULL)
+    {
+      Dwarf_Addr bias;
+      Elf *elf = dwfl_module_getelf (mod, &bias);
+      if (elf != NULL)
+        {
+	  GElf_Ehdr ehdr_mem;
+	  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+	  if (ehdr != NULL)
+	    width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
+	}
+    }
+  if (width == 0)
+    width = 16;
+
+  return width;
+}
+
+static inline void
+show_note (int (*get) (Dwarf_Line *, bool *),
+	   Dwarf_Line *info,
+	   const char *note)
+{
+  bool flag;
+  if ((*get) (info, &flag) == 0 && flag)
+    fputs (note, stdout);
+}
+
+static inline void
+show_int (int (*get) (Dwarf_Line *, unsigned int *),
+	  Dwarf_Line *info,
+	  const char *name)
+{
+  unsigned int val;
+  if ((*get) (info, &val) == 0 && val != 0)
+    printf (" (%s %u)", name, val);
+}
+
+static int
+handle_address (const char *string, Dwfl *dwfl)
+{
+  char *endp;
+  uintmax_t addr = strtoumax (string, &endp, 16);
+  if (endp == string || *endp != '\0')
+    {
+      bool parsed = false;
+      int i, j;
+      char *name = NULL;
+      if (sscanf (string, "(%m[^)])%" PRIiMAX "%n", &name, &addr, &i) == 2
+	  && string[i] == '\0')
+	parsed = adjust_to_section (name, &addr, dwfl);
+      switch (sscanf (string, "%m[^-+]%n%" PRIiMAX "%n", &name, &i, &addr, &j))
+	{
+	default:
+	  break;
+	case 1:
+	  addr = 0;
+	  j = i;
+	  FALLTHROUGH;
+	case 2:
+	  if (string[j] != '\0')
+	    break;
+
+	  /* It was symbol[+offset].  */
+	  GElf_Sym sym;
+	  GElf_Addr value = 0;
+	  void *arg[3] = { name, &sym, &value };
+	  (void) dwfl_getmodules (dwfl, &find_symbol, arg, 0);
+	  if (arg[0] != NULL)
+	    error (0, 0, _("cannot find symbol '%s'"), name);
+	  else
+	    {
+	      if (sym.st_size != 0 && addr >= sym.st_size)
+		error (0, 0,
+		       _("offset %#" PRIxMAX " lies outside"
+				" contents of '%s'"),
+		       addr, name);
+	      addr += value;
+	      parsed = true;
+	    }
+	  break;
+	}
+
+      free (name);
+      if (!parsed)
+	return 1;
+    }
+  else if (just_section != NULL
+	   && !adjust_to_section (just_section, &addr, dwfl))
+    return 1;
+
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, addr);
+
+  if (print_addresses)
+    {
+      int width = get_addr_width (mod);
+      printf ("0x%.*" PRIx64 "%s", width, addr, pretty ? ": " : "\n");
+    }
+
+  if (show_functions)
+    {
+      /* First determine the function name.  Use the DWARF information if
+	 possible.  */
+      if (! print_dwarf_function (mod, addr) && !show_symbols)
+	{
+	  const char *name = dwfl_module_addrname (mod, addr);
+	  name = name != NULL ? symname (name) : "??";
+	  printf ("%s%c", name, pretty ? ' ' : '\n');
+	}
+    }
+
+  if (show_symbols)
+    print_addrsym (mod, addr);
+
+  if ((show_functions || show_symbols) && pretty)
+    printf ("at ");
+
+  Dwfl_Line *line = dwfl_module_getsrc (mod, addr);
+
+  const char *src;
+  int lineno, linecol;
+
+  if (line != NULL && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
+					    NULL, NULL)) != NULL)
+    {
+      print_src (src, lineno, linecol, dwfl_linecu (line));
+      if (show_flags)
+	{
+	  Dwarf_Addr bias;
+	  Dwarf_Line *info = dwfl_dwarf_line (line, &bias);
+	  assert (info != NULL);
+
+	  show_note (&dwarf_linebeginstatement, info, " (is_stmt)");
+	  show_note (&dwarf_lineblock, info, " (basic_block)");
+	  show_note (&dwarf_lineprologueend, info, " (prologue_end)");
+	  show_note (&dwarf_lineepiloguebegin, info, " (epilogue_begin)");
+	  show_int (&dwarf_lineisa, info, "isa");
+	  show_int (&dwarf_linediscriminator, info, "discriminator");
+	}
+      putchar ('\n');
+    }
+  else
+    puts ("??:0");
+
+  if (show_inlines)
+    {
+      Dwarf_Addr bias = 0;
+      Dwarf_Die *cudie = dwfl_module_addrdie (mod, addr, &bias);
+
+      Dwarf_Die *scopes = NULL;
+      int nscopes = dwarf_getscopes (cudie, addr - bias, &scopes);
+      if (nscopes < 0)
+	return 1;
+
+      if (nscopes > 0)
+	{
+	  Dwarf_Die subroutine;
+	  Dwarf_Off dieoff = dwarf_dieoffset (&scopes[0]);
+	  dwarf_offdie (dwfl_module_getdwarf (mod, &bias),
+			dieoff, &subroutine);
+	  free (scopes);
+	  scopes = NULL;
+
+	  nscopes = dwarf_getscopes_die (&subroutine, &scopes);
+	  if (nscopes > 1)
+	    {
+	      Dwarf_Die cu;
+	      Dwarf_Files *files;
+	      if (dwarf_diecu (&scopes[0], &cu, NULL, NULL) != NULL
+		  && dwarf_getsrcfiles (cudie, &files, NULL) == 0)
+		{
+		  for (int i = 0; i < nscopes - 1; i++)
+		    {
+		      Dwarf_Word val;
+		      Dwarf_Attribute attr;
+		      Dwarf_Die *die = &scopes[i];
+		      if (dwarf_tag (die) != DW_TAG_inlined_subroutine)
+			continue;
+
+		      if (pretty)
+			printf (" (inlined by) ");
+
+		      if (show_functions)
+			{
+			  /* Search for the parent inline or function.  It
+			     might not be directly above this inline -- e.g.
+			     there could be a lexical_block in between.  */
+			  for (int j = i + 1; j < nscopes; j++)
+			    {
+			      Dwarf_Die *parent = &scopes[j];
+			      int tag = dwarf_tag (parent);
+			      if (tag == DW_TAG_inlined_subroutine
+				  || tag == DW_TAG_entry_point
+				  || tag == DW_TAG_subprogram)
+				{
+				  printf ("%s%s",
+					  symname (get_diename (parent)),
+					  pretty ? " at " : "\n");
+				  break;
+				}
+			    }
+			}
+
+		      src = NULL;
+		      lineno = 0;
+		      linecol = 0;
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file,
+						       &attr), &val) == 0)
+			src = dwarf_filesrc (files, val, NULL, NULL);
+
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
+						       &attr), &val) == 0)
+			lineno = val;
+
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
+						       &attr), &val) == 0)
+			linecol = val;
+
+		      if (src != NULL)
+			{
+			  print_src (src, lineno, linecol, &cu);
+			  putchar ('\n');
+			}
+		      else
+			puts ("??:0");
+		    }
+		}
+	    }
+	}
+      free (scopes);
+    }
+
+  return 0;
+}
+
+
+#include "debugpred.h"
diff --git a/src/ar.c b/src/ar.c
new file mode 100644
index 0000000..e6d6d58
--- /dev/null
+++ b/src/ar.c
@@ -0,0 +1,1572 @@
+/* Create, modify, and extract from archives.
+   Copyright (C) 2005-2012, 2016, 2017 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <limits.h>
+#include <locale.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <system.h>
+#include <printversion.h>
+
+#include "arlib.h"
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Prototypes for local functions.  */
+static int do_oper_extract (int oper, const char *arfname, char **argv,
+			    int argc, long int instance);
+static int do_oper_delete (const char *arfname, char **argv, int argc,
+			   long int instance);
+static int do_oper_insert (int oper, const char *arfname, char **argv,
+			   int argc, const char *member);
+
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Commands:"), 1 },
+  { NULL, 'd', NULL, 0, N_("Delete files from archive."), 0 },
+  { NULL, 'm', NULL, 0, N_("Move files in archive."), 0 },
+  { NULL, 'p', NULL, 0, N_("Print files in archive."), 0 },
+  { NULL, 'q', NULL, 0, N_("Quick append files to archive."), 0 },
+  { NULL, 'r', NULL, 0,
+    N_("Replace existing or insert new file into archive."), 0 },
+  { NULL, 't', NULL, 0, N_("Display content of archive."), 0 },
+  { NULL, 'x', NULL, 0, N_("Extract files from archive."), 0 },
+
+  { NULL, 0, NULL, 0, N_("Command Modifiers:"), 2 },
+  { NULL, 'o', NULL, 0, N_("Preserve original dates."), 0 },
+  { NULL, 'N', NULL, 0, N_("Use instance [COUNT] of name."), 0 },
+  { NULL, 'C', NULL, 0,
+    N_("Do not replace existing files with extracted files."), 0 },
+  { NULL, 'T', NULL, 0, N_("Allow filename to be truncated if necessary."),
+    0 },
+  { NULL, 'v', NULL, 0, N_("Provide verbose output."), 0 },
+  { NULL, 's', NULL, 0, N_("Force regeneration of symbol table."), 0 },
+  { NULL, 'a', NULL, 0, N_("Insert file after [MEMBER]."), 0 },
+  { NULL, 'b', NULL, 0, N_("Insert file before [MEMBER]."), 0 },
+  { NULL, 'i', NULL, 0, N_("Same as -b."), 0 },
+  { NULL, 'c', NULL, 0, N_("Suppress message when library has to be created."),
+    0 },
+  { NULL, 'P', NULL, 0, N_("Use full path for file matching."), 0 },
+  { NULL, 'u', NULL, 0, N_("Update only older files in archive."), 0 },
+
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("Create, modify, and extract from archives.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[MEMBER] [COUNT] ARCHIVE [FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, arlib_argp_children, NULL, NULL
+};
+
+
+/* What operation to perform.  */
+static enum
+  {
+    oper_none,
+    oper_delete,
+    oper_move,
+    oper_print,
+    oper_qappend,
+    oper_replace,
+    oper_list,
+    oper_extract
+  } operation;
+
+/* Modifiers.  */
+static bool verbose;
+static bool preserve_dates;
+static bool instance_specifed;
+static bool dont_replace_existing;
+static bool allow_truncate_fname;
+static bool force_symtab;
+static bool suppress_create_msg;
+static bool full_path;
+static bool update_newer;
+static enum { ipos_none, ipos_before, ipos_after } ipos;
+
+
+int
+main (int argc, char *argv[])
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* For historical reasons the options in the first parameter need
+     not be preceded by a dash.  Add it now if necessary.  */
+  if (argc > 1 && argv[1][0] != '-')
+    {
+      size_t len = strlen (argv[1]) + 1;
+      char *newp = alloca (len + 1);
+      newp[0] = '-';
+      memcpy (&newp[1], argv[1], len);
+      argv[1] = newp;
+    }
+
+  /* Parse and process arguments.  */
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
+
+  /* Tell the library which version we are expecting.  */
+  (void) elf_version (EV_CURRENT);
+
+  /* Handle the [MEMBER] parameter.  */
+  const char *member = NULL;
+  if (ipos != ipos_none)
+    {
+      /* Only valid for certain operations.  */
+      if (operation != oper_move && operation != oper_replace)
+	error (1, 0, _("\
+'a', 'b', and 'i' are only allowed with the 'm' and 'r' options"));
+
+      if (remaining == argc)
+	{
+	  error (0, 0, _("\
+MEMBER parameter required for 'a', 'b', and 'i' modifiers"));
+	  argp_help (&argp, stderr, ARGP_HELP_USAGE | ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (EXIT_FAILURE);
+	}
+
+      member = argv[remaining++];
+    }
+
+  /* Handle the [COUNT] parameter.  */
+  long int instance = -1;
+  if (instance_specifed)
+    {
+      /* Only valid for certain operations.  */
+      if (operation != oper_extract && operation != oper_delete)
+	error (1, 0, _("\
+'N' is only meaningful with the 'x' and 'd' options"));
+
+      if (remaining == argc)
+	{
+	  error (0, 0, _("COUNT parameter required"));
+	  argp_help (&argp, stderr, ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (EXIT_FAILURE);
+	}
+
+      char *endp;
+      errno = 0;
+      if (((instance = strtol (argv[remaining], &endp, 10)) == LONG_MAX
+	   && errno == ERANGE)
+	  || instance <= 0
+	  || *endp != '\0')
+	error (1, 0, _("invalid COUNT parameter %s"), argv[remaining]);
+
+      ++remaining;
+    }
+
+  if ((dont_replace_existing || allow_truncate_fname)
+      && unlikely (operation != oper_extract))
+    error (1, 0, _("'%c' is only meaningful with the 'x' option"),
+	   dont_replace_existing ? 'C' : 'T');
+
+  /* There must at least be one more parameter specifying the archive.   */
+  if (remaining == argc)
+    {
+      error (0, 0, _("archive name required"));
+      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
+      exit (EXIT_FAILURE);
+    }
+
+  const char *arfname = argv[remaining++];
+  argv += remaining;
+  argc -= remaining;
+
+  int status;
+  switch (operation)
+    {
+    case oper_none:
+      error (0, 0, _("command option required"));
+      argp_help (&argp, stderr, ARGP_HELP_STD_ERR,
+		 program_invocation_short_name);
+      status = 1;
+      break;
+
+    case oper_list:
+    case oper_print:
+      status = do_oper_extract (operation, arfname, argv, argc, -1);
+      break;
+
+    case oper_extract:
+      status = do_oper_extract (operation, arfname, argv, argc, instance);
+      break;
+
+    case oper_delete:
+      status = do_oper_delete (arfname, argv, argc, instance);
+      break;
+
+    case oper_move:
+    case oper_qappend:
+    case oper_replace:
+      status = do_oper_insert (operation, arfname, argv, argc, member);
+      break;
+
+    default:
+      assert (! "should not happen");
+      status = 1;
+      break;
+    }
+
+  return status;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'd':
+    case 'm':
+    case 'p':
+    case 'q':
+    case 'r':
+    case 't':
+    case 'x':
+      if (operation != oper_none)
+	{
+	  error (0, 0, _("More than one operation specified"));
+	  argp_help (&argp, stderr, ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (EXIT_FAILURE);
+	}
+
+      switch (key)
+	{
+	case 'd':
+	  operation = oper_delete;
+	  break;
+	case 'm':
+	  operation = oper_move;
+	  break;
+	case 'p':
+	  operation = oper_print;
+	  break;
+	case 'q':
+	  operation = oper_qappend;
+	  break;
+	case 'r':
+	  operation = oper_replace;
+	  break;
+	case 't':
+	  operation = oper_list;
+	  break;
+	case 'x':
+	  operation = oper_extract;
+	  break;
+	}
+      break;
+
+    case 'a':
+      ipos = ipos_after;
+      break;
+
+    case 'b':
+    case 'i':
+      ipos = ipos_before;
+      break;
+
+    case 'c':
+      suppress_create_msg = true;
+      break;
+
+    case 'C':
+      dont_replace_existing = true;
+      break;
+
+    case 'N':
+      instance_specifed = true;
+      break;
+
+    case 'o':
+      preserve_dates = true;
+      break;
+
+    case 'P':
+      full_path = true;
+      break;
+
+    case 's':
+      force_symtab = true;
+      break;
+
+    case 'T':
+      allow_truncate_fname = true;
+      break;
+
+    case 'u':
+      update_newer = true;
+      break;
+
+    case 'v':
+      verbose = true;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+static int
+open_archive (const char *arfname, int flags, int mode, Elf **elf,
+	      struct stat *st, bool miss_allowed)
+{
+  int fd = open (arfname, flags, mode);
+  if (fd == -1)
+    {
+      if (miss_allowed)
+	return -1;
+
+      error_exit (errno, _("cannot open archive '%s'"),
+		  arfname);
+    }
+
+  if (elf != NULL)
+    {
+      Elf_Cmd cmd = flags == O_RDONLY ? ELF_C_READ_MMAP : ELF_C_RDWR_MMAP;
+
+      *elf = elf_begin (fd, cmd, NULL);
+      if (*elf == NULL)
+	error_exit (0, _("cannot open archive '%s': %s"),
+		    arfname, elf_errmsg (-1));
+
+      if (flags == O_RDONLY && elf_kind (*elf) != ELF_K_AR)
+	error_exit (0, _("%s: not an archive file"), arfname);
+    }
+
+  if (st != NULL && fstat (fd, st) != 0)
+    error_exit (errno, _("cannot stat archive '%s'"),
+		arfname);
+
+  return fd;
+}
+
+
+static void
+not_found (int argc, char *argv[argc], bool found[argc])
+{
+  for (int i = 0; i < argc; ++i)
+    if (!found[i])
+      printf (_("no entry %s in archive\n"), argv[i]);
+}
+
+
+static int
+copy_content (Elf *elf, int newfd, off_t off, size_t n)
+{
+  size_t len;
+  char *rawfile = elf_rawfile (elf, &len);
+
+  assert (off + n <= len);
+
+  /* Tell the kernel we will read all the pages sequentially.  */
+  size_t ps = sysconf (_SC_PAGESIZE);
+  if (n > 2 * ps)
+    posix_madvise (rawfile + (off & ~(ps - 1)), n, POSIX_MADV_SEQUENTIAL);
+
+  return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
+}
+
+static inline bool
+should_truncate_fname (size_t *name_max)
+{
+  if (errno == ENAMETOOLONG && allow_truncate_fname)
+    {
+      if (*name_max == 0)
+	{
+	  long int len = pathconf (".", _PC_NAME_MAX);
+	  if (len > 0)
+	    *name_max = len;
+	}
+      return *name_max != 0;
+    }
+  return false;
+}
+
+static int
+do_oper_extract (int oper, const char *arfname, char **argv, int argc,
+		 long int instance)
+{
+  bool found[argc > 0 ? argc : 1];
+  memset (found, '\0', sizeof (found));
+
+  size_t name_max = 0;
+  off_t index_off = -1;
+  size_t index_size = 0;
+  off_t cur_off = SARMAG;
+
+  int status = 0;
+  Elf *elf;
+  int fd = open_archive (arfname, O_RDONLY, 0, &elf, NULL, false);
+
+  if (hcreate (2 * argc) == 0)
+    error_exit (errno, _("cannot create hash table"));
+
+  for (int cnt = 0; cnt < argc; ++cnt)
+    {
+      ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
+      if (hsearch (entry, ENTER) == NULL)
+	error_exit (errno, _("cannot insert into hash table"));
+    }
+
+  struct stat st;
+  if (force_symtab)
+    {
+      if (fstat (fd, &st) != 0)
+	{
+	  error (0, errno, _("cannot stat '%s'"), arfname);
+	  close (fd);
+	  return 1;
+	}
+      arlib_init ();
+    }
+
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  Elf *subelf;
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      if (strcmp (arhdr->ar_name, "/") == 0)
+	{
+	  index_off = elf_getaroff (subelf);
+	  index_size = arhdr->ar_size;
+	  goto next;
+	}
+      if (strcmp (arhdr->ar_name, "//") == 0)
+	goto next;
+
+      if (force_symtab)
+	{
+	  arlib_add_symbols (elf, arfname, arhdr->ar_name, cur_off);
+	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
+		      + sizeof (struct ar_hdr));
+	}
+
+      bool do_extract = argc <= 0;
+      if (!do_extract)
+	{
+	  ENTRY entry;
+	  entry.key = arhdr->ar_name;
+	  ENTRY *res = hsearch (entry, FIND);
+	  if (res != NULL && (instance < 0 || --instance == 0)
+	      && !found[(char **) res->data - argv])
+	    found[(char **) res->data - argv] = do_extract = true;
+	}
+
+      if (do_extract)
+	{
+	  if (verbose)
+	    {
+	      if (oper == oper_print)
+		{
+		  printf ("\n<%s>\n\n", arhdr->ar_name);
+
+		  /* We have to flush now because now we use the descriptor
+		     directly.  */
+		  fflush (stdout);
+		}
+	      else if (oper == oper_list)
+		{
+		  char datestr[100];
+		  struct tm *tp = localtime (&arhdr->ar_date);
+		  if (tp == NULL)
+		    {
+		      time_t time = 0;
+		      tp = localtime (&time);
+		    }
+
+		  strftime (datestr, sizeof (datestr), "%b %e %H:%M %Y", tp);
+
+		  printf ("%c%c%c%c%c%c%c%c%c %u/%u %6ju %s %s\n",
+			  (arhdr->ar_mode & S_IRUSR) ? 'r' : '-',
+			  (arhdr->ar_mode & S_IWUSR) ? 'w' : '-',
+			  (arhdr->ar_mode & S_IXUSR)
+			  ? ((arhdr->ar_mode & S_ISUID) ? 's' : 'x')
+			  : ((arhdr->ar_mode & S_ISUID) ? 'S' : '-'),
+			  (arhdr->ar_mode & S_IRGRP) ? 'r' : '-',
+			  (arhdr->ar_mode & S_IWGRP) ? 'w' : '-',
+			  (arhdr->ar_mode & S_IXGRP)
+			  ? ((arhdr->ar_mode & S_ISGID) ? 's' : 'x')
+			  : ((arhdr->ar_mode & S_ISGID) ? 'S' : '-'),
+			  (arhdr->ar_mode & S_IROTH) ? 'r' : '-',
+			  (arhdr->ar_mode & S_IWOTH) ? 'w' : '-',
+			  (arhdr->ar_mode & S_IXOTH)
+			  ? ((arhdr->ar_mode & S_ISVTX) ? 't' : 'x')
+			  : ((arhdr->ar_mode & S_ISVTX) ? 'T' : '-'),
+			  arhdr->ar_uid,
+			  arhdr->ar_gid,
+			  (uintmax_t) arhdr->ar_size,
+			  datestr,
+			  arhdr->ar_name);
+		}
+	      else
+		printf ("x - %s\n", arhdr->ar_name);
+	    }
+
+	  if (oper == oper_list)
+	    {
+	      if (!verbose)
+		puts (arhdr->ar_name);
+
+	      goto next;
+	    }
+
+	  size_t nleft;
+	  char *data = elf_rawfile (subelf, &nleft);
+	  if (data == NULL)
+	    {
+	      error (0, 0, _("cannot read content of %s: %s"),
+		     arhdr->ar_name, elf_errmsg (-1));
+	      status = 1;
+	      goto next;
+	    }
+
+	  int xfd;
+	  char tempfname[] = "XXXXXX";
+	  bool use_mkstemp = true;
+
+	  if (oper == oper_print)
+	    xfd = STDOUT_FILENO;
+	  else
+	    {
+	      xfd = mkstemp (tempfname);
+	      if (unlikely (xfd == -1))
+		{
+		  /* We cannot create a temporary file.  Try to overwrite
+		     the file or create it if it does not exist.  */
+		  int flags = O_WRONLY | O_CREAT;
+		  if (dont_replace_existing)
+		    flags |= O_EXCL;
+		  else
+		    flags |= O_TRUNC;
+		  xfd = open (arhdr->ar_name, flags, 0600);
+		  if (unlikely (xfd == -1))
+		    {
+		      int printlen = INT_MAX;
+
+		      if (should_truncate_fname (&name_max))
+			{
+			  /* Try to truncate the name.  First find out by how
+			     much.  */
+			  printlen = name_max;
+			  char truncfname[name_max + 1];
+			  *((char *) mempcpy (truncfname, arhdr->ar_name,
+					      name_max)) = '\0';
+
+			  xfd = open (truncfname, flags, 0600);
+			}
+
+		      if (xfd == -1)
+			{
+			  error (0, errno, _("cannot open %.*s"),
+				 (int) printlen, arhdr->ar_name);
+			  status = 1;
+			  goto next;
+			}
+		    }
+
+		  use_mkstemp = false;
+		}
+	    }
+
+	  ssize_t n;
+	  while ((n = TEMP_FAILURE_RETRY (write (xfd, data, nleft))) != -1)
+	    {
+	      nleft -= n;
+	      if (nleft == 0)
+		break;
+	      data += n;
+	    }
+
+	  if (unlikely (n == -1))
+	    {
+	      error (0, errno, _("failed to write %s"), arhdr->ar_name);
+	      status = 1;
+	      unlink (tempfname);
+	      close (xfd);
+	      goto next;
+	    }
+
+	  if (oper != oper_print)
+	    {
+	      /* Fix up the mode.  */
+	      if (unlikely (fchmod (xfd, arhdr->ar_mode) != 0))
+		{
+		  error (0, errno, _("cannot change mode of %s"),
+			 arhdr->ar_name);
+		  status = 0;
+		}
+
+	      if (preserve_dates)
+		{
+		  struct timespec tv[2];
+		  tv[0].tv_sec = arhdr->ar_date;
+		  tv[0].tv_nsec = 0;
+		  tv[1].tv_sec = arhdr->ar_date;
+		  tv[1].tv_nsec = 0;
+
+		  if (unlikely (futimens (xfd, tv) != 0))
+		    {
+		      error (0, errno,
+			     _("cannot change modification time of %s"),
+			     arhdr->ar_name);
+		      status = 1;
+		    }
+		}
+
+	      /* If we used a temporary file, move it do the right
+		 name now.  */
+	      if (use_mkstemp)
+		{
+		  int r;
+
+		  if (dont_replace_existing)
+		    {
+		      r = link (tempfname, arhdr->ar_name);
+		      if (likely (r == 0))
+			unlink (tempfname);
+		    }
+		  else
+		    r = rename (tempfname, arhdr->ar_name);
+
+		  if (unlikely (r) != 0)
+		    {
+		      int printlen = INT_MAX;
+
+		      if (should_truncate_fname (&name_max))
+			{
+			  /* Try to truncate the name.  First find out by how
+			     much.  */
+			  printlen = name_max;
+			  char truncfname[name_max + 1];
+			  *((char *) mempcpy (truncfname, arhdr->ar_name,
+					      name_max)) = '\0';
+
+			  if (dont_replace_existing)
+			    {
+			      r = link (tempfname, truncfname);
+			      if (likely (r == 0))
+				unlink (tempfname);
+			    }
+			  else
+			    r = rename (tempfname, truncfname);
+			}
+
+		      if (r != 0)
+			{
+			  error (0, errno, _("\
+cannot rename temporary file to %.*s"),
+				 printlen, arhdr->ar_name);
+			  unlink (tempfname);
+			  status = 1;
+			}
+		    }
+		}
+
+	      close (xfd);
+	    }
+	}
+
+    next:
+      cmd = elf_next (subelf);
+      if (elf_end (subelf) != 0)
+	error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
+    }
+
+  hdestroy ();
+
+  if (force_symtab)
+    {
+      arlib_finalize ();
+
+      if (symtab.symsnamelen != 0
+	  /* We have to rewrite the file also if it initially had an index
+	     but now does not need one anymore.  */
+	  || (symtab.symsnamelen == 0 && index_size != 0))
+	{
+	  char tmpfname[strlen (arfname) + 7];
+	  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
+	  int newfd = mkstemp (tmpfname);
+	  if (unlikely (newfd == -1))
+	    {
+	    nonew:
+	      error (0, errno, _("cannot create new file"));
+	      status = 1;
+	    }
+	  else
+	    {
+	      /* Create the header.  */
+	      if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
+		{
+		  // XXX Use /prof/self/fd/%d ???
+		nonew_unlink:
+		  unlink (tmpfname);
+		  if (newfd != -1)
+		    close (newfd);
+		  goto nonew;
+		}
+
+	      /* Create the new file.  There are three parts as far we are
+		 concerned: 1. original context before the index, 2. the
+		 new index, 3. everything after the new index.  */
+	      off_t rest_off;
+	      if (index_off != -1)
+		rest_off = (index_off + sizeof (struct ar_hdr)
+			    + ((index_size + 1) & ~1ul));
+	      else
+		rest_off = SARMAG;
+
+	      if (symtab.symsnamelen != 0
+		   && ((write_retry (newfd, symtab.symsoff,
+				     symtab.symsofflen)
+			!= (ssize_t) symtab.symsofflen)
+		       || (write_retry (newfd, symtab.symsname,
+					symtab.symsnamelen)
+			   != (ssize_t) symtab.symsnamelen)))
+		goto nonew_unlink;
+	      /* Even if the original file had content before the
+		 symbol table, we write it in the correct order.  */
+	      if ((index_off != SARMAG
+		   && copy_content (elf, newfd, SARMAG, index_off - SARMAG))
+		  || copy_content (elf, newfd, rest_off, st.st_size - rest_off))
+		goto nonew_unlink;
+
+	      /* Never complain about fchown failing.  */
+	      if (fchown (newfd, st.st_uid, st.st_gid) != 0) { ; }
+	      /* Set the mode of the new file to the same values the
+		 original file has.  */
+	      if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
+		  || close (newfd) != 0)
+		goto nonew_unlink;
+	      newfd = -1;
+	      if (rename (tmpfname, arfname) != 0)
+		goto nonew_unlink;
+	    }
+	}
+    }
+
+  elf_end (elf);
+
+  close (fd);
+
+  not_found (argc, argv, found);
+
+  return status;
+}
+
+
+struct armem
+{
+  off_t off;
+  off_t old_off;
+  size_t size;
+  long int long_name_off;
+  struct armem *next;
+  void *mem;
+  time_t sec;
+  uid_t uid;
+  gid_t gid;
+  mode_t mode;
+  const char *name;
+  Elf *elf;
+};
+
+
+static int
+write_member (struct armem *memb, off_t *startp, off_t *lenp, Elf *elf,
+	      off_t end_off, int newfd)
+{
+  struct ar_hdr arhdr;
+  /* The ar_name is not actually zero terminated, but we need that for
+     snprintf.  Also if the name is too long, then the string starts
+     with '/' plus an index off number (decimal).  */
+  char tmpbuf[sizeof (arhdr.ar_name) + 2];
+
+  bool changed_header = memb->long_name_off != -1;
+  if (changed_header)
+    {
+      /* In case of a long file name we assume the archive header
+	 changed and we write it here.  */
+      memcpy (&arhdr, elf_rawfile (elf, NULL) + *startp, sizeof (arhdr));
+
+      snprintf (tmpbuf, sizeof (tmpbuf), "/%-*ld",
+		(int) sizeof (arhdr.ar_name), memb->long_name_off);
+      changed_header = memcmp (arhdr.ar_name, tmpbuf,
+			       sizeof (arhdr.ar_name)) != 0;
+    }
+
+  /* If the files are adjacent in the old file extend the range.  */
+  if (*startp != -1 && !changed_header && *startp + *lenp == memb->old_off)
+    {
+      /* Extend the current range.  */
+      *lenp += (memb->next != NULL
+		? memb->next->off : end_off) - memb->off;
+      return 0;
+    }
+
+  /* Write out the old range.  */
+  if (*startp != -1 && copy_content (elf, newfd, *startp, *lenp))
+    return -1;
+
+  *startp = memb->old_off;
+  *lenp = (memb->next != NULL ? memb->next->off : end_off) - memb->off;
+
+  if (changed_header)
+    {
+      memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name));
+
+      if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr))
+		    != sizeof (arhdr)))
+	return -1;
+
+      *startp += sizeof (struct ar_hdr);
+      assert ((size_t) *lenp >= sizeof (struct ar_hdr));
+      *lenp -= sizeof (struct ar_hdr);
+    }
+
+  return 0;
+}
+
+/* Store the name in the long name table if necessary.
+   Record its offset or -1 if we did not need to use the table.  */
+static void
+remember_long_name (struct armem *mem, const char *name, size_t namelen)
+{
+  mem->long_name_off = (namelen > MAX_AR_NAME_LEN
+			? arlib_add_long_name (name, namelen)
+			: -1l);
+}
+
+static int
+do_oper_delete (const char *arfname, char **argv, int argc,
+		long int instance)
+{
+  bool *found = alloca (sizeof (bool) * argc);
+  memset (found, '\0', sizeof (bool) * argc);
+
+  /* List of the files we keep.  */
+  struct armem *to_copy = NULL;
+
+  int status = 0;
+  Elf *elf;
+  struct stat st;
+  int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, false);
+
+  if (hcreate (2 * argc) == 0)
+    error_exit (errno, _("cannot create hash table"));
+
+  for (int cnt = 0; cnt < argc; ++cnt)
+    {
+      ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] };
+      if (hsearch (entry, ENTER) == NULL)
+	error_exit (errno, _("cannot insert into hash table"));
+    }
+
+  arlib_init ();
+
+  off_t cur_off = SARMAG;
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  Elf *subelf;
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      /* Ignore the symbol table and the long file name table here.  */
+      if (strcmp (arhdr->ar_name, "/") == 0
+	  || strcmp (arhdr->ar_name, "//") == 0)
+	goto next;
+
+      bool do_delete = argc <= 0;
+      if (!do_delete)
+	{
+	  ENTRY entry;
+	  entry.key = arhdr->ar_name;
+	  ENTRY *res = hsearch (entry, FIND);
+	  if (res != NULL && (instance < 0 || --instance == 0)
+	      && !found[(char **) res->data - argv])
+	    found[(char **) res->data - argv] = do_delete = true;
+	}
+
+      if (do_delete)
+	{
+	  if (verbose)
+	    printf ("d - %s\n", arhdr->ar_name);
+	}
+      else
+	{
+	  struct armem *newp = alloca (sizeof (struct armem));
+	  newp->old_off = elf_getaroff (subelf);
+	  newp->off = cur_off;
+
+	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
+		      + sizeof (struct ar_hdr));
+
+	  if (to_copy == NULL)
+	    to_copy = newp->next = newp;
+	  else
+	    {
+	      newp->next = to_copy->next;
+	      to_copy = to_copy->next = newp;
+	    }
+
+	  /* If we recreate the symbol table read the file's symbol
+	     table now.  */
+	  arlib_add_symbols (subelf, arfname, arhdr->ar_name, newp->off);
+
+	  /* Remember long file names.  */
+	  remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name));
+	}
+
+    next:
+      cmd = elf_next (subelf);
+      if (elf_end (subelf) != 0)
+	error (1, 0, "%s: %s", arfname, elf_errmsg (-1));
+    }
+
+  arlib_finalize ();
+
+  hdestroy ();
+
+  /* Create a new, temporary file in the same directory as the
+     original file.  */
+  char tmpfname[strlen (arfname) + 7];
+  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
+  int newfd = mkstemp (tmpfname);
+  if (unlikely (newfd == -1))
+    goto nonew;
+
+  /* Create the header.  */
+  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
+    {
+      // XXX Use /prof/self/fd/%d ???
+    nonew_unlink:
+      unlink (tmpfname);
+      if (newfd != -1)
+	close (newfd);
+    nonew:
+      error (0, errno, _("cannot create new file"));
+      status = 1;
+      goto errout;
+    }
+
+  /* If the archive is empty that is all we have to do.  */
+  if (likely (to_copy != NULL))
+    {
+      /* Write the symbol table or the long file name table or both.  */
+      if (symtab.symsnamelen != 0
+	  && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen)
+	       != (ssize_t) symtab.symsofflen)
+	      || (write_retry (newfd, symtab.symsname, symtab.symsnamelen)
+		  != (ssize_t) symtab.symsnamelen)))
+	goto nonew_unlink;
+
+      if (symtab.longnameslen > sizeof (struct ar_hdr)
+	  && (write_retry (newfd, symtab.longnames, symtab.longnameslen)
+	      != (ssize_t) symtab.longnameslen))
+	goto nonew_unlink;
+
+      /* NULL-terminate the list of files to copy.  */
+      struct armem *last = to_copy;
+      to_copy = to_copy->next;
+      last->next = NULL;
+
+      off_t start = -1;
+      off_t len = -1;
+
+      do
+	if (write_member (to_copy, &start, &len, elf, cur_off, newfd) != 0)
+	  goto nonew_unlink;
+      while ((to_copy = to_copy->next) != NULL);
+
+      /* Write the last part.  */
+      if (copy_content (elf, newfd, start, len))
+	goto nonew_unlink;
+    }
+
+  /* Set the mode of the new file to the same values the original file
+     has.  Never complain about fchown failing.  But do it before
+     setting the mode (which might be reset/ignored if the owner is
+     wrong.  */
+  if (fchown (newfd, st.st_uid, st.st_gid) != 0) { ; }
+  if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
+      || close (newfd) != 0)
+    goto nonew_unlink;
+  newfd = -1;
+  if (rename (tmpfname, arfname) != 0)
+    goto nonew_unlink;
+
+ errout:
+  elf_end (elf);
+
+  arlib_fini ();
+
+  close (fd);
+
+  not_found (argc, argv, found);
+
+  return status;
+}
+
+
+/* Prints the given value in the given buffer without a trailing zero char.
+   Returns false if the given value doesn't fit in the given buffer.  */
+static bool
+no0print (bool ofmt, char *buf, int bufsize, long int val)
+{
+  char tmpbuf[bufsize + 1];
+  int ret = snprintf (tmpbuf, sizeof (tmpbuf), ofmt ? "%-*lo" : "%-*ld",
+		      bufsize, val);
+  if (ret >= (int) sizeof (tmpbuf))
+    return false;
+  memcpy (buf, tmpbuf, bufsize);
+  return true;
+}
+
+
+static int
+do_oper_insert (int oper, const char *arfname, char **argv, int argc,
+		const char *member)
+{
+  int status = 0;
+  Elf *elf = NULL;
+  struct stat st;
+  int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, oper != oper_move);
+
+  /* List of the files we keep.  */
+  struct armem *all = NULL;
+  struct armem *after_memberelem = NULL;
+  struct armem **found = alloca (sizeof (*found) * argc);
+  memset (found, '\0', sizeof (*found) * argc);
+
+  arlib_init ();
+
+  /* Initialize early for no_old case.  */
+  off_t cur_off = SARMAG;
+
+  if (fd == -1)
+    {
+      if (!suppress_create_msg)
+	fprintf (stderr, "%s: creating %s\n",
+		 program_invocation_short_name, arfname);
+
+      goto no_old;
+    }
+
+  /* Store the names of all files from the command line in a hash
+     table so that we can match it.  Note that when no file name is
+     given we are basically doing nothing except recreating the
+     index.  */
+  if (oper != oper_qappend)
+    {
+      if (hcreate (2 * argc) == 0)
+	error_exit (errno, _("cannot create hash table"));
+
+      for (int cnt = 0; cnt < argc; ++cnt)
+	{
+	  ENTRY entry;
+	  entry.key = full_path ? argv[cnt] : (char*)xbasename (argv[cnt]);
+	  entry.data = &argv[cnt];
+	  if (hsearch (entry, ENTER) == NULL)
+	    error_exit (errno, _("cannot insert into hash table"));
+	}
+    }
+
+  /* While iterating over the current content of the archive we must
+     determine a number of things: which archive members to keep,
+     which are replaced, and where to insert the new members.  */
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  Elf *subelf;
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      /* Ignore the symbol table and the long file name table here.  */
+      if (strcmp (arhdr->ar_name, "/") == 0
+	  || strcmp (arhdr->ar_name, "//") == 0)
+	goto next;
+
+      struct armem *newp = alloca (sizeof (struct armem));
+      newp->old_off = elf_getaroff (subelf);
+      newp->size = arhdr->ar_size;
+      newp->sec = arhdr->ar_date;
+      newp->mem = NULL;
+
+      /* Remember long file names.  */
+      remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name));
+
+      /* Check whether this is a file we are looking for.  */
+      if (oper != oper_qappend)
+	{
+	  /* Check whether this is the member used as the insert point.  */
+	  if (member != NULL && strcmp (arhdr->ar_name, member) == 0)
+	    {
+	      /* Note that all == NULL means insert at the beginning.  */
+	      if (ipos == ipos_before)
+		after_memberelem = all;
+	      else
+		after_memberelem = newp;
+	      member = NULL;
+	    }
+
+	  ENTRY entry;
+	  entry.key = arhdr->ar_name;
+	  ENTRY *res = hsearch (entry, FIND);
+	  if (res != NULL && found[(char **) res->data - argv] == NULL)
+	    {
+	      found[(char **) res->data - argv] = newp;
+
+	      /* If we insert before or after a certain element move
+		 all files to a special list.  */
+	      if (unlikely (ipos != ipos_none || oper == oper_move))
+		{
+		  if (after_memberelem == newp)
+		    /* Since we remove this element even though we should
+		       insert everything after it, we in fact insert
+		       everything after the previous element.  */
+		    after_memberelem = all;
+
+		  goto next;
+		}
+	    }
+	}
+
+      if (all == NULL)
+	all = newp->next = newp;
+      else
+	{
+	  newp->next = all->next;
+	  all = all->next = newp;
+	}
+
+    next:
+      cmd = elf_next (subelf);
+      if (elf_end (subelf) != 0)
+	error_exit (0, "%s: %s", arfname, elf_errmsg (-1));
+    }
+
+  if (oper != oper_qappend)
+    hdestroy ();
+
+ no_old:
+  if (member != NULL)
+    error_exit (0, _("position member %s not found"),
+		member);
+
+  if (oper == oper_move)
+    {
+      /* Make sure all requested elements are found in the archive.  */
+      for (int cnt = 0; cnt < argc; ++cnt)
+	{
+	  if (found[cnt] == NULL)
+	    {
+	      fprintf (stderr, _("%s: no entry %s in archive!\n"),
+		       program_invocation_short_name, argv[cnt]);
+	      status = 1;
+	    }
+
+	  if (verbose)
+	    printf ("m - %s\n", argv[cnt]);
+	}
+    }
+  else
+    {
+      /* Open all the new files, get their sizes and add all symbols.  */
+      for (int cnt = 0; cnt < argc; ++cnt)
+	{
+	  const char *bname = xbasename (argv[cnt]);
+	  size_t bnamelen = strlen (bname);
+	  if (found[cnt] == NULL)
+	    {
+	      found[cnt] = alloca (sizeof (struct armem));
+	      found[cnt]->old_off = -1;
+
+	      remember_long_name (found[cnt], bname, bnamelen);
+	    }
+
+	  struct stat newst;
+	  Elf *newelf;
+	  int newfd = open (argv[cnt], O_RDONLY);
+	  if (newfd == -1)
+	    {
+	      error (0, errno, _("cannot open %s"), argv[cnt]);
+	      status = 1;
+	    }
+	  else if (fstat (newfd, &newst) == -1)
+	    {
+	      error (0, errno, _("cannot stat %s"), argv[cnt]);
+	      close (newfd);
+	      status = 1;
+	    }
+	  else if (!S_ISREG (newst.st_mode))
+	    {
+	      error (0, errno, _("%s is no regular file"), argv[cnt]);
+	      close (newfd);
+	      status = 1;
+	    }
+	  else if (update_newer
+		   && found[cnt]->old_off != -1l
+		   && found[cnt]->sec > st.st_mtime)
+	    /* Do nothing, the file in the archive is younger.  */
+	    close (newfd);
+	  else if ((newelf = elf_begin (newfd, ELF_C_READ_MMAP, NULL))
+		   == NULL)
+	    {
+	      fprintf (stderr,
+		       _("cannot get ELF descriptor for %s: %s\n"),
+		       argv[cnt], elf_errmsg (-1));
+	      status = 1;
+	    }
+	  else
+	    {
+	      if (verbose)
+		printf ("%c - %s\n",
+			found[cnt]->old_off == -1l ? 'a' : 'r', argv[cnt]);
+
+	      found[cnt]->elf = newelf;
+	      found[cnt]->sec = arlib_deterministic_output ? 0 : newst.st_mtime;
+	      found[cnt]->uid = arlib_deterministic_output ? 0 : newst.st_uid;
+	      found[cnt]->gid = arlib_deterministic_output ? 0 : newst.st_gid;
+	      found[cnt]->mode = newst.st_mode;
+	      found[cnt]->name = bname;
+
+	      found[cnt]->mem = elf_rawfile (newelf, &found[cnt]->size);
+	      if (found[cnt]->mem == NULL
+		  || elf_cntl (newelf, ELF_C_FDDONE) != 0)
+		error_exit (0, _("cannot read %s: %s"),
+			    argv[cnt], elf_errmsg (-1));
+
+	      close (newfd);
+
+	      if (found[cnt]->old_off != -1l)
+		/* Remember long file names.  */
+		remember_long_name (found[cnt], bname, bnamelen);
+	    }
+	}
+    }
+
+  if (status != 0)
+    {
+      elf_end (elf);
+
+      arlib_fini ();
+
+      close (fd);
+
+      return status;
+    }
+
+  /* If we have no entry point so far add at the end.  AFTER_MEMBERELEM
+     being NULL when adding before an entry means add at the beginning.  */
+  if (ipos != ipos_before && after_memberelem == NULL)
+    after_memberelem = all;
+
+  /* Convert the circular list into a normal list first.  */
+  if (all != NULL)
+    {
+      struct armem *tmp = all;
+      all = all->next;
+      tmp->next = NULL;
+    }
+
+  struct armem *last_added = after_memberelem;
+  for (int cnt = 0; cnt < argc; ++cnt)
+    if (oper != oper_replace || found[cnt]->old_off == -1)
+      {
+	if (last_added == NULL)
+	  {
+	    found[cnt]->next = all;
+	    last_added = all = found[cnt];
+	  }
+	else
+	  {
+	    found[cnt]->next = last_added->next;
+	    last_added = last_added->next = found[cnt];
+	  }
+      }
+
+  /* Finally compute the offset and add the symbols for the files
+     after the insert point.  */
+  if (likely (all != NULL))
+    for (struct armem *memp = all; memp != NULL; memp = memp->next)
+      {
+	memp->off = cur_off;
+
+	if (memp->mem == NULL)
+	  {
+	    Elf_Arhdr *arhdr;
+	    /* Fake initializing arhdr and subelf to keep gcc calm.  */
+	    asm ("" : "=m" (arhdr), "=m" (subelf));
+	    if (elf_rand (elf, memp->old_off) == 0
+		|| (subelf = elf_begin (fd, ELF_C_READ_MMAP, elf)) == NULL
+		|| (arhdr = elf_getarhdr (subelf)) == NULL)
+	      /* This should never happen since we already looked at the
+		 archive content.  But who knows...  */
+	      error_exit (0, "%s: %s", arfname, elf_errmsg (-1));
+
+	    arlib_add_symbols (subelf, arfname, arhdr->ar_name, cur_off);
+
+	    elf_end (subelf);
+	  }
+	else
+	  arlib_add_symbols (memp->elf, arfname, memp->name, cur_off);
+
+	cur_off += (((memp->size + 1) & ~((off_t) 1))
+		    + sizeof (struct ar_hdr));
+      }
+
+  /* Now we have all the information for the symbol table and long
+     file name table.  Construct the final layout.  */
+  arlib_finalize ();
+
+  /* Create a new, temporary file in the same directory as the
+     original file.  */
+  char tmpfname[strlen (arfname) + 7];
+  strcpy (stpcpy (tmpfname, arfname), "XXXXXX");
+  int newfd;
+  if (fd != -1)
+    newfd = mkstemp (tmpfname);
+  else
+    {
+      newfd = open (arfname, O_RDWR | O_CREAT | O_EXCL, DEFFILEMODE);
+      if (newfd == -1 && errno == EEXIST)
+	/* Bah, first the file did not exist, now it does.  Restart.  */
+	return do_oper_insert (oper, arfname, argv, argc, member);
+    }
+  if (unlikely (newfd == -1))
+    goto nonew;
+
+  /* Create the header.  */
+  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
+    {
+    nonew_unlink:
+      if (fd != -1)
+	{
+	  // XXX Use /prof/self/fd/%d ???
+	  unlink (tmpfname);
+	  if (newfd != -1)
+	    close (newfd);
+	}
+    nonew:
+      error (0, errno, _("cannot create new file"));
+      status = 1;
+      goto errout;
+    }
+
+  /* If the new archive is not empty we actually have something to do.  */
+  if (likely (all != NULL))
+    {
+      /* Write the symbol table or the long file name table or both.  */
+      if (symtab.symsnamelen != 0
+	  && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen)
+	       != (ssize_t) symtab.symsofflen)
+	      || (write_retry (newfd, symtab.symsname, symtab.symsnamelen)
+		  != (ssize_t) symtab.symsnamelen)))
+	goto nonew_unlink;
+
+      if (symtab.longnameslen > sizeof (struct ar_hdr)
+	  && (write_retry (newfd, symtab.longnames, symtab.longnameslen)
+	      != (ssize_t) symtab.longnameslen))
+	goto nonew_unlink;
+
+      off_t start = -1;
+      off_t len = -1;
+
+      while (all != NULL)
+	{
+	  if (all->mem != NULL)
+	    {
+	      /* This is a new file.  If there is anything from the
+		 archive left to be written do it now.  */
+	      if (start != -1  && copy_content (elf, newfd, start, len))
+		goto nonew_unlink;
+
+	      start = -1;
+	      len = -1;
+
+	      /* Create the header.  */
+	      struct ar_hdr arhdr;
+	      /* The ar_name is not actually zero terminated, but we
+		 need that for snprintf.  Also if the name is too
+		 long, then the string starts with '/' plus an index
+		 off number (decimal).  */
+	      char tmpbuf[sizeof (arhdr.ar_name) + 2];
+	      if (all->long_name_off == -1)
+		{
+		  size_t namelen = strlen (all->name);
+		  char *p = mempcpy (arhdr.ar_name, all->name, namelen);
+		  *p++ = '/';
+		  memset (p, ' ', sizeof (arhdr.ar_name) - namelen - 1);
+		}
+	      else
+		{
+		  snprintf (tmpbuf, sizeof (tmpbuf), "/%-*ld",
+			    (int) sizeof (arhdr.ar_name), all->long_name_off);
+		  memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name));
+		}
+
+	      if (! no0print (false, arhdr.ar_date, sizeof (arhdr.ar_date),
+			      all->sec))
+		{
+		  error (0, errno, _("cannot represent ar_date"));
+		  goto nonew_unlink;
+		}
+	      if (! no0print (false, arhdr.ar_uid, sizeof (arhdr.ar_uid),
+			      all->uid))
+		{
+		  error (0, errno, _("cannot represent ar_uid"));
+		  goto nonew_unlink;
+		}
+	      if (! no0print (false, arhdr.ar_gid, sizeof (arhdr.ar_gid),
+			      all->gid))
+		{
+		  error (0, errno, _("cannot represent ar_gid"));
+		  goto nonew_unlink;
+		}
+	      if (! no0print (true, arhdr.ar_mode, sizeof (arhdr.ar_mode),
+			all->mode))
+		{
+		  error (0, errno, _("cannot represent ar_mode"));
+		  goto nonew_unlink;
+		}
+	      if (! no0print (false, arhdr.ar_size, sizeof (arhdr.ar_size),
+			all->size))
+		{
+		  error (0, errno, _("cannot represent ar_size"));
+		  goto nonew_unlink;
+		}
+	      memcpy (arhdr.ar_fmag, ARFMAG, sizeof (arhdr.ar_fmag));
+
+	      if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr))
+			    != sizeof (arhdr)))
+		goto nonew_unlink;
+
+	      /* Now the file itself.  */
+	      if (unlikely (write_retry (newfd, all->mem, all->size)
+			    != (off_t) all->size))
+		goto nonew_unlink;
+
+	      /* Pad the file if its size is odd.  */
+	      if ((all->size & 1) != 0)
+		if (unlikely (write_retry (newfd, "\n", 1) != 1))
+		  goto nonew_unlink;
+	    }
+	  else
+	    {
+	      /* This is a member from the archive.  */
+	      if (write_member (all, &start, &len, elf, cur_off, newfd)
+		  != 0)
+		goto nonew_unlink;
+	    }
+
+	  all = all->next;
+	}
+
+      /* Write the last part.  */
+      if (start != -1 && copy_content (elf, newfd, start, len))
+	goto nonew_unlink;
+    }
+
+  /* Set the mode of the new file to the same values the original file
+     has.  */
+  if (fd != -1)
+    {
+      /* Never complain about fchown failing.  But do it before
+	 setting the modes, or they might be reset/ignored if the
+	 owner is wrong.  */
+      if (fchown (newfd, st.st_uid, st.st_gid) != 0) { ; }
+      if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
+	  || close (newfd) != 0)
+        goto nonew_unlink;
+      newfd = -1;
+      if (rename (tmpfname, arfname) != 0)
+	goto nonew_unlink;
+    }
+
+ errout:
+  for (int cnt = 0; cnt < argc; ++cnt)
+    elf_end (found[cnt]->elf);
+
+  elf_end (elf);
+
+  arlib_fini ();
+
+  if (fd != -1)
+    close (fd);
+
+  if (newfd != -1)
+    close (newfd);
+
+  return status;
+}
+
+
+#include "debugpred.h"
diff --git a/src/arlib-argp.c b/src/arlib-argp.c
new file mode 100644
index 0000000..115b9d7
--- /dev/null
+++ b/src/arlib-argp.c
@@ -0,0 +1,94 @@
+/* Options common to ar and ranlib.
+   Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+
+#include "arlib.h"
+
+bool arlib_deterministic_output = DEFAULT_AR_DETERMINISTIC;
+
+static const struct argp_option options[] =
+  {
+    { NULL, 'D', NULL, 0,
+      N_("Use zero for uid, gid, and date in archive members."), 0 },
+    { NULL, 'U', NULL, 0,
+      N_("Use actual uid, gid, and date in archive members."), 0 },
+
+    { NULL, 0, NULL, 0, NULL, 0 }
+  };
+
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+           struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'D':
+      arlib_deterministic_output = true;
+      break;
+
+    case 'U':
+      arlib_deterministic_output = false;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static char *
+text_for_default (const char *text)
+{
+  char *new_text;
+  if (unlikely (asprintf (&new_text, _("%s (default)"), text) < 0))
+    return (char *) text;
+  return new_text;
+}
+
+static char *
+help_filter (int key, const char *text, void *input __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'D':
+      if (DEFAULT_AR_DETERMINISTIC)
+        return text_for_default (text);
+      break;
+    case 'U':
+      if (! DEFAULT_AR_DETERMINISTIC)
+        return text_for_default (text);
+      break;
+    }
+
+  return (char *) text;
+}
+
+static const struct argp argp =
+  {
+    options, parse_opt, NULL, NULL, NULL, help_filter, NULL
+  };
+
+const struct argp_child arlib_argp_children[] =
+  {
+    { &argp, 0, "", 2 },
+    { NULL, 0, NULL, 0 }
+  };
diff --git a/src/arlib.c b/src/arlib.c
new file mode 100644
index 0000000..b8f89ba
--- /dev/null
+++ b/src/arlib.c
@@ -0,0 +1,279 @@
+/* Functions to handle creation of Linux archives.
+   Copyright (C) 2007-2012, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#include <libeu.h>
+
+#include "system.h"
+#include "arlib.h"
+
+
+/* The one symbol table we hanble.  */
+struct arlib_symtab symtab;
+
+
+/* Initialize ARLIB_SYMTAB structure.  */
+void
+arlib_init (void)
+{
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+  obstack_init (&symtab.symsoffob);
+  obstack_init (&symtab.symsnameob);
+  obstack_init (&symtab.longnamesob);
+
+  /* We add the archive header here as well, that avoids allocating
+     another memory block.  */
+  struct ar_hdr ar_hdr;
+  memcpy (ar_hdr.ar_name, "/               ", sizeof (ar_hdr.ar_name));
+  /* Using snprintf here has a problem: the call always wants to add a
+     NUL byte.  We could use a trick whereby we specify the target
+     buffer size longer than it is and this would not actually fail,
+     since all the fields are consecutive and we fill them in
+     sequence (i.e., the NUL byte gets overwritten).  But
+     _FORTIFY_SOURCE=2 would not let us play these games.  Therefore
+     we play it safe.  */
+  char tmpbuf[sizeof (ar_hdr.ar_date) + 1];
+  int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*lld",
+		    (int) sizeof (ar_hdr.ar_date),
+                    (arlib_deterministic_output ? 0
+                     : (long long int) time (NULL)));
+  memcpy (ar_hdr.ar_date, tmpbuf, s);
+  assert ((sizeof (struct ar_hdr)  % sizeof (uint32_t)) == 0);
+
+  /* Note the string for the ar_uid and ar_gid cases is longer than
+     necessary.  This does not matter since we copy only as much as
+     necessary but it helps the compiler to use the same string for
+     the ar_mode case.  */
+  memcpy (ar_hdr.ar_uid, "0       ", sizeof (ar_hdr.ar_uid));
+  memcpy (ar_hdr.ar_gid, "0       ", sizeof (ar_hdr.ar_gid));
+  memcpy (ar_hdr.ar_mode, "0       ", sizeof (ar_hdr.ar_mode));
+  memcpy (ar_hdr.ar_fmag, ARFMAG, sizeof (ar_hdr.ar_fmag));
+
+  /* Add the archive header to the file content.  */
+  obstack_grow (&symtab.symsoffob, &ar_hdr, sizeof (ar_hdr));
+
+  /* The first word in the offset table specifies the size.  Create
+     such an entry now.  The real value will be filled-in later.  For
+     all supported platforms the following is true.  */
+  assert (sizeof (uint32_t) == sizeof (int));
+  obstack_int_grow (&symtab.symsoffob, 0);
+
+  /* The long name obstack also gets its archive header.  As above,
+     some of the input strings are longer than required but we only
+     copy the necessary part.  */
+  memcpy (ar_hdr.ar_name, "//              ", sizeof (ar_hdr.ar_name));
+  memcpy (ar_hdr.ar_date, "            ", sizeof (ar_hdr.ar_date));
+  memcpy (ar_hdr.ar_uid, "            ", sizeof (ar_hdr.ar_uid));
+  memcpy (ar_hdr.ar_gid, "            ", sizeof (ar_hdr.ar_gid));
+  memcpy (ar_hdr.ar_mode, "            ", sizeof (ar_hdr.ar_mode));
+  /* The ar_size field will be filled in later and ar_fmag is already OK.  */
+  obstack_grow (&symtab.longnamesob, &ar_hdr, sizeof (ar_hdr));
+
+  /* All other members are zero.  */
+  symtab.symsofflen = 0;
+  symtab.symsoff = NULL;
+  symtab.symsnamelen = 0;
+  symtab.symsname = NULL;
+}
+
+
+/* Finalize ARLIB_SYMTAB content.  */
+void
+arlib_finalize (void)
+{
+  /* Note that the size is stored as decimal string in 10 chars,
+     without zero terminator (we add + 1 here only so snprintf can
+     put it at the end, we then don't use it when we memcpy it).  */
+  char tmpbuf[sizeof (((struct ar_hdr *) NULL)->ar_size) + 1];
+
+  symtab.longnameslen = obstack_object_size (&symtab.longnamesob);
+  if (symtab.longnameslen != sizeof (struct ar_hdr))
+    {
+      if ((symtab.longnameslen & 1) != 0)
+	{
+	  /* Add one more byte to make length even.  */
+	  obstack_grow (&symtab.longnamesob, "\n", 1);
+	  ++symtab.longnameslen;
+	}
+
+      symtab.longnames = obstack_finish (&symtab.longnamesob);
+
+      int s = snprintf (tmpbuf, sizeof (tmpbuf), "%-*" PRIu32 "",
+			(int) sizeof (((struct ar_hdr *) NULL)->ar_size),
+			(uint32_t) (symtab.longnameslen - sizeof (struct ar_hdr)));
+      memcpy (&((struct ar_hdr *) symtab.longnames)->ar_size, tmpbuf, s);
+    }
+
+  symtab.symsofflen = obstack_object_size (&symtab.symsoffob);
+  assert (symtab.symsofflen % sizeof (uint32_t) == 0);
+  if (symtab.symsofflen != 0)
+    {
+      symtab.symsoff = (uint32_t *) obstack_finish (&symtab.symsoffob);
+
+      /* Fill in the number of offsets now.  */
+      symtab.symsoff[AR_HDR_WORDS] = le_bswap_32 ((symtab.symsofflen
+						    - sizeof (struct ar_hdr))
+						   / sizeof (uint32_t) - 1);
+    }
+
+  symtab.symsnamelen = obstack_object_size (&symtab.symsnameob);
+  if ((symtab.symsnamelen & 1) != 0)
+    {
+      /* Add one more NUL byte to make length even.  */
+      obstack_grow (&symtab.symsnameob, "", 1);
+      ++symtab.symsnamelen;
+    }
+  symtab.symsname = obstack_finish (&symtab.symsnameob);
+
+  /* Determine correction for the offsets in the symbol table.   */
+  off_t disp = 0;
+  if (symtab.symsnamelen > 0)
+    disp = symtab.symsofflen + symtab.symsnamelen;
+  if (symtab.longnameslen > sizeof (struct ar_hdr))
+    disp += symtab.longnameslen;
+
+  if (disp != 0 && symtab.symsoff != NULL)
+    {
+      uint32_t nsyms = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS]);
+
+      for (uint32_t cnt = 1; cnt <= nsyms; ++cnt)
+	{
+	  uint32_t val = le_bswap_32 (symtab.symsoff[AR_HDR_WORDS + cnt]);
+	  val += disp;
+	  symtab.symsoff[AR_HDR_WORDS + cnt] = le_bswap_32 (val);
+	}
+    }
+
+  /* See comment for ar_date above.  */
+  memcpy (&((struct ar_hdr *) symtab.symsoff)->ar_size, tmpbuf,
+	  snprintf (tmpbuf, sizeof (tmpbuf), "%-*" PRIu32 "",
+		    (int) sizeof (((struct ar_hdr *) NULL)->ar_size),
+		    (uint32_t) (symtab.symsofflen + symtab.symsnamelen
+				- sizeof (struct ar_hdr))));
+}
+
+
+/* Free resources for ARLIB_SYMTAB.  */
+void
+arlib_fini (void)
+{
+  obstack_free (&symtab.symsoffob, NULL);
+  obstack_free (&symtab.symsnameob, NULL);
+  obstack_free (&symtab.longnamesob, NULL);
+}
+
+
+/* Add name a file offset of a symbol.  */
+void
+arlib_add_symref (const char *symname, off_t symoff)
+{
+  /* For all supported platforms the following is true.  */
+  assert (sizeof (uint32_t) == sizeof (int));
+  obstack_int_grow (&symtab.symsoffob, (int) le_bswap_32 (symoff));
+
+  size_t symname_len = strlen (symname) + 1;
+  obstack_grow (&symtab.symsnameob, symname, symname_len);
+}
+
+
+/* Add symbols from ELF with value OFFSET to the symbol table SYMTAB.  */
+void
+arlib_add_symbols (Elf *elf, const char *arfname, const char *membername,
+		   off_t off)
+{
+  if (sizeof (off) > sizeof (uint32_t) && off > ~((uint32_t) 0))
+    /* The archive is too big.  */
+    error_exit (0, _("the archive '%s' is too large"),
+		arfname);
+
+  /* We only add symbol tables for ELF files.  It makes not much sense
+     to add symbols from executables but we do so for compatibility.
+     For DSOs and executables we use the dynamic symbol table, for
+     relocatable files all the DT_SYMTAB tables.  */
+  if (elf_kind (elf) != ELF_K_ELF)
+    return;
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    error_exit (0, _("cannot read ELF header of %s(%s): %s"),
+		arfname, membername, elf_errmsg (-1));
+
+  GElf_Word symtype;
+  if (ehdr->e_type == ET_REL)
+    symtype = SHT_SYMTAB;
+  else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
+    symtype = SHT_DYNSYM;
+  else
+    /* We do not handle that type.  */
+    return;
+
+  /* Iterate over all sections.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      /* Get the section header.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	continue;
+
+      if (shdr->sh_type != symtype)
+	continue;
+
+      Elf_Data *data = elf_getdata (scn, NULL);
+      if (data == NULL)
+	continue;
+
+      if (shdr->sh_entsize == 0)
+	continue;
+
+      int nsyms = shdr->sh_size / shdr->sh_entsize;
+      for (int ndx = shdr->sh_info; ndx < nsyms; ++ndx)
+	{
+	  GElf_Sym sym_mem;
+	  GElf_Sym *sym = gelf_getsym (data, ndx, &sym_mem);
+	  if (sym == NULL)
+	    continue;
+
+	  /* Ignore undefined symbols.  */
+	  if (sym->st_shndx == SHN_UNDEF)
+	    continue;
+
+	  /* Use this symbol.  */
+	  const char *symname = elf_strptr (elf, shdr->sh_link, sym->st_name);
+	  if (symname != NULL)
+	    arlib_add_symref (symname, off);
+	}
+
+      /* Only relocatable files can have more than one symbol table.  */
+      if (ehdr->e_type != ET_REL)
+	break;
+    }
+}
diff --git a/src/arlib.h b/src/arlib.h
new file mode 100644
index 0000000..d4a4221
--- /dev/null
+++ b/src/arlib.h
@@ -0,0 +1,98 @@
+/* Copyright (C) 2007-2012 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ARLIB_H
+#define _ARLIB_H	1
+
+#include <ar.h>
+#include <argp.h>
+#include <byteswap.h>
+#include <endian.h>
+#include <libelf.h>
+#include <obstack.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <sys/types.h>
+
+
+/* State of -D/-U flags.  */
+extern bool arlib_deterministic_output;
+
+/* For options common to ar and ranlib.  */
+extern const struct argp_child arlib_argp_children[];
+
+
+/* Maximum length of a file name that fits directly into the ar header.
+   We cannot use the final byte since a / goes there.  */
+#define MAX_AR_NAME_LEN (sizeof (((struct ar_hdr *) NULL)->ar_name) - 1)
+
+
+/* Words matching in size to archive header.  */
+#define AR_HDR_WORDS (sizeof (struct ar_hdr) / sizeof (uint32_t))
+
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+# define le_bswap_32(val) bswap_32 (val)
+#else
+# define le_bswap_32(val) (val)
+#endif
+
+
+/* Symbol table type.  */
+struct arlib_symtab
+{
+  /* Symbol table handling.  */
+  struct obstack symsoffob;
+  struct obstack symsnameob;
+  size_t symsofflen;
+  uint32_t *symsoff;
+  size_t symsnamelen;
+  char *symsname;
+
+  /* Long filename handling.  */
+  struct obstack longnamesob;
+  size_t longnameslen;
+  char *longnames;
+};
+
+
+/* Global variable with symbol table.  */
+extern struct arlib_symtab symtab;
+
+
+/* Initialize ARLIB_SYMTAB structure.  */
+extern void arlib_init (void);
+
+/* Finalize ARLIB_SYMTAB content.  */
+extern void arlib_finalize (void);
+
+/* Free resources for ARLIB_SYMTAB.  */
+extern void arlib_fini (void);
+
+/* Add symbols from ELF with value OFFSET to the symbol table SYMTAB.  */
+extern void arlib_add_symbols (Elf *elf, const char *arfname,
+			       const char *membername, off_t off);
+
+/* Add name a file offset of a symbol.  */
+extern void arlib_add_symref (const char *symname, off_t symoff);
+
+/* Add long file name FILENAME of length FILENAMELEN to the symbol table
+   SYMTAB.  Return the offset into the long file name table.  */
+extern long int arlib_add_long_name (const char *filename, size_t filenamelen);
+
+#endif	/* arlib.h */
diff --git a/src/arlib2.c b/src/arlib2.c
new file mode 100644
index 0000000..9ae6662
--- /dev/null
+++ b/src/arlib2.c
@@ -0,0 +1,40 @@
+/* Functions to handle creation of Linux archives.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <limits.h>
+#include <string.h>
+
+#include "arlib.h"
+
+
+/* Add long file name FILENAME of length FILENAMELEN to the symbol table
+   SYMTAB.  Return the offset into the long file name table.  */
+long int
+arlib_add_long_name (const char *filename, size_t filenamelen)
+{
+  size_t size = obstack_object_size (&symtab.longnamesob);
+
+  obstack_grow (&symtab.longnamesob, filename, filenamelen);
+  obstack_grow (&symtab.longnamesob, "/\n", 2);
+
+  return size - sizeof (struct ar_hdr);
+}
diff --git a/src/debugpred.h b/src/debugpred.h
new file mode 100644
index 0000000..4845a6e
--- /dev/null
+++ b/src/debugpred.h
@@ -0,0 +1,45 @@
+/* Support to debug branch prediction.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stdio.h>
+
+#if DEBUGPRED
+extern const unsigned long int __start_predict_data;
+extern const unsigned long int __stop_predict_data;
+extern const unsigned long int __start_predict_line;
+extern const char *const __start_predict_file;
+
+static void
+__attribute__ ((destructor))
+predprint (void)
+{
+  const unsigned long int *s = &__start_predict_data;
+  const unsigned long int *e = &__stop_predict_data;
+  const unsigned long int *sl = &__start_predict_line;
+  const char *const *sf = &__start_predict_file;
+  while (s < e)
+    {
+      if (s[0] != 0 || s[1] != 0)
+	printf ("%s:%lu: wrong=%lu, correct=%lu%s\n", *sf, *sl, s[0], s[1],
+		s[0] > s[1] ? "   <==== WARNING" : "");
+      ++sl;
+      ++sf;
+      s += 2;
+    }
+}
+#endif
diff --git a/src/elfclassify.c b/src/elfclassify.c
new file mode 100644
index 0000000..25fe9a6
--- /dev/null
+++ b/src/elfclassify.c
@@ -0,0 +1,1044 @@
+/* Classification of ELF files.
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <system.h>
+
+#include <argp.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include ELFUTILS_HEADER(dwelf)
+#include "printversion.h"
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Set by parse_opt.  */
+static int verbose;
+
+/* Set by the main function.  */
+static const char *current_path;
+
+/* Set by open_file.  */
+static int file_fd = -1;
+
+/* Set by issue or elf_issue.  */
+static bool issue_found;
+
+/* Non-fatal issue occurred while processing the current_path.  */
+static void
+issue (int e, const char *msg)
+{
+  if (verbose >= 0)
+    {
+      if (current_path == NULL)
+	error (0, e, "%s", msg);
+      else
+	error (0, e, "%s '%s'", msg, current_path);
+    }
+  issue_found = true;
+}
+
+/* Non-fatal issue occurred while processing the current ELF.  */
+static void
+elf_issue (const char *msg)
+{
+  if (verbose >= 0)
+    error (0, 0, "%s: %s: '%s'", msg, elf_errmsg (-1), current_path);
+  issue_found = true;
+}
+
+/* Set by parse_opt.  */
+static bool flag_only_regular_files;
+
+static bool
+open_file (void)
+{
+  if (verbose > 1)
+    fprintf (stderr, "debug: processing file: %s\n", current_path);
+
+  file_fd = open (current_path, O_RDONLY | (flag_only_regular_files
+					    ? O_NOFOLLOW : 0));
+  if (file_fd < 0)
+    {
+      if (!flag_only_regular_files || errno != ELOOP)
+	issue (errno, N_("opening"));
+      return false;
+    }
+
+  struct stat st;
+  if (fstat (file_fd, &st) != 0)
+    {
+      issue (errno, N_("reading"));
+      return false;
+    }
+
+  /* Don't even bother with directories.  */
+  if (S_ISDIR (st.st_mode)
+      || (flag_only_regular_files && !S_ISREG (st.st_mode)))
+    return false;
+
+  return true;
+}
+
+static void
+close_file (void)
+{
+  if (file_fd >= 0)
+    {
+      close (file_fd);
+      file_fd = -1;
+    }
+}
+
+/* Set by open_elf.  */
+static Elf *elf;
+
+/* Set by parse_opt.  */
+static bool flag_compressed;
+
+static bool
+open_elf (void)
+{
+  if (!open_file ())
+    {
+      /* Make sure the file descriptor is gone.  */
+      close_file ();
+      return false;
+    }
+
+  if (flag_compressed)
+    elf = dwelf_elf_begin (file_fd);
+  else
+    elf = elf_begin (file_fd, ELF_C_READ, NULL);
+
+  if (elf == NULL)
+    {
+      elf_issue ("opening ELF file");
+      close_file ();
+      return false;
+    }
+
+  return true;
+}
+
+static void
+close_elf (void)
+{
+  if (elf != NULL)
+    {
+      elf_end (elf);
+      elf = NULL;
+    }
+
+  close_file ();
+}
+
+static const char *
+elf_kind_string (int kind)
+{
+  switch (kind)
+    {
+    case ELF_K_NONE:
+      return "ELF_K_NONE";
+    case ELF_K_AR:
+      return "ELF_K_AR";
+    case ELF_K_COFF:
+      return "ELF_K_COFF"; /* libelf doesn't really support this.  */
+    case ELF_K_ELF:
+      return "ELF_K_ELF";
+    default:
+      return "<unknown>";
+    }
+}
+
+static const char *
+elf_type_string (int type)
+{
+  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";
+    default:
+      return "<unknown>";
+    }
+}
+
+static int elf_type;
+static bool has_program_load;
+static bool has_sections;
+static bool has_bits_alloc;
+static bool has_program_interpreter;
+static bool has_dynamic;
+static bool has_soname;
+static bool has_pie_flag;
+static bool has_dt_debug;
+static bool has_symtab;
+static bool has_debug_sections;
+static bool has_modinfo;
+static bool has_gnu_linkonce_this_module;
+
+static bool
+run_classify (void)
+{
+  /* Reset to unanalyzed default.  */
+  elf_type = 0;
+  has_program_load = false;
+  has_sections = false;
+  has_bits_alloc = false;
+  has_program_interpreter = false;
+  has_dynamic = false;
+  has_soname = false;
+  has_pie_flag = false;
+  has_dt_debug = false;
+  has_symtab = false;
+  has_debug_sections = false;
+  has_modinfo = false;
+  has_gnu_linkonce_this_module = false;
+
+  int kind = elf_kind (elf);
+  if (verbose > 0)
+    fprintf (stderr, "info: %s: ELF kind: %s (0x%x)\n", current_path,
+	     elf_kind_string (kind), kind);
+  if (kind != ELF_K_ELF)
+    return true;
+
+  GElf_Ehdr ehdr_storage;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_storage);
+  if (ehdr == NULL)
+    {
+      elf_issue (N_("ELF header"));
+      return false;
+    }
+  elf_type = ehdr->e_type;
+
+  /* Examine program headers.  */
+  GElf_Phdr dyn_seg = { .p_type = 0 };
+  {
+    size_t nphdrs;
+    if (elf_getphdrnum (elf, &nphdrs) != 0)
+      {
+	elf_issue (N_("program headers"));
+	return false;
+      }
+    for (size_t phdr_idx = 0; phdr_idx < nphdrs; ++phdr_idx)
+      {
+	GElf_Phdr phdr_storage;
+	GElf_Phdr *phdr = gelf_getphdr (elf, phdr_idx, &phdr_storage);
+	if (phdr == NULL)
+	  {
+	    elf_issue (N_("program header"));
+	    return false;
+	  }
+	if (phdr->p_type == PT_DYNAMIC)
+	  {
+	    dyn_seg = *phdr;
+	    has_dynamic = true;
+	  }
+	if (phdr->p_type == PT_INTERP)
+	  has_program_interpreter = true;
+	if (phdr->p_type == PT_LOAD)
+	  has_program_load = true;
+      }
+  }
+
+  /* Do we have sections?  */
+  {
+    size_t nshdrs;
+    if (elf_getshdrnum (elf, &nshdrs) != 0)
+      {
+	elf_issue (N_("section headers"));
+	return false;
+      }
+    if (nshdrs > 0)
+      has_sections = true;
+  }
+
+  {
+    size_t shstrndx;
+    if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
+      {
+	elf_issue (N_("section header string table index"));
+	return false;
+      }
+
+    Elf_Scn *scn = NULL;
+    while (true)
+      {
+        scn = elf_nextscn (elf, scn);
+        if (scn == NULL)
+          break;
+        GElf_Shdr shdr_storage;
+        GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_storage);
+        if (shdr == NULL)
+	  {
+            elf_issue (N_("could not obtain section header"));
+	    return false;
+	  }
+        const char *section_name = elf_strptr (elf, shstrndx, shdr->sh_name);
+        if (section_name == NULL)
+	  {
+            elf_issue(N_("could not obtain section name"));
+	    return false;
+	  }
+        if (verbose > 2)
+          fprintf (stderr, "debug: section header %s (type %d) found\n",
+                   section_name, shdr->sh_type);
+        if (shdr->sh_type == SHT_SYMTAB)
+          {
+            if (verbose > 1)
+              fputs ("debug: symtab section found\n", stderr);
+            has_symtab = true;
+          }
+	/* NOBITS and NOTE sections can be in any file.  We want to be
+	   sure there is at least one other allocated section.  */
+	if (shdr->sh_type != SHT_NOBITS
+	    && shdr->sh_type != SHT_NOTE
+	    && (shdr->sh_flags & SHF_ALLOC) != 0)
+	  {
+	    if (verbose > 1 && !has_bits_alloc)
+	      fputs ("debug: allocated (non-nobits/note) section found\n",
+		     stderr);
+	    has_bits_alloc = true;
+	  }
+        if (startswith (section_name, ".debug_")
+	    || startswith (section_name, ".zdebug_"))
+          {
+            if (verbose > 1 && !has_debug_sections)
+              fputs ("debug: .debug_* section found\n", stderr);
+            has_debug_sections = true;
+          }
+	if (strcmp (section_name, ".modinfo") == 0)
+	  {
+	    if (verbose > 1)
+	      fputs ("debug: .modinfo section found\n", stderr);
+	    has_modinfo = true;
+	  }
+	if (strcmp (section_name, ".gnu.linkonce.this_module") == 0)
+	  {
+	    if (verbose > 1)
+	      fputs ("debug: .gnu.linkonce.this_module section found\n",
+		     stderr);
+	    has_gnu_linkonce_this_module = true;
+	  }
+      }
+  }
+
+  /* Examine the dynamic section.  */
+  if (has_dynamic)
+    {
+      Elf_Data *data = elf_getdata_rawchunk (elf, dyn_seg.p_offset,
+					     dyn_seg.p_filesz,
+					     ELF_T_DYN);
+      if (data != NULL)
+	for (int dyn_idx = 0; ; ++dyn_idx)
+	  {
+	    GElf_Dyn dyn_storage;
+	    GElf_Dyn *dyn = gelf_getdyn (data, dyn_idx, &dyn_storage);
+	    if (dyn == NULL)
+	      break;
+	    if (verbose > 2)
+	      fprintf (stderr, "debug: dynamic entry %d"
+		       " with tag %llu found\n",
+		       dyn_idx, (unsigned long long int) dyn->d_tag);
+	    if (dyn->d_tag == DT_SONAME)
+	      has_soname = true;
+	    if (dyn->d_tag == DT_FLAGS_1 && (dyn->d_un.d_val & DF_1_PIE))
+	      has_pie_flag = true;
+	    if (dyn->d_tag == DT_DEBUG)
+	      has_dt_debug = true;
+	    if (dyn->d_tag == DT_NULL)
+	      break;
+	  }
+    }
+
+  if (verbose > 0)
+    {
+      fprintf (stderr, "info: %s: ELF type: %s (0x%x)\n", current_path,
+	       elf_type_string (elf_type), elf_type);
+      if (has_program_load)
+        fprintf (stderr, "info: %s: PT_LOAD found\n", current_path);
+      if (has_sections)
+	fprintf (stderr, "info: %s: has sections\n", current_path);
+      if (has_bits_alloc)
+	fprintf (stderr, "info: %s: allocated (real) section found\n",
+		 current_path);
+      if (has_program_interpreter)
+        fprintf (stderr, "info: %s: program interpreter found\n",
+                 current_path);
+      if (has_dynamic)
+        fprintf (stderr, "info: %s: dynamic segment found\n", current_path);
+      if (has_soname)
+        fprintf (stderr, "info: %s: soname found\n", current_path);
+      if (has_pie_flag)
+        fprintf (stderr, "info: %s: DF_1_PIE flag found\n", current_path);
+      if (has_dt_debug)
+        fprintf (stderr, "info: %s: DT_DEBUG found\n", current_path);
+      if (has_symtab)
+        fprintf (stderr, "info: %s: symbol table found\n", current_path);
+      if (has_debug_sections)
+        fprintf (stderr, "info: %s: .debug_* section found\n", current_path);
+      if (has_modinfo)
+        fprintf (stderr, "info: %s: .modinfo section found\n", current_path);
+      if (has_gnu_linkonce_this_module)
+        fprintf (stderr,
+		 "info: %s: .gnu.linkonce.this_module section found\n",
+		 current_path);
+    }
+
+  return true;
+}
+
+static bool
+is_elf (void)
+{
+  return elf_kind (elf) != ELF_K_NONE;
+}
+
+static bool
+is_elf_file (void)
+{
+  return elf_kind (elf) == ELF_K_ELF;
+}
+
+static bool
+is_elf_archive (void)
+{
+  return elf_kind (elf) == ELF_K_AR;
+}
+
+static bool
+is_core (void)
+{
+  return elf_kind (elf) == ELF_K_ELF && elf_type == ET_CORE;
+}
+
+/* Return true if the file is a loadable object, which basically means
+   it is an ELF file, but not a relocatable object or a core dump
+   file.  (The kernel and various userspace components can load ET_REL
+   files, but we disregard that for our classification purposes.)  */
+static bool
+is_loadable (void)
+{
+  return elf_kind (elf) == ELF_K_ELF
+    && (elf_type == ET_EXEC || elf_type == ET_DYN)
+    && has_program_load
+    && (!has_sections || has_bits_alloc); /* It isn't debug-only.  */
+}
+
+/* Return true if the file is an ELF file which has a symbol table or
+   .debug_* sections (and thus can be stripped further).  */
+static bool
+is_unstripped (void)
+{
+  return elf_kind (elf) != ELF_K_NONE
+    && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN)
+    && (has_symtab || has_debug_sections);
+}
+
+/* Return true if the file contains only debuginfo, but no loadable
+   program bits.  Then it is most likely a separate .debug file, a dwz
+   multi-file or a .dwo file.  Note that it can still be loadable,
+   but in that case the phdrs shouldn't be trusted.  */
+static bool
+is_debug_only (void)
+{
+  return elf_kind (elf) != ELF_K_NONE
+    && (elf_type == ET_REL || elf_type == ET_EXEC || elf_type == ET_DYN)
+    && (has_debug_sections || has_symtab)
+    && !has_bits_alloc;
+}
+
+static bool
+is_shared (void)
+{
+  if (!is_loadable ())
+    return false;
+
+  /* The ELF type is very clear: this is an executable.  */
+  if (elf_type == ET_EXEC)
+    return false;
+
+  /* If there is no dynamic section, the file cannot be loaded as a
+     shared object.  */
+  if (!has_dynamic)
+    return false;
+
+  /* If the object is marked as PIE, it is definitely an executable,
+     and not a loadlable shared object.  */
+  if (has_pie_flag)
+    return false;
+
+  /* Treat a DT_SONAME tag as a strong indicator that this is a shared
+     object.  */
+  if (has_soname)
+    return true;
+
+  /* This is probably a PIE program: there is no soname, but a program
+     interpreter.  In theory, this file could be also a DSO with a
+     soname implied by its file name that can be run as a program.
+     This situation is impossible to resolve in the general case. */
+  if (has_program_interpreter)
+    return false;
+
+  /* Roland McGrath mentions in
+     <https://www.sourceware.org/ml/libc-alpha/2015-03/msg00605.html>,
+     that “we defined a PIE as an ET_DYN with a DT_DEBUG”.  This
+     matches current binutils behavior (version 2.32).  DT_DEBUG is
+     added if bfd_link_executable returns true or if bfd_link_pic
+     returns false, depending on the architectures.  However, DT_DEBUG
+     is not documented as being specific to executables, therefore use
+     it only as a low-priority discriminator.  */
+  if (has_dt_debug)
+    return false;
+
+  return true;
+}
+
+static bool
+is_executable (void)
+{
+  if (!is_loadable ())
+    return false;
+
+  /* A loadable object which is not a shared object is treated as an
+     executable.  */
+  return !is_shared ();
+}
+
+/* Like is_executable, but the object can also be a shared library at
+   the same time.  */
+static bool
+is_program (void)
+{
+  if (!is_loadable ())
+    return false;
+
+  /* The ELF type is very clear: this is an executable.  */
+  if (elf_type == ET_EXEC)
+    return true;
+
+  /* If the object is marked as PIE, it is definitely an executable,
+     and not a loadlable shared object.  */
+  if (has_pie_flag)
+    return true;
+
+  /* This is probably a PIE program. It isn't ET_EXEC, but has a
+     program interpreter. In theory, this file could be also a DSO
+     with a soname. This situation is impossible to resolve in the
+     general case. See is_shared. This is different from
+     is_executable.  */
+  if (has_program_interpreter)
+    return true;
+
+  /* Roland McGrath mentions in
+     <https://www.sourceware.org/ml/libc-alpha/2015-03/msg00605.html>,
+     that “we defined a PIE as an ET_DYN with a DT_DEBUG”.  This
+     matches current binutils behavior (version 2.32).  DT_DEBUG is
+     added if bfd_link_executable returns true or if bfd_link_pic
+     returns false, depending on the architectures.  However, DT_DEBUG
+     is not documented as being specific to executables, therefore use
+     it only as a low-priority discriminator.  */
+  if (has_dt_debug)
+    return true;
+
+  return false;
+}
+
+/* Like is_shared but the library could also be an executable.  */
+static bool
+is_library  (void)
+{
+  /* Only ET_DYN can be shared libraries.  */
+  if (elf_type != ET_DYN)
+    return false;
+
+  if (!is_loadable ())
+    return false;
+
+  /* Without a PT_DYNAMIC segment the library cannot be loaded.  */
+  if (!has_dynamic)
+    return false;
+
+  /* This really is a (PIE) executable.  See is_shared.  */
+  if (has_pie_flag || has_dt_debug)
+    return false;
+
+  /* It could still (also) be a (PIE) executable, but most likely you
+     can dlopen it just fine.  */
+  return true;
+}
+
+/* Returns true if the file is a linux kernel module (is ET_REL and
+   has the two magic sections .modinfo and .gnu.linkonce.this_module).  */
+static bool
+is_linux_kernel_module (void)
+{
+  return (elf_kind (elf) == ELF_K_ELF
+	  && elf_type == ET_REL
+	  && has_modinfo
+	  && has_gnu_linkonce_this_module);
+}
+
+enum classify_requirement { do_not_care, required, forbidden };
+
+enum classify_check
+{
+  classify_elf,
+  classify_elf_file,
+  classify_elf_archive,
+  classify_core,
+  classify_unstripped,
+  classify_executable,
+  classify_program,
+  classify_shared,
+  classify_library,
+  classify_linux_kernel_module,
+  classify_debug_only,
+  classify_loadable,
+
+  classify_check_last = classify_loadable
+};
+
+enum
+{
+  classify_check_offset = 1000,
+  classify_check_not_offset = 2000,
+
+  classify_flag_stdin = 3000,
+  classify_flag_stdin0,
+  classify_flag_no_stdin,
+  classify_flag_print,
+  classify_flag_print0,
+  classify_flag_no_print,
+  classify_flag_matching,
+  classify_flag_not_matching,
+};
+
+static bool
+classify_check_positive (int key)
+{
+  return key >= classify_check_offset
+    && key <= classify_check_offset + classify_check_last;
+}
+
+static bool
+classify_check_negative (int key)
+{
+  return key >= classify_check_not_offset
+    && key <= classify_check_not_offset + classify_check_last;
+}
+
+/* Set by parse_opt.  */
+static enum classify_requirement requirements[classify_check_last + 1];
+static enum { no_stdin, do_stdin, do_stdin0 } flag_stdin;
+static enum { no_print, do_print, do_print0 } flag_print;
+static bool flag_print_matching = true;
+
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+           struct argp_state *state __attribute__ ((unused)))
+{
+  if (classify_check_positive (key))
+    requirements[key - classify_check_offset] = required;
+  else if (classify_check_negative (key))
+    requirements[key - classify_check_not_offset] = forbidden;
+  else
+    switch (key)
+      {
+      case 'v':
+        ++verbose;
+        break;
+
+      case 'q':
+	--verbose;
+	break;
+
+      case 'z':
+	flag_compressed = true;
+	break;
+
+      case 'f':
+	flag_only_regular_files = true;
+	break;
+
+      case classify_flag_stdin:
+        flag_stdin = do_stdin;
+        break;
+
+      case classify_flag_stdin0:
+        flag_stdin = do_stdin0;
+        break;
+
+      case classify_flag_no_stdin:
+        flag_stdin = no_stdin;
+        break;
+
+      case classify_flag_print:
+        flag_print = do_print;
+        break;
+
+      case classify_flag_print0:
+        flag_print = do_print0;
+        break;
+
+      case classify_flag_no_print:
+        flag_print = no_print;
+        break;
+
+      case classify_flag_matching:
+        flag_print_matching = true;
+        break;
+
+      case classify_flag_not_matching:
+        flag_print_matching = false;
+        break;
+
+      default:
+        return ARGP_ERR_UNKNOWN;
+      }
+
+  return 0;
+}
+
+/* Perform requested checks against the file at current_path.  If
+   necessary, sets *STATUS to 1 if checks failed.  */
+static void
+process_current_path (int *status)
+{
+  bool checks_passed = true;
+
+  if (open_elf () && run_classify ())
+    {
+      bool checks[] =
+        {
+	 [classify_elf] = is_elf (),
+	 [classify_elf_file] = is_elf_file (),
+	 [classify_elf_archive] = is_elf_archive (),
+	 [classify_core] = is_core (),
+	 [classify_unstripped] = is_unstripped (),
+	 [classify_executable] = is_executable (),
+	 [classify_program] = is_program (),
+	 [classify_shared] = is_shared (),
+	 [classify_library] = is_library (),
+	 [classify_linux_kernel_module] = is_linux_kernel_module (),
+	 [classify_debug_only] = is_debug_only (),
+	 [classify_loadable] = is_loadable (),
+	};
+
+      if (verbose > 1)
+        {
+	  if (checks[classify_elf])
+	    fprintf (stderr, "debug: %s: elf\n", current_path);
+	  if (checks[classify_elf_file])
+	    fprintf (stderr, "debug: %s: elf_file\n", current_path);
+	  if (checks[classify_elf_archive])
+	    fprintf (stderr, "debug: %s: elf_archive\n", current_path);
+	  if (checks[classify_core])
+	    fprintf (stderr, "debug: %s: core\n", current_path);
+          if (checks[classify_unstripped])
+            fprintf (stderr, "debug: %s: unstripped\n", current_path);
+          if (checks[classify_executable])
+            fprintf (stderr, "debug: %s: executable\n", current_path);
+          if (checks[classify_program])
+            fprintf (stderr, "debug: %s: program\n", current_path);
+          if (checks[classify_shared])
+            fprintf (stderr, "debug: %s: shared\n", current_path);
+          if (checks[classify_library])
+            fprintf (stderr, "debug: %s: library\n", current_path);
+	  if (checks[classify_linux_kernel_module])
+	    fprintf (stderr, "debug: %s: linux kernel module\n", current_path);
+	  if (checks[classify_debug_only])
+	    fprintf (stderr, "debug: %s: debug-only\n", current_path);
+          if (checks[classify_loadable])
+            fprintf (stderr, "debug: %s: loadable\n", current_path);
+        }
+
+      for (enum classify_check check = 0;
+           check <= classify_check_last; ++check)
+        switch (requirements[check])
+          {
+          case required:
+            if (!checks[check])
+              checks_passed = false;
+            break;
+          case forbidden:
+            if (checks[check])
+              checks_passed = false;
+            break;
+          case do_not_care:
+            break;
+          }
+    }
+  else if (file_fd == -1)
+    checks_passed = false; /* There is nothing to check, bad file.  */
+  else
+    {
+      for (enum classify_check check = 0;
+           check <= classify_check_last; ++check)
+        if (requirements[check] == required)
+          checks_passed = false;
+    }
+
+  close_elf ();
+
+  switch (flag_print)
+    {
+    case do_print:
+      if (checks_passed == flag_print_matching)
+        puts (current_path);
+      break;
+    case do_print0:
+      if (checks_passed == flag_print_matching)
+        if (fwrite (current_path, strlen (current_path) + 1, 1, stdout) < 1)
+	  issue (errno, N_("writing to standard output"));
+      break;
+    case no_print:
+      if (!checks_passed)
+        *status = 1;
+      break;
+    }
+}
+
+/* Called to process standard input if flag_stdin is not no_stdin.  */
+static void
+process_stdin (int *status)
+{
+  char delim;
+  if (flag_stdin == do_stdin0)
+    delim = '\0';
+  else
+    delim = '\n';
+
+  char *buffer = NULL;
+  size_t buffer_size = 0;
+  while (true)
+    {
+      ssize_t ret = getdelim (&buffer, &buffer_size, delim, stdin);
+      if (ferror (stdin))
+	{
+	  current_path = NULL;
+	  issue (errno, N_("reading from standard input"));
+	  break;
+	}
+      if (feof (stdin))
+        break;
+      if (ret < 0)
+        abort ();           /* Cannot happen due to error checks above.  */
+      if (delim != '\0' && ret > 0 && buffer[ret - 1] == '\n')
+        buffer[ret - 1] = '\0';
+      current_path = buffer;
+      process_current_path (status);
+    }
+
+  free (buffer);
+}
+
+int
+main (int argc, char **argv)
+{
+  const struct argp_option options[] =
+    {
+      { NULL, 0, NULL, OPTION_DOC, N_("Classification options"), 1 },
+      { "elf", classify_check_offset + classify_elf, NULL, 0,
+        N_("File looks like an ELF object or archive/static library (default)")
+	, 1 },
+      { "elf-file", classify_check_offset + classify_elf_file, NULL, 0,
+        N_("File is an regular ELF object (not an archive/static library)")
+	, 1 },
+      { "elf-archive", classify_check_offset + classify_elf_archive, NULL, 0,
+        N_("File is an ELF archive or static library")
+	, 1 },
+      { "core", classify_check_offset + classify_core, NULL, 0,
+        N_("File is an ELF core dump file")
+	, 1 },
+      { "unstripped", classify_check_offset + classify_unstripped, NULL, 0,
+        N_("File is an ELF file with symbol table or .debug_* sections \
+and can be stripped further"), 1 },
+      { "executable", classify_check_offset + classify_executable, NULL, 0,
+        N_("File is (primarily) an ELF program executable \
+(not primarily a DSO)"), 1 },
+      { "program", classify_check_offset + classify_program, NULL, 0,
+        N_("File is an ELF program executable \
+(might also be a DSO)"), 1 },
+      { "shared", classify_check_offset + classify_shared, NULL, 0,
+        N_("File is (primarily) an ELF shared object (DSO) \
+(not primarily an executable)"), 1 },
+      { "library", classify_check_offset + classify_library, NULL, 0,
+        N_("File is an ELF shared object (DSO) \
+(might also be an executable)"), 1 },
+      { "linux-kernel-module", (classify_check_offset
+				+ classify_linux_kernel_module), NULL, 0,
+        N_("File is a linux kernel module"), 1 },
+      { "debug-only", (classify_check_offset + classify_debug_only), NULL, 0,
+        N_("File is a debug only ELF file \
+(separate .debug, .dwo or dwz multi-file)"), 1 },
+      { "loadable", classify_check_offset + classify_loadable, NULL, 0,
+        N_("File is a loadable ELF object (program or shared object)"), 1 },
+
+      /* Negated versions of the above.  */
+      { "not-elf", classify_check_not_offset + classify_elf,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-elf-file", classify_check_not_offset + classify_elf_file,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-elf-archive", classify_check_not_offset + classify_elf_archive,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-core", classify_check_not_offset + classify_core,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-unstripped", classify_check_not_offset + classify_unstripped,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-executable", classify_check_not_offset + classify_executable,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-program", classify_check_not_offset + classify_program,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-shared", classify_check_not_offset + classify_shared,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-library", classify_check_not_offset + classify_library,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-linux-kernel-module", (classify_check_not_offset
+				    + classify_linux_kernel_module),
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-debug-only", (classify_check_not_offset + classify_debug_only),
+        NULL, OPTION_HIDDEN, NULL, 1 },
+      { "not-loadable", classify_check_not_offset + classify_loadable,
+        NULL, OPTION_HIDDEN, NULL, 1 },
+
+      { NULL, 0, NULL, OPTION_DOC, N_("Input flags"), 2 },
+      { "file", 'f', NULL, 0,
+        N_("Only classify regular (not symlink nor special device) files"), 2 },
+      { "stdin", classify_flag_stdin, NULL, 0,
+        N_("Also read file names to process from standard input, \
+separated by newlines"), 2 },
+      { "stdin0", classify_flag_stdin0, NULL, 0,
+        N_("Also read file names to process from standard input, \
+separated by ASCII NUL bytes"), 2 },
+      { "no-stdin", classify_flag_no_stdin, NULL, 0,
+        N_("Do not read files from standard input (default)"), 2 },
+      { "compressed", 'z', NULL, 0,
+	N_("Try to open compressed files or embedded (kernel) ELF images"),
+	2 },
+
+      { NULL, 0, NULL, OPTION_DOC, N_("Output flags"), 3 },
+      { "print", classify_flag_print, NULL, 0,
+        N_("Output names of files, separated by newline"), 3 },
+      { "print0", classify_flag_print0, NULL, 0,
+        N_("Output names of files, separated by ASCII NUL"), 3 },
+      { "no-print", classify_flag_no_print, NULL, 0,
+        N_("Do not output file names"), 3 },
+      { "matching", classify_flag_matching, NULL, 0,
+        N_("If printing file names, print matching files (default)"), 3 },
+      { "not-matching", classify_flag_not_matching, NULL, 0,
+        N_("If printing file names, print files that do not match"), 3 },
+
+      { NULL, 0, NULL, OPTION_DOC, N_("Additional flags"), 4 },
+      { "verbose", 'v', NULL, 0,
+        N_("Output additional information (can be specified multiple times)"), 4 },
+      { "quiet", 'q', NULL, 0,
+        N_("Suppress some error output (counterpart to --verbose)"), 4 },
+      { NULL, 0, NULL, 0, NULL, 0 }
+    };
+
+  const struct argp argp =
+    {
+      .options = options,
+      .parser = parse_opt,
+      .args_doc = N_("FILE..."),
+      .doc = N_("\
+Determine the type of an ELF file.\
+\n\n\
+All of the classification options must apply at the same time to a \
+particular file.  Classification options can be negated using a \
+\"--not-\" prefix.\
+\n\n\
+Since modern ELF does not clearly distinguish between programs and \
+dynamic shared objects, you should normally use either --executable or \
+--shared to identify the primary purpose of a file.  \
+Only one of the --shared and --executable checks can pass for a file.\
+\n\n\
+If you want to know whether an ELF object might a program or a \
+shared library (but could be both), then use --program or --library. \
+Some ELF files will classify as both a program and a library.\
+\n\n\
+If you just want to know whether an ELF file is loadable (as program \
+or library) use --loadable.  Note that files that only contain \
+(separate) debug information (--debug-only) are never --loadable (even \
+though they might contain program headers).  Linux kernel modules are \
+also not --loadable (in the normal sense).\
+\n\n\
+Without any of the --print options, the program exits with status 0 \
+if the requested checks pass for all input files, with 1 if a check \
+fails for any file, and 2 if there is an environmental issue (such \
+as a file read error or a memory allocation error).\
+\n\n\
+When printing file names, the program exits with status 0 even if \
+no file names are printed, and exits with status 2 if there is an \
+environmental issue.\
+\n\n\
+On usage error (e.g. a bad option was given), the program exits with \
+a status code larger than 2.\
+\n\n\
+The --quiet or -q option suppresses some error warning output, but \
+doesn't change the exit status.\
+")
+    };
+
+  /* Require that the file is an ELF file by default.  User can
+     disable with --not-elf.  */
+  requirements[classify_elf] = required;
+
+  int remaining;
+  if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
+    return 2;
+
+  elf_version (EV_CURRENT);
+
+  int status = 0;
+
+  for (int i = remaining; i < argc; ++i)
+    {
+      current_path = argv[i];
+      process_current_path (&status);
+    }
+
+  if (flag_stdin != no_stdin)
+    process_stdin (&status);
+
+  if (issue_found)
+    return 2;
+
+  return status;
+}
diff --git a/src/elfcmp.c b/src/elfcmp.c
new file mode 100644
index 0000000..fba67e0
--- /dev/null
+++ b/src/elfcmp.c
@@ -0,0 +1,910 @@
+/* Compare relevant content of two ELF files.
+   Copyright (C) 2005-2012, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <printversion.h>
+#include "../libelf/elf-knowledge.h"
+#include "../libebl/libeblP.h"
+#include "system.h"
+
+/* Prototypes of local functions.  */
+static Elf *open_file (const char *fname, int *fdp, Ebl **eblp);
+static bool search_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx);
+static  int regioncompare (const void *p1, const void *p2);
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Values for the parameters which have no short form.  */
+#define OPT_GAPS		0x100
+#define OPT_HASH_INEXACT	0x101
+#define OPT_IGNORE_BUILD_ID	0x102
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Control options:"), 0 },
+  { "verbose", 'l', NULL, 0,
+    N_("Output all differences, not just the first"), 0 },
+  { "gaps", OPT_GAPS, "ACTION", 0, N_("Control treatment of gaps in loadable segments [ignore|match] (default: ignore)"), 0 },
+  { "hash-inexact", OPT_HASH_INEXACT, NULL, 0,
+    N_("Ignore permutation of buckets in SHT_HASH section"), 0 },
+  { "ignore-build-id", OPT_IGNORE_BUILD_ID, NULL, 0,
+    N_("Ignore differences in build ID"), 0 },
+  { "quiet", 'q', NULL, 0, N_("Output nothing; yield exit status only"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Compare relevant parts of two ELF files for equality.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("FILE1 FILE2");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+
+/* How to treat gaps in loadable segments.  */
+static enum
+  {
+    gaps_ignore = 0,
+    gaps_match
+  }
+  gaps;
+
+/* Structure to hold information about used regions.  */
+struct region
+{
+  GElf_Addr from;
+  GElf_Addr to;
+  struct region *next;
+};
+
+/* Nonzero if only exit status is wanted.  */
+static bool quiet;
+
+/* True iff multiple differences should be output.  */
+static bool verbose;
+
+/* True iff SHT_HASH treatment should be generous.  */
+static bool hash_inexact;
+
+/* True iff build ID notes should be ignored.  */
+static bool ignore_build_id;
+
+static bool hash_content_equivalent (size_t entsize, Elf_Data *, Elf_Data *);
+
+
+int
+main (int argc, char *argv[])
+{
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* We expect exactly two non-option parameters.  */
+  if (unlikely (remaining + 2 != argc))
+    {
+      fputs (_("Invalid number of parameters.\n"), stderr);
+      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
+      exit (1);
+    }
+
+  if (quiet)
+    verbose = false;
+
+  /* Comparing the files is done in two phases:
+     1. compare all sections.  Sections which are irrelevant (i.e., if
+	strip would remove them) are ignored.  Some section types are
+	handled special.
+     2. all parts of the loadable segments which are not parts of any
+	section is compared according to the rules of the --gaps option.
+  */
+  int result = 0;
+  elf_version (EV_CURRENT);
+
+  const char *const fname1 = argv[remaining];
+  int fd1;
+  Ebl *ebl1;
+  Elf *elf1 = open_file (fname1, &fd1, &ebl1);
+
+  const char *const fname2 = argv[remaining + 1];
+  int fd2;
+  Ebl *ebl2;
+  Elf *elf2 = open_file (fname2, &fd2, &ebl2);
+
+  GElf_Ehdr ehdr1_mem;
+  GElf_Ehdr *ehdr1 = gelf_getehdr (elf1, &ehdr1_mem);
+  if (ehdr1 == NULL)
+    error (2, 0, _("cannot get ELF header of '%s': %s"),
+	   fname1, elf_errmsg (-1));
+  GElf_Ehdr ehdr2_mem;
+  GElf_Ehdr *ehdr2 = gelf_getehdr (elf2, &ehdr2_mem);
+  if (ehdr2 == NULL)
+    error (2, 0, _("cannot get ELF header of '%s': %s"),
+	   fname2, elf_errmsg (-1));
+
+#define DIFFERENCE							      \
+  do									      \
+    {									      \
+      result = 1;							      \
+      if (! verbose)							      \
+	goto out;							      \
+    }									      \
+  while (0)
+
+  /* Compare the ELF headers.  */
+  if (unlikely (memcmp (ehdr1->e_ident, ehdr2->e_ident, EI_NIDENT) != 0
+		|| ehdr1->e_type != ehdr2->e_type
+		|| ehdr1->e_machine != ehdr2->e_machine
+		|| ehdr1->e_version != ehdr2->e_version
+		|| ehdr1->e_entry != ehdr2->e_entry
+		|| ehdr1->e_phoff != ehdr2->e_phoff
+		|| ehdr1->e_flags != ehdr2->e_flags
+		|| ehdr1->e_ehsize != ehdr2->e_ehsize
+		|| ehdr1->e_phentsize != ehdr2->e_phentsize
+		|| ehdr1->e_phnum != ehdr2->e_phnum
+		|| ehdr1->e_shentsize != ehdr2->e_shentsize))
+    {
+      if (! quiet)
+	error (0, 0, _("%s %s diff: ELF header"), fname1, fname2);
+      DIFFERENCE;
+    }
+
+  size_t shnum1;
+  size_t shnum2;
+  if (unlikely (elf_getshdrnum (elf1, &shnum1) != 0))
+    error (2, 0, _("cannot get section count of '%s': %s"),
+	   fname1, elf_errmsg (-1));
+  if (unlikely (elf_getshdrnum (elf2, &shnum2) != 0))
+    error (2, 0, _("cannot get section count of '%s': %s"),
+	   fname2, elf_errmsg (-1));
+  if (unlikely (shnum1 != shnum2))
+    {
+      if (! quiet)
+	error (0, 0, _("%s %s diff: section count"), fname1, fname2);
+      DIFFERENCE;
+    }
+
+  size_t phnum1;
+  size_t phnum2;
+  if (unlikely (elf_getphdrnum (elf1, &phnum1) != 0))
+    error (2, 0, _("cannot get program header count of '%s': %s"),
+	   fname1, elf_errmsg (-1));
+  if (unlikely (elf_getphdrnum (elf2, &phnum2) != 0))
+    error (2, 0, _("cannot get program header count of '%s': %s"),
+	   fname2, elf_errmsg (-1));
+  if (unlikely (phnum1 != phnum2))
+    {
+      if (! quiet)
+	error (0, 0, _("%s %s diff: program header count"),
+	       fname1, fname2);
+      DIFFERENCE;
+    }
+
+  size_t shstrndx1;
+  size_t shstrndx2;
+  if (elf_getshdrstrndx (elf1, &shstrndx1) != 0)
+    error (2, 0, _("cannot get hdrstrndx of '%s': %s"),
+	   fname1, elf_errmsg (-1));
+  if (elf_getshdrstrndx (elf2, &shstrndx2) != 0)
+    error (2, 0, _("cannot get hdrstrndx of '%s': %s"),
+	   fname2, elf_errmsg (-1));
+  if (shstrndx1 != shstrndx2)
+    {
+      if (! quiet)
+	error (0, 0, _("%s %s diff: shdr string index"),
+	       fname1, fname2);
+      DIFFERENCE;
+    }
+
+  /* Iterate over all sections.  We expect the sections in the two
+     files to match exactly.  */
+  Elf_Scn *scn1 = NULL;
+  Elf_Scn *scn2 = NULL;
+  struct region *regions = NULL;
+  size_t nregions = 0;
+  while (1)
+    {
+      GElf_Shdr shdr1_mem;
+      GElf_Shdr *shdr1;
+      const char *sname1 = NULL;
+      do
+	{
+	  scn1 = elf_nextscn (elf1, scn1);
+	  shdr1 = gelf_getshdr (scn1, &shdr1_mem);
+	  if (shdr1 != NULL)
+	    sname1 = elf_strptr (elf1, shstrndx1, shdr1->sh_name);
+	}
+      while (scn1 != NULL && shdr1 != NULL
+	     && ebl_section_strip_p (ebl1, shdr1, sname1, true, false));
+
+      GElf_Shdr shdr2_mem;
+      GElf_Shdr *shdr2;
+      const char *sname2 = NULL;
+      do
+	{
+	  scn2 = elf_nextscn (elf2, scn2);
+	  shdr2 = gelf_getshdr (scn2, &shdr2_mem);
+	  if (shdr2 != NULL)
+	    sname2 = elf_strptr (elf2, shstrndx2, shdr2->sh_name);
+	}
+      while (scn2 != NULL && shdr2 != NULL
+	     && ebl_section_strip_p (ebl2, shdr2, sname2, true, false));
+
+      if (scn1 == NULL || scn2 == NULL || shdr1 == NULL || shdr2 == NULL)
+	break;
+
+      if (gaps != gaps_ignore && (shdr1->sh_flags & SHF_ALLOC) != 0)
+	{
+	  struct region *newp = (struct region *) alloca (sizeof (*newp));
+	  newp->from = shdr1->sh_offset;
+	  newp->to = shdr1->sh_offset + shdr1->sh_size;
+	  newp->next = regions;
+	  regions = newp;
+
+	  ++nregions;
+	}
+
+      /* Compare the headers.  We allow the name to be at a different
+	 location.  */
+      if (unlikely (sname1 == NULL || sname2 == NULL
+		    || strcmp (sname1, sname2) != 0))
+	{
+	  error (0, 0, _("%s %s differ: section [%zu], [%zu] name"),
+		 fname1, fname2, elf_ndxscn (scn1), elf_ndxscn (scn2));
+	  DIFFERENCE;
+	}
+
+      /* We ignore certain sections.  */
+      if ((sname1 != NULL && strcmp (sname1, ".gnu_debuglink") == 0)
+	  || (sname1 != NULL && strcmp (sname1, ".gnu.prelink_undo") == 0))
+	continue;
+
+      if (shdr1->sh_type != shdr2->sh_type
+	  // XXX Any flags which should be ignored?
+	  || shdr1->sh_flags != shdr2->sh_flags
+	  || shdr1->sh_addr != shdr2->sh_addr
+	  || (shdr1->sh_offset != shdr2->sh_offset
+	      && (shdr1->sh_flags & SHF_ALLOC)
+	      && ehdr1->e_type != ET_REL)
+	  || shdr1->sh_size != shdr2->sh_size
+	  || shdr1->sh_link != shdr2->sh_link
+	  || shdr1->sh_info != shdr2->sh_info
+	  || shdr1->sh_addralign != shdr2->sh_addralign
+	  || shdr1->sh_entsize != shdr2->sh_entsize)
+	{
+	  error (0, 0, _("%s %s differ: section [%zu] '%s' header"),
+		 fname1, fname2, elf_ndxscn (scn1), sname1);
+	  DIFFERENCE;
+	}
+
+      Elf_Data *data1 = elf_getdata (scn1, NULL);
+      if (data1 == NULL)
+	error (2, 0,
+	       _("cannot get content of section %zu in '%s': %s"),
+	       elf_ndxscn (scn1), fname1, elf_errmsg (-1));
+
+      Elf_Data *data2 = elf_getdata (scn2, NULL);
+      if (data2 == NULL)
+	error (2, 0,
+	       _("cannot get content of section %zu in '%s': %s"),
+	       elf_ndxscn (scn2), fname2, elf_errmsg (-1));
+
+      switch (shdr1->sh_type)
+	{
+	case SHT_DYNSYM:
+	case SHT_SYMTAB:
+	  if (shdr1->sh_entsize == 0)
+	    error (2, 0,
+		   _("symbol table [%zu] in '%s' has zero sh_entsize"),
+		   elf_ndxscn (scn1), fname1);
+
+	  /* Iterate over the symbol table.  We ignore the st_size
+	     value of undefined symbols.  */
+	  for (int ndx = 0; ndx < (int) (shdr1->sh_size / shdr1->sh_entsize);
+	       ++ndx)
+	    {
+	      GElf_Sym sym1_mem;
+	      GElf_Sym *sym1 = gelf_getsym (data1, ndx, &sym1_mem);
+	      if (sym1 == NULL)
+		error (2, 0,
+		       _("cannot get symbol in '%s': %s"),
+		       fname1, elf_errmsg (-1));
+	      GElf_Sym sym2_mem;
+	      GElf_Sym *sym2 = gelf_getsym (data2, ndx, &sym2_mem);
+	      if (sym2 == NULL)
+		error (2, 0,
+		       _("cannot get symbol in '%s': %s"),
+		       fname2, elf_errmsg (-1));
+
+	      const char *name1 = elf_strptr (elf1, shdr1->sh_link,
+					      sym1->st_name);
+	      const char *name2 = elf_strptr (elf2, shdr2->sh_link,
+					      sym2->st_name);
+	      if (unlikely (name1 == NULL || name2 == NULL
+			    || strcmp (name1, name2) != 0
+			    || sym1->st_value != sym2->st_value
+			    || (sym1->st_size != sym2->st_size
+				&& sym1->st_shndx != SHN_UNDEF)
+			    || sym1->st_info != sym2->st_info
+			    || sym1->st_other != sym2->st_other
+			    || sym1->st_shndx != sym2->st_shndx))
+		{
+		  // XXX Do we want to allow reordered symbol tables?
+		symtab_mismatch:
+		  if (! quiet)
+		    {
+		      if (elf_ndxscn (scn1) == elf_ndxscn (scn2))
+			error (0, 0,
+			       _("%s %s differ: symbol table [%zu]"),
+			       fname1, fname2, elf_ndxscn (scn1));
+		      else
+			error (0, 0, _("\
+%s %s differ: symbol table [%zu,%zu]"),
+			       fname1, fname2, elf_ndxscn (scn1),
+			       elf_ndxscn (scn2));
+		    }
+		  DIFFERENCE;
+		  break;
+		}
+
+	      if (sym1->st_shndx == SHN_UNDEF
+		  && sym1->st_size != sym2->st_size)
+		{
+		  /* The size of the symbol in the object defining it
+		     might have changed.  That is OK unless the symbol
+		     is used in a copy relocation.  Look over the
+		     sections in both files and determine which
+		     relocation section uses this symbol table
+		     section.  Then look through the relocations to
+		     see whether any copy relocation references this
+		     symbol.  */
+		  if (search_for_copy_reloc (ebl1, elf_ndxscn (scn1), ndx)
+		      || search_for_copy_reloc (ebl2, elf_ndxscn (scn2), ndx))
+		    goto symtab_mismatch;
+		}
+	    }
+	  break;
+
+	case SHT_NOTE:
+	  /* Parse the note format and compare the notes themselves.  */
+	  {
+	    GElf_Nhdr note1;
+	    GElf_Nhdr note2;
+
+	    size_t off1 = 0;
+	    size_t off2 = 0;
+	    size_t name_offset;
+	    size_t desc_offset;
+	    while (off1 < data1->d_size
+		   && (off1 = gelf_getnote (data1, off1, &note1,
+					    &name_offset, &desc_offset)) > 0)
+	      {
+		const char *name1 = (note1.n_namesz == 0
+				     ? "" : data1->d_buf + name_offset);
+		const void *desc1 = data1->d_buf + desc_offset;
+		if (off2 >= data2->d_size)
+		  {
+		    if (! quiet)
+		      error (0, 0, _("\
+%s %s differ: section [%zu] '%s' number of notes"),
+			     fname1, fname2, elf_ndxscn (scn1), sname1);
+		    DIFFERENCE;
+		  }
+		off2 = gelf_getnote (data2, off2, &note2,
+				     &name_offset, &desc_offset);
+		if (off2 == 0)
+		  error (2, 0, _("\
+cannot read note section [%zu] '%s' in '%s': %s"),
+			 elf_ndxscn (scn2), sname2, fname2, elf_errmsg (-1));
+		const char *name2 = (note2.n_namesz == 0
+				     ? "" : data2->d_buf + name_offset);
+		const void *desc2 = data2->d_buf + desc_offset;
+
+		if (note1.n_namesz != note2.n_namesz
+		    || memcmp (name1, name2, note1.n_namesz))
+		  {
+		    if (! quiet)
+		      error (0, 0, _("\
+%s %s differ: section [%zu] '%s' note name"),
+			     fname1, fname2, elf_ndxscn (scn1), sname1);
+		    DIFFERENCE;
+		  }
+		if (note1.n_type != note2.n_type)
+		  {
+		    if (! quiet)
+		      error (0, 0, _("\
+%s %s differ: section [%zu] '%s' note '%s' type"),
+			     fname1, fname2, elf_ndxscn (scn1), sname1, name1);
+		    DIFFERENCE;
+		  }
+		if (note1.n_descsz != note2.n_descsz
+		    || memcmp (desc1, desc2, note1.n_descsz))
+		  {
+		    if (note1.n_type == NT_GNU_BUILD_ID
+			&& note1.n_namesz == sizeof "GNU"
+			&& !memcmp (name1, "GNU", sizeof "GNU"))
+		      {
+			if (note1.n_descsz != note2.n_descsz)
+			  {
+			    if (! quiet)
+			      error (0, 0, _("\
+%s %s differ: build ID length"),
+				     fname1, fname2);
+			    DIFFERENCE;
+			  }
+			else if (! ignore_build_id)
+			  {
+			    if (! quiet)
+			      error (0, 0, _("\
+%s %s differ: build ID content"),
+				     fname1, fname2);
+			    DIFFERENCE;
+			  }
+		      }
+		    else
+		      {
+			if (! quiet)
+			  error (0, 0, _("\
+%s %s differ: section [%zu] '%s' note '%s' content"),
+				 fname1, fname2, elf_ndxscn (scn1), sname1,
+				 name1);
+			DIFFERENCE;
+		      }
+		  }
+	      }
+	    if (off2 < data2->d_size)
+	      {
+		if (! quiet)
+		  error (0, 0, _("\
+%s %s differ: section [%zu] '%s' number of notes"),
+			 fname1, fname2, elf_ndxscn (scn1), sname1);
+		DIFFERENCE;
+	      }
+	  }
+	  break;
+
+	default:
+	  /* Compare the section content byte for byte.  */
+	  assert (shdr1->sh_type == SHT_NOBITS
+		  || (data1->d_buf != NULL || data1->d_size == 0));
+	  assert (shdr2->sh_type == SHT_NOBITS
+		  || (data2->d_buf != NULL || data1->d_size == 0));
+
+	  if (unlikely (data1->d_size != data2->d_size
+			|| (shdr1->sh_type != SHT_NOBITS
+			    && data1->d_size != 0
+			    && memcmp (data1->d_buf, data2->d_buf,
+				       data1->d_size) != 0)))
+	    {
+	      if (hash_inexact
+		  && shdr1->sh_type == SHT_HASH
+		  && data1->d_size == data2->d_size
+		  && hash_content_equivalent (shdr1->sh_entsize, data1, data2))
+		break;
+
+	      if (! quiet)
+		{
+		  if (elf_ndxscn (scn1) == elf_ndxscn (scn2))
+		    error (0, 0, _("\
+%s %s differ: section [%zu] '%s' content"),
+			   fname1, fname2, elf_ndxscn (scn1), sname1);
+		  else
+		    error (0, 0, _("\
+%s %s differ: section [%zu,%zu] '%s' content"),
+			   fname1, fname2, elf_ndxscn (scn1),
+			   elf_ndxscn (scn2), sname1);
+		}
+	      DIFFERENCE;
+	    }
+	  break;
+	}
+    }
+
+  if (unlikely (scn1 != scn2))
+    {
+      if (! quiet)
+	error (0, 0,
+	       _("%s %s differ: unequal amount of important sections"),
+	       fname1, fname2);
+      DIFFERENCE;
+    }
+
+  /* We we look at gaps, create artificial ones for the parts of the
+     program which we are not in sections.  */
+  struct region ehdr_region;
+  struct region phdr_region;
+  if (gaps != gaps_ignore)
+    {
+      ehdr_region.from = 0;
+      ehdr_region.to = ehdr1->e_ehsize;
+      ehdr_region.next = &phdr_region;
+
+      phdr_region.from = ehdr1->e_phoff;
+      phdr_region.to = ehdr1->e_phoff + phnum1 * ehdr1->e_phentsize;
+      phdr_region.next = regions;
+
+      regions = &ehdr_region;
+      nregions += 2;
+    }
+
+  /* If we need to look at the gaps we need access to the file data.  */
+  char *raw1 = NULL;
+  size_t size1 = 0;
+  char *raw2 = NULL;
+  size_t size2 = 0;
+  struct region *regionsarr = alloca (nregions * sizeof (struct region));
+  if (gaps != gaps_ignore)
+    {
+      raw1 = elf_rawfile (elf1, &size1);
+      if (raw1 == NULL )
+	error (2, 0, _("cannot load data of '%s': %s"),
+	       fname1, elf_errmsg (-1));
+
+      raw2 = elf_rawfile (elf2, &size2);
+      if (raw2 == NULL )
+	error (2, 0, _("cannot load data of '%s': %s"),
+	       fname2, elf_errmsg (-1));
+
+      for (size_t cnt = 0; cnt < nregions; ++cnt)
+	{
+	  regionsarr[cnt] = *regions;
+	  regions = regions->next;
+	}
+
+      qsort (regionsarr, nregions, sizeof (regionsarr[0]), regioncompare);
+    }
+
+  /* Compare the program header tables.  */
+  for (unsigned int ndx = 0; ndx < phnum1; ++ndx)
+    {
+      GElf_Phdr phdr1_mem;
+      GElf_Phdr *phdr1 = gelf_getphdr (elf1, ndx, &phdr1_mem);
+      if (phdr1 == NULL)
+	error (2, 0,
+	       _("cannot get program header entry %d of '%s': %s"),
+	       ndx, fname1, elf_errmsg (-1));
+      GElf_Phdr phdr2_mem;
+      GElf_Phdr *phdr2 = gelf_getphdr (elf2, ndx, &phdr2_mem);
+      if (phdr2 == NULL)
+	error (2, 0,
+	       _("cannot get program header entry %d of '%s': %s"),
+	       ndx, fname2, elf_errmsg (-1));
+
+      if (unlikely (memcmp (phdr1, phdr2, sizeof (GElf_Phdr)) != 0))
+	{
+	  if (! quiet)
+	    error (0, 0, _("%s %s differ: program header %d"),
+		   fname1, fname2, ndx);
+	  DIFFERENCE;
+	}
+
+      if (gaps != gaps_ignore && phdr1->p_type == PT_LOAD)
+	{
+	  size_t cnt = 0;
+	  while (cnt < nregions && regionsarr[cnt].to < phdr1->p_offset)
+	    ++cnt;
+
+	  GElf_Off last = phdr1->p_offset;
+	  GElf_Off end = phdr1->p_offset + phdr1->p_filesz;
+	  while (cnt < nregions && regionsarr[cnt].from < end)
+	    {
+	      if (last < regionsarr[cnt].from)
+		{
+		  /* Compare the [LAST,FROM) region.  */
+		  assert (gaps == gaps_match);
+		  if (unlikely (memcmp (raw1 + last, raw2 + last,
+					regionsarr[cnt].from - last) != 0))
+		    {
+		    gapmismatch:
+		      if (!quiet)
+			error (0, 0, _("%s %s differ: gap"),
+			       fname1, fname2);
+		      DIFFERENCE;
+		      break;
+		    }
+
+		}
+	      last = regionsarr[cnt].to;
+	      ++cnt;
+	    }
+
+	  if (cnt == nregions && last < end)
+	    goto gapmismatch;
+	}
+    }
+
+ out:
+  elf_end (elf1);
+  elf_end (elf2);
+  ebl_closebackend (ebl1);
+  ebl_closebackend (ebl2);
+  close (fd1);
+  close (fd2);
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'q':
+      quiet = true;
+      break;
+
+    case 'l':
+      verbose = true;
+      break;
+
+    case OPT_GAPS:
+      if (strcasecmp (arg, "ignore") == 0)
+	gaps = gaps_ignore;
+      else if (likely (strcasecmp (arg, "match") == 0))
+	gaps = gaps_match;
+      else
+	{
+	  fprintf (stderr,
+		   _("Invalid value '%s' for --gaps parameter."),
+		   arg);
+	  argp_help (&argp, stderr, ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (1);
+	}
+      break;
+
+    case OPT_HASH_INEXACT:
+      hash_inexact = true;
+      break;
+
+    case OPT_IGNORE_BUILD_ID:
+      ignore_build_id = true;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+static Elf *
+open_file (const char *fname, int *fdp, Ebl **eblp)
+{
+  int fd = open (fname, O_RDONLY);
+  if (unlikely (fd == -1))
+    error (2, errno, _("cannot open '%s'"), fname);
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    error (2, 0,
+	   _("cannot create ELF descriptor for '%s': %s"),
+	   fname, elf_errmsg (-1));
+  Ebl *ebl = ebl_openbackend (elf);
+  if (ebl == NULL)
+    error (2, 0,
+	   _("cannot create EBL descriptor for '%s'"), fname);
+
+  *fdp = fd;
+  *eblp = ebl;
+  return elf;
+}
+
+
+static bool
+search_for_copy_reloc (Ebl *ebl, size_t scnndx, int symndx)
+{
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	error (2, 0,
+	       _("cannot get section header of section %zu: %s"),
+	       elf_ndxscn (scn), elf_errmsg (-1));
+
+      if ((shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA)
+	  || shdr->sh_link != scnndx)
+	continue;
+
+      Elf_Data *data = elf_getdata (scn, NULL);
+      if (data == NULL)
+	error (2, 0,
+	       _("cannot get content of section %zu: %s"),
+	       elf_ndxscn (scn), elf_errmsg (-1));
+
+      if (shdr->sh_type == SHT_REL && shdr->sh_entsize != 0)
+	for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize);
+	     ++ndx)
+	  {
+	    GElf_Rel rel_mem;
+	    GElf_Rel *rel = gelf_getrel (data, ndx, &rel_mem);
+	    if (rel == NULL)
+	      error (2, 0, _("cannot get relocation: %s"),
+		     elf_errmsg (-1));
+
+	    if ((int) GELF_R_SYM (rel->r_info) == symndx
+		&& ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
+	      return true;
+	  }
+      else if (shdr->sh_entsize != 0)
+	for (int ndx = 0; ndx < (int) (shdr->sh_size / shdr->sh_entsize);
+	     ++ndx)
+	  {
+	    GElf_Rela rela_mem;
+	    GElf_Rela *rela = gelf_getrela (data, ndx, &rela_mem);
+	    if (rela == NULL)
+	      error (2, 0, _("cannot get relocation: %s"),
+		     elf_errmsg (-1));
+
+	    if ((int) GELF_R_SYM (rela->r_info) == symndx
+		&& ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
+	      return true;
+	  }
+    }
+
+  return false;
+}
+
+
+static int
+regioncompare (const void *p1, const void *p2)
+{
+  const struct region *r1 = (const struct region *) p1;
+  const struct region *r2 = (const struct region *) p2;
+
+  if (r1->from < r2->from)
+    return -1;
+  return 1;
+}
+
+
+static int
+compare_Elf32_Word (const void *p1, const void *p2)
+{
+  const Elf32_Word *w1 = p1;
+  const Elf32_Word *w2 = p2;
+  return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0;
+}
+
+static int
+compare_Elf64_Xword (const void *p1, const void *p2)
+{
+  const Elf64_Xword *w1 = p1;
+  const Elf64_Xword *w2 = p2;
+  return *w1 < *w2 ? -1 : *w1 > *w2 ? 1 : 0;
+}
+
+static bool
+hash_content_equivalent (size_t entsize, Elf_Data *data1, Elf_Data *data2)
+{
+#define CHECK_HASH(Hash_Word)						      \
+  {									      \
+    const Hash_Word *const hash1 = data1->d_buf;			      \
+    const Hash_Word *const hash2 = data2->d_buf;			      \
+    const size_t nbucket = hash1[0];					      \
+    const size_t nchain = hash1[1];					      \
+    if (data1->d_size != (2 + nbucket + nchain) * sizeof hash1[0]	      \
+	|| hash2[0] != nbucket || hash2[1] != nchain)			      \
+      return false;							      \
+									      \
+    const Hash_Word *const bucket1 = &hash1[2];				      \
+    const Hash_Word *const chain1 = &bucket1[nbucket];			      \
+    const Hash_Word *const bucket2 = &hash2[2];				      \
+    const Hash_Word *const chain2 = &bucket2[nbucket];			      \
+									      \
+    bool chain_ok[nchain];						      \
+    Hash_Word temp1[nchain - 1];					      \
+    Hash_Word temp2[nchain - 1];					      \
+    memset (chain_ok, 0, sizeof chain_ok);				      \
+    for (size_t i = 0; i < nbucket; ++i)				      \
+      {									      \
+	if (bucket1[i] >= nchain || bucket2[i] >= nchain)		      \
+	  return false;							      \
+									      \
+	size_t b1 = 0;							      \
+	for (size_t p = bucket1[i]; p != STN_UNDEF; p = chain1[p])	      \
+	  if (p >= nchain || b1 >= nchain - 1)				      \
+	    return false;						      \
+	  else								      \
+	    temp1[b1++] = p;						      \
+									      \
+	size_t b2 = 0;							      \
+	for (size_t p = bucket2[i]; p != STN_UNDEF; p = chain2[p])	      \
+	  if (p >= nchain || b2 >= nchain - 1)				      \
+	    return false;						      \
+	  else								      \
+	    temp2[b2++] = p;						      \
+									      \
+	if (b1 != b2)							      \
+	  return false;							      \
+									      \
+	qsort (temp1, b1, sizeof temp1[0], compare_##Hash_Word);	      \
+	qsort (temp2, b2, sizeof temp2[0], compare_##Hash_Word);	      \
+									      \
+	for (b1 = 0; b1 < b2; ++b1)					      \
+	  if (temp1[b1] != temp2[b1])					      \
+	    return false;						      \
+	  else								      \
+	    chain_ok[temp1[b1]] = true;					      \
+      }									      \
+									      \
+    for (size_t i = 0; i < nchain; ++i)					      \
+      if (!chain_ok[i] && chain1[i] != chain2[i])			      \
+	return false;							      \
+									      \
+    return true;							      \
+  }
+
+  switch (entsize)
+    {
+    case 4:
+      CHECK_HASH (Elf32_Word);
+      break;
+    case 8:
+      CHECK_HASH (Elf64_Xword);
+      break;
+    }
+
+  return false;
+}
+
+
+#include "debugpred.h"
diff --git a/src/elfcompress.c b/src/elfcompress.c
new file mode 100644
index 0000000..f771b92
--- /dev/null
+++ b/src/elfcompress.c
@@ -0,0 +1,1463 @@
+/* Compress or decompress an ELF file.
+   Copyright (C) 2015, 2016, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <argp.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <locale.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include ELFUTILS_HEADER(elf)
+#include ELFUTILS_HEADER(ebl)
+#include ELFUTILS_HEADER(dwelf)
+#include <gelf.h>
+#include "system.h"
+#include "libeu.h"
+#include "printversion.h"
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+static int verbose = 0; /* < 0, no warnings, > 0 extra verbosity.  */
+static bool force = false;
+static bool permissive = false;
+static const char *foutput = NULL;
+
+/* Compression algorithm, where all legal values for ch_type
+   (compression algorithm) do match the following enum.  */
+enum ch_type
+{
+  UNSET = -1,
+  NONE,
+  ZLIB,
+  ZSTD,
+
+  /* Maximal supported ch_type.  */
+  MAXIMAL_CH_TYPE = ZSTD,
+
+  ZLIB_GNU = 1 << 16
+};
+
+#define WORD_BITS (8U * sizeof (unsigned int))
+
+static enum ch_type type = UNSET;
+
+struct section_pattern
+{
+  char *pattern;
+  struct section_pattern *next;
+};
+
+static struct section_pattern *patterns = NULL;
+
+static void
+add_pattern (const char *pattern)
+{
+  struct section_pattern *p = xmalloc (sizeof *p);
+  p->pattern = xstrdup (pattern);
+  p->next = patterns;
+  patterns = p;
+}
+
+static void
+free_patterns (void)
+{
+  struct section_pattern *pattern = patterns;
+  while (pattern != NULL)
+    {
+      struct section_pattern *p = pattern;
+      pattern = p->next;
+      free (p->pattern);
+      free (p);
+    }
+}
+
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'v':
+      verbose++;
+      break;
+
+    case 'q':
+      verbose--;
+      break;
+
+    case 'f':
+      force = true;
+      break;
+
+    case 'p':
+      permissive = true;
+      break;
+
+    case 'n':
+      add_pattern (arg);
+      break;
+
+    case 'o':
+      if (foutput != NULL)
+	argp_error (state, N_("-o option specified twice"));
+      else
+	foutput = arg;
+      break;
+
+    case 't':
+      if (type != UNSET)
+	argp_error (state, N_("-t option specified twice"));
+
+      if (strcmp ("none", arg) == 0)
+	type = NONE;
+      else if (strcmp ("zlib", arg) == 0 || strcmp ("zlib-gabi", arg) == 0)
+	type = ZLIB;
+      else if (strcmp ("zlib-gnu", arg) == 0 || strcmp ("gnu", arg) == 0)
+	type = ZLIB_GNU;
+      else if (strcmp ("zstd", arg) == 0)
+#ifdef USE_ZSTD_COMPRESS
+	type = ZSTD;
+#else
+	argp_error (state, N_("ZSTD support is not enabled"));
+#endif
+      else
+	argp_error (state, N_("unknown compression type '%s'"), arg);
+      break;
+
+    case ARGP_KEY_SUCCESS:
+      if (type == UNSET)
+	type = ZLIB;
+      if (patterns == NULL)
+	add_pattern (".?(z)debug*");
+      break;
+
+    case ARGP_KEY_NO_ARGS:
+      /* We need at least one input file.  */
+      argp_error (state, N_("No input file given"));
+      break;
+
+    case ARGP_KEY_ARGS:
+      if (foutput != NULL && state->argc - state->next > 1)
+	argp_error (state,
+		    N_("Only one input file allowed together with '-o'"));
+      /* We only use this for checking the number of arguments, we don't
+	 actually want to consume them.  */
+      FALLTHROUGH;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static bool
+section_name_matches (const char *name)
+{
+  struct section_pattern *pattern = patterns;
+  while (pattern != NULL)
+    {
+      if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0)
+	return true;
+      pattern = pattern->next;
+    }
+  return false;
+}
+
+static int
+setshdrstrndx (Elf *elf, GElf_Ehdr *ehdr, size_t ndx)
+{
+  if (ndx < SHN_LORESERVE)
+    ehdr->e_shstrndx = ndx;
+  else
+    {
+      ehdr->e_shstrndx = SHN_XINDEX;
+      Elf_Scn *zscn = elf_getscn (elf, 0);
+      GElf_Shdr zshdr_mem;
+      GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
+      if (zshdr == NULL)
+	return -1;
+      zshdr->sh_link = ndx;
+      if (gelf_update_shdr (zscn, zshdr) == 0)
+	return -1;
+    }
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    return -1;
+
+  return 0;
+}
+
+static int
+compress_section (Elf_Scn *scn, size_t orig_size, const char *name,
+		  const char *newname, size_t ndx,
+		  enum ch_type schtype, enum ch_type dchtype,
+		  bool report_verbose)
+{
+  /* We either compress or decompress.  */
+  assert (schtype == NONE || dchtype == NONE);
+  bool compress = dchtype != NONE;
+
+  int res;
+  unsigned int flags = compress && force ? ELF_CHF_FORCE : 0;
+  if (schtype == ZLIB_GNU || dchtype == ZLIB_GNU)
+    res = elf_compress_gnu (scn, compress ? 1 : 0, flags);
+  else
+    res = elf_compress (scn, dchtype, flags);
+
+  if (res < 0)
+    error (0, 0, "Couldn't %s section [%zd] %s: %s",
+	   compress ? "compress" : "decompress",
+	   ndx, name, elf_errmsg (-1));
+  else
+    {
+      if (compress && res == 0)
+	{
+	  if (verbose >= 0)
+	    printf ("[%zd] %s NOT compressed, wouldn't be smaller\n",
+		    ndx, name);
+	}
+
+      if (report_verbose && res > 0)
+	{
+	  printf ("[%zd] %s %s", ndx, name,
+		  compress ? "compressed" : "decompressed");
+	  if (newname != NULL)
+	    printf (" -> %s", newname);
+
+	  /* Reload shdr, it has changed.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    {
+	      error (0, 0, "Couldn't get shdr for section [%zd]", ndx);
+	      return -1;
+	    }
+	  float new = shdr->sh_size;
+	  float orig = orig_size ?: 1;
+	  printf (" (%zu => %" PRIu64 " %.2f%%)\n",
+		  orig_size, shdr->sh_size, (new / orig) * 100);
+	}
+    }
+
+  return res;
+}
+
+static void
+set_section (unsigned int *sections, size_t ndx)
+{
+  sections[ndx / WORD_BITS] |= (1U << (ndx % WORD_BITS));
+}
+
+static bool
+get_section (unsigned int *sections, size_t ndx)
+{
+  return (sections[ndx / WORD_BITS] & (1U << (ndx % WORD_BITS))) != 0;
+}
+
+/* How many sections are we going to change?  */
+static size_t
+get_sections (unsigned int *sections, size_t shnum)
+{
+  size_t s = 0;
+  for (size_t i = 0; i < shnum / WORD_BITS + 1; i++)
+    s += __builtin_popcount (sections[i]);
+  return s;
+}
+
+/* Return compression type of a given section SHDR.  */
+
+static enum ch_type
+get_section_chtype (Elf_Scn *scn, GElf_Shdr *shdr, const char *sname,
+		    size_t ndx)
+{
+  enum ch_type chtype = UNSET;
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+    {
+      GElf_Chdr chdr;
+      if (gelf_getchdr (scn, &chdr) != NULL)
+	{
+	  chtype = (enum ch_type)chdr.ch_type;
+	  if (chtype == NONE)
+	    {
+	      error (0, 0, "Compression type for section %zd"
+		     " can't be zero ", ndx);
+	      chtype = UNSET;
+	    }
+	  else if (chtype > MAXIMAL_CH_TYPE)
+	    {
+	      error (0, 0, "Compression type (%d) for section %zd"
+		     " is unsupported ", chtype, ndx);
+	      chtype = UNSET;
+	    }
+	}
+      else
+	error (0, 0, "Couldn't get chdr for section %zd", ndx);
+    }
+  /* Set ZLIB_GNU compression manually for .zdebug* sections.  */
+  else if (startswith (sname, ".zdebug"))
+    chtype = ZLIB_GNU;
+  else
+    chtype = NONE;
+
+  return chtype;
+}
+
+static int
+process_file (const char *fname)
+{
+  if (verbose > 0)
+    printf ("processing: %s\n", fname);
+
+  /* The input ELF.  */
+  int fd = -1;
+  Elf *elf = NULL;
+
+  /* The output ELF.  */
+  char *fnew = NULL;
+  int fdnew = -1;
+  Elf *elfnew = NULL;
+
+  /* Buffer for (one) new section name if necessary.  */
+  char *snamebuf = NULL;
+
+  /* String table (and symbol table), if section names need adjusting.  */
+  Dwelf_Strtab *names = NULL;
+  Dwelf_Strent **scnstrents = NULL;
+  Dwelf_Strent **symstrents = NULL;
+  char **scnnames = NULL;
+
+  /* Section data from names.  */
+  void *namesbuf = NULL;
+
+  /* Which sections match and need to be (un)compressed.  */
+  unsigned int *sections = NULL;
+
+  /* How many sections are we talking about?  */
+  size_t shnum = 0;
+  int res = 1;
+
+  fd = open (fname, O_RDONLY);
+  if (fd < 0)
+    {
+      error (0, errno, "Couldn't open %s\n", fname);
+      goto cleanup;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      error (0, 0, "Couldn't open ELF file %s for reading: %s",
+	     fname, elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* We don't handle ar files (or anything else), we probably should.  */
+  Elf_Kind kind = elf_kind (elf);
+  if (kind != ELF_K_ELF)
+    {
+      if (kind == ELF_K_AR)
+	error (0, 0, "Cannot handle ar files: %s", fname);
+      else
+	error (0, 0, "Unknown file type: %s", fname);
+      goto cleanup;
+    }
+
+  struct stat st;
+  if (fstat (fd, &st) != 0)
+    {
+      error (0, errno, "Couldn't fstat %s", fname);
+      goto cleanup;
+    }
+
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    {
+      error (0, 0, "Couldn't get ehdr for %s: %s", fname, elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* Get the section header string table.  */
+  size_t shdrstrndx;
+  if (elf_getshdrstrndx (elf, &shdrstrndx) != 0)
+    {
+      error (0, 0, "Couldn't get section header string table index in %s: %s",
+	     fname, elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* How many sections are we talking about?  */
+  if (elf_getshdrnum (elf, &shnum) != 0)
+    {
+      error (0, 0, "Couldn't get number of sections in %s: %s",
+	     fname, elf_errmsg (1));
+      goto cleanup;
+    }
+
+  if (shnum == 0)
+    {
+      error (0, 0, "ELF file %s has no sections", fname);
+      goto cleanup;
+    }
+
+  sections = xcalloc (shnum / 8 + 1, sizeof (unsigned int));
+
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    {
+      error (0, 0, "Couldn't get phdrnum: %s", elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* Whether we need to adjust any section names (going to/from GNU
+     naming).  If so we'll need to build a new section header string
+     table.  */
+  bool adjust_names = false;
+
+  /* If there are phdrs we want to maintain the layout of the
+     allocated sections in the file.  */
+  bool layout = phnum != 0;
+
+  /* While going through all sections keep track of last section data
+     offset if needed to keep the layout.  We are responsible for
+     adding the section offsets and headers (e_shoff) in that case
+     (which we will place after the last section).  */
+  GElf_Off last_offset = 0;
+  if (layout)
+    last_offset = (ehdr.e_phoff
+		   + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT));
+
+  /* Which section, if any, is a symbol table that shares a string
+     table with the section header string table?  */
+  size_t symtabndx = 0;
+
+  /* We do three passes over all sections.
+
+     First an inspection pass over the old Elf to see which section
+     data needs to be copied and/or transformed, which sections need a
+     names change and whether there is a symbol table that might need
+     to be adjusted be if the section header name table is changed.
+
+     If nothing needs changing, and the input and output file are the
+     same, we are done.
+
+     Second a collection pass that creates the Elf sections and copies
+     the data.  This pass will compress/decompress section data when
+     needed.  And it will collect all data needed if we'll need to
+     construct a new string table. Afterwards the new string table is
+     constructed.
+
+     Third a fixup/adjustment pass over the new Elf that will adjust
+     any section references (names) and adjust the layout based on the
+     new sizes of the sections if necessary.  This pass is optional if
+     we aren't responsible for the layout and the section header
+     string table hasn't been changed.  */
+
+  /* Inspection pass.  */
+  size_t maxnamelen = 0;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      size_t ndx = elf_ndxscn (scn);
+      if (ndx > shnum)
+	{
+	  error (0, 0, "Unexpected section number %zd, expected only %zd",
+		 ndx, shnum);
+	  goto cleanup;
+	}
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  error (0, 0, "Couldn't get shdr for section %zd", ndx);
+	  goto cleanup;
+	}
+
+      const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+      if (sname == NULL)
+	{
+	  error (0, 0, "Couldn't get name for section %zd", ndx);
+	  goto cleanup;
+	}
+
+      if (section_name_matches (sname))
+	{
+	  enum ch_type schtype = get_section_chtype (scn, shdr, sname, ndx);
+	  if (!force && verbose > 0)
+	    {
+	      /* The current compression matches the final one.  */
+	      if (type == schtype)
+		switch (type)
+		  {
+		  case NONE:
+		    printf ("[%zd] %s already decompressed\n", ndx, sname);
+		    break;
+		  case ZLIB:
+		  case ZSTD:
+		    printf ("[%zd] %s already compressed\n", ndx, sname);
+		    break;
+		  case ZLIB_GNU:
+		    printf ("[%zd] %s already GNU compressed\n", ndx, sname);
+		    break;
+		  default:
+		    abort ();
+		  }
+	    }
+
+	  if (force || type != schtype)
+	    {
+	      if (shdr->sh_type != SHT_NOBITS
+		  && (shdr->sh_flags & SHF_ALLOC) == 0)
+		{
+		  set_section (sections, ndx);
+		  /* Check if we might want to change this section name.  */
+		  if (! adjust_names
+		      && ((type != ZLIB_GNU
+			   && startswith (sname, ".zdebug"))
+			  || (type == ZLIB_GNU
+			      && startswith (sname, ".debug"))))
+		    adjust_names = true;
+
+		  /* We need a buffer this large if we change the names.  */
+		  if (adjust_names)
+		    {
+		      size_t slen = strlen (sname);
+		      if (slen > maxnamelen)
+			maxnamelen = slen;
+		    }
+		}
+	      else
+		if (verbose >= 0)
+		  printf ("[%zd] %s ignoring %s section\n", ndx, sname,
+			  (shdr->sh_type == SHT_NOBITS ? "no bits" : "allocated"));
+	    }
+	}
+
+      if (shdr->sh_type == SHT_SYMTAB)
+	{
+	  /* Check if we might have to adjust the symbol name indexes.  */
+	  if (shdr->sh_link == shdrstrndx)
+	    {
+	      if (symtabndx != 0)
+		{
+		  error (0, 0,
+			 "Multiple symbol tables (%zd, %zd) using the same string table unsupported", symtabndx, ndx);
+		  goto cleanup;
+		}
+	      symtabndx = ndx;
+	    }
+	}
+
+      /* Keep track of last allocated data offset.  */
+      if (layout)
+	if ((shdr->sh_flags & SHF_ALLOC) != 0)
+	  {
+	    GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS
+					      ? shdr->sh_size : 0);
+	    if (last_offset < off)
+	      last_offset = off;
+	  }
+    }
+
+  if (foutput == NULL && get_sections (sections, shnum) == 0)
+    {
+      if (verbose > 0)
+	printf ("Nothing to do.\n");
+      res = 0;
+      goto cleanup;
+    }
+
+  if (adjust_names)
+    {
+      names = dwelf_strtab_init (true);
+      if (names == NULL)
+	{
+	  error (0, 0, "Not enough memory for new strtab");
+	  goto cleanup;
+	}
+      scnstrents = xmalloc (shnum
+			    * sizeof (Dwelf_Strent *));
+      scnnames = xcalloc (shnum, sizeof (char *));
+    }
+
+  /* Create a new (temporary) ELF file for the result.  */
+  if (foutput == NULL)
+    {
+      size_t fname_len = strlen (fname);
+      fnew = xmalloc (fname_len + sizeof (".XXXXXX"));
+      strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX");
+      fdnew = mkstemp (fnew);
+    }
+  else
+    {
+      fnew = xstrdup (foutput);
+      fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS);
+    }
+
+  if (fdnew < 0)
+    {
+      error (0, errno, "Couldn't create output file %s", fnew);
+      /* Since we didn't create it we don't want to try to unlink it.  */
+      free (fnew);
+      fnew = NULL;
+      goto cleanup;
+    }
+
+  elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
+  if (elfnew == NULL)
+    {
+      error (0, 0, "Couldn't open new ELF %s for writing: %s",
+	     fnew, elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* Create the new ELF header and copy over all the data.  */
+  if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
+    {
+      error (0, 0, "Couldn't create new ehdr: %s", elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  GElf_Ehdr newehdr;
+  if (gelf_getehdr (elfnew, &newehdr) == NULL)
+    {
+      error (0, 0, "Couldn't get new ehdr: %s", elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
+  newehdr.e_type = ehdr.e_type;
+  newehdr.e_machine = ehdr.e_machine;
+  newehdr.e_version = ehdr.e_version;
+  newehdr.e_entry = ehdr.e_entry;
+  newehdr.e_flags = ehdr.e_flags;
+
+  if (gelf_update_ehdr (elfnew, &newehdr) == 0)
+    {
+      error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* Copy over the phdrs as is.  */
+  if (phnum != 0)
+    {
+      if (gelf_newphdr (elfnew, phnum) == 0)
+	{
+	  error (0, 0, "Couldn't create phdrs: %s", elf_errmsg (-1));
+	  goto cleanup;
+	}
+
+      for (size_t cnt = 0; cnt < phnum; ++cnt)
+	{
+	  GElf_Phdr phdr_mem;
+	  GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+	  if (phdr == NULL)
+	    {
+	      error (0, 0, "Couldn't get phdr %zd: %s", cnt, elf_errmsg (-1));
+	      goto cleanup;
+	    }
+	  if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
+	    {
+	      error (0, 0, "Couldn't create phdr %zd: %s", cnt,
+		     elf_errmsg (-1));
+	      goto cleanup;
+	    }
+	}
+    }
+
+  /* Possibly add a 'z' and zero terminator.  */
+  if (maxnamelen > 0)
+    snamebuf = xmalloc (maxnamelen + 2);
+
+  /* We might want to read/adjust the section header strings and
+     symbol tables.  If so, and those sections are to be compressed
+     then we will have to decompress it during the collection pass and
+     compress it again in the fixup pass.  Don't compress unnecessary
+     and keep track of whether or not to compress them (later in the
+     fixup pass).  Also record the original size, so we can report the
+     difference later when we do compress.  */
+  enum ch_type shstrtab_compressed = UNSET;
+  size_t shstrtab_size = 0;
+  char *shstrtab_name = NULL;
+  char *shstrtab_newname = NULL;
+  enum ch_type symtab_compressed = UNSET;
+  size_t symtab_size = 0;
+  char *symtab_name = NULL;
+  char *symtab_newname = NULL;
+
+  /* Collection pass.  Copy over the sections, (de)compresses matching
+     sections, collect names of sections and symbol table if
+     necessary.  */
+  scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      size_t ndx = elf_ndxscn (scn);
+      assert (ndx < shnum);
+
+      /* (de)compress if section matched.  */
+      char *sname = NULL;
+      char *newname = NULL;
+      if (get_section (sections, ndx))
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    {
+	      error (0, 0, "Couldn't get shdr for section %zd", ndx);
+	      goto cleanup;
+	    }
+
+	  uint64_t size = shdr->sh_size;
+	  sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+	  if (sname == NULL)
+	    {
+	      error (0, 0, "Couldn't get name for section %zd", ndx);
+	      goto cleanup;
+	    }
+
+	  /* strdup sname, the shdrstrndx section itself might be
+	     (de)compressed, invalidating the string pointers.  */
+	  sname = xstrdup (sname);
+
+
+	  /* Detect source compression that is how is the section compressed
+	     now.  */
+	  enum ch_type schtype = get_section_chtype (scn, shdr, sname, ndx);
+	  if (schtype == UNSET)
+	    goto cleanup;
+
+	  /* We might want to decompress (and rename), but not
+	     compress during this pass since we might need the section
+	     data in later passes.  Skip those sections for now and
+	     compress them in the fixup pass.  */
+	  bool skip_compress_section = (adjust_names
+					&& (ndx == shdrstrndx
+					    || ndx == symtabndx));
+
+	  switch (type)
+	    {
+	    case NONE:
+	      if (schtype != NONE)
+		{
+		  if (schtype == ZLIB_GNU)
+		    {
+		      snamebuf[0] = '.';
+		      strcpy (&snamebuf[1], &sname[2]);
+		      newname = snamebuf;
+		    }
+		  if (compress_section (scn, size, sname, NULL, ndx,
+					schtype, NONE, verbose > 0) < 0)
+		    goto cleanup;
+		}
+	      else if (verbose > 0)
+		printf ("[%zd] %s already decompressed\n", ndx, sname);
+	      break;
+
+	    case ZLIB_GNU:
+	      if (startswith (sname, ".debug"))
+		{
+		  if (schtype == ZLIB || schtype == ZSTD)
+		    {
+		      /* First decompress to recompress GNU style.
+			 Don't report even when verbose.  */
+		      if (compress_section (scn, size, sname, NULL, ndx,
+					    schtype, NONE, false) < 0)
+			goto cleanup;
+		    }
+
+		  snamebuf[0] = '.';
+		  snamebuf[1] = 'z';
+		  strcpy (&snamebuf[2], &sname[1]);
+		  newname = snamebuf;
+
+		  if (skip_compress_section)
+		    {
+		      if (ndx == shdrstrndx)
+			{
+			  shstrtab_size = size;
+			  shstrtab_compressed = ZLIB_GNU;
+			  if (shstrtab_name != NULL
+			      || shstrtab_newname != NULL)
+			    {
+			      error (0, 0, "Internal error,"
+					   " shstrtab_name already set,"
+					   " while handling section [%zd] %s",
+				     ndx, sname);
+			      goto cleanup;
+			    }
+			  shstrtab_name = xstrdup (sname);
+			  shstrtab_newname = xstrdup (newname);
+			}
+		      else
+			{
+			  symtab_size = size;
+			  symtab_compressed = ZLIB_GNU;
+			  symtab_name = xstrdup (sname);
+			  symtab_newname = xstrdup (newname);
+			}
+		    }
+		  else
+		    {
+		      int result = compress_section (scn, size, sname, newname,
+						     ndx, NONE, type,
+						     verbose > 0);
+		      if (result < 0)
+			goto cleanup;
+
+		      if (result == 0)
+			newname = NULL;
+		    }
+		}
+	      else if (verbose >= 0)
+		{
+		  if (schtype == ZLIB_GNU)
+		    printf ("[%zd] %s unchanged, already GNU compressed\n",
+			    ndx, sname);
+		  else
+		    printf ("[%zd] %s cannot GNU compress section not starting with .debug\n",
+			    ndx, sname);
+		}
+	      break;
+
+	    case ZLIB:
+	    case ZSTD:
+	      if (schtype != type)
+		{
+		  if (schtype != NONE)
+		    {
+		      /* Decompress first.  */
+		      if (compress_section (scn, size, sname, NULL, ndx,
+					    schtype, NONE, false) < 0)
+			goto cleanup;
+
+		      if (schtype == ZLIB_GNU)
+			{
+			  snamebuf[0] = '.';
+			  strcpy (&snamebuf[1], &sname[2]);
+			  newname = snamebuf;
+			}
+		    }
+
+		  if (skip_compress_section)
+		    {
+		      if (ndx == shdrstrndx)
+			{
+			  shstrtab_size = size;
+			  shstrtab_compressed = type;
+			  if (shstrtab_name != NULL
+			      || shstrtab_newname != NULL)
+			    {
+			      error (0, 0, "Internal error,"
+					   " shstrtab_name already set,"
+					   " while handling section [%zd] %s",
+				     ndx, sname);
+			      goto cleanup;
+			    }
+			  shstrtab_name = xstrdup (sname);
+			  shstrtab_newname = (newname == NULL
+					      ? NULL : xstrdup (newname));
+			}
+		      else
+			{
+			  symtab_size = size;
+			  symtab_compressed = type;
+			  symtab_name = xstrdup (sname);
+			  symtab_newname = (newname == NULL
+					    ? NULL : xstrdup (newname));
+			}
+		    }
+		  else if (compress_section (scn, size, sname, newname, ndx,
+					     NONE, type, verbose > 0) < 0)
+		    goto cleanup;
+		}
+	      else if (verbose > 0)
+		printf ("[%zd] %s already compressed\n", ndx, sname);
+	      break;
+
+	    case UNSET:
+	      break;
+	    }
+
+	  free (sname);
+	}
+
+      Elf_Scn *newscn = elf_newscn (elfnew);
+      if (newscn == NULL)
+	{
+	  error (0, 0, "Couldn't create new section %zd", ndx);
+	  goto cleanup;
+	}
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  error (0, 0, "Couldn't get shdr for section %zd", ndx);
+	  goto cleanup;
+	}
+
+      if (gelf_update_shdr (newscn, shdr) == 0)
+        {
+	  error (0, 0, "Couldn't update section header %zd", ndx);
+	  goto cleanup;
+	}
+
+      /* Except for the section header string table all data can be
+	 copied as is.  The section header string table will be
+	 created later and the symbol table might be fixed up if
+	 necessary.  */
+      if (! adjust_names || ndx != shdrstrndx)
+	{
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    {
+	      error (0, 0, "Couldn't get data from section %zd", ndx);
+	      goto cleanup;
+	    }
+
+	  Elf_Data *newdata = elf_newdata (newscn);
+	  if (newdata == NULL)
+	    {
+	      error (0, 0, "Couldn't create new data for section %zd", ndx);
+	      goto cleanup;
+	    }
+
+	  *newdata = *data;
+	}
+
+      /* Keep track of the (new) section names.  */
+      if (adjust_names)
+	{
+	  char *name;
+	  if (newname != NULL)
+	    name = newname;
+	  else
+	    {
+	      name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+	      if (name == NULL)
+		{
+		  error (0, 0, "Couldn't get name for section [%zd]", ndx);
+		  goto cleanup;
+		}
+	    }
+
+	  /* We need to keep a copy of the name till the strtab is done.  */
+	  name = scnnames[ndx] = xstrdup (name);
+	  if ((scnstrents[ndx] = dwelf_strtab_add (names, name)) == NULL)
+	    {
+	      error (0, 0, "No memory to add section name string table");
+	      goto cleanup;
+	    }
+
+	  /* If the symtab shares strings then add those too.  */
+	  if (ndx == symtabndx)
+	    {
+	      /* If the section is (still) compressed we'll need to
+		 uncompress it first to adjust the data, then
+		 recompress it in the fixup pass.  */
+	      if (symtab_compressed == UNSET)
+		{
+		  size_t size = shdr->sh_size;
+		  if ((shdr->sh_flags == SHF_COMPRESSED) != 0)
+		    {
+		      /* Don't report the (internal) uncompression.  */
+		      if (compress_section (newscn, size, sname, NULL, ndx,
+					    ZLIB, NONE, false) < 0)
+			goto cleanup;
+
+		      symtab_size = size;
+		      symtab_compressed = ZLIB;
+		    }
+		  else if (startswith (name, ".zdebug"))
+		    {
+		      /* Don't report the (internal) uncompression.  */
+		      if (compress_section (newscn, size, sname, NULL, ndx,
+					    ZLIB_GNU, NONE, false) < 0)
+			goto cleanup;
+
+		      symtab_size = size;
+		      symtab_compressed = ZLIB_GNU;
+		    }
+		}
+
+	      Elf_Data *symd = elf_getdata (newscn, NULL);
+	      if (symd == NULL)
+		{
+		  error (0, 0, "Couldn't get symtab data for section [%zd] %s",
+			 ndx, name);
+		  goto cleanup;
+		}
+	      size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
+	      size_t syms = symd->d_size / elsize;
+	      if (symstrents != NULL)
+		{
+		  error (0, 0, "Internal error, symstrents already set,"
+			 " while handling section [%zd] %s", ndx, name);
+		  goto cleanup;
+		}
+	      symstrents = xmalloc (syms * sizeof (Dwelf_Strent *));
+	      for (size_t i = 0; i < syms; i++)
+		{
+		  GElf_Sym sym_mem;
+		  GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
+		  if (sym == NULL)
+		    {
+		      error (0, 0, "Couldn't get symbol %zd", i);
+		      goto cleanup;
+		    }
+		  if (sym->st_name != 0)
+		    {
+		      /* Note we take the name from the original ELF,
+			 since the new one will not have setup the
+			 strtab yet.  */
+		      const char *symname = elf_strptr (elf, shdrstrndx,
+							sym->st_name);
+		      if (symname == NULL)
+			{
+			  error (0, 0, "Couldn't get symbol %zd name", i);
+			  goto cleanup;
+			}
+		      symstrents[i] = dwelf_strtab_add (names, symname);
+		      if (symstrents[i] == NULL)
+			{
+			  error (0, 0, "No memory to add to symbol name");
+			  goto cleanup;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+  if (adjust_names)
+    {
+      /* We got all needed strings, put the new data in the shstrtab.  */
+      if (verbose > 0)
+	printf ("[%zd] Updating section string table\n", shdrstrndx);
+
+      scn = elf_getscn (elfnew, shdrstrndx);
+      if (scn == NULL)
+	{
+	  error (0, 0, "Couldn't get new section header string table [%zd]",
+		 shdrstrndx);
+	  goto cleanup;
+	}
+
+      Elf_Data *data = elf_newdata (scn);
+      if (data == NULL)
+	{
+	  error (0, 0, "Couldn't create new section header string table data");
+	  goto cleanup;
+	}
+      if (dwelf_strtab_finalize (names, data) == NULL)
+	{
+	  error (0, 0, "Not enough memory to create string table");
+	  goto cleanup;
+	}
+      namesbuf = data->d_buf;
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  error (0, 0, "Couldn't get shdr for new section strings %zd",
+		 shdrstrndx);
+	  goto cleanup;
+	}
+
+      /* Note that we also might have to compress and possibly set
+	 sh_off below */
+      shdr->sh_name = dwelf_strent_off (scnstrents[shdrstrndx]);
+      shdr->sh_type = SHT_STRTAB;
+      shdr->sh_flags = 0;
+      shdr->sh_addr = 0;
+      shdr->sh_offset = 0;
+      shdr->sh_size = data->d_size;
+      shdr->sh_link = SHN_UNDEF;
+      shdr->sh_info = SHN_UNDEF;
+      shdr->sh_addralign = 1;
+      shdr->sh_entsize = 0;
+
+      if (gelf_update_shdr (scn, shdr) == 0)
+	{
+	  error (0, 0, "Couldn't update new section strings [%zd]",
+		 shdrstrndx);
+	  goto cleanup;
+	}
+
+      /* We might have to compress the data if the user asked us to,
+	 or if the section was already compressed (and the user didn't
+	 ask for decompression).  Note somewhat identical code for
+	 symtab below.  */
+      if (shstrtab_compressed == UNSET)
+	{
+	  /* The user didn't ask for compression, but maybe it was
+	     compressed in the original ELF file.  */
+	  Elf_Scn *oldscn = elf_getscn (elf, shdrstrndx);
+	  if (oldscn == NULL)
+	    {
+	      error (0, 0, "Couldn't get section header string table [%zd]",
+		     shdrstrndx);
+	      goto cleanup;
+	    }
+
+	  shdr = gelf_getshdr (oldscn, &shdr_mem);
+	  if (shdr == NULL)
+	    {
+	      error (0, 0, "Couldn't get shdr for old section strings [%zd]",
+		     shdrstrndx);
+	      goto cleanup;
+	    }
+
+	  shstrtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+	  if (shstrtab_name == NULL)
+	    {
+	      error (0, 0, "Couldn't get name for old section strings [%zd]",
+		     shdrstrndx);
+	      goto cleanup;
+	    }
+
+	  shstrtab_size = shdr->sh_size;
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    shstrtab_compressed = ZLIB;
+	  else if (startswith (shstrtab_name, ".zdebug"))
+	    shstrtab_compressed = ZLIB_GNU;
+	}
+
+      /* Should we (re)compress?  */
+      if (shstrtab_compressed != UNSET)
+	{
+	  if (compress_section (scn, shstrtab_size, shstrtab_name,
+				shstrtab_newname, shdrstrndx,
+				NONE, shstrtab_compressed,
+				verbose > 0) < 0)
+	    goto cleanup;
+	}
+    }
+
+  /* Make sure to re-get the new ehdr.  Adding phdrs and shdrs will
+     have changed it.  */
+  if (gelf_getehdr (elfnew, &newehdr) == NULL)
+    {
+      error (0, 0, "Couldn't re-get new ehdr: %s", elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* Set this after the sections have been created, otherwise section
+     zero might not exist yet.  */
+  if (setshdrstrndx (elfnew, &newehdr, shdrstrndx) != 0)
+    {
+      error (0, 0, "Couldn't set new shdrstrndx: %s", elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  /* Fixup pass.  Adjust string table references, symbol table and
+     layout if necessary.  */
+  if (layout || adjust_names)
+    {
+      scn = NULL;
+      while ((scn = elf_nextscn (elfnew, scn)) != NULL)
+	{
+	  size_t ndx = elf_ndxscn (scn);
+
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    {
+	      error (0, 0, "Couldn't get shdr for section %zd", ndx);
+	      goto cleanup;
+	    }
+
+	  /* Keep the offset of allocated sections so they are at the
+	     same place in the file. Add (possibly changed)
+	     unallocated ones after the allocated ones.  */
+	  if ((shdr->sh_flags & SHF_ALLOC) == 0)
+	    {
+	      /* Zero means one.  No alignment constraints.  */
+	      size_t addralign = shdr->sh_addralign ?: 1;
+	      last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
+	      shdr->sh_offset = last_offset;
+	      if (shdr->sh_type != SHT_NOBITS)
+		last_offset += shdr->sh_size;
+	    }
+
+	  if (adjust_names)
+	    shdr->sh_name = dwelf_strent_off (scnstrents[ndx]);
+
+	  if (gelf_update_shdr (scn, shdr) == 0)
+	    {
+	      error (0, 0, "Couldn't update section header %zd", ndx);
+	      goto cleanup;
+	    }
+
+	  if (adjust_names && ndx == symtabndx)
+	    {
+	      if (verbose > 0)
+		printf ("[%zd] Updating symbol table\n", symtabndx);
+
+	      Elf_Data *symd = elf_getdata (scn, NULL);
+	      if (symd == NULL)
+		{
+		  error (0, 0, "Couldn't get new symtab data section [%zd]",
+			 ndx);
+		  goto cleanup;
+		}
+	      size_t elsize = gelf_fsize (elfnew, ELF_T_SYM, 1, EV_CURRENT);
+	      size_t syms = symd->d_size / elsize;
+	      for (size_t i = 0; i < syms; i++)
+		{
+		  GElf_Sym sym_mem;
+		  GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
+		  if (sym == NULL)
+		    {
+		      error (0, 0, "2 Couldn't get symbol %zd", i);
+		      goto cleanup;
+		    }
+
+		  if (sym->st_name != 0)
+		    {
+		      sym->st_name = dwelf_strent_off (symstrents[i]);
+
+		      if (gelf_update_sym (symd, i, sym) == 0)
+			{
+			  error (0, 0, "Couldn't update symbol %zd", i);
+			  goto cleanup;
+			}
+		    }
+		}
+
+	      /* We might have to compress the data if the user asked
+		 us to, or if the section was already compressed (and
+		 the user didn't ask for decompression).  Note
+		 somewhat identical code for shstrtab above.  */
+	      if (symtab_compressed == UNSET)
+		{
+		  /* The user didn't ask for compression, but maybe it was
+		     compressed in the original ELF file.  */
+		  Elf_Scn *oldscn = elf_getscn (elf, symtabndx);
+		  if (oldscn == NULL)
+		    {
+		      error (0, 0, "Couldn't get symbol table [%zd]",
+			     symtabndx);
+		      goto cleanup;
+		    }
+
+		  shdr = gelf_getshdr (oldscn, &shdr_mem);
+		  if (shdr == NULL)
+		    {
+		      error (0, 0, "Couldn't get old symbol table shdr [%zd]",
+			     symtabndx);
+		      goto cleanup;
+		    }
+
+		  symtab_name = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+		  if (symtab_name == NULL)
+		    {
+		      error (0, 0, "Couldn't get old symbol table name [%zd]",
+			     symtabndx);
+		      goto cleanup;
+		    }
+
+		  symtab_size = shdr->sh_size;
+		  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+		    symtab_compressed = ZLIB;
+		  else if (startswith (symtab_name, ".zdebug"))
+		    symtab_compressed = ZLIB_GNU;
+		}
+
+	      /* Should we (re)compress?  */
+	      if (symtab_compressed != UNSET)
+		{
+		  if (compress_section (scn, symtab_size, symtab_name,
+					symtab_newname, symtabndx,
+					NONE, symtab_compressed,
+					verbose > 0) < 0)
+		    goto cleanup;
+		}
+	    }
+	}
+    }
+
+  /* If we have phdrs we want elf_update to layout the SHF_ALLOC
+     sections precisely as in the original file.  In that case we are
+     also responsible for setting phoff and shoff */
+  if (layout)
+    {
+      if (gelf_getehdr (elfnew, &newehdr) == NULL)
+	{
+	  error (0, 0, "Couldn't get ehdr: %s", elf_errmsg (-1));
+	  goto cleanup;
+	}
+
+      /* Position the shdrs after the last (unallocated) section.  */
+      const size_t offsize = gelf_fsize (elfnew, ELF_T_OFF, 1, EV_CURRENT);
+      newehdr.e_shoff = ((last_offset + offsize - 1)
+			 & ~((GElf_Off) (offsize - 1)));
+
+      /* The phdrs go in the same place as in the original file.
+	 Normally right after the ELF header.  */
+      newehdr.e_phoff = ehdr.e_phoff;
+
+      if (gelf_update_ehdr (elfnew, &newehdr) == 0)
+	{
+	  error (0, 0, "Couldn't update ehdr: %s", elf_errmsg (-1));
+	  goto cleanup;
+	}
+    }
+
+  elf_flagelf (elfnew, ELF_C_SET, ((layout ? ELF_F_LAYOUT : 0)
+				   | (permissive ? ELF_F_PERMISSIVE : 0)));
+
+  if (elf_update (elfnew, ELF_C_WRITE) < 0)
+    {
+      error (0, 0, "Couldn't write %s: %s", fnew, elf_errmsg (-1));
+      goto cleanup;
+    }
+
+  elf_end (elfnew);
+  elfnew = NULL;
+
+  /* Try to match mode and owner.group of the original file.
+     Note to set suid bits we have to make sure the owner is setup
+     correctly first. Otherwise fchmod will drop them silently
+     or fchown may clear them.  */
+  if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
+    if (verbose >= 0)
+      error (0, errno, "Couldn't fchown %s", fnew);
+  if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
+    if (verbose >= 0)
+      error (0, errno, "Couldn't fchmod %s", fnew);
+
+  /* Finally replace the old file with the new file.  */
+  if (foutput == NULL)
+    if (rename (fnew, fname) != 0)
+      {
+	error (0, errno, "Couldn't rename %s to %s", fnew, fname);
+	goto cleanup;
+      }
+
+  /* We are finally done with the new file, don't unlink it now.  */
+  free (fnew);
+  fnew = NULL;
+  res = 0;
+
+cleanup:
+  elf_end (elf);
+  close (fd);
+
+  elf_end (elfnew);
+  close (fdnew);
+
+  if (fnew != NULL)
+    {
+      unlink (fnew);
+      free (fnew);
+      fnew = NULL;
+    }
+
+  free (snamebuf);
+  if (names != NULL)
+    {
+      dwelf_strtab_free (names);
+      free (scnstrents);
+      free (symstrents);
+      free (namesbuf);
+      if (scnnames != NULL)
+	{
+	  for (size_t n = 0; n < shnum; n++)
+	    free (scnnames[n]);
+	  free (scnnames);
+	}
+    }
+
+  free (sections);
+  return res;
+}
+
+int
+main (int argc, char **argv)
+{
+  const struct argp_option options[] =
+    {
+      { "output", 'o', "FILE", 0,
+	N_("Place (de)compressed output into FILE"),
+	0 },
+      { "type", 't', "TYPE", 0,
+	N_("What type of compression to apply. TYPE can be 'none' (decompress), 'zlib' (ELF ZLIB compression, the default, 'zlib-gabi' is an alias), "
+	   "'zlib-gnu' (.zdebug GNU style compression, 'gnu' is an alias) or 'zstd' (ELF ZSTD compression)"),
+	0 },
+      { "name", 'n', "SECTION", 0,
+	N_("SECTION name to (de)compress, SECTION is an extended wildcard pattern (defaults to '.?(z)debug*')"),
+	0 },
+      { "verbose", 'v', NULL, 0,
+	N_("Print a message for each section being (de)compressed"),
+	0 },
+      { "force", 'f', NULL, 0,
+	N_("Force compression of section even if it would become larger or update/rewrite the file even if no section would be (de)compressed"),
+	0 },
+      { "permissive", 'p', NULL, 0,
+	N_("Relax a few rules to handle slightly broken ELF files"),
+	0 },
+      { "quiet", 'q', NULL, 0,
+	N_("Be silent when a section cannot be compressed"),
+	0 },
+      { NULL, 0, NULL, 0, NULL, 0 }
+    };
+
+  const struct argp argp =
+    {
+      .options = options,
+      .parser = parse_opt,
+      .args_doc = N_("FILE..."),
+      .doc = N_("Compress or decompress sections in an ELF file.")
+    };
+
+  int remaining;
+  if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
+    return EXIT_FAILURE;
+
+  /* Should already be handled by ARGP_KEY_NO_ARGS case above,
+     just sanity check.  */
+  if (remaining >= argc)
+    error_exit (0, N_("No input file given"));
+
+  /* Likewise for the ARGP_KEY_ARGS case above, an extra sanity check.  */
+  if (foutput != NULL && remaining + 1 < argc)
+    error_exit (0, N_("Only one input file allowed together with '-o'"));
+
+  elf_version (EV_CURRENT);
+
+  /* Process all the remaining files.  */
+  int result = 0;
+  do
+    result |= process_file (argv[remaining]);
+  while (++remaining < argc);
+
+  free_patterns ();
+  return result;
+}
diff --git a/src/elflint.c b/src/elflint.c
new file mode 100644
index 0000000..864de71
--- /dev/null
+++ b/src/elflint.c
@@ -0,0 +1,4881 @@
+/* Pedantic checking of ELF files compliance with gABI/psABI spec.
+   Copyright (C) 2001-2015, 2017, 2018 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <endian.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <elf-knowledge.h>
+#include <libeu.h>
+#include <system.h>
+#include <printversion.h>
+#include "../libelf/libelfP.h"
+#include "../libelf/common.h"
+#include "../libebl/libeblP.h"
+#include "../libdw/libdwP.h"
+#include "../libdwfl/libdwflP.h"
+#include "../libdw/memory-access.h"
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+#define ARGP_strict	300
+#define ARGP_gnuld	301
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { "strict", ARGP_strict, NULL, 0,
+    N_("Be extremely strict, flag level 2 features."), 0 },
+  { "quiet", 'q', NULL, 0, N_("Do not print anything if successful"), 0 },
+  { "debuginfo", 'd', NULL, 0, N_("Binary is a separate debuginfo file"), 0 },
+  { "gnu-ld", ARGP_gnuld, NULL, 0,
+    N_("Binary has been created with GNU ld and is therefore known to be \
+broken in certain ways"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Pedantic checking of ELF files compliance with gABI/psABI spec.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("FILE...");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+
+/* Declarations of local functions.  */
+static void process_file (int fd, Elf *elf, const char *prefix,
+			  const char *suffix, const char *fname, size_t size,
+			  bool only_one);
+static void process_elf_file (Elf *elf, const char *prefix, const char *suffix,
+			      const char *fname, size_t size, bool only_one);
+static void check_note_section (Ebl *ebl, GElf_Ehdr *ehdr,
+				GElf_Shdr *shdr, int idx);
+
+
+/* Report an error.  */
+#define ERROR(str, args...) \
+  do {									      \
+    printf (str, ##args);						      \
+    ++error_count;							      \
+  } while (0)
+static unsigned int error_count;
+
+/* True if we should perform very strict testing.  */
+static bool be_strict;
+
+/* True if no message is to be printed if the run is successful.  */
+static bool be_quiet;
+
+/* True if binary is from strip -f, not a normal ELF file.  */
+static bool is_debuginfo;
+
+/* True if binary is assumed to be generated with GNU ld.  */
+static bool gnuld;
+
+/* Index of section header string table.  */
+static uint32_t shstrndx;
+
+/* Array to count references in section groups.  */
+static int *scnref;
+
+/* Numbers of sections and program headers.  */
+static unsigned int shnum;
+static unsigned int phnum;
+
+
+int
+main (int argc, char *argv[])
+{
+  /* Set locale.  */
+  setlocale (LC_ALL, "");
+
+  /* Initialize the message catalog.  */
+  textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  int remaining;
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Before we start tell the ELF library which version we are using.  */
+  elf_version (EV_CURRENT);
+
+  /* Now process all the files given at the command line.  */
+  bool only_one = remaining + 1 == argc;
+  do
+    {
+      /* Open the file.  */
+      int fd = open (argv[remaining], O_RDONLY);
+      if (fd == -1)
+	{
+	  error (0, errno, _("cannot open input file '%s'"), argv[remaining]);
+	  continue;
+	}
+
+      /* Create an `Elf' descriptor.  */
+      Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+      if (elf == NULL)
+	ERROR (_("cannot generate Elf descriptor for '%s': %s\n"),
+	       argv[remaining], elf_errmsg (-1));
+      else
+	{
+	  unsigned int prev_error_count = error_count;
+	  struct stat st;
+
+	  if (fstat (fd, &st) != 0)
+	    {
+	      printf ("cannot stat '%s': %m\n", argv[remaining]);
+	      close (fd);
+	      continue;
+	    }
+
+	  process_file (fd, elf, NULL, NULL, argv[remaining], st.st_size,
+			only_one);
+
+	  /* Now we can close the descriptor.  */
+	  if (elf_end (elf) != 0)
+	    ERROR (_("error while closing Elf descriptor: %s\n"),
+		   elf_errmsg (-1));
+
+	  if (prev_error_count == error_count && !be_quiet)
+	    puts (_("No errors"));
+	}
+
+      close (fd);
+    }
+  while (++remaining < argc);
+
+  return error_count != 0;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case ARGP_strict:
+      be_strict = true;
+      break;
+
+    case 'q':
+      be_quiet = true;
+      break;
+
+    case 'd':
+      is_debuginfo = true;
+      break;
+
+    case ARGP_gnuld:
+      gnuld = true;
+      break;
+
+    case ARGP_KEY_NO_ARGS:
+      fputs (_("Missing file name.\n"), stderr);
+      argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name);
+      exit (EXIT_FAILURE);
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Process one file.  */
+static void
+process_file (int fd, Elf *elf, const char *prefix, const char *suffix,
+	      const char *fname, size_t size, bool only_one)
+{
+  /* We can handle two types of files: ELF files and archives.  */
+  Elf_Kind kind = elf_kind (elf);
+
+  switch (kind)
+    {
+    case ELF_K_ELF:
+      /* Yes!  It's an ELF file.  */
+      process_elf_file (elf, prefix, suffix, fname, size, only_one);
+      break;
+
+    case ELF_K_AR:
+      {
+	Elf *subelf;
+	Elf_Cmd cmd = ELF_C_READ_MMAP;
+	size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+	size_t fname_len = strlen (fname) + 1;
+	char new_prefix[prefix_len + 1 + fname_len];
+	char new_suffix[(suffix == NULL ? 0 : strlen (suffix)) + 2];
+	char *cp = new_prefix;
+
+	/* Create the full name of the file.  */
+	if (prefix != NULL)
+	  {
+	    cp = mempcpy (cp, prefix, prefix_len);
+	    *cp++ = '(';
+	    strcpy (stpcpy (new_suffix, suffix), ")");
+	  }
+	else
+	  new_suffix[0] = '\0';
+	memcpy (cp, fname, fname_len);
+
+	/* It's an archive.  We process each file in it.  */
+	while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+	  {
+	    kind = elf_kind (subelf);
+
+	    /* Call this function recursively.  */
+	    if (kind == ELF_K_ELF || kind == ELF_K_AR)
+	      {
+		Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+		assert (arhdr != NULL);
+
+		process_file (fd, subelf, new_prefix, new_suffix,
+			      arhdr->ar_name, arhdr->ar_size, false);
+	      }
+
+	    /* Get next archive element.  */
+	    cmd = elf_next (subelf);
+	    if (elf_end (subelf) != 0)
+	      ERROR (_(" error while freeing sub-ELF descriptor: %s\n"),
+		     elf_errmsg (-1));
+	  }
+      }
+      break;
+
+    default:
+      /* We cannot do anything.  */
+      ERROR (_("\
+Not an ELF file - it has the wrong magic bytes at the start\n"));
+      break;
+    }
+}
+
+
+static const char *
+section_name (Ebl *ebl, int idx)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr;
+  const char *ret;
+
+  if ((unsigned int) idx > shnum)
+    return "<invalid>";
+
+  shdr = gelf_getshdr (elf_getscn (ebl->elf, idx), &shdr_mem);
+  if (shdr == NULL)
+    return "<invalid>";
+
+  ret = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+  if (ret == NULL)
+    return "<invalid>";
+  return ret;
+}
+
+
+static const int valid_e_machine[] =
+  {
+    EM_M32, EM_SPARC, EM_386, EM_68K, EM_88K, EM_860, EM_MIPS, EM_S370,
+    EM_MIPS_RS3_LE, EM_PARISC, EM_VPP500, EM_SPARC32PLUS, EM_960, EM_PPC,
+    EM_PPC64, EM_S390, EM_V800, EM_FR20, EM_RH32, EM_RCE, EM_ARM,
+    EM_FAKE_ALPHA, EM_SH, EM_SPARCV9, EM_TRICORE, EM_ARC, EM_H8_300,
+    EM_H8_300H, EM_H8S, EM_H8_500, EM_IA_64, EM_MIPS_X, EM_COLDFIRE,
+    EM_68HC12, EM_MMA, EM_PCP, EM_NCPU, EM_NDR1, EM_STARCORE, EM_ME16,
+    EM_ST100, EM_TINYJ, EM_X86_64, EM_PDSP, EM_FX66, EM_ST9PLUS, EM_ST7,
+    EM_68HC16, EM_68HC11, EM_68HC08, EM_68HC05, EM_SVX, EM_ST19, EM_VAX,
+    EM_CRIS, EM_JAVELIN, EM_FIREPATH, EM_ZSP, EM_MMIX, EM_HUANY, EM_PRISM,
+    EM_AVR, EM_FR30, EM_D10V, EM_D30V, EM_V850, EM_M32R, EM_MN10300,
+    EM_MN10200, EM_PJ, EM_OPENRISC, EM_ARC_A5, EM_XTENSA, EM_ALPHA,
+    EM_TILEGX, EM_TILEPRO, EM_AARCH64, EM_BPF, EM_RISCV, EM_CSKY, EM_LOONGARCH,
+    EM_ARCV2
+  };
+#define nvalid_e_machine \
+  (sizeof (valid_e_machine) / sizeof (valid_e_machine[0]))
+
+
+static void
+check_elf_header (Ebl *ebl, GElf_Ehdr *ehdr, size_t size)
+{
+  char buf[512];
+  size_t cnt;
+
+  /* Check e_ident field.  */
+  if (ehdr->e_ident[EI_MAG0] != ELFMAG0)
+    ERROR ("e_ident[%d] != '%c'\n", EI_MAG0, ELFMAG0);
+  if (ehdr->e_ident[EI_MAG1] != ELFMAG1)
+    ERROR ("e_ident[%d] != '%c'\n", EI_MAG1, ELFMAG1);
+  if (ehdr->e_ident[EI_MAG2] != ELFMAG2)
+    ERROR ("e_ident[%d] != '%c'\n", EI_MAG2, ELFMAG2);
+  if (ehdr->e_ident[EI_MAG3] != ELFMAG3)
+    ERROR ("e_ident[%d] != '%c'\n", EI_MAG3, ELFMAG3);
+
+  if (ehdr->e_ident[EI_CLASS] != ELFCLASS32
+      && ehdr->e_ident[EI_CLASS] != ELFCLASS64)
+    ERROR (_("e_ident[%d] == %d is no known class\n"),
+	   EI_CLASS, ehdr->e_ident[EI_CLASS]);
+
+  if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB
+      && ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
+    ERROR (_("e_ident[%d] == %d is no known data encoding\n"),
+	   EI_DATA, ehdr->e_ident[EI_DATA]);
+
+  if (ehdr->e_ident[EI_VERSION] != EV_CURRENT)
+    ERROR (_("unknown ELF header version number e_ident[%d] == %d\n"),
+	   EI_VERSION, ehdr->e_ident[EI_VERSION]);
+
+  /* We currently don't handle any OS ABIs other than Linux and the
+     kFreeBSD variant of Debian.  */
+  if (ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE
+      && ehdr->e_ident[EI_OSABI] != ELFOSABI_LINUX
+      && ehdr->e_ident[EI_OSABI] != ELFOSABI_FREEBSD)
+    ERROR (_("unsupported OS ABI e_ident[%d] == '%s'\n"),
+	   EI_OSABI,
+	   ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
+
+  /* No ABI versions other than zero are supported either.  */
+  if (ehdr->e_ident[EI_ABIVERSION] != 0)
+    ERROR (_("unsupported ABI version e_ident[%d] == %d\n"),
+	   EI_ABIVERSION, ehdr->e_ident[EI_ABIVERSION]);
+
+  for (cnt = EI_PAD; cnt < EI_NIDENT; ++cnt)
+    if (ehdr->e_ident[cnt] != 0)
+      ERROR (_("e_ident[%zu] is not zero\n"), cnt);
+
+  /* Check the e_type field.  */
+  if (ehdr->e_type != ET_REL && ehdr->e_type != ET_EXEC
+      && ehdr->e_type != ET_DYN && ehdr->e_type != ET_CORE)
+    ERROR (_("unknown object file type %d\n"), ehdr->e_type);
+
+  /* Check the e_machine field.  */
+  for (cnt = 0; cnt < nvalid_e_machine; ++cnt)
+    if (valid_e_machine[cnt] == ehdr->e_machine)
+      break;
+  if (cnt == nvalid_e_machine)
+    ERROR (_("unknown machine type %d\n"), ehdr->e_machine);
+
+  /* Check the e_version field.  */
+  if (ehdr->e_version != EV_CURRENT)
+    ERROR (_("unknown object file version\n"));
+
+  /* Check the e_phoff and e_phnum fields.  */
+  if (ehdr->e_phoff == 0)
+    {
+      if (ehdr->e_phnum != 0)
+	ERROR (_("invalid program header offset\n"));
+      else if (ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
+	ERROR (_("\
+executables and DSOs cannot have zero program header offset\n"));
+    }
+  else if (ehdr->e_phnum == 0)
+    ERROR (_("invalid number of program header entries\n"));
+
+  /* Check the e_shoff field.  */
+  shnum = ehdr->e_shnum;
+  shstrndx = ehdr->e_shstrndx;
+  if (ehdr->e_shoff == 0)
+    {
+      if (ehdr->e_shnum != 0)
+	ERROR (_("invalid section header table offset\n"));
+      else if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
+	       && ehdr->e_type != ET_CORE)
+	ERROR (_("section header table must be present\n"));
+    }
+  else
+    {
+      if (ehdr->e_shnum == 0)
+	{
+	  /* Get the header of the zeroth section.  The sh_size field
+	     might contain the section number.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+	  if (shdr != NULL)
+	    {
+	      /* The error will be reported later.  */
+	      if (shdr->sh_size == 0)
+		ERROR (_("\
+invalid number of section header table entries\n"));
+	      else
+		shnum = shdr->sh_size;
+	    }
+	}
+
+      if (ehdr->e_shstrndx == SHN_XINDEX)
+	{
+	  /* Get the header of the zeroth section.  The sh_size field
+	     might contain the section number.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+	  if (shdr != NULL && shdr->sh_link < shnum)
+	    shstrndx = shdr->sh_link;
+	}
+      else if (shstrndx >= shnum)
+	ERROR (_("invalid section header index\n"));
+    }
+
+  /* Check the shdrs actually exist.  And uncompress them before
+     further checking.  Indexes between sections reference the
+     uncompressed data.  */
+  unsigned int scnt;
+  Elf_Scn *scn = NULL;
+  for (scnt = 1; scnt < shnum; ++scnt)
+     {
+	scn = elf_nextscn (ebl->elf, scn);
+	if (scn == NULL)
+	  break;
+	/* If the section wasn't compressed this does nothing, but
+	   returns an error.  We don't care.  */
+	if (elf_compress (scn, 0, 0) < 0) { ; }
+     }
+  if (scnt < shnum)
+    ERROR (_("Can only check %u headers, shnum was %u\n"), scnt, shnum);
+  shnum = scnt;
+
+  phnum = ehdr->e_phnum;
+  if (ehdr->e_phnum == PN_XNUM)
+    {
+      /* Get the header of the zeroth section.  The sh_info field
+	 might contain the phnum count.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+      if (shdr != NULL)
+	{
+	  /* The error will be reported later.  */
+	  if (shdr->sh_info < PN_XNUM)
+	    ERROR (_("\
+invalid number of program header table entries\n"));
+	  else
+	    phnum = shdr->sh_info;
+	}
+    }
+
+  /* Check the phdrs actually exist. */
+  unsigned int pcnt;
+  for (pcnt = 0; pcnt < phnum; ++pcnt)
+     {
+	GElf_Phdr phdr_mem;
+	GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
+	if (phdr == NULL)
+	  break;
+     }
+  if (pcnt < phnum)
+    ERROR (_("Can only check %u headers, phnum was %u\n"), pcnt, phnum);
+  phnum = pcnt;
+
+  /* Check the e_flags field.  */
+  if (!ebl_machine_flag_check (ebl, ehdr->e_flags))
+    ERROR (_("invalid machine flags: %s\n"),
+	   ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
+
+  /* Check e_ehsize, e_phentsize, and e_shentsize fields.  */
+  if (gelf_getclass (ebl->elf) == ELFCLASS32)
+    {
+      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf32_Ehdr))
+	ERROR (_("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
+
+      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf32_Phdr))
+	ERROR (_("invalid program header size: %hd\n"),
+	       ehdr->e_phentsize);
+      else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
+	ERROR (_("invalid program header position or size\n"));
+
+      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf32_Shdr))
+	ERROR (_("invalid section header size: %hd\n"),
+	       ehdr->e_shentsize);
+      else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
+	ERROR (_("invalid section header position or size\n"));
+    }
+  else if (gelf_getclass (ebl->elf) == ELFCLASS64)
+    {
+      if (ehdr->e_ehsize != 0 && ehdr->e_ehsize != sizeof (Elf64_Ehdr))
+	ERROR (_("invalid ELF header size: %hd\n"), ehdr->e_ehsize);
+
+      if (ehdr->e_phentsize != 0 && ehdr->e_phentsize != sizeof (Elf64_Phdr))
+	ERROR (_("invalid program header size: %hd\n"),
+	       ehdr->e_phentsize);
+      else if (ehdr->e_phoff + phnum * ehdr->e_phentsize > size)
+	ERROR (_("invalid program header position or size\n"));
+
+      if (ehdr->e_shentsize != 0 && ehdr->e_shentsize != sizeof (Elf64_Shdr))
+	ERROR (_("invalid section header size: %hd\n"),
+	       ehdr->e_shentsize);
+      else if (ehdr->e_shoff + shnum * ehdr->e_shentsize > size)
+	ERROR (_("invalid section header position or size\n"));
+    }
+}
+
+
+/* Check that there is a section group section with index < IDX which
+   contains section IDX and that there is exactly one.  */
+static void
+check_scn_group (Ebl *ebl, int idx)
+{
+  if (scnref[idx] == 0)
+    {
+      /* No reference so far.  Search following sections, maybe the
+	 order is wrong.  */
+      size_t cnt;
+
+      for (cnt = idx + 1; cnt < shnum; ++cnt)
+	{
+	  Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (shdr == NULL)
+	    /* We cannot get the section header so we cannot check it.
+	       The error to get the section header will be shown
+	       somewhere else.  */
+	    continue;
+
+	  if (shdr->sh_type != SHT_GROUP)
+	    continue;
+
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL || data->d_buf == NULL
+	      || data->d_size < sizeof (Elf32_Word))
+	    /* Cannot check the section.  */
+	    continue;
+
+	  Elf32_Word *grpdata = (Elf32_Word *) data->d_buf;
+	  for (size_t inner = 1; inner < data->d_size / sizeof (Elf32_Word);
+	       ++inner)
+	    if (grpdata[inner] == (Elf32_Word) idx)
+	      goto out;
+	}
+
+    out:
+      if (cnt == shnum)
+	ERROR (_("\
+section [%2d] '%s': section with SHF_GROUP flag set not part of a section group\n"),
+	       idx, section_name (ebl, idx));
+      else
+	ERROR (_("\
+section [%2d] '%s': section group [%2zu] '%s' does not precede group member\n"),
+	       idx, section_name (ebl, idx),
+	       cnt, section_name (ebl, cnt));
+    }
+}
+
+
+static void
+check_symtab (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  bool no_xndx_warned = false;
+  int no_pt_tls = 0;
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  GElf_Shdr strshdr_mem;
+  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				     &strshdr_mem);
+  if (strshdr == NULL)
+    return;
+
+  if (strshdr->sh_type != SHT_STRTAB)
+    {
+      ERROR (_("section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
+	     shdr->sh_link, section_name (ebl, shdr->sh_link),
+	     idx, section_name (ebl, idx));
+      strshdr = NULL;
+    }
+
+  /* Search for an extended section index table section.  */
+  Elf_Data *xndxdata = NULL;
+  Elf32_Word xndxscnidx = 0;
+  bool found_xndx = false;
+  for (size_t cnt = 1; cnt < shnum; ++cnt)
+    if (cnt != (size_t) idx)
+      {
+	Elf_Scn *xndxscn = elf_getscn (ebl->elf, cnt);
+	GElf_Shdr xndxshdr_mem;
+	GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
+	if (xndxshdr == NULL)
+	  continue;
+
+	if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
+	    && xndxshdr->sh_link == (GElf_Word) idx)
+	  {
+	    if (found_xndx)
+	      ERROR (_("\
+section [%2d] '%s': symbol table cannot have more than one extended index section\n"),
+		     idx, section_name (ebl, idx));
+
+	    xndxdata = elf_getdata (xndxscn, NULL);
+	    xndxscnidx = elf_ndxscn (xndxscn);
+	    found_xndx = true;
+	  }
+      }
+
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT);
+  if (shdr->sh_entsize != sh_entsize)
+    ERROR (_("\
+section [%2u] '%s': entry size is does not match ElfXX_Sym\n"),
+	   idx, section_name (ebl, idx));
+  else if (shdr->sh_info > shdr->sh_size / sh_entsize)
+    ERROR (_("\
+section [%2u] '%s': number of local entries in 'st_info' larger than table size\n"),
+	   idx, section_name (ebl, idx));
+
+  /* Test the zeroth entry.  */
+  GElf_Sym sym_mem;
+  Elf32_Word xndx;
+  GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, 0, &sym_mem, &xndx);
+  if (sym == NULL)
+      ERROR (_("section [%2d] '%s': cannot get symbol %d: %s\n"),
+	     idx, section_name (ebl, idx), 0, elf_errmsg (-1));
+  else
+    {
+      if (sym->st_name != 0)
+	ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
+	       idx, section_name (ebl, idx), "st_name");
+      if (sym->st_value != 0)
+	ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
+	       idx, section_name (ebl, idx), "st_value");
+      if (sym->st_size != 0)
+	ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
+	       idx, section_name (ebl, idx), "st_size");
+      if (sym->st_info != 0)
+	ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
+	       idx, section_name (ebl, idx), "st_info");
+      if (sym->st_other != 0)
+	ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
+	       idx, section_name (ebl, idx), "st_other");
+      if (sym->st_shndx != 0)
+	ERROR (_("section [%2d] '%s': '%s' in zeroth entry not zero\n"),
+	       idx, section_name (ebl, idx), "st_shndx");
+      if (xndxdata != NULL && xndx != 0)
+	ERROR (_("\
+section [%2d] '%s': XINDEX for zeroth entry not zero\n"),
+	       xndxscnidx, section_name (ebl, xndxscnidx));
+    }
+
+  for (size_t cnt = 1; cnt < shdr->sh_size / sh_entsize; ++cnt)
+    {
+      sym = gelf_getsymshndx (data, xndxdata, cnt, &sym_mem, &xndx);
+      if (sym == NULL)
+	{
+	  ERROR (_("section [%2d] '%s': cannot get symbol %zu: %s\n"),
+		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
+	  continue;
+	}
+
+      const char *name = "<invalid>";
+      if (strshdr == NULL)
+	name = "";
+      else if (sym->st_name >= strshdr->sh_size)
+	ERROR (_("\
+section [%2d] '%s': symbol %zu: invalid name value\n"),
+	       idx, section_name (ebl, idx), cnt);
+      else
+	{
+	  name = elf_strptr (ebl->elf, shdr->sh_link, sym->st_name);
+	  if (name == NULL)
+	    name = "";
+	}
+
+      if (sym->st_shndx == SHN_XINDEX)
+	{
+	  if (xndxdata == NULL)
+	    {
+	      if (!no_xndx_warned)
+		ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): too large section index but no extended section index section\n"),
+		       idx, section_name (ebl, idx), cnt, name);
+	      no_xndx_warned = true;
+	    }
+	  else if (xndx < SHN_LORESERVE)
+	    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): XINDEX used for index which would fit in st_shndx (%" PRIu32 ")\n"),
+		   xndxscnidx, section_name (ebl, xndxscnidx), cnt, name,
+		   xndx);
+	}
+      else if ((sym->st_shndx >= SHN_LORESERVE
+		// && sym->st_shndx <= SHN_HIRESERVE    always true
+		&& sym->st_shndx != SHN_ABS
+		&& sym->st_shndx != SHN_COMMON)
+	       || (sym->st_shndx >= shnum
+		   && (sym->st_shndx < SHN_LORESERVE
+		       /* || sym->st_shndx > SHN_HIRESERVE  always false */)))
+	ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): invalid section index\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+      else
+	xndx = sym->st_shndx;
+
+      if (GELF_ST_TYPE (sym->st_info) >= STT_NUM
+	  && !ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), NULL, 0))
+	ERROR (_("section [%2d] '%s': symbol %zu (%s): unknown type\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+
+      if (GELF_ST_BIND (sym->st_info) >= STB_NUM
+	  && !ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info), NULL,
+				       0))
+	ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): unknown symbol binding\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+      if (GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE
+	  && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
+	ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): unique symbol not of object type\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+
+      if (xndx == SHN_COMMON)
+	{
+	  /* Common symbols can only appear in relocatable files.  */
+	  if (ehdr->e_type != ET_REL)
+	    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): COMMON only allowed in relocatable files\n"),
+		   idx, section_name (ebl, idx), cnt, name);
+	  if (cnt < shdr->sh_info)
+	    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): local COMMON symbols are nonsense\n"),
+		   idx, section_name (ebl, idx), cnt, name);
+	  if (GELF_R_TYPE (sym->st_info) == STT_FUNC)
+	    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): function in COMMON section is nonsense\n"),
+		   idx, section_name (ebl, idx), cnt, name);
+	}
+      else if (xndx > 0 && xndx < shnum)
+	{
+	  GElf_Shdr destshdr_mem;
+	  GElf_Shdr *destshdr;
+
+	  destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx), &destshdr_mem);
+	  if (destshdr != NULL)
+	    {
+	      GElf_Addr sh_addr = (ehdr->e_type == ET_REL ? 0
+				   : destshdr->sh_addr);
+	      GElf_Addr st_value;
+	      if (GELF_ST_TYPE (sym->st_info) == STT_FUNC
+		  || (GELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
+		st_value = sym->st_value & ebl_func_addr_mask (ebl);
+	      else
+		st_value = sym->st_value;
+	      if (GELF_ST_TYPE (sym->st_info) != STT_TLS)
+		{
+		  if (! ebl_check_special_symbol (ebl, sym, name,
+						  destshdr))
+		    {
+		      if (st_value - sh_addr > destshdr->sh_size)
+			{
+			  /* GNU ld has severe bugs.  When it decides to remove
+			     empty sections it leaves symbols referencing them
+			     behind.  These are symbols in .symtab or .dynsym
+			     and for the named symbols have zero size.  See
+			     sourceware PR13621.  */
+			  if (!gnuld
+			      || (strcmp (section_name (ebl, idx), ".symtab")
+			          && strcmp (section_name (ebl, idx),
+					     ".dynsym"))
+			      || sym->st_size != 0
+			      || (strcmp (name, "__preinit_array_start") != 0
+				  && strcmp (name, "__preinit_array_end") != 0
+				  && strcmp (name, "__init_array_start") != 0
+				  && strcmp (name, "__init_array_end") != 0
+				  && strcmp (name, "__fini_array_start") != 0
+				  && strcmp (name, "__fini_array_end") != 0
+				  && strcmp (name, "__bss_start") != 0
+				  && strcmp (name, "__bss_start__") != 0
+				  && strcmp (name, "__TMC_END__") != 0
+				  && strcmp (name, ".TOC.") != 0
+				  && strcmp (name, "_edata") != 0
+				  && strcmp (name, "__edata") != 0
+				  && strcmp (name, "_end") != 0
+				  && strcmp (name, "__end") != 0))
+			    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): st_value out of bounds\n"),
+				   idx, section_name (ebl, idx), cnt, name);
+			}
+		      else if ((st_value - sh_addr
+				+ sym->st_size) > destshdr->sh_size)
+			ERROR (_("\
+section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced section [%2d] '%s'\n"),
+			       idx, section_name (ebl, idx), cnt, name,
+			       (int) xndx, section_name (ebl, xndx));
+		    }
+		}
+	      else
+		{
+		  if ((destshdr->sh_flags & SHF_TLS) == 0)
+		    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): referenced section [%2d] '%s' does not have SHF_TLS flag set\n"),
+			   idx, section_name (ebl, idx), cnt, name,
+			   (int) xndx, section_name (ebl, xndx));
+
+		  if (ehdr->e_type == ET_REL)
+		    {
+		      /* For object files the symbol value must fall
+			 into the section.  */
+		      if (st_value > destshdr->sh_size)
+			ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced section [%2d] '%s'\n"),
+			       idx, section_name (ebl, idx), cnt, name,
+			       (int) xndx, section_name (ebl, xndx));
+		      else if (st_value + sym->st_size
+			       > destshdr->sh_size)
+			ERROR (_("\
+section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced section [%2d] '%s'\n"),
+			       idx, section_name (ebl, idx), cnt, name,
+			       (int) xndx, section_name (ebl, xndx));
+		    }
+		  else
+		    {
+		      GElf_Phdr phdr_mem;
+		      GElf_Phdr *phdr = NULL;
+		      unsigned int pcnt;
+
+		      for (pcnt = 0; pcnt < phnum; ++pcnt)
+			{
+			  phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
+			  if (phdr != NULL && phdr->p_type == PT_TLS)
+			    break;
+			}
+
+		      if (pcnt == phnum)
+			{
+			  if (no_pt_tls++ == 0)
+			    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): TLS symbol but no TLS program header entry\n"),
+				   idx, section_name (ebl, idx), cnt, name);
+			}
+		      else if (phdr == NULL)
+			{
+			    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): TLS symbol but couldn't get TLS program header entry\n"),
+				   idx, section_name (ebl, idx), cnt, name);
+			}
+		      else if (!is_debuginfo)
+			{
+			  if (st_value
+			      < destshdr->sh_offset - phdr->p_offset)
+			    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): st_value short of referenced section [%2d] '%s'\n"),
+				   idx, section_name (ebl, idx), cnt, name,
+				   (int) xndx, section_name (ebl, xndx));
+			  else if (st_value
+				   > (destshdr->sh_offset - phdr->p_offset
+				      + destshdr->sh_size))
+			    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): st_value out of bounds of referenced section [%2d] '%s'\n"),
+				   idx, section_name (ebl, idx), cnt, name,
+				   (int) xndx, section_name (ebl, xndx));
+			  else if (st_value + sym->st_size
+				   > (destshdr->sh_offset - phdr->p_offset
+				      + destshdr->sh_size))
+			    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s) does not fit completely in referenced section [%2d] '%s'\n"),
+				   idx, section_name (ebl, idx), cnt, name,
+				   (int) xndx, section_name (ebl, xndx));
+			}
+		    }
+		}
+	    }
+	}
+
+      if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
+	{
+	  if (cnt >= shdr->sh_info)
+	    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): local symbol outside range described in sh_info\n"),
+		   idx, section_name (ebl, idx), cnt, name);
+	}
+      else
+	{
+	  if (cnt < shdr->sh_info)
+	    ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): non-local symbol outside range described in sh_info\n"),
+		   idx, section_name (ebl, idx), cnt, name);
+	}
+
+      if (GELF_ST_TYPE (sym->st_info) == STT_SECTION
+	  && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
+	ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): non-local section symbol\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+
+      if (name != NULL)
+	{
+	  if (strcmp (name, "_GLOBAL_OFFSET_TABLE_") == 0)
+	    {
+	      /* Check that address and size match the global offset table.  */
+
+	      GElf_Shdr destshdr_mem;
+	      GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, xndx),
+						  &destshdr_mem);
+
+	      if (destshdr == NULL && xndx == SHN_ABS)
+		{
+		  /* In a DSO, we have to find the GOT section by name.  */
+		  Elf_Scn *gotscn = NULL;
+		  Elf_Scn *gscn = NULL;
+		  while ((gscn = elf_nextscn (ebl->elf, gscn)) != NULL)
+		    {
+		      destshdr = gelf_getshdr (gscn, &destshdr_mem);
+		      assert (destshdr != NULL);
+		      const char *sname = elf_strptr (ebl->elf,
+						      shstrndx,
+						      destshdr->sh_name);
+		      if (sname != NULL)
+			{
+			  if (strcmp (sname, ".got.plt") == 0)
+			    break;
+			  if (strcmp (sname, ".got") == 0)
+			    /* Do not stop looking.
+			       There might be a .got.plt section.  */
+			    gotscn = gscn;
+			}
+
+		      destshdr = NULL;
+		    }
+
+		  if (destshdr == NULL && gotscn != NULL)
+		    destshdr = gelf_getshdr (gotscn, &destshdr_mem);
+		}
+
+	      const char *sname = ((destshdr == NULL || xndx == SHN_UNDEF)
+				   ? NULL
+				   : elf_strptr (ebl->elf, shstrndx,
+						 destshdr->sh_name));
+	      if (sname == NULL)
+		{
+		  if (xndx != SHN_UNDEF || ehdr->e_type != ET_REL)
+		    ERROR (_("\
+section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
+bad section [%2d]\n"),
+			   idx, section_name (ebl, idx), xndx);
+		}
+	      else if (strcmp (sname, ".got.plt") != 0
+		       && strcmp (sname, ".got") != 0)
+		ERROR (_("\
+section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol refers to \
+section [%2d] '%s'\n"),
+		       idx, section_name (ebl, idx), xndx, sname);
+
+	      if (destshdr != NULL)
+		{
+		  /* Found it.  */
+		  if (!ebl_check_special_symbol (ebl, sym, name,
+						 destshdr))
+		    {
+		      if (ehdr->e_type != ET_REL
+			  && sym->st_value != destshdr->sh_addr)
+			/* This test is more strict than the psABIs which
+			   usually allow the symbol to be in the middle of
+			   the .got section, allowing negative offsets.  */
+			ERROR (_("\
+section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol value %#" PRIx64 " does not match %s section address %#" PRIx64 "\n"),
+			       idx, section_name (ebl, idx),
+			       (uint64_t) sym->st_value,
+			       sname, (uint64_t) destshdr->sh_addr);
+
+		      if (!gnuld && sym->st_size != destshdr->sh_size)
+			ERROR (_("\
+section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol size %" PRIu64 " does not match %s section size %" PRIu64 "\n"),
+			       idx, section_name (ebl, idx),
+			       (uint64_t) sym->st_size,
+			       sname, (uint64_t) destshdr->sh_size);
+		    }
+		}
+	      else
+		ERROR (_("\
+section [%2d] '%s': _GLOBAL_OFFSET_TABLE_ symbol present, but no .got section\n"),
+		       idx, section_name (ebl, idx));
+	    }
+	  else if (strcmp (name, "_DYNAMIC") == 0)
+	    /* Check that address and size match the dynamic section.
+	       We locate the dynamic section via the program header
+	       entry.  */
+	    for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
+	      {
+		GElf_Phdr phdr_mem;
+		GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
+
+		if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
+		  {
+		    if (sym->st_value != phdr->p_vaddr)
+		      ERROR (_("\
+section [%2d] '%s': _DYNAMIC_ symbol value %#" PRIx64 " does not match dynamic segment address %#" PRIx64 "\n"),
+			     idx, section_name (ebl, idx),
+			     (uint64_t) sym->st_value,
+			     (uint64_t) phdr->p_vaddr);
+
+		    if (!gnuld && sym->st_size != phdr->p_memsz)
+		      ERROR (_("\
+section [%2d] '%s': _DYNAMIC symbol size %" PRIu64 " does not match dynamic segment size %" PRIu64 "\n"),
+			     idx, section_name (ebl, idx),
+			     (uint64_t) sym->st_size,
+			     (uint64_t) phdr->p_memsz);
+
+		    break;
+		  }
+	    }
+	}
+
+      if (GELF_ST_VISIBILITY (sym->st_other) != STV_DEFAULT
+	  && shdr->sh_type == SHT_DYNSYM)
+	ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): symbol in dynamic symbol table with non-default visibility\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+      if (! ebl_check_st_other_bits (ebl, sym->st_other))
+	ERROR (_("\
+section [%2d] '%s': symbol %zu (%s): unknown bit set in st_other\n"),
+	       idx, section_name (ebl, idx), cnt, name);
+
+    }
+}
+
+
+static bool
+is_rel_dyn (Ebl *ebl, const GElf_Ehdr *ehdr, int idx, const GElf_Shdr *shdr,
+	    bool is_rela)
+{
+  /* If this is no executable or DSO it cannot be a .rel.dyn section.  */
+  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+    return false;
+
+  /* Check the section name.  Unfortunately necessary.  */
+  if (strcmp (section_name (ebl, idx), is_rela ? ".rela.dyn" : ".rel.dyn"))
+    return false;
+
+  /* When a .rel.dyn section is used a DT_RELCOUNT dynamic section
+     entry can be present as well.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr rcshdr_mem;
+      const GElf_Shdr *rcshdr = gelf_getshdr (scn, &rcshdr_mem);
+
+      if (rcshdr == NULL)
+	break;
+
+      if (rcshdr->sh_type == SHT_DYNAMIC && rcshdr->sh_entsize != 0)
+	{
+	  /* Found the dynamic section.  Look through it.  */
+	  Elf_Data *d = elf_getdata (scn, NULL);
+	  size_t cnt;
+
+	  if (d == NULL)
+	    ERROR (_("\
+section [%2d] '%s': cannot get section data.\n"),
+		   idx, section_name (ebl, idx));
+
+	  for (cnt = 1; cnt < rcshdr->sh_size / rcshdr->sh_entsize; ++cnt)
+	    {
+	      GElf_Dyn dyn_mem;
+	      GElf_Dyn *dyn = gelf_getdyn (d, cnt, &dyn_mem);
+
+	      if (dyn == NULL)
+		break;
+
+	      if (dyn->d_tag == DT_RELCOUNT)
+		{
+		  /* Found it.  Does the type match.  */
+		  if (is_rela)
+		    ERROR (_("\
+section [%2d] '%s': DT_RELCOUNT used for this RELA section\n"),
+			   idx, section_name (ebl, idx));
+		  else
+		    {
+		      /* Does the number specified number of relative
+			 relocations exceed the total number of
+			 relocations?  */
+		      if (shdr->sh_entsize != 0
+			  && dyn->d_un.d_val > (shdr->sh_size
+						/ shdr->sh_entsize))
+			ERROR (_("\
+section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
+			       idx, section_name (ebl, idx),
+			       (int) dyn->d_un.d_val);
+
+		      /* Make sure the specified number of relocations are
+			 relative.  */
+		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
+								   idx), NULL);
+		      if (reldata != NULL && shdr->sh_entsize != 0)
+			for (size_t inner = 0;
+			     inner < shdr->sh_size / shdr->sh_entsize;
+			     ++inner)
+			  {
+			    GElf_Rel rel_mem;
+			    GElf_Rel *rel = gelf_getrel (reldata, inner,
+							 &rel_mem);
+			    if (rel == NULL)
+			      /* The problem will be reported elsewhere.  */
+			      break;
+
+			    if (ebl_relative_reloc_p (ebl,
+						      GELF_R_TYPE (rel->r_info)))
+			      {
+				if (inner >= dyn->d_un.d_val)
+				  ERROR (_("\
+section [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
+					 idx, section_name (ebl, idx),
+					 (int) dyn->d_un.d_val);
+			      }
+			    else if (inner < dyn->d_un.d_val)
+			      ERROR (_("\
+section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
+				     idx, section_name (ebl, idx),
+				     inner, (int) dyn->d_un.d_val);
+			  }
+		    }
+		}
+
+	      if (dyn->d_tag == DT_RELACOUNT)
+		{
+		  /* Found it.  Does the type match.  */
+		  if (!is_rela)
+		    ERROR (_("\
+section [%2d] '%s': DT_RELACOUNT used for this REL section\n"),
+			   idx, section_name (ebl, idx));
+		  else
+		    {
+		      /* Does the number specified number of relative
+			 relocations exceed the total number of
+			 relocations?  */
+		      if (shdr->sh_entsize != 0
+			  && dyn->d_un.d_val > shdr->sh_size / shdr->sh_entsize)
+			ERROR (_("\
+section [%2d] '%s': DT_RELCOUNT value %d too high for this section\n"),
+			       idx, section_name (ebl, idx),
+			       (int) dyn->d_un.d_val);
+
+		      /* Make sure the specified number of relocations are
+			 relative.  */
+		      Elf_Data *reldata = elf_getdata (elf_getscn (ebl->elf,
+								   idx), NULL);
+		      if (reldata != NULL && shdr->sh_entsize != 0)
+			for (size_t inner = 0;
+			     inner < shdr->sh_size / shdr->sh_entsize;
+			     ++inner)
+			  {
+			    GElf_Rela rela_mem;
+			    GElf_Rela *rela = gelf_getrela (reldata, inner,
+							    &rela_mem);
+			    if (rela == NULL)
+			      /* The problem will be reported elsewhere.  */
+			      break;
+
+			    if (ebl_relative_reloc_p (ebl,
+						      GELF_R_TYPE (rela->r_info)))
+			      {
+				if (inner >= dyn->d_un.d_val)
+				  ERROR (_("\
+section [%2d] '%s': relative relocations after index %d as specified by DT_RELCOUNT\n"),
+					 idx, section_name (ebl, idx),
+					 (int) dyn->d_un.d_val);
+			      }
+			    else if (inner < dyn->d_un.d_val)
+			      ERROR (_("\
+section [%2d] '%s': non-relative relocation at index %zu; DT_RELCOUNT specified %d relative relocations\n"),
+				     idx, section_name (ebl, idx),
+				     inner, (int) dyn->d_un.d_val);
+			  }
+		    }
+		}
+	    }
+
+	  break;
+	}
+    }
+
+  return true;
+}
+
+
+struct loaded_segment
+{
+  GElf_Addr from;
+  GElf_Addr to;
+  bool read_only;
+  struct loaded_segment *next;
+};
+
+
+/* Check whether binary has text relocation flag set.  */
+static bool textrel;
+
+/* Keep track of whether text relocation flag is needed.  */
+static bool needed_textrel;
+
+
+static bool
+check_reloc_shdr (Ebl *ebl, const GElf_Ehdr *ehdr, const GElf_Shdr *shdr,
+		  int idx, int reltype, GElf_Shdr **destshdrp,
+		  GElf_Shdr *destshdr_memp, struct loaded_segment **loadedp)
+{
+  bool reldyn = false;
+
+  /* Check whether the link to the section we relocate is reasonable.  */
+  if (shdr->sh_info >= shnum)
+    ERROR (_("section [%2d] '%s': invalid destination section index\n"),
+	   idx, section_name (ebl, idx));
+  else if (shdr->sh_info != 0)
+    {
+      *destshdrp = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
+				 destshdr_memp);
+      if (*destshdrp != NULL)
+	{
+	  if(! ebl_check_reloc_target_type (ebl, (*destshdrp)->sh_type))
+	    {
+	      reldyn = is_rel_dyn (ebl, ehdr, idx, shdr, true);
+	      if (!reldyn)
+		ERROR (_("\
+section [%2d] '%s': invalid destination section type\n"),
+		       idx, section_name (ebl, idx));
+	      else
+		{
+		  /* There is no standard, but we require that .rel{,a}.dyn
+		     sections have a sh_info value of zero.  */
+		  if (shdr->sh_info != 0)
+		    ERROR (_("\
+section [%2d] '%s': sh_info should be zero\n"),
+			   idx, section_name (ebl, idx));
+		}
+	    }
+
+	  if ((((*destshdrp)->sh_flags & SHF_MERGE) != 0)
+	      && ((*destshdrp)->sh_flags & SHF_STRINGS) != 0)
+	    ERROR (_("\
+section [%2d] '%s': no relocations for merge-able string sections possible\n"),
+		   idx, section_name (ebl, idx));
+	}
+    }
+
+  size_t sh_entsize = gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT);
+  if (shdr->sh_entsize != sh_entsize)
+    {
+      if (reltype == ELF_T_RELA)
+	ERROR ("\
+section [%2d] '%s': section entry size does not match ElfXX_Rela\n",
+	       idx, section_name (ebl, idx));
+      else if (reltype == ELF_T_REL)
+	ERROR ("\
+section [%2d] '%s': section entry size does not match ElfXX_Rel\n",
+	       idx, section_name (ebl, idx));
+      else
+	ERROR ("\
+section [%2d] '%s': section entry size does not match ElfXX_Relr\n",
+	       idx, section_name (ebl, idx));
+    }
+
+  /* In preparation of checking whether relocations are text
+     relocations or not we need to determine whether the file is
+     flagged to have text relocation and we need to determine a) what
+     the loaded segments are and b) which are read-only.  This will
+     also allow us to determine whether the same reloc section is
+     modifying loaded and not loaded segments.  */
+  for (unsigned int i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
+      if (phdr == NULL)
+	continue;
+
+      if (phdr->p_type == PT_LOAD)
+	{
+	  struct loaded_segment *newp = xmalloc (sizeof (*newp));
+	  newp->from = phdr->p_vaddr;
+	  newp->to = phdr->p_vaddr + phdr->p_memsz;
+	  newp->read_only = (phdr->p_flags & PF_W) == 0;
+	  newp->next = *loadedp;
+	  *loadedp = newp;
+	}
+      else if (phdr->p_type == PT_DYNAMIC)
+	{
+	  Elf_Scn *dynscn = gelf_offscn (ebl->elf, phdr->p_offset);
+	  GElf_Shdr dynshdr_mem;
+	  GElf_Shdr *dynshdr = gelf_getshdr (dynscn, &dynshdr_mem);
+	  Elf_Data *dyndata = elf_getdata (dynscn, NULL);
+	  if (dynshdr != NULL && dynshdr->sh_type == SHT_DYNAMIC
+	      && dyndata != NULL && dynshdr->sh_entsize != 0)
+	    for (size_t j = 0; j < dynshdr->sh_size / dynshdr->sh_entsize; ++j)
+	      {
+		GElf_Dyn dyn_mem;
+		GElf_Dyn *dyn = gelf_getdyn (dyndata, j, &dyn_mem);
+		if (dyn != NULL
+		    && (dyn->d_tag == DT_TEXTREL
+			|| (dyn->d_tag == DT_FLAGS
+			    && (dyn->d_un.d_val & DF_TEXTREL) != 0)))
+		  {
+		    textrel = true;
+		    break;
+		  }
+	      }
+	}
+    }
+
+  /* A quick test which can be easily done here (although it is a bit
+     out of place): the text relocation flag makes only sense if there
+     is a segment which is not writable.  */
+  if (textrel)
+    {
+      struct loaded_segment *seg = *loadedp;
+      while (seg != NULL && !seg->read_only)
+	seg = seg->next;
+      if (seg == NULL)
+	ERROR (_("\
+text relocation flag set but there is no read-only segment\n"));
+    }
+
+  return reldyn;
+}
+
+
+enum load_state
+  {
+    state_undecided,
+    state_loaded,
+    state_unloaded,
+    state_error
+  };
+
+
+static void
+check_one_reloc (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *relshdr, int idx,
+		 size_t cnt, const GElf_Shdr *symshdr, Elf_Data *symdata,
+		 GElf_Addr r_offset, GElf_Xword r_info,
+		 const GElf_Shdr *destshdr, bool reldyn,
+		 struct loaded_segment *loaded, enum load_state *statep)
+{
+  bool known_broken = gnuld;
+
+  if (!ebl_reloc_type_check (ebl, GELF_R_TYPE (r_info)))
+    ERROR (_("section [%2d] '%s': relocation %zu: invalid type\n"),
+	   idx, section_name (ebl, idx), cnt);
+  else if (((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+	    /* The executable/DSO can contain relocation sections with
+	       all the relocations the linker has applied.  Those sections
+	       are marked non-loaded, though.  */
+	    || (relshdr->sh_flags & SHF_ALLOC) != 0)
+	   && !ebl_reloc_valid_use (ebl, GELF_R_TYPE (r_info)))
+    ERROR (_("\
+section [%2d] '%s': relocation %zu: relocation type invalid for the file type\n"),
+	   idx, section_name (ebl, idx), cnt);
+
+  if (symshdr != NULL
+      && ((GELF_R_SYM (r_info) + 1)
+	  * gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT)
+	  > symshdr->sh_size))
+    ERROR (_("\
+section [%2d] '%s': relocation %zu: invalid symbol index\n"),
+	   idx, section_name (ebl, idx), cnt);
+
+  /* No more tests if this is a no-op relocation.  */
+  if (ebl_none_reloc_p (ebl, GELF_R_TYPE (r_info)))
+    return;
+
+  if (ebl_gotpc_reloc_check (ebl, GELF_R_TYPE (r_info)))
+    {
+      const char *name;
+      char buf[64];
+      GElf_Sym sym_mem;
+      GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
+      if (sym != NULL
+	  /* Get the name for the symbol.  */
+	  && (name = elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
+	  && strcmp (name, "_GLOBAL_OFFSET_TABLE_") !=0 )
+	ERROR (_("\
+section [%2d] '%s': relocation %zu: only symbol '_GLOBAL_OFFSET_TABLE_' can be used with %s\n"),
+	       idx, section_name (ebl, idx), cnt,
+	       ebl_reloc_type_name (ebl, GELF_R_SYM (r_info),
+				    buf, sizeof (buf)));
+    }
+
+  if (reldyn)
+    {
+      // XXX TODO Check .rel.dyn section addresses.
+    }
+  else if (!known_broken)
+    {
+      if (destshdr != NULL
+	  && GELF_R_TYPE (r_info) != 0
+	  && (r_offset - (ehdr->e_type == ET_REL ? 0
+			  : destshdr->sh_addr)) >= destshdr->sh_size)
+	ERROR (_("\
+section [%2d] '%s': relocation %zu: offset out of bounds\n"),
+	       idx, section_name (ebl, idx), cnt);
+    }
+
+  GElf_Sym sym_mem;
+  GElf_Sym *sym = gelf_getsym (symdata, GELF_R_SYM (r_info), &sym_mem);
+
+  if (ebl_copy_reloc_p (ebl, GELF_R_TYPE (r_info))
+      /* Make sure the referenced symbol is an object or unspecified.  */
+      && sym != NULL
+      && GELF_ST_TYPE (sym->st_info) != STT_NOTYPE
+      && GELF_ST_TYPE (sym->st_info) != STT_OBJECT)
+    {
+      char buf[64];
+      ERROR (_("section [%2d] '%s': relocation %zu: copy relocation against symbol of type %s\n"),
+	     idx, section_name (ebl, idx), cnt,
+	     ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info),
+				   buf, sizeof (buf)));
+    }
+
+  if ((ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+      || (relshdr->sh_flags & SHF_ALLOC) != 0)
+    {
+      bool in_loaded_seg = false;
+      while (loaded != NULL)
+	{
+	  if (r_offset < loaded->to
+	      && r_offset + (sym == NULL ? 0 : sym->st_size) >= loaded->from)
+	    {
+	      /* The symbol is in this segment.  */
+	      if  (loaded->read_only)
+		{
+		  if (textrel)
+		    needed_textrel = true;
+		  else
+		    ERROR (_("section [%2d] '%s': relocation %zu: read-only section modified but text relocation flag not set\n"),
+			   idx, section_name (ebl, idx), cnt);
+		}
+
+	      in_loaded_seg = true;
+	    }
+
+	  loaded = loaded->next;
+	}
+
+      if (*statep == state_undecided)
+	*statep = in_loaded_seg ? state_loaded : state_unloaded;
+      else if ((*statep == state_unloaded && in_loaded_seg)
+	       || (*statep == state_loaded && !in_loaded_seg))
+	{
+	  ERROR (_("\
+section [%2d] '%s': relocations are against loaded and unloaded data\n"),
+		 idx, section_name (ebl, idx));
+	  *statep = state_error;
+	}
+    }
+}
+
+
+static void
+check_rela (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  /* Check the fields of the section header.  */
+  GElf_Shdr destshdr_mem;
+  GElf_Shdr *destshdr = NULL;
+  struct loaded_segment *loaded = NULL;
+  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELA, &destshdr,
+				  &destshdr_mem, &loaded);
+
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  enum load_state state = state_undecided;
+
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
+  for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
+    {
+      GElf_Rela rela_mem;
+      GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
+      if (rela == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': cannot get relocation %zu: %s\n"),
+		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
+	  continue;
+	}
+
+      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
+		       rela->r_offset, rela->r_info, destshdr, reldyn, loaded,
+		       &state);
+    }
+
+  while (loaded != NULL)
+    {
+      struct loaded_segment *old = loaded;
+      loaded = loaded->next;
+      free (old);
+    }
+}
+
+
+static void
+check_rel (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  /* Check the fields of the section header.  */
+  GElf_Shdr destshdr_mem;
+  GElf_Shdr *destshdr = NULL;
+  struct loaded_segment *loaded = NULL;
+  bool reldyn = check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_REL, &destshdr,
+				  &destshdr_mem, &loaded);
+
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  enum load_state state = state_undecided;
+
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
+  for (size_t cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
+    {
+      GElf_Rel rel_mem;
+      GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
+      if (rel == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': cannot get relocation %zu: %s\n"),
+		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
+	  continue;
+	}
+
+      check_one_reloc (ebl, ehdr, shdr, idx, cnt, symshdr, symdata,
+		       rel->r_offset, rel->r_info, destshdr, reldyn, loaded,
+		       &state);
+    }
+
+  while (loaded != NULL)
+    {
+      struct loaded_segment *old = loaded;
+      loaded = loaded->next;
+      free (old);
+    }
+}
+
+static void
+check_relr (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  /* Check the fields of the section header.  */
+  GElf_Shdr destshdr_mem;
+  GElf_Shdr *destshdr = NULL;
+  struct loaded_segment *loaded = NULL;
+  check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELR, &destshdr,
+		    &destshdr_mem, &loaded);
+
+  /* Just throw them away.  */
+  while (loaded != NULL)
+    {
+      struct loaded_segment *old = loaded;
+      loaded = loaded->next;
+      free (old);
+    }
+}
+
+/* Number of dynamic sections.  */
+static int ndynamic;
+
+
+static void
+check_dynamic (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  Elf_Data *data;
+  GElf_Shdr strshdr_mem;
+  GElf_Shdr *strshdr;
+  size_t cnt;
+  static const bool dependencies[DT_NUM][DT_NUM] =
+    {
+      [DT_NEEDED] = { [DT_STRTAB] = true },
+      [DT_PLTRELSZ] = { [DT_JMPREL] = true },
+      [DT_HASH] = { [DT_SYMTAB] = true },
+      [DT_STRTAB] = { [DT_STRSZ] = true },
+      [DT_SYMTAB] = { [DT_STRTAB] = true, [DT_SYMENT] = true },
+      [DT_RELA] = { [DT_RELASZ] = true, [DT_RELAENT] = true },
+      [DT_RELASZ] = { [DT_RELA] = true },
+      [DT_RELAENT] = { [DT_RELA] = true },
+      [DT_STRSZ] = { [DT_STRTAB] = true },
+      [DT_SYMENT] = { [DT_SYMTAB] = true },
+      [DT_SONAME] = { [DT_STRTAB] = true },
+      [DT_RPATH] = { [DT_STRTAB] = true },
+      [DT_REL] = { [DT_RELSZ] = true, [DT_RELENT] = true },
+      [DT_RELSZ] = { [DT_REL] = true },
+      [DT_RELENT] = { [DT_REL] = true },
+      [DT_JMPREL] = { [DT_PLTRELSZ] = true, [DT_PLTREL] = true },
+      [DT_RUNPATH] = { [DT_STRTAB] = true },
+      [DT_PLTREL] = { [DT_JMPREL] = true },
+    };
+  bool has_dt[DT_NUM];
+  bool has_val_dt[DT_VALNUM];
+  bool has_addr_dt[DT_ADDRNUM];
+  static const bool level2[DT_NUM] =
+    {
+      [DT_RPATH] = true,
+      [DT_SYMBOLIC] = true,
+      [DT_TEXTREL] = true,
+      [DT_BIND_NOW] = true
+    };
+  static const bool mandatory[DT_NUM] =
+    {
+      [DT_NULL] = true,
+      [DT_STRTAB] = true,
+      [DT_SYMTAB] = true,
+      [DT_STRSZ] = true,
+      [DT_SYMENT] = true
+    };
+
+  memset (has_dt, '\0', sizeof (has_dt));
+  memset (has_val_dt, '\0', sizeof (has_val_dt));
+  memset (has_addr_dt, '\0', sizeof (has_addr_dt));
+
+  if (++ndynamic == 2)
+    ERROR (_("more than one dynamic section present\n"));
+
+  data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &strshdr_mem);
+  if (strshdr != NULL && strshdr->sh_type != SHT_STRTAB)
+    ERROR (_("\
+section [%2d] '%s': referenced as string table for section [%2d] '%s' but type is not SHT_STRTAB\n"),
+	   shdr->sh_link, section_name (ebl, shdr->sh_link),
+	   idx, section_name (ebl, idx));
+  else if (strshdr == NULL)
+    {
+      ERROR (_("\
+section [%2d]: referenced as string table for section [%2d] '%s' but section link value is invalid\n"),
+	   shdr->sh_link, idx, section_name (ebl, idx));
+      return;
+    }
+
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_DYN, 1, EV_CURRENT);
+  if (shdr->sh_entsize != sh_entsize)
+    ERROR (_("\
+section [%2d] '%s': section entry size does not match ElfXX_Dyn\n"),
+	   idx, section_name (ebl, idx));
+
+  if (shdr->sh_info != 0)
+    ERROR (_("section [%2d] '%s': sh_info not zero\n"),
+	   idx, section_name (ebl, idx));
+
+  bool non_null_warned = false;
+  for (cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
+    {
+      GElf_Dyn dyn_mem;
+      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dyn_mem);
+      if (dyn == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': cannot get dynamic section entry %zu: %s\n"),
+		 idx, section_name (ebl, idx), cnt, elf_errmsg (-1));
+	  continue;
+	}
+
+      if (has_dt[DT_NULL] && dyn->d_tag != DT_NULL && ! non_null_warned)
+	{
+	  ERROR (_("\
+section [%2d] '%s': non-DT_NULL entries follow DT_NULL entry\n"),
+		 idx, section_name (ebl, idx));
+	  non_null_warned = true;
+	}
+
+      if (!ebl_dynamic_tag_check (ebl, dyn->d_tag))
+	ERROR (_("section [%2d] '%s': entry %zu: unknown tag\n"),
+	       idx, section_name (ebl, idx), cnt);
+
+      if (dyn->d_tag >= 0 && dyn->d_tag < DT_NUM)
+	{
+	  if (has_dt[dyn->d_tag]
+	      && dyn->d_tag != DT_NEEDED
+	      && dyn->d_tag != DT_NULL
+	      && dyn->d_tag != DT_POSFLAG_1)
+	    {
+	      char buf[50];
+	      ERROR (_("\
+section [%2d] '%s': entry %zu: more than one entry with tag %s\n"),
+		     idx, section_name (ebl, idx), cnt,
+		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
+					   buf, sizeof (buf)));
+	    }
+
+	  if (be_strict && level2[dyn->d_tag])
+	    {
+	      char buf[50];
+	      ERROR (_("\
+section [%2d] '%s': entry %zu: level 2 tag %s used\n"),
+		     idx, section_name (ebl, idx), cnt,
+		     ebl_dynamic_tag_name (ebl, dyn->d_tag,
+					   buf, sizeof (buf)));
+	    }
+
+	  has_dt[dyn->d_tag] = true;
+	}
+      else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_VALRNGHI
+	       && DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
+	has_val_dt[DT_VALTAGIDX (dyn->d_tag)] = true;
+      else if (dyn->d_tag >= 0 && dyn->d_tag <= DT_ADDRRNGHI
+	       && DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
+	has_addr_dt[DT_ADDRTAGIDX (dyn->d_tag)] = true;
+
+      if (dyn->d_tag == DT_PLTREL && dyn->d_un.d_val != DT_REL
+	  && dyn->d_un.d_val != DT_RELA)
+	ERROR (_("\
+section [%2d] '%s': entry %zu: DT_PLTREL value must be DT_REL or DT_RELA\n"),
+	       idx, section_name (ebl, idx), cnt);
+
+      /* Check that addresses for entries are in loaded segments.  */
+      switch (dyn->d_tag)
+	{
+	  size_t n;
+	case DT_STRTAB:
+	  /* We require the referenced section is the same as the one
+	     specified in sh_link.  */
+	  if (strshdr->sh_addr != dyn->d_un.d_val)
+	    {
+	      ERROR (_("\
+section [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '%s' referenced by sh_link\n"),
+		     idx, section_name (ebl, idx), cnt,
+		     shdr->sh_link, section_name (ebl, shdr->sh_link));
+	      break;
+	    }
+	  goto check_addr;
+
+	default:
+	  if (dyn->d_tag < DT_ADDRRNGLO || dyn->d_tag > DT_ADDRRNGHI)
+	    /* Value is no pointer.  */
+	    break;
+	  FALLTHROUGH;
+
+	case DT_AUXILIARY:
+	case DT_FILTER:
+	case DT_FINI:
+	case DT_FINI_ARRAY:
+	case DT_HASH:
+	case DT_INIT:
+	case DT_INIT_ARRAY:
+	case DT_JMPREL:
+	case DT_PLTGOT:
+	case DT_REL:
+	case DT_RELA:
+	case DT_RELR:
+	case DT_SYMBOLIC:
+	case DT_SYMTAB:
+	case DT_VERDEF:
+	case DT_VERNEED:
+	case DT_VERSYM:
+	check_addr:
+	  for (n = 0; n < phnum; ++n)
+	    {
+	      GElf_Phdr phdr_mem;
+	      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, n, &phdr_mem);
+	      if (phdr != NULL && phdr->p_type == PT_LOAD
+		  && phdr->p_vaddr <= dyn->d_un.d_ptr
+		  && phdr->p_vaddr + phdr->p_memsz > dyn->d_un.d_ptr)
+		break;
+	    }
+	  if (unlikely (n >= phnum))
+	    {
+	      char buf[50];
+	      ERROR (_("\
+section [%2d] '%s': entry %zu: %s value must point into loaded segment\n"),
+		     idx, section_name (ebl, idx), cnt,
+		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
+					   sizeof (buf)));
+	    }
+	  break;
+
+	case DT_NEEDED:
+	case DT_RPATH:
+	case DT_RUNPATH:
+	case DT_SONAME:
+	  if (dyn->d_un.d_ptr >= strshdr->sh_size)
+	    {
+	      char buf[50];
+	      ERROR (_("\
+section [%2d] '%s': entry %zu: %s value must be valid offset in section [%2d] '%s'\n"),
+		     idx, section_name (ebl, idx), cnt,
+		     ebl_dynamic_tag_name (ebl, dyn->d_tag, buf,
+					   sizeof (buf)),
+		     shdr->sh_link, section_name (ebl, shdr->sh_link));
+	    }
+	  break;
+	}
+    }
+
+  for (cnt = 1; cnt < DT_NUM; ++cnt)
+    if (has_dt[cnt])
+      {
+	for (int inner = 0; inner < DT_NUM; ++inner)
+	  if (dependencies[cnt][inner] && ! has_dt[inner])
+	    {
+	      char buf1[50];
+	      char buf2[50];
+
+	      ERROR (_("\
+section [%2d] '%s': contains %s entry but not %s\n"),
+		     idx, section_name (ebl, idx),
+		     ebl_dynamic_tag_name (ebl, cnt, buf1, sizeof (buf1)),
+		     ebl_dynamic_tag_name (ebl, inner, buf2, sizeof (buf2)));
+	    }
+      }
+    else
+      {
+	if (mandatory[cnt])
+	  {
+	    char buf[50];
+	    ERROR (_("\
+section [%2d] '%s': mandatory tag %s not present\n"),
+		   idx, section_name (ebl, idx),
+		   ebl_dynamic_tag_name (ebl, cnt, buf, sizeof (buf)));
+	  }
+      }
+
+  /* Make sure we have an hash table.  */
+  if (!has_dt[DT_HASH] && !has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)])
+    ERROR (_("\
+section [%2d] '%s': no hash section present\n"),
+	   idx, section_name (ebl, idx));
+
+  /* The GNU-style hash table also needs a symbol table.  */
+  if (!has_dt[DT_HASH] && has_addr_dt[DT_ADDRTAGIDX (DT_GNU_HASH)]
+      && !has_dt[DT_SYMTAB])
+    ERROR (_("\
+section [%2d] '%s': contains %s entry but not %s\n"),
+	   idx, section_name (ebl, idx),
+	   "DT_GNU_HASH", "DT_SYMTAB");
+
+  /* Check the rel/rela tags.  At least one group must be available.  */
+  if ((has_dt[DT_RELA] || has_dt[DT_RELASZ] || has_dt[DT_RELAENT])
+      && (!has_dt[DT_RELA] || !has_dt[DT_RELASZ] || !has_dt[DT_RELAENT]))
+    ERROR (_("\
+section [%2d] '%s': not all of %s, %s, and %s are present\n"),
+	   idx, section_name (ebl, idx),
+	   "DT_RELA", "DT_RELASZ", "DT_RELAENT");
+
+  if ((has_dt[DT_REL] || has_dt[DT_RELSZ] || has_dt[DT_RELENT])
+      && (!has_dt[DT_REL] || !has_dt[DT_RELSZ] || !has_dt[DT_RELENT]))
+    ERROR (_("\
+section [%2d] '%s': not all of %s, %s, and %s are present\n"),
+	   idx, section_name (ebl, idx),
+	   "DT_REL", "DT_RELSZ", "DT_RELENT");
+
+  /* Check that all prelink sections are present if any of them is.  */
+  if (has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)]
+      || has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
+    {
+      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_PRELINKED)])
+	ERROR (_("\
+section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
+	       idx, section_name (ebl, idx), "DT_GNU_PRELINKED");
+      if (!has_val_dt[DT_VALTAGIDX (DT_CHECKSUM)])
+	ERROR (_("\
+section [%2d] '%s': %s tag missing in DSO marked during prelinking\n"),
+	       idx, section_name (ebl, idx), "DT_CHECKSUM");
+
+      /* Only DSOs can be marked like this.  */
+      if (ehdr->e_type != ET_DYN)
+	ERROR (_("\
+section [%2d] '%s': non-DSO file marked as dependency during prelink\n"),
+	       idx, section_name (ebl, idx));
+    }
+
+  if (has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)]
+      || has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)]
+      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)]
+      || has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
+    {
+      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_CONFLICTSZ)])
+	ERROR (_("\
+section [%2d] '%s': %s tag missing in prelinked executable\n"),
+	       idx, section_name (ebl, idx), "DT_GNU_CONFLICTSZ");
+      if (!has_val_dt[DT_VALTAGIDX (DT_GNU_LIBLISTSZ)])
+	ERROR (_("\
+section [%2d] '%s': %s tag missing in prelinked executable\n"),
+	       idx, section_name (ebl, idx), "DT_GNU_LIBLISTSZ");
+      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_CONFLICT)])
+	ERROR (_("\
+section [%2d] '%s': %s tag missing in prelinked executable\n"),
+	       idx, section_name (ebl, idx), "DT_GNU_CONFLICT");
+      if (!has_addr_dt[DT_ADDRTAGIDX (DT_GNU_LIBLIST)])
+	ERROR (_("\
+section [%2d] '%s': %s tag missing in prelinked executable\n"),
+	       idx, section_name (ebl, idx), "DT_GNU_LIBLIST");
+    }
+}
+
+
+static void
+check_symtab_shndx (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  if (ehdr->e_type != ET_REL)
+    {
+      ERROR (_("\
+section [%2d] '%s': only relocatable files can have extended section index\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  if (symshdr != NULL && symshdr->sh_type != SHT_SYMTAB)
+    ERROR (_("\
+section [%2d] '%s': extended section index section not for symbol table\n"),
+	   idx, section_name (ebl, idx));
+  else if (symshdr == NULL)
+    ERROR (_("\
+section [%2d] '%s': sh_link extended section index [%2d] is invalid\n"),
+	   idx, section_name (ebl, idx), shdr->sh_link);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  if (symdata == NULL)
+    ERROR (_("cannot get data for symbol section\n"));
+
+  if (shdr->sh_entsize != sizeof (Elf32_Word))
+    ERROR (_("\
+section [%2d] '%s': entry size does not match Elf32_Word\n"),
+	   idx, section_name (ebl, idx));
+
+  if (symshdr != NULL
+      && shdr->sh_entsize != 0
+      && symshdr->sh_entsize != 0
+      && (shdr->sh_size / shdr->sh_entsize
+	  < symshdr->sh_size / symshdr->sh_entsize))
+    ERROR (_("\
+section [%2d] '%s': extended index table too small for symbol table\n"),
+	   idx, section_name (ebl, idx));
+
+  if (shdr->sh_info != 0)
+    ERROR (_("section [%2d] '%s': sh_info not zero\n"),
+	   idx, section_name (ebl, idx));
+
+  for (size_t cnt = idx + 1; cnt < shnum; ++cnt)
+    {
+      GElf_Shdr rshdr_mem;
+      GElf_Shdr *rshdr = gelf_getshdr (elf_getscn (ebl->elf, cnt), &rshdr_mem);
+      if (rshdr != NULL && rshdr->sh_type == SHT_SYMTAB_SHNDX
+	  && rshdr->sh_link == shdr->sh_link)
+	{
+	  ERROR (_("\
+section [%2d] '%s': extended section index in section [%2zu] '%s' refers to same symbol table\n"),
+		 idx, section_name (ebl, idx),
+		 cnt, section_name (ebl, cnt));
+	  break;
+	}
+    }
+
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL || data->d_buf == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  if (data->d_size < sizeof (Elf32_Word)
+      || *((Elf32_Word *) data->d_buf) != 0)
+    ERROR (_("symbol 0 should have zero extended section index\n"));
+
+  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
+    {
+      Elf32_Word xndx = ((Elf32_Word *) data->d_buf)[cnt];
+
+      if (xndx != 0)
+	{
+	  GElf_Sym sym_data;
+	  GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_data);
+	  if (sym == NULL)
+	    {
+	      ERROR (_("cannot get data for symbol %zu\n"), cnt);
+	      continue;
+	    }
+
+	  if (sym->st_shndx != SHN_XINDEX)
+	    ERROR (_("\
+extended section index is %" PRIu32 " but symbol index is not XINDEX\n"),
+		   (uint32_t) xndx);
+	}
+    }
+}
+
+
+static void
+check_sysv_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
+		 GElf_Shdr *symshdr)
+{
+  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
+  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
+
+  if (shdr->sh_size < (2ULL + nbucket + nchain) * sizeof (Elf32_Word))
+    {
+      ERROR (_("\
+section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
+	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
+	     (long int) ((2 + nbucket + nchain) * sizeof (Elf32_Word)));
+      return;
+    }
+
+  size_t maxidx = nchain;
+
+  if (symshdr != NULL && symshdr->sh_entsize != 0)
+    {
+      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
+
+      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
+	ERROR (_("section [%2d] '%s': chain array too large\n"),
+	       idx, section_name (ebl, idx));
+
+      maxidx = symsize;
+    }
+
+  Elf32_Word *buf = (Elf32_Word *) data->d_buf;
+  Elf32_Word *end = (Elf32_Word *) ((char *) data->d_buf + shdr->sh_size);
+  size_t cnt;
+  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
+    {
+      if (buf + cnt >= end)
+	break;
+      else if (buf[cnt] >= maxidx)
+      ERROR (_("\
+section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
+	     idx, section_name (ebl, idx), cnt - 2);
+    }
+
+  for (; cnt < 2 + nbucket + nchain; ++cnt)
+    {
+      if (buf + cnt >= end)
+	break;
+      else if (buf[cnt] >= maxidx)
+      ERROR (_("\
+section [%2d] '%s': hash chain reference %zu out of bounds\n"),
+	     idx, section_name (ebl, idx), cnt - 2 - nbucket);
+    }
+}
+
+
+static void
+check_sysv_hash64 (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
+		 GElf_Shdr *symshdr)
+{
+  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
+  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
+
+  uint64_t maxwords = shdr->sh_size / sizeof (Elf64_Xword);
+  if (maxwords < 2
+      || maxwords - 2 < nbucket
+      || maxwords - 2 - nbucket < nchain)
+    {
+      ERROR (_("\
+section [%2d] '%s': hash table section is too small (is %ld, expected %ld)\n"),
+	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
+	     (long int) ((2 + nbucket + nchain) * sizeof (Elf64_Xword)));
+      return;
+    }
+
+  size_t maxidx = nchain;
+
+  if (symshdr != NULL && symshdr->sh_entsize != 0)
+    {
+      size_t symsize = symshdr->sh_size / symshdr->sh_entsize;
+
+      if (nchain > symshdr->sh_size / symshdr->sh_entsize)
+	ERROR (_("section [%2d] '%s': chain array too large\n"),
+	       idx, section_name (ebl, idx));
+
+      maxidx = symsize;
+    }
+
+  Elf64_Xword *buf = (Elf64_Xword *) data->d_buf;
+  Elf64_Xword *end = (Elf64_Xword *) ((char *) data->d_buf + shdr->sh_size);
+  size_t cnt;
+  for (cnt = 2; cnt < 2 + nbucket; ++cnt)
+    {
+      if (buf + cnt >= end)
+	break;
+      else if (buf[cnt] >= maxidx)
+      ERROR (_("\
+section [%2d] '%s': hash bucket reference %zu out of bounds\n"),
+	     idx, section_name (ebl, idx), cnt - 2);
+    }
+
+  for (; cnt < 2 + nbucket + nchain; ++cnt)
+    {
+      if (buf + cnt >= end)
+	break;
+      else if (buf[cnt] >= maxidx)
+      ERROR (_("\
+section [%2d] '%s': hash chain reference %" PRIu64 " out of bounds\n"),
+	       idx, section_name (ebl, idx), (uint64_t) cnt - 2 - nbucket);
+    }
+}
+
+
+static void
+check_gnu_hash (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data, int idx,
+		GElf_Shdr *symshdr)
+{
+  if (data->d_size < 4 * sizeof (Elf32_Word))
+    {
+      ERROR (_("\
+section [%2d] '%s': not enough data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  Elf32_Word nbuckets = ((Elf32_Word *) data->d_buf)[0];
+  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
+  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
+
+  if (bitmask_words == 0 || !powerof2 (bitmask_words))
+    {
+      ERROR (_("\
+section [%2d] '%s': bitmask size zero or not power of 2: %u\n"),
+	     idx, section_name (ebl, idx), bitmask_words);
+      return;
+    }
+
+  size_t bitmask_idxmask = bitmask_words - 1;
+  if (gelf_getclass (ebl->elf) == ELFCLASS64)
+    bitmask_words *= 2;
+  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
+
+  /* Is there still room for the sym chain?
+     Use uint64_t calculation to prevent 32bit overflow.  */
+  uint64_t used_buf = (4ULL + bitmask_words + nbuckets) * sizeof (Elf32_Word);
+  if (used_buf > data->d_size)
+    {
+      ERROR (_("\
+section [%2d] '%s': hash table section is too small (is %ld, expected at least %ld)\n"),
+	     idx, section_name (ebl, idx), (long int) shdr->sh_size,
+	     (long int) used_buf);
+      return;
+    }
+
+  if (shift > 31)
+    {
+      ERROR (_("\
+section [%2d] '%s': 2nd hash function shift too big: %u\n"),
+	     idx, section_name (ebl, idx), shift);
+      return;
+    }
+
+  size_t maxidx = shdr->sh_size / sizeof (Elf32_Word) - (4 + bitmask_words
+							 + nbuckets);
+
+  if (symshdr != NULL && symshdr->sh_entsize != 0)
+    maxidx = MIN (maxidx, symshdr->sh_size / symshdr->sh_entsize);
+
+  /* We need the symbol section data.  */
+  Elf_Data *symdata = elf_getdata (elf_getscn (ebl->elf, shdr->sh_link), NULL);
+
+  union
+  {
+    Elf32_Word *p32;
+    Elf64_Xword *p64;
+  } bitmask = { .p32 = &((Elf32_Word *) data->d_buf)[4] },
+      collected = { .p32 = xcalloc (bitmask_words, sizeof (Elf32_Word)) };
+
+  size_t classbits = gelf_getclass (ebl->elf) == ELFCLASS32 ? 32 : 64;
+
+  size_t cnt;
+  for (cnt = 4 + bitmask_words; cnt < 4 + bitmask_words + nbuckets; ++cnt)
+    {
+      Elf32_Word symidx = ((Elf32_Word *) data->d_buf)[cnt];
+
+      if (symidx == 0)
+	continue;
+
+      if (symidx < symbias)
+	{
+	  ERROR (_("\
+section [%2d] '%s': hash chain for bucket %zu lower than symbol index bias\n"),
+		 idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
+	  continue;
+	}
+
+      while (symidx - symbias < maxidx)
+	{
+	  Elf32_Word chainhash = ((Elf32_Word *) data->d_buf)[4
+							      + bitmask_words
+							      + nbuckets
+							      + symidx
+							      - symbias];
+
+	  if (symdata != NULL)
+	    {
+	      /* Check that the referenced symbol is not undefined.  */
+	      GElf_Sym sym_mem;
+	      GElf_Sym *sym = gelf_getsym (symdata, symidx, &sym_mem);
+	      if (sym != NULL && sym->st_shndx == SHN_UNDEF
+		  && GELF_ST_TYPE (sym->st_info) != STT_FUNC)
+		ERROR (_("\
+section [%2d] '%s': symbol %u referenced in chain for bucket %zu is undefined\n"),
+		       idx, section_name (ebl, idx), symidx,
+		       cnt - (4 + bitmask_words));
+
+	      const char *symname = (sym != NULL
+				     ? elf_strptr (ebl->elf, symshdr->sh_link,
+						   sym->st_name)
+				     : NULL);
+	      if (symname != NULL)
+		{
+		  Elf32_Word hval = elf_gnu_hash (symname);
+		  if ((hval & ~1u) != (chainhash & ~1u))
+		    ERROR (_("\
+section [%2d] '%s': hash value for symbol %u in chain for bucket %zu wrong\n"),
+			   idx, section_name (ebl, idx), symidx,
+			   cnt - (4 + bitmask_words));
+
+		  /* Set the bits in the bitmask.  */
+		  size_t maskidx = (hval / classbits) & bitmask_idxmask;
+		  if (maskidx >= bitmask_words)
+		    {
+		      ERROR (_("\
+section [%2d] '%s': mask index for symbol %u in chain for bucket %zu wrong\n"),
+			     idx, section_name (ebl, idx), symidx,
+			     cnt - (4 + bitmask_words));
+		      return;
+		    }
+		  if (classbits == 32)
+		    {
+		      collected.p32[maskidx]
+			|= UINT32_C (1) << (hval & (classbits - 1));
+		      collected.p32[maskidx]
+			|= UINT32_C (1) << ((hval >> shift) & (classbits - 1));
+		    }
+		  else
+		    {
+		      collected.p64[maskidx]
+			|= UINT64_C (1) << (hval & (classbits - 1));
+		      collected.p64[maskidx]
+			|= UINT64_C (1) << ((hval >> shift) & (classbits - 1));
+		    }
+		}
+	    }
+
+	  if ((chainhash & 1) != 0)
+	    break;
+
+	  ++symidx;
+	}
+
+      if (symidx - symbias >= maxidx)
+	ERROR (_("\
+section [%2d] '%s': hash chain for bucket %zu out of bounds\n"),
+	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
+      else if (symshdr != NULL && symshdr->sh_entsize != 0
+	       && symidx > symshdr->sh_size / symshdr->sh_entsize)
+	ERROR (_("\
+section [%2d] '%s': symbol reference in chain for bucket %zu out of bounds\n"),
+	       idx, section_name (ebl, idx), cnt - (4 + bitmask_words));
+    }
+
+  if (memcmp (collected.p32, bitmask.p32, bitmask_words * sizeof (Elf32_Word)))
+    ERROR (_("\
+section [%2d] '%s': bitmask does not match names in the hash table\n"),
+	   idx, section_name (ebl, idx));
+
+  free (collected.p32);
+}
+
+
+static void
+check_hash (int tag, Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  if (ehdr->e_type == ET_REL)
+    {
+      ERROR (_("\
+section [%2d] '%s': relocatable files cannot have hash tables\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL || data->d_buf == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				     &symshdr_mem);
+  if (symshdr != NULL && symshdr->sh_type != SHT_DYNSYM)
+    ERROR (_("\
+section [%2d] '%s': hash table not for dynamic symbol table\n"),
+	   idx, section_name (ebl, idx));
+  else if (symshdr == NULL)
+    ERROR (_("\
+section [%2d] '%s': invalid sh_link symbol table section index [%2d]\n"),
+	   idx, section_name (ebl, idx), shdr->sh_link);
+
+  size_t expect_entsize = (tag == SHT_GNU_HASH
+			   ? (gelf_getclass (ebl->elf) == ELFCLASS32
+			      ? sizeof (Elf32_Word) : 0)
+			   : (size_t) ebl_sysvhash_entrysize (ebl));
+
+  if (shdr->sh_entsize != expect_entsize)
+    ERROR (_("\
+section [%2d] '%s': hash table entry size incorrect\n"),
+	   idx, section_name (ebl, idx));
+
+  if ((shdr->sh_flags & SHF_ALLOC) == 0)
+    ERROR (_("section [%2d] '%s': not marked to be allocated\n"),
+	   idx, section_name (ebl, idx));
+
+  if (shdr->sh_size < (tag == SHT_GNU_HASH ? 4 : 2) * (expect_entsize ?: 4))
+    {
+      ERROR (_("\
+section [%2d] '%s': hash table has not even room for initial administrative entries\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  switch (tag)
+    {
+    case SHT_HASH:
+      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
+	check_sysv_hash64 (ebl, shdr, data, idx, symshdr);
+      else
+	check_sysv_hash (ebl, shdr, data, idx, symshdr);
+      break;
+
+    case SHT_GNU_HASH:
+      check_gnu_hash (ebl, shdr, data, idx, symshdr);
+      break;
+
+    default:
+      assert (! "should not happen");
+    }
+}
+
+
+/* Compare content of both hash tables, it must be identical.  */
+static void
+compare_hash_gnu_hash (Ebl *ebl, GElf_Ehdr *ehdr, size_t hash_idx,
+		       size_t gnu_hash_idx)
+{
+  Elf_Scn *hash_scn = elf_getscn (ebl->elf, hash_idx);
+  Elf_Data *hash_data = elf_getdata (hash_scn, NULL);
+  GElf_Shdr hash_shdr_mem;
+  GElf_Shdr *hash_shdr = gelf_getshdr (hash_scn, &hash_shdr_mem);
+  Elf_Scn *gnu_hash_scn = elf_getscn (ebl->elf, gnu_hash_idx);
+  Elf_Data *gnu_hash_data = elf_getdata (gnu_hash_scn, NULL);
+  GElf_Shdr gnu_hash_shdr_mem;
+  GElf_Shdr *gnu_hash_shdr = gelf_getshdr (gnu_hash_scn, &gnu_hash_shdr_mem);
+
+  if (hash_shdr == NULL || gnu_hash_shdr == NULL
+      || hash_data == NULL || hash_data->d_buf == NULL
+      || gnu_hash_data == NULL || gnu_hash_data->d_buf == NULL)
+    /* None of these pointers should be NULL since we used the
+       sections already.  We are careful nonetheless.  */
+    return;
+
+  /* The link must point to the same symbol table.  */
+  if (hash_shdr->sh_link != gnu_hash_shdr->sh_link)
+    {
+      ERROR (_("\
+sh_link in hash sections [%2zu] '%s' and [%2zu] '%s' not identical\n"),
+	     hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
+	     gnu_hash_idx,
+	     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
+      return;
+    }
+
+  Elf_Scn *sym_scn = elf_getscn (ebl->elf, hash_shdr->sh_link);
+  Elf_Data *sym_data = elf_getdata (sym_scn, NULL);
+  GElf_Shdr sym_shdr_mem;
+  GElf_Shdr *sym_shdr = gelf_getshdr (sym_scn, &sym_shdr_mem);
+
+  if (sym_data == NULL || sym_data->d_buf == NULL
+      || sym_shdr == NULL || sym_shdr->sh_entsize == 0)
+    return;
+
+  const char *hash_name;
+  const char *gnu_hash_name;
+  hash_name  = elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name);
+  gnu_hash_name  = elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name);
+
+  if (gnu_hash_data->d_size < 4 * sizeof (Elf32_Word))
+    {
+      ERROR (_("\
+hash section [%2zu] '%s' does not contain enough data\n"),
+	     gnu_hash_idx, gnu_hash_name);
+      return;
+    }
+
+  uint32_t nentries = sym_shdr->sh_size / sym_shdr->sh_entsize;
+  char *used = alloca (nentries);
+  memset (used, '\0', nentries);
+
+  /* First go over the GNU_HASH table and mark the entries as used.  */
+  const Elf32_Word *gnu_hasharr = (Elf32_Word *) gnu_hash_data->d_buf;
+  Elf32_Word gnu_nbucket = gnu_hasharr[0];
+  Elf32_Word gnu_symbias = gnu_hasharr[1];
+  const int bitmap_factor = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 1 : 2;
+  const Elf32_Word *gnu_bucket = (gnu_hasharr
+				  + (4 + gnu_hasharr[2] * bitmap_factor));
+  const Elf32_Word *gnu_chain = gnu_bucket + gnu_hasharr[0];
+
+  if (gnu_hasharr[2] == 0)
+    {
+      ERROR (_("\
+hash section [%2zu] '%s' has zero bit mask words\n"),
+	     gnu_hash_idx, gnu_hash_name);
+      return;
+    }
+
+  uint64_t used_buf = ((4ULL + gnu_hasharr[2] * bitmap_factor + gnu_nbucket)
+		       * sizeof (Elf32_Word));
+  uint32_t max_nsyms = (gnu_hash_data->d_size - used_buf) / sizeof (Elf32_Word);
+  if (used_buf > gnu_hash_data->d_size)
+    {
+      ERROR (_("\
+hash section [%2zu] '%s' uses too much data\n"),
+	     gnu_hash_idx, gnu_hash_name);
+      return;
+    }
+
+  for (Elf32_Word cnt = 0; cnt < gnu_nbucket; ++cnt)
+    {
+      if (gnu_bucket[cnt] != STN_UNDEF)
+	{
+	  Elf32_Word symidx = gnu_bucket[cnt] - gnu_symbias;
+	  do
+	    {
+	      if (symidx >= max_nsyms || symidx + gnu_symbias >= nentries)
+		{
+		  ERROR (_("\
+hash section [%2zu] '%s' invalid symbol index %" PRIu32 " (max_nsyms: %" PRIu32 ", nentries: %" PRIu32 "\n"),
+			 gnu_hash_idx, gnu_hash_name, symidx, max_nsyms, nentries);
+		  return;
+		}
+	      used[symidx + gnu_symbias] |= 1;
+	    }
+	  while ((gnu_chain[symidx++] & 1u) == 0);
+	}
+    }
+
+  /* Now go over the old hash table and check that we cover the same
+     entries.  */
+  if (hash_shdr->sh_entsize == sizeof (Elf32_Word))
+    {
+      const Elf32_Word *hasharr = (Elf32_Word *) hash_data->d_buf;
+      if (hash_data->d_size < 2 * sizeof (Elf32_Word))
+	{
+	  ERROR (_("\
+hash section [%2zu] '%s' does not contain enough data\n"),
+		 hash_idx, hash_name);
+	  return;
+	}
+
+      Elf32_Word nbucket = hasharr[0];
+      Elf32_Word nchain = hasharr[1];
+      uint64_t hash_used = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
+      if (hash_used > hash_data->d_size)
+	{
+	  ERROR (_("\
+hash section [%2zu] '%s' uses too much data\n"),
+		 hash_idx, hash_name);
+	  return;
+	}
+
+      const Elf32_Word *bucket = &hasharr[2];
+      const Elf32_Word *chain = &hasharr[2 + nbucket];
+
+      for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
+	{
+	  Elf32_Word symidx = bucket[cnt];
+	  while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
+	    {
+	      used[symidx] |= 2;
+	      symidx = chain[symidx];
+	    }
+	}
+    }
+  else if (hash_shdr->sh_entsize == sizeof (Elf64_Xword))
+    {
+      const Elf64_Xword *hasharr = (Elf64_Xword *) hash_data->d_buf;
+      if (hash_data->d_size < 2 * sizeof (Elf32_Word))
+	{
+	  ERROR (_("\
+hash section [%2zu] '%s' does not contain enough data\n"),
+		 hash_idx, hash_name);
+	  return;
+	}
+
+      Elf64_Xword nbucket = hasharr[0];
+      Elf64_Xword nchain = hasharr[1];
+      uint64_t maxwords = hash_data->d_size / sizeof (Elf64_Xword);
+      if (maxwords < 2
+	  || maxwords - 2 < nbucket
+	  || maxwords - 2 - nbucket < nchain)
+	{
+	  ERROR (_("\
+hash section [%2zu] '%s' uses too much data\n"),
+		 hash_idx, hash_name);
+	  return;
+	}
+
+      const Elf64_Xword *bucket = &hasharr[2];
+      const Elf64_Xword *chain = &hasharr[2 + nbucket];
+
+      for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
+	{
+	  Elf64_Xword symidx = bucket[cnt];
+	  while (symidx != STN_UNDEF && symidx < nentries && symidx < nchain)
+	    {
+	      used[symidx] |= 2;
+	      symidx = chain[symidx];
+	    }
+	}
+    }
+  else
+    {
+      ERROR (_("\
+hash section [%2zu] '%s' invalid sh_entsize\n"),
+	     hash_idx, hash_name);
+      return;
+    }
+
+  /* Now see which entries are not set in one or both hash tables
+     (unless the symbol is undefined in which case it can be omitted
+     in the new table format).  */
+  if ((used[0] & 1) != 0)
+    ERROR (_("section [%2zu] '%s': reference to symbol index 0\n"),
+	   gnu_hash_idx,
+	   elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
+  if ((used[0] & 2) != 0)
+    ERROR (_("section [%2zu] '%s': reference to symbol index 0\n"),
+	   hash_idx, elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
+
+  for (uint32_t cnt = 1; cnt < nentries; ++cnt)
+    if (used[cnt] != 0 && used[cnt] != 3)
+      {
+	if (used[cnt] == 1)
+	  ERROR (_("\
+symbol %d referenced in new hash table in [%2zu] '%s' but not in old hash table in [%2zu] '%s'\n"),
+		 cnt, gnu_hash_idx,
+		 elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name),
+		 hash_idx,
+		 elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name));
+	else
+	  {
+	    GElf_Sym sym_mem;
+	    GElf_Sym *sym = gelf_getsym (sym_data, cnt, &sym_mem);
+
+	    if (sym != NULL && sym->st_shndx != STN_UNDEF)
+	      ERROR (_("\
+symbol %d referenced in old hash table in [%2zu] '%s' but not in new hash table in [%2zu] '%s'\n"),
+		     cnt, hash_idx,
+		     elf_strptr (ebl->elf, shstrndx, hash_shdr->sh_name),
+		     gnu_hash_idx,
+		     elf_strptr (ebl->elf, shstrndx, gnu_hash_shdr->sh_name));
+	  }
+      }
+}
+
+
+static void
+check_null (Ebl *ebl, GElf_Shdr *shdr, int idx)
+{
+#define TEST(name, extra) \
+  if (extra && shdr->sh_##name != 0)					      \
+    ERROR (_("section [%2d] '%s': nonzero sh_%s for NULL section\n"),  \
+	   idx, section_name (ebl, idx), #name)
+
+  TEST (name, 1);
+  TEST (flags, 1);
+  TEST (addr, 1);
+  TEST (offset, 1);
+  TEST (size, idx != 0);
+  TEST (link, idx != 0);
+  TEST (info, 1);
+  TEST (addralign, 1);
+  TEST (entsize, 1);
+}
+
+
+static void
+check_group (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  if (ehdr->e_type != ET_REL)
+    {
+      ERROR (_("\
+section [%2d] '%s': section groups only allowed in relocatable object files\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  /* Check that sh_link is an index of a symbol table.  */
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  if (symshdr == NULL)
+    ERROR (_("section [%2d] '%s': cannot get symbol table: %s\n"),
+	   idx, section_name (ebl, idx), elf_errmsg (-1));
+  else
+    {
+      if (symshdr->sh_type != SHT_SYMTAB)
+	ERROR (_("\
+section [%2d] '%s': section reference in sh_link is no symbol table\n"),
+	       idx, section_name (ebl, idx));
+
+      if (shdr->sh_info >= symshdr->sh_size / gelf_fsize (ebl->elf, ELF_T_SYM,
+							  1, EV_CURRENT))
+	ERROR (_("\
+section [%2d] '%s': invalid symbol index in sh_info\n"),
+	       idx, section_name (ebl, idx));
+
+      if (shdr->sh_flags != 0)
+	ERROR (_("section [%2d] '%s': sh_flags not zero\n"),
+	       idx, section_name (ebl, idx));
+
+      GElf_Sym sym_data;
+      GElf_Sym *sym = gelf_getsym (elf_getdata (symscn, NULL), shdr->sh_info,
+				   &sym_data);
+      if (sym == NULL)
+	ERROR (_("\
+section [%2d] '%s': cannot get symbol for signature\n"),
+	       idx, section_name (ebl, idx));
+      else if (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name) == NULL)
+	ERROR (_("\
+section [%2d] '%s': cannot get symbol name for signature\n"),
+	       idx, section_name (ebl, idx));
+      else if (strcmp (elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name),
+		       "") == 0)
+	ERROR (_("\
+section [%2d] '%s': signature symbol cannot be empty string\n"),
+	       idx, section_name (ebl, idx));
+
+      if (be_strict
+	  && shdr->sh_entsize != elf32_fsize (ELF_T_WORD, 1, EV_CURRENT))
+	ERROR (_("section [%2d] '%s': sh_flags not set correctly\n"),
+	       idx, section_name (ebl, idx));
+    }
+
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL || data->d_buf == NULL)
+    ERROR (_("section [%2d] '%s': cannot get data: %s\n"),
+	   idx, section_name (ebl, idx), elf_errmsg (-1));
+  else
+    {
+      size_t elsize = elf32_fsize (ELF_T_WORD, 1, EV_CURRENT);
+      size_t cnt;
+      Elf32_Word val;
+
+      if (data->d_size % elsize != 0)
+	ERROR (_("\
+section [%2d] '%s': section size not multiple of sizeof(Elf32_Word)\n"),
+	       idx, section_name (ebl, idx));
+
+      if (data->d_size < elsize)
+	{
+	  ERROR (_("\
+section [%2d] '%s': section group without flags word\n"),
+	       idx, section_name (ebl, idx));
+	  return;
+	}
+      else if (be_strict)
+	{
+	  if (data->d_size < 2 * elsize)
+	    ERROR (_("\
+section [%2d] '%s': section group without member\n"),
+		   idx, section_name (ebl, idx));
+	  else if (data->d_size < 3 * elsize)
+	    ERROR (_("\
+section [%2d] '%s': section group with only one member\n"),
+		   idx, section_name (ebl, idx));
+	}
+
+#if ALLOW_UNALIGNED
+      val = *((Elf32_Word *) data->d_buf);
+#else
+      memcpy (&val, data->d_buf, elsize);
+#endif
+      if ((val & ~GRP_COMDAT) != 0)
+	ERROR (_("section [%2d] '%s': unknown section group flags\n"),
+	       idx, section_name (ebl, idx));
+
+      for (cnt = elsize; cnt + elsize <= data->d_size; cnt += elsize)
+	{
+#if ALLOW_UNALIGNED
+	  val = *((Elf32_Word *) ((char *) data->d_buf + cnt));
+#else
+	  memcpy (&val, (char *) data->d_buf + cnt, elsize);
+#endif
+
+	  if (val > shnum)
+	    ERROR (_("\
+section [%2d] '%s': section index %zu out of range\n"),
+		   idx, section_name (ebl, idx), cnt / elsize);
+	  else
+	    {
+	      GElf_Shdr refshdr_mem;
+	      GElf_Shdr *refshdr = gelf_getshdr (elf_getscn (ebl->elf, val),
+						 &refshdr_mem);
+	      if (refshdr == NULL)
+		ERROR (_("\
+section [%2d] '%s': cannot get section header for element %zu: %s\n"),
+		       idx, section_name (ebl, idx), cnt / elsize,
+		       elf_errmsg (-1));
+	      else
+		{
+		  if (refshdr->sh_type == SHT_GROUP)
+		    ERROR (_("\
+section [%2d] '%s': section group contains another group [%2d] '%s'\n"),
+			   idx, section_name (ebl, idx),
+			   val, section_name (ebl, val));
+
+		  if ((refshdr->sh_flags & SHF_GROUP) == 0)
+		    ERROR (_("\
+section [%2d] '%s': element %zu references section [%2d] '%s' without SHF_GROUP flag set\n"),
+			   idx, section_name (ebl, idx), cnt / elsize,
+			   val, section_name (ebl, val));
+		}
+
+	      if (val < shnum && ++scnref[val] == 2)
+		ERROR (_("\
+section [%2d] '%s' is contained in more than one section group\n"),
+		       val, section_name (ebl, val));
+	    }
+	}
+    }
+}
+
+
+static const char *
+section_flags_string (GElf_Word flags, char *buf, size_t len)
+{
+  if (flags == 0)
+    return "none";
+
+  static const struct
+  {
+    GElf_Word flag;
+    const char *name;
+  } known_flags[] =
+    {
+#define NEWFLAG(name) { SHF_##name, #name }
+      NEWFLAG (WRITE),
+      NEWFLAG (ALLOC),
+      NEWFLAG (EXECINSTR),
+      NEWFLAG (MERGE),
+      NEWFLAG (STRINGS),
+      NEWFLAG (INFO_LINK),
+      NEWFLAG (LINK_ORDER),
+      NEWFLAG (OS_NONCONFORMING),
+      NEWFLAG (GROUP),
+      NEWFLAG (TLS),
+      NEWFLAG (COMPRESSED),
+      NEWFLAG (GNU_RETAIN),
+      NEWFLAG (ORDERED),
+      NEWFLAG (EXCLUDE)
+    };
+#undef NEWFLAG
+  const size_t nknown_flags = sizeof (known_flags) / sizeof (known_flags[0]);
+
+  char *cp = buf;
+
+  for (size_t cnt = 0; cnt < nknown_flags; ++cnt)
+    if (flags & known_flags[cnt].flag)
+      {
+	if (cp != buf && len > 1)
+	  {
+	    *cp++ = '|';
+	    --len;
+	  }
+
+	size_t ncopy = MIN (len - 1, strlen (known_flags[cnt].name));
+	cp = mempcpy (cp, known_flags[cnt].name, ncopy);
+	len -= ncopy;
+
+	flags ^= known_flags[cnt].flag;
+      }
+
+  if (flags != 0 || cp == buf)
+    {
+      int r = snprintf (cp, len - 1, "%s%" PRIx64,
+			(cp == buf) ? "" : "|", (uint64_t) flags);
+      if (r > 0)
+	cp += r;
+    }
+  *cp = '\0';
+
+  return buf;
+}
+
+
+static int
+has_copy_reloc (Ebl *ebl, unsigned int symscnndx, unsigned int symndx)
+{
+  /* First find the relocation section for the symbol table.  */
+  Elf_Scn *scn = NULL;
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr != NULL
+	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+	  && shdr->sh_link == symscnndx)
+	/* Found the section.  */
+	break;
+    }
+
+  if (scn == NULL)
+    return 0;
+
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL || shdr->sh_entsize == 0)
+    return 0;
+
+  if (shdr->sh_type == SHT_REL)
+    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
+      {
+	GElf_Rel rel_mem;
+	GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
+	if (rel == NULL)
+	  continue;
+
+	if (GELF_R_SYM (rel->r_info) == symndx
+	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rel->r_info)))
+	  return 1;
+      }
+  else
+    for (int i = 0; (size_t) i < shdr->sh_size / shdr->sh_entsize; ++i)
+      {
+	GElf_Rela rela_mem;
+	GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
+	if (rela == NULL)
+	  continue;
+
+	if (GELF_R_SYM (rela->r_info) == symndx
+	    && ebl_copy_reloc_p (ebl, GELF_R_TYPE (rela->r_info)))
+	  return 1;
+      }
+
+  return 0;
+}
+
+
+static int
+in_nobits_scn (Ebl *ebl, unsigned int shndx)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, shndx), &shdr_mem);
+  return shdr != NULL && shdr->sh_type == SHT_NOBITS;
+}
+
+
+static struct version_namelist
+{
+  const char *objname;
+  const char *name;
+  GElf_Versym ndx;
+  enum { ver_def, ver_need } type;
+  struct version_namelist *next;
+} *version_namelist;
+
+
+static int
+add_version (const char *objname, const char *name, GElf_Versym ndx, int type)
+{
+  /* Check that there are no duplications.  */
+  struct version_namelist *nlp = version_namelist;
+  while (nlp != NULL)
+    {
+      if (((nlp->objname == NULL && objname == NULL)
+	   || (nlp->objname != NULL && objname != NULL
+	       && strcmp (nlp->objname, objname) == 0))
+	  && strcmp (nlp->name, name) == 0)
+	return nlp->type == ver_def ? 1 : -1;
+      nlp = nlp->next;
+    }
+
+  nlp = xmalloc (sizeof (*nlp));
+  nlp->objname = objname;
+  nlp->name = name;
+  nlp->ndx = ndx;
+  nlp->type = type;
+  nlp->next = version_namelist;
+  version_namelist = nlp;
+
+  return 0;
+}
+
+
+static void
+check_versym (Ebl *ebl, int idx)
+{
+  Elf_Scn *scn = elf_getscn (ebl->elf, idx);
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    /* The error has already been reported.  */
+    return;
+
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  if (symshdr == NULL)
+    /* The error has already been reported.  */
+    return;
+
+  if (symshdr->sh_type != SHT_DYNSYM)
+    {
+      ERROR (_("\
+section [%2d] '%s' refers in sh_link to section [%2d] '%s' which is no dynamic symbol table\n"),
+	     idx, section_name (ebl, idx),
+	     shdr->sh_link, section_name (ebl, shdr->sh_link));
+      return;
+    }
+
+  /* The number of elements in the version symbol table must be the
+     same as the number of symbols.  */
+  if (shdr->sh_entsize != 0 && symshdr->sh_entsize != 0
+      && (shdr->sh_size / shdr->sh_entsize
+	  != symshdr->sh_size / symshdr->sh_entsize))
+    ERROR (_("\
+section [%2d] '%s' has different number of entries than symbol table [%2d] '%s'\n"),
+	   idx, section_name (ebl, idx),
+	   shdr->sh_link, section_name (ebl, shdr->sh_link));
+
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  if (symdata == NULL || shdr->sh_entsize == 0)
+    /* The error has already been reported.  */
+    return;
+
+  for (int cnt = 1; (size_t) cnt < shdr->sh_size / shdr->sh_entsize; ++cnt)
+    {
+      GElf_Versym versym_mem;
+      GElf_Versym *versym = gelf_getversym (data, cnt, &versym_mem);
+      if (versym == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': symbol %d: cannot read version data\n"),
+		 idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+
+      GElf_Sym sym_mem;
+      GElf_Sym *sym = gelf_getsym (symdata, cnt, &sym_mem);
+      if (sym == NULL)
+	/* Already reported elsewhere.  */
+	continue;
+
+      if (*versym == VER_NDX_GLOBAL)
+	{
+	  /* Global symbol.  Make sure it is not defined as local.  */
+	  if (GELF_ST_BIND (sym->st_info) == STB_LOCAL)
+	    ERROR (_("\
+section [%2d] '%s': symbol %d: local symbol with global scope\n"),
+		   idx, section_name (ebl, idx), cnt);
+	}
+      else if (*versym != VER_NDX_LOCAL)
+	{
+	  /* Versioned symbol.  Make sure it is not defined as local.  */
+	  if (!gnuld && GELF_ST_BIND (sym->st_info) == STB_LOCAL)
+	    ERROR (_("\
+section [%2d] '%s': symbol %d: local symbol with version\n"),
+		   idx, section_name (ebl, idx), cnt);
+
+	  /* Look through the list of defined versions and locate the
+	     index we need for this symbol.  */
+	  struct version_namelist *runp = version_namelist;
+	  while (runp != NULL)
+	    if (runp->ndx == (*versym & (GElf_Versym) 0x7fff))
+	      break;
+	    else
+	      runp = runp->next;
+
+	  if (runp == NULL)
+	    ERROR (_("\
+section [%2d] '%s': symbol %d: invalid version index %d\n"),
+		   idx, section_name (ebl, idx), cnt, (int) *versym);
+	  else if (sym->st_shndx == SHN_UNDEF
+		   && runp->type == ver_def)
+	    ERROR (_("\
+section [%2d] '%s': symbol %d: version index %d is for defined version\n"),
+		   idx, section_name (ebl, idx), cnt, (int) *versym);
+	  else if (sym->st_shndx != SHN_UNDEF
+		   && runp->type == ver_need)
+	    {
+	      /* Unless this symbol has a copy relocation associated
+		 this must not happen.  */
+	      if (!has_copy_reloc (ebl, shdr->sh_link, cnt)
+		  && !in_nobits_scn (ebl, sym->st_shndx))
+		ERROR (_("\
+section [%2d] '%s': symbol %d: version index %d is for requested version\n"),
+		       idx, section_name (ebl, idx), cnt, (int) *versym);
+	    }
+	}
+    }
+}
+
+
+static int
+unknown_dependency_p (Elf *elf, const char *fname)
+{
+  GElf_Phdr phdr_mem;
+  GElf_Phdr *phdr = NULL;
+
+  unsigned int i;
+  for (i = 0; i < phnum; ++i)
+    if ((phdr = gelf_getphdr (elf, i, &phdr_mem)) != NULL
+	&& phdr->p_type == PT_DYNAMIC)
+      break;
+
+  if (i == phnum)
+    return 1;
+  assert (phdr != NULL);
+  Elf_Scn *scn = gelf_offscn (elf, phdr->p_offset);
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC
+      && data != NULL && shdr->sh_entsize != 0)
+    for (size_t j = 0; j < shdr->sh_size / shdr->sh_entsize; ++j)
+      {
+	GElf_Dyn dyn_mem;
+	GElf_Dyn *dyn = gelf_getdyn (data, j, &dyn_mem);
+	if (dyn != NULL && dyn->d_tag == DT_NEEDED)
+	  {
+	    const char *str = elf_strptr (elf, shdr->sh_link, dyn->d_un.d_val);
+	    if (str != NULL && strcmp (str, fname) == 0)
+	      /* Found it.  */
+	      return 0;
+	  }
+      }
+
+  return 1;
+}
+
+
+static unsigned int nverneed;
+
+static void
+check_verneed (Ebl *ebl, GElf_Shdr *shdr, int idx)
+{
+  if (++nverneed == 2)
+    ERROR (_("more than one version reference section present\n"));
+
+  GElf_Shdr strshdr_mem;
+  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				     &strshdr_mem);
+  if (strshdr == NULL)
+    return;
+  if (strshdr->sh_type != SHT_STRTAB)
+    ERROR (_("\
+section [%2d] '%s': sh_link does not link to string table\n"),
+	   idx, section_name (ebl, idx));
+
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+  unsigned int offset = 0;
+  for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
+    {
+      cnt--;
+
+      /* Get the data at the next offset.  */
+      GElf_Verneed needmem;
+      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
+      if (need == NULL)
+	break;
+
+      unsigned int auxoffset = offset + need->vn_aux;
+
+      if (need->vn_version != EV_CURRENT)
+	ERROR (_("\
+section [%2d] '%s': entry %d has wrong version %d\n"),
+	       idx, section_name (ebl, idx), cnt, (int) need->vn_version);
+
+      if (need->vn_cnt > 0 && need->vn_aux < gelf_fsize (ebl->elf, ELF_T_VNEED,
+							 1, EV_CURRENT))
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
+	         idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+
+      const char *libname = elf_strptr (ebl->elf, shdr->sh_link,
+					need->vn_file);
+      if (libname == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has invalid file reference\n"),
+		 idx, section_name (ebl, idx), cnt);
+	  goto next_need;
+	}
+
+      /* Check that there is a DT_NEEDED entry for the referenced library.  */
+      if (unknown_dependency_p (ebl->elf, libname))
+	ERROR (_("\
+section [%2d] '%s': entry %d references unknown dependency\n"),
+	       idx, section_name (ebl, idx), cnt);
+
+      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
+	{
+	  GElf_Vernaux auxmem;
+	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
+	  if (aux == NULL)
+	    break;
+
+	  if ((aux->vna_flags & ~VER_FLG_WEAK) != 0)
+	    ERROR (_("\
+section [%2d] '%s': auxiliary entry %d of entry %d has unknown flag\n"),
+		   idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
+
+	  const char *verstr = elf_strptr (ebl->elf, shdr->sh_link,
+					   aux->vna_name);
+	  if (verstr == NULL)
+	    {
+	      ERROR (_("\
+section [%2d] '%s': auxiliary entry %d of entry %d has invalid name reference\n"),
+		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
+	      break;
+	    }
+	  else
+	    {
+	      GElf_Word hashval = elf_hash (verstr);
+	      if (hashval != aux->vna_hash)
+		ERROR (_("\
+section [%2d] '%s': auxiliary entry %d of entry %d has wrong hash value: %#x, expected %#x\n"),
+		       idx, section_name (ebl, idx), need->vn_cnt - cnt2,
+		       cnt, (int) hashval, (int) aux->vna_hash);
+
+	      int res = add_version (libname, verstr, aux->vna_other,
+				     ver_need);
+	      if (unlikely (res !=0))
+		{
+		  ERROR (_("\
+section [%2d] '%s': auxiliary entry %d of entry %d has duplicate version name '%s'\n"),
+			 idx, section_name (ebl, idx), need->vn_cnt - cnt2,
+			 cnt, verstr);
+		}
+	    }
+
+	  if ((aux->vna_next != 0 || cnt2 > 0)
+	      && aux->vna_next < gelf_fsize (ebl->elf, ELF_T_VNAUX, 1,
+					     EV_CURRENT))
+	    {
+	      ERROR (_("\
+section [%2d] '%s': auxiliary entry %d of entry %d has wrong next field\n"),
+		     idx, section_name (ebl, idx), need->vn_cnt - cnt2, cnt);
+	      break;
+	    }
+
+	  auxoffset += MAX (aux->vna_next,
+			    gelf_fsize (ebl->elf, ELF_T_VNAUX, 1, EV_CURRENT));
+	}
+
+      /* Find the next offset.  */
+    next_need:
+      offset += need->vn_next;
+
+      if ((need->vn_next != 0 || cnt > 0)
+	  && offset < auxoffset)
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has invalid offset to next entry\n"),
+	         idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+
+      if (need->vn_next == 0 && cnt > 0)
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
+	         idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+    }
+}
+
+
+static unsigned int nverdef;
+
+static void
+check_verdef (Ebl *ebl, GElf_Shdr *shdr, int idx)
+{
+  if (++nverdef == 2)
+    ERROR (_("more than one version definition section present\n"));
+
+  GElf_Shdr strshdr_mem;
+  GElf_Shdr *strshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				     &strshdr_mem);
+  if (strshdr == NULL)
+    return;
+  if (strshdr->sh_type != SHT_STRTAB)
+    ERROR (_("\
+section [%2d] '%s': sh_link does not link to string table\n"),
+	   idx, section_name (ebl, idx));
+
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL)
+    {
+    no_data:
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  /* Iterate over all version definition entries.  We check that there
+     is a BASE entry and that each index is unique.  To do the later
+     we collection the information in a list which is later
+     examined.  */
+  struct namelist
+  {
+    const char *name;
+    struct namelist *next;
+  } *namelist = NULL;
+  struct namelist *refnamelist = NULL;
+
+  bool has_base = false;
+  unsigned int offset = 0;
+  for (Elf64_Word cnt = shdr->sh_info; cnt > 0; )
+    {
+      cnt--;
+
+      /* Get the data at the next offset.  */
+      GElf_Verdef defmem;
+      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
+      if (def == NULL)
+	goto no_data;
+
+      if ((def->vd_flags & VER_FLG_BASE) != 0)
+	{
+	  if (has_base)
+	    ERROR (_("\
+section [%2d] '%s': more than one BASE definition\n"),
+		   idx, section_name (ebl, idx));
+	  if (def->vd_ndx != VER_NDX_GLOBAL)
+	    ERROR (_("\
+section [%2d] '%s': BASE definition must have index VER_NDX_GLOBAL\n"),
+		   idx, section_name (ebl, idx));
+	  has_base = true;
+	}
+      if ((def->vd_flags & ~(VER_FLG_BASE|VER_FLG_WEAK)) != 0)
+	ERROR (_("\
+section [%2d] '%s': entry %d has unknown flag\n"),
+	       idx, section_name (ebl, idx), cnt);
+
+      if (def->vd_version != EV_CURRENT)
+	ERROR (_("\
+section [%2d] '%s': entry %d has wrong version %d\n"),
+	       idx, section_name (ebl, idx), cnt, (int) def->vd_version);
+
+      if (def->vd_cnt > 0 && def->vd_aux < gelf_fsize (ebl->elf, ELF_T_VDEF,
+						       1, EV_CURRENT))
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has wrong offset of auxiliary data\n"),
+	         idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+
+      unsigned int auxoffset = offset + def->vd_aux;
+      GElf_Verdaux auxmem;
+      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
+      if (aux == NULL)
+	goto no_data;
+
+      const char *name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
+      if (name == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has invalid name reference\n"),
+		 idx, section_name (ebl, idx), cnt);
+	  goto next_def;
+	}
+      GElf_Word hashval = elf_hash (name);
+      if (def->vd_hash != hashval)
+	ERROR (_("\
+section [%2d] '%s': entry %d has wrong hash value: %#x, expected %#x\n"),
+	       idx, section_name (ebl, idx), cnt, (int) hashval,
+	       (int) def->vd_hash);
+
+      int res = add_version (NULL, name, def->vd_ndx, ver_def);
+      if (unlikely (res !=0))
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has duplicate version name '%s'\n"),
+		 idx, section_name (ebl, idx), cnt, name);
+	}
+
+      struct namelist *newname = alloca (sizeof (*newname));
+      newname->name = name;
+      newname->next = namelist;
+      namelist = newname;
+
+      auxoffset += aux->vda_next;
+      for (int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
+	{
+	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
+	  if (aux == NULL)
+	    goto no_data;
+
+	  name = elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name);
+	  if (name == NULL)
+	    {
+	      ERROR (_("\
+section [%2d] '%s': entry %d has invalid name reference in auxiliary data\n"),
+		     idx, section_name (ebl, idx), cnt);
+	      break;
+	    }
+	  else
+	    {
+	      newname = alloca (sizeof (*newname));
+	      newname->name = name;
+	      newname->next = refnamelist;
+	      refnamelist = newname;
+	    }
+
+	  if ((aux->vda_next != 0 || cnt2 + 1 < def->vd_cnt)
+	      && aux->vda_next < gelf_fsize (ebl->elf, ELF_T_VDAUX, 1,
+					     EV_CURRENT))
+	    {
+	      ERROR (_("\
+section [%2d] '%s': entry %d has wrong next field in auxiliary data\n"),
+		     idx, section_name (ebl, idx), cnt);
+	      break;
+	    }
+
+	  auxoffset += MAX (aux->vda_next,
+			    gelf_fsize (ebl->elf, ELF_T_VDAUX, 1, EV_CURRENT));
+	}
+
+      /* Find the next offset.  */
+    next_def:
+      offset += def->vd_next;
+
+      if ((def->vd_next != 0 || cnt > 0)
+	  && offset < auxoffset)
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has invalid offset to next entry\n"),
+	         idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+
+      if (def->vd_next == 0 && cnt > 0)
+	{
+	  ERROR (_("\
+section [%2d] '%s': entry %d has zero offset to next entry, but sh_info says there are more entries\n"),
+	         idx, section_name (ebl, idx), cnt);
+	  break;
+	}
+    }
+
+  if (!has_base)
+    ERROR (_("section [%2d] '%s': no BASE definition\n"),
+	   idx, section_name (ebl, idx));
+
+  /* Check whether the referenced names are available.  */
+  while (namelist != NULL)
+    {
+      struct version_namelist *runp = version_namelist;
+      while (runp != NULL)
+	{
+	  if (runp->type == ver_def
+	      && strcmp (runp->name, namelist->name) == 0)
+	    break;
+	  runp = runp->next;
+	}
+
+      if (runp == NULL)
+	ERROR (_("\
+section [%2d] '%s': unknown parent version '%s'\n"),
+	       idx, section_name (ebl, idx), namelist->name);
+
+      namelist = namelist->next;
+    }
+}
+
+static inline size_t
+buffer_pos (Elf_Data *data, const unsigned char *p)
+{
+  return p - (const unsigned char *) data->d_buf;
+}
+
+static inline size_t
+buffer_left (Elf_Data *data, const unsigned char *p)
+{
+  return (const unsigned char *) data->d_buf + data->d_size - p;
+}
+
+static void
+check_attributes (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  if (shdr->sh_size == 0)
+    {
+      ERROR (_("section [%2d] '%s': empty object attributes section\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  Elf_Data *data = elf_rawdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL || data->d_size == 0 || data->d_buf == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  const unsigned char *p = data->d_buf;
+  if (*p++ != 'A')
+    {
+      ERROR (_("section [%2d] '%s': unrecognized attribute format\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  while (buffer_left (data, p) >= 4)
+    {
+      uint32_t len;
+      memcpy (&len, p, sizeof len);
+
+      if (len == 0)
+	ERROR (_("\
+section [%2d] '%s': offset %zu: zero length field in attribute section\n"),
+	       idx, section_name (ebl, idx), buffer_pos (data, p));
+
+      if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+	CONVERT (len);
+
+      if (len > buffer_left (data, p))
+	{
+	  ERROR (_("\
+section [%2d] '%s': offset %zu: invalid length in attribute section\n"),
+		 idx, section_name (ebl, idx), buffer_pos (data, p));
+	  break;
+	}
+
+      const unsigned char *name = p + sizeof len;
+      p += len;
+
+      unsigned const char *q = memchr (name, '\0', len);
+      if (q == NULL)
+	{
+	  ERROR (_("\
+section [%2d] '%s': offset %zu: unterminated vendor name string\n"),
+		 idx, section_name (ebl, idx), buffer_pos (data, p));
+	  break;
+	}
+      ++q;
+
+      if (q - name == sizeof "gnu" && !memcmp (name, "gnu", sizeof "gnu"))
+	while (q < p)
+	  {
+	    unsigned const char *chunk = q;
+
+	    unsigned int subsection_tag;
+	    get_uleb128 (subsection_tag, q, p);
+
+	    if (q >= p)
+	      {
+		ERROR (_("\
+section [%2d] '%s': offset %zu: endless ULEB128 in attribute subsection tag\n"),
+		       idx, section_name (ebl, idx), buffer_pos (data, chunk));
+		break;
+	      }
+
+	    uint32_t subsection_len;
+	    if (p - q < (ptrdiff_t) sizeof subsection_len)
+	      {
+		ERROR (_("\
+section [%2d] '%s': offset %zu: truncated attribute section\n"),
+		       idx, section_name (ebl, idx), buffer_pos (data, q));
+		break;
+	      }
+
+	    memcpy (&subsection_len, q, sizeof subsection_len);
+	    if (subsection_len == 0)
+	      {
+		ERROR (_("\
+section [%2d] '%s': offset %zu: zero length field in attribute subsection\n"),
+		       idx, section_name (ebl, idx), buffer_pos (data, q));
+
+		q += sizeof subsection_len;
+		continue;
+	      }
+
+	    if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+	      CONVERT (subsection_len);
+
+	    /* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
+	    if (p - chunk < (ptrdiff_t) subsection_len
+	        || subsection_len >= (uint32_t) PTRDIFF_MAX)
+	      {
+		ERROR (_("\
+section [%2d] '%s': offset %zu: invalid length in attribute subsection\n"),
+		       idx, section_name (ebl, idx), buffer_pos (data, q));
+		break;
+	      }
+
+	    const unsigned char *subsection_end = chunk + subsection_len;
+	    chunk = q;
+	    q = subsection_end;
+
+	    if (subsection_tag != 1) /* Tag_File */
+	      ERROR (_("\
+section [%2d] '%s': offset %zu: attribute subsection has unexpected tag %u\n"),
+		     idx, section_name (ebl, idx), buffer_pos (data, chunk), subsection_tag);
+	    else
+	      {
+		chunk += sizeof subsection_len;
+		while (chunk < q)
+		  {
+		    unsigned int tag;
+		    get_uleb128 (tag, chunk, q);
+
+		    uint64_t value = 0;
+		    const unsigned char *r = chunk;
+		    if (tag == 32 || (tag & 1) == 0)
+		      {
+			if (r >= q)
+			  goto invalid_uleb;
+			get_uleb128 (value, r, q);
+			if (r > q)
+			  {
+			  invalid_uleb:
+			    ERROR (_("\
+section [%2d] '%s': offset %zu: endless ULEB128 in attribute tag\n"),
+				   idx, section_name (ebl, idx), buffer_pos (data, chunk));
+			    break;
+			  }
+		      }
+		    if (tag == 32 || (tag & 1) != 0)
+		      {
+			r = memchr (r, '\0', q - r);
+			if (r == NULL)
+			  {
+			    ERROR (_("\
+section [%2d] '%s': offset %zu: unterminated string in attribute\n"),
+				   idx, section_name (ebl, idx), buffer_pos (data, chunk));
+			    break;
+			  }
+			++r;
+		      }
+
+		    const char *tag_name = NULL;
+		    const char *value_name = NULL;
+		    if (!ebl_check_object_attribute (ebl, (const char *) name,
+						     tag, value,
+						     &tag_name, &value_name))
+		      ERROR (_("\
+section [%2d] '%s': offset %zu: unrecognized attribute tag %u\n"),
+			     idx, section_name (ebl, idx), buffer_pos (data, chunk), tag);
+		    else if ((tag & 1) == 0 && value_name == NULL)
+		      ERROR (_("\
+section [%2d] '%s': offset %zu: unrecognized %s attribute value %" PRIu64 "\n"),
+			     idx, section_name (ebl, idx), buffer_pos (data, chunk),
+			     tag_name, value);
+
+		    chunk = r;
+		  }
+	      }
+	  }
+      else
+	ERROR (_("\
+section [%2d] '%s': offset %zu: vendor '%s' unknown\n"),
+	       idx, section_name (ebl, idx), buffer_pos (data, p), name);
+    }
+
+  if (buffer_left (data, p) != 0)
+    ERROR (_("\
+section [%2d] '%s': offset %zu: extra bytes after last attribute section\n"),
+	   idx, section_name (ebl, idx), buffer_pos (data, p));
+}
+
+static bool has_loadable_segment;
+static bool has_interp_segment;
+
+static const struct
+{
+  const char *name;
+  size_t namelen;
+  GElf_Word type;
+  enum { unused, exact, atleast, exact_or_gnuld } attrflag;
+  GElf_Word attr;
+  GElf_Word attr2;
+} special_sections[] =
+  {
+    /* See figure 4-14 in the gABI.  */
+    { ".bss", 5, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".comment", 8, SHT_PROGBITS, atleast, 0, SHF_MERGE | SHF_STRINGS },
+    { ".data", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".data1", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".debug_str", 11, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
+    { ".debug_line_str", 16, SHT_PROGBITS, exact_or_gnuld, SHF_MERGE | SHF_STRINGS, 0 },
+    { ".debug", 6, SHT_PROGBITS, exact, 0, 0 },
+    { ".dynamic", 9, SHT_DYNAMIC, atleast, SHF_ALLOC, SHF_WRITE },
+    { ".dynstr", 8, SHT_STRTAB, exact, SHF_ALLOC, 0 },
+    { ".dynsym", 8, SHT_DYNSYM, exact, SHF_ALLOC, 0 },
+    { ".fini", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
+    { ".fini_array", 12, SHT_FINI_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".got", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more info?
+    { ".hash", 6, SHT_HASH, exact, SHF_ALLOC, 0 },
+    { ".init", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
+    { ".init_array", 12, SHT_INIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".interp", 8, SHT_PROGBITS, atleast, 0, SHF_ALLOC }, // XXX more tests?
+    { ".line", 6, SHT_PROGBITS, exact, 0, 0 },
+    { ".note", 6, SHT_NOTE, atleast, 0, SHF_ALLOC },
+    { ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
+    { ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
+    { ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
+    { ".relr", 5, SHT_RELR, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
+    { ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
+    { ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
+    { ".shstrtab", 10, SHT_STRTAB, exact, 0, 0 },
+    { ".strtab", 8, SHT_STRTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".symtab", 8, SHT_SYMTAB, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".symtab_shndx", 14, SHT_SYMTAB_SHNDX, atleast, 0, SHF_ALLOC }, // XXX more tests
+    { ".tbss", 6, SHT_NOBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
+    { ".tdata", 7, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
+    { ".tdata1", 8, SHT_PROGBITS, exact, SHF_ALLOC | SHF_WRITE | SHF_TLS, 0 },
+    { ".text", 6, SHT_PROGBITS, exact, SHF_ALLOC | SHF_EXECINSTR, 0 },
+
+    /* The following are GNU extensions.  */
+    { ".gnu.version", 13, SHT_GNU_versym, exact, SHF_ALLOC, 0 },
+    { ".gnu.version_d", 15, SHT_GNU_verdef, exact, SHF_ALLOC, 0 },
+    { ".gnu.version_r", 15, SHT_GNU_verneed, exact, SHF_ALLOC, 0 },
+    { ".gnu.attributes", 16, SHT_GNU_ATTRIBUTES, exact, 0, 0 },
+  };
+#define nspecial_sections \
+  (sizeof (special_sections) / sizeof (special_sections[0]))
+
+#define IS_KNOWN_SPECIAL(idx, string, prefix)			      \
+  (special_sections[idx].namelen == sizeof string - (prefix ? 1 : 0)  \
+   && !memcmp (special_sections[idx].name, string, \
+	       sizeof string - (prefix ? 1 : 0)))
+
+/* Extra section flags that might or might not be added to the section
+   and have to be ignored.  */
+#define EXTRA_SHFLAGS (SHF_LINK_ORDER \
+		       | SHF_GNU_RETAIN \
+		       | SHF_GROUP \
+		       | SHF_COMPRESSED)
+
+
+/* Indices of some sections we need later.  */
+static size_t eh_frame_hdr_scnndx;
+static size_t eh_frame_scnndx;
+static size_t gcc_except_table_scnndx;
+
+
+static void
+check_sections (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  if (ehdr->e_shoff == 0)
+    /* No section header.  */
+    return;
+
+  /* Allocate array to count references in section groups.  */
+  scnref = xcalloc (shnum, sizeof (int));
+
+  /* Check the zeroth section first.  It must not have any contents
+     and the section header must contain nonzero value at most in the
+     sh_size and sh_link fields.  */
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+  if (shdr == NULL)
+    ERROR (_("cannot get section header of zeroth section\n"));
+  else
+    {
+      if (shdr->sh_name != 0)
+	ERROR (_("zeroth section has nonzero name\n"));
+      if (shdr->sh_type != 0)
+	ERROR (_("zeroth section has nonzero type\n"));
+      if (shdr->sh_flags != 0)
+	ERROR (_("zeroth section has nonzero flags\n"));
+      if (shdr->sh_addr != 0)
+	ERROR (_("zeroth section has nonzero address\n"));
+      if (shdr->sh_offset != 0)
+	ERROR (_("zeroth section has nonzero offset\n"));
+      if (shdr->sh_addralign != 0)
+	ERROR (_("zeroth section has nonzero align value\n"));
+      if (shdr->sh_entsize != 0)
+	ERROR (_("zeroth section has nonzero entry size value\n"));
+
+      if (shdr->sh_size != 0 && ehdr->e_shnum != 0)
+	ERROR (_("\
+zeroth section has nonzero size value while ELF header has nonzero shnum value\n"));
+
+      if (shdr->sh_link != 0 && ehdr->e_shstrndx != SHN_XINDEX)
+	ERROR (_("\
+zeroth section has nonzero link value while ELF header does not signal overflow in shstrndx\n"));
+
+      if (shdr->sh_info != 0 && ehdr->e_phnum != PN_XNUM)
+	ERROR (_("\
+zeroth section has nonzero link value while ELF header does not signal overflow in phnum\n"));
+    }
+
+  int *segment_flags = xcalloc (phnum, sizeof segment_flags[0]);
+
+  bool dot_interp_section = false;
+
+  size_t hash_idx = 0;
+  size_t gnu_hash_idx = 0;
+
+  size_t versym_scnndx = 0;
+  for (size_t cnt = 1; cnt < shnum; ++cnt)
+    {
+      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  ERROR (_("\
+cannot get section header for section [%2zu] '%s': %s\n"),
+		 cnt, section_name (ebl, cnt), elf_errmsg (-1));
+	  continue;
+	}
+
+      const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+
+      if (scnname == NULL)
+	ERROR (_("section [%2zu]: invalid name\n"), cnt);
+      else
+	{
+	  /* Check whether it is one of the special sections defined in
+	     the gABI.  */
+	  size_t s;
+	  for (s = 0; s < nspecial_sections; ++s)
+	    if (strncmp (scnname, special_sections[s].name,
+			 special_sections[s].namelen) == 0)
+	      {
+		char stbuf1[100];
+		char stbuf2[100];
+		char stbuf3[100];
+
+		GElf_Word good_type = special_sections[s].type;
+		if (IS_KNOWN_SPECIAL (s, ".plt", false)
+		    && ebl_bss_plt_p (ebl))
+		  good_type = SHT_NOBITS;
+
+		/* In a debuginfo file, any normal section can be SHT_NOBITS.
+		   This is only invalid for DWARF sections and .shstrtab.  */
+		if (shdr->sh_type != good_type
+		    && (shdr->sh_type != SHT_NOBITS
+			|| !is_debuginfo
+			|| IS_KNOWN_SPECIAL (s, ".debug_str", false)
+			|| IS_KNOWN_SPECIAL (s, ".debug", true)
+			|| IS_KNOWN_SPECIAL (s, ".shstrtab", false)))
+		  ERROR (_("\
+section [%2d] '%s' has wrong type: expected %s, is %s\n"),
+			 (int) cnt, scnname,
+			 ebl_section_type_name (ebl, special_sections[s].type,
+						stbuf1, sizeof (stbuf1)),
+			 ebl_section_type_name (ebl, shdr->sh_type,
+						stbuf2, sizeof (stbuf2)));
+
+		if (special_sections[s].attrflag == exact
+		    || special_sections[s].attrflag == exact_or_gnuld)
+		  {
+		    /* Except for the link order, retain, group bit and
+		       compression flag all the other bits should
+		       match exactly.  */
+		    if ((shdr->sh_flags & ~EXTRA_SHFLAGS)
+			!= special_sections[s].attr
+			&& (special_sections[s].attrflag == exact || !gnuld))
+		      ERROR (_("\
+section [%2zu] '%s' has wrong flags: expected %s, is %s\n"),
+			     cnt, scnname,
+			     section_flags_string (special_sections[s].attr,
+						   stbuf1, sizeof (stbuf1)),
+			     section_flags_string (shdr->sh_flags
+						   & ~EXTRA_SHFLAGS,
+						   stbuf2, sizeof (stbuf2)));
+		  }
+		else if (special_sections[s].attrflag == atleast)
+		  {
+		    if ((shdr->sh_flags & special_sections[s].attr)
+			!= special_sections[s].attr
+			|| ((shdr->sh_flags
+			     & ~(EXTRA_SHFLAGS
+				 | special_sections[s].attr
+				 | special_sections[s].attr2))
+			    != 0))
+		      ERROR (_("\
+section [%2zu] '%s' has wrong flags: expected %s and possibly %s, is %s\n"),
+			     cnt, scnname,
+			     section_flags_string (special_sections[s].attr,
+						   stbuf1, sizeof (stbuf1)),
+			     section_flags_string (special_sections[s].attr2,
+						   stbuf2, sizeof (stbuf2)),
+			     section_flags_string (shdr->sh_flags
+						   & ~EXTRA_SHFLAGS,
+						   stbuf3, sizeof (stbuf3)));
+		  }
+
+		if (strcmp (scnname, ".interp") == 0)
+		  {
+		    dot_interp_section = true;
+
+		    if (ehdr->e_type == ET_REL)
+		      ERROR (_("\
+section [%2zu] '%s' present in object file\n"),
+			     cnt, scnname);
+
+		    if ((shdr->sh_flags & SHF_ALLOC) != 0
+			&& !has_loadable_segment)
+		      ERROR (_("\
+section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
+			     cnt, scnname);
+		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
+			     && has_loadable_segment)
+		      ERROR (_("\
+section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
+			     cnt, scnname);
+		  }
+		else
+		  {
+		    if (strcmp (scnname, ".symtab_shndx") == 0
+			&& ehdr->e_type != ET_REL)
+		      ERROR (_("\
+section [%2zu] '%s' is extension section index table in non-object file\n"),
+			     cnt, scnname);
+
+		    /* These sections must have the SHF_ALLOC flag set iff
+		       a loadable segment is available.
+
+		       .relxxx
+		       .strtab
+		       .symtab
+		       .symtab_shndx
+
+		       Check that if there is a reference from the
+		       loaded section these sections also have the
+		       ALLOC flag set.  */
+#if 0
+		    // XXX TODO
+		    if ((shdr->sh_flags & SHF_ALLOC) != 0
+			&& !has_loadable_segment)
+		      ERROR (_("\
+section [%2zu] '%s' has SHF_ALLOC flag set but there is no loadable segment\n"),
+			     cnt, scnname);
+		    else if ((shdr->sh_flags & SHF_ALLOC) == 0
+			     && has_loadable_segment)
+		      ERROR (_("\
+section [%2zu] '%s' has SHF_ALLOC flag not set but there are loadable segments\n"),
+			     cnt, scnname);
+#endif
+		  }
+
+		break;
+	      }
+
+	  /* Remember a few special sections for later.  */
+	  if (strcmp (scnname, ".eh_frame_hdr") == 0)
+	    eh_frame_hdr_scnndx = cnt;
+	  else if (strcmp (scnname, ".eh_frame") == 0)
+	    eh_frame_scnndx = cnt;
+	  else if (strcmp (scnname, ".gcc_except_table") == 0)
+	    gcc_except_table_scnndx = cnt;
+	}
+
+      if (shdr->sh_entsize != 0 && shdr->sh_size % shdr->sh_entsize)
+	ERROR (_("\
+section [%2zu] '%s': size not multiple of entry size\n"),
+	       cnt, section_name (ebl, cnt));
+
+      if (elf_strptr (ebl->elf, shstrndx, shdr->sh_name) == NULL)
+	ERROR (_("cannot get section header\n"));
+
+      if (shdr->sh_type >= SHT_NUM
+	  && shdr->sh_type != SHT_GNU_ATTRIBUTES
+	  && shdr->sh_type != SHT_GNU_LIBLIST
+	  && shdr->sh_type != SHT_CHECKSUM
+	  && shdr->sh_type != SHT_GNU_verdef
+	  && shdr->sh_type != SHT_GNU_verneed
+	  && shdr->sh_type != SHT_GNU_versym
+	  && ebl_section_type_name (ebl, shdr->sh_type, NULL, 0) == NULL)
+	ERROR (_("section [%2zu] '%s' has unsupported type %d\n"),
+	       cnt, section_name (ebl, cnt),
+	       (int) shdr->sh_type);
+
+#define ALL_SH_FLAGS (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR | SHF_MERGE \
+		      | SHF_STRINGS | SHF_INFO_LINK | SHF_LINK_ORDER \
+		      | SHF_OS_NONCONFORMING | SHF_GROUP | SHF_TLS \
+		      | SHF_COMPRESSED | SHF_GNU_RETAIN)
+      if (shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS)
+	{
+	  GElf_Xword sh_flags = shdr->sh_flags & ~(GElf_Xword) ALL_SH_FLAGS;
+	  if (sh_flags & SHF_MASKPROC)
+	    {
+	      /* Strictly speaking SHF_EXCLUDE is a processor specific
+		 section flag, but it is used generically in the GNU
+		 toolchain.  */
+	      if (gnuld)
+		sh_flags &= ~(GElf_Xword) SHF_EXCLUDE;
+	      if (!ebl_machine_section_flag_check (ebl,
+						   sh_flags & SHF_MASKPROC))
+		ERROR (_("section [%2zu] '%s'"
+				" contains invalid processor-specific flag(s)"
+				" %#" PRIx64 "\n"),
+		       cnt, section_name (ebl, cnt), sh_flags & SHF_MASKPROC);
+	      sh_flags &= ~(GElf_Xword) SHF_MASKPROC;
+	    }
+	  if (sh_flags & SHF_MASKOS)
+	    if (gnuld)
+	      sh_flags &= ~(GElf_Xword) SHF_GNU_RETAIN;
+	  if (sh_flags != 0)
+	    ERROR (_("section [%2zu] '%s' contains unknown flag(s)"
+			    " %#" PRIx64 "\n"),
+		   cnt, section_name (ebl, cnt), sh_flags);
+	}
+      if (shdr->sh_flags & SHF_TLS)
+	{
+	  // XXX Correct?
+	  if (shdr->sh_addr != 0 && !gnuld)
+	    ERROR (_("\
+section [%2zu] '%s': thread-local data sections address not zero\n"),
+		   cnt, section_name (ebl, cnt));
+
+	  // XXX TODO more tests!?
+	}
+
+      if (shdr->sh_flags & SHF_COMPRESSED)
+	{
+	  if (shdr->sh_flags & SHF_ALLOC)
+	    ERROR (_("\
+section [%2zu] '%s': allocated section cannot be compressed\n"),
+		   cnt, section_name (ebl, cnt));
+
+	  if (shdr->sh_type == SHT_NOBITS)
+	    ERROR (_("\
+section [%2zu] '%s': nobits section cannot be compressed\n"),
+		   cnt, section_name (ebl, cnt));
+
+	  GElf_Chdr chdr;
+	  if (gelf_getchdr (scn, &chdr) == NULL)
+	    ERROR (_("\
+section [%2zu] '%s': compressed section with no compression header: %s\n"),
+		   cnt, section_name (ebl, cnt), elf_errmsg (-1));
+	}
+
+      if (shdr->sh_link >= shnum)
+	ERROR (_("\
+section [%2zu] '%s': invalid section reference in link value\n"),
+	       cnt, section_name (ebl, cnt));
+
+      if (SH_INFO_LINK_P (shdr) && shdr->sh_info >= shnum)
+	ERROR (_("\
+section [%2zu] '%s': invalid section reference in info value\n"),
+	       cnt, section_name (ebl, cnt));
+
+      if ((shdr->sh_flags & SHF_MERGE) == 0
+	  && (shdr->sh_flags & SHF_STRINGS) != 0
+	  && be_strict)
+	ERROR (_("\
+section [%2zu] '%s': strings flag set without merge flag\n"),
+	       cnt, section_name (ebl, cnt));
+
+      if ((shdr->sh_flags & SHF_MERGE) != 0 && shdr->sh_entsize == 0)
+	ERROR (_("\
+section [%2zu] '%s': merge flag set but entry size is zero\n"),
+	       cnt, section_name (ebl, cnt));
+
+      if (shdr->sh_flags & SHF_GROUP)
+	check_scn_group (ebl, cnt);
+
+      if (shdr->sh_flags & SHF_EXECINSTR)
+	{
+	  switch (shdr->sh_type)
+	    {
+	    case SHT_PROGBITS:
+	      break;
+
+	    case SHT_NOBITS:
+	      if (is_debuginfo)
+		break;
+	      FALLTHROUGH;
+	    default:
+	      ERROR (_("\
+section [%2zu] '%s' has unexpected type %d for an executable section\n"),
+		     cnt, section_name (ebl, cnt), shdr->sh_type);
+	      break;
+	    }
+
+	  if (shdr->sh_flags & SHF_WRITE)
+	    {
+	      if (is_debuginfo && shdr->sh_type != SHT_NOBITS)
+		ERROR (_("\
+section [%2zu] '%s' must be of type NOBITS in debuginfo files\n"),
+		       cnt, section_name (ebl, cnt));
+
+	      if (!is_debuginfo
+		  && !ebl_check_special_section (ebl, cnt, shdr,
+						 section_name (ebl, cnt)))
+		ERROR (_("\
+section [%2zu] '%s' is both executable and writable\n"),
+		       cnt, section_name (ebl, cnt));
+	    }
+	}
+
+      if (ehdr->e_type != ET_REL && (shdr->sh_flags & SHF_ALLOC) != 0
+	  && !is_debuginfo)
+	{
+	  /* Make sure the section is contained in a loaded segment
+	     and that the initialization part matches NOBITS sections.  */
+	  unsigned int pcnt;
+	  GElf_Phdr phdr_mem;
+	  GElf_Phdr *phdr;
+
+	  for (pcnt = 0; pcnt < phnum; ++pcnt)
+	    if ((phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem)) != NULL
+		&& ((phdr->p_type == PT_LOAD
+		     && (shdr->sh_flags & SHF_TLS) == 0)
+		    || (phdr->p_type == PT_TLS
+			&& (shdr->sh_flags & SHF_TLS) != 0))
+		&& phdr->p_offset <= shdr->sh_offset
+		&& ((shdr->sh_offset - phdr->p_offset <= phdr->p_filesz
+		     && (shdr->sh_offset - phdr->p_offset < phdr->p_filesz
+			 || shdr->sh_size == 0))
+		    || (shdr->sh_offset - phdr->p_offset < phdr->p_memsz
+			&& shdr->sh_type == SHT_NOBITS)))
+	      {
+		/* Found the segment.  */
+		if (phdr->p_offset + phdr->p_memsz
+		    < shdr->sh_offset + shdr->sh_size)
+		  ERROR (_("\
+section [%2zu] '%s' not fully contained in segment of program header entry %d\n"),
+			 cnt, section_name (ebl, cnt), pcnt);
+
+		if (shdr->sh_type == SHT_NOBITS)
+		  {
+		    if (shdr->sh_offset < phdr->p_offset + phdr->p_filesz
+			&& !is_debuginfo)
+		      {
+			if (!gnuld)
+			  ERROR (_("\
+section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d\n"),
+				 cnt, section_name (ebl, cnt), pcnt);
+			else
+			  {
+			    /* This is truly horrible. GNU ld might put a
+			       NOBITS section in the middle of a PT_LOAD
+			       segment, assuming the next gap in the file
+			       actually consists of zero bits...
+			       So it really is like a PROGBITS section
+			       where the data is all zeros.  Check those
+			       zero bytes are really there.  */
+			    bool bad;
+			    Elf_Data *databits;
+			    databits = elf_getdata_rawchunk (ebl->elf,
+							     shdr->sh_offset,
+							     shdr->sh_size,
+							     ELF_T_BYTE);
+			    bad = (databits == NULL
+				   || databits->d_size != shdr->sh_size);
+			    for (size_t idx = 0;
+				 ! bad && idx < databits->d_size;
+				 idx++)
+			      bad = ((char *) databits->d_buf)[idx] != 0;
+
+			    if (bad)
+			      ERROR (_("\
+section [%2zu] '%s' has type NOBITS but is read from the file in segment of program header entry %d and file contents is non-zero\n"),
+				     cnt, section_name (ebl, cnt), pcnt);
+			  }
+		      }
+		  }
+		else
+		  {
+		    const GElf_Off end = phdr->p_offset + phdr->p_filesz;
+		    if (shdr->sh_offset > end ||
+			(shdr->sh_offset == end && shdr->sh_size != 0))
+		      ERROR (_("\
+section [%2zu] '%s' has not type NOBITS but is not read from the file in segment of program header entry %d\n"),
+			 cnt, section_name (ebl, cnt), pcnt);
+		  }
+
+		if (shdr->sh_type != SHT_NOBITS)
+		  {
+		    if ((shdr->sh_flags & SHF_EXECINSTR) != 0)
+		      {
+			segment_flags[pcnt] |= PF_X;
+			if ((phdr->p_flags & PF_X) == 0)
+			  ERROR (_("\
+section [%2zu] '%s' is executable in nonexecutable segment %d\n"),
+				 cnt, section_name (ebl, cnt), pcnt);
+		      }
+
+		    if ((shdr->sh_flags & SHF_WRITE) != 0)
+		      {
+			segment_flags[pcnt] |= PF_W;
+			if (0	/* XXX vdso images have this */
+			    && (phdr->p_flags & PF_W) == 0)
+			  ERROR (_("\
+section [%2zu] '%s' is writable in unwritable segment %d\n"),
+				 cnt, section_name (ebl, cnt), pcnt);
+		      }
+		  }
+
+		break;
+	      }
+
+	  if (pcnt == phnum)
+	    ERROR (_("\
+section [%2zu] '%s': alloc flag set but section not in any loaded segment\n"),
+		   cnt, section_name (ebl, cnt));
+	}
+
+      if (cnt == shstrndx && shdr->sh_type != SHT_STRTAB)
+	ERROR (_("\
+section [%2zu] '%s': ELF header says this is the section header string table but type is not SHT_TYPE\n"),
+	       cnt, section_name (ebl, cnt));
+
+      switch (shdr->sh_type)
+	{
+	case SHT_DYNSYM:
+	  if (ehdr->e_type == ET_REL)
+	    ERROR (_("\
+section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
+		   cnt, section_name (ebl, cnt));
+	  FALLTHROUGH;
+	case SHT_SYMTAB:
+	  check_symtab (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_RELA:
+	  check_rela (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_REL:
+	  check_rel (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_RELR:
+	  check_relr (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_DYNAMIC:
+	  check_dynamic (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_SYMTAB_SHNDX:
+	  check_symtab_shndx (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_HASH:
+	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
+	  hash_idx = cnt;
+	  break;
+
+	case SHT_GNU_HASH:
+	  check_hash (shdr->sh_type, ebl, ehdr, shdr, cnt);
+	  gnu_hash_idx = cnt;
+	  break;
+
+	case SHT_NULL:
+	  check_null (ebl, shdr, cnt);
+	  break;
+
+	case SHT_GROUP:
+	  check_group (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_NOTE:
+	  check_note_section (ebl, ehdr, shdr, cnt);
+	  break;
+
+	case SHT_GNU_versym:
+	  /* We cannot process this section now since we have no guarantee
+	     that the verneed and verdef sections have already been read.
+	     Just remember the section index.  */
+	  if (versym_scnndx != 0)
+	    ERROR (_("more than one version symbol table present\n"));
+	  versym_scnndx = cnt;
+	  break;
+
+	case SHT_GNU_verneed:
+	  check_verneed (ebl, shdr, cnt);
+	  break;
+
+	case SHT_GNU_verdef:
+	  check_verdef (ebl, shdr, cnt);
+	  break;
+
+	case SHT_GNU_ATTRIBUTES:
+	  check_attributes (ebl, ehdr, shdr, cnt);
+	  break;
+
+	default:
+	  /* Nothing.  */
+	  break;
+	}
+    }
+
+  if (has_interp_segment && !dot_interp_section)
+    ERROR (_("INTERP program header entry but no .interp section\n"));
+
+  if (!is_debuginfo)
+    for (unsigned int pcnt = 0; pcnt < phnum; ++pcnt)
+      {
+	GElf_Phdr phdr_mem;
+	GElf_Phdr *phdr = gelf_getphdr (ebl->elf, pcnt, &phdr_mem);
+	if (phdr != NULL && (phdr->p_type == PT_LOAD || phdr->p_type == PT_TLS))
+	  {
+	    if ((phdr->p_flags & PF_X) != 0
+		&& (segment_flags[pcnt] & PF_X) == 0)
+	      ERROR (_("\
+loadable segment [%u] is executable but contains no executable sections\n"),
+		     pcnt);
+
+	    if ((phdr->p_flags & PF_W) != 0
+		&& (segment_flags[pcnt] & PF_W) == 0)
+	      ERROR (_("\
+loadable segment [%u] is writable but contains no writable sections\n"),
+		     pcnt);
+	  }
+      }
+
+  free (segment_flags);
+
+  if (version_namelist != NULL)
+    {
+      if (versym_scnndx == 0)
+    ERROR (_("\
+no .gnu.versym section present but .gnu.versym_d or .gnu.versym_r section exist\n"));
+      else
+	check_versym (ebl, versym_scnndx);
+
+      /* Check for duplicate index numbers.  */
+      do
+	{
+	  struct version_namelist *runp = version_namelist->next;
+	  while (runp != NULL)
+	    {
+	      if (version_namelist->ndx == runp->ndx)
+		{
+		  ERROR (_("duplicate version index %d\n"),
+			 (int) version_namelist->ndx);
+		  break;
+		}
+	      runp = runp->next;
+	    }
+
+	  struct version_namelist *old = version_namelist;
+	  version_namelist = version_namelist->next;
+	  free (old);
+	}
+      while (version_namelist != NULL);
+    }
+  else if (versym_scnndx != 0)
+    ERROR (_("\
+.gnu.versym section present without .gnu.versym_d or .gnu.versym_r\n"));
+
+  if (hash_idx != 0 && gnu_hash_idx != 0)
+    compare_hash_gnu_hash (ebl, ehdr, hash_idx, gnu_hash_idx);
+
+  free (scnref);
+}
+
+
+static GElf_Off
+check_note_data (Ebl *ebl, const GElf_Ehdr *ehdr,
+		 Elf_Data *data, int shndx, int phndx, GElf_Off start)
+{
+  size_t offset = 0;
+  size_t last_offset = 0;
+  GElf_Nhdr nhdr;
+  size_t name_offset;
+  size_t desc_offset;
+  while (offset < data->d_size
+	 && (offset = gelf_getnote (data, offset,
+				    &nhdr, &name_offset, &desc_offset)) > 0)
+    {
+      last_offset = offset;
+
+      /* Make sure it is one of the note types we know about.  */
+      if (ehdr->e_type == ET_CORE)
+	switch (nhdr.n_type)
+	  {
+	  case NT_PRSTATUS:
+	  case NT_FPREGSET:
+	  case NT_PRPSINFO:
+	  case NT_TASKSTRUCT:		/* NT_PRXREG on Solaris.  */
+	  case NT_PLATFORM:
+	  case NT_AUXV:
+	  case NT_GWINDOWS:
+	  case NT_ASRS:
+	  case NT_PSTATUS:
+	  case NT_PSINFO:
+	  case NT_PRCRED:
+	  case NT_UTSNAME:
+	  case NT_LWPSTATUS:
+	  case NT_LWPSINFO:
+	  case NT_PRFPXREG:
+	    /* Known type.  */
+	    break;
+
+	  default:
+	    if (shndx == 0)
+	      ERROR (_("\
+phdr[%d]: unknown core file note type %" PRIu32 " at offset %" PRIu64 "\n"),
+		     phndx, (uint32_t) nhdr.n_type, start + offset);
+	    else
+	      ERROR (_("\
+section [%2d] '%s': unknown core file note type %" PRIu32
+			      " at offset %zu\n"),
+		     shndx, section_name (ebl, shndx),
+		     (uint32_t) nhdr.n_type, offset);
+	  }
+      else
+	switch (nhdr.n_type)
+	  {
+	  case NT_GNU_ABI_TAG:
+	  case NT_GNU_HWCAP:
+	  case NT_GNU_BUILD_ID:
+	  case NT_GNU_GOLD_VERSION:
+	  case NT_GNU_PROPERTY_TYPE_0:
+	    if (nhdr.n_namesz == sizeof ELF_NOTE_GNU
+		&& strcmp (data->d_buf + name_offset, ELF_NOTE_GNU) == 0)
+	      break;
+	    else
+	      {
+		/* NT_VERSION is 1, same as NT_GNU_ABI_TAG.  It has no
+		   descriptor and (ab)uses the name as version string.  */
+		if (nhdr.n_descsz == 0 && nhdr.n_type == NT_VERSION)
+		  break;
+	      }
+	      goto unknown_note;
+
+	  case NT_GNU_BUILD_ATTRIBUTE_OPEN:
+	  case NT_GNU_BUILD_ATTRIBUTE_FUNC:
+	    /* GNU Build Attributes store most data in the owner
+	       name, which must start with the
+	       ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX "GA".  */
+	    if (nhdr.n_namesz >= sizeof ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX
+		&& strncmp (data->d_buf + name_offset,
+			    ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
+			    strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0)
+	      break;
+	    else
+	      goto unknown_note;
+
+	  case NT_FDO_PACKAGING_METADATA:
+	    if (nhdr.n_namesz == sizeof ELF_NOTE_FDO
+		&& strcmp (data->d_buf + name_offset, ELF_NOTE_FDO) == 0)
+	      break;
+	    else
+	      goto unknown_note;
+
+	  case 0:
+	    /* Linux vDSOs use a type 0 note for the kernel version word.  */
+	    if (nhdr.n_namesz == sizeof "Linux"
+		&& !memcmp (data->d_buf + name_offset, "Linux", sizeof "Linux"))
+	      break;
+	    FALLTHROUGH;
+	  default:
+	    {
+	    unknown_note:
+	    if (shndx == 0)
+	      ERROR (_("\
+phdr[%d]: unknown object file note type %" PRIu32 " with owner name '%s' at offset %zu\n"),
+		     phndx, (uint32_t) nhdr.n_type,
+		     (char *) data->d_buf + name_offset, offset);
+	    else
+	      ERROR (_("\
+section [%2d] '%s': unknown object file note type %" PRIu32
+			      " with owner name '%s' at offset %zu\n"),
+		     shndx, section_name (ebl, shndx),
+		     (uint32_t) nhdr.n_type,
+		     (char *) data->d_buf + name_offset, offset);
+	    }
+	  }
+    }
+
+  return last_offset;
+}
+
+
+static void
+check_note (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Phdr *phdr, int cnt)
+{
+  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
+      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+    ERROR (_("\
+phdr[%d]: no note entries defined for the type of file\n"),
+	   cnt);
+
+  if (is_debuginfo)
+    /* The p_offset values in a separate debug file are bogus.  */
+    return;
+
+  if (phdr->p_filesz == 0)
+    return;
+
+  GElf_Off notes_size = 0;
+  Elf_Data *data = elf_getdata_rawchunk (ebl->elf,
+					 phdr->p_offset, phdr->p_filesz,
+					 (phdr->p_align == 8
+					  ? ELF_T_NHDR8 : ELF_T_NHDR));
+  if (data != NULL && data->d_buf != NULL)
+    notes_size = check_note_data (ebl, ehdr, data, 0, cnt, phdr->p_offset);
+
+  if (notes_size == 0)
+    ERROR (_("phdr[%d]: cannot get content of note section: %s\n"),
+	   cnt, elf_errmsg (-1));
+  else if (notes_size != phdr->p_filesz)
+    ERROR (_("phdr[%d]: extra %" PRIu64 " bytes after last note\n"),
+	   cnt, phdr->p_filesz - notes_size);
+}
+
+
+static void
+check_note_section (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
+{
+  if (shdr->sh_size == 0)
+    return;
+
+  Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
+  if (data == NULL || data->d_buf == NULL)
+    {
+      ERROR (_("section [%2d] '%s': cannot get section data\n"),
+	     idx, section_name (ebl, idx));
+      return;
+    }
+
+  if (ehdr->e_type != ET_CORE && ehdr->e_type != ET_REL
+      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+    ERROR (_("\
+section [%2d] '%s': no note entries defined for the type of file\n"),
+	     idx, section_name (ebl, idx));
+
+  GElf_Off notes_size = check_note_data (ebl, ehdr, data, idx, 0, 0);
+
+  if (notes_size == 0)
+    ERROR (_("section [%2d] '%s': cannot get content of note section\n"),
+	   idx, section_name (ebl, idx));
+  else if (notes_size != shdr->sh_size)
+    ERROR (_("section [%2d] '%s': extra %" PRIu64
+		    " bytes after last note\n"),
+	   idx, section_name (ebl, idx), shdr->sh_size - notes_size);
+}
+
+
+/* Index of the PT_GNU_EH_FRAME program eader entry.  */
+static int pt_gnu_eh_frame_pndx;
+
+
+static void
+check_program_header (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  if (ehdr->e_phoff == 0)
+    return;
+
+  if (ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN
+      && ehdr->e_type != ET_CORE)
+    ERROR (_("\
+only executables, shared objects, and core files can have program headers\n"));
+
+  int num_pt_interp = 0;
+  int num_pt_tls = 0;
+  int num_pt_relro = 0;
+
+  for (unsigned int cnt = 0; cnt < phnum; ++cnt)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr;
+
+      phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
+      if (phdr == NULL)
+	{
+	  ERROR (_("cannot get program header entry %d: %s\n"),
+		 cnt, elf_errmsg (-1));
+	  continue;
+	}
+
+      if (phdr->p_type >= PT_NUM && phdr->p_type != PT_GNU_EH_FRAME
+	  && phdr->p_type != PT_GNU_STACK && phdr->p_type != PT_GNU_RELRO
+	  && phdr->p_type != PT_GNU_PROPERTY
+	  /* Check for a known machine-specific type.  */
+	  && ebl_segment_type_name (ebl, phdr->p_type, NULL, 0) == NULL)
+	ERROR (_("\
+program header entry %d: unknown program header entry type %#" PRIx64 "\n"),
+	       cnt, (uint64_t) phdr->p_type);
+
+      if (phdr->p_type == PT_LOAD)
+	has_loadable_segment = true;
+      else if (phdr->p_type == PT_INTERP)
+	{
+	  if (++num_pt_interp != 1)
+	    {
+	      if (num_pt_interp == 2)
+		ERROR (_("\
+more than one INTERP entry in program header\n"));
+	    }
+	  has_interp_segment = true;
+	}
+      else if (phdr->p_type == PT_TLS)
+	{
+	  if (++num_pt_tls == 2)
+	    ERROR (_("more than one TLS entry in program header\n"));
+	}
+      else if (phdr->p_type == PT_NOTE)
+	check_note (ebl, ehdr, phdr, cnt);
+      else if (phdr->p_type == PT_DYNAMIC)
+	{
+	  if (ehdr->e_type == ET_EXEC && ! has_interp_segment)
+	    ERROR (_("\
+static executable cannot have dynamic sections\n"));
+	  else
+	    {
+	      /* Check that the .dynamic section, if it exists, has
+		 the same address.  */
+	      Elf_Scn *scn = NULL;
+	      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+		{
+		  GElf_Shdr shdr_mem;
+		  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+		  if (shdr != NULL && shdr->sh_type == SHT_DYNAMIC)
+		    {
+		      if (phdr->p_offset != shdr->sh_offset)
+			ERROR (_("\
+dynamic section reference in program header has wrong offset\n"));
+		      if (phdr->p_memsz != shdr->sh_size)
+			ERROR (_("\
+dynamic section size mismatch in program and section header\n"));
+		      break;
+		    }
+		}
+	    }
+	}
+      else if (phdr->p_type == PT_GNU_RELRO)
+	{
+	  if (++num_pt_relro == 2)
+	    ERROR (_("\
+more than one GNU_RELRO entry in program header\n"));
+	  else
+	    {
+	      /* Check that the region is in a writable segment.  */
+	      unsigned int inner;
+	      for (inner = 0; inner < phnum; ++inner)
+		{
+		  GElf_Phdr phdr2_mem;
+		  GElf_Phdr *phdr2;
+
+		  phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
+		  if (phdr2 == NULL)
+		    continue;
+
+		  if (phdr2->p_type == PT_LOAD
+		      && phdr->p_vaddr >= phdr2->p_vaddr
+		      && (phdr->p_vaddr + phdr->p_memsz
+			  <= phdr2->p_vaddr + phdr2->p_memsz))
+		    {
+		      if ((phdr2->p_flags & PF_W) == 0)
+			ERROR (_("\
+loadable segment GNU_RELRO applies to is not writable\n"));
+		      /* Unless fully covered, relro flags could be a
+			 subset of the phdrs2 flags.  For example the load
+			 segment could also have PF_X set.  */
+		      if (phdr->p_vaddr == phdr2->p_vaddr
+			  && (phdr->p_vaddr + phdr->p_memsz
+			      == phdr2->p_vaddr + phdr2->p_memsz))
+			{
+			  if ((phdr2->p_flags & ~PF_W)
+			      != (phdr->p_flags & ~PF_W))
+			    ERROR (_("\
+loadable segment [%u] flags do not match GNU_RELRO [%u] flags\n"),
+				   cnt, inner);
+			}
+		      else
+			{
+			  if ((phdr->p_flags & ~phdr2->p_flags) != 0)
+			    ERROR (_("\
+GNU_RELRO [%u] flags are not a subset of the loadable segment [%u] flags\n"),
+				   inner, cnt);
+			}
+		      break;
+		    }
+		}
+
+	      if (inner >= phnum)
+		ERROR (_("\
+%s segment not contained in a loaded segment\n"), "GNU_RELRO");
+	    }
+	}
+      else if (phdr->p_type == PT_PHDR)
+	{
+	  /* Check that the region is in a writable segment.  */
+	  unsigned int inner;
+	  for (inner = 0; inner < phnum; ++inner)
+	    {
+	      GElf_Phdr phdr2_mem;
+	      GElf_Phdr *phdr2;
+
+	      phdr2 = gelf_getphdr (ebl->elf, inner, &phdr2_mem);
+	      if (phdr2 != NULL
+		  && phdr2->p_type == PT_LOAD
+		  && phdr->p_vaddr >= phdr2->p_vaddr
+		  && (phdr->p_vaddr + phdr->p_memsz
+		      <= phdr2->p_vaddr + phdr2->p_memsz))
+		break;
+	    }
+
+	  if (inner >= phnum)
+	    ERROR (_("\
+%s segment not contained in a loaded segment\n"), "PHDR");
+
+	  /* Check that offset in segment corresponds to offset in ELF
+	     header.  */
+	  if (phdr->p_offset != ehdr->e_phoff)
+	    ERROR (_("\
+program header offset in ELF header and PHDR entry do not match"));
+	}
+      else if (phdr->p_type == PT_GNU_EH_FRAME)
+	{
+	  /* If there is an .eh_frame_hdr section it must be
+	     referenced by this program header entry.  */
+	  Elf_Scn *scn = NULL;
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = NULL;
+	  bool any = false;
+	  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	    {
+	      any = true;
+	      shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (shdr != NULL
+		  && ((is_debuginfo && shdr->sh_type == SHT_NOBITS)
+		      || (! is_debuginfo
+			  && (shdr->sh_type == SHT_PROGBITS
+			      || shdr->sh_type == SHT_X86_64_UNWIND)))
+		  && elf_strptr (ebl->elf, shstrndx, shdr->sh_name) != NULL
+		  && ! strcmp (".eh_frame_hdr",
+			       elf_strptr (ebl->elf, shstrndx, shdr->sh_name)))
+		{
+		  if (! is_debuginfo)
+		    {
+		      if (phdr->p_offset != shdr->sh_offset)
+			ERROR (_("\
+call frame search table reference in program header has wrong offset\n"));
+		      if (phdr->p_memsz != shdr->sh_size)
+			ERROR (_("\
+call frame search table size mismatch in program and section header\n"));
+		    }
+		  break;
+		}
+	    }
+
+	  if (scn == NULL)
+	    {
+	      /* If there is no section header table we don't
+		 complain.  But if there is one there should be an
+		 entry for .eh_frame_hdr.  */
+	      if (any)
+		ERROR (_("\
+PT_GNU_EH_FRAME present but no .eh_frame_hdr section\n"));
+	    }
+	  else
+	    {
+	      /* The section must be allocated and not be writable and
+		 executable.  */
+	      if ((phdr->p_flags & PF_R) == 0)
+		ERROR (_("\
+call frame search table must be allocated\n"));
+	      else if (shdr != NULL && (shdr->sh_flags & SHF_ALLOC) == 0)
+		ERROR (_("\
+section [%2zu] '%s' must be allocated\n"), elf_ndxscn (scn), ".eh_frame_hdr");
+
+	      if ((phdr->p_flags & PF_W) != 0)
+		ERROR (_("\
+call frame search table must not be writable\n"));
+	      else if (shdr != NULL && (shdr->sh_flags & SHF_WRITE) != 0)
+		ERROR (_("\
+section [%2zu] '%s' must not be writable\n"),
+		       elf_ndxscn (scn), ".eh_frame_hdr");
+
+	      if ((phdr->p_flags & PF_X) != 0)
+		ERROR (_("\
+call frame search table must not be executable\n"));
+	      else if (shdr != NULL && (shdr->sh_flags & SHF_EXECINSTR) != 0)
+		ERROR (_("\
+section [%2zu] '%s' must not be executable\n"),
+		       elf_ndxscn (scn), ".eh_frame_hdr");
+	    }
+
+	  /* Remember which entry this is.  */
+	  pt_gnu_eh_frame_pndx = cnt;
+	}
+
+      if (phdr->p_filesz > phdr->p_memsz
+	  && (phdr->p_memsz != 0
+	      || (phdr->p_type != PT_NOTE
+		  && !(ehdr->e_machine == EM_RISCV
+		       && phdr->p_type == PT_RISCV_ATTRIBUTES))))
+	ERROR (_("\
+program header entry %d: file size greater than memory size\n"),
+	       cnt);
+
+      if (phdr->p_align > 1)
+	{
+	  if (!powerof2 (phdr->p_align))
+	    ERROR (_("\
+program header entry %d: alignment not a power of 2\n"), cnt);
+	  else if ((phdr->p_vaddr - phdr->p_offset) % phdr->p_align != 0)
+	    ERROR (_("\
+program header entry %d: file offset and virtual address not module of alignment\n"), cnt);
+	}
+    }
+}
+
+
+static void
+check_exception_data (Ebl *ebl __attribute__ ((unused)),
+		      GElf_Ehdr *ehdr __attribute__ ((unused)))
+{
+  if ((ehdr->e_type == ET_EXEC || ehdr->e_type == ET_DYN)
+      && pt_gnu_eh_frame_pndx == 0 && eh_frame_hdr_scnndx != 0)
+    ERROR (_("executable/DSO with .eh_frame_hdr section does not have "
+		    "a PT_GNU_EH_FRAME program header entry"));
+}
+
+
+/* Process one file.  */
+static void
+process_elf_file (Elf *elf, const char *prefix, const char *suffix,
+		  const char *fname, size_t size, bool only_one)
+{
+  /* Reset variables.  */
+  ndynamic = 0;
+  nverneed = 0;
+  nverdef = 0;
+  textrel = false;
+  needed_textrel = false;
+  has_loadable_segment = false;
+  has_interp_segment = false;
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  Ebl *ebl;
+
+  /* Print the file name.  */
+  if (!only_one)
+    {
+      if (prefix != NULL)
+	printf ("\n%s(%s)%s:\n", prefix, fname, suffix);
+      else
+	printf ("\n%s:\n", fname);
+    }
+
+  if (ehdr == NULL)
+    {
+      ERROR (_("cannot read ELF header: %s\n"), elf_errmsg (-1));
+      return;
+    }
+
+  ebl = ebl_openbackend (elf);
+  /* If there is no appropriate backend library we cannot test
+     architecture and OS specific features.  Any encountered extension
+     is an error.  Often we'll get a "dummy" ebl, except if something
+     really bad happen, like a totally corrupted ELF file or out of
+     memory situation.  */
+  if (ebl == NULL)
+    {
+      ERROR (_("cannot create backend for ELF file\n"));
+      return;
+    }
+
+  /* Go straight by the gABI, check all the parts in turn.  */
+  check_elf_header (ebl, ehdr, size);
+
+  /* Check the program header.  */
+  check_program_header (ebl, ehdr);
+
+  /* Next the section headers.  It is OK if there are no section
+     headers at all.  */
+  check_sections (ebl, ehdr);
+
+  /* Check the exception handling data, if it exists.  */
+  if (pt_gnu_eh_frame_pndx != 0 || eh_frame_hdr_scnndx != 0
+      || eh_frame_scnndx != 0 || gcc_except_table_scnndx != 0)
+    check_exception_data (ebl, ehdr);
+
+  /* Report if no relocation section needed the text relocation flag.  */
+  if (textrel && !needed_textrel)
+    ERROR (_("text relocation flag set but not needed\n"));
+
+  /* Free the resources.  */
+  ebl_closebackend (ebl);
+}
+
+
+#include "debugpred.h"
diff --git a/src/findtextrel.c b/src/findtextrel.c
new file mode 100644
index 0000000..d3021a3
--- /dev/null
+++ b/src/findtextrel.c
@@ -0,0 +1,603 @@
+/* Locate source files or functions which caused text relocations.
+   Copyright (C) 2005-2010, 2012, 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libdw.h>
+#include <locale.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <printversion.h>
+#include "libeu.h"
+#include "system.h"
+
+struct segments
+{
+  GElf_Addr from;
+  GElf_Addr to;
+};
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Values for the parameters which have no short form.  */
+#define OPT_DEBUGINFO 0x100
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Input Selection:"), 0 },
+  { "root", 'r', "PATH", 0, N_("Prepend PATH to all file names"), 0 },
+  { "debuginfo", OPT_DEBUGINFO, "PATH", 0,
+    N_("Use PATH as root of debuginfo hierarchy"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Locate source of text relocations in FILEs (a.out by default).");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+
+/* Print symbols in file named FNAME.  */
+static int process_file (const char *fname, bool more_than_one);
+
+/* Check for text relocations in the given file.  The segment
+   information is known.  */
+static void check_rel (size_t nsegments, struct segments segments[nsegments],
+		       GElf_Addr addr, Elf *elf, Elf_Scn *symscn, Dwarf *dw,
+		       const char *fname, bool more_than_one,
+		       void **knownsrcs);
+
+
+
+/* User-provided root directory.  */
+static const char *rootdir = "/";
+
+/* Root of debuginfo directory hierarchy.  */
+static const char *debuginfo_root;
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+  int result = 0;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Tell the library which version we are expecting.  */
+  elf_version (EV_CURRENT);
+
+  /* If the user has not specified the root directory for the
+     debuginfo hierarchy, we have to determine it ourselves.  */
+  if (debuginfo_root == NULL)
+    {
+      // XXX The runtime should provide this information.
+#if defined __ia64__ || defined __alpha__
+      debuginfo_root = "/usr/lib/debug";
+#else
+      debuginfo_root = (sizeof (long int) == 4
+			? "/usr/lib/debug" : "/usr/lib64/debug");
+#endif
+    }
+
+  if (remaining == argc)
+    result = process_file ("a.out", false);
+  else
+    {
+      /* Process all the remaining files.  */
+      const bool more_than_one = remaining + 1 < argc;
+
+      do
+	result |= process_file (argv[remaining], more_than_one);
+      while (++remaining < argc);
+    }
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'r':
+      rootdir = arg;
+      break;
+
+    case OPT_DEBUGINFO:
+      debuginfo_root = arg;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+static void
+noop (void *arg __attribute__ ((unused)))
+{
+}
+
+
+static int
+open_rootdir_file (const char *fname)
+{
+  char *new_fname = NULL;
+  const char *real_fname = fname;
+
+  if (fname[0] == '/' && (rootdir[0] != '/' || rootdir[1] != '\0'))
+    real_fname = new_fname = xasprintf ("%s/%s", rootdir, fname);
+
+  int fd = open (real_fname, O_RDONLY);
+  if (fd == -1)
+    error (0, errno, _("cannot open '%s'"), fname);
+
+  free (new_fname);
+  return fd;
+}
+
+
+static int
+process_file (const char *fname, bool more_than_one)
+{
+  int result = 0;
+  void *knownsrcs = NULL;
+  int fd = open_rootdir_file (fname);
+  if (fd == -1)
+    return 1;
+
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    {
+      error (0, 0, _("cannot create ELF descriptor for '%s': %s"),
+	     fname, elf_errmsg (-1));
+      goto err_close;
+    }
+
+  /* Make sure the file is a DSO.  */
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      error (0, 0, _("cannot get ELF header '%s': %s"),
+	     fname, elf_errmsg (-1));
+    err_elf_close:
+      elf_end (elf);
+    err_close:
+      close (fd);
+      return 1;
+    }
+
+  if (ehdr->e_type != ET_DYN)
+    {
+      error (0, 0, _("'%s' is not a DSO or PIE"), fname);
+      goto err_elf_close;
+    }
+
+  /* Determine whether the DSO has text relocations at all and locate
+     the symbol table.  */
+  Elf_Scn *symscn = NULL;
+  Elf_Scn *scn = NULL;
+  bool seen_dynamic = false;
+  bool have_textrel = false;
+  while ((scn = elf_nextscn (elf, scn)) != NULL
+	 && (!seen_dynamic || symscn == NULL))
+    {
+      /* Handle the section if it is a symbol table.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	{
+	  error (0, 0,
+		 _("getting get section header of section %zu: %s"),
+		 elf_ndxscn (scn), elf_errmsg (-1));
+	  goto err_elf_close;
+	}
+
+      switch (shdr->sh_type)
+	{
+	case SHT_DYNAMIC:
+	  if (!seen_dynamic)
+	    {
+	      seen_dynamic = true;
+
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      size_t entries = (shdr->sh_entsize == 0
+				? 0 : shdr->sh_size / shdr->sh_entsize);
+
+	      for (size_t cnt = 0; cnt < entries; ++cnt)
+		{
+		  GElf_Dyn dynmem;
+		  GElf_Dyn *dyn;
+
+		  dyn = gelf_getdyn (data, cnt, &dynmem);
+		  if (dyn == NULL)
+		    {
+		      error (0, 0, _("cannot read dynamic section: %s"),
+			     elf_errmsg (-1));
+		      goto err_elf_close;
+		    }
+
+		  if (dyn->d_tag == DT_TEXTREL
+		      || (dyn->d_tag == DT_FLAGS
+			  && (dyn->d_un.d_val & DF_TEXTREL) != 0))
+		    have_textrel = true;
+		}
+	    }
+	  break;
+
+	case SHT_SYMTAB:
+	  symscn = scn;
+	  break;
+	}
+    }
+
+  if (!have_textrel)
+    {
+      error (0, 0, _("no text relocations reported in '%s'"), fname);
+      goto err_elf_close;
+    }
+
+  int fd2 = -1;
+  Elf *elf2 = NULL;
+  /* Get the address ranges for the loaded segments.  */
+  size_t nsegments_max = 10;
+  size_t nsegments = 0;
+  struct segments *segments = malloc (nsegments_max * sizeof (segments[0]));
+  if (segments == NULL)
+    error (1, errno, _("while reading ELF file"));
+
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    error (1, 0, _("cannot get program header count: %s"),
+           elf_errmsg (-1));
+
+
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, i, &phdr_mem);
+      if (phdr == NULL)
+	{
+	  error (0, 0,
+		 _("cannot get program header index at offset %zd: %s"),
+		 i, elf_errmsg (-1));
+	  result = 1;
+	  goto next;
+	}
+
+      if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
+	{
+	  if (nsegments == nsegments_max)
+	    {
+	      nsegments_max *= 2;
+	      segments
+		= realloc (segments, nsegments_max * sizeof (segments[0]));
+	      if (segments == NULL)
+		{
+		  error (0, 0, _("\
+cannot get program header index at offset %zd: %s"),
+			 i, elf_errmsg (-1));
+		  result = 1;
+		  goto next;
+		}
+	    }
+
+	  segments[nsegments].from = phdr->p_vaddr;
+	  segments[nsegments].to = phdr->p_vaddr + phdr->p_memsz;
+	  ++nsegments;
+	}
+    }
+
+  if (nsegments > 0)
+    {
+
+      Dwarf *dw = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
+      /* Look for debuginfo files if the information is not the in
+	 opened file itself.  This makes only sense if the input file
+	 is specified with an absolute path.  */
+      if (dw == NULL && fname[0] == '/')
+	{
+	  char *difname =
+	    xasprintf("%s%s/%s.debug", rootdir, debuginfo_root, fname);
+	  fd2 = open (difname, O_RDONLY);
+	  free (difname);
+	  if (fd2 != -1
+	      && (elf2 = elf_begin (fd2, ELF_C_READ_MMAP, NULL)) != NULL)
+	    dw = dwarf_begin_elf (elf2, DWARF_C_READ, NULL);
+	}
+
+      /* Look at all relocations and determine which modify
+	 write-protected segments.  */
+      scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  /* Handle the section if it is a symbol table.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+	  if (shdr == NULL)
+	    {
+	      error (0, 0,
+		     _("cannot get section header of section %zu: %s"),
+		     elf_ndxscn (scn), elf_errmsg (-1));
+	      result = 1;
+	      goto next;
+	    }
+
+	  if ((shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+	      && symscn == NULL)
+	    {
+	      symscn = elf_getscn (elf, shdr->sh_link);
+	      if (symscn == NULL)
+		{
+		  error (0, 0, _("\
+cannot get symbol table section %zu in '%s': %s"),
+			 (size_t) shdr->sh_link, fname, elf_errmsg (-1));
+		  result = 1;
+		  goto next;
+		}
+	    }
+
+	  if (shdr->sh_type == SHT_REL)
+	    {
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      size_t entries = (shdr->sh_entsize == 0
+				? 0 : shdr->sh_size / shdr->sh_entsize);
+
+	      for (int cnt = 0;
+		   (size_t) cnt < entries; ++cnt)
+		{
+		  GElf_Rel rel_mem;
+		  GElf_Rel *rel = gelf_getrel (data, cnt, &rel_mem);
+		  if (rel == NULL)
+		    {
+		      error (0, 0, _("\
+cannot get relocation at index %d in section %zu in '%s': %s"),
+			     cnt, elf_ndxscn (scn), fname, elf_errmsg (-1));
+		      result = 1;
+		      goto next;
+		    }
+
+		  check_rel (nsegments, segments, rel->r_offset, elf,
+			     symscn, dw, fname, more_than_one, &knownsrcs);
+		}
+	    }
+	  else if (shdr->sh_type == SHT_RELA)
+	    {
+	      Elf_Data *data = elf_getdata (scn, NULL);
+	      size_t entries = (shdr->sh_entsize == 0
+				? 0 : shdr->sh_size / shdr->sh_entsize);
+
+	      for (int cnt = 0; (size_t) cnt < entries; ++cnt)
+		{
+		  GElf_Rela rela_mem;
+		  GElf_Rela *rela = gelf_getrela (data, cnt, &rela_mem);
+		  if (rela == NULL)
+		    {
+		      error (0, 0, _("\
+cannot get relocation at index %d in section %zu in '%s': %s"),
+			     cnt, elf_ndxscn (scn), fname, elf_errmsg (-1));
+		      result = 1;
+		      goto next;
+		    }
+
+		  check_rel (nsegments, segments, rela->r_offset, elf,
+			     symscn, dw, fname, more_than_one, &knownsrcs);
+		}
+	    }
+	}
+
+      dwarf_end (dw);
+    }
+
+ next:
+  elf_end (elf);
+  elf_end (elf2);
+  close (fd);
+  if (fd2 != -1)
+    close (fd2);
+
+  free (segments);
+  tdestroy (knownsrcs, noop);
+
+  return result;
+}
+
+
+static int
+ptrcompare (const void *p1, const void *p2)
+{
+  if ((uintptr_t) p1 < (uintptr_t) p2)
+    return -1;
+  if ((uintptr_t) p1 > (uintptr_t) p2)
+    return 1;
+  return 0;
+}
+
+
+static void
+check_rel (size_t nsegments, struct segments segments[nsegments],
+	   GElf_Addr addr, Elf *elf, Elf_Scn *symscn, Dwarf *dw,
+	   const char *fname, bool more_than_one, void **knownsrcs)
+{
+  for (size_t cnt = 0; cnt < nsegments; ++cnt)
+    if (segments[cnt].from <= addr && segments[cnt].to > addr)
+      {
+	Dwarf_Die die_mem;
+	Dwarf_Die *die;
+	Dwarf_Line *line;
+	const char *src;
+
+	if (more_than_one)
+	  printf ("%s: ", fname);
+
+	if ((die = dwarf_addrdie (dw, addr, &die_mem)) != NULL
+	    && (line = dwarf_getsrc_die (die, addr)) != NULL
+	    && (src = dwarf_linesrc (line, NULL, NULL)) != NULL)
+	  {
+	    /* There can be more than one relocation against one file.
+	       Try to avoid multiple messages.  And yes, the code uses
+	       pointer comparison.  */
+	    if (tfind (src, knownsrcs, ptrcompare) == NULL)
+	      {
+		printf (_("%s not compiled with -fpic/-fPIC\n"), src);
+		tsearch (src, knownsrcs, ptrcompare);
+	      }
+	    return;
+	  }
+	else
+	  {
+	    /* At least look at the symbol table to see which function
+	       the modified address is in.  */
+	    Elf_Data *symdata = elf_getdata (symscn, NULL);
+	    GElf_Shdr shdr_mem;
+	    GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
+	    if (shdr != NULL)
+	      {
+		GElf_Addr lowaddr = 0;
+		int lowidx = -1;
+		GElf_Addr highaddr = ~0ul;
+		int highidx = -1;
+		GElf_Sym sym_mem;
+		GElf_Sym *sym;
+		size_t entries = (shdr->sh_entsize == 0
+				  ? 0 : shdr->sh_size / shdr->sh_entsize);
+
+		for (int i = 0; (size_t) i < entries; ++i)
+		  {
+		    sym = gelf_getsym (symdata, i, &sym_mem);
+		    if (sym == NULL)
+		      continue;
+
+		    if (sym->st_value < addr && sym->st_value > lowaddr)
+		      {
+			lowaddr = sym->st_value;
+			lowidx = i;
+		      }
+		    if (sym->st_value > addr && sym->st_value < highaddr)
+		      {
+			highaddr = sym->st_value;
+			highidx = i;
+		      }
+		  }
+
+		if (lowidx != -1)
+		  {
+		    sym = gelf_getsym (symdata, lowidx, &sym_mem);
+		    assert (sym != NULL);
+
+		    const char *lowstr = elf_strptr (elf, shdr->sh_link,
+						     sym->st_name);
+
+		    if (sym->st_value + sym->st_size > addr)
+		      {
+			/* It is this function.  */
+			if (tfind (lowstr, knownsrcs, ptrcompare) == NULL)
+			  {
+			    printf (_("\
+the file containing the function '%s' is not compiled with -fpic/-fPIC\n"),
+				    lowstr);
+			    tsearch (lowstr, knownsrcs, ptrcompare);
+			  }
+		      }
+		    else if (highidx == -1)
+		      printf (_("\
+the file containing the function '%s' might not be compiled with -fpic/-fPIC\n"),
+			      lowstr);
+		    else
+		      {
+			sym = gelf_getsym (symdata, highidx, &sym_mem);
+			assert (sym != NULL);
+
+			printf (_("\
+either the file containing the function '%s' or the file containing the function '%s' is not compiled with -fpic/-fPIC\n"),
+				lowstr, elf_strptr (elf, shdr->sh_link,
+						    sym->st_name));
+		      }
+		    return;
+		  }
+		else if (highidx != -1)
+		  {
+		    sym = gelf_getsym (symdata, highidx, &sym_mem);
+		    assert (sym != NULL);
+
+		    printf (_("\
+the file containing the function '%s' might not be compiled with -fpic/-fPIC\n"),
+			    elf_strptr (elf, shdr->sh_link, sym->st_name));
+		    return;
+		  }
+	      }
+	  }
+
+	printf (_("\
+a relocation modifies memory at offset %llu in a write-protected segment\n"),
+		(unsigned long long int) addr);
+	break;
+      }
+}
+
+
+#include "debugpred.h"
diff --git a/src/make-debug-archive.in b/src/make-debug-archive.in
new file mode 100644
index 0000000..c3fcbce
--- /dev/null
+++ b/src/make-debug-archive.in
@@ -0,0 +1,132 @@
+#!/bin/sh
+#
+# Script to make an offline archive for debugging with libdwfl-based tools.
+#
+#	make-debug-archive ARCHIVE {options}
+#	make-debug-archive --kernel [--force] [RELEASE]
+#
+# Valid options are those listed under 'Input selection options'
+# by running @UNSTRIP@ --help.
+#
+# The archive installed by --kernel be used automatically by -K.
+# An offline archive can be used via -e in any tool that accepts those options.
+#
+
+UNSTRIP=${UNSTRIP:-@UNSTRIP@}
+AR=${AR:-@AR@}
+SUDO=${SUDO:-/usr/bin/sudo}
+
+LS=/bin/ls
+RM=/bin/rm
+MV=/bin/mv
+MKDIR=/bin/mkdir
+XARGS=/usr/bin/xargs
+
+outdir=${TMPDIR:-/tmp}/debugar$$
+
+usage()
+{
+  echo "Usage: $0 ARCHIVE {options}"
+  echo "   or: $0 --kernel [--sudo] [--force] [RELEASE]"
+  echo
+  echo "Valid options are listed under 'Input selection options'"
+  echo "when running: $UNSTRIP --help"
+  echo
+  echo "The --kernel form updates the file used by -K if the"
+  echo "kernel installation has changed, or always with --force."
+  echo "With --sudo, touches the installed file via $SUDO."
+}
+
+fatal_usage()
+{
+  usage >&2
+  exit 2
+}
+
+script_version()
+{
+  echo "`basename $0` (@PACKAGE_NAME@) @PACKAGE_VERSION@"
+  echo "Copyright (C) 2007 Red Hat, Inc."
+  echo "This is free software; see the source for copying conditions."
+  echo "There is NO warranty; not even for MERCHANTABILITY or"
+  echo "FITNESS FOR A PARTICULAR PURPOSE."
+  echo "Written by Roland McGrath."
+}
+
+sudo=
+kernel=no
+force_kernel=no
+while [ $# -gt 0 ]; do
+  case "x$1" in
+  x--help) usage; exit 0 ;;
+  x--version) script_version; exit 0 ;;
+  x--kernel) kernel=yes ;;
+  x--force) force_kernel=yes ;;
+  x--sudo) sudo=$SUDO ;;
+  *) break ;;
+  esac
+  shift
+done
+
+if [ $kernel = no ] && [ $force_kernel = yes -o -n "$sudo" ]; then
+  usage
+fi
+
+if [ $kernel = yes ]; then
+  if [ $# -eq 0 ]; then
+    release=`uname -r`
+  elif [ $# -eq 1 ]; then
+    release=$1
+  else
+    fatal_usage
+  fi
+
+  dir=/usr/lib/debug/lib/modules/$release
+  archive=$dir/debug.a
+  dep=/lib/modules/$release/modules.dep
+
+  if [ ! -d $dir ]; then
+    echo >&2 "$0: $dir not installed"
+    exit 1
+  fi
+
+  # Without --force, bail if the kernel installation is not newer.
+  # This file is normally touched by installing new kernels or modules.
+  if [ $force_kernel = no -a "$archive" -nt "$dep" ]; then
+    exit 0
+  fi
+
+  # We have to kill the old one first, because our own -K would use it.
+  [ ! -e "$archive" ] || $sudo $RM -f "$archive" || exit
+
+  set "$archive" "-K$release"
+fi
+
+if [ $# -lt 2 ]; then
+  fatal_usage
+fi
+
+archive="$1"
+shift
+
+case "$archive" in
+/*) ;;
+*) archive="`/bin/pwd`/$archive" ;;
+esac
+
+if [ -z "$sudo" ]; then
+  new_archive="$archive.new"
+else
+  new_archive="$outdir.a"
+fi
+
+$RM -f "$new_archive" || exit
+
+trap '$RM -rf "$outdir" "$new_archive"' 0 1 2 15
+
+$MKDIR "$outdir" &&
+$UNSTRIP -d "$outdir" -m -a -R "$@" &&
+(cd "$outdir" && $LS | $XARGS $AR cq "$new_archive") &&
+$sudo $MV -f "$new_archive" "$archive"
+
+exit
diff --git a/src/nm.c b/src/nm.c
new file mode 100644
index 0000000..3675f59
--- /dev/null
+++ b/src/nm.c
@@ -0,0 +1,1629 @@
+/* Print symbol information from ELF file in human-readable form.
+   Copyright (C) 2000-2008, 2009, 2011, 2012, 2014, 2015, 2020 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ar.h>
+#include <argp.h>
+#include <assert.h>
+#include <ctype.h>
+#include <dwarf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <libdw.h>
+#include <locale.h>
+#include <obstack.h>
+#include <search.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libeu.h>
+#include <system.h>
+#include <color.h>
+#include <printversion.h>
+#include "../libebl/libeblP.h"
+#include "../libdwfl/libdwflP.h"
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Values for the parameters which have no short form.  */
+#define OPT_DEFINED		0x100
+#define OPT_MARK_SPECIAL	0x101
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
+  { "debug-syms", 'a', NULL, 0, N_("Display debugger-only symbols"), 0 },
+  { "defined-only", OPT_DEFINED, NULL, 0, N_("Display only defined symbols"),
+    0 },
+  { "dynamic", 'D', NULL, 0,
+    N_("Display dynamic symbols instead of normal symbols"), 0 },
+  { "extern-only", 'g', NULL, 0, N_("Display only external symbols"), 0 },
+  { "undefined-only", 'u', NULL, 0, N_("Display only undefined symbols"), 0 },
+  { "print-armap", 's', NULL, 0,
+    N_("Include index for symbols from archive members"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output format:"), 0 },
+  { "print-file-name", 'A', NULL, 0,
+    N_("Print name of the input file before every symbol"), 0 },
+  { NULL, 'o', NULL, OPTION_HIDDEN, "Same as -A", 0 },
+  { "format", 'f', "FORMAT", 0,
+    N_("Use the output format FORMAT.  FORMAT can be `bsd', `sysv' or `posix'.  The default is `sysv'"),
+    0 },
+  { NULL, 'B', NULL, 0, N_("Same as --format=bsd"), 0 },
+  { "portability", 'P', NULL, 0, N_("Same as --format=posix"), 0 },
+  { "radix", 't', "RADIX", 0, N_("Use RADIX for printing symbol values"), 0 },
+  { "mark-special", OPT_MARK_SPECIAL, NULL, 0, N_("Mark special symbols"), 0 },
+  { "mark-weak", OPT_MARK_SPECIAL, NULL, OPTION_HIDDEN, "", 0 },
+  { "print-size", 'S', NULL, 0, N_("Print size of defined symbols"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
+  { "numeric-sort", 'n', NULL, 0, N_("Sort symbols numerically by address"),
+    0 },
+  { "no-sort", 'p', NULL, 0, N_("Do not sort the symbols"), 0 },
+  { "reverse-sort", 'r', NULL, 0, N_("Reverse the sense of the sort"), 0 },
+#ifdef USE_DEMANGLE
+  { "demangle", 'C', NULL, 0,
+    N_("Decode low-level symbol names into source code names"), 0 },
+#endif
+  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("List symbols from FILEs (a.out by default).");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Parser children.  */
+static struct argp_child argp_children[] =
+  {
+    { &color_argp, 0, N_("Output formatting"), 2 },
+    { NULL, 0, NULL, 0}
+  };
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
+};
+
+
+/* Print symbols in file named FNAME.  */
+static int process_file (const char *fname, bool more_than_one);
+
+/* Handle content of archive.  */
+static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
+		      const char *suffix);
+
+/* Handle ELF file.  */
+static int handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
+		       const char *suffix);
+
+
+#define INTERNAL_ERROR(fname) \
+  error_exit (0, _("%s: INTERNAL ERROR %d (%s): %s"),      \
+	      fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
+
+
+/* Internal representation of symbols.  */
+typedef struct GElf_SymX
+{
+  GElf_Sym sym;
+  Elf32_Word xndx;
+  char *where;
+} GElf_SymX;
+
+
+/* User-selectable options.  */
+
+/* The selected output format.  */
+static enum
+{
+  format_sysv = 0,
+  format_bsd,
+  format_posix
+} format;
+
+/* Print defined, undefined, or both?  */
+static bool hide_undefined;
+static bool hide_defined;
+
+/* Print local symbols also?  */
+static bool hide_local;
+
+/* Nonzero if full filename should precede every symbol.  */
+static bool print_file_name;
+
+/* If true print size of defined symbols in BSD format.  */
+static bool print_size;
+
+/* If true print archive index.  */
+static bool print_armap;
+
+/* If true reverse sorting.  */
+static bool reverse_sort;
+
+#ifdef USE_DEMANGLE
+/* If true demangle symbols.  */
+static bool demangle;
+#endif
+
+/* Type of the section we are printing.  */
+static GElf_Word symsec_type = SHT_SYMTAB;
+
+/* Sorting selection.  */
+static enum
+{
+  sort_name = 0,
+  sort_numeric,
+  sort_nosort
+} sort;
+
+/* Radix for printed numbers.  */
+static enum
+{
+  radix_hex = 0,
+  radix_decimal,
+  radix_octal
+} radix;
+
+/* If nonzero mark special symbols:
+   - weak symbols are distinguished from global symbols by adding
+     a `*' after the identifying letter for the symbol class and type.
+   - TLS symbols are distinguished from normal symbols by adding
+     a '@' after the identifying letter for the symbol class and type.  */
+static bool mark_special;
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+  int result = 0;
+
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Tell the library which version we are expecting.  */
+  (void) elf_version (EV_CURRENT);
+
+  if (remaining == argc)
+    /* The user didn't specify a name so we use a.out.  */
+    result = process_file ("a.out", false);
+  else
+    {
+      /* Process all the remaining files.  */
+      const bool more_than_one = remaining + 1 < argc;
+
+      do
+	result |= process_file (argv[remaining], more_than_one);
+      while (++remaining < argc);
+    }
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'a':
+      /* XXX */
+      break;
+
+#ifdef USE_DEMANGLE
+    case 'C':
+      demangle = true;
+      break;
+#endif
+
+    case 'f':
+      if (strcmp (arg, "bsd") == 0)
+	format = format_bsd;
+      else if (strcmp (arg, "posix") == 0)
+	format = format_posix;
+      else
+	/* Be bug compatible.  The BFD implementation also defaulted to
+	   using the SysV format if nothing else matches.  */
+	format = format_sysv;
+      break;
+
+    case 'g':
+      hide_local = true;
+      break;
+
+    case 'n':
+      sort = sort_numeric;
+      break;
+
+    case 'p':
+      sort = sort_nosort;
+      break;
+
+    case 't':
+      if (strcmp (arg, "10") == 0 || strcmp (arg, "d") == 0)
+	radix = radix_decimal;
+      else if (strcmp (arg, "8") == 0 || strcmp (arg, "o") == 0)
+	radix = radix_octal;
+      else
+	radix = radix_hex;
+      break;
+
+    case 'u':
+      hide_undefined = false;
+      hide_defined = true;
+      break;
+
+    case 'A':
+    case 'o':
+      print_file_name = true;
+      break;
+
+    case 'B':
+      format = format_bsd;
+      break;
+
+    case 'D':
+      symsec_type = SHT_DYNSYM;
+      break;
+
+    case 'P':
+      format = format_posix;
+      break;
+
+    case OPT_DEFINED:
+      hide_undefined = true;
+      hide_defined = false;
+      break;
+
+    case OPT_MARK_SPECIAL:
+      mark_special = true;
+      break;
+
+    case 'S':
+      print_size = true;
+      break;
+
+    case 's':
+      print_armap = true;
+      break;
+
+    case 'r':
+      reverse_sort = true;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Open the file and determine the type.  */
+static int
+process_file (const char *fname, bool more_than_one)
+{
+  /* Open the file.  */
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      error (0, errno, _("cannot open '%s'"), fname);
+      return 1;
+    }
+
+  /* Now get the ELF descriptor.  */
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf != NULL)
+    {
+      if (elf_kind (elf) == ELF_K_ELF)
+	{
+	  int result = handle_elf (fd, elf, more_than_one ? "" : NULL,
+				   fname, NULL);
+
+	  if (elf_end (elf) != 0)
+	    INTERNAL_ERROR (fname);
+
+	  if (close (fd) != 0)
+	    error_exit (errno, _("while closing '%s'"), fname);
+
+	  return result;
+	}
+      else if (elf_kind (elf) == ELF_K_AR)
+	{
+	  int result = handle_ar (fd, elf, NULL, fname, NULL);
+
+	  if (elf_end (elf) != 0)
+	    INTERNAL_ERROR (fname);
+
+	  if (close (fd) != 0)
+	    error_exit (errno, _("while closing '%s'"), fname);
+
+	  return result;
+	}
+
+      /* We cannot handle this type.  Close the descriptor anyway.  */
+      if (elf_end (elf) != 0)
+	INTERNAL_ERROR (fname);
+    }
+
+  error (0, 0, _("%s: File format not recognized"), fname);
+
+  return 1;
+}
+
+
+static int
+handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
+	   const char *suffix)
+{
+  size_t fname_len = strlen (fname) + 1;
+  size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
+  char new_prefix[prefix_len + fname_len + 2];
+  size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
+  char new_suffix[suffix_len + 2];
+  Elf *subelf;
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  int result = 0;
+
+  char *cp = new_prefix;
+  if (prefix != NULL)
+    cp = stpcpy (cp, prefix);
+  cp = stpcpy (cp, fname);
+  stpcpy (cp, "[");
+
+  cp = new_suffix;
+  if (suffix != NULL)
+    cp = stpcpy (cp, suffix);
+  stpcpy (cp, "]");
+
+  /* First print the archive index if this is wanted.  */
+  if (print_armap)
+    {
+      Elf_Arsym *arsym = elf_getarsym (elf, NULL);
+
+      if (arsym != NULL)
+	{
+	  Elf_Arhdr *arhdr = NULL;
+	  size_t arhdr_off = 0;	/* Note: 0 is no valid offset.  */
+
+	  fputs_unlocked (_("\nArchive index:\n"), stdout);
+
+	  while (arsym->as_off != 0)
+	    {
+	      if (arhdr_off != arsym->as_off
+		  && (elf_rand (elf, arsym->as_off) != arsym->as_off
+		      || (subelf = elf_begin (fd, cmd, elf)) == NULL
+		      || (arhdr = elf_getarhdr (subelf)) == NULL))
+		{
+		  error (0, 0, _("invalid offset %zu for symbol %s"),
+			 arsym->as_off, arsym->as_name);
+		  break;
+		}
+
+	      printf (_("%s in %s\n"), arsym->as_name, arhdr->ar_name);
+
+	      ++arsym;
+	    }
+
+	  if (elf_rand (elf, SARMAG) != SARMAG)
+	    {
+	      error (0, 0,
+		     _("cannot reset archive offset to beginning"));
+	      return 1;
+	    }
+	}
+    }
+
+  /* Process all the files contained in the archive.  */
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      /* The the header for this element.  */
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      /* Skip over the index entries.  */
+      if (strcmp (arhdr->ar_name, "/") != 0
+	  && strcmp (arhdr->ar_name, "//") != 0
+	  && strcmp (arhdr->ar_name, "/SYM64/") != 0)
+	{
+	  if (elf_kind (subelf) == ELF_K_ELF)
+	    result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name,
+				  new_suffix);
+	  else if (elf_kind (subelf) == ELF_K_AR)
+	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
+				 new_suffix);
+	  else
+	    {
+	      error (0, 0, _("%s%s%s: file format not recognized"),
+		     new_prefix, arhdr->ar_name, new_suffix);
+	      result = 1;
+	    }
+	}
+
+      /* Get next archive element.  */
+      cmd = elf_next (subelf);
+      if (elf_end (subelf) != 0)
+	INTERNAL_ERROR (fname);
+    }
+
+  return result;
+}
+
+
+/* Mapping of radix and binary class to length.  */
+static const int length_map[2][3] =
+{
+  [ELFCLASS32 - 1] =
+  {
+    [radix_hex] = 8,
+    [radix_decimal] = 10,
+    [radix_octal] = 11
+  },
+  [ELFCLASS64 - 1] =
+  {
+    [radix_hex] = 16,
+    [radix_decimal] = 20,
+    [radix_octal] = 22
+  }
+};
+
+
+static int
+global_compare (const void *p1, const void *p2)
+{
+  const Dwarf_Global *g1 = (const Dwarf_Global *) p1;
+  const Dwarf_Global *g2 = (const Dwarf_Global *) p2;
+
+  return strcmp (g1->name, g2->name);
+}
+
+
+static void *global_root;
+
+
+static int
+get_global (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
+	    void *arg __attribute__ ((unused)))
+{
+  tsearch (memcpy (xmalloc (sizeof (Dwarf_Global)), global,
+		   sizeof (Dwarf_Global)),
+	   &global_root, global_compare);
+
+  return DWARF_CB_OK;
+}
+
+
+struct local_name
+{
+  const char *name;
+  const char *file;
+  Dwarf_Word lineno;
+  Dwarf_Addr lowpc;
+  Dwarf_Addr highpc;
+};
+
+
+static int
+local_compare (const void *p1, const void *p2)
+{
+  struct local_name *g1 = (struct local_name *) p1;
+  struct local_name *g2 = (struct local_name *) p2;
+  int result;
+
+  result = strcmp (g1->name, g2->name);
+  if (result == 0)
+    {
+      if (g1->lowpc <= g2->lowpc && g1->highpc >= g2->highpc)
+	{
+	  /* g2 is contained in g1.  Update the data.  */
+	  g2->lowpc = g1->lowpc;
+	  g2->highpc = g1->highpc;
+	  result = 0;
+	}
+      else if (g2->lowpc <= g1->lowpc && g2->highpc >= g1->highpc)
+	{
+	  /* g1 is contained in g2.  Update the data.  */
+	  g1->lowpc = g2->lowpc;
+	  g1->highpc = g2->highpc;
+	  result = 0;
+	}
+      else
+	result = g1->lowpc < g2->lowpc ? -1 : 1;
+    }
+
+  return result;
+}
+
+
+static int
+get_var_range (Dwarf_Die *die, Dwarf_Word *lowpc, Dwarf_Word *highpc)
+{
+  Dwarf_Attribute locattr_mem;
+  Dwarf_Attribute *locattr = dwarf_attr (die, DW_AT_location, &locattr_mem);
+  if  (locattr == NULL)
+    return 1;
+
+  Dwarf_Op *loc;
+  size_t nloc;
+  if (dwarf_getlocation (locattr, &loc, &nloc) != 0)
+    return 1;
+
+  /* Interpret the location expressions.  */
+  // XXX For now just the simple one:
+  if (nloc == 1 && loc[0].atom == DW_OP_addr)
+    {
+      *lowpc = *highpc = loc[0].number;
+      return 0;
+    }
+
+  return 1;
+}
+
+
+
+static void *local_root;
+
+
+static void
+get_local_names (Dwarf *dbg)
+{
+  Dwarf_Off offset = 0;
+  Dwarf_Off old_offset;
+  size_t hsize;
+
+  while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL,
+		       NULL) == 0)
+    {
+      Dwarf_Die cudie_mem;
+      Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
+
+      /* If we cannot get the CU DIE there is no need to go on with
+	 this CU.  */
+      if (cudie == NULL)
+	continue;
+      /* This better be a CU DIE.  */
+      if (dwarf_tag (cudie) != DW_TAG_compile_unit)
+	continue;
+
+      /* Get the line information.  */
+      Dwarf_Files *files;
+      size_t nfiles;
+      if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
+	continue;
+
+      Dwarf_Die die_mem;
+      Dwarf_Die *die = &die_mem;
+      if (dwarf_child (cudie, die) == 0)
+	/* Iterate over all immediate children of the CU DIE.  */
+	do
+	  {
+	    int tag = dwarf_tag (die);
+	    if (tag != DW_TAG_subprogram && tag != DW_TAG_variable)
+	      continue;
+
+	    /* We are interested in five attributes: name, decl_file,
+	       decl_line, low_pc, and high_pc.  */
+	    Dwarf_Attribute attr_mem;
+	    Dwarf_Attribute *attr = dwarf_attr (die, DW_AT_name, &attr_mem);
+	    const char *name = dwarf_formstring (attr);
+	    if (name == NULL)
+	      continue;
+
+	    Dwarf_Word fileidx;
+	    attr = dwarf_attr (die, DW_AT_decl_file, &attr_mem);
+	    if (dwarf_formudata (attr, &fileidx) != 0 || fileidx >= nfiles)
+	      continue;
+
+	    Dwarf_Word lineno;
+	    attr = dwarf_attr (die, DW_AT_decl_line, &attr_mem);
+	    if (dwarf_formudata (attr, &lineno) != 0 || lineno == 0)
+	      continue;
+
+	    Dwarf_Addr lowpc;
+	    Dwarf_Addr highpc;
+	    if (tag == DW_TAG_subprogram)
+	      {
+		if (dwarf_lowpc (die, &lowpc) != 0
+		    || dwarf_highpc (die, &highpc) != 0)
+		  continue;
+	      }
+	    else
+	      {
+		if (get_var_range (die, &lowpc, &highpc) != 0)
+		  continue;
+	      }
+
+	    /* We have all the information.  Create a record.  */
+	    struct local_name *newp = xmalloc (sizeof (*newp));
+	    newp->name = name;
+	    newp->file = dwarf_filesrc (files, fileidx, NULL, NULL);
+	    newp->lineno = lineno;
+	    newp->lowpc = lowpc;
+	    newp->highpc = highpc;
+
+	   /* Check whether a similar local_name is already in the
+	      cache.  That should not happen.  But if it does, we
+	      don't want to leak memory.  */
+	    struct local_name **tres = tsearch (newp, &local_root,
+						local_compare);
+	    if (tres == NULL)
+              error_exit (errno, _("cannot create search tree"));
+	    else if (*tres != newp)
+	      free (newp);
+	  }
+	while (dwarf_siblingof (die, die) == 0);
+    }
+}
+
+/* Do elf_strptr, but return a backup string and never NULL.  */
+static const char *
+sym_name (Elf *elf, GElf_Word strndx, GElf_Word st_name, char buf[], size_t n)
+{
+  const char *symstr = elf_strptr (elf, strndx, st_name);
+  if (symstr == NULL)
+    {
+      snprintf (buf, n, "[invalid st_name %#" PRIx32 "]", st_name);
+      symstr = buf;
+    }
+  return symstr;
+}
+
+/* Show symbols in SysV format.  */
+static void
+show_symbols_sysv (Ebl *ebl, GElf_Word strndx, const char *fullname,
+		   GElf_SymX *syms, size_t nsyms, int longest_name,
+		   int longest_where)
+{
+  size_t shnum;
+  if (elf_getshdrnum (ebl->elf, &shnum) < 0)
+    INTERNAL_ERROR (fullname);
+
+  bool scnnames_malloced = shnum * sizeof (const char *) > 128 * 1024;
+  const char **scnnames;
+  if (scnnames_malloced)
+    scnnames = xmalloc (sizeof (const char *) * shnum);
+  else
+    scnnames = (const char **) alloca (sizeof (const char *) * shnum);
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* Cache the section names.  */
+  Elf_Scn *scn = NULL;
+  size_t cnt = 1;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      assert (elf_ndxscn (scn) == cnt);
+      cnt++;
+
+      char *name = NULL;
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr != NULL)
+	name = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+      if (unlikely (name == NULL))
+	name = "[invalid section name]";
+      scnnames[elf_ndxscn (scn)] = name;
+    }
+
+  int digits = length_map[gelf_getclass (ebl->elf) - 1][radix];
+
+  /* We always print this prolog.  */
+  printf (_("\n\nSymbols from %s:\n\n"), fullname);
+
+  /* The header line.  */
+  printf (_("%*s%-*s %-*s Class  Type     %-*s %*s Section\n\n"),
+	  print_file_name ? (int) strlen (fullname) + 1: 0, "",
+	  longest_name, sgettext ("sysv|Name"),
+	  /* TRANS: the "sysv|" parts makes the string unique.  */
+	  digits, sgettext ("sysv|Value"),
+	  /* TRANS: the "sysv|" parts makes the string unique.  */
+	  digits, sgettext ("sysv|Size"),
+	  /* TRANS: the "sysv|" parts makes the string unique.  */
+	  longest_where, sgettext ("sysv|Line"));
+
+#ifdef USE_DEMANGLE
+  size_t demangle_buffer_len = 0;
+  char *demangle_buffer = NULL;
+#endif
+
+  /* Iterate over all symbols.  */
+  for (cnt = 0; cnt < nsyms; ++cnt)
+    {
+      /* In this format SECTION entries are not printed.  */
+      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_SECTION)
+	continue;
+
+      char symstrbuf[50];
+      const char *symstr = sym_name (ebl->elf, strndx, syms[cnt].sym.st_name,
+				     symstrbuf, sizeof symstrbuf);
+
+      /* Printing entries with a zero-length name makes the output
+	 not very well parseable.  Since these entries don't carry
+	 much information we leave them out.  */
+      if (symstr[0] == '\0')
+	continue;
+
+      /* We do not print the entries for files.  */
+      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
+	continue;
+
+#ifdef USE_DEMANGLE
+      /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
+      if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
+	{
+	  int status = -1;
+	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
+					   &demangle_buffer_len, &status);
+
+	  if (status == 0)
+	    symstr = dmsymstr;
+	}
+#endif
+
+      char symbindbuf[50];
+      char symtypebuf[50];
+      char secnamebuf[1024];
+      char addressbuf[(64 + 2) / 3 + 1];
+      char sizebuf[(64 + 2) / 3 + 1];
+
+      /* If we have to precede the line with the file name.  */
+      if (print_file_name)
+	{
+	  fputs_unlocked (fullname, stdout);
+	  putchar_unlocked (':');
+	}
+
+      /* Convert the address.  */
+      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
+	{
+	  sprintf (addressbuf, "%*c", digits, ' ');
+	  sprintf (sizebuf, "%*c", digits, ' ');
+	}
+      else
+	{
+	  snprintf (addressbuf, sizeof (addressbuf),
+		    (radix == radix_hex ? "%0*" PRIx64
+		     : (radix == radix_decimal ? "%0*" PRId64
+			: "%0*" PRIo64)),
+		    digits, syms[cnt].sym.st_value);
+	  snprintf (sizebuf, sizeof (sizebuf),
+		    (radix == radix_hex ? "%0*" PRIx64
+		     : (radix == radix_decimal ? "%0*" PRId64
+			: "%0*" PRIo64)),
+		    digits, syms[cnt].sym.st_size);
+	}
+
+      /* Print the actual string.  */
+      const char *bind;
+      bind = ebl_symbol_binding_name (ebl,
+				      GELF_ST_BIND (syms[cnt].sym.st_info),
+				      symbindbuf, sizeof (symbindbuf));
+      if (bind != NULL && startswith (bind, "GNU_"))
+	bind += strlen ("GNU_");
+      printf ("%-*s|%s|%-6s|%-8s|%s|%*s|%s\n",
+	      longest_name, symstr, addressbuf, bind,
+	      ebl_symbol_type_name (ebl, GELF_ST_TYPE (syms[cnt].sym.st_info),
+				    symtypebuf, sizeof (symtypebuf)),
+	      sizebuf, longest_where, syms[cnt].where,
+	      ebl_section_name (ebl, syms[cnt].sym.st_shndx, syms[cnt].xndx,
+				secnamebuf, sizeof (secnamebuf), scnnames,
+				shnum));
+    }
+
+#ifdef USE_DEMANGLE
+  free (demangle_buffer);
+#endif
+
+  if (scnnames_malloced)
+    free (scnnames);
+}
+
+
+static char
+class_type_char (Elf *elf, const GElf_Ehdr *ehdr, GElf_Sym *sym)
+{
+  int local_p = GELF_ST_BIND (sym->st_info) == STB_LOCAL;
+
+  /* XXX Add support for architecture specific types and classes.  */
+  if (sym->st_shndx == SHN_ABS)
+    return local_p ? 'a' : 'A';
+
+  if (sym->st_shndx == SHN_UNDEF)
+    /* Undefined symbols must be global.  */
+    return 'U';
+
+  char result = "NDTSFBD         "[GELF_ST_TYPE (sym->st_info)];
+
+  if (result == 'D')
+    {
+      /* Special handling: unique data symbols.  */
+      if (ehdr->e_ident[EI_OSABI] == ELFOSABI_LINUX
+	  && GELF_ST_BIND (sym->st_info) == STB_GNU_UNIQUE)
+	result = 'u';
+      else if (GELF_ST_BIND (sym->st_info) == STB_WEAK)
+	result = 'V';
+      else if (sym->st_shndx == SHN_COMMON)
+	result = 'C';
+      else
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, sym->st_shndx),
+					  &shdr_mem);
+	  if (shdr != NULL)
+	    {
+	      if ((shdr->sh_flags & SHF_WRITE) == 0)
+		result = 'R';
+	      else if (shdr->sh_type == SHT_NOBITS)
+		result = 'B';
+	    }
+	}
+    }
+  else if (result == 'T')
+    {
+      if (GELF_ST_BIND (sym->st_info) == STB_WEAK)
+	result = 'W';
+    }
+
+  return local_p ? tolower (result) : result;
+}
+
+
+static void
+show_symbols_bsd (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
+		  const char *prefix, const char *fname, const char *fullname,
+		  GElf_SymX *syms, size_t nsyms)
+{
+  int digits = length_map[gelf_getclass (elf) - 1][radix];
+
+  if (prefix != NULL && ! print_file_name)
+    printf ("\n%s:\n", fname);
+
+#ifdef USE_DEMANGLE
+  size_t demangle_buffer_len = 0;
+  char *demangle_buffer = NULL;
+#endif
+
+  /* Iterate over all symbols.  */
+  for (size_t cnt = 0; cnt < nsyms; ++cnt)
+    {
+      char symstrbuf[50];
+      const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
+				     symstrbuf, sizeof symstrbuf);
+
+      /* Printing entries with a zero-length name makes the output
+	 not very well parseable.  Since these entries don't carry
+	 much information we leave them out.  */
+      if (symstr[0] == '\0')
+	continue;
+
+      /* We do not print the entries for files.  */
+      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
+	continue;
+
+#ifdef USE_DEMANGLE
+      /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
+      if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
+	{
+	  int status = -1;
+	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
+					   &demangle_buffer_len, &status);
+
+	  if (status == 0)
+	    symstr = dmsymstr;
+	}
+#endif
+
+      /* If we have to precede the line with the file name.  */
+      if (print_file_name)
+	{
+	  fputs_unlocked (fullname, stdout);
+	  putchar_unlocked (':');
+	}
+
+      bool is_tls = GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS;
+      bool is_weak = GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK;
+      const char *marker = (mark_special
+			    ? (is_tls ? "@" : (is_weak ? "*" : " ")) : "");
+
+      if (syms[cnt].sym.st_shndx == SHN_UNDEF)
+	{
+	  const char *color = "";
+	  if (color_mode)
+	    {
+	      if (is_tls)
+		color = color_undef_tls;
+	      else if (is_weak)
+		color = color_undef_weak;
+	      else
+		color = color_undef;
+	    }
+
+	  printf ("%*s %sU%s %s", digits, "", color, marker, symstr);
+	}
+      else
+	{
+	  const char *color = "";
+	  if (color_mode)
+	    {
+	      if (is_tls)
+		color = color_tls;
+	      else if (is_weak)
+		color = color_weak;
+	      else
+		color = color_symbol;
+	    }
+	  if (print_size && syms[cnt].sym.st_size != 0)
+	    {
+#define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %10$0*9$" PRIx64 " %7$s%3$c%4$s %5$s"
+#define DECFMT "%6$s%2$*1$" PRId64 "%8$s %10$*9$" PRId64 " %7$s%3$c%4$s %5$s"
+#define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %10$0*9$" PRIo64 " %7$s%3$c%4$s %5$s"
+	      printf ((radix == radix_hex ? HEXFMT
+		       : (radix == radix_decimal ? DECFMT : OCTFMT)),
+		      digits, syms[cnt].sym.st_value,
+		      class_type_char (elf, ehdr, &syms[cnt].sym), marker,
+		      symstr,
+		      color_mode ? color_address : "",
+		      color,
+		      color_mode ? color_off : "",
+		      digits, (uint64_t) syms[cnt].sym.st_size);
+#undef HEXFMT
+#undef DECFMT
+#undef OCTFMT
+	    }
+	  else
+	    {
+#define HEXFMT "%6$s%2$0*1$" PRIx64 "%8$s %7$s%3$c%4$s %5$s"
+#define DECFMT "%6$s%2$*1$" PRId64 "%8$s %7$s%3$c%4$s %5$s"
+#define OCTFMT "%6$s%2$0*1$" PRIo64 "%8$s %7$s%3$c%4$s %5$s"
+	      printf ((radix == radix_hex ? HEXFMT
+		       : (radix == radix_decimal ? DECFMT : OCTFMT)),
+		      digits, syms[cnt].sym.st_value,
+		      class_type_char (elf, ehdr, &syms[cnt].sym), marker,
+		      symstr,
+		      color_mode ? color_address : "",
+		      color,
+		      color_mode ? color_off : "");
+#undef HEXFMT
+#undef DECFMT
+#undef OCTFMT
+	    }
+	}
+
+      if (color_mode)
+	fputs_unlocked (color_off, stdout);
+      putchar_unlocked ('\n');
+    }
+
+#ifdef USE_DEMANGLE
+  free (demangle_buffer);
+#endif
+}
+
+
+static void
+show_symbols_posix (Elf *elf, const GElf_Ehdr *ehdr, GElf_Word strndx,
+		    const char *prefix, const char *fullname, GElf_SymX *syms,
+		    size_t nsyms)
+{
+  if (prefix != NULL && ! print_file_name)
+    printf ("%s:\n", fullname);
+
+  int digits = length_map[gelf_getclass (elf) - 1][radix];
+
+#ifdef USE_DEMANGLE
+  size_t demangle_buffer_len = 0;
+  char *demangle_buffer = NULL;
+#endif
+
+  /* Iterate over all symbols.  */
+  for (size_t cnt = 0; cnt < nsyms; ++cnt)
+    {
+      char symstrbuf[50];
+      const char *symstr = sym_name (elf, strndx, syms[cnt].sym.st_name,
+				     symstrbuf, sizeof symstrbuf);
+
+      /* Printing entries with a zero-length name makes the output
+	 not very well parseable.  Since these entries don't carry
+	 much information we leave them out.  */
+      if (symstr[0] == '\0')
+	continue;
+
+      /* We do not print the entries for files.  */
+      if (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_FILE)
+	continue;
+
+#ifdef USE_DEMANGLE
+      /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
+      if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
+	{
+	  int status = -1;
+	  char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
+					   &demangle_buffer_len, &status);
+
+	  if (status == 0)
+	    symstr = dmsymstr;
+	}
+#endif
+
+      /* If we have to precede the line with the file name.  */
+      if (print_file_name)
+	{
+	  fputs_unlocked (fullname, stdout);
+	  putchar_unlocked (':');
+	  putchar_unlocked (' ');
+	}
+
+      printf ("%s %c%s", symstr,
+	      class_type_char (elf, ehdr, &syms[cnt].sym),
+	      mark_special
+	      ? (GELF_ST_TYPE (syms[cnt].sym.st_info) == STT_TLS
+		 ? "@"
+		 : (GELF_ST_BIND (syms[cnt].sym.st_info) == STB_WEAK
+		    ? "*" : " "))
+	      : "");
+      if (syms[cnt].sym.st_shndx != SHN_UNDEF)
+	printf ((radix == radix_hex
+		 ? " %0*" PRIx64 " %0*" PRIx64
+		 : (radix == radix_decimal
+		    ? " %*" PRId64 " %*" PRId64
+		    : " %0*" PRIo64 " %0*" PRIo64)),
+		digits, syms[cnt].sym.st_value,
+		digits, syms[cnt].sym.st_size);
+      putchar ('\n');
+    }
+
+#ifdef USE_DEMANGLE
+  free (demangle_buffer);
+#endif
+}
+
+
+/* Maximum size of memory we allocate on the stack.  */
+#define MAX_STACK_ALLOC	65536
+
+static int
+sort_by_address (const void *p1, const void *p2)
+{
+  GElf_SymX *s1 = (GElf_SymX *) p1;
+  GElf_SymX *s2 = (GElf_SymX *) p2;
+
+  int result = (s1->sym.st_value < s2->sym.st_value
+		? -1 : (s1->sym.st_value == s2->sym.st_value ? 0 : 1));
+
+  return reverse_sort ? -result : result;
+}
+
+static Elf *sort_by_name_elf;
+static size_t sort_by_name_ndx;
+
+static int
+sort_by_name (const void *p1, const void *p2)
+{
+  GElf_SymX *s1 = (GElf_SymX *) p1;
+  GElf_SymX *s2 = (GElf_SymX *) p2;
+
+  const char *n1 = elf_strptr (sort_by_name_elf, sort_by_name_ndx,
+			       s1->sym.st_name) ?: "";
+  const char *n2 = elf_strptr (sort_by_name_elf, sort_by_name_ndx,
+			       s2->sym.st_name) ?: "";
+
+  int result = strcmp (n1, n2);
+
+  return reverse_sort ? -result : result;
+}
+
+/* Stub libdwfl callback, only the ELF handle already open is ever
+   used.  Only used for finding the alternate debug file if the Dwarf
+   comes from the main file.  We are not interested in separate
+   debuginfo.  */
+static int
+find_no_debuginfo (Dwfl_Module *mod,
+		   void **userdata,
+		   const char *modname,
+		   Dwarf_Addr base,
+		   const char *file_name,
+		   const char *debuglink_file,
+		   GElf_Word debuglink_crc,
+		   char **debuginfo_file_name)
+{
+  Dwarf_Addr dwbias;
+  dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
+
+  /* We are only interested if the Dwarf has been setup on the main
+     elf file but is only missing the alternate debug link.  If dwbias
+     hasn't even been setup, this is searching for separate debuginfo
+     for the main elf.  We don't care in that case.  */
+  if (dwbias == (Dwarf_Addr) -1)
+    return -1;
+
+  return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
+				       file_name, debuglink_file,
+				       debuglink_crc, debuginfo_file_name);
+}
+
+/* Get the Dwarf for the module/file we want.  */
+struct getdbg
+{
+  const char *name;
+  Dwarf **dbg;
+};
+
+static int
+getdbg_dwflmod (Dwfl_Module *dwflmod,
+		void **userdata __attribute__ ((unused)),
+		const char *name,
+		Dwarf_Addr base __attribute__ ((unused)),
+		void *arg)
+{
+  struct getdbg *get = (struct getdbg *) arg;
+  if (get != NULL && get->name != NULL && strcmp (get->name, name) == 0)
+    {
+      Dwarf_Addr bias;
+      *get->dbg = dwfl_module_getdwarf (dwflmod, &bias);
+      return DWARF_CB_ABORT;
+    }
+
+  return DWARF_CB_OK;
+}
+
+static void
+show_symbols (int fd, Ebl *ebl, GElf_Ehdr *ehdr,
+	      Elf_Scn *scn, Elf_Scn *xndxscn,
+	      GElf_Shdr *shdr, const char *prefix, const char *fname,
+	      const char *fullname)
+{
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* The section is that large.  */
+  size_t size = shdr->sh_size;
+  /* One entry is this large.  */
+  size_t entsize = shdr->sh_entsize;
+
+  /* Consistency checks.  */
+  if (entsize == 0
+      || entsize != gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT))
+    error (0, 0,
+	   _("%s: entry size in section %zd `%s' is not what we expect"),
+	   fullname, elf_ndxscn (scn),
+	   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+  else if (size % entsize != 0)
+    error (0, 0,
+	   _("%s: size of section %zd `%s' is not multiple of entry size"),
+	   fullname, elf_ndxscn (scn),
+	   elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+
+  /* Compute number of entries.  Handle buggy entsize values.  */
+  size_t nentries = size / (entsize ?: 1);
+
+
+#define obstack_chunk_alloc xmalloc
+#define obstack_chunk_free free
+  struct obstack whereob;
+  obstack_init (&whereob);
+
+  /* Get a DWARF debugging descriptor.  It's no problem if this isn't
+     possible.  We just won't print any line number information.  */
+  Dwarf *dbg = NULL;
+  Dwfl *dwfl = NULL;
+  if (format == format_sysv)
+    {
+      if (ehdr->e_type != ET_REL)
+	dbg = dwarf_begin_elf (ebl->elf, DWARF_C_READ, NULL);
+      else
+	{
+	  /* Abuse libdwfl to do the relocations for us.  This is just
+	     for the ET_REL file containing Dwarf, so no need for
+	     fancy lookups.  */
+
+	  /* Duplicate an fd for dwfl_report_offline to swallow.  */
+	  int dwfl_fd = dup (fd);
+	  if (likely (dwfl_fd >= 0))
+	    {
+	      static const Dwfl_Callbacks callbacks =
+		{
+		  .section_address = dwfl_offline_section_address,
+		  .find_debuginfo = find_no_debuginfo
+		};
+	      dwfl = dwfl_begin (&callbacks);
+	      if (likely (dwfl != NULL))
+		{
+		  /* Let 0 be the logical address of the file (or
+		     first in archive).  */
+		  dwfl->offline_next_address = 0;
+		  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd)
+		      == NULL)
+		    {
+		      /* Consumed on success, not on failure.  */
+		      close (dwfl_fd);
+		    }
+		  else
+		    {
+		      dwfl_report_end (dwfl, NULL, NULL);
+
+		      struct getdbg get = { .name = fname, .dbg = &dbg };
+		      dwfl_getmodules (dwfl, &getdbg_dwflmod, &get, 0);
+		    }
+		}
+	      else
+		close (dwfl_fd);
+	    }
+	}
+      if (dbg != NULL)
+	{
+	  (void) dwarf_getpubnames (dbg, get_global, NULL, 0);
+
+	  get_local_names (dbg);
+	}
+    }
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  Elf_Data *xndxdata = elf_getdata (xndxscn, NULL);
+  if (data == NULL || (xndxscn != NULL && xndxdata == NULL))
+    INTERNAL_ERROR (fullname);
+
+  /* Allocate the memory.
+
+     XXX We can use a dirty trick here.  Since GElf_Sym == Elf64_Sym we
+     can use the data memory instead of copying again if what we read
+     is a 64 bit file.  */
+  if (nentries > SIZE_MAX / sizeof (GElf_SymX))
+    error_exit (0, _("%s: entries (%zd) in section %zd `%s' is too large"),
+		fullname, nentries, elf_ndxscn (scn),
+		elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+  GElf_SymX *sym_mem;
+  if (nentries * sizeof (GElf_SymX) < MAX_STACK_ALLOC)
+    sym_mem = (GElf_SymX *) alloca (nentries * sizeof (GElf_SymX));
+  else
+    sym_mem = xmalloc (nentries * sizeof (GElf_SymX));
+
+  /* Iterate over all symbols.  */
+#ifdef USE_DEMANGLE
+  size_t demangle_buffer_len = 0;
+  char *demangle_buffer = NULL;
+#endif
+  int longest_name = 4;
+  int longest_where = 4;
+  size_t nentries_used = 0;
+  for (size_t cnt = 0; cnt < nentries; ++cnt)
+    {
+      GElf_Sym *sym = gelf_getsymshndx (data, xndxdata, cnt,
+					&sym_mem[nentries_used].sym,
+					&sym_mem[nentries_used].xndx);
+      if (sym == NULL)
+	INTERNAL_ERROR (fullname);
+
+      /* Filter out administrative symbols without a name and those
+	 deselected by the user with command line options.  */
+      if ((hide_undefined && sym->st_shndx == SHN_UNDEF)
+	  || (hide_defined && sym->st_shndx != SHN_UNDEF)
+	  || (hide_local && GELF_ST_BIND (sym->st_info) == STB_LOCAL))
+	continue;
+
+      sym_mem[nentries_used].where = "";
+      if (format == format_sysv)
+	{
+	  const char *symstr = elf_strptr (ebl->elf, shdr->sh_link,
+					   sym->st_name);
+	  if (symstr == NULL)
+	    continue;
+
+#ifdef USE_DEMANGLE
+	  /* Demangle if necessary.  Require GNU v3 ABI by the "_Z" prefix.  */
+	  if (demangle && symstr[0] == '_' && symstr[1] == 'Z')
+	    {
+	      int status = -1;
+	      char *dmsymstr = __cxa_demangle (symstr, demangle_buffer,
+					       &demangle_buffer_len, &status);
+
+	      if (status == 0)
+		symstr = dmsymstr;
+	    }
+#endif
+
+	  longest_name = MAX ((size_t) longest_name, strlen (symstr));
+
+	  if (sym->st_shndx != SHN_UNDEF
+	      && GELF_ST_BIND (sym->st_info) != STB_LOCAL
+	      && global_root != NULL)
+	    {
+	      Dwarf_Global fake = { .name = symstr };
+	      Dwarf_Global **found = tfind (&fake, &global_root,
+					    global_compare);
+	      if (found != NULL)
+		{
+		  Dwarf_Die die_mem;
+		  Dwarf_Die *die = dwarf_offdie (dbg, (*found)->die_offset,
+						 &die_mem);
+
+		  Dwarf_Die cudie_mem;
+		  Dwarf_Die *cudie = NULL;
+
+		  Dwarf_Addr lowpc;
+		  Dwarf_Addr highpc;
+		  if (die != NULL
+		      && dwarf_lowpc (die, &lowpc) == 0
+		      && lowpc <= sym->st_value
+		      && dwarf_highpc (die, &highpc) == 0
+		      && highpc > sym->st_value)
+		    cudie = dwarf_offdie (dbg, (*found)->cu_offset,
+					  &cudie_mem);
+		  if (cudie != NULL)
+		    {
+		      Dwarf_Line *line = dwarf_getsrc_die (cudie,
+							   sym->st_value);
+		      if (line != NULL)
+			{
+			  /* We found the line.  */
+			  int lineno;
+			  (void) dwarf_lineno (line, &lineno);
+			  const char *file = dwarf_linesrc (line, NULL, NULL);
+			  file = (file != NULL) ? xbasename (file) : "???";
+			  int n;
+			  n = obstack_printf (&whereob, "%s:%d%c", file,
+					      lineno, '\0');
+			  sym_mem[nentries_used].where
+			    = obstack_finish (&whereob);
+
+			  /* The return value of obstack_print included the
+			     NUL byte, so subtract one.  */
+			  if (--n > (int) longest_where)
+			    longest_where = (size_t) n;
+			}
+		    }
+		}
+	    }
+
+	  /* Try to find the symbol among the local symbols.  */
+	  if (sym_mem[nentries_used].where[0] == '\0')
+	    {
+	      struct local_name fake =
+		{
+		  .name = symstr,
+		  .lowpc = sym->st_value,
+		  .highpc = sym->st_value,
+		};
+	      struct local_name **found = tfind (&fake, &local_root,
+						 local_compare);
+	      if (found != NULL)
+		{
+		  /* We found the line.  */
+		  int n = obstack_printf (&whereob, "%s:%" PRIu64 "%c",
+					  xbasename ((*found)->file),
+					  (*found)->lineno,
+					  '\0');
+		  sym_mem[nentries_used].where = obstack_finish (&whereob);
+
+		  /* The return value of obstack_print included the
+		     NUL byte, so subtract one.  */
+		  if (--n > (int) longest_where)
+		    longest_where = (size_t) n;
+		}
+	    }
+	}
+
+      /* We use this entry.  */
+      ++nentries_used;
+    }
+#ifdef USE_DEMANGLE
+  free (demangle_buffer);
+#endif
+  /* Now we know the exact number.  */
+  size_t nentries_orig = nentries;
+  nentries = nentries_used;
+
+  /* Sort the entries according to the users wishes.  */
+  if (sort == sort_name)
+    {
+      sort_by_name_elf = ebl->elf;
+      sort_by_name_ndx = shdr->sh_link;
+      qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_name);
+    }
+  else if (sort == sort_numeric)
+    qsort (sym_mem, nentries, sizeof (GElf_SymX), sort_by_address);
+
+  /* Finally print according to the users selection.  */
+  switch (format)
+    {
+    case format_sysv:
+      show_symbols_sysv (ebl, shdr->sh_link, fullname, sym_mem, nentries,
+			 longest_name, longest_where);
+      break;
+
+    case format_bsd:
+      show_symbols_bsd (ebl->elf, ehdr, shdr->sh_link, prefix, fname, fullname,
+			sym_mem, nentries);
+      break;
+
+    case format_posix:
+    default:
+      assert (format == format_posix);
+      show_symbols_posix (ebl->elf, ehdr, shdr->sh_link, prefix, fullname,
+			  sym_mem, nentries);
+      break;
+    }
+
+  /* Free all memory.  */
+  if (nentries_orig * sizeof (sym_mem[0]) >= MAX_STACK_ALLOC)
+    free (sym_mem);
+
+  obstack_free (&whereob, NULL);
+
+  if (dbg != NULL)
+    {
+      tdestroy (global_root, free);
+      global_root = NULL;
+
+      tdestroy (local_root, free);
+      local_root = NULL;
+
+      if (dwfl == NULL)
+	(void) dwarf_end (dbg);
+    }
+  if (dwfl != NULL)
+    dwfl_end (dwfl);
+}
+
+
+static int
+handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
+	    const char *suffix)
+{
+  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
+  size_t fname_len = strlen (fname) + 1;
+  char fullname[prefix_len + 1 + fname_len + suffix_len];
+  char *cp = fullname;
+  Elf_Scn *scn = NULL;
+  int any = 0;
+  int result = 0;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  Ebl *ebl;
+
+  /* Create the full name of the file.  */
+  if (prefix != NULL)
+    cp = mempcpy (cp, prefix, prefix_len);
+  cp = mempcpy (cp, fname, fname_len);
+  if (suffix != NULL)
+    memcpy (cp - 1, suffix, suffix_len + 1);
+
+  /* Get the backend for this object file type.  */
+  ebl = ebl_openbackend (elf);
+  if (ebl == NULL)
+    INTERNAL_ERROR (fullname);
+
+  /* We need the ELF header in a few places.  */
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    INTERNAL_ERROR (fullname);
+
+  /* If we are asked to print the dynamic symbol table and this is
+     executable or dynamic executable, fail.  */
+  if (symsec_type == SHT_DYNSYM
+      && ehdr->e_type != ET_EXEC && ehdr->e_type != ET_DYN)
+    {
+      /* XXX Add machine specific object file types.  */
+      error (0, 0, _("%s%s%s%s: Invalid operation"),
+	     prefix ?: "", prefix ? "(" : "", fname, prefix ? ")" : "");
+      result = 1;
+      goto out;
+    }
+
+  /* Find the symbol table.
+
+     XXX Can there be more than one?  Do we print all?  Currently we do.  */
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fullname);
+
+      if (shdr->sh_type == symsec_type)
+	{
+	  Elf_Scn *xndxscn = NULL;
+
+	  /* We have a symbol table.  First make sure we remember this.  */
+	  any = 1;
+
+	  /* Look for an extended section index table for this section.  */
+	  if (symsec_type == SHT_SYMTAB)
+	    {
+	      size_t scnndx = elf_ndxscn (scn);
+
+	      while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
+		{
+		  GElf_Shdr xndxshdr_mem;
+		  GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
+
+		  if (xndxshdr == NULL)
+		    INTERNAL_ERROR (fullname);
+
+		  if (xndxshdr->sh_type == SHT_SYMTAB_SHNDX
+		      && xndxshdr->sh_link == scnndx)
+		    break;
+		}
+	    }
+
+	  show_symbols (fd, ebl, ehdr, scn, xndxscn, shdr, prefix, fname,
+			fullname);
+	}
+    }
+
+  if (! any)
+    {
+      error (0, 0, _("%s%s%s: no symbols"),
+	     prefix ?: "", prefix ? ":" : "", fname);
+      result = 1;
+    }
+
+ out:
+  /* Close the ELF backend library descriptor.  */
+  ebl_closebackend (ebl);
+
+  return result;
+}
+
+
+#include "debugpred.h"
diff --git a/src/objdump.c b/src/objdump.c
new file mode 100644
index 0000000..d43c1dd
--- /dev/null
+++ b/src/objdump.c
@@ -0,0 +1,795 @@
+/* Print information from ELF file in human-readable form.
+   Copyright (C) 2005, 2006, 2007, 2009, 2011, 2012, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <libeu.h>
+#include <system.h>
+#include <color.h>
+#include <printversion.h>
+#include "../libebl/libeblP.h"
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Mode selection:"), 0 },
+  { "reloc", 'r', NULL, 0, N_("Display relocation information."), 0 },
+  { "full-contents", 's', NULL, 0,
+    N_("Display the full contents of all sections requested"), 0 },
+  { "disassemble", 'd', NULL, 0,
+    N_("Display assembler code of executable sections"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output content selection:"), 0 },
+  { "section", 'j', "NAME", 0,
+    N_("Only display information for section NAME."), 0 },
+
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Show information from FILEs (a.out by default).");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Parser children.  */
+static struct argp_child argp_children[] =
+  {
+    { &color_argp, 0, N_("Output formatting"), 2 },
+    { NULL, 0, NULL, 0}
+  };
+
+/* Data structure to communicate with argp functions.  */
+static const struct argp argp =
+{
+  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
+};
+
+
+/* Print symbols in file named FNAME.  */
+static int process_file (const char *fname, bool more_than_one);
+
+/* Handle content of archive.  */
+static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
+		      const char *suffix);
+
+/* Handle ELF file.  */
+static int handle_elf (Elf *elf, const char *prefix, const char *fname,
+		       const char *suffix);
+
+
+#define INTERNAL_ERROR(fname) \
+  error_exit (0, _("%s: INTERNAL ERROR %d (%s): %s"),      \
+	      fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
+
+
+/* List of sections which should be used.  */
+static struct section_list
+{
+  bool is_name;
+  union
+  {
+    const char *name;
+    uint32_t scnndx;
+  };
+  struct section_list *next;
+} *section_list;
+
+
+/* If true print archive index.  */
+static bool print_relocs;
+
+/* If true print full contents of requested sections.  */
+static bool print_full_content;
+
+/* If true print disassembled output..  */
+static bool print_disasm;
+
+
+int
+main (int argc, char *argv[])
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Tell the library which version we are expecting.  */
+  (void) elf_version (EV_CURRENT);
+
+  int result = 0;
+  if (remaining == argc)
+    /* The user didn't specify a name so we use a.out.  */
+    result = process_file ("a.out", false);
+  else
+    {
+      /* Process all the remaining files.  */
+      const bool more_than_one = remaining + 1 < argc;
+
+      do
+	result |= process_file (argv[remaining], more_than_one);
+      while (++remaining < argc);
+    }
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  /* True if any of the control options is set.  */
+  static bool any_control_option;
+
+  switch (key)
+    {
+    case 'j':
+      {
+	struct section_list *newp = xmalloc (sizeof (*newp));
+	char *endp;
+	newp->scnndx = strtoul (arg, &endp, 0);
+	if (*endp == 0)
+	  newp->is_name = false;
+	else
+	  {
+	    newp->name = arg;
+	    newp->is_name = true;
+	  }
+	newp->next = section_list;
+	section_list = newp;
+      }
+      any_control_option = true;
+      break;
+
+    case 'd':
+      print_disasm = true;
+      any_control_option = true;
+      break;
+
+    case 'r':
+      print_relocs = true;
+      any_control_option = true;
+      break;
+
+    case 's':
+      print_full_content = true;
+      any_control_option = true;
+      break;
+
+    case ARGP_KEY_FINI:
+      if (! any_control_option)
+	{
+	  fputs (_("No operation specified.\n"), stderr);
+	  argp_help (&argp, stderr, ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (EXIT_FAILURE);
+	}
+      /* We only use this for checking the number of arguments, we don't
+	 actually want to consume them.  */
+      FALLTHROUGH;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Open the file and determine the type.  */
+static int
+process_file (const char *fname, bool more_than_one)
+{
+  /* Open the file.  */
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      error (0, errno, _("cannot open %s"), fname);
+      return 1;
+    }
+
+  /* Now get the ELF descriptor.  */
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf != NULL)
+    {
+      if (elf_kind (elf) == ELF_K_ELF)
+	{
+	  int result = handle_elf (elf, more_than_one ? "" : NULL,
+				   fname, NULL);
+
+	  if (elf_end (elf) != 0)
+	    INTERNAL_ERROR (fname);
+
+	  if (close (fd) != 0)
+	    error_exit (errno, _("while close `%s'"), fname);
+
+	  return result;
+	}
+      else if (elf_kind (elf) == ELF_K_AR)
+	{
+	  int result = handle_ar (fd, elf, NULL, fname, NULL);
+
+	  if (elf_end (elf) != 0)
+	    INTERNAL_ERROR (fname);
+
+	  if (close (fd) != 0)
+	    error_exit (errno, _("while close `%s'"), fname);
+
+	  return result;
+	}
+
+      /* We cannot handle this type.  Close the descriptor anyway.  */
+      if (elf_end (elf) != 0)
+	INTERNAL_ERROR (fname);
+    }
+
+  error (0, 0, _("%s: File format not recognized"), fname);
+
+  return 1;
+}
+
+
+static int
+handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
+	   const char *suffix)
+{
+  size_t fname_len = strlen (fname) + 1;
+  size_t prefix_len = prefix != NULL ? strlen (prefix) : 0;
+  char new_prefix[prefix_len + fname_len + 2];
+  size_t suffix_len = suffix != NULL ? strlen (suffix) : 0;
+  char new_suffix[suffix_len + 2];
+  Elf *subelf;
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  int result = 0;
+
+  char *cp = new_prefix;
+  if (prefix != NULL)
+    cp = stpcpy (cp, prefix);
+  cp = stpcpy (cp, fname);
+  stpcpy (cp, "[");
+
+  cp = new_suffix;
+  if (suffix != NULL)
+    cp = stpcpy (cp, suffix);
+  stpcpy (cp, "]");
+
+  /* Process all the files contained in the archive.  */
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      /* The the header for this element.  */
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      /* Skip over the index entries.  */
+      if (strcmp (arhdr->ar_name, "/") != 0
+	  && strcmp (arhdr->ar_name, "//") != 0)
+	{
+	  if (elf_kind (subelf) == ELF_K_ELF)
+	    result |= handle_elf (subelf, new_prefix, arhdr->ar_name,
+				  new_suffix);
+	  else if (elf_kind (subelf) == ELF_K_AR)
+	    result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name,
+				 new_suffix);
+	  else
+	    {
+	      error (0, 0, _("%s%s%s: file format not recognized"),
+		     new_prefix, arhdr->ar_name, new_suffix);
+	      result = 1;
+	    }
+	}
+
+      /* Get next archive element.  */
+      cmd = elf_next (subelf);
+      if (elf_end (subelf) != 0)
+	INTERNAL_ERROR (fname);
+    }
+
+  return result;
+}
+
+
+static void
+show_relocs_x (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *symdata,
+	       Elf_Data *xndxdata, size_t symstrndx, size_t shstrndx,
+	       GElf_Addr r_offset, GElf_Xword r_info, GElf_Sxword r_addend)
+{
+  int elfclass = gelf_getclass (ebl->elf);
+  char buf[128];
+
+  printf ("%0*" PRIx64 " %-20s ",
+	  elfclass == ELFCLASS32 ? 8 : 16, r_offset,
+	  ebl_reloc_type_name (ebl, GELF_R_TYPE (r_info), buf, sizeof (buf)));
+
+  Elf32_Word xndx;
+  GElf_Sym symmem;
+  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata, GELF_R_SYM (r_info),
+				    &symmem, &xndx);
+
+  if (sym == NULL)
+    printf ("<%s %ld>",
+	    _("INVALID SYMBOL"), (long int) GELF_R_SYM (r_info));
+  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
+    printf ("%s",
+	    elf_strptr (ebl->elf, symstrndx, sym->st_name));
+  else
+    {
+      GElf_Shdr destshdr_mem;
+      GElf_Shdr *destshdr;
+      destshdr = gelf_getshdr (elf_getscn (ebl->elf,
+					   sym->st_shndx == SHN_XINDEX
+					   ? xndx : sym->st_shndx),
+			       &destshdr_mem);
+
+      if (shdr == NULL || destshdr == NULL)
+	printf ("<%s %ld>",
+		_("INVALID SECTION"),
+		(long int) (sym->st_shndx == SHN_XINDEX
+			    ? xndx : sym->st_shndx));
+      else
+	printf ("%s",
+		elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
+    }
+
+  if (r_addend != 0)
+    {
+      char sign = '+';
+      if (r_addend < 0)
+	{
+	  sign = '-';
+	  r_addend = -r_addend;
+	}
+      printf ("%c%#" PRIx64, sign, r_addend);
+    }
+  putchar ('\n');
+}
+
+
+static void
+show_relocs_rel (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
+		 Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
+		 size_t shstrndx)
+{
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
+  int nentries = shdr->sh_size / sh_entsize;
+
+  for (int cnt = 0; cnt < nentries; ++cnt)
+    {
+      GElf_Rel relmem;
+      GElf_Rel *rel;
+
+      rel = gelf_getrel (data, cnt, &relmem);
+      if (rel != NULL)
+	show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
+		       rel->r_offset, rel->r_info, 0);
+    }
+}
+
+
+static void
+show_relocs_rela (Ebl *ebl, GElf_Shdr *shdr, Elf_Data *data,
+		  Elf_Data *symdata, Elf_Data *xndxdata, size_t symstrndx,
+		  size_t shstrndx)
+{
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
+  int nentries = shdr->sh_size / sh_entsize;
+
+  for (int cnt = 0; cnt < nentries; ++cnt)
+    {
+      GElf_Rela relmem;
+      GElf_Rela *rel;
+
+      rel = gelf_getrela (data, cnt, &relmem);
+      if (rel != NULL)
+	show_relocs_x (ebl, shdr, symdata, xndxdata, symstrndx, shstrndx,
+		       rel->r_offset, rel->r_info, rel->r_addend);
+    }
+}
+
+
+static bool
+section_match (Elf *elf, uint32_t scnndx, GElf_Shdr *shdr, size_t shstrndx)
+{
+  if (section_list == NULL)
+    return true;
+
+  struct section_list *runp = section_list;
+  const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
+
+  do
+    {
+      if (runp->is_name)
+	{
+	  if (name && strcmp (runp->name, name) == 0)
+	    return true;
+	}
+      else
+	{
+	  if (runp->scnndx == scnndx)
+	    return true;
+	}
+
+      runp = runp->next;
+    }
+  while (runp != NULL);
+
+  return false;
+}
+
+
+static int
+show_relocs (Ebl *ebl, const char *fname, uint32_t shstrndx)
+{
+  int elfclass = gelf_getclass (ebl->elf);
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fname);
+
+      if (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA)
+	{
+	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+	    continue;
+
+	  GElf_Shdr destshdr_mem;
+	  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf,
+							  shdr->sh_info),
+					      &destshdr_mem);
+	  if (unlikely (destshdr == NULL))
+	    continue;
+
+	  printf (_("\nRELOCATION RECORDS FOR [%s]:\n"
+			   "%-*s TYPE                 VALUE\n"),
+		  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
+		  elfclass == ELFCLASS32 ? 8 : 16, _("OFFSET"));
+
+	  /* Get the data of the section.  */
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    continue;
+
+	  /* Get the symbol table information.  */
+	  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+	  GElf_Shdr symshdr_mem;
+	  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+	  Elf_Data *symdata = elf_getdata (symscn, NULL);
+	  if (unlikely (symshdr == NULL || symdata == NULL))
+	    continue;
+
+	  /* Search for the optional extended section index table.  */
+	  Elf_Data *xndxdata = NULL;
+	  Elf_Scn *xndxscn = NULL;
+	  while ((xndxscn = elf_nextscn (ebl->elf, xndxscn)) != NULL)
+	    {
+	      GElf_Shdr xndxshdr_mem;
+	      GElf_Shdr *xndxshdr;
+
+	      xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
+	      if (xndxshdr != NULL && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
+		  && xndxshdr->sh_link == elf_ndxscn (symscn))
+		{
+		  /* Found it.  */
+		  xndxdata = elf_getdata (xndxscn, NULL);
+		  break;
+		}
+	    }
+
+	  if (shdr->sh_type == SHT_REL)
+	    show_relocs_rel (ebl, shdr, data, symdata, xndxdata,
+			     symshdr->sh_link, shstrndx);
+	  else
+	    show_relocs_rela (ebl, shdr, data, symdata, xndxdata,
+			      symshdr->sh_link, shstrndx);
+
+	  putchar ('\n');
+	}
+    }
+
+  return 0;
+}
+
+
+static int
+show_full_content (Ebl *ebl, const char *fname, uint32_t shstrndx)
+{
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fname);
+
+      if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0)
+	{
+	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+	    continue;
+
+	  printf (_("Contents of section %s:\n"),
+		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+
+	  /* Get the data of the section.  */
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    continue;
+
+	  unsigned char *cp = data->d_buf;
+	  size_t cnt;
+	  for (cnt = 0; cnt + 16 < data->d_size; cp += 16, cnt += 16)
+	    {
+	      printf (" %04zx ", cnt);
+
+	      for (size_t inner = 0; inner < 16; inner += 4)
+		printf ("%02hhx%02hhx%02hhx%02hhx ",
+			cp[inner], cp[inner + 1], cp[inner + 2],
+			cp[inner + 3]);
+	      fputc_unlocked (' ', stdout);
+
+	      for (size_t inner = 0; inner < 16; ++inner)
+		fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
+				? cp[inner] : '.', stdout);
+	      fputc_unlocked ('\n', stdout);
+	    }
+
+	  printf (" %04zx ", cnt);
+
+	  size_t remaining = data->d_size - cnt;
+	  size_t inner;
+	  for (inner = 0; inner + 4 <= remaining; inner += 4)
+	    printf ("%02hhx%02hhx%02hhx%02hhx ",
+		    cp[inner], cp[inner + 1], cp[inner + 2], cp[inner + 3]);
+
+	  for (; inner < remaining; ++inner)
+	    printf ("%02hhx", cp[inner]);
+
+	  for (inner = 2 * (16 - inner) + (16 - inner + 3) / 4 + 1; inner > 0;
+	       --inner)
+	    fputc_unlocked (' ', stdout);
+
+	  for (inner = 0; inner < remaining; ++inner)
+	    fputc_unlocked (isascii (cp[inner]) && isprint (cp[inner])
+			    ? cp[inner] : '.', stdout);
+	  fputc_unlocked ('\n', stdout);
+
+	  fputc_unlocked ('\n', stdout);
+	}
+    }
+
+  return 0;
+}
+
+
+struct disasm_info
+{
+  GElf_Addr addr;
+  const uint8_t *cur;
+  const uint8_t *last_end;
+  const char *address_color;
+  const char *bytes_color;
+};
+
+
+// XXX This is not the preferred output for all architectures.  Needs
+// XXX customization, too.
+static int
+disasm_output (char *buf, size_t buflen, void *arg)
+{
+  struct disasm_info *info = (struct disasm_info *) arg;
+
+  if (info->address_color != NULL)
+    printf ("%s%8" PRIx64 "%s:   ",
+	    info->address_color, (uint64_t) info->addr, color_off);
+  else
+    printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
+
+  if (info->bytes_color != NULL)
+    fputs_unlocked (info->bytes_color, stdout);
+  size_t cnt;
+  for (cnt = 0; cnt < (size_t) MIN (info->cur - info->last_end, 8); ++cnt)
+    printf (" %02" PRIx8, info->last_end[cnt]);
+  if (info->bytes_color != NULL)
+    fputs_unlocked (color_off, stdout);
+
+  printf ("%*s %.*s\n",
+	  (int) (8 - cnt) * 3 + 1, "", (int) buflen, buf);
+
+  info->addr += cnt;
+
+  /* We limit the number of bytes printed before the mnemonic to 8.
+     Print the rest on a separate, following line.  */
+  if (info->cur - info->last_end > 8)
+    {
+      if (info->address_color != NULL)
+	printf ("%s%8" PRIx64 "%s:   ",
+		info->address_color, (uint64_t) info->addr, color_off);
+      else
+	printf ("%8" PRIx64 ":   ", (uint64_t) info->addr);
+
+      if (info->bytes_color != NULL)
+	fputs_unlocked (info->bytes_color, stdout);
+      for (; cnt < (size_t) (info->cur - info->last_end); ++cnt)
+	printf (" %02" PRIx8, info->last_end[cnt]);
+      if (info->bytes_color != NULL)
+	fputs_unlocked (color_off, stdout);
+      putchar_unlocked ('\n');
+      info->addr += info->cur - info->last_end - 8;
+    }
+
+  info->last_end = info->cur;
+
+  return 0;
+}
+
+
+static int
+show_disasm (Ebl *ebl, const char *fname, uint32_t shstrndx)
+{
+  DisasmCtx_t *ctx = disasm_begin (ebl, ebl->elf, NULL /* XXX TODO */);
+  if (ctx == NULL)
+    error_exit (0, _("cannot disassemble"));
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fname);
+
+      if (shdr->sh_type == SHT_PROGBITS && shdr->sh_size > 0
+	  && (shdr->sh_flags & SHF_EXECINSTR) != 0)
+	{
+	  if  (! section_match (ebl->elf, elf_ndxscn (scn), shdr, shstrndx))
+	    continue;
+
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    continue;
+
+	  printf ("Disassembly of section %s:\n\n",
+		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+
+	  struct disasm_info info;
+	  info.addr = shdr->sh_addr;
+	  info.last_end = info.cur = data->d_buf;
+	  char *fmt;
+	  if (color_mode)
+	    {
+	      info.address_color = color_address;
+	      info.bytes_color = color_bytes;
+
+	      fmt = xasprintf ("%s%%7m %s%%.1o,%s%%.2o,%s%%.3o,,%s%%.4o%s%%.5o%%34a %s%%l",
+			       color_mnemonic ?: "",
+			       color_operand1 ?: "",
+			       color_operand2 ?: "",
+			       color_operand3 ?: "",
+			       color_operand4 ?: "",
+			       color_operand5 ?: "",
+			       color_label ?: "");
+	    }
+	  else
+	    {
+	      info.address_color = info.bytes_color = NULL;
+
+	      fmt = "%7m %.1o,%.2o,%.3o,%.4o,%.5o%34a %l";
+	    }
+
+	  disasm_cb (ctx, &info.cur, info.cur + data->d_size, info.addr,
+		     fmt, disasm_output, &info, NULL /* XXX */);
+
+	  if (color_mode)
+	    free (fmt);
+	}
+    }
+
+  (void) disasm_end (ctx);
+
+  return 0;
+}
+
+
+static int
+handle_elf (Elf *elf, const char *prefix, const char *fname,
+	    const char *suffix)
+{
+
+  /* Get the backend for this object file type.  */
+  Ebl *ebl = ebl_openbackend (elf);
+  if (ebl == NULL)
+    error_exit (0, _("cannot create backend for elf file"));
+
+  printf ("%s: elf%d-%s\n\n",
+	  fname, gelf_getclass (elf) == ELFCLASS32 ? 32 : 64,
+	  ebl_backend_name (ebl));
+
+  /* Create the full name of the file.  */
+  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t suffix_len = suffix == NULL ? 0 : strlen (suffix);
+  size_t fname_len = strlen (fname) + 1;
+  char fullname[prefix_len + 1 + fname_len + suffix_len];
+  char *cp = fullname;
+  if (prefix != NULL)
+    cp = mempcpy (cp, prefix, prefix_len);
+  cp = mempcpy (cp, fname, fname_len);
+  if (suffix != NULL)
+    memcpy (cp - 1, suffix, suffix_len + 1);
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
+    error_exit (0, _("cannot get section header string table index"));
+
+  int result = 0;
+  if (print_disasm)
+    result = show_disasm (ebl, fullname, shstrndx);
+  if (print_relocs && !print_disasm)
+    result = show_relocs (ebl, fullname, shstrndx);
+  if (print_full_content)
+    result = show_full_content (ebl, fullname, shstrndx);
+
+  /* Close the ELF backend library descriptor.  */
+  ebl_closebackend (ebl);
+
+  return result;
+}
+
+
+#include "debugpred.h"
diff --git a/src/ranlib.c b/src/ranlib.c
new file mode 100644
index 0000000..7838d69
--- /dev/null
+++ b/src/ranlib.c
@@ -0,0 +1,286 @@
+/* Generate an index to speed access to archives.
+   Copyright (C) 2005-2012 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ar.h>
+#include <argp.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <locale.h>
+#include <obstack.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <system.h>
+#include <printversion.h>
+
+#include "arlib.h"
+
+
+/* Prototypes for local functions.  */
+static int handle_file (const char *fname);
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("Generate an index to speed access to archives.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("ARCHIVE");
+
+/* Data structure to communicate with argp functions.  */
+static const struct argp argp =
+{
+  options, NULL, args_doc, doc, arlib_argp_children, NULL, NULL
+};
+
+
+int
+main (int argc, char *argv[])
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &remaining, NULL);
+
+  /* Tell the library which version we are expecting.  */
+  (void) elf_version (EV_CURRENT);
+
+  /* There must at least be one more parameter specifying the archive.   */
+  if (remaining == argc)
+    {
+      error (0, 0, _("Archive name required"));
+      argp_help (&argp, stderr, ARGP_HELP_SEE, "ranlib");
+      exit (EXIT_FAILURE);
+    }
+
+  /* We accept the names of multiple archives.  */
+  int status = 0;
+  do
+    status |= handle_file (argv[remaining]);
+  while (++remaining < argc);
+
+  return status;
+}
+
+
+static int
+copy_content (Elf *elf, int newfd, off_t off, size_t n)
+{
+  size_t len;
+  char *rawfile = elf_rawfile (elf, &len);
+
+  assert (off + n <= len);
+
+  /* Tell the kernel we will read all the pages sequentially.  */
+  size_t ps = sysconf (_SC_PAGESIZE);
+  if (n > 2 * ps)
+    posix_madvise (rawfile + (off & ~(ps - 1)), n, POSIX_MADV_SEQUENTIAL);
+
+  return write_retry (newfd, rawfile + off, n) != (ssize_t) n;
+}
+
+
+/* Handle a file given on the command line.  */
+static int
+handle_file (const char *fname)
+{
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      error (0, errno, _("cannot open '%s'"), fname);
+      return 1;
+    }
+
+  struct stat st;
+  if (fstat (fd, &st) != 0)
+    {
+      error (0, errno, _("cannot stat '%s'"), fname);
+      close (fd);
+      return 1;
+    }
+
+  /* First we walk through the file, looking for all ELF files to
+     collect symbols from.  */
+  Elf *arelf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (arelf == NULL)
+    {
+      error (0, 0, _("cannot create ELF descriptor for '%s': %s"),
+	     fname, elf_errmsg (-1));
+      close (fd);
+      return 1;
+    }
+
+  if (elf_kind (arelf) != ELF_K_AR)
+    {
+      error (0, 0, _("'%s' is no archive"), fname);
+      elf_end (arelf);
+      close (fd);
+      return 1;
+    }
+
+  arlib_init ();
+
+  /* Iterate over the content of the archive.  */
+  off_t index_off = -1;
+  size_t index_size = 0;
+  off_t cur_off = SARMAG;
+  Elf *elf;
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  while ((elf = elf_begin (fd, cmd, arelf)) != NULL)
+    {
+      Elf_Arhdr *arhdr = elf_getarhdr (elf);
+      assert (arhdr != NULL);
+
+      /* If this is the index, remember the location.  */
+      if (strcmp (arhdr->ar_name, "/") == 0)
+	{
+	  index_off = elf_getaroff (elf);
+	  index_size = arhdr->ar_size;
+	}
+      else
+	{
+	  arlib_add_symbols (elf, fname, arhdr->ar_name, cur_off);
+	  cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1))
+		      + sizeof (struct ar_hdr));
+	}
+
+      /* Get next archive element.  */
+      cmd = elf_next (elf);
+      if (elf_end (elf) != 0)
+	error (0, 0, _("error while freeing sub-ELF descriptor: %s"),
+	       elf_errmsg (-1));
+    }
+
+  arlib_finalize ();
+
+  /* If the file contains no symbols we need not do anything.  */
+  int status = 0;
+  if (symtab.symsnamelen != 0
+      /* We have to rewrite the file also if it initially had an index
+	 but now does not need one anymore.  */
+      || (symtab.symsnamelen == 0 && index_size != 0))
+    {
+      /* Create a new, temporary file in the same directory as the
+	 original file.  */
+      char tmpfname[strlen (fname) + 7];
+      strcpy (stpcpy (tmpfname, fname), "XXXXXX");
+      int newfd = mkstemp (tmpfname);
+      if (unlikely (newfd == -1))
+	{
+	nonew:
+	  error (0, errno, _("cannot create new file"));
+	  status = 1;
+	}
+      else
+	{
+	  /* Create the header.  */
+	  if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG))
+	    {
+	      // XXX Use /prof/self/fd/%d ???
+	    nonew_unlink:
+	      unlink (tmpfname);
+	      if (newfd != -1)
+		close (newfd);
+	      goto nonew;
+	    }
+
+	  /* Create the new file.  There are three parts as far we are
+	     concerned: 1. original context before the index, 2. the
+	     new index, 3. everything after the new index.  */
+	  off_t rest_off;
+	  if (index_off != -1)
+	    rest_off = (index_off + sizeof (struct ar_hdr)
+			+ ((index_size + 1) & ~1ul));
+	  else
+	    rest_off = SARMAG;
+
+	  if (symtab.symsnamelen != 0
+	      && ((write_retry (newfd, symtab.symsoff,
+				symtab.symsofflen)
+		   != (ssize_t) symtab.symsofflen)
+		  || (write_retry (newfd, symtab.symsname,
+				   symtab.symsnamelen)
+		      != (ssize_t) symtab.symsnamelen)))
+	    goto nonew_unlink;
+
+	  /* Even if the original file had content before the
+	     symbol table, we write it in the correct order.  */
+	  if ((index_off > SARMAG
+	       && copy_content (arelf, newfd, SARMAG, index_off - SARMAG))
+	      || copy_content (arelf, newfd, rest_off, st.st_size - rest_off))
+	    goto nonew_unlink;
+
+	  /* Never complain about fchown failing.  */
+	  if (fchown (newfd, st.st_uid, st.st_gid) != 0) { ; }
+	  /* Set the mode of the new file to the same values the
+	     original file has.  */
+	  if (fchmod (newfd, st.st_mode & ALLPERMS) != 0
+	      || close (newfd) != 0)
+	    goto nonew_unlink;
+	  newfd = -1;
+	  if (rename (tmpfname, fname) != 0)
+	    goto nonew_unlink;
+	}
+    }
+
+  elf_end (arelf);
+
+  arlib_fini ();
+
+  close (fd);
+
+  return status;
+}
+
+
+#include "debugpred.h"
diff --git a/src/readelf.c b/src/readelf.c
new file mode 100644
index 0000000..0e93118
--- /dev/null
+++ b/src/readelf.c
@@ -0,0 +1,13562 @@
+/* Print information from ELF file in human-readable form.
+   Copyright (C) 1999-2018 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <ctype.h>
+#include <dwarf.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <langinfo.h>
+#include <libdw.h>
+#include <libdwfl.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <signal.h>
+
+#include <libeu.h>
+#include <system.h>
+#include <printversion.h>
+#include "../libelf/libelfP.h"
+#include "../libelf/common.h"
+#include "../libebl/libeblP.h"
+#include "../libdwelf/libdwelf.h"
+#include "../libdw/libdwP.h"
+#include "../libdwfl/libdwflP.h"
+#include "../libdw/memory-access.h"
+
+#include "../libdw/known-dwarf.h"
+
+#ifdef __linux__
+#define CORE_SIGILL  SIGILL
+#define CORE_SIGBUS  SIGBUS
+#define CORE_SIGFPE  SIGFPE
+#define CORE_SIGSEGV SIGSEGV
+#define CORE_SI_USER SI_USER
+#else
+/* We want the linux version of those as that is what shows up in the core files. */
+#define CORE_SIGILL  4  /* Illegal instruction (ANSI).  */
+#define CORE_SIGBUS  7  /* BUS error (4.2 BSD).  */
+#define CORE_SIGFPE  8  /* Floating-point exception (ANSI).  */
+#define CORE_SIGSEGV 11 /* Segmentation violation (ANSI).  */
+#define CORE_SI_USER 0  /* Sent by kill, sigsend.  */
+#endif
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* argp key value for --elf-section, non-ascii.  */
+#define ELF_INPUT_SECTION 256
+
+/* argp key value for --dwarf-skeleton, non-ascii.  */
+#define DWARF_SKELETON 257
+
+/* argp key value for --dyn-syms, non-ascii.  */
+#define PRINT_DYNSYM_TABLE 258
+
+/* Terrible hack for hooking unrelated skeleton/split compile units,
+   see __libdw_link_skel_split in print_debug.  */
+static bool do_not_close_dwfl = false;
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("ELF input selection:"), 0 },
+  { "elf-section", ELF_INPUT_SECTION, "SECTION", OPTION_ARG_OPTIONAL,
+    N_("Use the named SECTION (default .gnu_debugdata) as (compressed) ELF "
+       "input data"), 0 },
+  { "dwarf-skeleton", DWARF_SKELETON, "FILE", 0,
+    N_("Used with -w to find the skeleton Compile Units in FILE associated "
+       "with the Split Compile units in a .dwo input file"), 0 },
+  { NULL, 0, NULL, 0, N_("ELF output selection:"), 0 },
+  { "all", 'a', NULL, 0,
+    N_("All these plus -p .strtab -p .dynstr -p .comment"), 0 },
+  { "dynamic", 'd', NULL, 0, N_("Display the dynamic segment"), 0 },
+  { "file-header", 'h', NULL, 0, N_("Display the ELF file header"), 0 },
+  { "histogram", 'I', NULL, 0,
+    N_("Display histogram of bucket list lengths"), 0 },
+  { "program-headers", 'l', NULL, 0, N_("Display the program headers"), 0 },
+  { "segments", 'l', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
+  { "relocs", 'r', NULL, 0, N_("Display relocations"), 0 },
+  { "section-groups", 'g', NULL, 0, N_("Display the section groups"), 0 },
+  { "section-headers", 'S', NULL, 0, N_("Display the sections' headers"), 0 },
+  { "sections", 'S', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
+  { "symbols", 's', "SECTION", OPTION_ARG_OPTIONAL,
+    N_("Display the symbol table sections"), 0 },
+  { "syms", 's', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
+  { "dyn-syms", PRINT_DYNSYM_TABLE, NULL, 0,
+    N_("Display (only) the dynamic symbol table"), 0 },
+  { "version-info", 'V', NULL, 0, N_("Display versioning information"), 0 },
+  { "notes", 'n', "SECTION", OPTION_ARG_OPTIONAL, N_("Display the ELF notes"), 0 },
+  { "arch-specific", 'A', NULL, 0,
+    N_("Display architecture specific information, if any"), 0 },
+  { "exception", 'e', NULL, 0,
+    N_("Display sections for exception handling"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Additional output selection:"), 0 },
+  { "debug-dump", 'w', "SECTION", OPTION_ARG_OPTIONAL,
+    N_("Display DWARF section content.  SECTION can be one of abbrev, addr, "
+       "aranges, decodedaranges, frame, gdb_index, info, info+, loc, line, "
+       "decodedline, ranges, pubnames, str, macinfo, macro or exception"), 0 },
+  { "hex-dump", 'x', "SECTION", 0,
+    N_("Dump the uninterpreted contents of SECTION, by number or name"), 0 },
+  { "strings", 'p', "SECTION", OPTION_ARG_OPTIONAL,
+    N_("Print string contents of sections"), 0 },
+  { "string-dump", 'p', NULL, OPTION_ALIAS | OPTION_HIDDEN, NULL, 0 },
+  { "archive-index", 'c', NULL, 0,
+    N_("Display the symbol index of an archive"), 0 },
+  { "use-dynamic", 'D', NULL, 0,
+    N_("Use the dynamic segment when possible for displaying info"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output control:"), 0 },
+  { "numeric-addresses", 'N', NULL, 0,
+    N_("Do not find symbol names for addresses in DWARF data"), 0 },
+  { "unresolved-address-offsets", 'U', NULL, 0,
+    N_("Display just offsets instead of resolving values to addresses in DWARF data"), 0 },
+  { "wide", 'W', NULL, 0,
+    N_("Ignored for compatibility (lines always wide)"), 0 },
+  { "decompress", 'z', NULL, 0,
+    N_("Show compression information for compressed sections (when used with -S); decompress section before dumping data (when used with -p or -x)"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Print information from ELF file in human-readable form.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("FILE...");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+/* If non-null, the section from which we should read to (compressed) ELF.  */
+static const char *elf_input_section = NULL;
+
+/* If non-null, the file that contains the skeleton CUs.  */
+static const char *dwarf_skeleton = NULL;
+
+/* Flags set by the option controlling the output.  */
+
+/* True if dynamic segment should be printed.  */
+static bool print_dynamic_table;
+
+/* True if the file header should be printed.  */
+static bool print_file_header;
+
+/* True if the program headers should be printed.  */
+static bool print_program_header;
+
+/* True if relocations should be printed.  */
+static bool print_relocations;
+
+/* True if the section headers should be printed.  */
+static bool print_section_header;
+
+/* True if the symbol table should be printed.  */
+static bool print_symbol_table;
+
+/* True if (only) the dynsym table should be printed.  */
+static bool print_dynsym_table;
+
+/* True if reconstruct dynamic symbol table from the PT_DYNAMIC segment.  */
+static bool use_dynamic_segment;
+
+/* A specific section name, or NULL to print all symbol tables.  */
+static char *symbol_table_section;
+
+/* A specific section name, or NULL to print all ELF notes.  */
+static char *notes_section;
+
+/* True if the version information should be printed.  */
+static bool print_version_info;
+
+/* True if section groups should be printed.  */
+static bool print_section_groups;
+
+/* True if bucket list length histogram should be printed.  */
+static bool print_histogram;
+
+/* True if the architecture specific data should be printed.  */
+static bool print_arch;
+
+/* True if note section content should be printed.  */
+static bool print_notes;
+
+/* True if SHF_STRINGS section content should be printed.  */
+static bool print_string_sections;
+
+/* True if archive index should be printed.  */
+static bool print_archive_index;
+
+/* True if any of the control options except print_archive_index is set.  */
+static bool any_control_option;
+
+/* True if we should print addresses from DWARF in symbolic form.  */
+static bool print_address_names = true;
+
+/* True if we should print raw values instead of relativized addresses.  */
+static bool print_unresolved_addresses = false;
+
+/* True if we should print the .debug_aranges section using libdw.  */
+static bool decodedaranges = false;
+
+/* True if we should print the .debug_aranges section using libdw.  */
+static bool decodedline = false;
+
+/* True if we want to show more information about compressed sections.  */
+static bool print_decompress = false;
+
+/* True if we want to show split compile units for debug_info skeletons.  */
+static bool show_split_units = false;
+
+/* Select printing of debugging sections.  */
+static enum section_e
+{
+  section_abbrev = 1,		/* .debug_abbrev  */
+  section_aranges = 2,		/* .debug_aranges  */
+  section_frame = 4,		/* .debug_frame or .eh_frame & al.  */
+  section_info = 8,		/* .debug_info, (implies .debug_types)  */
+  section_line = 16,		/* .debug_line  */
+  section_loc = 32,		/* .debug_loc  */
+  section_pubnames = 64,	/* .debug_pubnames  */
+  section_str = 128,		/* .debug_str  */
+  section_macinfo = 256,	/* .debug_macinfo  */
+  section_ranges = 512, 	/* .debug_ranges  */
+  section_exception = 1024,	/* .eh_frame & al.  */
+  section_gdb_index = 2048,	/* .gdb_index  */
+  section_macro = 4096,		/* .debug_macro  */
+  section_addr = 8192,		/* .debug_addr  */
+  section_types = 16384,	/* .debug_types (implied by .debug_info)  */
+  section_all = (section_abbrev | section_aranges | section_frame
+		 | section_info | section_line | section_loc
+		 | section_pubnames | section_str | section_macinfo
+		 | section_ranges | section_exception | section_gdb_index
+		 | section_macro | section_addr | section_types)
+} print_debug_sections, implicit_debug_sections;
+
+/* Select hex dumping of sections.  */
+static struct section_argument *dump_data_sections;
+static struct section_argument **dump_data_sections_tail = &dump_data_sections;
+
+/* Select string dumping of sections.  */
+static struct section_argument *string_sections;
+static struct section_argument **string_sections_tail = &string_sections;
+
+struct section_argument
+{
+  struct section_argument *next;
+  const char *arg;
+  bool implicit;
+};
+
+/* Numbers of sections and program headers in the file.  */
+static size_t shnum;
+static size_t phnum;
+
+
+/* Declarations of local functions.  */
+static void process_file (int fd, const char *fname, bool only_one);
+static void process_elf_file (Dwfl_Module *dwflmod, int fd);
+static void print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr);
+static void print_shdr (Ebl *ebl, GElf_Ehdr *ehdr);
+static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
+static void print_scngrp (Ebl *ebl);
+static void print_dynamic (Ebl *ebl);
+static void print_relocs (Ebl *ebl, Dwfl_Module *mod, GElf_Ehdr *ehdr);
+static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+			       GElf_Shdr *shdr);
+static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+				GElf_Shdr *shdr);
+static void handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn,
+				GElf_Shdr *shdr);
+static bool print_symtab (Ebl *ebl, int type);
+static bool handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
+static bool handle_dynamic_symtab (Ebl *ebl);
+static void
+process_symtab(
+	Ebl * ebl,
+	unsigned int nsyms,
+	Elf64_Word idx,
+	Elf32_Word verneed_stridx,
+	Elf32_Word verdef_stridx,
+	Elf_Data * symdata,
+	Elf_Data * versym_data,
+	Elf_Data * symstr_data,
+	Elf_Data * verneed_data,
+	Elf_Data * verdef_data,
+	Elf_Data * xndx_data);
+static void print_verinfo (Ebl *ebl);
+static void handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
+static void handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
+static void handle_versym (Ebl *ebl, Elf_Scn *scn,
+			   GElf_Shdr *shdr);
+static void print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr);
+static void handle_hash (Ebl *ebl);
+static void handle_notes (Ebl *ebl, GElf_Ehdr *ehdr);
+static void print_liblist (Ebl *ebl);
+static void print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr);
+static void dump_data (Ebl *ebl);
+static void dump_strings (Ebl *ebl);
+static void print_strings (Ebl *ebl);
+static void dump_archive_index (Elf *, const char *);
+static void print_dwarf_addr (Dwfl_Module *dwflmod, int address_size,
+			      Dwarf_Addr address, Dwarf_Addr raw);
+
+enum dyn_idx
+{
+  i_symtab_shndx,
+  i_strsz,
+  i_verneed,
+  i_verneednum,
+  i_verdef,
+  i_verdefnum,
+  i_versym,
+  i_symtab,
+  i_strtab,
+  i_hash,
+  i_gnu_hash,
+  i_max
+};
+
+/* Declarations of local functions for use-dynamic.  */
+static Elf_Data *get_dynscn_strtab (Elf *elf, GElf_Phdr *phdr);
+static void get_dynscn_addrs (Elf *elf, GElf_Phdr *phdr, GElf_Addr addrs[i_max]);
+static void find_offsets (Elf *elf, GElf_Addr main_bias, size_t n,
+			  GElf_Addr addrs[n], GElf_Off offs[n]);
+
+/* Looked up once with gettext in main.  */
+static char *yes_str;
+static char *no_str;
+
+static void
+cleanup_list (struct section_argument *list)
+{
+  while (list != NULL)
+    {
+      struct section_argument *a = list;
+      list = a->next;
+      free (a);
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  setlocale (LC_ALL, "");
+
+  /* Initialize the message catalog.  */
+  textdomain (PACKAGE_TARNAME);
+
+  /* Look up once.  */
+  yes_str = _("yes");
+  no_str = _("no");
+
+  /* Parse and process arguments.  */
+  int remaining;
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Before we start tell the ELF library which version we are using.  */
+  elf_version (EV_CURRENT);
+
+  /* Now process all the files given at the command line.  */
+  bool only_one = remaining + 1 == argc;
+  do
+    {
+      /* Open the file.  */
+      int fd = open (argv[remaining], O_RDONLY);
+      if (fd == -1)
+	{
+	  error (0, errno, _("cannot open input file '%s'"), argv[remaining]);
+	  continue;
+	}
+
+      process_file (fd, argv[remaining], only_one);
+
+      close (fd);
+    }
+  while (++remaining < argc);
+
+  cleanup_list (dump_data_sections);
+  cleanup_list (string_sections);
+
+  return error_message_count != 0;
+}
+
+static void
+add_dump_section (const char *name,
+		  int key,
+		  bool implicit)
+{
+  struct section_argument *a = xmalloc (sizeof *a);
+  a->arg = name;
+  a->next = NULL;
+  a->implicit = implicit;
+  struct section_argument ***tailp
+    = key == 'x' ? &dump_data_sections_tail : &string_sections_tail;
+  **tailp = a;
+  *tailp = &a->next;
+}
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'a':
+      print_file_header = true;
+      print_program_header = true;
+      print_relocations = true;
+      print_section_header = true;
+      print_symbol_table = true;
+      print_version_info = true;
+      print_dynamic_table = true;
+      print_section_groups = true;
+      print_histogram = true;
+      print_arch = true;
+      print_notes = true;
+      implicit_debug_sections |= section_exception;
+      add_dump_section (".strtab", key, true);
+      add_dump_section (".dynstr", key, true);
+      add_dump_section (".comment", key, true);
+      any_control_option = true;
+      break;
+    case 'A':
+      print_arch = true;
+      any_control_option = true;
+      break;
+    case 'd':
+      print_dynamic_table = true;
+      any_control_option = true;
+      break;
+    case 'D':
+      use_dynamic_segment = true;
+      break;
+    case 'e':
+      print_debug_sections |= section_exception;
+      any_control_option = true;
+      break;
+    case 'g':
+      print_section_groups = true;
+      any_control_option = true;
+      break;
+    case 'h':
+      print_file_header = true;
+      any_control_option = true;
+      break;
+    case 'I':
+      print_histogram = true;
+      any_control_option = true;
+      break;
+    case 'l':
+      print_program_header = true;
+      any_control_option = true;
+      break;
+    case 'n':
+      print_notes = true;
+      any_control_option = true;
+      notes_section = arg;
+      break;
+    case 'r':
+      print_relocations = true;
+      any_control_option = true;
+     break;
+    case 'S':
+      print_section_header = true;
+      any_control_option = true;
+      break;
+    case 's':
+      print_symbol_table = true;
+      any_control_option = true;
+      symbol_table_section = arg;
+      break;
+    case PRINT_DYNSYM_TABLE:
+      print_dynsym_table = true;
+      any_control_option = true;
+      break;
+    case 'V':
+      print_version_info = true;
+      any_control_option = true;
+      break;
+    case 'c':
+      print_archive_index = true;
+      break;
+    case 'w':
+      if (arg == NULL)
+	{
+	  print_debug_sections = section_all;
+	  implicit_debug_sections = section_info;
+	  show_split_units = true;
+	}
+      else if (strcmp (arg, "abbrev") == 0)
+	print_debug_sections |= section_abbrev;
+      else if (strcmp (arg, "addr") == 0)
+	{
+	  print_debug_sections |= section_addr;
+	  implicit_debug_sections |= section_info;
+	}
+      else if (strcmp (arg, "aranges") == 0)
+	print_debug_sections |= section_aranges;
+      else if (strcmp (arg, "decodedaranges") == 0)
+	{
+	  print_debug_sections |= section_aranges;
+	  decodedaranges = true;
+	}
+      else if (strcmp (arg, "ranges") == 0)
+	{
+	  print_debug_sections |= section_ranges;
+	  implicit_debug_sections |= section_info;
+	}
+      else if (strcmp (arg, "frame") == 0 || strcmp (arg, "frames") == 0)
+	print_debug_sections |= section_frame;
+      else if (strcmp (arg, "info") == 0)
+	{
+	  print_debug_sections |= section_info;
+	  print_debug_sections |= section_types;
+	}
+      else if (strcmp (arg, "info+") == 0)
+	{
+	  print_debug_sections |= section_info;
+	  print_debug_sections |= section_types;
+	  show_split_units = true;
+	}
+      else if (strcmp (arg, "loc") == 0)
+	{
+	  print_debug_sections |= section_loc;
+	  implicit_debug_sections |= section_info;
+	}
+      else if (strcmp (arg, "line") == 0)
+	print_debug_sections |= section_line;
+      else if (strcmp (arg, "decodedline") == 0)
+	{
+	  print_debug_sections |= section_line;
+	  decodedline = true;
+	}
+      else if (strcmp (arg, "pubnames") == 0)
+	print_debug_sections |= section_pubnames;
+      else if (strcmp (arg, "str") == 0)
+	{
+	  print_debug_sections |= section_str;
+	  /* For mapping string offset tables to CUs.  */
+	  implicit_debug_sections |= section_info;
+	}
+      else if (strcmp (arg, "macinfo") == 0)
+	print_debug_sections |= section_macinfo;
+      else if (strcmp (arg, "macro") == 0)
+	print_debug_sections |= section_macro;
+      else if (strcmp (arg, "exception") == 0)
+	print_debug_sections |= section_exception;
+      else if (strcmp (arg, "gdb_index") == 0)
+	print_debug_sections |= section_gdb_index;
+      else
+	{
+	  fprintf (stderr, _("Unknown DWARF debug section `%s'.\n"),
+		   arg);
+	  argp_help (&argp, stderr, ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (1);
+	}
+      any_control_option = true;
+      break;
+    case 'p':
+      any_control_option = true;
+      if (arg == NULL)
+	{
+	  print_string_sections = true;
+	  break;
+	}
+      FALLTHROUGH;
+    case 'x':
+      add_dump_section (arg, key, false);
+      any_control_option = true;
+      break;
+    case 'N':
+      print_address_names = false;
+      break;
+    case 'U':
+      print_unresolved_addresses = true;
+      break;
+    case ARGP_KEY_NO_ARGS:
+      fputs (_("Missing file name.\n"), stderr);
+      goto do_argp_help;
+    case ARGP_KEY_FINI:
+      if (! any_control_option && ! print_archive_index)
+	{
+	  fputs (_("No operation specified.\n"), stderr);
+	do_argp_help:
+	  argp_help (&argp, stderr, ARGP_HELP_SEE,
+		     program_invocation_short_name);
+	  exit (EXIT_FAILURE);
+	}
+      break;
+    case 'W':			/* Ignored.  */
+      break;
+    case 'z':
+      print_decompress = true;
+      break;
+    case ELF_INPUT_SECTION:
+      if (arg == NULL)
+	elf_input_section = ".gnu_debugdata";
+      else
+	elf_input_section = arg;
+      break;
+    case DWARF_SKELETON:
+      dwarf_skeleton = arg;
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Create a file descriptor to read the data from the
+   elf_input_section given a file descriptor to an ELF file.  */
+static int
+open_input_section (int fd)
+{
+  size_t shnums;
+  size_t cnt;
+  size_t shstrndx;
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    {
+      error (0, 0, _("cannot generate Elf descriptor: %s"),
+	     elf_errmsg (-1));
+      return -1;
+    }
+
+  if (elf_getshdrnum (elf, &shnums) < 0)
+    {
+      error (0, 0, _("cannot determine number of sections: %s"),
+	     elf_errmsg (-1));
+    open_error:
+      elf_end (elf);
+      return -1;
+    }
+
+  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+    {
+      error (0, 0, _("cannot get section header string table index"));
+      goto open_error;
+    }
+
+  for (cnt = 0; cnt < shnums; ++cnt)
+    {
+      Elf_Scn *scn = elf_getscn (elf, cnt);
+      if (scn == NULL)
+	{
+	  error (0, 0, _("cannot get section: %s"),
+		 elf_errmsg (-1));
+	  goto open_error;
+	}
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (shdr == NULL))
+	{
+	  error (0, 0, _("cannot get section header: %s"),
+		 elf_errmsg (-1));
+	  goto open_error;
+	}
+
+      const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
+      if (sname == NULL)
+	{
+	  error (0, 0, _("cannot get section name"));
+	  goto open_error;
+	}
+
+      if (strcmp (sname, elf_input_section) == 0)
+	{
+	  Elf_Data *data = elf_rawdata (scn, NULL);
+	  if (data == NULL)
+	    {
+	      error (0, 0, _("cannot get %s content: %s"),
+		     sname, elf_errmsg (-1));
+	      goto open_error;
+	    }
+
+	  /* Create (and immediately unlink) a temporary file to store
+	     section data in to create a file descriptor for it.  */
+	  const char *tmpdir = getenv ("TMPDIR") ?: P_tmpdir;
+	  static const char suffix[] = "/readelfXXXXXX";
+	  int tmplen = strlen (tmpdir) + sizeof (suffix);
+	  char *tempname = alloca (tmplen);
+	  sprintf (tempname, "%s%s", tmpdir, suffix);
+
+	  int sfd = mkstemp (tempname);
+	  if (sfd == -1)
+	    {
+	      error (0, 0, _("cannot create temp file '%s'"),
+		     tempname);
+	      goto open_error;
+	    }
+	  unlink (tempname);
+
+	  ssize_t size = data->d_size;
+	  if (write_retry (sfd, data->d_buf, size) != size)
+	    {
+	      error (0, 0, _("cannot write section data"));
+	      goto open_error;
+	    }
+
+	  if (elf_end (elf) != 0)
+	    {
+	      error (0, 0, _("error while closing Elf descriptor: %s"),
+		     elf_errmsg (-1));
+	      return -1;
+	    }
+
+	  if (lseek (sfd, 0, SEEK_SET) == -1)
+	    {
+	      error (0, 0, _("error while rewinding file descriptor"));
+	      return -1;
+	    }
+
+	  return sfd;
+	}
+    }
+
+  /* Named section not found.  */
+  if (elf_end (elf) != 0)
+    error (0, 0, _("error while closing Elf descriptor: %s"),
+	   elf_errmsg (-1));
+  return -1;
+}
+
+/* Check if the file is an archive, and if so dump its index.  */
+static void
+check_archive_index (int fd, const char *fname, bool only_one)
+{
+  /* Create an `Elf' descriptor.  */
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    error (0, 0, _("cannot generate Elf descriptor: %s"),
+	   elf_errmsg (-1));
+  else
+    {
+      if (elf_kind (elf) == ELF_K_AR)
+	{
+	  if (!only_one)
+	    printf ("\n%s:\n\n", fname);
+	  dump_archive_index (elf, fname);
+	}
+      else
+	error (0, 0,
+	       _("'%s' is not an archive, cannot print archive index"),
+	       fname);
+
+      /* Now we can close the descriptor.  */
+      if (elf_end (elf) != 0)
+	error (0, 0, _("error while closing Elf descriptor: %s"),
+	       elf_errmsg (-1));
+    }
+}
+
+/* Trivial callback used for checking if we opened an archive.  */
+static int
+count_dwflmod (Dwfl_Module *dwflmod __attribute__ ((unused)),
+	       void **userdata __attribute__ ((unused)),
+	       const char *name __attribute__ ((unused)),
+	       Dwarf_Addr base __attribute__ ((unused)),
+	       void *arg)
+{
+  if (*(bool *) arg)
+    return DWARF_CB_ABORT;
+  *(bool *) arg = true;
+  return DWARF_CB_OK;
+}
+
+struct process_dwflmod_args
+{
+  int fd;
+  bool only_one;
+};
+
+static int
+process_dwflmod (Dwfl_Module *dwflmod,
+		 void **userdata __attribute__ ((unused)),
+		 const char *name __attribute__ ((unused)),
+		 Dwarf_Addr base __attribute__ ((unused)),
+		 void *arg)
+{
+  const struct process_dwflmod_args *a = arg;
+
+  /* Print the file name.  */
+  if (!a->only_one)
+    {
+      const char *fname;
+      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL, &fname, NULL);
+
+      printf ("\n%s:\n\n", fname);
+    }
+
+  process_elf_file (dwflmod, a->fd);
+
+  return DWARF_CB_OK;
+}
+
+/* Stub libdwfl callback, only the ELF handle already open is ever used.
+   Only used for finding the alternate debug file if the Dwarf comes from
+   the main file.  We are not interested in separate debuginfo.  */
+static int
+find_no_debuginfo (Dwfl_Module *mod,
+		   void **userdata,
+		   const char *modname,
+		   Dwarf_Addr base,
+		   const char *file_name,
+		   const char *debuglink_file,
+		   GElf_Word debuglink_crc,
+		   char **debuginfo_file_name)
+{
+  Dwarf_Addr dwbias;
+  dwfl_module_info (mod, NULL, NULL, NULL, &dwbias, NULL, NULL, NULL);
+
+  /* We are only interested if the Dwarf has been setup on the main
+     elf file but is only missing the alternate debug link.  If dwbias
+     hasn't even been setup, this is searching for separate debuginfo
+     for the main elf.  We don't care in that case.  */
+  if (dwbias == (Dwarf_Addr) -1)
+    return -1;
+
+  return dwfl_standard_find_debuginfo (mod, userdata, modname, base,
+				       file_name, debuglink_file,
+				       debuglink_crc, debuginfo_file_name);
+}
+
+static Dwfl *
+create_dwfl (int fd, const char *fname)
+{
+  /* Duplicate an fd for dwfl_report_offline to swallow.  */
+  int dwfl_fd = dup (fd);
+  if (unlikely (dwfl_fd < 0))
+    error_exit (errno, "dup");
+
+  /* Use libdwfl in a trivial way to open the libdw handle for us.
+     This takes care of applying relocations to DWARF data in ET_REL files.  */
+  static const Dwfl_Callbacks callbacks =
+    {
+      .section_address = dwfl_offline_section_address,
+      .find_debuginfo = find_no_debuginfo
+    };
+  Dwfl *dwfl = dwfl_begin (&callbacks);
+  if (likely (dwfl != NULL))
+    /* Let 0 be the logical address of the file (or first in archive).  */
+    dwfl->offline_next_address = 0;
+  if (dwfl_report_offline (dwfl, fname, fname, dwfl_fd) == NULL)
+    {
+      struct stat st;
+      if (fstat (dwfl_fd, &st) != 0)
+	error (0, errno, _("cannot stat input file"));
+      else if (unlikely (st.st_size == 0))
+	error (0, 0, _("input file is empty"));
+      else
+	error (0, 0, _("failed reading '%s': %s"),
+	       fname, dwfl_errmsg (-1));
+      close (dwfl_fd);		/* Consumed on success, not on failure.  */
+      dwfl = NULL;
+    }
+  else
+    dwfl_report_end (dwfl, NULL, NULL);
+
+  return dwfl;
+}
+
+/* Process one input file.  */
+static void
+process_file (int fd, const char *fname, bool only_one)
+{
+  if (print_archive_index)
+    check_archive_index (fd, fname, only_one);
+
+  if (!any_control_option)
+    return;
+
+  if (elf_input_section != NULL)
+    {
+      /* Replace fname and fd with section content. */
+      char *fnname = alloca (strlen (fname) + strlen (elf_input_section) + 2);
+      sprintf (fnname, "%s:%s", fname, elf_input_section);
+      fd = open_input_section (fd);
+      if (fd == -1)
+        {
+          error (0, 0, _("No such section '%s' in '%s'"),
+		 elf_input_section, fname);
+          return;
+        }
+      fname = fnname;
+    }
+
+  Dwfl *dwfl = create_dwfl (fd, fname);
+  if (dwfl != NULL)
+    {
+      if (only_one)
+	{
+	  /* Clear ONLY_ONE if we have multiple modules, from an archive.  */
+	  bool seen = false;
+	  only_one = dwfl_getmodules (dwfl, &count_dwflmod, &seen, 0) == 0;
+	}
+
+      /* Process the one or more modules gleaned from this file.  */
+      struct process_dwflmod_args a = { .fd = fd, .only_one = only_one };
+      dwfl_getmodules (dwfl, &process_dwflmod, &a, 0);
+    }
+  /* Terrible hack for hooking unrelated skeleton/split compile units,
+     see __libdw_link_skel_split in print_debug.  */
+  if (! do_not_close_dwfl)
+    dwfl_end (dwfl);
+
+  /* Need to close the replaced fd if we created it.  Caller takes
+     care of original.  */
+  if (elf_input_section != NULL)
+    close (fd);
+}
+
+/* Check whether there are any compressed sections in the ELF file.  */
+static bool
+elf_contains_chdrs (Elf *elf)
+{
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+	return true;
+    }
+  return false;
+}
+
+/* Process one ELF file.  */
+static void
+process_elf_file (Dwfl_Module *dwflmod, int fd)
+{
+  GElf_Addr dwflbias;
+  Elf *elf = dwfl_module_getelf (dwflmod, &dwflbias);
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+
+  if (ehdr == NULL)
+    {
+      error (0, 0, _("cannot read ELF header: %s"), elf_errmsg (-1));
+      return;
+    }
+
+  Ebl *ebl = ebl_openbackend (elf);
+  if (unlikely (ebl == NULL))
+    {
+    ebl_error:
+      error (0, errno, _("cannot create EBL handle"));
+      return;
+    }
+
+  /* Determine the number of sections.  */
+  if (unlikely (elf_getshdrnum (ebl->elf, &shnum) < 0))
+    error_exit (0, _("cannot determine number of sections: %s"),
+		elf_errmsg (-1));
+
+  /* Determine the number of phdrs.  */
+  if (unlikely (elf_getphdrnum (ebl->elf, &phnum) < 0))
+    error_exit (0, _("cannot determine number of program headers: %s"),
+		elf_errmsg (-1));
+
+  /* For an ET_REL file, libdwfl has adjusted the in-core shdrs and
+     may have applied relocation to some sections.  If there are any
+     compressed sections, any pass (or libdw/libdwfl) might have
+     uncompressed them.  So we need to get a fresh Elf handle on the
+     file to display those.  */
+  bool print_unchanged = ((print_section_header
+			   || print_relocations
+			   || dump_data_sections != NULL
+			   || print_notes)
+			  && (ehdr->e_type == ET_REL
+			      || elf_contains_chdrs (ebl->elf)));
+
+  Elf *pure_elf = NULL;
+  Ebl *pure_ebl = ebl;
+  if (print_unchanged)
+    {
+      /* Read the file afresh.  */
+      off_t aroff = elf_getaroff (elf);
+      pure_elf = dwelf_elf_begin (fd);
+      if (aroff > 0)
+	{
+	  /* Archive member.  */
+	  (void) elf_rand (pure_elf, aroff);
+	  Elf *armem = elf_begin (-1, ELF_C_READ_MMAP, pure_elf);
+	  elf_end (pure_elf);
+	  pure_elf = armem;
+	}
+      if (pure_elf == NULL)
+	{
+	  error (0, 0, _("cannot read ELF: %s"), elf_errmsg (-1));
+	  return;
+	}
+      pure_ebl = ebl_openbackend (pure_elf);
+      if (pure_ebl == NULL)
+	goto ebl_error;
+    }
+
+  bool symtab_printed = false;
+
+  if (print_file_header)
+    print_ehdr (ebl, ehdr);
+  if (print_section_header)
+    print_shdr (pure_ebl, ehdr);
+  if (print_program_header)
+    print_phdr (ebl, ehdr);
+  if (print_section_groups)
+    print_scngrp (ebl);
+  if (print_dynamic_table)
+    print_dynamic (ebl);
+  if (print_relocations)
+    print_relocs (pure_ebl, dwflmod, ehdr);
+  if (print_histogram)
+    handle_hash (ebl);
+  if (print_symbol_table || print_dynsym_table)
+    symtab_printed |= print_symtab (ebl, SHT_DYNSYM);
+  if (print_version_info)
+    print_verinfo (ebl);
+  if (print_symbol_table && !use_dynamic_segment)
+    symtab_printed |= print_symtab (ebl, SHT_SYMTAB);
+
+  if ((print_symbol_table || print_dynsym_table)
+      && !symtab_printed && symbol_table_section != NULL)
+    printf ("WARNING: %s: '%s'\n", _("cannot find section"),
+        symbol_table_section);
+
+  if (print_arch)
+    print_liblist (ebl);
+  if (print_arch)
+    print_attributes (ebl, ehdr);
+  if (dump_data_sections != NULL)
+    dump_data (pure_ebl);
+  if (string_sections != NULL)
+    dump_strings (ebl);
+  if ((print_debug_sections | implicit_debug_sections) != 0)
+    print_debug (dwflmod, ebl, ehdr);
+  if (print_notes)
+    handle_notes (pure_ebl, ehdr);
+  if (print_string_sections)
+    print_strings (ebl);
+
+  if (pure_ebl != ebl)
+    {
+      ebl_closebackend (ebl);
+      ebl_closebackend (pure_ebl);
+      elf_end (pure_elf);
+    }
+  else
+    ebl_closebackend (ebl);
+}
+
+
+/* Print file type.  */
+static void
+print_file_type (unsigned short int e_type)
+{
+  if (likely (e_type <= ET_CORE))
+    {
+      static const char *const knowntypes[] =
+      {
+	N_("NONE (None)"),
+	N_("REL (Relocatable file)"),
+	N_("EXEC (Executable file)"),
+	N_("DYN (Shared object file)"),
+	N_("CORE (Core file)")
+      };
+      puts (_(knowntypes[e_type]));
+    }
+  else if (e_type >= ET_LOOS && e_type <= ET_HIOS)
+    printf (_("OS Specific: (%x)\n"),  e_type);
+  else if (e_type >= ET_LOPROC /* && e_type <= ET_HIPROC always true */)
+    printf (_("Processor Specific: (%x)\n"),  e_type);
+  else
+    puts ("???");
+}
+
+
+/* Print ELF header.  */
+static void
+print_ehdr (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  fputs_unlocked (_("ELF Header:\n  Magic:  "), stdout);
+  for (size_t cnt = 0; cnt < EI_NIDENT; ++cnt)
+    printf (" %02hhx", ehdr->e_ident[cnt]);
+
+  printf (_("\n  Class:                             %s\n"),
+	  ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? "ELF32"
+	  : ehdr->e_ident[EI_CLASS] == ELFCLASS64 ? "ELF64"
+	  : "\?\?\?");
+
+  printf (_("  Data:                              %s\n"),
+	  ehdr->e_ident[EI_DATA] == ELFDATA2LSB
+	  ? "2's complement, little endian"
+	  : ehdr->e_ident[EI_DATA] == ELFDATA2MSB
+	  ? "2's complement, big endian" : "\?\?\?");
+
+  printf (_("  Ident Version:                     %hhd %s\n"),
+	  ehdr->e_ident[EI_VERSION],
+	  ehdr->e_ident[EI_VERSION] == EV_CURRENT ? _("(current)")
+	  : "(\?\?\?)");
+
+  char buf[512];
+  printf (_("  OS/ABI:                            %s\n"),
+	  ebl_osabi_name (ebl, ehdr->e_ident[EI_OSABI], buf, sizeof (buf)));
+
+  printf (_("  ABI Version:                       %hhd\n"),
+	  ehdr->e_ident[EI_ABIVERSION]);
+
+  fputs_unlocked (_("  Type:                              "), stdout);
+  print_file_type (ehdr->e_type);
+
+  const char *machine = dwelf_elf_e_machine_string (ehdr->e_machine);
+  if (machine != NULL)
+    printf (_("  Machine:                           %s\n"), machine);
+  else
+    printf (_("  Machine:                           <unknown>: 0x%x\n"),
+	    ehdr->e_machine);
+
+  printf (_("  Version:                           %d %s\n"),
+	  ehdr->e_version,
+	  ehdr->e_version  == EV_CURRENT ? _("(current)") : "(\?\?\?)");
+
+  printf (_("  Entry point address:               %#" PRIx64 "\n"),
+	  ehdr->e_entry);
+
+  printf (_("  Start of program headers:          %" PRId64 " %s\n"),
+	  ehdr->e_phoff, _("(bytes into file)"));
+
+  printf (_("  Start of section headers:          %" PRId64 " %s\n"),
+	  ehdr->e_shoff, _("(bytes into file)"));
+
+  printf (_("  Flags:                             %s\n"),
+	  ebl_machine_flag_name (ebl, ehdr->e_flags, buf, sizeof (buf)));
+
+  printf (_("  Size of this header:               %" PRId16 " %s\n"),
+	  ehdr->e_ehsize, _("(bytes)"));
+
+  printf (_("  Size of program header entries:    %" PRId16 " %s\n"),
+	  ehdr->e_phentsize, _("(bytes)"));
+
+  printf (_("  Number of program headers entries: %" PRId16),
+	  ehdr->e_phnum);
+  if (ehdr->e_phnum == PN_XNUM)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+      if (shdr != NULL)
+	printf (_(" (%" PRIu32 " in [0].sh_info)"),
+		(uint32_t) shdr->sh_info);
+      else
+	fputs_unlocked (_(" ([0] not available)"), stdout);
+    }
+  fputc_unlocked ('\n', stdout);
+
+  printf (_("  Size of section header entries:    %" PRId16 " %s\n"),
+	  ehdr->e_shentsize, _("(bytes)"));
+
+  printf (_("  Number of section headers entries: %" PRId16),
+	  ehdr->e_shnum);
+  if (ehdr->e_shnum == 0)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+      if (shdr != NULL)
+	printf (_(" (%" PRIu32 " in [0].sh_size)"),
+		(uint32_t) shdr->sh_size);
+      else
+	fputs_unlocked (_(" ([0] not available)"), stdout);
+    }
+  fputc_unlocked ('\n', stdout);
+
+  if (unlikely (ehdr->e_shstrndx == SHN_XINDEX))
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (ebl->elf, 0), &shdr_mem);
+      if (shdr != NULL)
+	/* We managed to get the zeroth section.  */
+	snprintf (buf, sizeof (buf), _(" (%" PRIu32 " in [0].sh_link)"),
+		  (uint32_t) shdr->sh_link);
+      else
+	{
+	  strncpy (buf, _(" ([0] not available)"), sizeof (buf) - 1);
+	  buf[sizeof (buf) - 1] = '\0';
+	}
+
+      printf (_("  Section header string table index: XINDEX%s\n\n"),
+	      buf);
+    }
+  else
+    printf (_("  Section header string table index: %" PRId16 "\n\n"),
+	    ehdr->e_shstrndx);
+}
+
+
+static const char *
+get_visibility_type (int value)
+{
+  switch (value)
+    {
+    case STV_DEFAULT:
+      return "DEFAULT";
+    case STV_INTERNAL:
+      return "INTERNAL";
+    case STV_HIDDEN:
+      return "HIDDEN";
+    case STV_PROTECTED:
+      return "PROTECTED";
+    default:
+      return "???";
+    }
+}
+
+static const char *
+elf_ch_type_name (unsigned int code)
+{
+  switch (code)
+    {
+    case 0:
+      return "NONE";
+    case ELFCOMPRESS_ZLIB:
+      return "ZLIB";
+    case ELFCOMPRESS_ZSTD:
+      return "ZSTD";
+    default:
+      return "UNKNOWN";
+    }
+}
+
+/* Print the section headers.  */
+static void
+print_shdr (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  size_t cnt;
+  size_t shstrndx;
+
+  if (! print_file_header)
+    {
+      size_t sections;
+      if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
+	error_exit (0, _("cannot get number of sections: %s"),
+		    elf_errmsg (-1));
+
+      printf (_("\
+There are %zd section headers, starting at offset %#" PRIx64 ":\n\
+\n"),
+	      sections, ehdr->e_shoff);
+    }
+
+  /* Get the section header string table index.  */
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index: %s"),
+		elf_errmsg (-1));
+
+  puts (_("Section Headers:"));
+
+  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
+    puts (_("[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al"));
+  else
+    puts (_("[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al"));
+
+  if (print_decompress)
+    {
+      if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
+	puts (_("     [Compression  Size   Al]"));
+      else
+	puts (_("     [Compression  Size     Al]"));
+    }
+
+  for (cnt = 0; cnt < shnum; ++cnt)
+    {
+      Elf_Scn *scn = elf_getscn (ebl->elf, cnt);
+
+      if (unlikely (scn == NULL))
+	error_exit (0, _("cannot get section: %s"),
+		    elf_errmsg (-1));
+
+      /* Get the section header.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (unlikely (shdr == NULL))
+	error_exit (0, _("cannot get section header: %s"),
+		    elf_errmsg (-1));
+
+      char flagbuf[20];
+      char *cp = flagbuf;
+      if (shdr->sh_flags & SHF_WRITE)
+	*cp++ = 'W';
+      if (shdr->sh_flags & SHF_ALLOC)
+	*cp++ = 'A';
+      if (shdr->sh_flags & SHF_EXECINSTR)
+	*cp++ = 'X';
+      if (shdr->sh_flags & SHF_MERGE)
+	*cp++ = 'M';
+      if (shdr->sh_flags & SHF_STRINGS)
+	*cp++ = 'S';
+      if (shdr->sh_flags & SHF_INFO_LINK)
+	*cp++ = 'I';
+      if (shdr->sh_flags & SHF_LINK_ORDER)
+	*cp++ = 'L';
+      if (shdr->sh_flags & SHF_OS_NONCONFORMING)
+	*cp++ = 'N';
+      if (shdr->sh_flags & SHF_GROUP)
+	*cp++ = 'G';
+      if (shdr->sh_flags & SHF_TLS)
+	*cp++ = 'T';
+      if (shdr->sh_flags & SHF_COMPRESSED)
+	*cp++ = 'C';
+      if (shdr->sh_flags & SHF_ORDERED)
+	*cp++ = 'O';
+      if (shdr->sh_flags & SHF_EXCLUDE)
+	*cp++ = 'E';
+      if (shdr->sh_flags & SHF_GNU_RETAIN)
+	*cp++ = 'R';
+      *cp = '\0';
+
+      const char *sname;
+      char buf[128];
+      sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "<corrupt>";
+      printf ("[%2zu] %-20s %-12s %0*" PRIx64 " %0*" PRIx64 " %0*" PRIx64
+	      " %2" PRId64 " %-5s %2" PRId32 " %3" PRId32
+	      " %2" PRId64 "\n",
+	      cnt, sname,
+	      ebl_section_type_name (ebl, shdr->sh_type, buf, sizeof (buf)),
+	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, shdr->sh_addr,
+	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_offset,
+	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, shdr->sh_size,
+	      shdr->sh_entsize, flagbuf, shdr->sh_link, shdr->sh_info,
+	      shdr->sh_addralign);
+
+      if (print_decompress)
+	{
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      GElf_Chdr chdr;
+	      if (gelf_getchdr (scn, &chdr) != NULL)
+		printf ("     [ELF %s (%" PRId32 ") %0*" PRIx64
+			" %2" PRId64 "]\n",
+			elf_ch_type_name (chdr.ch_type),
+			chdr.ch_type,
+			ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8,
+			chdr.ch_size, chdr.ch_addralign);
+	      else
+		error (0, 0,
+		       _("bad compression header for section %zd: %s"),
+		       elf_ndxscn (scn), elf_errmsg (-1));
+	    }
+	  else if (startswith (sname, ".zdebug"))
+	    {
+	      ssize_t size;
+	      if ((size = dwelf_scn_gnu_compressed_size (scn)) >= 0)
+		printf ("     [GNU ZLIB     %0*zx   ]\n",
+			ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 6 : 8, size);
+	      else
+		error (0, 0,
+		       _("bad gnu compressed size for section %zd: %s"),
+		       elf_ndxscn (scn), elf_errmsg (-1));
+	    }
+	}
+    }
+
+  fputc_unlocked ('\n', stdout);
+}
+
+
+/* Print the program header.  */
+static void
+print_phdr (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  if (phnum == 0)
+    /* No program header, this is OK in relocatable objects.  */
+    return;
+
+  puts (_("Program Headers:"));
+  if (ehdr->e_ident[EI_CLASS] == ELFCLASS32)
+    puts (_("\
+  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align"));
+  else
+    puts (_("\
+  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align"));
+
+  /* Process all program headers.  */
+  bool has_relro = false;
+  GElf_Addr relro_from = 0;
+  GElf_Addr relro_to = 0;
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    {
+      char buf[128];
+      GElf_Phdr mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
+
+      /* If for some reason the header cannot be returned show this.  */
+      if (unlikely (phdr == NULL))
+	{
+	  puts ("  ???");
+	  continue;
+	}
+
+      printf ("  %-14s 0x%06" PRIx64 " 0x%0*" PRIx64 " 0x%0*" PRIx64
+	      " 0x%06" PRIx64 " 0x%06" PRIx64 " %c%c%c 0x%" PRIx64 "\n",
+	      ebl_segment_type_name (ebl, phdr->p_type, buf, sizeof (buf)),
+	      phdr->p_offset,
+	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_vaddr,
+	      ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16, phdr->p_paddr,
+	      phdr->p_filesz,
+	      phdr->p_memsz,
+	      phdr->p_flags & PF_R ? 'R' : ' ',
+	      phdr->p_flags & PF_W ? 'W' : ' ',
+	      phdr->p_flags & PF_X ? 'E' : ' ',
+	      phdr->p_align);
+
+      if (phdr->p_type == PT_INTERP)
+	{
+	  /* If we are sure the file offset is valid then we can show
+	     the user the name of the interpreter.  We check whether
+	     there is a section at the file offset.  Normally there
+	     would be a section called ".interp".  But in separate
+	     .debug files it is a NOBITS section (and so doesn't match
+	     with gelf_offscn).  Which probably means the offset is
+	     not valid another reason could be because the ELF file
+	     just doesn't contain any section headers, in that case
+	     just play it safe and don't display anything.  */
+
+	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+	  size_t maxsize;
+	  char *filedata = elf_rawfile (ebl->elf, &maxsize);
+
+	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS
+	      && filedata != NULL && phdr->p_offset < maxsize
+	      && phdr->p_filesz <= maxsize - phdr->p_offset
+	      && memchr (filedata + phdr->p_offset, '\0',
+			 phdr->p_filesz) != NULL)
+	    printf (_("\t[Requesting program interpreter: %s]\n"),
+		    filedata + phdr->p_offset);
+	}
+      else if (phdr->p_type == PT_GNU_RELRO)
+	{
+	  has_relro = true;
+	  relro_from = phdr->p_vaddr;
+	  relro_to = relro_from + phdr->p_memsz;
+	}
+    }
+
+  size_t sections;
+  if (unlikely (elf_getshdrnum (ebl->elf, &sections) < 0))
+    error_exit (0, _("cannot get number of sections: %s"),
+		elf_errmsg (-1));
+
+  if (sections == 0)
+    /* No sections in the file.  Punt.  */
+    return;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  puts (_("\n Section to Segment mapping:\n  Segment Sections..."));
+
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    {
+      /* Print the segment number.  */
+      printf ("   %2.2zu     ", cnt);
+
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &phdr_mem);
+      /* This must not happen.  */
+      if (unlikely (phdr == NULL))
+	error_exit (0, _("cannot get program header: %s"),
+		    elf_errmsg (-1));
+
+      /* Iterate over the sections.  */
+      bool in_relro = false;
+      bool in_ro = false;
+      for (size_t inner = 1; inner < shnum; ++inner)
+	{
+	  Elf_Scn *scn = elf_getscn (ebl->elf, inner);
+	  /* This should not happen.  */
+	  if (unlikely (scn == NULL))
+	    error_exit (0, _("cannot get section: %s"),
+			elf_errmsg (-1));
+
+	  /* Get the section header.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if (unlikely (shdr == NULL))
+	    error_exit (0, _("cannot get section header: %s"),
+			elf_errmsg (-1));
+
+	  if (shdr->sh_size > 0
+	      /* Compare allocated sections by VMA, unallocated
+		 sections by file offset.  */
+	      && (shdr->sh_flags & SHF_ALLOC
+		  ? (shdr->sh_addr >= phdr->p_vaddr
+		     && (shdr->sh_addr + shdr->sh_size
+			 <= phdr->p_vaddr + phdr->p_memsz))
+		  : (shdr->sh_offset >= phdr->p_offset
+		     && (shdr->sh_offset + shdr->sh_size
+			 <= phdr->p_offset + phdr->p_filesz))))
+	    {
+	      if (has_relro && !in_relro
+		  && shdr->sh_addr >= relro_from
+		  && shdr->sh_addr + shdr->sh_size <= relro_to)
+		{
+		  fputs_unlocked (" [RELRO:", stdout);
+		  in_relro = true;
+		}
+	      else if (has_relro && in_relro && shdr->sh_addr >= relro_to)
+		{
+		  fputs_unlocked ("]", stdout);
+		  in_relro =  false;
+		}
+	      else if (has_relro && in_relro
+		       && shdr->sh_addr + shdr->sh_size > relro_to)
+		fputs_unlocked ("] <RELRO:", stdout);
+	      else if (phdr->p_type == PT_LOAD && (phdr->p_flags & PF_W) == 0)
+		{
+		  if (!in_ro)
+		    {
+		      fputs_unlocked (" [RO:", stdout);
+		      in_ro = true;
+		    }
+		}
+	      else
+		{
+		  /* Determine the segment this section is part of.  */
+		  size_t cnt2;
+		  GElf_Phdr phdr2_mem;
+		  GElf_Phdr *phdr2 = NULL;
+		  for (cnt2 = 0; cnt2 < phnum; ++cnt2)
+		    {
+		      phdr2 = gelf_getphdr (ebl->elf, cnt2, &phdr2_mem);
+
+		      if (phdr2 != NULL && phdr2->p_type == PT_LOAD
+			  && shdr->sh_addr >= phdr2->p_vaddr
+			  && (shdr->sh_addr + shdr->sh_size
+			      <= phdr2->p_vaddr + phdr2->p_memsz))
+			break;
+		    }
+
+		  if (cnt2 < phnum)
+		    {
+		      if ((phdr2->p_flags & PF_W) == 0 && !in_ro)
+			{
+			  fputs_unlocked (" [RO:", stdout);
+			  in_ro = true;
+			}
+		      else if ((phdr2->p_flags & PF_W) != 0 && in_ro)
+			{
+			  fputs_unlocked ("]", stdout);
+			  in_ro = false;
+			}
+		    }
+		}
+
+	      printf (" %s",
+		      elf_strptr (ebl->elf, shstrndx, shdr->sh_name));
+
+	      /* Signal that this section is only partially covered.  */
+	      if (has_relro && in_relro
+		       && shdr->sh_addr + shdr->sh_size > relro_to)
+		{
+		  fputs_unlocked (">", stdout);
+		  in_relro =  false;
+		}
+	    }
+	}
+      if (in_relro || in_ro)
+	fputs_unlocked ("]", stdout);
+
+      /* Finish the line.  */
+      fputc_unlocked ('\n', stdout);
+    }
+}
+
+
+static const char *
+section_name (Ebl *ebl, GElf_Shdr *shdr)
+{
+  size_t shstrndx;
+  if (shdr == NULL || elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
+    return "???";
+  return elf_strptr (ebl->elf, shstrndx, shdr->sh_name) ?: "???";
+}
+
+
+static void
+handle_scngrp (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+
+  if (data == NULL || data->d_size < sizeof (Elf32_Word) || symshdr == NULL
+      || symdata == NULL)
+    return;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  Elf32_Word *grpref = (Elf32_Word *) data->d_buf;
+
+  GElf_Sym sym_mem;
+  GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
+
+  printf ((grpref[0] & GRP_COMDAT)
+	  ? ngettext ("\
+\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entry:\n",
+		      "\
+\nCOMDAT section group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
+		      data->d_size / sizeof (Elf32_Word) - 1)
+	  : ngettext ("\
+\nSection group [%2zu] '%s' with signature '%s' contains %zu entry:\n", "\
+\nSection group [%2zu] '%s' with signature '%s' contains %zu entries:\n",
+		      data->d_size / sizeof (Elf32_Word) - 1),
+	  elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	  (sym == NULL ? NULL
+	   : elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name))
+	  ?: _("<INVALID SYMBOL>"),
+	  data->d_size / sizeof (Elf32_Word) - 1);
+
+  for (size_t cnt = 1; cnt < data->d_size / sizeof (Elf32_Word); ++cnt)
+    {
+      GElf_Shdr grpshdr_mem;
+      GElf_Shdr *grpshdr = gelf_getshdr (elf_getscn (ebl->elf, grpref[cnt]),
+					 &grpshdr_mem);
+
+      const char *str;
+      printf ("  [%2u] %s\n",
+	      grpref[cnt],
+	      grpshdr != NULL
+	      && (str = elf_strptr (ebl->elf, shstrndx, grpshdr->sh_name))
+	      ? str : _("<INVALID SECTION>"));
+    }
+}
+
+
+static void
+print_scngrp (Ebl *ebl)
+{
+  /* Find all relocation sections and handle them.  */
+  Elf_Scn *scn = NULL;
+
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+       /* Handle the section if it is a symbol table.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr != NULL && shdr->sh_type == SHT_GROUP)
+	{
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      if (elf_compress (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	      shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (unlikely (shdr == NULL))
+		error_exit (0, _("cannot get section [%zd] header: %s"),
+			    elf_ndxscn (scn),
+			    elf_errmsg (-1));
+	    }
+	  handle_scngrp (ebl, scn, shdr);
+	}
+    }
+}
+
+
+static const struct flags
+{
+  int mask;
+  const char *str;
+} dt_flags[] =
+  {
+    { DF_ORIGIN, "ORIGIN" },
+    { DF_SYMBOLIC, "SYMBOLIC" },
+    { DF_TEXTREL, "TEXTREL" },
+    { DF_BIND_NOW, "BIND_NOW" },
+    { DF_STATIC_TLS, "STATIC_TLS" }
+  };
+static const int ndt_flags = sizeof (dt_flags) / sizeof (dt_flags[0]);
+
+static const struct flags dt_flags_1[] =
+  {
+    { DF_1_NOW, "NOW" },
+    { DF_1_GLOBAL, "GLOBAL" },
+    { DF_1_GROUP, "GROUP" },
+    { DF_1_NODELETE, "NODELETE" },
+    { DF_1_LOADFLTR, "LOADFLTR" },
+    { DF_1_INITFIRST, "INITFIRST" },
+    { DF_1_NOOPEN, "NOOPEN" },
+    { DF_1_ORIGIN, "ORIGIN" },
+    { DF_1_DIRECT, "DIRECT" },
+    { DF_1_TRANS, "TRANS" },
+    { DF_1_INTERPOSE, "INTERPOSE" },
+    { DF_1_NODEFLIB, "NODEFLIB" },
+    { DF_1_NODUMP, "NODUMP" },
+    { DF_1_CONFALT, "CONFALT" },
+    { DF_1_ENDFILTEE, "ENDFILTEE" },
+    { DF_1_DISPRELDNE, "DISPRELDNE" },
+    { DF_1_DISPRELPND, "DISPRELPND" },
+  };
+static const int ndt_flags_1 = sizeof (dt_flags_1) / sizeof (dt_flags_1[0]);
+
+static const struct flags dt_feature_1[] =
+  {
+    { DTF_1_PARINIT, "PARINIT" },
+    { DTF_1_CONFEXP, "CONFEXP" }
+  };
+static const int ndt_feature_1 = (sizeof (dt_feature_1)
+				  / sizeof (dt_feature_1[0]));
+
+static const struct flags dt_posflag_1[] =
+  {
+    { DF_P1_LAZYLOAD, "LAZYLOAD" },
+    { DF_P1_GROUPPERM, "GROUPPERM" }
+  };
+static const int ndt_posflag_1 = (sizeof (dt_posflag_1)
+				  / sizeof (dt_posflag_1[0]));
+
+
+static void
+print_flags (int class, GElf_Xword d_val, const struct flags *flags,
+		int nflags)
+{
+  bool first = true;
+  int cnt;
+
+  for (cnt = 0; cnt < nflags; ++cnt)
+    if (d_val & flags[cnt].mask)
+      {
+	if (!first)
+	  putchar_unlocked (' ');
+	fputs_unlocked (flags[cnt].str, stdout);
+	d_val &= ~flags[cnt].mask;
+	first = false;
+      }
+
+  if (d_val != 0)
+    {
+      if (!first)
+	putchar_unlocked (' ');
+      printf ("%#0*" PRIx64, class == ELFCLASS32 ? 10 : 18, d_val);
+    }
+
+  putchar_unlocked ('\n');
+}
+
+
+static void
+print_dt_flags (int class, GElf_Xword d_val)
+{
+  print_flags (class, d_val, dt_flags, ndt_flags);
+}
+
+
+static void
+print_dt_flags_1 (int class, GElf_Xword d_val)
+{
+  print_flags (class, d_val, dt_flags_1, ndt_flags_1);
+}
+
+
+static void
+print_dt_feature_1 (int class, GElf_Xword d_val)
+{
+  print_flags (class, d_val, dt_feature_1, ndt_feature_1);
+}
+
+
+static void
+print_dt_posflag_1 (int class, GElf_Xword d_val)
+{
+  print_flags (class, d_val, dt_posflag_1, ndt_posflag_1);
+}
+
+
+static size_t
+get_dyn_ents (Elf_Data * dyn_data)
+{
+  GElf_Dyn *dyn;
+  GElf_Dyn dyn_mem;
+  size_t dyn_idx = 0;
+  do
+    {
+      dyn = gelf_getdyn(dyn_data, dyn_idx, &dyn_mem);
+      if (dyn != NULL)
+	++dyn_idx;
+    }
+  while (dyn != NULL && dyn->d_tag != DT_NULL);
+
+  return dyn_idx;
+}
+
+
+static void
+handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, GElf_Phdr *phdr)
+{
+  int class = gelf_getclass (ebl->elf);
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink;
+  Elf_Data *data;
+  size_t cnt;
+  size_t shstrndx;
+  size_t dyn_ents;
+
+  /* Get the data of the section.  */
+  if (use_dynamic_segment && phdr != NULL)
+    data = elf_getdata_rawchunk(ebl->elf, phdr->p_offset,
+				phdr->p_filesz, ELF_T_DYN);
+  else
+    data = elf_getdata (scn, NULL);
+
+  if (data == NULL)
+    return;
+
+  /* Get the dynamic section entry number */
+  dyn_ents = get_dyn_ents (data);
+
+  if (!use_dynamic_segment && shdr != NULL)
+    {
+      /* Get the section header string table index.  */
+      if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+	error_exit (0, _("cannot get section header string table index"));
+
+      glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
+      if (glink == NULL)
+	error_exit (0, _("invalid sh_link value in section %zu"),
+		    elf_ndxscn (scn));
+
+      printf (ngettext ("\
+\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    "\
+\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+			dyn_ents),
+	      (unsigned long int) dyn_ents,
+	      class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+	      shdr->sh_offset,
+	      (int) shdr->sh_link,
+	      elf_strptr (ebl->elf, shstrndx, glink->sh_name));
+    }
+  else if (phdr != NULL)
+    {
+      printf (ngettext ("\
+\nDynamic segment contains %lu entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "\n",
+		    "\
+\nDynamic segment contains %lu entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "\n",
+			dyn_ents),
+	      (unsigned long int) dyn_ents,
+	      class == ELFCLASS32 ? 10 : 18, phdr->p_paddr,
+	      phdr->p_offset);
+    }
+
+  fputs_unlocked (_("  Type              Value\n"), stdout);
+
+  /* if --use-dynamic option is enabled,
+     use the string table to get the related library info.  */
+  Elf_Data *strtab_data = NULL;
+  if (use_dynamic_segment && phdr != NULL)
+    {
+      strtab_data = get_dynscn_strtab(ebl->elf, phdr);
+      if (strtab_data == NULL)
+	error_exit (0, _("cannot get string table by using dynamic segment"));
+    }
+
+  for (cnt = 0; cnt < dyn_ents; ++cnt)
+    {
+      GElf_Dyn dynmem;
+      GElf_Dyn *dyn = gelf_getdyn (data, cnt, &dynmem);
+      if (dyn == NULL)
+	break;
+
+      char buf[64];
+      printf ("  %-17s ",
+	      ebl_dynamic_tag_name (ebl, dyn->d_tag, buf, sizeof (buf)));
+
+      char *name = NULL;
+      if (dyn->d_tag == DT_NEEDED
+	  || dyn->d_tag == DT_SONAME
+	  || dyn->d_tag == DT_RPATH
+	  || dyn->d_tag == DT_RUNPATH)
+	{
+	  if (! use_dynamic_segment && shdr != NULL)
+	    name = elf_strptr (ebl->elf, shdr->sh_link, dyn->d_un.d_val);
+	  else if (dyn->d_un.d_val < strtab_data->d_size
+		   && memrchr (strtab_data->d_buf + dyn->d_un.d_val, '\0',
+			       strtab_data->d_size - 1 - dyn->d_un.d_val) != NULL)
+	    name = ((char *) strtab_data->d_buf) + dyn->d_un.d_val;
+	}
+
+      switch (dyn->d_tag)
+	{
+	case DT_NULL:
+	case DT_DEBUG:
+	case DT_BIND_NOW:
+	case DT_TEXTREL:
+	  /* No further output.  */
+	  fputc_unlocked ('\n', stdout);
+	  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_PLTRELSZ:
+	case DT_RELASZ:
+	case DT_STRSZ:
+	case DT_RELSZ:
+	case DT_RELRSZ:
+	case DT_RELAENT:
+	case DT_SYMENT:
+	case DT_RELENT:
+	case DT_RELRENT:
+	case DT_PLTPADSZ:
+	case DT_MOVEENT:
+	case DT_MOVESZ:
+	case DT_INIT_ARRAYSZ:
+	case DT_FINI_ARRAYSZ:
+	case DT_SYMINSZ:
+	case DT_SYMINENT:
+	case DT_GNU_CONFLICTSZ:
+	case DT_GNU_LIBLISTSZ:
+	  printf (_("%" PRId64 " (bytes)\n"), dyn->d_un.d_val);
+	  break;
+
+	case DT_VERDEFNUM:
+	case DT_VERNEEDNUM:
+	case DT_RELACOUNT:
+	case DT_RELCOUNT:
+	  printf ("%" PRId64 "\n", dyn->d_un.d_val);
+	  break;
+
+	case DT_PLTREL:;
+	  const char *tagname = ebl_dynamic_tag_name (ebl, dyn->d_un.d_val,
+						      NULL, 0);
+	  puts (tagname ?: "???");
+	  break;
+
+	case DT_FLAGS:
+	  print_dt_flags (class, dyn->d_un.d_val);
+	  break;
+
+	case DT_FLAGS_1:
+	  print_dt_flags_1 (class, dyn->d_un.d_val);
+	  break;
+
+	case DT_FEATURE_1:
+	  print_dt_feature_1 (class, dyn->d_un.d_val);
+	  break;
+
+	case DT_POSFLAG_1:
+	  print_dt_posflag_1 (class, dyn->d_un.d_val);
+	  break;
+
+	default:
+	  printf ("%#0*" PRIx64 "\n",
+		  class == ELFCLASS32 ? 10 : 18, dyn->d_un.d_val);
+	  break;
+	}
+    }
+}
+
+
+/* Print the dynamic segment.  */
+static void
+print_dynamic (Ebl *ebl)
+{
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
+
+      if (phdr != NULL && phdr->p_type == PT_DYNAMIC)
+	{
+	  Elf_Scn *scn = gelf_offscn (ebl->elf, phdr->p_offset);
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	  if ((use_dynamic_segment && phdr != NULL)
+	      || (shdr != NULL && shdr->sh_type == SHT_DYNAMIC))
+	    handle_dynamic (ebl, scn, shdr, phdr);
+	  break;
+	}
+    }
+}
+
+
+/* Print relocations.  */
+static void
+print_relocs (Ebl *ebl, Dwfl_Module *mod, GElf_Ehdr *ehdr)
+{
+  /* Find all relocation sections and handle them.  */
+  Elf_Scn *scn = NULL;
+
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+       /* Handle the section if it is a symbol table.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (likely (shdr != NULL))
+	{
+	  if (shdr->sh_type == SHT_REL)
+	    handle_relocs_rel (ebl, ehdr, scn, shdr);
+	  else if (shdr->sh_type == SHT_RELA)
+	    handle_relocs_rela (ebl, ehdr, scn, shdr);
+	  else if (shdr->sh_type == SHT_RELR)
+	    handle_relocs_relr (ebl, mod, scn, shdr);
+	}
+    }
+}
+
+
+/* Handle a relocation section.  */
+static void
+handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  int class = gelf_getclass (ebl->elf);
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_REL, 1, EV_CURRENT);
+  int nentries = shdr->sh_size / sh_entsize;
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return;
+
+  /* Get the symbol table information.  */
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+
+  /* Get the section header of the section the relocations are for.  */
+  GElf_Shdr destshdr_mem;
+  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
+				      &destshdr_mem);
+
+  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
+    {
+      printf (_("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
+	      shdr->sh_offset);
+      return;
+    }
+
+  /* Search for the optional extended section index table.  */
+  Elf_Data *xndxdata = NULL;
+  int xndxscnidx = elf_scnshndx (scn);
+  if (unlikely (xndxscnidx > 0))
+    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  if (shdr->sh_info != 0)
+    printf (ngettext ("\
+\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+		    "\
+\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+		      nentries),
+	    elf_ndxscn (scn),
+	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	    (unsigned int) shdr->sh_info,
+	    elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
+	    shdr->sh_offset,
+	    nentries);
+  else
+    /* The .rel.dyn section does not refer to a specific section but
+       instead of section index zero.  Do not try to print a section
+       name.  */
+    printf (ngettext ("\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+		    "\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+		      nentries),
+	    (unsigned int) elf_ndxscn (scn),
+	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	    shdr->sh_offset,
+	    nentries);
+  fputs_unlocked (class == ELFCLASS32
+		  ? _("\
+  Offset      Type                 Value       Name\n")
+		  : _("\
+  Offset              Type                 Value               Name\n"),
+	 stdout);
+
+  int is_statically_linked = 0;
+  for (int cnt = 0; cnt < nentries; ++cnt)
+    {
+      GElf_Rel relmem;
+      GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
+      if (likely (rel != NULL))
+	{
+	  char buf[128];
+	  GElf_Sym symmem;
+	  Elf32_Word xndx;
+	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+					    GELF_R_SYM (rel->r_info),
+					    &symmem, &xndx);
+	  if (unlikely (sym == NULL))
+	    {
+	      /* As a special case we have to handle relocations in static
+		 executables.  This only happens for IRELATIVE relocations
+		 (so far).  There is no symbol table.  */
+	      if (is_statically_linked == 0)
+		{
+		  /* Find the program header and look for a PT_INTERP entry. */
+		  is_statically_linked = -1;
+		  if (ehdr->e_type == ET_EXEC)
+		    {
+		      is_statically_linked = 1;
+
+		      for (size_t inner = 0; inner < phnum; ++inner)
+			{
+			  GElf_Phdr phdr_mem;
+			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
+							  &phdr_mem);
+			  if (phdr != NULL && phdr->p_type == PT_INTERP)
+			    {
+			      is_statically_linked = -1;
+			      break;
+			    }
+			}
+		    }
+		}
+
+	      if (is_statically_linked > 0 && shdr->sh_link == 0)
+		printf ("\
+  %#0*" PRIx64 "  %-20s %*s  %s\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			class == ELFCLASS32 ? 10 : 18, "",
+			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
+	      else
+		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			_("INVALID SYMBOL"),
+			(long int) GELF_R_SYM (rel->r_info));
+	    }
+	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
+	    printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
+		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+		    likely (ebl_reloc_type_check (ebl,
+						  GELF_R_TYPE (rel->r_info)))
+		    /* Avoid the leading R_ which isn't carrying any
+		       information.  */
+		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					   buf, sizeof (buf)) + 2
+		    : _("<INVALID RELOC>"),
+		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
+		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+	  else
+	    {
+	      /* This is a relocation against a STT_SECTION symbol.  */
+	      GElf_Shdr secshdr_mem;
+	      GElf_Shdr *secshdr;
+	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
+						  sym->st_shndx == SHN_XINDEX
+						  ? xndx : sym->st_shndx),
+				      &secshdr_mem);
+
+	      if (unlikely (secshdr == NULL))
+		printf ("  %#0*" PRIx64 "  %-20s <%s %ld>\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			_("INVALID SECTION"),
+			(long int) (sym->st_shndx == SHN_XINDEX
+				    ? xndx : sym->st_shndx));
+	      else
+		printf ("  %#0*" PRIx64 "  %-20s %#0*" PRIx64 "  %s\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			class == ELFCLASS32 ? 10 : 18, sym->st_value,
+			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+	    }
+	}
+    }
+}
+
+
+/* Handle a relocation section.  */
+static void
+handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  int class = gelf_getclass (ebl->elf);
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELA, 1, EV_CURRENT);
+  int nentries = shdr->sh_size / sh_entsize;
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return;
+
+  /* Get the symbol table information.  */
+  Elf_Scn *symscn = elf_getscn (ebl->elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+
+  /* Get the section header of the section the relocations are for.  */
+  GElf_Shdr destshdr_mem;
+  GElf_Shdr *destshdr = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_info),
+				      &destshdr_mem);
+
+  if (unlikely (symshdr == NULL || symdata == NULL || destshdr == NULL))
+    {
+      printf (_("\nInvalid symbol table at offset %#0" PRIx64 "\n"),
+	      shdr->sh_offset);
+      return;
+    }
+
+  /* Search for the optional extended section index table.  */
+  Elf_Data *xndxdata = NULL;
+  int xndxscnidx = elf_scnshndx (scn);
+  if (unlikely (xndxscnidx > 0))
+    xndxdata = elf_getdata (elf_getscn (ebl->elf, xndxscnidx), NULL);
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  if (shdr->sh_info != 0)
+    printf (ngettext ("\
+\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+		    "\
+\nRelocation section [%2zu] '%s' for section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+		    nentries),
+	  elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	  (unsigned int) shdr->sh_info,
+	  elf_strptr (ebl->elf, shstrndx, destshdr->sh_name),
+	  shdr->sh_offset,
+	  nentries);
+  else
+    /* The .rela.dyn section does not refer to a specific section but
+       instead of section index zero.  Do not try to print a section
+       name.  */
+    printf (ngettext ("\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+		    "\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+		      nentries),
+	    (unsigned int) elf_ndxscn (scn),
+	    elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	    shdr->sh_offset,
+	    nentries);
+  fputs_unlocked (class == ELFCLASS32
+		  ? _("\
+  Offset      Type            Value       Addend Name\n")
+		  : _("\
+  Offset              Type            Value               Addend Name\n"),
+		  stdout);
+
+  int is_statically_linked = 0;
+  for (int cnt = 0; cnt < nentries; ++cnt)
+    {
+      GElf_Rela relmem;
+      GElf_Rela *rel = gelf_getrela (data, cnt, &relmem);
+      if (likely (rel != NULL))
+	{
+	  char buf[64];
+	  GElf_Sym symmem;
+	  Elf32_Word xndx;
+	  GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+					    GELF_R_SYM (rel->r_info),
+					    &symmem, &xndx);
+
+	  if (unlikely (sym == NULL))
+	    {
+	      /* As a special case we have to handle relocations in static
+		 executables.  This only happens for IRELATIVE relocations
+		 (so far).  There is no symbol table.  */
+	      if (is_statically_linked == 0)
+		{
+		  /* Find the program header and look for a PT_INTERP entry. */
+		  is_statically_linked = -1;
+		  if (ehdr->e_type == ET_EXEC)
+		    {
+		      is_statically_linked = 1;
+
+		      for (size_t inner = 0; inner < phnum; ++inner)
+			{
+			  GElf_Phdr phdr_mem;
+			  GElf_Phdr *phdr = gelf_getphdr (ebl->elf, inner,
+							  &phdr_mem);
+			  if (phdr != NULL && phdr->p_type == PT_INTERP)
+			    {
+			      is_statically_linked = -1;
+			      break;
+			    }
+			}
+		    }
+		}
+
+	      if (is_statically_linked > 0 && shdr->sh_link == 0)
+		printf ("\
+  %#0*" PRIx64 "  %-15s %*s  %#6" PRIx64 " %s\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			class == ELFCLASS32 ? 10 : 18, "",
+			rel->r_addend,
+			elf_strptr (ebl->elf, shstrndx, destshdr->sh_name));
+	      else
+		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			_("INVALID SYMBOL"),
+			(long int) GELF_R_SYM (rel->r_info));
+	    }
+	  else if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
+	    printf ("\
+  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
+		    class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+		    likely (ebl_reloc_type_check (ebl,
+						  GELF_R_TYPE (rel->r_info)))
+		    /* Avoid the leading R_ which isn't carrying any
+		       information.  */
+		    ? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					   buf, sizeof (buf)) + 2
+		    : _("<INVALID RELOC>"),
+		    class == ELFCLASS32 ? 10 : 18, sym->st_value,
+		    rel->r_addend,
+		    elf_strptr (ebl->elf, symshdr->sh_link, sym->st_name));
+	  else
+	    {
+	      /* This is a relocation against a STT_SECTION symbol.  */
+	      GElf_Shdr secshdr_mem;
+	      GElf_Shdr *secshdr;
+	      secshdr = gelf_getshdr (elf_getscn (ebl->elf,
+						  sym->st_shndx == SHN_XINDEX
+						  ? xndx : sym->st_shndx),
+				      &secshdr_mem);
+
+	      if (unlikely (secshdr == NULL))
+		printf ("  %#0*" PRIx64 "  %-15s <%s %ld>\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			_("INVALID SECTION"),
+			(long int) (sym->st_shndx == SHN_XINDEX
+				    ? xndx : sym->st_shndx));
+	      else
+		printf ("\
+  %#0*" PRIx64 "  %-15s %#0*" PRIx64 "  %+6" PRId64 " %s\n",
+			class == ELFCLASS32 ? 10 : 18, rel->r_offset,
+			ebl_reloc_type_check (ebl, GELF_R_TYPE (rel->r_info))
+			/* Avoid the leading R_ which isn't carrying any
+			   information.  */
+			? ebl_reloc_type_name (ebl, GELF_R_TYPE (rel->r_info),
+					       buf, sizeof (buf)) + 2
+			: _("<INVALID RELOC>"),
+			class == ELFCLASS32 ? 10 : 18, sym->st_value,
+			rel->r_addend,
+			elf_strptr (ebl->elf, shstrndx, secshdr->sh_name));
+	    }
+	}
+    }
+}
+
+/* Handle a relocation section.  */
+static void
+handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  int class = gelf_getclass (ebl->elf);
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELR, 1, EV_CURRENT);
+  int nentries = shdr->sh_size / sh_entsize;
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* A .relr.dyn section does not refer to a specific section.  */
+  printf (ngettext ("\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+		    "\
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+		    nentries),
+	  (unsigned int) elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	  shdr->sh_offset,
+	  nentries);
+
+  if (class == ELFCLASS32)
+    {
+      uint32_t base = 0;
+      for (int cnt = 0; cnt < nentries; ++cnt)
+	{
+	  Elf32_Word *words = data->d_buf;
+	  Elf32_Word entry = words[cnt];
+
+	  /* Just the raw entries?  */
+	  if (print_unresolved_addresses)
+            printf ("  %#010" PRIx32 "%s\n", entry,
+                    (entry & 1) == 0 ? " *" : "");
+	  else
+	    {
+	      /* A real address, also sets base.  */
+	      if ((entry & 1) == 0)
+		{
+		  printf ("  ");
+		  print_dwarf_addr (mod, 4, entry, entry);
+		  printf (" *\n");
+
+		  base = entry + 4;
+		}
+	      else
+		{
+		  /* Untangle address from base and bits.  */
+		  uint32_t addr;
+		  for (addr = base; (entry >>= 1) != 0; addr += 4)
+		    if ((entry & 1) != 0)
+		      {
+			printf ("  ");
+			print_dwarf_addr (mod, 4, addr, addr);
+			printf ("\n");
+		      }
+		  base += 4 * (4 * 8 - 1);
+		}
+	    }
+	}
+    }
+  else
+    {
+      uint64_t base = 0;
+      for (int cnt = 0; cnt < nentries; ++cnt)
+	{
+	  Elf64_Xword *xwords = data->d_buf;
+	  Elf64_Xword entry = xwords[cnt];
+
+	  /* Just the raw entries?  */
+	  if (print_unresolved_addresses)
+	    printf ("  %#018" PRIx64 "%s\n", entry,
+		    (entry & 1) == 0 ? " *" : "");
+	  else
+	    {
+	      /* A real address, also sets base.  */
+	      if ((entry & 1) == 0)
+		{
+		  printf ("  ");
+		  print_dwarf_addr (mod, 8, entry, entry);
+		  printf (" *\n");
+
+		  base = entry + 8;
+		}
+	      else
+		{
+		  /* Untangle address from base and bits.  */
+		  uint64_t addr;
+		  for (addr = base; (entry >>= 1) != 0; addr += 8)
+		    if ((entry & 1) != 0)
+		      {
+			printf ("  ");
+			print_dwarf_addr (mod, 8, addr, addr);
+			printf ("\n");
+		      }
+		  base += 8 * (8 * 8 - 1);
+		}
+	    }
+	}
+    }
+}
+
+/* Print the program header.  Return true if a symtab is printed,
+   false otherwise.  */
+static bool
+print_symtab (Ebl *ebl, int type)
+{
+  /* Use the dynamic section info to display symbol tables.  */
+  if (use_dynamic_segment && type == SHT_DYNSYM)
+    return handle_dynamic_symtab(ebl);
+
+  /* Find the symbol table(s).  For this we have to search through the
+     section table.  */
+  Elf_Scn *scn = NULL;
+  bool symtab_printed = false;
+
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      /* Handle the section if it is a symbol table.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr != NULL && shdr->sh_type == (GElf_Word) type)
+	{
+	  if (symbol_table_section != NULL)
+	    {
+	      /* Get the section header string table index.  */
+	      size_t shstrndx;
+	      const char *sname;
+	      if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+		error_exit (0,
+			    _("cannot get section header string table index"));
+	      sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+	      if (sname == NULL || strcmp (sname, symbol_table_section) != 0)
+		continue;
+	    }
+
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      if (elf_compress (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	      shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (unlikely (shdr == NULL))
+		error_exit (0,
+			    _("cannot get section [%zd] header: %s"),
+			    elf_ndxscn (scn), elf_errmsg (-1));
+	    }
+	  symtab_printed = handle_symtab (ebl, scn, shdr);
+	}
+    }
+
+  return symtab_printed;
+}
+
+
+static void
+process_symtab (Ebl *ebl, unsigned int nsyms, Elf64_Word idx,
+                Elf32_Word verneed_stridx, Elf32_Word verdef_stridx,
+                Elf_Data *symdata, Elf_Data *versym_data,
+                Elf_Data *symstr_data, Elf_Data *verneed_data,
+                Elf_Data *verdef_data, Elf_Data *xndx_data)
+{
+  for (unsigned int cnt = 0; cnt < nsyms; ++cnt)
+    {
+      char typebuf[64];
+      char bindbuf[64];
+      char scnbuf[64];
+      Elf32_Word xndx;
+      GElf_Sym sym_mem;
+      GElf_Sym *sym
+          = gelf_getsymshndx (symdata, xndx_data, cnt, &sym_mem, &xndx);
+
+      if (unlikely (sym == NULL))
+        continue;
+
+      /* Determine the real section index.  */
+      if (likely (sym->st_shndx != SHN_XINDEX))
+        xndx = sym->st_shndx;
+
+      printf (_ ("\
+%5u: %0*" PRIx64 " %6" PRId64 " %-7s %-6s %-9s %6s %s"),
+              cnt, gelf_getclass (ebl->elf) == ELFCLASS32 ? 8 : 16,
+              sym->st_value, sym->st_size,
+              ebl_symbol_type_name (ebl, GELF_ST_TYPE (sym->st_info), typebuf,
+                                    sizeof (typebuf)),
+              ebl_symbol_binding_name (ebl, GELF_ST_BIND (sym->st_info),
+                                       bindbuf, sizeof (bindbuf)),
+              get_visibility_type (GELF_ST_VISIBILITY (sym->st_other)),
+              ebl_section_name (ebl, sym->st_shndx, xndx, scnbuf,
+                                sizeof (scnbuf), NULL, shnum),
+              use_dynamic_segment == true
+                  ? (char *)symstr_data->d_buf + sym->st_name
+                  : elf_strptr (ebl->elf, idx, sym->st_name));
+
+      if (versym_data != NULL)
+        {
+          /* Get the version information.  */
+          GElf_Versym versym_mem;
+          GElf_Versym *versym = gelf_getversym (versym_data, cnt, &versym_mem);
+
+          if (versym != NULL && ((*versym & 0x8000) != 0 || *versym > 1))
+            {
+              bool is_nobits = false;
+              bool check_def = xndx != SHN_UNDEF;
+
+              if (xndx < SHN_LORESERVE || sym->st_shndx == SHN_XINDEX)
+                {
+                  GElf_Shdr symshdr_mem;
+                  GElf_Shdr *symshdr = gelf_getshdr (
+                      elf_getscn (ebl->elf, xndx), &symshdr_mem);
+
+                  is_nobits
+                      = (symshdr != NULL && symshdr->sh_type == SHT_NOBITS);
+                }
+
+              if (is_nobits || !check_def)
+                {
+                  /* We must test both.  */
+                  GElf_Vernaux vernaux_mem;
+                  GElf_Vernaux *vernaux = NULL;
+                  size_t vn_offset = 0;
+
+                  GElf_Verneed verneed_mem;
+                  GElf_Verneed *verneed
+                      = gelf_getverneed (verneed_data, 0, &verneed_mem);
+                  while (verneed != NULL)
+                    {
+                      size_t vna_offset = vn_offset;
+
+                      vernaux = gelf_getvernaux (verneed_data,
+                                                 vna_offset += verneed->vn_aux,
+                                                 &vernaux_mem);
+                      while (vernaux != NULL && vernaux->vna_other != *versym
+                             && vernaux->vna_next != 0
+                             && (verneed_data->d_size - vna_offset
+                                 >= vernaux->vna_next))
+                        {
+                          /* Update the offset.  */
+                          vna_offset += vernaux->vna_next;
+
+                          vernaux = (vernaux->vna_next == 0
+                                         ? NULL
+                                         : gelf_getvernaux (verneed_data,
+                                                            vna_offset,
+                                                            &vernaux_mem));
+                        }
+
+                      /* Check whether we found the version.  */
+                      if (vernaux != NULL && vernaux->vna_other == *versym)
+                        /* Found it.  */
+                        break;
+
+                      if (verneed_data->d_size - vn_offset < verneed->vn_next)
+                        break;
+
+                      vn_offset += verneed->vn_next;
+                      verneed
+                          = (verneed->vn_next == 0
+                                 ? NULL
+                                 : gelf_getverneed (verneed_data, vn_offset,
+                                                    &verneed_mem));
+                    }
+
+                  if (vernaux != NULL && vernaux->vna_other == *versym)
+                    {
+                      printf ("@%s (%u)",
+                              use_dynamic_segment == true
+                                  ? (char *)symstr_data->d_buf
+                                        + vernaux->vna_name
+                                  : elf_strptr (ebl->elf, verneed_stridx,
+                                                vernaux->vna_name),
+                              (unsigned int)vernaux->vna_other);
+                      check_def = 0;
+                    }
+                  else if (unlikely (!is_nobits))
+                    error (0, 0, _ ("bad dynamic symbol"));
+                  else
+                    check_def = 1;
+                }
+
+              if (check_def && *versym != 0x8001)
+                {
+                  /* We must test both.  */
+                  size_t vd_offset = 0;
+
+                  GElf_Verdef verdef_mem;
+                  GElf_Verdef *verdef
+                      = gelf_getverdef (verdef_data, 0, &verdef_mem);
+                  while (verdef != NULL)
+                    {
+                      if (verdef->vd_ndx == (*versym & 0x7fff))
+                        /* Found the definition.  */
+                        break;
+
+                      if (verdef_data->d_size - vd_offset < verdef->vd_next)
+                        break;
+
+                      vd_offset += verdef->vd_next;
+                      verdef = (verdef->vd_next == 0
+                                    ? NULL
+                                    : gelf_getverdef (verdef_data, vd_offset,
+                                                      &verdef_mem));
+                    }
+
+                  if (verdef != NULL)
+                    {
+                      GElf_Verdaux verdaux_mem;
+                      GElf_Verdaux *verdaux = gelf_getverdaux (
+                          verdef_data, vd_offset + verdef->vd_aux,
+                          &verdaux_mem);
+
+                      if (verdaux != NULL)
+                        printf ((*versym & 0x8000) ? "@%s" : "@@%s",
+                                use_dynamic_segment == true
+                                    ? (char *)symstr_data->d_buf
+                                          + verdaux->vda_name
+                                    : elf_strptr (ebl->elf, verdef_stridx,
+                                                  verdaux->vda_name));
+                    }
+                }
+            }
+        }
+
+      putchar_unlocked ('\n');
+    }
+}
+
+
+static bool
+handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  Elf_Data *versym_data = NULL;
+  Elf_Data *verneed_data = NULL;
+  Elf_Data *verdef_data = NULL;
+  Elf_Data *xndx_data = NULL;
+  int class = gelf_getclass (ebl->elf);
+  Elf32_Word verneed_stridx = 0;
+  Elf32_Word verdef_stridx = 0;
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return false;
+
+  /* Find out whether we have other sections we might need.  */
+  Elf_Scn *runscn = NULL;
+  while ((runscn = elf_nextscn (ebl->elf, runscn)) != NULL)
+    {
+      GElf_Shdr runshdr_mem;
+      GElf_Shdr *runshdr = gelf_getshdr (runscn, &runshdr_mem);
+
+      if (likely (runshdr != NULL))
+	{
+	  if (runshdr->sh_type == SHT_GNU_versym
+	      && runshdr->sh_link == elf_ndxscn (scn))
+	    /* Bingo, found the version information.  Now get the data.  */
+	    versym_data = elf_getdata (runscn, NULL);
+	  else if (runshdr->sh_type == SHT_GNU_verneed)
+	    {
+	      /* This is the information about the needed versions.  */
+	      verneed_data = elf_getdata (runscn, NULL);
+	      verneed_stridx = runshdr->sh_link;
+	    }
+	  else if (runshdr->sh_type == SHT_GNU_verdef)
+	    {
+	      /* This is the information about the defined versions.  */
+	      verdef_data = elf_getdata (runscn, NULL);
+	      verdef_stridx = runshdr->sh_link;
+	    }
+	  else if (runshdr->sh_type == SHT_SYMTAB_SHNDX
+	      && runshdr->sh_link == elf_ndxscn (scn))
+	    /* Extended section index.  */
+	    xndx_data = elf_getdata (runscn, NULL);
+	}
+    }
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				   &glink_mem);
+  if (glink == NULL)
+    error_exit (0, _("invalid sh_link value in section %zu"),
+		elf_ndxscn (scn));
+
+  /* Now we can compute the number of entries in the section.  */
+  unsigned int nsyms = data->d_size / (class == ELFCLASS32
+				       ? sizeof (Elf32_Sym)
+				       : sizeof (Elf64_Sym));
+
+  printf (ngettext ("\nSymbol table [%2u] '%s' contains %u entry:\n",
+		    "\nSymbol table [%2u] '%s' contains %u entries:\n",
+		    nsyms),
+	  (unsigned int) elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), nsyms);
+  printf (ngettext (" %lu local symbol  String table: [%2u] '%s'\n",
+		    " %lu local symbols  String table: [%2u] '%s'\n",
+		    shdr->sh_info),
+	  (unsigned long int) shdr->sh_info,
+	  (unsigned int) shdr->sh_link,
+	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
+
+  fputs_unlocked (class == ELFCLASS32
+		  ? _("\
+  Num:    Value   Size Type    Bind   Vis          Ndx Name\n")
+		  : _("\
+  Num:            Value   Size Type    Bind   Vis          Ndx Name\n"),
+		  stdout);
+
+	process_symtab(ebl, nsyms, shdr->sh_link, verneed_stridx, verdef_stridx,
+	data, versym_data, NULL, verneed_data, verdef_data, xndx_data);
+    return true;
+}
+
+
+static bool
+handle_dynamic_symtab (Ebl *ebl)
+{
+  GElf_Phdr phdr_mem;
+  GElf_Phdr *phdr = NULL;
+  /* phnum is a static variable which was already fetched in function
+     process_elf_file.  */
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      phdr = gelf_getphdr (ebl->elf, i, &phdr_mem);
+      if (phdr->p_type == PT_DYNAMIC)
+	break;
+    }
+  if (phdr == NULL)
+    return false;
+
+  GElf_Addr addrs[i_max] = {
+    0,
+  };
+  GElf_Off offs[i_max] = {
+    0,
+  };
+  get_dynscn_addrs (ebl->elf, phdr, addrs);
+  find_offsets (ebl->elf, 0, i_max, addrs, offs);
+
+  size_t syments = 0;
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (ebl->elf, &ehdr_mem);
+
+  if (offs[i_hash] != 0)
+    {
+      /* In the original format, .hash says the size of .dynsym.  */
+
+      size_t entsz = SH_ENTSIZE_HASH (ehdr);
+      Elf_Data *data
+          = elf_getdata_rawchunk (ebl->elf, offs[i_hash] + entsz, entsz,
+                                  (entsz == 4 ? ELF_T_WORD : ELF_T_XWORD));
+      if (data != NULL)
+        syments = (entsz == 4 ? *(const GElf_Word *)data->d_buf
+                              : *(const GElf_Xword *)data->d_buf);
+    }
+  if (offs[i_gnu_hash] != 0 && syments == 0)
+    {
+      /* In the new format, we can derive it with some work.  */
+
+      const struct
+      {
+        Elf32_Word nbuckets;
+        Elf32_Word symndx;
+        Elf32_Word maskwords;
+        Elf32_Word shift2;
+      } * header;
+
+      Elf_Data *data = elf_getdata_rawchunk (ebl->elf, offs[i_gnu_hash],
+                                             sizeof *header, ELF_T_WORD);
+      if (data != NULL)
+        {
+          header = data->d_buf;
+          Elf32_Word nbuckets = header->nbuckets;
+          Elf32_Word symndx = header->symndx;
+          GElf_Off buckets_at
+              = (offs[i_gnu_hash] + sizeof *header
+                 + (gelf_getclass (ebl->elf) * sizeof (Elf32_Word)
+                    * header->maskwords));
+
+          // elf_getdata_rawchunk takes a size_t, make sure it
+          // doesn't overflow.
+#if SIZE_MAX <= UINT32_MAX
+          if (nbuckets > SIZE_MAX / sizeof (Elf32_Word))
+            data = NULL;
+          else
+#endif
+            data = elf_getdata_rawchunk (ebl->elf, buckets_at,
+                                         nbuckets * sizeof (Elf32_Word),
+                                         ELF_T_WORD);
+          if (data != NULL && symndx < nbuckets)
+            {
+              const Elf32_Word *const buckets = data->d_buf;
+              Elf32_Word maxndx = symndx;
+              for (Elf32_Word bucket = 0; bucket < nbuckets; ++bucket)
+                if (buckets[bucket] > maxndx)
+                  maxndx = buckets[bucket];
+
+              GElf_Off hasharr_at
+                  = (buckets_at + nbuckets * sizeof (Elf32_Word));
+              hasharr_at += (maxndx - symndx) * sizeof (Elf32_Word);
+              do
+                {
+                  data = elf_getdata_rawchunk (
+                      ebl->elf, hasharr_at, sizeof (Elf32_Word), ELF_T_WORD);
+                  if (data != NULL && (*(const Elf32_Word *)data->d_buf & 1u))
+                    {
+                      syments = maxndx + 1;
+                      break;
+                    }
+                  ++maxndx;
+                  hasharr_at += sizeof (Elf32_Word);
+                }
+              while (data != NULL);
+            }
+        }
+    }
+  if (offs[i_strtab] > offs[i_symtab] && syments == 0)
+    syments = ((offs[i_strtab] - offs[i_symtab])
+               / gelf_fsize (ebl->elf, ELF_T_SYM, 1, EV_CURRENT));
+
+  if (syments <= 0 || offs[i_strtab] == 0 || offs[i_symtab] == 0)
+    {
+      error_exit (0, _ ("Dynamic symbol information is not available for "
+                        "displaying symbols."));
+    }
+
+  /* All the data chunk initializaion.  */
+  Elf_Data *symdata = NULL;
+  Elf_Data *symstrdata = NULL;
+  Elf_Data *versym_data = NULL;
+  Elf_Data *verdef_data = NULL;
+  Elf_Data *verneed_data = NULL;
+
+  symdata = elf_getdata_rawchunk (
+      ebl->elf, offs[i_symtab],
+      gelf_fsize (ebl->elf, ELF_T_SYM, syments, EV_CURRENT), ELF_T_SYM);
+  symstrdata = elf_getdata_rawchunk (ebl->elf, offs[i_strtab], addrs[i_strsz],
+                                     ELF_T_BYTE);
+  versym_data = elf_getdata_rawchunk (
+      ebl->elf, offs[i_versym], syments * sizeof (Elf64_Half), ELF_T_HALF);
+
+  /* Get the verneed_data without vernaux.  */
+  verneed_data = elf_getdata_rawchunk (
+      ebl->elf, offs[i_verneed], addrs[i_verneednum] * sizeof (Elf64_Verneed),
+      ELF_T_VNEED);
+  size_t vernauxnum = 0;
+  size_t vn_next_offset = 0;
+
+  for (size_t i = 0; i < addrs[i_verneednum]; i++)
+    {
+      GElf_Verneed *verneed
+          = (GElf_Verneed *)(verneed_data->d_buf + vn_next_offset);
+      vernauxnum += verneed->vn_cnt;
+      vn_next_offset += verneed->vn_next;
+    }
+
+  /* Update the verneed_data to include the vernaux.  */
+  verneed_data = elf_getdata_rawchunk (
+      ebl->elf, offs[i_verneed],
+      (addrs[i_verneednum] + vernauxnum) * sizeof (GElf_Verneed), ELF_T_VNEED);
+
+  /* Get the verdef_data without verdaux.  */
+  verdef_data = elf_getdata_rawchunk (
+      ebl->elf, offs[i_verdef], addrs[i_verdefnum] * sizeof (Elf64_Verdef),
+      ELF_T_VDEF);
+  size_t verdauxnum = 0;
+  size_t vd_next_offset = 0;
+
+  for (size_t i = 0; i < addrs[i_verdefnum]; i++)
+    {
+      GElf_Verdef *verdef
+          = (GElf_Verdef *)(verdef_data->d_buf + vd_next_offset);
+      verdauxnum += verdef->vd_cnt;
+      vd_next_offset += verdef->vd_next;
+    }
+
+  /* Update the verdef_data to include the verdaux.  */
+  verdef_data = elf_getdata_rawchunk (
+      ebl->elf, offs[i_verdef],
+      (addrs[i_verdefnum] + verdauxnum) * sizeof (GElf_Verdef), ELF_T_VDEF);
+
+  unsigned int nsyms = (unsigned int)syments;
+  process_symtab (ebl, nsyms, 0, 0, 0, symdata, versym_data, symstrdata,
+                  verneed_data, verdef_data, NULL);
+  return true;
+}
+
+
+/* Print version information.  */
+static void
+print_verinfo (Ebl *ebl)
+{
+  /* Find the version information sections.  For this we have to
+     search through the section table.  */
+  Elf_Scn *scn = NULL;
+
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      /* Handle the section if it is part of the versioning handling.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (likely (shdr != NULL))
+	{
+	  if (shdr->sh_type == SHT_GNU_verneed)
+	    handle_verneed (ebl, scn, shdr);
+	  else if (shdr->sh_type == SHT_GNU_verdef)
+	    handle_verdef (ebl, scn, shdr);
+	  else if (shdr->sh_type == SHT_GNU_versym)
+	    handle_versym (ebl, scn, shdr);
+	}
+    }
+}
+
+
+static const char *
+get_ver_flags (unsigned int flags)
+{
+  static char buf[32];
+  char *endp;
+
+  if (flags == 0)
+    return _("none");
+
+  if (flags & VER_FLG_BASE)
+    endp = stpcpy (buf, "BASE ");
+  else
+    endp = buf;
+
+  if (flags & VER_FLG_WEAK)
+    {
+      if (endp != buf)
+	endp = stpcpy (endp, "| ");
+
+      endp = stpcpy (endp, "WEAK ");
+    }
+
+  if (unlikely (flags & ~(VER_FLG_BASE | VER_FLG_WEAK)))
+    {
+      strncpy (endp, _("| <unknown>"), buf + sizeof (buf) - endp);
+      buf[sizeof (buf) - 1] = '\0';
+    }
+
+  return buf;
+}
+
+
+static void
+handle_verneed (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  int class = gelf_getclass (ebl->elf);
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				   &glink_mem);
+  if (glink == NULL)
+    error_exit (0, _("invalid sh_link value in section %zu"),
+		elf_ndxscn (scn));
+
+  printf (ngettext ("\
+\nVersion needs section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    "\
+\nVersion needs section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    shdr->sh_info),
+	  (unsigned int) elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name), shdr->sh_info,
+	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+	  shdr->sh_offset,
+	  (unsigned int) shdr->sh_link,
+	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
+
+  unsigned int offset = 0;
+  for (unsigned int cnt = shdr->sh_info; cnt > 0; cnt--)
+    {
+      /* Get the data at the next offset.  */
+      GElf_Verneed needmem;
+      GElf_Verneed *need = gelf_getverneed (data, offset, &needmem);
+      if (unlikely (need == NULL))
+	break;
+
+      printf (_("  %#06x: Version: %hu  File: %s  Cnt: %hu\n"),
+	      offset, (unsigned short int) need->vn_version,
+	      elf_strptr (ebl->elf, shdr->sh_link, need->vn_file),
+	      (unsigned short int) need->vn_cnt);
+
+      unsigned int auxoffset = offset + need->vn_aux;
+      for (unsigned int cnt2 = need->vn_cnt; cnt2 > 0; cnt2--)
+	{
+	  GElf_Vernaux auxmem;
+	  GElf_Vernaux *aux = gelf_getvernaux (data, auxoffset, &auxmem);
+	  if (unlikely (aux == NULL))
+	    break;
+
+	  printf (_("  %#06x: Name: %s  Flags: %s  Version: %hu\n"),
+		  auxoffset,
+		  elf_strptr (ebl->elf, shdr->sh_link, aux->vna_name),
+		  get_ver_flags (aux->vna_flags),
+		  (unsigned short int) aux->vna_other);
+
+	  if (aux->vna_next == 0)
+	    break;
+
+	  auxoffset += aux->vna_next;
+	}
+
+      /* Find the next offset.  */
+      if (need->vn_next == 0)
+	break;
+
+      offset += need->vn_next;
+    }
+}
+
+
+static void
+handle_verdef (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				   &glink_mem);
+  if (glink == NULL)
+    error_exit (0, _("invalid sh_link value in section %zu"),
+		elf_ndxscn (scn));
+
+  int class = gelf_getclass (ebl->elf);
+  printf (ngettext ("\
+\nVersion definition section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    "\
+\nVersion definition section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    shdr->sh_info),
+	  (unsigned int) elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	  shdr->sh_info,
+	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+	  shdr->sh_offset,
+	  (unsigned int) shdr->sh_link,
+	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
+
+  unsigned int offset = 0;
+  for (unsigned int cnt = shdr->sh_info; cnt > 0; cnt--)
+    {
+      /* Get the data at the next offset.  */
+      GElf_Verdef defmem;
+      GElf_Verdef *def = gelf_getverdef (data, offset, &defmem);
+      if (unlikely (def == NULL))
+	break;
+
+      unsigned int auxoffset = offset + def->vd_aux;
+      GElf_Verdaux auxmem;
+      GElf_Verdaux *aux = gelf_getverdaux (data, auxoffset, &auxmem);
+      if (unlikely (aux == NULL))
+	break;
+
+      printf (_("\
+  %#06x: Version: %hd  Flags: %s  Index: %hd  Cnt: %hd  Name: %s\n"),
+	      offset, def->vd_version,
+	      get_ver_flags (def->vd_flags),
+	      def->vd_ndx,
+	      def->vd_cnt,
+	      elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
+
+      auxoffset += aux->vda_next;
+      for (unsigned int cnt2 = 1; cnt2 < def->vd_cnt; ++cnt2)
+	{
+	  aux = gelf_getverdaux (data, auxoffset, &auxmem);
+	  if (unlikely (aux == NULL))
+	    break;
+
+	  printf (_("  %#06x: Parent %d: %s\n"),
+		  auxoffset, cnt2,
+		  elf_strptr (ebl->elf, shdr->sh_link, aux->vda_name));
+
+	  if (aux->vda_next == 0)
+	    break;
+
+	  auxoffset += aux->vda_next;
+	}
+
+      /* Find the next offset.  */
+      if (def->vd_next == 0)
+	break;
+      offset += def->vd_next;
+    }
+}
+
+
+static void
+handle_versym (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr)
+{
+  int class = gelf_getclass (ebl->elf);
+  const char **vername;
+  const char **filename;
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* We have to find the version definition section and extract the
+     version names.  */
+  Elf_Scn *defscn = NULL;
+  Elf_Scn *needscn = NULL;
+
+  Elf_Scn *verscn = NULL;
+  while ((verscn = elf_nextscn (ebl->elf, verscn)) != NULL)
+    {
+      GElf_Shdr vershdr_mem;
+      GElf_Shdr *vershdr = gelf_getshdr (verscn, &vershdr_mem);
+
+      if (likely (vershdr != NULL))
+	{
+	  if (vershdr->sh_type == SHT_GNU_verdef)
+	    defscn = verscn;
+	  else if (vershdr->sh_type == SHT_GNU_verneed)
+	    needscn = verscn;
+	}
+    }
+
+  size_t nvername;
+  if (defscn != NULL || needscn != NULL)
+    {
+      /* We have a version information (better should have).  Now get
+	 the version names.  First find the maximum version number.  */
+      nvername = 0;
+      if (defscn != NULL)
+	{
+	  /* Run through the version definitions and find the highest
+	     index.  */
+	  unsigned int offset = 0;
+	  Elf_Data *defdata;
+	  GElf_Shdr defshdrmem;
+	  GElf_Shdr *defshdr;
+
+	  defdata = elf_getdata (defscn, NULL);
+	  if (unlikely (defdata == NULL))
+	    return;
+
+	  defshdr = gelf_getshdr (defscn, &defshdrmem);
+	  if (unlikely (defshdr == NULL))
+	    return;
+
+	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
+	    {
+	      GElf_Verdef defmem;
+	      GElf_Verdef *def;
+
+	      /* Get the data at the next offset.  */
+	      def = gelf_getverdef (defdata, offset, &defmem);
+	      if (unlikely (def == NULL))
+		break;
+
+	      nvername = MAX (nvername, (size_t) (def->vd_ndx & 0x7fff));
+
+	      if (def->vd_next == 0)
+		break;
+	      offset += def->vd_next;
+	    }
+	}
+      if (needscn != NULL)
+	{
+	  unsigned int offset = 0;
+	  Elf_Data *needdata;
+	  GElf_Shdr needshdrmem;
+	  GElf_Shdr *needshdr;
+
+	  needdata = elf_getdata (needscn, NULL);
+	  if (unlikely (needdata == NULL))
+	    return;
+
+	  needshdr = gelf_getshdr (needscn, &needshdrmem);
+	  if (unlikely (needshdr == NULL))
+	    return;
+
+	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
+	    {
+	      GElf_Verneed needmem;
+	      GElf_Verneed *need;
+	      unsigned int auxoffset;
+	      int cnt2;
+
+	      /* Get the data at the next offset.  */
+	      need = gelf_getverneed (needdata, offset, &needmem);
+	      if (unlikely (need == NULL))
+		break;
+
+	      /* Run through the auxiliary entries.  */
+	      auxoffset = offset + need->vn_aux;
+	      for (cnt2 = need->vn_cnt; --cnt2 >= 0; )
+		{
+		  GElf_Vernaux auxmem;
+		  GElf_Vernaux *aux;
+
+		  aux = gelf_getvernaux (needdata, auxoffset, &auxmem);
+		  if (unlikely (aux == NULL))
+		    break;
+
+		  nvername = MAX (nvername,
+				  (size_t) (aux->vna_other & 0x7fff));
+
+		  if (aux->vna_next == 0)
+		    break;
+		  auxoffset += aux->vna_next;
+		}
+
+	      if (need->vn_next == 0)
+		break;
+	      offset += need->vn_next;
+	    }
+	}
+
+      /* This is the number of versions we know about.  */
+      ++nvername;
+
+      /* Allocate the array.  */
+      vername = (const char **) alloca (nvername * sizeof (const char *));
+      memset(vername, 0, nvername * sizeof (const char *));
+      filename = (const char **) alloca (nvername * sizeof (const char *));
+      memset(filename, 0, nvername * sizeof (const char *));
+
+      /* Run through the data structures again and collect the strings.  */
+      if (defscn != NULL)
+	{
+	  /* Run through the version definitions and find the highest
+	     index.  */
+	  unsigned int offset = 0;
+	  Elf_Data *defdata;
+	  GElf_Shdr defshdrmem;
+	  GElf_Shdr *defshdr;
+
+	  defdata = elf_getdata (defscn, NULL);
+	  if (unlikely (defdata == NULL))
+	    return;
+
+	  defshdr = gelf_getshdr (defscn, &defshdrmem);
+	  if (unlikely (defshdr == NULL))
+	    return;
+
+	  for (unsigned int cnt = 0; cnt < defshdr->sh_info; ++cnt)
+	    {
+
+	      /* Get the data at the next offset.  */
+	      GElf_Verdef defmem;
+	      GElf_Verdef *def = gelf_getverdef (defdata, offset, &defmem);
+	      if (unlikely (def == NULL))
+		break;
+
+	      GElf_Verdaux auxmem;
+	      GElf_Verdaux *aux = gelf_getverdaux (defdata,
+						   offset + def->vd_aux,
+						   &auxmem);
+	      if (unlikely (aux == NULL))
+		break;
+
+	      vername[def->vd_ndx & 0x7fff]
+		= elf_strptr (ebl->elf, defshdr->sh_link, aux->vda_name);
+	      filename[def->vd_ndx & 0x7fff] = NULL;
+
+	      if (def->vd_next == 0)
+		break;
+	      offset += def->vd_next;
+	    }
+	}
+      if (needscn != NULL)
+	{
+	  unsigned int offset = 0;
+
+	  Elf_Data *needdata = elf_getdata (needscn, NULL);
+	  GElf_Shdr needshdrmem;
+	  GElf_Shdr *needshdr = gelf_getshdr (needscn, &needshdrmem);
+	  if (unlikely (needdata == NULL || needshdr == NULL))
+	    return;
+
+	  for (unsigned int cnt = 0; cnt < needshdr->sh_info; ++cnt)
+	    {
+	      /* Get the data at the next offset.  */
+	      GElf_Verneed needmem;
+	      GElf_Verneed *need = gelf_getverneed (needdata, offset,
+						    &needmem);
+	      if (unlikely (need == NULL))
+		break;
+
+	      /* Run through the auxiliary entries.  */
+	      unsigned int auxoffset = offset + need->vn_aux;
+	      for (int cnt2 = need->vn_cnt; --cnt2 >= 0; )
+		{
+		  GElf_Vernaux auxmem;
+		  GElf_Vernaux *aux = gelf_getvernaux (needdata, auxoffset,
+						       &auxmem);
+		  if (unlikely (aux == NULL))
+		    break;
+
+		  vername[aux->vna_other & 0x7fff]
+		    = elf_strptr (ebl->elf, needshdr->sh_link, aux->vna_name);
+		  filename[aux->vna_other & 0x7fff]
+		    = elf_strptr (ebl->elf, needshdr->sh_link, need->vn_file);
+
+		  if (aux->vna_next == 0)
+		    break;
+		  auxoffset += aux->vna_next;
+		}
+
+	      if (need->vn_next == 0)
+		break;
+	      offset += need->vn_next;
+	    }
+	}
+    }
+  else
+    {
+      vername = NULL;
+      nvername = 1;
+      filename = NULL;
+    }
+
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link),
+				   &glink_mem);
+  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_HALF, 1, EV_CURRENT);
+  if (glink == NULL)
+    error_exit (0, _("invalid sh_link value in section %zu"),
+		elf_ndxscn (scn));
+
+  /* Print the header.  */
+  printf (ngettext ("\
+\nVersion symbols section [%2u] '%s' contains %d entry:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
+		    "\
+\nVersion symbols section [%2u] '%s' contains %d entries:\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'",
+		    shdr->sh_size / sh_entsize),
+	  (unsigned int) elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	  (int) (shdr->sh_size / sh_entsize),
+	  class == ELFCLASS32 ? 10 : 18, shdr->sh_addr,
+	  shdr->sh_offset,
+	  (unsigned int) shdr->sh_link,
+	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
+
+  /* Now we can finally look at the actual contents of this section.  */
+  for (unsigned int cnt = 0; cnt < shdr->sh_size / sh_entsize; ++cnt)
+    {
+      if (cnt % 2 == 0)
+	printf ("\n %4d:", cnt);
+
+      GElf_Versym symmem;
+      GElf_Versym *sym = gelf_getversym (data, cnt, &symmem);
+      if (sym == NULL)
+	break;
+
+      switch (*sym)
+	{
+	  ssize_t n;
+	case 0:
+	  fputs_unlocked (_("   0 *local*                     "),
+			  stdout);
+	  break;
+
+	case 1:
+	  fputs_unlocked (_("   1 *global*                    "),
+			  stdout);
+	  break;
+
+	default:
+	  n = printf ("%4d%c%s",
+		      *sym & 0x7fff, *sym & 0x8000 ? 'h' : ' ',
+		      (vername != NULL
+		       && (unsigned int) (*sym & 0x7fff) < nvername)
+		      ? vername[*sym & 0x7fff] : "???");
+	  if ((unsigned int) (*sym & 0x7fff) < nvername
+	      && filename != NULL && filename[*sym & 0x7fff] != NULL)
+	    n += printf ("(%s)", filename[*sym & 0x7fff]);
+	  printf ("%*s", MAX (0, 33 - (int) n), " ");
+	  break;
+	}
+    }
+  putchar_unlocked ('\n');
+}
+
+
+static void
+print_hash_info (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx,
+		 uint_fast32_t maxlength, Elf32_Word nbucket,
+		 uint_fast32_t nsyms, uint32_t *lengths, const char *extrastr)
+{
+  uint32_t *counts = xcalloc (maxlength + 1, sizeof (uint32_t));
+
+  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
+    ++counts[lengths[cnt]];
+
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink = gelf_getshdr (elf_getscn (ebl->elf,
+					       shdr->sh_link),
+				   &glink_mem);
+  if (glink == NULL)
+    {
+      error (0, 0, _("invalid sh_link value in section %zu"),
+	     elf_ndxscn (scn));
+      return;
+    }
+
+  printf (ngettext ("\
+\nHistogram for bucket list length in section [%2u] '%s' (total of %d bucket):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    "\
+\nHistogram for bucket list length in section [%2u] '%s' (total of %d buckets):\n Addr: %#0*" PRIx64 "  Offset: %#08" PRIx64 "  Link to section: [%2u] '%s'\n",
+		    nbucket),
+	  (unsigned int) elf_ndxscn (scn),
+	  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	  (int) nbucket,
+	  gelf_getclass (ebl->elf) == ELFCLASS32 ? 10 : 18,
+	  shdr->sh_addr,
+	  shdr->sh_offset,
+	  (unsigned int) shdr->sh_link,
+	  elf_strptr (ebl->elf, shstrndx, glink->sh_name));
+
+  if (extrastr != NULL)
+    fputs (extrastr, stdout);
+
+  if (likely (nbucket > 0))
+    {
+      uint64_t success = 0;
+
+      /* xgettext:no-c-format */
+      fputs_unlocked (_("\
+ Length  Number  % of total  Coverage\n"), stdout);
+      printf (_("      0  %6" PRIu32 "      %5.1f%%\n"),
+	      counts[0], (counts[0] * 100.0) / nbucket);
+
+      uint64_t nzero_counts = 0;
+      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
+	{
+	  nzero_counts += counts[cnt] * cnt;
+	  printf (_("\
+%7d  %6" PRIu32 "      %5.1f%%    %5.1f%%\n"),
+		  (int) cnt, counts[cnt], (counts[cnt] * 100.0) / nbucket,
+		  (nzero_counts * 100.0) / nsyms);
+	}
+
+      Elf32_Word acc = 0;
+      for (Elf32_Word cnt = 1; cnt <= maxlength; ++cnt)
+	{
+	  acc += cnt;
+	  success += counts[cnt] * acc;
+	}
+
+      if (nzero_counts > 0)
+	printf (_("\
+ Average number of tests:   successful lookup: %f\n\
+			  unsuccessful lookup: %f\n"),
+		(double) success / (double) nzero_counts,
+		(double) nzero_counts / (double) nbucket);
+    }
+
+  free (counts);
+}
+
+
+/* This function handles the traditional System V-style hash table format.  */
+static void
+handle_sysv_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
+{
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (unlikely (data == NULL))
+    {
+      error (0, 0, _("cannot get data for section %d: %s"),
+	     (int) elf_ndxscn (scn), elf_errmsg (-1));
+      return;
+    }
+
+  if (unlikely (data->d_size < 2 * sizeof (Elf32_Word)))
+    {
+    invalid_data:
+      error (0, 0, _("invalid data in sysv.hash section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
+  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
+  Elf32_Word nchain = ((Elf32_Word *) data->d_buf)[1];
+
+  uint64_t used_buf = (2ULL + nchain + nbucket) * sizeof (Elf32_Word);
+  if (used_buf > data->d_size)
+    goto invalid_data;
+
+  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[2];
+  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[2 + nbucket];
+
+  uint32_t *lengths = xcalloc (nbucket, sizeof (uint32_t));
+
+  uint_fast32_t maxlength = 0;
+  uint_fast32_t nsyms = 0;
+  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
+    {
+      Elf32_Word inner = bucket[cnt];
+      Elf32_Word chain_len = 0;
+      while (inner > 0 && inner < nchain)
+	{
+	  ++nsyms;
+	  ++chain_len;
+	  if (chain_len > nchain)
+	    {
+	      error (0, 0, _("invalid chain in sysv.hash section %d"),
+		     (int) elf_ndxscn (scn));
+	      free (lengths);
+	      return;
+	    }
+	  if (maxlength < ++lengths[cnt])
+	    ++maxlength;
+
+	  inner = chain[inner];
+	}
+    }
+
+  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
+		   lengths, NULL);
+
+  free (lengths);
+}
+
+
+/* This function handles the incorrect, System V-style hash table
+   format some 64-bit architectures use.  */
+static void
+handle_sysv_hash64 (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
+{
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (unlikely (data == NULL))
+    {
+      error (0, 0, _("cannot get data for section %d: %s"),
+	     (int) elf_ndxscn (scn), elf_errmsg (-1));
+      return;
+    }
+
+  if (unlikely (data->d_size < 2 * sizeof (Elf64_Xword)))
+    {
+    invalid_data:
+      error (0, 0, _("invalid data in sysv.hash64 section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
+  Elf64_Xword nbucket = ((Elf64_Xword *) data->d_buf)[0];
+  Elf64_Xword nchain = ((Elf64_Xword *) data->d_buf)[1];
+
+  uint64_t maxwords = data->d_size / sizeof (Elf64_Xword);
+  if (maxwords < 2
+      || maxwords - 2 < nbucket
+      || maxwords - 2 - nbucket < nchain)
+    goto invalid_data;
+
+  Elf64_Xword *bucket = &((Elf64_Xword *) data->d_buf)[2];
+  Elf64_Xword *chain = &((Elf64_Xword *) data->d_buf)[2 + nbucket];
+
+  uint32_t *lengths = xcalloc (nbucket, sizeof (uint32_t));
+
+  uint_fast32_t maxlength = 0;
+  uint_fast32_t nsyms = 0;
+  for (Elf64_Xword cnt = 0; cnt < nbucket; ++cnt)
+    {
+      Elf64_Xword inner = bucket[cnt];
+      Elf64_Xword chain_len = 0;
+      while (inner > 0 && inner < nchain)
+	{
+	  ++nsyms;
+	  ++chain_len;
+	  if (chain_len > nchain)
+	    {
+	      error (0, 0, _("invalid chain in sysv.hash64 section %d"),
+		     (int) elf_ndxscn (scn));
+	      free (lengths);
+	      return;
+	    }
+	  if (maxlength < ++lengths[cnt])
+	    ++maxlength;
+
+	  inner = chain[inner];
+	}
+    }
+
+  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
+		   lengths, NULL);
+
+  free (lengths);
+}
+
+
+/* This function handles the GNU-style hash table format.  */
+static void
+handle_gnu_hash (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, size_t shstrndx)
+{
+  uint32_t *lengths = NULL;
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (unlikely (data == NULL))
+    {
+      error (0, 0, _("cannot get data for section %d: %s"),
+	     (int) elf_ndxscn (scn), elf_errmsg (-1));
+      return;
+    }
+
+  if (unlikely (data->d_size < 4 * sizeof (Elf32_Word)))
+    {
+    invalid_data:
+      free (lengths);
+      error (0, 0, _("invalid data in gnu.hash section %d"),
+	     (int) elf_ndxscn (scn));
+      return;
+    }
+
+  Elf32_Word nbucket = ((Elf32_Word *) data->d_buf)[0];
+  Elf32_Word symbias = ((Elf32_Word *) data->d_buf)[1];
+
+  /* Next comes the size of the bitmap.  It's measured in words for
+     the architecture.  It's 32 bits for 32 bit archs, and 64 bits for
+     64 bit archs.  There is always a bloom filter present, so zero is
+     an invalid value.  */
+  Elf32_Word bitmask_words = ((Elf32_Word *) data->d_buf)[2];
+  if (gelf_getclass (ebl->elf) == ELFCLASS64)
+    bitmask_words *= 2;
+
+  if (bitmask_words == 0)
+    goto invalid_data;
+
+  Elf32_Word shift = ((Elf32_Word *) data->d_buf)[3];
+
+  /* Is there still room for the sym chain?
+     Use uint64_t calculation to prevent 32bit overflow.  */
+  uint64_t used_buf = (4ULL + bitmask_words + nbucket) * sizeof (Elf32_Word);
+  uint32_t max_nsyms = (data->d_size - used_buf) / sizeof (Elf32_Word);
+  if (used_buf > data->d_size)
+    goto invalid_data;
+
+  lengths = xcalloc (nbucket, sizeof (uint32_t));
+
+  Elf32_Word *bitmask = &((Elf32_Word *) data->d_buf)[4];
+  Elf32_Word *bucket = &((Elf32_Word *) data->d_buf)[4 + bitmask_words];
+  Elf32_Word *chain = &((Elf32_Word *) data->d_buf)[4 + bitmask_words
+						    + nbucket];
+
+  /* Compute distribution of chain lengths.  */
+  uint_fast32_t maxlength = 0;
+  uint_fast32_t nsyms = 0;
+  for (Elf32_Word cnt = 0; cnt < nbucket; ++cnt)
+    if (bucket[cnt] != 0)
+      {
+	Elf32_Word inner = bucket[cnt] - symbias;
+	do
+	  {
+	    ++nsyms;
+	    if (maxlength < ++lengths[cnt])
+	      ++maxlength;
+	    if (inner >= max_nsyms)
+	      goto invalid_data;
+	  }
+	while ((chain[inner++] & 1) == 0);
+      }
+
+  /* Count bits in bitmask.  */
+  uint_fast32_t nbits = 0;
+  for (Elf32_Word cnt = 0; cnt < bitmask_words; ++cnt)
+    {
+      uint_fast32_t word = bitmask[cnt];
+
+      word = (word & 0x55555555) + ((word >> 1) & 0x55555555);
+      word = (word & 0x33333333) + ((word >> 2) & 0x33333333);
+      word = (word & 0x0f0f0f0f) + ((word >> 4) & 0x0f0f0f0f);
+      word = (word & 0x00ff00ff) + ((word >> 8) & 0x00ff00ff);
+      nbits += (word & 0x0000ffff) + ((word >> 16) & 0x0000ffff);
+    }
+
+  char *str = xasprintf (_("\
+ Symbol Bias: %u\n\
+ Bitmask Size: %zu bytes  %" PRIuFAST32 "%% bits set  2nd hash shift: %u\n"),
+			 (unsigned int) symbias,
+			 bitmask_words * sizeof (Elf32_Word),
+			 ((nbits * 100 + 50)
+			  / (uint_fast32_t) (bitmask_words
+					      * sizeof (Elf32_Word) * 8)),
+			  (unsigned int) shift);
+
+  print_hash_info (ebl, scn, shdr, shstrndx, maxlength, nbucket, nsyms,
+		   lengths, str);
+
+  free (str);
+  free (lengths);
+}
+
+
+/* Find the symbol table(s).  For this we have to search through the
+   section table.  */
+static void
+handle_hash (Ebl *ebl)
+{
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      /* Handle the section if it is a symbol table.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (likely (shdr != NULL))
+	{
+	  if ((shdr->sh_type == SHT_HASH || shdr->sh_type == SHT_GNU_HASH)
+	      && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      if (elf_compress (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	      shdr = gelf_getshdr (scn, &shdr_mem);
+	      if (unlikely (shdr == NULL))
+		error_exit (0, _("cannot get section [%zd] header: %s"),
+			    elf_ndxscn (scn), elf_errmsg (-1));
+	    }
+
+	  if (shdr->sh_type == SHT_HASH)
+	    {
+	      if (ebl_sysvhash_entrysize (ebl) == sizeof (Elf64_Xword))
+		handle_sysv_hash64 (ebl, scn, shdr, shstrndx);
+	      else
+		handle_sysv_hash (ebl, scn, shdr, shstrndx);
+	    }
+	  else if (shdr->sh_type == SHT_GNU_HASH)
+	    handle_gnu_hash (ebl, scn, shdr, shstrndx);
+	}
+    }
+}
+
+
+static void
+print_liblist (Ebl *ebl)
+{
+  /* Find the library list sections.  For this we have to search
+     through the section table.  */
+  Elf_Scn *scn = NULL;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr != NULL && shdr->sh_type == SHT_GNU_LIBLIST)
+	{
+	  size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_LIB, 1, EV_CURRENT);
+	  int nentries = shdr->sh_size / sh_entsize;
+	  printf (ngettext ("\
+\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
+			    "\
+\nLibrary list section [%2zu] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
+			    nentries),
+		  elf_ndxscn (scn),
+		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+		  shdr->sh_offset,
+		  nentries);
+
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    return;
+
+	  puts (_("\
+       Library                       Time Stamp          Checksum Version Flags"));
+
+	  for (int cnt = 0; cnt < nentries; ++cnt)
+	    {
+	      GElf_Lib lib_mem;
+	      GElf_Lib *lib = gelf_getlib (data, cnt, &lib_mem);
+	      if (unlikely (lib == NULL))
+		continue;
+
+	      time_t t = (time_t) lib->l_time_stamp;
+	      struct tm *tm = gmtime (&t);
+	      if (unlikely (tm == NULL))
+		continue;
+
+	      printf ("  [%2d] %-29s %04u-%02u-%02uT%02u:%02u:%02u %08x %-7u %u\n",
+		      cnt, elf_strptr (ebl->elf, shdr->sh_link, lib->l_name),
+		      tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
+		      tm->tm_hour, tm->tm_min, tm->tm_sec,
+		      (unsigned int) lib->l_checksum,
+		      (unsigned int) lib->l_version,
+		      (unsigned int) lib->l_flags);
+	    }
+	}
+    }
+}
+
+static inline size_t
+left (Elf_Data *data,
+      const unsigned char *p)
+{
+  return (const unsigned char *) data->d_buf + data->d_size - p;
+}
+
+static void
+print_attributes (Ebl *ebl, const GElf_Ehdr *ehdr)
+{
+  /* Find the object attributes sections.  For this we have to search
+     through the section table.  */
+  Elf_Scn *scn = NULL;
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL || (shdr->sh_type != SHT_GNU_ATTRIBUTES
+			   && (shdr->sh_type != SHT_ARM_ATTRIBUTES
+			       || ehdr->e_machine != EM_ARM)
+			   && (shdr->sh_type != SHT_CSKY_ATTRIBUTES
+			       || ehdr->e_machine != EM_CSKY)
+			   && (shdr->sh_type != SHT_RISCV_ATTRIBUTES
+			       || ehdr->e_machine != EM_RISCV)))
+	continue;
+
+      printf (_("\
+\nObject attributes section [%2zu] '%s' of %" PRIu64
+		       " bytes at offset %#0" PRIx64 ":\n"),
+	      elf_ndxscn (scn),
+	      elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+	      shdr->sh_size, shdr->sh_offset);
+
+      Elf_Data *data = elf_rawdata (scn, NULL);
+      if (unlikely (data == NULL || data->d_size == 0))
+	return;
+
+      const unsigned char *p = data->d_buf;
+
+      /* There is only one 'version', A.  */
+      if (unlikely (*p++ != 'A'))
+	return;
+
+      fputs_unlocked (_("  Owner          Size\n"), stdout);
+
+      /* Loop over the sections.  */
+      while (left (data, p) >= 4)
+	{
+	  /* Section length.  */
+	  uint32_t len;
+	  memcpy (&len, p, sizeof len);
+
+	  if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+	    CONVERT (len);
+
+	  if (unlikely (len > left (data, p)))
+	    break;
+
+	  /* Section vendor name.  */
+	  const unsigned char *name = p + sizeof len;
+	  p += len;
+
+	  unsigned const char *q = memchr (name, '\0', len);
+	  if (unlikely (q == NULL))
+	    break;
+	  ++q;
+
+	  printf (_("  %-13s  %4" PRIu32 "\n"), name, len);
+
+	  bool gnu_vendor = (q - name == sizeof "gnu"
+			     && !memcmp (name, "gnu", sizeof "gnu"));
+
+	  /* Loop over subsections.  */
+	  if (shdr->sh_type != SHT_GNU_ATTRIBUTES
+	      || gnu_vendor)
+	    while (q < p)
+	      {
+		const unsigned char *const sub = q;
+
+		unsigned int subsection_tag;
+		get_uleb128 (subsection_tag, q, p);
+		if (unlikely (q >= p))
+		  break;
+
+		uint32_t subsection_len;
+		if (unlikely (p - sub < (ptrdiff_t) sizeof subsection_len))
+		  break;
+
+		memcpy (&subsection_len, q, sizeof subsection_len);
+
+		if (MY_ELFDATA != ehdr->e_ident[EI_DATA])
+		  CONVERT (subsection_len);
+
+		/* Don't overflow, ptrdiff_t might be 32bits, but signed.  */
+		if (unlikely (subsection_len == 0
+			      || subsection_len >= (uint32_t) PTRDIFF_MAX
+			      || p - sub < (ptrdiff_t) subsection_len))
+		  break;
+
+		const unsigned char *r = q + sizeof subsection_len;
+		q = sub + subsection_len;
+
+		switch (subsection_tag)
+		  {
+		  default:
+		    /* Unknown subsection, print and skip.  */
+		    printf (_("    %-4u %12" PRIu32 "\n"),
+			    subsection_tag, subsection_len);
+		    break;
+
+		  case 1:	/* Tag_File */
+		    printf (_("    File: %11" PRIu32 "\n"),
+			    subsection_len);
+
+		    while (r < q)
+		      {
+			unsigned int tag;
+			get_uleb128 (tag, r, q);
+			if (unlikely (r >= q))
+			  break;
+
+			/* GNU style tags have either a uleb128 value,
+			   when lowest bit is not set, or a string
+			   when the lowest bit is set.
+			   "compatibility" (32) is special.  It has
+			   both a string and a uleb128 value.  For
+			   non-gnu we assume 6 till 31 only take ints.
+			   XXX see arm backend, do we need a separate
+			   hook?  */
+			uint64_t value = 0;
+			const char *string = NULL;
+			if (tag == 32 || (tag & 1) == 0
+			    || (! gnu_vendor && (tag > 5 && tag < 32)))
+			  {
+			    // Note r >= q check above.
+			    get_uleb128 (value, r, q);
+			    if (r > q)
+			      break;
+			  }
+			if (tag == 32
+			    || ((tag & 1) != 0
+				&& (gnu_vendor
+				    || (! gnu_vendor && tag > 32)))
+			    || (! gnu_vendor && tag > 3 && tag < 6))
+			  {
+			    string = (const char *) r;
+			    r = memchr (r, '\0', q - r);
+			    if (r == NULL)
+			      break;
+			    ++r;
+			  }
+
+			const char *tag_name = NULL;
+			const char *value_name = NULL;
+			ebl_check_object_attribute (ebl, (const char *) name,
+						    tag, value,
+						    &tag_name, &value_name);
+
+			if (tag_name != NULL)
+			  {
+			    if (tag == 32)
+			      printf (_("      %s: %" PRId64 ", %s\n"),
+				      tag_name, value, string);
+			    else if (string == NULL && value_name == NULL)
+			      printf (_("      %s: %" PRId64 "\n"),
+				      tag_name, value);
+			    else
+			      printf (_("      %s: %s\n"),
+				      tag_name, string ?: value_name);
+			  }
+			else
+			  {
+			    /* For "gnu" vendor 32 "compatibility" has
+			       already been handled above.  */
+			    assert (tag != 32
+				    || strcmp ((const char *) name, "gnu"));
+			    if (string == NULL)
+			      printf (_("      %u: %" PRId64 "\n"),
+				      tag, value);
+			    else
+			      printf (_("      %u: %s\n"),
+				      tag, string);
+			  }
+		      }
+		  }
+	      }
+	}
+    }
+}
+
+/* Returns either the (relocated) data from the Dwarf, or tries to get
+   the "raw" (uncompressed) data from the Elf section. Produces a
+   warning if the data cannot be found (or decompressed).  */
+static Elf_Data *
+get_debug_elf_data (Dwarf *dbg, Ebl *ebl, int idx, Elf_Scn *scn)
+{
+  /* We prefer to get the section data from the Dwarf because that
+     might have been relocated already.  Note this is subtly wrong if
+     there are multiple sections with the same .debug name.  */
+  if (dbg->sectiondata[idx] != NULL)
+    return dbg->sectiondata[idx];
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr != NULL && (shdr->sh_flags & SHF_COMPRESSED) != 0)
+    {
+      if (elf_compress (scn, 0, 0) < 0)
+	{
+	  error (0, 0, "%s [%zd] '%s'\n",
+		 _("Couldn't uncompress section"),
+		 elf_ndxscn (scn), section_name (ebl, shdr));
+	  return NULL;
+	}
+    }
+
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    error (0, 0, "%s [%zd] '%s': %s\n",
+	   _("Couldn't get data from section"),
+	   elf_ndxscn (scn), section_name (ebl, shdr), elf_errmsg (-1));
+
+  return elf_getdata (scn, NULL);
+}
+
+static void
+print_dwarf_addr (Dwfl_Module *dwflmod,
+		  int address_size, Dwarf_Addr address, Dwarf_Addr raw)
+{
+  /* See if there is a name we can give for this address.  */
+  GElf_Sym sym;
+  GElf_Off off = 0;
+  const char *name = (print_address_names && ! print_unresolved_addresses)
+    ? dwfl_module_addrinfo (dwflmod, address, &off, &sym, NULL, NULL, NULL)
+    : NULL;
+
+  const char *scn;
+  if (print_unresolved_addresses)
+    {
+      address = raw;
+      scn = NULL;
+    }
+  else
+    {
+      /* Relativize the address.  */
+      int n = dwfl_module_relocations (dwflmod);
+      int i = n < 1 ? -1 : dwfl_module_relocate_address (dwflmod, &address);
+
+      /* In an ET_REL file there is a section name to refer to.  */
+      scn = (i < 0 ? NULL
+	     : dwfl_module_relocation_info (dwflmod, i, NULL));
+    }
+
+  if ((name != NULL
+       ? (off != 0
+	  ? (scn != NULL
+	     ? (address_size == 0
+		? printf ("%s+%#" PRIx64 " <%s+%#" PRIx64 ">",
+			  scn, address, name, off)
+		: printf ("%s+%#0*" PRIx64 " <%s+%#" PRIx64 ">",
+			  scn, 2 + address_size * 2, address,
+			  name, off))
+	     : (address_size == 0
+		? printf ("%#" PRIx64 " <%s+%#" PRIx64 ">",
+			  address, name, off)
+		: printf ("%#0*" PRIx64 " <%s+%#" PRIx64 ">",
+			  2 + address_size * 2, address,
+			  name, off)))
+	  : (scn != NULL
+	     ? (address_size == 0
+		? printf ("%s+%#" PRIx64 " <%s>", scn, address, name)
+		: printf ("%s+%#0*" PRIx64 " <%s>",
+			   scn, 2 + address_size * 2, address, name))
+	     : (address_size == 0
+		? printf ("%#" PRIx64 " <%s>", address, name)
+		: printf ("%#0*" PRIx64 " <%s>",
+			  2 + address_size * 2, address, name))))
+       : (scn != NULL
+	  ? (address_size == 0
+	     ? printf ("%s+%#" PRIx64, scn, address)
+	     : printf ("%s+%#0*" PRIx64, scn, 2 + address_size * 2, address))
+	  : (address_size == 0
+	     ? printf ("%#" PRIx64, address)
+	     : printf ("%#0*" PRIx64, 2 + address_size * 2, address)))) < 0)
+    error_exit (0, _("sprintf failure"));
+}
+
+
+static const char *
+dwarf_tag_string (unsigned int tag)
+{
+  switch (tag)
+    {
+#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_TAG
+#undef DWARF_ONE_KNOWN_DW_TAG
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_attr_string (unsigned int attrnum)
+{
+  switch (attrnum)
+    {
+#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_AT
+#undef DWARF_ONE_KNOWN_DW_AT
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_form_string (unsigned int form)
+{
+  switch (form)
+    {
+#define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_FORM
+#undef DWARF_ONE_KNOWN_DW_FORM
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_lang_string (unsigned int lang)
+{
+  switch (lang)
+    {
+#define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_LANG
+#undef DWARF_ONE_KNOWN_DW_LANG
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_inline_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_INL(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_INL
+#undef DWARF_ONE_KNOWN_DW_INL
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_encoding_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_ATE
+#undef DWARF_ONE_KNOWN_DW_ATE
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_access_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_ACCESS(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_ACCESS
+#undef DWARF_ONE_KNOWN_DW_ACCESS
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_defaulted_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_DEFAULTED(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_DEFAULTED
+#undef DWARF_ONE_KNOWN_DW_DEFAULTED
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_visibility_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_VIS(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_VIS
+#undef DWARF_ONE_KNOWN_DW_VIS
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_virtuality_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_VIRTUALITY(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_VIRTUALITY
+#undef DWARF_ONE_KNOWN_DW_VIRTUALITY
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_identifier_case_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_ID(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_ID
+#undef DWARF_ONE_KNOWN_DW_ID
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_calling_convention_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_CC(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_CC
+#undef DWARF_ONE_KNOWN_DW_CC
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_ordering_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_ORD(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_ORD
+#undef DWARF_ONE_KNOWN_DW_ORD
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_discr_list_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_DSC(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_DSC
+#undef DWARF_ONE_KNOWN_DW_DSC
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_locexpr_opcode_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+      /* Normally we can't afford building huge table of 64K entries,
+	 most of them zero, just because there are a couple defined
+	 values at the far end.  In case of opcodes, it's OK.  */
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static const char *
+dwarf_unit_string (unsigned int type)
+{
+  switch (type)
+    {
+#define DWARF_ONE_KNOWN_DW_UT(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_UT
+#undef DWARF_ONE_KNOWN_DW_UT
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_range_list_encoding_string (unsigned int kind)
+{
+  switch (kind)
+    {
+#define DWARF_ONE_KNOWN_DW_RLE(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_RLE
+#undef DWARF_ONE_KNOWN_DW_RLE
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_loc_list_encoding_string (unsigned int kind)
+{
+  switch (kind)
+    {
+#define DWARF_ONE_KNOWN_DW_LLE(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_LLE
+#undef DWARF_ONE_KNOWN_DW_LLE
+    /* DW_LLE_GNU_view_pair is special/incompatible with default codes.  */
+    case DW_LLE_GNU_view_pair: return "GNU_view_pair";
+    default:
+      return NULL;
+    }
+}
+
+
+static const char *
+dwarf_line_content_description_string (unsigned int kind)
+{
+  switch (kind)
+    {
+#define DWARF_ONE_KNOWN_DW_LNCT(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_LNCT
+#undef DWARF_ONE_KNOWN_DW_LNCT
+    default:
+      return NULL;
+    }
+}
+
+
+/* Used by all dwarf_foo_name functions.  */
+static const char *
+string_or_unknown (const char *known, unsigned int code,
+                   unsigned int lo_user, unsigned int hi_user,
+		   bool print_unknown_num)
+{
+  static char unknown_buf[20];
+
+  if (likely (known != NULL))
+    return known;
+
+  if (lo_user != 0 && code >= lo_user && code <= hi_user)
+    {
+      snprintf (unknown_buf, sizeof unknown_buf, "lo_user+%#x",
+		code - lo_user);
+      return unknown_buf;
+    }
+
+  if (print_unknown_num)
+    {
+      snprintf (unknown_buf, sizeof unknown_buf, "??? (%#x)", code);
+      return unknown_buf;
+    }
+
+  return "???";
+}
+
+
+static const char *
+dwarf_tag_name (unsigned int tag)
+{
+  const char *ret = dwarf_tag_string (tag);
+  return string_or_unknown (ret, tag, DW_TAG_lo_user, DW_TAG_hi_user, true);
+}
+
+static const char *
+dwarf_attr_name (unsigned int attr)
+{
+  const char *ret = dwarf_attr_string (attr);
+  return string_or_unknown (ret, attr, DW_AT_lo_user, DW_AT_hi_user, true);
+}
+
+
+static const char *
+dwarf_form_name (unsigned int form)
+{
+  const char *ret = dwarf_form_string (form);
+  return string_or_unknown (ret, form, 0, 0, true);
+}
+
+
+static const char *
+dwarf_lang_name (unsigned int lang)
+{
+  const char *ret = dwarf_lang_string (lang);
+  return string_or_unknown (ret, lang, DW_LANG_lo_user, DW_LANG_hi_user, false);
+}
+
+
+static const char *
+dwarf_inline_name (unsigned int code)
+{
+  const char *ret = dwarf_inline_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_encoding_name (unsigned int code)
+{
+  const char *ret = dwarf_encoding_string (code);
+  return string_or_unknown (ret, code, DW_ATE_lo_user, DW_ATE_hi_user, false);
+}
+
+
+static const char *
+dwarf_access_name (unsigned int code)
+{
+  const char *ret = dwarf_access_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_defaulted_name (unsigned int code)
+{
+  const char *ret = dwarf_defaulted_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_visibility_name (unsigned int code)
+{
+  const char *ret = dwarf_visibility_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_virtuality_name (unsigned int code)
+{
+  const char *ret = dwarf_virtuality_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_identifier_case_name (unsigned int code)
+{
+  const char *ret = dwarf_identifier_case_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_calling_convention_name (unsigned int code)
+{
+  const char *ret = dwarf_calling_convention_string (code);
+  return string_or_unknown (ret, code, DW_CC_lo_user, DW_CC_hi_user, false);
+}
+
+
+static const char *
+dwarf_ordering_name (unsigned int code)
+{
+  const char *ret = dwarf_ordering_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_discr_list_name (unsigned int code)
+{
+  const char *ret = dwarf_discr_list_string (code);
+  return string_or_unknown (ret, code, 0, 0, false);
+}
+
+
+static const char *
+dwarf_unit_name (unsigned int type)
+{
+  const char *ret = dwarf_unit_string (type);
+  return string_or_unknown (ret, type, DW_UT_lo_user, DW_UT_hi_user, true);
+}
+
+
+static const char *
+dwarf_range_list_encoding_name (unsigned int kind)
+{
+  const char *ret = dwarf_range_list_encoding_string (kind);
+  return string_or_unknown (ret, kind, 0, 0, false);
+}
+
+
+static const char *
+dwarf_loc_list_encoding_name (unsigned int kind)
+{
+  const char *ret = dwarf_loc_list_encoding_string (kind);
+  return string_or_unknown (ret, kind, 0, 0, false);
+}
+
+
+static const char *
+dwarf_line_content_description_name (unsigned int kind)
+{
+  const char *ret = dwarf_line_content_description_string (kind);
+  return string_or_unknown (ret, kind, DW_LNCT_lo_user, DW_LNCT_hi_user,
+			    false);
+}
+
+
+static void
+print_block (size_t n, const void *block)
+{
+  if (n == 0)
+    puts (_("empty block"));
+  else
+    {
+      printf (_("%zu byte block:"), n);
+      const unsigned char *data = block;
+      do
+	printf (" %02x", *data++);
+      while (--n > 0);
+      putchar ('\n');
+    }
+}
+
+static void
+print_bytes (size_t n, const unsigned char *bytes)
+{
+  while (n-- > 0)
+    {
+      printf ("%02x", *bytes++);
+      if (n > 0)
+	printf (" ");
+    }
+}
+
+static int
+get_indexed_addr (Dwarf_CU *cu, Dwarf_Word idx, Dwarf_Addr *addr)
+{
+  if (cu == NULL)
+    return -1;
+
+  Elf_Data *debug_addr = cu->dbg->sectiondata[IDX_debug_addr];
+  if (debug_addr == NULL)
+    return -1;
+
+  Dwarf_Off base = __libdw_cu_addr_base (cu);
+  Dwarf_Word off = idx * cu->address_size;
+  if (base > debug_addr->d_size
+      || off > debug_addr->d_size - base
+      || cu->address_size > debug_addr->d_size - base - off)
+    return -1;
+
+  const unsigned char *addrp = debug_addr->d_buf + base + off;
+  if (cu->address_size == 4)
+    *addr = read_4ubyte_unaligned (cu->dbg, addrp);
+  else
+    *addr = read_8ubyte_unaligned (cu->dbg, addrp);
+
+  return 0;
+}
+
+static void
+print_ops (Dwfl_Module *dwflmod, Dwarf *dbg, int indent, int indentrest,
+	   unsigned int vers, unsigned int addrsize, unsigned int offset_size,
+	   struct Dwarf_CU *cu, Dwarf_Word len, const unsigned char *data)
+{
+  const unsigned int ref_size = vers < 3 ? addrsize : offset_size;
+
+  if (len == 0)
+    {
+      printf ("%*s(empty)\n", indent, "");
+      return;
+    }
+
+#define NEED(n)		if (len < (Dwarf_Word) (n)) goto invalid
+#define CONSUME(n)	NEED (n); else len -= (n)
+
+  Dwarf_Word offset = 0;
+  while (len-- > 0)
+    {
+      uint_fast8_t op = *data++;
+
+      const char *op_name = dwarf_locexpr_opcode_string (op);
+      if (unlikely (op_name == NULL))
+	{
+	  static char buf[20];
+	  if (op >= DW_OP_lo_user)
+	    snprintf (buf, sizeof buf, "lo_user+%#x", op - DW_OP_lo_user);
+	  else
+	    snprintf (buf, sizeof buf, "??? (%#x)", op);
+	  op_name = buf;
+	}
+
+      switch (op)
+	{
+	case DW_OP_addr:;
+	  /* Address operand.  */
+	  Dwarf_Word addr;
+	  NEED (addrsize);
+	  if (addrsize == 4)
+	    addr = read_4ubyte_unaligned (dbg, data);
+	  else if (addrsize == 8)
+	    addr = read_8ubyte_unaligned (dbg, data);
+	  else
+	    goto invalid;
+	  data += addrsize;
+	  CONSUME (addrsize);
+
+	  printf ("%*s[%2" PRIuMAX "] %s ",
+		  indent, "", (uintmax_t) offset, op_name);
+	  print_dwarf_addr (dwflmod, 0, addr, addr);
+	  printf ("\n");
+
+	  offset += 1 + addrsize;
+	  break;
+
+	case DW_OP_call_ref:
+	case DW_OP_GNU_variable_value:
+	  /* Offset operand.  */
+	  if (ref_size != 4 && ref_size != 8)
+	    goto invalid; /* Cannot be used in CFA.  */
+	  NEED (ref_size);
+	  if (ref_size == 4)
+	    addr = read_4ubyte_unaligned (dbg, data);
+	  else
+	    addr = read_8ubyte_unaligned (dbg, data);
+	  data += ref_size;
+	  CONSUME (ref_size);
+	  /* addr is a DIE offset, so format it as one.  */
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, (uintmax_t) addr);
+	  offset += 1 + ref_size;
+	  break;
+
+	case DW_OP_deref_size:
+	case DW_OP_xderef_size:
+	case DW_OP_pick:
+	case DW_OP_const1u:
+	  // XXX value might be modified by relocation
+	  NEED (1);
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, *((uint8_t *) data));
+	  ++data;
+	  --len;
+	  offset += 2;
+	  break;
+
+	case DW_OP_const2u:
+	  NEED (2);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu16 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, read_2ubyte_unaligned (dbg, data));
+	  CONSUME (2);
+	  data += 2;
+	  offset += 3;
+	  break;
+
+	case DW_OP_const4u:
+	  NEED (4);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu32 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, read_4ubyte_unaligned (dbg, data));
+	  CONSUME (4);
+	  data += 4;
+	  offset += 5;
+	  break;
+
+	case DW_OP_const8u:
+	  NEED (8);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, (uint64_t) read_8ubyte_unaligned (dbg, data));
+	  CONSUME (8);
+	  data += 8;
+	  offset += 9;
+	  break;
+
+	case DW_OP_const1s:
+	  NEED (1);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRId8 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, *((int8_t *) data));
+	  ++data;
+	  --len;
+	  offset += 2;
+	  break;
+
+	case DW_OP_const2s:
+	  NEED (2);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRId16 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, read_2sbyte_unaligned (dbg, data));
+	  CONSUME (2);
+	  data += 2;
+	  offset += 3;
+	  break;
+
+	case DW_OP_const4s:
+	  NEED (4);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRId32 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, read_4sbyte_unaligned (dbg, data));
+	  CONSUME (4);
+	  data += 4;
+	  offset += 5;
+	  break;
+
+	case DW_OP_const8s:
+	  NEED (8);
+	  // XXX value might be modified by relocation
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, read_8sbyte_unaligned (dbg, data));
+	  CONSUME (8);
+	  data += 8;
+	  offset += 9;
+	  break;
+
+	case DW_OP_piece:
+	case DW_OP_regx:
+	case DW_OP_plus_uconst:
+	case DW_OP_constu:;
+	  const unsigned char *start = data;
+	  uint64_t uleb;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 "\n",
+		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_addrx:
+	case DW_OP_GNU_addr_index:
+	case DW_OP_constx:
+	case DW_OP_GNU_const_index:;
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s [%" PRIu64 "] ",
+		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  if (get_indexed_addr (cu, uleb, &addr) != 0)
+	    printf ("???\n");
+	  else
+	    {
+	      print_dwarf_addr (dwflmod, 0, addr, addr);
+	      printf ("\n");
+	    }
+	  break;
+
+	case DW_OP_bit_piece:
+	  start = data;
+	  uint64_t uleb2;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  NEED (1);
+	  get_uleb128 (uleb2, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 ", %" PRIu64 "\n",
+		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_fbreg:
+	case DW_OP_breg0 ... DW_OP_breg31:
+	case DW_OP_consts:
+	  start = data;
+	  int64_t sleb;
+	  NEED (1);
+	  get_sleb128 (sleb, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRId64 "\n",
+		  indent, "", (uintmax_t) offset, op_name, sleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_bregx:
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  NEED (1);
+	  get_sleb128 (sleb, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " %" PRId64 "\n",
+		  indent, "", (uintmax_t) offset, op_name, uleb, sleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_call2:
+	  NEED (2);
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx16 "]\n",
+		  indent, "", (uintmax_t) offset, op_name,
+		  read_2ubyte_unaligned (dbg, data));
+	  CONSUME (2);
+	  data += 2;
+	  offset += 3;
+	  break;
+
+	case DW_OP_call4:
+	  NEED (4);
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIx32 "]\n",
+		  indent, "", (uintmax_t) offset, op_name,
+		  read_4ubyte_unaligned (dbg, data));
+	  CONSUME (4);
+	  data += 4;
+	  offset += 5;
+	  break;
+
+	case DW_OP_skip:
+	case DW_OP_bra:
+	  NEED (2);
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIuMAX "\n",
+		  indent, "", (uintmax_t) offset, op_name,
+		  (uintmax_t) (offset + read_2sbyte_unaligned (dbg, data) + 3));
+	  CONSUME (2);
+	  data += 2;
+	  offset += 3;
+	  break;
+
+	case DW_OP_implicit_value:
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s: ",
+		  indent, "", (uintmax_t) offset, op_name);
+	  NEED (uleb);
+	  print_block (uleb, data);
+	  data += uleb;
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_implicit_pointer:
+	case DW_OP_GNU_implicit_pointer:
+	  /* DIE offset operand.  */
+	  start = data;
+	  NEED (ref_size);
+	  if (ref_size != 4 && ref_size != 8)
+	    goto invalid; /* Cannot be used in CFA.  */
+	  if (ref_size == 4)
+	    addr = read_4ubyte_unaligned (dbg, data);
+	  else
+	    addr = read_8ubyte_unaligned (dbg, data);
+	  data += ref_size;
+	  /* Byte offset operand.  */
+	  NEED (1);
+	  get_sleb128 (sleb, data, data + len);
+
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] %+" PRId64 "\n",
+		  indent, "", (intmax_t) offset,
+		  op_name, (uintmax_t) addr, sleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_entry_value:
+	case DW_OP_GNU_entry_value:
+	  /* Size plus expression block.  */
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  printf ("%*s[%2" PRIuMAX "] %s:\n",
+		  indent, "", (uintmax_t) offset, op_name);
+	  NEED (uleb);
+	  print_ops (dwflmod, dbg, indent + 5, indent + 5, vers,
+		     addrsize, offset_size, cu, uleb, data);
+	  data += uleb;
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_const_type:
+	case DW_OP_GNU_const_type:
+	  /* uleb128 CU relative DW_TAG_base_type DIE offset, 1-byte
+	     unsigned size plus block.  */
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  if (! print_unresolved_addresses && cu != NULL)
+	    uleb += cu->start;
+	  NEED (1);
+	  uint8_t usize = *(uint8_t *) data++;
+	  NEED (usize);
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "] ",
+		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  print_block (usize, data);
+	  data += usize;
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_regval_type:
+	case DW_OP_GNU_regval_type:
+	  /* uleb128 register number, uleb128 CU relative
+	     DW_TAG_base_type DIE offset.  */
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  NEED (1);
+	  get_uleb128 (uleb2, data, data + len);
+	  if (! print_unresolved_addresses && cu != NULL)
+	    uleb2 += cu->start;
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu64 " [%6" PRIx64 "]\n",
+		  indent, "", (uintmax_t) offset, op_name, uleb, uleb2);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_deref_type:
+	case DW_OP_GNU_deref_type:
+	  /* 1-byte unsigned size of value, uleb128 CU relative
+	     DW_TAG_base_type DIE offset.  */
+	  start = data;
+	  NEED (1);
+	  usize = *(uint8_t *) data++;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  if (! print_unresolved_addresses && cu != NULL)
+	    uleb += cu->start;
+	  printf ("%*s[%2" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, usize, uleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_xderef_type:
+	  /* 1-byte unsigned size of value, uleb128 base_type DIE offset.  */
+	  start = data;
+	  NEED (1);
+	  usize = *(uint8_t *) data++;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  printf ("%*s[%4" PRIuMAX "] %s %" PRIu8 " [%6" PRIxMAX "]\n",
+		  indent, "", (uintmax_t) offset,
+		  op_name, usize, uleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_convert:
+	case DW_OP_GNU_convert:
+	case DW_OP_reinterpret:
+	case DW_OP_GNU_reinterpret:
+	  /* uleb128 CU relative offset to DW_TAG_base_type, or zero
+	     for conversion to untyped.  */
+	  start = data;
+	  NEED (1);
+	  get_uleb128 (uleb, data, data + len);
+	  if (uleb != 0 && ! print_unresolved_addresses && cu != NULL)
+	    uleb += cu->start;
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		  indent, "", (uintmax_t) offset, op_name, uleb);
+	  CONSUME (data - start);
+	  offset += 1 + (data - start);
+	  break;
+
+	case DW_OP_GNU_parameter_ref:
+	  /* 4 byte CU relative reference to the abstract optimized away
+	     DW_TAG_formal_parameter.  */
+	  NEED (4);
+	  uintmax_t param_off = (uintmax_t) read_4ubyte_unaligned (dbg, data);
+	  if (! print_unresolved_addresses && cu != NULL)
+	    param_off += cu->start;
+	  printf ("%*s[%2" PRIuMAX "] %s [%6" PRIxMAX "]\n",
+		  indent, "", (uintmax_t) offset, op_name, param_off);
+	  CONSUME (4);
+	  data += 4;
+	  offset += 5;
+	  break;
+
+	default:
+	  /* No Operand.  */
+	  printf ("%*s[%2" PRIuMAX "] %s\n",
+		  indent, "", (uintmax_t) offset, op_name);
+	  ++offset;
+	  break;
+	}
+
+      indent = indentrest;
+      continue;
+
+    invalid:
+      printf (_("%*s[%2" PRIuMAX "] %s  <TRUNCATED>\n"),
+	      indent, "", (uintmax_t) offset, op_name);
+      break;
+    }
+}
+
+
+/* Turn the addresses into file offsets by using the phdrs.  */
+static void
+find_offsets(Elf *elf, GElf_Addr main_bias, size_t n,
+                  GElf_Addr addrs[n], GElf_Off offs[n])
+{
+  size_t unsolved = n;
+  for (size_t i = 0; i < phnum; ++i) {
+    GElf_Phdr phdr_mem;
+    GElf_Phdr *phdr = gelf_getphdr(elf, i, &phdr_mem);
+    if (phdr != NULL && phdr->p_type == PT_LOAD && phdr->p_memsz > 0)
+      for (size_t j = 0; j < n; ++j)
+        if (offs[j] == 0 && addrs[j] >= phdr->p_vaddr + main_bias &&
+            addrs[j] - (phdr->p_vaddr + main_bias) < phdr->p_filesz) {
+          offs[j] = addrs[j] - (phdr->p_vaddr + main_bias) + phdr->p_offset;
+          if (--unsolved == 0)
+            break;
+        }
+  }
+}
+
+/* The dynamic segment (type PT_DYNAMIC), contains the .dynamic section.
+   And .dynamic section contains an array of the dynamic structures.
+   We use the array to get:
+    DT_STRTAB: the address of the string table
+    DT_SYMTAB: the address of the symbol table
+    DT_STRSZ: the size, in bytes, of the string table
+    ...  */
+static void
+get_dynscn_addrs(Elf *elf, GElf_Phdr *phdr, GElf_Addr addrs[i_max])
+{
+  Elf_Data *data = elf_getdata_rawchunk(
+    elf, phdr->p_offset, phdr->p_filesz, ELF_T_DYN);
+
+  int dyn_idx = 0;
+  for (;; ++dyn_idx) {
+    GElf_Dyn dyn_mem;
+    GElf_Dyn *dyn = gelf_getdyn(data, dyn_idx, &dyn_mem);
+    /* DT_NULL Marks end of dynamic section.  */
+    if (dyn == NULL || dyn->d_tag == DT_NULL)
+      break;
+
+    switch (dyn->d_tag) {
+    case DT_SYMTAB:
+      addrs[i_symtab] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_HASH:
+      addrs[i_hash] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_GNU_HASH:
+      addrs[i_gnu_hash] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_STRTAB:
+      addrs[i_strtab] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_VERSYM:
+      addrs[i_versym] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_VERDEF:
+      addrs[i_verdef] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_VERDEFNUM:
+      addrs[i_verdefnum] = dyn->d_un.d_val;
+      break;
+
+    case DT_VERNEED:
+      addrs[i_verneed] = dyn->d_un.d_ptr;
+      break;
+
+    case DT_VERNEEDNUM:
+      addrs[i_verneednum] = dyn->d_un.d_val;
+      break;
+
+    case DT_STRSZ:
+      addrs[i_strsz] = dyn->d_un.d_val;
+      break;
+
+    case DT_SYMTAB_SHNDX:
+      addrs[i_symtab_shndx] = dyn->d_un.d_ptr;
+      break;
+    }
+  }
+}
+
+
+/* Use dynamic segment to get data for the string table section.  */
+static Elf_Data *
+get_dynscn_strtab(Elf *elf, GElf_Phdr *phdr)
+{
+  Elf_Data *strtab_data;
+  GElf_Addr addrs[i_max] = {0,};
+  GElf_Off offs[i_max] = {0,};
+  get_dynscn_addrs(elf, phdr, addrs);
+  find_offsets(elf, 0, i_max, addrs, offs);
+  strtab_data = elf_getdata_rawchunk(
+          elf, offs[i_strtab], addrs[i_strsz], ELF_T_BYTE);
+  return strtab_data;
+}
+
+
+struct listptr
+{
+  Dwarf_Off offset:(64 - 3);
+  bool addr64:1;
+  bool dwarf64:1;
+  bool warned:1;
+  struct Dwarf_CU *cu;
+  unsigned int attr;
+};
+
+#define listptr_offset_size(p)	((p)->dwarf64 ? 8 : 4)
+#define listptr_address_size(p)	((p)->addr64 ? 8 : 4)
+
+static Dwarf_Addr
+cudie_base (Dwarf_Die *cudie)
+{
+  Dwarf_Addr base;
+  /* Find the base address of the compilation unit.  It will normally
+     be specified by DW_AT_low_pc.  In DWARF-3 draft 4, the base
+     address could be overridden by DW_AT_entry_pc.  It's been
+     removed, but GCC emits DW_AT_entry_pc and not DW_AT_lowpc for
+     compilation units with discontinuous ranges.  */
+  if (unlikely (dwarf_lowpc (cudie, &base) != 0))
+    {
+      Dwarf_Attribute attr_mem;
+      if (dwarf_formaddr (dwarf_attr (cudie, DW_AT_entry_pc, &attr_mem),
+			  &base) != 0)
+	base = 0;
+    }
+  return base;
+}
+
+static Dwarf_Addr
+listptr_base (struct listptr *p)
+{
+  Dwarf_Die cu = CUDIE (p->cu);
+  return cudie_base (&cu);
+}
+
+/* To store the name used in compare_listptr */
+static const char *sort_listptr_name;
+
+static int
+compare_listptr (const void *a, const void *b)
+{
+  const char *name = sort_listptr_name;
+  struct listptr *p1 = (void *) a;
+  struct listptr *p2 = (void *) b;
+
+  if (p1->offset < p2->offset)
+    return -1;
+  if (p1->offset > p2->offset)
+    return 1;
+
+  if (!p1->warned && !p2->warned)
+    {
+      if (p1->addr64 != p2->addr64)
+	{
+	  p1->warned = p2->warned = true;
+	  error (0, 0,
+		 _("%s %#" PRIx64 " used with different address sizes"),
+		 name, (uint64_t) p1->offset);
+	}
+      if (p1->dwarf64 != p2->dwarf64)
+	{
+	  p1->warned = p2->warned = true;
+	  error (0, 0,
+		 _("%s %#" PRIx64 " used with different offset sizes"),
+		 name, (uint64_t) p1->offset);
+	}
+      if (listptr_base (p1) != listptr_base (p2))
+	{
+	  p1->warned = p2->warned = true;
+	  error (0, 0,
+		 _("%s %#" PRIx64 " used with different base addresses"),
+		 name, (uint64_t) p1->offset);
+	}
+      if (p1->attr != p2 ->attr)
+	{
+	  p1->warned = p2->warned = true;
+	  error (0, 0,
+		 _("%s %#" PRIx64
+			  " used with different attribute %s and %s"),
+		 name, (uint64_t) p1->offset, dwarf_attr_name (p1->attr),
+		 dwarf_attr_name (p2->attr));
+	}
+    }
+
+  return 0;
+}
+
+struct listptr_table
+{
+  size_t n;
+  size_t alloc;
+  struct listptr *table;
+};
+
+static struct listptr_table known_locsptr;
+static struct listptr_table known_loclistsptr;
+static struct listptr_table known_rangelistptr;
+static struct listptr_table known_rnglistptr;
+static struct listptr_table known_addrbases;
+static struct listptr_table known_stroffbases;
+
+static void
+reset_listptr (struct listptr_table *table)
+{
+  free (table->table);
+  table->table = NULL;
+  table->n = table->alloc = 0;
+}
+
+/* Returns false if offset doesn't fit.  See struct listptr.  */
+static bool
+notice_listptr (enum section_e section, struct listptr_table *table,
+		uint_fast8_t address_size, uint_fast8_t offset_size,
+		struct Dwarf_CU *cu, Dwarf_Off offset, unsigned int attr)
+{
+  if (print_debug_sections & section)
+    {
+      if (table->n == table->alloc)
+	{
+	  if (table->alloc == 0)
+	    table->alloc = 128;
+	  else
+	    table->alloc *= 2;
+	  table->table = xrealloc (table->table,
+				   table->alloc * sizeof table->table[0]);
+	}
+
+      struct listptr *p = &table->table[table->n++];
+
+      *p = (struct listptr)
+	{
+	  .addr64 = address_size == 8,
+	  .dwarf64 = offset_size == 8,
+	  .offset = offset,
+	  .cu = cu,
+	  .attr = attr
+	};
+
+      if (p->offset != offset)
+	{
+	  table->n--;
+	  return false;
+	}
+    }
+  return true;
+}
+
+static void
+sort_listptr (struct listptr_table *table, const char *name)
+{
+  if (table->n > 0)
+    {
+      sort_listptr_name = name;
+      qsort (table->table, table->n, sizeof table->table[0],
+	     &compare_listptr);
+    }
+}
+
+static bool
+skip_listptr_hole (struct listptr_table *table, size_t *idxp,
+		   uint_fast8_t *address_sizep, uint_fast8_t *offset_sizep,
+		   Dwarf_Addr *base, struct Dwarf_CU **cu, ptrdiff_t offset,
+		   unsigned char **readp, unsigned char *endp,
+		   unsigned int *attr)
+{
+  if (table->n == 0)
+    return false;
+
+  while (*idxp < table->n && table->table[*idxp].offset < (Dwarf_Off) offset)
+    ++*idxp;
+
+  struct listptr *p = &table->table[*idxp];
+
+  if (*idxp == table->n
+      || p->offset >= (Dwarf_Off) (endp - *readp + offset))
+    {
+      *readp = endp;
+      printf (_(" [%6tx]  <UNUSED GARBAGE IN REST OF SECTION>\n"),
+	      offset);
+      return true;
+    }
+
+  if (p->offset != (Dwarf_Off) offset)
+    {
+      *readp += p->offset - offset;
+      printf (_(" [%6tx]  <UNUSED GARBAGE> ... %" PRIu64 " bytes ...\n"),
+	      offset, (Dwarf_Off) p->offset - offset);
+      return true;
+    }
+
+  if (address_sizep != NULL)
+    *address_sizep = listptr_address_size (p);
+  if (offset_sizep != NULL)
+    *offset_sizep = listptr_offset_size (p);
+  if (base != NULL)
+    *base = listptr_base (p);
+  if (cu != NULL)
+    *cu = p->cu;
+  if (attr != NULL)
+    *attr = p->attr;
+
+  return false;
+}
+
+static Dwarf_Off
+next_listptr_offset (struct listptr_table *table, size_t *idxp, Dwarf_Off off)
+{
+  /* Note that multiple attributes could in theory point to the same loclist
+     offset, so make sure we pick one that is bigger than the current one.
+     The table is sorted on offset.  */
+  if (*idxp < table->n)
+    {
+      while (++*idxp < table->n)
+	{
+	  Dwarf_Off next = table->table[*idxp].offset;
+	  if (next > off)
+	    return next;
+	}
+    }
+  return 0;
+}
+
+/* Returns the listptr associated with the given index, or NULL.  */
+static struct listptr *
+get_listptr (struct listptr_table *table, size_t idx)
+{
+  if (idx >= table->n)
+    return NULL;
+  return &table->table[idx];
+}
+
+/* Returns the next index, base address and CU associated with the
+   list unit offsets.  If there is none false is returned, otherwise
+   true.  Assumes the table has been sorted.  */
+static bool
+listptr_cu (struct listptr_table *table, size_t *idxp,
+	    Dwarf_Off start, Dwarf_Off end,
+	    Dwarf_Addr *base, struct Dwarf_CU **cu)
+{
+  while (*idxp < table->n
+	 && table->table[*idxp].offset < start)
+    ++*idxp;
+
+  if (*idxp < table->n
+      && table->table[*idxp].offset >= start
+      && table->table[*idxp].offset < end)
+    {
+      struct listptr *p = &table->table[*idxp];
+      *base = listptr_base (p);
+      *cu = p->cu;
+      return true;
+    }
+
+  return false;
+}
+
+/* Returns the next index with the current CU for the given attribute.
+   If there is none false is returned, otherwise true.  Assumes the
+   table has been sorted.  */
+static bool
+listptr_attr (struct listptr_table *table, size_t idxp,
+	      Dwarf_Off offset, unsigned int attr)
+{
+  struct listptr *listptr;
+  do
+    {
+      listptr = get_listptr (table, idxp);
+      if (listptr == NULL)
+	return false;
+
+      if (listptr->offset == offset && listptr->attr == attr)
+	return true;
+
+      idxp++;
+    }
+  while (listptr->offset <= offset);
+
+  return false;
+}
+
+static void
+print_debug_abbrev_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			    Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
+			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Elf_Data *elf_data = get_debug_elf_data (dbg, ebl, IDX_debug_abbrev, scn);
+  if (elf_data == NULL)
+    return;
+
+  const size_t sh_size = elf_data->d_size;
+
+  printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
+		   " [ Code]\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  Dwarf_Off offset = 0;
+  while (offset < sh_size)
+    {
+      printf (_("\nAbbreviation section at offset %" PRIu64 ":\n"),
+	      offset);
+
+      while (1)
+	{
+	  size_t length;
+	  Dwarf_Abbrev abbrev;
+
+	  int res = dwarf_offabbrev (dbg, offset, &length, &abbrev);
+	  if (res != 0)
+	    {
+	      if (unlikely (res < 0))
+		{
+		  printf (_("\
+ *** error while reading abbreviation: %s\n"),
+			  dwarf_errmsg (-1));
+		  return;
+		}
+
+	      /* This is the NUL byte at the end of the section.  */
+	      ++offset;
+	      break;
+	    }
+
+	  /* We know these calls can never fail.  */
+	  unsigned int code = dwarf_getabbrevcode (&abbrev);
+	  unsigned int tag = dwarf_getabbrevtag (&abbrev);
+	  int has_children = dwarf_abbrevhaschildren (&abbrev);
+
+	  printf (_(" [%5u] offset: %" PRId64
+			   ", children: %s, tag: %s\n"),
+		  code, (int64_t) offset,
+		  has_children ? yes_str : no_str,
+		  dwarf_tag_name (tag));
+
+	  size_t cnt = 0;
+	  unsigned int name;
+	  unsigned int form;
+	  Dwarf_Sword data;
+	  Dwarf_Off enoffset;
+	  while (dwarf_getabbrevattr_data (&abbrev, cnt, &name, &form,
+					   &data, &enoffset) == 0)
+	    {
+	      printf ("          attr: %s, form: %s",
+		      dwarf_attr_name (name), dwarf_form_name (form));
+	      if (form == DW_FORM_implicit_const)
+		printf (" (%" PRId64 ")", data);
+	      printf (", offset: %#" PRIx64 "\n", (uint64_t) enoffset);
+	      ++cnt;
+	    }
+
+	  offset += length;
+	}
+    }
+}
+
+
+static void
+print_debug_addr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			  Ebl *ebl, GElf_Ehdr *ehdr,
+			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_addr, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  if (shdr->sh_size == 0)
+    return;
+
+  size_t idx = 0;
+  sort_listptr (&known_addrbases, "addr_base");
+
+  const unsigned char *start = (const unsigned char *) data->d_buf;
+  const unsigned char *readp = start;
+  const unsigned char *readendp = ((const unsigned char *) data->d_buf
+				   + data->d_size);
+
+  while (readp < readendp)
+    {
+      /* We cannot really know whether or not there is an header.  The
+	 DebugFission extension to DWARF4 doesn't add one.  The DWARF5
+	 .debug_addr variant does.  Whether or not we have an header,
+	 DW_AT_[GNU_]addr_base points at "index 0".  So if the current
+	 offset equals the CU addr_base then we can just start
+	 printing addresses.  If there is no CU with an exact match
+	 then we'll try to parse the header first.  */
+      Dwarf_Off off = (Dwarf_Off) (readp
+				   - (const unsigned char *) data->d_buf);
+
+      printf ("Table at offset %" PRIx64 " ", off);
+
+      struct listptr *listptr = get_listptr (&known_addrbases, idx++);
+      const unsigned char *next_unitp;
+
+      uint64_t unit_length;
+      uint16_t version;
+      uint8_t address_size;
+      uint8_t segment_size;
+      if (listptr == NULL)
+	{
+	  error (0, 0, "Warning: No CU references .debug_addr after %" PRIx64,
+		 off);
+
+	  /* We will have to assume it is just addresses to the end... */
+	  address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+	  next_unitp = readendp;
+	  printf ("Unknown CU:\n");
+	}
+      else
+	{
+	  Dwarf_Die cudie;
+	  if (dwarf_cu_die (listptr->cu, &cudie,
+			    NULL, NULL, NULL, NULL,
+			    NULL, NULL) == NULL)
+	    printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
+	  else
+	    printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
+
+	  if (listptr->offset == off)
+	    {
+	      address_size = listptr_address_size (listptr);
+	      segment_size = 0;
+	      version = 4;
+
+	      /* The addresses start here, but where do they end?  */
+	      listptr = get_listptr (&known_addrbases, idx);
+	      if (listptr == NULL)
+		next_unitp = readendp;
+	      else if (listptr->cu->version < 5)
+		{
+		  next_unitp = start + listptr->offset;
+		  if (listptr->offset < off || listptr->offset > data->d_size)
+		    {
+		      error (0, 0,
+			     "Warning: Bad address base for next unit at %"
+			     PRIx64, off);
+		      next_unitp = readendp;
+		    }
+		}
+	      else
+		{
+		  /* Tricky, we don't have a header for this unit, but
+		     there is one for the next.  We will have to
+		     "guess" how big it is and subtract it from the
+		     offset (because that points after the header).  */
+		  unsigned int offset_size = listptr_offset_size (listptr);
+		  Dwarf_Off next_off = (listptr->offset
+					- (offset_size == 4 ? 4 : 12) /* len */
+					- 2 /* version */
+					- 1 /* address size */
+					- 1); /* segment selector size */
+		  next_unitp = start + next_off;
+		  if (next_off < off || next_off > data->d_size)
+		    {
+		      error (0, 0,
+			     "Warning: Couldn't calculate .debug_addr "
+			     " unit length at %" PRIx64, off);
+		      next_unitp = readendp;
+		    }
+		}
+	      unit_length = (uint64_t) (next_unitp - readp);
+
+	      /* Pretend we have a header.  */
+	      printf ("\n");
+	      printf (_(" Length:         %8" PRIu64 "\n"),
+		      unit_length);
+	      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+	      printf (_(" Address size:   %8" PRIu64 "\n"),
+		      (uint64_t) address_size);
+	      printf (_(" Segment size:   %8" PRIu64 "\n"),
+		      (uint64_t) segment_size);
+	      printf ("\n");
+	    }
+	  else
+	    {
+	      /* OK, we have to parse an header first.  */
+	      unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+	      if (unlikely (unit_length == 0xffffffff))
+		{
+		  if (unlikely (readp > readendp - 8))
+		    {
+		    invalid_data:
+		      error (0, 0, "Invalid data");
+		      return;
+		    }
+		  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      printf ("\n");
+	      printf (_(" Length:         %8" PRIu64 "\n"),
+		      unit_length);
+
+	      /* We need at least 2-bytes (version) + 1-byte
+		 (addr_size) + 1-byte (segment_size) = 4 bytes to
+		 complete the header.  And this unit cannot go beyond
+		 the section data.  */
+	      if (readp > readendp - 4
+		  || unit_length < 4
+		  || unit_length > (uint64_t) (readendp - readp))
+		goto invalid_data;
+
+	      next_unitp = readp + unit_length;
+
+	      version = read_2ubyte_unaligned_inc (dbg, readp);
+	      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+
+	      if (version != 5)
+		{
+		  error (0, 0, _("Unknown version"));
+		  goto next_unit;
+		}
+
+	      address_size = *readp++;
+	      printf (_(" Address size:   %8" PRIu64 "\n"),
+		      (uint64_t) address_size);
+
+	      if (address_size != 4 && address_size != 8)
+		{
+		  error (0, 0, _("unsupported address size"));
+		  goto next_unit;
+		}
+
+	      segment_size = *readp++;
+	      printf (_(" Segment size:   %8" PRIu64 "\n"),
+		      (uint64_t) segment_size);
+	      printf ("\n");
+
+	      if (segment_size != 0)
+		{
+		  error (0, 0, _("unsupported segment size"));
+		  goto next_unit;
+		}
+
+	      if (listptr->offset != (Dwarf_Off) (readp - start))
+		{
+		  error (0, 0, "Address index doesn't start after header");
+		  goto next_unit;
+		}
+	    }
+	}
+
+      int digits = 1;
+      size_t addresses = (next_unitp - readp) / address_size;
+      while (addresses >= 10)
+	{
+	  ++digits;
+	  addresses /= 10;
+	}
+
+      unsigned int uidx = 0;
+      size_t index_offset =  readp - (const unsigned char *) data->d_buf;
+      printf (" Addresses start at offset 0x%zx:\n", index_offset);
+      while (readp <= next_unitp - address_size)
+	{
+	  Dwarf_Addr addr = read_addr_unaligned_inc (address_size, dbg,
+						     readp);
+	  printf (" [%*u] ", digits, uidx++);
+	  print_dwarf_addr (dwflmod, address_size, addr, addr);
+	  printf ("\n");
+	}
+      printf ("\n");
+
+      if (readp != next_unitp)
+	error (0, 0, "extra %zd bytes at end of unit",
+	       (size_t) (next_unitp - readp));
+
+    next_unit:
+      readp = next_unitp;
+    }
+}
+
+/* Print content of DWARF .debug_aranges section.  We fortunately do
+   not have to know a bit about the structure of the section, libdwarf
+   takes care of it.  */
+static void
+print_decoded_aranges_section (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+			       GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Dwarf_Aranges *aranges;
+  size_t cnt;
+  if (unlikely (dwarf_getaranges (dbg, &aranges, &cnt) != 0))
+    {
+      error (0, 0, _("cannot get .debug_aranges content: %s"),
+	     dwarf_errmsg (-1));
+      return;
+    }
+
+  GElf_Shdr glink_mem;
+  GElf_Shdr *glink;
+  glink = gelf_getshdr (elf_getscn (ebl->elf, shdr->sh_link), &glink_mem);
+  if (glink == NULL)
+    {
+      error (0, 0, _("invalid sh_link value in section %zu"),
+	     elf_ndxscn (scn));
+      return;
+    }
+
+  printf (ngettext ("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entry:\n",
+		    "\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 " contains %zu entries:\n",
+		    cnt),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset, cnt);
+
+  /* Compute floor(log16(cnt)).  */
+  size_t tmp = cnt;
+  int digits = 1;
+  while (tmp >= 16)
+    {
+      ++digits;
+      tmp >>= 4;
+    }
+
+  for (size_t n = 0; n < cnt; ++n)
+    {
+      Dwarf_Arange *runp = dwarf_onearange (aranges, n);
+      if (unlikely (runp == NULL))
+	{
+	  printf ("cannot get arange %zu: %s\n", n, dwarf_errmsg (-1));
+	  return;
+	}
+
+      Dwarf_Addr start;
+      Dwarf_Word length;
+      Dwarf_Off offset;
+
+      if (unlikely (dwarf_getarangeinfo (runp, &start, &length, &offset) != 0))
+	printf (_(" [%*zu] ???\n"), digits, n);
+      else
+	printf (_(" [%*zu] start: %0#*" PRIx64
+			 ", length: %5" PRIu64 ", CU DIE offset: %6"
+			 PRId64 "\n"),
+		digits, n, ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 10 : 18,
+		(uint64_t) start, (uint64_t) length, (int64_t) offset);
+    }
+}
+
+
+/* Print content of DWARF .debug_aranges section.  */
+static void
+print_debug_aranges_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			     Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
+			     GElf_Shdr *shdr, Dwarf *dbg)
+{
+  if (decodedaranges)
+    {
+      print_decoded_aranges_section (ebl, ehdr, scn, shdr, dbg);
+      return;
+    }
+
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_aranges, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *readendp = readp + data->d_size;
+
+  while (readp < readendp)
+    {
+      const unsigned char *hdrstart = readp;
+      size_t start_offset = hdrstart - (const unsigned char *) data->d_buf;
+
+      printf (_("\nTable at offset %zu:\n"), start_offset);
+      if (readp + 4 > readendp)
+	{
+	invalid_data:
+	  error (0, 0, _("invalid data in section [%zu] '%s'"),
+		 elf_ndxscn (scn), section_name (ebl, shdr));
+	  return;
+	}
+
+      Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
+      unsigned int length_bytes = 4;
+      if (length == DWARF3_LENGTH_64_BIT)
+	{
+	  if (readp + 8 > readendp)
+	    goto invalid_data;
+	  length = read_8ubyte_unaligned_inc (dbg, readp);
+	  length_bytes = 8;
+	}
+
+      const unsigned char *nexthdr = readp + length;
+      printf (_("\n Length:        %6" PRIu64 "\n"),
+	      (uint64_t) length);
+
+      if (unlikely (length > (size_t) (readendp - readp)))
+	goto invalid_data;
+
+      if (length == 0)
+	continue;
+
+      if (readp + 2 > readendp)
+	goto invalid_data;
+      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+      printf (_(" DWARF version: %6" PRIuFAST16 "\n"),
+	      version);
+      if (version != 2)
+	{
+	  error (0, 0, _("unsupported aranges version"));
+	  goto next_table;
+	}
+
+      Dwarf_Word offset;
+      if (readp + length_bytes > readendp)
+	goto invalid_data;
+      if (length_bytes == 8)
+	offset = read_8ubyte_unaligned_inc (dbg, readp);
+      else
+	offset = read_4ubyte_unaligned_inc (dbg, readp);
+      printf (_(" CU offset:     %6" PRIx64 "\n"),
+	      (uint64_t) offset);
+
+      if (readp + 1 > readendp)
+	goto invalid_data;
+      unsigned int address_size = *readp++;
+      printf (_(" Address size:  %6" PRIu64 "\n"),
+	      (uint64_t) address_size);
+      if (address_size != 4 && address_size != 8)
+	{
+	  error (0, 0, _("unsupported address size"));
+	  goto next_table;
+	}
+
+      if (readp + 1 > readendp)
+	goto invalid_data;
+      unsigned int segment_size = *readp++;
+      printf (_(" Segment size:  %6" PRIu64 "\n\n"),
+	      (uint64_t) segment_size);
+      if (segment_size != 0 && segment_size != 4 && segment_size != 8)
+	{
+	  error (0, 0, _("unsupported segment size"));
+	  goto next_table;
+	}
+
+      /* Round the address to the next multiple of 2*address_size.  */
+      readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
+		% (2 * address_size));
+
+      while (readp < nexthdr)
+	{
+	  Dwarf_Word range_address;
+	  Dwarf_Word range_length;
+	  Dwarf_Word segment = 0;
+	  if (readp + 2 * address_size + segment_size > readendp)
+	    goto invalid_data;
+	  if (address_size == 4)
+	    {
+	      range_address = read_4ubyte_unaligned_inc (dbg, readp);
+	      range_length = read_4ubyte_unaligned_inc (dbg, readp);
+	    }
+	  else
+	    {
+	      range_address = read_8ubyte_unaligned_inc (dbg, readp);
+	      range_length = read_8ubyte_unaligned_inc (dbg, readp);
+	    }
+
+	  if (segment_size == 4)
+	    segment = read_4ubyte_unaligned_inc (dbg, readp);
+	  else if (segment_size == 8)
+	    segment = read_8ubyte_unaligned_inc (dbg, readp);
+
+	  if (range_address == 0 && range_length == 0 && segment == 0)
+	    break;
+
+	  printf ("   ");
+	  print_dwarf_addr (dwflmod, address_size, range_address,
+			    range_address);
+	  printf ("..");
+	  print_dwarf_addr (dwflmod, address_size,
+			    range_address + range_length - 1,
+			    range_length);
+	  if (segment_size != 0)
+	    printf (" (%" PRIx64 ")\n", (uint64_t) segment);
+	  else
+	    printf ("\n");
+	}
+
+    next_table:
+      if (readp != nexthdr)
+	{
+	  size_t padding = nexthdr - readp;
+	  printf (_("   %zu padding bytes\n"), padding);
+	  readp = nexthdr;
+	}
+    }
+}
+
+
+static bool is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu);
+
+/* Returns true and sets cu and cu_base if the given Dwarf is a split
+   DWARF (.dwo) file.  */
+static bool
+split_dwarf_cu_base (Dwarf *dbg, Dwarf_CU **cu, Dwarf_Addr *cu_base)
+{
+  uint64_t id;
+  if (is_split_dwarf (dbg, &id, cu))
+    {
+      Dwarf_Die cudie;
+      if (dwarf_cu_info (*cu, NULL, NULL, &cudie, NULL, NULL, NULL, NULL) == 0)
+	{
+	  *cu_base = cudie_base (&cudie);
+	  return true;
+	}
+    }
+  return false;
+}
+
+/* Print content of DWARF .debug_rnglists section.  */
+static void
+print_debug_rnglists_section (Dwfl_Module *dwflmod,
+			      Ebl *ebl,
+			      GElf_Ehdr *ehdr __attribute__ ((unused)),
+			      Elf_Scn *scn, GElf_Shdr *shdr,
+			      Dwarf *dbg __attribute__((unused)))
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_rnglists, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  /* For the listptr to get the base address/CU.  */
+  sort_listptr (&known_rnglistptr, "rnglistptr");
+  size_t listptr_idx = 0;
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *const dataend = ((unsigned char *) data->d_buf
+					+ data->d_size);
+  while (readp < dataend)
+    {
+      if (unlikely (readp > dataend - 4))
+	{
+	invalid_data:
+	  error (0, 0, _("invalid data in section [%zu] '%s'"),
+		 elf_ndxscn (scn), section_name (ebl, shdr));
+	  return;
+	}
+
+      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+      printf (_("Table at Offset 0x%" PRIx64 ":\n\n"),
+	      (uint64_t) offset);
+
+      uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+      unsigned int offset_size = 4;
+      if (unlikely (unit_length == 0xffffffff))
+	{
+	  if (unlikely (readp > dataend - 8))
+	    goto invalid_data;
+
+	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+	  offset_size = 8;
+	}
+      printf (_(" Length:         %8" PRIu64 "\n"), unit_length);
+
+      /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
+	 bytes to complete the header.  And this unit cannot go beyond
+	 the section data.  */
+      if (readp > dataend - 8
+	  || unit_length < 8
+	  || unit_length > (uint64_t) (dataend - readp))
+	goto invalid_data;
+
+      const unsigned char *nexthdr = readp + unit_length;
+
+      uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+
+      if (version != 5)
+	{
+	  error (0, 0, _("Unknown version"));
+	  goto next_table;
+	}
+
+      uint8_t address_size = *readp++;
+      printf (_(" Address size:   %8" PRIu64 "\n"),
+	      (uint64_t) address_size);
+
+      if (address_size != 4 && address_size != 8)
+	{
+	  error (0, 0, _("unsupported address size"));
+	  goto next_table;
+	}
+
+      uint8_t segment_size = *readp++;
+      printf (_(" Segment size:   %8" PRIu64 "\n"),
+	      (uint64_t) segment_size);
+
+      if (segment_size != 0 && segment_size != 4 && segment_size != 8)
+        {
+          error (0, 0, _("unsupported segment size"));
+          goto next_table;
+        }
+
+      uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
+      printf (_(" Offset entries: %8" PRIu64 "\n"),
+	      (uint64_t) offset_entry_count);
+
+      /* We need the CU that uses this unit to get the initial base address. */
+      Dwarf_Addr cu_base = 0;
+      struct Dwarf_CU *cu = NULL;
+      if (listptr_cu (&known_rnglistptr, &listptr_idx,
+		      (Dwarf_Off) offset,
+		      (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
+		      &cu_base, &cu)
+	  || split_dwarf_cu_base (dbg, &cu, &cu_base))
+	{
+	  Dwarf_Die cudie;
+	  if (dwarf_cu_die (cu, &cudie,
+			    NULL, NULL, NULL, NULL,
+			    NULL, NULL) == NULL)
+	    printf (_(" Unknown CU base: "));
+	  else
+	    printf (_(" CU [%6" PRIx64 "] base: "),
+		    dwarf_dieoffset (&cudie));
+	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
+	  printf ("\n");
+	}
+      else
+	printf (_(" Not associated with a CU.\n"));
+
+      printf ("\n");
+
+      const unsigned char *offset_array_start = readp;
+      if (offset_entry_count > 0)
+	{
+	  uint64_t max_entries = (unit_length - 8) / offset_size;
+	  if (offset_entry_count > max_entries)
+	    {
+	      error (0, 0,
+		     _("too many offset entries for unit length"));
+	      offset_entry_count = max_entries;
+	    }
+
+	  printf (_("  Offsets starting at 0x%" PRIx64 ":\n"),
+		  (uint64_t) (offset_array_start
+			      - (unsigned char *) data->d_buf));
+	  for (uint32_t idx = 0; idx < offset_entry_count; idx++)
+	    {
+	      printf ("   [%6" PRIu32 "] ", idx);
+	      if (offset_size == 4)
+		{
+		  uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
+		  printf ("0x%" PRIx32 "\n", off);
+		}
+	      else
+		{
+		  uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
+		  printf ("0x%" PRIx64 "\n", off);
+		}
+	    }
+	  printf ("\n");
+	}
+
+      Dwarf_Addr base = cu_base;
+      bool start_of_list = true;
+      while (readp < nexthdr)
+	{
+	  uint8_t kind = *readp++;
+	  uint64_t op1, op2;
+
+	  /* Skip padding.  */
+	  if (start_of_list && kind == DW_RLE_end_of_list)
+	    continue;
+
+	  if (start_of_list)
+	    {
+	      base = cu_base;
+	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+		      (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
+		      (uint64_t) (readp - offset_array_start - 1));
+	      start_of_list = false;
+	    }
+
+	  printf ("    %s", dwarf_range_list_encoding_name (kind));
+	  switch (kind)
+	    {
+	    case DW_RLE_end_of_list:
+	      start_of_list = true;
+	      printf ("\n\n");
+	      break;
+
+	    case DW_RLE_base_addressx:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		{
+		invalid_range:
+		  error (0, 0, _("invalid range list data"));
+		  goto next_table;
+		}
+	      get_uleb128 (op1, readp, nexthdr);
+	      printf (" %" PRIx64 "\n", op1);
+	      if (! print_unresolved_addresses)
+		{
+		  Dwarf_Addr addr;
+		  if (get_indexed_addr (cu, op1, &addr) != 0)
+		    printf ("      ???\n");
+		  else
+		    {
+		      printf ("      ");
+		      print_dwarf_addr (dwflmod, address_size, addr, addr);
+		      printf ("\n");
+		    }
+		}
+	      break;
+
+	    case DW_RLE_startx_endx:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  Dwarf_Addr addr1;
+		  Dwarf_Addr addr2;
+		  if (get_indexed_addr (cu, op1, &addr1) != 0
+		      || get_indexed_addr (cu, op2, &addr2) != 0)
+		    {
+		      printf ("      ???..\n");
+		      printf ("      ???\n");
+		    }
+		  else
+		    {
+		      printf ("      ");
+		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
+		      printf ("..\n      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr2 - 1, addr2);
+		      printf ("\n");
+		    }
+		}
+	      break;
+
+	    case DW_RLE_startx_length:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  Dwarf_Addr addr1;
+		  Dwarf_Addr addr2;
+		  if (get_indexed_addr (cu, op1, &addr1) != 0)
+		    {
+		      printf ("      ???..\n");
+		      printf ("      ???\n");
+		    }
+		  else
+		    {
+		      addr2 = addr1 + op2;
+		      printf ("      ");
+		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
+		      printf ("..\n      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr2 - 1, addr2);
+		      printf ("\n");
+		    }
+		}
+	      break;
+
+	    case DW_RLE_offset_pair:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  op1 += base;
+		  op2 += base;
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1);
+		  printf ("..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
+		  printf ("\n");
+		}
+	      break;
+
+	    case DW_RLE_base_address:
+	      if (address_size == 4)
+		{
+		  if ((uint64_t) (nexthdr - readp) < 4)
+		    goto invalid_range;
+		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
+		}
+	      else
+		{
+		  if ((uint64_t) (nexthdr - readp) < 8)
+		    goto invalid_range;
+		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      base = op1;
+	      printf (" 0x%" PRIx64 "\n", base);
+	      if (! print_unresolved_addresses)
+		{
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, base, base);
+		  printf ("\n");
+		}
+	      break;
+
+	    case DW_RLE_start_end:
+	      if (address_size == 4)
+		{
+		  if ((uint64_t) (nexthdr - readp) < 8)
+		    goto invalid_range;
+		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
+		  op2 = read_4ubyte_unaligned_inc (dbg, readp);
+		}
+	      else
+		{
+		  if ((uint64_t) (nexthdr - readp) < 16)
+		    goto invalid_range;
+		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
+		  op2 = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1);
+		  printf ("..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
+		  printf ("\n");
+		}
+	      break;
+
+	    case DW_RLE_start_length:
+	      if (address_size == 4)
+		{
+		  if ((uint64_t) (nexthdr - readp) < 4)
+		    goto invalid_range;
+		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
+		}
+	      else
+		{
+		  if ((uint64_t) (nexthdr - readp) < 8)
+		    goto invalid_range;
+		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_range;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  op2 = op1 + op2;
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1);
+		  printf ("..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
+		  printf ("\n");
+		}
+	      break;
+
+	    default:
+	      goto invalid_range;
+	    }
+	}
+
+    next_table:
+      if (readp != nexthdr)
+	{
+          size_t padding = nexthdr - readp;
+          printf (_("   %zu padding bytes\n\n"), padding);
+	  readp = nexthdr;
+	}
+    }
+}
+
+/* Print content of DWARF .debug_ranges section.  */
+static void
+print_debug_ranges_section (Dwfl_Module *dwflmod,
+			    Ebl *ebl, GElf_Ehdr *ehdr,
+			    Elf_Scn *scn, GElf_Shdr *shdr,
+			    Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_ranges, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  sort_listptr (&known_rangelistptr, "rangelistptr");
+  size_t listptr_idx = 0;
+
+  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+  bool first = true;
+  Dwarf_Addr base = 0;
+  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
+  unsigned char *readp = data->d_buf;
+  Dwarf_CU *last_cu = NULL;
+  while (readp < endp)
+    {
+      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+      Dwarf_CU *cu = last_cu;
+
+      if (first && skip_listptr_hole (&known_rangelistptr, &listptr_idx,
+				      &address_size, NULL, &base, &cu,
+				      offset, &readp, endp, NULL))
+	continue;
+
+      if (last_cu != cu)
+	{
+	  Dwarf_Die cudie;
+	  if (dwarf_cu_die (cu, &cudie,
+			    NULL, NULL, NULL, NULL,
+			    NULL, NULL) == NULL)
+	    printf (_("\n Unknown CU base: "));
+	  else
+	    printf (_("\n CU [%6" PRIx64 "] base: "),
+		    dwarf_dieoffset (&cudie));
+	  print_dwarf_addr (dwflmod, address_size, base, base);
+	  printf ("\n");
+	}
+      last_cu = cu;
+
+      if (unlikely (data->d_size - offset < (size_t) address_size * 2))
+	{
+	  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
+	  break;
+	}
+
+      Dwarf_Addr begin;
+      Dwarf_Addr end;
+      if (address_size == 8)
+	{
+	  begin = read_8ubyte_unaligned_inc (dbg, readp);
+	  end = read_8ubyte_unaligned_inc (dbg, readp);
+	}
+      else
+	{
+	  begin = read_4ubyte_unaligned_inc (dbg, readp);
+	  end = read_4ubyte_unaligned_inc (dbg, readp);
+	  if (begin == (Dwarf_Addr) (uint32_t) -1)
+	    begin = (Dwarf_Addr) -1l;
+	}
+
+      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
+	{
+	  if (first)
+	    printf (" [%6tx] ", offset);
+	  else
+	    printf ("          ");
+	  puts (_("base address"));
+	  printf ("          ");
+	  print_dwarf_addr (dwflmod, address_size, end, end);
+	  printf ("\n");
+	  base = end;
+	  first = false;
+	}
+      else if (begin == 0 && end == 0) /* End of list entry.  */
+	{
+	  if (first)
+	    printf (_(" [%6tx] empty list\n"), offset);
+	  first = true;
+	}
+      else
+	{
+	  /* We have an address range entry.  */
+	  if (first)		/* First address range entry in a list.  */
+	    printf (" [%6tx] ", offset);
+	  else
+	    printf ("          ");
+
+	  printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
+	  if (! print_unresolved_addresses)
+	    {
+	      printf ("          ");
+	      print_dwarf_addr (dwflmod, address_size, base + begin,
+			        base + begin);
+	      printf ("..\n          ");
+	      print_dwarf_addr (dwflmod, address_size,
+				base + end - 1, base + end);
+	      printf ("\n");
+	    }
+
+	  first = false;
+	}
+    }
+}
+
+#define REGNAMESZ 16
+static const char *
+register_info (Ebl *ebl, unsigned int regno, const Ebl_Register_Location *loc,
+	       char name[REGNAMESZ], int *bits, int *type)
+{
+  const char *set;
+  const char *pfx;
+  int ignore;
+  ssize_t n = ebl_register_info (ebl, regno, name, REGNAMESZ, &pfx, &set,
+				 bits ?: &ignore, type ?: &ignore);
+  if (n <= 0)
+    {
+      if (loc != NULL)
+	snprintf (name, REGNAMESZ, "reg%u", loc->regno);
+      else
+	snprintf (name, REGNAMESZ, "??? 0x%x", regno);
+      if (bits != NULL)
+	*bits = loc != NULL ? loc->bits : 0;
+      if (type != NULL)
+	*type = DW_ATE_unsigned;
+      set = "??? unrecognized";
+    }
+  else
+    {
+      if (bits != NULL && *bits <= 0)
+	*bits = loc != NULL ? loc->bits : 0;
+      if (type != NULL && *type == DW_ATE_void)
+	*type = DW_ATE_unsigned;
+
+    }
+  return set;
+}
+
+static const unsigned char *
+read_encoded (unsigned int encoding, const unsigned char *readp,
+	      const unsigned char *const endp, uint64_t *res, Dwarf *dbg)
+{
+  if ((encoding & 0xf) == DW_EH_PE_absptr)
+    encoding = gelf_getclass (dbg->elf) == ELFCLASS32
+      ? DW_EH_PE_udata4 : DW_EH_PE_udata8;
+
+  switch (encoding & 0xf)
+    {
+    case DW_EH_PE_uleb128:
+      if (readp >= endp)
+	goto invalid;
+      get_uleb128 (*res, readp, endp);
+      break;
+    case DW_EH_PE_sleb128:
+      if (readp >= endp)
+	goto invalid;
+      get_sleb128 (*res, readp, endp);
+      break;
+    case DW_EH_PE_udata2:
+      if (readp + 2 > endp)
+	goto invalid;
+      *res = read_2ubyte_unaligned_inc (dbg, readp);
+      break;
+    case DW_EH_PE_udata4:
+      if (readp + 4 > endp)
+	goto invalid;
+      *res = read_4ubyte_unaligned_inc (dbg, readp);
+      break;
+    case DW_EH_PE_udata8:
+      if (readp + 8 > endp)
+	goto invalid;
+      *res = read_8ubyte_unaligned_inc (dbg, readp);
+      break;
+    case DW_EH_PE_sdata2:
+      if (readp + 2 > endp)
+	goto invalid;
+      *res = read_2sbyte_unaligned_inc (dbg, readp);
+      break;
+    case DW_EH_PE_sdata4:
+      if (readp + 4 > endp)
+	goto invalid;
+      *res = read_4sbyte_unaligned_inc (dbg, readp);
+      break;
+    case DW_EH_PE_sdata8:
+      if (readp + 8 > endp)
+	goto invalid;
+      *res = read_8sbyte_unaligned_inc (dbg, readp);
+      break;
+    default:
+    invalid:
+      error (1, 0,
+	     _("invalid encoding"));
+    }
+
+  return readp;
+}
+
+static const char *
+regname (Ebl *ebl, unsigned int regno, char *regnamebuf)
+{
+  register_info (ebl, regno, NULL, regnamebuf, NULL, NULL);
+
+  return regnamebuf;
+}
+
+static void
+print_cfa_program (const unsigned char *readp, const unsigned char *const endp,
+		   Dwarf_Word vma_base, unsigned int code_align,
+		   int data_align,
+		   unsigned int version, unsigned int ptr_size,
+		   unsigned int encoding,
+		   Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr, Dwarf *dbg)
+{
+  char regnamebuf[REGNAMESZ];
+
+  puts ("\n   Program:");
+  Dwarf_Word pc = vma_base;
+  while (readp < endp)
+    {
+      unsigned int opcode = *readp++;
+
+      if (opcode < DW_CFA_advance_loc)
+	/* Extended opcode.  */
+	switch (opcode)
+	  {
+	    uint64_t op1;
+	    int64_t sop1;
+	    uint64_t op2;
+	    int64_t sop2;
+
+	  case DW_CFA_nop:
+	    puts ("     nop");
+	    break;
+	  case DW_CFA_set_loc:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    readp = read_encoded (encoding, readp, endp, &op1, dbg);
+	    printf ("     set_loc %#" PRIx64 " to %#" PRIx64 "\n",
+		    op1, pc = vma_base + op1);
+	    break;
+	  case DW_CFA_advance_loc1:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    printf ("     advance_loc1 %u to %#" PRIx64 "\n",
+		    *readp, pc += *readp * code_align);
+	    ++readp;
+	    break;
+	  case DW_CFA_advance_loc2:
+	    if ((uint64_t) (endp - readp) < 2)
+	      goto invalid;
+	    op1 = read_2ubyte_unaligned_inc (dbg, readp);
+	    printf ("     advance_loc2 %" PRIu64 " to %#" PRIx64 "\n",
+		    op1, pc += op1 * code_align);
+	    break;
+	  case DW_CFA_advance_loc4:
+	    if ((uint64_t) (endp - readp) < 4)
+	      goto invalid;
+	    op1 = read_4ubyte_unaligned_inc (dbg, readp);
+	    printf ("     advance_loc4 %" PRIu64 " to %#" PRIx64 "\n",
+		    op1, pc += op1 * code_align);
+	    break;
+	  case DW_CFA_offset_extended:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
+	    printf ("     offset_extended r%" PRIu64 " (%s) at cfa%+" PRId64
+		    "\n",
+		    op1, regname (ebl, op1, regnamebuf), op2 * data_align);
+	    break;
+	  case DW_CFA_restore_extended:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    printf ("     restore_extended r%" PRIu64 " (%s)\n",
+		    op1, regname (ebl, op1, regnamebuf));
+	    break;
+	  case DW_CFA_undefined:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    printf ("     undefined r%" PRIu64 " (%s)\n", op1,
+		    regname (ebl, op1, regnamebuf));
+	    break;
+	  case DW_CFA_same_value:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    printf ("     same_value r%" PRIu64 " (%s)\n", op1,
+		    regname (ebl, op1, regnamebuf));
+	    break;
+	  case DW_CFA_register:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
+	    printf ("     register r%" PRIu64 " (%s) in r%" PRIu64 " (%s)\n",
+		    op1, regname (ebl, op1, regnamebuf), op2,
+		    regname (ebl, op2, regnamebuf));
+	    break;
+	  case DW_CFA_remember_state:
+	    puts ("     remember_state");
+	    break;
+	  case DW_CFA_restore_state:
+	    puts ("     restore_state");
+	    break;
+	  case DW_CFA_def_cfa:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
+	    printf ("     def_cfa r%" PRIu64 " (%s) at offset %" PRIu64 "\n",
+		    op1, regname (ebl, op1, regnamebuf), op2);
+	    break;
+	  case DW_CFA_def_cfa_register:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    printf ("     def_cfa_register r%" PRIu64 " (%s)\n",
+		    op1, regname (ebl, op1, regnamebuf));
+	    break;
+	  case DW_CFA_def_cfa_offset:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    printf ("     def_cfa_offset %" PRIu64 "\n", op1);
+	    break;
+	  case DW_CFA_def_cfa_expression:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);	/* Length of DW_FORM_block.  */
+	    printf ("     def_cfa_expression %" PRIu64 "\n", op1);
+	    if ((uint64_t) (endp - readp) < op1)
+	      {
+	    invalid:
+	        fputs (_("         <INVALID DATA>\n"), stdout);
+		return;
+	      }
+	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
+		       op1, readp);
+	    readp += op1;
+	    break;
+	  case DW_CFA_expression:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
+	    printf ("     expression r%" PRIu64 " (%s) \n",
+		    op1, regname (ebl, op1, regnamebuf));
+	    if ((uint64_t) (endp - readp) < op2)
+	      goto invalid;
+	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0, NULL,
+		       op2, readp);
+	    readp += op2;
+	    break;
+	  case DW_CFA_offset_extended_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop2, readp, endp);
+	    printf ("     offset_extended_sf r%" PRIu64 " (%s) at cfa%+"
+		    PRId64 "\n",
+		    op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
+	    break;
+	  case DW_CFA_def_cfa_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop2, readp, endp);
+	    printf ("     def_cfa_sf r%" PRIu64 " (%s) at offset %" PRId64 "\n",
+		    op1, regname (ebl, op1, regnamebuf), sop2 * data_align);
+	    break;
+	  case DW_CFA_def_cfa_offset_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop1, readp, endp);
+	    printf ("     def_cfa_offset_sf %" PRId64 "\n", sop1 * data_align);
+	    break;
+	  case DW_CFA_val_offset:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);
+	    printf ("     val_offset %" PRIu64 " at offset %" PRIu64 "\n",
+		    op1, op2 * data_align);
+	    break;
+	  case DW_CFA_val_offset_sf:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_sleb128 (sop2, readp, endp);
+	    printf ("     val_offset_sf %" PRIu64 " at offset %" PRId64 "\n",
+		    op1, sop2 * data_align);
+	    break;
+	  case DW_CFA_val_expression:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op2, readp, endp);	/* Length of DW_FORM_block.  */
+	    printf ("     val_expression r%" PRIu64 " (%s)\n",
+		    op1, regname (ebl, op1, regnamebuf));
+	    if ((uint64_t) (endp - readp) < op2)
+	      goto invalid;
+	    print_ops (dwflmod, dbg, 10, 10, version, ptr_size, 0,
+		       NULL, op2, readp);
+	    readp += op2;
+	    break;
+	  case DW_CFA_MIPS_advance_loc8:
+	    if ((uint64_t) (endp - readp) < 8)
+	      goto invalid;
+	    op1 = read_8ubyte_unaligned_inc (dbg, readp);
+	    printf ("     MIPS_advance_loc8 %" PRIu64 " to %#" PRIx64 "\n",
+		    op1, pc += op1 * code_align);
+	    break;
+	  case DW_CFA_GNU_window_save:  /* DW_CFA_AARCH64_negate_ra_state  */
+	    if (ehdr->e_machine == EM_AARCH64)
+	      puts ("     AARCH64_negate_ra_state");
+	    else
+	      puts ("     GNU_window_save");
+	    break;
+	  case DW_CFA_GNU_args_size:
+	    if ((uint64_t) (endp - readp) < 1)
+	      goto invalid;
+	    get_uleb128 (op1, readp, endp);
+	    printf ("     args_size %" PRIu64 "\n", op1);
+	    break;
+	  default:
+	    printf ("     ??? (%u)\n", opcode);
+	    break;
+	  }
+      else if (opcode < DW_CFA_offset)
+	printf ("     advance_loc %u to %#" PRIx64 "\n",
+		opcode & 0x3f, pc += (opcode & 0x3f) * code_align);
+      else if (opcode < DW_CFA_restore)
+	{
+	  uint64_t offset;
+	  if ((uint64_t) (endp - readp) < 1)
+	    goto invalid;
+	  get_uleb128 (offset, readp, endp);
+	  printf ("     offset r%u (%s) at cfa%+" PRId64 "\n",
+		  opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf),
+		  offset * data_align);
+	}
+      else
+	printf ("     restore r%u (%s)\n",
+		opcode & 0x3f, regname (ebl, opcode & 0x3f, regnamebuf));
+    }
+}
+
+
+static unsigned int
+encoded_ptr_size (int encoding, unsigned int ptr_size)
+{
+  switch (encoding & 7)
+    {
+    case DW_EH_PE_udata4:
+      return 4;
+    case DW_EH_PE_udata8:
+      return 8;
+    case 0:
+      return ptr_size;
+    }
+
+  fprintf (stderr, "Unsupported pointer encoding: %#x, "
+	   "assuming pointer size of %d.\n", encoding, ptr_size);
+  return ptr_size;
+}
+
+
+static unsigned int
+print_encoding (unsigned int val)
+{
+  switch (val & 0xf)
+    {
+    case DW_EH_PE_absptr:
+      fputs ("absptr", stdout);
+      break;
+    case DW_EH_PE_uleb128:
+      fputs ("uleb128", stdout);
+      break;
+    case DW_EH_PE_udata2:
+      fputs ("udata2", stdout);
+      break;
+    case DW_EH_PE_udata4:
+      fputs ("udata4", stdout);
+      break;
+    case DW_EH_PE_udata8:
+      fputs ("udata8", stdout);
+      break;
+    case DW_EH_PE_sleb128:
+      fputs ("sleb128", stdout);
+      break;
+    case DW_EH_PE_sdata2:
+      fputs ("sdata2", stdout);
+      break;
+    case DW_EH_PE_sdata4:
+      fputs ("sdata4", stdout);
+      break;
+    case DW_EH_PE_sdata8:
+      fputs ("sdata8", stdout);
+      break;
+    default:
+      /* We did not use any of the bits after all.  */
+      return val;
+    }
+
+  return val & ~0xf;
+}
+
+
+static unsigned int
+print_relinfo (unsigned int val)
+{
+  switch (val & 0x70)
+    {
+    case DW_EH_PE_pcrel:
+      fputs ("pcrel", stdout);
+      break;
+    case DW_EH_PE_textrel:
+      fputs ("textrel", stdout);
+      break;
+    case DW_EH_PE_datarel:
+      fputs ("datarel", stdout);
+      break;
+    case DW_EH_PE_funcrel:
+      fputs ("funcrel", stdout);
+      break;
+    case DW_EH_PE_aligned:
+      fputs ("aligned", stdout);
+      break;
+    default:
+      return val;
+    }
+
+  return val & ~0x70;
+}
+
+
+static void
+print_encoding_base (const char *pfx, unsigned int fde_encoding)
+{
+  printf ("(%s", pfx);
+
+  if (fde_encoding == DW_EH_PE_omit)
+    puts ("omit)");
+  else
+    {
+      unsigned int w = fde_encoding;
+
+      w = print_encoding (w);
+
+      if (w & 0x70)
+	{
+	  if (w != fde_encoding)
+	    fputc_unlocked (' ', stdout);
+
+	  w = print_relinfo (w);
+	}
+
+      if (w != 0)
+	printf ("%s%x", w != fde_encoding ? " " : "", w);
+
+      puts (")");
+    }
+}
+
+
+static void
+print_debug_frame_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  size_t shstrndx;
+  /* We know this call will succeed since it did in the caller.  */
+  (void) elf_getshdrstrndx (ebl->elf, &shstrndx);
+  const char *scnname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+
+  /* Needed if we find PC-relative addresses.  */
+  GElf_Addr bias;
+  if (dwfl_module_getelf (dwflmod, &bias) == NULL)
+    {
+      error (0, 0, _("cannot get ELF: %s"), dwfl_errmsg (-1));
+      return;
+    }
+
+  bool is_eh_frame = strcmp (scnname, ".eh_frame") == 0;
+  Elf_Data *data;
+  if (is_eh_frame)
+    {
+      data = elf_rawdata (scn, NULL);
+      if (data == NULL)
+	{
+	  error (0, 0, _("cannot get %s content: %s"),
+		 scnname, elf_errmsg (-1));
+	  return;
+	}
+    }
+  else
+    {
+      data = get_debug_elf_data (dbg, ebl, IDX_debug_frame, scn);
+      if (data == NULL)
+	return;
+    }
+
+  if (is_eh_frame)
+    printf (_("\
+\nCall frame information section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
+  else
+    printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	    elf_ndxscn (scn), scnname, (uint64_t) shdr->sh_offset);
+
+  struct cieinfo
+  {
+    ptrdiff_t cie_offset;
+    const char *augmentation;
+    unsigned int code_alignment_factor;
+    unsigned int data_alignment_factor;
+    uint8_t address_size;
+    uint8_t fde_encoding;
+    uint8_t lsda_encoding;
+    struct cieinfo *next;
+  } *cies = NULL;
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *const dataend = ((unsigned char *) data->d_buf
+					+ data->d_size);
+  while (readp < dataend)
+    {
+      if (unlikely (readp + 4 > dataend))
+	{
+	invalid_data:
+	  error (0, 0, _("invalid data in section [%zu] '%s'"),
+		     elf_ndxscn (scn), scnname);
+	      return;
+	}
+
+      /* At the beginning there must be a CIE.  There can be multiple,
+	 hence we test tis in a loop.  */
+      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+
+      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+      unsigned int length = 4;
+      if (unlikely (unit_length == 0xffffffff))
+	{
+	  if (unlikely (readp + 8 > dataend))
+	    goto invalid_data;
+
+	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+	  length = 8;
+	}
+
+      if (unlikely (unit_length == 0))
+	{
+	  printf (_("\n [%6tx] Zero terminator\n"), offset);
+	  continue;
+	}
+
+      Dwarf_Word maxsize = dataend - readp;
+      if (unlikely (unit_length > maxsize))
+	goto invalid_data;
+
+      unsigned int ptr_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+      ptrdiff_t start = readp - (unsigned char *) data->d_buf;
+      const unsigned char *const cieend = readp + unit_length;
+      if (unlikely (cieend > dataend))
+	goto invalid_data;
+
+      Dwarf_Off cie_id;
+      if (length == 4)
+	{
+	  if (unlikely (cieend - readp < 4))
+	    goto invalid_data;
+	  cie_id = read_4ubyte_unaligned_inc (dbg, readp);
+	  if (!is_eh_frame && cie_id == DW_CIE_ID_32)
+	    cie_id = DW_CIE_ID_64;
+	}
+      else
+	{
+	  if (unlikely (cieend - readp < 8))
+	    goto invalid_data;
+	  cie_id = read_8ubyte_unaligned_inc (dbg, readp);
+	}
+
+      uint_fast8_t version = 2;
+      unsigned int code_alignment_factor;
+      int data_alignment_factor;
+      unsigned int fde_encoding = 0;
+      unsigned int lsda_encoding = 0;
+      Dwarf_Word initial_location = 0;
+      Dwarf_Word vma_base = 0;
+
+      if (cie_id == (is_eh_frame ? 0 : DW_CIE_ID_64))
+	{
+	  if (unlikely (cieend - readp < 2))
+	    goto invalid_data;
+	  version = *readp++;
+	  const char *const augmentation = (const char *) readp;
+	  readp = memchr (readp, '\0', cieend - readp);
+	  if (unlikely (readp == NULL))
+	    goto invalid_data;
+	  ++readp;
+
+	  uint_fast8_t segment_size = 0;
+	  if (version >= 4)
+	    {
+	      if (cieend - readp < 5)
+		goto invalid_data;
+	      ptr_size = *readp++;
+	      segment_size = *readp++;
+	    }
+
+	  if (cieend - readp < 1)
+	    goto invalid_data;
+	  get_uleb128 (code_alignment_factor, readp, cieend);
+	  if (cieend - readp < 1)
+	    goto invalid_data;
+	  get_sleb128 (data_alignment_factor, readp, cieend);
+
+	  /* In some variant for unwind data there is another field.  */
+	  if (strcmp (augmentation, "eh") == 0)
+	    readp += ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+	  unsigned int return_address_register;
+	  if (cieend - readp < 1)
+	    goto invalid_data;
+	  if (unlikely (version == 1))
+	    return_address_register = *readp++;
+	  else
+	    get_uleb128 (return_address_register, readp, cieend);
+
+	  printf ("\n [%6tx] CIE length=%" PRIu64 "\n"
+		  "   CIE_id:                   %" PRIu64 "\n"
+		  "   version:                  %u\n"
+		  "   augmentation:             \"%s\"\n",
+		  offset, (uint64_t) unit_length, (uint64_t) cie_id,
+		  version, augmentation);
+	  if (version >= 4)
+	    printf ("   address_size:             %u\n"
+		    "   segment_size:             %u\n",
+		    ptr_size, segment_size);
+	  printf ("   code_alignment_factor:    %u\n"
+		  "   data_alignment_factor:    %d\n"
+		  "   return_address_register:  %u\n",
+		  code_alignment_factor,
+		  data_alignment_factor, return_address_register);
+
+	  if (augmentation[0] == 'z')
+	    {
+	      if (cieend - readp < 1)
+		goto invalid_data;
+
+	      unsigned int augmentationlen;
+	      get_uleb128 (augmentationlen, readp, cieend);
+
+	      if (augmentationlen > (size_t) (cieend - readp))
+		{
+		  error (0, 0, _("invalid augmentation length"));
+		  readp = cieend;
+		  continue;
+		}
+
+	      const char *hdr = "Augmentation data:";
+	      const char *cp = augmentation + 1;
+	      while (*cp != '\0' && cp < augmentation + augmentationlen + 1)
+		{
+		  printf ("   %-26s%#x ", hdr, *readp);
+		  hdr = "";
+
+		  if (*cp == 'R')
+		    {
+		      fde_encoding = *readp++;
+		      print_encoding_base (_("FDE address encoding: "),
+					   fde_encoding);
+		    }
+		  else if (*cp == 'L')
+		    {
+		      lsda_encoding = *readp++;
+		      print_encoding_base (_("LSDA pointer encoding: "),
+					   lsda_encoding);
+		    }
+		  else if (*cp == 'P')
+		    {
+		      /* Personality.  This field usually has a relocation
+			 attached pointing to __gcc_personality_v0.  */
+		      const unsigned char *startp = readp;
+		      unsigned int encoding = *readp++;
+		      uint64_t val = 0;
+		      readp = read_encoded (encoding, readp,
+					    readp - 1 + augmentationlen,
+					    &val, dbg);
+
+		      while (++startp < readp)
+			printf ("%#x ", *startp);
+
+		      putchar ('(');
+		      print_encoding (encoding);
+		      putchar (' ');
+		      switch (encoding & 0xf)
+			{
+			case DW_EH_PE_sleb128:
+			case DW_EH_PE_sdata2:
+			case DW_EH_PE_sdata4:
+			  printf ("%" PRId64 ")\n", val);
+			  break;
+			default:
+			  printf ("%#" PRIx64 ")\n", val);
+			  break;
+			}
+		    }
+		  else
+		    printf ("(%x)\n", *readp++);
+
+		  ++cp;
+		}
+	    }
+
+	  if (likely (ptr_size == 4 || ptr_size == 8))
+	    {
+	      struct cieinfo *newp = alloca (sizeof (*newp));
+	      newp->cie_offset = offset;
+	      newp->augmentation = augmentation;
+	      newp->fde_encoding = fde_encoding;
+	      newp->lsda_encoding = lsda_encoding;
+	      newp->address_size = ptr_size;
+	      newp->code_alignment_factor = code_alignment_factor;
+	      newp->data_alignment_factor = data_alignment_factor;
+	      newp->next = cies;
+	      cies = newp;
+	    }
+	}
+      else
+	{
+	  struct cieinfo *cie = cies;
+	  while (cie != NULL)
+	    if (is_eh_frame
+		? ((Dwarf_Off) start - cie_id) == (Dwarf_Off) cie->cie_offset
+		: cie_id == (Dwarf_Off) cie->cie_offset)
+	      break;
+	    else
+	      cie = cie->next;
+	  if (unlikely (cie == NULL))
+	    {
+	      puts ("invalid CIE reference in FDE");
+	      return;
+	    }
+
+	  /* Initialize from CIE data.  */
+	  fde_encoding = cie->fde_encoding;
+	  lsda_encoding = cie->lsda_encoding;
+	  ptr_size = encoded_ptr_size (fde_encoding, cie->address_size);
+	  code_alignment_factor = cie->code_alignment_factor;
+	  data_alignment_factor = cie->data_alignment_factor;
+
+	  const unsigned char *base = readp;
+	  // XXX There are sometimes relocations for this value
+	  initial_location = read_addr_unaligned_inc (ptr_size, dbg, readp);
+	  Dwarf_Word address_range
+	    = read_addr_unaligned_inc (ptr_size, dbg, readp);
+
+	  /* pcrel for an FDE address is relative to the runtime
+	     address of the start_address field itself.  Sign extend
+	     if necessary to make sure the calculation is done on the
+	     full 64 bit address even when initial_location only holds
+	     the lower 32 bits.  */
+	  Dwarf_Addr pc_start = initial_location;
+	  if (ptr_size == 4)
+	    pc_start = (uint64_t) (int32_t) pc_start;
+	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
+	    pc_start += ((uint64_t) shdr->sh_addr
+			 + (base - (const unsigned char *) data->d_buf)
+			 - bias);
+
+	  printf ("\n [%6tx] FDE length=%" PRIu64 " cie=[%6tx]\n"
+		  "   CIE_pointer:              %" PRIu64 "\n"
+		  "   initial_location:         ",
+		  offset, (uint64_t) unit_length,
+		  cie->cie_offset, (uint64_t) cie_id);
+	  print_dwarf_addr (dwflmod, cie->address_size,
+			    pc_start, initial_location);
+	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
+	    {
+	      vma_base = (((uint64_t) shdr->sh_offset
+			   + (base - (const unsigned char *) data->d_buf)
+			   + (uint64_t) initial_location)
+			  & (ptr_size == 4
+			     ? UINT64_C (0xffffffff)
+			     : UINT64_C (0xffffffffffffffff)));
+	      printf (_(" (offset: %#" PRIx64 ")"),
+		      (uint64_t) vma_base);
+	    }
+
+	  printf ("\n   address_range:            %#" PRIx64,
+		  (uint64_t) address_range);
+	  if ((fde_encoding & 0x70) == DW_EH_PE_pcrel)
+	    printf (_(" (end offset: %#" PRIx64 ")"),
+		    ((uint64_t) vma_base + (uint64_t) address_range)
+		    & (ptr_size == 4
+		       ? UINT64_C (0xffffffff)
+		       : UINT64_C (0xffffffffffffffff)));
+	  putchar ('\n');
+
+	  if (cie->augmentation[0] == 'z')
+	    {
+	      unsigned int augmentationlen;
+	      if (cieend - readp < 1)
+		goto invalid_data;
+	      get_uleb128 (augmentationlen, readp, cieend);
+
+	      if (augmentationlen > (size_t) (cieend - readp))
+		{
+		  error (0, 0, _("invalid augmentation length"));
+		  readp = cieend;
+		  continue;
+		}
+
+	      if (augmentationlen > 0)
+		{
+		  const char *hdr = "Augmentation data:";
+		  const char *cp = cie->augmentation + 1;
+		  unsigned int u = 0;
+		  while (*cp != '\0'
+			 && cp < cie->augmentation + augmentationlen + 1)
+		    {
+		      if (*cp == 'L')
+			{
+			  uint64_t lsda_pointer;
+			  const unsigned char *p
+			    = read_encoded (lsda_encoding, &readp[u],
+					    &readp[augmentationlen],
+					    &lsda_pointer, dbg);
+			  u = p - readp;
+			  printf (_("\
+   %-26sLSDA pointer: %#" PRIx64 "\n"),
+				  hdr, lsda_pointer);
+			  hdr = "";
+			}
+		      ++cp;
+		    }
+
+		  while (u < augmentationlen)
+		    {
+		      printf ("   %-26s%#x\n", hdr, readp[u++]);
+		      hdr = "";
+		    }
+		}
+
+	      readp += augmentationlen;
+	    }
+	}
+
+      /* Handle the initialization instructions.  */
+      if (ptr_size != 4 && ptr_size !=8)
+	printf ("invalid CIE pointer size (%u), must be 4 or 8.\n", ptr_size);
+      else
+	print_cfa_program (readp, cieend, vma_base, code_alignment_factor,
+			   data_alignment_factor, version, ptr_size,
+			   fde_encoding, dwflmod, ebl, ehdr, dbg);
+      readp = cieend;
+    }
+}
+
+
+/* Returns the signedness (or false if it cannot be determined) and
+   the byte size (or zero if it cannot be gotten) of the given DIE
+   DW_AT_type attribute.  Uses dwarf_peel_type and dwarf_aggregate_size.  */
+static void
+die_type_sign_bytes (Dwarf_Die *die, bool *is_signed, int *bytes)
+{
+  Dwarf_Attribute attr;
+  Dwarf_Die type;
+
+  *bytes = 0;
+  *is_signed = false;
+
+  if (dwarf_peel_type (dwarf_formref_die (dwarf_attr_integrate (die,
+								DW_AT_type,
+								&attr), &type),
+		       &type) == 0)
+    {
+      Dwarf_Word val;
+      *is_signed = (dwarf_formudata (dwarf_attr (&type, DW_AT_encoding,
+						 &attr), &val) == 0
+		    && (val == DW_ATE_signed || val == DW_ATE_signed_char));
+
+      if (dwarf_aggregate_size (&type, &val) == 0)
+	*bytes = val;
+    }
+}
+
+struct attrcb_args
+{
+  Dwfl_Module *dwflmod;
+  Dwarf *dbg;
+  Dwarf_Die *dies;
+  int level;
+  bool silent;
+  bool is_split;
+  unsigned int version;
+  unsigned int addrsize;
+  unsigned int offset_size;
+  struct Dwarf_CU *cu;
+};
+
+
+static int
+attr_callback (Dwarf_Attribute *attrp, void *arg)
+{
+  struct attrcb_args *cbargs = (struct attrcb_args *) arg;
+  const int level = cbargs->level;
+  Dwarf_Die *die = &cbargs->dies[level];
+  bool is_split = cbargs->is_split;
+
+  unsigned int attr = dwarf_whatattr (attrp);
+  if (unlikely (attr == 0))
+    {
+      if (!cbargs->silent)
+	error (0, 0, _("DIE [%" PRIx64 "] "
+			      "cannot get attribute code: %s"),
+	       dwarf_dieoffset (die), dwarf_errmsg (-1));
+      return DWARF_CB_ABORT;
+    }
+
+  unsigned int form = dwarf_whatform (attrp);
+  if (unlikely (form == 0))
+    {
+      if (!cbargs->silent)
+	error (0, 0, _("DIE [%" PRIx64 "] "
+			      "cannot get attribute form: %s"),
+	       dwarf_dieoffset (die), dwarf_errmsg (-1));
+      return DWARF_CB_ABORT;
+    }
+
+  switch (form)
+    {
+    case DW_FORM_addr:
+    case DW_FORM_addrx:
+    case DW_FORM_addrx1:
+    case DW_FORM_addrx2:
+    case DW_FORM_addrx3:
+    case DW_FORM_addrx4:
+    case DW_FORM_GNU_addr_index:
+      if (!cbargs->silent)
+	{
+	  Dwarf_Addr addr;
+	  if (unlikely (dwarf_formaddr (attrp, &addr) != 0))
+	    {
+	    attrval_out:
+	      if (!cbargs->silent)
+		error (0, 0, _("DIE [%" PRIx64 "] "
+				      "cannot get attribute '%s' (%s) value: "
+				      "%s"),
+		       dwarf_dieoffset (die),
+		       dwarf_attr_name (attr),
+		       dwarf_form_name (form),
+		       dwarf_errmsg (-1));
+	      /* Don't ABORT, it might be other attributes can be resolved.  */
+	      return DWARF_CB_OK;
+	    }
+	  if (form != DW_FORM_addr )
+	    {
+	      Dwarf_Word word;
+	      if (dwarf_formudata (attrp, &word) != 0)
+		goto attrval_out;
+	      printf ("           %*s%-20s (%s) [%" PRIx64 "] ",
+		      (int) (level * 2), "", dwarf_attr_name (attr),
+		      dwarf_form_name (form), word);
+	    }
+	  else
+	    printf ("           %*s%-20s (%s) ",
+		    (int) (level * 2), "", dwarf_attr_name (attr),
+		    dwarf_form_name (form));
+	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, addr, addr);
+	  printf ("\n");
+	}
+      break;
+
+    case DW_FORM_indirect:
+    case DW_FORM_strp:
+    case DW_FORM_line_strp:
+    case DW_FORM_strx:
+    case DW_FORM_strx1:
+    case DW_FORM_strx2:
+    case DW_FORM_strx3:
+    case DW_FORM_strx4:
+    case DW_FORM_string:
+    case DW_FORM_GNU_strp_alt:
+    case DW_FORM_GNU_str_index:
+      if (cbargs->silent)
+	break;
+      const char *str = dwarf_formstring (attrp);
+      if (unlikely (str == NULL))
+	goto attrval_out;
+      printf ("           %*s%-20s (%s) \"%s\"\n",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), str);
+      break;
+
+    case DW_FORM_ref_addr:
+    case DW_FORM_ref_udata:
+    case DW_FORM_ref8:
+    case DW_FORM_ref4:
+    case DW_FORM_ref2:
+    case DW_FORM_ref1:
+    case DW_FORM_GNU_ref_alt:
+    case DW_FORM_ref_sup4:
+    case DW_FORM_ref_sup8:
+      if (cbargs->silent)
+	break;
+      Dwarf_Die ref;
+      if (unlikely (dwarf_formref_die (attrp, &ref) == NULL))
+	goto attrval_out;
+
+      printf ("           %*s%-20s (%s) ",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form));
+      if (is_split)
+	printf ("{%6" PRIxMAX "}\n", (uintmax_t) dwarf_dieoffset (&ref));
+      else
+	printf ("[%6" PRIxMAX "]\n", (uintmax_t) dwarf_dieoffset (&ref));
+      break;
+
+    case DW_FORM_ref_sig8:
+      if (cbargs->silent)
+	break;
+      printf ("           %*s%-20s (%s) {%6" PRIx64 "}\n",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form),
+	      (uint64_t) read_8ubyte_unaligned (attrp->cu->dbg, attrp->valp));
+      break;
+
+    case DW_FORM_sec_offset:
+    case DW_FORM_rnglistx:
+    case DW_FORM_loclistx:
+    case DW_FORM_implicit_const:
+    case DW_FORM_udata:
+    case DW_FORM_sdata:
+    case DW_FORM_data8: /* Note no data16 here, we see that as block. */
+    case DW_FORM_data4:
+    case DW_FORM_data2:
+    case DW_FORM_data1:;
+      Dwarf_Word num;
+      if (unlikely (dwarf_formudata (attrp, &num) != 0))
+	goto attrval_out;
+
+      const char *valuestr = NULL;
+      bool as_hex_id = false;
+      switch (attr)
+	{
+	  /* This case can take either a constant or a loclistptr.  */
+	case DW_AT_data_member_location:
+	  if (form != DW_FORM_sec_offset
+	      && (cbargs->version >= 4
+		  || (form != DW_FORM_data4 && form != DW_FORM_data8)))
+	    {
+	      if (!cbargs->silent)
+		printf ("           %*s%-20s (%s) %" PRIuMAX "\n",
+			(int) (level * 2), "", dwarf_attr_name (attr),
+			dwarf_form_name (form), (uintmax_t) num);
+	      return DWARF_CB_OK;
+	    }
+	  FALLTHROUGH;
+
+	/* These cases always take a loclist[ptr] and no constant. */
+	case DW_AT_location:
+	case DW_AT_data_location:
+	case DW_AT_vtable_elem_location:
+	case DW_AT_string_length:
+	case DW_AT_use_location:
+	case DW_AT_frame_base:
+	case DW_AT_return_addr:
+	case DW_AT_static_link:
+	case DW_AT_segment:
+	case DW_AT_GNU_call_site_value:
+	case DW_AT_GNU_call_site_data_value:
+	case DW_AT_GNU_call_site_target:
+	case DW_AT_GNU_call_site_target_clobbered:
+	case DW_AT_GNU_locviews:
+	  {
+	    bool nlpt;
+	    if (cbargs->cu->version < 5)
+	      {
+		if (! cbargs->is_split)
+		  {
+		    nlpt = notice_listptr (section_loc, &known_locsptr,
+					   cbargs->addrsize,
+					   cbargs->offset_size,
+					   cbargs->cu, num, attr);
+		  }
+		else
+		  nlpt = true;
+	      }
+	    else
+	      {
+		/* Only register for a real section offset.  Otherwise
+		   it is a DW_FORM_loclistx which is just an index
+		   number and we should already have registered the
+		   section offset for the index when we saw the
+		   DW_AT_loclists_base CU attribute.  */
+		if (form == DW_FORM_sec_offset)
+		  nlpt = notice_listptr (section_loc, &known_loclistsptr,
+					 cbargs->addrsize, cbargs->offset_size,
+					 cbargs->cu, num, attr);
+		else
+		  nlpt = true;
+
+	      }
+
+	    if (!cbargs->silent)
+	      {
+		if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
+		  printf ("           %*s%-20s (%s) location list [%6"
+			  PRIxMAX "]%s\n",
+			  (int) (level * 2), "", dwarf_attr_name (attr),
+			  dwarf_form_name (form), (uintmax_t) num,
+			  nlpt ? "" : " <WARNING offset too big>");
+		else
+		  printf ("           %*s%-20s (%s) location index [%6"
+			  PRIxMAX "]\n",
+			  (int) (level * 2), "", dwarf_attr_name (attr),
+			  dwarf_form_name (form), (uintmax_t) num);
+	      }
+	  }
+	  return DWARF_CB_OK;
+
+	case DW_AT_loclists_base:
+	  {
+	    bool nlpt = notice_listptr (section_loc, &known_loclistsptr,
+                                        cbargs->addrsize, cbargs->offset_size,
+                                        cbargs->cu, num, attr);
+
+	    if (!cbargs->silent)
+	      printf ("           %*s%-20s (%s) location list [%6" PRIxMAX "]%s\n",
+		      (int) (level * 2), "", dwarf_attr_name (attr),
+		      dwarf_form_name (form), (uintmax_t) num,
+		      nlpt ? "" : " <WARNING offset too big>");
+	  }
+	  return DWARF_CB_OK;
+
+	case DW_AT_ranges:
+	case DW_AT_start_scope:
+	  {
+	    bool nlpt;
+	    if (cbargs->cu->version < 5)
+	      nlpt = notice_listptr (section_ranges, &known_rangelistptr,
+				     cbargs->addrsize, cbargs->offset_size,
+				     cbargs->cu, num, attr);
+	    else
+	      {
+		/* Only register for a real section offset.  Otherwise
+		   it is a DW_FORM_rangelistx which is just an index
+		   number and we should already have registered the
+		   section offset for the index when we saw the
+		   DW_AT_rnglists_base CU attribute.  */
+		if (form == DW_FORM_sec_offset)
+		  nlpt = notice_listptr (section_ranges, &known_rnglistptr,
+					 cbargs->addrsize, cbargs->offset_size,
+					 cbargs->cu, num, attr);
+		else
+		  nlpt = true;
+	      }
+
+	    if (!cbargs->silent)
+	      {
+		if (cbargs->cu->version < 5 || form == DW_FORM_sec_offset)
+		  printf ("           %*s%-20s (%s) range list [%6"
+			  PRIxMAX "]%s\n",
+			  (int) (level * 2), "", dwarf_attr_name (attr),
+			  dwarf_form_name (form), (uintmax_t) num,
+			  nlpt ? "" : " <WARNING offset too big>");
+		else
+		  printf ("           %*s%-20s (%s) range index [%6"
+			  PRIxMAX "]\n",
+			  (int) (level * 2), "", dwarf_attr_name (attr),
+			  dwarf_form_name (form), (uintmax_t) num);
+	      }
+	  }
+	  return DWARF_CB_OK;
+
+	case DW_AT_rnglists_base:
+	  {
+	    bool nlpt = notice_listptr (section_ranges, &known_rnglistptr,
+					cbargs->addrsize, cbargs->offset_size,
+					cbargs->cu, num, attr);
+	    if (!cbargs->silent)
+	      printf ("           %*s%-20s (%s) range list [%6"
+		      PRIxMAX "]%s\n",
+		      (int) (level * 2), "", dwarf_attr_name (attr),
+		      dwarf_form_name (form), (uintmax_t) num,
+		      nlpt ? "" : " <WARNING offset too big>");
+	  }
+	  return DWARF_CB_OK;
+
+	case DW_AT_addr_base:
+	case DW_AT_GNU_addr_base:
+	  {
+	    bool addrbase = notice_listptr (section_addr, &known_addrbases,
+					    cbargs->addrsize,
+					    cbargs->offset_size,
+					    cbargs->cu, num, attr);
+	    if (!cbargs->silent)
+	      printf ("           %*s%-20s (%s) address base [%6"
+		      PRIxMAX "]%s\n",
+		      (int) (level * 2), "", dwarf_attr_name (attr),
+		      dwarf_form_name (form), (uintmax_t) num,
+		      addrbase ? "" : " <WARNING offset too big>");
+	  }
+	  return DWARF_CB_OK;
+
+	case DW_AT_str_offsets_base:
+	  {
+	    bool stroffbase = notice_listptr (section_str, &known_stroffbases,
+					      cbargs->addrsize,
+					      cbargs->offset_size,
+					      cbargs->cu, num, attr);
+	    if (!cbargs->silent)
+	      printf ("           %*s%-20s (%s) str offsets base [%6"
+		      PRIxMAX "]%s\n",
+		      (int) (level * 2), "", dwarf_attr_name (attr),
+		      dwarf_form_name (form), (uintmax_t) num,
+		      stroffbase ? "" : " <WARNING offset too big>");
+	  }
+	  return DWARF_CB_OK;
+
+	case DW_AT_language:
+	  valuestr = dwarf_lang_name (num);
+	  break;
+	case DW_AT_encoding:
+	  valuestr = dwarf_encoding_name (num);
+	  break;
+	case DW_AT_accessibility:
+	  valuestr = dwarf_access_name (num);
+	  break;
+	case DW_AT_defaulted:
+	  valuestr = dwarf_defaulted_name (num);
+	  break;
+	case DW_AT_visibility:
+	  valuestr = dwarf_visibility_name (num);
+	  break;
+	case DW_AT_virtuality:
+	  valuestr = dwarf_virtuality_name (num);
+	  break;
+	case DW_AT_identifier_case:
+	  valuestr = dwarf_identifier_case_name (num);
+	  break;
+	case DW_AT_calling_convention:
+	  valuestr = dwarf_calling_convention_name (num);
+	  break;
+	case DW_AT_inline:
+	  valuestr = dwarf_inline_name (num);
+	  break;
+	case DW_AT_ordering:
+	  valuestr = dwarf_ordering_name (num);
+	  break;
+	case DW_AT_decl_file:
+	case DW_AT_call_file:
+	  {
+	    if (cbargs->silent)
+	      break;
+
+	    /* Try to get the actual file, the current interface only
+	       gives us full paths, but we only want to show the file
+	       name for now.  */
+	    Dwarf_Die cudie;
+	    if (dwarf_cu_die (cbargs->cu, &cudie,
+			      NULL, NULL, NULL, NULL, NULL, NULL) != NULL)
+	      {
+		Dwarf_Files *files;
+		size_t nfiles;
+		if (dwarf_getsrcfiles (&cudie, &files, &nfiles) == 0)
+		  {
+		    valuestr = dwarf_filesrc (files, num, NULL, NULL);
+		    if (valuestr != NULL)
+		      {
+			char *filename = strrchr (valuestr, '/');
+			if (filename != NULL)
+			  valuestr = filename + 1;
+		      }
+		    else
+		      error (0, 0, _("invalid file (%" PRId64 "): %s"),
+			     num, dwarf_errmsg (-1));
+		  }
+		else
+		  error (0, 0, _("no srcfiles for CU [%" PRIx64 "]"),
+			 dwarf_dieoffset (&cudie));
+	      }
+	    else
+	     error (0, 0, _("couldn't get DWARF CU: %s"),
+		    dwarf_errmsg (-1));
+	    if (valuestr == NULL)
+	      valuestr = "???";
+	  }
+	  break;
+	case DW_AT_GNU_dwo_id:
+	  as_hex_id = true;
+	  break;
+
+	default:
+	  /* Nothing.  */
+	  break;
+	}
+
+      if (cbargs->silent)
+	break;
+
+      /* When highpc is in constant form it is relative to lowpc.
+	 In that case also show the address.  */
+      Dwarf_Addr highpc;
+      if (attr == DW_AT_high_pc && dwarf_highpc (die, &highpc) == 0)
+	{
+	  printf ("           %*s%-20s (%s) %" PRIuMAX " (",
+		  (int) (level * 2), "", dwarf_attr_name (attr),
+		  dwarf_form_name (form), (uintmax_t) num);
+	  print_dwarf_addr (cbargs->dwflmod, cbargs->addrsize, highpc, highpc);
+	  printf (")\n");
+	}
+      else
+	{
+	  if (as_hex_id)
+	    {
+	      printf ("           %*s%-20s (%s) 0x%.16" PRIx64 "\n",
+		      (int) (level * 2), "", dwarf_attr_name (attr),
+		      dwarf_form_name (form), num);
+	    }
+	  else
+	    {
+	      Dwarf_Sword snum = 0;
+	      bool is_signed;
+	      int bytes = 0;
+	      if (attr == DW_AT_const_value)
+		die_type_sign_bytes (die, &is_signed, &bytes);
+	      else
+		is_signed = (form == DW_FORM_sdata
+			     || form == DW_FORM_implicit_const);
+
+	      if (is_signed)
+		if (unlikely (dwarf_formsdata (attrp, &snum) != 0))
+		  goto attrval_out;
+
+	      if (valuestr == NULL)
+		{
+		  printf ("           %*s%-20s (%s) ",
+			  (int) (level * 2), "", dwarf_attr_name (attr),
+			  dwarf_form_name (form));
+		}
+	      else
+		{
+		  printf ("           %*s%-20s (%s) %s (",
+			  (int) (level * 2), "", dwarf_attr_name (attr),
+			  dwarf_form_name (form), valuestr);
+		}
+
+	      switch (bytes)
+		{
+		case 1:
+		  if (is_signed)
+		    printf ("%" PRId8, (int8_t) snum);
+		  else
+		    printf ("%" PRIu8, (uint8_t) num);
+		  break;
+
+		case 2:
+		  if (is_signed)
+		    printf ("%" PRId16, (int16_t) snum);
+		  else
+		    printf ("%" PRIu16, (uint16_t) num);
+		  break;
+
+		case 4:
+		  if (is_signed)
+		    printf ("%" PRId32, (int32_t) snum);
+		  else
+		    printf ("%" PRIu32, (uint32_t) num);
+		  break;
+
+		case 8:
+		  if (is_signed)
+		    printf ("%" PRId64, (int64_t) snum);
+		  else
+		    printf ("%" PRIu64, (uint64_t) num);
+		  break;
+
+		default:
+		  if (is_signed)
+		    printf ("%" PRIdMAX, (intmax_t) snum);
+		  else
+		    printf ("%" PRIuMAX, (uintmax_t) num);
+		  break;
+		}
+
+	      /* Make clear if we switched from a signed encoding to
+		 an unsigned value.  */
+	      if (attr == DW_AT_const_value
+		  && (form == DW_FORM_sdata || form == DW_FORM_implicit_const)
+		  && !is_signed)
+		printf (" (%" PRIdMAX ")", (intmax_t) num);
+
+	      if (valuestr == NULL)
+		printf ("\n");
+	      else
+		printf (")\n");
+	    }
+	}
+      break;
+
+    case DW_FORM_flag:
+      if (cbargs->silent)
+	break;
+      bool flag;
+      if (unlikely (dwarf_formflag (attrp, &flag) != 0))
+	goto attrval_out;
+
+      printf ("           %*s%-20s (%s) %s\n",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), flag ? yes_str : no_str);
+      break;
+
+    case DW_FORM_flag_present:
+      if (cbargs->silent)
+	break;
+      printf ("           %*s%-20s (%s) %s\n",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form), yes_str);
+      break;
+
+    case DW_FORM_exprloc:
+    case DW_FORM_block4:
+    case DW_FORM_block2:
+    case DW_FORM_block1:
+    case DW_FORM_block:
+    case DW_FORM_data16: /* DWARF5 calls this a constant class.  */
+      if (cbargs->silent)
+	break;
+      Dwarf_Block block;
+      if (unlikely (dwarf_formblock (attrp, &block) != 0))
+	goto attrval_out;
+
+      printf ("           %*s%-20s (%s) ",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form));
+
+      switch (attr)
+	{
+	default:
+	  if (form != DW_FORM_exprloc)
+	    {
+	      print_block (block.length, block.data);
+	      break;
+	    }
+	  FALLTHROUGH;
+
+	case DW_AT_location:
+	case DW_AT_data_location:
+	case DW_AT_data_member_location:
+	case DW_AT_vtable_elem_location:
+	case DW_AT_string_length:
+	case DW_AT_use_location:
+	case DW_AT_frame_base:
+	case DW_AT_return_addr:
+	case DW_AT_static_link:
+	case DW_AT_allocated:
+	case DW_AT_associated:
+	case DW_AT_bit_size:
+	case DW_AT_bit_offset:
+	case DW_AT_bit_stride:
+	case DW_AT_byte_size:
+	case DW_AT_byte_stride:
+	case DW_AT_count:
+	case DW_AT_lower_bound:
+	case DW_AT_upper_bound:
+	case DW_AT_GNU_call_site_value:
+	case DW_AT_GNU_call_site_data_value:
+	case DW_AT_GNU_call_site_target:
+	case DW_AT_GNU_call_site_target_clobbered:
+	  if (form == DW_FORM_exprloc
+	      || (form != DW_FORM_data16
+		  && attrp->cu->version < 4)) /* blocks were expressions.  */
+	    {
+	      putchar ('\n');
+	      print_ops (cbargs->dwflmod, cbargs->dbg,
+			 12 + level * 2, 12 + level * 2,
+			 cbargs->version, cbargs->addrsize, cbargs->offset_size,
+			 attrp->cu, block.length, block.data);
+	    }
+	  else
+	    print_block (block.length, block.data);
+	  break;
+
+	case DW_AT_discr_list:
+	  if (block.length == 0)
+	    puts ("<default>");
+	  else if (form != DW_FORM_data16)
+	    {
+	      const unsigned char *readp = block.data;
+	      const unsigned char *readendp = readp + block.length;
+
+	      /* See if we are dealing with a signed or unsigned
+		 values.  If the parent of this variant DIE is a
+		 variant_part then it will either have a discriminant
+		 which points to the member which type is the
+		 discriminant type.  Or the variant_part itself has a
+		 type representing the discriminant.  */
+	      bool is_signed = false;
+	      if (level > 0)
+		{
+		  Dwarf_Die *parent = &cbargs->dies[level - 1];
+		  if (dwarf_tag (die) == DW_TAG_variant
+		      && dwarf_tag (parent) == DW_TAG_variant_part)
+		    {
+		      Dwarf_Die member;
+		      Dwarf_Attribute discr_attr;
+		      int bytes;
+		      if (dwarf_formref_die (dwarf_attr (parent,
+							 DW_AT_discr,
+							 &discr_attr),
+					     &member) != NULL)
+			die_type_sign_bytes (&member, &is_signed, &bytes);
+		      else
+			die_type_sign_bytes (parent, &is_signed, &bytes);
+		    }
+		}
+	      while (readp < readendp)
+		{
+		  int d = (int) *readp++;
+		  printf ("%s ", dwarf_discr_list_name (d));
+		  if (readp >= readendp)
+		    goto attrval_out;
+
+		  Dwarf_Word val;
+		  Dwarf_Sword sval;
+		  if (d == DW_DSC_label)
+		    {
+		      if (is_signed)
+			{
+			  get_sleb128 (sval, readp, readendp);
+			  printf ("%" PRId64 "", sval);
+			}
+		      else
+			{
+			  get_uleb128 (val, readp, readendp);
+			  printf ("%" PRIu64 "", val);
+			}
+		    }
+		  else if (d == DW_DSC_range)
+		    {
+		      if (is_signed)
+			{
+			  get_sleb128 (sval, readp, readendp);
+			  printf ("%" PRId64 "..", sval);
+			  if (readp >= readendp)
+			    goto attrval_out;
+			  get_sleb128 (sval, readp, readendp);
+			  printf ("%" PRId64 "", sval);
+			}
+		      else
+			{
+			  get_uleb128 (val, readp, readendp);
+			  printf ("%" PRIu64 "..", val);
+			  if (readp >= readendp)
+			    goto attrval_out;
+			  get_uleb128 (val, readp, readendp);
+			  printf ("%" PRIu64 "", val);
+			}
+		    }
+		  else
+		    {
+		      print_block (readendp - readp, readp);
+		      break;
+		    }
+		  if (readp < readendp)
+		    printf (", ");
+		}
+	      putchar ('\n');
+	    }
+	  else
+	    print_block (block.length, block.data);
+	  break;
+	}
+      break;
+
+    default:
+      if (cbargs->silent)
+	break;
+      printf ("           %*s%-20s (%s) ???\n",
+	      (int) (level * 2), "", dwarf_attr_name (attr),
+	      dwarf_form_name (form));
+      break;
+    }
+
+  return DWARF_CB_OK;
+}
+
+static void
+print_debug_units (Dwfl_Module *dwflmod,
+		   Ebl *ebl, GElf_Ehdr *ehdr __attribute__ ((unused)),
+		   Elf_Scn *scn, GElf_Shdr *shdr,
+		   Dwarf *dbg, bool debug_types)
+{
+  const bool silent = !(print_debug_sections & section_info) && !debug_types;
+  const char *secname = section_name (ebl, shdr);
+
+  /* Check section actually exists.  */
+  if (!silent)
+    if (get_debug_elf_data (dbg, ebl,
+			    debug_types ? IDX_debug_types : IDX_debug_info,
+			    scn) == NULL)
+      return;
+
+  if (!silent)
+    printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n [Offset]\n"),
+	    elf_ndxscn (scn), secname, (uint64_t) shdr->sh_offset);
+
+  /* If the section is empty we don't have to do anything.  */
+  if (!silent && shdr->sh_size == 0)
+    return;
+
+  int maxdies = 20;
+  Dwarf_Die *dies = xmalloc (maxdies * sizeof (Dwarf_Die));
+
+  /* New compilation unit.  */
+  Dwarf_Half version;
+
+  Dwarf_Die result;
+  Dwarf_Off abbroffset;
+  uint8_t addrsize;
+  uint8_t offsize;
+  uint64_t unit_id;
+  Dwarf_Off subdie_off;
+
+  int unit_res;
+  Dwarf_CU *cu;
+  Dwarf_CU cu_mem;
+  uint8_t unit_type;
+  Dwarf_Die cudie;
+
+  /* We cheat a little because we want to see only the CUs from .debug_info
+     or .debug_types.  We know the Dwarf_CU struct layout.  Set it up at
+     the end of .debug_info if we want .debug_types only.  Check the returned
+     Dwarf_CU is still in the expected section.  */
+  if (debug_types)
+    {
+      cu_mem.dbg = dbg;
+      cu_mem.end = dbg->sectiondata[IDX_debug_info]->d_size;
+      cu_mem.sec_idx = IDX_debug_info;
+      cu = &cu_mem;
+    }
+  else
+    cu = NULL;
+
+ next_cu:
+  unit_res = dwarf_get_units (dbg, cu, &cu, &version, &unit_type,
+			      &cudie, NULL);
+  if (unit_res == 1)
+    goto do_return;
+
+  if (unit_res == -1)
+    {
+      if (!silent)
+	error (0, 0, _("cannot get next unit: %s"), dwarf_errmsg (-1));
+      goto do_return;
+    }
+
+  if (cu->sec_idx != (size_t) (debug_types ? IDX_debug_types : IDX_debug_info))
+    goto do_return;
+
+  dwarf_cu_die (cu, &result, NULL, &abbroffset, &addrsize, &offsize,
+		&unit_id, &subdie_off);
+
+  if (!silent)
+    {
+      Dwarf_Off offset = cu->start;
+      if (debug_types && version < 5)
+	{
+	  Dwarf_Die typedie;
+	  Dwarf_Off dieoffset;
+	  dieoffset = dwarf_dieoffset (dwarf_offdie_types (dbg, cu->start
+							   + subdie_off,
+							   &typedie));
+	  printf (_(" Type unit at offset %" PRIu64 ":\n"
+			   " Version: %" PRIu16
+			   ", Abbreviation section offset: %" PRIu64
+			   ", Address size: %" PRIu8
+			   ", Offset size: %" PRIu8
+			   "\n Type signature: %#" PRIx64
+			   ", Type offset: %#" PRIx64 " [%" PRIx64 "]\n"),
+		  (uint64_t) offset, version, abbroffset, addrsize, offsize,
+		  unit_id, (uint64_t) subdie_off, dieoffset);
+	}
+      else
+	{
+	  printf (_(" Compilation unit at offset %" PRIu64 ":\n"
+			   " Version: %" PRIu16
+			   ", Abbreviation section offset: %" PRIu64
+			   ", Address size: %" PRIu8
+			   ", Offset size: %" PRIu8 "\n"),
+		  (uint64_t) offset, version, abbroffset, addrsize, offsize);
+
+	  if (version >= 5 || (unit_type != DW_UT_compile
+			       && unit_type != DW_UT_partial))
+	    {
+	      printf (_(" Unit type: %s (%" PRIu8 ")"),
+			       dwarf_unit_name (unit_type), unit_type);
+	      if (unit_type == DW_UT_type
+		  || unit_type == DW_UT_skeleton
+		  || unit_type == DW_UT_split_compile
+		  || unit_type == DW_UT_split_type)
+		printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
+	      if (unit_type == DW_UT_type
+		  || unit_type == DW_UT_split_type)
+		{
+		  Dwarf_Die typedie;
+		  Dwarf_Off dieoffset;
+		  dwarf_cu_info (cu, NULL, NULL, NULL, &typedie,
+				 NULL, NULL, NULL);
+		  dieoffset = dwarf_dieoffset (&typedie);
+		  printf (", Unit DIE off: %#" PRIx64 " [%" PRIx64 "]",
+			  subdie_off, dieoffset);
+		}
+	      printf ("\n");
+	    }
+	}
+    }
+
+  if (version < 2 || version > 5
+      || unit_type < DW_UT_compile || unit_type > DW_UT_split_type)
+    {
+      if (!silent)
+	error (0, 0, _("unknown version (%d) or unit type (%d)"),
+	       version, unit_type);
+      goto next_cu;
+    }
+
+  struct attrcb_args args =
+    {
+      .dwflmod = dwflmod,
+      .silent = silent,
+      .version = version,
+      .addrsize = addrsize,
+      .offset_size = offsize
+    };
+
+  bool is_split = false;
+  int level = 0;
+  dies[0] = cudie;
+  args.cu = dies[0].cu;
+  args.dbg = dbg;
+  args.is_split = is_split;
+
+  /* We might return here again for the split CU subdie.  */
+  do_cu:
+  do
+    {
+      Dwarf_Off offset = dwarf_dieoffset (&dies[level]);
+      if (unlikely (offset == (Dwarf_Off) -1))
+	{
+	  if (!silent)
+	    error (0, 0, _("cannot get DIE offset: %s"),
+		   dwarf_errmsg (-1));
+	  goto do_return;
+	}
+
+      int tag = dwarf_tag (&dies[level]);
+      if (unlikely (tag == DW_TAG_invalid))
+	{
+	  if (!silent)
+	    error (0, 0, _("cannot get tag of DIE at offset [%" PRIx64
+				  "] in section '%s': %s"),
+		   (uint64_t) offset, secname, dwarf_errmsg (-1));
+	  goto do_return;
+	}
+
+      if (!silent)
+	{
+	  unsigned int code = dwarf_getabbrevcode (dies[level].abbrev);
+	  if (is_split)
+	    printf (" {%6" PRIx64 "}  ", (uint64_t) offset);
+	  else
+	    printf (" [%6" PRIx64 "]  ", (uint64_t) offset);
+	  printf ("%*s%-20s abbrev: %u\n", (int) (level * 2), "",
+		  dwarf_tag_name (tag), code);
+	}
+
+      /* Print the attribute values.  */
+      args.level = level;
+      args.dies = dies;
+      (void) dwarf_getattrs (&dies[level], attr_callback, &args, 0);
+
+      /* Make room for the next level's DIE.  */
+      if (level + 1 == maxdies)
+	dies = xrealloc (dies, (maxdies += 10) * sizeof (Dwarf_Die));
+
+      int res = dwarf_child (&dies[level], &dies[level + 1]);
+      if (res > 0)
+	{
+	  while ((res = dwarf_siblingof (&dies[level], &dies[level])) == 1)
+	    if (level-- == 0)
+	      break;
+
+	  if (unlikely (res == -1))
+	    {
+	      if (!silent)
+		error (0, 0, _("cannot get next DIE: %s\n"),
+		       dwarf_errmsg (-1));
+	      goto do_return;
+	    }
+	}
+      else if (unlikely (res < 0))
+	{
+	  if (!silent)
+	    error (0, 0, _("cannot get next DIE: %s"),
+		   dwarf_errmsg (-1));
+	  goto do_return;
+	}
+      else
+	++level;
+    }
+  while (level >= 0);
+
+  /* We might want to show the split compile unit if this was a skeleton.
+     We need to scan it if we are requesting printing .debug_ranges for
+     DWARF4 since GNU DebugFission uses "offsets" into the main ranges
+     section.  */
+  if (unit_type == DW_UT_skeleton
+      && ((!silent && show_split_units)
+	  || (version < 5 && (print_debug_sections & section_ranges) != 0)))
+    {
+      Dwarf_Die subdie;
+      if (dwarf_cu_info (cu, NULL, NULL, NULL, &subdie, NULL, NULL, NULL) != 0
+	  || dwarf_tag (&subdie) == DW_TAG_invalid)
+	{
+	  if (!silent)
+	    {
+	      Dwarf_Attribute dwo_at;
+	      const char *dwo_name =
+		(dwarf_formstring (dwarf_attr (&cudie, DW_AT_dwo_name,
+					       &dwo_at))
+		 ?: (dwarf_formstring (dwarf_attr (&cudie, DW_AT_GNU_dwo_name,
+						   &dwo_at))
+		     ?: "<unknown>"));
+	      fprintf (stderr,
+		       "Could not find split unit '%s', id: %" PRIx64 "\n",
+		       dwo_name, unit_id);
+	    }
+	}
+      else
+	{
+	  Dwarf_CU *split_cu = subdie.cu;
+	  dwarf_cu_die (split_cu, &result, NULL, &abbroffset,
+			&addrsize, &offsize, &unit_id, &subdie_off);
+	  Dwarf_Off offset = cu->start;
+
+	  if (!silent)
+	    {
+	      printf (_(" Split compilation unit at offset %"
+			       PRIu64 ":\n"
+			       " Version: %" PRIu16
+			       ", Abbreviation section offset: %" PRIu64
+			       ", Address size: %" PRIu8
+			       ", Offset size: %" PRIu8 "\n"),
+		      (uint64_t) offset, version, abbroffset,
+		      addrsize, offsize);
+	      printf (_(" Unit type: %s (%" PRIu8 ")"),
+		      dwarf_unit_name (unit_type), unit_type);
+	      printf (", Unit id: 0x%.16" PRIx64 "", unit_id);
+	      printf ("\n");
+	    }
+
+	  unit_type = DW_UT_split_compile;
+	  is_split = true;
+	  level = 0;
+	  dies[0] = subdie;
+	  args.cu = dies[0].cu;
+	  args.dbg = split_cu->dbg;
+	  args.is_split = is_split;
+	  goto do_cu;
+	}
+    }
+
+  /* And again... */
+  goto next_cu;
+
+ do_return:
+  free (dies);
+}
+
+static void
+print_debug_info_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, false);
+}
+
+static void
+print_debug_types_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  print_debug_units (dwflmod, ebl, ehdr, scn, shdr, dbg, true);
+}
+
+
+static void
+print_decoded_line_section (Dwfl_Module *dwflmod, Ebl *ebl,
+			    GElf_Ehdr *ehdr __attribute__ ((unused)),
+			    Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  size_t address_size
+    = elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+
+  Dwarf_Lines *lines;
+  size_t nlines;
+  Dwarf_Off off, next_off = 0;
+  Dwarf_CU *cu = NULL;
+  while (dwarf_next_lines (dbg, off = next_off, &next_off, &cu, NULL, NULL,
+			   &lines, &nlines) == 0)
+    {
+      Dwarf_Die cudie;
+      if (cu != NULL && dwarf_cu_info (cu, NULL, NULL, &cudie,
+				       NULL, NULL, NULL, NULL) == 0)
+	printf (" CU [%" PRIx64 "] %s\n",
+		dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
+      else
+	{
+	  /* DWARF5 lines can be independent of any CU, but they probably
+	     are used by some CU.  Determine the CU this block is for.  */
+	  Dwarf_Off cuoffset;
+	  Dwarf_Off ncuoffset = 0;
+	  size_t hsize;
+	  while (dwarf_nextcu (dbg, cuoffset = ncuoffset, &ncuoffset, &hsize,
+			       NULL, NULL, NULL) == 0)
+	    {
+	      if (dwarf_offdie (dbg, cuoffset + hsize, &cudie) == NULL)
+		continue;
+	      Dwarf_Attribute stmt_list;
+	      if (dwarf_attr (&cudie, DW_AT_stmt_list, &stmt_list) == NULL)
+		continue;
+	      Dwarf_Word lineoff;
+	      if (dwarf_formudata (&stmt_list, &lineoff) != 0)
+		continue;
+	      if (lineoff == off)
+		{
+		  /* Found the CU.  */
+		  cu = cudie.cu;
+		  break;
+		}
+	    }
+
+	  if (cu != NULL)
+	    printf (" CU [%" PRIx64 "] %s\n",
+		    dwarf_dieoffset (&cudie), dwarf_diename (&cudie));
+	  else
+	    printf (" No CU\n");
+	}
+
+      printf ("  line:col SBPE* disc isa op address"
+	      " (Statement Block Prologue Epilogue *End)\n");
+      const char *last_file = "";
+      for (size_t n = 0; n < nlines; n++)
+	{
+	  Dwarf_Line *line = dwarf_onesrcline (lines, n);
+	  if (line == NULL)
+	    {
+	      printf ("  dwarf_onesrcline: %s\n", dwarf_errmsg (-1));
+	      continue;
+	    }
+	  Dwarf_Word mtime, length;
+	  const char *file = dwarf_linesrc (line, &mtime, &length);
+	  if (file == NULL)
+	    {
+	      printf ("  <%s> (mtime: ?, length: ?)\n", dwarf_errmsg (-1));
+	      last_file = "";
+	    }
+	  else if (strcmp (last_file, file) != 0)
+	    {
+	      printf ("  %s (mtime: %" PRIu64 ", length: %" PRIu64 ")\n",
+		      file, mtime, length);
+	      last_file = file;
+	    }
+
+	  int lineno, colno;
+	  bool statement, endseq, block, prologue_end, epilogue_begin;
+	  unsigned int lineop, isa, disc;
+	  Dwarf_Addr address;
+	  dwarf_lineaddr (line, &address);
+	  dwarf_lineno (line, &lineno);
+	  dwarf_linecol (line, &colno);
+	  dwarf_lineop_index (line, &lineop);
+	  dwarf_linebeginstatement (line, &statement);
+	  dwarf_lineendsequence (line, &endseq);
+	  dwarf_lineblock (line, &block);
+	  dwarf_lineprologueend (line, &prologue_end);
+	  dwarf_lineepiloguebegin (line, &epilogue_begin);
+	  dwarf_lineisa (line, &isa);
+	  dwarf_linediscriminator (line, &disc);
+
+	  /* End sequence is special, it is one byte past.  */
+	  printf ("  %4d:%-3d %c%c%c%c%c %4d %3d %2d ",
+		  lineno, colno,
+		  (statement ? 'S' : ' '),
+		  (block ? 'B' : ' '),
+		  (prologue_end ? 'P' : ' '),
+		  (epilogue_begin ? 'E' : ' '),
+		  (endseq ? '*' : ' '),
+		  disc, isa, lineop);
+	  print_dwarf_addr (dwflmod, address_size,
+			    address - (endseq ? 1 : 0), address);
+	  printf ("\n");
+
+	  if (endseq)
+	    printf("\n");
+	}
+    }
+}
+
+
+/* Print the value of a form.
+   Returns new value of readp, or readendp on failure.  */
+static const unsigned char *
+print_form_data (Dwarf *dbg, int form, const unsigned char *readp,
+		 const unsigned char *readendp, unsigned int offset_len,
+		 Dwarf_Off str_offsets_base)
+{
+  Dwarf_Word val;
+  unsigned char *endp;
+  Elf_Data *data;
+  char *str;
+  switch (form)
+    {
+    case DW_FORM_data1:
+      if (readendp - readp < 1)
+	{
+	invalid_data:
+	  error (0, 0, "invalid data");
+	  return readendp;
+	}
+      val = *readp++;
+      printf (" %" PRIx8, (unsigned int) val);
+      break;
+
+    case DW_FORM_data2:
+      if (readendp - readp < 2)
+	goto invalid_data;
+      val = read_2ubyte_unaligned_inc (dbg, readp);
+      printf(" %" PRIx16, (unsigned int) val);
+      break;
+
+    case DW_FORM_data4:
+      if (readendp - readp < 4)
+	goto invalid_data;
+      val = read_4ubyte_unaligned_inc (dbg, readp);
+      printf (" %" PRIx32, (unsigned int) val);
+      break;
+
+    case DW_FORM_data8:
+      if (readendp - readp < 8)
+	goto invalid_data;
+      val = read_8ubyte_unaligned_inc (dbg, readp);
+      printf (" %" PRIx64, val);
+      break;
+
+    case DW_FORM_sdata:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      get_sleb128 (val, readp, readendp);
+      printf (" %" PRIx64, val);
+      break;
+
+    case DW_FORM_udata:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      get_uleb128 (val, readp, readendp);
+      printf (" %" PRIx64, val);
+      break;
+
+    case DW_FORM_block:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      get_uleb128 (val, readp, readendp);
+      if ((size_t) (readendp - readp) < val)
+	goto invalid_data;
+      print_bytes (val, readp);
+      readp += val;
+      break;
+
+    case DW_FORM_block1:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      val = *readp++;
+      if ((size_t) (readendp - readp) < val)
+	goto invalid_data;
+      print_bytes (val, readp);
+      readp += val;
+      break;
+
+    case DW_FORM_block2:
+      if (readendp - readp < 2)
+	goto invalid_data;
+      val = read_2ubyte_unaligned_inc (dbg, readp);
+      if ((size_t) (readendp - readp) < val)
+	goto invalid_data;
+      print_bytes (val, readp);
+      readp += val;
+      break;
+
+    case DW_FORM_block4:
+      if (readendp - readp < 4)
+	goto invalid_data;
+      val = read_4ubyte_unaligned_inc (dbg, readp);
+      if ((size_t) (readendp - readp) < val)
+	goto invalid_data;
+      print_bytes (val, readp);
+      readp += val;
+      break;
+
+    case DW_FORM_data16:
+      if (readendp - readp < 16)
+	goto invalid_data;
+      print_bytes (16, readp);
+      readp += 16;
+      break;
+
+    case DW_FORM_flag:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      val = *readp++;
+      printf ("%s", val != 0 ? yes_str : no_str);
+      break;
+
+    case DW_FORM_string:
+      endp = memchr (readp, '\0', readendp - readp);
+      if (endp == NULL)
+	goto invalid_data;
+      printf ("%s", readp);
+      readp = endp + 1;
+      break;
+
+    case DW_FORM_strp:
+    case DW_FORM_line_strp:
+    case DW_FORM_strp_sup:
+      if ((size_t) (readendp - readp) < offset_len)
+	goto invalid_data;
+      if (offset_len == 8)
+	val = read_8ubyte_unaligned_inc (dbg, readp);
+      else
+	val = read_4ubyte_unaligned_inc (dbg, readp);
+      if (form == DW_FORM_strp)
+	data = dbg->sectiondata[IDX_debug_str];
+      else if (form == DW_FORM_line_strp)
+	data = dbg->sectiondata[IDX_debug_line_str];
+      else /* form == DW_FORM_strp_sup */
+	{
+	  Dwarf *alt = dwarf_getalt (dbg);
+	  data = alt != NULL ? alt->sectiondata[IDX_debug_str] : NULL;
+	}
+      if (data == NULL || val >= data->d_size
+	  || memchr (data->d_buf + val, '\0', data->d_size - val) == NULL)
+	str = "???";
+      else
+	str = (char *) data->d_buf + val;
+      printf ("%s (%" PRIu64 ")", str, val);
+      break;
+
+    case DW_FORM_sec_offset:
+      if ((size_t) (readendp - readp) < offset_len)
+	goto invalid_data;
+      if (offset_len == 8)
+	val = read_8ubyte_unaligned_inc (dbg, readp);
+      else
+	val = read_4ubyte_unaligned_inc (dbg, readp);
+      printf ("[%" PRIx64 "]", val);
+      break;
+
+    case DW_FORM_strx:
+    case DW_FORM_GNU_str_index:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      get_uleb128 (val, readp, readendp);
+    strx_val:
+      data = dbg->sectiondata[IDX_debug_str_offsets];
+      if (data == NULL
+	  || data->d_size - str_offsets_base < val)
+	str = "???";
+      else
+	{
+	  const unsigned char *strreadp = data->d_buf + str_offsets_base + val;
+	  const unsigned char *strreadendp = data->d_buf + data->d_size;
+	  if ((size_t) (strreadendp - strreadp) < offset_len)
+	    str = "???";
+	  else
+	    {
+	      Dwarf_Off idx;
+	      if (offset_len == 8)
+		idx = read_8ubyte_unaligned (dbg, strreadp);
+	      else
+		idx = read_4ubyte_unaligned (dbg, strreadp);
+
+	      data = dbg->sectiondata[IDX_debug_str];
+	      if (data == NULL || idx >= data->d_size
+		  || memchr (data->d_buf + idx, '\0',
+			     data->d_size - idx) == NULL)
+		str = "???";
+	      else
+		str = (char *) data->d_buf + idx;
+	    }
+	}
+      printf ("%s (%" PRIu64 ")", str, val);
+      break;
+
+    case DW_FORM_strx1:
+      if (readendp - readp < 1)
+	goto invalid_data;
+      val = *readp++;
+      goto strx_val;
+
+    case DW_FORM_strx2:
+      if (readendp - readp < 2)
+	goto invalid_data;
+      val = read_2ubyte_unaligned_inc (dbg, readp);
+      goto strx_val;
+
+    case DW_FORM_strx3:
+      if (readendp - readp < 3)
+	goto invalid_data;
+      val = read_3ubyte_unaligned_inc (dbg, readp);
+      goto strx_val;
+
+    case DW_FORM_strx4:
+      if (readendp - readp < 4)
+	goto invalid_data;
+      val = read_4ubyte_unaligned_inc (dbg, readp);
+      goto strx_val;
+
+    default:
+      error (0, 0, _("unknown form: %s"), dwarf_form_name (form));
+      return readendp;
+    }
+
+  return readp;
+}
+
+/* Only used via run_advance_pc() macro */
+static inline void
+run_advance_pc (unsigned int op_advance,
+                unsigned int minimum_instr_len,
+                unsigned int max_ops_per_instr,
+                unsigned int *op_addr_advance,
+                Dwarf_Word *address,
+                unsigned int *op_index)
+{
+  const unsigned int advanced_op_index = (*op_index) + op_advance;
+
+  *op_addr_advance = minimum_instr_len * (advanced_op_index
+                                         / max_ops_per_instr);
+  *address = *address + *op_addr_advance;
+  *op_index = advanced_op_index % max_ops_per_instr;
+}
+
+static void
+print_debug_line_section (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr,
+			  Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  if (decodedline)
+    {
+      print_decoded_line_section (dwflmod, ebl, ehdr, scn, shdr, dbg);
+      return;
+    }
+
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_line, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  if (shdr->sh_size == 0)
+    return;
+
+  /* There is no functionality in libdw to read the information in the
+     way it is represented here.  Hardcode the decoder.  */
+
+  const unsigned char *linep = (const unsigned char *) data->d_buf;
+  const unsigned char *lineendp;
+
+  while (linep
+	 < (lineendp = (const unsigned char *) data->d_buf + data->d_size))
+    {
+      size_t start_offset = linep - (const unsigned char *) data->d_buf;
+
+      printf (_("\nTable at offset %zu:\n"), start_offset);
+
+      if (unlikely (linep + 4 > lineendp))
+	goto invalid_data;
+      Dwarf_Word unit_length = read_4ubyte_unaligned_inc (dbg, linep);
+      unsigned int length = 4;
+      if (unlikely (unit_length == 0xffffffff))
+	{
+	  if (unlikely (linep + 8 > lineendp))
+	    {
+	    invalid_data:
+	      error (0, 0, _("invalid data in section [%zu] '%s'"),
+		     elf_ndxscn (scn), section_name (ebl, shdr));
+	      return;
+	    }
+	  unit_length = read_8ubyte_unaligned_inc (dbg, linep);
+	  length = 8;
+	}
+
+      /* Check whether we have enough room in the section.  */
+      if (unlikely (unit_length > (size_t) (lineendp - linep)))
+	goto invalid_data;
+      lineendp = linep + unit_length;
+
+      /* The next element of the header is the version identifier.  */
+      if ((size_t) (lineendp - linep) < 2)
+	goto invalid_data;
+      uint_fast16_t version = read_2ubyte_unaligned_inc (dbg, linep);
+
+      size_t address_size
+	= elf_getident (ebl->elf, NULL)[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+      unsigned char segment_selector_size = 0;
+      if (version > 4)
+	{
+	  if ((size_t) (lineendp - linep) < 2)
+	    goto invalid_data;
+	  address_size = *linep++;
+	  segment_selector_size = *linep++;
+	}
+
+      /* Next comes the header length.  */
+      Dwarf_Word header_length;
+      if (length == 4)
+	{
+	  if ((size_t) (lineendp - linep) < 4)
+	    goto invalid_data;
+	  header_length = read_4ubyte_unaligned_inc (dbg, linep);
+	}
+      else
+	{
+	  if ((size_t) (lineendp - linep) < 8)
+	    goto invalid_data;
+	  header_length = read_8ubyte_unaligned_inc (dbg, linep);
+	}
+
+      const unsigned char *header_start = linep;
+
+      /* Next the minimum instruction length.  */
+      if ((size_t) (lineendp - linep) < 1)
+	goto invalid_data;
+      uint_fast8_t minimum_instr_len = *linep++;
+
+      /* Next the maximum operations per instruction, in version 4 format.  */
+      uint_fast8_t max_ops_per_instr;
+      if (version < 4)
+	max_ops_per_instr = 1;
+      else
+	{
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  max_ops_per_instr = *linep++;
+	}
+
+      /* We need at least 4 more bytes.  */
+      if ((size_t) (lineendp - linep) < 4)
+	goto invalid_data;
+
+      /* Then the flag determining the default value of the is_stmt
+	 register.  */
+      uint_fast8_t default_is_stmt = *linep++;
+
+      /* Now the line base.  */
+      int_fast8_t line_base = *linep++;
+
+      /* And the line range.  */
+      uint_fast8_t line_range = *linep++;
+
+      /* The opcode base.  */
+      uint_fast8_t opcode_base = *linep++;
+
+      /* Print what we got so far.  */
+      printf (_("\n"
+		       " Length:                         %" PRIu64 "\n"
+		       " DWARF version:                  %" PRIuFAST16 "\n"
+		       " Prologue length:                %" PRIu64 "\n"
+		       " Address size:                   %zd\n"
+		       " Segment selector size:          %zd\n"
+		       " Min instruction length:         %" PRIuFAST8 "\n"
+		       " Max operations per instruction: %" PRIuFAST8 "\n"
+		       " Initial value if 'is_stmt':     %" PRIuFAST8 "\n"
+		       " Line base:                      %" PRIdFAST8 "\n"
+		       " Line range:                     %" PRIuFAST8 "\n"
+		       " Opcode base:                    %" PRIuFAST8 "\n"
+		       "\n"
+		       "Opcodes:\n"),
+	      (uint64_t) unit_length, version, (uint64_t) header_length,
+	      address_size, (size_t) segment_selector_size,
+	      minimum_instr_len, max_ops_per_instr,
+	      default_is_stmt, line_base,
+	      line_range, opcode_base);
+
+      if (version < 2 || version > 5)
+	{
+	  error (0, 0, _("cannot handle .debug_line version: %u\n"),
+		 (unsigned int) version);
+	  linep = lineendp;
+	  continue;
+	}
+
+      if (address_size != 4 && address_size != 8)
+	{
+	  error (0, 0, _("cannot handle address size: %u\n"),
+		 (unsigned int) address_size);
+	  linep = lineendp;
+	  continue;
+	}
+
+      if (segment_selector_size != 0)
+	{
+	  error (0, 0, _("cannot handle segment selector size: %u\n"),
+		 (unsigned int) segment_selector_size);
+	  linep = lineendp;
+	  continue;
+	}
+
+      if (unlikely (linep + opcode_base - 1 >= lineendp))
+	{
+	invalid_unit:
+	  error (0, 0,
+		 _("invalid data at offset %tu in section [%zu] '%s'"),
+		 linep - (const unsigned char *) data->d_buf,
+		 elf_ndxscn (scn), section_name (ebl, shdr));
+	  linep = lineendp;
+	  continue;
+	}
+      int opcode_base_l10 = 1;
+      unsigned int tmp = opcode_base;
+      while (tmp > 10)
+	{
+	  tmp /= 10;
+	  ++opcode_base_l10;
+	}
+      const uint8_t *standard_opcode_lengths = linep - 1;
+      for (uint_fast8_t cnt = 1; cnt < opcode_base; ++cnt)
+	printf (ngettext ("  [%*" PRIuFAST8 "]  %hhu argument\n",
+			  "  [%*" PRIuFAST8 "]  %hhu arguments\n",
+			  (int) linep[cnt - 1]),
+		opcode_base_l10, cnt, linep[cnt - 1]);
+      linep += opcode_base - 1;
+
+      if (unlikely (linep >= lineendp))
+	goto invalid_unit;
+
+      Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, NULL);
+
+      puts (_("\nDirectory table:"));
+      if (version > 4)
+	{
+	  struct encpair { uint16_t desc; uint16_t form; };
+	  struct encpair enc[256];
+
+	  printf (_("      ["));
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  unsigned char directory_entry_format_count = *linep++;
+	  for (int i = 0; i < directory_entry_format_count; i++)
+	    {
+	      uint16_t desc, form;
+	      if ((size_t) (lineendp - linep) < 1)
+		goto invalid_data;
+	      get_uleb128 (desc, linep, lineendp);
+	      if ((size_t) (lineendp - linep) < 1)
+		goto invalid_data;
+	      get_uleb128 (form, linep, lineendp);
+
+	      enc[i].desc = desc;
+	      enc[i].form = form;
+
+	      printf ("%s(%s)",
+		      dwarf_line_content_description_name (desc),
+		      dwarf_form_name (form));
+	      if (i + 1 < directory_entry_format_count)
+		printf (", ");
+	    }
+	  printf ("]\n");
+
+	  uint64_t directories_count;
+	  if ((size_t) (lineendp - linep) < 1)
+            goto invalid_data;
+	  get_uleb128 (directories_count, linep, lineendp);
+
+	  if (directory_entry_format_count == 0
+	      && directories_count != 0)
+	    goto invalid_data;
+
+	  for (uint64_t i = 0; i < directories_count; i++)
+	    {
+	      printf (" %-5" PRIu64 " ", i);
+	      for (int j = 0; j < directory_entry_format_count; j++)
+		{
+		  linep = print_form_data (dbg, enc[j].form,
+					   linep, lineendp, length,
+					   str_offsets_base);
+		  if (j + 1 < directory_entry_format_count)
+		    printf (", ");
+		}
+	      printf ("\n");
+	      if (linep >= lineendp)
+		goto invalid_unit;
+	    }
+	}
+      else
+	{
+	  while (linep < lineendp && *linep != 0)
+	    {
+	      unsigned char *endp = memchr (linep, '\0', lineendp - linep);
+	      if (unlikely (endp == NULL))
+		goto invalid_unit;
+
+	      printf (" %s\n", (char *) linep);
+
+	      linep = endp + 1;
+	    }
+	  if (linep >= lineendp || *linep != 0)
+	    goto invalid_unit;
+	  /* Skip the final NUL byte.  */
+	  ++linep;
+	}
+
+      if (unlikely (linep >= lineendp))
+	goto invalid_unit;
+
+      puts (_("\nFile name table:"));
+      if (version > 4)
+	{
+	  struct encpair { uint16_t desc; uint16_t form; };
+	  struct encpair enc[256];
+
+	  printf (_("      ["));
+	  if ((size_t) (lineendp - linep) < 1)
+	    goto invalid_data;
+	  unsigned char file_name_format_count = *linep++;
+	  for (int i = 0; i < file_name_format_count; i++)
+	    {
+	      uint64_t desc, form;
+	      if ((size_t) (lineendp - linep) < 1)
+		goto invalid_data;
+	      get_uleb128 (desc, linep, lineendp);
+	      if ((size_t) (lineendp - linep) < 1)
+		goto invalid_data;
+	      get_uleb128 (form, linep, lineendp);
+
+	      if (! libdw_valid_user_form (form))
+		goto invalid_data;
+
+	      enc[i].desc = desc;
+	      enc[i].form = form;
+
+	      printf ("%s(%s)",
+		      dwarf_line_content_description_name (desc),
+		      dwarf_form_name (form));
+	      if (i + 1 < file_name_format_count)
+		printf (", ");
+	    }
+	  printf ("]\n");
+
+	  uint64_t file_name_count;
+	  if ((size_t) (lineendp - linep) < 1)
+            goto invalid_data;
+	  get_uleb128 (file_name_count, linep, lineendp);
+
+	  if (file_name_format_count == 0
+	      && file_name_count != 0)
+	    goto invalid_data;
+
+	  for (uint64_t i = 0; i < file_name_count; i++)
+	    {
+	      printf (" %-5" PRIu64 " ", i);
+	      for (int j = 0; j < file_name_format_count; j++)
+		{
+		  linep = print_form_data (dbg, enc[j].form,
+					   linep, lineendp, length,
+					   str_offsets_base);
+		  if (j + 1 < file_name_format_count)
+		    printf (", ");
+		}
+	      printf ("\n");
+	      if (linep > lineendp)
+		goto invalid_unit;
+	    }
+	}
+      else
+	{
+	  puts (_(" Entry Dir   Time      Size      Name"));
+	  for (unsigned int cnt = 1; linep < lineendp && *linep != 0; ++cnt)
+	    {
+	      /* First comes the file name.  */
+	      char *fname = (char *) linep;
+	      unsigned char *endp = memchr (fname, '\0', lineendp - linep);
+	      if (unlikely (endp == NULL))
+		goto invalid_unit;
+	      linep = endp + 1;
+
+	      /* Then the index.  */
+	      unsigned int diridx;
+	      if (lineendp - linep < 1)
+		goto invalid_unit;
+	      get_uleb128 (diridx, linep, lineendp);
+
+	      /* Next comes the modification time.  */
+	      unsigned int mtime;
+	      if (lineendp - linep < 1)
+		goto invalid_unit;
+	      get_uleb128 (mtime, linep, lineendp);
+
+	      /* Finally the length of the file.  */
+	      unsigned int fsize;
+	      if (lineendp - linep < 1)
+		goto invalid_unit;
+	      get_uleb128 (fsize, linep, lineendp);
+
+	      printf (" %-5u %-5u %-9u %-9u %s\n",
+		      cnt, diridx, mtime, fsize, fname);
+	    }
+	  if (linep >= lineendp || *linep != '\0')
+	    goto invalid_unit;
+	  /* Skip the final NUL byte.  */
+	  ++linep;
+	}
+
+      unsigned int debug_str_offset = 0;
+      if (unlikely (linep == header_start + header_length - 4))
+	{
+	  /* CUBINs contain an unsigned 4-byte offset */
+	  debug_str_offset = read_4ubyte_unaligned_inc (dbg, linep);
+	}
+
+      if (linep == lineendp)
+	{
+	  puts (_("\nNo line number statements."));
+	  continue;
+	}
+
+      puts (_("\nLine number statements:"));
+      Dwarf_Word address = 0;
+      unsigned int op_index = 0;
+      size_t line = 1;
+      uint_fast8_t is_stmt = default_is_stmt;
+
+      /* Apply the "operation advance" from a special opcode
+	 or DW_LNS_advance_pc (as per DWARF4 6.2.5.1).  */
+      unsigned int op_addr_advance;
+#define advance_pc(op_advance) run_advance_pc(op_advance, minimum_instr_len, \
+                      max_ops_per_instr, &op_addr_advance, &address, &op_index)
+
+      if (max_ops_per_instr == 0)
+	{
+	  error (0, 0,
+		 _("invalid maximum operations per instruction is zero"));
+	  linep = lineendp;
+	  continue;
+	}
+
+      while (linep < lineendp)
+	{
+	  size_t offset = linep - (const unsigned char *) data->d_buf;
+	  unsigned int u128;
+	  int s128;
+
+	  /* Read the opcode.  */
+	  unsigned int opcode = *linep++;
+
+	  printf (" [%6" PRIx64 "]", (uint64_t)offset);
+	  /* Is this a special opcode?  */
+	  if (likely (opcode >= opcode_base))
+	    {
+	      if (unlikely (line_range == 0))
+		goto invalid_unit;
+
+	      /* Yes.  Handling this is quite easy since the opcode value
+		 is computed with
+
+		 opcode = (desired line increment - line_base)
+			   + (line_range * address advance) + opcode_base
+	      */
+	      int line_increment = (line_base
+				    + (opcode - opcode_base) % line_range);
+
+	      /* Perform the increments.  */
+	      line += line_increment;
+	      advance_pc ((opcode - opcode_base) / line_range);
+
+	      printf (_(" special opcode %u: address+%u = "),
+		      opcode, op_addr_advance);
+	      print_dwarf_addr (dwflmod, 0, address, address);
+	      if (op_index > 0)
+		printf (_(", op_index = %u, line%+d = %zu\n"),
+			op_index, line_increment, line);
+	      else
+		printf (_(", line%+d = %zu\n"),
+			line_increment, line);
+	    }
+	  else if (opcode == 0)
+	    {
+	      /* This an extended opcode.  */
+	      if (unlikely (linep + 2 > lineendp))
+		goto invalid_unit;
+
+	      /* The length.  */
+	      unsigned int len = *linep++;
+
+	      if (unlikely (linep + len > lineendp))
+		goto invalid_unit;
+
+	      /* The sub-opcode.  */
+	      opcode = *linep++;
+
+	      printf (_(" extended opcode %u: "), opcode);
+
+	      switch (opcode)
+		{
+		case DW_LNE_end_sequence:
+		  puts (_(" end of sequence"));
+
+		  /* Reset the registers we care about.  */
+		  address = 0;
+		  op_index = 0;
+		  line = 1;
+		  is_stmt = default_is_stmt;
+		  break;
+
+		case DW_LNE_set_address:
+		  op_index = 0;
+		  if (unlikely ((size_t) (lineendp - linep) < address_size))
+		    goto invalid_unit;
+		  if (address_size == 4)
+		    address = read_4ubyte_unaligned_inc (dbg, linep);
+		  else
+		    address = read_8ubyte_unaligned_inc (dbg, linep);
+		  {
+		    printf (_(" set address to "));
+		    print_dwarf_addr (dwflmod, 0, address, address);
+		    printf ("\n");
+		  }
+		  break;
+
+		case DW_LNE_define_file:
+		  {
+		    char *fname = (char *) linep;
+		    unsigned char *endp = memchr (linep, '\0',
+						  lineendp - linep);
+		    if (unlikely (endp == NULL))
+		      goto invalid_unit;
+		    linep = endp + 1;
+
+		    unsigned int diridx;
+		    if (lineendp - linep < 1)
+		      goto invalid_unit;
+		    get_uleb128 (diridx, linep, lineendp);
+		    Dwarf_Word mtime;
+		    if (lineendp - linep < 1)
+		      goto invalid_unit;
+		    get_uleb128 (mtime, linep, lineendp);
+		    Dwarf_Word filelength;
+		    if (lineendp - linep < 1)
+		      goto invalid_unit;
+		    get_uleb128 (filelength, linep, lineendp);
+
+		    printf (_("\
+ define new file: dir=%u, mtime=%" PRIu64 ", length=%" PRIu64 ", name=%s\n"),
+			    diridx, (uint64_t) mtime, (uint64_t) filelength,
+			    fname);
+		  }
+		  break;
+
+		case DW_LNE_set_discriminator:
+		  /* Takes one ULEB128 parameter, the discriminator.  */
+		  if (unlikely (standard_opcode_lengths[opcode] != 1
+				|| lineendp - linep < 1))
+		    goto invalid_unit;
+
+		  get_uleb128 (u128, linep, lineendp);
+		  printf (_(" set discriminator to %u\n"), u128);
+		  break;
+
+		case DW_LNE_NVIDIA_inlined_call:
+		  {
+		    if (unlikely (linep >= lineendp))
+		      goto invalid_data;
+
+		    unsigned int context;
+		    get_uleb128 (context, linep, lineendp);
+
+		    if (unlikely (linep >= lineendp))
+		      goto invalid_data;
+
+		    unsigned int function_name;
+		    get_uleb128 (function_name, linep, lineendp);
+		    function_name += debug_str_offset;
+
+		    Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
+		    char *function_str;
+		    if (str_data == NULL || function_name >= str_data->d_size
+			|| memchr (str_data->d_buf + function_name, '\0',
+				   str_data->d_size - function_name) == NULL)
+		      function_str = "???";
+		    else
+		      function_str = (char *) str_data->d_buf + function_name;
+
+		    printf (_(" set inlined context %u,"
+		              " function name %s (0x%x)\n"),
+			    context, function_str, function_name);
+		    break;
+		  }
+
+		case DW_LNE_NVIDIA_set_function_name:
+		  {
+		    if (unlikely (linep >= lineendp))
+		      goto invalid_data;
+
+		    unsigned int function_name;
+		    get_uleb128 (function_name, linep, lineendp);
+		    function_name += debug_str_offset;
+
+		    Elf_Data *str_data = dbg->sectiondata[IDX_debug_str];
+		    char *function_str;
+		    if (str_data == NULL || function_name >= str_data->d_size
+			|| memchr (str_data->d_buf + function_name, '\0',
+				   str_data->d_size - function_name) == NULL)
+		      function_str = "???";
+		    else
+		      function_str = (char *) str_data->d_buf + function_name;
+
+		    printf (_(" set function name %s (0x%x)\n"),
+			    function_str, function_name);
+		  }
+		  break;
+
+		default:
+		  /* Unknown, ignore it.  */
+		  puts (_(" unknown opcode"));
+		  linep += len - 1;
+		  break;
+		}
+	    }
+	  else if (opcode <= DW_LNS_set_isa)
+	    {
+	      /* This is a known standard opcode.  */
+	      switch (opcode)
+		{
+		case DW_LNS_copy:
+		  /* Takes no argument.  */
+		  puts (_(" copy"));
+		  break;
+
+		case DW_LNS_advance_pc:
+		  /* Takes one uleb128 parameter which is added to the
+		     address.  */
+		  if (lineendp - linep < 1)
+		    goto invalid_unit;
+		  get_uleb128 (u128, linep, lineendp);
+		  advance_pc (u128);
+		  {
+		    printf (_(" advance address by %u to "),
+			    op_addr_advance);
+		    print_dwarf_addr (dwflmod, 0, address, address);
+		    if (op_index > 0)
+		      printf (_(", op_index to %u"), op_index);
+		    printf ("\n");
+		  }
+		  break;
+
+		case DW_LNS_advance_line:
+		  /* Takes one sleb128 parameter which is added to the
+		     line.  */
+		  if (lineendp - linep < 1)
+		    goto invalid_unit;
+		  get_sleb128 (s128, linep, lineendp);
+		  line += s128;
+		  printf (_("\
+ advance line by constant %d to %" PRId64 "\n"),
+			  s128, (int64_t) line);
+		  break;
+
+		case DW_LNS_set_file:
+		  /* Takes one uleb128 parameter which is stored in file.  */
+		  if (lineendp - linep < 1)
+		    goto invalid_unit;
+		  get_uleb128 (u128, linep, lineendp);
+		  printf (_(" set file to %" PRIu64 "\n"),
+			  (uint64_t) u128);
+		  break;
+
+		case DW_LNS_set_column:
+		  /* Takes one uleb128 parameter which is stored in column.  */
+		  if (unlikely (standard_opcode_lengths[opcode] != 1
+				|| lineendp - linep < 1))
+		    goto invalid_unit;
+
+		  get_uleb128 (u128, linep, lineendp);
+		  printf (_(" set column to %" PRIu64 "\n"),
+			  (uint64_t) u128);
+		  break;
+
+		case DW_LNS_negate_stmt:
+		  /* Takes no argument.  */
+		  is_stmt = 1 - is_stmt;
+		  printf (_(" set '%s' to %" PRIuFAST8 "\n"),
+			  "is_stmt", is_stmt);
+		  break;
+
+		case DW_LNS_set_basic_block:
+		  /* Takes no argument.  */
+		  puts (_(" set basic block flag"));
+		  break;
+
+		case DW_LNS_const_add_pc:
+		  /* Takes no argument.  */
+
+		  if (unlikely (line_range == 0))
+		    goto invalid_unit;
+
+		  advance_pc ((255 - opcode_base) / line_range);
+		  {
+		    printf (_(" advance address by constant %u to "),
+			    op_addr_advance);
+		    print_dwarf_addr (dwflmod, 0, address, address);
+		    if (op_index > 0)
+		      printf (_(", op_index to %u"), op_index);
+		    printf ("\n");
+		  }
+		  break;
+
+		case DW_LNS_fixed_advance_pc:
+		  /* Takes one 16 bit parameter which is added to the
+		     address.  */
+		  if (unlikely (standard_opcode_lengths[opcode] != 1
+				|| lineendp - linep < 2))
+		    goto invalid_unit;
+
+		  u128 = read_2ubyte_unaligned_inc (dbg, linep);
+		  address += u128;
+		  op_index = 0;
+		  {
+		    printf (_("\
+ advance address by fixed value %u to \n"),
+			    u128);
+		    print_dwarf_addr (dwflmod, 0, address, address);
+		    printf ("\n");
+		  }
+		  break;
+
+		case DW_LNS_set_prologue_end:
+		  /* Takes no argument.  */
+		  puts (_(" set prologue end flag"));
+		  break;
+
+		case DW_LNS_set_epilogue_begin:
+		  /* Takes no argument.  */
+		  puts (_(" set epilogue begin flag"));
+		  break;
+
+		case DW_LNS_set_isa:
+		  /* Takes one uleb128 parameter which is stored in isa.  */
+		  if (unlikely (standard_opcode_lengths[opcode] != 1
+				|| lineendp - linep < 1))
+		    goto invalid_unit;
+
+		  get_uleb128 (u128, linep, lineendp);
+		  printf (_(" set isa to %u\n"), u128);
+		  break;
+		}
+	    }
+	  else
+	    {
+	      /* This is a new opcode the generator but not we know about.
+		 Read the parameters associated with it but then discard
+		 everything.  Read all the parameters for this opcode.  */
+	      printf (ngettext (" unknown opcode with %" PRIu8 " parameter:",
+				" unknown opcode with %" PRIu8 " parameters:",
+				standard_opcode_lengths[opcode]),
+		      standard_opcode_lengths[opcode]);
+	      for (int n = standard_opcode_lengths[opcode];
+		   n > 0 && linep < lineendp; --n)
+		{
+		  get_uleb128 (u128, linep, lineendp);
+		  if (n != standard_opcode_lengths[opcode])
+		    putc_unlocked (',', stdout);
+		  printf (" %u", u128);
+		}
+
+	      /* Next round, ignore this opcode.  */
+	      continue;
+	    }
+	}
+    }
+
+  /* There must only be one data block.  */
+  assert (elf_getdata (scn, data) == NULL);
+}
+
+
+static void
+print_debug_loclists_section (Dwfl_Module *dwflmod,
+			      Ebl *ebl,
+			      GElf_Ehdr *ehdr __attribute__ ((unused)),
+			      Elf_Scn *scn, GElf_Shdr *shdr,
+			      Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loclists, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  /* For the listptr to get the base address/CU.  */
+  sort_listptr (&known_loclistsptr, "loclistsptr");
+  size_t listptr_idx = 0;
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *const dataend = ((unsigned char *) data->d_buf
+					+ data->d_size);
+  while (readp < dataend)
+    {
+      if (unlikely (readp > dataend - 4))
+	{
+	invalid_data:
+	  error (0, 0, _("invalid data in section [%zu] '%s'"),
+		 elf_ndxscn (scn), section_name (ebl, shdr));
+	  return;
+	}
+
+      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+      printf (_("Table at Offset 0x%" PRIx64 ":\n\n"),
+	      (uint64_t) offset);
+
+      uint64_t unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+      unsigned int offset_size = 4;
+      if (unlikely (unit_length == 0xffffffff))
+	{
+	  if (unlikely (readp > dataend - 8))
+	    goto invalid_data;
+
+	  unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+	  offset_size = 8;
+	}
+      printf (_(" Length:         %8" PRIu64 "\n"), unit_length);
+
+      /* We need at least 2-bytes + 1-byte + 1-byte + 4-bytes = 8
+	 bytes to complete the header.  And this unit cannot go beyond
+	 the section data.  */
+      if (readp > dataend - 8
+	  || unit_length < 8
+	  || unit_length > (uint64_t) (dataend - readp))
+	goto invalid_data;
+
+      const unsigned char *nexthdr = readp + unit_length;
+
+      uint16_t version = read_2ubyte_unaligned_inc (dbg, readp);
+      printf (_(" DWARF version:  %8" PRIu16 "\n"), version);
+
+      if (version != 5)
+	{
+	  error (0, 0, _("Unknown version"));
+	  goto next_table;
+	}
+
+      uint8_t address_size = *readp++;
+      printf (_(" Address size:   %8" PRIu64 "\n"),
+	      (uint64_t) address_size);
+
+      if (address_size != 4 && address_size != 8)
+	{
+	  error (0, 0, _("unsupported address size"));
+	  goto next_table;
+	}
+
+      uint8_t segment_size = *readp++;
+      printf (_(" Segment size:   %8" PRIu64 "\n"),
+	      (uint64_t) segment_size);
+
+      if (segment_size != 0)
+        {
+          error (0, 0, _("unsupported segment size"));
+          goto next_table;
+        }
+
+      uint32_t offset_entry_count = read_4ubyte_unaligned_inc (dbg, readp);
+      printf (_(" Offset entries: %8" PRIu64 "\n"),
+	      (uint64_t) offset_entry_count);
+
+      /* We need the CU that uses this unit to get the initial base address. */
+      Dwarf_Addr cu_base = 0;
+      struct Dwarf_CU *cu = NULL;
+      if (listptr_cu (&known_loclistsptr, &listptr_idx,
+		      (Dwarf_Off) offset,
+		      (Dwarf_Off) (nexthdr - (unsigned char *) data->d_buf),
+		      &cu_base, &cu)
+	  || split_dwarf_cu_base (dbg, &cu, &cu_base))
+	{
+	  Dwarf_Die cudie;
+	  if (dwarf_cu_die (cu, &cudie,
+			    NULL, NULL, NULL, NULL,
+			    NULL, NULL) == NULL)
+	    printf (_(" Unknown CU base: "));
+	  else
+	    printf (_(" CU [%6" PRIx64 "] base: "),
+		    dwarf_dieoffset (&cudie));
+	  print_dwarf_addr (dwflmod, address_size, cu_base, cu_base);
+	  printf ("\n");
+	}
+      else
+	printf (_(" Not associated with a CU.\n"));
+
+      printf ("\n");
+
+      const unsigned char *offset_array_start = readp;
+      if (offset_entry_count > 0)
+	{
+	  uint64_t max_entries = (unit_length - 8) / offset_size;
+	  if (offset_entry_count > max_entries)
+	    {
+	      error (0, 0,
+		     _("too many offset entries for unit length"));
+	      offset_entry_count = max_entries;
+	    }
+
+	  printf (_("  Offsets starting at 0x%" PRIx64 ":\n"),
+		  (uint64_t) (offset_array_start
+			      - (unsigned char *) data->d_buf));
+	  for (uint32_t idx = 0; idx < offset_entry_count; idx++)
+	    {
+	      printf ("   [%6" PRIu32 "] ", idx);
+	      if (offset_size == 4)
+		{
+		  uint32_t off = read_4ubyte_unaligned_inc (dbg, readp);
+		  printf ("0x%" PRIx32 "\n", off);
+		}
+	      else
+		{
+		  uint64_t off = read_8ubyte_unaligned_inc (dbg, readp);
+		  printf ("0x%" PRIx64 "\n", off);
+		}
+	    }
+	  printf ("\n");
+	}
+
+      Dwarf_Addr base = cu_base;
+      bool start_of_list = true;
+      while (readp < nexthdr)
+	{
+	  Dwarf_Off off = (Dwarf_Off) (readp - (unsigned char *) data->d_buf);
+	  if (listptr_attr (&known_loclistsptr, listptr_idx, off,
+			    DW_AT_GNU_locviews))
+	    {
+	      Dwarf_Off next_off = next_listptr_offset (&known_loclistsptr,
+							&listptr_idx, off);
+	      const unsigned char *locp = readp;
+	      const unsigned char *locendp;
+	      if (next_off == 0
+		  || next_off > (size_t) (nexthdr - ((const unsigned char *)
+						     data->d_buf)))
+		locendp = nexthdr;
+	      else
+		locendp = (const unsigned char *) data->d_buf + next_off;
+
+	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+		      (uint64_t) (readp - (unsigned char *) data->d_buf),
+		      (uint64_t) (readp - offset_array_start));
+
+	      while (locp < locendp)
+		{
+		  uint64_t v1, v2;
+		  get_uleb128 (v1, locp, locendp);
+		  if (locp >= locendp)
+		    {
+		      printf (_("    <INVALID DATA>\n"));
+		      break;
+		    }
+		  get_uleb128 (v2, locp, locendp);
+		  printf ("    view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
+		}
+
+	      printf ("\n");
+	      readp = (unsigned char *) locendp;
+	      continue;
+	    }
+
+	  uint8_t kind = *readp++;
+	  uint64_t op1, op2, len;
+
+	  /* Skip padding.  */
+	  if (start_of_list && kind == DW_LLE_end_of_list)
+	    continue;
+
+	  if (start_of_list)
+	    {
+	      base = cu_base;
+	      printf ("  Offset: %" PRIx64 ", Index: %" PRIx64 "\n",
+		      (uint64_t) (readp - (unsigned char *) data->d_buf - 1),
+		      (uint64_t) (readp - offset_array_start - 1));
+	      start_of_list = false;
+	    }
+
+	  printf ("    %s", dwarf_loc_list_encoding_name (kind));
+	  switch (kind)
+	    {
+	    case DW_LLE_end_of_list:
+	      start_of_list = true;
+	      printf ("\n\n");
+	      break;
+
+	    case DW_LLE_base_addressx:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		{
+		invalid_entry:
+		  error (0, 0, _("invalid loclists data"));
+		  goto next_table;
+		}
+	      get_uleb128 (op1, readp, nexthdr);
+	      printf (" %" PRIx64 "\n", op1);
+	      if (! print_unresolved_addresses)
+		{
+		  Dwarf_Addr addr;
+		  if (get_indexed_addr (cu, op1, &addr) != 0)
+		    printf ("      ???\n");
+		  else
+		    {
+		      printf ("      ");
+		      print_dwarf_addr (dwflmod, address_size, addr, addr);
+		      printf ("\n");
+		    }
+		}
+	      break;
+
+	    case DW_LLE_startx_endx:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  Dwarf_Addr addr1;
+		  Dwarf_Addr addr2;
+		  if (get_indexed_addr (cu, op1, &addr1) != 0
+		      || get_indexed_addr (cu, op2, &addr2) != 0)
+		    {
+		      printf ("      ???..\n");
+		      printf ("      ???\n");
+		    }
+		  else
+		    {
+		      printf ("      ");
+		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
+		      printf ("..\n      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr2 - 1, addr2);
+		      printf ("\n");
+		    }
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (len, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < len)
+		goto invalid_entry;
+	      print_ops (dwflmod, dbg, 8, 8, version,
+			 address_size, offset_size, cu, len, readp);
+	      readp += len;
+	      break;
+
+	    case DW_LLE_startx_length:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  Dwarf_Addr addr1;
+		  Dwarf_Addr addr2;
+		  if (get_indexed_addr (cu, op1, &addr1) != 0)
+		    {
+		      printf ("      ???..\n");
+		      printf ("      ???\n");
+		    }
+		  else
+		    {
+		      addr2 = addr1 + op2;
+		      printf ("      ");
+		      print_dwarf_addr (dwflmod, address_size, addr1, addr1);
+		      printf ("..\n      ");
+		      print_dwarf_addr (dwflmod, address_size,
+					addr2 - 1, addr2);
+		      printf ("\n");
+		    }
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (len, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < len)
+		goto invalid_entry;
+	      print_ops (dwflmod, dbg, 8, 8, version,
+			 address_size, offset_size, cu, len, readp);
+	      readp += len;
+	      break;
+
+	    case DW_LLE_offset_pair:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  op1 += base;
+		  op2 += base;
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1);
+		  printf ("..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
+		  printf ("\n");
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (len, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < len)
+		goto invalid_entry;
+	      print_ops (dwflmod, dbg, 8, 8, version,
+			 address_size, offset_size, cu, len, readp);
+	      readp += len;
+	      break;
+
+	    case DW_LLE_default_location:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (len, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < len)
+		goto invalid_entry;
+	      print_ops (dwflmod, dbg, 8, 8, version,
+			 address_size, offset_size, cu, len, readp);
+	      readp += len;
+	      break;
+
+	    case DW_LLE_base_address:
+	      if (address_size == 4)
+		{
+		  if ((uint64_t) (nexthdr - readp) < 4)
+		    goto invalid_entry;
+		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
+		}
+	      else
+		{
+		  if ((uint64_t) (nexthdr - readp) < 8)
+		    goto invalid_entry;
+		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      base = op1;
+	      printf (" 0x%" PRIx64 "\n", base);
+	      if (! print_unresolved_addresses)
+		{
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, base, base);
+		  printf ("\n");
+		}
+	      break;
+
+	    case DW_LLE_start_end:
+	      if (address_size == 4)
+		{
+		  if ((uint64_t) (nexthdr - readp) < 8)
+		    goto invalid_entry;
+		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
+		  op2 = read_4ubyte_unaligned_inc (dbg, readp);
+		}
+	      else
+		{
+		  if ((uint64_t) (nexthdr - readp) < 16)
+		    goto invalid_entry;
+		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
+		  op2 = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      printf (" 0x%" PRIx64 "..0x%" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1);
+		  printf ("..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
+		  printf ("\n");
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (len, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < len)
+		goto invalid_entry;
+	      print_ops (dwflmod, dbg, 8, 8, version,
+			 address_size, offset_size, cu, len, readp);
+	      readp += len;
+	      break;
+
+	    case DW_LLE_start_length:
+	      if (address_size == 4)
+		{
+		  if ((uint64_t) (nexthdr - readp) < 4)
+		    goto invalid_entry;
+		  op1 = read_4ubyte_unaligned_inc (dbg, readp);
+		}
+	      else
+		{
+		  if ((uint64_t) (nexthdr - readp) < 8)
+		    goto invalid_entry;
+		  op1 = read_8ubyte_unaligned_inc (dbg, readp);
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" 0x%" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      if (! print_unresolved_addresses)
+		{
+		  op2 = op1 + op2;
+		  printf ("      ");
+		  print_dwarf_addr (dwflmod, address_size, op1, op1);
+		  printf ("..\n      ");
+		  print_dwarf_addr (dwflmod, address_size, op2 - 1, op2);
+		  printf ("\n");
+		}
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (len, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < len)
+		goto invalid_entry;
+	      print_ops (dwflmod, dbg, 8, 8, version,
+			 address_size, offset_size, cu, len, readp);
+	      readp += len;
+	      break;
+
+	    case DW_LLE_GNU_view_pair:
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op1, readp, nexthdr);
+	      if ((uint64_t) (nexthdr - readp) < 1)
+		goto invalid_entry;
+	      get_uleb128 (op2, readp, nexthdr);
+	      printf (" %" PRIx64 ", %" PRIx64 "\n", op1, op2);
+	      break;
+
+	    default:
+	      goto invalid_entry;
+	    }
+	}
+
+    next_table:
+      if (readp != nexthdr)
+	{
+          size_t padding = nexthdr - readp;
+          printf (_("   %zu padding bytes\n\n"), padding);
+	  readp = nexthdr;
+	}
+    }
+}
+
+
+static void
+print_debug_loc_section (Dwfl_Module *dwflmod,
+			 Ebl *ebl, GElf_Ehdr *ehdr,
+			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_loc, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  sort_listptr (&known_locsptr, "loclistptr");
+  size_t listptr_idx = 0;
+
+  uint_fast8_t address_size = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8;
+  uint_fast8_t offset_size = 4;
+
+  bool first = true;
+  Dwarf_Addr base = 0;
+  unsigned char *readp = data->d_buf;
+  unsigned char *const endp = (unsigned char *) data->d_buf + data->d_size;
+  Dwarf_CU *last_cu = NULL;
+  while (readp < endp)
+    {
+      ptrdiff_t offset = readp - (unsigned char *) data->d_buf;
+      Dwarf_CU *cu = last_cu;
+      unsigned int attr = 0;
+
+      if (first && skip_listptr_hole (&known_locsptr, &listptr_idx,
+				      &address_size, &offset_size, &base,
+				      &cu, offset, &readp, endp, &attr))
+	continue;
+
+      if (last_cu != cu)
+       {
+	Dwarf_Die cudie;
+	if (dwarf_cu_die (cu, &cudie,
+			  NULL, NULL, NULL, NULL,
+			  NULL, NULL) == NULL)
+	  printf (_("\n Unknown CU base: "));
+	else
+	  printf (_("\n CU [%6" PRIx64 "] base: "),
+		  dwarf_dieoffset (&cudie));
+	print_dwarf_addr (dwflmod, address_size, base, base);
+	printf ("\n");
+       }
+      last_cu = cu;
+
+      if (attr == DW_AT_GNU_locviews)
+	{
+	  Dwarf_Off next_off = next_listptr_offset (&known_locsptr,
+						    &listptr_idx, offset);
+	  const unsigned char *locp = readp;
+	  const unsigned char *locendp;
+	  if (next_off == 0
+	      || next_off > (size_t) (endp
+				      - (const unsigned char *) data->d_buf))
+	    locendp = endp;
+	  else
+	    locendp = (const unsigned char *) data->d_buf + next_off;
+
+	  while (locp < locendp)
+	    {
+	      uint64_t v1, v2;
+	      get_uleb128 (v1, locp, locendp);
+	      if (locp >= locendp)
+		{
+		  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
+		  break;
+		}
+	      get_uleb128 (v2, locp, locendp);
+	      if (first)		/* First view pair in a list.  */
+		printf (" [%6tx] ", offset);
+	      else
+		printf ("          ");
+	      printf ("view pair %" PRId64 ", %" PRId64 "\n", v1, v2);
+	      first = false;
+	    }
+
+	  first = true;
+	  readp = (unsigned char *) locendp;
+	  continue;
+	}
+
+      /* GNU DebugFission encoded addresses as addrx.  */
+      bool is_debugfission = ((cu != NULL
+			       || split_dwarf_cu_base (dbg, &cu, &base))
+			      && (cu->version < 5
+				  && cu->unit_type == DW_UT_split_compile));
+      if (!is_debugfission
+	  && unlikely (data->d_size - offset < (size_t) address_size * 2))
+        {
+	invalid_data:
+	  printf (_(" [%6tx]  <INVALID DATA>\n"), offset);
+	  break;
+	}
+
+      Dwarf_Addr begin;
+      Dwarf_Addr end;
+      bool use_base = true;
+      if (is_debugfission)
+	{
+	  const unsigned char *locp = readp;
+	  const unsigned char *locendp = readp + data->d_size;
+	  if (locp >= locendp)
+	    goto invalid_data;
+
+	  Dwarf_Word idx;
+	  unsigned char code = *locp++;
+	  switch (code)
+	    {
+	    case DW_LLE_GNU_end_of_list_entry:
+	      begin = 0;
+	      end = 0;
+	      break;
+
+	    case DW_LLE_GNU_base_address_selection_entry:
+	      if (locp >= locendp)
+		goto invalid_data;
+	      begin = (Dwarf_Addr) -1;
+	      get_uleb128 (idx, locp, locendp);
+	      if (get_indexed_addr (cu, idx, &end) != 0)
+		end = idx; /* ... */
+	      break;
+
+	    case DW_LLE_GNU_start_end_entry:
+	      if (locp >= locendp)
+		goto invalid_data;
+	      get_uleb128 (idx, locp, locendp);
+	      if (get_indexed_addr (cu, idx, &begin) != 0)
+		begin = idx; /* ... */
+	      if (locp >= locendp)
+		goto invalid_data;
+	      get_uleb128 (idx, locp, locendp);
+	      if (get_indexed_addr (cu, idx, &end) != 0)
+		end = idx; /* ... */
+	      use_base = false;
+	      break;
+
+	    case DW_LLE_GNU_start_length_entry:
+	      if (locp >= locendp)
+		goto invalid_data;
+	      get_uleb128 (idx, locp, locendp);
+	      if (get_indexed_addr (cu, idx, &begin) != 0)
+		begin = idx; /* ... */
+	      if (locendp - locp < 4)
+		goto invalid_data;
+	      end = read_4ubyte_unaligned_inc (dbg, locp);
+	      end += begin;
+	      use_base = false;
+	      break;
+
+	    default:
+		goto invalid_data;
+	    }
+
+	  readp = (unsigned char *) locp;
+	}
+      else if (address_size == 8)
+	{
+	  begin = read_8ubyte_unaligned_inc (dbg, readp);
+	  end = read_8ubyte_unaligned_inc (dbg, readp);
+	}
+      else
+	{
+	  begin = read_4ubyte_unaligned_inc (dbg, readp);
+	  end = read_4ubyte_unaligned_inc (dbg, readp);
+	  if (begin == (Dwarf_Addr) (uint32_t) -1)
+	    begin = (Dwarf_Addr) -1l;
+	}
+
+      if (begin == (Dwarf_Addr) -1l) /* Base address entry.  */
+	{
+	  if (first)
+	    printf (" [%6tx] ", offset);
+	  else
+	    printf ("          ");
+	  puts (_("base address"));
+	  printf ("          ");
+	  print_dwarf_addr (dwflmod, address_size, end, end);
+	  printf ("\n");
+	  base = end;
+	  first = false;
+	}
+      else if (begin == 0 && end == 0) /* End of list entry.  */
+	{
+	  if (first)
+	    printf (_(" [%6tx] empty list\n"), offset);
+	  first = true;
+	}
+      else
+	{
+	  /* We have a location expression entry.  */
+	  uint_fast16_t len = read_2ubyte_unaligned_inc (dbg, readp);
+
+	  if (first)		/* First entry in a list.  */
+	    printf (" [%6tx] ", offset);
+	  else
+	    printf ("          ");
+
+	  printf ("range %" PRIx64 ", %" PRIx64 "\n", begin, end);
+	  if (! print_unresolved_addresses)
+	    {
+	      Dwarf_Addr dab = use_base ? base + begin : begin;
+	      Dwarf_Addr dae = use_base ? base + end : end;
+	      printf ("          ");
+	      print_dwarf_addr (dwflmod, address_size, dab, dab);
+	      printf ("..\n          ");
+	      print_dwarf_addr (dwflmod, address_size, dae - 1, dae);
+	      printf ("\n");
+	    }
+
+	  if (endp - readp <= (ptrdiff_t) len)
+	    {
+	      fputs (_("   <INVALID DATA>\n"), stdout);
+	      break;
+	    }
+
+	  print_ops (dwflmod, dbg, 11, 11,
+		     cu != NULL ? cu->version : 3,
+		     address_size, offset_size, cu, len, readp);
+
+	  first = false;
+	  readp += len;
+	}
+    }
+}
+
+struct mac_culist
+{
+  Dwarf_Die die;
+  Dwarf_Off offset;
+  Dwarf_Files *files;
+  struct mac_culist *next;
+};
+
+
+static int
+mac_compare (const void *p1, const void *p2)
+{
+  struct mac_culist *m1 = (struct mac_culist *) p1;
+  struct mac_culist *m2 = (struct mac_culist *) p2;
+
+  if (m1->offset < m2->offset)
+    return -1;
+  if (m1->offset > m2->offset)
+    return 1;
+  return 0;
+}
+
+
+static void
+print_debug_macinfo_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			     Ebl *ebl,
+			     GElf_Ehdr *ehdr __attribute__ ((unused)),
+			     Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macinfo, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+  putc_unlocked ('\n', stdout);
+
+  /* There is no function in libdw to iterate over the raw content of
+     the section but it is easy enough to do.  */
+
+  /* Get the source file information for all CUs.  */
+  Dwarf_Off offset;
+  Dwarf_Off ncu = 0;
+  size_t hsize;
+  struct mac_culist *culist = NULL;
+  size_t nculist = 0;
+  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
+    {
+      Dwarf_Die cudie;
+      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
+	continue;
+
+      Dwarf_Attribute attr;
+      if (dwarf_attr (&cudie, DW_AT_macro_info, &attr) == NULL)
+	continue;
+
+      Dwarf_Word macoff;
+      if (dwarf_formudata (&attr, &macoff) != 0)
+	continue;
+
+      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
+      newp->die = cudie;
+      newp->offset = macoff;
+      newp->files = NULL;
+      newp->next = culist;
+      culist = newp;
+      ++nculist;
+    }
+
+  /* Convert the list into an array for easier consumption.  */
+  struct mac_culist *cus = (struct mac_culist *) alloca ((nculist + 1)
+							 * sizeof (*cus));
+  /* Add sentinel.  */
+  cus[nculist].offset = data->d_size;
+  cus[nculist].files = (Dwarf_Files *) -1l;
+  if (nculist > 0)
+    {
+      for (size_t cnt = nculist - 1; culist != NULL; --cnt)
+	{
+	  assert (cnt < nculist);
+	  cus[cnt] = *culist;
+	  culist = culist->next;
+	}
+
+      /* Sort the array according to the offset in the .debug_macinfo
+	 section.  Note we keep the sentinel at the end.  */
+      qsort (cus, nculist, sizeof (*cus), mac_compare);
+    }
+
+  const unsigned char *readp = (const unsigned char *) data->d_buf;
+  const unsigned char *readendp = readp + data->d_size;
+  int level = 1;
+
+  while (readp < readendp)
+    {
+      unsigned int opcode = *readp++;
+      unsigned int u128;
+      unsigned int u128_2;
+      const unsigned char *endp;
+
+      switch (opcode)
+	{
+	case DW_MACINFO_define:
+	case DW_MACINFO_undef:
+	case DW_MACINFO_vendor_ext:
+	  /*  For the first two opcodes the parameters are
+		line, string
+	      For the latter
+		number, string.
+	      We can treat these cases together.  */
+	  get_uleb128 (u128, readp, readendp);
+
+	  endp = memchr (readp, '\0', readendp - readp);
+	  if (unlikely (endp == NULL))
+	    {
+	      printf (_("\
+%*s*** non-terminated string at end of section"),
+		      level, "");
+	      return;
+	    }
+
+	  if (opcode == DW_MACINFO_define)
+	    printf ("%*s#define %s, line %u\n",
+		    level, "", (char *) readp, u128);
+	  else if (opcode == DW_MACINFO_undef)
+	    printf ("%*s#undef %s, line %u\n",
+		    level, "", (char *) readp, u128);
+	  else
+	    printf (" #vendor-ext %s, number %u\n", (char *) readp, u128);
+
+	  readp = endp + 1;
+	  break;
+
+	case DW_MACINFO_start_file:
+	  /* The two parameters are line and file index, in this order.  */
+	  get_uleb128 (u128, readp, readendp);
+	  if (readendp - readp < 1)
+	    {
+	      printf (_("\
+%*s*** missing DW_MACINFO_start_file argument at end of section"),
+		      level, "");
+	      return;
+	    }
+	  get_uleb128 (u128_2, readp, readendp);
+
+	  /* Find the CU DIE for this file.  */
+	  size_t macoff = readp - (const unsigned char *) data->d_buf;
+	  const char *fname = "???";
+	  if (macoff >= cus[0].offset && cus[0].offset != data->d_size)
+	    {
+	      while (macoff >= cus[1].offset && cus[1].offset != data->d_size)
+		++cus;
+
+	      if (cus[0].files == NULL
+		  && dwarf_getsrcfiles (&cus[0].die, &cus[0].files, NULL) != 0)
+		cus[0].files = (Dwarf_Files *) -1l;
+
+	      if (cus[0].files != (Dwarf_Files *) -1l)
+		fname = (dwarf_filesrc (cus[0].files, u128_2, NULL, NULL)
+			 ?: "???");
+	    }
+
+	  printf ("%*sstart_file %u, [%u] %s\n",
+		  level, "", u128, u128_2, fname);
+	  ++level;
+	  break;
+
+	case DW_MACINFO_end_file:
+	  --level;
+	  printf ("%*send_file\n", level, "");
+	  /* Nothing more to do.  */
+	  break;
+
+	default:
+	  // XXX gcc seems to generate files with a trailing zero.
+	  if (unlikely (opcode != 0 || readp != readendp))
+	    printf ("%*s*** invalid opcode %u\n", level, "", opcode);
+	  break;
+	}
+    }
+}
+
+
+static void
+print_debug_macro_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			   Ebl *ebl,
+			   GElf_Ehdr *ehdr __attribute__ ((unused)),
+			   Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_macro, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+  putc_unlocked ('\n', stdout);
+
+  /* Get the source file information for all CUs.  Uses same
+     datastructure as macinfo.  But uses offset field to directly
+     match .debug_line offset.  And just stored in a list.  */
+  Dwarf_Off offset;
+  Dwarf_Off ncu = 0;
+  size_t hsize;
+  struct mac_culist *culist = NULL;
+  while (dwarf_nextcu (dbg, offset = ncu, &ncu, &hsize, NULL, NULL, NULL) == 0)
+    {
+      Dwarf_Die cudie;
+      if (dwarf_offdie (dbg, offset + hsize, &cudie) == NULL)
+	continue;
+
+      Dwarf_Attribute attr;
+      if (dwarf_attr (&cudie, DW_AT_stmt_list, &attr) == NULL)
+	continue;
+
+      Dwarf_Word lineoff;
+      if (dwarf_formudata (&attr, &lineoff) != 0)
+	continue;
+
+      struct mac_culist *newp = (struct mac_culist *) alloca (sizeof (*newp));
+      newp->die = cudie;
+      newp->offset = lineoff;
+      newp->files = NULL;
+      newp->next = culist;
+      culist = newp;
+    }
+
+  const unsigned char *readp = (const unsigned char *) data->d_buf;
+  const unsigned char *readendp = readp + data->d_size;
+
+  while (readp < readendp)
+    {
+      printf (_(" Offset:             0x%" PRIx64 "\n"),
+	      (uint64_t) (readp - (const unsigned char *) data->d_buf));
+
+      // Header, 2 byte version, 1 byte flag, optional .debug_line offset,
+      // optional vendor extension macro entry table.
+      if (readp + 2 > readendp)
+	{
+	invalid_data:
+	  error (0, 0, _("invalid data"));
+	  return;
+	}
+      const uint16_t vers = read_2ubyte_unaligned_inc (dbg, readp);
+      printf (_(" Version:            %" PRIu16 "\n"), vers);
+
+      // Version 4 is the GNU extension for DWARF4.  DWARF5 will use version
+      // 5 when it gets standardized.
+      if (vers != 4 && vers != 5)
+	{
+	  printf (_("  unknown version, cannot parse section\n"));
+	  return;
+	}
+
+      if (readp + 1 > readendp)
+	goto invalid_data;
+      const unsigned char flag = *readp++;
+      printf (_(" Flag:               0x%" PRIx8), flag);
+      if (flag != 0)
+	{
+	  printf (" (");
+	  if ((flag & 0x01) != 0)
+	    {
+	      printf ("offset_size");
+	      if ((flag & 0xFE) !=  0)
+		printf (", ");
+	    }
+	  if ((flag & 0x02) != 0)
+	    {
+	      printf ("debug_line_offset");
+	      if ((flag & 0xFC) !=  0)
+		printf (", ");
+	    }
+	  if ((flag & 0x04) != 0)
+	    {
+	      printf ("operands_table");
+	      if ((flag & 0xF8) !=  0)
+		printf (", ");
+	    }
+	  if ((flag & 0xF8) != 0)
+	    printf ("unknown");
+	  printf (")");
+	}
+      printf ("\n");
+
+      unsigned int offset_len = (flag & 0x01) ? 8 : 4;
+      printf (_(" Offset length:      %" PRIu8 "\n"), offset_len);
+      Dwarf_Off line_offset = -1;
+      if (flag & 0x02)
+	{
+	  if (offset_len == 8)
+	    line_offset = read_8ubyte_unaligned_inc (dbg, readp);
+	  else
+	    line_offset = read_4ubyte_unaligned_inc (dbg, readp);
+	  printf (_(" .debug_line offset: 0x%" PRIx64 "\n"),
+		  line_offset);
+	}
+
+      struct mac_culist *cu = NULL;
+      if (line_offset != (Dwarf_Off) -1)
+	{
+	  cu = culist;
+	  while (cu != NULL && line_offset != cu->offset)
+	    cu = cu->next;
+	}
+
+      Dwarf_Off str_offsets_base = str_offsets_base_off (dbg, (cu != NULL
+							       ? cu->die.cu
+							       : NULL));
+
+      const unsigned char *vendor[DW_MACRO_hi_user - DW_MACRO_lo_user + 1];
+      memset (vendor, 0, sizeof vendor);
+      if (flag & 0x04)
+	{
+	  // 1 byte length, for each item, 1 byte opcode, uleb128 number
+	  // of arguments, for each argument 1 byte form code.
+	  if (readp + 1 > readendp)
+	    goto invalid_data;
+	  unsigned int tlen = *readp++;
+	  printf (_("  extension opcode table, %" PRIu8 " items:\n"),
+		  tlen);
+	  for (unsigned int i = 0; i < tlen; i++)
+	    {
+	      if (readp + 1 > readendp)
+		goto invalid_data;
+	      unsigned int opcode = *readp++;
+	      printf (_("    [%" PRIx8 "]"), opcode);
+	      if (opcode < DW_MACRO_lo_user
+		  || opcode > DW_MACRO_hi_user)
+		goto invalid_data;
+	      // Record the start of description for this vendor opcode.
+	      // uleb128 nr args, 1 byte per arg form.
+	      vendor[opcode - DW_MACRO_lo_user] = readp;
+	      if (readp + 1 > readendp)
+		goto invalid_data;
+	      unsigned int args = *readp++;
+	      if (args > 0)
+		{
+		  printf (_(" %" PRIu8 " arguments:"), args);
+		  while (args > 0)
+		    {
+		      if (readp + 1 > readendp)
+			goto invalid_data;
+		      unsigned int form = *readp++;
+		      printf (" %s", dwarf_form_name (form));
+		      if (! libdw_valid_user_form (form))
+			goto invalid_data;
+		      args--;
+		      if (args > 0)
+			putchar_unlocked (',');
+		    }
+		}
+	      else
+		printf (_(" no arguments."));
+	      putchar_unlocked ('\n');
+	    }
+	}
+      putchar_unlocked ('\n');
+
+      int level = 1;
+      if (readp + 1 > readendp)
+	goto invalid_data;
+      unsigned int opcode = *readp++;
+      while (opcode != 0)
+	{
+	  unsigned int u128;
+	  unsigned int u128_2;
+	  const unsigned char *endp;
+	  uint64_t off;
+
+          switch (opcode)
+            {
+            case DW_MACRO_start_file:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp >= readendp)
+		goto invalid_data;
+	      get_uleb128 (u128_2, readp, readendp);
+
+	      /* Find the CU DIE that matches this line offset.  */
+	      const char *fname = "???";
+	      if (cu != NULL)
+		{
+		  if (cu->files == NULL
+		      && dwarf_getsrcfiles (&cu->die, &cu->files,
+					    NULL) != 0)
+		    cu->files = (Dwarf_Files *) -1l;
+
+		  if (cu->files != (Dwarf_Files *) -1l)
+		    fname = (dwarf_filesrc (cu->files, u128_2,
+					    NULL, NULL) ?: "???");
+		}
+	      printf ("%*sstart_file %u, [%u] %s\n",
+		      level, "", u128, u128_2, fname);
+	      ++level;
+	      break;
+
+	    case DW_MACRO_end_file:
+	      --level;
+	      printf ("%*send_file\n", level, "");
+	      break;
+
+	    case DW_MACRO_define:
+	      get_uleb128 (u128, readp, readendp);
+	      endp = memchr (readp, '\0', readendp - readp);
+	      if (endp == NULL)
+		goto invalid_data;
+	      printf ("%*s#define %s, line %u\n",
+		      level, "", readp, u128);
+	      readp = endp + 1;
+	      break;
+
+	    case DW_MACRO_undef:
+	      get_uleb128 (u128, readp, readendp);
+	      endp = memchr (readp, '\0', readendp - readp);
+	      if (endp == NULL)
+		goto invalid_data;
+	      printf ("%*s#undef %s, line %u\n",
+		      level, "", readp, u128);
+	      readp = endp + 1;
+	      break;
+
+	    case DW_MACRO_define_strp:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      if (offset_len == 8)
+		off = read_8ubyte_unaligned_inc (dbg, readp);
+	      else
+		off = read_4ubyte_unaligned_inc (dbg, readp);
+	      printf ("%*s#define %s, line %u (indirect)\n",
+		      level, "", dwarf_getstring (dbg, off, NULL), u128);
+	      break;
+
+	    case DW_MACRO_undef_strp:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      if (offset_len == 8)
+		off = read_8ubyte_unaligned_inc (dbg, readp);
+	      else
+		off = read_4ubyte_unaligned_inc (dbg, readp);
+	      printf ("%*s#undef %s, line %u (indirect)\n",
+		      level, "", dwarf_getstring (dbg, off, NULL), u128);
+	      break;
+
+	    case DW_MACRO_import:
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      if (offset_len == 8)
+		off = read_8ubyte_unaligned_inc (dbg, readp);
+	      else
+		off = read_4ubyte_unaligned_inc (dbg, readp);
+	      printf ("%*s#include offset 0x%" PRIx64 "\n",
+		      level, "", off);
+	      break;
+
+	    case DW_MACRO_define_sup:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      printf ("%*s#define ", level, "");
+	      readp =  print_form_data (dbg, DW_FORM_strp_sup,
+					readp, readendp, offset_len,
+					str_offsets_base);
+	      printf (", line %u (sup)\n", u128);
+	      break;
+
+	    case DW_MACRO_undef_sup:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      printf ("%*s#undef ", level, "");
+	      readp =  print_form_data (dbg, DW_FORM_strp_sup,
+					readp, readendp, offset_len,
+					str_offsets_base);
+	      printf (", line %u (sup)\n", u128);
+	      break;
+
+	    case DW_MACRO_import_sup:
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      if (offset_len == 8)
+		off = read_8ubyte_unaligned_inc (dbg, readp);
+	      else
+		off = read_4ubyte_unaligned_inc (dbg, readp);
+	      // XXX Needs support for reading from supplementary object file.
+	      printf ("%*s#include offset 0x%" PRIx64 " (sup)\n",
+		      level, "", off);
+	      break;
+
+	    case DW_MACRO_define_strx:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      printf ("%*s#define ", level, "");
+	      readp =  print_form_data (dbg, DW_FORM_strx,
+					readp, readendp, offset_len,
+					str_offsets_base);
+	      printf (", line %u (strx)\n", u128);
+	      break;
+
+	    case DW_MACRO_undef_strx:
+	      get_uleb128 (u128, readp, readendp);
+	      if (readp + offset_len > readendp)
+		goto invalid_data;
+	      printf ("%*s#undef ", level, "");
+	      readp =  print_form_data (dbg, DW_FORM_strx,
+					readp, readendp, offset_len,
+					str_offsets_base);
+	      printf (", line %u (strx)\n", u128);
+	      break;
+
+	    default:
+	      printf ("%*svendor opcode 0x%" PRIx8, level, "", opcode);
+	      if (opcode < DW_MACRO_lo_user
+		  || opcode > DW_MACRO_lo_user
+		  || vendor[opcode - DW_MACRO_lo_user] == NULL)
+		goto invalid_data;
+
+	      const unsigned char *op_desc;
+	      op_desc = vendor[opcode - DW_MACRO_lo_user];
+
+	      // Just skip the arguments, we cannot really interpret them,
+	      // but print as much as we can.
+	      unsigned int args = *op_desc++;
+	      while (args > 0 && readp < readendp)
+		{
+		  unsigned int form = *op_desc++;
+		  readp = print_form_data (dbg, form, readp, readendp,
+					   offset_len, str_offsets_base);
+		  args--;
+		  if (args > 0)
+		    printf (", ");
+		}
+	      putchar_unlocked ('\n');
+	    }
+
+	  if (readp + 1 > readendp)
+	    goto invalid_data;
+	  opcode = *readp++;
+	  if (opcode == 0)
+	    putchar_unlocked ('\n');
+	}
+    }
+}
+
+
+/* Callback for printing global names.  */
+static int
+print_pubnames (Dwarf *dbg __attribute__ ((unused)), Dwarf_Global *global,
+		void *arg)
+{
+  int *np = (int *) arg;
+
+  printf (_(" [%5d] DIE offset: %6" PRId64
+		   ", CU DIE offset: %6" PRId64 ", name: %s\n"),
+	  (*np)++, global->die_offset, global->cu_offset, global->name);
+
+  return 0;
+}
+
+
+/* Print the known exported symbols in the DWARF section '.debug_pubnames'.  */
+static void
+print_debug_pubnames_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			      Ebl *ebl,
+			      GElf_Ehdr *ehdr __attribute__ ((unused)),
+			      Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  /* Check section actually exists.  */
+  if (get_debug_elf_data (dbg, ebl, IDX_debug_pubnames, scn) == NULL)
+      return;
+
+  printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  int n = 0;
+  (void) dwarf_getpubnames (dbg, print_pubnames, &n, 0);
+}
+
+/* Print the content of the DWARF string section '.debug_str'
+   or 'debug_line_str'.  */
+static void
+print_debug_str_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			 Ebl *ebl,
+			 GElf_Ehdr *ehdr __attribute__ ((unused)),
+			 Elf_Scn *scn, GElf_Shdr *shdr,
+			 Dwarf *dbg __attribute__ ((unused)))
+{
+  const char *name = section_name (ebl, shdr);
+  int idx = ((name != NULL && strstr (name, "debug_line_str") != NULL)
+	     ? IDX_debug_line_str : IDX_debug_str);
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, idx, scn);
+  if (data == NULL)
+    return;
+
+  const size_t sh_size = data->d_size;
+
+  /* Compute floor(log16(shdr->sh_size)).  */
+  GElf_Addr tmp = sh_size;
+  int digits = 1;
+  while (tmp >= 16)
+    {
+      ++digits;
+      tmp >>= 4;
+    }
+  digits = MAX (4, digits);
+
+  printf (_("\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"
+		   " %*s  String\n"),
+	  elf_ndxscn (scn),
+	  section_name (ebl, shdr), (uint64_t) shdr->sh_offset,
+	  /* TRANS: the debugstr| prefix makes the string unique.  */
+	  digits + 2, sgettext ("debugstr|Offset"));
+
+  Dwarf_Off offset = 0;
+  while (offset < sh_size)
+    {
+      size_t len;
+      const char *str = (const char *) data->d_buf + offset;
+      const char *endp = memchr (str, '\0', sh_size - offset);
+      if (unlikely (endp == NULL))
+	{
+	  printf (_(" *** error, missing string terminator\n"));
+	  break;
+	}
+
+      printf (" [%*" PRIx64 "]  \"%s\"\n", digits, (uint64_t) offset, str);
+      len = endp - str;
+      offset += len + 1;
+    }
+}
+
+static void
+print_debug_str_offsets_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+				 Ebl *ebl,
+				 GElf_Ehdr *ehdr __attribute__ ((unused)),
+				 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  Elf_Data *data = get_debug_elf_data (dbg, ebl, IDX_debug_str_offsets, scn);
+  if (data == NULL)
+    return;
+
+  printf (_("\
+\nDWARF section [%2zu] '%s' at offset %#" PRIx64 ":\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset);
+
+  if (shdr->sh_size == 0)
+    return;
+
+  size_t idx = 0;
+  sort_listptr (&known_stroffbases, "str_offsets");
+
+  const unsigned char *start = (const unsigned char *) data->d_buf;
+  const unsigned char *readp = start;
+  const unsigned char *readendp = ((const unsigned char *) data->d_buf
+				   + data->d_size);
+
+  while (readp < readendp)
+    {
+      /* Most string offset tables will have a header.  For split
+	 dwarf unit GNU DebugFission didn't add one.  But they were
+	 also only defined for split units (main or skeleton units
+	 didn't have indirect strings).  So if we don't have a
+	 DW_AT_str_offsets_base at all and this is offset zero, then
+	 just start printing offsets immediately, if this is a .dwo
+	 section.  */
+      Dwarf_Off off = (Dwarf_Off) (readp
+				   - (const unsigned char *) data->d_buf);
+
+      printf ("Table at offset %" PRIx64 " ", off);
+
+      struct listptr *listptr = get_listptr (&known_stroffbases, idx++);
+      const unsigned char *next_unitp = readendp;
+      uint8_t offset_size;
+      bool has_header;
+      if (listptr == NULL)
+	{
+	  /* This can happen for .dwo files.  There is only an header
+	     in the case this is a version 5 split DWARF file.  */
+	  Dwarf_CU *cu;
+	  uint8_t unit_type;
+	  if (dwarf_get_units (dbg, NULL, &cu, NULL, &unit_type,
+			       NULL, NULL) != 0)
+	    {
+	      error (0, 0, "Warning: Cannot find any DWARF unit.");
+	      /* Just guess some values.  */
+	      has_header = false;
+	      offset_size = 4;
+	    }
+	  else if (off == 0
+		   && (unit_type == DW_UT_split_type
+		       || unit_type == DW_UT_split_compile))
+	    {
+	      has_header = cu->version > 4;
+	      offset_size = cu->offset_size;
+	    }
+	  else
+	    {
+	      error (0, 0,
+		     "Warning: No CU references .debug_str_offsets after %"
+		     PRIx64, off);
+	      has_header = cu->version > 4;
+	      offset_size = cu->offset_size;
+	    }
+	  printf ("\n");
+	}
+      else
+	{
+	  /* This must be DWARF5, since GNU DebugFission didn't define
+	     DW_AT_str_offsets_base.  */
+	  has_header = true;
+
+	  Dwarf_Die cudie;
+	  if (dwarf_cu_die (listptr->cu, &cudie,
+			    NULL, NULL, NULL, NULL,
+			    NULL, NULL) == NULL)
+	    printf ("Unknown CU (%s):\n", dwarf_errmsg (-1));
+	  else
+	    printf ("for CU [%6" PRIx64 "]:\n", dwarf_dieoffset (&cudie));
+	}
+
+      if (has_header)
+	{
+	  uint64_t unit_length;
+	  uint16_t version;
+	  uint16_t padding;
+
+	  unit_length = read_4ubyte_unaligned_inc (dbg, readp);
+	  if (unlikely (unit_length == 0xffffffff))
+	    {
+	      if (unlikely (readp > readendp - 8))
+		{
+		invalid_data:
+		  error (0, 0, "Invalid data");
+		  return;
+		}
+	      unit_length = read_8ubyte_unaligned_inc (dbg, readp);
+	      offset_size = 8;
+	    }
+	  else
+	    offset_size = 4;
+
+	  printf ("\n");
+	  printf (_(" Length:        %8" PRIu64 "\n"),
+		  unit_length);
+	  printf (_(" Offset size:   %8" PRIu8 "\n"),
+		  offset_size);
+
+	  /* We need at least 2-bytes (version) + 2-bytes (padding) =
+	     4 bytes to complete the header.  And this unit cannot go
+	     beyond the section data.  */
+	  if (readp > readendp - 4
+	      || unit_length < 4
+	      || unit_length > (uint64_t) (readendp - readp))
+	    goto invalid_data;
+
+	  next_unitp = readp + unit_length;
+
+	  version = read_2ubyte_unaligned_inc (dbg, readp);
+	  printf (_(" DWARF version: %8" PRIu16 "\n"), version);
+
+	  if (version != 5)
+	    {
+	      error (0, 0, _("Unknown version"));
+	      goto next_unit;
+	    }
+
+	  padding = read_2ubyte_unaligned_inc (dbg, readp);
+	  printf (_(" Padding:       %8" PRIx16 "\n"), padding);
+
+	  if (listptr != NULL
+	      && listptr->offset != (Dwarf_Off) (readp - start))
+	    {
+	      error (0, 0, "String offsets index doesn't start after header");
+	      goto next_unit;
+	    }
+
+	  printf ("\n");
+	}
+
+      int digits = 1;
+      size_t offsets = (next_unitp - readp) / offset_size;
+      while (offsets >= 10)
+	{
+	  ++digits;
+	  offsets /= 10;
+	}
+
+      unsigned int uidx = 0;
+      size_t index_offset =  readp - (const unsigned char *) data->d_buf;
+      printf (" Offsets start at 0x%zx:\n", index_offset);
+      while (readp <= next_unitp - offset_size)
+	{
+	  Dwarf_Word offset;
+	  if (offset_size == 4)
+	    offset = read_4ubyte_unaligned_inc (dbg, readp);
+	  else
+	    offset = read_8ubyte_unaligned_inc (dbg, readp);
+	  const char *str = dwarf_getstring (dbg, offset, NULL);
+	  printf (" [%*u] [%*" PRIx64 "]  \"%s\"\n",
+		  digits, uidx++, (int) offset_size * 2, offset, str ?: "???");
+	}
+      printf ("\n");
+
+      if (readp != next_unitp)
+	error (0, 0, "extra %zd bytes at end of unit",
+	       (size_t) (next_unitp - readp));
+
+    next_unit:
+      readp = next_unitp;
+    }
+}
+
+
+/* Print the content of the call frame search table section
+   '.eh_frame_hdr'.  */
+static void
+print_debug_frame_hdr_section (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			       Ebl *ebl __attribute__ ((unused)),
+			       GElf_Ehdr *ehdr __attribute__ ((unused)),
+			       Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  printf (_("\
+\nCall frame search table section [%2zu] '.eh_frame_hdr':\n"),
+	  elf_ndxscn (scn));
+
+  Elf_Data *data = elf_rawdata (scn, NULL);
+
+  if (unlikely (data == NULL))
+    {
+      error (0, 0, _("cannot get %s content: %s"),
+	     ".eh_frame_hdr", elf_errmsg (-1));
+      return;
+    }
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *const dataend = ((unsigned char *) data->d_buf
+					+ data->d_size);
+
+  if (unlikely (readp + 4 > dataend))
+    {
+    invalid_data:
+      error (0, 0, _("invalid data"));
+      return;
+    }
+
+  unsigned int version = *readp++;
+  unsigned int eh_frame_ptr_enc = *readp++;
+  unsigned int fde_count_enc = *readp++;
+  unsigned int table_enc = *readp++;
+
+  printf (" version:          %u\n"
+	  " eh_frame_ptr_enc: %#x ",
+	  version, eh_frame_ptr_enc);
+  print_encoding_base ("", eh_frame_ptr_enc);
+  printf (" fde_count_enc:    %#x ", fde_count_enc);
+  print_encoding_base ("", fde_count_enc);
+  printf (" table_enc:        %#x ", table_enc);
+  print_encoding_base ("", table_enc);
+
+  uint64_t eh_frame_ptr = 0;
+  if (eh_frame_ptr_enc != DW_EH_PE_omit)
+    {
+      readp = read_encoded (eh_frame_ptr_enc, readp, dataend, &eh_frame_ptr,
+			    dbg);
+      if (unlikely (readp == NULL))
+	goto invalid_data;
+
+      printf (" eh_frame_ptr:     %#" PRIx64, eh_frame_ptr);
+      if ((eh_frame_ptr_enc & 0x70) == DW_EH_PE_pcrel)
+	printf (" (offset: %#" PRIx64 ")",
+		/* +4 because of the 4 byte header of the section.  */
+		(uint64_t) shdr->sh_offset + 4 + eh_frame_ptr);
+
+      putchar_unlocked ('\n');
+    }
+
+  uint64_t fde_count = 0;
+  if (fde_count_enc != DW_EH_PE_omit)
+    {
+      readp = read_encoded (fde_count_enc, readp, dataend, &fde_count, dbg);
+      if (unlikely (readp == NULL))
+	goto invalid_data;
+
+      printf (" fde_count:        %" PRIu64 "\n", fde_count);
+    }
+
+  if (fde_count == 0 || table_enc == DW_EH_PE_omit)
+    return;
+
+  puts (" Table:");
+
+  /* Optimize for the most common case.  */
+  if (table_enc == (DW_EH_PE_datarel | DW_EH_PE_sdata4))
+    while (fde_count > 0 && readp + 8 <= dataend)
+      {
+	int32_t initial_location = read_4sbyte_unaligned_inc (dbg, readp);
+	uint64_t initial_offset = ((uint64_t) shdr->sh_offset
+				   + (int64_t) initial_location);
+	int32_t address = read_4sbyte_unaligned_inc (dbg, readp);
+	// XXX Possibly print symbol name or section offset for initial_offset
+	printf ("  %#" PRIx32 " (offset: %#6" PRIx64 ") -> %#" PRIx32
+		" fde=[%6" PRIx64 "]\n",
+		initial_location, initial_offset,
+		address, address - (eh_frame_ptr + 4));
+      }
+  else
+    while (0 && readp < dataend)
+      {
+
+      }
+}
+
+
+/* Print the content of the exception handling table section
+   '.eh_frame_hdr'.  */
+static void
+print_debug_exception_table (Dwfl_Module *dwflmod __attribute__ ((unused)),
+			     Ebl *ebl __attribute__ ((unused)),
+			     GElf_Ehdr *ehdr __attribute__ ((unused)),
+			     Elf_Scn *scn,
+			     GElf_Shdr *shdr __attribute__ ((unused)),
+			     Dwarf *dbg __attribute__ ((unused)))
+{
+  printf (_("\
+\nException handling table section [%2zu] '.gcc_except_table':\n"),
+	  elf_ndxscn (scn));
+
+  Elf_Data *data = elf_rawdata (scn, NULL);
+
+  if (unlikely (data == NULL))
+    {
+      error (0, 0, _("cannot get %s content: %s"),
+	     ".gcc_except_table", elf_errmsg (-1));
+      return;
+    }
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *const dataend = readp + data->d_size;
+
+  if (unlikely (readp + 1 > dataend))
+    {
+    invalid_data:
+      error (0, 0, _("invalid data"));
+      return;
+    }
+  unsigned int lpstart_encoding = *readp++;
+  printf (_(" LPStart encoding:    %#x "), lpstart_encoding);
+  print_encoding_base ("", lpstart_encoding);
+  if (lpstart_encoding != DW_EH_PE_omit)
+    {
+      uint64_t lpstart;
+      readp = read_encoded (lpstart_encoding, readp, dataend, &lpstart, dbg);
+      printf (" LPStart:             %#" PRIx64 "\n", lpstart);
+    }
+
+  if (unlikely (readp + 1 > dataend))
+    goto invalid_data;
+  unsigned int ttype_encoding = *readp++;
+  printf (_(" TType encoding:      %#x "), ttype_encoding);
+  print_encoding_base ("", ttype_encoding);
+  const unsigned char *ttype_base = NULL;
+  if (ttype_encoding != DW_EH_PE_omit)
+    {
+      unsigned int ttype_base_offset;
+      if (readp >= dataend)
+	goto invalid_data;
+      get_uleb128 (ttype_base_offset, readp, dataend);
+      printf (" TType base offset:   %#x\n", ttype_base_offset);
+      if ((size_t) (dataend - readp) > ttype_base_offset)
+        ttype_base = readp + ttype_base_offset;
+    }
+
+  if (unlikely (readp + 1 > dataend))
+    goto invalid_data;
+  unsigned int call_site_encoding = *readp++;
+  printf (_(" Call site encoding:  %#x "), call_site_encoding);
+  print_encoding_base ("", call_site_encoding);
+  unsigned int call_site_table_len;
+  if (readp >= dataend)
+    goto invalid_data;
+  get_uleb128 (call_site_table_len, readp, dataend);
+
+  const unsigned char *const action_table = readp + call_site_table_len;
+  if (unlikely (action_table > dataend))
+    goto invalid_data;
+  unsigned int u = 0;
+  unsigned int max_action = 0;
+  while (readp < action_table)
+    {
+      if (u == 0)
+	puts (_("\n Call site table:"));
+
+      uint64_t call_site_start;
+      readp = read_encoded (call_site_encoding, readp, dataend,
+			    &call_site_start, dbg);
+      uint64_t call_site_length;
+      readp = read_encoded (call_site_encoding, readp, dataend,
+			    &call_site_length, dbg);
+      uint64_t landing_pad;
+      readp = read_encoded (call_site_encoding, readp, dataend,
+			    &landing_pad, dbg);
+      unsigned int action;
+      if (readp >= dataend)
+	goto invalid_data;
+      get_uleb128 (action, readp, dataend);
+      max_action = MAX (action, max_action);
+      printf (_(" [%4u] Call site start:   %#" PRIx64 "\n"
+		       "        Call site length:  %" PRIu64 "\n"
+		       "        Landing pad:       %#" PRIx64 "\n"
+		       "        Action:            %u\n"),
+	      u++, call_site_start, call_site_length, landing_pad, action);
+    }
+  if (readp != action_table)
+    goto invalid_data;
+
+  unsigned int max_ar_filter = 0;
+  if (max_action > 0)
+    {
+      puts ("\n Action table:");
+
+      size_t maxdata = (size_t) (dataend - action_table);
+      if (max_action > maxdata || maxdata - max_action < 1)
+	{
+	invalid_action_table:
+	  fputs (_("   <INVALID DATA>\n"), stdout);
+	  return;
+	}
+
+      const unsigned char *const action_table_end
+	= action_table + max_action + 1;
+
+      u = 0;
+      do
+	{
+	  int ar_filter;
+	  get_sleb128 (ar_filter, readp, action_table_end);
+	  if (ar_filter > 0 && (unsigned int) ar_filter > max_ar_filter)
+	    max_ar_filter = ar_filter;
+	  int ar_disp;
+	  if (readp >= action_table_end)
+	    goto invalid_action_table;
+	  get_sleb128 (ar_disp, readp, action_table_end);
+
+	  printf (" [%4u] ar_filter:  % d\n"
+		  "        ar_disp:    % -5d",
+		  u, ar_filter, ar_disp);
+	  if (abs (ar_disp) & 1)
+	    printf (" -> [%4u]\n", u + (ar_disp + 1) / 2);
+	  else if (ar_disp != 0)
+	    puts (" -> ???");
+	  else
+	    putchar_unlocked ('\n');
+	  ++u;
+	}
+      while (readp < action_table_end);
+    }
+
+  if (max_ar_filter > 0 && ttype_base != NULL)
+    {
+      unsigned char dsize;
+      puts ("\n TType table:");
+
+      // XXX Not *4, size of encoding;
+      switch (ttype_encoding & 7)
+	{
+	case DW_EH_PE_udata2:
+	case DW_EH_PE_sdata2:
+	  dsize = 2;
+	  break;
+	case DW_EH_PE_udata4:
+	case DW_EH_PE_sdata4:
+	  dsize = 4;
+	  break;
+	case DW_EH_PE_udata8:
+	case DW_EH_PE_sdata8:
+	  dsize = 8;
+	  break;
+	default:
+	  dsize = 0;
+	  error (1, 0, _("invalid TType encoding"));
+	}
+
+      if (max_ar_filter
+	  > (size_t) (ttype_base - (const unsigned char *) data->d_buf) / dsize)
+	goto invalid_data;
+
+      readp = ttype_base - max_ar_filter * dsize;
+      do
+	{
+	  uint64_t ttype;
+	  readp = read_encoded (ttype_encoding, readp, ttype_base, &ttype,
+				dbg);
+	  printf (" [%4u] %#" PRIx64 "\n", max_ar_filter--, ttype);
+	}
+      while (readp < ttype_base);
+    }
+}
+
+/* Print the content of the '.gdb_index' section.
+   http://sourceware.org/gdb/current/onlinedocs/gdb/Index-Section-Format.html
+*/
+static void
+print_gdb_index_section (Dwfl_Module *dwflmod, Ebl *ebl,
+			 GElf_Ehdr *ehdr __attribute__ ((unused)),
+			 Elf_Scn *scn, GElf_Shdr *shdr, Dwarf *dbg)
+{
+  printf (_("\nGDB section [%2zu] '%s' at offset %#" PRIx64
+		   " contains %" PRId64 " bytes :\n"),
+	  elf_ndxscn (scn), section_name (ebl, shdr),
+	  (uint64_t) shdr->sh_offset, (uint64_t) shdr->sh_size);
+
+  Elf_Data *data = elf_rawdata (scn, NULL);
+
+  if (unlikely (data == NULL))
+    {
+      error (0, 0, _("cannot get %s content: %s"),
+	     ".gdb_index", elf_errmsg (-1));
+      return;
+    }
+
+  // .gdb_index is always in little endian.
+  Dwarf dummy_dbg = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
+  dbg = &dummy_dbg;
+
+  const unsigned char *readp = data->d_buf;
+  const unsigned char *const dataend = readp + data->d_size;
+
+  if (unlikely (readp + 4 > dataend))
+    {
+    invalid_data:
+      error (0, 0, _("invalid data"));
+      return;
+    }
+
+  int32_t vers = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" Version:         %" PRId32 "\n"), vers);
+
+  // The only difference between version 4 and version 5 is the
+  // hash used for generating the table.  Version 6 contains symbols
+  // for inlined functions, older versions didn't.  Version 7 adds
+  // symbol kinds.  Version 8 just indicates that it correctly includes
+  // TUs for symbols.  Version 9 adds shortcut table for information
+  // regarding the main function.
+  if (vers < 4 || vers > 9)
+    {
+      printf (_("  unknown version, cannot parse section\n"));
+      return;
+    }
+
+  readp += 4;
+  if (unlikely (readp + 4 > dataend))
+    goto invalid_data;
+
+  uint32_t cu_off = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" CU offset:       %#" PRIx32 "\n"), cu_off);
+
+  readp += 4;
+  if (unlikely (readp + 4 > dataend))
+    goto invalid_data;
+
+  uint32_t tu_off = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" TU offset:       %#" PRIx32 "\n"), tu_off);
+
+  readp += 4;
+  if (unlikely (readp + 4 > dataend))
+    goto invalid_data;
+
+  uint32_t addr_off = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" address offset:  %#" PRIx32 "\n"), addr_off);
+
+  readp += 4;
+  if (unlikely (readp + 4 > dataend))
+    goto invalid_data;
+
+  uint32_t sym_off = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" symbol offset:   %#" PRIx32 "\n"), sym_off);
+
+  readp += 4;
+  if (unlikely (readp + 4 > dataend))
+    goto invalid_data;
+
+  uint32_t shortcut_off = 0;
+  if (vers >= 9)
+    {
+      shortcut_off = read_4ubyte_unaligned (dbg, readp);
+      printf (_(" shortcut offset: %#" PRIx32 "\n"), shortcut_off);
+
+      readp += 4;
+      if (unlikely (readp + 4 > dataend))
+	goto invalid_data;
+    }
+
+  uint32_t const_off = read_4ubyte_unaligned (dbg, readp);
+  printf (_(" constant offset: %#" PRIx32 "\n"), const_off);
+
+  if (unlikely ((size_t) (dataend - (const unsigned char *) data->d_buf)
+		< const_off))
+    goto invalid_data;
+
+  readp = data->d_buf + cu_off;
+
+  const unsigned char *nextp = data->d_buf + tu_off;
+  if (tu_off >= data->d_size)
+    goto invalid_data;
+
+  size_t cu_nr = (nextp - readp) / 16;
+
+  printf (_("\n CU list at offset %#" PRIx32
+		   " contains %zu entries:\n"),
+	  cu_off, cu_nr);
+
+  size_t n = 0;
+  while (dataend - readp >= 16 && n < cu_nr)
+    {
+      uint64_t off = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      uint64_t len = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      printf (" [%4zu] start: %0#8" PRIx64
+	      ", length: %5" PRIu64 "\n", n, off, len);
+      n++;
+    }
+
+  readp = data->d_buf + tu_off;
+  nextp = data->d_buf + addr_off;
+  if (addr_off >= data->d_size)
+    goto invalid_data;
+
+  size_t tu_nr = (nextp - readp) / 24;
+
+  printf (_("\n TU list at offset %#" PRIx32
+		   " contains %zu entries:\n"),
+	  tu_off, tu_nr);
+
+  n = 0;
+  while (dataend - readp >= 24 && n < tu_nr)
+    {
+      uint64_t off = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      uint64_t type = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      uint64_t sig = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      printf (" [%4zu] CU offset: %5" PRId64
+	      ", type offset: %5" PRId64
+	      ", signature: %0#8" PRIx64 "\n", n, off, type, sig);
+      n++;
+    }
+
+  readp = data->d_buf + addr_off;
+  nextp = data->d_buf + sym_off;
+  if (sym_off >= data->d_size)
+    goto invalid_data;
+
+  size_t addr_nr = (nextp - readp) / 20;
+
+  printf (_("\n Address list at offset %#" PRIx32
+		   " contains %zu entries:\n"),
+	  addr_off, addr_nr);
+
+  n = 0;
+  while (dataend - readp >= 20 && n < addr_nr)
+    {
+      uint64_t low = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      uint64_t high = read_8ubyte_unaligned (dbg, readp);
+      readp += 8;
+
+      uint32_t idx = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+
+      printf (" [%4zu] ", n);
+      print_dwarf_addr (dwflmod, 8, low, low);
+      printf ("..");
+      print_dwarf_addr (dwflmod, 8, high - 1, high);
+      printf (", CU index: %5" PRId32 "\n", idx);
+      n++;
+    }
+
+  const unsigned char *const_start = data->d_buf + const_off;
+  if (const_off >= data->d_size)
+    goto invalid_data;
+
+  const unsigned char *shortcut_start = NULL;
+  if (vers >= 9)
+    {
+      if (shortcut_off >= data->d_size)
+	goto invalid_data;
+
+      shortcut_start = data->d_buf + shortcut_off;
+      nextp = shortcut_start;
+    }
+  else
+    nextp = const_start;
+
+  readp = data->d_buf + sym_off;
+  size_t sym_nr = (nextp - readp) / 8;
+
+  printf (_("\n Symbol table at offset %#" PRIx32
+		   " contains %zu slots:\n"),
+	  addr_off, sym_nr);
+
+  n = 0;
+  while (dataend - readp >= 8 && n < sym_nr)
+    {
+      uint32_t name = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+
+      uint32_t vector = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+
+      if (name != 0 || vector != 0)
+	{
+	  const unsigned char *sym = const_start + name;
+	  if (unlikely ((size_t) (dataend - const_start) < name
+			|| memchr (sym, '\0', dataend - sym) == NULL))
+	    goto invalid_data;
+
+	  printf (" [%4zu] symbol: %s, CUs: ", n, sym);
+
+	  const unsigned char *readcus = const_start + vector;
+	  if (unlikely ((size_t) (dataend - const_start) < vector))
+	    goto invalid_data;
+	  uint32_t cus = read_4ubyte_unaligned (dbg, readcus);
+	  while (cus--)
+	    {
+	      uint32_t cu_kind, cu, kind;
+	      bool is_static;
+	      readcus += 4;
+	      if (unlikely (readcus + 4 > dataend))
+		goto invalid_data;
+	      cu_kind = read_4ubyte_unaligned (dbg, readcus);
+	      cu = cu_kind & ((1 << 24) - 1);
+	      kind = (cu_kind >> 28) & 7;
+	      is_static = cu_kind & (1U << 31);
+	      if (cu > cu_nr - 1)
+		printf ("%" PRId32 "T", cu - (uint32_t) cu_nr);
+	      else
+		printf ("%" PRId32, cu);
+	      if (kind != 0)
+		{
+		  printf (" (");
+		  switch (kind)
+		    {
+		    case 1:
+		      printf ("type");
+		      break;
+		    case 2:
+		      printf ("var");
+		      break;
+		    case 3:
+		      printf ("func");
+		      break;
+		    case 4:
+		      printf ("other");
+		      break;
+		    default:
+		      printf ("unknown-0x%" PRIx32, kind);
+		      break;
+		    }
+		  printf (":%c)", (is_static ? 'S' : 'G'));
+		}
+	      if (cus > 0)
+		printf (", ");
+	    }
+	  printf ("\n");
+	}
+      n++;
+    }
+
+  if (vers < 9)
+    return;
+
+  if (unlikely (shortcut_start == NULL))
+    goto invalid_data;
+
+  readp = shortcut_start;
+  nextp = const_start;
+  size_t shortcut_nr = (nextp - readp) / 4;
+
+  if (unlikely (shortcut_nr != 2))
+    goto invalid_data;
+
+  printf (_("\nShortcut table at offset %#" PRIx32 " contains %zu slots:\n"),
+	  shortcut_off, shortcut_nr);
+
+  uint32_t lang = read_4ubyte_unaligned (dbg, readp);
+  readp += 4;
+
+  /* Include the hex number of LANG in the output if the language
+     is unknown.  */
+  const char *lang_str = dwarf_lang_string (lang);
+  lang_str = string_or_unknown (lang_str, lang, DW_LANG_lo_user,
+				DW_LANG_hi_user, true);
+
+  printf (_("Language of main: %s\n"), lang_str);
+  printf (_("Name of main: "));
+
+  if (lang != 0)
+    {
+      uint32_t name = read_4ubyte_unaligned (dbg, readp);
+      readp += 4;
+      const unsigned char *sym = const_start + name;
+
+      if (unlikely ((size_t) (dataend - const_start) < name
+		    || memchr (sym, '\0', dataend - sym) == NULL))
+	goto invalid_data;
+
+      printf ("%s\n", sym);
+    }
+  else
+    printf ("<unknown>\n");
+}
+
+/* Returns true and sets split DWARF CU id if there is a split compile
+   unit in the given Dwarf, and no non-split units are found (before it).  */
+static bool
+is_split_dwarf (Dwarf *dbg, uint64_t *id, Dwarf_CU **split_cu)
+{
+  Dwarf_CU *cu = NULL;
+  while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
+    {
+      uint8_t unit_type;
+      if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
+			 id, NULL, NULL) != 0)
+	return false;
+
+      if (unit_type != DW_UT_split_compile && unit_type != DW_UT_split_type)
+	return false;
+
+      /* We really only care about the split compile unit, the types
+	 should be fine and self sufficient.  Also they don't have an
+	 id that we can match with a skeleton unit.  */
+      if (unit_type == DW_UT_split_compile)
+	{
+	  *split_cu = cu;
+	  return true;
+	}
+    }
+
+  return false;
+}
+
+/* Check that there is one and only one Dwfl_Module, return in arg.  */
+static int
+getone_dwflmod (Dwfl_Module *dwflmod,
+	       void **userdata __attribute__ ((unused)),
+	       const char *name __attribute__ ((unused)),
+	       Dwarf_Addr base __attribute__ ((unused)),
+	       void *arg)
+{
+  Dwfl_Module **m = (Dwfl_Module **) arg;
+  if (*m != NULL)
+    return DWARF_CB_ABORT;
+  *m = dwflmod;
+  return DWARF_CB_OK;
+}
+
+static void
+print_debug (Dwfl_Module *dwflmod, Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  /* Used for skeleton file, if necessary for split DWARF.  */
+  Dwfl *skel_dwfl = NULL;
+  Dwfl_Module *skel_mod = NULL;
+  char *skel_name = NULL;
+  Dwarf *split_dbg = NULL;
+  Dwarf_CU *split_cu = NULL;
+
+  /* Before we start the real work get a debug context descriptor.  */
+  Dwarf_Addr dwbias;
+  Dwarf *dbg = dwfl_module_getdwarf (dwflmod, &dwbias);
+  Dwarf dummy_dbg =
+    {
+      .elf = ebl->elf,
+      .other_byte_order = MY_ELFDATA != ehdr->e_ident[EI_DATA]
+    };
+  if (dbg == NULL)
+    {
+      if ((print_debug_sections & ~(section_exception|section_frame)) != 0)
+	error (0, 0, _("cannot get debug context descriptor: %s"),
+	       dwfl_errmsg (-1));
+      dbg = &dummy_dbg;
+    }
+  else
+    {
+      /* If we are asked about a split dwarf (.dwo) file, use the user
+	 provided, or find the corresponding skeleton file. If we got
+	 a skeleton file, replace the given dwflmod and dbg, with one
+	 derived from the skeleton file to provide enough context.  */
+      uint64_t split_id;
+      if (is_split_dwarf (dbg, &split_id, &split_cu))
+	{
+	  if (dwarf_skeleton != NULL)
+	    skel_name = strdup (dwarf_skeleton);
+	  else
+	    {
+	      /* Replace file.dwo with file.o and see if that matches. */
+	      const char *fname;
+	      dwfl_module_info (dwflmod, NULL, NULL, NULL, NULL, NULL,
+				&fname, NULL);
+	      if (fname != NULL)
+		{
+		  size_t flen = strlen (fname);
+		  if (flen > 4 && strcmp (".dwo", fname + flen - 4) == 0)
+		    {
+		      skel_name = strdup (fname);
+		      if (skel_name != NULL)
+			{
+			  skel_name[flen - 3] = 'o';
+			  skel_name[flen - 2] = '\0';
+			}
+		    }
+		}
+	    }
+
+	  if (skel_name != NULL)
+	    {
+	      int skel_fd = open (skel_name, O_RDONLY);
+	      if (skel_fd == -1)
+		fprintf (stderr, "Warning: Couldn't open DWARF skeleton file"
+			 " '%s'\n", skel_name);
+	      else
+		skel_dwfl = create_dwfl (skel_fd, skel_name);
+
+	      if (skel_dwfl != NULL)
+		{
+		  if (dwfl_getmodules (skel_dwfl, &getone_dwflmod,
+				       &skel_mod, 0) != 0)
+		    {
+		      fprintf (stderr, "Warning: Bad DWARF skeleton,"
+			       " multiple modules '%s'\n", skel_name);
+		      dwfl_end (skel_dwfl);
+		      skel_mod = NULL;
+		    }
+		}
+	      else if (skel_fd != -1)
+		fprintf (stderr, "Warning: Couldn't create skeleton dwfl for"
+			 " '%s': %s\n", skel_name, dwfl_errmsg (-1));
+
+	      if (skel_mod != NULL)
+		{
+		  Dwarf *skel_dbg = dwfl_module_getdwarf (skel_mod, &dwbias);
+		  if (skel_dbg != NULL)
+		    {
+		      /* First check the skeleton CU DIE, only fetch
+			 the split DIE if we know the id matches to
+			 not unnecessary search for any split DIEs we
+			 don't need. */
+		      Dwarf_CU *cu = NULL;
+		      while (dwarf_get_units (skel_dbg, cu, &cu,
+					      NULL, NULL, NULL, NULL) == 0)
+			{
+			  uint8_t unit_type;
+			  uint64_t skel_id;
+			  if (dwarf_cu_info (cu, NULL, &unit_type, NULL, NULL,
+					     &skel_id, NULL, NULL) == 0
+			      && unit_type == DW_UT_skeleton
+			      && split_id == skel_id)
+			    {
+			      Dwarf_Die subdie;
+			      if (dwarf_cu_info (cu, NULL, NULL, NULL,
+						 &subdie,
+						 NULL, NULL, NULL) == 0
+				  && dwarf_tag (&subdie) != DW_TAG_invalid)
+				{
+				  split_dbg = dwarf_cu_getdwarf (subdie.cu);
+				  if (split_dbg == NULL)
+				    fprintf (stderr,
+					     "Warning: Couldn't get split_dbg:"
+					     " %s\n", dwarf_errmsg (-1));
+				  break;
+				}
+			      else
+				{
+				  /* Everything matches up, but not
+				     according to libdw. Which means
+				     the user knew better.  So...
+				     Terrible hack... We can never
+				     destroy the underlying dwfl
+				     because it would free the wrong
+				     Dwarfs... So we leak memory...*/
+				  if (cu->split == NULL
+				      && dwarf_skeleton != NULL)
+				    {
+				      do_not_close_dwfl = true;
+				      __libdw_link_skel_split (cu, split_cu);
+				      split_dbg = dwarf_cu_getdwarf (split_cu);
+				      break;
+				    }
+				  else
+				    fprintf (stderr, "Warning: Couldn't get"
+					     " skeleton subdie: %s\n",
+					     dwarf_errmsg (-1));
+				}
+			    }
+			}
+		      if (split_dbg == NULL)
+			fprintf (stderr, "Warning: '%s' didn't contain a skeleton for split id %" PRIx64 "\n", skel_name, split_id);
+		    }
+		  else
+		    fprintf (stderr, "Warning: Couldn't get skeleton DWARF:"
+			     " %s\n", dwfl_errmsg (-1));
+		}
+	    }
+
+	  if (split_dbg != NULL)
+	    {
+	      dbg = split_dbg;
+	      dwflmod = skel_mod;
+	    }
+	  else if (skel_name == NULL)
+	    fprintf (stderr,
+		     "Warning: split DWARF file, but no skeleton found.\n");
+	}
+      else if (dwarf_skeleton != NULL)
+	fprintf (stderr, "Warning: DWARF skeleton given,"
+		 " but not a split DWARF file\n");
+    }
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* If the .debug_info section is listed as implicitly required then
+     we must make sure to handle it before handling any other debug
+     section.  Various other sections depend on the CU DIEs being
+     scanned (silently) first.  */
+  bool implicit_info = (implicit_debug_sections & section_info) != 0;
+  bool explicit_info = (print_debug_sections & section_info) != 0;
+  if (implicit_info)
+    {
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+	  if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
+	    {
+	      const char *name = elf_strptr (ebl->elf, shstrndx,
+					     shdr->sh_name);
+	      if (name == NULL)
+		continue;
+
+	      if (strcmp (name, ".debug_info") == 0
+		  || strcmp (name, ".debug_info.dwo") == 0
+		  || strcmp (name, ".zdebug_info") == 0
+		  || strcmp (name, ".zdebug_info.dwo") == 0
+		  || strcmp (name, ".gnu.debuglto_.debug_info") == 0)
+		{
+		  print_debug_info_section (dwflmod, ebl, ehdr,
+					    scn, shdr, dbg);
+		  break;
+		}
+	    }
+	}
+      print_debug_sections &= ~section_info;
+      implicit_debug_sections &= ~section_info;
+    }
+
+  /* Look through all the sections for the debugging sections to print.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr != NULL && shdr->sh_type == SHT_PROGBITS)
+	{
+	  static const struct
+	  {
+	    const char *name;
+	    enum section_e bitmask;
+	    void (*fp) (Dwfl_Module *, Ebl *,
+			GElf_Ehdr *, Elf_Scn *, GElf_Shdr *, Dwarf *);
+	  } debug_sections[] =
+	    {
+#define NEW_SECTION(name) \
+	      { ".debug_" #name, section_##name, print_debug_##name##_section }
+	      NEW_SECTION (abbrev),
+	      NEW_SECTION (addr),
+	      NEW_SECTION (aranges),
+	      NEW_SECTION (frame),
+	      NEW_SECTION (info),
+	      NEW_SECTION (types),
+	      NEW_SECTION (line),
+	      NEW_SECTION (loc),
+	      /* loclists is loc for DWARF5.  */
+	      { ".debug_loclists", section_loc,
+		print_debug_loclists_section },
+	      NEW_SECTION (pubnames),
+	      NEW_SECTION (str),
+	      /* A DWARF5 specialised debug string section.  */
+	      { ".debug_line_str", section_str,
+		print_debug_str_section },
+	      /* DWARF5 string offsets table.  */
+	      { ".debug_str_offsets", section_str,
+		print_debug_str_offsets_section },
+	      NEW_SECTION (macinfo),
+	      NEW_SECTION (macro),
+	      NEW_SECTION (ranges),
+	      /* rnglists is ranges for DWARF5.  */
+	      { ".debug_rnglists", section_ranges,
+		print_debug_rnglists_section },
+	      { ".eh_frame", section_frame | section_exception,
+		print_debug_frame_section },
+	      { ".eh_frame_hdr", section_frame | section_exception,
+		print_debug_frame_hdr_section },
+	      { ".gcc_except_table", section_frame | section_exception,
+		print_debug_exception_table },
+	      { ".gdb_index", section_gdb_index, print_gdb_index_section }
+	    };
+	  const int ndebug_sections = (sizeof (debug_sections)
+				       / sizeof (debug_sections[0]));
+	  const char *name = elf_strptr (ebl->elf, shstrndx,
+					 shdr->sh_name);
+	  if (name == NULL)
+	    continue;
+
+	  int n;
+	  for (n = 0; n < ndebug_sections; ++n)
+	    {
+	      size_t dbglen = strlen (debug_sections[n].name);
+	      size_t scnlen = strlen (name);
+	      if ((strncmp (name, debug_sections[n].name, dbglen) == 0
+		   && (dbglen == scnlen
+		       || (scnlen == dbglen + 4
+			   && strstr (name, ".dwo") == name + dbglen)))
+		  || (name[0] == '.' && name[1] == 'z'
+		      && debug_sections[n].name[1] == 'd'
+		      && strncmp (&name[2], &debug_sections[n].name[1],
+				  dbglen - 1) == 0
+		      && (scnlen == dbglen + 1
+			  || (scnlen == dbglen + 5
+			      && strstr (name, ".dwo") == name + dbglen + 1)))
+		  || (scnlen > 14 /* .gnu.debuglto_ prefix. */
+		      && startswith (name, ".gnu.debuglto_")
+		      && strcmp (&name[14], debug_sections[n].name) == 0)
+)
+		{
+		  if ((print_debug_sections | implicit_debug_sections)
+		      & debug_sections[n].bitmask)
+		    debug_sections[n].fp (dwflmod, ebl, ehdr, scn, shdr, dbg);
+		  break;
+		}
+	    }
+	}
+    }
+
+  dwfl_end (skel_dwfl);
+  free (skel_name);
+
+  /* Turn implicit and/or explicit back on in case we go over another file.  */
+  if (implicit_info)
+    implicit_debug_sections |= section_info;
+  if (explicit_info)
+    print_debug_sections |= section_info;
+
+  reset_listptr (&known_locsptr);
+  reset_listptr (&known_loclistsptr);
+  reset_listptr (&known_rangelistptr);
+  reset_listptr (&known_rnglistptr);
+  reset_listptr (&known_addrbases);
+  reset_listptr (&known_stroffbases);
+}
+
+
+#define ITEM_INDENT		4
+#define WRAP_COLUMN		75
+
+/* Print "NAME: FORMAT", wrapping when output text would make the line
+   exceed WRAP_COLUMN.  Unpadded numbers look better for the core items
+   but this function is also used for registers which should be printed
+   aligned.  Fortunately registers output uses fixed fields width (such
+   as %11d) for the alignment.
+
+   Line breaks should not depend on the particular values although that
+   may happen in some cases of the core items.  */
+
+static unsigned int
+__attribute__ ((format (printf, 6, 7)))
+print_core_item (unsigned int colno, char sep, unsigned int wrap,
+		 size_t name_width, const char *name, const char *format, ...)
+{
+  size_t len = strlen (name);
+  if (name_width < len)
+    name_width = len;
+
+  char *out;
+  va_list ap;
+  va_start (ap, format);
+  int out_len = vasprintf (&out, format, ap);
+  va_end (ap);
+  if (out_len == -1)
+    error_exit (0, _("memory exhausted"));
+
+  size_t n = name_width + sizeof ": " - 1 + out_len;
+
+  if (colno == 0)
+    {
+      printf ("%*s", ITEM_INDENT, "");
+      colno = ITEM_INDENT + n;
+    }
+  else if (colno + 2 + n < wrap)
+    {
+      printf ("%c ", sep);
+      colno += 2 + n;
+    }
+  else
+    {
+      printf ("\n%*s", ITEM_INDENT, "");
+      colno = ITEM_INDENT + n;
+    }
+
+  printf ("%s: %*s%s", name, (int) (name_width - len), "", out);
+
+  free (out);
+
+  return colno;
+}
+
+static const void *
+convert (Elf *core, Elf_Type type, uint_fast16_t count,
+	 void *value, const void *data, size_t size)
+{
+  Elf_Data valuedata =
+    {
+      .d_type = type,
+      .d_buf = value,
+      .d_size = size ?: gelf_fsize (core, type, count, EV_CURRENT),
+      .d_version = EV_CURRENT,
+    };
+  Elf_Data indata =
+    {
+      .d_type = type,
+      .d_buf = (void *) data,
+      .d_size = valuedata.d_size,
+      .d_version = EV_CURRENT,
+    };
+
+  Elf_Data *d = (gelf_getclass (core) == ELFCLASS32
+		 ? elf32_xlatetom : elf64_xlatetom)
+    (&valuedata, &indata, elf_getident (core, NULL)[EI_DATA]);
+  if (d == NULL)
+    error_exit (0, _("cannot convert core note data: %s"),
+		elf_errmsg (-1));
+
+  return data + indata.d_size;
+}
+
+typedef uint8_t GElf_Byte;
+
+static unsigned int
+handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
+		  unsigned int colno, size_t *repeated_size)
+{
+  uint_fast16_t count = item->count ?: 1;
+  /* Ebl_Core_Item count is always a small number.
+     Make sure the backend didn't put in some large bogus value.  */
+  assert (count < 128);
+
+#define TYPES								      \
+  DO_TYPE (BYTE, Byte, "0x%.2" PRIx8, "%" PRId8);			      \
+  DO_TYPE (HALF, Half, "0x%.4" PRIx16, "%" PRId16);			      \
+  DO_TYPE (WORD, Word, "0x%.8" PRIx32, "%" PRId32);			      \
+  DO_TYPE (SWORD, Sword, "%" PRId32, "%" PRId32);			      \
+  DO_TYPE (XWORD, Xword, "0x%.16" PRIx64, "%" PRId64);			      \
+  DO_TYPE (SXWORD, Sxword, "%" PRId64, "%" PRId64)
+
+#define DO_TYPE(NAME, Name, hex, dec) GElf_##Name Name
+  typedef union { TYPES; } value_t;
+  void *data = alloca (count * sizeof (value_t));
+#undef DO_TYPE
+
+#define DO_TYPE(NAME, Name, hex, dec) \
+    GElf_##Name *value_##Name __attribute__((unused)) = data
+  TYPES;
+#undef DO_TYPE
+
+  size_t size = gelf_fsize (core, item->type, count, EV_CURRENT);
+  size_t convsize = size;
+  if (repeated_size != NULL)
+    {
+      if (*repeated_size > size && (item->format == 'b' || item->format == 'B'))
+	{
+	  data = alloca (*repeated_size);
+	  count *= *repeated_size / size;
+	  convsize = count * size;
+	  *repeated_size -= convsize;
+	}
+      else if (item->count != 0 || item->format != '\n')
+	*repeated_size -= size;
+    }
+
+  convert (core, item->type, count, data, desc + item->offset, convsize);
+
+  Elf_Type type = item->type;
+  if (type == ELF_T_ADDR)
+    type = gelf_getclass (core) == ELFCLASS32 ? ELF_T_WORD : ELF_T_XWORD;
+
+  switch (item->format)
+    {
+    case 'd':
+      assert (count == 1);
+      switch (type)
+	{
+#define DO_TYPE(NAME, Name, hex, dec)					      \
+	  case ELF_T_##NAME:						      \
+	    colno = print_core_item (colno, ',', WRAP_COLUMN,		      \
+				     0, item->name, dec, value_##Name[0]); \
+	    break
+	  TYPES;
+#undef DO_TYPE
+	default:
+	  abort ();
+	}
+      break;
+
+    case 'x':
+      assert (count == 1);
+      switch (type)
+	{
+#define DO_TYPE(NAME, Name, hex, dec)					      \
+	  case ELF_T_##NAME:						      \
+	    colno = print_core_item (colno, ',', WRAP_COLUMN,		      \
+				     0, item->name, hex, value_##Name[0]);      \
+	    break
+	  TYPES;
+#undef DO_TYPE
+	default:
+	  abort ();
+	}
+      break;
+
+    case 'b':
+    case 'B':
+      assert (size % sizeof (unsigned int) == 0);
+      unsigned int nbits = count * size * 8;
+      unsigned int pop = 0;
+      for (const unsigned int *i = data; (void *) i < data + count * size; ++i)
+	pop += __builtin_popcount (*i);
+      bool negate = pop > nbits / 2;
+      const unsigned int bias = item->format == 'b';
+
+      {
+	char printed[(negate ? nbits - pop : pop) * 16 + 1];
+	char *p = printed;
+	*p = '\0';
+
+	if (BYTE_ORDER != LITTLE_ENDIAN && size > sizeof (unsigned int))
+	  {
+	    assert (size == sizeof (unsigned int) * 2);
+	    for (unsigned int *i = data;
+		 (void *) i < data + count * size; i += 2)
+	      {
+		unsigned int w = i[1];
+		i[1] = i[0];
+		i[0] = w;
+	      }
+	  }
+
+	unsigned int lastbit = 0;
+	unsigned int run = 0;
+	for (const unsigned int *i = data;
+	     (void *) i < data + count * size; ++i)
+	  {
+	    unsigned int bit = ((void *) i - data) * 8;
+	    unsigned int w = negate ? ~*i : *i;
+	    while (w != 0)
+	      {
+		/* Note that a right shift equal to (or greater than)
+		   the number of bits of w is undefined behaviour.  In
+		   particular when the least significant bit is bit 32
+		   (w = 0x8000000) then w >>= n is undefined.  So
+		   explicitly handle that case separately.  */
+		unsigned int n = ffs (w);
+		if (n < sizeof (w) * 8)
+		  w >>= n;
+		else
+		  w = 0;
+		bit += n;
+
+		if (lastbit != 0 && lastbit + 1 == bit)
+		  ++run;
+		else
+		  {
+		    if (lastbit == 0)
+		      p += sprintf (p, "%u", bit - bias);
+		    else if (run == 0)
+		      p += sprintf (p, ",%u", bit - bias);
+		    else
+		      p += sprintf (p, "-%u,%u", lastbit - bias, bit - bias);
+		    run = 0;
+		  }
+
+		lastbit = bit;
+	      }
+	  }
+	if (lastbit > 0 && run > 0 && lastbit + 1 != nbits)
+	  p += sprintf (p, "-%u", lastbit - bias);
+
+	colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
+				 negate ? "~<%s>" : "<%s>", printed);
+      }
+      break;
+
+    case 'T':
+    case (char) ('T'|0x80):
+      assert (count == 2);
+      Dwarf_Word sec;
+      Dwarf_Word usec;
+      switch (type)
+	{
+#define DO_TYPE(NAME, Name, hex, dec)					      \
+	  case ELF_T_##NAME:						      \
+	    sec = value_##Name[0];					      \
+	    usec = value_##Name[1];					      \
+	    break
+	  TYPES;
+#undef DO_TYPE
+	default:
+	  abort ();
+	}
+      if (unlikely (item->format == (char) ('T'|0x80)))
+	{
+	  /* This is a hack for an ill-considered 64-bit ABI where
+	     tv_usec is actually a 32-bit field with 32 bits of padding
+	     rounding out struct timeval.  We've already converted it as
+	     a 64-bit field.  For little-endian, this just means the
+	     high half is the padding; it's presumably zero, but should
+	     be ignored anyway.  For big-endian, it means the 32-bit
+	     field went into the high half of USEC.  */
+	  GElf_Ehdr ehdr_mem;
+	  GElf_Ehdr *ehdr = gelf_getehdr (core, &ehdr_mem);
+	  if (likely (ehdr->e_ident[EI_DATA] == ELFDATA2MSB))
+	    usec >>= 32;
+	  else
+	    usec &= UINT32_MAX;
+	}
+      colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
+			       "%" PRIu64 ".%.6" PRIu64, sec, usec);
+      break;
+
+    case 'c':
+      assert (count == 1);
+      colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
+			       "%c", value_Byte[0]);
+      break;
+
+    case 's':
+      colno = print_core_item (colno, ',', WRAP_COLUMN, 0, item->name,
+			       "%.*s", (int) count, value_Byte);
+      break;
+
+    case '\n':
+      /* This is a list of strings separated by '\n'.  */
+      assert (item->count == 0);
+      assert (repeated_size != NULL);
+      assert (item->name == NULL);
+      if (unlikely (item->offset >= *repeated_size))
+	break;
+
+      const char *s = desc + item->offset;
+      size = *repeated_size - item->offset;
+      *repeated_size = 0;
+      while (size > 0)
+	{
+	  const char *eol = memchr (s, '\n', size);
+	  int len = size;
+	  if (eol != NULL)
+	    len = eol - s;
+	  printf ("%*s%.*s\n", ITEM_INDENT, "", len, s);
+	  if (eol == NULL)
+	    break;
+	  size -= eol + 1 - s;
+	  s = eol + 1;
+	}
+
+      colno = WRAP_COLUMN;
+      break;
+
+    case 'h':
+      break;
+
+    default:
+      error (0, 0, "XXX not handling format '%c' for %s",
+	     item->format, item->name);
+      break;
+    }
+
+#undef TYPES
+
+  return colno;
+}
+
+
+/* Sort items by group, and by layout offset within each group.  */
+static int
+compare_core_items (const void *a, const void *b)
+{
+  const Ebl_Core_Item *const *p1 = a;
+  const Ebl_Core_Item *const *p2 = b;
+  const Ebl_Core_Item *item1 = *p1;
+  const Ebl_Core_Item *item2 = *p2;
+
+  return ((item1->group == item2->group ? 0
+	   : strcmp (item1->group, item2->group))
+	  ?: (int) item1->offset - (int) item2->offset);
+}
+
+/* Sort item groups by layout offset of the first item in the group.  */
+static int
+compare_core_item_groups (const void *a, const void *b)
+{
+  const Ebl_Core_Item *const *const *p1 = a;
+  const Ebl_Core_Item *const *const *p2 = b;
+  const Ebl_Core_Item *const *group1 = *p1;
+  const Ebl_Core_Item *const *group2 = *p2;
+  const Ebl_Core_Item *item1 = *group1;
+  const Ebl_Core_Item *item2 = *group2;
+
+  return (int) item1->offset - (int) item2->offset;
+}
+
+static unsigned int
+handle_core_items (Elf *core, const void *desc, size_t descsz,
+		   const Ebl_Core_Item *items, size_t nitems)
+{
+  if (nitems == 0)
+    return 0;
+  unsigned int colno = 0;
+
+  /* FORMAT '\n' makes sense to be present only as a single item as it
+     processes all the data of a note.  FORMATs 'b' and 'B' have a special case
+     if present as a single item but they can be also processed with other
+     items below.  */
+  if (nitems == 1 && (items[0].format == '\n' || items[0].format == 'b'
+		      || items[0].format == 'B'))
+    {
+      assert (items[0].offset == 0);
+      size_t size = descsz;
+      colno = handle_core_item (core, items, desc, colno, &size);
+      /* If SIZE is not zero here there is some remaining data.  But we do not
+	 know how to process it anyway.  */
+      return colno;
+    }
+  for (size_t i = 0; i < nitems; ++i)
+    assert (items[i].format != '\n');
+
+  /* Sort to collect the groups together.  */
+  const Ebl_Core_Item *sorted_items[nitems];
+  for (size_t i = 0; i < nitems; ++i)
+    sorted_items[i] = &items[i];
+  qsort (sorted_items, nitems, sizeof sorted_items[0], &compare_core_items);
+
+  /* Collect the unique groups and sort them.  */
+  const Ebl_Core_Item **groups[nitems];
+  groups[0] = &sorted_items[0];
+  size_t ngroups = 1;
+  for (size_t i = 1; i < nitems; ++i)
+    if (sorted_items[i]->group != sorted_items[i - 1]->group
+	&& strcmp (sorted_items[i]->group, sorted_items[i - 1]->group))
+      groups[ngroups++] = &sorted_items[i];
+  qsort (groups, ngroups, sizeof groups[0], &compare_core_item_groups);
+
+  /* Write out all the groups.  */
+  const void *last = desc;
+  do
+    {
+      for (size_t i = 0; i < ngroups; ++i)
+	{
+	  for (const Ebl_Core_Item **item = groups[i];
+	       (item < &sorted_items[nitems]
+		&& ((*item)->group == groups[i][0]->group
+		    || !strcmp ((*item)->group, groups[i][0]->group)));
+	       ++item)
+	    colno = handle_core_item (core, *item, desc, colno, NULL);
+
+	  /* Force a line break at the end of the group.  */
+	  colno = WRAP_COLUMN;
+	}
+
+      if (descsz == 0)
+	break;
+
+      /* This set of items consumed a certain amount of the note's data.
+	 If there is more data there, we have another unit of the same size.
+	 Loop to print that out too.  */
+      const Ebl_Core_Item *item = &items[nitems - 1];
+      size_t eltsz = item->offset + gelf_fsize (core, item->type,
+						item->count ?: 1, EV_CURRENT);
+
+      int reps = -1;
+      do
+	{
+	  ++reps;
+	  desc += eltsz;
+	  descsz -= eltsz;
+	}
+      while (descsz >= eltsz && !memcmp (desc, last, eltsz));
+
+      if (reps == 1)
+	{
+	  /* For just one repeat, print it unabridged twice.  */
+	  desc -= eltsz;
+	  descsz += eltsz;
+	}
+      else if (reps > 1)
+	printf (_("\n%*s... <repeats %u more times> ..."),
+		ITEM_INDENT, "", reps);
+
+      last = desc;
+    }
+  while (descsz > 0);
+
+  return colno;
+}
+
+static unsigned int
+handle_core_register (Ebl *ebl, Elf *core, int maxregname,
+		      const Ebl_Register_Location *regloc, const void *desc,
+		      unsigned int colno)
+{
+  if (regloc->bits % 8 != 0)
+    {
+      error (0, 0, "Warning: Cannot handle register with %" PRIu8 "bits\n",
+	     regloc->bits);
+      return colno;
+    }
+
+  desc += regloc->offset;
+
+  for (int reg = regloc->regno; reg < regloc->regno + regloc->count; ++reg)
+    {
+      char name[REGNAMESZ];
+      int bits;
+      int type;
+      register_info (ebl, reg, regloc, name, &bits, &type);
+
+#define TYPES								      \
+      BITS (8, BYTE, "%4" PRId8, "0x%.2" PRIx8);			      \
+      BITS (16, HALF, "%6" PRId16, "0x%.4" PRIx16);			      \
+      BITS (32, WORD, "%11" PRId32, " 0x%.8" PRIx32);			      \
+      BITS (64, XWORD, "%20" PRId64, "  0x%.16" PRIx64)
+
+#define BITS(bits, xtype, sfmt, ufmt)				\
+      uint##bits##_t b##bits; int##bits##_t b##bits##s
+      union { TYPES; uint64_t b128[2]; } value;
+#undef	BITS
+
+      switch (type)
+	{
+	case DW_ATE_unsigned:
+	case DW_ATE_signed:
+	case DW_ATE_address:
+	  switch (bits)
+	    {
+#define BITS(bits, xtype, sfmt, ufmt)					      \
+	    case bits:							      \
+	      desc = convert (core, ELF_T_##xtype, 1, &value, desc, 0);	      \
+	      if (type == DW_ATE_signed)				      \
+		colno = print_core_item (colno, ' ', WRAP_COLUMN,	      \
+					 maxregname, name,		      \
+					 sfmt, value.b##bits##s);	      \
+	      else							      \
+		colno = print_core_item (colno, ' ', WRAP_COLUMN,	      \
+					 maxregname, name,		      \
+					 ufmt, value.b##bits);		      \
+	      break
+
+	    TYPES;
+
+	    case 128:
+	      assert (type == DW_ATE_unsigned);
+	      desc = convert (core, ELF_T_XWORD, 2, &value, desc, 0);
+	      int be = elf_getident (core, NULL)[EI_DATA] == ELFDATA2MSB;
+	      colno = print_core_item (colno, ' ', WRAP_COLUMN,
+				       maxregname, name,
+				       "0x%.16" PRIx64 "%.16" PRIx64,
+				       value.b128[!be], value.b128[be]);
+	      break;
+
+	    default:
+	      abort ();
+#undef	BITS
+	    }
+	  break;
+
+	default:
+	  /* Print each byte in hex, the whole thing in native byte order.  */
+	  assert (bits % 8 == 0);
+	  const uint8_t *bytes = desc;
+	  desc += bits / 8;
+	  char hex[bits / 4 + 1];
+	  hex[bits / 4] = '\0';
+	  int incr = 1;
+	  if (elf_getident (core, NULL)[EI_DATA] == ELFDATA2LSB)
+	    {
+	      bytes += bits / 8 - 1;
+	      incr = -1;
+	    }
+	  size_t idx = 0;
+	  for (char *h = hex; bits > 0; bits -= 8, idx += incr)
+	    {
+	      *h++ = "0123456789abcdef"[bytes[idx] >> 4];
+	      *h++ = "0123456789abcdef"[bytes[idx] & 0xf];
+	    }
+	  colno = print_core_item (colno, ' ', WRAP_COLUMN,
+				   maxregname, name, "0x%s", hex);
+	  break;
+	}
+      desc += regloc->pad;
+
+#undef TYPES
+    }
+
+  return colno;
+}
+
+
+struct register_info
+{
+  const Ebl_Register_Location *regloc;
+  const char *set;
+  char name[REGNAMESZ];
+  int regno;
+  int bits;
+  int type;
+};
+
+static int
+register_bitpos (const struct register_info *r)
+{
+  return (r->regloc->offset * 8
+	  + ((r->regno - r->regloc->regno)
+	     * (r->regloc->bits + r->regloc->pad * 8)));
+}
+
+static int
+compare_sets_by_info (const struct register_info *r1,
+		      const struct register_info *r2)
+{
+  return ((int) r2->bits - (int) r1->bits
+	  ?: register_bitpos (r1) - register_bitpos (r2));
+}
+
+/* Sort registers by set, and by size and layout offset within each set.  */
+static int
+compare_registers (const void *a, const void *b)
+{
+  const struct register_info *r1 = a;
+  const struct register_info *r2 = b;
+
+  /* Unused elements sort last.  */
+  if (r1->regloc == NULL)
+    return r2->regloc == NULL ? 0 : 1;
+  if (r2->regloc == NULL)
+    return -1;
+
+  return ((r1->set == r2->set ? 0 : strcmp (r1->set, r2->set))
+	  ?: compare_sets_by_info (r1, r2));
+}
+
+/* Sort register sets by layout offset of the first register in the set.  */
+static int
+compare_register_sets (const void *a, const void *b)
+{
+  const struct register_info *const *p1 = a;
+  const struct register_info *const *p2 = b;
+  return compare_sets_by_info (*p1, *p2);
+}
+
+static inline bool
+same_set (const struct register_info *a,
+	  const struct register_info *b,
+	  const struct register_info *regs,
+	  size_t maxnreg)
+{
+  return (a < &regs[maxnreg] && a->regloc != NULL
+	  && b < &regs[maxnreg] && b->regloc != NULL
+	  && a->bits == b->bits
+	  && (a->set == b->set || !strcmp (a->set, b->set)));
+}
+
+static unsigned int
+handle_core_registers (Ebl *ebl, Elf *core, const void *desc,
+		       const Ebl_Register_Location *reglocs, size_t nregloc)
+{
+  if (nregloc == 0)
+    return 0;
+
+  ssize_t maxnreg = ebl_register_info (ebl, 0, NULL, 0, NULL, NULL, NULL, NULL);
+  if (maxnreg <= 0)
+    {
+      for (size_t i = 0; i < nregloc; ++i)
+	if (maxnreg < reglocs[i].regno + reglocs[i].count)
+	  maxnreg = reglocs[i].regno + reglocs[i].count;
+      assert (maxnreg > 0);
+    }
+
+  struct register_info regs[maxnreg];
+  memset (regs, 0, sizeof regs);
+
+  /* Sort to collect the sets together.  */
+  int maxreg = 0;
+  for (size_t i = 0; i < nregloc; ++i)
+    for (int reg = reglocs[i].regno;
+	 reg < reglocs[i].regno + reglocs[i].count;
+	 ++reg)
+      {
+	assert (reg < maxnreg);
+	if (reg > maxreg)
+	  maxreg = reg;
+	struct register_info *info = &regs[reg];
+	info->regloc = &reglocs[i];
+	info->regno = reg;
+	info->set = register_info (ebl, reg, &reglocs[i],
+				   info->name, &info->bits, &info->type);
+      }
+  qsort (regs, maxreg + 1, sizeof regs[0], &compare_registers);
+
+  /* Collect the unique sets and sort them.  */
+  struct register_info *sets[maxreg + 1];
+  sets[0] = &regs[0];
+  size_t nsets = 1;
+  for (int i = 1; i <= maxreg; ++i)
+    if (regs[i].regloc != NULL
+	&& !same_set (&regs[i], &regs[i - 1], regs, maxnreg))
+      sets[nsets++] = &regs[i];
+  qsort (sets, nsets, sizeof sets[0], &compare_register_sets);
+
+  /* Write out all the sets.  */
+  unsigned int colno = 0;
+  for (size_t i = 0; i < nsets; ++i)
+    {
+      /* Find the longest name of a register in this set.  */
+      size_t maxname = 0;
+      const struct register_info *end;
+      for (end = sets[i]; same_set (sets[i], end, regs, maxnreg); ++end)
+	{
+	  size_t len = strlen (end->name);
+	  if (len > maxname)
+	    maxname = len;
+	}
+
+      for (const struct register_info *reg = sets[i];
+	   reg < end;
+	   reg += reg->regloc->count ?: 1)
+	colno = handle_core_register (ebl, core, maxname,
+				      reg->regloc, desc, colno);
+
+      /* Force a line break at the end of the group.  */
+      colno = WRAP_COLUMN;
+    }
+
+  return colno;
+}
+
+static void
+handle_auxv_note (Ebl *ebl, Elf *core, GElf_Word descsz, GElf_Off desc_pos)
+{
+  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_AUXV);
+  if (data == NULL)
+  elf_error:
+    error_exit (0, _("cannot convert core note data: %s"), elf_errmsg (-1));
+
+  const size_t nauxv = descsz / gelf_fsize (core, ELF_T_AUXV, 1, EV_CURRENT);
+  for (size_t i = 0; i < nauxv; ++i)
+    {
+      GElf_auxv_t av_mem;
+      GElf_auxv_t *av = gelf_getauxv (data, i, &av_mem);
+      if (av == NULL)
+	goto elf_error;
+
+      const char *name;
+      const char *fmt;
+      if (ebl_auxv_info (ebl, av->a_type, &name, &fmt) == 0)
+	{
+	  /* Unknown type.  */
+	  if (av->a_un.a_val == 0)
+	    printf ("    %" PRIu64 "\n", av->a_type);
+	  else
+	    printf ("    %" PRIu64 ": %#" PRIx64 "\n",
+		    av->a_type, av->a_un.a_val);
+	}
+      else
+	switch (fmt[0])
+	  {
+	  case '\0':		/* Normally zero.  */
+	    if (av->a_un.a_val == 0)
+	      {
+		printf ("    %s\n", name);
+		break;
+	      }
+	    FALLTHROUGH;
+	  case 'x':		/* hex */
+	  case 'p':		/* address */
+	  case 's':		/* address of string */
+	    printf ("    %s: %#" PRIx64 "\n", name, av->a_un.a_val);
+	    break;
+	  case 'u':
+	    printf ("    %s: %" PRIu64 "\n", name, av->a_un.a_val);
+	    break;
+	  case 'd':
+	    printf ("    %s: %" PRId64 "\n", name, av->a_un.a_val);
+	    break;
+
+	  case 'b':
+	    printf ("    %s: %#" PRIx64 "  ", name, av->a_un.a_val);
+	    GElf_Xword bit = 1;
+	    const char *pfx = "<";
+	    for (const char *p = fmt + 1; *p != 0; p = strchr (p, '\0') + 1)
+	      {
+		if (av->a_un.a_val & bit)
+		  {
+		    printf ("%s%s", pfx, p);
+		    pfx = " ";
+		  }
+		bit <<= 1;
+	      }
+	    printf (">\n");
+	    break;
+
+	  default:
+	    abort ();
+	  }
+    }
+}
+
+static bool
+buf_has_data (unsigned char const *ptr, unsigned char const *end, size_t sz)
+{
+  return ptr < end && (size_t) (end - ptr) >= sz;
+}
+
+static bool
+buf_read_int (Elf *core, unsigned char const **ptrp, unsigned char const *end,
+	      int *retp)
+{
+  if (! buf_has_data (*ptrp, end, 4))
+    return false;
+
+  *ptrp = convert (core, ELF_T_WORD, 1, retp, *ptrp, 4);
+  return true;
+}
+
+static bool
+buf_read_ulong (Elf *core, unsigned char const **ptrp, unsigned char const *end,
+		uint64_t *retp)
+{
+  size_t sz = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
+  if (! buf_has_data (*ptrp, end, sz))
+    return false;
+
+  union
+  {
+    uint64_t u64;
+    uint32_t u32;
+  } u;
+
+  *ptrp = convert (core, ELF_T_ADDR, 1, &u, *ptrp, sz);
+
+  if (sz == 4)
+    *retp = u.u32;
+  else
+    *retp = u.u64;
+  return true;
+}
+
+static void
+handle_siginfo_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
+{
+  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
+  if (data == NULL)
+    error_exit (0, _("cannot convert core note data: %s"), elf_errmsg (-1));
+
+  unsigned char const *ptr = data->d_buf;
+  unsigned char const *const end = data->d_buf + data->d_size;
+
+  /* Siginfo head is three ints: signal number, error number, origin
+     code.  */
+  int si_signo, si_errno, si_code;
+  if (! buf_read_int (core, &ptr, end, &si_signo)
+      || ! buf_read_int (core, &ptr, end, &si_errno)
+      || ! buf_read_int (core, &ptr, end, &si_code))
+    {
+    fail:
+      printf ("    Not enough data in NT_SIGINFO note.\n");
+      return;
+    }
+
+  /* Next is a pointer-aligned union of structures.  On 64-bit
+     machines, that implies a word of padding.  */
+  if (gelf_getclass (core) == ELFCLASS64)
+    ptr += 4;
+
+  printf ("    si_signo: %d, si_errno: %d, si_code: %d\n",
+	  si_signo, si_errno, si_code);
+
+  if (si_code > 0)
+    switch (si_signo)
+      {
+      case CORE_SIGILL:
+      case CORE_SIGFPE:
+      case CORE_SIGSEGV:
+      case CORE_SIGBUS:
+	{
+	  uint64_t addr;
+	  if (! buf_read_ulong (core, &ptr, end, &addr))
+	    goto fail;
+	  printf ("    fault address: %#" PRIx64 "\n", addr);
+	  break;
+	}
+      default:
+	;
+      }
+  else if (si_code == CORE_SI_USER)
+    {
+      int pid, uid;
+      if (! buf_read_int (core, &ptr, end, &pid)
+	  || ! buf_read_int (core, &ptr, end, &uid))
+	goto fail;
+      printf ("    sender PID: %d, sender UID: %d\n", pid, uid);
+    }
+}
+
+static void
+handle_file_note (Elf *core, GElf_Word descsz, GElf_Off desc_pos)
+{
+  Elf_Data *data = elf_getdata_rawchunk (core, desc_pos, descsz, ELF_T_BYTE);
+  if (data == NULL)
+    error_exit (0, _("cannot convert core note data: %s"), elf_errmsg (-1));
+
+  unsigned char const *ptr = data->d_buf;
+  unsigned char const *const end = data->d_buf + data->d_size;
+
+  uint64_t count, page_size;
+  if (! buf_read_ulong (core, &ptr, end, &count)
+      || ! buf_read_ulong (core, &ptr, end, &page_size))
+    {
+    fail:
+      printf ("    Not enough data in NT_FILE note.\n");
+      return;
+    }
+
+  size_t addrsize = gelf_fsize (core, ELF_T_ADDR, 1, EV_CURRENT);
+  uint64_t maxcount = (size_t) (end - ptr) / (3 * addrsize);
+  if (count > maxcount)
+    goto fail;
+
+  /* Where file names are stored.  */
+  unsigned char const *const fstart = ptr + 3 * count * addrsize;
+  char const *fptr = (char *) fstart;
+
+  printf ("    %" PRId64 " files:\n", count);
+  for (uint64_t i = 0; i < count; ++i)
+    {
+      uint64_t mstart, mend, moffset;
+      if (! buf_read_ulong (core, &ptr, fstart, &mstart)
+	  || ! buf_read_ulong (core, &ptr, fstart, &mend)
+	  || ! buf_read_ulong (core, &ptr, fstart, &moffset))
+	goto fail;
+
+      const char *fnext = memchr (fptr, '\0', (char *) end - fptr);
+      if (fnext == NULL)
+	goto fail;
+
+      int ct = printf ("      %08" PRIx64 "-%08" PRIx64
+		       " %08" PRIx64 " %" PRId64,
+		       mstart, mend, moffset * page_size, mend - mstart);
+      printf ("%*s%s\n", ct > 50 ? 3 : 53 - ct, "", fptr);
+
+      fptr = fnext + 1;
+    }
+}
+
+static void
+handle_core_note (Ebl *ebl, const GElf_Nhdr *nhdr,
+		  const char *name, const void *desc)
+{
+  GElf_Word regs_offset;
+  size_t nregloc;
+  const Ebl_Register_Location *reglocs;
+  size_t nitems;
+  const Ebl_Core_Item *items;
+
+  if (! ebl_core_note (ebl, nhdr, name, desc,
+		       &regs_offset, &nregloc, &reglocs, &nitems, &items))
+    return;
+
+  /* Pass 0 for DESCSZ when there are registers in the note,
+     so that the ITEMS array does not describe the whole thing.
+     For non-register notes, the actual descsz might be a multiple
+     of the unit size, not just exactly the unit size.  */
+  unsigned int colno = handle_core_items (ebl->elf, desc,
+					  nregloc == 0 ? nhdr->n_descsz : 0,
+					  items, nitems);
+  if (colno != 0)
+    putchar_unlocked ('\n');
+
+  colno = handle_core_registers (ebl, ebl->elf, desc + regs_offset,
+				 reglocs, nregloc);
+  if (colno != 0)
+    putchar_unlocked ('\n');
+}
+
+static void
+handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
+		   GElf_Off start, Elf_Data *data)
+{
+  fputs_unlocked (_("  Owner          Data size  Type\n"), stdout);
+
+  if (data == NULL)
+    goto bad_note;
+
+  size_t offset = 0;
+  GElf_Nhdr nhdr;
+  size_t name_offset;
+  size_t desc_offset;
+  while (offset < data->d_size
+	 && (offset = gelf_getnote (data, offset,
+				    &nhdr, &name_offset, &desc_offset)) > 0)
+    {
+      const char *name = nhdr.n_namesz == 0 ? "" : data->d_buf + name_offset;
+      const char *desc = data->d_buf + desc_offset;
+
+      /* GNU Build Attributes are weird, they store most of their data
+	 into the owner name field.  Extract just the owner name
+	 prefix here, then use the rest later as data.  */
+      bool is_gnu_build_attr
+	= startswith (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX);
+      const char *print_name = (is_gnu_build_attr
+				? ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX : name);
+      size_t print_namesz = (is_gnu_build_attr
+			     ? strlen (print_name) : nhdr.n_namesz);
+
+      char buf[100];
+      char buf2[100];
+      printf (_("  %-13.*s  %9" PRId32 "  %s\n"),
+	      (int) print_namesz, print_name, nhdr.n_descsz,
+	      ehdr->e_type == ET_CORE
+	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
+					 buf, sizeof (buf))
+	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
+					   nhdr.n_descsz,
+					   buf2, sizeof (buf2)));
+
+      /* Filter out invalid entries.  */
+      if (memchr (name, '\0', nhdr.n_namesz) != NULL
+	  /* XXX For now help broken Linux kernels.  */
+	  || 1)
+	{
+	  if (ehdr->e_type == ET_CORE)
+	    {
+	      if (nhdr.n_type == NT_AUXV
+		  && (nhdr.n_namesz == 4 /* Broken old Linux kernels.  */
+		      || (nhdr.n_namesz == 5 && name[4] == '\0'))
+		  && !memcmp (name, "CORE", 4))
+		handle_auxv_note (ebl, ebl->elf, nhdr.n_descsz,
+				  start + desc_offset);
+	      else if (nhdr.n_namesz == 5 && strcmp (name, "CORE") == 0)
+		switch (nhdr.n_type)
+		  {
+		  case NT_SIGINFO:
+		    handle_siginfo_note (ebl->elf, nhdr.n_descsz,
+					 start + desc_offset);
+		    break;
+
+		  case NT_FILE:
+		    handle_file_note (ebl->elf, nhdr.n_descsz,
+				      start + desc_offset);
+		    break;
+
+		  default:
+		    handle_core_note (ebl, &nhdr, name, desc);
+		  }
+	      else
+		handle_core_note (ebl, &nhdr, name, desc);
+	    }
+	  else
+	    ebl_object_note (ebl, nhdr.n_namesz, name, nhdr.n_type,
+			     nhdr.n_descsz, desc);
+	}
+    }
+
+  if (offset == data->d_size)
+    return;
+
+ bad_note:
+  error (0, 0,
+	 _("cannot get content of note: %s"),
+	 data != NULL ? "garbage data" : elf_errmsg (-1));
+}
+
+static void
+handle_notes (Ebl *ebl, GElf_Ehdr *ehdr)
+{
+  /* If we have section headers, just look for SHT_NOTE sections.
+     In a debuginfo file, the program headers are not reliable.  */
+  if (shnum != 0)
+    {
+      /* Get the section header string table index.  */
+      size_t shstrndx;
+      if (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0)
+	error_exit (0, _("cannot get section header string table index"));
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+	{
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+	  if (shdr == NULL || shdr->sh_type != SHT_NOTE)
+	    /* Not what we are looking for.  */
+	    continue;
+
+	  if (notes_section != NULL)
+	    {
+	      char *sname = elf_strptr (ebl->elf, shstrndx, shdr->sh_name);
+	      if (sname == NULL || strcmp (sname, notes_section) != 0)
+		continue;
+	    }
+
+	  printf (_("\
+\nNote section [%2zu] '%s' of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
+		  elf_ndxscn (scn),
+		  elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
+		  shdr->sh_size, shdr->sh_offset);
+
+	  handle_notes_data (ebl, ehdr, shdr->sh_offset,
+			     elf_getdata (scn, NULL));
+	}
+      return;
+    }
+
+  /* We have to look through the program header to find the note
+     sections.  There can be more than one.  */
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    {
+      GElf_Phdr mem;
+      GElf_Phdr *phdr = gelf_getphdr (ebl->elf, cnt, &mem);
+
+      if (phdr == NULL || phdr->p_type != PT_NOTE)
+	/* Not what we are looking for.  */
+	continue;
+
+      printf (_("\
+\nNote segment of %" PRIu64 " bytes at offset %#0" PRIx64 ":\n"),
+	      phdr->p_filesz, phdr->p_offset);
+
+      handle_notes_data (ebl, ehdr, phdr->p_offset,
+			 elf_getdata_rawchunk (ebl->elf,
+					       phdr->p_offset, phdr->p_filesz,
+					       (phdr->p_align == 8
+						? ELF_T_NHDR8 : ELF_T_NHDR)));
+    }
+}
+
+
+static void
+hex_dump (const uint8_t *data, size_t len)
+{
+  size_t pos = 0;
+  while (pos < len)
+    {
+      printf ("  0x%08zx ", pos);
+
+      const size_t chunk = MIN (len - pos, 16);
+
+      for (size_t i = 0; i < chunk; ++i)
+	if (i % 4 == 3)
+	  printf ("%02x ", data[pos + i]);
+	else
+	  printf ("%02x", data[pos + i]);
+
+      if (chunk < 16)
+	printf ("%*s", (int) ((16 - chunk) * 2 + (16 - chunk + 3) / 4), "");
+
+      for (size_t i = 0; i < chunk; ++i)
+	{
+	  unsigned char b = data[pos + i];
+	  printf ("%c", isprint (b) ? b : '.');
+	}
+
+      putchar ('\n');
+      pos += chunk;
+    }
+}
+
+static void
+dump_data_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
+{
+  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
+    printf (_("\nSection [%zu] '%s' has no data to dump.\n"),
+	    elf_ndxscn (scn), name);
+  else
+    {
+      if (print_decompress)
+	{
+	  /* We try to decompress the section, but keep the old shdr around
+	     so we can show both the original shdr size and the uncompressed
+	     data size.   */
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      if (elf_compress (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	    }
+	  else if (startswith (name, ".zdebug"))
+	    {
+	      if (elf_compress_gnu (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	    }
+	}
+
+      Elf_Data *data = elf_rawdata (scn, NULL);
+      if (data == NULL)
+	error (0, 0, _("cannot get data for section [%zu] '%s': %s"),
+	       elf_ndxscn (scn), name, elf_errmsg (-1));
+      else
+	{
+	  if (data->d_size == shdr->sh_size)
+	    printf (_("\nHex dump of section [%zu] '%s', %" PRIu64
+			     " bytes at offset %#0" PRIx64 ":\n"),
+		    elf_ndxscn (scn), name,
+		    shdr->sh_size, shdr->sh_offset);
+	  else
+	    printf (_("\nHex dump of section [%zu] '%s', %" PRIu64
+			     " bytes (%zd uncompressed) at offset %#0"
+			     PRIx64 ":\n"),
+		    elf_ndxscn (scn), name,
+		    shdr->sh_size, data->d_size, shdr->sh_offset);
+	  hex_dump (data->d_buf, data->d_size);
+	}
+    }
+}
+
+static void
+print_string_section (Elf_Scn *scn, const GElf_Shdr *shdr, const char *name)
+{
+  if (shdr->sh_size == 0 || shdr->sh_type == SHT_NOBITS)
+    printf (_("\nSection [%zu] '%s' has no strings to dump.\n"),
+	    elf_ndxscn (scn), name);
+  else
+    {
+      if (print_decompress)
+	{
+	  /* We try to decompress the section, but keep the old shdr around
+	     so we can show both the original shdr size and the uncompressed
+	     data size.  */
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      if (elf_compress (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	    }
+	  else if (startswith (name, ".zdebug"))
+	    {
+	      if (elf_compress_gnu (scn, 0, 0) < 0)
+		printf ("WARNING: %s [%zd]\n",
+			_("Couldn't uncompress section"),
+			elf_ndxscn (scn));
+	    }
+	}
+
+      Elf_Data *data = elf_rawdata (scn, NULL);
+      if (data == NULL)
+	error (0, 0, _("cannot get data for section [%zu] '%s': %s"),
+	       elf_ndxscn (scn), name, elf_errmsg (-1));
+      else
+	{
+	  if (data->d_size == shdr->sh_size)
+	    printf (_("\nString section [%zu] '%s' contains %" PRIu64
+			     " bytes at offset %#0" PRIx64 ":\n"),
+		    elf_ndxscn (scn), name,
+		    shdr->sh_size, shdr->sh_offset);
+	  else
+	    printf (_("\nString section [%zu] '%s' contains %" PRIu64
+			     " bytes (%zd uncompressed) at offset %#0"
+			     PRIx64 ":\n"),
+		    elf_ndxscn (scn), name,
+		    shdr->sh_size, data->d_size, shdr->sh_offset);
+
+	  const char *start = data->d_buf;
+	  const char *const limit = start + data->d_size;
+	  do
+	    {
+	      const char *end = memchr (start, '\0', limit - start);
+	      const size_t pos = start - (const char *) data->d_buf;
+	      if (unlikely (end == NULL))
+		{
+		  printf ("  [%6zx]- %.*s\n",
+			  pos, (int) (limit - start), start);
+		  break;
+		}
+	      printf ("  [%6zx]  %s\n", pos, start);
+	      start = end + 1;
+	    } while (start < limit);
+	}
+    }
+}
+
+static void
+for_each_section_argument (Elf *elf, const struct section_argument *list,
+			   void (*dump) (Elf_Scn *scn, const GElf_Shdr *shdr,
+					 const char *name))
+{
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+    error_exit (0, _("cannot get section header string table index"));
+
+  for (const struct section_argument *a = list; a != NULL; a = a->next)
+    {
+      Elf_Scn *scn;
+      GElf_Shdr shdr_mem;
+      const char *name = NULL;
+
+      char *endp = NULL;
+      unsigned long int shndx = strtoul (a->arg, &endp, 0);
+      if (endp != a->arg && *endp == '\0')
+	{
+	  scn = elf_getscn (elf, shndx);
+	  if (scn == NULL)
+	    {
+	      error (0, 0, _("\nsection [%lu] does not exist"), shndx);
+	      continue;
+	    }
+
+	  if (gelf_getshdr (scn, &shdr_mem) == NULL)
+	    error_exit (0, _("cannot get section header: %s"),
+			elf_errmsg (-1));
+	  name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
+	  (*dump) (scn, &shdr_mem, name);
+	}
+      else
+	{
+	  /* Need to look up the section by name.  */
+	  scn = NULL;
+	  bool found = false;
+	  while ((scn = elf_nextscn (elf, scn)) != NULL)
+	    {
+	      if (gelf_getshdr (scn, &shdr_mem) == NULL)
+		continue;
+	      name = elf_strptr (elf, shstrndx, shdr_mem.sh_name);
+	      if (name == NULL)
+		continue;
+	      if (!strcmp (name, a->arg))
+		{
+		  found = true;
+		  (*dump) (scn, &shdr_mem, name);
+		}
+	    }
+
+	  if (unlikely (!found) && !a->implicit)
+	    error (0, 0, _("\nsection '%s' does not exist"), a->arg);
+	}
+    }
+}
+
+static void
+dump_data (Ebl *ebl)
+{
+  for_each_section_argument (ebl->elf, dump_data_sections, &dump_data_section);
+}
+
+static void
+dump_strings (Ebl *ebl)
+{
+  for_each_section_argument (ebl->elf, string_sections, &print_string_section);
+}
+
+static void
+print_strings (Ebl *ebl)
+{
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  Elf_Scn *scn;
+  GElf_Shdr shdr_mem;
+  const char *name;
+  scn = NULL;
+  while ((scn = elf_nextscn (ebl->elf, scn)) != NULL)
+    {
+      if (gelf_getshdr (scn, &shdr_mem) == NULL)
+	continue;
+
+      if (shdr_mem.sh_type != SHT_PROGBITS
+	  || !(shdr_mem.sh_flags & SHF_STRINGS))
+	continue;
+
+      name = elf_strptr (ebl->elf, shstrndx, shdr_mem.sh_name);
+      if (name == NULL)
+	continue;
+
+      print_string_section (scn, &shdr_mem, name);
+    }
+}
+
+static void
+dump_archive_index (Elf *elf, const char *fname)
+{
+  size_t narsym;
+  const Elf_Arsym *arsym = elf_getarsym (elf, &narsym);
+  if (arsym == NULL)
+    {
+      int result = elf_errno ();
+      if (unlikely (result != ELF_E_NO_INDEX))
+	error_exit (0, _("cannot get symbol index of archive '%s': %s"),
+		    fname, elf_errmsg (result));
+      else
+	printf (_("\nArchive '%s' has no symbol index\n"), fname);
+      return;
+    }
+
+  printf (_("\nIndex of archive '%s' has %zu entries:\n"),
+	  fname, narsym);
+
+  size_t as_off = 0;
+  for (const Elf_Arsym *s = arsym; s < &arsym[narsym - 1]; ++s)
+    {
+      if (s->as_off != as_off)
+	{
+	  as_off = s->as_off;
+
+	  Elf *subelf = NULL;
+	  if (unlikely (elf_rand (elf, as_off) == 0)
+	      || unlikely ((subelf = elf_begin (-1, ELF_C_READ_MMAP, elf))
+			   == NULL))
+#if __GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 7)
+	    while (1)
+#endif
+	      error_exit (0,
+			  _("cannot extract member at offset %zu in '%s': %s"),
+			  as_off, fname, elf_errmsg (-1));
+
+	  const Elf_Arhdr *h = elf_getarhdr (subelf);
+
+	  printf (_("Archive member '%s' contains:\n"), h->ar_name);
+
+	  elf_end (subelf);
+	}
+
+      printf ("\t%s\n", s->as_name);
+    }
+}
+
+#include "debugpred.h"
diff --git a/src/size.c b/src/size.c
new file mode 100644
index 0000000..ff8ca07
--- /dev/null
+++ b/src/size.c
@@ -0,0 +1,664 @@
+/* Print size information from ELF file.
+   Copyright (C) 2000-2007,2009,2012,2014,2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <system.h>
+#include <printversion.h>
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Values for the parameters which have no short form.  */
+#define OPT_FORMAT	0x100
+#define OPT_RADIX	0x101
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Output format:"), 0 },
+  { "format", OPT_FORMAT, "FORMAT", 0,
+    N_("Use the output format FORMAT.  FORMAT can be `bsd' or `sysv'.  "
+       "The default is `bsd'"), 0 },
+  { NULL, 'A', NULL, 0, N_("Same as `--format=sysv'"), 0 },
+  { NULL, 'B', NULL, 0, N_("Same as `--format=bsd'"), 0 },
+  { "radix", OPT_RADIX, "RADIX", 0, N_("Use RADIX for printing symbol values"),
+    0},
+  { NULL, 'd', NULL, 0, N_("Same as `--radix=10'"), 0 },
+  { NULL, 'o', NULL, 0, N_("Same as `--radix=8'"), 0 },
+  { NULL, 'x', NULL, 0, N_("Same as `--radix=16'"), 0 },
+  { NULL, 'f', NULL, 0,
+    N_("Similar to `--format=sysv' output but in one line"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
+  { NULL, 'F', NULL, 0,
+    N_("Print size and permission flags for loadable segments"), 0 },
+  { "totals", 't', NULL, 0, N_("Display the total sizes (bsd only)"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+List section sizes of FILEs (a.out by default).");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+
+/* Print symbols in file named FNAME.  */
+static int process_file (const char *fname);
+
+/* Handle content of archive.  */
+static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname);
+
+/* Handle ELF file.  */
+static void handle_elf (Elf *elf, const char *fullname, const char *fname);
+
+/* Show total size.  */
+static void show_bsd_totals (void);
+
+#define INTERNAL_ERROR(fname) \
+  error_exit (0, _("%s: INTERNAL ERROR %d (%s): %s"),      \
+	      fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1))
+
+
+/* User-selectable options.  */
+
+/* The selected output format.  */
+static enum
+{
+  format_bsd = 0,
+  format_sysv,
+  format_sysv_one_line,
+  format_segments
+} format;
+
+/* Radix for printed numbers.  */
+static enum
+{
+  radix_decimal = 0,
+  radix_hex,
+  radix_octal
+} radix;
+
+
+/* Mapping of radix and binary class to length.  */
+static const int length_map[2][3] =
+{
+  [ELFCLASS32 - 1] =
+  {
+    [radix_hex] = 8,
+    [radix_decimal] = 10,
+    [radix_octal] = 11
+  },
+  [ELFCLASS64 - 1] =
+  {
+    [radix_hex] = 16,
+    [radix_decimal] = 20,
+    [radix_octal] = 22
+  }
+};
+
+/* True if total sizes should be printed.  */
+static bool totals;
+/* To print the total sizes in a reasonable format remember the highest
+   "class" of ELF binaries processed.  */
+static int totals_class;
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+  int result = 0;
+
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+
+  /* Tell the library which version we are expecting.  */
+  elf_version (EV_CURRENT);
+
+  if (remaining == argc)
+    /* The user didn't specify a name so we use a.out.  */
+    result = process_file ("a.out");
+  else
+    /* Process all the remaining files.  */
+    do
+      result |= process_file (argv[remaining]);
+    while (++remaining < argc);
+
+  /* Print the total sizes but only if the output format is BSD and at
+     least one file has been correctly read (i.e., we recognized the
+     class).  */
+  if (totals && format == format_bsd && totals_class != 0)
+    show_bsd_totals ();
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'd':
+      radix = radix_decimal;
+      break;
+
+    case 'f':
+      format = format_sysv_one_line;
+      break;
+
+    case 'o':
+      radix = radix_octal;
+      break;
+
+    case 'x':
+      radix = radix_hex;
+      break;
+
+    case 'A':
+      format = format_sysv;
+      break;
+
+    case 'B':
+      format = format_bsd;
+      break;
+
+    case 'F':
+      format = format_segments;
+      break;
+
+    case OPT_FORMAT:
+      if (strcmp (arg, "bsd") == 0 || strcmp (arg, "berkeley") == 0)
+	format = format_bsd;
+      else if (likely (strcmp (arg, "sysv") == 0))
+	format = format_sysv;
+      else
+	error_exit (0, _("Invalid format: %s"), arg);
+      break;
+
+    case OPT_RADIX:
+      if (strcmp (arg, "x") == 0 || strcmp (arg, "16") == 0)
+	radix = radix_hex;
+      else if (strcmp (arg, "d") == 0 || strcmp (arg, "10") == 0)
+	radix = radix_decimal;
+      else if (strcmp (arg, "o") == 0 || strcmp (arg, "8") == 0)
+	radix = radix_octal;
+      else
+	error_exit (0, _("Invalid radix: %s"), arg);
+      break;
+
+    case 't':
+      totals = true;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+/* Open the file and determine the type.  */
+static int
+process_file (const char *fname)
+{
+  int fd = open (fname, O_RDONLY);
+  if (unlikely (fd == -1))
+    {
+      error (0, errno, _("cannot open '%s'"), fname);
+      return 1;
+    }
+
+  /* Now get the ELF descriptor.  */
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (likely (elf != NULL))
+    {
+      if (elf_kind (elf) == ELF_K_ELF)
+	{
+	  handle_elf (elf, NULL, fname);
+
+	  if (unlikely (elf_end (elf) != 0))
+	    INTERNAL_ERROR (fname);
+
+	  if (unlikely (close (fd) != 0))
+	    error_exit (errno, _("while closing '%s'"), fname);
+
+	  return 0;
+	}
+      else if (likely (elf_kind (elf) == ELF_K_AR))
+	{
+	  int result = handle_ar (fd, elf, NULL, fname);
+
+	  if (unlikely  (close (fd) != 0))
+	    error_exit (errno, _("while closing '%s'"), fname);
+
+	  return result;
+	}
+
+      /* We cannot handle this type.  Close the descriptor anyway.  */
+      if (unlikely (elf_end (elf) != 0))
+	INTERNAL_ERROR (fname);
+    }
+
+  if (unlikely (close (fd) != 0))
+    error_exit (errno, _("while closing '%s'"), fname);
+
+  error (0, 0, _("%s: file format not recognized"), fname);
+
+  return 1;
+}
+
+
+/* Print the BSD-style header.  This is done exactly once.  */
+static void
+print_header (Elf *elf)
+{
+  static int done;
+
+  if (! done)
+    {
+      int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
+      int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
+
+      printf ("%*s %*s %*s %*s %*s %s\n",
+	      ddigits - 2, sgettext ("bsd|text"),
+	      ddigits - 2, sgettext ("bsd|data"),
+	      ddigits - 2, sgettext ("bsd|bss"),
+	      ddigits - 2, sgettext ("bsd|dec"),
+	      xdigits - 2, sgettext ("bsd|hex"),
+	      sgettext ("bsd|filename"));
+
+      done = 1;
+    }
+}
+
+
+static int
+handle_ar (int fd, Elf *elf, const char *prefix, const char *fname)
+{
+  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t fname_len = strlen (fname) + 1;
+  char new_prefix[prefix_len + 1 + fname_len];
+  char *cp = new_prefix;
+
+  /* Create the full name of the file.  */
+  if (prefix != NULL)
+    {
+      cp = mempcpy (cp, prefix, prefix_len);
+      *cp++ = ':';
+    }
+  memcpy (cp, fname, fname_len);
+
+  /* Process all the files contained in the archive.  */
+  int result = 0;
+  Elf *subelf;
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      /* The the header for this element.  */
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      if (elf_kind (subelf) == ELF_K_ELF)
+	handle_elf (subelf, new_prefix, arhdr->ar_name);
+      else if (likely (elf_kind (subelf) == ELF_K_AR))
+	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name);
+      /* else signal error??? */
+
+      /* Get next archive element.  */
+      cmd = elf_next (subelf);
+      if (unlikely (elf_end (subelf) != 0))
+	INTERNAL_ERROR (fname);
+    }
+
+  /* Only close ELF handle if this was a "top level" ar file.  */
+  if (prefix == NULL)
+    if (unlikely (elf_end (elf) != 0))
+      INTERNAL_ERROR (fname);
+
+  return result;
+}
+
+
+/* Show sizes in SysV format.  */
+static void
+show_sysv (Elf *elf, const char *prefix, const char *fname,
+	   const char *fullname)
+{
+  int maxlen = 10;
+  const int digits = length_map[gelf_getclass (elf) - 1][radix];
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* First round over the sections: determine the longest section name.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fullname);
+
+      /* Ignore all sections which are not used at runtime.  */
+      const char *name = elf_strptr (elf, shstrndx, shdr->sh_name);
+      if (name != NULL && (shdr->sh_flags & SHF_ALLOC) != 0)
+	maxlen = MAX (maxlen, (int) strlen (name));
+    }
+
+  fputs_unlocked (fname, stdout);
+  if (prefix != NULL)
+    printf (_(" (ex %s)"), prefix);
+  printf (":\n%-*s %*s %*s\n",
+	  maxlen, sgettext ("sysv|section"),
+	  digits - 2, sgettext ("sysv|size"),
+	  digits, sgettext ("sysv|addr"));
+
+  /* Iterate over all sections.  */
+  GElf_Off total = 0;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fullname);
+
+      /* Ignore all sections which are not used at runtime.  */
+      if ((shdr->sh_flags & SHF_ALLOC) != 0)
+	{
+	  printf ((radix == radix_hex
+		   ? "%-*s %*" PRIx64 " %*" PRIx64 "\n"
+		   : (radix == radix_decimal
+		      ? "%-*s %*" PRId64 " %*" PRId64 "\n"
+		      : "%-*s %*" PRIo64 " %*" PRIo64 "\n")),
+		  maxlen, elf_strptr (elf, shstrndx, shdr->sh_name),
+		  digits - 2, shdr->sh_size,
+		  digits, shdr->sh_addr);
+
+	  total += shdr->sh_size;
+	}
+    }
+
+  if (radix == radix_hex)
+    printf ("%-*s %*" PRIx64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
+	    digits - 2, total);
+  else if (radix == radix_decimal)
+    printf ("%-*s %*" PRId64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
+	    digits - 2, total);
+  else
+    printf ("%-*s %*" PRIo64 "\n\n\n", maxlen, sgettext ("sysv|Total"),
+	    digits - 2, total);
+}
+
+
+/* Show sizes in SysV format in one line.  */
+static void
+show_sysv_one_line (Elf *elf)
+{
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
+    error_exit (0, _("cannot get section header string table index"));
+
+  /* Iterate over all sections.  */
+  GElf_Off total = 0;
+  bool first = true;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (unlikely (shdr == NULL))
+	error_exit (0, _("cannot get section header"));
+
+      /* Ignore all sections which are not used at runtime.  */
+      if ((shdr->sh_flags & SHF_ALLOC) == 0)
+	continue;
+
+      if (! first)
+	fputs_unlocked (" + ", stdout);
+      first = false;
+
+      printf ((radix == radix_hex ? "%" PRIx64 "(%s)"
+	       : (radix == radix_decimal ? "%" PRId64 "(%s)"
+		  : "%" PRIo64 "(%s)")),
+	      shdr->sh_size, elf_strptr (elf, shstrndx, shdr->sh_name));
+
+      total += shdr->sh_size;
+    }
+
+  if (radix == radix_hex)
+    printf (" = %#" PRIx64 "\n", total);
+  else if (radix == radix_decimal)
+    printf (" = %" PRId64 "\n", total);
+  else
+    printf (" = %" PRIo64 "\n", total);
+}
+
+
+/* Variables to add up the sizes of all files.  */
+static uintmax_t total_textsize;
+static uintmax_t total_datasize;
+static uintmax_t total_bsssize;
+
+
+/* Show sizes in BSD format.  */
+static void
+show_bsd (Elf *elf, const char *prefix, const char *fname,
+	  const char *fullname)
+{
+  GElf_Off textsize = 0;
+  GElf_Off datasize = 0;
+  GElf_Off bsssize = 0;
+  const int ddigits = length_map[gelf_getclass (elf) - 1][radix_decimal];
+  const int xdigits = length_map[gelf_getclass (elf) - 1][radix_hex];
+
+  /* Iterate over all sections.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr == NULL)
+	INTERNAL_ERROR (fullname);
+
+      /* Ignore all sections which are not marked as loaded.  */
+      if ((shdr->sh_flags & SHF_ALLOC) == 0)
+	continue;
+
+      if ((shdr->sh_flags & SHF_WRITE) == 0)
+	textsize += shdr->sh_size;
+      else if (shdr->sh_type == SHT_NOBITS)
+	bsssize += shdr->sh_size;
+      else
+	datasize += shdr->sh_size;
+    }
+
+  printf (radix == radix_decimal
+          ? "%*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRId64 " %*" PRIx64 " %s"
+	  : radix == radix_hex
+	  ? "%#*" PRIx64 " %#*" PRIx64 " %#*" PRIx64 " %*" PRId64 " %*" PRIx64 " %s"
+	  : "%#*" PRIo64 " %#*" PRIo64 " %#*" PRIo64 " %*" PRId64 " %*" PRIx64 " %s",
+	  ddigits - 2, textsize,
+	  ddigits - 2, datasize,
+	  ddigits - 2, bsssize,
+	  ddigits - 2, textsize + datasize + bsssize,
+	  xdigits - 2, textsize + datasize + bsssize,
+	  fname);
+  if (prefix != NULL)
+    printf (_(" (ex %s)"), prefix);
+  fputs_unlocked ("\n", stdout);
+
+  total_textsize += textsize;
+  total_datasize += datasize;
+  total_bsssize += bsssize;
+
+  totals_class = MAX (totals_class, gelf_getclass (elf));
+}
+
+
+/* Show total size.  */
+static void
+show_bsd_totals (void)
+{
+  int ddigits = length_map[totals_class - 1][radix_decimal];
+  int xdigits = length_map[totals_class - 1][radix_hex];
+
+  printf ("%*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*" PRIuMAX " %*"
+	  PRIxMAX " %s",
+	  ddigits - 2, total_textsize,
+	  ddigits - 2, total_datasize,
+	  ddigits - 2, total_bsssize,
+	  ddigits - 2, total_textsize + total_datasize + total_bsssize,
+	  xdigits - 2, total_textsize + total_datasize + total_bsssize,
+	  _("(TOTALS)\n"));
+}
+
+
+/* Show size and permission of loadable segments.  */
+static void
+show_segments (Elf *elf, const char *fullname)
+{
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    INTERNAL_ERROR (fullname);
+
+  GElf_Off total = 0;
+  bool first = true;
+  for (size_t cnt = 0; cnt < phnum; ++cnt)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr;
+
+      phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+      if (phdr == NULL)
+	INTERNAL_ERROR (fullname);
+
+      if (phdr->p_type != PT_LOAD)
+	/* Only load segments.  */
+	continue;
+
+      if (! first)
+	fputs_unlocked (" + ", stdout);
+      first = false;
+
+      printf (radix == radix_hex ? "%" PRIx64 "(%c%c%c)"
+	      : (radix == radix_decimal ? "%" PRId64 "(%c%c%c)"
+		 : "%" PRIo64 "(%c%c%c)"),
+	      phdr->p_memsz,
+	      (phdr->p_flags & PF_R) == 0 ? '-' : 'r',
+	      (phdr->p_flags & PF_W) == 0 ? '-' : 'w',
+	      (phdr->p_flags & PF_X) == 0 ? '-' : 'x');
+
+      total += phdr->p_memsz;
+    }
+
+  if (radix == radix_hex)
+    printf (" = %#" PRIx64 "\n", total);
+  else if (radix == radix_decimal)
+    printf (" = %" PRId64 "\n", total);
+  else
+    printf (" = %" PRIo64 "\n", total);
+}
+
+
+static void
+handle_elf (Elf *elf, const char *prefix, const char *fname)
+{
+  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t fname_len = strlen (fname) + 1;
+  char fullname[prefix_len + 1 + fname_len];
+  char *cp = fullname;
+
+  /* Create the full name of the file.  */
+  if (prefix != NULL)
+    {
+      cp = mempcpy (cp, prefix, prefix_len);
+      *cp++ = ':';
+    }
+  memcpy (cp, fname, fname_len);
+
+  if (format == format_sysv)
+    show_sysv (elf, prefix, fname, fullname);
+  else if (format == format_sysv_one_line)
+    show_sysv_one_line (elf);
+  else if (format == format_segments)
+    show_segments (elf, fullname);
+  else
+    {
+      print_header (elf);
+
+      show_bsd (elf, prefix, fname, fullname);
+    }
+}
+
+
+#include "debugpred.h"
diff --git a/src/srcfiles.cxx b/src/srcfiles.cxx
new file mode 100644
index 0000000..892737c
--- /dev/null
+++ b/src/srcfiles.cxx
@@ -0,0 +1,457 @@
+/* Print the source files of a given ELF file.
+   Copyright (C) 2023 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Housam Alamour <alamourh@redhat.com>.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+/* In case we have a bad fts we include this before config.h because it
+   can't handle _FILE_OFFSET_BITS.
+   Everything we need here is fine if its declarations just come first.
+   Also, include sys/types.h before fts.  On some systems fts.h is not self
+   contained.  */
+#ifdef BAD_FTS
+#include <sys/types.h>
+#include <fts.h>
+#endif
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "printversion.h"
+#include <dwarf.h>
+#include <argp.h>
+#include <cstring>
+#include <set>
+#include <string>
+#include <cassert>
+#include <gelf.h>
+#include <memory>
+
+#ifdef ENABLE_LIBDEBUGINFOD
+#include "debuginfod.h"
+#endif
+
+#include <libdwfl.h>
+#include <fcntl.h>
+#include <iostream>
+#include <libdw.h>
+#include <sstream>
+#include <vector>
+
+/* Libraries for use by the --zip option */
+#ifdef HAVE_LIBARCHIVE
+#include <archive.h>
+#include <archive_entry.h>
+#endif
+
+/* If fts.h is included before config.h, its indirect inclusions may not
+   give us the right LFS aliases of these functions, so map them manually.  */
+#ifdef BAD_FTS
+#ifdef _FILE_OFFSET_BITS
+#define open open64
+#define fopen fopen64
+#endif
+#else
+  #include <sys/types.h>
+  #include <fts.h>
+#endif
+
+using namespace std;
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+constexpr size_t BUFFER_SIZE = 8192;
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, OPTION_DOC, N_("Output options:"), 1 },
+  { "null", '0', NULL, 0,
+    N_ ("Separate items by a null instead of a newline."), 0 },
+  { "verbose", 'v', NULL, 0,
+    N_ ("Increase verbosity of logging messages."), 0 },
+  { "cu-only", 'c', NULL, 0, N_("Only list the CU names."), 0 },
+  #ifdef HAVE_LIBARCHIVE
+  { "zip", 'z', NULL, 0, N_("Zip all the source files and send to stdout. "
+    "Cannot be used with the null option"), 0 },
+    #ifdef ENABLE_LIBDEBUGINFOD
+    { "no-backup", 'b', NULL, 0, N_("Disables local source file search when "
+      "debuginfod fails to fetch files. This option is only applicable"
+      "when fetching and zipping files."), 0 },
+    #endif
+  #endif
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("Lists the source files of a DWARF/ELF file.  The default input is the file 'a.out'.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("INPUT");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+static struct argp_child argp_children[2]; /* [0] is set in main.  */
+
+/* Data structure to communicate with argp functions.  */
+static const struct argp argp =
+{
+  options, parse_opt, args_doc, doc, argp_children, NULL, NULL
+};
+
+/* Verbose message printing.  */
+static bool verbose;
+/* Delimit the output with nulls.  */
+static bool null_arg;
+/* Only print compilation unit names.  */
+static bool CU_only;
+#ifdef HAVE_LIBARCHIVE
+  /* Zip all the source files and send to stdout. */
+  static bool zip;
+
+  #ifdef ENABLE_LIBDEBUGINFOD
+    /* Disables local source file search when debuginfod fails to fetch them.
+       This option is only applicable when fetching and zipping files.*/
+    static bool no_backup;
+  #endif
+#endif
+
+/* Handle program arguments.  Note null arg and zip
+    cannot be combined due to warnings raised when unzipping.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  /* Suppress "unused parameter" warning.  */
+  (void)arg;
+  switch (key)
+    {
+    case ARGP_KEY_INIT:
+      state->child_inputs[0] = state->input;
+      break;
+
+    case '0':
+      null_arg = true;
+      break;
+
+    case 'v':
+      verbose = true;
+      break;
+
+    case 'c':
+      CU_only = true;
+      break;
+
+    #ifdef HAVE_LIBARCHIVE
+      case 'z':
+      zip = true;
+      break;
+
+      #ifdef ENABLE_LIBDEBUGINFOD
+        case 'b':
+        no_backup = true;
+        break;
+      #endif
+    #endif
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+/* Remove the "/./" , "../" and the preceding directory
+    that some paths include which raise errors during unzip.  */
+string canonicalize_path(string path)
+{
+    stringstream ss(path);
+    string token;
+    vector<string> tokens;
+    /* Extract each directory of the path and place into a vector.  */
+    while (getline(ss, token, '/')) {
+      /* Ignore any empty //, or /./ dirs.  */
+        if (token == "" || token == ".")
+            continue;
+      /* When /..  is encountered, remove the most recent directory from the vector.  */
+        else if (token == "..") {
+            if (!tokens.empty())
+                tokens.pop_back();
+        } else
+            tokens.push_back(token);
+    }
+    stringstream result;
+    if (tokens.empty())
+        return "/";
+    /* Reconstruct the path from the extracted directories.  */
+    for (const string &t : tokens) {
+        result << '/' << t;
+    }
+    return result.str();
+}
+
+/* Global list of collected source files and their respective module.
+   Normally, it'll contain the sources of just one named binary, but
+   the '-K' option can cause multiple dwfl modules to be loaded, thus
+   listed.  */
+set<pair<string, Dwfl_Module*>> debug_sourcefiles;
+
+static int
+collect_sourcefiles (Dwfl_Module *dwflmod,
+                     void **userdata __attribute__ ((unused)),
+                     const char *name __attribute__ ((unused)),
+                     Dwarf_Addr base __attribute__ ((unused)),
+                     void *arg __attribute__ ((unused)))
+{
+  Dwarf *dbg;
+  Dwarf_Addr bias; /* ignored - for addressing purposes only.  */
+
+  dbg = dwfl_module_getdwarf (dwflmod, &bias);
+
+  Dwarf_Off offset = 0;
+  Dwarf_Off old_offset;
+  size_t hsize;
+  /* Traverse all CUs of this module.  */
+  while (dwarf_nextcu (dbg, old_offset = offset, &offset, &hsize, NULL, NULL, NULL) == 0)
+    {
+      Dwarf_Die cudie_mem;
+      Dwarf_Die *cudie = dwarf_offdie (dbg, old_offset + hsize, &cudie_mem);
+
+      if (cudie == NULL)
+        continue;
+
+      const char *cuname = dwarf_diename (cudie) ?: "<unknown>";
+      Dwarf_Files *files;
+      size_t nfiles;
+      if (dwarf_getsrcfiles (cudie, &files, &nfiles) != 0)
+        continue;
+
+      /* extract DW_AT_comp_dir to resolve relative file names.  */
+      const char *comp_dir = "";
+      const char *const *dirs;
+      size_t ndirs;
+
+      if (dwarf_getsrcdirs (files, &dirs, &ndirs) == 0 && dirs[0] != NULL)
+        comp_dir = dirs[0];
+      if (comp_dir == NULL)
+        comp_dir = "";
+
+      if (verbose)
+        clog << "searching for sources for cu=" << cuname
+                  << " comp_dir=" << comp_dir << " #files=" << nfiles
+                  << " #dirs=" << ndirs << endl;
+
+      if (comp_dir[0] == '\0' && cuname[0] != '/')
+        {
+          /* This is a common symptom for dwz-compressed debug files,
+             where the altdebug file cannot be resolved.  */
+          if (verbose)
+            clog << "skipping cu=" << cuname << " due to empty comp_dir" << endl;
+          continue;
+        }
+      for (size_t f = 1; f < nfiles; ++f)
+        {
+          const char *hat;
+          if (CU_only)
+          {
+            if (strcmp(cuname, "<unknown>") == 0 || strcmp(cuname, "<artificial>") == 0 )
+              continue;
+            hat = cuname;
+          }
+          else
+            hat = dwarf_filesrc (files, f, NULL, NULL);
+
+          if (hat == NULL)
+            continue;
+
+          if (string(hat).find("<built-in>")
+              != string::npos) /* gcc intrinsics, don't bother recording */
+            continue;
+
+          string waldo;
+          if (hat[0] == '/') /* absolute */
+            waldo = (string (hat));
+          else if (comp_dir[0] != '\0') /* comp_dir relative */
+            waldo = (string (comp_dir) + string ("/") + string (hat));
+          else
+           {
+             if (verbose)
+              clog << "skipping file=" << hat << " due to empty comp_dir" << endl;
+             continue;
+           }
+          waldo = canonicalize_path (waldo);
+          debug_sourcefiles.insert (make_pair(waldo, dwflmod));
+        }
+    }
+  return DWARF_CB_OK;
+}
+
+#ifdef HAVE_LIBARCHIVE
+void zip_files()
+{
+  struct archive *a = archive_write_new();
+  struct stat st;
+  char buff[BUFFER_SIZE];
+  int len;
+  int fd;
+  #ifdef ENABLE_LIBDEBUGINFOD
+  /* Initialize a debuginfod client.  */
+  static unique_ptr <debuginfod_client, void (*)(debuginfod_client*)>
+    client (debuginfod_begin(), &debuginfod_end);
+  #endif
+
+  archive_write_set_format_zip(a);
+  archive_write_open_fd(a, STDOUT_FILENO);
+
+  int missing_files = 0;
+  for (const auto &pair : debug_sourcefiles)
+  {
+    fd = -1;
+    const std::string &file_path = pair.first;
+
+    /* Attempt to query debuginfod client to fetch source files.  */
+    #ifdef ENABLE_LIBDEBUGINFOD
+    Dwfl_Module* dwflmod = pair.second;
+    /* Obtain source file's build ID.  */
+    const unsigned char *bits;
+    GElf_Addr vaddr;
+    int bits_length = dwfl_module_build_id(dwflmod, &bits, &vaddr);
+    /* Ensure successful client and build ID acquisition.  */
+    if (client.get() != NULL && bits_length > 0)
+    {
+      fd = debuginfod_find_source(client.get(),
+                                    bits, bits_length,
+                                    file_path.c_str(), NULL);
+    }
+    else
+    {
+        if (client.get() == NULL)
+            cerr << "Error: Failed to initialize debuginfod client." << endl;
+        else
+            cerr << "Error: Invalid build ID length (" << bits_length << ")." << endl;
+    }
+    #endif
+
+    if (!no_backup)
+      /* Files could not be located using debuginfod, search locally */
+      if (fd < 0)
+        fd = open(file_path.c_str(), O_RDONLY);
+    if (fd < 0)
+    {
+      if (verbose)
+        cerr << file_path << endl;
+      missing_files++;
+      continue;
+    }
+
+    /* Create an entry for each file including file information to be placed in the zip.  */
+    if (fstat(fd, &st) == -1)
+    {
+      if (verbose)
+        cerr << file_path << endl;
+      missing_files++;
+      if (verbose)
+        cerr << "Error: Failed to get file status for " << file_path << ": " << strerror(errno) << endl;
+      continue;
+    }
+    struct archive_entry *entry = archive_entry_new();
+    /* Removing first "/"" to make the path "relative" before zipping, otherwise warnings are raised when unzipping.  */
+    string entry_name = file_path.substr(file_path.find_first_of('/') + 1);
+    archive_entry_set_pathname(entry, entry_name.c_str());
+    archive_entry_copy_stat(entry, &st);
+    if (archive_write_header(a, entry) != ARCHIVE_OK)
+    {
+      if (verbose)
+        cerr << file_path << endl;
+      missing_files++;
+      if (verbose)
+        cerr << "Error: failed to write header for " << file_path << ": " << archive_error_string(a) << endl;
+      continue;
+    }
+
+    /* Write the file to the zip.  */
+    len = read(fd, buff, sizeof(buff));
+    if (len == -1)
+    {
+      if (verbose)
+        cerr << file_path << endl;
+      missing_files++;
+      if (verbose)
+        cerr << "Error: Failed to open file: " << file_path << ": " << strerror(errno) <<endl;
+      continue;
+    }
+    while (len > 0)
+    {
+      if (archive_write_data(a, buff, len) < ARCHIVE_OK)
+      {
+        if (verbose)
+          cerr << "Error: Failed to read from the file: " << file_path << ": " << strerror(errno) << endl;
+        break;
+      }
+      len = read(fd, buff, sizeof(buff));
+    }
+    close(fd);
+    archive_entry_free(entry);
+  }
+  if (verbose && missing_files > 0 )
+    cerr << missing_files << " file(s) listed above could not be found.  " << endl;
+
+  archive_write_close(a);
+  archive_write_free(a);
+}
+#endif
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Parse and process arguments.  This includes opening the modules.  */
+  argp_children[0].argp = dwfl_standard_argp ();
+  argp_children[0].group = 1;
+
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+  /* Process all loaded modules - probably just one, except if -K or -p is used.  */
+  (void) dwfl_getmodules (dwfl, &collect_sourcefiles, NULL, 0);
+
+  if (!debug_sourcefiles.empty ())
+  {
+    #ifdef HAVE_LIBARCHIVE
+      if (zip)
+        zip_files();
+      else
+    #endif
+      {
+        for (const auto &pair : debug_sourcefiles)
+          {
+            cout << pair.first;
+            if (null_arg)
+              cout << '\0';
+            else
+              cout << '\n';
+          }
+      }
+  }
+
+  dwfl_end (dwfl);
+  return 0;
+}
diff --git a/src/stack.c b/src/stack.c
new file mode 100644
index 0000000..f4c5ba8
--- /dev/null
+++ b/src/stack.c
@@ -0,0 +1,763 @@
+/* Unwinding of frames like gstack/pstack.
+   Copyright (C) 2013-2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <argp.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <string.h>
+#include <locale.h>
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dwfl)
+
+#include <dwarf.h>
+#include <system.h>
+#include <printversion.h>
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* non-printable argp options.  */
+#define OPT_DEBUGINFO	0x100
+#define OPT_COREFILE	0x101
+
+static bool show_activation = false;
+static bool show_module = false;
+static bool show_build_id = false;
+static bool show_source = false;
+static bool show_one_tid = false;
+static bool show_quiet = false;
+static bool show_raw = false;
+static bool show_modules = false;
+static bool show_debugname = false;
+static bool show_inlines = false;
+
+static int maxframes = 256;
+
+struct frame
+{
+  Dwarf_Addr pc;
+  bool isactivation;
+};
+
+struct frames
+{
+  int frames;
+  int allocated;
+  struct frame *frame;
+};
+
+static Dwfl *dwfl = NULL;
+static pid_t pid = 0;
+static int core_fd = -1;
+static Elf *core = NULL;
+static const char *exec = NULL;
+static char *debuginfo_path = NULL;
+
+static const Dwfl_Callbacks proc_callbacks =
+  {
+    .find_elf = dwfl_linux_proc_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+    .debuginfo_path = &debuginfo_path,
+  };
+
+static const Dwfl_Callbacks core_callbacks =
+  {
+    .find_elf = dwfl_build_id_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+    .debuginfo_path = &debuginfo_path,
+  };
+
+#ifdef USE_DEMANGLE
+static size_t demangle_buffer_len = 0;
+static char *demangle_buffer = NULL;
+#endif
+
+/* Whether any frames have been shown at all.  Determines exit status.  */
+static bool frames_shown = false;
+
+/* Program exit codes. All frames shown without any errors is GOOD.
+   Some frames shown with some non-fatal errors is an ERROR.  A fatal
+   error or no frames shown at all is BAD.  A command line USAGE exit
+   is generated by argp_error.  */
+#define EXIT_OK     0
+#define EXIT_ERROR  1
+#define EXIT_BAD    2
+#define EXIT_USAGE 64
+
+static int
+get_addr_width (Dwfl_Module *mod)
+{
+  // Try to find the address wide if possible.
+  static int width = 0;
+  if (width == 0 && mod)
+    {
+      Dwarf_Addr bias;
+      Elf *elf = dwfl_module_getelf (mod, &bias);
+      if (elf)
+        {
+	  GElf_Ehdr ehdr_mem;
+	  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+	  if (ehdr)
+	    width = ehdr->e_ident[EI_CLASS] == ELFCLASS32 ? 8 : 16;
+	}
+    }
+  if (width == 0)
+    width = 16;
+
+  return width;
+}
+
+static int
+module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)),
+		 const char *name, Dwarf_Addr start,
+		 void *arg __attribute__((unused)))
+{
+  /* Forces resolving of main elf and debug files. */
+  Dwarf_Addr bias;
+  Elf *elf = dwfl_module_getelf (mod, &bias);
+  Dwarf *dwarf = dwfl_module_getdwarf (mod, &bias);
+
+  Dwarf_Addr end;
+  const char *mainfile;
+  const char *debugfile;
+  const char *modname = dwfl_module_info (mod, NULL, NULL, &end, NULL,
+                                          NULL, &mainfile, &debugfile);
+  if (modname == NULL || strcmp (modname, name) != 0)
+    {
+      end = start + 1;
+      mainfile = NULL;
+      debugfile = NULL;
+    }
+
+  int width = get_addr_width (mod);
+  printf ("0x%0*" PRIx64 "-0x%0*" PRIx64 " %s\n",
+	  width, start, width, end, xbasename (name));
+
+  const unsigned char *id;
+  GElf_Addr id_vaddr;
+  int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
+  if (id_len > 0)
+    {
+      printf ("  [");
+      do
+	printf ("%02" PRIx8, *id++);
+      while (--id_len > 0);
+      printf ("]\n");
+    }
+
+  if (elf != NULL)
+    printf ("  %s\n", mainfile != NULL ? mainfile : "-");
+  if (dwarf != NULL)
+    printf ("  %s\n", debugfile != NULL ? debugfile : "-");
+
+  return DWARF_CB_OK;
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+  struct frames *frames = (struct frames *) arg;
+  int nr = frames->frames;
+  if (! dwfl_frame_pc (state, &frames->frame[nr].pc,
+		       &frames->frame[nr].isactivation))
+    return -1;
+
+  frames->frames++;
+  if (frames->frames == maxframes)
+    return DWARF_CB_ABORT;
+
+  if (frames->frames == frames->allocated)
+    {
+      frames->allocated *= 2;
+      frames->frame = realloc (frames->frame,
+			       sizeof (struct frame) * frames->allocated);
+      if (frames->frame == NULL)
+	error (EXIT_BAD, errno, "realloc frames.frame");
+    }
+
+  return DWARF_CB_OK;
+}
+
+static const char*
+die_name (Dwarf_Die *die)
+{
+  Dwarf_Attribute attr;
+  const char *name;
+  name = dwarf_formstring (dwarf_attr_integrate (die,
+						 DW_AT_MIPS_linkage_name,
+						 &attr)
+			   ?: dwarf_attr_integrate (die,
+						    DW_AT_linkage_name,
+						    &attr));
+  if (name == NULL)
+    name = dwarf_diename (die);
+
+  return name;
+}
+
+static void
+print_frame (int nr, Dwarf_Addr pc, bool isactivation,
+	     Dwarf_Addr pc_adjusted, Dwfl_Module *mod,
+	     const char *symname, Dwarf_Die *cudie,
+	     Dwarf_Die *die)
+{
+  int width = get_addr_width (mod);
+  printf ("#%-2u 0x%0*" PRIx64, nr, width, (uint64_t) pc);
+
+  if (show_activation)
+    printf ("%4s", ! isactivation ? "- 1" : "");
+
+  if (symname != NULL)
+    {
+#ifdef USE_DEMANGLE
+      // Require GNU v3 ABI by the "_Z" prefix.
+      if (! show_raw && symname[0] == '_' && symname[1] == 'Z')
+	{
+	  int status = -1;
+	  char *dsymname = __cxa_demangle (symname, demangle_buffer,
+					   &demangle_buffer_len, &status);
+	  if (status == 0)
+	    symname = demangle_buffer = dsymname;
+	}
+#endif
+      printf (" %s", symname);
+    }
+
+  const char* fname;
+  Dwarf_Addr start;
+  fname = dwfl_module_info(mod, NULL, &start,
+			   NULL, NULL, NULL, NULL, NULL);
+  if (show_module)
+    {
+      if (fname != NULL)
+	printf (" - %s", fname);
+    }
+
+  if (show_build_id)
+    {
+      const unsigned char *id;
+      GElf_Addr id_vaddr;
+      int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
+      if (id_len > 0)
+	{
+	  printf ("\n    [");
+	  do
+	    printf ("%02" PRIx8, *id++);
+	  while (--id_len > 0);
+	  printf ("]@0x%0" PRIx64 "+0x%" PRIx64,
+		  start, pc_adjusted - start);
+	}
+    }
+
+  if (show_source)
+    {
+      int line, col;
+      const char* sname;
+      line = col = -1;
+      sname = NULL;
+      if (die != NULL)
+	{
+	  Dwarf_Files *files;
+	  if (dwarf_getsrcfiles (cudie, &files, NULL) == 0)
+	    {
+	      Dwarf_Attribute attr;
+	      Dwarf_Word val;
+	      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_file, &attr),
+				   &val) == 0)
+		{
+		  sname = dwarf_filesrc (files, val, NULL, NULL);
+		  if (dwarf_formudata (dwarf_attr (die, DW_AT_call_line,
+						   &attr), &val) == 0)
+		    {
+		      line = val;
+		      if (dwarf_formudata (dwarf_attr (die, DW_AT_call_column,
+						       &attr), &val) == 0)
+			col = val;
+		    }
+		}
+	    }
+	}
+      else
+	{
+	  Dwfl_Line *lineobj = dwfl_module_getsrc(mod, pc_adjusted);
+	  if (lineobj)
+	    sname = dwfl_lineinfo (lineobj, NULL, &line, &col, NULL, NULL);
+	}
+
+      if (sname != NULL)
+	{
+	  printf ("\n    %s", sname);
+	  if (line > 0)
+	    {
+	      printf (":%d", line);
+	      if (col > 0)
+		printf (":%d", col);
+	    }
+	}
+    }
+  printf ("\n");
+}
+
+static void
+print_inline_frames (int *nr, Dwarf_Addr pc, bool isactivation,
+		     Dwarf_Addr pc_adjusted, Dwfl_Module *mod,
+		     const char *symname, Dwarf_Die *cudie, Dwarf_Die *die)
+{
+  Dwarf_Die *scopes = NULL;
+  int nscopes = dwarf_getscopes_die (die, &scopes);
+  if (nscopes > 0)
+    {
+      /* scopes[0] == die, the lowest level, for which we already have
+	 the name.  This is the actual source location where it
+	 happened.  */
+      print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname,
+		   NULL, NULL);
+
+      /* last_scope is the source location where the next frame/function
+	 call was done. */
+      Dwarf_Die *last_scope = &scopes[0];
+      for (int i = 1; i < nscopes && (maxframes == 0 || *nr < maxframes); i++)
+	{
+	  Dwarf_Die *scope = &scopes[i];
+	  int tag = dwarf_tag (scope);
+	  if (tag != DW_TAG_inlined_subroutine
+	      && tag != DW_TAG_entry_point
+	      && tag != DW_TAG_subprogram)
+	    continue;
+
+	  symname = die_name (scope);
+	  print_frame ((*nr)++, pc, isactivation, pc_adjusted, mod, symname,
+		       cudie, last_scope);
+
+	  /* Found the "top-level" in which everything was inlined?  */
+	  if (tag == DW_TAG_subprogram)
+	    break;
+
+	  last_scope = scope;
+	}
+    }
+  free (scopes);
+}
+
+static void
+print_frames (struct frames *frames, pid_t tid, int dwflerr, const char *what)
+{
+  if (frames->frames > 0)
+    frames_shown = true;
+
+  printf ("TID %lld:\n", (long long) tid);
+  int frame_nr = 0;
+  for (int nr = 0; nr < frames->frames && (maxframes == 0
+					   || frame_nr < maxframes); nr++)
+    {
+      Dwarf_Addr pc = frames->frame[nr].pc;
+      bool isactivation = frames->frame[nr].isactivation;
+      Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+      /* Get PC->SYMNAME.  */
+      Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+      const char *symname = NULL;
+      Dwarf_Die die_mem;
+      Dwarf_Die *die = NULL;
+      Dwarf_Die *cudie = NULL;
+      if (mod && ! show_quiet)
+	{
+	  if (show_debugname)
+	    {
+	      Dwarf_Addr bias = 0;
+	      Dwarf_Die *scopes = NULL;
+	      cudie = dwfl_module_addrdie (mod, pc_adjusted, &bias);
+	      int nscopes = dwarf_getscopes (cudie, pc_adjusted - bias,
+					     &scopes);
+
+	      /* Find the first function-like DIE with a name in scope.  */
+	      for (int i = 0; symname == NULL && i < nscopes; i++)
+		{
+		  Dwarf_Die *scope = &scopes[i];
+		  int tag = dwarf_tag (scope);
+		  if (tag == DW_TAG_subprogram
+		      || tag == DW_TAG_inlined_subroutine
+		      || tag == DW_TAG_entry_point)
+		    symname = die_name (scope);
+
+		  if (symname != NULL)
+		    {
+		      die_mem = *scope;
+		      die = &die_mem;
+		    }
+		}
+	      free (scopes);
+	    }
+
+	  if (symname == NULL)
+	    symname = dwfl_module_addrname (mod, pc_adjusted);
+	}
+
+      if (show_inlines && die != NULL)
+	print_inline_frames (&frame_nr, pc, isactivation, pc_adjusted, mod,
+			     symname, cudie, die);
+      else
+	print_frame (frame_nr++, pc, isactivation, pc_adjusted, mod, symname,
+		     NULL, NULL);
+    }
+
+  if (frames->frames > 0 && frame_nr == maxframes)
+    error (0, 0, "tid %lld: shown max number of frames "
+	   "(%d, use -n 0 for unlimited)", (long long) tid, maxframes);
+  else if (dwflerr != 0)
+    {
+      if (frames->frames > 0)
+	{
+	  unsigned nr = frames->frames - 1;
+	  Dwarf_Addr pc = frames->frame[nr].pc;
+	  bool isactivation = frames->frame[nr].isactivation;
+	  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+	  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+	  const char *mainfile = NULL;
+	  const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL,
+						  NULL, &mainfile, NULL);
+	  if (modname == NULL || modname[0] == '\0')
+	    {
+	      if (mainfile != NULL)
+		modname = mainfile;
+	      else
+		modname = "<unknown>";
+	    }
+	  error (0, 0, "%s tid %lld at 0x%" PRIx64 " in %s: %s", what,
+		 (long long) tid, pc_adjusted, modname, dwfl_errmsg (dwflerr));
+	}
+      else
+	error (0, 0, "%s tid %lld: %s", what, (long long) tid,
+	       dwfl_errmsg (dwflerr));
+    }
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
+{
+  struct frames *frames = (struct frames *) thread_arg;
+  pid_t tid = dwfl_thread_tid (thread);
+  int err = 0;
+  frames->frames = 0;
+  switch (dwfl_thread_getframes (thread, frame_callback, thread_arg))
+    {
+    case DWARF_CB_OK:
+    case DWARF_CB_ABORT:
+      break;
+    case -1:
+      err = dwfl_errno ();
+      break;
+    default:
+      abort ();
+    }
+  print_frames (frames, tid, err, "dwfl_thread_getframes");
+  return DWARF_CB_OK;
+}
+
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+	   struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'p':
+      pid = atoi (arg);
+      if (pid == 0)
+	argp_error (state, N_("-p PID should be a positive process id."));
+      break;
+
+    case OPT_COREFILE:
+      core_fd = open (arg, O_RDONLY);
+      if (core_fd < 0)
+	error (EXIT_BAD, errno, N_("Cannot open core file '%s'"), arg);
+      elf_version (EV_CURRENT);
+      core = elf_begin (core_fd, ELF_C_READ_MMAP, NULL);
+      if (core == NULL)
+	error (EXIT_BAD, 0, "core '%s' elf_begin: %s", arg, elf_errmsg(-1));
+      break;
+
+    case 'e':
+      exec = arg;
+      break;
+
+    case OPT_DEBUGINFO:
+      debuginfo_path = arg;
+      break;
+
+    case 'm':
+      show_module = true;
+      break;
+
+    case 's':
+      show_source = true;
+      break;
+
+    case 'a':
+      show_activation = true;
+      break;
+
+    case 'd':
+      show_debugname = true;
+      break;
+
+    case 'i':
+      show_inlines = show_debugname = true;
+      break;
+
+    case 'v':
+      show_activation = show_source = show_module = show_debugname = true;
+      show_inlines = true;
+      break;
+
+    case 'b':
+      show_build_id = true;
+      break;
+
+    case 'q':
+      show_quiet = true;
+      break;
+
+    case 'r':
+      show_raw = true;
+      break;
+
+    case '1':
+      show_one_tid = true;
+      break;
+
+    case 'n':
+      maxframes = atoi (arg);
+      if (maxframes < 0)
+	{
+	  argp_error (state, N_("-n MAXFRAMES should be 0 or higher."));
+	  return EINVAL;
+	}
+      break;
+
+    case 'l':
+      show_modules = true;
+      break;
+
+    case ARGP_KEY_END:
+      if (core == NULL && exec != NULL)
+	argp_error (state,
+		    N_("-e EXEC needs a core given by --core."));
+
+      if (pid == 0 && show_one_tid == true)
+	argp_error (state,
+		    N_("-1 needs a thread id given by -p."));
+
+      if ((pid == 0 && core == NULL) || (pid != 0 && core != NULL))
+	argp_error (state,
+		    N_("One of -p PID or --core COREFILE should be given."));
+
+      if (pid != 0)
+	{
+	  dwfl = dwfl_begin (&proc_callbacks);
+	  if (dwfl == NULL)
+	    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+
+	  int err = dwfl_linux_proc_report (dwfl, pid);
+	  if (err < 0)
+	    error (EXIT_BAD, 0, "dwfl_linux_proc_report pid %lld: %s",
+		   (long long) pid, dwfl_errmsg (-1));
+	  else if (err > 0)
+	    error (EXIT_BAD, err, "dwfl_linux_proc_report pid %lld",
+		   (long long) pid);
+	}
+
+      if (core != NULL)
+	{
+	  dwfl = dwfl_begin (&core_callbacks);
+	  if (dwfl == NULL)
+	    error (EXIT_BAD, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+	  if (dwfl_core_file_report (dwfl, core, exec) < 0)
+	    error (EXIT_BAD, 0, "dwfl_core_file_report: %s", dwfl_errmsg (-1));
+	}
+
+      if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+	error (EXIT_BAD, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+      if (pid != 0)
+	{
+	  int err = dwfl_linux_proc_attach (dwfl, pid, false);
+	  if (err < 0)
+	    error (EXIT_BAD, 0, "dwfl_linux_proc_attach pid %lld: %s",
+		   (long long) pid, dwfl_errmsg (-1));
+	  else if (err > 0)
+	    error (EXIT_BAD, err, "dwfl_linux_proc_attach pid %lld",
+		   (long long) pid);
+	}
+
+      if (core != NULL)
+	{
+	  if (dwfl_core_file_attach (dwfl, core) < 0)
+	    error (EXIT_BAD, 0, "dwfl_core_file_attach: %s", dwfl_errmsg (-1));
+	}
+
+      /* Makes sure we are properly attached.  */
+      if (dwfl_pid (dwfl) < 0)
+	error (EXIT_BAD, 0, "dwfl_pid: %s\n", dwfl_errmsg (-1));
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  const struct argp_option options[] =
+    {
+      { NULL, 0, NULL, 0, N_("Input selection options:"), 0 },
+      { "pid", 'p', "PID", 0,
+	N_("Show stack of process PID"), 0 },
+      { "core", OPT_COREFILE, "COREFILE", 0,
+	N_("Show stack found in COREFILE"), 0 },
+      {  "executable", 'e', "EXEC", 0, N_("(optional) EXECUTABLE that produced COREFILE"), 0 },
+      { "debuginfo-path", OPT_DEBUGINFO, "PATH", 0,
+	N_("Search path for separate debuginfo files"), 0 },
+
+      { NULL, 0, NULL, 0, N_("Output selection options:"), 0 },
+      { "activation",  'a', NULL, 0,
+	N_("Additionally show frame activation"), 0 },
+      { "debugname",  'd', NULL, 0,
+	N_("Additionally try to lookup DWARF debuginfo name for frame address"),
+	0 },
+      { "inlines",  'i', NULL, 0,
+	N_("Additionally show inlined function frames using DWARF debuginfo if available (implies -d)"), 0 },
+      { "module",  'm', NULL, 0,
+	N_("Additionally show module file information"), 0 },
+      { "source",  's', NULL, 0,
+	N_("Additionally show source file information"), 0 },
+      { "verbose", 'v', NULL, 0,
+	N_("Show all additional information (activation, debugname, inlines, module and source)"), 0 },
+      { "quiet", 'q', NULL, 0,
+	N_("Do not resolve address to function symbol name"), 0 },
+      { "raw", 'r', NULL, 0,
+	N_("Show raw function symbol names, do not try to demangle names"), 0 },
+      { "build-id",  'b', NULL, 0,
+	N_("Show module build-id, load address and pc offset"), 0 },
+      { NULL, '1', NULL, 0,
+	N_("Show the backtrace of only one thread"), 0 },
+      { NULL, 'n', "MAXFRAMES", 0,
+	N_("Show at most MAXFRAMES per thread (default 256, use 0 for unlimited)"), 0 },
+      { "list-modules", 'l', NULL, 0,
+	N_("Show module memory map with build-id, elf and debug files detected"), 0 },
+      { NULL, 0, NULL, 0, NULL, 0 }
+    };
+
+  const struct argp argp =
+    {
+      .options = options,
+      .parser = parse_opt,
+      .doc = N_("Print a stack for each thread in a process or core file.\n\
+\n\
+Program exits with return code 0 if all frames were shown without \
+any errors.  If some frames were shown, but there were some non-fatal \
+errors, possibly causing an incomplete backtrace, the program exits \
+with return code 1.  If no frames could be shown, or a fatal error \
+occurred the program exits with return code 2.  If the program was \
+invoked with bad or missing arguments it will exit with return code 64.")
+    };
+
+  argp_parse (&argp, argc, argv, 0, NULL, NULL);
+
+  if (show_modules)
+    {
+      printf ("PID %lld - %s module memory map\n", (long long) dwfl_pid (dwfl),
+	      pid != 0 ? "process" : "core");
+      if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0)
+	error (EXIT_BAD, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+    }
+
+  struct frames frames;
+  /* When maxframes is zero, then 2048 is just the initial allocation
+     that will be increased using realloc in framecallback ().  */
+  frames.allocated = maxframes == 0 ? 2048 : maxframes;
+  frames.frames = 0;
+  frames.frame = malloc (sizeof (struct frame) * frames.allocated);
+  if (frames.frame == NULL)
+    error (EXIT_BAD, errno, "malloc frames.frame");
+
+  if (show_one_tid)
+    {
+      int err = 0;
+      switch (dwfl_getthread_frames (dwfl, pid, frame_callback, &frames))
+	{
+	case DWARF_CB_OK:
+	case DWARF_CB_ABORT:
+	  break;
+	case -1:
+	  err = dwfl_errno ();
+	  break;
+	default:
+	  abort ();
+	}
+      print_frames (&frames, pid, err, "dwfl_getthread_frames");
+    }
+  else
+    {
+      printf ("PID %lld - %s\n", (long long) dwfl_pid (dwfl),
+	      pid != 0 ? "process" : "core");
+      switch (dwfl_getthreads (dwfl, thread_callback, &frames))
+	{
+	case DWARF_CB_OK:
+	case DWARF_CB_ABORT:
+	  break;
+	case -1:
+	  error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+	  break;
+	default:
+	  abort ();
+	}
+    }
+  free (frames.frame);
+  dwfl_end (dwfl);
+
+  if (core != NULL)
+    elf_end (core);
+
+  if (core_fd != -1)
+    close (core_fd);
+
+#ifdef USE_DEMANGLE
+  free (demangle_buffer);
+#endif
+
+  if (! frames_shown)
+    error (EXIT_BAD, 0, N_("Couldn't show any frames."));
+
+  return error_message_count != 0 ? EXIT_ERROR : EXIT_OK;
+}
diff --git a/src/strings.c b/src/strings.c
new file mode 100644
index 0000000..69d09cc
--- /dev/null
+++ b/src/strings.c
@@ -0,0 +1,745 @@
+/* Print the strings of printable characters in files.
+   Copyright (C) 2005-2010, 2012, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <ctype.h>
+#include <endian.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <libeu.h>
+#include <system.h>
+#include <printversion.h>
+
+#ifndef MAP_POPULATE
+# define MAP_POPULATE 0
+#endif
+
+
+/* Prototypes of local functions.  */
+static int read_fd (int fd, const char *fname, off_t fdlen);
+static int read_elf (Elf *elf, int fd, const char *fname, off_t fdlen);
+
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Output Selection:"), 0 },
+  { "all", 'a', NULL, 0, N_("Scan entire file, not only loaded sections"), 0 },
+  { "bytes", 'n', "MIN-LEN", 0,
+    N_("Only NUL-terminated sequences of MIN-LEN characters or more are printed"), 0 },
+  { "encoding", 'e', "SELECTOR", 0, N_("\
+Select character size and endianness: s = 7-bit, S = 8-bit, {b,l} = 16-bit, {B,L} = 32-bit"),
+    0},
+  { "print-file-name", 'f', NULL, 0,
+    N_("Print name of the file before each string."), 0 },
+  { "radix", 't', "{o,d,x}", 0,
+    N_("Print location of the string in base 8, 10, or 16 respectively."), 0 },
+  { NULL, 'o', NULL, 0, N_("Alias for --radix=o"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Miscellaneous:"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("\
+Print the strings of printable characters in files.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+
+/* Global variables.  */
+
+/* True if whole file and not only loaded sections are looked at.  */
+static bool entire_file;
+
+/* Minimum length of any sequence reported.  */
+static size_t min_len = 4;
+
+/* Number of bytes per character.  */
+static size_t bytes_per_char = 1;
+
+/* Minimum length of any sequence reported in bytes.  */
+static size_t min_len_bytes;
+
+/* True if multibyte characters are in big-endian order.  */
+static bool big_endian;
+
+/* True unless 7-bit ASCII are expected.  */
+static bool char_7bit;
+
+/* True if file names should be printed before strings.  */
+static bool print_file_name;
+
+/* Radix for printed numbers.  */
+static enum
+{
+  radix_none = 0,
+  radix_decimal,
+  radix_hex,
+  radix_octal
+} radix = radix_none;
+
+
+/* Page size in use.  */
+static size_t ps;
+
+
+/* Mapped parts of the ELF file.  */
+static unsigned char *elfmap;
+static unsigned char *elfmap_base;
+static size_t elfmap_size;
+static off_t elfmap_off;
+
+
+int
+main (int argc, char *argv[])
+{
+  /* We use no threads.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  (void) textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  int remaining;
+  (void) argp_parse (&argp, argc, argv, 0, &remaining, NULL);
+
+  /* Tell the library which version we are expecting.  */
+  elf_version (EV_CURRENT);
+
+  /* Determine the page size.  We will likely need it a couple of times.  */
+  ps = sysconf (_SC_PAGESIZE);
+
+  struct stat st;
+  int result = 0;
+  if (remaining == argc)
+    /* We read from standard input.  This we cannot do for a
+       structured file.  */
+    result = read_fd (STDIN_FILENO,
+		      print_file_name ? "{standard input}" : NULL,
+		      (fstat (STDIN_FILENO, &st) == 0 && S_ISREG (st.st_mode))
+		      ? st.st_size : INT64_C (0x7fffffffffffffff));
+  else
+    do
+      {
+	int fd = (strcmp (argv[remaining], "-") == 0
+		  ? STDIN_FILENO : open (argv[remaining], O_RDONLY));
+	if (unlikely (fd == -1))
+	  {
+	    error (0, errno, _("cannot open '%s'"), argv[remaining]);
+	    result = 1;
+	  }
+	else
+	  {
+	    const char *fname = print_file_name ? argv[remaining] : NULL;
+	    int fstat_fail = fstat (fd, &st);
+	    off_t fdlen = (fstat_fail
+			     ? INT64_C (0x7fffffffffffffff) : st.st_size);
+	    if (fdlen > (off_t) min_len_bytes)
+	      {
+		Elf *elf = NULL;
+		if (entire_file
+		    || fstat_fail
+		    || !S_ISREG (st.st_mode)
+		    || (elf = elf_begin (fd, ELF_C_READ, NULL)) == NULL
+		    || elf_kind (elf) != ELF_K_ELF)
+		  result |= read_fd (fd, fname, fdlen);
+		else
+		  result |= read_elf (elf, fd, fname, fdlen);
+
+		/* This call will succeed even if ELF is NULL.  */
+		elf_end (elf);
+	      }
+
+	    if (strcmp (argv[remaining], "-") != 0)
+	      close (fd);
+	  }
+
+	if (elfmap != NULL && elfmap != MAP_FAILED)
+	  munmap (elfmap, elfmap_size);
+	elfmap = NULL;
+      }
+    while (++remaining < argc);
+
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg,
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case 'a':
+      entire_file = true;
+      break;
+
+    case 'e':
+      /* We expect a string of one character.  */
+      switch (arg[1] != '\0' ? '\0' : arg[0])
+	{
+	case 's':
+	case 'S':
+	  char_7bit = arg[0] == 's';
+	  bytes_per_char = 1;
+	  break;
+
+	case 'b':
+	case 'B':
+	  big_endian = true;
+	  FALLTHROUGH;
+
+	case 'l':
+	case 'L':
+	  bytes_per_char = isupper (arg[0]) ? 4 : 2;
+	  break;
+
+	default:
+	  error (0, 0, _("invalid value '%s' for %s parameter"),
+		 arg, "-e");
+	  argp_help (&argp, stderr, ARGP_HELP_SEE, "strings");
+	  return ARGP_ERR_UNKNOWN;
+	}
+      break;
+
+    case 'f':
+      print_file_name = true;
+      break;
+
+    case 'n':
+      min_len = atoi (arg);
+      break;
+
+    case 'o':
+      goto octfmt;
+
+    case 't':
+      switch (arg[0])
+	{
+	case 'd':
+	  radix = radix_decimal;
+	  break;
+
+	case 'o':
+	octfmt:
+	  radix = radix_octal;
+	  break;
+
+	case 'x':
+	  radix = radix_hex;
+	  break;
+
+	default:
+	  error (0, 0, _("invalid value '%s' for %s parameter"),
+		 arg, "-t");
+	  argp_help (&argp, stderr, ARGP_HELP_SEE, "strings");
+	  return ARGP_ERR_UNKNOWN;
+	}
+      break;
+
+    case ARGP_KEY_FINI:
+      /* Compute the length in bytes of any match.  */
+      if (min_len <= 0 || min_len > INT_MAX / bytes_per_char)
+	error_exit (0, _("invalid minimum length of matched string size"));
+      min_len_bytes = min_len * bytes_per_char;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+
+static void
+process_chunk_mb (const char *fname, const unsigned char *buf, off_t to,
+		  size_t len, char **unprinted)
+{
+  size_t curlen = *unprinted == NULL ? 0 : strlen (*unprinted);
+  const unsigned char *start = buf;
+  while (len >= bytes_per_char)
+    {
+      uint32_t ch;
+
+      if (bytes_per_char == 2)
+	{
+	  if (big_endian)
+	    ch = buf[0] << 8 | buf[1];
+	  else
+	    ch = buf[1] << 8 | buf[0];
+	}
+      else
+	{
+	  if (big_endian)
+	    ch = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
+	  else
+	    ch = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
+	}
+
+      if (ch <= 255 && (isprint (ch) || ch == '\t'))
+	{
+	  ++buf;
+	  ++curlen;
+	}
+      else
+	{
+	  if (curlen >= min_len)
+	    {
+	      /* We found a match.  */
+	      if (unlikely (fname != NULL))
+		{
+		  fputs_unlocked (fname, stdout);
+		  fputs_unlocked (": ", stdout);
+		}
+
+	      if (unlikely (radix != radix_none))
+		printf ((radix == radix_octal ? "%7" PRIo64 " "
+			 : (radix == radix_decimal ? "%7" PRId64 " "
+			    : "%7" PRIx64 " ")),
+			(int64_t) to - len - (buf - start));
+
+	      if (unlikely (*unprinted != NULL))
+		{
+		  fputs_unlocked (*unprinted, stdout);
+		  free (*unprinted);
+		  *unprinted = NULL;
+		}
+
+	      /* There is no sane way of printing the string.  If we
+		 assume the file data is encoded in UCS-2/UTF-16 or
+		 UCS-4/UTF-32 respectively we could convert the string.
+		 But there is no such guarantee.  */
+	      fwrite_unlocked (start, 1, buf - start, stdout);
+	      putc_unlocked ('\n', stdout);
+	    }
+
+	  start = ++buf;
+	  curlen =  0;
+
+	  if (len <= min_len)
+	    break;
+	}
+
+      --len;
+    }
+
+  if (curlen != 0)
+    *unprinted = xstrndup ((const char *) start, curlen);
+}
+
+
+static void
+process_chunk (const char *fname, const unsigned char *buf, off_t to,
+	       size_t len, char **unprinted)
+{
+  /* We are not going to slow the check down for the 2- and 4-byte
+     encodings.  Handle them special.  */
+  if (unlikely (bytes_per_char != 1))
+    {
+      process_chunk_mb (fname, buf, to, len, unprinted);
+      return;
+    }
+
+  size_t curlen = *unprinted == NULL ? 0 : strlen (*unprinted);
+  const unsigned char *start = buf;
+  while (len > 0)
+    {
+      if ((isprint (*buf) || *buf == '\t') && (! char_7bit || *buf <= 127))
+	{
+	  ++buf;
+	  ++curlen;
+	}
+      else
+	{
+	  if (curlen >= min_len)
+	    {
+	      /* We found a match.  */
+	      if (likely (fname != NULL))
+		{
+		  fputs_unlocked (fname, stdout);
+		  fputs_unlocked (": ", stdout);
+		}
+
+	      if (likely (radix != radix_none))
+		printf ((radix == radix_octal ? "%7" PRIo64 " "
+			 : (radix == radix_decimal ? "%7" PRId64 " "
+			    : "%7" PRIx64 " ")),
+			(int64_t) to - len - (buf - start));
+
+	      if (unlikely (*unprinted != NULL))
+		{
+		  fputs_unlocked (*unprinted, stdout);
+		  free (*unprinted);
+		  *unprinted = NULL;
+		}
+	      fwrite_unlocked (start, 1, buf - start, stdout);
+	      putc_unlocked ('\n', stdout);
+	    }
+
+	  start = ++buf;
+	  curlen =  0;
+
+	  if (len <= min_len)
+	    break;
+	}
+
+      --len;
+    }
+
+  if (curlen != 0)
+    *unprinted = xstrndup ((const char *) start, curlen);
+}
+
+
+/* Map a file in as large chunks as possible.  */
+static void *
+map_file (int fd, off_t start_off, off_t fdlen, size_t *map_sizep)
+{
+  /* Maximum size we mmap.  We use an #ifdef to avoid overflows on
+     32-bit machines.  64-bit machines these days do not have usable
+     address spaces larger than about 43 bits.  Not that any file
+     should be that large.  */
+# if SIZE_MAX > 0xffffffff
+  const size_t mmap_max = 0x4000000000lu;
+# else
+  const size_t mmap_max = 0x40000000lu;
+# endif
+
+  /* Try to mmap the file.  */
+  size_t map_size = MIN ((off_t) mmap_max, fdlen);
+  const size_t map_size_min = MAX (MAX (SIZE_MAX / 16, 2 * ps),
+				   roundup (2 * min_len_bytes + 1, ps));
+  void *mem;
+  while (1)
+    {
+      /* We map the memory for reading only here.  Since we will
+	 always look at every byte of the file it makes sense to
+	 use MAP_POPULATE.  */
+      mem = mmap (NULL, map_size, PROT_READ, MAP_PRIVATE | MAP_POPULATE,
+		  fd, start_off);
+      if (mem != MAP_FAILED)
+	{
+	  /* We will go through the mapping sequentially.  */
+	  (void) posix_madvise (mem, map_size, POSIX_MADV_SEQUENTIAL);
+	  break;
+	}
+      if (errno != EINVAL && errno != ENOMEM)
+	/* This is an error other than the lack of address space.  */
+	break;
+
+      /* Maybe the size of the mapping is too big.  Try again.  */
+      map_size /= 2;
+      if (map_size < map_size_min)
+	/* That size should have fit.  */
+	break;
+    }
+
+  *map_sizep = map_size;
+  return mem;
+}
+
+
+/* Read the file without mapping.  */
+static int
+read_block_no_mmap (int fd, const char *fname, off_t from, off_t fdlen)
+{
+  char *unprinted = NULL;
+#define CHUNKSIZE 65536
+  unsigned char *buf = xmalloc (CHUNKSIZE + min_len_bytes
+				+ bytes_per_char - 1);
+  size_t ntrailer = 0;
+  int result = 0;
+  while (fdlen > 0)
+    {
+      ssize_t n = TEMP_FAILURE_RETRY (read (fd, buf + ntrailer,
+					    MIN (fdlen, CHUNKSIZE)));
+      if (n == 0)
+	{
+	  /* There are less than MIN_LEN+1 bytes left so there cannot be
+	     another match.  */
+	  assert (unprinted == NULL || ntrailer == 0);
+	  break;
+	}
+      if (unlikely (n < 0))
+	{
+	  /* Something went wrong.  */
+	  result = 1;
+	  break;
+	}
+
+      /* Account for the number of bytes read in this round.  */
+      fdlen -= n;
+
+      /* Do not use the signed N value.  Note that the addition cannot
+	 overflow.  */
+      size_t nb = (size_t) n + ntrailer;
+      if (nb >= min_len_bytes)
+	{
+	  /* We only use complete characters.  */
+	  nb &= ~(bytes_per_char - 1);
+
+	  process_chunk (fname, buf, from + nb, nb, &unprinted);
+
+	  /* If the last bytes of the buffer (modulo the character
+	     size) have been printed we are not copying them.  */
+	  size_t to_keep = unprinted != NULL ? 0 : min_len_bytes;
+
+	  memmove (buf, buf + nb - to_keep, to_keep);
+	  ntrailer = to_keep;
+	  from += nb;
+	}
+      else
+	ntrailer = nb;
+    }
+
+  free (buf);
+
+  /* Don't print anything we collected so far.  There is no
+     terminating NUL byte.  */
+  free (unprinted);
+
+  return result;
+}
+
+
+static int
+read_block (int fd, const char *fname, off_t fdlen, off_t from, off_t to)
+{
+  if (elfmap == NULL)
+    {
+      /* We need a completely new mapping.  */
+      elfmap_off = from & ~(ps - 1);
+      elfmap_base = elfmap = map_file (fd, elfmap_off, fdlen, &elfmap_size);
+
+      if (unlikely (elfmap == MAP_FAILED))
+	/* Let the kernel know we are going to read everything in sequence.  */
+	(void) posix_fadvise (fd, 0, 0, POSIX_FADV_SEQUENTIAL);
+    }
+
+  if (unlikely (elfmap == MAP_FAILED))
+    {
+      /* Read from the file descriptor.  For this we must position the
+	 read pointer.  */
+      // XXX Eventually add flag which avoids this if the position
+      // XXX is known to match.
+      if (from != 0 && lseek (fd, from, SEEK_SET) != from)
+	error_exit (errno, _("lseek failed"));
+
+      return read_block_no_mmap (fd, fname, from, to - from);
+    }
+
+  assert ((off_t) min_len_bytes < fdlen);
+
+  if (to < (off_t) elfmap_off || from > (off_t) (elfmap_off + elfmap_size))
+    {
+      /* The existing mapping cannot fit at all.  Map the new area.
+	 We always map the full range of ELFMAP_SIZE bytes even if
+	 this extend beyond the end of the file.  The Linux kernel
+	 handles this OK if the access pages are not touched.  */
+      elfmap_off = from & ~(ps - 1);
+      if (mmap (elfmap, elfmap_size, PROT_READ,
+		MAP_PRIVATE | MAP_POPULATE | MAP_FIXED, fd, from)
+	  == MAP_FAILED)
+	error_exit (errno, _("re-mmap failed"));
+      elfmap_base = elfmap;
+    }
+
+  char *unprinted = NULL;
+
+  /* Use the existing mapping as much as possible.  If necessary, map
+     new pages.  */
+  if (from >= (off_t) elfmap_off
+      && from < (off_t) (elfmap_off + elfmap_size))
+    /* There are at least a few bytes in this mapping which we can
+       use.  */
+    process_chunk (fname, elfmap_base + (from - elfmap_off),
+		   MIN (to, (off_t) (elfmap_off + elfmap_size)),
+		   MIN (to, (off_t) (elfmap_off + elfmap_size)) - from,
+		   &unprinted);
+
+  if (to > (off_t) (elfmap_off + elfmap_size))
+    {
+      unsigned char *remap_base = elfmap_base;
+      size_t read_now = elfmap_size - (elfmap_base - elfmap);
+
+      assert (from >= (off_t) elfmap_off
+	      && from < (off_t) (elfmap_off + elfmap_size));
+      off_t handled_to = elfmap_off + elfmap_size;
+      assert (elfmap == elfmap_base
+	      || (elfmap_base - elfmap
+		  == (ptrdiff_t) ((min_len_bytes + ps - 1) & ~(ps - 1))));
+      if (elfmap == elfmap_base)
+	{
+	  size_t keep_area = (min_len_bytes + ps - 1) & ~(ps - 1);
+	  assert (elfmap_size >= keep_area + ps);
+	  /* The keep area is used for the content of the previous
+	     buffer we have to keep.  This means copying those bytes
+	     and for this we have to make the data writable.  */
+	  if (unlikely (mprotect (elfmap, keep_area, PROT_READ | PROT_WRITE)
+			!= 0))
+	    error_exit (errno, _("mprotect failed"));
+
+	  elfmap_base = elfmap + keep_area;
+	}
+
+      while (1)
+	{
+	  /* Map the rest of the file, eventually again in pieces.
+	     We speed things up with a nice Linux feature.  Note
+	     that we have at least two pages mapped.  */
+	  size_t to_keep = unprinted != NULL ? 0 : min_len_bytes;
+
+	  assert (read_now >= to_keep);
+	  memmove (elfmap_base - to_keep,
+		   remap_base + read_now - to_keep, to_keep);
+	  remap_base = elfmap_base;
+
+	  assert ((elfmap_size - (elfmap_base - elfmap)) % bytes_per_char
+		  == 0);
+	  read_now = MIN (to - handled_to,
+			  (ptrdiff_t) elfmap_size - (elfmap_base - elfmap));
+
+	  assert (handled_to % ps == 0);
+	  assert (handled_to % bytes_per_char == 0);
+	  if (mmap (remap_base, read_now, PROT_READ,
+		    MAP_PRIVATE | MAP_POPULATE | MAP_FIXED, fd, handled_to)
+	      == MAP_FAILED)
+	    error_exit (errno, _("re-mmap failed"));
+	  elfmap_off = handled_to;
+
+	  process_chunk (fname, remap_base - to_keep,
+			 elfmap_off + (read_now & ~(bytes_per_char - 1)),
+			 to_keep + (read_now & ~(bytes_per_char - 1)),
+			 &unprinted);
+	  handled_to += read_now;
+	  if (handled_to >= to)
+	    break;
+	}
+    }
+
+  /* Don't print anything we collected so far.  There is no
+     terminating NUL byte.  */
+  free (unprinted);
+
+  return 0;
+}
+
+
+static int
+read_fd (int fd, const char *fname, off_t fdlen)
+{
+  return read_block (fd, fname, fdlen, 0, fdlen);
+}
+
+
+static int
+read_elf (Elf *elf, int fd, const char *fname, off_t fdlen)
+{
+  assert (fdlen >= 0);
+
+  /* We will look at each section separately.  The ELF file is not
+     mmapped.  The libelf implementation will load the needed parts on
+     demand.  Since we only iterate over the section header table the
+     memory consumption at this stage is kept minimal.  */
+  Elf_Scn *scn = elf_nextscn (elf, NULL);
+  if (scn == NULL)
+    return read_fd (fd, fname, fdlen);
+
+  int result = 0;
+  do
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      /* Only look in sections which are loaded at runtime and
+	 actually have content.  */
+      if (shdr != NULL && shdr->sh_type != SHT_NOBITS
+	  && (shdr->sh_flags & SHF_ALLOC) != 0)
+	{
+	  if (shdr->sh_offset > (Elf64_Off) fdlen
+	      || fdlen - shdr->sh_offset < shdr->sh_size)
+	    {
+	      size_t strndx = 0;
+	      const char *sname;
+	      if (unlikely (elf_getshdrstrndx (elf, &strndx) < 0))
+		sname = "<unknown>";
+	      else
+		sname = elf_strptr (elf, strndx, shdr->sh_name) ?: "<unknown>";
+	      error (0, 0,
+		     _("Skipping section %zd '%s' data outside file"),
+		     elf_ndxscn (scn), sname);
+	      result = 1;
+	    }
+	  else
+	    result |= read_block (fd, fname, fdlen, shdr->sh_offset,
+				  shdr->sh_offset + shdr->sh_size);
+	}
+    }
+  while ((scn = elf_nextscn (elf, scn)) != NULL);
+
+  if (elfmap != NULL && elfmap != MAP_FAILED)
+    munmap (elfmap, elfmap_size);
+  elfmap = NULL;
+
+  return result;
+}
+
+
+#include "debugpred.h"
diff --git a/src/strip.c b/src/strip.c
new file mode 100644
index 0000000..6436443
--- /dev/null
+++ b/src/strip.c
@@ -0,0 +1,2769 @@
+/* Discard section not used at runtime from object files.
+   Copyright (C) 2000-2012, 2014, 2015, 2016, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <byteswap.h>
+#include <endian.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+
+#include <elf-knowledge.h>
+#include <libebl.h>
+#include "libdwelf.h"
+#include <libeu.h>
+#include <system.h>
+#include <printversion.h>
+
+typedef uint8_t GElf_Byte;
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+
+/* Values for the parameters which have no short form.  */
+#define OPT_REMOVE_COMMENT	0x100
+#define OPT_PERMISSIVE		0x101
+#define OPT_STRIP_SECTIONS	0x102
+#define OPT_RELOC_DEBUG 	0x103
+#define OPT_KEEP_SECTION 	0x104
+#define OPT_RELOC_DEBUG_ONLY    0x105
+
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  { NULL, 0, NULL, 0, N_("Output selection:"), 0 },
+  { "output", 'o', "FILE", 0, N_("Place stripped output into FILE"), 0 },
+  { NULL, 'f', "FILE", 0, N_("Extract the removed sections into FILE"), 0 },
+  { NULL, 'F', "FILE", 0, N_("Embed name FILE instead of -f argument"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
+  { "strip-all", 's', NULL, OPTION_HIDDEN, NULL, 0 },
+  { "strip-debug", 'g', NULL, 0, N_("Remove all debugging symbols"), 0 },
+  { NULL, 'd', NULL, OPTION_ALIAS, NULL, 0 },
+  { NULL, 'S', NULL, OPTION_ALIAS, NULL, 0 },
+  { "strip-sections", OPT_STRIP_SECTIONS, NULL, 0,
+    N_("Remove section headers (not recommended)"), 0 },
+  { "preserve-dates", 'p', NULL, 0,
+    N_("Copy modified/access timestamps to the output"), 0 },
+  { "reloc-debug-sections", OPT_RELOC_DEBUG, NULL, 0,
+    N_("Resolve all trivial relocations between debug sections if the removed sections are placed in a debug file (only relevant for ET_REL files, operation is not reversible, needs -f)"), 0 },
+  { "reloc-debug-sections-only", OPT_RELOC_DEBUG_ONLY, NULL, 0,
+    N_("Similar to --reloc-debug-sections, but resolve all trivial relocations between debug sections in place.  No other stripping is performed (operation is not reversible, incompatible with -f, -g, --remove-comment and --remove-section)"), 0 },
+  { "remove-comment", OPT_REMOVE_COMMENT, NULL, 0,
+    N_("Remove .comment section"), 0 },
+  { "remove-section", 'R', "SECTION", 0, N_("Remove the named section.  SECTION is an extended wildcard pattern.  May be given more than once.  Only non-allocated sections can be removed."), 0 },
+  { "keep-section", OPT_KEEP_SECTION, "SECTION", 0, N_("Keep the named section.  SECTION is an extended wildcard pattern.  May be given more than once."), 0 },
+  { "permissive", OPT_PERMISSIVE, NULL, 0,
+    N_("Relax a few rules to handle slightly broken ELF files"), 0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+/* Short description of program.  */
+static const char doc[] = N_("Discard symbols from object files.");
+
+/* Strings for arguments in help texts.  */
+static const char args_doc[] = N_("[FILE...]");
+
+/* Prototype for option handler.  */
+static error_t parse_opt (int key, char *arg, struct argp_state *state);
+
+/* Data structure to communicate with argp functions.  */
+static struct argp argp =
+{
+  options, parse_opt, args_doc, doc, NULL, NULL, NULL
+};
+
+
+/* Print symbols in file named FNAME.  */
+static int process_file (const char *fname);
+
+/* Handle one ELF file.  */
+static int handle_elf (int fd, Elf *elf, const char *prefix,
+		       const char *fname, mode_t mode, struct timespec tvp[2]);
+
+/* Handle all files contained in the archive.  */
+static int handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
+		      struct timespec tvp[2]) __attribute__ ((unused));
+
+static int debug_fd = -1;
+static char *tmp_debug_fname = NULL;
+
+/* Close debug file descriptor, if opened. And remove temporary debug file.  */
+static void cleanup_debug (void);
+
+#define INTERNAL_ERROR(fname) \
+  do { \
+    cleanup_debug (); \
+    error_exit (0, _("%s: INTERNAL ERROR %d (%s): %s"),			\
+		fname, __LINE__, PACKAGE_VERSION, elf_errmsg (-1));	\
+  } while (0)
+
+
+/* Name of the output file.  */
+static const char *output_fname;
+
+/* Name of the debug output file.  */
+static const char *debug_fname;
+
+/* Name to pretend the debug output file has.  */
+static const char *debug_fname_embed;
+
+/* If true output files shall have same date as the input file.  */
+static bool preserve_dates;
+
+/* If true .comment sections will be removed.  */
+static bool remove_comment;
+
+/* If true remove all debug sections.  */
+static bool remove_debug;
+
+/* If true remove all section headers.  */
+static bool remove_shdrs;
+
+/* If true relax some ELF rules for input files.  */
+static bool permissive;
+
+/* If true perform relocations between debug sections.  */
+static bool reloc_debug;
+
+/* If true perform relocations between debug sections only.  */
+static bool reloc_debug_only;
+
+/* Sections the user explicitly wants to keep or remove.  */
+struct section_pattern
+{
+  char *pattern;
+  struct section_pattern *next;
+};
+
+static struct section_pattern *keep_secs = NULL;
+static struct section_pattern *remove_secs = NULL;
+
+static void
+add_pattern (struct section_pattern **patterns, const char *pattern)
+{
+  struct section_pattern *p = xmalloc (sizeof *p);
+  p->pattern = xstrdup (pattern);
+  p->next = *patterns;
+  *patterns = p;
+}
+
+static void
+free_sec_patterns (struct section_pattern *patterns)
+{
+  struct section_pattern *pattern = patterns;
+  while (pattern != NULL)
+    {
+      struct section_pattern *p = pattern;
+      pattern = p->next;
+      free (p->pattern);
+      free (p);
+    }
+}
+
+static void
+free_patterns (void)
+{
+  free_sec_patterns (keep_secs);
+  free_sec_patterns (remove_secs);
+}
+
+static bool
+section_name_matches (struct section_pattern *patterns, const char *name)
+{
+  struct section_pattern *pattern = patterns;
+  while (pattern != NULL)
+    {
+      if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0)
+	return true;
+      pattern = pattern->next;
+    }
+  return false;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+  int result = 0;
+
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  if (argp_parse (&argp, argc, argv, 0, &remaining, NULL) != 0)
+    return EXIT_FAILURE;
+
+  if (reloc_debug && debug_fname == NULL)
+    error_exit (0, _("--reloc-debug-sections used without -f"));
+
+  if (reloc_debug_only &&
+      (debug_fname != NULL || remove_secs != NULL
+       || remove_comment == true || remove_debug == true))
+    error_exit (0,
+		_("--reloc-debug-sections-only incompatible with -f, -g, --remove-comment and --remove-section"));
+
+  /* Tell the library which version we are expecting.  */
+  elf_version (EV_CURRENT);
+
+  if (remaining == argc)
+    /* The user didn't specify a name so we use a.out.  */
+    result = process_file ("a.out");
+  else
+    {
+      /* If we have seen the '-o' or '-f' option there must be exactly one
+	 input file.  */
+      if ((output_fname != NULL || debug_fname != NULL)
+	  && remaining + 1 < argc)
+	error_exit (0, _("Only one input file allowed together with '-o' and '-f'"));
+
+      /* Process all the remaining files.  */
+      do
+	result |= process_file (argv[remaining]);
+      while (++remaining < argc);
+    }
+
+  free_patterns ();
+  return result;
+}
+
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case 'f':
+      if (debug_fname != NULL)
+	{
+	  error (0, 0, _("-f option specified twice"));
+	  return EINVAL;
+	}
+      debug_fname = arg;
+      break;
+
+    case 'F':
+      if (debug_fname_embed != NULL)
+	{
+	  error (0, 0, _("-F option specified twice"));
+	  return EINVAL;
+	}
+      debug_fname_embed = arg;
+      break;
+
+    case 'o':
+      if (output_fname != NULL)
+	{
+	  error (0, 0, _("-o option specified twice"));
+	  return EINVAL;
+	}
+      output_fname = arg;
+      break;
+
+    case 'p':
+      preserve_dates = true;
+      break;
+
+    case OPT_RELOC_DEBUG:
+      reloc_debug = true;
+      break;
+
+    case OPT_RELOC_DEBUG_ONLY:
+      reloc_debug_only = true;
+      break;
+
+    case OPT_REMOVE_COMMENT:
+      remove_comment = true;
+      break;
+
+    case 'R':
+      if (fnmatch (arg, ".comment", FNM_EXTMATCH) == 0)
+	remove_comment = true;
+      add_pattern (&remove_secs, arg);
+      break;
+
+    case OPT_KEEP_SECTION:
+      add_pattern (&keep_secs, arg);
+      break;
+
+    case 'g':
+    case 'd':
+    case 'S':
+      remove_debug = true;
+      break;
+
+    case OPT_STRIP_SECTIONS:
+      remove_shdrs = true;
+      break;
+
+    case OPT_PERMISSIVE:
+      permissive = true;
+      break;
+
+    case 's':			/* Ignored for compatibility.  */
+      break;
+
+    case ARGP_KEY_SUCCESS:
+      if (remove_comment == true
+	  && section_name_matches (keep_secs, ".comment"))
+	{
+	  argp_error (state,
+		      _("cannot both keep and remove .comment section"));
+	  return EINVAL;
+	}
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static const char *
+secndx_name (Elf *elf, size_t ndx)
+{
+  size_t shstrndx;
+  GElf_Shdr mem;
+  Elf_Scn *sec = elf_getscn (elf, ndx);
+  GElf_Shdr *shdr = gelf_getshdr (sec, &mem);
+  if (shdr == NULL || elf_getshdrstrndx (elf, &shstrndx) < 0)
+    return "???";
+  return elf_strptr (elf, shstrndx, shdr->sh_name) ?: "???";
+}
+
+/* Get the extended section index table data for a symbol table section.  */
+static Elf_Data *
+get_xndxdata (Elf *elf, Elf_Scn *symscn)
+{
+  Elf_Data *xndxdata = NULL;
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
+  if (shdr != NULL && shdr->sh_type == SHT_SYMTAB)
+    {
+      size_t scnndx = elf_ndxscn (symscn);
+      Elf_Scn *xndxscn = NULL;
+      while ((xndxscn = elf_nextscn (elf, xndxscn)) != NULL)
+	{
+	  GElf_Shdr xndxshdr_mem;
+	  GElf_Shdr *xndxshdr = gelf_getshdr (xndxscn, &xndxshdr_mem);
+
+	  if (xndxshdr != NULL
+	      && xndxshdr->sh_type == SHT_SYMTAB_SHNDX
+	      && xndxshdr->sh_link == scnndx)
+	    {
+	      xndxdata = elf_getdata (xndxscn, NULL);
+	      break;
+	    }
+	}
+    }
+
+  return xndxdata;
+}
+
+/* Updates the shdrstrndx for the given Elf by updating the Ehdr and
+   possibly the section zero extension field.  Returns zero on success.  */
+static int
+update_shdrstrndx (Elf *elf, size_t shdrstrndx)
+{
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == 0)
+    return 1;
+
+  if (shdrstrndx < SHN_LORESERVE)
+    ehdr.e_shstrndx = shdrstrndx;
+  else
+    {
+      ehdr.e_shstrndx = SHN_XINDEX;
+      Elf_Scn *scn0 = elf_getscn (elf, 0);
+      GElf_Shdr shdr0_mem;
+      GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem);
+      if (shdr0 == NULL)
+	return 1;
+
+      shdr0->sh_link = shdrstrndx;
+      if (gelf_update_shdr (scn0, shdr0) == 0)
+	return 1;
+    }
+
+  if (unlikely (gelf_update_ehdr (elf, &ehdr) == 0))
+    return 1;
+
+  return 0;
+}
+
+
+/* Apply one relocation.  Returns true when trivial
+   relocation actually done.  */
+static bool
+relocate (Elf *elf, GElf_Addr offset, const GElf_Sxword addend,
+	  Elf_Data *tdata, unsigned int ei_data, const char *fname,
+	  bool is_rela, GElf_Sym *sym, int addsub, Elf_Type type)
+{
+  /* These are the types we can relocate.  */
+#define TYPES   DO_TYPE (BYTE, Byte); DO_TYPE (HALF, Half);		\
+      DO_TYPE (WORD, Word); DO_TYPE (SWORD, Sword);		\
+      DO_TYPE (XWORD, Xword); DO_TYPE (SXWORD, Sxword)
+
+  size_t size;
+
+#define DO_TYPE(NAME, Name) GElf_##Name Name;
+  union { TYPES; } tmpbuf;
+#undef DO_TYPE
+
+  switch (type)
+    {
+#define DO_TYPE(NAME, Name)				\
+      case ELF_T_##NAME:			\
+	size = sizeof (GElf_##Name);	\
+	tmpbuf.Name = 0;			\
+	break;
+      TYPES;
+#undef DO_TYPE
+    default:
+      return false;
+    }
+
+  if (offset > tdata->d_size
+      || tdata->d_size - offset < size)
+    {
+      cleanup_debug ();
+      error_exit (0, _("bad relocation"));
+    }
+
+  /* When the symbol value is zero then for SHT_REL
+     sections this is all that needs to be checked.
+     The addend is contained in the original data at
+     the offset already.  So if the (section) symbol
+     address is zero and the given addend is zero
+     just remove the relocation, it isn't needed
+     anymore.  */
+  if (addend == 0 && sym->st_value == 0)
+    return true;
+
+  Elf_Data tmpdata =
+    {
+      .d_type = type,
+      .d_buf = &tmpbuf,
+      .d_size = size,
+      .d_version = EV_CURRENT,
+    };
+  Elf_Data rdata =
+    {
+      .d_type = type,
+      .d_buf = tdata->d_buf + offset,
+      .d_size = size,
+      .d_version = EV_CURRENT,
+    };
+
+  GElf_Addr value = sym->st_value;
+  if (is_rela)
+    {
+      /* For SHT_RELA sections we just take the
+	 given addend and add it to the value.  */
+      value += addend;
+      /* For ADD/SUB relocations we need to fetch the
+	 current section contents.  */
+      if (addsub != 0)
+	{
+	  Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
+				       &rdata,
+				       ei_data);
+	  if (d == NULL)
+	    INTERNAL_ERROR (fname);
+	  assert (d == &tmpdata);
+	}
+    }
+  else
+    {
+      /* For SHT_REL sections we have to peek at
+	 what is already in the section at the given
+	 offset to get the addend.  */
+      Elf_Data *d = gelf_xlatetom (elf, &tmpdata,
+				   &rdata,
+				   ei_data);
+      if (d == NULL)
+	INTERNAL_ERROR (fname);
+      assert (d == &tmpdata);
+    }
+
+  switch (type)
+    {
+#define DO_TYPE(NAME, Name)					 \
+      case ELF_T_##NAME:				 \
+	if (addsub < 0)				 \
+	  tmpbuf.Name -= (GElf_##Name) value;	 \
+	else					 \
+	  tmpbuf.Name += (GElf_##Name) value;	 \
+	break;
+      TYPES;
+#undef DO_TYPE
+    default:
+      abort ();
+    }
+
+  /* Now finally put in the new value.  */
+  Elf_Data *s = gelf_xlatetof (elf, &rdata,
+			       &tmpdata,
+			       ei_data);
+  if (s == NULL)
+    INTERNAL_ERROR (fname);
+  assert (s == &rdata);
+
+  return true;
+}
+
+/* Remove any relocations between debug sections in ET_REL
+   for the debug file when requested.  These relocations are always
+   zero based between the unallocated sections.  */
+static void
+remove_debug_relocations (Ebl *ebl, Elf *elf, GElf_Ehdr *ehdr,
+			  const char *fname, size_t shstrndx)
+{
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      /* We need the actual section and header from the elf
+	 not just the cached original in shdr_info because we
+	 might want to change the size.  */
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr != NULL
+	  && (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
+	{
+	  /* Make sure that this relocation section points to a
+	     section to relocate with contents, that isn't
+	     allocated and that is a debug section.  */
+	  Elf_Scn *tscn = elf_getscn (elf, shdr->sh_info);
+	  GElf_Shdr tshdr_mem;
+	  GElf_Shdr *tshdr = gelf_getshdr (tscn, &tshdr_mem);
+	  if (tshdr == NULL
+	      || tshdr->sh_type == SHT_NOBITS
+	      || tshdr->sh_size == 0
+	      || (tshdr->sh_flags & SHF_ALLOC) != 0)
+	    continue;
+
+	  const char *tname =  elf_strptr (elf, shstrndx,
+					   tshdr->sh_name);
+	  if (! tname || ! ebl_debugscn_p (ebl, tname))
+	    continue;
+
+	  /* OK, lets relocate all trivial cross debug section
+	     relocations. */
+	  Elf_Data *reldata = elf_getdata (scn, NULL);
+	  if (reldata == NULL || reldata->d_buf == NULL)
+	    INTERNAL_ERROR (fname);
+
+	  /* Make sure we adjust the uncompressed debug data
+	     (and recompress if necessary at the end).  */
+	  GElf_Chdr tchdr;
+	  int tcompress_type = 0;
+	  bool is_gnu_compressed = false;
+	  if (startswith (tname, ".zdebug"))
+	    {
+	      is_gnu_compressed = true;
+	      if (elf_compress_gnu (tscn, 0, 0) != 1)
+		INTERNAL_ERROR (fname);
+	    }
+	  else
+	    {
+	      if (gelf_getchdr (tscn, &tchdr) != NULL)
+		{
+		  tcompress_type = tchdr.ch_type;
+		  if (elf_compress (tscn, 0, 0) != 1)
+		    INTERNAL_ERROR (fname);
+		}
+	    }
+
+	  Elf_Data *tdata = elf_getdata (tscn, NULL);
+	  if (tdata == NULL || tdata->d_buf == NULL
+	      || tdata->d_type != ELF_T_BYTE)
+	    INTERNAL_ERROR (fname);
+
+	  /* Pick up the symbol table and shndx table to
+	     resolve relocation symbol indexes.  */
+	  Elf64_Word symt = shdr->sh_link;
+	  Elf_Data *symdata, *xndxdata;
+	  Elf_Scn * symscn = elf_getscn (elf, symt);
+	  symdata = elf_getdata (symscn, NULL);
+	  xndxdata = get_xndxdata (elf, symscn);
+	  if (symdata == NULL)
+	    INTERNAL_ERROR (fname);
+
+	  if (shdr->sh_entsize == 0)
+	    INTERNAL_ERROR (fname);
+
+	  size_t nrels = shdr->sh_size / shdr->sh_entsize;
+	  size_t next = 0;
+	  const bool is_rela = (shdr->sh_type == SHT_RELA);
+	  const unsigned int ei_data = ehdr->e_ident[EI_DATA];
+
+	  for (size_t relidx = 0; relidx < nrels; ++relidx)
+	    {
+	      int rtype, symndx, offset, addend;
+	      union { GElf_Rela rela; GElf_Rel rel; } mem;
+	      void *rel_p; /* Pointer to either rela or rel above */
+
+	      if (is_rela)
+		{
+		  GElf_Rela *r = gelf_getrela (reldata, relidx, &mem.rela);
+		  if (r == NULL)
+		    INTERNAL_ERROR (fname);
+		  offset = r->r_offset;
+		  addend = r->r_addend;
+		  rtype = GELF_R_TYPE (r->r_info);
+		  symndx = GELF_R_SYM (r->r_info);
+		  rel_p = r;
+		}
+	      else
+		{
+		  GElf_Rel *r = gelf_getrel (reldata, relidx, &mem.rel);
+		  if (r == NULL)
+		    INTERNAL_ERROR (fname);
+		  offset = r->r_offset;
+		  addend = 0;
+		  rtype = GELF_R_TYPE (r->r_info);
+		  symndx = GELF_R_SYM (r->r_info);
+		  rel_p = r;
+		}
+
+	      /* R_*_NONE relocs can always just be removed.  */
+	      if (rtype == 0)
+		continue;
+
+	      /* We only do simple absolute relocations.  */
+	      int addsub = 0;
+	      Elf_Type type = ebl_reloc_simple_type (ebl, rtype, &addsub);
+	      if (type == ELF_T_NUM)
+		goto relocate_failed;
+
+	      /* And only for relocations against other debug sections.  */
+	      GElf_Sym sym_mem;
+	      Elf32_Word xndx;
+	      GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+						symndx, &sym_mem,
+						  &xndx);
+	      if (sym == NULL)
+		INTERNAL_ERROR (fname);
+	      Elf32_Word sec = (sym->st_shndx == SHN_XINDEX
+				? xndx : sym->st_shndx);
+
+	      bool dbg_scn = ebl_debugscn_p (ebl, secndx_name (elf, sec));
+
+	      if (!dbg_scn)
+		goto relocate_failed;
+
+	      if (! relocate (elf, offset, addend,
+			    tdata, ei_data, fname, is_rela,
+			    sym, addsub, type))
+	      goto relocate_failed;
+
+	      continue; /* Next */
+
+relocate_failed:
+	      if (relidx != next)
+		{
+		  int updated;
+		  if (is_rela)
+		    updated = gelf_update_rela (reldata, next, rel_p);
+		  else
+		    updated = gelf_update_rel (reldata, next, rel_p);
+		  if (updated == 0)
+		    INTERNAL_ERROR (fname);
+		}
+	      ++next;
+	    }
+
+	  nrels = next;
+	  shdr->sh_size = reldata->d_size = nrels * shdr->sh_entsize;
+	  if (gelf_update_shdr (scn, shdr) == 0)
+	    INTERNAL_ERROR (fname);
+
+	  if (is_gnu_compressed)
+	    {
+	      if (elf_compress_gnu (tscn, 1, ELF_CHF_FORCE) != 1)
+		INTERNAL_ERROR (fname);
+	    }
+	  else if (tcompress_type != 0)
+	    {
+	      if (elf_compress (tscn, tcompress_type, ELF_CHF_FORCE) != 1)
+		INTERNAL_ERROR (fname);
+	    }
+	}
+    }
+}
+
+static int
+process_file (const char *fname)
+{
+  /* If we have to preserve the modify and access timestamps get them
+     now.  We cannot use fstat() after opening the file since the open
+     would change the access time.  */
+  struct stat pre_st;
+  struct timespec tv[2];
+ again:
+  if (preserve_dates)
+    {
+      if (stat (fname, &pre_st) != 0)
+	{
+	  error (0, errno, _("cannot stat input file '%s'"), fname);
+	  return 1;
+	}
+
+      /* If we have to preserve the timestamp, we need it in the
+	 format utimes() understands.  */
+      tv[0] = pre_st.st_atim;
+      tv[1] = pre_st.st_mtim;
+    }
+
+  /* Open the file.  */
+  int fd = open (fname, output_fname == NULL ? O_RDWR : O_RDONLY);
+  if (fd == -1)
+    {
+      error (0, errno, _("while opening '%s'"), fname);
+      return 1;
+    }
+
+  /* We always use fstat() even if we called stat() before.  This is
+     done to make sure the information returned by stat() is for the
+     same file.  */
+  struct stat st;
+  if (fstat (fd, &st) != 0)
+    {
+      error (0, errno, _("cannot stat input file '%s'"), fname);
+      return 1;
+    }
+  /* Paranoid mode on.  */
+  if (preserve_dates
+      && (st.st_ino != pre_st.st_ino || st.st_dev != pre_st.st_dev))
+    {
+      /* We detected a race.  Try again.  */
+      close (fd);
+      goto again;
+    }
+
+  /* Now get the ELF descriptor.  */
+  Elf *elf = elf_begin (fd, output_fname == NULL ? ELF_C_RDWR : ELF_C_READ,
+			NULL);
+  int result;
+  switch (elf_kind (elf))
+    {
+    case ELF_K_ELF:
+      result = handle_elf (fd, elf, NULL, fname, st.st_mode & ACCESSPERMS,
+			   preserve_dates ? tv : NULL);
+      break;
+
+    case ELF_K_AR:
+      /* It is not possible to strip the content of an archive direct
+	 the output to a specific file.  */
+      if (unlikely (output_fname != NULL || debug_fname != NULL))
+	{
+	  error (0, 0, _("%s: cannot use -o or -f when stripping archive"),
+		 fname);
+	  result = 1;
+	}
+      else
+	{
+	  /* We would like to support ar archives, but currently it just
+	     doesn't work at all since we call elf_clone on the members
+	     which doesn't really support ar members.
+	     result = handle_ar (fd, elf, NULL, fname,
+				 preserve_dates ? tv : NULL);
+	   */
+	  error (0, 0, _("%s: no support for stripping archive"),
+		 fname);
+	  result = 1;
+	}
+      break;
+
+    default:
+      error (0, 0, _("%s: File format not recognized"), fname);
+      result = 1;
+      break;
+    }
+
+  if (unlikely (elf_end (elf) != 0))
+    INTERNAL_ERROR (fname);
+
+  close (fd);
+
+  return result;
+}
+
+/* Processing for --reloc-debug-sections-only.  */
+static int
+handle_debug_relocs (Elf *elf, Ebl *ebl, Elf *new_elf,
+		     GElf_Ehdr *ehdr, const char *fname, size_t shstrndx,
+		     GElf_Off *last_offset, GElf_Xword *last_size)
+{
+
+  /* Copy over the ELF header.  */
+  if (gelf_update_ehdr (new_elf, ehdr) == 0)
+    {
+      error (0, 0, "couldn't update new ehdr: %s", elf_errmsg (-1));
+      return 1;
+    }
+
+  /* Copy over sections and record end of allocated sections.  */
+  GElf_Off lastoffset = 0;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      /* Get the header.  */
+      GElf_Shdr shdr;
+      if (gelf_getshdr (scn, &shdr) == NULL)
+	{
+	  error (0, 0, "couldn't get shdr: %s", elf_errmsg (-1));
+	  return 1;
+	}
+
+      /* Create new section.  */
+      Elf_Scn *new_scn = elf_newscn (new_elf);
+      if (new_scn == NULL)
+	{
+	  error (0, 0, "couldn't create new section: %s", elf_errmsg (-1));
+	  return 1;
+	}
+
+      if (gelf_update_shdr (new_scn, &shdr) == 0)
+	{
+	  error (0, 0, "couldn't update shdr: %s", elf_errmsg (-1));
+	  return 1;
+	}
+
+      /* Copy over section data.  */
+      Elf_Data *data = NULL;
+      while ((data = elf_getdata (scn, data)) != NULL)
+	{
+	  Elf_Data *new_data = elf_newdata (new_scn);
+	  if (new_data == NULL)
+	    {
+	      error (0, 0, "couldn't create new section data: %s",
+		     elf_errmsg (-1));
+	      return 1;
+	    }
+	  *new_data = *data;
+	}
+
+      /* Record last offset of allocated section.  */
+      if ((shdr.sh_flags & SHF_ALLOC) != 0)
+	{
+	  GElf_Off filesz = (shdr.sh_type != SHT_NOBITS
+			     ? shdr.sh_size : 0);
+	  if (lastoffset < shdr.sh_offset + filesz)
+	    lastoffset = shdr.sh_offset + filesz;
+	}
+    }
+
+  /* Make sure section header name table is setup correctly, we'll
+     need it to determine whether to relocate sections.  */
+  if (update_shdrstrndx (new_elf, shstrndx) != 0)
+    {
+      error (0, 0, "error updating shdrstrndx: %s", elf_errmsg (-1));
+      return 1;
+    }
+
+  /* Adjust the relocation sections.  */
+  remove_debug_relocations (ebl, new_elf, ehdr, fname, shstrndx);
+
+  /* Adjust the offsets of the non-allocated sections, so they come after
+     the allocated sections.  */
+  scn = NULL;
+  while ((scn = elf_nextscn (new_elf, scn)) != NULL)
+    {
+      /* Get the header.  */
+      GElf_Shdr shdr;
+      if (gelf_getshdr (scn, &shdr) == NULL)
+	{
+	  error (0, 0, "couldn't get shdr: %s", elf_errmsg (-1));
+	  return 1;
+	}
+
+      /* Adjust non-allocated section offsets to be after any allocated.  */
+      if ((shdr.sh_flags & SHF_ALLOC) == 0)
+	{
+	  shdr.sh_offset = ((lastoffset + shdr.sh_addralign - 1)
+			    & ~((GElf_Off) (shdr.sh_addralign - 1)));
+	  if (gelf_update_shdr (scn, &shdr) == 0)
+	    {
+	      error (0, 0, "couldn't update shdr: %s", elf_errmsg (-1));
+	      return 1;
+	    }
+
+	  GElf_Off filesz = (shdr.sh_type != SHT_NOBITS
+			     ? shdr.sh_size : 0);
+	  lastoffset = shdr.sh_offset + filesz;
+	  *last_offset = shdr.sh_offset;
+	  *last_size = filesz;
+	}
+    }
+
+  return 0;
+}
+
+/* Update section headers when the data size has changed.
+   We also update the SHT_NOBITS section in the debug
+   file so that the section headers match in sh_size.  */
+static inline void
+update_section_size (Elf_Scn *scn,
+		     const Elf_Data *newdata,
+		     Elf *debugelf,
+		     size_t cnt,
+		     const char *fname)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  shdr->sh_size = newdata->d_size;
+  if (gelf_update_shdr (scn, shdr) == 0)
+    INTERNAL_ERROR (fname);
+  if (debugelf != NULL)
+    {
+      /* libelf will use d_size to set sh_size.  */
+      Elf_Data *debugdata = elf_getdata (elf_getscn (debugelf,
+						     cnt), NULL);
+      if (debugdata == NULL)
+	INTERNAL_ERROR (fname);
+      debugdata->d_size = newdata->d_size;
+    }
+}
+
+/* Maximum size of array allocated on stack.  */
+#define MAX_STACK_ALLOC	(400 * 1024)
+
+static int
+handle_elf (int fd, Elf *elf, const char *prefix, const char *fname,
+	    mode_t mode, struct timespec tvp[2])
+{
+  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t fname_len = strlen (fname) + 1;
+  char *fullname = alloca (prefix_len + 1 + fname_len);
+  char *cp = fullname;
+  Elf *debugelf = NULL;
+  tmp_debug_fname = NULL;
+  int result = 0;
+  size_t shdridx = 0;
+  GElf_Off lastsec_offset = 0;
+  Elf64_Xword lastsec_size = 0;
+  size_t shstrndx;
+  struct shdr_info
+  {
+    Elf_Scn *scn;
+    GElf_Shdr shdr;
+    Elf_Data *data;
+    Elf_Data *debug_data;
+    const char *name;
+    Elf32_Word idx;		/* Index in new file.  */
+    Elf32_Word old_sh_link;	/* Original value of shdr.sh_link.  */
+    Elf32_Word symtab_idx;
+    Elf32_Word version_idx;
+    Elf32_Word group_idx;
+    Elf32_Word group_cnt;
+    Elf_Scn *newscn;
+    Dwelf_Strent *se;
+    Elf32_Word *newsymidx;
+  } *shdr_info = NULL;
+  Elf_Scn *scn;
+  size_t cnt;
+  size_t idx;
+  bool changes;
+  GElf_Ehdr newehdr_mem;
+  GElf_Ehdr *newehdr;
+  GElf_Ehdr debugehdr_mem;
+  GElf_Ehdr *debugehdr;
+  Dwelf_Strtab *shst = NULL;
+  Elf_Data debuglink_crc_data;
+  bool any_symtab_changes = false;
+  Elf_Data *shstrtab_data = NULL;
+  void *debuglink_buf = NULL;
+
+  /* Create the full name of the file.  */
+  if (prefix != NULL)
+    {
+      cp = mempcpy (cp, prefix, prefix_len);
+      *cp++ = ':';
+    }
+  memcpy (cp, fname, fname_len);
+
+  /* If we are not replacing the input file open a new file here.  */
+  if (output_fname != NULL)
+    {
+      fd = open (output_fname, O_RDWR | O_CREAT, mode);
+      if (unlikely (fd == -1))
+	{
+	  error (0, errno, _("cannot open '%s'"), output_fname);
+	  return 1;
+	}
+    }
+
+  debug_fd = -1;
+
+  /* Get the EBL handling.  Removing all debugging symbols with the -g
+     option or resolving all relocations between debug sections with
+     the --reloc-debug-sections option are currently the only reasons
+     we need EBL so don't open the backend unless necessary.  */
+  Ebl *ebl = NULL;
+  if (remove_debug || reloc_debug || reloc_debug_only)
+    {
+      ebl = ebl_openbackend (elf);
+      if (ebl == NULL)
+	{
+	  error (0, errno, _("cannot open EBL backend"));
+	  result = 1;
+	  goto fail;
+	}
+    }
+
+  /* Open the additional file the debug information will be stored in.  */
+  if (debug_fname != NULL)
+    {
+      /* Create a temporary file name.  We do not want to overwrite
+	 the debug file if the file would not contain any
+	 information.  */
+      size_t debug_fname_len = strlen (debug_fname);
+      tmp_debug_fname = xmalloc (debug_fname_len + sizeof (".XXXXXX"));
+      strcpy (mempcpy (tmp_debug_fname, debug_fname, debug_fname_len),
+	      ".XXXXXX");
+
+      debug_fd = mkstemp (tmp_debug_fname);
+      if (unlikely (debug_fd == -1))
+	{
+	  error (0, errno, _("cannot open '%s'"), debug_fname);
+	  result = 1;
+	  goto fail;
+	}
+    }
+
+  /* Get the information from the old file.  */
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    INTERNAL_ERROR (fname);
+
+  /* Get the section header string table index.  */
+  if (unlikely (elf_getshdrstrndx (elf, &shstrndx) < 0))
+    {
+      cleanup_debug ();
+      error_exit (0, _("cannot get section header string table index"));
+    }
+
+  /* Get the number of phdrs in the old file.  */
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    {
+      cleanup_debug ();
+      error_exit (0, _("cannot get number of phdrs"));
+    }
+
+  /* We now create a new ELF descriptor for the same file.  We
+     construct it almost exactly in the same way with some information
+     dropped.  */
+  Elf *newelf;
+  if (output_fname != NULL)
+    newelf = elf_begin (fd, ELF_C_WRITE_MMAP, NULL);
+  else
+    newelf = elf_clone (elf, ELF_C_EMPTY);
+
+  if (unlikely (gelf_newehdr (newelf, gelf_getclass (elf)) == 0))
+    {
+      error (0, 0, _("cannot create new ehdr for file '%s': %s"),
+	     output_fname ?: fname, elf_errmsg (-1));
+      goto fail;
+    }
+
+  /* Copy over the old program header if needed.  */
+  if (phnum > 0)
+    {
+      if (unlikely (gelf_newphdr (newelf, phnum) == 0))
+	{
+	  error (0, 0, _("cannot create new phdr for file '%s': %s"),
+		 output_fname ?: fname, elf_errmsg (-1));
+	  goto fail;
+	}
+
+      for (cnt = 0; cnt < phnum; ++cnt)
+	{
+	  GElf_Phdr phdr_mem;
+	  GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+	  if (phdr == NULL
+	      || unlikely (gelf_update_phdr (newelf, cnt, phdr) == 0))
+	    INTERNAL_ERROR (fname);
+	}
+    }
+
+  if (reloc_debug_only)
+    {
+      if (handle_debug_relocs (elf, ebl, newelf, ehdr, fname, shstrndx,
+			       &lastsec_offset, &lastsec_size) != 0)
+	{
+	  result = 1;
+	  goto fail_close;
+	}
+      idx = shstrndx;
+      goto done; /* Skip all actual stripping operations.  */
+    }
+
+  if (debug_fname != NULL)
+    {
+      /* Also create an ELF descriptor for the debug file */
+      debugelf = elf_begin (debug_fd, ELF_C_WRITE, NULL);
+      if (unlikely (gelf_newehdr (debugelf, gelf_getclass (elf)) == 0))
+	{
+	  error (0, 0, _("cannot create new ehdr for file '%s': %s"),
+		 debug_fname, elf_errmsg (-1));
+	  goto fail_close;
+	}
+
+      /* Copy over the old program header if needed.  */
+      if (phnum > 0)
+	{
+	  if (unlikely (gelf_newphdr (debugelf, phnum) == 0))
+	    {
+	      error (0, 0, _("cannot create new phdr for file '%s': %s"),
+		     debug_fname, elf_errmsg (-1));
+	      goto fail_close;
+	    }
+
+	  for (cnt = 0; cnt < phnum; ++cnt)
+	    {
+	      GElf_Phdr phdr_mem;
+	      GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+	      if (phdr == NULL
+		  || unlikely (gelf_update_phdr (debugelf, cnt, phdr) == 0))
+		INTERNAL_ERROR (fname);
+	    }
+	}
+    }
+
+  /* Number of sections.  */
+  size_t shnum;
+  if (unlikely (elf_getshdrnum (elf, &shnum) < 0))
+    {
+      error (0, 0, _("cannot determine number of sections: %s"),
+	     elf_errmsg (-1));
+      goto fail_close;
+    }
+
+  if (shstrndx >= shnum)
+    goto illformed;
+
+#define elf_assert(test) do { if (!(test)) goto illformed; } while (0)
+
+  /* Storage for section information.  We leave room for two more
+     entries since we unconditionally create a section header string
+     table.  Maybe some weird tool created an ELF file without one.
+     The other one is used for the debug link section.  */
+  if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
+    shdr_info = xcalloc (shnum + 2, sizeof (struct shdr_info));
+  else
+    {
+      shdr_info = (struct shdr_info *) alloca ((shnum + 2)
+					       * sizeof (struct shdr_info));
+      memset (shdr_info, '\0', (shnum + 2) * sizeof (struct shdr_info));
+    }
+
+  /* Track whether allocated sections all come before non-allocated ones.  */
+  bool seen_allocated = false;
+  bool seen_unallocated = false;
+  bool mixed_allocated_unallocated = false;
+
+  /* Prepare section information data structure.  */
+  scn = NULL;
+  cnt = 1;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      /* This should always be true (i.e., there should not be any
+	 holes in the numbering).  */
+      elf_assert (elf_ndxscn (scn) == cnt);
+
+      shdr_info[cnt].scn = scn;
+
+      /* Get the header.  */
+      if (gelf_getshdr (scn, &shdr_info[cnt].shdr) == NULL)
+	INTERNAL_ERROR (fname);
+
+      /* Normally (in non-ET_REL files) we see all allocated sections first,
+	 then all non-allocated.  */
+      if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
+	seen_unallocated = true;
+      else
+	{
+	  if (seen_unallocated && seen_allocated)
+	    mixed_allocated_unallocated = true;
+	  seen_allocated = true;
+	}
+
+      /* Get the name of the section.  */
+      shdr_info[cnt].name = elf_strptr (elf, shstrndx,
+					shdr_info[cnt].shdr.sh_name);
+      if (shdr_info[cnt].name == NULL)
+	{
+	illformed:
+	  error (0, 0, _("illformed file '%s'"), fname);
+	  goto fail_close;
+	}
+
+      /* Sanity check the user.  */
+      if (section_name_matches (remove_secs, shdr_info[cnt].name))
+	{
+	  if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0)
+	    {
+	      error (0, 0,
+		     _("Cannot remove allocated section '%s'"),
+		     shdr_info[cnt].name);
+	      result = 1;
+	      goto fail_close;
+	    }
+
+	  if (section_name_matches (keep_secs, shdr_info[cnt].name))
+	    {
+	      error (0, 0,
+		     _("Cannot both keep and remove section '%s'"),
+		     shdr_info[cnt].name);
+	      result = 1;
+	      goto fail_close;
+	    }
+	}
+
+      /* Mark them as present but not yet investigated.  */
+      shdr_info[cnt].idx = 1;
+
+      /* Remember the shdr.sh_link value.  */
+      shdr_info[cnt].old_sh_link = shdr_info[cnt].shdr.sh_link;
+      if (shdr_info[cnt].old_sh_link >= shnum)
+	goto illformed;
+
+      /* Sections in files other than relocatable object files which
+	 not loaded can be freely moved by us.  In theory we can also
+	 freely move around allocated nobits sections.  But we don't
+	 to keep the layout of all allocated sections as similar as
+	 possible to the original file.  In relocatable object files
+	 everything can be moved.  */
+      if (phnum == 0
+	  || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
+	shdr_info[cnt].shdr.sh_offset = 0;
+
+      /* If this is an extended section index table store an
+	 appropriate reference.  */
+      if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX))
+	{
+	  elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0);
+	  shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx = cnt;
+	}
+      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GROUP))
+	{
+	  /* Cross-reference the sections contained in the section
+	     group.  */
+	  shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
+	  if (shdr_info[cnt].data == NULL
+	      || shdr_info[cnt].data->d_size < sizeof (Elf32_Word))
+	    INTERNAL_ERROR (fname);
+
+	  /* XXX Fix for unaligned access.  */
+	  Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
+	  size_t inner;
+	  for (inner = 1;
+	       inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
+	       ++inner)
+	    {
+	      if (grpref[inner] < shnum)
+		shdr_info[grpref[inner]].group_idx = cnt;
+	      else
+		goto illformed;
+	    }
+
+	  if (inner == 1 || (inner == 2 && (grpref[0] & GRP_COMDAT) == 0))
+	    /* If the section group contains only one element and this
+	       is n COMDAT section we can drop it right away.  */
+	    shdr_info[cnt].idx = 0;
+	  else
+	    shdr_info[cnt].group_cnt = inner - 1;
+	}
+      else if (unlikely (shdr_info[cnt].shdr.sh_type == SHT_GNU_versym))
+	{
+	  elf_assert (shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0);
+	  shdr_info[shdr_info[cnt].shdr.sh_link].version_idx = cnt;
+	}
+
+      /* If this section is part of a group make sure it is not
+	 discarded right away.  */
+      if ((shdr_info[cnt].shdr.sh_flags & SHF_GROUP) != 0)
+	{
+	  elf_assert (shdr_info[cnt].group_idx != 0);
+
+	  if (shdr_info[shdr_info[cnt].group_idx].idx == 0)
+	    {
+	      /* The section group section might be removed.
+		 Don't remove the SHF_GROUP flag.  The section is
+		 either also removed, in which case the flag doesn't matter.
+		 Or it moves with the group into the debug file, then
+		 it will be reconnected with the new group and should
+		 still have the flag set.  */
+	      shdr_info[cnt].group_idx = 0;
+	    }
+	}
+
+      /* Increment the counter.  */
+      ++cnt;
+    }
+
+  /* Now determine which sections can go away.  The general rule is that
+     all sections which are not used at runtime are stripped out.  But
+     there are a few exceptions:
+
+     - special sections named ".comment" and ".note" are kept
+     - OS or architecture specific sections are kept since we might not
+       know how to handle them
+     - if a section is referred to from a section which is not removed
+       in the sh_link or sh_info element it cannot be removed either
+     - the user might have explicitly said to remove or keep a section
+  */
+  for (cnt = 1; cnt < shnum; ++cnt)
+    /* Check whether the section can be removed.  Since we will create
+       a new .shstrtab assume it will be removed too.  */
+    if (remove_shdrs ? !(shdr_info[cnt].shdr.sh_flags & SHF_ALLOC)
+	: (ebl_section_strip_p (ebl, &shdr_info[cnt].shdr,
+				shdr_info[cnt].name, remove_comment,
+				remove_debug)
+	   || cnt == shstrndx
+	   || section_name_matches (remove_secs, shdr_info[cnt].name)))
+      {
+	/* The user might want to explicitly keep this one.  */
+	if (section_name_matches (keep_secs, shdr_info[cnt].name))
+	  continue;
+
+	/* For now assume this section will be removed.  */
+	shdr_info[cnt].idx = 0;
+
+	idx = shdr_info[cnt].group_idx;
+	while (idx != 0)
+	  {
+	    /* The section group data is already loaded.  */
+	    elf_assert (shdr_info[idx].data != NULL
+			&& shdr_info[idx].data->d_buf != NULL
+			&& shdr_info[idx].data->d_size >= sizeof (Elf32_Word));
+
+	    /* If the references section group is a normal section
+	       group and has one element remaining, or if it is an
+	       empty COMDAT section group it is removed.  */
+	    bool is_comdat = (((Elf32_Word *) shdr_info[idx].data->d_buf)[0]
+			      & GRP_COMDAT) != 0;
+
+	    --shdr_info[idx].group_cnt;
+	    if ((!is_comdat && shdr_info[idx].group_cnt == 1)
+		|| (is_comdat && shdr_info[idx].group_cnt == 0))
+	      {
+		shdr_info[idx].idx = 0;
+		/* Continue recursively.  */
+		idx = shdr_info[idx].group_idx;
+	      }
+	    else
+	      break;
+	  }
+      }
+
+  /* Mark the SHT_NULL section as handled.  */
+  shdr_info[0].idx = 2;
+
+
+  /* Handle exceptions: section groups and cross-references.  We might
+     have to repeat this a few times since the resetting of the flag
+     might propagate.  */
+  do
+    {
+      changes = false;
+
+      for (cnt = 1; cnt < shnum; ++cnt)
+	{
+	  if (shdr_info[cnt].idx == 0)
+	    {
+	      /* If a relocation section is marked as being removed make
+		 sure the section it is relocating is removed, too.  */
+	      if (shdr_info[cnt].shdr.sh_type == SHT_REL
+		   || shdr_info[cnt].shdr.sh_type == SHT_RELA)
+		{
+		  if (shdr_info[cnt].shdr.sh_info >= shnum)
+		    goto illformed;
+		  else if (shdr_info[shdr_info[cnt].shdr.sh_info].idx != 0)
+		    shdr_info[cnt].idx = 1;
+		}
+
+	      /* If a group section is marked as being removed make
+		 sure all the sections it contains are being removed, too.  */
+	      if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
+		{
+		  Elf32_Word *grpref;
+		  grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
+		  for (size_t in = 1;
+		       in < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
+		       ++in)
+		    if (grpref[in] < shnum)
+		      {
+			if (shdr_info[grpref[in]].idx != 0)
+			  {
+			    shdr_info[cnt].idx = 1;
+			    break;
+			  }
+		      }
+		    else
+		      goto illformed;
+		}
+	    }
+
+	  if (shdr_info[cnt].idx == 1)
+	    {
+	      /* The content of symbol tables we don't remove must not
+		 reference any section which we do remove.  Otherwise
+		 we cannot remove the section.  */
+	      if (debug_fname != NULL
+		  && shdr_info[cnt].debug_data == NULL
+		  && (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
+		      || shdr_info[cnt].shdr.sh_type == SHT_SYMTAB))
+		{
+		  /* Make sure the data is loaded.  */
+		  if (shdr_info[cnt].data == NULL)
+		    {
+		      shdr_info[cnt].data
+			= elf_getdata (shdr_info[cnt].scn, NULL);
+		      if (shdr_info[cnt].data == NULL)
+			INTERNAL_ERROR (fname);
+		    }
+		  Elf_Data *symdata = shdr_info[cnt].data;
+
+		  /* If there is an extended section index table load it
+		     as well.  */
+		  if (shdr_info[cnt].symtab_idx != 0
+		      && shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
+		    {
+		      elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB);
+
+		      shdr_info[shdr_info[cnt].symtab_idx].data
+			= elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
+				       NULL);
+		      if (shdr_info[shdr_info[cnt].symtab_idx].data == NULL)
+			INTERNAL_ERROR (fname);
+		    }
+		  Elf_Data *xndxdata
+		    = shdr_info[shdr_info[cnt].symtab_idx].data;
+
+		  /* Go through all symbols and make sure the section they
+		     reference is not removed.  */
+		  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+
+		  for (size_t inner = 0;
+		       inner < shdr_info[cnt].data->d_size / elsize;
+		       ++inner)
+		    {
+		      GElf_Sym sym_mem;
+		      Elf32_Word xndx;
+		      GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+							inner, &sym_mem,
+							&xndx);
+		      if (sym == NULL)
+			INTERNAL_ERROR (fname);
+
+		      size_t scnidx = sym->st_shndx;
+		      if (scnidx == SHN_UNDEF || scnidx >= shnum
+			  || (scnidx >= SHN_LORESERVE
+			      && scnidx <= SHN_HIRESERVE
+			      && scnidx != SHN_XINDEX)
+			  /* Don't count in the section symbols.  */
+			  || GELF_ST_TYPE (sym->st_info) == STT_SECTION)
+			/* This is no section index, leave it alone.  */
+			continue;
+		      else if (scnidx == SHN_XINDEX)
+			scnidx = xndx;
+
+		      if (scnidx >= shnum)
+			goto illformed;
+
+		      if (shdr_info[scnidx].idx == 0)
+			/* This symbol table has a real symbol in
+			   a discarded section.  So preserve the
+			   original table in the debug file.  Unless
+			   it is a redundant data marker to a debug
+			   (data only) section.  */
+			if (! (ebl_section_strip_p (ebl,
+						    &shdr_info[scnidx].shdr,
+						    shdr_info[scnidx].name,
+						    remove_comment,
+						    remove_debug)
+			       && ebl_data_marker_symbol (ebl, sym,
+					elf_strptr (elf,
+						    shdr_info[cnt].shdr.sh_link,
+						    sym->st_name))))
+			  shdr_info[cnt].debug_data = symdata;
+		    }
+		}
+
+	      /* Cross referencing happens:
+		 - for the cases the ELF specification says.  That are
+		   + SHT_DYNAMIC in sh_link to string table
+		   + SHT_HASH in sh_link to symbol table
+		   + SHT_REL and SHT_RELA in sh_link to symbol table
+		   + SHT_SYMTAB and SHT_DYNSYM in sh_link to string table
+		   + SHT_GROUP in sh_link to symbol table
+		   + SHT_SYMTAB_SHNDX in sh_link to symbol table
+		   Other (OS or architecture-specific) sections might as
+		   well use this field so we process it unconditionally.
+		 - references inside section groups
+		 - specially marked references in sh_info if the SHF_INFO_LINK
+		 flag is set
+	      */
+
+	      if (shdr_info[shdr_info[cnt].shdr.sh_link].idx == 0)
+		{
+		  shdr_info[shdr_info[cnt].shdr.sh_link].idx = 1;
+		  changes |= shdr_info[cnt].shdr.sh_link < cnt;
+		}
+
+	      /* Handle references through sh_info.  */
+	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
+		{
+		  if (shdr_info[cnt].shdr.sh_info >= shnum)
+		    goto illformed;
+		  else if ( shdr_info[shdr_info[cnt].shdr.sh_info].idx == 0)
+		    {
+		      shdr_info[shdr_info[cnt].shdr.sh_info].idx = 1;
+		      changes |= shdr_info[cnt].shdr.sh_info < cnt;
+		    }
+		}
+
+	      /* Mark the section as investigated.  */
+	      shdr_info[cnt].idx = 2;
+	    }
+
+	  if (debug_fname != NULL
+	      && (shdr_info[cnt].idx == 0 || shdr_info[cnt].debug_data != NULL))
+	    {
+	      /* This section is being preserved in the debug file.
+		 Sections it refers to must be preserved there too.
+
+		 In this pass we mark sections to be preserved in both
+		 files by setting the .debug_data pointer to the original
+		 file's .data pointer.  Below, we'll copy the section
+		 contents.  */
+	      size_t shdr_indices[2] = { shdr_info[cnt].shdr.sh_link, 0 };
+	      int n = 1;
+
+	      if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
+		{
+		  shdr_indices[1] = shdr_info[cnt].shdr.sh_info;
+		  n++;
+		}
+
+	      for (int j = 0; j < n; j++)
+		{
+		  size_t i = shdr_indices[j];
+		  if (i != 0 && i < shnum + 2 && shdr_info[i].idx != 0
+		      && shdr_info[i].debug_data == NULL)
+		    {
+		      if (shdr_info[i].data == NULL)
+			shdr_info[i].data = elf_getdata (shdr_info[i].scn, NULL);
+		      if (shdr_info[i].data == NULL)
+			INTERNAL_ERROR (fname);
+
+		      shdr_info[i].debug_data = shdr_info[i].data;
+		      changes |= i < cnt;
+		    }
+		}
+	    }
+	}
+    }
+  while (changes);
+
+  /* Copy the removed sections to the debug output file.
+     The ones that are not removed in the stripped file are SHT_NOBITS.  */
+  if (debug_fname != NULL)
+    {
+      for (cnt = 1; cnt < shnum; ++cnt)
+	{
+	  scn = elf_newscn (debugelf);
+	  if (scn == NULL)
+	    {
+	      cleanup_debug ();
+	      error_exit (0, _("while generating output file: %s"),
+			  elf_errmsg (-1));
+	    }
+
+	  bool discard_section = (shdr_info[cnt].idx > 0
+				  && shdr_info[cnt].debug_data == NULL
+				  && shdr_info[cnt].shdr.sh_type != SHT_NOTE
+				  && shdr_info[cnt].shdr.sh_type != SHT_GROUP
+				  && cnt != shstrndx);
+
+	  /* Set the section header in the new file.  */
+	  GElf_Shdr debugshdr = shdr_info[cnt].shdr;
+	  if (discard_section)
+	    debugshdr.sh_type = SHT_NOBITS;
+
+	  if (unlikely (gelf_update_shdr (scn, &debugshdr) == 0))
+	    /* There cannot be any overflows.  */
+	    INTERNAL_ERROR (fname);
+
+	  /* Get the data from the old file if necessary. */
+	  if (shdr_info[cnt].data == NULL)
+	    {
+	      shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
+	      if (shdr_info[cnt].data == NULL)
+		INTERNAL_ERROR (fname);
+	    }
+
+	  /* Set the data.  This is done by copying from the old file.  */
+	  Elf_Data *debugdata = elf_newdata (scn);
+	  if (debugdata == NULL)
+	    INTERNAL_ERROR (fname);
+
+	  /* Copy the structure.  This data may be modified in place
+	     before we write out the file.  */
+	  *debugdata = *shdr_info[cnt].data;
+	  if (discard_section)
+	    debugdata->d_buf = NULL;
+	  else if (shdr_info[cnt].debug_data != NULL
+		   || shdr_info[cnt].shdr.sh_type == SHT_GROUP)
+	    {
+	      /* Copy the original data before it gets modified.  */
+	      shdr_info[cnt].debug_data = debugdata;
+	      if (debugdata->d_buf == NULL)
+		INTERNAL_ERROR (fname);
+	      debugdata->d_buf = memcpy (xmalloc (debugdata->d_size),
+					 debugdata->d_buf, debugdata->d_size);
+	    }
+	}
+
+      /* Finish the ELF header.  Fill in the fields not handled by
+	 libelf from the old file.  */
+      debugehdr = gelf_getehdr (debugelf, &debugehdr_mem);
+      if (debugehdr == NULL)
+	INTERNAL_ERROR (fname);
+
+      memcpy (debugehdr->e_ident, ehdr->e_ident, EI_NIDENT);
+      debugehdr->e_type = ehdr->e_type;
+      debugehdr->e_machine = ehdr->e_machine;
+      debugehdr->e_version = ehdr->e_version;
+      debugehdr->e_entry = ehdr->e_entry;
+      debugehdr->e_flags = ehdr->e_flags;
+
+      if (unlikely (gelf_update_ehdr (debugelf, debugehdr) == 0))
+	{
+	  error (0, 0, _("%s: error while updating ELF header: %s"),
+		 debug_fname, elf_errmsg (-1));
+	  result = 1;
+	  goto fail_close;
+	}
+
+      size_t shdrstrndx;
+      if (elf_getshdrstrndx (elf, &shdrstrndx) < 0)
+	{
+	  error (0, 0, _("%s: error while getting shdrstrndx: %s"),
+		 fname, elf_errmsg (-1));
+	  result = 1;
+	  goto fail_close;
+	}
+
+      if (update_shdrstrndx (debugelf, shdrstrndx) != 0)
+	{
+	  error (0, 0, _("%s: error updating shdrstrndx: %s"),
+		 debug_fname, elf_errmsg (-1));
+	  result = 1;
+	  goto fail_close;
+	}
+    }
+
+  /* Although we always create a new section header string table we
+     don't explicitly mark the existing one as unused.  It can still
+     be used through a symbol table section we are keeping.  If not it
+     will already be marked as unused.  */
+
+  /* We need a string table for the section headers.  */
+  shst = dwelf_strtab_init (true);
+  if (shst == NULL)
+    {
+      cleanup_debug ();
+      error_exit (errno, _("while preparing output for '%s'"),
+		  output_fname ?: fname);
+    }
+
+  /* Assign new section numbers.  */
+  shdr_info[0].idx = 0;
+  for (cnt = idx = 1; cnt < shnum; ++cnt)
+    if (shdr_info[cnt].idx > 0)
+      {
+	shdr_info[cnt].idx = idx++;
+
+	/* Create a new section.  */
+	shdr_info[cnt].newscn = elf_newscn (newelf);
+	if (shdr_info[cnt].newscn == NULL)
+	  {
+	    cleanup_debug ();
+	    error_exit (0,
+			_("while generating output file: %s"),
+		   elf_errmsg (-1));
+	  }
+
+	elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
+
+	/* Add this name to the section header string table.  */
+	shdr_info[cnt].se = dwelf_strtab_add (shst, shdr_info[cnt].name);
+      }
+
+  /* Test whether we are doing anything at all.  Either all removable
+     sections are already gone.  Or the only section we would remove is
+     the .shstrtab section which we would add again.  */
+  bool removing_sections = !(cnt == idx
+			     || (cnt == idx + 1
+				 && shdr_info[shstrndx].idx == 0));
+  if (output_fname == NULL && !removing_sections)
+      goto fail_close;
+
+  /* Create the reference to the file with the debug info (if any).  */
+  if (debug_fname != NULL && !remove_shdrs && removing_sections)
+    {
+      /* Add the section header string table section name.  */
+      shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".gnu_debuglink", 15);
+      shdr_info[cnt].idx = idx++;
+
+      /* Create the section header.  */
+      shdr_info[cnt].shdr.sh_type = SHT_PROGBITS;
+      shdr_info[cnt].shdr.sh_flags = 0;
+      shdr_info[cnt].shdr.sh_addr = 0;
+      shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
+      shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
+      shdr_info[cnt].shdr.sh_entsize = 0;
+      shdr_info[cnt].shdr.sh_addralign = 4;
+      /* We set the offset to zero here.  Before we write the ELF file the
+	 field must have the correct value.  This is done in the final
+	 loop over all section.  Then we have all the information needed.  */
+      shdr_info[cnt].shdr.sh_offset = 0;
+
+      /* Create the section.  */
+      shdr_info[cnt].newscn = elf_newscn (newelf);
+      if (shdr_info[cnt].newscn == NULL)
+	{
+	  cleanup_debug ();
+	  error_exit (0, _("while create section header section: %s"),
+		      elf_errmsg (-1));
+	}
+      elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx);
+
+      shdr_info[cnt].data = elf_newdata (shdr_info[cnt].newscn);
+      if (shdr_info[cnt].data == NULL)
+	{
+	  cleanup_debug ();
+	  error_exit (0, _("cannot allocate section data: %s"),
+		      elf_errmsg (-1));
+	}
+
+      const char *debug_basename = xbasename (debug_fname_embed ?: debug_fname);
+      off_t crc_offset = strlen (debug_basename) + 1;
+      /* Align to 4 byte boundary */
+      crc_offset = ((crc_offset - 1) & ~3) + 4;
+
+      shdr_info[cnt].data->d_align = 4;
+      shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size
+	= crc_offset + 4;
+      debuglink_buf = xcalloc (1, shdr_info[cnt].data->d_size);
+      shdr_info[cnt].data->d_buf = debuglink_buf;
+
+      strcpy (shdr_info[cnt].data->d_buf, debug_basename);
+
+      /* Cache this Elf_Data describing the CRC32 word in the section.
+	 We'll fill this in when we have written the debug file.  */
+      debuglink_crc_data = *shdr_info[cnt].data;
+      debuglink_crc_data.d_buf = ((char *) debuglink_crc_data.d_buf
+				  + crc_offset);
+      debuglink_crc_data.d_size = 4;
+
+      /* One more section done.  */
+      ++cnt;
+    }
+
+  /* Index of the section header table in the shdr_info array.  */
+  shdridx = cnt;
+
+  /* Add the section header string table section name.  */
+  shdr_info[cnt].se = dwelf_strtab_add_len (shst, ".shstrtab", 10);
+  shdr_info[cnt].idx = idx;
+
+  /* Create the section header.  */
+  shdr_info[cnt].shdr.sh_type = SHT_STRTAB;
+  shdr_info[cnt].shdr.sh_flags = 0;
+  shdr_info[cnt].shdr.sh_addr = 0;
+  shdr_info[cnt].shdr.sh_link = SHN_UNDEF;
+  shdr_info[cnt].shdr.sh_info = SHN_UNDEF;
+  shdr_info[cnt].shdr.sh_entsize = 0;
+  /* We set the offset to zero here.  Before we write the ELF file the
+     field must have the correct value.  This is done in the final
+     loop over all section.  Then we have all the information needed.  */
+  shdr_info[cnt].shdr.sh_offset = 0;
+  shdr_info[cnt].shdr.sh_addralign = 1;
+
+  /* Create the section.  */
+  shdr_info[cnt].newscn = elf_newscn (newelf);
+  if (shdr_info[cnt].newscn == NULL)
+    {
+      cleanup_debug ();
+      error_exit (0, _("while create section header section: %s"),
+		  elf_errmsg (-1));
+    }
+  elf_assert (elf_ndxscn (shdr_info[cnt].newscn) == idx);
+
+  /* Finalize the string table and fill in the correct indices in the
+     section headers.  */
+  shstrtab_data = elf_newdata (shdr_info[cnt].newscn);
+  if (shstrtab_data == NULL)
+    {
+      cleanup_debug ();
+      error_exit (0, _("while create section header string table: %s"),
+		  elf_errmsg (-1));
+    }
+  if (dwelf_strtab_finalize (shst, shstrtab_data) == NULL)
+    {
+      cleanup_debug ();
+      error_exit (0, _("no memory to create section header string table"));
+    }
+
+  /* We have to set the section size.  */
+  shdr_info[cnt].shdr.sh_size = shstrtab_data->d_size;
+
+  /* Update the section information.  */
+  GElf_Off lastoffset = 0;
+  for (cnt = 1; cnt <= shdridx; ++cnt)
+    if (shdr_info[cnt].idx > 0)
+      {
+	Elf_Data *newdata;
+
+	scn = elf_getscn (newelf, shdr_info[cnt].idx);
+	elf_assert (scn != NULL);
+
+	/* Update the name.  */
+	shdr_info[cnt].shdr.sh_name = dwelf_strent_off (shdr_info[cnt].se);
+
+	/* Update the section header from the input file.  Some fields
+	   might be section indices which now have to be adjusted.  Keep
+	   the index to the "current" sh_link in case we need it to lookup
+	   symbol table names.  */
+	size_t sh_link = shdr_info[cnt].shdr.sh_link;
+	if (shdr_info[cnt].shdr.sh_link != 0)
+	  shdr_info[cnt].shdr.sh_link =
+	    shdr_info[shdr_info[cnt].shdr.sh_link].idx;
+
+	if (shdr_info[cnt].shdr.sh_type == SHT_GROUP)
+	  {
+	    elf_assert (shdr_info[cnt].data != NULL
+			&& shdr_info[cnt].data->d_buf != NULL);
+
+	    Elf32_Word *grpref = (Elf32_Word *) shdr_info[cnt].data->d_buf;
+	    /* First word is the section group flag.
+	       Followed by section indexes, that need to be renumbered.  */
+	    for (size_t inner = 1;
+		 inner < shdr_info[cnt].data->d_size / sizeof (Elf32_Word);
+		 ++inner)
+	      if (grpref[inner] < shnum)
+		grpref[inner] = shdr_info[grpref[inner]].idx;
+	      else
+		goto illformed;
+	  }
+
+	/* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag.  */
+	if (SH_INFO_LINK_P (&shdr_info[cnt].shdr))
+	  shdr_info[cnt].shdr.sh_info =
+	    shdr_info[shdr_info[cnt].shdr.sh_info].idx;
+
+	/* Get the data from the old file if necessary.  We already
+	   created the data for the section header string table.  */
+	if (cnt < shnum)
+	  {
+	    if (shdr_info[cnt].data == NULL)
+	      {
+		shdr_info[cnt].data = elf_getdata (shdr_info[cnt].scn, NULL);
+		if (shdr_info[cnt].data == NULL)
+		  INTERNAL_ERROR (fname);
+	      }
+
+	    /* Set the data.  This is done by copying from the old file.  */
+	    newdata = elf_newdata (scn);
+	    if (newdata == NULL)
+	      INTERNAL_ERROR (fname);
+
+	    /* Copy the structure.  */
+	    *newdata = *shdr_info[cnt].data;
+
+	    /* We know the size.  */
+	    shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
+
+	    /* We have to adjust symbol tables.  The st_shndx member might
+	       have to be updated.  */
+	    if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM
+		|| shdr_info[cnt].shdr.sh_type == SHT_SYMTAB)
+	      {
+		Elf_Data *versiondata = NULL;
+		Elf_Data *shndxdata = NULL;
+
+		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+
+		if (shdr_info[cnt].symtab_idx != 0)
+		  {
+		    elf_assert (shdr_info[cnt].shdr.sh_type == SHT_SYMTAB_SHNDX);
+		    /* This section has extended section information.
+		       We have to modify that information, too.  */
+		    shndxdata = elf_getdata (shdr_info[shdr_info[cnt].symtab_idx].scn,
+					     NULL);
+
+		    elf_assert (shndxdata != NULL
+				&& shndxdata->d_buf != NULL
+				&& ((shndxdata->d_size / sizeof (Elf32_Word))
+				    >= shdr_info[cnt].data->d_size / elsize));
+		  }
+
+		if (shdr_info[cnt].version_idx != 0)
+		  {
+		    elf_assert (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM);
+		    /* This section has associated version
+		       information.  We have to modify that
+		       information, too.  */
+		    versiondata = elf_getdata (shdr_info[shdr_info[cnt].version_idx].scn,
+					       NULL);
+
+		    elf_assert (versiondata != NULL
+				&& versiondata->d_buf != NULL
+				&& ((versiondata->d_size / sizeof (GElf_Versym))
+				    >= shdr_info[cnt].data->d_size / elsize));
+		  }
+
+		shdr_info[cnt].newsymidx
+		  = xcalloc (shdr_info[cnt].data->d_size / elsize,
+			     sizeof (Elf32_Word));
+
+		bool last_was_local = true;
+		size_t destidx;
+		size_t inner;
+		for (destidx = inner = 1;
+		     inner < shdr_info[cnt].data->d_size / elsize;
+		     ++inner)
+		  {
+		    Elf32_Word sec;
+		    GElf_Sym sym_mem;
+		    Elf32_Word xshndx;
+		    GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
+						      shndxdata, inner,
+						      &sym_mem, &xshndx);
+		    if (sym == NULL)
+		      INTERNAL_ERROR (fname);
+
+		    if (sym->st_shndx == SHN_UNDEF
+			|| (sym->st_shndx >= SHN_LORESERVE
+			    && sym->st_shndx != SHN_XINDEX))
+		      {
+			/* This is no section index, leave it alone
+			   unless it is moved.  */
+			if (destidx != inner
+			    && gelf_update_symshndx (shdr_info[cnt].data,
+						     shndxdata,
+						     destidx, sym,
+						     xshndx) == 0)
+			  INTERNAL_ERROR (fname);
+
+			shdr_info[cnt].newsymidx[inner] = destidx++;
+
+			if (last_was_local
+			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
+			  {
+			    last_was_local = false;
+			    shdr_info[cnt].shdr.sh_info = destidx - 1;
+			  }
+
+			continue;
+		      }
+
+		    /* Get the full section index, if necessary from the
+		       XINDEX table.  */
+		    if (sym->st_shndx == SHN_XINDEX)
+		      elf_assert (shndxdata != NULL
+				  && shndxdata->d_buf != NULL);
+		    size_t sidx = (sym->st_shndx != SHN_XINDEX
+				   ? sym->st_shndx : xshndx);
+		    elf_assert (sidx < shnum);
+		    sec = shdr_info[sidx].idx;
+
+		    if (sec != 0)
+		      {
+			GElf_Section nshndx;
+			Elf32_Word nxshndx;
+
+			if (sec < SHN_LORESERVE)
+			  {
+			    nshndx = sec;
+			    nxshndx = 0;
+			  }
+			else
+			  {
+			    nshndx = SHN_XINDEX;
+			    nxshndx = sec;
+			  }
+
+			elf_assert (sec < SHN_LORESERVE || shndxdata != NULL);
+
+			if ((inner != destidx || nshndx != sym->st_shndx
+			     || (shndxdata != NULL && nxshndx != xshndx))
+			    && (sym->st_shndx = nshndx,
+				gelf_update_symshndx (shdr_info[cnt].data,
+						      shndxdata,
+						      destidx, sym,
+						      nxshndx) == 0))
+			  INTERNAL_ERROR (fname);
+
+			shdr_info[cnt].newsymidx[inner] = destidx++;
+
+			if (last_was_local
+			    && GELF_ST_BIND (sym->st_info) != STB_LOCAL)
+			  {
+			    last_was_local = false;
+			    shdr_info[cnt].shdr.sh_info = destidx - 1;
+			  }
+		      }
+		    else if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0
+			     && GELF_ST_TYPE (sym->st_info) != STT_SECTION
+			     && shdr_info[sidx].shdr.sh_type != SHT_GROUP)
+		      {
+			/* Removing a real symbol from an allocated
+			   symbol table is hard and probably a
+			   mistake.  Really removing it means
+			   rewriting the dynamic segment and hash
+			   sections.  Just warn and set the symbol
+			   section to UNDEF.  */
+			error (0, 0,
+			       _("Cannot remove symbol [%zd] from allocated symbol table [%zd]"), inner, cnt);
+			sym->st_shndx = SHN_UNDEF;
+			if (gelf_update_sym (shdr_info[cnt].data, destidx,
+					     sym) == 0)
+			  INTERNAL_ERROR (fname);
+			shdr_info[cnt].newsymidx[inner] = destidx++;
+		      }
+		    else if (debug_fname != NULL
+			     && shdr_info[cnt].debug_data == NULL)
+		      /* The symbol points to a section that is discarded
+			 but isn't preserved in the debug file. Check that
+			 this is a section or group signature symbol
+			 for a section which has been removed.  Or a special
+			 data marker symbol to a debug section.  */
+		      {
+			elf_assert (GELF_ST_TYPE (sym->st_info) == STT_SECTION
+				    || ((shdr_info[sidx].shdr.sh_type
+					 == SHT_GROUP)
+					&& (shdr_info[sidx].shdr.sh_info
+					    == inner))
+				    || ebl_data_marker_symbol (ebl, sym,
+						elf_strptr (elf, sh_link,
+							    sym->st_name)));
+		      }
+		  }
+
+		if (destidx != inner)
+		  {
+		    /* The size of the symbol table changed.  */
+		    shdr_info[cnt].shdr.sh_size = newdata->d_size
+		      = destidx * elsize;
+		    any_symtab_changes = true;
+		  }
+		else
+		  {
+		    /* The symbol table didn't really change.  */
+		    free (shdr_info[cnt].newsymidx);
+		    shdr_info[cnt].newsymidx = NULL;
+		  }
+	      }
+	  }
+
+	/* If we have to, compute the offset of the section.
+	   If allocate and unallocated sections are mixed, we only update
+	   the allocated ones now.  The unallocated ones come second.  */
+	if (! mixed_allocated_unallocated
+	    || (shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) != 0)
+	  {
+	    if (shdr_info[cnt].shdr.sh_offset == 0)
+	      shdr_info[cnt].shdr.sh_offset
+		= ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
+		   & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
+
+	    /* Set the section header in the new file.  */
+	    if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
+	      /* There cannot be any overflows.  */
+	      INTERNAL_ERROR (fname);
+
+	    /* Remember the last section written so far.  */
+	    GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
+			       ? shdr_info[cnt].shdr.sh_size : 0);
+	    if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
+	      lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
+	  }
+      }
+
+  /* We might have to update the unallocated sections after we done the
+     allocated ones.  lastoffset is set to right after the last allocated
+     section.  */
+  if (mixed_allocated_unallocated)
+    for (cnt = 1; cnt <= shdridx; ++cnt)
+      if (shdr_info[cnt].idx > 0)
+	{
+	  scn = elf_getscn (newelf, shdr_info[cnt].idx);
+	  if ((shdr_info[cnt].shdr.sh_flags & SHF_ALLOC) == 0)
+	    {
+	      if (shdr_info[cnt].shdr.sh_offset == 0)
+		shdr_info[cnt].shdr.sh_offset
+		  = ((lastoffset + shdr_info[cnt].shdr.sh_addralign - 1)
+		     & ~((GElf_Off) (shdr_info[cnt].shdr.sh_addralign - 1)));
+
+	      /* Set the section header in the new file.  */
+	      if (unlikely (gelf_update_shdr (scn, &shdr_info[cnt].shdr) == 0))
+		/* There cannot be any overflows.  */
+		INTERNAL_ERROR (fname);
+
+	      /* Remember the last section written so far.  */
+	      GElf_Off filesz = (shdr_info[cnt].shdr.sh_type != SHT_NOBITS
+				 ? shdr_info[cnt].shdr.sh_size : 0);
+	      if (lastoffset < shdr_info[cnt].shdr.sh_offset + filesz)
+		lastoffset = shdr_info[cnt].shdr.sh_offset + filesz;
+	    }
+	}
+
+  /* Adjust symbol references if symbol tables changed.  */
+  if (any_symtab_changes)
+    /* Find all relocation sections which use this symbol table.  */
+    for (cnt = 1; cnt <= shdridx; ++cnt)
+      {
+	struct shdr_info *info = &shdr_info[cnt];
+	if (info->idx == 0 && debug_fname == NULL)
+	  /* Ignore sections which are discarded.  When we are saving a
+	     relocation section in a separate debug file, we must fix up
+	     the symbol table references.  */
+	  continue;
+
+	const Elf32_Word symtabidx = info->old_sh_link;
+	elf_assert (symtabidx < shnum + 2);
+	const Elf32_Word *const newsymidx = shdr_info[symtabidx].newsymidx;
+
+	/* If the symbol table hasn't changed, do not do anything.  */
+	if (newsymidx == NULL)
+	  continue;
+
+	/* If the symbol table is not discarded, but additionally
+	   duplicated in the separate debug file and this section
+	   is discarded, don't adjust anything.  */
+	if (info->idx == 0 && shdr_info[symtabidx].debug_data != NULL)
+	  continue;
+
+	switch (info->shdr.sh_type)
+	  {
+	  case SHT_REL:
+	  case SHT_RELA:
+	    scn = (info->idx == 0
+		   ? elf_getscn (debugelf, cnt)
+		   : elf_getscn (newelf, info->idx));
+	    Elf_Data *d = elf_getdata (scn, NULL);
+	    elf_assert (d != NULL && d->d_buf != NULL
+			&& info->shdr.sh_entsize != 0);
+	    size_t nrels = (info->shdr.sh_size / info->shdr.sh_entsize);
+
+	    size_t symsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+	    const Elf32_Word symidxn = (shdr_info[symtabidx].data->d_size
+					/ symsize);
+	    if (info->shdr.sh_type == SHT_REL)
+	      for (size_t relidx = 0; relidx < nrels; ++relidx)
+		{
+		  GElf_Rel rel_mem;
+		  if (gelf_getrel (d, relidx, &rel_mem) == NULL)
+		    INTERNAL_ERROR (fname);
+
+		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
+		  elf_assert (symidx < symidxn);
+		  if (newsymidx[symidx] != symidx)
+		    {
+		      rel_mem.r_info
+			= GELF_R_INFO (newsymidx[symidx],
+				       GELF_R_TYPE (rel_mem.r_info));
+
+		      if (gelf_update_rel (d, relidx, &rel_mem) == 0)
+			INTERNAL_ERROR (fname);
+		    }
+		}
+	    else
+	      for (size_t relidx = 0; relidx < nrels; ++relidx)
+		{
+		  GElf_Rela rel_mem;
+		  if (gelf_getrela (d, relidx, &rel_mem) == NULL)
+		    INTERNAL_ERROR (fname);
+
+		  size_t symidx = GELF_R_SYM (rel_mem.r_info);
+		  elf_assert (symidx < symidxn);
+		  if (newsymidx[symidx] != symidx)
+		    {
+		      rel_mem.r_info
+			= GELF_R_INFO (newsymidx[symidx],
+				       GELF_R_TYPE (rel_mem.r_info));
+
+		      if (gelf_update_rela (d, relidx, &rel_mem) == 0)
+			INTERNAL_ERROR (fname);
+		    }
+		}
+	    break;
+
+	  case SHT_HASH:
+	    /* We have to recompute the hash table.  */
+
+	    elf_assert (info->idx > 0);
+
+	    /* The hash section in the new file.  */
+	    scn = elf_getscn (newelf, info->idx);
+
+	    /* The symbol table data.  */
+	    Elf_Data *symd = elf_getdata (elf_getscn (newelf,
+						      shdr_info[symtabidx].idx),
+					  NULL);
+	    elf_assert (symd != NULL && symd->d_buf != NULL);
+
+	    /* The hash table data.  */
+	    Elf_Data *hashd = elf_getdata (scn, NULL);
+	    elf_assert (hashd != NULL && hashd->d_buf != NULL);
+
+	    if (info->shdr.sh_entsize == sizeof (Elf32_Word))
+	      {
+		/* Sane arches first.  */
+		elf_assert (hashd->d_size >= 2 * sizeof (Elf32_Word));
+		Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf;
+
+		size_t strshndx = shdr_info[symtabidx].old_sh_link;
+		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+
+		Elf32_Word nchain = bucket[1];
+		Elf32_Word nbucket = bucket[0];
+		uint64_t used_buf = ((2ULL + nchain + nbucket)
+				     * sizeof (Elf32_Word));
+		elf_assert (used_buf <= hashd->d_size);
+
+		/* Adjust the nchain value.  The symbol table size
+		   changed.  We keep the same size for the bucket array.  */
+		bucket[1] = symd->d_size / elsize;
+		bucket += 2;
+		Elf32_Word *chain = bucket + nbucket;
+
+		/* New size of the section.  */
+		size_t n_size = ((2 + symd->d_size / elsize + nbucket)
+				 * sizeof (Elf32_Word));
+		elf_assert (n_size <= hashd->d_size);
+		hashd->d_size = n_size;
+		update_section_size (scn, hashd, debugelf, cnt, fname);
+
+		/* Clear the arrays.  */
+		memset (bucket, '\0',
+			(symd->d_size / elsize + nbucket)
+			* sizeof (Elf32_Word));
+
+		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
+		     inner < symd->d_size / elsize; ++inner)
+		  {
+		    GElf_Sym sym_mem;
+		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
+		    elf_assert (sym != NULL);
+
+		    const char *name = elf_strptr (elf, strshndx,
+						   sym->st_name);
+		    elf_assert (name != NULL && nbucket != 0);
+		    size_t hidx = elf_hash (name) % nbucket;
+
+		    if (bucket[hidx] == 0)
+		      bucket[hidx] = inner;
+		    else
+		      {
+			hidx = bucket[hidx];
+
+			while (chain[hidx] != 0 && chain[hidx] < nchain)
+			  hidx = chain[hidx];
+
+			chain[hidx] = inner;
+		      }
+		  }
+	      }
+	    else
+	      {
+		/* Alpha and S390 64-bit use 64-bit SHT_HASH entries.  */
+		elf_assert (info->shdr.sh_entsize == sizeof (Elf64_Xword));
+
+		Elf64_Xword *bucket = (Elf64_Xword *) hashd->d_buf;
+
+		size_t strshndx = shdr_info[symtabidx].old_sh_link;
+		size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+
+		elf_assert (symd->d_size >= 2 * sizeof (Elf64_Xword));
+		Elf64_Xword nbucket = bucket[0];
+		Elf64_Xword nchain = bucket[1];
+		uint64_t maxwords = hashd->d_size / sizeof (Elf64_Xword);
+		elf_assert (maxwords >= 2
+			    && maxwords - 2 >= nbucket
+			    && maxwords - 2 - nbucket >= nchain);
+
+		/* Adjust the nchain value.  The symbol table size
+		   changed.  We keep the same size for the bucket array.  */
+		bucket[1] = symd->d_size / elsize;
+		bucket += 2;
+		Elf64_Xword *chain = bucket + nbucket;
+
+		/* New size of the section.  */
+		size_t n_size = ((2 + symd->d_size / elsize + nbucket)
+				 * sizeof (Elf64_Xword));
+		elf_assert (n_size <= hashd->d_size);
+		hashd->d_size = n_size;
+		update_section_size (scn, hashd, debugelf, cnt, fname);
+
+		/* Clear the arrays.  */
+		memset (bucket, '\0',
+			(symd->d_size / elsize + nbucket)
+			* sizeof (Elf64_Xword));
+
+		for (size_t inner = shdr_info[symtabidx].shdr.sh_info;
+		     inner < symd->d_size / elsize; ++inner)
+		  {
+		    GElf_Sym sym_mem;
+		    GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
+		    elf_assert (sym != NULL);
+
+		    const char *name = elf_strptr (elf, strshndx,
+						   sym->st_name);
+		    elf_assert (name != NULL && nbucket != 0);
+		    size_t hidx = elf_hash (name) % nbucket;
+
+		    if (bucket[hidx] == 0)
+		      bucket[hidx] = inner;
+		    else
+		      {
+			hidx = bucket[hidx];
+
+			while (chain[hidx] != 0 && chain[hidx] < nchain)
+			  hidx = chain[hidx];
+
+			chain[hidx] = inner;
+		      }
+		  }
+	      }
+	    break;
+
+	  case SHT_GNU_versym:
+	    /* If the symbol table changed we have to adjust the entries.  */
+	    elf_assert (info->idx > 0);
+
+	    /* The symbol version section in the new file.  */
+	    scn = elf_getscn (newelf, info->idx);
+
+	    /* The symbol table data.  */
+	    symd = elf_getdata (elf_getscn (newelf, shdr_info[symtabidx].idx),
+				NULL);
+	    elf_assert (symd != NULL && symd->d_buf != NULL);
+	    size_t symz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+	    const Elf32_Word syms = (shdr_info[symtabidx].data->d_size / symz);
+
+	    /* The version symbol data.  */
+	    Elf_Data *verd = elf_getdata (scn, NULL);
+	    elf_assert (verd != NULL && verd->d_buf != NULL);
+
+	    /* The symbol version array.  */
+	    GElf_Half *verstab = (GElf_Half *) verd->d_buf;
+
+	    /* Walk through the list and */
+	    size_t elsize = gelf_fsize (elf, verd->d_type, 1, EV_CURRENT);
+	    Elf32_Word vers = verd->d_size / elsize;
+	    for (size_t inner = 1; inner < vers && inner < syms; ++inner)
+	      if (newsymidx[inner] != 0 && newsymidx[inner] < vers)
+		/* Overwriting the same array works since the
+		   reordering can only move entries to lower indices
+		   in the array.  */
+		verstab[newsymidx[inner]] = verstab[inner];
+
+	    /* New size of the section.  */
+	    verd->d_size = gelf_fsize (newelf, verd->d_type,
+				       symd->d_size
+				       / gelf_fsize (elf, symd->d_type, 1,
+						     EV_CURRENT),
+				       EV_CURRENT);
+	    update_section_size (scn, verd, debugelf, cnt, fname);
+	    break;
+
+	  case SHT_GROUP:
+	    /* Yes, the symbol table changed.
+	       Update the section header of the section group.  */
+	    scn = elf_getscn (newelf, info->idx);
+	    GElf_Shdr shdr_mem;
+	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	    elf_assert (shdr != NULL);
+
+	    size_t symsz = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+	    const Elf32_Word symn = (shdr_info[symtabidx].data->d_size
+				     / symsz);
+	    elf_assert (shdr->sh_info < symn);
+	    shdr->sh_info = newsymidx[shdr->sh_info];
+
+	    (void) gelf_update_shdr (scn, shdr);
+	    break;
+	  }
+      }
+
+  /* Remove any relocations between debug sections in ET_REL
+     for the debug file when requested.  These relocations are always
+     zero based between the unallocated sections.  */
+  if (debug_fname != NULL && removing_sections
+      && reloc_debug && ehdr->e_type == ET_REL)
+    remove_debug_relocations (ebl, debugelf, ehdr, fname, shstrndx);
+
+  /* Now that we have done all adjustments to the data,
+     we can actually write out the debug file.  */
+  if (debug_fname != NULL && removing_sections)
+    {
+      /* Finally write the file.  */
+      if (unlikely (elf_update (debugelf, ELF_C_WRITE) == -1))
+	{
+	  error (0, 0, _("while writing '%s': %s"),
+		 tmp_debug_fname, elf_errmsg (-1));
+	  result = 1;
+	  goto fail_close;
+	}
+
+      /* Create the real output file.  First rename, then change the
+	 mode.  */
+      if (rename (tmp_debug_fname, debug_fname) != 0
+	  || fchmod (debug_fd, mode) != 0)
+	{
+	  error (0, errno, _("while creating '%s'"), debug_fname);
+	  result = 1;
+	  goto fail_close;
+	}
+
+      /* The temporary file does not exist anymore.  */
+      free (tmp_debug_fname);
+      tmp_debug_fname = NULL;
+
+      if (!remove_shdrs)
+	{
+	  uint32_t debug_crc;
+	  Elf_Data debug_crc_data =
+	    {
+	      .d_type = ELF_T_WORD,
+	      .d_buf = &debug_crc,
+	      .d_size = sizeof (debug_crc),
+	      .d_version = EV_CURRENT
+	    };
+
+	  /* Compute the checksum which we will add to the executable.  */
+	  if (crc32_file (debug_fd, &debug_crc) != 0)
+	    {
+	      error (0, errno, _("\
+while computing checksum for debug information"));
+	      unlink (debug_fname);
+	      result = 1;
+	      goto fail_close;
+	    }
+
+	  /* Store it in the debuglink section data.  */
+	  if (unlikely (gelf_xlatetof (newelf, &debuglink_crc_data,
+				       &debug_crc_data, ehdr->e_ident[EI_DATA])
+			!= &debuglink_crc_data))
+	    INTERNAL_ERROR (fname);
+	}
+    }
+
+  lastsec_offset = shdr_info[shdridx].shdr.sh_offset;
+  lastsec_size = shdr_info[shdridx].shdr.sh_size;
+
+ done:
+  /* Finally finish the ELF header.  Fill in the fields not handled by
+     libelf from the old file.  */
+  newehdr = gelf_getehdr (newelf, &newehdr_mem);
+  if (newehdr == NULL)
+    INTERNAL_ERROR (fname);
+
+  memcpy (newehdr->e_ident, ehdr->e_ident, EI_NIDENT);
+  newehdr->e_type = ehdr->e_type;
+  newehdr->e_machine = ehdr->e_machine;
+  newehdr->e_version = ehdr->e_version;
+  newehdr->e_entry = ehdr->e_entry;
+  newehdr->e_flags = ehdr->e_flags;
+  newehdr->e_phoff = ehdr->e_phoff;
+
+  /* We need to position the section header table.  */
+  const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
+  newehdr->e_shoff = ((lastsec_offset + lastsec_size + offsize - 1)
+		      & ~((GElf_Off) (offsize - 1)));
+  newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
+
+  if (gelf_update_ehdr (newelf, newehdr) == 0)
+    {
+      error (0, 0, _("%s: error while creating ELF header: %s"),
+	     output_fname ?: fname, elf_errmsg (-1));
+      result = 1;
+    }
+
+  /* The new section header string table index.  */
+  if (update_shdrstrndx (newelf, idx) != 0)
+    {
+      error (0, 0, _("%s: error updating shdrstrndx: %s"),
+	     output_fname ?: fname, elf_errmsg (-1));
+      result = 1;
+    }
+
+  /* We have everything from the old file.  */
+  if (elf_cntl (elf, ELF_C_FDDONE) != 0)
+    {
+      error (0, 0, _("%s: error while reading the file: %s"),
+	     fname, elf_errmsg (-1));
+      result = 1;
+    }
+
+  /* The ELF library better follows our layout when this is not a
+     relocatable object file.  */
+  elf_flagelf (newelf, ELF_C_SET,
+	       (phnum > 0 ? ELF_F_LAYOUT : 0)
+	       | (permissive ? ELF_F_PERMISSIVE : 0));
+
+  /* Finally write the file.  */
+  if (elf_update (newelf, ELF_C_WRITE) == -1)
+    {
+      error (0, 0, _("while writing '%s': %s"),
+	     output_fname ?: fname, elf_errmsg (-1));
+      result = 1;
+    }
+
+  if (remove_shdrs)
+    {
+      /* libelf can't cope without the section headers being properly intact.
+	 So we just let it write them normally, and then we nuke them later.  */
+
+      if (newehdr->e_ident[EI_CLASS] == ELFCLASS32)
+	{
+	  assert (offsetof (Elf32_Ehdr, e_shentsize) + sizeof (Elf32_Half)
+		  == offsetof (Elf32_Ehdr, e_shnum));
+	  assert (offsetof (Elf32_Ehdr, e_shnum) + sizeof (Elf32_Half)
+		  == offsetof (Elf32_Ehdr, e_shstrndx));
+	  const Elf32_Off zero_off = 0;
+	  const Elf32_Half zero[3] = { 0, 0, SHN_UNDEF };
+	  if (pwrite_retry (fd, &zero_off, sizeof zero_off,
+			    offsetof (Elf32_Ehdr, e_shoff)) != sizeof zero_off
+	      || (pwrite_retry (fd, zero, sizeof zero,
+				offsetof (Elf32_Ehdr, e_shentsize))
+		  != sizeof zero)
+	      || ftruncate (fd, lastsec_offset) < 0)
+	    {
+	      error (0, errno, _("while writing '%s'"),
+		     output_fname ?: fname);
+	      result = 1;
+	    }
+	}
+      else
+	{
+	  assert (offsetof (Elf64_Ehdr, e_shentsize) + sizeof (Elf64_Half)
+		  == offsetof (Elf64_Ehdr, e_shnum));
+	  assert (offsetof (Elf64_Ehdr, e_shnum) + sizeof (Elf64_Half)
+		  == offsetof (Elf64_Ehdr, e_shstrndx));
+	  const Elf64_Off zero_off = 0;
+	  const Elf64_Half zero[3] = { 0, 0, SHN_UNDEF };
+	  if (pwrite_retry (fd, &zero_off, sizeof zero_off,
+			    offsetof (Elf64_Ehdr, e_shoff)) != sizeof zero_off
+	      || (pwrite_retry (fd, zero, sizeof zero,
+				offsetof (Elf64_Ehdr, e_shentsize))
+		  != sizeof zero)
+	      || ftruncate (fd, lastsec_offset) < 0)
+	    {
+	      error (0, errno, _("while writing '%s'"),
+		     output_fname ?: fname);
+	      result = 1;
+	    }
+	}
+    }
+
+ fail_close:
+  if (shdr_info != NULL)
+    {
+      /* For some sections we might have created an table to map symbol
+	 table indices.  Or we might kept (original) data around to put
+	 into the .debug file.  */
+      for (cnt = 1; cnt <= shdridx; ++cnt)
+	{
+	  free (shdr_info[cnt].newsymidx);
+	  if (shdr_info[cnt].debug_data != NULL)
+	    free (shdr_info[cnt].debug_data->d_buf);
+	}
+
+      /* Free data we allocated for the .gnu_debuglink section. */
+      free (debuglink_buf);
+
+      /* Free the memory.  */
+      if ((shnum + 2) * sizeof (struct shdr_info) > MAX_STACK_ALLOC)
+	free (shdr_info);
+    }
+
+  /* Free other resources.  */
+  if (shstrtab_data != NULL)
+    free (shstrtab_data->d_buf);
+  if (shst != NULL)
+    dwelf_strtab_free (shst);
+
+  /* That was it.  Close the descriptors.  */
+  if (elf_end (newelf) != 0)
+    {
+      error (0, 0, _("error while finishing '%s': %s"),
+	     output_fname ?: fname, elf_errmsg (-1));
+      result = 1;
+    }
+
+  if (debugelf != NULL && elf_end (debugelf) != 0)
+    {
+      error (0, 0, _("error while finishing '%s': %s"), debug_fname,
+	     elf_errmsg (-1));
+      result = 1;
+    }
+
+ fail:
+  /* Close the EBL backend.  */
+  if (ebl != NULL)
+    ebl_closebackend (ebl);
+
+  cleanup_debug ();
+
+  /* If requested, preserve the timestamp.  */
+  if (tvp != NULL)
+    {
+      if (futimens (fd, tvp) != 0)
+	{
+	  error (0, errno, _("\
+cannot set access and modification date of '%s'"),
+		 output_fname ?: fname);
+	  result = 1;
+	}
+    }
+
+  /* Close the file descriptor if we created a new file.  */
+  if (output_fname != NULL)
+    {
+      close (fd);
+      if (result != 0)
+       unlink (output_fname);
+    }
+
+  return result;
+}
+
+static void
+cleanup_debug (void)
+{
+  if (debug_fd >= 0)
+    {
+      if (tmp_debug_fname != NULL)
+	{
+	  unlink (tmp_debug_fname);
+	  free (tmp_debug_fname);
+	  tmp_debug_fname = NULL;
+	}
+      close (debug_fd);
+      debug_fd = -1;
+    }
+}
+
+static int
+handle_ar (int fd, Elf *elf, const char *prefix, const char *fname,
+	   struct timespec tvp[2])
+{
+  size_t prefix_len = prefix == NULL ? 0 : strlen (prefix);
+  size_t fname_len = strlen (fname) + 1;
+  char new_prefix[prefix_len + 1 + fname_len];
+  char *cp = new_prefix;
+
+  /* Create the full name of the file.  */
+  if (prefix != NULL)
+    {
+      cp = mempcpy (cp, prefix, prefix_len);
+      *cp++ = ':';
+    }
+  memcpy (cp, fname, fname_len);
+
+
+  /* Process all the files contained in the archive.  */
+  Elf *subelf;
+  Elf_Cmd cmd = ELF_C_RDWR;
+  int result = 0;
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      /* The the header for this element.  */
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      if (elf_kind (subelf) == ELF_K_ELF)
+	result |= handle_elf (fd, subelf, new_prefix, arhdr->ar_name, 0, NULL);
+      else if (elf_kind (subelf) == ELF_K_AR)
+	result |= handle_ar (fd, subelf, new_prefix, arhdr->ar_name, NULL);
+
+      /* Get next archive element.  */
+      cmd = elf_next (subelf);
+      if (unlikely (elf_end (subelf) != 0))
+	INTERNAL_ERROR (fname);
+    }
+
+  if (tvp != NULL)
+    {
+      if (unlikely (futimens (fd, tvp) != 0))
+	{
+	  error (0, errno, _("\
+cannot set access and modification date of '%s'"), fname);
+	  result = 1;
+	}
+    }
+
+  if (unlikely (close (fd) != 0))
+    error_exit (errno, _("while closing '%s'"), fname);
+
+  return result;
+}
+
+
+#include "debugpred.h"
diff --git a/src/unstrip.c b/src/unstrip.c
new file mode 100644
index 0000000..d70053d
--- /dev/null
+++ b/src/unstrip.c
@@ -0,0 +1,2678 @@
+/* Combine stripped files with separate symbols and debug information.
+   Copyright (C) 2007-2012, 2014, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Roland McGrath <roland@redhat.com>, 2007.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* TODO:
+
+  * SHX_XINDEX
+
+  * prelink vs .debug_* linked addresses
+
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <argp.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fnmatch.h>
+#include <locale.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/stat.h>
+
+#include <gelf.h>
+#include <libebl.h>
+#include <libdwfl.h>
+#include "system.h"
+#include "libdwelf.h"
+#include "libeu.h"
+#include "printversion.h"
+
+/* Name and version of program.  */
+ARGP_PROGRAM_VERSION_HOOK_DEF = print_version;
+
+/* Bug report address.  */
+ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT;
+
+/* Definitions of arguments for argp functions.  */
+static const struct argp_option options[] =
+{
+  /* Group 2 will follow group 1 from dwfl_standard_argp.  */
+  { "match-file-names", 'f', NULL, 0,
+    N_("Match MODULE against file names, not module names"), 2 },
+  { "ignore-missing", 'i', NULL, 0, N_("Silently skip unfindable files"), 0 },
+
+  { NULL, 0, NULL, 0, N_("Output options:"), 0 },
+  { "output", 'o', "FILE", 0, N_("Place output into FILE"), 0 },
+  { "output-directory", 'd', "DIRECTORY",
+    0, N_("Create multiple output files under DIRECTORY"), 0 },
+  { "module-names", 'm', NULL, 0, N_("Use module rather than file names"), 0 },
+  { "all", 'a', NULL, 0,
+    N_("Create output for modules that have no separate debug information"),
+    0 },
+  { "relocate", 'R', NULL, 0,
+    N_("Apply relocations to section contents in ET_REL files"), 0 },
+  { "list-only", 'n', NULL, 0,
+    N_("Only list module and file names, build IDs"), 0 },
+ { "force", 'F', NULL, 0,
+    N_("Force combining files even if some ELF headers don't seem to match"),
+   0 },
+  { NULL, 0, NULL, 0, NULL, 0 }
+};
+
+struct arg_info
+{
+  const char *output_file;
+  const char *output_dir;
+  Dwfl *dwfl;
+  char **args;
+  bool list;
+  bool all;
+  bool ignore;
+  bool modnames;
+  bool match_files;
+  bool relocate;
+  bool force;
+};
+
+/* Handle program arguments.  */
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  struct arg_info *info = state->input;
+
+  switch (key)
+    {
+    case ARGP_KEY_INIT:
+      state->child_inputs[0] = &info->dwfl;
+      break;
+
+    case 'o':
+      if (info->output_file != NULL)
+	{
+	  argp_error (state, _("-o option specified twice"));
+	  return EINVAL;
+	}
+      info->output_file = arg;
+      break;
+
+    case 'd':
+      if (info->output_dir != NULL)
+	{
+	  argp_error (state, _("-d option specified twice"));
+	  return EINVAL;
+	}
+      info->output_dir = arg;
+      break;
+
+    case 'm':
+      info->modnames = true;
+      break;
+    case 'f':
+      info->match_files = true;
+      break;
+    case 'a':
+      info->all = true;
+      break;
+    case 'i':
+      info->ignore = true;
+      break;
+    case 'n':
+      info->list = true;
+      break;
+    case 'R':
+      info->relocate = true;
+      break;
+    case 'F':
+      info->force = true;
+      break;
+
+    case ARGP_KEY_ARGS:
+    case ARGP_KEY_NO_ARGS:
+      /* We "consume" all the arguments here.  */
+      info->args = &state->argv[state->next];
+
+      if (info->output_file != NULL && info->output_dir != NULL)
+	{
+	  argp_error (state, _("only one of -o or -d allowed"));
+	  return EINVAL;
+	}
+
+      if (info->list && (info->dwfl == NULL
+			 || info->output_dir != NULL
+			 || info->output_file != NULL))
+	{
+	  argp_error (state,
+		      _("-n cannot be used with explicit files or -o or -d"));
+	  return EINVAL;
+	}
+
+      if (info->output_dir != NULL)
+	{
+	  struct stat st;
+	  error_t fail = 0;
+	  if (stat (info->output_dir, &st) < 0)
+	    fail = errno;
+	  else if (!S_ISDIR (st.st_mode))
+	    fail = ENOTDIR;
+	  if (fail)
+	    {
+	      argp_failure (state, EXIT_FAILURE, fail,
+			    _("output directory '%s'"), info->output_dir);
+	      return fail;
+	    }
+	}
+
+      if (info->dwfl == NULL)
+	{
+	  if (state->next + 2 != state->argc)
+	    {
+	      argp_error (state, _("exactly two file arguments are required"));
+	      return EINVAL;
+	    }
+
+	  if (info->ignore || info->all || info->modnames || info->relocate)
+	    {
+	      argp_error (state, _("\
+-m, -a, -R, and -i options not allowed with explicit files"));
+	      return EINVAL;
+	    }
+
+	  /* Bail out immediately to prevent dwfl_standard_argp's parser
+	     from defaulting to "-e a.out".  */
+	  return ENOSYS;
+	}
+      else if (info->output_file == NULL && info->output_dir == NULL
+	       && !info->list)
+	{
+	  argp_error (state,
+		      _("-o or -d is required when using implicit files"));
+	  return EINVAL;
+	}
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+#define ELF_CHECK(call, msg)						      \
+  do									      \
+    {									      \
+      if (unlikely (!(call)))						      \
+	error_exit (0, msg, elf_errmsg (-1));				      \
+    } while (0)
+
+/* Copy INELF to newly-created OUTELF, exit via error for any problems.  */
+static void
+copy_elf (Elf *outelf, Elf *inelf)
+{
+  ELF_CHECK (gelf_newehdr (outelf, gelf_getclass (inelf)),
+	     _("cannot create ELF header: %s"));
+
+  size_t shstrndx;
+  ELF_CHECK (elf_getshdrstrndx (inelf, &shstrndx) == 0,
+	     _("cannot get shdrstrndx:%s"));
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (inelf, &ehdr_mem);
+  ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s"));
+  if (shstrndx < SHN_LORESERVE)
+    ehdr->e_shstrndx = shstrndx;
+  else
+    {
+      ehdr->e_shstrndx = SHN_XINDEX;
+      Elf_Scn *scn0 = elf_getscn (outelf, 0);
+      GElf_Shdr shdr0_mem;
+      GElf_Shdr *shdr0 = gelf_getshdr (scn0, &shdr0_mem);
+      ELF_CHECK (shdr0 != NULL,
+		 _("cannot get new zero section: %s"));
+      shdr0->sh_link = shstrndx;
+      ELF_CHECK (gelf_update_shdr (scn0, shdr0),
+		 _("cannot update new zero section: %s"));
+    }
+
+  ELF_CHECK (gelf_update_ehdr (outelf, ehdr),
+	     _("cannot copy ELF header: %s"));
+
+  size_t phnum;
+  ELF_CHECK (elf_getphdrnum (inelf, &phnum) == 0,
+	     _("cannot get number of program headers: %s"));
+
+  if (phnum > 0)
+    {
+      ELF_CHECK (gelf_newphdr (outelf, phnum),
+		 _("cannot create program headers: %s"));
+
+      GElf_Phdr phdr_mem;
+      for (size_t i = 0; i < phnum; ++i)
+	ELF_CHECK (gelf_update_phdr (outelf, i,
+				     gelf_getphdr (inelf, i, &phdr_mem)),
+		   _("cannot copy program header: %s"));
+    }
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (inelf, scn)) != NULL)
+    {
+      Elf_Scn *newscn = elf_newscn (outelf);
+
+      GElf_Shdr shdr_mem;
+      ELF_CHECK (gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem)),
+		 _("cannot copy section header: %s"));
+
+      Elf_Data *data = elf_getdata (scn, NULL);
+      ELF_CHECK (data != NULL, _("cannot get section data: %s"));
+      Elf_Data *newdata = elf_newdata (newscn);
+      ELF_CHECK (newdata != NULL, _("cannot copy section data: %s"));
+      *newdata = *data;
+      elf_flagdata (newdata, ELF_C_SET, ELF_F_DIRTY);
+    }
+}
+
+/* Create directories containing PATH.  */
+static void
+make_directories (const char *path)
+{
+  const char *lastslash = strrchr (path, '/');
+  if (lastslash == NULL)
+    return;
+
+  while (lastslash > path && lastslash[-1] == '/')
+    --lastslash;
+  if (lastslash == path)
+    return;
+
+  char *dir = strndup (path, lastslash - path);
+  if (dir == NULL)
+    error(EXIT_FAILURE, errno, _("memory exhausted"));
+
+  while (mkdir (dir, ACCESSPERMS) < 0 && errno != EEXIST)
+    {
+      if (errno == ENOENT)
+        make_directories (dir);
+      else
+        error_exit (errno, _("cannot create directory '%s'"), dir);
+    }
+  free (dir);
+}
+
+/* Keep track of new section data we are creating, so we can free it
+   when done.  */
+struct data_list
+{
+  void *data;
+  struct data_list *next;
+};
+
+struct data_list *new_data_list;
+
+static void
+record_new_data (void *data)
+{
+  struct data_list *next = new_data_list;
+  new_data_list = xmalloc (sizeof (struct data_list));
+  new_data_list->data = data;
+  new_data_list->next = next;
+}
+
+static void
+free_new_data (void)
+{
+  struct data_list *list = new_data_list;
+  while (list != NULL)
+    {
+      struct data_list *next = list->next;
+      free (list->data);
+      free (list);
+      list = next;
+    }
+  new_data_list = NULL;
+}
+
+/* The binutils linker leaves gratuitous section symbols in .symtab
+   that strip has to remove.  Older linkers likewise include a
+   symbol for every section, even unallocated ones, in .dynsym.
+   Because of this, the related sections can shrink in the stripped
+   file from their original size.  Older versions of strip do not
+   adjust the sh_size field in the debuginfo file's SHT_NOBITS
+   version of the section header, so it can appear larger.  */
+static bool
+section_can_shrink (const GElf_Shdr *shdr)
+{
+  switch (shdr->sh_type)
+    {
+    case SHT_SYMTAB:
+    case SHT_DYNSYM:
+    case SHT_HASH:
+    case SHT_GNU_versym:
+      return true;
+    }
+  return false;
+}
+
+/* See if this symbol table has a leading section symbol for every single
+   section, in order.  The binutils linker produces this.  While we're here,
+   update each section symbol's st_value.  */
+static size_t
+symtab_count_leading_section_symbols (Elf *elf, Elf_Scn *scn, size_t shnum,
+				      Elf_Data *newsymdata)
+{
+  Elf_Data *data = elf_getdata (scn, NULL);
+  Elf_Data *shndxdata = NULL;	/* XXX */
+
+  for (size_t i = 1; i < shnum; ++i)
+    {
+      GElf_Sym sym_mem;
+      GElf_Word shndx = SHN_UNDEF;
+      GElf_Sym *sym = gelf_getsymshndx (data, shndxdata, i, &sym_mem, &shndx);
+      ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (elf_getscn (elf, i), &shdr_mem);
+      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+      if (sym->st_shndx != SHN_XINDEX)
+	shndx = sym->st_shndx;
+
+      if (shndx != i || GELF_ST_TYPE (sym->st_info) != STT_SECTION)
+	return i;
+
+      sym->st_value = shdr->sh_addr;
+      if (sym->st_shndx != SHN_XINDEX)
+	shndx = SHN_UNDEF;
+      ELF_CHECK (gelf_update_symshndx (newsymdata, shndxdata, i, sym, shndx),
+		 _("cannot update symbol table: %s"));
+    }
+
+  return shnum;
+}
+
+static void
+update_shdr (Elf_Scn *outscn, GElf_Shdr *newshdr)
+{
+  ELF_CHECK (gelf_update_shdr (outscn, newshdr),
+	     _("cannot update section header: %s"));
+}
+
+/* We expanded the output section, so update its header.  */
+static void
+update_sh_size (Elf_Scn *outscn, const Elf_Data *data)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
+  ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
+
+  newshdr->sh_size = data->d_size;
+
+  update_shdr (outscn, newshdr);
+}
+
+static inline void
+adjust_reloc (GElf_Xword *info,
+	      size_t map[], size_t map_size)
+{
+  size_t ndx = GELF_R_SYM (*info);
+  if (ndx != STN_UNDEF)
+    {
+      if (ndx > map_size)
+	error_exit (0, "bad symbol ndx section");
+      *info = GELF_R_INFO (map[ndx - 1], GELF_R_TYPE (*info));
+    }
+}
+
+/* Update relocation sections using the symbol table.  */
+static void
+adjust_relocs (Elf_Scn *outscn, Elf_Scn *inscn, const GElf_Shdr *shdr,
+	       size_t map[], size_t map_size, const GElf_Shdr *symshdr)
+{
+  Elf_Data *data = elf_getdata (outscn, NULL);
+
+  switch (shdr->sh_type)
+    {
+    case SHT_REL:
+      if (shdr->sh_entsize == 0)
+	error_exit (0, "REL section cannot have zero sh_entsize");
+
+      for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
+	{
+	  GElf_Rel rel_mem;
+	  GElf_Rel *rel = gelf_getrel (data, i, &rel_mem);
+	  ELF_CHECK (rel != NULL, _("gelf_getrel failed: %s"));
+	  adjust_reloc (&rel->r_info, map, map_size);
+	  ELF_CHECK (gelf_update_rel (data, i, rel),
+		     _("cannot update relocation: %s"));
+	}
+      break;
+
+    case SHT_RELA:
+      if (shdr->sh_entsize == 0)
+	error_exit (0, "RELA section cannot have zero sh_entsize");
+
+      for (size_t i = 0; i < shdr->sh_size / shdr->sh_entsize; ++i)
+	{
+	  GElf_Rela rela_mem;
+	  GElf_Rela *rela = gelf_getrela (data, i, &rela_mem);
+	  ELF_CHECK (rela != NULL, _("gelf_getrela failed: %s"));
+	  adjust_reloc (&rela->r_info, map, map_size);
+	  ELF_CHECK (gelf_update_rela (data, i, rela),
+		     _("cannot update relocation: %s"));
+	}
+      break;
+
+    case SHT_GROUP:
+      {
+	GElf_Shdr shdr_mem;
+	GElf_Shdr *newshdr = gelf_getshdr (outscn, &shdr_mem);
+	ELF_CHECK (newshdr != NULL, _("cannot get section header: %s"));
+	if (newshdr->sh_info != STN_UNDEF)
+	  {
+	    newshdr->sh_info = map[newshdr->sh_info - 1];
+	    update_shdr (outscn, newshdr);
+	  }
+	break;
+      }
+
+    case SHT_HASH:
+      /* We must expand the table and rejigger its contents.  */
+      {
+	if (shdr->sh_entsize == 0)
+	  error_exit (0, "HASH section cannot have zero sh_entsize");
+	if (symshdr->sh_entsize == 0)
+	  error_exit (0, "Symbol table cannot have zero sh_entsize");
+	const size_t nsym = symshdr->sh_size / symshdr->sh_entsize;
+	const size_t onent = shdr->sh_size / shdr->sh_entsize;
+	if (data->d_size != shdr->sh_size)
+	  error_exit (0, "HASH section has inconsistent size");
+
+#define CONVERT_HASH(Hash_Word)						      \
+	{								      \
+	  const Hash_Word *const old_hash = data->d_buf;		      \
+	  const size_t nbucket = old_hash[0];				      \
+	  const size_t nchain = old_hash[1];				      \
+	  const Hash_Word *const old_bucket = &old_hash[2];		      \
+	  const Hash_Word *const old_chain = &old_bucket[nbucket];	      \
+	  if (onent != 2 + nbucket + nchain)				      \
+	    error_exit (0, "HASH section has inconsistent entsize");	      \
+									      \
+	  const size_t nent = 2 + nbucket + nsym;			      \
+	  Hash_Word *const new_hash = xcalloc (nent, sizeof new_hash[0]);     \
+	  Hash_Word *const new_bucket = &new_hash[2];			      \
+	  Hash_Word *const new_chain = &new_bucket[nbucket];		      \
+									      \
+	  new_hash[0] = nbucket;					      \
+	  new_hash[1] = nsym;						      \
+	  for (size_t i = 0; i < nbucket; ++i)				      \
+	    if (old_bucket[i] != STN_UNDEF)				      \
+	      new_bucket[i] = map[old_bucket[i] - 1];			      \
+									      \
+	  for (size_t i = 1; i < nchain; ++i)				      \
+	    if (old_chain[i] != STN_UNDEF)				      \
+	      new_chain[map[i - 1]] = map[old_chain[i] - 1];		      \
+									      \
+	  record_new_data (new_hash);					\
+	  data->d_buf = new_hash;					      \
+	  data->d_size = nent * sizeof new_hash[0];			      \
+	}
+
+	switch (shdr->sh_entsize)
+	  {
+	  case 4:
+	    CONVERT_HASH (Elf32_Word);
+	    break;
+	  case 8:
+	    CONVERT_HASH (Elf64_Xword);
+	    break;
+	  default:
+	    abort ();
+	  }
+
+	elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
+	update_sh_size (outscn, data);
+
+#undef	CONVERT_HASH
+      }
+      break;
+
+    case SHT_GNU_versym:
+      /* We must expand the table and move its elements around.  */
+      {
+	if (shdr->sh_entsize == 0)
+	  error_exit (0, "GNU_versym section cannot have zero sh_entsize");
+	if (symshdr->sh_entsize == 0)
+	  error_exit (0, "Symbol table cannot have zero sh_entsize");
+	const size_t nent = symshdr->sh_size / symshdr->sh_entsize;
+	const size_t onent = shdr->sh_size / shdr->sh_entsize;
+	assert (nent >= onent);
+
+	/* We don't bother using gelf_update_versym because there is
+	   really no conversion to be done.  */
+	assert (sizeof (Elf32_Versym) == sizeof (GElf_Versym));
+	assert (sizeof (Elf64_Versym) == sizeof (GElf_Versym));
+	GElf_Versym *versym = xcalloc (nent, sizeof versym[0]);
+
+	for (size_t i = 1; i < onent; ++i)
+	  {
+	    GElf_Versym *v = gelf_getversym (data, i, &versym[map[i - 1]]);
+	    ELF_CHECK (v != NULL, _("cannot get symbol version: %s"));
+	  }
+
+	record_new_data (versym);
+	data->d_buf = versym;
+	data->d_size = nent * sizeof versym[0];
+	elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
+	update_sh_size (outscn, data);
+      }
+      break;
+
+    default:
+      error_exit (0,
+		  _("unexpected section type in [%zu] with sh_link to symtab"),
+		  elf_ndxscn (inscn));
+    }
+}
+
+/* Adjust all the relocation sections in the file.  */
+static void
+adjust_all_relocs (Elf *elf, Elf_Scn *symtab, const GElf_Shdr *symshdr,
+		   size_t map[], size_t map_size, bool scn_filter[])
+{
+  size_t new_sh_link = elf_ndxscn (symtab);
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    if (scn != symtab)
+      {
+	if (scn_filter != NULL)
+	  {
+	    size_t ndx = elf_ndxscn (scn);
+
+	    /* Skip relocations that were already mapped during adjust_relocs
+	       for the stripped symtab.  This is to avoid mapping a relocation's
+	       symbol index from X to Y during the first adjust_relocs and then
+	       wrongly remapping it from Y to Z during the second call.  */
+	    if (scn_filter[ndx])
+	      continue;
+	  }
+
+	GElf_Shdr shdr_mem;
+	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+	if (shdr->sh_type != SHT_NOBITS && shdr->sh_link == new_sh_link)
+	  adjust_relocs (scn, scn, shdr, map, map_size, symshdr);
+      }
+}
+
+/* The original file probably had section symbols for all of its
+   sections, even the unallocated ones.  To match it as closely as
+   possible, add in section symbols for the added sections.  */
+static Elf_Data *
+add_new_section_symbols (Elf_Scn *old_symscn, size_t old_shnum,
+			 Elf *elf, bool rel, Elf_Scn *symscn, size_t shnum)
+{
+  const size_t added = shnum - old_shnum;
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (symscn, &shdr_mem);
+  ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+  if (shdr->sh_entsize == 0)
+    error_exit (0, "Symbol table section cannot have zero sh_entsize");
+
+  const size_t nsym = shdr->sh_size / shdr->sh_entsize;
+  size_t symndx_map[nsym - 1];
+
+  shdr->sh_info += added;
+  shdr->sh_size += added * shdr->sh_entsize;
+  update_shdr (symscn, shdr);
+
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  Elf_Data *shndxdata = NULL;	/* XXX */
+
+  symdata->d_size = shdr->sh_size;
+  symdata->d_buf = xmalloc (symdata->d_size);
+  record_new_data (symdata->d_buf);
+
+  /* Copy the existing section symbols.  */
+  Elf_Data *old_symdata = elf_getdata (old_symscn, NULL);
+  for (size_t i = 0; i < old_shnum; ++i)
+    {
+      GElf_Sym sym_mem;
+      GElf_Word shndx = SHN_UNDEF;
+      GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
+					i, &sym_mem, &shndx);
+      ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
+      ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
+				       sym, shndx),
+		 _("cannot update symbol table: %s"));
+
+      if (i > 0)
+	symndx_map[i - 1] = i;
+    }
+
+  /* Add in the new section symbols.  */
+  for (size_t i = old_shnum; i < shnum; ++i)
+    {
+      GElf_Shdr i_shdr_mem;
+      GElf_Shdr *i_shdr = gelf_getshdr (elf_getscn (elf, i), &i_shdr_mem);
+      ELF_CHECK (i_shdr != NULL, _("cannot get section header: %s"));
+      GElf_Sym sym =
+	{
+	  .st_value = rel ? 0 : i_shdr->sh_addr,
+	  .st_info = GELF_ST_INFO (STB_LOCAL, STT_SECTION),
+	  .st_shndx = i < SHN_LORESERVE ? i : SHN_XINDEX
+	};
+      GElf_Word shndx = i < SHN_LORESERVE ? SHN_UNDEF : i;
+      ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, i,
+				       &sym, shndx),
+		 _("cannot update symbol table: %s"));
+    }
+
+  /* Now copy the rest of the existing symbols.  */
+  for (size_t i = old_shnum; i < nsym; ++i)
+    {
+      GElf_Sym sym_mem;
+      GElf_Word shndx = SHN_UNDEF;
+      GElf_Sym *sym = gelf_getsymshndx (old_symdata, shndxdata,
+					i, &sym_mem, &shndx);
+      ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
+      ELF_CHECK (gelf_update_symshndx (symdata, shndxdata,
+				       i + added, sym, shndx),
+		 _("cannot update symbol table: %s"));
+
+      symndx_map[i - 1] = i + added;
+    }
+
+  /* Adjust any relocations referring to the old symbol table.  */
+  adjust_all_relocs (elf, symscn, shdr, symndx_map, nsym - 1, NULL);
+
+  return symdata;
+}
+
+/* This has the side effect of updating STT_SECTION symbols' values,
+   in case of prelink adjustments.  */
+static Elf_Data *
+check_symtab_section_symbols (Elf *elf, bool rel, Elf_Scn *scn,
+			      size_t shnum, size_t shstrndx,
+			      Elf_Scn *oscn, size_t oshnum, size_t oshstrndx,
+			      size_t debuglink)
+{
+  size_t n = symtab_count_leading_section_symbols (elf, oscn, oshnum,
+						   elf_getdata (scn, NULL));
+
+  if (n == oshnum)
+    return add_new_section_symbols (oscn, n, elf, rel, scn, shnum);
+
+  if (n == oshstrndx || (n == debuglink && n == oshstrndx - 1))
+    return add_new_section_symbols (oscn, n, elf, rel, scn, shstrndx);
+
+  return NULL;
+}
+
+struct section
+{
+  Elf_Scn *scn;
+  const char *name;
+  const char *sig;
+  Elf_Scn *outscn;
+  Dwelf_Strent *strent;
+  GElf_Shdr shdr;
+};
+
+static int
+compare_alloc_sections (const struct section *s1, const struct section *s2,
+			bool rel)
+{
+  if (!rel)
+    {
+      /* Sort by address.  */
+      if (s1->shdr.sh_addr < s2->shdr.sh_addr)
+	return -1;
+      if (s1->shdr.sh_addr > s2->shdr.sh_addr)
+	return 1;
+    }
+
+  /* At the same address, preserve original section order.  */
+  return (ssize_t) elf_ndxscn (s1->scn) - (ssize_t) elf_ndxscn (s2->scn);
+}
+
+static int
+compare_unalloc_sections (const GElf_Shdr *shdr1, const GElf_Shdr *shdr2,
+			  const char *name1, const char *name2,
+			  const char *sig1, const char *sig2)
+{
+  /* Sort by sh_flags as an arbitrary ordering.  */
+  if (shdr1->sh_flags < shdr2->sh_flags)
+    return -1;
+  if (shdr1->sh_flags > shdr2->sh_flags)
+    return 1;
+
+  /* Sizes should be the same.  */
+  if (shdr1->sh_size < shdr2->sh_size)
+    return -1;
+  if (shdr1->sh_size > shdr2->sh_size)
+    return 1;
+
+  /* Are they both SHT_GROUP sections? Then compare signatures.  */
+  if (sig1 != NULL && sig2 != NULL)
+    return strcmp (sig1, sig2);
+
+  /* Sort by name as last resort.  */
+  return strcmp (name1, name2);
+}
+
+static int
+compare_sections (const void *a, const void *b, bool rel)
+{
+  const struct section *s1 = a;
+  const struct section *s2 = b;
+
+  /* Sort all non-allocated sections last.  */
+  if ((s1->shdr.sh_flags ^ s2->shdr.sh_flags) & SHF_ALLOC)
+    return (s1->shdr.sh_flags & SHF_ALLOC) ? -1 : 1;
+
+  return ((s1->shdr.sh_flags & SHF_ALLOC)
+	  ? compare_alloc_sections (s1, s2, rel)
+	  : compare_unalloc_sections (&s1->shdr, &s2->shdr,
+				      s1->name, s2->name,
+				      s1->sig, s2->sig));
+}
+
+static int
+compare_sections_rel (const void *a, const void *b)
+{
+  return compare_sections (a, b, true);
+}
+
+static int
+compare_sections_nonrel (const void *a, const void *b)
+{
+  return compare_sections (a, b, false);
+}
+
+
+struct symbol
+{
+  size_t *map;
+
+  union
+  {
+    const char *name;
+    Dwelf_Strent *strent;
+  };
+  union
+  {
+    struct
+    {
+      GElf_Addr value;
+      GElf_Xword size;
+      GElf_Word shndx;
+      union
+      {
+	struct
+	{
+	  uint8_t info;
+	  uint8_t other;
+	} info;
+	int16_t compare;
+      };
+    };
+
+    /* For a symbol discarded after first sort, this matches its better's
+       map pointer.  */
+    size_t *duplicate;
+  };
+};
+
+/* Collect input symbols into our internal form.  */
+static void
+collect_symbols (Elf *outelf, bool rel, Elf_Scn *symscn, Elf_Scn *strscn,
+		 const size_t nent, const GElf_Addr bias,
+		 const size_t scnmap[], struct symbol *table, size_t *map,
+		 struct section *split_bss)
+{
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  ELF_CHECK (symdata != NULL, _("cannot get symbol section data: %s"));
+  Elf_Data *strdata = elf_getdata (strscn, NULL);
+  ELF_CHECK (strdata != NULL, _("cannot get string section data: %s"));
+  Elf_Data *shndxdata = NULL;	/* XXX */
+
+  for (size_t i = 1; i < nent; ++i)
+    {
+      GElf_Sym sym_mem;
+      GElf_Word shndx = SHN_UNDEF;
+      GElf_Sym *sym = gelf_getsymshndx (symdata, shndxdata, i,
+					&sym_mem, &shndx);
+      ELF_CHECK (sym != NULL, _("cannot get symbol table entry: %s"));
+      if (sym->st_shndx != SHN_XINDEX)
+	shndx = sym->st_shndx;
+
+      if (sym->st_name >= strdata->d_size
+	  || memrchr (strdata->d_buf + sym->st_name, '\0',
+		      strdata->d_size - sym->st_name) == NULL)
+	error_exit (0,
+		    _("invalid string offset in symbol [%zu]"), i);
+
+      struct symbol *s = &table[i - 1];
+      s->map = &map[i - 1];
+      s->name = strdata->d_buf + sym->st_name;
+      s->value = sym->st_value + bias;
+      s->size = sym->st_size;
+      s->shndx = shndx;
+      s->info.info = sym->st_info;
+      s->info.other = sym->st_other;
+      s->duplicate = NULL;
+
+      if (scnmap != NULL && shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
+	s->shndx = scnmap[shndx - 1];
+
+      if (GELF_ST_TYPE (s->info.info) == STT_SECTION && !rel)
+	{
+	  /* Update the value to match the output section.  */
+	  GElf_Shdr shdr_mem;
+	  GElf_Shdr *shdr = gelf_getshdr (elf_getscn (outelf, s->shndx),
+					  &shdr_mem);
+	  ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+	  s->value = shdr->sh_addr;
+	}
+      else if (split_bss != NULL
+	       && s->value < split_bss->shdr.sh_addr
+	       && s->value >= split_bss[-1].shdr.sh_addr
+	       && shndx == elf_ndxscn (split_bss->outscn))
+	/* This symbol was in .bss and was split into .dynbss.  */
+	s->shndx = elf_ndxscn (split_bss[-1].outscn);
+    }
+}
+
+
+#define CMP(value)							      \
+  if (s1->value < s2->value)						      \
+    return -1;								      \
+  if (s1->value > s2->value)						      \
+    return 1
+
+/* Symbol comparison used to sort symbols in preparation for deduplication.  */
+static int
+compare_symbols (const void *a, const void *b)
+{
+  const struct symbol *s1 = a;
+  const struct symbol *s2 = b;
+
+  CMP (value);
+  CMP (size);
+  CMP (shndx);
+
+  int res = s1->compare - s2->compare;
+  if (res != 0)
+    return res;
+
+  res = strcmp (s1->name, s2->name);
+  if (res != 0)
+    return res;
+
+  /* Duplicates still have distinct positions in the symbol index map.
+     Compare map positions to ensure that duplicate symbols are ordered
+     consistently even if the sort function is unstable.  */
+  CMP (map);
+  error_exit (0, _("found two identical index map positions."));
+}
+
+/* Symbol comparison used to deduplicate symbols found in both the stripped
+   and unstripped input files.
+
+   Similar to compare_symbols, but does not differentiate symbols based
+   on their position in the symbol index map.  Duplicates can't be found
+   by comparing index map postions because they always have distinct
+   positions in the map.  */
+static int
+compare_symbols_duplicate (const void *a, const void *b)
+{
+  const struct symbol *s1 = a;
+  const struct symbol *s2 = b;
+
+  CMP (value);
+  CMP (size);
+  CMP (shndx);
+
+  return (s1->compare - s2->compare) ?: strcmp (s1->name, s2->name);
+}
+
+/* Compare symbols for output order after slots have been assigned.  */
+static int
+compare_symbols_output (const void *a, const void *b)
+{
+  const struct symbol *s1 = a;
+  const struct symbol *s2 = b;
+  int cmp;
+
+  /* Sort discarded symbols last.  */
+  cmp = (s1->name == NULL) - (s2->name == NULL);
+
+  if (cmp == 0)
+    /* Local symbols must come first.  */
+    cmp = ((GELF_ST_BIND (s2->info.info) == STB_LOCAL)
+	   - (GELF_ST_BIND (s1->info.info) == STB_LOCAL));
+
+  if (cmp == 0)
+    /* binutils always puts section symbols first.  */
+    cmp = ((GELF_ST_TYPE (s2->info.info) == STT_SECTION)
+	   - (GELF_ST_TYPE (s1->info.info) == STT_SECTION));
+
+  if (cmp == 0)
+    {
+      if (GELF_ST_TYPE (s1->info.info) == STT_SECTION)
+	{
+	  /* binutils always puts section symbols in section index order.  */
+	  CMP (shndx);
+	  else if (s1 != s2)
+	    error_exit (0, _("section symbols in unexpected order"));
+	}
+
+      /* Nothing really matters, so preserve the original order.  */
+      CMP (map);
+      else if (s1 != s2)
+	error_exit (0, _("found two identical symbols"));
+    }
+
+  return cmp;
+}
+
+#undef CMP
+
+/* Return true if the flags of the sections match, ignoring the SHF_INFO_LINK
+   flag if the section contains relocation information.  */
+static bool
+sections_flags_match (Elf64_Xword sh_flags1, Elf64_Xword sh_flags2,
+		      Elf64_Word sh_type)
+{
+  if (sh_type == SHT_REL || sh_type == SHT_RELA)
+    {
+      sh_flags1 &= ~SHF_INFO_LINK;
+      sh_flags2 &= ~SHF_INFO_LINK;
+    }
+
+  return sh_flags1 == sh_flags2;
+}
+
+/* Return true iff the flags, size, and name match.  */
+static bool
+sections_match (const struct section *sections, size_t i,
+		const GElf_Shdr *shdr, const char *name)
+{
+  return (sections_flags_match (sections[i].shdr.sh_flags, shdr->sh_flags,
+				sections[i].shdr.sh_type)
+	  && (sections[i].shdr.sh_size == shdr->sh_size
+	      || (sections[i].shdr.sh_size < shdr->sh_size
+		  && section_can_shrink (&sections[i].shdr)))
+	  && !strcmp (sections[i].name, name));
+}
+
+/* Locate a matching allocated section in SECTIONS.  */
+static struct section *
+find_alloc_section (const GElf_Shdr *shdr, GElf_Addr bias, const char *name,
+		    struct section sections[], size_t nalloc)
+{
+  const GElf_Addr addr = shdr->sh_addr + bias;
+  size_t l = 0, u = nalloc;
+  while (l < u)
+    {
+      size_t i = (l + u) / 2;
+      if (addr < sections[i].shdr.sh_addr)
+	u = i;
+      else if (addr > sections[i].shdr.sh_addr)
+	l = i + 1;
+      else
+	{
+	  /* We've found allocated sections with this address.
+	     Find one with matching size, flags, and name.  */
+	  while (i > 0 && sections[i - 1].shdr.sh_addr == addr)
+	    --i;
+	  for (; i < nalloc && sections[i].shdr.sh_addr == addr;
+	       ++i)
+	    if (sections_match (sections, i, shdr, name))
+	      return &sections[i];
+	  break;
+	}
+    }
+  return NULL;
+}
+
+static inline const char *
+get_section_name (size_t ndx, const GElf_Shdr *shdr, const Elf_Data *shstrtab)
+{
+  if (shdr->sh_name >= shstrtab->d_size)
+    error_exit (0, _("cannot read section [%zu] name: %s"),
+		ndx, elf_errmsg (-1));
+  return shstrtab->d_buf + shdr->sh_name;
+}
+
+/* Returns the signature of a group section, or NULL if the given
+   section isn't a group.  */
+static const char *
+get_group_sig (Elf *elf, GElf_Shdr *shdr)
+{
+  if (shdr->sh_type != SHT_GROUP)
+    return NULL;
+
+  Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
+  if (symscn == NULL)
+    error_exit (0, _("bad sh_link for group section: %s"),
+		elf_errmsg (-1));
+
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  if (symshdr == NULL)
+    error_exit (0, _("couldn't get shdr for group section: %s"),
+		elf_errmsg (-1));
+
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  if (symdata == NULL)
+    error_exit (0, _("bad data for group symbol section: %s"),
+		elf_errmsg (-1));
+
+  GElf_Sym sym_mem;
+  GElf_Sym *sym = gelf_getsym (symdata, shdr->sh_info, &sym_mem);
+  if (sym == NULL)
+    error_exit (0, _("couldn't get symbol for group section: %s"),
+		elf_errmsg (-1));
+
+  const char *sig = elf_strptr (elf, symshdr->sh_link, sym->st_name);
+  if (sig == NULL)
+    error_exit (0, _("bad symbol name for group section: %s"),
+		elf_errmsg (-1));
+
+  return sig;
+}
+
+static inline bool
+check_match (bool match, Elf_Scn *scn, const char *name)
+{
+  if (!match)
+    {
+      error (0, 0, _("cannot find matching section for [%zu] '%s'"),
+	     elf_ndxscn (scn), name);
+      return true;
+    }
+
+  return false;
+}
+
+
+/* Fix things up when prelink has moved some allocated sections around
+   and the debuginfo file's section headers no longer match up.
+   This fills in SECTIONS[0..NALLOC-1].outscn or exits.
+   If there was a .bss section that was split into two sections
+   with the new one preceding it in sh_addr, we return that pointer.  */
+static struct section *
+find_alloc_sections_prelink (Elf *debug, Elf_Data *debug_shstrtab,
+			     Elf *main, const GElf_Ehdr *main_ehdr,
+			     Elf_Data *main_shstrtab, GElf_Addr bias,
+			     struct section *sections,
+			     size_t nalloc, size_t nsections)
+{
+  Elf_Scn *undo = NULL;
+  for (size_t i = nalloc; i < nsections; ++i)
+    {
+      const struct section *sec = &sections[i];
+      if (sec->shdr.sh_type == SHT_PROGBITS
+	  && !(sec->shdr.sh_flags & SHF_ALLOC)
+	  && !strcmp (sec->name, ".gnu.prelink_undo"))
+	{
+	  undo = sec->scn;
+	  break;
+	}
+    }
+
+  /* Find the original allocated sections before prelinking.  */
+  struct section *undo_sections = NULL;
+  size_t undo_nalloc = 0;
+  if (undo != NULL)
+    {
+      /* Clear assignments that might have been bogus.  */
+      for (size_t i = 0; i < nalloc; ++i)
+	sections[i].outscn = NULL;
+
+      Elf_Data *undodata = elf_rawdata (undo, NULL);
+      ELF_CHECK (undodata != NULL,
+		 _("cannot read '.gnu.prelink_undo' section: %s"));
+
+      union
+      {
+	Elf32_Ehdr e32;
+	Elf64_Ehdr e64;
+      } ehdr;
+      Elf_Data dst =
+	{
+	  .d_buf = &ehdr,
+	  .d_size = sizeof ehdr,
+	  .d_type = ELF_T_EHDR,
+	  .d_version = EV_CURRENT
+	};
+      Elf_Data src = *undodata;
+      src.d_size = gelf_fsize (main, ELF_T_EHDR, 1, EV_CURRENT);
+      src.d_type = ELF_T_EHDR;
+      ELF_CHECK (gelf_xlatetom (main, &dst, &src,
+				main_ehdr->e_ident[EI_DATA]) != NULL,
+		 _("cannot read '.gnu.prelink_undo' section: %s"));
+
+      uint_fast16_t phnum;
+      uint_fast16_t shnum;  /* prelink doesn't handle > SHN_LORESERVE.  */
+      if (ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32)
+	{
+	  phnum = ehdr.e32.e_phnum;
+	  shnum = ehdr.e32.e_shnum;
+	}
+      else
+	{
+	  phnum = ehdr.e64.e_phnum;
+	  shnum = ehdr.e64.e_shnum;
+	}
+
+      bool class32 = ehdr.e32.e_ident[EI_CLASS] == ELFCLASS32;
+      size_t shsize = class32 ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr);
+      if (unlikely (shnum == 0 || shnum > SIZE_MAX / shsize + 1))
+	error_exit (0, _("overflow with shnum = %zu in '%s' section"),
+		    (size_t) shnum, ".gnu.prelink_undo");
+
+      --shnum;
+
+      size_t phsize = gelf_fsize (main, ELF_T_PHDR, phnum, EV_CURRENT);
+      src.d_buf += src.d_size + phsize;
+      src.d_size = gelf_fsize (main, ELF_T_SHDR, shnum, EV_CURRENT);
+      src.d_type = ELF_T_SHDR;
+      if ((size_t) (src.d_buf - undodata->d_buf) > undodata->d_size
+	  || undodata->d_size - (src.d_buf - undodata->d_buf) != src.d_size)
+	error_exit (0, _("invalid contents in '%s' section"),
+		    ".gnu.prelink_undo");
+
+      const size_t shdr_bytes = shnum * shsize;
+      void *shdr = xmalloc (shdr_bytes);
+      dst.d_buf = shdr;
+      dst.d_size = shdr_bytes;
+      ELF_CHECK (gelf_xlatetom (main, &dst, &src,
+				main_ehdr->e_ident[EI_DATA]) != NULL,
+		 _("cannot read '.gnu.prelink_undo' section: %s"));
+
+      undo_sections = xmalloc (shnum * sizeof undo_sections[0]);
+      for (size_t i = 0; i < shnum; ++i)
+	{
+	  struct section *sec = &undo_sections[undo_nalloc];
+	  Elf32_Shdr (*s32)[shnum] = shdr;
+	  Elf64_Shdr (*s64)[shnum] = shdr;
+	  if (class32)
+	    {
+#define COPY(field) sec->shdr.field = (*s32)[i].field
+	      COPY (sh_name);
+	      COPY (sh_type);
+	      COPY (sh_flags);
+	      COPY (sh_addr);
+	      COPY (sh_offset);
+	      COPY (sh_size);
+	      COPY (sh_link);
+	      COPY (sh_info);
+	      COPY (sh_addralign);
+	      COPY (sh_entsize);
+#undef	COPY
+	    }
+	  else
+	    sec->shdr = (*s64)[i];
+	  if (sec->shdr.sh_flags & SHF_ALLOC)
+	    {
+	      sec->shdr.sh_addr += bias;
+	      sec->name = get_section_name (i + 1, &sec->shdr, main_shstrtab);
+	      sec->scn = elf_getscn (main, i + 1); /* Really just for ndx.  */
+	      sec->outscn = NULL;
+	      sec->strent = NULL;
+	      sec->sig = get_group_sig (main, &sec->shdr);
+	      ++undo_nalloc;
+	    }
+	}
+      qsort (undo_sections, undo_nalloc,
+	     sizeof undo_sections[0], compare_sections_nonrel);
+      free (shdr);
+    }
+
+  bool fail = false;
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (debug, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+      if (!(shdr->sh_flags & SHF_ALLOC))
+	continue;
+
+      const char *name = get_section_name (elf_ndxscn (scn), shdr,
+					   debug_shstrtab);
+
+      if (undo_sections != NULL)
+	{
+	  struct section *sec = find_alloc_section (shdr, 0, name,
+						    undo_sections,
+						    undo_nalloc);
+	  if (sec != NULL)
+	    {
+	      sec->outscn = scn;
+	      continue;
+	    }
+	}
+
+      /* If there is no prelink info, we are just here to find
+	 the sections to give error messages about.  */
+      for (size_t i = 0; shdr != NULL && i < nalloc; ++i)
+	if (sections[i].outscn == scn)
+	  shdr = NULL;
+      fail |= check_match (shdr == NULL, scn, name);
+    }
+
+  if (fail)
+    exit (EXIT_FAILURE);
+
+  /* Now we have lined up output sections for each of the original sections
+     before prelinking.  Translate those to the prelinked sections.
+     This matches what prelink's undo_sections does.  */
+  struct section *split_bss = NULL;
+  for (size_t i = 0; i < undo_nalloc; ++i)
+    {
+      const struct section *undo_sec = &undo_sections[i];
+
+      const char *name = undo_sec->name;
+      scn = undo_sec->scn; /* This is just for elf_ndxscn.  */
+
+      for (size_t j = 0; j < nalloc; ++j)
+	{
+	  struct section *sec = &sections[j];
+#define RELA_SCALED(field) \
+	  (2 * sec->shdr.field == 3 * undo_sec->shdr.field)
+	  if (sec->outscn == NULL
+	      && sec->shdr.sh_name == undo_sec->shdr.sh_name
+	      && sec->shdr.sh_flags == undo_sec->shdr.sh_flags
+	      && sec->shdr.sh_addralign == undo_sec->shdr.sh_addralign
+	      && (((sec->shdr.sh_type == undo_sec->shdr.sh_type
+		    && sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
+		    && (sec->shdr.sh_size == undo_sec->shdr.sh_size
+			|| (sec->shdr.sh_size > undo_sec->shdr.sh_size
+			    && main_ehdr->e_type == ET_EXEC
+			    && !strcmp (sec->name, ".dynstr"))))
+		   || (sec->shdr.sh_size == undo_sec->shdr.sh_size
+		       && ((sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
+			    && undo_sec->shdr.sh_type == SHT_NOBITS)
+			   || undo_sec->shdr.sh_type == SHT_PROGBITS)
+		       && !strcmp (sec->name, ".plt")))
+		  || (sec->shdr.sh_type == SHT_RELA
+		      && undo_sec->shdr.sh_type == SHT_REL
+		      && RELA_SCALED (sh_entsize) && RELA_SCALED (sh_size))
+		  || (sec->shdr.sh_entsize == undo_sec->shdr.sh_entsize
+		      && (sec->shdr.sh_type == undo_sec->shdr.sh_type
+			  || (sec->shdr.sh_type == SHT_PROGBITS
+			      && undo_sec->shdr.sh_type == SHT_NOBITS))
+		      && sec->shdr.sh_size <= undo_sec->shdr.sh_size
+		      && (!strcmp (sec->name, ".bss")
+			  || !strcmp (sec->name, ".sbss"))
+		      && (sec->shdr.sh_size == undo_sec->shdr.sh_size
+			  || (split_bss = sec) > sections))))
+	    {
+	      sec->outscn = undo_sec->outscn;
+	      undo_sec = NULL;
+	      break;
+	    }
+	}
+
+      fail |= check_match (undo_sec == NULL, scn, name);
+    }
+
+  free (undo_sections);
+
+  if (fail)
+    exit (EXIT_FAILURE);
+
+  return split_bss;
+}
+
+/* Create new .shstrtab contents, subroutine of copy_elided_sections.
+   This can't be open coded there and still use variable-length auto arrays,
+   since the end of our block would free other VLAs too.  */
+static Elf_Data *
+new_shstrtab (Elf *unstripped, size_t unstripped_shnum,
+	      Elf_Data *shstrtab, size_t unstripped_shstrndx,
+	      struct section *sections, size_t stripped_shnum,
+	      Dwelf_Strtab *strtab)
+{
+  if (strtab == NULL)
+    return NULL;
+
+  Dwelf_Strent *unstripped_strent[unstripped_shnum];
+  memset (unstripped_strent, 0, sizeof unstripped_strent);
+  for (struct section *sec = sections;
+       sec < &sections[stripped_shnum - 1];
+       ++sec)
+    if (sec->outscn != NULL)
+      {
+	if (sec->strent == NULL)
+	  {
+	    sec->strent = dwelf_strtab_add (strtab, sec->name);
+	    ELF_CHECK (sec->strent != NULL,
+		       _("cannot add section name to string table: %s"));
+	  }
+	unstripped_strent[elf_ndxscn (sec->outscn) - 1] = sec->strent;
+      }
+
+  /* Add names of sections we aren't touching.  */
+  for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+    if (unstripped_strent[i] == NULL)
+      {
+	Elf_Scn *scn = elf_getscn (unstripped, i + 1);
+	GElf_Shdr shdr_mem;
+	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+	const char *name = get_section_name (i + 1, shdr, shstrtab);
+	unstripped_strent[i] = dwelf_strtab_add (strtab, name);
+	ELF_CHECK (unstripped_strent[i] != NULL,
+		   _("cannot add section name to string table: %s"));
+      }
+    else
+      unstripped_strent[i] = NULL;
+
+  /* Now finalize the string table so we can get offsets.  */
+  Elf_Data *strtab_data = elf_getdata (elf_getscn (unstripped,
+						   unstripped_shstrndx), NULL);
+  ELF_CHECK (elf_flagdata (strtab_data, ELF_C_SET, ELF_F_DIRTY),
+	     _("cannot update section header string table data: %s"));
+  if (dwelf_strtab_finalize (strtab, strtab_data) == NULL)
+    error_exit (0, "Not enough memory to create string table");
+
+  /* Update the sh_name fields of sections we aren't modifying later.  */
+  for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+    if (unstripped_strent[i] != NULL)
+      {
+	Elf_Scn *scn = elf_getscn (unstripped, i + 1);
+	GElf_Shdr shdr_mem;
+	GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+	shdr->sh_name = dwelf_strent_off (unstripped_strent[i]);
+	if (i + 1 == unstripped_shstrndx)
+	  shdr->sh_size = strtab_data->d_size;
+	update_shdr (scn, shdr);
+      }
+
+  return strtab_data;
+}
+
+/* Fill in any SHT_NOBITS sections in UNSTRIPPED by
+   copying their contents and sh_type from STRIPPED.  */
+static void
+copy_elided_sections (Elf *unstripped, Elf *stripped,
+		      const GElf_Ehdr *stripped_ehdr, GElf_Addr bias)
+{
+  size_t unstripped_shstrndx;
+  ELF_CHECK (elf_getshdrstrndx (unstripped, &unstripped_shstrndx) == 0,
+	     _("cannot get section header string table section index: %s"));
+
+  size_t stripped_shstrndx;
+  ELF_CHECK (elf_getshdrstrndx (stripped, &stripped_shstrndx) == 0,
+	     _("cannot get section header string table section index: %s"));
+
+  size_t unstripped_shnum;
+  ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
+	     _("cannot get section count: %s"));
+
+  size_t stripped_shnum;
+  ELF_CHECK (elf_getshdrnum (stripped, &stripped_shnum) == 0,
+	     _("cannot get section count: %s"));
+
+  if (unlikely (stripped_shnum > unstripped_shnum))
+    error_exit (0, _("\
+more sections in stripped file than debug file -- arguments reversed?"));
+
+  if (unlikely (stripped_shnum == 0))
+    error_exit (0, _("no sections in stripped file"));
+
+  /* Used as sanity check for allocated section offset, if the section
+     offset needs to be preserved.  We want to know the max size of the
+     ELF file, to check if any existing section offsets are OK.  */
+  int64_t max_off = -1;
+  if (stripped_ehdr->e_type != ET_REL)
+    {
+      elf_flagelf (stripped, ELF_C_SET, ELF_F_LAYOUT);
+      max_off = elf_update (stripped, ELF_C_NULL);
+    }
+
+  /* Cache the stripped file's section details.  */
+  struct section sections[stripped_shnum - 1];
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (stripped, scn)) != NULL)
+    {
+      size_t i = elf_ndxscn (scn) - 1;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &sections[i].shdr);
+      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+      sections[i].name = elf_strptr (stripped, stripped_shstrndx,
+				     shdr->sh_name);
+      if (sections[i].name == NULL)
+	error_exit (0, _("cannot read section [%zu] name: %s"),
+		    elf_ndxscn (scn), elf_errmsg (-1));
+      sections[i].scn = scn;
+      sections[i].outscn = NULL;
+      sections[i].strent = NULL;
+      sections[i].sig = get_group_sig (stripped, shdr);
+    }
+
+  const struct section *stripped_symtab = NULL;
+
+  /* Sort the sections, allocated by address and others after.  */
+  qsort (sections, stripped_shnum - 1, sizeof sections[0],
+	 stripped_ehdr->e_type == ET_REL
+	 ? compare_sections_rel : compare_sections_nonrel);
+  size_t nalloc = stripped_shnum - 1;
+  while (nalloc > 0 && !(sections[nalloc - 1].shdr.sh_flags & SHF_ALLOC))
+    {
+      --nalloc;
+      if (sections[nalloc].shdr.sh_type == SHT_SYMTAB)
+	stripped_symtab = &sections[nalloc];
+    }
+
+  Elf_Data *shstrtab = elf_getdata (elf_getscn (unstripped,
+						unstripped_shstrndx), NULL);
+  ELF_CHECK (shstrtab != NULL,
+	     _("cannot read section header string table: %s"));
+
+  /* Match each debuginfo section with its corresponding stripped section.  */
+  bool check_prelink = false;
+  Elf_Scn *unstripped_symtab = NULL;
+  size_t unstripped_strndx = 0;
+  size_t alloc_avail = 0;
+  scn = NULL;
+  while ((scn = elf_nextscn (unstripped, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+      if (shdr->sh_type == SHT_SYMTAB)
+	{
+	  unstripped_symtab = scn;
+	  unstripped_strndx = shdr->sh_link;
+	  continue;
+	}
+
+      const size_t ndx = elf_ndxscn (scn);
+      if (ndx == unstripped_shstrndx || ndx == unstripped_strndx)
+	continue;
+
+      const char *name = get_section_name (ndx, shdr, shstrtab);
+
+      struct section *sec = NULL;
+      if (shdr->sh_flags & SHF_ALLOC)
+	{
+	  if (stripped_ehdr->e_type != ET_REL)
+	    {
+	      /* Look for the section that matches.  */
+	      sec = find_alloc_section (shdr, bias, name, sections, nalloc);
+	      if (sec == NULL)
+		{
+		  /* We couldn't figure it out.  It may be a prelink issue.  */
+		  check_prelink = true;
+		  continue;
+		}
+	    }
+	  else
+	    {
+	      /* The sh_addr of allocated sections does not help us,
+		 but the order usually matches.  */
+	      if (likely (sections_match (sections, alloc_avail, shdr, name)))
+		sec = &sections[alloc_avail++];
+	      else
+		for (size_t i = alloc_avail + 1; i < nalloc; ++i)
+		  if (sections_match (sections, i, shdr, name))
+		    {
+		      sec = &sections[i];
+		      break;
+		    }
+	    }
+	}
+      else
+	{
+	  /* Locate a matching unallocated section in SECTIONS.  */
+	  const char *sig = get_group_sig (unstripped, shdr);
+	  size_t l = nalloc, u = stripped_shnum - 1;
+	  while (l < u)
+	    {
+	      size_t i = (l + u) / 2;
+	      struct section *section = &sections[i];
+	      int cmp = compare_unalloc_sections (shdr, &section->shdr,
+						  name, section->name,
+						  sig, section->sig);
+	      if (cmp < 0)
+		u = i;
+	      else if (cmp > 0)
+		l = i + 1;
+	      else
+		{
+		  sec = section;
+		  break;
+		}
+	    }
+
+	  if (sec == NULL)
+	    {
+	      /* An additional unallocated section is fine if not SHT_NOBITS.
+		 We looked it up anyway in case it's an unallocated section
+		 copied in both files (e.g. SHT_NOTE), and don't keep both.  */
+	      if (shdr->sh_type != SHT_NOBITS)
+		continue;
+
+	      /* Somehow some old .debug files wound up with SHT_NOBITS
+		 .comment sections, so let those pass.  */
+	      if (!strcmp (name, ".comment"))
+		continue;
+	    }
+	}
+
+      if (sec == NULL)
+	error_exit (0, _("cannot find matching section for [%zu] '%s'"),
+		    elf_ndxscn (scn), name);
+
+      sec->outscn = scn;
+    }
+
+  /* If that failed due to changes made by prelink, we take another tack.
+     We keep track of a .bss section that was partly split into .dynbss
+     so that collect_symbols can update symbols' st_shndx fields.  */
+  struct section *split_bss = NULL;
+  if (check_prelink)
+    {
+      Elf_Data *data = elf_getdata (elf_getscn (stripped, stripped_shstrndx),
+				    NULL);
+      ELF_CHECK (data != NULL,
+		 _("cannot read section header string table: %s"));
+      split_bss = find_alloc_sections_prelink (unstripped, shstrtab,
+					       stripped, stripped_ehdr,
+					       data, bias, sections,
+					       nalloc, stripped_shnum - 1);
+    }
+
+  /* Make sure each main file section has a place to go.  */
+  const struct section *stripped_dynsym = NULL;
+  size_t debuglink = SHN_UNDEF;
+  size_t ndx_sec_num = stripped_shnum - 1;
+  size_t ndx_section[ndx_sec_num];
+  Dwelf_Strtab *strtab = NULL;
+  for (struct section *sec = sections;
+       sec < &sections[ndx_sec_num];
+       ++sec)
+    {
+      size_t secndx = elf_ndxscn (sec->scn);
+
+      if (sec->outscn == NULL)
+	{
+	  /* We didn't find any corresponding section for this.  */
+
+	  if (secndx == stripped_shstrndx)
+	    {
+	      /* We only need one .shstrtab.  */
+	      ndx_section[secndx - 1] = unstripped_shstrndx;
+	      continue;
+	    }
+
+	  if (unstripped_symtab != NULL && sec == stripped_symtab)
+	    {
+	      /* We don't need a second symbol table.  */
+	      ndx_section[secndx - 1] = elf_ndxscn (unstripped_symtab);
+	      continue;
+	    }
+
+	  if (unstripped_symtab != NULL && stripped_symtab != NULL
+	      && secndx == stripped_symtab->shdr.sh_link
+	      && unstripped_strndx != 0)
+	    {
+	      /* ... nor its string table.  */
+	      ndx_section[secndx - 1] = unstripped_strndx;
+	      continue;
+	    }
+
+	  if (!(sec->shdr.sh_flags & SHF_ALLOC)
+	      && !strcmp (sec->name, ".gnu_debuglink"))
+	    {
+	      /* This was created by stripping.  We don't want it.  */
+	      debuglink = secndx;
+	      ndx_section[secndx - 1] = SHN_UNDEF;
+	      continue;
+	    }
+
+	  sec->outscn = elf_newscn (unstripped);
+	  Elf_Data *newdata = elf_newdata (sec->outscn);
+	  ELF_CHECK (newdata != NULL && gelf_update_shdr (sec->outscn,
+							  &sec->shdr),
+		     _("cannot add new section: %s"));
+
+	  if (strtab == NULL)
+	    strtab = dwelf_strtab_init (true);
+	  sec->strent = dwelf_strtab_add (strtab, sec->name);
+	  ELF_CHECK (sec->strent != NULL,
+		     _("cannot add section name to string table: %s"));
+	}
+
+      /* Cache the mapping of original section indices to output sections.  */
+      ndx_section[secndx - 1] = elf_ndxscn (sec->outscn);
+    }
+
+  /* We added some sections, so we need a new shstrtab.  */
+  Elf_Data *strtab_data = new_shstrtab (unstripped, unstripped_shnum,
+					shstrtab, unstripped_shstrndx,
+					sections, stripped_shnum,
+					strtab);
+
+  /* Get the updated section count.  */
+  ELF_CHECK (elf_getshdrnum (unstripped, &unstripped_shnum) == 0,
+	     _("cannot get section count: %s"));
+
+  bool placed[unstripped_shnum - 1];
+  memset (placed, 0, sizeof placed);
+
+  /* Now update the output sections and copy in their data.  */
+  GElf_Off offset = 0;
+  for (const struct section *sec = sections;
+       sec < &sections[stripped_shnum - 1];
+       ++sec)
+    if (sec->outscn != NULL)
+      {
+	GElf_Shdr shdr_mem;
+	GElf_Shdr *shdr = gelf_getshdr (sec->outscn, &shdr_mem);
+	ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+	/* In an ET_REL file under --relocate, the sh_addr of SHF_ALLOC
+	   sections will have been set nonzero by relocation.  This
+	   touched the shdrs of whichever file had the symtab.  sh_addr
+	   is still zero in the corresponding shdr.  The relocated
+	   address is what we want to use.  */
+	if (stripped_ehdr->e_type != ET_REL
+	    || !(shdr_mem.sh_flags & SHF_ALLOC)
+	    || shdr_mem.sh_addr == 0)
+	  shdr_mem.sh_addr = sec->shdr.sh_addr;
+
+	shdr_mem.sh_type = sec->shdr.sh_type;
+	shdr_mem.sh_size = sec->shdr.sh_size;
+	shdr_mem.sh_info = sec->shdr.sh_info;
+	shdr_mem.sh_link = sec->shdr.sh_link;
+
+	/* Buggy binutils objdump might have stripped the SHF_INFO_LINK
+	   put it back if necessary.  */
+	if ((sec->shdr.sh_type == SHT_REL || sec->shdr.sh_type == SHT_RELA)
+	    && sec->shdr.sh_flags != shdr_mem.sh_flags
+	    && (sec->shdr.sh_flags & SHF_INFO_LINK) != 0)
+	  shdr_mem.sh_flags |= SHF_INFO_LINK;
+
+	if (sec->shdr.sh_link != SHN_UNDEF)
+	  {
+	    if (sec->shdr.sh_link > ndx_sec_num)
+	      error_exit (0,
+			  "section [%zd] has invalid sh_link %" PRId32,
+			  elf_ndxscn (sec->scn), sec->shdr.sh_link);
+	    shdr_mem.sh_link = ndx_section[sec->shdr.sh_link - 1];
+	  }
+	if (SH_INFO_LINK_P (&sec->shdr) && sec->shdr.sh_info != 0)
+	  {
+	    if (sec->shdr.sh_info > ndx_sec_num)
+	      error_exit (0,
+			  "section [%zd] has invalid sh_info %" PRId32,
+			  elf_ndxscn (sec->scn), sec->shdr.sh_info);
+	    shdr_mem.sh_info = ndx_section[sec->shdr.sh_info - 1];
+	  }
+
+	if (strtab != NULL)
+	  shdr_mem.sh_name = dwelf_strent_off (sec->strent);
+
+	Elf_Data *indata = elf_getdata (sec->scn, NULL);
+	ELF_CHECK (indata != NULL, _("cannot get section data: %s"));
+	Elf_Data *outdata = elf_getdata (sec->outscn, NULL);
+	ELF_CHECK (outdata != NULL, _("cannot copy section data: %s"));
+	*outdata = *indata;
+	elf_flagdata (outdata, ELF_C_SET, ELF_F_DIRTY);
+
+	/* Preserve the file layout of the allocated sections.  */
+	if (stripped_ehdr->e_type != ET_REL && (shdr_mem.sh_flags & SHF_ALLOC))
+	  {
+	    if (max_off > 0 && sec->shdr.sh_offset > (Elf64_Off) max_off)
+		error_exit (0,
+			    "allocated section offset too large [%zd] %" PRIx64,
+			    elf_ndxscn (sec->scn), sec->shdr.sh_offset);
+
+	    shdr_mem.sh_offset = sec->shdr.sh_offset;
+	    placed[elf_ndxscn (sec->outscn) - 1] = true;
+
+	    const GElf_Off end_offset = (shdr_mem.sh_offset
+					 + (shdr_mem.sh_type == SHT_NOBITS
+					    ? 0 : shdr_mem.sh_size));
+	    if (end_offset > offset)
+	      offset = end_offset;
+	  }
+
+	update_shdr (sec->outscn, &shdr_mem);
+
+	if (shdr_mem.sh_type == SHT_SYMTAB || shdr_mem.sh_type == SHT_DYNSYM)
+	  {
+	    /* We must adjust all the section indices in the symbol table.  */
+
+	    Elf_Data *shndxdata = NULL;	/* XXX */
+
+	    if (shdr_mem.sh_entsize == 0)
+	      error_exit (0,
+			  "SYMTAB section cannot have zero sh_entsize");
+	    for (size_t i = 1; i < shdr_mem.sh_size / shdr_mem.sh_entsize; ++i)
+	      {
+		GElf_Sym sym_mem;
+		GElf_Word shndx = SHN_UNDEF;
+		GElf_Sym *sym = gelf_getsymshndx (outdata, shndxdata,
+						  i, &sym_mem, &shndx);
+		ELF_CHECK (sym != NULL,
+			   _("cannot get symbol table entry: %s"));
+		if (sym->st_shndx != SHN_XINDEX)
+		  shndx = sym->st_shndx;
+
+		if (shndx != SHN_UNDEF && shndx < SHN_LORESERVE)
+		  {
+		    if (shndx >= stripped_shnum)
+		      error_exit (0,
+				  _("symbol [%zu] has invalid section index"), i);
+
+		    shndx = ndx_section[shndx - 1];
+		    if (shndx < SHN_LORESERVE)
+		      {
+			sym->st_shndx = shndx;
+			shndx = SHN_UNDEF;
+		      }
+		    else
+		      sym->st_shndx = SHN_XINDEX;
+
+		    ELF_CHECK (gelf_update_symshndx (outdata, shndxdata,
+						     i, sym, shndx),
+			       _("cannot update symbol table: %s"));
+		  }
+	      }
+
+	    if (shdr_mem.sh_type == SHT_SYMTAB)
+	      stripped_symtab = sec;
+	    if (shdr_mem.sh_type == SHT_DYNSYM)
+	      stripped_dynsym = sec;
+	  }
+
+	if (shdr_mem.sh_type == SHT_GROUP)
+	  {
+	    /* We must adjust all the section indices in the group.
+	       Skip the first word, which is the section group flag.
+	       Everything else is a section index.  */
+	    Elf32_Word *shndx = (Elf32_Word *) outdata->d_buf;
+	    for (size_t i = 1; i < shdr_mem.sh_size / sizeof (Elf32_Word); ++i)
+	      if (shndx[i]  == SHN_UNDEF || shndx[i] >= stripped_shnum)
+		error_exit (0,
+			    _("group has invalid section index [%zd]"), i);
+	      else
+		shndx[i] = ndx_section[shndx[i] - 1];
+	  }
+      }
+
+  /* We may need to update the symbol table.  */
+  Elf_Data *symdata = NULL;
+  Dwelf_Strtab *symstrtab = NULL;
+  Elf_Data *symstrdata = NULL;
+  if (unstripped_symtab != NULL && (stripped_symtab != NULL
+				    || check_prelink /* Section adjustments. */
+				    || (stripped_ehdr->e_type != ET_REL
+					&& bias != 0)))
+    {
+      /* Merge the stripped file's symbol table into the unstripped one.  */
+      const size_t stripped_nsym = (stripped_symtab == NULL ? 1
+				    : (stripped_symtab->shdr.sh_size
+				       / (stripped_symtab->shdr.sh_entsize == 0
+					  ? 1
+					  : stripped_symtab->shdr.sh_entsize)));
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
+      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+      if (shdr->sh_entsize == 0)
+	error_exit (0,
+		    "unstripped SYMTAB section cannot have zero sh_entsize");
+      const size_t unstripped_nsym = shdr->sh_size / shdr->sh_entsize;
+
+      /* First collect all the symbols from both tables.  */
+
+      const size_t total_syms = stripped_nsym - 1 + unstripped_nsym - 1;
+      struct symbol *symbols = xmalloc (total_syms * sizeof (struct symbol));
+      size_t *symndx_map = xmalloc (total_syms * sizeof (size_t));
+
+      if (stripped_symtab != NULL)
+	collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
+			 stripped_symtab->scn,
+			 elf_getscn (stripped, stripped_symtab->shdr.sh_link),
+			 stripped_nsym, 0, ndx_section,
+			 symbols, symndx_map, NULL);
+
+      Elf_Scn *unstripped_strtab = elf_getscn (unstripped, shdr->sh_link);
+      collect_symbols (unstripped, stripped_ehdr->e_type == ET_REL,
+		       unstripped_symtab, unstripped_strtab, unstripped_nsym,
+		       stripped_ehdr->e_type == ET_REL ? 0 : bias, NULL,
+		       &symbols[stripped_nsym - 1],
+		       &symndx_map[stripped_nsym - 1], split_bss);
+
+      /* Next, sort our array of all symbols.  */
+      qsort (symbols, total_syms, sizeof symbols[0], compare_symbols);
+
+      /* Now we can weed out the duplicates.  Assign remaining symbols
+	 new slots, collecting a map from old indices to new.  */
+      size_t nsym = 0;
+      for (struct symbol *s = symbols; s < &symbols[total_syms]; ++s)
+	{
+	  /* Skip a section symbol for a removed section.  */
+	  if (s->shndx == SHN_UNDEF
+	      && GELF_ST_TYPE (s->info.info) == STT_SECTION)
+	    {
+	      s->name = NULL;	/* Mark as discarded. */
+	      *s->map = STN_UNDEF;
+	      s->duplicate = NULL;
+	      continue;
+	    }
+
+	  struct symbol *n = s;
+	  while (n + 1 < &symbols[total_syms]
+		 && !compare_symbols_duplicate (s, n + 1))
+	    ++n;
+
+	  while (s < n)
+	    {
+	      /* This is a duplicate.  Its twin will get the next slot.  */
+	      s->name = NULL;	/* Mark as discarded. */
+	      s->duplicate = n->map;
+	      ++s;
+	    }
+
+	  /* Allocate the next slot.  */
+	  *s->map = ++nsym;
+	}
+
+      /* Now we sort again, to determine the order in the output.  */
+      qsort (symbols, total_syms, sizeof symbols[0], compare_symbols_output);
+
+      if (nsym < total_syms)
+	/* The discarded symbols are now at the end of the table.  */
+	assert (symbols[nsym].name == NULL);
+
+      /* Now a final pass updates the map with the final order,
+	 and builds up the new string table.  */
+      symstrtab = dwelf_strtab_init (true);
+      for (size_t i = 0; i < nsym; ++i)
+	{
+	  assert (symbols[i].name != NULL);
+	  assert (*symbols[i].map != 0);
+	  *symbols[i].map = 1 + i;
+	  symbols[i].strent = dwelf_strtab_add (symstrtab, symbols[i].name);
+	}
+
+      /* Scan the discarded symbols too, just to update their slots
+	 in SYMNDX_MAP to refer to their live duplicates.  */
+      for (size_t i = nsym; i < total_syms; ++i)
+	{
+	  assert (symbols[i].name == NULL);
+	  if (symbols[i].duplicate == NULL)
+	    assert (*symbols[i].map == STN_UNDEF);
+	  else
+	    {
+	      assert (*symbols[i].duplicate != STN_UNDEF);
+	      *symbols[i].map = *symbols[i].duplicate;
+	    }
+	}
+
+      /* Now we are ready to write the new symbol table.  */
+      symdata = elf_getdata (unstripped_symtab, NULL);
+      symstrdata = elf_getdata (unstripped_strtab, NULL);
+      Elf_Data *shndxdata = NULL;	/* XXX */
+
+      /* If symtab and the section header table share the string table
+	 add the section names to the strtab and then (after finalizing)
+	 fixup the section header sh_names.  Also dispose of the old data.  */
+      Dwelf_Strent *unstripped_strent[unstripped_shnum - 1];
+      if (unstripped_shstrndx == elf_ndxscn (unstripped_strtab))
+	{
+	  for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+	    {
+	      Elf_Scn *sec = elf_getscn (unstripped, i + 1);
+	      GElf_Shdr mem;
+	      GElf_Shdr *hdr = gelf_getshdr (sec, &mem);
+	      const char *name = get_section_name (i + 1, hdr, shstrtab);
+	      unstripped_strent[i] = dwelf_strtab_add (symstrtab, name);
+	      ELF_CHECK (unstripped_strent[i] != NULL,
+			 _("cannot add section name to string table: %s"));
+	    }
+
+	  if (strtab != NULL)
+	    {
+	      dwelf_strtab_free (strtab);
+	      free (strtab_data->d_buf);
+	      strtab = NULL;
+	    }
+	}
+
+      if (dwelf_strtab_finalize (symstrtab, symstrdata) == NULL)
+	error_exit (0, "Not enough memory to create symbol table");
+
+      elf_flagdata (symstrdata, ELF_C_SET, ELF_F_DIRTY);
+
+      /* And update the section header names if necessary.  */
+      if (unstripped_shstrndx == elf_ndxscn (unstripped_strtab))
+	{
+	  for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+	    {
+	      Elf_Scn *sec = elf_getscn (unstripped, i + 1);
+	      GElf_Shdr mem;
+	      GElf_Shdr *hdr = gelf_getshdr (sec, &mem);
+	      shdr->sh_name = dwelf_strent_off (unstripped_strent[i]);
+	      update_shdr (sec, hdr);
+	    }
+	}
+
+      /* Now update the symtab shdr.  Reload symtab shdr because sh_name
+	 might have changed above. */
+      shdr = gelf_getshdr (unstripped_symtab, &shdr_mem);
+      ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+      shdr->sh_size = symdata->d_size = (1 + nsym) * shdr->sh_entsize;
+      symdata->d_buf = xmalloc (symdata->d_size);
+      record_new_data (symdata->d_buf);
+
+      GElf_Sym sym;
+      memset (&sym, 0, sizeof sym);
+      ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 0, &sym, SHN_UNDEF),
+		 _("cannot update symbol table: %s"));
+
+      shdr->sh_info = 1;
+      for (size_t i = 0; i < nsym; ++i)
+	{
+	  struct symbol *s = &symbols[i];
+
+	  /* Fill in the symbol details.  */
+	  sym.st_name = dwelf_strent_off (s->strent);
+	  sym.st_value = s->value; /* Already biased to output address.  */
+	  sym.st_size = s->size;
+	  sym.st_shndx = s->shndx; /* Already mapped to output index.  */
+	  sym.st_info = s->info.info;
+	  sym.st_other = s->info.other;
+
+	  /* Keep track of the number of leading local symbols.  */
+	  if (GELF_ST_BIND (sym.st_info) == STB_LOCAL)
+	    {
+	      assert (shdr->sh_info == 1 + i);
+	      shdr->sh_info = 1 + i + 1;
+	    }
+
+	  ELF_CHECK (gelf_update_symshndx (symdata, shndxdata, 1 + i,
+					   &sym, SHN_UNDEF),
+		     _("cannot update symbol table: %s"));
+
+	}
+      elf_flagdata (symdata, ELF_C_SET, ELF_F_DIRTY);
+      update_shdr (unstripped_symtab, shdr);
+
+      /* Track which sections are adjusted during the first round
+	 of calls to adjust_relocs.  */
+      bool scn_adjusted[unstripped_shnum];
+      memset (scn_adjusted, 0, sizeof scn_adjusted);
+
+      if (stripped_symtab != NULL)
+	{
+	  /* Adjust any relocations referring to the old symbol table.  */
+	  const size_t old_sh_link = elf_ndxscn (stripped_symtab->scn);
+	  for (const struct section *sec = sections;
+	       sec < &sections[stripped_shnum - 1];
+	       ++sec)
+	    if (sec->outscn != NULL && sec->shdr.sh_link == old_sh_link)
+	      {
+		adjust_relocs (sec->outscn, sec->scn, &sec->shdr,
+			       symndx_map, total_syms, shdr);
+		scn_adjusted[elf_ndxscn (sec->outscn)] = true;
+	      }
+	}
+
+      /* Also adjust references to the other old symbol table.  */
+      adjust_all_relocs (unstripped, unstripped_symtab, shdr,
+			 &symndx_map[stripped_nsym - 1],
+			 total_syms - (stripped_nsym - 1),
+			 scn_adjusted);
+
+      free (symbols);
+      free (symndx_map);
+    }
+  else if (stripped_symtab != NULL && stripped_shnum != unstripped_shnum)
+    check_symtab_section_symbols (unstripped,
+				  stripped_ehdr->e_type == ET_REL,
+				  stripped_symtab->scn,
+				  unstripped_shnum, unstripped_shstrndx,
+				  stripped_symtab->outscn,
+				  stripped_shnum, stripped_shstrndx,
+				  debuglink);
+
+  if (stripped_dynsym != NULL)
+    (void) check_symtab_section_symbols (unstripped,
+					 stripped_ehdr->e_type == ET_REL,
+					 stripped_dynsym->outscn,
+					 unstripped_shnum,
+					 unstripped_shstrndx,
+					 stripped_dynsym->scn, stripped_shnum,
+					 stripped_shstrndx, debuglink);
+
+  /* We need to preserve the layout of the stripped file so the
+     phdrs will match up.  This requires us to do our own layout of
+     the added sections.  We do manual layout even for ET_REL just
+     so we can try to match what the original probably had.  */
+
+  elf_flagelf (unstripped, ELF_C_SET, ELF_F_LAYOUT);
+
+  if (offset == 0)
+    /* For ET_REL we are starting the layout from scratch.  */
+    offset = gelf_fsize (unstripped, ELF_T_EHDR, 1, EV_CURRENT);
+
+  bool skip_reloc = false;
+  do
+    {
+      skip_reloc = !skip_reloc;
+      for (size_t i = 0; i < unstripped_shnum - 1; ++i)
+	if (!placed[i])
+	  {
+	    scn = elf_getscn (unstripped, 1 + i);
+
+	    GElf_Shdr shdr_mem;
+	    GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	    ELF_CHECK (shdr != NULL, _("cannot get section header: %s"));
+
+	    /* We must make sure we have read in the data of all sections
+	       beforehand and marked them to be written out.  When we're
+	       modifying the existing file in place, we might overwrite
+	       this part of the file before we get to handling the section.  */
+
+	    ELF_CHECK (elf_flagdata (elf_getdata (scn, NULL),
+				     ELF_C_SET, ELF_F_DIRTY),
+		       _("cannot read section data: %s"));
+
+	    if (skip_reloc
+		&& (shdr->sh_type == SHT_REL || shdr->sh_type == SHT_RELA))
+	      continue;
+
+	    GElf_Off align = shdr->sh_addralign ?: 1;
+	    offset = (offset + align - 1) & -align;
+	    shdr->sh_offset = offset;
+	    if (shdr->sh_type != SHT_NOBITS)
+	      offset += shdr->sh_size;
+
+	    update_shdr (scn, shdr);
+
+	    if (unstripped_shstrndx == 1 + i)
+	      {
+		/* Place the section headers immediately after
+		   .shstrtab, and update the ELF header.  */
+
+		GElf_Ehdr ehdr_mem;
+		GElf_Ehdr *ehdr = gelf_getehdr (unstripped, &ehdr_mem);
+		ELF_CHECK (ehdr != NULL, _("cannot get ELF header: %s"));
+
+		GElf_Off sh_align = gelf_getclass (unstripped) * 4;
+		offset = (offset + sh_align - 1) & -sh_align;
+		ehdr->e_shnum = unstripped_shnum;
+		ehdr->e_shoff = offset;
+		offset += unstripped_shnum * ehdr->e_shentsize;
+		ELF_CHECK (gelf_update_ehdr (unstripped, ehdr),
+			   _("cannot update ELF header: %s"));
+	      }
+
+	    placed[i] = true;
+	  }
+    }
+  while (skip_reloc);
+
+  size_t phnum;
+  ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
+	     _("cannot get number of program headers: %s"));
+
+  if (phnum > 0)
+    ELF_CHECK (gelf_newphdr (unstripped, phnum),
+	       _("cannot create program headers: %s"));
+
+  /* Copy each program header from the stripped file.  */
+  for (size_t i = 0; i < phnum; ++i)
+    {
+      GElf_Phdr phdr_mem;
+      GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
+      ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
+
+      ELF_CHECK (gelf_update_phdr (unstripped, i, phdr),
+		 _("cannot update program header: %s"));
+    }
+
+  /* Finally, write out the file.  */
+  ELF_CHECK (elf_update (unstripped, ELF_C_WRITE) > 0,
+	     _("cannot write output file: %s"));
+
+  if (strtab != NULL)
+    {
+      dwelf_strtab_free (strtab);
+      free (strtab_data->d_buf);
+    }
+
+  if (symstrtab != NULL)
+    {
+      dwelf_strtab_free (symstrtab);
+      free (symstrdata->d_buf);
+    }
+  free_new_data ();
+}
+
+/* Process one pair of files, already opened.  */
+static void
+handle_file (const char *output_file, bool create_dirs,
+	     Elf *stripped, const GElf_Ehdr *stripped_ehdr,
+	     Elf *unstripped)
+{
+  size_t phnum;
+  ELF_CHECK (elf_getphdrnum (stripped, &phnum) == 0,
+	     _("cannot get number of program headers: %s"));
+
+  /* Determine the address bias between the debuginfo file and the main
+     file, which may have been modified by prelinking.  */
+  GElf_Addr bias = 0;
+  if (unstripped != NULL)
+    for (size_t i = 0; i < phnum; ++i)
+      {
+	GElf_Phdr phdr_mem;
+	GElf_Phdr *phdr = gelf_getphdr (stripped, i, &phdr_mem);
+	ELF_CHECK (phdr != NULL, _("cannot get program header: %s"));
+	if (phdr->p_type == PT_LOAD)
+	  {
+	    GElf_Phdr unstripped_phdr_mem;
+	    GElf_Phdr *unstripped_phdr = gelf_getphdr (unstripped, i,
+						       &unstripped_phdr_mem);
+	    ELF_CHECK (unstripped_phdr != NULL,
+		       _("cannot get program header: %s"));
+	    bias = phdr->p_vaddr - unstripped_phdr->p_vaddr;
+	    break;
+	  }
+      }
+
+  /* One day we could adjust all the DWARF data (like prelink itself does).  */
+  if (bias != 0)
+    {
+      if (output_file == NULL)
+	error (0, 0, _("\
+DWARF data not adjusted for prelinking bias; consider prelink -u"));
+      else
+	error (0, 0, _("\
+DWARF data in '%s' not adjusted for prelinking bias; consider prelink -u"),
+	       output_file);
+    }
+
+  if (output_file == NULL)
+    /* Modify the unstripped file in place.  */
+    copy_elided_sections (unstripped, stripped, stripped_ehdr, bias);
+  else
+    {
+      if (create_dirs)
+	make_directories (output_file);
+
+      /* Copy the unstripped file and then modify it.  */
+      int outfd = open (output_file, O_RDWR | O_CREAT,
+			(stripped_ehdr->e_type == ET_REL
+			 ? DEFFILEMODE : ACCESSPERMS));
+      if (outfd < 0)
+	error_exit (errno, _("cannot open '%s'"), output_file);
+      Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
+      ELF_CHECK (outelf != NULL, _("cannot create ELF descriptor: %s"));
+
+      if (unstripped == NULL)
+	{
+	  /* Actually, we are just copying out the main file as it is.  */
+	  copy_elf (outelf, stripped);
+	  if (stripped_ehdr->e_type != ET_REL)
+	    elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT);
+	  ELF_CHECK (elf_update (outelf, ELF_C_WRITE) > 0,
+		     _("cannot write output file: %s"));
+	}
+      else
+	{
+	  copy_elf (outelf, unstripped);
+	  copy_elided_sections (outelf, stripped, stripped_ehdr, bias);
+	}
+
+      elf_end (outelf);
+      close (outfd);
+    }
+}
+
+static int
+open_file (const char *file, bool writable)
+{
+  int fd = open (file, writable ? O_RDWR : O_RDONLY);
+  if (fd < 0)
+    error_exit (errno, _("cannot open '%s'"), file);
+  return fd;
+}
+
+/* Warn, and exit if not forced to continue, if some ELF header
+   sanity check for the stripped and unstripped files failed.  */
+static void
+warn (const char *msg, bool force,
+      const char *stripped_file, const char *unstripped_file)
+{
+  error (force ? 0 : EXIT_FAILURE, 0, "%s'%s' and '%s' %s%s.",
+	 force ? _("WARNING: ") : "",
+	 stripped_file, unstripped_file, msg,
+	 force ? "" : _(", use --force"));
+}
+
+/* Handle a pair of files we need to open by name.  */
+static void
+handle_explicit_files (const char *output_file, bool create_dirs, bool force,
+		       const char *stripped_file, const char *unstripped_file)
+{
+  int stripped_fd = open_file (stripped_file, false);
+  Elf *stripped = elf_begin (stripped_fd, ELF_C_READ, NULL);
+  GElf_Ehdr stripped_ehdr;
+  ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
+	     _("cannot create ELF descriptor: %s"));
+
+  int unstripped_fd = -1;
+  Elf *unstripped = NULL;
+  if (unstripped_file != NULL)
+    {
+      unstripped_fd = open_file (unstripped_file, output_file == NULL);
+      unstripped = elf_begin (unstripped_fd,
+			      (output_file == NULL ? ELF_C_RDWR : ELF_C_READ),
+			      NULL);
+      GElf_Ehdr unstripped_ehdr;
+      ELF_CHECK (gelf_getehdr (unstripped, &unstripped_ehdr),
+		 _("cannot create ELF descriptor: %s"));
+
+      if (memcmp (stripped_ehdr.e_ident,
+		  unstripped_ehdr.e_ident, EI_NIDENT) != 0)
+	warn (_("ELF header identification (e_ident) different"), force,
+	      stripped_file, unstripped_file);
+
+      if (stripped_ehdr.e_type != unstripped_ehdr.e_type)
+	warn (_("ELF header type (e_type) different"), force,
+	      stripped_file, unstripped_file);
+
+      if (stripped_ehdr.e_machine != unstripped_ehdr.e_machine)
+	warn (_("ELF header machine type (e_machine) different"), force,
+	      stripped_file, unstripped_file);
+
+      if (stripped_ehdr.e_phnum < unstripped_ehdr.e_phnum)
+	warn (_("stripped program header (e_phnum) smaller than unstripped"),
+	      force, stripped_file, unstripped_file);
+    }
+
+  handle_file (output_file, create_dirs, stripped, &stripped_ehdr, unstripped);
+
+  elf_end (stripped);
+  close (stripped_fd);
+
+  elf_end (unstripped);
+  close (unstripped_fd);
+}
+
+
+/* Handle a pair of files opened implicitly by libdwfl for one module.  */
+static void
+handle_dwfl_module (const char *output_file, bool create_dirs, bool force,
+		    Dwfl_Module *mod, bool all, bool ignore, bool relocate)
+{
+  GElf_Addr bias;
+  Elf *stripped = dwfl_module_getelf (mod, &bias);
+  if (stripped == NULL)
+    {
+      if (ignore)
+	return;
+
+      const char *file;
+      const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
+					      NULL, NULL, &file, NULL);
+      if (file == NULL)
+	error_exit (0,
+		    _("cannot find stripped file for module '%s': %s"),
+		    modname, dwfl_errmsg (-1));
+      else
+	error_exit (0,
+		    _("cannot open stripped file '%s' for module '%s': %s"),
+		    modname, file, dwfl_errmsg (-1));
+    }
+
+  Elf *debug = dwarf_getelf (dwfl_module_getdwarf (mod, &bias));
+  if (debug == NULL && !all)
+    {
+      if (ignore)
+	return;
+
+      const char *file;
+      const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
+					      NULL, NULL, NULL, &file);
+      if (file == NULL)
+	error_exit (0,
+		    _("cannot find debug file for module '%s': %s"),
+		    modname, dwfl_errmsg (-1));
+      else
+	error_exit (0,
+		    _("cannot open debug file '%s' for module '%s': %s"),
+		    modname, file, dwfl_errmsg (-1));
+    }
+
+  if (debug == stripped)
+    {
+      if (all)
+	debug = NULL;
+      else
+	{
+	  const char *file;
+	  const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
+						  NULL, NULL, &file, NULL);
+	  error_exit (0, _("module '%s' file '%s' is not stripped"),
+		      modname, file);
+	}
+    }
+
+  GElf_Ehdr stripped_ehdr;
+  ELF_CHECK (gelf_getehdr (stripped, &stripped_ehdr),
+	     _("cannot create ELF descriptor: %s"));
+
+  if (stripped_ehdr.e_type == ET_REL)
+    {
+      if (!relocate)
+	{
+	  /* We can't use the Elf handles already open,
+	     because the DWARF sections have been relocated.  */
+
+	  const char *stripped_file = NULL;
+	  const char *unstripped_file = NULL;
+	  (void) dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL,
+				   &stripped_file, &unstripped_file);
+
+	  handle_explicit_files (output_file, create_dirs, force,
+				 stripped_file, unstripped_file);
+	  return;
+	}
+
+      /* Relocation is what we want!  This ensures that all sections that can
+	 get sh_addr values assigned have them, even ones not used in DWARF.
+	 They might still be used in the symbol table.  */
+      if (dwfl_module_relocations (mod) < 0)
+	error_exit (0,
+		    _("cannot cache section addresses for module '%s': %s"),
+		    dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+		    dwfl_errmsg (-1));
+    }
+
+  handle_file (output_file, create_dirs, stripped, &stripped_ehdr, debug);
+}
+
+/* Handle one module being written to the output directory.  */
+static void
+handle_output_dir_module (const char *output_dir, Dwfl_Module *mod, bool force,
+			  bool all, bool ignore, bool modnames, bool relocate)
+{
+  if (! modnames)
+    {
+      /* Make sure we've searched for the ELF file.  */
+      GElf_Addr bias;
+      (void) dwfl_module_getelf (mod, &bias);
+    }
+
+  const char *file;
+  const char *name = dwfl_module_info (mod, NULL, NULL, NULL,
+				       NULL, NULL, &file, NULL);
+
+  if (file == NULL && ignore)
+    return;
+
+  char *output_file = xasprintf ("%s/%s", output_dir, modnames ? name : file);
+
+  handle_dwfl_module (output_file, true, force, mod, all, ignore, relocate);
+
+  free (output_file);
+}
+
+
+static void
+list_module (Dwfl_Module *mod)
+{
+  /* Make sure we have searched for the files.  */
+  GElf_Addr bias;
+  bool have_elf = dwfl_module_getelf (mod, &bias) != NULL;
+  bool have_dwarf = dwfl_module_getdwarf (mod, &bias) != NULL;
+
+  const char *file;
+  const char *debug;
+  Dwarf_Addr start;
+  Dwarf_Addr end;
+  const char *name = dwfl_module_info (mod, NULL, &start, &end,
+				       NULL, NULL, &file, &debug);
+  if (file != NULL && debug != NULL && (debug == file || !strcmp (debug, file)))
+    debug = ".";
+
+  const unsigned char *id;
+  GElf_Addr id_vaddr;
+  int id_len = dwfl_module_build_id (mod, &id, &id_vaddr);
+
+  printf ("%#" PRIx64 "+%#" PRIx64 " ", start, end - start);
+
+  if (id_len > 0)
+    {
+      do
+	printf ("%02" PRIx8, *id++);
+      while (--id_len > 0);
+      if (id_vaddr != 0)
+	printf ("@%#" PRIx64, id_vaddr);
+    }
+  else
+    putchar ('-');
+
+  printf (" %s %s %s\n",
+	  file ?: have_elf ? "." : "-",
+	  debug ?: have_dwarf ? "." : "-",
+	  name);
+}
+
+
+struct match_module_info
+{
+  char **patterns;
+  Dwfl_Module *found;
+  bool match_files;
+};
+
+static int
+match_module (Dwfl_Module *mod,
+	      void **userdata __attribute__ ((unused)),
+	      const char *name,
+	      Dwarf_Addr start __attribute__ ((unused)),
+	      void *arg)
+{
+  struct match_module_info *info = arg;
+
+  if (info->patterns[0] == NULL) /* Match all.  */
+    {
+    match:
+      info->found = mod;
+      return DWARF_CB_ABORT;
+    }
+
+  if (info->match_files)
+    {
+      /* Make sure we've searched for the ELF file.  */
+      GElf_Addr bias;
+      (void) dwfl_module_getelf (mod, &bias);
+
+      const char *file;
+      const char *check = dwfl_module_info (mod, NULL, NULL, NULL,
+					    NULL, NULL, &file, NULL);
+      if (check == NULL || strcmp (check, name) != 0 || file == NULL)
+	return DWARF_CB_OK;
+
+      name = file;
+    }
+
+  for (char **p = info->patterns; *p != NULL; ++p)
+    if (fnmatch (*p, name, 0) == 0)
+      goto match;
+
+  return DWARF_CB_OK;
+}
+
+/* Handle files opened implicitly via libdwfl.  */
+static void
+handle_implicit_modules (const struct arg_info *info)
+{
+  struct match_module_info mmi = { info->args, NULL, info->match_files };
+  ptrdiff_t offset = dwfl_getmodules (info->dwfl, &match_module, &mmi, 0);
+  if (offset == 0)
+    error_exit (0, _("no matching modules found"));
+
+  if (info->list)
+    do
+      list_module (mmi.found);
+    while ((offset = dwfl_getmodules (info->dwfl, &match_module, &mmi,
+				      offset)) > 0);
+  else if (info->output_dir == NULL)
+    {
+      if (dwfl_getmodules (info->dwfl, &match_module, &mmi, offset) != 0)
+	error_exit (0, _("matched more than one module"));
+      handle_dwfl_module (info->output_file, false, info->force, mmi.found,
+			  info->all, info->ignore, info->relocate);
+    }
+  else
+    do
+      handle_output_dir_module (info->output_dir, mmi.found, info->force,
+				info->all, info->ignore,
+				info->modnames, info->relocate);
+    while ((offset = dwfl_getmodules (info->dwfl, &match_module, &mmi,
+				      offset)) > 0);
+}
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  setlocale (LC_ALL, "");
+
+  /* Make sure the message catalog can be found.  */
+  bindtextdomain (PACKAGE_TARNAME, LOCALEDIR);
+
+  /* Initialize the message catalog.  */
+  textdomain (PACKAGE_TARNAME);
+
+  /* Parse and process arguments.  */
+  const struct argp_child argp_children[] =
+    {
+      {
+	.argp = dwfl_standard_argp (),
+	.header = N_("Input selection options:"),
+	.group = 1,
+      },
+      { .argp = NULL },
+    };
+  const struct argp argp =
+    {
+      .options = options,
+      .parser = parse_opt,
+      .children = argp_children,
+      .args_doc = N_("STRIPPED-FILE DEBUG-FILE\n[MODULE...]"),
+      .doc = N_("\
+Combine stripped files with separate symbols and debug information.\n\
+\n\
+The first form puts the result in DEBUG-FILE if -o was not given.\n\
+\n\
+MODULE arguments give file name patterns matching modules to process.\n\
+With -f these match the file name of the main (stripped) file \
+(slashes are never special), otherwise they match the simple module names.  \
+With no arguments, process all modules found.\n\
+\n\
+Multiple modules are written to files under OUTPUT-DIRECTORY, \
+creating subdirectories as needed.  \
+With -m these files have simple module names, otherwise they have the \
+name of the main file complete with directory underneath OUTPUT-DIRECTORY.\n\
+\n\
+With -n no files are written, but one line to standard output for each module:\
+\n\tSTART+SIZE BUILDID FILE DEBUGFILE MODULENAME\n\
+START and SIZE are hexadecimal giving the address bounds of the module.  \
+BUILDID is hexadecimal for the build ID bits, or - if no ID is known; \
+the hexadecimal may be followed by @0xADDR giving the address where the \
+ID resides if that is known.  \
+FILE is the file name found for the module, or - if none was found, \
+or . if an ELF image is available but not from any named file.  \
+DEBUGFILE is the separate debuginfo file name, \
+or - if no debuginfo was found, or . if FILE contains the debug information.\
+")
+    };
+
+  int remaining;
+  struct arg_info info = { .args = NULL };
+  error_t result = argp_parse (&argp, argc, argv, 0, &remaining, &info);
+  if (result == ENOSYS)
+    assert (info.dwfl == NULL);
+  else if (result)
+    return EXIT_FAILURE;
+  assert (info.args != NULL);
+
+  /* Tell the library which version we are expecting.  */
+  elf_version (EV_CURRENT);
+
+  if (info.dwfl == NULL)
+    {
+      assert (result == ENOSYS);
+
+      if (info.output_dir != NULL)
+	{
+	  char *file = xasprintf ("%s/%s", info.output_dir, info.args[0]);
+	  handle_explicit_files (file, true, info.force,
+				 info.args[0], info.args[1]);
+	  free (file);
+	}
+      else
+	handle_explicit_files (info.output_file, false, info.force,
+			       info.args[0], info.args[1]);
+    }
+  else
+    {
+      /* parse_opt checked this.  */
+      assert (info.output_file != NULL || info.output_dir != NULL || info.list);
+
+      handle_implicit_modules (&info);
+
+      dwfl_end (info.dwfl);
+    }
+
+  return 0;
+}
+
+
+#include "debugpred.h"
diff --git a/tests/ChangeLog b/tests/ChangeLog
new file mode 100644
index 0000000..d97749f
--- /dev/null
+++ b/tests/ChangeLog
@@ -0,0 +1,4798 @@
+2023-09-27  Omar Sandoval  <osandov@fb.com>
+
+	* dwarf-getmacros.c (mac): Add DW_MACRO_define_sup,
+	DW_MACRO_define_strx, DW_MACRO_undef_sup, and DW_MACRO_undef_strx
+	cases to opcode switch statement.
+	(getmacros): New function.
+	(main): If second argument is empty, call getmacros on every unit.
+	Otherwise, call getmacros on given unit.
+
+2023-09-27  Omar Sandoval  <osandov@fb.com>
+
+	* run-varlocs.sh: Add entry PC to split units.
+
+2023-04-21  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-IXr.sh: New test.
+	* Makefile.am: Run it, ship it.
+
+2023-02-10  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (print_expr): Handle DW_OP_GNU_uninit.
+
+2023-02-07  Mark Wielaard  <mark@klomp.org>
+
+	* tests/funcretval.c (handle_function): Check for
+	DW_TAG_unspecified_type.
+
+2023-02-03  Mark Wielaard  <mark@klomp.org>
+
+	* run-addr2line-C-test.sh: Check ELFUTILS_DISABLE_DEMANGLE.
+
+2023-01-22  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-inlines-lto.bz2: New testfile.
+	* run-addr2line-i-test.sh: Add new lto inlines test.
+	* Makefile.am (EXTRA_DIST): Add testfile-inlines-lto.bz2.
+
+2023-01-19  Mark Wielaard  <mark@klomp.org>
+
+	* run-addr2line-C-test.sh: New test.
+	* Makefile.am (TESTS): Add run-addr2line-C-test.sh.
+	(EXTRA_DIST): Likewise.
+
+2023-01-19  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-query-retry.sh: Use libdebuginfod.so.1 instead
+	of /bin/sh as test file.
+
+2022-12-21  Shahab Vahedi  <shahab@synopsys.email>
+
+	* hello_arc_hs4.ko.bz2: New testfile.
+	* run-strip-reloc.sh: Add ARC HS4 test.
+	* Makefile.am (EXTRA_DIST): Add hello_arc_hs4.ko.bz2.
+
+2022-11-01  Aaron Merey  <amerey@redhat.com>
+
+	* run-debuginfod-section.sh (RPM_BUILDID): Use buildid from non-zstd
+	compressed rpm.
+
+2022-10-31  Aaron Merey  <amerey@redhat.com>
+
+	* Makefile.am (TESTS): Add run-debuginfod-section.sh.
+	* run-debuginfod-section.sh: New test.
+
+2022-09-20  Yonggang Luo  <luoyonggang@gmail.com>
+
+	* Makefile.am (EXTRA_DIST): Remove debuginfod-rpms/hello2.spec.
+	Add debuginfod-rpms/hello{2,3}.specfile.
+	* tests/debuginfod-rpms/hello2.spec.: Renamed to...
+	* tests/debuginfod-rpms/hello2.specfile: ...this.
+	* tests/debuginfod-rpms/hello3.spec.: Renamed to...
+	* tests/debuginfod-rpms/hello3.specfile: ...this.
+
+2022-10-28  Arsen Arsenović  <arsen@aarsen.me>
+
+	* run-readelf-s.sh: Add tests for the --syms alias.
+
+2022-10-27  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-subr.sh: Use grep -E instead of egrep, use grep -F
+	instead of fgrep.
+	* debuginfod-subr.sh: Likewise.
+	* run-debuginfod-archive-rename.sh: Likewise.
+	* run-debuginfod-extraction-passive.sh: Likewise.
+	* run-debuginfod-response-headers.sh: Likewise.
+	* run-debuginfod-webapi-concurrency.sh: Likewise.
+	* run-strip-test.sh: Likewise.
+
+2022-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl-report-offline-memory.c: Include config.h first.
+
+2022-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl-report-offline-memory.c (main): Check lseek, read and malloc
+	results with correct types.
+
+2022-09-13  Aleksei Vetrov  <vvvvvv@google.com>
+
+	* Makefile.am (check_PROGRAMS): Add dwfl-report-offline-memory.
+	(TESTS): Add run-dwfl-report-offline-memory.sh.
+	(EXTRA_DIST): Likewise.
+	(dwfl_report_offline_memory_LDADD): New variable.
+	* dwfl-report-offline-memory.c: New file.
+	* run-dwfl-report-offline-memory.sh: Likewise.
+
+2022-09-13  Khem Raj <raj.khem@gmail.com>
+
+	* Makefile.am (*_LDADD): Add libeu if needed for error.
+
+2022-08-26  Mark Wielaard  <mark@klomp.org>
+
+	* run-ar-N.sh: New test.
+	* Makefile.am (TESTS): Add run-ar-N.sh.
+	(EXTRA_DIST): Likewise.
+
+2022-09-02  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-response-headers.sh: Use case-insensitive
+	header name matches.  Use socat & sleep for greater
+	portability.
+	* run-debuginfod-sizetime.sh: Update for debuginfod-find -v -v.
+
+2022-07-15  Noah Sanci  <nsanci@redhat.com>
+
+	* run-debuginfod-response-headers.sh: Added test
+	to ensure that federated servers pass headers down to
+	queried server.
+
+2022-08-04  Sergei Trofimovich  <slyich@gmail.com>
+
+	* low_high_pc.c (handle_die): Drop redundant 'lx' suffix.
+
+2022-08-01  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-percent-escape.sh: Add initial scan wait_ready.
+
+2022-04-28  Di Chen  <dichen@redhat.com>
+
+	* run-readelf-Dd.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-Dd.sh.
+	(EXTRA_DIST): Likewise.
+
+2022-06-01  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-arm-flags.bz2: New test file.
+	* run-readelf-arm-flags.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-arm-flags.sh.
+	(EXTRA_DIST): Add readelf-arm-flags.sh and testfile-arm-flags.bz2
+
+2022-05-13  Noah Sanci  <nsanci@redhat.com>
+
+	* run-debuginfod-fd-prefetch-caches.sh: Rewritten.
+
+2022-06-02  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS): Add run-debuginfod-federation-metrics.sh
+	only when OLD_LIBMICROHTTPD conditional is not set.
+
+2022-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-webapi-concurrency.sh: Fix PR number in xfail.
+
+2022-04-23  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-webapi-concurrency.sh: Lower parallel lookups.
+
+2022-03-01  Di Chen <dichen@redhat.com>
+
+	* alldts.c (dtflags): Put DT_NULL last.
+	* run-alldts.sh: NULL comes last.
+	* run-readelf-d.sh: Adjust Dynamic entries, remove DT_NULL
+	padding.
+
+2022-04-14  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-federation-sqlite.sh: Don't try to corrupt
+	sqlite database.
+
+2022-04-13  Aaron Merey  <amerey@redhat.com>
+
+	* Makefile.am (TESTS): Remove run-debuginfod-000-permission.sh
+	and add run-debuginfod-negative-cache.sh.
+	(EXTRA_DIST): Likewise.
+	* run-debuginfod-federation-link.sh: Update comments about
+	negative-hit file.
+	* run-debuginfod-federation-metrics.sh: Likewise.
+	* run-debuginfod-federation-sqlite.sh: Likewise.
+	* run-debuginfod-tmp-home.sh: Likewise.
+
+2022-03-20  Mark Wielaard  <mark@klomp.org>
+
+	* run-large-elf-file.sh: Check elf class of addsections binary.
+
+2021-12-17  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-query-retry.sh: Use /bin/sh instead of /bin/ls.
+
+2021-12-09  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-subr.sh (xfail): New proc.
+	* run-debuginfod-webapi-concurrency.sh: New test for -C.
+	* Makefile.am: List it.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (EXTRA_NLIST_CFLAGS): New variable depends on
+	USE_ADDRESS_SANITIZER.
+	(test_nlist_CFLAGS): Add EXTRA_NLIST_CFLAGS.
+
+2021-12-04  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (dwarf_encoding_string): Return "<unknown encoding>" instead
+	of NULL.
+	(dwarf_tag_string): Return "<unknown tag>" instead of NULL.
+	(dwarf_attr_string): Return "<unknown attr>" instead of NULL.
+	(dwarf_form_string): Return "<unknown form>" instead of NULL.
+	(dwarf_opcode_string): Return "<unknown opcode>" instead of NULL.
+	(print_expr): Remove assert.
+
+2021-11-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (dwfl_proc_attach_LDFLAGS): Add -rdynamic.
+
+2021-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-000-permission.sh: Don't set DEBUGINFOD_TIMEOUT.
+	* run-debuginfod-archive-groom.sh: Likewise.
+	* run-debuginfod-archive-rename.sh: Likewise.
+	* run-debuginfod-archive-test.sh: Likewise.
+	* run-debuginfod-artifact-running.sh: Likewise.
+	* run-debuginfod-dlopen.sh: Likewise.
+	* run-debuginfod-extraction.sh: Likewise.
+	* run-debuginfod-federation-link.sh: Likewise.
+	* run-debuginfod-federation-metrics.sh: Likewise.
+	* run-debuginfod-federation-sqlite.sh: Likewise.
+	* run-debuginfod-malformed.sh: Likewise.
+	* run-debuginfod-tmp-home.sh: Likewise.
+	* run-debuginfod-writable.sh: Likewise.
+
+2021-11-05  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28430
+	* run-debuginfod-extraction-passive.sh: New test.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+2021-10-20  John M Mellor-Crummey  <johnmc@rice.edu>
+
+	* nvidia_extended_linemap_libdw.c: New file.
+	* run-nvidia-extended-linemap-libdw.sh: New test.
+	* run-nvidia-extended-linemap-readelf.sh: Likewise.
+	* testfile_nvidia_linemap.bz2: New test file.
+	* .gitignore: Add nvidia_extended_linemap_libdw.
+	* Makefile.am (check_PROGRAMS): Add nvidia_extended_linemap_libdw.
+	(TESTS): Add run-nvidia-extended-linemap-libdw.sh and
+	run-nvidia-extended-linemap-readelf.sh
+	(EXTRA_DIST): Likewise and testfile_nvidia_linemap.bz2.
+	(nvidia_extended_linemap_libdw_LDADD): New variable.
+
+2021-11-08  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS): Add run-readelf-fat-lto.sh.
+	(EXTRA_DIST): Add run-readelf-fat-lto.sh and
+	testfile-dwarf5-fat-lto.o.bz2.
+	* run-readelf-fat-lto.sh: New test.
+	* testfile-dwarf5-fat-lto.o.bz2: New test file.
+
+2021-11-04  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28514
+	* run-debuginfod-archive-groom.sh: Look for new groom metric.
+
+2021-10-23  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR28240
+	* run-debuginfod-000-permission.sh, -writable.sh:
+	Correct negative-cache file permission checking.
+
+2021-10-06  Mark Wielaard  <mark@klomp.org>
+
+	* show-die-info.c (handle): Handle dwarf_attr_string returning NULL.
+
+2021-10-06  Di Chen <dichen@redhat.com>
+
+	PR28242
+	* run-debuginfod-000-permission.sh: Expect artifacttype metrics.
+
+2021-09-17  Noah Sanci  <nsanci@redhat.com>
+
+	* run-debuginfod-response-header.sh: removed checking for Connection
+	and Cache-Control in response headers.
+
+2021-09-08  Mark Wielaard  <mark@klomp.org>
+
+	* run-varlocs-vars.sh: New test.
+	* testfile-vars-clang-dwarf4-32.o.bz2: New test file.
+	* testfile-vars-clang-dwarf4-64.o.bz2: Likewise.
+	* testfile-vars-clang-dwarf5-32.o.bz2: Likewise.
+	* testfile-vars-clang-dwarf5-64.o.bz2: Likewise.
+	* testfile-vars-gcc-dwarf4-32.o.bz2: Likewise.
+	* testfile-vars-gcc-dwarf4-64.o.bz2: Likewise.
+	* testfile-vars-gcc-dwarf5-32.o.bz2: Likewise.
+	* testfile-vars-gcc-dwarf5-64.o.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add new test and test files.
+	(TESTS): Add run-varlocs-vars.sh.
+
+2021-09-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-subr.sh: set -o functrace.
+	(cleanup): Disable trap 0.
+	(err): Disable trap ERR.
+	* run-debuginfod-fd-prefetch-caches.sh: Use || true when grep -c fails.
+
+2021-09-09  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-subr.sh: set -o errtrace.
+	(cleanup): Don't fail kill or wait. Only trap on normal exit.
+	(err): Don't fail curl metrics. Call cleanup.
+	* run-debuginfod-federation-link.sh: Use separate client caches
+	for both servers and debuginfod client. Remove duplicate valgrind
+	disabling.
+	* run-debuginfod-federation-metrics.sh: Likewise.
+	* run-debuginfod-federation-sqlite.sh: Likewise.
+
+2021-09-13  Noah Sanci  <nsanci@redhat.com>
+
+	* Makefile.am: added run-debuginfod-percent-escape.sh to TESTS and
+	EXTRA_DIST.
+
+2021-09-06  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* elfcopy.c (copy_elf): Remove cast of malloc return value.
+
+2021-09-07  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-archive-groom.sh: Wait for initial scan and groom
+	cycle before making any changes to the scan dirs.
+	* run-debuginfod-archive-rename.sh: Likewise.
+	* run-debuginfod-artifact-running.sh: Wait for initial scan cycle
+	before making any changes to the scan dirs.
+	* run-debuginfod-dlopen.sh: Likewise.
+	* run-debuginfod-extraction.sh: Likewise.
+	* run-debuginfod-federation-link.sh: Don't wait twice for the initial
+	scan.
+
+2021-09-06  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-archive-groom.sh: Wait for initial scan and groom
+	cycle.
+	* run-debuginfod-archive-rename.sh: Likewise.
+	* run-debuginfod-federation-sqlite.sh: Likewise.
+	* run-debuginfod-archive-test.sh: Wait for initial scan cycle.
+	* run-debuginfod-artifact-running.sh: Likewise.
+	* run-debuginfod-dlopen.sh: Likewise.
+	* run-debuginfod-extraction.sh: Likewise.
+	* run-debuginfod-federation-link.sh: Likewise.
+	* run-debuginfod-federation-metrics.sh: Likewise.
+	* run-debuginfod-malformed.sh: Likewise.
+	* run-debuginfod-regex.sh: Likewise.
+	* run-debuginfod-tmp-home.sh: Likewise.
+	* run-debuginfod-writable.sh: Likewise.
+
+2021-09-06  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-archive-groom.sh: Set DEBUGINFOD_URLS after starting
+	debuginfod server.
+	* run-debuginfod-archive-rename.sh: Likewise.
+	* run-debuginfod-federation-link.sh: Don't set DEBUGINFOD_URLS.
+	* run-debuginfod-federation-sqlite.sh: Likewise.
+	* run-debuginfod-federation-metrics.sh: Add comment why invalid
+	DEBUGINFOD_URLS is set.
+
+2021-09-06  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-subr.sh (err): Change ports to port in for loop so both
+	PORT1 and PORT2 are used.
+	(get_ports): Simplify port selection by using for 50 for PORT1 and
+	second 50 for PORT2.
+
+2021-09-06  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-file.sh: Set DEBUGINFOD_CACHE_PATH. Export
+	correct DEBUGINFOD_URLS.
+	* run-debuginfod-query-retry.sh: Add DEBUGINFOD_CACHE_PATH
+	to env.
+
+2021-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-000-permission.sh: Set DEBUGINFOD_CACHE_PATH
+	and use an unique sqlite db.
+	* run-debuginfod-archive-groom.sh: Likewise.
+	* run-debuginfod-archive-test.sh: Likewise.
+	* run-debuginfod-dlopen.sh: Likewise.
+	* run-debuginfod-duplicate-urls.sh: Likewise.
+	* run-debuginfod-extraction.sh: Likewise.
+	* run-debuginfod-fd-prefetch-caches.sh: Likewise.
+	* run-debuginfod-malformed.sh: Likewise.
+	* run-debuginfod-sizetime.sh: Likewise.
+	* run-debuginfod-tmp-home.sh: Likewise.
+	* run-debuginfod-writable.sh: Likewise.
+
+2021-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* debuginfod-subr.sh (EXTRA_DIST): Add debuginfod-subr.sh.
+
+2021-08-20  Noah Sanci  <nsanci@redhat.com>
+
+	* run-debuginfod-response-headers.sh: Ensures custom http response
+	headers are used and functional
+	* Makefile.am: Added the above new file to TESTS and EXTRA_DIST
+
+2021-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Use ":memory:" for the
+	forwarded-ttl-limit tests.
+
+2021-08-28  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Use clean, separate databases for
+	forwarded-ttl-limit tests.
+
+2021-08-20  Di Chen  <dichen@redhat.com>
+
+	* run-debuginfod-find.sh: Add test for X-Forwarded-For hops limit.
+
+2021-08-20  Noah Sanci  <nsanci@redhat.com>
+
+	* debuginfod-find.sh: Separated file into 
+	run-debuginfod-000-permission.sh, 
+	run-debuginfod-archive-groom.sh,
+	run-debuginfod-archive-rename.sh,
+	run-debuginfod-archive-test.sh,
+	run-debuginfod-artifact-running.sh,
+	run-debuginfod-dlopen.sh,
+	run-debuginfod-duplicate-urls.sh,
+	run-debuginfod-extraction.sh,
+	run-debuginfod-fd-prefetch-caches.sh,
+	run-debuginfod-federation-link.sh,
+	run-debuginfod-federation-metrics.sh,
+	run-debuginfod-federation-sqlite.sh,
+	run-debuginfod-file.sh,
+	run-debuginfod-malformed.sh,
+	run-debuginfod-no-urls.sh,
+	run-debuginfod-query-retry.sh,
+	run-debuginfod-regex.sh,
+	run-debuginfod-sizetime.sh,
+	run-debuginfod-tmp-home.sh,
+	run-debuginfod-x-forwarded.sh
+	and run-debuginfod-writable.sh.
+	All files source debuginfod-subr.sh and use the $base variable to find ports.
+	* tests/Makefile.am: Added the above new files to the test suite
+	* tests/debuginfod-subr.sh: Added some general functions for above tests
+
+2021-08-04  Mark Wielaard  <mark@klomp.org>
+
+	PR28190
+	* backtrace.c (callback_verify): Check for pthread_kill as first
+	frame. Change asserts to fprintf plus abort.
+
+2021-07-26  Noah Sanci  <nsanci@redhat.com>
+
+	PR27982
+	* run-debuginfod-find.sh: Added a test to ensure that
+	DEBUGINFOD_MAXSIZE and DEBUGINFOD_MAXTIME work properly
+	by searching server and client logs for prompts.
+
+2021-07-16  Noah Sanci  <nsanci@redhat.com>
+
+	PR28034
+	* run-debuginfod-percent-escape.sh: Added a test ensuring files with %
+	escapable characters in their paths are accessible.
+
+2021-07-21  Noah Sanci <nsanci@redhat.com>
+
+	* run-debuginfod-find.sh: Properly kill $PID4 by waiting for it to
+	finish. Report $PORT3's metrics in err().
+
+2021-06-28  Noah Sanci <nsanci@redhat.com>
+
+	PR25978
+	* run-debuginfod-find.sh: Test to ensure options
+	fdcache-prefetch-fds/mbs are set. Check that inc_metric works for lru
+	and prefetch cache metrics.
+
+2021-07-06  Alice Zhang  <alizhang@redhat.com>
+
+	PR27531
+	* run-debuginfod-find.sh: Add test case for retry mechanism.
+
+2021-07-01  Noah Sanci <nsanci@redhat.com>
+
+	PR2711
+	* run-debuginfod-find.sh: Added test case for grooming the database
+	using regexes. 
+
+2021-07-09  Noah Sanci  <nsanci@redhat.com>
+
+	PR27983
+	* run-debuginfod-find.sh: Wrote test to ensure duplicate urls are in
+	fact not checked.
+
+2021-07-08  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (EXTRA_DIST): Fix typo testfile-largealign.bz2 was
+	was missing .o.
+
+2021-06-09  Andrei Homescu  <ah@immunant.com>
+
+	* testfile-largealign.o.bz2: New test file.
+	* run-strip-largealign.sh: New test.
+	* Makefile.am (TESTS): Add run-strip-largealign.sh.
+	(EXTRA_DIST): Add run-strip-largealign.sh and
+	testfile-largealign.o.bz2
+
+2021-07-02  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfo-find.sh: unset VALGRIND_CMD before testing debuginfod
+	client cache.
+
+2021-06-16  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Fix intermittent groom/stale failure,
+	due to SIGUSR1/SIGUSR2 races.  Trace more.
+
+2021-06-15  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh (err): Elaborate.  Use as the reliable
+	error-report triggering function, rather than "exit 1".
+
+2021-06-03  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27863
+	* run-debuginfod-find.sh: Test "after-you" queueing via flooding
+	with concurent curls.
+
+2021-05-14  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27859
+	* run-debuginfod-find.sh: Test absence of 404-latch bug in client
+	curl handle reuse.
+
+2021-04-19  Martin Liska  <mliska@suse.cz>
+
+	* dwelf_elf_e_machine_string.c (main): Use startswith.
+	* dwelfgnucompressed.c (main): Likewise.
+	* elfgetchdr.c (main): Likewise.
+	* elfputzdata.c (main): Likewise.
+	* vdsosyms.c (module_callback): Likewise.
+
+2021-05-04  Alice Zhang  <alizhang@redhat.com>
+
+	* run-debuginfod-find.sh: Added tests for negative cache files.
+
+2021-04-26  Frank Ch. Eigler <fche@redhat.com>
+
+	PR27571
+	* run-debuginfod-find.sh: Add test case for unwriteable cache files.
+
+2021-04-23  Omar Sandoval  <osandov@fb.com>
+
+	* run-low_high_pc-dw-form-indirect.sh: New file.
+	* run-readelf-dw-form-indirect.sh: New file.
+	* testfile-dw-form-indirect.bz2: New file.
+	* Makefile.am (TESTS): Add run-low_high_pc-dw-form-indirect.sh and
+	run-readelf-dw-form-indirect.sh.
+	(EXTRA_DIST): Add run-low_high_pc-dw-form-indirect.sh,
+	run-readelf-dw-form-indirect.sh, and testfile-dw-form-indirect.bz2.
+
+2021-04-26  Frank Ch. Eigler <fche@redhat.com>
+
+	PR26125
+	* run-debuginfod-find.sh: Add test case for cache cleanup rmdir.
+
+2021-04-23  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Add a tiny test for client object reuse.
+	Add an "errfiles" test construct to ask the framework to print
+	various files in the case of an error.
+
+2021-03-30  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Add thread comm checks.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elfstrmerge.c (main): Move new_data_buf function to...
+	(new_data_buf): ...top-level static function adding fname,
+	ndx, shdrstrnd and shdrnum as arguments.
+
+2021-02-17  Timm Bäder  <tbaeder@redhat.com>
+
+	* elfstrmerge.c (main): Move newsecndx function to...
+	(newsecndx): ...top-level static function adding shdrstrndx,
+	shdrnum and fname as arguments.
+
+2021-02-25  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Add bad webapi artifacttype test.
+
+2021-02-17  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Tweak wait_ready() to also print -vvv log of
+	appropriate debuginfod if metric timeout occurs.  Focus grooming
+	test carefully at a more deterministic metric.
+
+2021-02-12  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-types.sh: Add CU start to type offset reference.
+
+2021-02-07  Alexander Miller  <alex.miller@gmx.de>
+
+	* Makefile.am (TESTS_ENVIRONMENT): Quote variables.
+	(valgrind_cmd): Unquote variable.
+
+2021-02-08  Érico Nogueira  <ericonr@disroot.org>
+
+	* run-debuginfod-find.sh: Check for cpio availability.
+
+2021-02-04  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Smoke test --fdcache-mintmp option handling.
+
+2021-01-31  Sergei Trofimovich  <slyfox@gentoo.org>
+
+	* Makefile.am (TESTS_ENVIRONMENT): export CC variable
+	to tests for use instead of 'gcc'.
+	* run-disasm-x86-64.sh: use ${CC} instead of 'gcc'.
+	* run-disasm-x86.sh: Likewise.
+	* run-strip-g.sh: Likewise.
+	* run-strip-nothing.sh: Likewise.
+	* run-test-includes.sh: Likewise.
+
+2021-01-06  Timm Bäder  <tbaeder@redhat.com>
+
+	* zstrptr.c (main): Lift print_strings function up to ...
+	(print_strings): ... here. New file scope function taking
+	Elf_Scn*, Elf* and ndx as arguments.
+
+2020-12-20  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* .gitignore: New file.
+
+2020-12-12  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-retain.o.bz2: New test file.
+	* run-retain.sh: New test.
+	* Makefile.am (TESTS): Add run-retain.sh.
+	(EXTRA_DIST): Add run-retain.sh and testfile-retain.o.bz2
+
+2020-12-16  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* dwflmodtest.c (N_): Remove.
+
+2020-12-12  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* dwarf-die-addr-die.c (main): Fix spelling typo in error diagnostics.
+	* run-lfs-symbols.sh: Likewise.
+	* elfstrmerge.c (main): Fix spelling typos in comments.
+	* dwfl-bug-fd-leak.c: Likewise.
+	* run-readelf-line.sh: Likewise.
+	* run-stack-demangled-test.sh: Likewise.
+	* sectiondump.c (main): Likewise.
+	* varlocs.c (handle_die): Likewise.
+
+2020-12-11  Dmitry V. Levin  <ldv@altlinux.org>
+
+	* configure.ac: Remove.
+	* Makefile.am [STANDALONE]: Remove.
+	(check_PROGRAMS): Add msg_tst, system-elf-libelf-test, and $(asm_TESTS)
+	unconditionally.
+	(TESTS): Add msg_tst, system-elf-libelf-test, $(asm_TESTS), and
+	run-disasm-bpf.sh unconditionally.
+
+2020-11-23  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Add sqlite error injection & stats.
+
+2020-11-02  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Create bogus R/nothing.rpm with cyclic
+	symlink instead of chmod 000.
+
+2020-11-19  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Look for http-* metrics.
+
+2020-11-01  Érico N. Rolim  <erico.erc@gmail.com>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* alldts.c (main): Use DEFFILEMODE for open with O_CREAT.
+	* arextract.c (main): Likewise.
+	* ecp.c (main): Likewise for creat.
+	* elfstrtab.c (check_elf): Use DEFFILEMODE for open with O_CREAT,
+	remove mode from open calls without O_CREAT.
+	* emptyfile.c (check_elf): Likewise.
+	* fillfile.c (check_elf): Likewise.
+	* vendorelf.c (check_elf): Likewise.
+	* newdata.c (checkelf): Use DEFFILEMODE for open with O_CREAT.
+	* update{1,2,3,4}.c (main): Likewise.
+	*
+
+2020-10-31  Mark Wielaard  <mark@klomp.org>
+
+	* dwfl-proc-attach.c (dlopen): New external function override.
+
+2020-10-31  Mark Wielaard  <mark@klomp.org>
+
+	* test-wrapper.sh: Use =, not == for string compare.
+
+2020-10-29  Mark Wielaard  <mark@klomp.org>
+
+	* test-wrapper.sh: Determine whether the test is a script or not
+	and run binaries directly under valgrind.
+	* dwfl-bug-fd-leak.c (main): Call getrlimit before calling setrlimit.
+	* dwfl-proc-attach.c (main): Call dwfl_end, pthread_cancel and
+	pthread_join.
+	* vdsosyms.c (main): Call dwfl_end.
+
+2020-10-31  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Modify for tweaked/new metrics.
+
+2020-10-30  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26775
+	* run-debuginfod-find.sh: Modify test for restored
+	thread_work_total semantics for grooming.
+
+2020-10-29  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26775
+	* run-debuginfod-find.sh: Modify test for different
+	thread_work_total semantics for grooming.
+
+2020-10-29  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26810
+	* run-debuginfod-find.sh: Add tests for successful archive fetches across
+	renamed RPMs, even without grooming.
+
+2020-10-25  Mark Wielaard  <mark@klomp.org>
+
+	* read_unaligned.c: New test.
+	* Makefile.am (check_PROGRAMS, TESTS): Add read_unaligned.
+	(read_unaligned_LDADD): New variable.
+
+2020-10-28  Tom Tromey  <tom@tromey.com>
+
+	PR26773
+	* Makefile.am (check_PROGRAMS, TESTS): Add leb128.
+	(leb128_LDADD): New variable.
+	* leb128.c: New file.
+
+2020-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* addrcfi.c (print_register): Make ops_mem 3 elements.
+
+2020-10-19  Mark Wielaard  <mark@klomp.org>
+
+	* testfile60.bz2: Removed.
+	* Makefile.am (EXTRA_DIST): Remove testfile60.bz2.
+	* run-allregs.sh: Remove tilegx testfile60 testcase.
+
+2020-10-20  Frank Ch. Eigler  <fche@redhat.com>
+
+	PR26756: more prometheus metrics
+	* run-debuginfod-find.sh: Trigger some errors with dummy "nothing.rpm"
+	and check for new metrics.
+
+2020-09-18  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-compressed-zstd.sh: New test.
+	* Makefile.am (EXTRA_DISTS): Add run-readelf-compressed-zstd.sh.
+	(TESTS): Add run-readelf-compressed-zstd.sh if HAVE_ZSTD.
+
+2020-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-frames.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-frames.sh.
+	(EXTRA_DIST): Likewise.
+
+2020-09-03  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-gnu-property-note-aarch64.bz2: New file.
+	* run-readelf-n.sh: Handle testfile-gnu-property-note-aarch64.
+	* Makefile.am (EXTRA_DIST): Add
+	testfile-gnu-property-note-aarch64.bz2.
+
+2020-07-19  Mark Wielaard  <mark@klomp.org>
+
+	* asm-tst1.c: Include libebl.h after libasm.h.
+	* asm-tst2.c: Likewise.
+	* asm-tst3.c: Likewise.
+	* asm-tst4.c: Likewise.
+	* asm-tst5.c: Likewise.
+	* asm-tst6.c: Likewise.
+	* asm-tst7.c: Likewise.
+	* asm-tst8.c: Likewise.
+	* asm-tst9.c: Likewise.
+
+2020-07-05  Mark Wielaard  <mark@klomp.org>
+
+	* run-test-includes.sh: New test.
+	* Makefile.am (TESTS): Add run-test-includes.sh.
+	(EXTRA_DIST): Likewise.
+
+2020-07-03  Alice Zhang  <alizhang@redhat.com>
+
+	* run-debuginfod-find.sh: Add scheme free url testcase.
+
+2020-06-19  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS): Don't add run-debuginfod-find.sh when
+	DUMMY_LIBDEBUGINFOD.
+
+2020-06-16  Mark Wielaard  <mark@klomp.org>
+
+	* coverage.sh: Use /usr/bin/env bash.
+	* run-ar.sh: Likewise.
+	* run-backtrace-core-aarch64.sh: Likewise.
+	* run-backtrace-core-i386.sh: Likewise.
+	* run-backtrace-core-ppc.sh: Likewise.
+	* run-backtrace-core-s390.sh: Likewise.
+	* run-backtrace-core-s390x.sh: Likewise.
+	* run-backtrace-core-sparc.sh: Likewise.
+	* run-backtrace-core-x32.sh: Likewise.
+	* run-backtrace-core-x86_64.sh: Likewise.
+	* run-backtrace-data.sh: Likewise.
+	* run-backtrace-demangle.sh: Likewise.
+	* run-backtrace-dwarf.sh: Likewise.
+	* run-backtrace-fp-core-aarch64.sh: Likewise.
+	* run-backtrace-fp-core-i386.sh: Likewise.
+	* run-backtrace-fp-core-ppc64le.sh: Likewise.
+	* run-backtrace-fp-core-x86_64.sh: Likewise.
+	* run-backtrace-native-biarch.sh: Likewise.
+	* run-backtrace-native-core-biarch.sh: Likewise.
+	* run-backtrace-native-core.sh: Likewise.
+	* run-backtrace-native.sh: Likewise.
+	* run-debuginfod-find.sh: Likewise.
+	* run-deleted.sh: Likewise.
+	* run-dwelf_elf_e_machine_string.sh: Likewise.
+	* run-large-elf-file.sh: Likewise.
+	* run-lfs-symbols.sh: Likewise.
+	* run-linkmap-cut.sh: Likewise.
+
+2020-06-11  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (nlist-test): Add GCOV flags when necessary.
+
+2020-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* testfilesyms32.bz2: New test file.
+	* testfilesyms64.bz2: Likewise.
+	* run-nm-syms.sh: New test.
+	* Makefile.am (TESTS): Add run-nm-syms.sh.
+	(EXTRA_DIST): run-nm-syms.sh, testfilesyms32.bz2 and
+	testfilesyms64.bz2
+
+2020-05-08  Mark Wielaard  <mark@klomp.org>
+
+	* elfputzdata.c (main): Explicitly check orig_buf is not NULL
+	before calling memcmp.
+
+2020-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-lto-gcc8.bz2: New test file.
+	* testfile-lto-gcc9.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfile-lto-gcc8.bz2 and
+	testfile-lto-gcc9.bz2.
+	* run-allfcts.sh: Add testfile-lto-gcc9 and testfile-lto-gcc8
+	tests.
+
+2020-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-lto-gcc10.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfile-lto-gcc10.bz2.
+	* run-allfcts.sh: Add testfile-lto-gcc10 test.
+
+2020-04-17  Mark Wielaard  <mark@klomp.org>
+
+	* test-subr.sh (testrun_on_self_obj): New function.
+	* run-varlocs-self.sh: Run testrun_on_self_exe and
+	testrun_on_self_lib with -e, run testrun_on_self_obj with
+	--exprlocs -e.
+
+2020-04-17  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (test-nlist$): New goal with minimal CFLAGS.
+	(test_nlist_CFLAGS): New variable.
+
+2020-03-28  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test timestamps of archive-origin files.
+
+2020-03-27  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test /path/-based debuginfod-find.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test relay of UA and XFF headers across
+	federating debuginfods.
+
+2020-03-26  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Look for debuginfod's new
+	http_responses_* metrics.
+
+2020-03-26  Frank Ch. Eigler <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Look for bsdtar instead of dpkg.
+
+2020-03-26  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Check for bsdtar zstd capability
+	for running tests against zstd-compressed fedora31 rpms.
+
+2020-03-26  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (EXTRA_DIST): Add
+	debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm,
+	debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm,
+	debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm,
+	debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm,
+	debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm,
+	debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-rpms/hello3.spec., /fedora31/*: New files with
+	uncanonicalized source paths.
+	* run-debuginfod-find.sh: Test them.
+
+2020-03-24  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test the more detailed debuginfod
+	webapi log format.
+
+2020-03-23  Mark Wielaard  <mark@klomp.org>
+
+	* getphdrnum.c: Include config.h.
+	* run-lfs-symbols.sh: Also check that file exists. Add more logs.
+	Remove ebl modules check.
+
+2020-03-22  Omar Sandoval  <osandov@fb.com>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* getphdrnum.c: New file.
+	* run-getphdrnum.sh: New test.
+	* testfile-phdrs.elf.bz2: New test file.
+	* Makefile.am (check_PROGRAMS): Add getphdrnum.
+	(TESTS): Add run-getphdrnum.sh.
+	(EXTRA_DIST): Add run-getphdrnum.sh and testfile-phdrs.elf.bz2.
+	(getphdrnum_LDADD): New variable.
+
+2020-03-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Look for URL in default progressfn
+	and from debuginfod-find -v.
+
+2020-02-19  Aaron Merey  <amerey@redhat.com>
+
+	* run-debuginfod-find.sh: Run tests for	verifying default
+	client cache locations.
+
+2020-02-26  Konrad Kleine <kkleine@redhat.com>
+
+	* run-debuginfod-find.sh: added tests for DEBUGINFOD_URLS beginning
+	with "file://"
+
+2020-02-21  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS_ENVIRONMENT): Explicitly unset DEBUGINFOD_URLS.
+	(installed_TESTS_ENVIRONMENT): Likewise.
+
+2020-02-19  Aaron Merey  <amerey@redhat.com>
+
+	* run-debuginfod-find.sh: Test that files unrelated to debuginfod
+	survive cache cleaning.
+
+2020-02-08  Mark Wielaard  <mark@klomp.org>
+
+	* run-pt_gnu_prop-tests.sh: New test.
+	* testfile_pt_gnu_prop.bz2: New test file.
+	* testfile_pt_gnu_prop32.bz2: Likewise.
+	* Makefile.am (TESTS): Add run-pt_gnu_prop-tests.sh
+	(EXTRA_DISTS): Likewise. Add testfile_pt_gnu_prop.bz2 and
+	testfile_pt_gnu_prop32.bz2.
+
+2020-02-05  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfo-tars/*: New test files from Eli Schwartz of ArchLinux.
+	* Makefile.am (EXTRA_DIST): Package them.
+	* run-debuginfod-find.sh: Run basic archive extraction tests.
+
+2020-02-03  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Protect against missing curl & rpm2cpio.
+
+2020-01-19  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Check for proper groom completion count.
+
+2020-01-18  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test empty source_paths[].
+
+2020-01-08  Mark Wielaard  <mark@klomp.org>
+
+	* asm-test?.c: include libebl.h.
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test --fdcache* options.
+
+2020-01-11  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Adjust to new work-queue metrics.
+
+2020-01-02  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Set DEBUGINFOD_TIMEOUT to 10.
+
+2019-12-22  Frank Ch. Eigler  <fche@redhat.com>
+
+	* debuginfod-debs/*: New test files, based on
+	https://wiki.debian.org/Packaging/Intro.
+	* run-debuginfod-find.sh: Test deb file processing (if dpkg
+	installed).
+
+2019-12-04  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuinfod-find.sh: Test $DEBUGINFOD_PROGRESS.
+
+2019-12-11  Omar Sandoval  <osandov@fb.com>
+
+	* dwfl-report-segment-coalesce.c: New test.
+	* Makefile.am: Add dwfl-report-segment-coalesce
+
+2019-12-06  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Force -Wl,--build-id.
+
+2019-12-05  Mark Wielaard  <mark@klomp.org>
+
+	* run-findinfod-find.sh: Run strip under testrun.
+
+2019-12-06  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-data.c (main): Add break after assert.
+
+2019-12-05  Mark Wielaard  <mark@klomp.org>
+
+	* run-elfclassify.sh: Run elfcompress under testrun.
+
+2019-11-26  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (BUILD_STATIC): Add libraries needed for libdw.
+	* coverage.sh: Add debuginfod directory, check whether source
+	is .c or cxx.
+
+2019-11-24  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Reduce verbosity. Add new cleanup
+	function to use with trap. Add wait_ready function to query
+	metrics instead of sleeping. Calculate rpms and sourcefiles
+	to check.
+
+2019-11-23  Mark Wielaard  <mark@klomp.org>
+
+	* run-debuginfod-find.sh: Replace all localhost with 127.0.0.1.
+
+2019-11-07  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test debuginfod metrics via curl.
+	Fix federated testing, asserted by metrics.
+
+2019-11-06  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test debuginfod -L mode.  Drop
+	plain debuginfo-find help-output-comparison.
+
+2019-11-04  Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh: Test debuginfod-find -v progress mode.
+
+2019-10-28  Aaron Merey  <amerey@redhat.com>
+	    Frank Ch. Eigler  <fche@redhat.com>
+
+	* run-debuginfod-find.sh, debuginfod_build_id_find.c: New test.
+	* testfile-debuginfod-*.rpm.bz2: New data files for test.
+	* Makefile.am: Run it.
+
+2019-11-14  Andreas Schwab  <schwab@suse.de>
+
+	* run-large-elf-file.sh: Skip if available memory cannot be
+	determined.
+
+2019-11-14  Andreas Schwab  <schwab@suse.de>
+
+	* dwelf_elf_e_machine_string.c (main): Clear errno before calling
+	strtol.
+
+2019-09-02  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-s.sh: Add --dyn-syms case.
+
+2019-09-07  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (EXTRA_DIST): Add run-disasm-riscv64.sh,
+	testfile-riscv64-dis1.o.bz2 and testfile-riscv64-dis1.expect.bz2.
+
+2019-08-27  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-test2.sh: Add -x num testcase.
+
+2019-08-29  Mark Wielaard  <mark@klomp.org>
+
+	* test-subr.sh (self_test_files_exe): replace elfcmp, objdump and
+	readelf with elfclassify, stack and unstrip.
+	(self_test_files_lib): Replace libdw.so with libasm.so.
+
+2019-07-05  Omar Sandoval  <osandov@fb.com>
+
+	* Makefile.am: Remove -ldl.
+	* tests-subr.sh (self_test_files): Remove libebl_{i386,x86_64}.so.
+
+2019-07-26  Florian Weimer  <fweimer@redhat.com>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* run-elfclassify.sh: New test.
+	* run-elfclassify-self.sh: Likewise.
+	* Makefile.sh (TESTS): Add run-elfclassify.sh and
+	run-elfclassify-self.sh.
+	(EXTRA_DIST): Likewise.
+
+2019-07-16  Mao Han  <han_mao@c-sky.com>
+
+	* hello_csky.ko.bz2: New testfile.
+	* run-addrcfi.sh: Add C-SKY testfile.
+	* run-strip-reloc.sh: Likewise.
+	* testfilecsky.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add hello_csky.ko.bz2 and
+	testfilecsky.bz2.
+
+2019-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add dwelf_elf_e_machine_string.
+	(TESTS): Add run-dwelf_elf_e_machine_string.sh.
+	(EXTRA_DIST): Likewise.
+	(dwelf_elf_e_machine_string_LDADD): New variable.
+	* dwelf_elf_e_machine_string.c: New file.
+	* run-dwelf_elf_e_machine_string.sh: New test.
+
+2019-07-01  Mark Wielaard  <mark@klomp.org>
+
+	* run-large-elf-file.sh: Add 2GB to mem_needed when running under
+	valgrind.
+
+2019-06-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS): Add run-large-elf-file.sh.
+	(EXTRA_DIST): Likewise.
+	* addsections.c (add_sections): Add sec_size argument, use it
+	as the size of the section data.
+	(main): Handle extra sec_size argument. Pass to add_sections.
+	* run-large-elf-file.sh: New test.
+
+2019-06-03  Mark Wielaard  <mark@klomp.org>
+
+	* elfcopy.c (copy_elf): When swapping the sh_offsets of two sections,
+	make sure they are actually next to each other.
+
+2019-05-12  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add elfrdwrnop.
+	(TESTS): Add run-reverse-sections.sh and
+	run-reverse-sections-self.sh.
+	(EXTRA_DIST): Likewise.
+	(elfrdwrnop): New variable.
+	* elfcopy.c (copy_elf): Add reverse_off argument. Record offsets
+	of sections and swap them when possible.
+	(main): Check for --reverse-off argument. Pass reverse_offs to
+	copy_elf.
+	* run-reverse-sections.sh: New test.
+	* run-reverse-sections-self.sh: Likewise.
+	* elfrdwrnop.c: New file.
+
+2019-05-10  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS): Add run-readelf-discr.sh.
+	(EXTRA_DIST): Likewise and add testfile-rng.debug.bz2 and
+	testfile-urng.debug.bz2.
+	* run-readelf-discr.sh: New test.
+	* testfile-rng.debug.bz2: New test file.
+	* testfile-urng.debug.bz2: Likewise.
+
+2019-04-30  Mark Wielaard  <mark@klomp.org>
+
+	* xlate_notes.c: New file.
+	* run-xlate-note.sh: New test.
+	* Makefile.am (check_PROGRAMS): Add xlate_notes.
+	(TESTS): Add run-xlate-note.sh.
+	(EXTRA_DIST): Likewise.
+	(xlate_notes_LDADD): New variable.
+
+2019-04-30  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-dwarf.c (frame_callback): Explicitly check symname is
+	NULL.
+
+2019-04-30  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace.c (frame_callback): Explicitly check symname is NULL.
+
+2019-03-04  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace.c (tgkill): Remove define.
+
+2019-01-24  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (system_elf_libelf_test_CPPFLAGS): Guard by
+	!INSTALL_ELFH.
+
+2019-01-31  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-child.c (stdarg): Remove assert (errno == 0).
+	(main): Likewise.
+	* backtrace-data.c (maps_lookup): Likewise.
+	(set_initial_registers): Likewise.
+	(main): Likewise.
+	* backtrace.c (prepare_thread): Likewise.
+	(exec_dump): Likewise.
+
+2019-01-29  Yonghong Song  <yhs@fb.com>
+
+	* backtrace-data.c (maps_lookup): Use %*u, not %*x, to parse
+	inode number.
+
+2019-01-18  Ulf Hermann <ulf.hermann@qt.io>
+
+	* run-annobingroup.sh: Use different files for strip output.
+	* run-strip-test-many.sh: Use different files for strip output,
+	check results of strip, unstrip, elflint.
+
+2019-01-24  Mark Wielaard  <mark@klomp.org>
+
+	* addsections.c (add_sections): Change the name of the old shstrtab
+	section to ".old_shstrtab" and give the old shstrtab name to the
+	new shstrtab section.
+
+2019-01-09  Ulf Hermann <ulf.hermann@qt.io>
+
+	* run-readelf-compressed.sh: Skip if USE_BZIP2 not found.
+
+2018-12-27  Jim Wilson  <jimw@sifive.com>
+
+	* run-readelf-mixed-corenote.sh: Update with new riscv64 output.
+
+2018-12-02  Mark Wielaard  <mark@klomp.org>
+
+	* testfile_gnu_props.32le.o.bz2: New testfile.
+	* testfile_gnu_props.64le.o.bz2: Likewise.
+	* testfile_gnu_props.32be.o.bz2: Likewise.
+	* testfile_gnu_props.64be.o.bz2: Likewise.
+	* Makefile (EXTRA_DIST): Add new testfiles.
+	* run-readelf-n.sh: Run tests on new testfiles.
+
+2018-11-28  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-data.c (main): Improve error message.
+	* run-backtrace-data.sh: Skip exit 77 return.
+
+2018-11-21  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-subr.sh (check_unsupported): Call test_cleanup before
+	exit.
+
+2018-11-17  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-version.sh: New test.
+	* testfile-version.bz2: New test file.
+	* Makefile.am (TESTS): Add run-strip-version.sh.
+	(EXTRA_DIST): Add run-strip-version.sh and testfile-version.bz2.
+
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-reloc.sh: Also test testfile-debug-rel-ppc64-z.o
+	testfile-debug-rel-ppc64-g.o.
+
+2018-11-12  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-n.sh: Add testfile-annobingroup.o test.
+
+2018-11-11  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-n.sh: Fix NT_GNU_ABI_TAG type. Add testfile11 test
+	for NT_VERSION.
+
+2018-11-04  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-bpf-reloc.expect.bz2: Update with new expected jump
+	variants.
+
+2018-10-20  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-compressed.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-compressed.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-11-09  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-debug-rel-ppc64-g.o.bz2: New test file.
+	* testfile-debug-rel-ppc64-z.o.bz2: Likewise.
+	* testfile-debug-rel-ppc64.o.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfile-debug-rel-ppc64-g.o.bz2,
+	testfile-debug-rel-ppc64-z.o.bz2 and testfile-debug-rel-ppc64.o.bz2.
+	* run-strip-reloc.sh: Also test on testfile-debug-rel-ppc64.o.
+	* run-readelf-zdebug-rel.sh: Also test on testfile-debug-rel-ppc64*.o.
+
+2018-10-26  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-reloc.sh: Add a test for --reloc-debug-sections-only.
+
+2018-10-18  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-n.sh: New test.
+	* testfile-gnu-property-note.bz2: New testfile.
+	* testfile-gnu-property-note.o.bz2: Likewise.
+	* Makefile.am (TESTS): Add run-readelf-n.sh.
+	(EXTRA_DIST): Likewise and testfile-gnu-property-note.bz2,
+	testfile-gnu-property-note.o.bz2.
+
+2018-10-12  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-zdebug.sh: Adjust flags output.
+	* run-readelf-macro.sh: Likewise.
+	* run-readelf-macros.sh: New test.
+	* testfile-macros-object.o.bz2: New test file.
+	* Makefile.am (TESTS): Add run-readelf-macros.sh.
+	(EXTRA_DIST): Add run-readelf-macros.sh and
+	testfile-macros-object.o.bz2.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* run-annobingroup.sh: Add x86_64 ET_REL testcase.
+	* testfile-annobingroup-x86_64.o.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfile-annobingroup-x86_64.o.bz2.
+
+2018-09-18  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-dwarf.c (thread_callback): Only error when
+	dwfl_thread_getframes returns an error.
+	(main): Don't call abort or assert but print an error when
+	something unexpected happens.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-test-many.sh: New test.
+	* Makefile.am (TESTS): Add run-strip-test-many.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* run-typeiter-many.sh: New test.
+	* Makefile.am (TESTS): Add run-typeiter-many.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-09-13  Mark Wielaard  <mark@klomp.org>
+
+	* run-copymany-sections.sh: New test.
+	* Makefile.am (TESTS): Add run-copymany-sections.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-09-12  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add elfcopy and addsections.
+	(TESTS): Add run-copyadd-sections.sh.
+	(EXTRA_DIST): Likewise.
+	(elfcopy_LDADD): New variable.
+	(addsections_LDADD): Likewise.
+	* addsections.c: New file.
+	* elfcopy.c: Likewise.
+	* run-copyadd-sections.sh: New test.
+
+2018-09-11  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-dwarf.c (main): Add section attribute.
+
+2018-07-24  Mark Wielaard  <mark@klomp.org>
+
+	* run-annobingroup.sh: Add testfile-annobingroup-i386.o tests.
+	* testfile-annobingroup-i386.o.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfile-annobingroup-i386.o.bz2.
+
+2018-07-21  Mark Wielaard  <mark@klomp.org>
+
+	* run-annobingroup.sh: New test.
+	* testfile-annobingroup.o.bz2: New test file.
+	* Makefile.am (TESTS): Add run-annobingroup.sh.
+	(EXTRA_DIST): Add run-annobingroup.sh and
+	testfile-annobingroup.o.bz2.
+
+2018-07-19  Andreas Schwab  <schwab@suse.de>
+
+	* Makefile.am (TESTS): Add run-strip-test12.sh.
+	(EXTRA_DIST): Add run-strip-test12.sh, testfile-riscv64.bz2,
+	testfile-riscv64-s.bz2, testfile-riscv64-core.bz2.
+	(run-strip-test11.sh): New file.
+	(testfile-riscv64.bz2): New file.
+	(testfile-riscv64-s.bz2): New file.
+	(testfile-riscv64-core.bz2): New file.
+	* run-allregs.sh: Add test for testfile-riscv64-core.
+	* run-readelf-mixed-corenote.sh: Likewise.
+
+2018-07-16  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* run-strip-reloc.sh: Remove previous testfiles before running the
+	next test.
+
+2018-07-17  Mark Wielaard  <mark@klomp.org>
+
+	* hello_riscv64.ko.bz2: Updated with debuginfo.
+	* run-strip-reloc.sh: Add documentation on CONFIG_DEBUG_INFO=y.
+
+2018-07-05  Mark Wielaard  <mark@klomp.org>
+
+	* next_cfi.c (handle_section): Take a new argument name. Check
+	whether the section is compressed and uncompress if so.
+	(main): Check also for .zdebug_frame and pass the name of the
+	section to handle_section.
+
+2018-07-04  Ross Burton <ross.burton@intel.com>
+
+	* addrscopes.c: Remove error.h include, add system.h include.
+	* allregs.c: Likewise.
+	* backtrace-data.c: Likewise.
+	* backtrace-dwarf.c: Likewise.
+	* backtrace.c: Likewise.
+	* buildid.c: Likewise.
+	* debugaltlink.c: Likewise.
+	* debuglink.c: Likewise.
+	* deleted.c : Likewise.
+	* dwarfcfi.c: Likewise.
+	* dwfl-addr-sect.c: Likewise.
+	* dwfl-bug-addr-overflow.c: Likewise.
+	* dwfl-bug-fd-leak.c: Likewise.
+	* dwfl-bug-getmodules.c: Likewise.
+	* dwfl-proc-attach.c: Likewise.
+	* dwfl-report-elf-align.c: Likewise.
+	* dwfllines.c: Likewise.
+	* dwflmodtest.c: Likewise.
+	* dwflsyms.c: Likewise.
+	* early-offscn.c: Likewise
+	* ecp.c: Likewise.
+	* elfstrmerge.c: Likewise.
+	* find-prologues.c: Likewise.
+	* funcretval.c: Likewise.
+	* funcscopes.c: Likewise.
+	* getsrc_die.c: Likewise.
+	* line2addr.c: Likewise.
+	* low_high_pc.c: Likewise.
+	* next_cfi.c: Likewise.
+	* rdwrmmap.c: Likewise.
+	* saridx.c: Likewise.
+	* sectiondump.c: Likewise.
+	* varlocs.c: Likewise.
+	* vdsosyms.c: Likewise.
+
+2018-06-28  Mark Wielaard  <mark@klomp.org>
+
+	* next_cfi.c: New file.
+	* run-next-cfi.sh: New test.
+	* run-next-cfi-self.sh: Likewise.
+	* Makefile.am (check_PROGRAMS): Add next_cfi.
+	(TESTS): Add run-next-cfi.sh and run-next-cfi-self.sh.
+	(EXTRA_DIST): Likewise.
+	(next_cfi_LDADD): New variable.
+
+2018-06-27  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf_cfi.c: New file.
+	* run-dwarfcfi.sh: New test.
+	* testfile11-debugframe.bz2: New testfile.
+	* testfile12-debugframe.bz2: Likewise.
+	* testfileaarch64-debugframe.bz2: Likewise.
+	* testfilearm-debugframe.bz2: Likewise.
+	* testfileppc32-debugframe.bz2: Likewise.
+	* testfileppc64-debugframe.bz2: Likewise.
+	* Makefile.am (check_PROGRAMS): Add dwarfcfi.
+	(TESTS): Add run-dwarfcfi.sh.
+	(EXTRA_DIST): Add run-dwarfcfi.sh, testfile11-debugframe.bz2,
+	testfile12-debugframe.bz2, testfileaarch64-debugframe.bz2,
+	testfilearm-debugframe.bz2, testfileppc32-debugframe.bz2 and
+	testfileppc64-debugframe.bz2.
+
+2018-06-23  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (print_expr): Take a new depth argument. Check it isn't
+	greater than MAX_DEPTH (64). Pass on to print_expr_block.
+	(print_expr_block): Take a new depth argument. Pass it to print_expr.
+	(print_expr_block_addrs): Call print_expr_block with zero depth.
+
+2018-06-25  Mark Wielaard  <mark@klomp.org>
+
+	* next-files.c: New file.
+	* next-lines.c: Likewise.
+	* run-next-files.sh: New test.
+	* run-next-lines.sh: Likewise.
+	* testfile-only-debug-line.bz2: New test file.
+	* Makefile.am (check_PROGRAMS): Add next-files and next-lines.
+	(TESTS): Add run-next-files.sh and run-next-lines.sh.
+	(EXTRA_DIST): Add run-next-files.sh, run-next-lines.sh and
+	testfile-only-debug-line.bz2.
+	(next_lines_LDADD): New variable.
+	(next_files_LDADD): Likewise.
+
+2018-06-16  Yonghong Song  <yhs@fb.com>
+
+	* run-reloc-bpf.sh: New test.
+	* testfile-bpf-reloc.o.bz2: New test file.
+	* testfile-bpf-reloc.expect.bz2: New test file.
+	* Makefile.am (TESTS): Add run-reloc-bpf.sh.
+	(EXTRA_DIST): Add run-reloc-bpf.sh, testfile-bpf-reloc.o.bz2 and
+	testfile-bpf-reloc.expect.bz2.
+
+2018-06-13  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-const-values.sh: New test.
+	* testfile-const-values.debug.bz2: New test file.
+	* run-readelf-zdebug-rel.sh: Adjust expected const_value.
+	* Makefile.am (TESTS): Add run-readelf-const-values.sh.
+	(EXTRA_DIST): Add run-readelf-const-values.sh and
+	testfile-const-values.debug.bz2.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (print_expr): Error on bad DW_OP_GNU_parameter_ref
+	target, do not assert.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* get-units-invalid.c (main): Check invalid dwarf_getabbrev call.
+	* show-abbrev.c (main): Check illegal dwarf_getabbrev offset call.
+
+2018-06-08  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (main): Only assert when cfi_debug_bias != 0 if there
+	actually is a cfi_debug.
+
+2018-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-loc.sh: Fix expected output for startx_length.
+
+2018-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (print_base_type): Use error, not assert when the DIE
+	isn't a base type.
+
+2018-06-02  Mark Wielaard  <mark@klomp.org>
+
+	* test-subr.sh (self_test_files_exe): Drop shared libraries.
+	Keep addr2line, elfcmp, objdump and readelf.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-types.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-types.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* splitdwarf4-not-split4.dwo.bz2: New test file.
+	* testfile-splitdwarf4-not-split4.debug.bz2: Likewise.
+	* run-readelf-loc.sh: Add test for splitdwarf4-not-split4.dwo
+	and testfile-splitdwarf4-not-split4.debug.
+	* run-varlocs.sh: Test testfile-splitdwarf4-not-split4.debug.
+	* Makefile.am (EXTRA_DIST): Add splitdwarf4-not-split4.dwo.bz2
+	and testfile-splitdwarf4-not-split4.debug.bz2.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* test-subr.sh (self_test_files): Split into self_test_files_exe,
+	self_test_files_lib and self_test_obj.
+	(testrun_on_self_exe): New function.
+	(testrun_on_self_lib): Likewise.
+	* run-get-units-split.sh: Replace testrun_on_self with
+	testrun_on_self_exe and testrun_on_self_lib.
+	* run-unit-info.sh: Likewise.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* low_high_pc.c (handle_die): Handle NULL name. Print offset and
+	name of die.
+	(main): Check if the cu DIE is a skeleton, then get and handle
+	the split subdie.
+	* run-low-high-pc.sh: Run on testfile-splitdwarf-4 and
+	testfile-splitdwarf-5. Run on all selftest files.
+
+2018-05-31  Mark Wielaard  <mark@klomp.org>
+
+	* get-units-invalid.c (main): Check dwarf_cuoffset and
+	dwarf_dieoffset.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf-die-addr-die.c (check_dbg): Also check subdies, split or
+	type, gotten through dwarf_get_units.
+	* run-dwarf-die-addr-die.sh: Add tests for dwarf-4, dwarf-5,
+	split-dwarf-4, split-dwarf-5 and dwo files.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-loc.sh: Add GNU DebugFission split-dwarf variant.
+	* run-varlocs.sh: Likewise.
+
+2018-05-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-twofiles.sh: Add --debug-dump=loc testcase.
+
+2018-05-28  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-info-plus.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-info-plus.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-04-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-addr.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-addr.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-04-27  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-ranges.sh: Adjust expected output for address base.
+	* run-readelf-addr.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-addr.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-04-07  Mark Wielaard  <mark@klomp.org>
+
+	* run-varlocs.sh: Run on testfileranges5.debug and
+	testsplitfileranges5.debug.
+	* varlocs.c (is_debug): New bool.
+	(print_expr): Don't fail on missing CFI for is_debug.
+	(main): Parse --debug, set is_debug.
+
+2018-04-12  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-loc.sh: Add new testcases.
+
+2018-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* testfileranges5.debug.bz2: New testfile.
+	* testfilesplitranges5.debug.bz2: Likewise.
+	* testfile-ranges-hello5.dwo.bz2: Likewise.
+	* testfile-ranges-world5.dwo.bz2: Likewise.
+	* run-dwarf-ranges.sh: Run on testfileranges5.debug.
+	* run-all-dwarf-ranges.sh: Run on testfilesplitranges5.debug.
+	* tests/Makefile.am (EXTRA_DIST): Add testfileranges5.debug.bz2,
+	testfilesplitranges5.debug.bz2, testfile-ranges-hello5.dwo.bz2 and
+	testfile-ranges-world5.dwo.bz2.
+
+2018-04-11  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-ranges.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-ranges.sh.
+	(EXTRA_DIST): Likewise.
+
+2018-05-21  Mark Wielaard  <mark@klomp.org>
+
+	* addrx_constx-4.dwo.bz2: New testfile.
+	* addrx_constx-5.dwo.bz2: Likewise.
+	* testfile-addrx_constx-4.bz2: Likewise.
+	* testfile-addrx_constx-5.bz2: Likewise
+	* Makefile.am (EXTRA_DIST): Add addrx_constx-5.dwo.bz2
+	testfile-addrx_constx-4\ .bz2 testfile-addrx_constx-5.bz2.
+	* run-varlocs.sh: Add addrx_constx tests for DWARF4 and DWARF5.
+	* varlocx.c (print_expr): Handle DW_OP_GNU_addr_index,
+	DW_OP_addrx, DW_OP_GNU_const_index and DW_OP_constx.
+	(main): Handle split DWARF.
+	* run-all-dwarf-ranges.sh: Add new ranges for addrx low/highpc.
+
+2018-05-20  Mark Wielaard  <mark@klomp.org>
+
+	* unit-info.c: New test.
+	* run-unit-info.sh: New test runner.
+	* Makefile.am (check_PROGRAMS): Add unit-info.
+	(TESTS): Add run-unit-info.sh
+	(EXTRA_INFO): Likewise.
+	(unit_info_LDADD): New variable.
+
+2018-05-24  Mark Wielaard  <mark@klomp.org>
+
+	* get-units-invalid.c (main): Add check for invalid dwarf_ranges.
+	* run-all-dwarf-ranges.sh: Correct expected output.
+
+2018-05-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefiles.am (check_PROGRAMS): Add all-dwarf-ranges.
+	(TESTS): Add run-all-dwarf-ranges.sh.
+	(EXTRA_DIST): Add run-all-dwarf-ranges.sh,
+	testfilesplitranges4.debug.bz2, testfile-ranges-hello.dwo.bz2
+	and testfile-ranges-world.dwo.bz2.
+	(all_dwarf_ranges_LDADD): New variable.
+	* all-dwarf-ranges.c: New test program.
+	* run-all-dwarf-ranges: New test runner.
+	* testfile-ranges-hello.dwo.bz2: New test file.
+	* testfile-ranges-world.dwo.bz2: Likewise.
+	* testfilesplitranges4.debug.bz2: Likewise.
+
+2018-05-18  Mark Wielaard  <mark@klomp.org>
+
+	* run-get-files.sh: Add testcases for testfile-splitdwarf-4,
+	testfile-hello4.dwo, testfile-world4.dwo and testfile-splitdwarf-5,
+	testfile-hello5.dwo, testfile-world5.dwo.
+
+2018-05-17  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add attr-integrate-skel.
+	(TESTS): Add run-attr-integrate-skel.
+	(EXTRA_DIST): Likewise.
+	(attr_integrate_skel_LDADD): New variable.
+	* attr-integrate-skel.c: New test.
+	* run-attr-integrate-skel.sh: New test runner.
+
+2018-05-16  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add get-units-split.
+	(TESTS): Add run-get-units-split.sh.
+	(EXTRA_DIST): Add run-get-units-split.sh, testfile-hello4.dwo.bz2,
+	testfile-hello5.dwo.bz2, testfile-splitdwarf-4.bz2,
+	testfile-splitdwarf-5.bz2, testfile-world5.dwo.bz2 and
+	testfile-world4.dwo.bz2.
+	(get_units_split_LDADD): New variable.
+	* get-units-split.c: New test.
+	* run-get-units-split.sh: New test runner.
+	* testfile-dwarf-45.source: Extend with build instructions for new
+	test files.
+	* testfile-hello4.dwo.bz2: New test file.
+	* testfile-hello5.dwo.bz2: Likewise.
+	* testfile-splitdwarf-4.bz2: Likewise.
+	* testfile-splitdwarf-5.bz2: Likewise.
+	* testfile-world5.dwo.bz2 and: Likewise.
+	* testfile-world4.dwo.bz2: Likewise.
+
+2018-05-09  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-zdebug.sh: Adjust test output for new header layout.
+	* run-readelf-line.sh: Likewise. Add new tests for testfile-dwarf-4
+	and testfile-dwarf-5.
+
+2018-05-11  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add get-units-invalid.
+	(TESTS): Add run-get-units-invalid.sh.
+	(EXTRA_DIST): Likewise.
+	(get_units_invalid_LDADD): New variable.
+	* get-units-invalid.c: New test program.
+	* run-get-units-invalid.sh: New test program runner.
+
+2018-05-05  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-dwarf-45.source: New file.
+	* testfile-dwarf-4.bz2: New test file.
+	* testfile-dwarf-5.bz2: Likewise.
+	* run-readelf-line.sh: Add testcases for testfile-dwarf-4 and
+	testfile-dwarf-5.
+	* Makefile (EXTRA_DIST): Add testfile-dwarf-45.source,
+	testfile-dwarf-4.bz2 and testfile-dwarf-5.bz2.
+
+2018-04-19  Andreas Schwab  <schwab@suse.de>
+
+	* hello_riscv64.ko.bz2: New file.
+	* run-strip-reloc.sh: Test it.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2018-04-16  Mark Wielaard  <mark@klomp.org>
+
+	* testfile-ppc64-min-instr.bz2: New testfile.
+	* run-readelf-line.sh: Run against testfile-ppc64-min-instr.bz2.
+	* Makefile.am (EXTRA_DIST): Add testfile-ppc64-min-instr.bz2.
+
+2018-04-11  Mark Wielaard  <mark@klomp.org>
+
+	* run-addrcfi.sh: Adjust expected rule for aarch64 sp.
+
+2018-04-03  Mark Wielaard  <mark@klomp.org>
+
+	* testfileranges4.debug.bz2: New testfile.
+	* run-dwarf-ranges.sh: Run on testfileranges4.debug.
+	* tests/Makefile.am (EXTRA_DIST): Add testfileranges4.debug.bz2.
+
+2018-03-06  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (print_expr): Handle DW_OP_implicit_pointer,
+	DW_OP_entry_value, DW_OP_convert, DW_OP_reinterpret,
+	DW_OP_regval_type, DW_OP_deref_type, DW_OP_xderef_type and
+	DW_OP_const_type.
+
+2018-02-16  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-subr.sh (check_native_core): Check if there is any core,
+	if so, use it.
+
+2018-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-child.c: Include signal.h after sys/ptrace.h.
+	* backtrace-dwarf.c: Include sys/wait.h and signal.h after
+	sys/ptrace.h.
+
+2018-01-25  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (check_PROGRAMS): Add dwarf-die-addr-die.
+	(TESTS): Add run-dwarf-die-addr-die.sh.
+	(EXTRA_DIST): Likewise.
+	(dwarf_die_addr_die_LDADD): New variable.
+	* dwarf-die-addr-die.c: New file.
+	* run-dwarf-die-addr-die.sh: New test.
+
+2018-02-09  Joshua Watt  <JPEWhacker@gmail.com>
+
+	* elfstrmerge.c (main): Use FALLTHROUGH macro instead of comment.
+
+2018-01-22  Mark Wielaard  <mark@klomp.org>
+
+	* allfcts.c (setup_alt): Print warning when alt file couldn't be
+	found.
+	* run-allfcts-multi.sh: Add testcase where alt file is in a subdir
+	where it cannot be found by allfcts itself (but it can by libdw).
+
+2018-01-25  Mark Wielaard  <mark@klomp.org>
+
+	* elfstrmerge.c (main): Initialize and check symtabshdr instead of
+	symtabndx.
+
+2018-01-14  Petr Machata  <pmachata@gmail.com>
+
+	* testfile-sizes4.o.bz2: New test file.
+	* testfile-sizes4.s: New test source.
+	* run-aggregate-size.sh: Check testfile-sizes4.o v size 257.
+
+2017-12-23  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-subr.sh (check_native_core): Use a lock file and try
+	to extract core using coredumpctl.
+	* Makefile.am (CLEANFILES): Clean core-dump-backtrace.lock.
+
+2017-12-11  Dima Kogan  <dima@secretsauce.net>
+
+	* run-aggregate-size.sh: Added check for multi-dimensional arrays.
+	* run-peel-type.sh: Likewise.
+	* testfile-sizes3.o.bz2: Likewise.
+
+2017-12-07  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-variant.sh: New test.
+	* testfile-ada-variant.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-readelf-variant.sh.
+	(EXTRA_DISTS): Add run-readelf-variant.sh and
+	testfile-ada-variant.bz2.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-loc.sh: Adjust expected loc list output.
+	* run-readelf-zdebug-rel.sh: Likewise.
+	* run-readelf-zdebug.sh: Likewise.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-loc.sh: Adjust expected range list output.
+	* run-readelf-zdebug.sh: Likewise.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-dwz-multi.sh: Add expected file names.
+	* run-readelf-zdebug-rel.sh: Likewise.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-dwz-multi.sh: Add expected abbrev codes.
+	* run-readelf-zdebug-rel.sh: Likewise.
+
+2017-11-29  Mark Wielaard  <mark@klomp.org>
+
+	* run-readelf-dwz-multi.sh: Adjust expected ops index spaces.
+	* run-readelf-loc.sh: Likewise.
+	* run-readelf-zdebug-rel.sh: Likewise.
+	* run-readelf-zdebug.sh: Likewise.
+
+2017-11-16  Mark Wielaard  <mark@klomp.org>
+
+	* varlocs.c (main): Fix cfi_debug => cfi_debug_bias typo in assert.
+
+2017-11-10  Mark Wielaard  <mark@klomp.org>
+
+	* run-exprlocs-self.sh: New test.
+	* run-varlocs-self.sh: Likewise.
+	* Makefile.am (TESTS) Add run-exprlocs-self.sh and
+	run-varlocs-self.sh.
+	(EXTRA_DIST): Likewise.
+	* varlocs.c (cfi_debug_bias): New global variable.
+	(is_ET_REL): Likewise.
+	(print_expr): Don't crash and burn when CFI cannot be found for an
+	ET_REL file for DW_OP_call_frame_cfa.
+	(handle_die): If there is no entry_pc pick the lowest pc start range
+	for the DIE.
+	(main): Check at least one CU was found. Use dwfl_module_dwarf_cfi
+	and dwfl_module_eh_cfi to fix memory leak. Set is_ET_REL.
+
+2017-11-03  Mark Wielaard  <mark@klomp.org>
+
+	* run-exprlocs.sh: New test.
+	* testfile-stridex.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-exprlocs.sh.
+	(EXTRA_DIST): Add run-exprlocs.sh and testfile-stridex.bz2.
+	* varlocs.c (dwarf_tag_string): New function.
+	(dwarf_attr_string): Likewise.
+	(dwarf_form_string): Likewise.
+	(print_expr): Fix typo in error message.r
+	Handle DW_OP_GNU_variable_value.
+	(attr_arg): New struct.
+	(handle_attr): New function.
+	(handle_die): Likewise.
+	(main): Handle --exprlocs argument. Call handle_die.
+
+2017-10-16  Mark Wielaard  <mark@klomp.org>
+
+	* md5-sha1-test.c: Removed.
+	* Makefile.am (check_PROGRAMS): Remove md5-sha1-test.
+	(TESTS): Likewise.
+	(md5_sha1_test_LDADD): Removed.
+
+2017-10-04  Mark Wielaard  <mark@klomp.org>
+
+	* msg_tst.c: Handle ELF_E_INVALID_ELF.
+
+2017-09-10  Mark Wielaard  <mark@klomp.org>
+
+	* run-ar.sh: New test.
+	* Makefile.am (TESTS): Add run-ar.sh.
+	(EXTRA_DIST): Likewise.
+
+2017-08-18  Ulf Hermann <ulf.hermann@qt.io>
+
+	* Makefile.am: Drop -rdynamic from deleted_lib_so_LDFLAGS.
+
+2017-04-27  Ulf Hermann <ulf.hermann@qt.io>
+
+	* Makefile.am: Use fpie_CFLAGS and fpic_CFLAGS.
+
+2017-08-08  Dmitry V. Levin <ldv@altlinux.org>
+
+	* run-strip-nothing.sh: Add -s.
+
+2017-07-26  Mark Wielaard  <mark@klomp.org>
+
+	* dwarf-getmacros.c (mac): Use DW_MACRO names instead of DW_MACRO_GNU.
+
+2016-10-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwarf_default_lower_bound.c: New test.
+	* Makefile.am (check_PROGRAMS): Add dwarf_default_lower_bound.
+	(TESTS): Likewise.
+	(dwarf_default_lower_bound_LDADD): New variable.
+
+2017-07-21  Mark Wielaard  <mark@klomp.org>
+
+	* get-lines.c (main): Add dwarf_line_file test.
+
+2017-07-19  Gustavo Romero <gromero@linux.vnet.ibm.com>
+
+	* run-addrcfi.sh: Update generic SPRs names to HTM SPRs names
+	* run-allregs.sh: Update generic SPRs names to HTM SPRs names
+
+2017-07-20  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-g.sh: New test.
+	* Makefile.am (TESTS): Add run-strip-g.sh.
+	(EXTRA_DIST): Likewise.
+
+2017-07-18  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (TESTS): Always add run-disasm-bpf.sh if HAVE_LIBASM.
+
+2017-05-04  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* elfshphehdr.c: For writing, use /dev/null rather than /dev/zero.
+
+2017-07-14  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-remove-keep.sh: New test.
+	* Makefile.am (TESTS): Add run-strip-remove-keep.sh.
+	(EXTRA_DIST): Likewise.
+
+2017-06-07  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-nothing.sh: New test.
+	* Makefile.am (TESTS): Add run-strip-nothing.sh.
+	(EXTRA_DIST): Likewise.
+
+2017-06-06  Mark Wielaard  <mark@klomp.org>
+
+	* run-strip-test.sh: Test strip -g doesn't introduce extra .shstrtab.
+
+2017-05-30  Mark Wielaard  <mark@klomp.org>
+
+	* run-backtrace-fp-core-ppc64le.sh: New test.
+	* backtrace.ppc64le.fp.core.bz2: New test file.
+	* backtrace.ppc64le.fp.exec.bz2: New testfile.
+	* backtrace-subr.sh (check_backtracegen): Accept '(null)'.
+	* Makefile.am (TESTS): Add run-backtrace-fp-core-ppc64le.sh.
+	(EXTRA_DIST): Add run-backtrace-fp-core-ppc64le.sh,
+	backtrace.ppc64le.fp.core.bz2 and backtrace.ppc64le.fp.exec.bz2.
+
+2017-02-13  Ulf Hermann  <ulf.hermann@qt.io>
+	    Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am: Add test for unwinding with frame pointers on aarch64
+	* backtrace.aarch64.fp.core.bz2: New file
+	* backtrace.aarch64.fp.exec.bz2: New file
+	* run-backtrace-fp-core-aarch64.sh: New file
+	* backtrace-subr.sh (check_err): Allow Invalid register.
+	* backtrace.c (callback_verify): Allow duplicate_sigusr2 frames.
+
+2017-04-06  Mark Wielaard  <mark@klomp.org>
+
+	* run-backtrace-fp-core-i386.sh: New test.
+	* backtrace.i386.fp.core.bz2: New test file.
+	* backtrace.i386.fp.exec.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-backtrace-fp-core-i386.sh.
+	(EXTRA_DIST): Add run-backtrace-fp-core-i386.sh,
+	backtrace.i386.fp.core.bz2 and backtrace.i386.fp.exec.bz2.
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* Makefile.am: Add test for unwinding with frame pointers on x86_64
+	* backtrace.x86_64.fp.core.bz2: New file
+	* backtrace.x86_64.fp.exec.bz2: New file
+	* run-backtrace-fp-core-x86_64.sh: New file
+
+2017-04-25  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace-subr.sh (check_backtracegen): New function.
+	(check_core): Add check_backtracegen call.
+	* backtrace.ppc.exec.bz2: Regenerated.
+	* backtrace.ppc.core.bz2: Likewise.
+
+2017-04-24  Mark Wielaard  <mark@klomp.org>
+
+	* backtrace.c: Remove option to allow unknown symbols in the trace.
+	* backtrace-substr.sh: Remove option to allow unknown symbols
+	to check_core() and allow failed symbol lookups in check_err().
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* run-readelf-dwz-multi.sh: Expect readelf to output "yes" for flags
+	that are set.
+	* run-readelf-zdebug-rel.sh: Likewise.
+
+2017-04-20  Ulf Hermann <ulf.hermann@qt.io>
+
+	* backtrace-child.c: Include sys/ptrace.h only on linux.
+	* backtrace-dwarf.c: Likewise.
+
+2017-04-05  Mark Wielaard  <mark@klomp.org>
+
+	* test-subr.sh (testrun_on_self_compressed): New function.
+	* run-elflint-self.sh: Call testrun_on_self_compressed.
+	* run-elflint-test.sh: Add testfile42z and testfile-s390x-hash-bothz.
+
+2017-03-30  Mark Wielaard  <mark@klomp.org>
+
+	* peel_type.c: New file.
+	* run-peel-type.sh: New test.
+	* Makefile.am (check_PROGRAMS): Add peel_type.c.
+	(TESTS): Add run-peel-type.sh.
+	(EXTRA_DIST): Likewise.
+	(peel_type_LDADD): New variable.
+
+2017-03-27  Mark Wielaard  <mark@klomp.org>
+
+	* fillfile.c: New file.
+	* Makefile.am (check_PROGRAMS): Add fillfile.
+	(TESTS): Likewise.
+	(fillfile_LDADD): New variable.
+
+2017-02-15  Mark Wielaard  <mark@klomp.org>
+
+	* Makefile.am (EXTRA_DIST): Add testfileppc64attrs.o.bz2.
+	* run-readelf-A.sh: Add testfileppc64.o test.
+
+2017-02-15  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* elfstrmerge.c: Include system.h.
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* backtrace.c: Add an option to allow unknown symbols in the trace
+	* backtrace-substr.sh: Add an option to allow unknown symbols
+	to check_core() and allow failed symbol lookups in check_err()
+
+2017-02-09  Ulf Hermann  <ulf.hermann@qt.io>
+
+	* backtrace-data.c: Don't assert that symbols are found.
+	The unwinder is allowed to ask for invalid addresses. We deny
+	such requests, rather than make the test fail.
+
+2016-11-17  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-s.sh: Add --symbols=.dynsym and --symbols=.symtab tests.
+
+2016-11-02  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-data.c (thread_callback): Add explicit break after error.
+	* backtrace.c (callback_verify): Change PASSTHRU to FALLTHRU.
+
+2016-10-22  Kevin Cernekee  <cernekee@chromium.org>
+
+	* Makefile.am (TESTS): Add run-unstrip-test4.sh.
+	(EXTRA_DIST): Add run-unstrip-test4.sh, testfile-strtab.bz2,
+	testfile-strtab.stripped.bz2, testfile-strtab.debuginfo.bz2.
+	(run-unstrip-test4.sh): New file.
+	(testfile-strtab.bz2): New file.
+	(testfile-strtab.stripped.bz2): New file.
+	(testfile-strtab.debuginfo.bz2): New file.
+
+2016-10-11  Akihiko Odaki  <akihiko.odaki.4i@stu.hosei.ac.jp>
+
+	* arextract.c: Remove sys/param.h include, add system.h include.
+
+2016-08-30  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (asm_tst?_LDADD): Add libdw.
+
+2016-08-25  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-child.c: Disable and add documentation about why we disable
+	RAISE_JMP_PATCHING even on x86_64.
+	* backtrace.c (is_x86_64_native): Rename to...
+	(use_raise_jmp_patching): ... this.
+	(callback_verify): Use use_raise_jmp_patching instead of
+	is_x86_64_native.
+	(see_exec_module): Return DWARF_CB_ABORT after finding the correct exe
+	path.
+	(prepare_thread): Use RAISE_JMP_PATCHING instead of __x86_64__
+	conditional.
+	(exec_dump): Only assert on data.mod != NULL. Drop ptrdiff. Use
+	RAISE_JMP_PATCHING instead of __x86_64__ conditional. Use
+	use_raise_jmp_patching instead of is_x86_64_native.
+
+2016-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add testfilesparc64attrs.o.bz2.
+
+2016-08-09  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* testfilesparc64attrs.o.bz2: New file.
+	* run-readelf-A.sh: Check attributes in a sparc object.
+
+2016-08-06  Mark Wielaard  <mjw@redhat.com>
+
+	* run-strip-reloc.sh: Add explicit compressed and uncompressed
+	test cases.
+
+2016-08-10  Richard Henderson  <rth@redhat.com>
+
+	* file-bpf-dis1.expect.bz2: Fix expected mod and endian operations
+	output.
+
+2016-07-08  Mark Wielaard  <mjw@redhat.com>
+
+	* update3_LDADD: Use libdw instead of libebl.
+	* update4_LDADD: Likewise.
+	* alldts_LDADD: Likewise.
+	* elfstrmerge_LDADD: Likewise.
+	* alldts.c (main): Use dwelf_strtab instead of ebl_strtab.
+	* elfstrmerge.c (release): Likewise.
+	(main): Likewise.
+	* update3.c (main): Likewise.
+	* update4.c (main): Likewise.
+
+2016-07-10  Andreas Schwab  <schwab@linux-m68k.org>
+
+	* Makefile.am (TESTS): Add run-strip-test11.sh.
+	(EXTRA_DIST): Add run-strip-test11.sh, hello_m68k.ko.bz2,
+	testfile-m86k-core.bz2, testfile-m68k.bz2, testfile-m68k-s.bz2.
+	(run-strip-test11.sh): New file.
+	(hello_m68k.ko.bz2): New file.
+	(testfile-m68k-core.bz2): New file.
+	(testfile-m68k.bz2): New file.
+	(testfile-m68k-s.bz2): New file.
+	* run-allregs.sh: Add test for testfile-m68k-core.
+	* run-readelf-mixed-corenote.sh: Likewise.
+	* run-strip-reloc.sh: Add test for hello_m68k.ko.
+
+2016-07-06  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add vendorelf.
+	(TESTS): Likewise.
+	(vendorelf_LDADD): New variable.
+	* vendorelf.c: New test.
+	* elfshphehdr.c (test): Check elf_getphdrnum succeeds.
+
+2016-06-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add emptyfile.
+	(TESTS): Likewise.
+	(emptyfile_LDADD): New variable.
+	* emptyfile.c: New test.
+
+2016-06-28  Richard Henderson  <rth@redhat.com>
+
+	* Makefile.am (TESTS): Add run-disasm-bpf.sh, conditionally.
+	(EXTRA_DIST): Add run-disasm-bpf.sh, testfile-bpf-dis1.expect.bz2,
+	testfile-bpf-dis1.o.bz2
+	(run-disasm-bpf.sh): New file.
+	(testfile-bpf-dis1.expect.bz2): New file.
+	(testfile-bpf-dis1.o.bz2): New file.
+
+2016-02-09  Mark Wielaard  <mjw@redhat.com>
+
+	* testfile-s390x-hash-both.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfile-s390x-hash-both.bz2.
+	* run-elflint-test.sh: Add elflint testfile-s390x-hash-both test.
+
+2016-02-04  Mark Wielaard  <mjw@redhat.com>
+
+	* run-strip-nobitsalign.sh: New test.
+	* testfile-nobitsalign.bz2: New testfile.
+	* testfile-nobitsalign.strip.bz2: Likewise.
+	* Makefile.am (TESTS): Add run-strip-nobitsalign.sh.
+	(EXTRA_DIST): Add run-strip-nobitsalign.sh, testfile-nobitsalign.bz2
+	and testfile-nobitsalign.strip.bz2.
+	* run-strip-test.sh: Add --gnu to elflint calls.
+
+2016-01-13  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl-bug-fd-leak.c: Skip test unless on __linux__.
+
+2016-01-13  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl-proc-attach.c: Guard linux specific header.
+
+2016-01-13  Mark Wielaard  <mjw@redhat.com>
+
+	* system-elf-libelf-test.c: New test.
+	* Makefile.am (TESTS): Add system-elf-libelf-test, if !STANDALONE.
+	(check_PROGRAMS): Likewise.
+	(system_elf_libelf_test_CPPFLAGS): New variable.
+	(system_elf_libelf_test_LDADD): Likewise.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* elfputzdata.c (main): Fix parentheses in strncmp test.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* elfputzdata.c (main): Use PRId64 to print 64 bit value.
+
+2016-01-08  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Always unconditionally add
+	run-readelf-zdebug.sh and run-readelf-zdebug-rel.sh.
+
+2015-12-16  Mark Wielaard  <mjw@redhat.com>
+
+	* run-compress-test.sh: New test.
+	* Makefile.am (TESTS): Add run-compress-test.sh.
+	(EXTRA_DISTS): Likewise.
+
+2015-11-26  Mark Wielaard  <mjw@redhat.com>
+
+	* zstrptr.c: New file.
+	* run-zstrptr.sh: New test.
+	* elfputzdata.c (main): (re)compress .shstrtab.
+	* run-elfputzdata.sh: Expect .shstrtab compression.
+	* Makefile.am (check_PROGRAMS): Add zstrptr.
+	(TESTS): Add run-zstrptr.sh.
+	(EXTRA_DIST): Likewise.
+	(zstrptr_LDADD): New variable.
+
+2015-10-20  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-zx.sh: New test.
+	* run-readelf-zp.sh: Likewise.
+	* Makefile.am (TESTS): Add run-readelf-zx.sh and run-readelf-zp.sh.
+	(EXTRA_DIST): Likewise.
+
+2015-10-21  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add elfgetzdata and elfputzdata.
+	(TESTS): Add run-elfgetzdata.sh and run-elfputzdata.sh.
+	(EXTRA_DIST: Likewise.
+	(elfgetzdata_LDADD): New variable.
+	(elfputzdata_LDADD): Likewise.
+	* elfgetzdata.c: New file.
+	* elfputzdata.c: Likewise.
+	* msg_tst.c: Handle ELF_E_ALREADY_COMPRESSED,
+	ELF_E_UNKNOWN_COMPRESSION_TYPE, ELF_E_COMPRESS_ERROR and
+	ELF_E_DECOMPRESS_ERROR.
+	* run-elfgetzdata.sh: New test.
+	* run-elfputzdata.sh: Likewise.
+
+2015-10-28  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-z.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-z.sh.
+	(EXTRA_DIST): Likewise.
+
+2015-10-28  Mark Wielaard  <mjw@redhat.com>
+
+	* elfgetchdr.c: New file.
+	* run-elfgetchdr.sh: New test.
+	* testfile-zgabi32.bz2: New testfile.
+	* testfile-zgabi32be.bz2: Likewise.
+	* testfile-zgabi64.bz2: Likewise.
+	* testfile-zgabi64be.bz2: Likewise.
+	* Makefile.am (check_PROGRAMS): Add elfgetchdr.
+	(TESTS): Add run-elfgetchdr.sh.
+	(EXTRA_DIST): Add run-elfgetchdr.sh, testfile-zgabi32.bz2,
+	testfile-zgabi32be.bz2, testfile-zgabi64.bz2, testfile-zgabi64be.bz2.
+	(welfgetchdr_LDADD): New variable.
+	* msg_tst.c: Add ELF_E_NOT_COMPRESSED, ELF_E_INVALID_SECTION_TYPE
+	and ELF_E_INVALID_SECTION_FLAGS,
+
+
+2015-10-28  Mark Wielaard  <mjw@redhat.com>
+
+	* dwelfgnucompressed.c: New file.
+	* run-dwelfgnucompressed.sh: New test.
+	* testfile-zgnu32.bz2: New testfile.
+	* testfile-zgnu64.bz2: Likewise.
+	* Makefile.am (check_PROGRAMS): Add dwelfgnucompressed.
+	(TESTS): Add run-dwelfgnucompressed.sh.
+	(EXTRA_DIST): Add run-dwelfgnucompressed.sh, testfile-zgnu32.bz2,
+	testfile-zgnu64.bz2, testfile-zgnu32be.bz2, testfile-zgnu64be.bz2.
+	(dwelfgnucompressed_LDADD): New variable.
+
+2015-12-31  Mark Wielaard  <mjw@redhat.com>
+
+	* elfstrmerge.c (main): Warn about STT_SECTION symbol for shstrhndx.
+	* run-elfstrmerge-test.sh: New test.
+	* Makefile.am (TESTS): Add run-elfstrmerge-test.sh
+	(EXTRA_DIST): Likewise.
+
+2015-12-08  Jose E. Marchesi  <jose.marchesi@oracle.com>
+
+	* run-backtrace-core-sparc.sh: New file.
+	* backtrace.sparc.core.bz2: New file.
+	* backtrace.sparc.exec.bz2: New file.
+	* Makefile.am (EXTRA_DIST): ... and added all here.
+	(TESTS): Added run-backtrace-core-sparc.sh.
+
+2015-12-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (valgrind_cmd): Use --leak-check=full.
+	* run-backtrace-demangle.sh: Disable valgrind.
+	* run-stack-demangled-test.sh: Likewise.
+	* run-stack-d-test.sh: Likewise.
+	* run-stack-i-test.sh: Likewise.
+
+2015-12-01  Mark Wielaard  <mjw@redhat.com>
+
+	* test-flag-nobits.c (main): Call elf_end.
+	* rerequest_tag.c (main): Call dwarf_end.
+	* funcscopes.c (handle_function): Free scopes.
+	* dwarf-getstring.c (main): Call dwarf_end.
+	* allregs.c (main): Free state.info.
+	* alldts.c (main): Free dyn.
+	* addrcfi.c (handle_address): Free stuff.frame between handle_cfi
+	calls.
+	* addrscopes.c (handle_address): Free scopes.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am [BUILD_STATIC] (libdw): Add -lz.
+	[BUILD_STATIC] (libelf): Likewise.
+
+2015-10-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (dwfl_proc_attach_LDFLAGS): Add AM_LDFLAGS.
+
+2015-10-09  Josh Stone  <jistone@redhat.com>
+
+	* lfs-symbols: New list of LFS-related symbols from lintian.
+	* testfile-nolfs.bz2: New test binary for sanity checking.
+	* run-lfs-symbols.sh: New test.
+	* Makefile.am (TESTS): Add run-lfs-symbols.sh.
+	(EXTRA_DIST): Add lfs-symbols, testfile-nolfs.bz2, and
+	run-lfs-symbols.sh.
+	* alldts.c (main): Replace open64 with open.
+	* dwarf-getstring.c (main): Likewise.
+	* arls.c: Include config.h.
+	* ecp.c: Likewise.
+	* rdwrmmap.c: Likewise.
+	* test-elf_cntl_gelf_getshdr.c: Likewise.
+	* test-flag-nobits.c: Include config.h.
+	(main): Replace open64 with open.
+
+2015-10-09  Mark Wielaard  <mjw@redhat.com>
+
+	* elfshphehdr.c (check): Rename argument from check to statement.
+	(check_elf): Likewise.
+
+2015-10-05  Josh Stone  <jistone@redhat.com>
+
+	* Makefile.am (backtrace-child-biarch): Add AM_V_CC silencer.
+
+2015-10-02  Mark Wielaard  <mjw@redhat.com>
+
+	* elfstrmerge.c: New check program.
+	* run-strip-strmerge.sh: New test.
+	* Makefile.am (check_PROGRAMS): Add elfstrmerge.
+	(EXTRA_DIST): Add run-strip-strmerge.sh
+	(elfstrmerge_LDADD): New variable.
+
+2015-09-29  Mark Wielaard  <mjw@redhat.com>
+
+	* elfshphehdr.c: New test.
+	* Makefile.am (check_PROGRAMS): Add elfshphehdr.
+	(TESTS): Likewise.
+	(elfshphehdr_LDADD): New variable.
+
+2015-09-08  Mark Wielaard  <mjw@redhat.com>
+
+	* dwfl-proc-attach.c: New test.
+	* Makefile.am (check_PROGRAMS): Add dwfl-proc-attach.
+	(TESTS): Likewise.
+	(dwfl_proc_attach_LDADD): New variable.
+	(dwfl_proc_attach_LDFLAGS): Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* varlocs.c (print_base_type): Initialize enctype.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* md5-sha1-test.c (md5_expected): Removed.
+	(sha1_expected): Likewise.
+
+2015-09-04  Chih-Hung Hsieh  <chh@google.com>
+
+	* asm-tst1.c (main): Replace %Z length modifier with %z.
+	* asm-tst2.c (main): Likewise.
+	* asm-tst3.c (main): Likewise.
+	* asm-tst4.c (main): Likewise.
+	* asm-tst5.c (main): Likewise.
+	* asm-tst6.c (main): Likewise.
+	* asm-tst7.c (main): Likewise.
+	* asm-tst8.c (main): Likewise.
+	* asm-tst9.c (main): Likewise.
+	* sectiondump.c (print_bytes): Likewise.
+
+2015-08-14  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-alt-debugpath.sh: New test.
+	* Makefile.am (TESTS): Add run-addr2line-alt-debugpath.sh
+	(EXTRA_DIST): Likewise.
+
+2015-07-29  Mark Wielaard  <mjw@redhat.com>
+
+	* run-unstrip-test3.sh: New test.
+	* testfile-info-link.bz2: New file.
+	* testfile-info-link.debuginfo.bz2: Likewise.
+	* testfile-info-link.stripped.bz2: Likewise.
+	* Makefile.am (TESTS): Add run-unstrip-test3.sh.
+	(EXTRA_DIST): Add run-unstrip-test3.sh, testfile-info-link.bz2,
+	testfile-info-link.debuginfo.bz2, testfile-info-link.stripped.bz2.
+
+2015-06-27  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* tests/run-deleted.sh: Skip when detecting a not implemented
+	dwfl_linux_proc_attach.
+
+2015-06-27  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* tests/dwfl-bug-fd-leak.c (elfutils_open): Check for null results of
+	dwfl_addrmodule.
+
+2015-06-26  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* tests/vdsosyms.c [!__linux__] (main): Mark argv as unused.
+
+2015-06-26  Pino Toscano  <toscano.pino@tiscali.it>
+
+	* tests/backtrace-data.c: Reduce scope of some includes to match their
+	usage.
+	* tests/backtrace.c: Likewise.
+	* tests/deleted.c: Likewise.
+
+2015-06-16  Mark Wielaard  <mjw@redhat.com>
+
+	* run-strip-test.sh: Add strip-in-place (eu-strip without -o) test
+	for non-ET_REL files.
+
+2015-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-subr.sh (check_native_core): Notice core file couldn't be
+	generated before skipping.
+	* run-addr2line-i-demangle-test.sh: Notice demangler is unsupported
+	before skipping.
+	* run-backtrace-demangle.sh: Likewise.
+	* run-stack-demangled-test.sh: Likewise.
+	* run-backtrace-native-biarch.sh: Notice biarch testing is disabled
+	before skipping.
+	* run-backtrace-native-core-biarch.sh: Likewise.
+	* test-subr.sh (testfiles): Notice how bunzip2 fails before skipping.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-i-test.sh: Add pretty test.
+	* run-addr2line-test.sh: Likewise.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-i-demangle-test.sh: New test.
+	* Makefile.am (TESTS): Add run-addr2line-i-demangle-test.sh.
+	(EXTRA_DIST): Likewise.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-test.sh: Add -a test variants.
+	* run-addr2line-i-test.sh: Likewise.
+
+2015-05-20  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrname-test.sh: Make sure all input addresses are hex.
+
+2015-05-04  Max Filippov  <jcmvbkbc@gmail.com>
+
+	* backtrace-child.c (stdarg, main): Replace assert_perror with assert.
+	* backtrace-data.c (memory_read, maps_lookup, set_initial_registers)
+	(main): Likewise.
+	* backtrace-dwarf.c (main): Likewise.
+	* backtrace.c (prepare_thread, exec_dump): Likewise.
+
+2015-05-04  Anthony G. Basile  <blueness@gentoo.org>
+
+	* Makefile.am (line2addr_LDADD, addrscopes_LDADD, funcscopes_LDADD)
+	(funcretval_LDADD, allregs_LDADD, find_prologues_LDADD)
+	(dwflmodtest_LDADD, dwfl_addr_sect_LDADD, addrcfi_LDADD)
+	(low_high_pc_LDADD, dwflsyms_LDADD, dwfllines_LDADD, varlocs_LDADD)
+	(backtrace_LDADD, aggregate_size_LDADD): Append $(argp_LDADD).
+
+2015-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* run-stack-d-test.sh: Use --raw and mangled output.
+	* run-stack-i-test.sh: Likewise.
+	* run-stack-demangled-test.sh: New test.
+	* Makefile.am (EXTRA_DIST): Add run-stack-demangled-test.sh.
+	(TESTS): Likewise.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* Makefile.am (TESTS): Add run-strip-test10.sh.
+	(EXTRA_DIST): Likewise. Add testfile-x32-d.bz2.
+	Add testfile-x32-debug.bz2.
+	* run-strip-test10.sh: New file.
+	* testfile-x32-d.bz2: Likewise.
+	* testfile-x32-debug.bz2: Likewise.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* Makefile.am (TESTS): Add run-strip-test9.sh.
+	(EXTRA_DIST): Likewise. Add testfile-x32-s.bz2.
+	* run-strip-test9.sh: New file.
+	* testfile-x32-s.bz2: Likewise.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* Makefile.am (TESTS): Add run-backtrace-core-x32.sh.
+	(EXTRA_DIST): Likewise. Add backtrace.x32.core.bz2.
+	Add backtrace.x32.exec.bz2.
+	* backtrace.x32.core.bz2 : New file.
+	* backtrace.x32.exec.bz2: Likewise.
+	* run-backtrace-core-x32.sh: Likewise.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* run-addrcfi.sh: Add a test for testfile-x32.
+	* testfile-x32.bz2: New file.
+	* Makefile.am (EXTRA_DIST): Add testfile-x32.bz2.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* run-allregs.sh: Add a test for testfile-x32-core.
+
+2015-04-01  H.J. Lu  <hjl.tools@gmail.com>
+
+	* run-readelf-mixed-corenote.sh: Add a test for testfile-x32-core.
+	* testfile-x32-core.bz2: New file.
+	* Makefile.am (EXTRA_DIST): Add testfile-x32-core.bz2.
+
+2015-03-18  Petr Machata  <pmachata@redhat.com>
+
+	* addrcfi.c (op_name): Adjust uses of know-dwarf.h macros to match
+	the API changes.
+	* allregs.c (dwarf_encoding_string): Likewise.
+	* show-die-info.c (dwarf_tag_string, dwarf_attr_string): Likewise.
+	* varlocs.c (dwarf_encoding_string, dwarf_opcode_string): Likewise.
+
+2015-03-18  Petr Machata  <pmachata@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add run-dwarf-ranges.sh,
+	debug-ranges-no-lowpc.o.bz2.
+
+2015-03-13  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-dwarf.c: Add explicit includes.
+	(cleanup_13_abort): Remove unused static declaration.
+	(thread_callback): Add explicit return.
+
+2015-03-13  H.J. Lu  <hjl.tools@gmail.com>
+
+	* backtrace.c (prepare_thread): Use PTRACE_GETREGS/PTRACE_SETREGS
+	instead of PTRACE_POKEUSER.
+	(exec_dump): Check EM_X86_64 instead of ELFCLASS64 for
+	is_x86_64_native.
+
+2015-02-18  Mark Wielaard  <mjw@redhat.com>
+
+	* newdata.c (check_section_data): Use PRId64 for printing loff_t.
+
+2015-02-11  Josh Stone  <jistone@redhat.com>
+
+	* backtrace.c (exec_dump): Initialize jmp.
+
+2015-02-11  Petr Machata  <pmachata@redhat.com>
+
+	* run-dwarf-ranges.sh: New test.
+	* dwarf-ranges.c: New file.
+	* debug-ranges-no-lowpc.s, debug-ranges-no-lowpc.o.bz2: New test case.
+
+2015-01-21  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add elfstrtab.
+	(TESTS): Likewise.
+	(elfstrtab_LDADD): New variable.
+	* elfstrtab.c: New test.
+
+2015-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add newdata.
+	(TESTS): Likewise.
+	(newdata_LDADD): new variable.
+	* newdata.c: New test.
+
+2015-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* strptr.c: New file.
+	* run-strptr.sh: New test.
+	* Makefile.am (check_PROGRAMS): Add strptr.
+	(TESTS): Add run-strptr.sh.
+	(EXTRA_DIST): Likewise.
+	(strptr_LDADD): New variable.
+
+2015-01-15  Mark Wielaard  <mjw@redhat.com>
+
+	* deleted.c (main): Call prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY).
+	* vdsosyms.c (main): Use getpid () instead of getppid ().
+
+2014-12-27  Mark Wielaard  <mjw@redhat.com>
+
+	* addrscopes.c (handle_address): Last address in scope is highpc - 1.
+	* funcscopes.c (handle_function): Likewise.
+	* run-addrscopes.sh: Adjust last address in scope.
+	* run-funcscopes.sh: Likewise.
+
+2015-01-07  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrcfi.sh: Add test for ppc32 eh_frame_hdr address search.
+
+2015-01-14  Mark Wielaard  <mjw@redhat.com>
+
+	* testfile-debug-types.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfile-debug-types.bz2.
+	* typeiter2.c (main): Print both name and offset of found form DIE.
+	* run-typeiter.s: Adjust output and add testfile-debug-types.
+
+2014-12-26  Mark Wielaard  <mjw@redhat.com>
+
+	* run-test-archive64.sh: Add nm test.
+
+2014-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* run-deleted.sh: Don't check libfunc on ppc64.
+
+2014-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* vdsosyms.c (vdso_seen): Removed.
+	(vdso_syms): New global.
+	(module_callback): Set and check vdso_syms.
+	(main): Return value depends on vdso_syms.
+
+2014-12-19  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-subr.sh (check_native_unsupported): Relax special ARM
+	grep a little.
+	* run-deleted.sh: Call check_native_unsupported.
+
+2014-12-18  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add testfile-macros-0xff.bz2.
+
+2014-12-12  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (deleted_lib_so_CFLAGS): Add
+	-fasynchronous-unwind-tables.
+
+2014-12-11  Josh Stone  <jistone@redhat.com>
+
+	* run-addr2line-i-lex-test.sh: New test.
+	* testfile-lex-inlines.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add run-addr2line-i-lex-test.sh and
+	testfile-lex-inlines.bz2.
+	(TESTS): Add run-addr2line-i-lex-test.sh.
+
+2014-12-10  Josh Stone  <jistone@redhat.com>
+
+	* run-addr2line-i-test.sh: Test 0x5f0 to make sure linkage_name is
+	preferred over the plain die name.
+
+2014-12-02  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf-getmacros.c (mac): Skip over DW_MACINFO_undef,
+	DW_MACRO_GNU_undef_indirect opcodes.  Add a default branch.
+	(main): Initialize off to DWARF_GETMACROS_START when an extra
+	command line argument is passed.
+	* testfile-macros-0xff.bz2: New test case.
+	* testfile-macros-0xff.s: New file (source for the above).
+	* run-dwarf-getmacros.sh: Add two tests.
+
+2014-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* vdsosyms.c (main): Call dwfl_linux_proc_attach.
+
+2014-11-21  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-A.sh: New test.
+	* testfileppc32attrs.o.bz2: New test file.
+	* Makefile.am (TESTS): Add run-readelf-A.sh.
+	(EXTRA_DIST): Add run-readelf-A.sh and testfileppc32attrs.o.bz2.
+
+2014-11-10  Mark Wielaard  <mjw@redhat.com>
+
+	* vdsosyms.c: New test.
+	* Makefile.am (check_PROGRAMS): Add vdsosyms.
+	(TESTS): Likewise.
+	(vdsosyms_LDADD): New variable.
+
+2014-09-10  Petr Machata  <pmachata@redhat.com>
+
+	* dwarf-getmacros.c: Update to use the new macro iteration
+	interfaces.
+	* run-dwarf-getmacros.sh: Adjust, add a test that uses
+	testfile-macros.
+
+2014-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* run-aggregate-size.sh: Add testfile-sizes3.o test case.
+	* testfile-sizes3.o.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfile-sizes3.o.bz2.
+
+2014-10-02  Mark Wielaard  <mjw@redhat.com>
+
+	* run-deleted.sh: Unset VALGRIND_CMD before running deleted.
+
+2014-10-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add aggregate_size.c.
+	(TESTS): Add run-aggregate-size.sh.
+	(EXTRA_DIST): Add run-aggregate-size.sh, testfile-sizes1.o.bz2
+	and testfile-sizes2.o.bz2.
+	(aggregate_size_LDADD): New variable.
+	* aggregate_size.c: New file.
+	* run-aggregate-size.sh: New test.
+	* testfile-sizes1.o.bz2: New test file.
+	* testfile-sizes2.o.bz2: Likewise.
+
+2014-09-26  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Support NT_FILE for locating files.
+	* Makefile.am (TESTS): Add run-linkmap-cut.sh.
+	(EXTRA_DIST): Add run-linkmap-cut.sh, linkmap-cut-lib.so.bz2,
+	linkmap-cut.bz2 and linkmap-cut.core.bz2 .
+	* linkmap-cut-lib.so.bz2: New file.
+	* linkmap-cut.bz2: New file.
+	* linkmap-cut.core.bz2: New file.
+	* run-linkmap-cut.sh: New file.
+	* run-unstrip-n.sh: Update its expected output.
+
+2014-08-28  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add deleted and deleted-lib.so.
+	(TESTS, EXTRA_DIST): Add run-deleted.sh.
+	(deleted_LDADD, deleted_lib_so_LDFLAGS, deleted_lib_so_CFLAGS): New.
+	* deleted-lib.c: New file.
+	* deleted.c: New file.
+	* run-deleted.sh: New file.
+
+2014-06-15  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace.c (frame_callback): Error on seeing more than 16 frames.
+
+2014-06-13  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace.c (callback_verify): Accept "__libc_do_syscall" as first
+	frame symname.
+
+2014-06-13  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-subr.sh (check_native_unsupported): New function.
+	(check_native): Call it.
+	(check_native_core): Likewise.
+	* run-backtrace-dwarf.sh: Likewise.
+
+2014-06-11  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace.c (main): Check that Dwfl was attached by calling
+	dwfl_pid and printing the error when it is not.
+
+2014-05-18  Mark Wielaard  <mjw@redhat.com>
+
+	* testfile-backtrace-demangle.cc (cxxfunc): Make non-static.
+	(f): Likewise.
+	* testfile-backtrace-demangle.bz2: Regenerate.
+	* testfile-backtrace-demangle.core.bz2: Likewise.
+
+2014-05-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): run-readelf-dwz-multi.sh and
+	run-allfcts-multi.sh are now added unconditionally.
+
+2014-05-01  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-dwz-multi.sh: Add tests with alt debug files in .dwz
+	subdir.
+
+2014-04-30  Mark Wielaard  <mjw@redhat.com>
+
+	* buildid.c, buildid.sh, testfile42_noshdrs.bz2: New files.
+	* Makefile.am (check_PROGRAMS): Add buildid.
+	(TESTS): Add run-buildid.sh.
+	(EXTRA_DISTS): Add run-buildid.sh and testfile42_noshdrs.bz2.
+	(buildid_LDADD): New variable.
+
+2014-04-24  Florian Weimer  <fweimer@redhat.com>
+
+	* allfcts.c (setup_alt): New function.
+	(main): Call it.  Implementation additional error checking and
+	reporting.
+
+2014-04-24  Florian Weimer  <fweimer@redhat.com>
+
+	* debugaltlink.c, run-debugaltlink.sh: New files.
+	* Makefile.am (check_PROGRAMS): Add debugaltlink.
+	(TESTS): Add run-debugaltlink.sh.
+	(debugaltlink_LDADD): New variable.
+
+2014-04-11  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (AM_CPPFLAGS): Add -I libdwelf.
+	(check_PROGRAMS): Add debuglink.
+	(TESTS): Add run-debuglink.sh
+	(EXTRA_DIST): Likewise.
+	(debuglink_LDADD): New.
+	* debuglink.c: New file.
+	* run-debuglink.sh: Likewise.
+
+2014-03-23  Mark Wielaard  <mjw@redhat.com>
+
+	* run-nm-self.sh: Use test = not == for string comparisons.
+
+2014-04-22  Kurt Roeckx  <kurt@roeckx.be>
+
+	* backtrace.c: Make Linux only.
+	* backtrace-child.c: Make Linux only.
+	* backtrace-data.c: Make Linux only.
+	* backtrace-dwarf.c: Make Linux only.
+	* backtrace-subr.sh: Skip core file unwinding tests when not supported.
+
+2014-03-14  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Remove MUDFLAP conditions. Remove libmudflap from all
+	LDADD lines.
+	* configure.ac: Remove MUDFLAP conditional.
+
+2014-04-09  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-zdebug.sh: New test.
+	* testfile-debug.bz2: New testfile.
+	* testfile-zdebug.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-readelf-zdebug.sh if ZLIB.
+	(EXTRA_DIST): Add run-readelf-zdebug.sh, testfile-debug.bz2 and
+	testfile-zdebug.bz2.
+
+2014-04-10  Mark Wielaard  <mjw@redhat.com>
+
+	* testfile_i686_core.bz2: New test file.
+	* run-readelf-mixed-corenote.sh: Add testfile_i686_core test.
+	* Makefile.am (EXTRA_DIST): Add testfile_i686_core.bz2
+
+2014-04-09  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-backtrace-core-aarch64.sh.
+	(EXTRA_DIST): Add run-backtrace-core-aarch64.sh,
+	backtrace.aarch64.core.bz2 and backtrace.aarch64.exec.bz2.
+	* run-backtrace-core-aarch64.sh: New test.
+
+2014-03-11  Josh Stone  <jistone@redhat.com>
+
+	* testfilebaxmin.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfilebaxmin.bz2.
+	* run-readelf-s.sh: Test testfilebaxmin.
+	* run-dwflsyms.sh: Likewise.
+
+2014-01-26  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-subr.sh (check_unsupported): Special case arm*.
+
+2014-01-25  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrcfi.sh (EM_ARM): Change reg13 (sp) from undefined to
+	location expression: call_frame_cfa stack_value.
+
+2014-01-22  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (line2addr_no_Wformat): Removed.
+
+2014-01-21  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-stack-i-test.sh.
+	(EXTRA_DIST): Likewise.
+	* run-stack-i-test.sh: New test.
+
+2014-01-20  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-stack-d-test.sh.
+	(EXTRA_DIST): Add run-stack-d-test.sh, testfiledwarfinlines.bz2
+	testfiledwarfinlines.core.bz2.
+	* run-stack-d-test.sh: New test.
+	* testfiledwarfinlines.bz2: New test file.
+	* testfiledwarfinlines.core.bz2: Likewise.
+
+2014-01-16  Mark Wielaard  <mjw@redhat.com>
+
+	* run-nm-self.sh: Don't use testrun_on_self_quiet but just testrun
+	on one ET_REL, one ET_EXEC and one ET_DYN file.
+	* test-subr.sh (self_test_files): Add two ET_REL files, only add
+	two libebl ET_DYN backend files.
+
+2014-01-16  Mark Wielaard  <mjw@redhat.com>
+
+	* run-backtrace-demangle.sh: Check exitcode and max number of frames.
+
+2014-01-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix false FAILs on testsuite with ulimit -c unlimited.
+	* backtrace-child.c (sigusr2): Call pthread_exit.
+	(main): Return, do not call abort.
+
+2014-01-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix corruption of non-C++ symbols by the demangler.
+	* Makefile.am (TESTS): Add run-backtrace-demangle.sh.
+	<!DEMANGLE>: Add ELFUTILS_DISABLE_DEMANGLE export.
+	(EXTRA_DIST): Add run-backtrace-demangle.sh,
+	testfile-backtrace-demangle.bz2, testfile-backtrace-demangle.cc,
+	testfile-backtrace-demangle.core.bz2.
+	* backtrace-demangle.cc: New file.
+	* run-backtrace-demangle.sh: New file.
+	* testfile-backtrace-demangle.bz2: New file.
+	* testfile-backtrace-demangle.cc: New file.
+	* testfile-backtrace-demangle.core.bz2: New file.
+
+2014-01-07  Matthias Klose <doko@ubuntu.com>
+
+	* backtrace-subr.sh (check_native_core): Check to see if core file
+	was created without ".PID" extension, if so mv core to core.PID.
+	Skip test if no core file was created or could be found.
+
+2014-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-data.c (main): Don't assert if raise returns.
+	* backtrace-dwarf.c (report_pid): Call dwfl_linux_proc_attach with
+	assume_ptrace_attached true.
+	(ptrace_detach_stopped): Removed function.
+	(main): Don't call ptrace_detach_stopped.
+	* backtrace.c (ptrace_detach_stopped): Removed function.
+	(report_pid): Call dwfl_linux_proc_attach with assume_ptrace_attached
+	true.
+	(exec_dump): Don't call ptrace_detach_stopped.
+
+2014-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-subr.sh (check_native_core): Skip, exit 77, the test
+	if we cannot adjust core ulimit.
+
+2014-01-04  Mark Wielaard  <mjw@redhat.com>
+
+	* cleanup-13.c (force_unwind_stop): Removed.
+	(force_unwind): Just call abort. Don't setup _Unwind_Exception and
+	don't call _Unwind_ForcedUnwind.
+
+2014-01-03  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrcfi.sh: Add case for EM_AARCH64.
+	* testfileaarch64.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfilesaarch64.bz2.
+
+2013-12-30  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-dwarf.c (report_pid): Explicitly call
+	dwfl_linux_proc_attach and check for errors.
+	* backtrace.c (report_pid): Likewise.
+
+2013-12-21  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace.c (callback_verify): Only assert that case 5 is the last
+	instruction of backtracegen on x86_64 native.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	    Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add testfile66.bz2, testfile66.core.bz2
+	and testfilebaz*ppc64*.bz2 files.
+	* dwflsyms.c (list_syms): Remove unused from parameter mod_name.  Print
+	error on dwfl_module_getsymtab error.
+	(list_syms): Use dwfl_module_getsym and dwfl_module_getsym_info.
+	Compare values for non-ET_REL. Use dwfl_module_addrinfo.
+	Also print section of actual value if different from sym.
+	* run-addrname-test.sh (testfile66, testfile66.core): New tests.
+	Test addr2line -x by showing different sections for address and
+	found name in testfile66.
+	* run-dwflsyms.sh (testfile66, testfile66.core, hello_ppc64.ko,
+	testfilebaz*ppc64): New tests.
+	* testfile66.bz2, testfile66.core.bz2, testfilebazdbgppc64.bz2,
+	testfilebazdbgppc64.debug.bz2, testfilebazdbgppc64_pl.bz2,
+	testfilebazdbgppc64_plr.bz2, testfilebazdynppc64.bz2,
+	testfilebazmdbppc64.bz2, testfilebazminppc64.bz2,
+	testfilebazminppc64_pl.bz2, testfilebazminppc64_plr.bz2,
+	testfilebaztabppc64.bz2: New test files.
+
+2013-12-18  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: s390 and s390x
+	* Makefile.am (TESTS): Add run-backtrace-core-s390x.sh and
+	run-backtrace-core-s390.sh.
+	(EXTRA_DIST): Add backtrace.s390x.core.bz2, backtrace.s390x.exec.bz2,
+	backtrace.s390.core.bz2, backtrace.s390.exec.bz2,
+	run-backtrace-core-s390x.sh and run-backtrace-core-s390.sh.
+	* backtrace.s390.core.bz2: New file.
+	* backtrace.s390.exec.bz2: New file.
+	* backtrace.s390x.core.bz2: New file.
+	* backtrace.s390x.exec.bz2: New file.
+	* run-backtrace-core-s390.sh: New file.
+	* run-backtrace-core-s390x.sh: New file.
+
+2013-12-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* backtrace-dwarf.c (executable, find_elf, dwfl_offline): Remove unused
+	code.
+
+2013-12-15  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	unwinder: ppc
+	* Makefile.am (TESTS): Add run-backtrace-core-ppc.sh.
+	(EXTRA_DIST): Add backtrace.ppc.core.bz2,
+	backtrace.ppc.exec.bz2 and run-backtrace-core-ppc.sh.
+	* backtrace.ppc.core.bz2: New file.
+	* backtrace.ppc.exec.bz2: New file.
+	* run-backtrace-core-ppc.sh: New file.
+
+2013-12-10  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (backtrace_child_biarch_SOURCES): New backtrace-child.c.
+
+2013-12-10  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (valgrind_cmd): Remove --trace-children=yes.
+	* backtrace-subr.sh (check_native_core): Disable valgrind while
+	dumping core.
+	* run-backtrace-data.sh: Disable valgrind.
+	* run-backtrace-dwarf.sh: Likewise.
+
+2013-12-09  Mark Wielaard  <mjw@redhat.com>
+
+	* varlocs.c (print_expr): Update comment to explain empty location
+	associated with DW_OP_GNU_implicit_pointer.
+
+2013-12-05  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	Fix test FAIL with -O2.
+	* backtrace-child.c (sigusr2): Add NOINLINE_NOCLONE and final asm stub.
+
+2013-12-05  Mark Wielaard  <mjw@redhat.com>
+
+	* backtrace-data.c (main): If unsupported also print to stderr.
+	* run-backtrace-dwarf.sh: Add check_unsupported and check_main.
+
+2013-12-04  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (backtrace-child-biarch): Add $(EXEEXT).
+
+2013-12-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add backtrace, backtrace-child,
+	backtrace-data and backtrace-dwarf.
+	(BUILT_SOURCES, clean-local, backtrace-child-biarch): New.
+	(TESTS): Add run-backtrace-native.sh, run-backtrace-data.sh,
+	run-backtrace-dwarf.sh, run-backtrace-native-biarch.sh,
+	run-backtrace-native-core.sh, run-backtrace-native-core-biarch.sh,
+	run-backtrace-core-x86_64.sh and run-backtrace-core-i386.sh.
+	<!BIARCH> Add export of ELFUTILS_DISABLE_BIARCH.
+	(EXTRA_DIST): Add run-backtrace-data.sh, run-backtrace-dwarf.sh,
+	cleanup-13.c, run-backtrace-native.sh, run-backtrace-native-biarch.sh,
+	run-backtrace-native-core.sh, run-backtrace-native-core-biarch.sh,
+	run-backtrace-core-x86_64.sh, run-backtrace-core-i386.sh,
+	backtrace-subr.sh, backtrace.i386.core.bz2, backtrace.i386.exec.bz2,
+	backtrace.x86_64.core.bz2, backtrace.x86_64.exec.bz2.
+	(backtrace_LDADD, backtrace_child_CFLAGS, backtrace_child_LDFLAGS)
+	(backtrace_data_LDADD, backtrace_dwarf_CFLAGS, backtrace_dwarf_LDADD):
+	New.
+	* backtrace-child.c: New file.
+	* backtrace-data.c: New file.
+	* backtrace-dwarf.c: New file.
+	* backtrace-subr.sh: New file.
+	* backtrace.c: New file.
+	* cleanup-13.c: New file.
+	* backtrace.i386.core.bz2: New file.
+	* backtrace.i386.exec.bz2: New file.
+	* backtrace.x86_64.core.bz2: New file.
+	* backtrace.x86_64.exec.bz2: New file.
+	* run-backtrace-core-i386.sh: New file.
+	* run-backtrace-core-x86_64.sh: New file.
+	* run-backtrace-native-biarch.sh: New file.
+	* run-backtrace-native-core-biarch.sh: New file.
+	* run-backtrace-native-core.sh: New file.
+	* run-backtrace-native.sh: New file.
+	* run-backtrace-data.sh: New file.
+	* run-backtrace-dwarf.sh: New file.
+
+2013-11-27  Mark Wielaard  <mjw@redhat.com>
+
+	* dwflsyms.c (gelf_bind_order): New function.
+	(elf_section_name): Likewise.
+	(addr_in_section): Likewise.
+	(list_syms): Use dwfl_module_getsym_elf and dwfl_module_addrsym_elf.
+	Refine assert using gelf_bind_order. Print elf_section_name. Check
+	bias with addr_in_section.
+	* run-dwflsyms.sh: Add section names to expected output.
+
+2013-11-26  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add run-funcretval.sh.
+
+2013-11-25  Petr Machata  <pmachata@redhat.com>
+
+	* testfile_aarch64_core.bz2, hello_aarch64.ko.bz2: New files.
+	* funcretval_test.c, funcretval_test_aarch64.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add these.
+	(TESTS): Add run-funcretval.sh.
+	* run-allregs.sh: Use testfile_aarch64_core.bz2 for a regs_test.
+	* run-readelf-mixed-corenote.sh: ... and for a readelf -n test.
+	* run-strip-reloc.sh: Add a test on hello_aarch64.ko.bz2.
+	* run-funcretval.sh: New file.
+
+2013-11-18  Josh Stone  <jistone@redhat.com>
+
+	* testfilebazdbg_plr.bz2: New testfile.
+	* testfilebazmin_plr.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add the above files.
+	* run-dwflsyms.sh: Add prelink -r tests.
+
+2013-11-15  Mark Wielaard  <mjw@redhat.com>
+
+	* testfilebazmdb.bz2: Regenerated.
+	* testfilebazmin.bz2: Likewise.
+	* testfilebazdbg_pl.bz2: New testfile.
+	* testfilebazmin_pl.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfilebazdbg_pl.bz2 and
+	testfilebazmin_pl.bz2.
+	* dwflsyms.c (list_syms): Call dwfl_module_relocate_address and
+	print relative address of function symbols.
+	* run-dwflsyms.sh: Add prelink tests and adjust expected output.
+
+2013-11-01  Michael Forney  <mforney@mforney.org>
+
+	* Makefile.am (TESTS_ENVIRONMENT): Use and export NM.
+	* run-arsymtest.sh: Use NM.
+
+2013-11-05  Mark Wielaard  <mjw@redhat.com>
+
+	* allfcts.c (main): Correct dwarf_getfuncs return value check.
+
+2013-10-10  Mark Wielaard  <mjw@redhat.com>
+	    Josh Stone  <jistone@redhat.com>
+
+	* run-allfcts-multi.sh: New test.
+	* test-offset-loop.bz2: New testfile.
+	* test-offset-loop.alt.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-allcft-multi.sh if ENABLE_DWZ.
+	(EXTRA_DIST): Add run-allfcts-multi.sh, test-offset-loop.bz2 and
+	test-offset-loop.alt.bz2.
+
+2013-10-15  Mark Wielaard  <mjw@redhat.com>
+
+	* run-unstrip-M.sh: New test.
+	* Makefile.am (TESTS): Add run-unstrip-M.sh.
+	(EXTRA_DIST): Likewise.
+
+2013-10-06  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrcfi.sh: Remove nop from expected ppc and ppc64
+	location expression.
+
+2013-10-03  Josh Stone  <jistone@redhat.com>
+
+	* typeiter2.c: New file, reversing typeiter.c.
+	* run-typeiter.sh: Also run typeiter2.
+	* Makefile.am (check_PROGRAMS): Add typeiter2.
+	(typeiter2_LDADD): New variable.
+
+2013-09-26  Petr Machata  <pmachata@redhat.com>
+
+	* run-readelf-mixed-corenote.sh: Update output of testfile71
+	dump--readelf can newly decode the NT_FILE note.
+
+2013-09-26  Petr Machata  <pmachata@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add testfile71.bz2.
+	* run-readelf-mixed-corenote.sh: New test for this file.
+	* testfile71.bz2: New file.
+
+2013-09-20  Mark Wielaard  <mjw@redhat.com>
+
+	* allfcts.c (cb): Return DWARF_CB_ABORT.
+	(main): Iterate over all offsets returned by dwarf_getfuncs.
+	* run-allfcts.sh: Add nested_funcs and class_func testcases.
+	* testfile_nested_funcs.bz2: New test file.
+	* testfile_class_func.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfile_class_func.bz2 and
+	testfile_nested_funcs.bz2.
+
+2013-08-30  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add varlocs.
+	(TESTS): Add run-varlocs.sh.
+	(EXTRA_DIST): Add run-varlocs.sh, testfile_const_type.c,
+	testfile_const_type.bz2, testfile_implicit_pointer.c,
+	testfile_implicit_pointer.bz2, testfile_parameter_ref.c,
+	testfile_entry_value.c, testfile_entry_value.bz2,
+	testfile_implicit_value.c and testfile_implicit_value.bz2.
+	(varlocs_LDADD): New.
+	* run-varlocs: New test.
+	* testfile_const_type.c: New test source file.
+	* testfile_entry_value.c: Likewise.
+	* testfile_implicit_pointer.c: Likewise.
+	* testfile_implicit_value.c: Likewise.
+	* testfile_parameter_ref.c: Likewise.
+	* testfile_const_type.bz2: New test file.
+	* testfile_entry_value.bz2: Likewise.
+	* testfile_implicit_pointer.bz2: Likewise.
+	* testfile_implicit_value.bz2: Likewise.
+	* testfile_parameter_ref.bz2: Likewise.
+	* varlocs.c: New test source.
+
+2013-08-29  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrcfi.sh: Add case for EM_ARM.
+	* testfilearm.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfilesarm.bz2.
+
+2013-08-28  Mark Wielaard  <mjw@redhat.com>
+
+	* addrcfi.c (handle_cfi): Handle .debug_frame or .eh_frame
+	completely missing.
+	* run-addrcfi.sh: Add case for EM_S390 ELFCLASS32 and ELFCLASS64.
+	* testfiles390.bz2: New testfile.
+	* testfiles390x.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfiles390.bz2 and
+	testfiles390x.bz2.
+
+2013-08-28  Mark Wielaard  <mjw@redhat.com>
+
+	* addrcfi.c (handle_cfi): Use printf not error.
+	* run-addrcfi.sh: Add case for EM_PPC and EM_PPC64.
+	* testfileppc32.bz2: New testfile.
+	* testfileppc64.bz2: Likewise.
+	* Makefile.am (EXTRA_DIST): Add testfileppc32.bz2 and
+	testfileppc64.bz2.
+
+2013-08-27  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addrcfi.sh: New test.
+	* Makefile.am (TESTS): Add run-addrcfi.sh.
+	(EXTRA_DIST): Likewise.
+	* addrcfi.c (op_name): New function.
+	(print_detail): Call and print op_name. Check ops, not result
+	to check if this is "same value" or "undefined".
+	(handle_cfi): Make sure cfa_ops doesn't point to NULL.
+
+2013-08-13  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-i-test.sh: New test.
+	* testfile-inlines.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add run-addr2line-i-test.sh and
+	testfile-inlines.bz2.
+	(TESTS): Add run-addr2line-i-test.sh.
+
+2013-08-12  Mark Wielaard  <mjw@redhat.com>
+
+	* run-addr2line-test.sh: New test.
+	* Makefile.am (EXTRA_DIST): Add run-addr2line-test.sh.
+	(TESTS): Likewise.
+
+2013-07-23  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* run-unstrip-n.sh (test-core.*): Ignore libc.so.6 entry and order of
+	the entries.
+
+2013-07-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Fix typo, forgot extension in
+	testfilenolines.bz2.
+
+2013-05-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add test-core-lib.so.bz2,
+	test-core.core.bz2 and test-core.exec.bz2.
+	* run-addrname-test.sh: New test for these files.
+	* run-unstrip-n.sh: Update expected output.  New test for these files.
+	* test-core-lib.so.bz2: New file.
+	* test-core.core.bz2: New file.
+	* test-core.exec.bz2: New file.
+
+2013-05-03  Mark Wielaard  <mjw@redhat.com>
+
+	* testfilenolines.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfilenolines.bz2.
+	* run-get-lines.sh: Run testrun_compare on testfilenolines.
+
+2013-04-30  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* dwfl-report-elf-align.c: Use false add_p_vaddr for dwfl_report_elf.
+
+2013-04-29  Mark Wielaard  <mjw@redhat.com>
+
+	* test-subr.sh: Don't use pushd, just cd into test-dir.
+	(exit_cleanup): Don't use popd, just cd .. to get out.
+
+2013-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* test-subr.sh (exit_cleanup): New function.
+	(trap): Use exit_cleanup as argument.
+	* run-native-test.sh (native_exit): New function.
+	(trap): For EXIT (0) use native_exit as argument.
+
+2013-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* update1.c (main): Use unique tempfile name and unlink file.
+	* update2.c (main): Likewise.
+	* update3.c (main): Likewise.
+	* update4.c (main): Use unique tempfile name.
+
+2013-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* run-alldts.sh: Add testfile-alldts to tempfiles.
+	* run-elf_cntl_gelf_getshdr.sh: Add test_shdr.out to tempfiles.
+	* run-macro-test.sh: Add readelf.macros.out to tempfiles.
+	* run-strip-reloc.sh: Add readelf.out, readelf.out1, readelf.out2
+	and out.stripped1, out.debug1, out.stripped2, out.debug2 to tempfiles.
+
+2013-04-26  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (installed_TESTS_ENVIRONMENT): Export environment,
+	remove wrapper.
+	(TESTS_ENVIRONMENT): Likewise.
+	(installed_LOG_COMPILER): New variable defining wrapper.
+	(LOG_COMPILER): Likewise.
+	* run-*.sh: Fixup location of input and output files.
+	* test-subr.sh: Create test_dir, pushd to execute test in.
+	(trap): Remove test_dir.
+	(testfiles): Use abs_srcdir.
+	(installed_testrun): Match on abs_builddir or abs_top_builddir.
+	(self_test_files): Adjust path.
+
+2013-04-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am: Use AM_CPPFLAGS instead of INCLUDES.
+
+2013-03-25  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-aranges.sh: New test.
+	* testfilefoobarbaz.bz2: New test file.
+	* Makefile.am (TESTS): Add run-readelf-aranges.sh.
+	(EXTRA_DIST): Add run-readelf-aranges.sh and testfilefoobarbaz.bz2.
+
+2013-03-25  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-dwz-multi.sh: Expect high_pc also as address.
+
+2013-03-20  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add dwfl-report-elf-align.
+	(TESTS): Add run-dwfl-report-elf-align.sh.
+	(EXTRA_DIST): Add run-dwfl-report-elf-align.sh and
+	testfile-dwfl-report-elf-align-shlib.so.bz2 .
+	(dwfl_report_elf_align_LDADD): New.
+	* dwfl-report-elf-align.c: New file.
+	* run-dwfl-report-elf-align.sh: New file.
+	* testfile-dwfl-report-elf-align-shlib.so.bz2: New file.
+
+2013-03-12  Mark Wielaard  <mjw@redhat.com>
+
+	* run-dwfllines.sh: New test.
+	* dwfllines.c: New test program.
+	* Makefile.am (TESTS): Add run-dwfllines.sh.
+	(EXTRA_DIST): Likewise.
+	(dwfllines_LDADD): New variable.
+
+2013-02-22  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Remove run-readelf-s.sh and run-dwflsyms.sh.
+	(LZMA): Add run-readelf-s.sh and run-dwflsyms.sh to TESTS.
+
+2013-02-15  Mark Wielaard  <mjw@redhat.com>
+
+	* testfile-dwzstr.bz2: New testfile.
+	* testfile-dwzstr.multi.bz2: Likewise.
+	* run-readelf-dwz-multi.sh: Add readelf testfile-dwzstr test.
+	* Makefile.am (EXTRA_DIST): Add testfile-dwzstr.bz2 and
+	testfile-dwzstr.multi.bz2.
+
+2013-01-30  Mark Wielaard  <mjw@redhat.com>
+
+	* testfileloc.bz2: New testfile.
+	* run-readelf-loc.sh: New test.
+	* Makefile.am (TESTS): Add run-readelf-loc.sh.
+	(EXTRA_DIST): Add run-readelf-loc.sh and testfileloc.bz2.
+
+2013-01-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* run-readelf-mixed-corenote.sh: New testcase for readelf -n of s390
+	and s390x core notes.
+	* testfile67.bz2: New file.
+	* testfile68.bz2: New file.
+	* Makefile.am (EXTRA_DIST): Add testfile67.bz2 and testfile68.bz2 .
+
+2013-01-23  Mark Wielaard  <mjw@redhat.com>
+
+	* testfilebasmin.bz2: New testfile.
+	* Makefile.am (EXTRA_DIST): Add testfilebasmin.bz2.
+	* run-readelf-s.sh: Test testfilebasmin.
+	* run-dwflsyms.sh: Likewise.
+
+2013-01-16  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add dwflsyms.
+	(TESTS): Add run-readelf-s.sh and run-dwflsyms.sh.
+	(EXTRA_DIST): Add run-readelf-s.sh, testfilebazdbg.bz2,
+	testfilebazdyn.bz2, testfilebazmin.bz2, testfilebazdbg.debug.bz2,
+	testfilebazmdb.bz2, testfilebaztab.bz2 and run-dwflsyms.sh.
+	(dwflsyms_LDADD): New variable.
+
+2013-01-07  Roland McGrath  <roland@hack.frob.com>
+
+	* run-prelink-addr-test.sh: Use ln -snf.
+
+2012-12-03  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (valgrind_cmd): Add --run-libc-freeres=no.
+
+2012-11-29  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* run-addrname-test.sh: New test for PIE relocation.
+	* testfile70.core.bz2: New file.
+	* testfile70.exec.bz2: New file.
+	* Makefile.am (EXTRA_DIST): Add testfile70.core.bz2 and
+	testfile70.exec.bz2 .
+
+2012-10-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add testfile64.bz2, testfile65.bz2,
+	testfile69.core.bz2 and testfile69.so.bz2 .
+
+2012-10-17  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* run-addrname-test.sh: New test for DSO with build-id bias.
+	* testfile69.core.bz2: New file.
+	* testfile69.so.bz2: New file.
+
+2012-10-10  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* run-addrname-test.sh: New test for core vDSO bias.
+	* testfile65.bz2: New file.
+
+2012-10-10  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* run-addrname-test.sh: New test for symbol preferences.
+	* testfile64.bz2: New file.
+
+2012-10-01  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS_ENVIRONMENT): Define valgrind_cmd if USE_VALGRIND.
+	* test-wrapper.sh: Export VALGRIND_CMD if available.
+	* test-subr.sh (built_testrun): Use VALGRIND_CMD to invoke test prog.
+	(installed_testrun): Likewise.
+
+2012-09-24  Petr Machata  <pmachata@redhat.com>
+
+	* testfile63.bz2: New testfile.
+	* run-readelf-mixed-corenote.sh: New test.
+	* Makefile.am (TEST): Add run-readelf-mixed-corenote.sh.
+	(EXTRA_DIST): Add testfile63.bz2 and run-readelf-mixed-corenote.sh.
+
+2012-09-24  Petr Machata  <pmachata@redhat.com>
+
+	* testfile62.bz2: New testfile.
+	* run-readelf-vmcoreinfo.sh: New test.
+	* Makefile.am (TEST): Add run-readelf-vmcoreinfo.sh.
+	(EXTRA_DIST): Add testfile62.bz2 and run-readelf-vmcoreinfo.sh.
+
+2012-09-18  Petr Machata  <pmachata@redhat.com>
+
+	* testfile61.bz2: New testfile.
+	* run-allregs.sh: Run reg_test testfile61.
+	* Makefile.am (EXTRA_DIST): Add testfile61.bz2.
+
+2012-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add testfile60.bz2.
+
+2012-08-22  Jeff Kenton  <jkenton@tilera.com>
+
+	* testfile60.bz2: New testfile.
+	* run-allregs.sh: Run reg_test testfile60.
+
+2012-08-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Only add run-readelf-dwz-multi.sh if
+	ENABLE_DWZ.
+
+2012-08-16  Mark Wielaard  <mjw@redhat.com>
+
+	* allregs.c (dwarf_encoding_string): Rewritten using known-dwarf
+	macros.
+	* show-die-info.c (tagnames): Removed.
+	(attrs): Removed.
+	(dwarf_tag_string): New function using known-dwarf macros.
+	(dwarf_attr_string): Likewise.
+	(handle): Call dwarf_tag_string and dwarf_attr_string instead.
+	* run-readelf-dwz-multi.sh: Expect language C89, not ISO C89.
+
+2012-06-27  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-readelf-dwz-multi.sh.
+	(EXTRA_DIST): Add run-readelf-dwz-multi.sh,
+	libtestfile_multi_shared.so.bz2, testfile_multi.dwz.bz2 and
+	testfile_multi_main.bz2.
+	* run-readelf-dwz-multi.sh: New test.
+	* libtestfile_multi_shared.so.bz2: New testfile.
+	* testfile_multi.dwz.bz2: New testifle.
+	* testfile_multi_main.bz2: New testifle.
+
+2012-08-01  Petr Machata  <pmachata@redhat.com>
+
+	* run-test-archive64.sh: New test.
+	* testarchive64.a.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-test-archive64.sh.
+	(EXTRA_DIST): Likewise.
+
+2012-08-01  Mark Wielaard  <mjw@redhat.com>
+
+	* run-nm-self.sh: New test.
+	* run-readelf-self.sh: Likewise.
+	* test-subr.sh (testrun_on_self_quiet): New function.
+	* Makefile.am (TESTS): Add run-nm-self.sh and run-readelf-self.sh.
+	(EXTRA_DIST): Likewise.
+
+2012-08-01  Mark Wielaard  <mjw@redhat.com>
+
+	* test-subr.sh (self_test_files): New list of files.
+	(testrun_on_self): New function.
+	* run-elflint-self.sh: Use testrun_on_self.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (check_PROGRAMS): Add test-elf_cntl_gelf_getshdr.
+	(TESTS): Add run-elf_cntl_gelf_getshdr.sh.
+	(EXTRA_DIST): Likewise.
+	(test_elf_cntl_gelf_getshdr_LDADD): New.
+	test-elf_cntl_gelf_getshdr.c: New test program.
+	run-elf_cntl_gelf_getshdr.sh: New test script.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* run-elflint-self.sh: runtests on ../backends/*so files.
+
+2012-07-19  Mark Wielaard  <mjw@redhat.com>
+
+	* run-unstrip-n.sh: test_cleanup.
+	* Makefile.am (EXTRA_DIST): Add testcore-rtlib-ppc.bz2.
+
+2012-07-11  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-macro.sh: New test.
+	* testfilemacro.bz2: New testfile.
+	* Makefile.am (TESTS): Add run-readelf-macro.sh.
+	(EXTRA_DIST): Add run-readelf-macro.sh and testfilemacro.bz2.
+
+2012-06-27  Mark Wielaard  <mjw@redhat.com>
+
+	* run-readelf-gdb-index.sh: New test.
+	* testfilegdbindex5.bz2: New testfile.
+	* testfilegdbindex7.bz2: Likewise.
+	* Makefile.am (TESTS): Add run-readelf-gdb-index.sh.
+	(EXTRA_DIST): run-readelf-gdb_index.sh, testfilegdbindex5.bz2 and
+	testfilegdbindex7.bz2.
+
+2012-07-17  Mark Wielaard  <mjw@redhat.com>
+
+	* testcore-rtlib-ppc.bz2: New testfile.
+	* run-unstrip-n.sh: Check new ppc core testfile.
+
+2012-06-26  Mike Frysinger  <vapier@gentoo.org>
+
+	* Makefile.am (check_PROGRAMS): Rename from noinst_PROGRAMS.
+
+2012-06-26  Mark Wielaard  <mjw@redhat.com>
+
+	* run-macro-test.sh: New test.
+	* testfile-macinfo.bz2: New testfile.
+	* testfile-macros.bz2: Likewise.
+
+2012-05-07  Mark Wielaard  <mjw@redhat.com>
+
+	* low_high_pc.c: Use proper inttypes in printf formats.
+
+2012-05-11  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS_ENVIRONMENT): Set LC_ALL and LANG to C.
+
+2012-05-07  Mark Wielaard  <mjw@redhat.com>
+
+	* low_high_pc.c: Allow highpc == lowpc for CU DIEs for buggy GCC.
+
+2012-04-27  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-low_high_pc.sh
+	(EXTRA_DIST): Add run-low_high_pc.sh and testfile_low_high_pc.bz2
+	(noinst_PROGRAMS): Add low_high_pc.
+	(low_high_pc_LDADD): New variable.
+	* low_high_pc.c: New test.
+
+2012-04-26  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Remove run-show-ciefde.sh.
+	* run-show-ciefde.sh: Removed old libdwarf test.
+	* show-ciefde.c: Likewise.
+
+2012-04-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-unstrip-n.sh.
+	(EXTRA_DIST): Add testcore-rtlib.bz2 and run-unstrip-n.sh.
+	* run-unstrip-n.sh: New test.
+	* testcore-rtlib.bz2: New testfile.
+
+2012-04-02  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-readelf-d.sh.
+	(EXTRA_DIST): Add testlib_dynseg.so.bz2 and run-readelf-d.sh.
+	* run-readelf-d.sh: New test.
+	* run-elflint-test.sh: Check new testfile.
+
+2012-03-21  Tom Tromey  <tromey@redhat.com>
+
+	* typeiter.c: New file.
+	* run-typeiter.sh: New file.
+	* testfile59.bz2: New file.
+	* Makefile.am (noinst_PROGRAMS): Add typeiter.
+	(TESTS): Add run-typeiter.sh.
+	(EXTRA_DIST): Add run-typeiter.sh, testfile59.bz2.
+	(typeiter_LDADD): New variable.
+
+2012-02-21  Kurt Roeckx  <kurt@roeckx.be>
+
+	* run-alldts.sh: testrun ./alldts.
+
+2012-02-21  Roland McGrath  <roland@hack.frob.com>
+
+	* test-wrapper.sh: Add ${libdir}/elfutils to LD_LIBRARY_PATH.
+	* test-subr.sh (installed_testrun): Likewise.
+
+2012-01-18  Roland McGrath  <roland@hack.frob.com>
+
+	* asm-tst4.c (main): Don't set LD_LIBRARY_PATH in system invocation;
+	it will have been inherited correctly from the test harness.
+	* asm-tst5.c (main): Likewise.
+	* asm-tst6.c (main): Likewise.
+	Reported by Serge Pavlov <serge.pavlov.at.gnu@gmail.com>.
+
+2011-07-09  Roland McGrath  <roland@hack.frob.com>
+
+	* sha1-tst.c: File removed.
+	* Makefile.am (noinst_PROGRAMS, TESTS): Remove it.
+	(sha1_tst_LDADD): Variable removed.
+
+	* md5-sha1-test.c: New file.
+	* Makefile.am [!STANDALONE] (noinst_PROGRAMS, TESTS): Add it.
+	(md5_sha1_test_LDADD): New variable.
+
+2011-05-30  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add run-readelf-twofiles.sh and
+	run-rerequest_tag.sh
+
+2011-05-24  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add hello_s390.ko.bz2.
+	* run-strip-reloc.sh: Add hello_s390.ko testcase.
+	* hello_s390.ko.bz2: New test file.
+
+2011-05-23  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (TESTS): Add run-strip-reloc.sh.
+	(EXTRA_DIST): Add run-strip-reloc.sh, hello_i386.ko.bz2
+	hello_x86_64.ko.bz2 and hello_ppc64.ko.bz2
+	* run-strip-reloc.sh: New test.
+	* hello_i386.ko.bz2: New test file.
+	* hello_x86_64.ko.bz2: Likewise.
+	* hello_ppc64.ko.bz2: Likewise.
+
+2011-05-18  Mark Wielaard  <mjw@redhat.com>
+
+	* run-strip-groups.sh: New test.
+	* testfile58.bz2: New test file.
+	* Makefile.am (EXTRA_DIST): Add testfile58.bz2.
+	(TESTS): Add run-strip-groups.sh.
+	(EXTRA_DIST): Likewise.
+
+2011-03-28  Marek Polacek  <mpolacek@redhat.com>
+
+	* alldts.c: New file.
+	* run-alldts.sh: Use it.
+	* Makefile.am (TESTS, EXTRA_DIST, noinst_PROGRAMS): Add them.
+	(alldts_LDADD): New variable.
+
+2011-03-02  Marek Polacek  <mpolacek@redhat.com>
+
+	* dwarf-getstring.c: New test.
+	* run-dwarf-getstring.sh: And its wrapper.
+	* Makefile.am (EXTRA_DIST): Add and update all.
+
+2011-02-27  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* Makefile.am (TESTS): Add run-readelf-twofiles.sh.
+	* run-readelf-twofiles.sh: New file.
+
+2011-02-25  Mark Wielaard  <mjw@redhat.com>
+
+	* Makefile.am (BUILD_RPATH): Be consistent in naming.
+
+2011-02-02  Josh Stone  <jistone@redhat.com>
+
+	* run-prelink-addr-test.sh: Add testfile55, 32 and 64-bit.
+	* testfile55-64.bz2, testfile55-64.debug.bz2,
+	testfile55-64.prelink.bz2, testfile55-32.bz2,
+	testfile55-32.debug.bz2, testfile55-32.prelink.bz2: New.
+	* Makefile.am (EXTRA_DIST): Add and update all.
+
+2011-01-12  Roland McGrath  <roland@redhat.com>
+
+	* run-prelink-addr-test.sh: Make symlinks to find .debug files
+	corresponding to .noshdrs files.
+
+2011-01-11  Josh Stone  <jistone@redhat.com>
+
+	* run-prelink-addr-test.sh: Add testfile54, 32 and 64-bit.
+	* testfile54-32.so.bz2, testfile54-32.so.debug.bz2,
+	testfile54-32.prelink.so.bz2, testfile54-32.noshdrs.so.bz2,
+	testfile54-64.so.bz2, testfile54-64.so.debug.bz2,
+	testfile54-64.prelink.so.bz2, testfile54-64.noshdrs.so.bz2: New.
+	* Makefile.am (EXTRA_DIST): Add and update all.
+
+	* run-prelink-addr-test.sh: Run 32 and 64-bit testfile53 tests.
+	* testfile53.bz2, testfile53.debug.bz2,
+	testfile53.prelink.bz2: Deleted, so...
+	* testfile53-64.bz2, testfile53-64.debug.bz2,
+	testfile53-64.prelink.bz2: Recreated with 64-bit names.
+	* testfile53-32.bz2, testfile53-32.debug.bz2,
+	testfile53-32.prelink.bz2: New in 32-bit.
+	* Makefile.am (EXTRA_DIST): Add and update all.
+
+	* run-prelink-addr-test.sh: Run 32 and 64-bit testfile52 tests.
+	* testfile52.so.bz2, testfile52.so.debug.bz2,
+	testfile52.prelink.so.bz2: Deleted, so...
+	* testfile52-32.so.bz2, testfile52-32.so.debug.bz2,
+	testfile52-32.prelink.so.bz2: Recreated with 32-bit names.
+	* testfile52-32.noshdrs.so.bz2: New data file, stripped of headers.
+	* testfile52-64.so.bz2, testfile52-64.so.debug.bz2,
+	testfile52-64.prelink.so.bz2, testfile52-64.noshdrs.so.bz2: New files.
+	* Makefile.am (EXTRA_DIST): Add and update all.
+
+2011-01-10  Josh Stone  <jistone@redhat.com>
+
+	* run-prelink-addr-test.sh: New test for prelinked addrs.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+	* testfile52.so.bz2, testfile52.so.debug.bz2: New data files.
+	* testfile52.prelink.so.bz2: New data file, shows REL->RELA.
+	* testfile53.bz2, testfile53.debug.bz2: New data files.
+	* testfile53.prelink.bz2: New data file, shows ET_EXEC remap.
+	* Makefile.am (EXTRA_DIST): Add them.
+
+2010-06-04  Roland McGrath  <roland@redhat.com>
+
+	* run-unstrip-test.sh: Also test modifying the file in place.
+
+2010-04-22  Roland McGrath  <roland@redhat.com>
+
+	* addrcfi.c (handle_cfi): Fix function name in error message.
+	Use dwarf_errmsg, not dwfl_errmsg, after dwarf_cfi_addrframe.
+
+2010-04-14  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add run-test-flag-nobits.sh here too.
+
+2010-04-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* msg_tst.c: Adjust expected error message.
+
+2010-04-01  Petr Machata  <pmachata@redhat.com>
+
+	* test-flag-nobits.c: New test.
+	* run-test-flag-nobits.sh: And its wrapper.
+	* Makefile.am (noinst_PROGRAMS, TESTS): Add them.
+	(test_flag_nobits_LDADD): New variable.
+
+2010-02-15  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am: Use config/eu.am for common stuff.
+
+	* asm-tst9.c (main): Rename local to avoid shadowing another local.
+
+2009-07-22  Roland McGrath  <roland@redhat.com>
+
+	* addrcfi.c: Update dwarf_frame_{cfa,register} calling convention.
+
+2009-07-08  Roland McGrath  <roland@redhat.com>
+
+	* addrcfi.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(addrcfi_LDADD): New variable.
+
+2009-05-07  Petr Machata  <pmachata@redhat.com>
+
+	* testfile51.bz2: New data file.
+	* dwarf-getmacros.c: New test core.
+	* run-dwarf-getmacros.sh: New test wrapper.
+	* Makefile.am (TESTS, EXTRA_DIST, noinst_PROGRAMS): Add them.
+	(dwarf_getmacros_LDADD): New variable.
+
+2009-04-23  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile [BUILD_STATIC] (libdw): Add $(zip_LIBS).
+	(rdwrmmap_LDADD): Add $(libmudflap).
+
+2009-04-21  Roland McGrath  <roland@redhat.com>
+
+	* testfile50.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+	* run-dwfl-addr-sect.sh: Add a case using it.
+
+2008-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: Add tests for dppd, dpps, insertps, movntdqa,
+	mpsadbw, packusdw, pblendvb, pblendw, pcmpeqq, pcmpestri, pcmpestrm,
+	pcmpistri, pcmpistrm, pcmpgtq, phminposuw, pinsrb, pinsrd, pmaxsb,
+	pmaxsd, pmaxud, pmaxuw, pminsb, pminsd, pminud, pminuw, pmovsxbw,
+	pmovsxbd, pmovsxbq, pmovsxwd, pmovsxwq, pmovsxdq, pmovsxbw, pmovsxbd,
+	pmovsxbq, pmovsxwd, pmovsxwq, pmovsxdq, pmuldq, pmulld, popcnt, ptest,
+	roundss, roundps, roundpd, and roundsd.
+	* testfile45.S.bz2: Likewise.
+	* testfile44.expect.bz2: Adjust accordingly.
+	* testfile45.expect.bz2: Likewise.
+
+	* testfile44.S.bz2: Add tests for blendvpd and blendvps.
+	* testfile45.S.bz2: Likewise.
+	* testfile44.expect.bz2: Adjust accordingly.
+	* testfile45.expect.bz2: Likewise.
+
+2008-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: Add tests for blendpd and blendps.
+	* testfile45.S.bz2: Likewise.
+	* testfile44.expect.bz2: Adjust accordingly.
+	* testfile45.expect.bz2: Likewise.
+
+2008-12-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: Add tests for AMD 3DNOW.
+	* testfile45.S.bz2: Likewise.
+	* testfile44.expect.bz2: Adjust accordingly.
+	* testfile45.expect.bz2: Likewise.
+
+2008-11-26  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-bug-getmodules.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(dwfl_bug_getmodules_LDADD): New variable.
+
+2008-09-10  Roland McGrath  <roland@redhat.com>
+
+	* test-subr.sh (LC_ALL): Export it set to "C".
+	* run-dwfl-addr-sect.sh: Don't do it here.
+	* run-strings-test.sh: Likewise.
+
+2008-08-21  Denys Vlasenko  <dvlasenk@redhat.com>
+
+	* run-addrname-test.sh: Add a new case.
+	* testfile49.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2008-04-10  Roland McGrath  <roland@redhat.com>
+
+	* testfile48.bz2, testfile48.bz2.debug: New data files.
+	* Makefile.am (EXTRA_DIST): Add them.
+	* run-strip-test8.sh: Use them.
+
+	* testfile16.bz2, testfile16.debug.bz2: Replace data files.
+
+	* run-strip-test.sh: Fail if stripped output has ".debug_*" sections.
+	* run-strip-test8.sh: New file.
+	* testfile47.bz2: New data file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+2008-03-31  Roland McGrath  <roland@redhat.com>
+
+	* run-early-offscn.sh: New file.
+	* early-offscn.c: New file.
+	* Makefile.am (noinst_PROGRAMS, TESTS, EXTRA_DIST): Add them.
+	(early_offscn_LDADD): New variable.
+
+2008-03-19  Roland McGrath  <roland@redhat.com>
+
+	* run-addrname-test.sh: Add a new case.
+
+2008-02-22  Roland McGrath  <roland@redhat.com>
+
+	* run-elflint-test.sh: Typo fix.
+
+2008-02-21  Roland McGrath  <roland@redhat.com>
+
+	* run-disasm-x86.sh: Use uname instead of arch, keep tools required
+	for the build down to minimum.
+	* run-disasm-x86-64.sh: Likewise.
+
+2008-02-20  Roland McGrath  <roland@redhat.com>
+
+	* testfile46.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+	* run-elflint-test.sh: Test on it.
+
+2008-02-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Hook up sha1-tst.c.
+	* sha1-tst.c: New file.
+
+2008-01-21  Roland McGrath  <roland@redhat.com>
+
+	* testfile45.S.bz2: Add tests for cltq, cqto.
+	* testfile45.expect.bz2: Adjust.
+
+2008-01-14  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile45.S.bz2: Add more tests.
+	* testfile45.expect.bz2: Adjust.
+
+2008-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile45.expect.bz2: Adjust for adding of address for %rip based
+	address mode.
+
+2008-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile45.S.bz2: Add more tests.
+	* testfile45.expect.bz2: Adjust.
+
+2008-01-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (TESTS): Add run-disasm-x86-64.sh.
+	(EXTRA): Add testfile45.S.bz2, testfile45.expect.bz2,
+	run-disasm-x86-64.sh.
+	* run-disasm-x86-64.sh: New file.
+	* testfile45.S.bz2: New file.
+	* testfile45.expect.bz2: New file.
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2008-01-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2008-01-04  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-bug-fd-leak.c (main): Add a cast.
+
+2008-01-03  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2008-01-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* line2addr.c: Use %m modifier instead of %a to appease gcc.
+
+2008-01-01  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2007-12-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2007-12-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2007-12-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.s.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2007-12-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2007-12-27  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust.
+
+2007-12-26  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: New tests.
+	* testfile44.expect.bz2: Adjust
+
+2007-12-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile44.S.bz2: More tests.
+	* testfile44.expect.bz2: Adjust appropriately.
+
+2007-12-19  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (TESTS): Add run-disasm.sh.
+	(EXTRA_DIST): Add run-disasm.sh, testfile44.S.bz2, and
+	testfile44.expect.bz2.
+	* run-disasm.sh: New file.
+	* testfile44.S.bz2: New file.
+	* testfile44.expect.bz2: New file.
+
+2007-12-15  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Change expected output for powerpc spefscr.
+
+2007-10-20  Roland McGrath  <roland@redhat.com>
+
+	* run-dwfl-addr-sect.sh: Change expected output, no errors.
+
+2007-10-19  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-addr-sect.c (handle_address): Return int.
+	Don't exit on error, just return nonzero.
+	(main): Collect results.
+	* run-dwfl-addr-sect.sh: New file.
+	* testfile43.bz2: New data file.
+	* Makefile.am (EXTRA_DIST, TESTS): Add them.
+
+2007-10-18  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Update expected ppc output for vrsave/vscr.
+
+2007-10-16  Roland McGrath  <roland@redhat.com>
+
+	* test-subr.sh (remove_files): Don't pass -Bb to diff.
+
+2007-10-09  Roland McGrath  <roland@redhat.com>
+
+	* dwflmodtest.c (print_module): Don't use %p in output.
+	* run-dwfl-bug-offline-rel.sh: Updated expected output.
+
+2007-10-08  Roland McGrath  <roland@redhat.com>
+
+	* testfile42.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+	* run-elflint-test.sh: New test on that file.
+
+2007-10-04  Roland McGrath  <roland@redhat.com>
+
+	* run-readelf-test4.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+2007-10-03  Roland McGrath  <roland@redhat.com>
+
+	* run-readelf-test3.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+2007-10-01  Roland McGrath  <roland@redhat.com>
+
+	* run-readelf-test2.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+2007-09-11  Roland McGrath  <roland@redhat.com>
+
+	* run-addrname-test.sh: Add a new case.
+	* testfile41.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2007-08-23  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Update expected x86-64 output for %rflags.
+
+2007-08-12  Roland McGrath  <roland@redhat.com>
+
+	* run-strip-test7.sh: New file.
+	* testfile39.bz2: New data file.
+	* testfile40.bz2: New data file.
+	* testfile40.debug.bz2: New data file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+2007-08-09  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-bug-report.c: Fix header inclusion.
+
+2007-08-08  Roland McGrath  <roland@redhat.com>
+
+	* run-addrname-test.sh: Add a new case using addr2line -S.
+	* testfile38.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2007-07-16  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-bug-report.c: New file.
+	* Makefile.am (noinst_PROGRAMS, TESTS): Add it.
+	(dwfl_bug_report_LDADD): New variable.
+
+2007-06-06  Roland McGrath  <roland@redhat.com>
+
+	* run-unstrip-test.sh: Declare testfile.unstrip for removal.
+
+2007-06-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add missing line continuation and
+	testfile37.bz and testfile37.debug.bz2.
+
+2007-05-23  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Update expected Alpha results.
+
+2007-05-18  Roland McGrath  <roland@redhat.com>
+
+	* run-strip-test4.sh (stripped, debugfile): Use new reference files.
+	* testfile37.bz2: New data file.
+	* testfile37.debug.bz2: New data file.
+	* run-unstrip-test2.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+2007-05-10  Roland McGrath  <roland@redhat.com>
+
+	* run-dwfl-bug-offline-rel.sh: New file.
+	* testfile36.bz2: New data file.
+	* testfile36.debug.bz2: New data file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+2007-04-28  Roland McGrath  <roland@redhat.com>
+
+	* run-strip-test6.sh (stripped, debugfile): Use new reference files.
+	* testfile35.bz2: New data file.
+	* testfile35.debug.bz2: New data file.
+	* run-unstrip-test.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+	* run-strip-test.sh: Do all elflint and cmp runs even when some fail.
+
+2007-04-26  Roland McGrath  <roland@redhat.com>
+
+	* run-elflint-self.sh: Run all tests even if one fails.
+
+	* run-allregs.sh: Add expected output for alpha.
+
+2007-04-24  Roland McGrath  <roland@redhat.com>
+
+	* run-strip-test.sh: When we saved the debug info, test unstrip too.
+
+2007-04-22  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Update expected register info.
+
+2007-04-16  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-addr-sect.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(dwfl_addr_sect_LDADD): New variable.
+
+2007-04-05  Roland McGrath  <roland@redhat.com>
+
+	* get-files.c: Test dwarf_getsrcdirs.
+	* run-get-files.sh: Update expected output.
+
+2007-04-01  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Updated expected output for x86_64.
+
+2007-03-04  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-bug-fd-leak.c: New file.
+	* Makefile.am (noinst_PROGRAMS, TESTS): Add it.
+	(dwfl_bug_fd_leak_LDADD): New variable.
+
+	* dwflmodtest.c: Test dwfl_getmodules before and after getdwarf,
+	show what files have been located.
+
+2007-02-02  Roland McGrath  <roland@redhat.com>
+
+	* run-addrname-test.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+	* testfile34.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2007-01-20  Roland McGrath  <roland@redhat.com>
+
+	* testfile33.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+	* run-elflint-test.sh: Test on it too.
+
+2007-01-18  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (CFLAGS): Don't molest it.
+
+2007-01-11  Roland McGrath  <roland@redhat.com>
+
+	* testfile32.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+	* run-elflint-test.sh: Test on it too.
+
+2007-02-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* arls.c: New file.
+	* Makefile (noinst_PROGRAMS): Add arls.
+
+	* run-ranlib-test2.sh: Fix type in comment.
+
+2007-01-10  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-elflint-self.sh (runtest): Show which file has the problem.
+
+2007-01-10  Roland McGrath  <roland@redhat.com>
+
+	* dwfl-bug-addr-overflow.c: New file.
+	* Makefile.am (TESTS): Add it.
+	(dwfl_bug_addr_overflow_LDADD): New variable.
+
+2006-12-17  Roland McGrath  <roland@redhat.com>
+
+	* msg_tst.c (libelf_msgs): Fix ELF_E_INVALID_PHDR msg.
+
+2006-09-05  Roland McGrath  <roland@redhat.com>
+
+	* run-strings-test.sh: Export LC_ALL=C for the test.
+
+2006-08-29  Roland McGrath  <roland@redhat.com>
+
+	* run-arextract.sh: Use testrun, tempfiles functions from test-subr.sh.
+	* run-arsymtest.sh: Likewise.
+
+	* run-native-test.sh (native.c compilation): Add some braces.
+
+2006-08-22  Roland McGrath  <roland@redhat.com>
+
+	* allregs.c (dwarf_encoding_string): New function, swiped from readelf.
+	(struct reginfo): New members bits, type.
+	(one_register, match_register): Update to take new args,
+	record and display new info.
+	(main): Display new info.
+	* run-allregs.sh: Update expected results.
+
+2006-08-03  Roland McGrath  <roland@redhat.com>
+
+	* run-allregs.sh: Add sparc cases.
+	* testfile30.bz2: New data file.
+	* testfile31.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add them.
+
+2006-07-21  Roland McGrath  <roland@redhat.com>
+
+	* allregs.c (struct reginfo): Increase size of name.
+	(one_register): Assert that it's big enough.
+
+2006-04-04  Roland McGrath  <roland@redhat.com>
+
+	* run-bug1-test.sh: Test a second case, to cover both byte orders.
+	* testfile29.bz2: New file.
+	* testfile29.rdwr.bz2: New file.
+	* Makefile.am (EXTRA_DIST): Add them.
+
+2006-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add rules to run run-bug1-test.sh.
+	* rdwrmmap.c: New file.
+	* run-bug1-test.sh: New file.
+	* testfile28.bz2: New file.
+	* testfile28.rdwr.bz2: New file.
+
+2006-03-09  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (AM_LDFLAGS): Define to pass -rpath-link.
+
+2006-03-01  Roland McGrath  <roland@redhat.com>
+
+	* show-die-info.c (tagnames, attrs): Update name tables for dwarf.h
+	changes matching 3.0 spec.
+
+2006-01-13  Roland McGrath  <roland@redhat.com>
+
+	* run-native-test.sh: Do kill -9 and reap explicitly at end, since
+	bash 3.1 whines when it's done in the trap 0 handler.
+
+2006-01-11  Roland McGrath  <roland@redhat.com>
+
+	* testfile26.bz2: New data file.
+	* testfile27.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add them.
+	* run-allregs.sh: Test s390 data.
+
+2005-12-14  Roland McGrath  <roland@redhat.com>
+
+	* run-native-test.sh: Redirect output from native test process.
+
+2005-12-13  Roland McGrath  <roland@redhat.com>
+
+	* allregs.c (main): Fail if we find no registers.
+
+	* run-native-test.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+2005-12-10  Ulrich Drepper  <drepper@redhat.com
+
+	* run-readelf-test1.sh: New file.
+	* Makefile.am (TESTS): Add run-readelf-test1.sh.
+	(EXTRA_DIST): Likewise.
+
+2005-12-07  Roland McGrath  <roland@redhat.com>
+
+	* ecp.c (main): Use elf_end to clean up.
+
+2005-11-25  Roland McGrath  <roland@redhat.com>
+
+	* coverage.sh: Given -v argument, print names of unused files.
+
+	* addrscopes.c (main): Use dwfl_end before return.
+	* allregs.c (main): Likewise.
+	* find-prologues.c (main): Likewise.
+	* funcretval.c (main): Likewise.
+	* funcscopes.c (main): Likewise.
+	* line2addr.c (main): Likewise.
+
+	* run-allregs.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+	* allregs.c: Use libdwfl wrapper instead of direct libebl calls.
+	* Makefile.am (allregs_LDADD): Updated.
+
+	* allregs.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(allregs_LDADD): New variable.
+
+2005-11-18  Roland McGrath  <roland@redhat.com>
+
+	* test-subr.sh (installed_testrun): Treat /usr/lib64 like /usr/lib.
+	* test-wrapper.sh: Likewise.
+
+2005-11-17  Roland McGrath  <roland@redhat.com>
+
+	* Makefile.am (installed_TESTS_ENVIRONMENT): Set libdir, bindir in
+	environment for test-wrapper.sh.
+	* test-wrapper.sh: Set LD_LIBRARY_PATH from ${libdir} if not /usr/lib.
+	* test-subr.sh (installed_testrun): Likewise.
+	Use explicit path in ${bindir}.
+
+	* Makefile.am (installcheck-local): Fix typo in last change.
+
+2005-11-16  Roland McGrath  <roland@redhat.com>
+
+	* configure.ac: New file, for standalone build/dist of test suite.
+	* Makefile.am [!STANDALONE] (INCLUDES): Don't define it.
+	(asm_TESTS): New variable, broken out of ...
+	(TESTS): ... here.  Also remove msg_tst.
+	[!STANDALONE] (TESTS, noinst_PROGRAMS): Add in $(asm_TESTS), msg_tst.
+	(installed_TESTS_ENVIRONMENT): New variable.
+	[STANDALONE] (TESTS_ENVIRONMENT): Use that.
+	[!STANDALONE] (installcheck-local): Likewise.
+	[STANDALONE] (libdw, libelf, libasm, libebl): Define using -lfoo.
+	* addrscopes.c: Include <config.h>.
+	Use ELFUTILS_HEADER macro in #include of installed elfutils/ headers.
+	* allfcts.c: Likewise.
+	* asm-tst1.c: Likewise.
+	* asm-tst2.c: Likewise.
+	* asm-tst3.c: Likewise.
+	* asm-tst4.c: Likewise.
+	* asm-tst5.c: Likewise.
+	* asm-tst6.c: Likewise.
+	* asm-tst7.c: Likewise.
+	* asm-tst8.c: Likewise.
+	* asm-tst9.c: Likewise.
+	* dwflmodtest.c: Likewise.
+	* find-prologues.c: Likewise.
+	* funcscopes.c: Likewise.
+	* get-aranges.c: Likewise.
+	* get-files.c: Likewise.
+	* get-lines.c: Likewise.
+	* get-pubnames.c: Likewise.
+	* line2addr.c: Likewise.
+	* newscn.c: Likewise.
+	* show-abbrev.c: Likewise.
+	* show-die-info.c: Likewise.
+	* update3.c: Likewise.
+	* update4.c: Likewise.
+	* funcretval.c: Likewise.
+
+	* dwflmodtest.c (print_instance): Don't use INTUSE.
+	(options): Don't use N_ macro.
+
+2005-11-15  Roland McGrath  <roland@redhat.com>
+
+	* coverage.sh: Look in backends.
+	* Makefile.am (BUILD_RPATH): Search ../backends, not ../libebl.
+	(TESTS_ENVIRONMENT): Likewise.
+
+	* funcretval.c (handle_function): Don't take DW_AT_type of FUNCDIE,
+	pass FUNCDIE direclty to dwfl_module_return_value_location.
+
+	* Makefile.am (BUILD_RPATH): New variable.
+	[TESTS_RPATH] (AM_LDFLAGS): Pass -rpath option using that value.
+	(tests_rpath): New variable.
+	(installcheck-local): Pass it to test-wrapper.sh.
+	* test-wrapper.sh: In "installed" format, take yes/no value
+	for elfutils_tests_rpath, which export.  When running a test
+	binary for installcheck, exit 77.
+	* test-subr.sh (installed_testrun): When running a test binary
+	for installcheck, exit 77 if $elfutils_tests_rpath = yes.
+
+2005-11-14  Roland McGrath  <roland@redhat.com>
+
+	* test-subr.sh: New file.
+	* test-wrapper.sh: New file.
+	* Makefile.am (EXTRA_DIST): Add them.
+	(AM_LDFLAGS): Variable removed.
+	(TESTS_ENVIRONMENT): New variable.
+	(installcheck-local): New target.
+	* run-addrscopes.sh: Use test-subr.sh.
+	* run-allfcts.sh: Likewise.
+	* run-ecp-test.sh: Likewise.
+	* run-ecp-test2.sh: Likewise.
+	* run-elflint-self.sh: Likewise.
+	* run-elflint-test.sh: Likewise.
+	* run-find-prologues.sh: Likewise.
+	* run-funcscopes.sh: Likewise.
+	* run-get-aranges.sh: Likewise.
+	* run-get-files.sh: Likewise.
+	* run-get-lines.sh: Likewise.
+	* run-get-pubnames.sh: Likewise.
+	* run-line2addr.sh: Likewise.
+	* run-ranlib-test.sh: Likewise.
+	* run-ranlib-test2.sh: Likewise.
+	* run-show-abbrev.sh: Likewise.
+	* run-show-ciefde.sh: Likewise.
+	* run-show-die-info.sh: Likewise.
+	* run-strings-test.sh: Likewise.
+	* run-strip-test.sh: Likewise.
+
+2005-11-13  Roland McGrath  <roland@redhat.com>
+
+	* funcretval.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(funcretval_LDADD): New variable.
+
+2005-11-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* line2addr.c (handle_module): Add missing parameter to printf.
+
+2005-10-27  Roland McGrath  <roland@redhat.com>
+
+	* allfcts.c (cb): Update for dwarf_func_* -> dwarf_decl_* changes.
+	* funcscopes.c (handle_function): Likewise.
+	* dwflmodtest.c (print_inline, print_func): Likewise.
+	* find-prologues.c (handle_function): Likewise.
+
+2005-10-27  Roland McGrath  <roland@redhat.com>
+
+	* run-find-prologues.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+	* find-prologues.c (handle_function): Skip inlines.
+
+2005-10-25  Roland McGrath  <roland@redhat.com>
+
+	* find-prologues.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(find_prologues_LDADD): New variable.
+
+2005-09-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-strings-test.sh: Remove strings.out in the end.
+
+2005-08-31  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-addrscopes.sh: Use correct exit code if test cannot be performed.
+	* run-allfcts.sh: Likewise.
+	* run-ecp-test.sh: Likewise.
+	* run-ecp-test2.sh: Likewise.
+	* run-elflint-test.sh: Likewise.
+	* run-funcscopes.sh: Likewise.
+	* run-get-aranges.sh: Likewise.
+	* run-get-files.sh: Likewise.
+	* run-get-lines.sh: Likewise.
+	* run-get-pubnames.sh: Likewise.
+	* run-line2addr.sh: Likewise.
+	* run-ranlib-test2.sh: Likewise.
+	* run-show-abbrev.sh: Likewise.
+	* run-show-ciefde.sh: Likewise.
+	* run-show-die-info.sh: Likewise.
+	* run-strings-test.sh: Likewise.
+	* run-strip-test.sh: Likewise.
+
+2005-08-30  Ulrich Drepper  <drepper@redhat.com>
+
+	* coverage.sh: Handle case where there is no .gcno file at all.
+
+2005-08-29  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (EXTRA_DIST): Add coverage.
+	[GCOV]: Generate coverage summary after the tests ran
+	* coverage.sh: New file.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.an [BUILD_STATIC] (libdw): Add -ldl.
+	(CLEANFILES): Add *.gcno *.gcda *.gconv.
+
+2005-08-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-strings-test.sh: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add it.
+
+2005-08-27  Roland McGrath  <roland@redhat.com>
+
+	* addrscopes.c (handle_address): Apply bias to PC addresses.
+
+	* run-funcscopes.sh: New file.
+	* testfile25.bz2: New data file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+2005-08-26  Roland McGrath  <roland@redhat.com>
+
+	* addrscopes.c (dwarf_diename_integrate): Removed.
+	(print_vars, handle_address): Use plain dwarf_diename.
+
+2005-08-25  Roland McGrath  <roland@redhat.com>
+
+	* funcscopes.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(funcscopes_LDADD): New variable.
+
+	* run-addrscopes.sh: Add another case.
+	* testfile24.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+	* addrscopes.c (handle_address): Take new argument IGNORE_INLINES,
+	pass it to dwarf_getscopes.
+	(main): Pass it, true when '=' follows an address.
+
+2005-08-24  Roland McGrath  <roland@redhat.com>
+
+	* line2addr.c (print_address): Omit () for DSOs.
+
+2005-08-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-line2addr.sh: Remove testfile23 in the end.
+
+	* Makefile.am [BUILD_STATIC] (libdw): Add $(libelf) and $(libebl).
+	[MUDFLAP] (AM_LDFLAGS): Define to find libebl modules.
+
+2005-08-22  Roland McGrath  <roland@redhat.com>
+
+	* run-line2addr.sh: Add a case.
+	* testfile23.bz2: New data file.
+	* Makefile.am (EXTRA_DIST): Add it.
+
+2005-08-18  Roland McGrath  <roland@redhat.com>
+
+	* run-addrscopes.sh: New file.
+	* testfile22.bz2: New data file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+	* addrscopes.c: New file.
+	* Makefile.am (noinst_PROGRAMS): Add it.
+	(addrscopes_LDADD): New variable.
+
+2005-08-15  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-elflint-self.sh: Don't run test if the file doesn't exist.
+
+2005-08-15  Roland McGrath  <roland@redhat.com>
+
+	* dwflmodtest.c (print_instance, print_inline): New functions.
+	(print_func): Call print_inline.
+	(options, parse_opt): Grok -i/--inlines.
+
+2005-08-07  Roland McGrath  <roland@redhat.com>
+
+	* dwflmodtest.c: Print function details only if -f flag is given.
+
+2005-08-06  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-elflint-self.sh: New file.
+	* Makefile.am (TESTS): Add run-elflint-self.sh.
+	(EXTRA_DIST): Likewise.
+
+	* Makefile.am: Link with statis libs if BUILD_STATIC.
+	(dwflmodtest_LDADD): Also link with -ldl.
+
+2005-08-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add -ldl to asm_tst[1-9]_LDASS.
+	* asm-tst1.c: Adjust for new asm_begin interface.  Open backend
+	library first.
+	* asm-tst2.c: Likewise.
+	* asm-tst3.c: Likewise.
+	* asm-tst4.c: Likewise.
+	* asm-tst5.c: Likewise.
+	* asm-tst6.c: Likewise.
+	* asm-tst7.c: Likewise.
+	* asm-tst8.c: Likewise.
+	* asm-tst9.c: Likewise.
+
+	* msg_tst.c: Add new error message.
+
+2005-07-28  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am (dwflmodtest_LDADD): Add $(libebl).
+
+2005-06-01  Roland McGrath  <roland@redhat.com>
+
+	* line2addr.c: Rewritten using libdwfl.
+	* run-line2addr.sh: Update test for changed arguments.
+	* Makefile.am (INCLUDES): Add libdwfl source directory to path.
+	(libdwfl): New variable.
+	(line2addr_LDADD): Use it.
+
+2005-07-28  Roland McGrath  <roland@redhat.com>
+
+	* dwflmodtest.c: New file, moved from ../libdwfl/ptest.c to here.
+	* Makefile.am (noinst_PROGRAMS): Add dwflmodtest.
+	(dwflmodtest_LDADD): New variable.
+	(INCLUDES): Add -I$(top_srcdir)/libdwfl here.
+
+2005-07-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* testfile18.bz2: New file.
+	* run-elflint-test.sh: New file.
+	* Makefile.am (TESTS): Add run-elflint-test.sh.
+	(EXTRA_DIST): Add run-elflint-test.sh and testfile18.bz2.
+
+2005-05-24  Ulrich Drepper  <drepper@redhat.com>
+
+	* get-files.c (main): Use correct format specifier.
+
+2005-05-21  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Add -Wextra to CFLAGS.
+	* get-files.c: Remove warning this produced.
+	* get-pubnames.c: Likewise.
+	* newfile.c: Likewise.
+	* newscn.c: Likewise.
+	* scnnames.c: Likewise.
+	* showptable.c: Likewise.
+	* test-nlist.c: Likewise.
+	* update1.c: Likewise.
+	* update2.c: Likewise.
+	* update3.c: Likewise.
+	* update4.c: Likewise.
+
+2005-05-08  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-line2addr.sh: Remove testfile14 at the end.
+
+	* run-strip-test.sh: Remove debuginfo test input file as well.
+
+	* Makefile.am (EXTRA_DIST): Newly added files incorrectly used
+	.bz, not .bz2.
+
+2005-05-03  Roland McGrath  <roland@redhat.com>
+
+	* run-strip-test.sh: Use variables for test file names.
+	Optionally produce separate debug file and check it.
+	* run-strip-test2.sh: Use run-strip-test.sh via ., no duplication.
+	* run-strip-test3.sh: Likewise.
+	* run-strip-test4.sh: New file.
+	* run-strip-test5.sh: New file.
+	* run-strip-test6.sh: New file.
+	* testfile15.bz: New file.
+	* testfile15.debug.bz: New file.
+	* testfile16.bz: New file.
+	* testfile16.debug.bz: New file.
+	* testfile17.bz: New file.
+	* testfile17.debug.bz: New file.
+	* Makefile.am (TESTS, EXTRA_DIST): Add them.
+
+2005-04-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* run-line2addr.sh: Also use testfile14.  Adjust for correct
+	return of multiple matches.
+	* testfile14.bz2: New file.
+	* Makefile.am (EXTRA_DIST): Add testfile14.bz2.
+
+	* show-abbrev.c (main): Adjust for dwarf_getabbrev interface change.
+
+2005-04-04  Roland McGrath  <roland@redhat.com>
+
+	* line2addr.c (main): Initialize LINES and NLINES before calling
+	dwarf_getsrc_file, and free LINES afterwards.
+
+	* allfcts.c (main): Use size_t for CUHL.
+
+2005-04-04  Ulrich Drepper  <drepper@redhat.com>
+
+	* line2addr.c: New file.
+	* run-line2addr.sh: New file.
+	* Makefile.am: Add rules to build, run, and distribute new code.
+
+2005-04-02  Ulrich Drepper  <drepper@redhat.com>
+
+	* allfcts.c: New file.
+	* run-allfcts.sh: New file.
+	* Makefile.am: Add rules to build, run, and distribute new code.
+
+2005-02-05  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am [MUDFLAP] (AM_CFLAGS): Add -fmudflap.  Link all test
+	programs with -lmudflap.
+
+2004-09-25  Ulrich Drepper  <drepper@redhat.com>
+
+	* asm-tst4.c (main): Add LD_LIBRARY_PATH to elflint invocation.
+	* asm-tst5.c (main): Likewise.
+	* asm-tst6.c (main): Likewise.
+
+2004-01-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.am: Support building with mudflap.
+
+2004-01-12  Ulrich Drepper  <drepper@redhat.com>
+
+	* get-aranges.c: Rewrite to use libdw.
+	* Makefile.am: Reenable get-aranges test.
+
+2004-01-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* get-lines.c: New file.
+	* get-files.c: Adjust for libdw.
+	* run-get-files.sh: Adjust expected result.
+	* run-get-lines.sh: Likewise.
+	* Makefile.am: Run get-lines test.  Don't run get-aranges and
+	get-ciefde test for now.
+
+	* show-abbrev.c: Adjust call to dwarf_getabbrevattr after interface
+	change.  Print attribute offset information.
+	* run-show-abbrev.sh: Adjust expected output.
+
+2004-01-09  Ulrich Drepper  <drepper@redhat.com>
+
+	* show-abbrev.c: Adjust call to dwarf_nextcu after interface change.
+	* show-die-info.c: Likewise.
+	* run-show-die-info.sh: Adjust expected output.
+
+2003-08-13  Ulrich Drepper  <drepper@redhat.com>
+
+	* Makefile.in: Depend on libebl.a, not libebl.so.
+
+2003-08-11  Ulrich Drepper  <drepper@redhat.com>
+
+	* Moved to CVS archive.
diff --git a/tests/Makefile.am b/tests/Makefile.am
new file mode 100644
index 0000000..c8645dc
--- /dev/null
+++ b/tests/Makefile.am
@@ -0,0 +1,854 @@
+## Process this file with automake to create Makefile.in
+##
+## Copyright (C) 1996-2019 Red Hat, Inc.
+## This file is part of elfutils.
+##
+## This file is free software; you can redistribute it and/or modify
+## it under the terms of the GNU General Public License as published by
+## the Free Software Foundation; either version 3 of the License, or
+## (at your option) any later version.
+##
+## elfutils is distributed in the hope that it will be useful, but
+## WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program.  If not, see <http://www.gnu.org/licenses/>.
+##
+include $(top_srcdir)/config/eu.am
+BUILD_RPATH = \$$ORIGIN/../libasm:\$$ORIGIN/../libdw:\$$ORIGIN/../backends:\$$ORIGIN/../libelf
+
+AM_CPPFLAGS += -I$(top_srcdir)/libasm -I$(top_srcdir)/libdw \
+	    -I$(top_srcdir)/libdwfl -I$(top_srcdir)/libdwelf \
+	    -I$(top_srcdir)/libebl -I$(top_srcdir)/libelf \
+	    -I$(top_srcdir)/lib -I..
+AM_LDFLAGS = -Wl,-rpath-link,../libasm:../libdw:../libelf
+
+if TESTS_RPATH
+AM_LDFLAGS += -Wl,-rpath,$(BUILD_RPATH)
+tests_rpath = yes
+else
+tests_rpath = no
+endif
+
+check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \
+		  showptable update1 update2 update3 update4 test-nlist \
+		  show-die-info get-files next-files get-lines next-lines \
+		  get-pubnames \
+		  get-aranges allfcts line2addr addrscopes funcscopes \
+		  show-abbrev hash newscn ecp dwflmodtest \
+		  find-prologues funcretval allregs rdwrmmap \
+		  dwfl-bug-addr-overflow arls dwfl-bug-fd-leak \
+		  dwfl-addr-sect dwfl-bug-report early-offscn \
+		  dwfl-bug-getmodules dwarf-getmacros dwarf-ranges addrcfi \
+		  dwfl-core-noncontig dwarfcfi \
+		  test-flag-nobits dwarf-getstring rerequest_tag \
+		  alldts typeiter typeiter2 low_high_pc \
+		  test-elf_cntl_gelf_getshdr dwflsyms dwfllines \
+		  dwfl-report-elf-align dwfl-report-segment-contiguous \
+		  dwfl-report-offline-memory \
+		  varlocs backtrace backtrace-child \
+		  backtrace-data backtrace-dwarf debuglink debugaltlink \
+		  buildid deleted deleted-lib.so aggregate_size peel_type \
+		  vdsosyms \
+		  getsrc_die strptr newdata elfstrtab dwfl-proc-attach \
+		  elfshphehdr elfstrmerge dwelfgnucompressed elfgetchdr \
+		  elfgetzdata elfputzdata zstrptr emptyfile vendorelf \
+		  fillfile dwarf_default_lower_bound dwarf-die-addr-die \
+		  get-units-invalid get-units-split attr-integrate-skel \
+		  all-dwarf-ranges unit-info next_cfi \
+		  elfcopy addsections xlate_notes elfrdwrnop \
+		  dwelf_elf_e_machine_string \
+		  getphdrnum leb128 read_unaligned \
+		  msg_tst system-elf-libelf-test system-elf-gelf-test \
+		  nvidia_extended_linemap_libdw elf-print-reloc-syms \
+		  cu-dwp-section-info declfiles \
+		  $(asm_TESTS)
+
+asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \
+	    asm-tst6 asm-tst7 asm-tst8 asm-tst9
+
+if BIARCH
+check_PROGRAMS += backtrace-child-biarch
+endif
+
+# Substitute $(COMPILE).
+backtrace-child-biarch$(EXEEXT): backtrace-child.c
+	$(AM_V_CC)$(CC_BIARCH) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+		     $(AM_CPPFLAGS) $(CPPFLAGS) \
+		     $(AM_CFLAGS) $(CFLAGS) $(backtrace_child_CFLAGS) \
+		     $(AM_LDFLAGS) $(LDFLAGS) $(backtrace_child_LDFLAGS) \
+		     -o $@ $<
+
+if GCOV
+GCOV_FLAGS=-fprofile-arcs -ftest-coverage
+else
+GCOV_FLAGS=
+endif
+
+# test_nlist checks its own symbol table, and expects various symbols
+# to be in the order as specified in the source file. Explicitly set
+# minimal CFLAGS. But add sanitizers if in use.
+if USE_ADDRESS_SANITIZER
+EXTRA_NLIST_CFLAGS=-fsanitize=address
+else
+if USE_MEMORY_SANITIZER
+EXTRA_NLIST_CFLAGS=-fsanitize=memory -fsanitize-memory-track-origins
+else
+EXTRA_NLIST_CFLAGS=
+endif
+endif
+
+test-nlist$(EXEEXT): test-nlist.c
+	$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+	  $(AM_CPPFLAGS) $(CPPFLAGS) \
+	  $(test_nlist_CFLAGS) $(GCOV_FLAGS) -o $@ $< $(test_nlist_LDADD)
+
+TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \
+	run-ar-N.sh \
+	update1 update2 update3 update4 \
+	run-show-die-info.sh run-get-files.sh run-get-lines.sh \
+	run-next-files.sh run-next-lines.sh \
+	run-get-pubnames.sh run-get-aranges.sh run-allfcts.sh \
+	run-show-abbrev.sh run-line2addr.sh hash \
+	run-large-elf-file.sh \
+	newscn run-strip-test.sh run-strip-test2.sh \
+	run-strip-test3.sh run-strip-test4.sh run-strip-test5.sh \
+	run-strip-test6.sh run-strip-test7.sh run-strip-test8.sh \
+	run-strip-test9.sh run-strip-test10.sh run-strip-test11.sh \
+	run-strip-test12.sh \
+	run-strip-nothing.sh run-strip-g.sh run-annobingroup.sh \
+	run-strip-groups.sh run-strip-strmerge.sh \
+	run-strip-reloc-ko.sh run-strip-reloc-self.sh \
+	run-strip-reloc-ppc64.sh \
+	run-strip-nobitsalign.sh run-strip-remove-keep.sh \
+	run-unstrip-test.sh run-unstrip-test2.sh run-unstrip-test3.sh \
+	run-unstrip-test4.sh run-unstrip-M.sh run-elfstrmerge-test.sh \
+	run-ecp-test.sh run-ecp-test2.sh run-alldts.sh \
+	run-elflint-test.sh run-elflint-self.sh run-ranlib-test.sh \
+	run-ranlib-test2.sh run-ranlib-test3.sh run-ranlib-test4.sh \
+	run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
+	run-find-prologues.sh run-allregs.sh run-addrcfi.sh \
+	run-dwarfcfi.sh run-nm-syms.sh \
+	run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \
+	run-srcfiles-self.sh \
+	run-readelf-compressed.sh \
+	run-readelf-const-values.sh \
+	run-varlocs-self.sh run-exprlocs-self.sh \
+	run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
+	run-readelf-test4.sh run-readelf-twofiles.sh \
+	run-readelf-macro.sh run-readelf-loc.sh run-readelf-ranges.sh \
+	run-readelf-aranges.sh run-readelf-line.sh run-readelf-z.sh \
+	run-readelf-frames.sh \
+	run-readelf-n.sh \
+	run-retain.sh \
+	run-native-test.sh run-bug1-test.sh \
+	run-debuglink.sh run-debugaltlink.sh run-buildid.sh \
+	dwfl-bug-addr-overflow run-addrname-test.sh \
+	dwfl-bug-fd-leak dwfl-bug-report dwfl-report-segment-contiguous \
+	run-dwfl-bug-offline-rel.sh run-dwfl-addr-sect.sh \
+	run-disasm-x86.sh run-disasm-x86-64.sh \
+	run-early-offscn.sh run-dwarf-getmacros.sh run-dwarf-ranges.sh \
+	run-test-flag-nobits.sh run-prelink-addr-test.sh \
+	run-dwarf-getstring.sh run-rerequest_tag.sh run-typeiter.sh \
+	run-readelf-d.sh run-readelf-gdb_index.sh run-unstrip-n.sh \
+	run-low_high_pc.sh run-macro-test.sh run-elf_cntl_gelf_getshdr.sh \
+	run-test-archive64.sh run-readelf-vmcoreinfo.sh \
+	run-readelf-mixed-corenote.sh run-dwfllines.sh \
+	run-readelf-variant.sh run-readelf-fat-lto.sh \
+	run-dwfl-report-elf-align.sh run-addr2line-test.sh \
+	run-dwfl-report-offline-memory.sh \
+	run-addr2line-C-test.sh \
+	run-addr2line-i-test.sh run-addr2line-i-lex-test.sh \
+	run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \
+	run-varlocs.sh run-exprlocs.sh run-varlocs-vars.sh run-funcretval.sh \
+	run-backtrace-native.sh run-backtrace-data.sh run-backtrace-dwarf.sh \
+	run-backtrace-native-biarch.sh run-backtrace-native-core.sh \
+	run-backtrace-native-core-biarch.sh run-backtrace-core-x86_64.sh \
+	run-backtrace-fp-core-x86_64.sh \
+	run-backtrace-fp-core-aarch64.sh \
+	run-backtrace-fp-core-ppc64le.sh \
+	run-backtrace-core-x32.sh \
+	run-backtrace-core-i386.sh run-backtrace-fp-core-i386.sh \
+	run-backtrace-core-ppc.sh \
+	run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \
+	run-backtrace-core-aarch64.sh run-backtrace-core-sparc.sh \
+	run-backtrace-demangle.sh run-stack-d-test.sh run-stack-i-test.sh \
+	run-stack-demangled-test.sh run-readelf-zx.sh run-readelf-zp.sh \
+	run-readelf-arm-flags.sh \
+	run-readelf-addr.sh run-readelf-str.sh \
+	run-readelf-multi-noline.sh \
+	run-readelf-types.sh \
+	run-readelf-dwz-multi.sh run-allfcts-multi.sh run-deleted.sh \
+	run-linkmap-cut.sh run-aggregate-size.sh run-peel-type.sh \
+	vdsosyms run-readelf-A.sh \
+	run-getsrc-die.sh run-strptr.sh newdata elfstrtab dwfl-proc-attach \
+	elfshphehdr run-lfs-symbols.sh run-dwelfgnucompressed.sh \
+	run-elfgetchdr.sh \
+	run-elfgetzdata.sh run-elfputzdata.sh run-zstrptr.sh \
+	run-compress-test.sh \
+	run-readelf-zdebug.sh run-readelf-zdebug-rel.sh \
+	emptyfile vendorelf fillfile dwarf_default_lower_bound \
+	run-dwarf-die-addr-die.sh \
+	run-get-units-invalid.sh run-get-units-split.sh \
+	run-attr-integrate-skel.sh \
+	run-all-dwarf-ranges.sh run-unit-info.sh \
+	run-reloc-bpf.sh \
+	run-next-cfi.sh run-next-cfi-self.sh \
+	run-reverse-sections.sh run-reverse-sections-self.sh \
+	run-copyadd-sections.sh \
+	run-copymany-be32.sh run-copymany-le32.sh \
+	run-copymany-be64.sh run-copymany-le64.sh \
+	run-typeiter-many.sh run-strip-test-many.sh \
+	run-strip-version.sh run-xlate-note.sh \
+	run-readelf-discr.sh \
+	run-dwelf_elf_e_machine_string.sh \
+	run-elfclassify.sh run-elfclassify-self.sh \
+	run-disasm-riscv64.sh \
+	run-pt_gnu_prop-tests.sh \
+	run-getphdrnum.sh run-test-includes.sh \
+	leb128 read_unaligned \
+	msg_tst system-elf-libelf-test system-elf-gelf-test \
+	$(asm_TESTS) run-disasm-bpf.sh run-low_high_pc-dw-form-indirect.sh \
+	run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
+	run-readelf-dw-form-indirect.sh run-strip-largealign.sh \
+	run-readelf-Dd.sh run-dwfl-core-noncontig.sh run-cu-dwp-section-info.sh \
+	run-declfiles.sh
+
+if !BIARCH
+export ELFUTILS_DISABLE_BIARCH = 1
+endif
+
+if !DEMANGLE
+export ELFUTILS_DISABLE_DEMANGLE = 1
+endif
+
+if LZMA
+TESTS += run-readelf-s.sh run-dwflsyms.sh
+endif
+
+if HAVE_ZSTD
+TESTS += run-readelf-compressed-zstd.sh
+endif
+
+if USE_ZSTD_COMPRESS
+export ELFUTILS_ZSTD = 1
+endif
+
+if USE_MEMORY_SANITIZER
+export ELFUTILS_MEMORY_SANITIZER = 1
+endif
+
+if DEBUGINFOD
+check_PROGRAMS += debuginfod_build_id_find
+# With the dummy delegation doesn't work
+if !DUMMY_LIBDEBUGINFOD
+TESTS += run-debuginfod-dlopen.sh \
+	 run-debuginfod-artifact-running.sh \
+	 run-debuginfod-fd-prefetch-caches.sh \
+	 run-debuginfod-regex.sh \
+	 run-debuginfod-duplicate-urls.sh \
+	 run-debuginfod-file.sh \
+	 run-debuginfod-sizetime.sh \
+	 run-debuginfod-malformed.sh \
+	 run-debuginfod-negative-cache.sh \
+	 run-debuginfod-tmp-home.sh \
+	 run-debuginfod-writable.sh \
+	 run-debuginfod-no-urls.sh \
+	 run-debuginfod-query-retry.sh \
+	 run-debuginfod-extraction.sh \
+	 run-debuginfod-archive-groom.sh \
+	 run-debuginfod-archive-rename.sh \
+	 run-debuginfod-archive-test.sh \
+	 run-debuginfod-federation-sqlite.sh \
+	 run-debuginfod-federation-link.sh \
+         run-debuginfod-percent-escape.sh \
+         run-debuginfod-x-forwarded-for.sh \
+         run-debuginfod-response-headers.sh \
+         run-debuginfod-extraction-passive.sh \
+	 run-debuginfod-webapi-concurrency.sh \
+	 run-debuginfod-section.sh \
+	 run-debuginfod-IXr.sh
+endif
+if !OLD_LIBMICROHTTPD
+# Will crash on too old libmicrohttpd
+# Too many open file descriptors confuses libmicrohttpd < 0.9.51
+TESTS += run-debuginfod-federation-metrics.sh
+endif
+endif
+
+if HAVE_CXX11
+check_PROGRAMS += funcretval_test++11
+funcretval_test__11_SOURCES = funcretval_test++11.cxx
+TESTS += run-funcretval++11.sh
+endif
+
+EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \
+	     run-ar-N.sh \
+	     run-show-die-info.sh run-get-files.sh run-get-lines.sh \
+	     run-next-files.sh run-next-lines.sh testfile-only-debug-line.bz2 \
+	     run-get-pubnames.sh run-get-aranges.sh \
+	     run-show-abbrev.sh run-strip-test.sh \
+	     run-strip-test2.sh run-ecp-test.sh run-ecp-test2.sh \
+	     testfile.bz2 testfile2.bz2 testfile3.bz2 testfile4.bz2 \
+	     testfile5.bz2 testfile6.bz2 testfile7.bz2 testfile8.bz2 \
+	     testfile9.bz2 testfile10.bz2 testfile11.bz2 testfile12.bz2 \
+	     testfile13.bz2 run-strip-test3.sh run-allfcts.sh \
+	     testfile_class_func.bz2 testfile_nested_funcs.bz2 \
+	     testfile-lto-gcc10.bz2 \
+	     testfile-lto-gcc9.bz2 testfile-lto-gcc8.bz2 \
+	     run-line2addr.sh run-elflint-test.sh testfile14.bz2 \
+	     run-strip-test4.sh run-strip-test5.sh run-strip-test6.sh \
+	     run-strip-test7.sh run-strip-test8.sh run-strip-groups.sh \
+	     run-strip-test9.sh run-strip-test10.sh run-strip-test11.sh \
+	     run-strip-test12.sh \
+	     run-strip-nothing.sh run-strip-remove-keep.sh run-strip-g.sh \
+	     run-annobingroup.sh testfile-annobingroup.o.bz2 \
+	     testfile-annobingroup-i386.o.bz2 \
+	     testfile-annobingroup-x86_64.o.bz2 \
+	     run-strip-strmerge.sh run-strip-nobitsalign.sh \
+	     testfile-nobitsalign.bz2 testfile-nobitsalign.strip.bz2 \
+	     run-strip-reloc-ko.sh run-strip-reloc-self.sh \
+	     run-strip-reloc-ppc64.sh strip-reloc-subr.sh \
+	     hello_i386.ko.bz2 hello_x86_64.ko.bz2 \
+	     hello_ppc64.ko.bz2 hello_s390.ko.bz2 hello_aarch64.ko.bz2 \
+	     hello_m68k.ko.bz2 hello_riscv64.ko.bz2 hello_csky.ko.bz2 \
+	     hello_arc_hs4.ko.bz2 \
+	     run-unstrip-test.sh run-unstrip-test2.sh \
+	     testfile-info-link.bz2 testfile-info-link.debuginfo.bz2 \
+	     testfile-info-link.stripped.bz2 run-unstrip-test3.sh \
+	     run-unstrip-test4.sh testfile-strtab.bz2 \
+	     testfile-strtab.stripped.bz2 testfile-strtab.debuginfo.bz2 \
+	     run-unstrip-M.sh run-elfstrmerge-test.sh \
+	     run-elflint-self.sh run-ranlib-test.sh run-ranlib-test2.sh \
+	     run-ranlib-test3.sh run-ranlib-test4.sh \
+	     run-addrscopes.sh run-strings-test.sh run-funcscopes.sh \
+	     run-nm-syms.sh testfilesyms32.bz2 testfilesyms64.bz2 \
+	     run-nm-self.sh run-readelf-self.sh run-readelf-info-plus.sh \
+	     run-srcfiles-self.sh \
+		 run-readelf-compressed.sh \
+	     run-readelf-compressed-zstd.sh \
+	     run-readelf-const-values.sh testfile-const-values.debug.bz2 \
+	     run-addrcfi.sh run-dwarfcfi.sh \
+	     testfile11-debugframe.bz2 testfile12-debugframe.bz2 \
+	     testfileaarch64-debugframe.bz2 testfilearm-debugframe.bz2 \
+	     testfileppc32-debugframe.bz2 testfileppc64-debugframe.bz2 \
+	     testfilecsky.bz2 \
+	     run-varlocs-self.sh run-exprlocs-self.sh \
+	     run-find-prologues.sh run-allregs.sh run-native-test.sh \
+	     run-addrname-test.sh run-dwfl-bug-offline-rel.sh \
+	     run-dwfl-addr-sect.sh run-early-offscn.sh \
+	     run-dwarf-getmacros.sh \
+	     run-dwarf-ranges.sh debug-ranges-no-lowpc.o.bz2 \
+	     testfileranges4.debug.bz2 testfileranges5.debug.bz2 \
+	     testfilesplitranges5.debug.bz2 \
+	     testfile-ranges-hello5.dwo.bz2 testfile-ranges-world5.dwo.bz2 \
+	     run-test-flag-nobits.sh \
+	     run-dwarf-getstring.sh run-rerequest_tag.sh run-alldts.sh \
+	     testfile15.bz2 testfile15.debug.bz2 \
+	     testfile16.bz2 testfile16.debug.bz2 \
+	     testfile17.bz2 testfile17.debug.bz2 \
+	     testfile18.bz2 testfile19.bz2 testfile19.index.bz2 \
+	     testfile20.bz2 testfile20.index.bz2 \
+	     testfile21.bz2 testfile21.index.bz2 \
+	     testfile22.bz2 testfile23.bz2 testfile24.bz2 testfile25.bz2 \
+	     testfile26.bz2 testfile27.bz2 \
+	     coverage.sh test-subr.sh test-wrapper.sh debuginfod-subr.sh \
+	     run-readelf-test1.sh run-readelf-test2.sh run-readelf-test3.sh \
+	     run-readelf-test4.sh run-readelf-twofiles.sh \
+	     run-bug1-test.sh testfile28.bz2 testfile28.rdwr.bz2 \
+	     run-debuglink.sh run-debugaltlink.sh run-buildid.sh \
+	     testfile29.bz2 testfile29.rdwr.bz2 \
+	     testfile30.bz2 testfile31.bz2 testfile32.bz2 testfile33.bz2 \
+	     testfile34.bz2 testfile35.bz2 testfile35.debug.bz2 \
+	     testfile36.bz2 testfile36.debug.bz2 \
+	     testfile37.bz2 testfile37.debug.bz2 \
+	     testfile38.bz2 testfile39.bz2 testfile40.bz2 testfile40.debug.bz2 \
+	     testfile41.bz2 testfile42.bz2 testfile42_noshdrs.bz2 \
+	     testfile43.bz2 \
+	     testfile44.S.bz2 testfile44.expect.bz2 run-disasm-x86.sh \
+	     testfile45.S.bz2 testfile45.expect.bz2 run-disasm-x86-64.sh \
+	     testfile46.bz2 testfile47.bz2 testfile48.bz2 testfile48.debug.bz2 \
+	     testfile49.bz2 testfile50.bz2 testfile51.bz2 \
+	     testfile-macros-0xff.bz2 \
+	     run-readelf-macro.sh testfilemacro.bz2 \
+	     run-readelf-loc.sh testfileloc.bz2 \
+	     splitdwarf4-not-split4.dwo.bz2 \
+	     testfile-splitdwarf4-not-split4.debug.bz2 \
+	     run-readelf-ranges.sh \
+	     run-readelf-aranges.sh run-readelf-line.sh testfilefoobarbaz.bz2 \
+	     testfile-ppc64-min-instr.bz2 \
+	     testfile-dwarf-45.source \
+	     testfile-dwarf-4.bz2 testfile-dwarf-5.bz2 \
+	     run-readelf-z.sh \
+	     run-readelf-dwz-multi.sh libtestfile_multi_shared.so.bz2 \
+	     testfile_multi.dwz.bz2 testfile_multi_main.bz2 \
+	     testfile-dwzstr.bz2 testfile-dwzstr.multi.bz2 \
+	     run-readelf-arm-flags.sh testfile-arm-flags.bz2 \
+	     run-readelf-addr.sh run-readelf-str.sh \
+	     run-readelf-multi-noline.sh testfile_multi_noline.bz2 \
+	     run-readelf-types.sh \
+	     run-readelf-frames.sh \
+	     run-readelf-n.sh \
+	     testfile-gnu-property-note.bz2 testfile-gnu-property-note.o.bz2 \
+	     testfile_gnu_props.32le.o.bz2 \
+	     testfile_gnu_props.64le.o.bz2 \
+	     testfile_gnu_props.32be.o.bz2 \
+	     testfile_gnu_props.64be.o.bz2 \
+	     testfile-gnu-property-note-aarch64.bz2 \
+	     run-retain.sh testfile-retain.o.bz2 \
+	     run-allfcts-multi.sh \
+	     test-offset-loop.bz2 test-offset-loop.alt.bz2 \
+	     run-prelink-addr-test.sh \
+	     testfile52-32.so.bz2 testfile52-32.so.debug.bz2 \
+	     testfile52-32.prelink.so.bz2 testfile52-32.noshdrs.so.bz2 \
+	     testfile52-64.so.bz2 testfile52-64.so.debug.bz2 \
+	     testfile52-64.prelink.so.bz2 testfile52-64.noshdrs.so.bz2 \
+	     testfile53-32.bz2 testfile53-32.debug.bz2 \
+	     testfile53-32.prelink.bz2 testfile53-64.bz2 \
+	     testfile53-64.debug.bz2 testfile53-64.prelink.bz2 \
+	     testfile54-32.so.bz2 testfile54-32.so.debug.bz2 \
+	     testfile54-32.prelink.so.bz2 testfile54-32.noshdrs.so.bz2 \
+	     testfile54-64.so.bz2 testfile54-64.so.debug.bz2 \
+	     testfile54-64.prelink.so.bz2 testfile54-64.noshdrs.so.bz2 \
+	     testfile55-32.bz2 testfile55-32.debug.bz2 \
+	     testfile55-32.prelink.bz2 testfile55-64.bz2 \
+	     testfile55-64.debug.bz2 testfile55-64.prelink.bz2 \
+	     testfile56.bz2 testfile57.bz2 testfile58.bz2 \
+	     run-typeiter.sh testfile59.bz2 \
+	     run-readelf-d.sh testlib_dynseg.so.bz2 \
+	     run-readelf-Dd.sh \
+	     testfile-s390x-hash-both.bz2 \
+	     run-readelf-gdb_index.sh testfilegdbindex5.bz2 \
+	     testfilegdbindex7.bz2 testfilegdbindex9.bz2 \
+	     testfilegdbindex9-no-maininfo.bz2 \
+	     run-readelf-s.sh testfilebazdbg.bz2 testfilebazdyn.bz2 \
+	     testfilebazmin.bz2 testfilebazdbg.debug.bz2 testfilebazmdb.bz2 \
+	     testfilebaztab.bz2 testfilebasmin.bz2 testfilebaxmin.bz2 \
+	     testfilebazdbg_pl.bz2 testfilebazmin_pl.bz2 \
+	     testfilebazdbg_plr.bz2 testfilebazmin_plr.bz2 \
+	     testfilebazdbgppc64.bz2 testfilebazdbgppc64.debug.bz2 \
+	     testfilebazdbgppc64_pl.bz2 testfilebazdbgppc64_plr.bz2 \
+	     testfilebazdynppc64.bz2 testfilebazmdbppc64.bz2 \
+	     testfilebazminppc64.bz2 testfilebazminppc64_pl.bz2 \
+	     testfilebazminppc64_plr.bz2 testfilebaztabppc64.bz2 \
+	     run-readelf-variant.sh testfile-ada-variant.bz2 \
+	     run-readelf-fat-lto.sh testfile-dwarf5-fat-lto.o.bz2 \
+	     run-dwflsyms.sh \
+	     run-unstrip-n.sh testcore-rtlib.bz2 testcore-rtlib-ppc.bz2 \
+	     run-low_high_pc.sh testfile_low_high_pc.bz2 \
+	     run-macro-test.sh testfile-macinfo.bz2 testfile-macros.bz2 \
+	     run-elf_cntl_gelf_getshdr.sh \
+	     run-test-archive64.sh testarchive64.a.bz2 \
+	     testfile61.bz2 \
+	     run-readelf-vmcoreinfo.sh testfile62.bz2 \
+	     run-readelf-mixed-corenote.sh testfile63.bz2 testfile64.bz2 \
+	     testfile65.bz2 testfile67.bz2 testfile68.bz2 \
+	     testfile69.core.bz2 testfile69.so.bz2 \
+	     testfile70.core.bz2 testfile70.exec.bz2 testfile71.bz2 \
+	     run-dwfllines.sh run-dwfl-report-elf-align.sh \
+	     run-dwfl-report-offline-memory.sh \
+	     testfile-dwfl-report-elf-align-shlib.so.bz2 \
+	     testfilenolines.bz2 test-core-lib.so.bz2 test-core.core.bz2 \
+	     test-core.exec.bz2 run-addr2line-test.sh \
+	     run-addr2line-C-test.sh \
+	     run-addr2line-i-test.sh testfile-inlines.bz2 \
+	     testfile-inlines-lto.bz2 \
+	     run-addr2line-i-lex-test.sh testfile-lex-inlines.bz2 \
+	     run-addr2line-i-demangle-test.sh run-addr2line-alt-debugpath.sh \
+	     testfileppc32.bz2 testfileppc64.bz2 \
+	     testfiles390.bz2 testfiles390x.bz2 \
+	     testfilearm.bz2 testfileaarch64.bz2 \
+	     run-varlocs.sh run-exprlocs.sh run-varlocs-vars.sh \
+	     testfile-vars-clang-dwarf4-32.o.bz2 \
+	     testfile-vars-clang-dwarf4-64.o.bz2 \
+	     testfile-vars-clang-dwarf5-32.o.bz2 \
+	     testfile-vars-clang-dwarf5-64.o.bz2 \
+	     testfile-vars-gcc-dwarf4-32.o.bz2 \
+	     testfile-vars-gcc-dwarf4-64.o.bz2 \
+	     testfile-vars-gcc-dwarf5-32.o.bz2 \
+	     testfile-vars-gcc-dwarf5-64.o.bz2 \
+	     testfile-stridex.bz2 \
+	     testfile_const_type.c testfile_const_type.bz2 \
+	     testfile_implicit_pointer.c testfile_implicit_pointer.bz2 \
+	     testfile_parameter_ref.c testfile_parameter_ref.bz2 \
+	     testfile_entry_value.c testfile_entry_value.bz2 \
+	     testfile_implicit_value.c testfile_implicit_value.bz2 \
+	     testfile_aarch64_core.bz2 testfile_i686_core.bz2 \
+	     addrx_constx-4.dwo.bz2 addrx_constx-5.dwo.bz2 \
+	     testfile-addrx_constx-4.bz2 testfile-addrx_constx-5.bz2 \
+	     run-funcretval.sh funcretval_test.c funcretval_test_aarch64.bz2 \
+	     run-backtrace-data.sh run-backtrace-dwarf.sh cleanup-13.c \
+	     run-backtrace-native.sh run-backtrace-native-biarch.sh \
+	     run-backtrace-native-core.sh run-backtrace-native-core-biarch.sh \
+	     run-backtrace-core-x86_64.sh run-backtrace-core-i386.sh \
+	     run-backtrace-fp-core-x86_64.sh \
+	     run-backtrace-core-x32.sh \
+	     run-backtrace-fp-core-aarch64.sh \
+	     backtrace.aarch64.fp.core.bz2 backtrace.aarch64.fp.exec.bz2 \
+	     backtrace-subr.sh backtrace.i386.core.bz2 backtrace.i386.exec.bz2 \
+	     run-backtrace-fp-core-i386.sh \
+	     backtrace.i386.fp.core.bz2 backtrace.i386.fp.exec.bz2 \
+	     run-backtrace-fp-core-ppc64le.sh \
+	     backtrace.ppc64le.fp.core.bz2 backtrace.ppc64le.fp.exec.bz2 \
+	     backtrace.x86_64.core.bz2 backtrace.x86_64.exec.bz2 \
+	     backtrace.x86_64.fp.core.bz2 backtrace.x86_64.fp.exec.bz2 \
+	     backtrace.ppc.core.bz2 backtrace.ppc.exec.bz2 \
+	     run-backtrace-core-ppc.sh testfile66.bz2 testfile66.core.bz2 \
+	     backtrace.s390x.core.bz2 backtrace.s390x.exec.bz2 \
+	     backtrace.s390.core.bz2 backtrace.s390.exec.bz2 \
+	     run-backtrace-core-s390x.sh run-backtrace-core-s390.sh \
+	     run-backtrace-core-aarch64.sh \
+	     backtrace.aarch64.core.bz2 backtrace.aarch64.exec.bz2 \
+	     run-backtrace-core-sparc.sh \
+	     backtrace.sparc.core.bz2 backtrace.sparc.exec.bz2 \
+	     run-backtrace-demangle.sh testfile-backtrace-demangle.bz2 \
+	     testfile-backtrace-demangle.cc \
+	     testfile-backtrace-demangle.core.bz2 \
+	     run-stack-d-test.sh run-stack-i-test.sh \
+	     run-stack-demangled-test.sh \
+	     testfiledwarfinlines.bz2 testfiledwarfinlines.core.bz2 \
+	     run-readelf-zdebug.sh testfile-debug.bz2 testfile-zdebug.bz2 \
+	     run-readelf-zdebug-rel.sh testfile-debug-rel.o.bz2 \
+	     testfile-debug-rel-g.o.bz2 testfile-debug-rel-z.o.bz2 \
+	     run-readelf-zx.sh run-readelf-zp.sh \
+	     run-deleted.sh run-linkmap-cut.sh linkmap-cut-lib.so.bz2 \
+	     linkmap-cut.bz2 linkmap-cut.core.bz2 \
+	     run-aggregate-size.sh testfile-sizes1.o.bz2 testfile-sizes2.o.bz2 \
+	     testfile-sizes3.o.bz2 testfile-sizes4.o.bz2 testfile-sizes4.s \
+	     run-peel-type.sh \
+	     run-readelf-A.sh testfileppc32attrs.o.bz2 \
+	     testfilesparc64attrs.o.bz2 testfileppc64attrs.o.bz2 \
+	     testfile-debug-types.bz2 \
+	     run-getsrc-die.sh run-strptr.sh \
+	     testfile-x32-core.bz2 testfile-x32.bz2 \
+	     backtrace.x32.core.bz2 backtrace.x32.exec.bz2 \
+	     testfile-x32-s.bz2 testfile-x32-d.bz2 testfile-x32-debug.bz2 \
+	     run-lfs-symbols.sh lfs-symbols testfile-nolfs.bz2 \
+	     testfile-zgnu32.bz2 testfile-zgnu64.bz2 \
+	     testfile-zgnu32be.bz2 testfile-zgnu64be.bz2 \
+	     run-dwelfgnucompressed.sh \
+	     testfile-zgabi32.bz2 testfile-zgabi64.bz2 \
+	     testfile-zgabi32be.bz2 testfile-zgabi64be.bz2 \
+	     run-elfgetchdr.sh run-elfgetzdata.sh run-elfputzdata.sh \
+	     run-zstrptr.sh run-compress-test.sh \
+	     run-disasm-bpf.sh \
+	     testfile-bpf-dis1.expect.bz2 testfile-bpf-dis1.o.bz2 \
+	     run-reloc-bpf.sh \
+	     testfile-bpf-reloc.expect.bz2 testfile-bpf-reloc.o.bz2 \
+	     testfile-m68k-core.bz2 testfile-m68k.bz2 testfile-m68k-s.bz2 \
+	     run-dwarf-die-addr-die.sh \
+	     run-get-units-invalid.sh run-get-units-split.sh \
+	     testfile-hello4.dwo.bz2 testfile-hello5.dwo.bz2 \
+	     testfile-splitdwarf-4.bz2 testfile-splitdwarf-5.bz2 \
+	     testfile-world5.dwo.bz2 testfile-world4.dwo.bz2 \
+	     run-attr-integrate-skel.sh \
+	     run-all-dwarf-ranges.sh testfilesplitranges4.debug.bz2 \
+	     testfile-ranges-hello.dwo.bz2 testfile-ranges-world.dwo.bz2 \
+	     run-unit-info.sh run-next-cfi.sh run-next-cfi-self.sh \
+	     testfile-riscv64.bz2 testfile-riscv64-s.bz2 \
+	     testfile-riscv64-core.bz2 \
+	     run-reverse-sections.sh run-reverse-sections-self.sh \
+	     run-copyadd-sections.sh test-copymany-subr.sh \
+	     run-copymany-be32.sh run-copymany-le32.sh \
+	     run-copymany-be64.sh run-copymany-le64.sh \
+	     run-large-elf-file.sh \
+	     run-typeiter-many.sh run-strip-test-many.sh \
+	     testfile-debug-rel-ppc64-g.o.bz2 \
+	     testfile-debug-rel-ppc64-z.o.bz2 \
+	     testfile-debug-rel-ppc64.o.bz2 \
+	     run-strip-version.sh testfile-version.bz2 \
+	     run-xlate-note.sh \
+	     run-readelf-discr.sh \
+	     testfile-rng.debug.bz2 testfile-urng.debug.bz2 \
+	     run-dwelf_elf_e_machine_string.sh \
+	     run-elfclassify.sh run-elfclassify-self.sh \
+	     run-disasm-riscv64.sh \
+	     testfile-riscv64-dis1.o.bz2 testfile-riscv64-dis1.expect.bz2 \
+             run-debuginfod-extraction.sh \
+             run-debuginfod-federation-link.sh \
+             run-debuginfod-federation-metrics.sh \
+             run-debuginfod-artifact-running.sh \
+             run-debuginfod-federation-sqlite.sh \
+             run-debuginfod-x-forwarded-for.sh \
+	     run-debuginfod-fd-prefetch-caches.sh \
+	     run-debuginfod-regex.sh \
+	     run-debuginfod-duplicate-urls.sh \
+	     run-debuginfod-file.sh \
+	     run-debuginfod-sizetime.sh \
+	     run-debuginfod-dlopen.sh \
+	     run-debuginfod-malformed.sh \
+	     run-debuginfod-negative-cache.sh \
+	     run-debuginfod-tmp-home.sh \
+	     run-debuginfod-writable.sh \
+	     run-debuginfod-no-urls.sh \
+	     run-debuginfod-query-retry.sh \
+	     run-debuginfod-archive-groom.sh \
+	     run-debuginfod-archive-rename.sh \
+             run-debuginfod-archive-test.sh \
+             run-debuginfod-percent-escape.sh \
+	     run-debuginfod-response-headers.sh \
+             run-debuginfod-extraction-passive.sh \
+             run-debuginfod-webapi-concurrency.sh \
+	     run-debuginfod-section.sh \
+	     run-debuginfod-IXr.sh \
+	     debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm \
+	     debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora30/hello2-debugsource-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora30/hello2-two-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora30/hello2-two-debuginfo-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm \
+	     debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/hello2.specfile \
+	     debuginfod-rpms/hello3.specfile \
+	     debuginfod-rpms/rhel6/hello2-1.0-2.i686.rpm \
+	     debuginfod-rpms/rhel6/hello2-1.0-2.src.rpm \
+	     debuginfod-rpms/rhel6/hello2-debuginfo-1.0-2.i686.rpm \
+	     debuginfod-rpms/rhel6/hello2-two-1.0-2.i686.rpm \
+	     debuginfod-rpms/rhel7/hello2-1.0-2.src.rpm \
+	     debuginfod-rpms/rhel7/hello2-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/rhel7/hello2-debuginfo-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm \
+	     debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm \
+	     debuginfod-debs/hithere-dbgsym_1.0-1_amd64.ddeb \
+	     debuginfod-debs/hithere_1.0-1.debian.tar.xz \
+	     debuginfod-debs/hithere_1.0-1.dsc \
+	     debuginfod-debs/hithere_1.0-1_amd64.deb \
+	     debuginfod-debs/hithere_1.0.orig.tar.gz \
+	     debuginfod-tars/hello-1-1-x86_64.pkg.tar.xz \
+	     debuginfod-tars/hello-debug-1-1-x86_64.pkg.tar.bz2 \
+	     debuginfod-tars/pacman-sources/PKGBUILD \
+	     debuginfod-tars/pacman-sources/README.md \
+	     debuginfod-tars/pacman-sources/hello.c \
+	     run-pt_gnu_prop-tests.sh \
+	     testfile_pt_gnu_prop.bz2 testfile_pt_gnu_prop32.bz2 \
+	     run-getphdrnum.sh testfile-phdrs.elf.bz2 \
+	     run-test-includes.sh run-low_high_pc-dw-form-indirect.sh \
+	     run-readelf-dw-form-indirect.sh testfile-dw-form-indirect.bz2 \
+	     run-nvidia-extended-linemap-libdw.sh run-nvidia-extended-linemap-readelf.sh \
+	     testfile_nvidia_linemap.bz2 \
+	     testfile-largealign.o.bz2 run-strip-largealign.sh \
+	     run-funcretval++11.sh \
+	     test-ar-duplicates.a.bz2 \
+	     run-dwfl-core-noncontig.sh testcore-noncontig.bz2 \
+	     testfile-dwarf5-line-clang.bz2 \
+	     testfile-dwp-4.bz2 testfile-dwp-4.dwp.bz2 \
+	     testfile-dwp-4-strict.bz2 testfile-dwp-4-strict.dwp.bz2 \
+	     testfile-dwp-5.bz2 testfile-dwp-5.dwp.bz2 testfile-dwp.source \
+	     run-cu-dwp-section-info.sh run-declfiles.sh \
+	     testfile-dwp-5-cu-index-overflow.bz2 \
+	     testfile-dwp-5-cu-index-overflow.dwp.bz2 \
+	     testfile-dwp-4-cu-index-overflow.bz2 \
+	     testfile-dwp-4-cu-index-overflow.dwp.bz2 \
+	     testfile-dwp-cu-index-overflow.source
+
+
+if USE_VALGRIND
+valgrind_cmd=valgrind -q --leak-check=full --error-exitcode=1
+endif
+
+
+installed_TESTS_ENVIRONMENT = libdir='$(DESTDIR)$(libdir)'; \
+			      bindir='$(DESTDIR)$(bindir)'; \
+			      LC_ALL=C; LANG=C; \
+			      VALGRIND_CMD='$(valgrind_cmd)'; \
+			      abs_srcdir='$(abs_srcdir)'; \
+			      abs_builddir='$(abs_builddir)'; \
+			      abs_top_builddir='$(abs_top_builddir)'; \
+			      export abs_srcdir; export abs_builddir; \
+			      export abs_top_builddir; \
+			      export libdir; export bindir; \
+			      export LC_ALL; export LANG; export VALGRIND_CMD; \
+			      unset DEBUGINFOD_URLS; \
+			      NM='$(NM)'; export NM; \
+			      CC='$(CC)'; export CC;
+installed_LOG_COMPILER = $(abs_srcdir)/test-wrapper.sh \
+			 installed $(tests_rpath) \
+			 '$(program_transform_name)'
+TESTS_ENVIRONMENT = LC_ALL=C; LANG=C; VALGRIND_CMD='$(valgrind_cmd)'; \
+		    abs_srcdir='$(abs_srcdir)'; \
+		    abs_builddir='$(abs_builddir)'; \
+		    abs_top_builddir='$(abs_top_builddir)'; \
+		    export abs_srcdir; export abs_builddir; \
+		    export abs_top_builddir; \
+		    export LC_ALL; export LANG; export VALGRIND_CMD; \
+		    unset DEBUGINFOD_URLS; \
+		    NM='$(NM)'; export NM; \
+		    CC='$(CC)'; export CC;
+LOG_COMPILER = $(abs_srcdir)/test-wrapper.sh \
+	       $(abs_top_builddir)/libdw:$(abs_top_builddir)/backends:$(abs_top_builddir)/libelf:$(abs_top_builddir)/libasm:$(abs_top_builddir)/debuginfod
+
+installcheck-local:
+	$(MAKE) $(AM_MAKEFLAGS) \
+		TESTS_ENVIRONMENT="$(installed_TESTS_ENVIRONMENT)" \
+		LOG_COMPILER="$(installed_LOG_COMPILER)" check-TESTS
+
+if BUILD_STATIC
+libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl) -ldl -lpthread
+libelf = ../libelf/libelf.a -lz $(zstd_LIBS)
+libasm = ../libasm/libasm.a
+else
+libdw = ../libdw/libdw.so
+libelf = ../libelf/libelf.so
+libasm = ../libasm/libasm.so
+endif
+libebl = ../libebl/libebl.a ../backends/libebl_backends.a ../libcpu/libcpu.a
+libeu = ../lib/libeu.a
+
+arextract_LDADD = $(libelf)
+arsymtest_LDADD = $(libelf)
+newfile_LDADD = $(libelf)
+saridx_LDADD = $(libeu) $(libelf)
+scnnames_LDADD = $(libelf)
+sectiondump_LDADD = $(libeu) $(libelf)
+showptable_LDADD = $(libelf)
+hash_LDADD = $(libelf)
+test_nlist_CFLAGS =-g -O0 $(EXTRA_NLIST_CFLAGS)
+test_nlist_LDADD = $(libelf)
+msg_tst_LDADD = $(libelf)
+newscn_LDADD = $(libelf)
+early_offscn_LDADD = $(libeu) $(libelf)
+ecp_LDADD = $(libeu) $(libelf)
+update1_LDADD = $(libelf)
+update2_LDADD = $(libelf)
+update3_LDADD = $(libdw) $(libelf)
+update4_LDADD = $(libdw) $(libelf)
+show_die_info_LDADD = $(libdw) $(libelf)
+get_pubnames_LDADD = $(libdw) $(libelf)
+show_abbrev_LDADD = $(libdw) $(libelf)
+get_lines_LDADD = $(libdw) $(libelf)
+next_lines_LDADD = $(libdw) $(libelf)
+get_files_LDADD = $(libdw) $(libelf)
+next_files_LDADD = $(libdw) $(libelf)
+get_aranges_LDADD = $(libdw) $(libelf)
+allfcts_LDADD = $(libdw) $(libelf)
+line2addr_LDADD = $(libeu) $(libdw) $(argp_LDADD)
+addrscopes_LDADD = $(libeu) $(libdw) $(argp_LDADD)
+funcscopes_LDADD = $(libeu) $(libdw) $(argp_LDADD)
+funcretval_LDADD = $(libeu) $(libdw) $(argp_LDADD)
+allregs_LDADD = $(libeu) $(libdw) $(argp_LDADD)
+find_prologues_LDADD = $(libeu) $(libdw) $(argp_LDADD)
+#show_ciefde_LDADD = ../libdwarf/libdwarf.so $(libelf)
+asm_tst1_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst2_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst3_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst4_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst5_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst6_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst7_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst8_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+asm_tst9_LDADD = $(libasm) $(libebl) $(libelf) $(libdw)
+dwflmodtest_LDADD = $(libeu) $(libdw) $(libebl) $(libelf) $(argp_LDADD)
+rdwrmmap_LDADD = $(libeu) $(libelf)
+dwfl_bug_addr_overflow_LDADD = $(libdw) $(libebl) $(libelf)
+arls_LDADD = $(libelf)
+dwfl_bug_fd_leak_LDADD = $(libeu) $(libdw) $(libebl) $(libelf)
+dwfl_bug_report_LDADD = $(libdw) $(libebl) $(libelf)
+dwfl_bug_getmodules_LDADD = $(libeu) $(libdw) $(libebl) $(libelf)
+dwfl_addr_sect_LDADD = $(libeu) $(libdw) $(libebl) $(libelf) $(argp_LDADD)
+dwfl_core_noncontig_LDADD = $(libdw) $(libelf)
+dwarf_getmacros_LDADD = $(libdw)
+dwarf_ranges_LDADD = $(libdw)
+dwarf_getstring_LDADD = $(libdw)
+addrcfi_LDADD = $(libdw) $(libebl) $(libelf) $(argp_LDADD)
+dwarfcfi_LDADD = $(libeu) $(libdw) $(libelf)
+test_flag_nobits_LDADD = $(libelf)
+rerequest_tag_LDADD = $(libdw)
+alldts_LDADD = $(libdw) $(libelf)
+typeiter_LDADD = $(libdw) $(libelf)
+typeiter2_LDADD = $(libdw) $(libelf)
+low_high_pc_LDADD = $(libdw) $(libelf) $(argp_LDADD)
+test_elf_cntl_gelf_getshdr_LDADD = $(libelf)
+dwflsyms_LDADD = $(libdw) $(libelf) $(argp_LDADD)
+dwfllines_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
+dwfl_report_elf_align_LDADD = $(libeu) $(libdw)
+dwfl_report_offline_memory_LDADD = $(libeu) $(libdw) $(libelf)
+dwfl_report_segment_contiguous_LDADD = $(libdw) $(libebl) $(libelf)
+varlocs_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
+backtrace_LDADD = $(libeu) $(libdw) $(libelf) $(argp_LDADD)
+# backtrace-child-biarch also uses those *_CFLAGS and *_LDLAGS variables:
+backtrace_child_CFLAGS = $(fpie_CFLAGS)
+backtrace_child_LDFLAGS = -pie -pthread
+backtrace_child_biarch_SOURCES = backtrace-child.c
+backtrace_data_LDADD = $(libeu) $(libdw) $(libelf)
+backtrace_dwarf_CFLAGS = -Wno-unused-parameter
+backtrace_dwarf_LDADD = $(libeu) $(libdw) $(libelf)
+debuglink_LDADD = $(libeu) $(libdw) $(libelf)
+debugaltlink_LDADD = $(libeu) $(libdw) $(libelf)
+buildid_LDADD = $(libeu) $(libdw) $(libelf)
+deleted_LDADD = ./deleted-lib.so
+deleted_lib_so_LDFLAGS = -shared
+deleted_lib_so_CFLAGS = $(fpic_CFLAGS) -fasynchronous-unwind-tables
+aggregate_size_LDADD = $(libdw) $(libelf) $(argp_LDADD)
+peel_type_LDADD = $(libdw) $(libelf) $(argp_LDADD)
+vdsosyms_LDADD = $(libeu) $(libdw) $(libelf)
+getsrc_die_LDADD = $(libeu) $(libdw) $(libelf)
+strptr_LDADD = $(libelf)
+newdata_LDADD = $(libelf)
+elfstrtab_LDADD = $(libelf)
+dwfl_proc_attach_LDADD = $(libeu) $(libdw)
+dwfl_proc_attach_LDFLAGS = -pthread -rdynamic $(AM_LDFLAGS)
+elfshphehdr_LDADD =$(libelf)
+elfstrmerge_LDADD = $(libeu) $(libdw) $(libelf)
+dwelfgnucompressed_LDADD = $(libelf) $(libdw)
+elfgetchdr_LDADD = $(libelf) $(libdw)
+elfgetzdata_LDADD = $(libelf)
+elfputzdata_LDADD = $(libelf)
+zstrptr_LDADD = $(libelf)
+emptyfile_LDADD = $(libelf)
+vendorelf_LDADD = $(libelf)
+fillfile_LDADD = $(libelf)
+dwarf_default_lower_bound_LDADD = $(libdw)
+dwarf_die_addr_die_LDADD = $(libdw)
+get_units_invalid_LDADD = $(libdw)
+get_units_split_LDADD = $(libdw)
+attr_integrate_skel_LDADD = $(libdw)
+all_dwarf_ranges_LDADD = $(libdw)
+unit_info_LDADD = $(libdw)
+next_cfi_LDADD = $(libeu) $(libelf) $(libdw)
+elfcopy_LDADD = $(libelf)
+addsections_LDADD = $(libelf)
+debuginfod_build_id_find_LDADD = $(libelf) $(libdw)
+xlate_notes_LDADD = $(libelf)
+elfrdwrnop_LDADD = $(libelf)
+dwelf_elf_e_machine_string_LDADD = $(libelf) $(libdw)
+getphdrnum_LDADD = $(libelf) $(libdw)
+leb128_LDADD = $(libelf) $(libdw)
+read_unaligned_LDADD = $(libelf) $(libdw)
+nvidia_extended_linemap_libdw_LDADD = $(libelf) $(libdw)
+elf_print_reloc_syms_LDADD = $(libelf)
+cu_dwp_section_info_LDADD = $(libdw)
+declfiles_LDADD = $(libdw)
+
+# We want to test the libelf headers against the system elf.h header.
+# Don't include any -I CPPFLAGS. Except when we install our own elf.h.
+# For the gelf test we do want our own libelf.h, but nothing else.
+BUILT_SOURCES = libelf.h
+CLEANFILES += libelf.h
+libelf.h: $(top_srcdir)/libelf/libelf.h
+	cp $< $@
+if !INSTALL_ELFH
+system_elf_libelf_test_CPPFLAGS =
+system_elf_gelf_test_CPPFLAGS = -I.
+else
+system_elf_libelf_test_CPPFLAGS = -I$(top_srcdir)/libelf
+system_elf_gelf_test_CPPFLAGS = -I$(top_srcdir)/libelf
+endif
+system_elf_libelf_test_LDADD = $(libelf)
+system_elf_gelf_test_LDADD = $(libelf)
+
+# A lock file used to make sure only one test dumps core at a time
+CLEANFILES += core-dump-backtrace.lock
+
+if GCOV
+check: check-am coverage
+.PHONY: coverage
+coverage:
+	-$(srcdir)/coverage.sh
+endif
diff --git a/tests/addrcfi.c b/tests/addrcfi.c
new file mode 100644
index 0000000..2b7d7bd
--- /dev/null
+++ b/tests/addrcfi.c
@@ -0,0 +1,233 @@
+/* Test program for CFI handling.
+   Copyright (C) 2009-2010, 2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "../libdw/known-dwarf.h"
+
+static const char *
+op_name (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+static void
+print_detail (int result, const Dwarf_Op *ops, size_t nops, Dwarf_Addr bias)
+{
+  if (result < 0)
+    printf ("indeterminate (%s)\n", dwarf_errmsg (-1));
+  else if (nops == 0)
+    printf ("%s\n", ops == NULL ? "same_value" : "undefined");
+  else
+    {
+      printf ("%s expression:", result == 0 ? "location" : "value");
+      for (size_t i = 0; i < nops; ++i)
+	{
+	  printf (" %s", op_name(ops[i].atom));
+	  if (ops[i].number2 == 0)
+	    {
+	      if (ops[i].atom == DW_OP_addr)
+		printf ("(%#" PRIx64 ")", ops[i].number + bias);
+	      else if (ops[i].number != 0)
+		printf ("(%" PRId64 ")", ops[i].number);
+	    }
+	  else
+	    printf ("(%" PRId64 ",%" PRId64 ")",
+		    ops[i].number, ops[i].number2);
+	}
+      puts ("");
+    }
+}
+
+struct stuff
+{
+  Dwarf_Frame *frame;
+  Dwarf_Addr bias;
+};
+
+static int
+print_register (void *arg,
+		int regno,
+		const char *setname,
+		const char *prefix,
+		const char *regname,
+		int bits __attribute__ ((unused)),
+		int type __attribute__ ((unused)))
+{
+  struct stuff *stuff = arg;
+
+  printf ("\t%s reg%u (%s%s): ", setname, regno, prefix, regname);
+
+  Dwarf_Op ops_mem[3];
+  Dwarf_Op *ops;
+  size_t nops;
+  int result = dwarf_frame_register (stuff->frame, regno, ops_mem, &ops, &nops);
+  print_detail (result, ops, nops, stuff->bias);
+
+  return DWARF_CB_OK;
+}
+
+static int
+handle_cfi (Dwfl *dwfl, const char *which, Dwarf_CFI *cfi,
+	    GElf_Addr pc, struct stuff *stuff)
+{
+  if (cfi == NULL)
+    {
+      printf ("handle_cfi no CFI (%s): %s\n", which, dwarf_errmsg (-1));
+      return -1;
+    }
+
+  int result = dwarf_cfi_addrframe (cfi, pc - stuff->bias, &stuff->frame);
+  if (result != 0)
+    {
+      printf ("dwarf_cfi_addrframe (%s): %s\n", which, dwarf_errmsg (-1));
+      return 1;
+    }
+
+  Dwarf_Addr start = pc;
+  Dwarf_Addr end = pc;
+  bool signalp;
+  int ra_regno = dwarf_frame_info (stuff->frame, &start, &end, &signalp);
+  if (ra_regno >= 0)
+    {
+      start += stuff->bias;
+      end += stuff->bias;
+    }
+
+  printf ("%s has %#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n",
+	  which, pc, start, end);
+
+  if (ra_regno < 0)
+    printf ("\treturn address register unavailable (%s)\n",
+	    dwarf_errmsg (0));
+  else
+    printf ("\treturn address in reg%u%s\n",
+	    ra_regno, signalp ? " (signal frame)" : "");
+
+  // Point cfa_ops to dummy to match print_detail expectations.
+  // (nops == 0 && cfa_ops != NULL => "undefined")
+  Dwarf_Op dummy;
+  Dwarf_Op *cfa_ops = &dummy;
+  size_t cfa_nops;
+  result = dwarf_frame_cfa (stuff->frame, &cfa_ops, &cfa_nops);
+
+  printf ("\tCFA ");
+  print_detail (result, cfa_ops, cfa_nops, stuff->bias);
+
+  (void) dwfl_module_register_names (dwfl_addrmodule (dwfl, pc),
+				     &print_register, stuff);
+
+  return 0;
+}
+
+static int
+handle_address (GElf_Addr pc, Dwfl *dwfl)
+{
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc);
+
+  struct stuff stuff;
+  stuff.frame = NULL;
+  stuff.bias = 0;
+  int res = handle_cfi (dwfl, ".eh_frame",
+			dwfl_module_eh_cfi (mod, &stuff.bias), pc, &stuff);
+  free (stuff.frame);
+
+  stuff.frame = NULL;
+  stuff.bias = 0;
+  res &= handle_cfi (dwfl, ".debug_frame",
+		     dwfl_module_dwarf_cfi (mod, &stuff.bias), pc, &stuff);
+  free (stuff.frame);
+
+  return res;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+
+  int result = 0;
+
+  /* Now handle the addresses.  In case none are given on the command
+     line, read from stdin.  */
+  if (remaining == argc)
+    {
+      /* We use no threads here which can interfere with handling a stream.  */
+      (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+
+      char *buf = NULL;
+      size_t len = 0;
+      while (!feof_unlocked (stdin))
+	{
+	  if (getline (&buf, &len, stdin) < 0)
+	    break;
+
+	  char *endp;
+	  uintmax_t addr = strtoumax (buf, &endp, 0);
+	  if (endp != buf)
+	    result |= handle_address (addr, dwfl);
+	  else
+	    result = 1;
+	}
+
+      free (buf);
+    }
+  else
+    {
+      do
+	{
+	  char *endp;
+	  uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
+	  if (endp != argv[remaining])
+	    result |= handle_address (addr, dwfl);
+	  else
+	    result = 1;
+	}
+      while (++remaining < argc);
+    }
+
+  dwfl_end (dwfl);
+
+  return result;
+}
diff --git a/tests/addrscopes.c b/tests/addrscopes.c
new file mode 100644
index 0000000..b231b6a
--- /dev/null
+++ b/tests/addrscopes.c
@@ -0,0 +1,196 @@
+/* Test program for dwarf_getscopes.
+   Copyright (C) 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include "system.h"
+
+
+static void
+paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line)
+{
+  const char *src;
+  int lineno, linecol;
+  if (line != NULL
+      && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
+			       NULL, NULL)) != NULL)
+    {
+      if (linecol != 0)
+	printf ("%s%#" PRIx64 " (%s:%d:%d)",
+		prefix, addr, src, lineno, linecol);
+      else
+	printf ("%s%#" PRIx64 " (%s:%d)",
+		prefix, addr, src, lineno);
+    }
+  else
+    printf ("%s%#" PRIx64, prefix, addr);
+}
+
+static void
+print_vars (unsigned int indent, Dwarf_Die *die)
+{
+  Dwarf_Die child;
+  if (dwarf_child (die, &child) == 0)
+    do
+      switch (dwarf_tag (&child))
+	{
+	case DW_TAG_variable:
+	case DW_TAG_formal_parameter:
+	  printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "",
+		  dwarf_diename (&child),
+		  (uint64_t) dwarf_dieoffset (&child));
+	  break;
+	default:
+	  break;
+	}
+    while (dwarf_siblingof (&child, &child) == 0);
+
+  Dwarf_Attribute attr_mem;
+  Dwarf_Die origin;
+  if (dwarf_hasattr (die, DW_AT_abstract_origin)
+      && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem),
+			    &origin) != NULL
+      && dwarf_child (&origin, &child) == 0)
+    do
+      switch (dwarf_tag (&child))
+	{
+	case DW_TAG_variable:
+	case DW_TAG_formal_parameter:
+	  printf ("%*s%s (abstract)\n", indent, "",
+		  dwarf_diename (&child));
+	  break;
+	default:
+	  break;
+	}
+    while (dwarf_siblingof (&child, &child) == 0);
+}
+
+
+#define INDENT 4
+
+static void
+handle_address (GElf_Addr pc, Dwfl *dwfl)
+{
+  Dwarf_Addr cubias;
+  Dwarf_Die *cudie = dwfl_addrdie (dwfl, pc, &cubias);
+  if (cudie == NULL)
+    error (EXIT_FAILURE, 0, "dwfl_addrdie: %s", dwfl_errmsg (-1));
+
+  Dwarf_Die *scopes;
+  int n = dwarf_getscopes (cudie, pc - cubias, &scopes);
+  if (n < 0)
+    error (EXIT_FAILURE, 0, "dwarf_getscopes: %s", dwarf_errmsg (-1));
+  else if (n == 0)
+    printf ("%#" PRIx64 ": not in any scope\n", pc);
+  else
+    {
+      printf ("%#" PRIx64 ":\n", pc);
+      unsigned int indent = 0;
+      while (n-- > 0)
+	{
+	  Dwarf_Die *const die = &scopes[n];
+
+	  indent += INDENT;
+	  printf ("%*s%s (%#x)", indent, "",
+		  dwarf_diename (die) ?: "<unnamed>",
+		  dwarf_tag (die));
+
+	  Dwarf_Addr lowpc, highpc;
+	  if (dwarf_lowpc (die, &lowpc) == 0
+	      && dwarf_highpc (die, &highpc) == 0)
+	    {
+	      lowpc += cubias;
+	      highpc += cubias;
+	      Dwfl_Line *loline = dwfl_getsrc (dwfl, lowpc);
+	      Dwfl_Line *hiline = dwfl_getsrc (dwfl, highpc - 1);
+	      paddr (": ", lowpc, loline);
+	      if (highpc != lowpc)
+		paddr (" .. ", highpc - 1, hiline == loline ? NULL : hiline);
+	    }
+	  puts ("");
+
+	  print_vars (indent + INDENT, die);
+	}
+      free (scopes);
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+
+  int result = 0;
+
+  /* Now handle the addresses.  In case none are given on the command
+     line, read from stdin.  */
+  if (remaining == argc)
+    {
+      /* We use no threads here which can interfere with handling a stream.  */
+      (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+
+      char *buf = NULL;
+      size_t len = 0;
+      while (!feof_unlocked (stdin))
+	{
+	  if (getline (&buf, &len, stdin) < 0)
+	    break;
+
+	  char *endp;
+	  uintmax_t addr = strtoumax (buf, &endp, 0);
+	  if (endp != buf)
+	    handle_address (addr, dwfl);
+	  else
+	    result = 1;
+	}
+
+      free (buf);
+    }
+  else
+    {
+      do
+	{
+	  char *endp;
+	  uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
+	  if (endp != argv[remaining])
+	    handle_address (addr, dwfl);
+	  else
+	    result = 1;
+	}
+      while (++remaining < argc);
+    }
+
+  dwfl_end (dwfl);
+
+  return result;
+}
diff --git a/tests/addrx_constx-4.dwo.bz2 b/tests/addrx_constx-4.dwo.bz2
new file mode 100644
index 0000000..f0bae1c
--- /dev/null
+++ b/tests/addrx_constx-4.dwo.bz2
Binary files differ
diff --git a/tests/addrx_constx-5.dwo.bz2 b/tests/addrx_constx-5.dwo.bz2
new file mode 100644
index 0000000..a5f4b1a
--- /dev/null
+++ b/tests/addrx_constx-5.dwo.bz2
Binary files differ
diff --git a/tests/addsections.c b/tests/addsections.c
new file mode 100644
index 0000000..a4e4203
--- /dev/null
+++ b/tests/addsections.c
@@ -0,0 +1,332 @@
+/* Test program for adding (more than SHN_LORESERVE) sections.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+/* shstrndx is special, might overflow into section zero header sh_link.  */
+static int
+setshstrndx (Elf *elf, size_t ndx)
+{
+  printf ("setshstrndx: %zd\n", ndx);
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    return -1;
+
+  if (ndx < SHN_LORESERVE)
+    ehdr->e_shstrndx = ndx;
+  else
+    {
+      ehdr->e_shstrndx = SHN_XINDEX;
+      Elf_Scn *zscn = elf_getscn (elf, 0);
+      GElf_Shdr zshdr_mem;
+      GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
+      if (zshdr == NULL)
+	return -1;
+      zshdr->sh_link = ndx;
+      if (gelf_update_shdr (zscn, zshdr) == 0)
+	return -1;
+    }
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    return -1;
+
+  return 0;
+}
+
+/* Will add nr new '.extra' sections and a new '.new_shstrtab' section
+   at the end.  */
+static void
+add_sections (const char *name, size_t nr, int use_mmap, size_t sec_size)
+{
+  printf ("add_sections '%s': %zd (sec_size: %zd)\n", name, nr, sec_size);
+
+  int fd = open (name, O_RDWR);
+  if (fd < 0)
+    {
+      fprintf (stderr, "Couldn't open file '%s': %s\n",
+	       name, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
+  if (elf == NULL)
+    {
+      fprintf (stderr, "Couldn't open ELF file '%s': %s\n",
+	       name, elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* We will add a new shstrtab section with two new names at the end.
+     Just get the current shstrtab table and add two entries '.extra'
+     and '.old_shstrtab' at the end of the table, so all existing indexes
+     are still valid.  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+    {
+      printf ("cannot get shstrndx: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  Elf_Scn *shstrtab_scn = elf_getscn (elf, shstrndx);
+  if (shstrtab_scn == NULL)
+    {
+      printf ("couldn't get shstrtab scn: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  Elf_Data *shstrtab_data = elf_getdata (shstrtab_scn, NULL);
+  if (shstrtab_data == NULL)
+    {
+      printf ("couldn't get shstrtab data: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  size_t new_shstrtab_size = (shstrtab_data->d_size
+			      + strlen (".extra") + 1
+			      + strlen (".old_shstrtab") + 1);
+  void *new_shstrtab_buf = malloc (new_shstrtab_size);
+  if (new_shstrtab_buf == NULL)
+    {
+      printf ("couldn't allocate new shstrtab data d_buf\n");
+      exit (1);
+    }
+  memcpy (new_shstrtab_buf, shstrtab_data->d_buf, shstrtab_data->d_size);
+  size_t extra_idx = shstrtab_data->d_size;
+  size_t old_shstrtab_idx = extra_idx + strlen (".extra") + 1;
+  strcpy (new_shstrtab_buf + extra_idx, ".extra");
+  strcpy (new_shstrtab_buf + old_shstrtab_idx, ".old_shstrtab");
+
+  /* Change the name of the old shstrtab section, because elflint
+     has a strict check on the name/type for .shstrtab.  */
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (shstrtab_scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for old shstrtab section: %s\n",
+              elf_errmsg (-1));
+      exit (1);
+    }
+
+  size_t shstrtab_idx = shdr->sh_name;
+  shdr->sh_name = old_shstrtab_idx;
+
+  if (gelf_update_shdr (shstrtab_scn, shdr) == 0)
+    {
+      printf ("cannot update old shstrtab section header: %s\n",
+	      elf_errmsg (-1));
+      exit (1);
+    }
+
+  void *buf;
+  size_t bufsz;
+  if (sec_size == 0)
+    {
+      buf = "";
+      bufsz = 1;
+    }
+  else
+    {
+      buf = malloc (sec_size);
+      if (buf == NULL)
+	{
+	  printf ("cannot allocate buffer data of %zd bytes\n", sec_size);
+	  exit (1);
+	}
+      memset (buf, 0xAA, sec_size);
+      bufsz = sec_size;
+    }
+
+  // Add lots of .extra sections...
+  size_t cnt = 0;
+  while (cnt++ < nr)
+    {
+      Elf_Scn *scn = elf_newscn (elf);
+      if (scn == NULL)
+	{
+	  printf ("cannot create .extra section (%zd): %s\n", cnt,
+		  elf_errmsg (-1));
+	  exit (1);
+	}
+
+      Elf_Data *data = elf_newdata (scn);
+      if (data == NULL)
+	{
+	  printf ("couldn't create new section data (%zd): %s\n", cnt,
+		  elf_errmsg (-1));
+	  exit (1);
+	}
+
+      data->d_size = bufsz;
+      data->d_buf = buf;
+      data->d_type = ELF_T_BYTE;
+      data->d_align = 1;
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get header for new section (%zd): %s\n", cnt,
+		  elf_errmsg (-1));
+	  exit (1);
+	}
+
+      shdr->sh_type = SHT_PROGBITS;
+      shdr->sh_flags = 0;
+      shdr->sh_addr = 0;
+      shdr->sh_link = SHN_UNDEF;
+      shdr->sh_info = SHN_UNDEF;
+      shdr->sh_addralign = 1;
+      shdr->sh_entsize = 0;
+      shdr->sh_size = data->d_size;
+      shdr->sh_name = extra_idx;
+
+      if (gelf_update_shdr (scn, shdr) == 0)
+	{
+	  printf ("cannot update new section header (%zd): %s\n", cnt,
+		  elf_errmsg (-1));
+	  exit (1);
+	}
+    }
+
+  // Create new shstrtab section.
+  Elf_Scn *new_shstrtab_scn = elf_newscn (elf);
+  if (new_shstrtab_scn == NULL)
+    {
+      printf ("cannot create new shstrtab section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  Elf_Data *new_shstrtab_data = elf_newdata (new_shstrtab_scn);
+  if (new_shstrtab_data == NULL)
+    {
+      printf ("couldn't create new shstrtab section data: %s\n",
+	      elf_errmsg (-1));
+      exit (1);
+    }
+
+  new_shstrtab_data->d_size = new_shstrtab_size;
+  new_shstrtab_data->d_buf = new_shstrtab_buf;
+  new_shstrtab_data->d_type = ELF_T_BYTE;
+  new_shstrtab_data->d_align = 1;
+
+  shdr = gelf_getshdr (new_shstrtab_scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for new shstrtab section: %s\n",
+	      elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 1;
+  shdr->sh_entsize = 0;
+  shdr->sh_size = new_shstrtab_size;
+  shdr->sh_name = shstrtab_idx;
+
+  // Finished new shstrtab section, update the header.
+  if (gelf_update_shdr (new_shstrtab_scn, shdr) == 0)
+    {
+      printf ("cannot update new shstrtab section header: %s\n",
+	      elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Set it as the new shstrtab section to get the names correct.
+  size_t new_shstrndx = elf_ndxscn (new_shstrtab_scn);
+  if (setshstrndx (elf, new_shstrndx) < 0)
+    {
+      printf ("cannot set shstrndx: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("couldn't cleanup elf '%s': %s\n", name, elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (close (fd) != 0)
+    {
+      printf ("couldn't close '%s': %s\n", name, strerror (errno));
+      exit (1);
+    }
+
+  if (sec_size != 0)
+    free (buf);
+  free (new_shstrtab_buf);
+}
+
+int
+main (int argc, char *argv[])
+{
+  elf_version (EV_CURRENT);
+
+  /* Takes the given file, and adds the given number of sections.
+     Optionally using mmap and optionally using a given section size.  */
+  if (argc < 3 || argc > 5)
+    {
+      fprintf (stderr, "addsections [--mmap] nr elf.file [sec_size]\n");
+      exit (1);
+    }
+
+  int argn = 1;
+  bool use_mmap = false;
+  if (strcmp (argv[argn], "--mmap") == 0)
+    {
+      use_mmap = true;
+      argn++;
+    }
+
+  size_t nr = atoi (argv[argn++]);
+  const char *file = argv[argn++];
+
+  size_t sec_size = 0;
+  if (argn < argc)
+    sec_size = atol (argv[argn++]);
+
+  add_sections (file, nr, use_mmap, sec_size);
+
+  return 0;
+}
diff --git a/tests/aggregate_size.c b/tests/aggregate_size.c
new file mode 100644
index 0000000..930eafa
--- /dev/null
+++ b/tests/aggregate_size.c
@@ -0,0 +1,83 @@
+/* Test program for dwarf_aggregate_size. Prints size of top-level vars.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <argp.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwfl)
+#include <stdio.h>
+#include <unistd.h>
+#include <dwarf.h>
+
+void
+print_var_type_size (Dwarf_Die *var)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Die type_mem;
+  Dwarf_Die *type;
+  const char *name = dwarf_diename (var);
+
+  type = dwarf_formref_die (dwarf_attr (var, DW_AT_type, &attr_mem),
+			    &type_mem);
+  if (type != NULL)
+    {
+      Dwarf_Word size;
+      if (dwarf_aggregate_size (type, &size) < 0)
+        printf ("%s no size: %s\n", name, dwarf_errmsg (-1));
+      else
+	printf ("%s size %" PRIu64 "\n", name, size);
+    }
+  else
+    printf ("%s has no type.\n", name);
+}
+
+int
+main (int argc, char *argv[])
+{
+
+  int remaining;
+  Dwfl *dwfl;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+                     &dwfl);
+  assert (dwfl != NULL);
+
+  Dwarf_Die *cu = NULL;
+  Dwarf_Addr dwbias;
+  while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
+    {
+      Dwarf_Die die_mem;
+      Dwarf_Die *die = &die_mem;
+      dwarf_child (cu, &die_mem);
+
+      while (1)
+	{
+	  if (dwarf_tag (die) == DW_TAG_variable)
+	    print_var_type_size (die);
+
+	  if (dwarf_siblingof (die, &die_mem) != 0)
+	    break;
+	}
+    }
+
+  dwfl_end (dwfl);
+}
diff --git a/tests/all-dwarf-ranges.c b/tests/all-dwarf-ranges.c
new file mode 100644
index 0000000..4331a05
--- /dev/null
+++ b/tests/all-dwarf-ranges.c
@@ -0,0 +1,90 @@
+/* Test program for dwarf_ranges
+   Copyright (C) 2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+
+static void
+ranges_die (Dwarf_Die *die)
+{
+  Dwarf_Addr base, start, end;
+  int ranges = dwarf_ranges (die, 0, &base, &start, &end);
+  if (ranges < 0)
+    puts (dwarf_errmsg (-1));
+  else if (ranges > 0)
+    {
+      printf ("die: %s (%x)\n", dwarf_diename (die) ?: "<unknown>",
+	      dwarf_tag (die));
+      for (ptrdiff_t off = 0;
+	   (off = dwarf_ranges (die, off, &base, &start, &end)); )
+	if (off == -1)
+	  {
+	    puts (dwarf_errmsg (-1));
+	    break;
+	  }
+	else
+	  printf (" %"PRIx64"..%"PRIx64"\n", start, end);
+      printf ("\n");
+    }
+}
+
+static void
+walk_tree (Dwarf_Die *dwarf_die)
+{
+  Dwarf_Die die = *dwarf_die;
+  do
+    {
+      Dwarf_Die child;
+      ranges_die (&die);
+      if (dwarf_child (&die, &child) == 0)
+	walk_tree (&child);
+    }
+  while (dwarf_siblingof (&die, &die) == 0);
+}
+
+int
+main (int argc, char *argv[])
+{
+  assert (argc >= 2);
+  const char *name = argv[1];
+
+  int fd = open (name, O_RDONLY);
+  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+
+  Dwarf_CU *cu = NULL;
+  Dwarf_Die cudie, subdie;
+  uint8_t unit_type;
+  while (dwarf_get_units (dbg, cu, &cu, NULL,
+			  &unit_type, &cudie, &subdie) == 0)
+    {
+      Dwarf_Die die = (unit_type == DW_UT_skeleton
+		       ? subdie : cudie);
+      walk_tree (&die);
+    }
+  dwarf_end (dbg);
+
+  return 0;
+}
diff --git a/tests/alldts.c b/tests/alldts.c
new file mode 100644
index 0000000..d0fe4f2
--- /dev/null
+++ b/tests/alldts.c
@@ -0,0 +1,272 @@
+/* Create an ELF file with all the DT_* flags set.
+   Copyright (C) 2011, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Marek Polacek <mpolacek@redhat.com>, 2011.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include ELFUTILS_HEADER(dwelf)
+#include <elf.h>
+#include <gelf.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+
+int
+main (void)
+{
+  static const char fname[] = "testfile-alldts";
+  Dwelf_Strtab *shst;
+  Dwelf_Strent *dynscn;
+  Dwelf_Strent *shstrtabse;
+  const Elf32_Sword dtflags[] =
+    {
+      DT_NEEDED, DT_PLTRELSZ, DT_PLTGOT,
+      DT_HASH, DT_STRTAB, DT_SYMTAB, DT_RELA,
+      DT_RELASZ, DT_RELAENT, DT_STRSZ, DT_SYMENT,
+      DT_INIT, DT_FINI, DT_SONAME, DT_RPATH,
+      DT_SYMBOLIC, DT_REL, DT_RELSZ, DT_RELENT,
+      DT_PLTREL, DT_DEBUG, DT_TEXTREL, DT_JMPREL,
+      DT_BIND_NOW, DT_INIT_ARRAY, DT_FINI_ARRAY,
+      DT_INIT_ARRAYSZ, DT_FINI_ARRAYSZ, DT_RUNPATH,
+      DT_FLAGS, DT_ENCODING, DT_PREINIT_ARRAY,
+      DT_PREINIT_ARRAYSZ, DT_VERSYM, DT_GNU_PRELINKED,
+      DT_GNU_CONFLICTSZ, DT_GNU_LIBLISTSZ, DT_CHECKSUM,
+      DT_PLTPADSZ, DT_MOVEENT, DT_MOVESZ, DT_FEATURE_1,
+      DT_POSFLAG_1, DT_SYMINSZ, DT_SYMINENT, DT_GNU_HASH,
+      DT_TLSDESC_PLT, DT_TLSDESC_GOT, DT_GNU_CONFLICT,
+      DT_GNU_LIBLIST, DT_CONFIG, DT_DEPAUDIT, DT_AUDIT,
+      DT_PLTPAD, DT_MOVETAB, DT_SYMINFO, DT_RELACOUNT,
+      DT_RELCOUNT, DT_FLAGS_1, DT_VERDEF, DT_VERDEFNUM,
+      DT_VERNEED, DT_VERNEEDNUM, DT_AUXILIARY, DT_FILTER,
+      DT_NULL
+    };
+  const int ndtflags = sizeof (dtflags) / sizeof (dtflags[0]);
+
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Open the file.  */
+  int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %m\n", fname);
+      return 1;
+    }
+
+  /* Tell the library which version are we expecting.  */
+  elf_version (EV_CURRENT);
+
+  /* Create an ELF descriptor.  */
+  Elf *elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  /* Create an ELF header.  */
+  Elf32_Ehdr *ehdr = elf32_newehdr (elf);
+  if (ehdr == NULL)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  ehdr->e_ident[0] = 42;
+  ehdr->e_ident[5] = 1;
+  ehdr->e_ident[6] = 2;
+  ehdr->e_type = ET_EXEC;
+  ehdr->e_machine = EM_386;
+  ehdr->e_version = 1;
+  ehdr->e_ehsize = 1;
+  ehdr->e_shnum = 3;
+
+  elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  /* Create the program headers.  */
+  Elf32_Phdr *phdr = elf32_newphdr (elf, 2);
+  if (phdr == NULL)
+    {
+      printf ("cannot create program headers: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  phdr[0].p_type = PT_PHDR;
+  phdr[1].p_type = PT_DYNAMIC;
+
+  elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
+  shst = dwelf_strtab_init (true);
+
+  /* Create the .dynamic section.  */
+  Elf_Scn *scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create DYNAMIC section: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  Elf32_Shdr *shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for DYNAMIC section: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  dynscn = dwelf_strtab_add (shst, ".dynamic");
+
+  /* We'll need to know the section offset.  But this will be set up
+     by elf_update later, so for now just store the address.  */
+  const Elf32_Off *const dynscn_offset = &shdr->sh_offset;
+  shdr->sh_type = SHT_DYNAMIC;
+  shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  /* This section will start here.  */
+  shdr->sh_addr = 0x1a0;
+
+  /* Create new section data.  */
+  Elf_Data *data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data for DYNAMIC section: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  /* Allocate memory for all the .dynamic entries.  */
+  Elf32_Dyn *dyn = malloc (ndtflags * sizeof (Elf32_Dyn));
+  if (dyn == NULL)
+    {
+      printf ("malloc failed: %m\n");
+      return 1;
+    }
+
+  /* Now write all the DT_* flags.  */
+  for (int i = 0; i < ndtflags; ++i)
+    {
+      dyn[i].d_tag = dtflags[i];
+      dyn[i].d_un.d_val = 0xdeadbeef;
+    }
+
+  /* Set the pointer to allocated memory.  */
+  data->d_buf = dyn;
+  data->d_type = ELF_T_DYN;
+  data->d_version = EV_CURRENT;
+  data->d_size = ndtflags * sizeof (Elf32_Dyn);
+  data->d_align = 0x8;
+
+  /* Create .shstrtab section.  */
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  shstrtabse = dwelf_strtab_add (shst, ".shstrtab");
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_entsize = 1;
+
+  /* We have to store the section index in the ELF header.  */
+  ehdr->e_shstrndx = elf_ndxscn (scn);
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  /* No more sections, finalize the section header string table.  */
+  dwelf_strtab_finalize (shst, data);
+
+  elf32_getshdr (elf_getscn (elf, 1))->sh_name = dwelf_strent_off (dynscn);
+  shdr->sh_name = dwelf_strent_off (shstrtabse);
+
+  /* Let the library compute the internal structure information.  */
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  ehdr = elf32_getehdr (elf);
+
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_vaddr = ehdr->e_phoff;
+  phdr[0].p_paddr = ehdr->e_phoff;
+  phdr[0].p_flags = PF_R | PF_X;
+  phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_align = sizeof (Elf32_Word);
+
+  phdr[1].p_flags = PF_W | PF_R;
+  phdr[1].p_offset = *dynscn_offset;
+  /* Set up the start of this segment to equal start address of the
+     .dynamic section.  */
+  phdr[1].p_vaddr = 0x1a0;
+  phdr[1].p_paddr = 0x1a0;
+  phdr[1].p_align = 2 * sizeof (Elf32_Word);
+  phdr[1].p_filesz = ndtflags * sizeof (Elf32_Dyn);
+  phdr[1].p_memsz = ndtflags * sizeof (Elf32_Dyn);
+
+  /* Write out the file.  */
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  /* We don't need the string table anymore.  */
+  dwelf_strtab_free (shst);
+
+  /* And the data allocated in the .shstrtab section.  */
+  free (data->d_buf);
+
+  /* And the dynamic entries.  */
+  free (dyn);
+
+  /* All done.  */
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      return 1;
+    }
+
+  return 0;
+}
diff --git a/tests/allfcts.c b/tests/allfcts.c
new file mode 100644
index 0000000..f637311
--- /dev/null
+++ b/tests/allfcts.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 2005, 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <err.h>
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwelf)
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int
+cb (Dwarf_Die *func, void *arg __attribute__ ((unused)))
+{
+  const char *file = dwarf_decl_file (func);
+  int line = -1;
+  dwarf_decl_line (func, &line);
+  const char *fct = dwarf_diename (func);
+
+  printf ("%s:%d:%s\n", file, line, fct);
+
+  return DWARF_CB_ABORT;
+}
+
+static Dwarf *
+setup_alt (Dwarf *main)
+{
+  const char *alt_name;
+  const void *build_id;
+  ssize_t ret = dwelf_dwarf_gnu_debugaltlink (main, &alt_name, &build_id);
+  if (ret == 0)
+    return NULL;
+  if (ret == -1)
+    errx (1, "dwelf_dwarf_gnu_debugaltlink: %s", dwarf_errmsg (-1));
+  int fd = open (alt_name, O_RDONLY);
+  if (fd < 0)
+    {
+      printf ("Warning: no alt file found.\n");
+      return NULL;
+    }
+  Dwarf *dbg_alt = dwarf_begin (fd, DWARF_C_READ);
+  if (dbg_alt == NULL)
+    errx (1, "dwarf_begin (%s): %s", alt_name, dwarf_errmsg (-1));
+  if (elf_cntl (dwarf_getelf (dbg_alt), ELF_C_FDREAD) != 0)
+    errx (1, "elf_cntl (%s, ELF_C_FDREAD): %s", alt_name, elf_errmsg (-1));
+  close (fd);
+  dwarf_setalt (main, dbg_alt);
+  return dbg_alt;
+}
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; ++i)
+    {
+      int fd = open (argv[i], O_RDONLY);
+      if (fd < 0)
+	err (1, "open (%s)", argv[i]);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg != NULL)
+	{
+	  Dwarf_Off off = 0;
+	  size_t cuhl;
+	  Dwarf_Off noff;
+	  Dwarf *dbg_alt = setup_alt (dbg);
+
+	  while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+	    {
+	      Dwarf_Die die_mem;
+	      Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem);
+
+	      /* Explicitly stop in the callback and then resume each time.  */
+	      ptrdiff_t doff = 0;
+	      do
+		{
+		  doff = dwarf_getfuncs (die, cb, NULL, doff);
+		  if (dwarf_errno () != 0)
+		    errx (1, "dwarf_getfuncs (%s): %s",
+			  argv[i], dwarf_errmsg (-1));
+		}
+	      while (doff != 0);
+
+	      off = noff;
+	    }
+
+	  dwarf_end (dbg_alt);
+	  dwarf_end (dbg);
+	}
+      else
+	errx (1, "dwarf_begin (%s): %s", argv[i], dwarf_errmsg (-1));
+
+      close (fd);
+    }
+}
diff --git a/tests/allregs.c b/tests/allregs.c
new file mode 100644
index 0000000..f18f0b2
--- /dev/null
+++ b/tests/allregs.c
@@ -0,0 +1,204 @@
+/* Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <argp.h>
+#include <assert.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+
+#include "system.h"
+#include "../libdw/known-dwarf.h"
+
+static const char *
+dwarf_encoding_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_ATE
+#undef DWARF_ONE_KNOWN_DW_ATE
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+
+static int
+first_module (Dwfl_Module *mod,
+	      void **userdatap __attribute__ ((unused)),
+	      const char *name __attribute__ ((unused)),
+	      Dwarf_Addr low_addr __attribute__ ((unused)),
+	      void *arg)
+{
+  Dwarf_Addr bias;
+  if (dwfl_module_getelf (mod, &bias) == NULL) /* Not really a module.  */
+    return DWARF_CB_OK;
+
+  *(Dwfl_Module **) arg = mod;
+  return DWARF_CB_ABORT;
+}
+
+
+struct state
+{
+  struct reginfo *info;
+  int nregs;
+};
+
+struct reginfo
+{
+  const char *set, *pfx;
+  int regno;
+  int bits;
+  int type;
+  char name[32];
+};
+
+static int
+compare (const void *r1, const void *r2)
+{
+  const struct reginfo *a = r1, *b = r2;
+  if (a->set == b->set)
+    return a->regno - b->regno;
+  if (a->set == NULL)
+    return 1;
+  if (b->set == NULL)
+    return -1;
+  if (!strcmp (a->set, "integer"))
+    return -1;
+  if (!strcmp (b->set, "integer"))
+    return 1;
+  return strcmp (a->set, b->set);
+}
+
+static int
+one_register (void *arg,
+	      int regno,
+	      const char *setname,
+	      const char *prefix,
+	      const char *regname,
+	      int bits, int type)
+{
+  struct state *state = arg;
+
+  if (regno >= state->nregs)
+    {
+      state->info = realloc (state->info, (regno + 1) * sizeof state->info[0]);
+      memset (&state->info[state->nregs], 0,
+	      ((void *) &state->info[regno + 1]
+	       - (void *) &state->info[state->nregs]));
+      state->nregs = regno + 1;
+    }
+
+  state->info[regno].regno = regno;
+  state->info[regno].set = setname;
+  state->info[regno].pfx = prefix;
+  state->info[regno].bits = bits;
+  state->info[regno].type = type;
+  assert (strlen (regname) < sizeof state->info[regno].name);
+  strcpy (state->info[regno].name, regname);
+
+  return DWARF_CB_OK;
+}
+
+
+static int
+match_register (void *arg,
+		int regno,
+		const char *setname,
+		const char *prefix,
+		const char *regname,
+		int bits, int type)
+{
+  if (regno == *(int *) arg)
+    printf ("%5d => %s register %s%s %s %d bits\n",
+	    regno, setname, prefix, regname,
+	    dwarf_encoding_string (type), bits);
+
+  return DWARF_CB_ABORT;
+}
+
+
+int
+main (int argc, char **argv)
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+
+  Dwfl_Module *mod = NULL;
+  if (dwfl_getmodules (dwfl, &first_module, &mod, 0) < 0)
+    error (EXIT_FAILURE, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+
+  if (remaining == argc)
+    {
+      struct state state = { NULL, 0 };
+      int result = dwfl_module_register_names (mod, &one_register, &state);
+      if (result != 0 || state.nregs == 0)
+	error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s",
+	       result ? dwfl_errmsg (-1) : "no backend registers known");
+
+      qsort (state.info, state.nregs, sizeof state.info[0], &compare);
+
+      const char *set = NULL;
+      for (int i = 0; i < state.nregs; ++i)
+	if (state.info[i].set != NULL)
+	  {
+	    if (set != state.info[i].set)
+	      printf ("%s registers:\n", state.info[i].set);
+	    set = state.info[i].set;
+
+	    printf ("\t%3d: %s%s (%s), %s %d bits\n",
+		    state.info[i].regno,
+		    state.info[i].pfx ?: "", state.info[i].name,
+		    state.info[i].name,
+		    dwarf_encoding_string (state.info[i].type),
+		    state.info[i].bits);
+	  }
+      free (state.info);
+    }
+  else
+    do
+      {
+	const char *arg = argv[remaining++];
+	int regno = atoi (arg);
+	int result = dwfl_module_register_names (mod, &match_register, &regno);
+	if (result != DWARF_CB_ABORT)
+	  error (EXIT_FAILURE, 0, "dwfl_module_register_names: %s",
+		 result ? dwfl_errmsg (-1) : "no backend registers known");
+      }
+    while (remaining < argc);
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/arextract.c b/tests/arextract.c
new file mode 100644
index 0000000..936d7f5
--- /dev/null
+++ b/tests/arextract.c
@@ -0,0 +1,159 @@
+/* Copyright (C) 1999, 2000, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <system.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int fd;
+  Elf *elf;
+  Elf *subelf;
+  Elf_Cmd cmd;
+  off_t offset;
+  size_t todo;
+
+  if (argc < 4)
+    exit (1);
+
+  /* Open the archive.  */
+  fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("Cannot open input file: %m");
+      exit (1);
+    }
+
+  /* Set the ELF version.  */
+  elf_version (EV_CURRENT);
+
+  /* Create an ELF descriptor.  */
+  cmd = ELF_C_READ;
+  elf = elf_begin (fd, cmd, NULL);
+  if (elf == NULL)
+    {
+      printf ("Cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* If it is no archive punt.  */
+  if (elf_kind (elf) != ELF_K_AR)
+    {
+      printf ("`%s' is no archive\n", argv[1]);
+      exit (1);
+    }
+
+  /* Get the elements of the archive one after the other.  */
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      /* The the header for this element.  */
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+      if (arhdr == NULL)
+	{
+	  printf ("cannot get arhdr: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      if (strcmp (arhdr->ar_name, argv[2]) == 0)
+	{
+	  int outfd;
+
+	  /* Get the offset of the file in the archive.  */
+	  offset = elf_getbase (subelf);
+	  if (offset == -1)
+	    {
+	      printf ("\
+Failed to get base address for the archive element: %s\n",
+		      elf_errmsg (-1));
+	      exit (1);
+	    }
+
+	  /* Open the output file.  */
+	  outfd = open (argv[3], O_CREAT | O_TRUNC | O_RDWR, DEFFILEMODE);
+	  if (outfd == -1)
+	    {
+	      printf ("cannot open output file: %m");
+	      exit (1);
+	    }
+
+	  /* Now write out the data.  */
+	  todo = arhdr->ar_size;
+	  while (todo > 0)
+	    {
+	      char buf[1024];
+	      ssize_t n = pread (fd, buf, MIN (sizeof buf, todo), offset);
+	      if (n == 0)
+		break;
+
+	      if (write (outfd, buf, n) != n)
+		{
+		  puts ("Writing output failed");
+		  exit (1);
+		}
+
+	      offset += n;
+	      todo -= n;
+	    }
+
+	  /* Check whether all the date was read and written out.  */
+	  if (todo != 0)
+	    {
+	      puts ("Reading archive member failed.");
+	      exit (1);
+	    }
+
+	  /* Close the descriptors.  */
+	  if (elf_end (subelf) != 0 || elf_end (elf) != 0)
+	    {
+	      printf ("Freeing ELF descriptors failed: %s", elf_errmsg (-1));
+	      exit (1);
+	    }
+
+	  close (outfd);
+	  close (fd);
+
+	  /* All went well.  */
+	  exit (0);
+	}
+
+      /* Get next archive element.  */
+      cmd = elf_next (subelf);
+      if (elf_end (subelf) != 0)
+	{
+	  printf ("error while freeing sub-ELF descriptor: %s\n",
+		  elf_errmsg (-1));
+	  exit (1);
+	}
+    }
+
+  /* When we reach this point we haven't found the given file in the
+     archive.  */
+  printf ("File `%s' not found in archive\n", argv[2]);
+  exit (1);
+}
diff --git a/tests/arls.c b/tests/arls.c
new file mode 100644
index 0000000..ca0d3e6
--- /dev/null
+++ b/tests/arls.c
@@ -0,0 +1,111 @@
+/* Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <ar.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int handle (const char *fname);
+
+
+int
+main (int argc, char *argv[])
+{
+  elf_version (EV_CURRENT);
+
+  int result = 0;
+  if (argc == 1)
+    result = handle ("a.out");
+  else
+    for (int i = 1; i < argc; ++i)
+      result |= handle (argv[1]);
+
+  return result;
+}
+
+
+static int
+handle (const char *fname)
+{
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open '%s': %m\n", fname);
+      return 1;
+    }
+
+  Elf *elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot get ELF handling for '%s': %s\n",
+	      fname, elf_errmsg (-1));
+      close (fd);
+      return 1;
+    }
+
+  if (elf_kind (elf) != ELF_K_AR)
+    {
+      printf ("'%s' is no archive\n", fname);
+      elf_end (elf);
+      close (fd);
+      return 1;
+    }
+
+  printf ("%s:\n", fname);
+  Elf *subelf = NULL;
+  Elf_Cmd cmd = ELF_C_READ_MMAP;
+  while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+    {
+      Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+      if (arhdr == NULL)
+	{
+	  printf ("cannot get archive header in '%s': %s\n",
+		  fname, elf_errmsg (-1));
+	  elf_end (subelf);
+	  elf_end (elf);
+	  close (fd);
+	  return 1;
+	}
+
+      off_t off = elf_getaroff (subelf);
+
+      printf ("\nOffset    %llu\n"
+	      "  Name    %s\n"
+	      "  Date    %ld\n"
+	      "  UID     %d\n"
+	      "  GID     %d\n"
+	      "  Mode    %o\n"
+	      "  Size    %lld\n",
+	      (unsigned long long int) off,
+	      arhdr->ar_name, (long int) arhdr->ar_date, (int) arhdr->ar_uid,
+	      (int) arhdr->ar_gid,
+	      (int) arhdr->ar_mode, (long long int) arhdr->ar_size);
+
+      cmd = elf_next (subelf);
+      elf_end (subelf);
+    }
+
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/arsymtest.c b/tests/arsymtest.c
new file mode 100644
index 0000000..c724863
--- /dev/null
+++ b/tests/arsymtest.c
@@ -0,0 +1,136 @@
+/* Copyright (C) 1999, 2000, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int fd;
+  FILE *fp;
+  Elf *elf;
+  Elf_Arsym *arsym;
+  size_t narsym;
+
+  if (argc < 3)
+    exit (1);
+
+  /* Open the archive.  */
+  fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("Cannot open input file: %m");
+      exit (1);
+    }
+
+  /* Open the output file.  */
+  fp = fopen (argv[2], "w");
+  if (fp == NULL)
+    {
+      printf ("Cannot open output file: %m");
+      exit (1);
+    }
+
+  /* Set the ELF version.  */
+  elf_version (EV_CURRENT);
+
+  /* Create an ELF descriptor.  */
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("Cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* If it is no archive punt.  */
+  if (elf_kind (elf) != ELF_K_AR)
+    {
+      printf ("`%s' is no archive\n", argv[1]);
+      exit (1);
+    }
+
+  /* Now get the index of the archive.  */
+  arsym = elf_getarsym (elf, &narsym);
+  if (arsym == NULL)
+    {
+      printf ("Cannot get archive index: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* If there is no element in the index do nothing.  There always is
+     an empty entry at the end which is included in the count and
+     which we want to skip.  */
+  if (narsym-- > 1)
+    while (narsym-- > 0)
+      {
+	Elf *subelf;
+	Elf_Arhdr *arhdr;
+
+	if (elf_rand (elf, arsym[narsym].as_off) != arsym[narsym].as_off)
+	  {
+	    printf ("random access for symbol `%s' fails: %s\n",
+		    arsym[narsym].as_name, elf_errmsg (-1));
+	    exit (1);
+	  }
+
+	subelf = elf_begin (fd, ELF_C_READ, elf);
+	if (subelf == NULL)
+	  {
+	    printf ("Cannot create ELF descriptor for archive member: %s\n",
+		    elf_errmsg (-1));
+	    exit (1);
+	  }
+
+	arhdr = elf_getarhdr (subelf);
+	if (arhdr == NULL)
+	  {
+	    printf ("Cannot get archive header for element `%s': %s\n",
+		    arsym[narsym].as_name, elf_errmsg (-1));
+	    exit (1);
+	  }
+
+	/* Now print what we actually want.  */
+	fprintf (fp, "%s in %s\n", arsym[narsym].as_name, arhdr->ar_name);
+
+	/* Free the ELF descriptor.  */
+	if (elf_end (subelf) != 0)
+	  {
+	    printf ("Error while freeing subELF descriptor: %s\n",
+		    elf_errmsg (-1));
+	    exit (1);
+	  }
+      }
+
+  /* Free the ELF descriptor.  */
+  if (elf_end (elf) != 0)
+    {
+      printf ("Error while freeing ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+  fclose (fp);
+
+  return 0;
+}
diff --git a/tests/asm-tst1.c b/tests/asm-tst1.c
new file mode 100644
index 0000000..d03a436
--- /dev/null
+++ b/tests/asm-tst1.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static const char fname[] = "asm-tst1-out.o";
+
+
+static const GElf_Ehdr expected_ehdr =
+  {
+    .e_ident = { [EI_MAG0] = ELFMAG0,
+		 [EI_MAG1] = ELFMAG1,
+		 [EI_MAG2] = ELFMAG2,
+		 [EI_MAG3] = ELFMAG3,
+		 [EI_CLASS] = ELFCLASS32,
+		 [EI_DATA] = ELFDATA2LSB,
+		 [EI_VERSION] = EV_CURRENT },
+    .e_type = ET_REL,
+    .e_machine = EM_386,
+    .e_version = EV_CURRENT,
+    .e_shoff = 88,
+    .e_ehsize = sizeof (Elf32_Ehdr),
+    .e_shentsize = sizeof (Elf32_Shdr),
+    .e_shnum = 4,
+    .e_shstrndx = 3
+  };
+
+
+static const char *scnnames[4] =
+  {
+    [0] = "",
+    [1] = ".text",
+    [2] = ".data",
+    [3] = ".shstrtab"
+  };
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  AsmScn_t *scn1;
+  AsmScn_t *scn2;
+  int fd;
+  Elf *elf;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  int result = 0;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  /* Create two sections.  */
+  scn1 = asm_newscn (ctx, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
+  scn2 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+  if (scn1 == NULL || scn2 == NULL)
+    {
+      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Special alignment for the .text section.  */
+  if (asm_align (scn1, 32) != 0)
+    {
+      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Check the file.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open generated file: %m\n");
+      result = 1;
+      goto out;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close;
+    }
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      puts ("not a valid ELF file");
+      result = 1;
+      goto out_close2;
+    }
+
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close2;
+    }
+
+  if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
+    {
+      puts ("ELF header does not match");
+      result = 1;
+      goto out_close2;
+    }
+
+  for (cnt = 1; cnt < 4; ++cnt)
+    {
+      Elf_Scn *scn;
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      scn = elf_getscn (elf, cnt);
+      if (scn == NULL)
+	{
+	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get section header for section %zd: %s\n",
+		  cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]) != 0)
+	{
+	  printf ("section %zd's name differs: %s vs %s\n", cnt,
+		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]);
+	  result = 1;
+	}
+
+      if (shdr->sh_type != (cnt == 3 ? SHT_STRTAB : SHT_PROGBITS))
+	{
+	  printf ("section %zd's type differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_EXECINSTR))
+	  || (cnt == 2 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
+	  || (cnt == 3 && shdr->sh_flags != 0))
+	{
+	  printf ("section %zd's flags differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_addr != 0)
+	{
+	  printf ("section %zd's address differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 31) & ~31))
+	{
+	  printf ("section %zd's offset differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt != 3 && shdr->sh_size != 0)
+	  || (cnt == 3 && shdr->sh_size != 23))
+	{
+	  printf ("section %zd's size differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_link != 0)
+	{
+	  printf ("section %zd's link differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_info != 0)
+	{
+	  printf ("section %zd's info differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_addralign != 32)
+	  || (cnt != 1 && shdr->sh_addralign != 1))
+	{
+	  printf ("section %zd's addralign differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_entsize != 0)
+	{
+	  printf ("section %zd's entsize differs\n", cnt);
+	  result = 1;
+	}
+    }
+
+ out_close2:
+  elf_end (elf);
+ out_close:
+  close (fd);
+ out:
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst2.c b/tests/asm-tst2.c
new file mode 100644
index 0000000..e65a9d2
--- /dev/null
+++ b/tests/asm-tst2.c
@@ -0,0 +1,279 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static const char fname[] = "asm-tst2-out.o";
+
+
+static const GElf_Ehdr expected_ehdr =
+  {
+    .e_ident = { [EI_MAG0] = ELFMAG0,
+		 [EI_MAG1] = ELFMAG1,
+		 [EI_MAG2] = ELFMAG2,
+		 [EI_MAG3] = ELFMAG3,
+		 [EI_CLASS] = ELFCLASS32,
+		 [EI_DATA] = ELFDATA2LSB,
+		 [EI_VERSION] = EV_CURRENT },
+    .e_type = ET_REL,
+    .e_machine = EM_386,
+    .e_version = EV_CURRENT,
+    .e_shoff = 96,
+    .e_ehsize = sizeof (Elf32_Ehdr),
+    .e_shentsize = sizeof (Elf32_Shdr),
+    .e_shnum = 3,
+    .e_shstrndx = 2
+  };
+
+
+static const char *scnnames[3] =
+  {
+    [0] = "",
+    [1] = ".data",
+    [2] = ".shstrtab"
+  };
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  AsmScn_t *scn1;
+  AsmScn_t *scn2;
+  int result = 0;
+  int fd;
+  Elf *elf;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  /* Create two sections.  */
+  scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+  scn2 = asm_newsubscn (scn1, 1);
+  if (scn1 == NULL || scn2 == NULL)
+    {
+      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Special alignment for the .text section.  */
+  if (asm_align (scn1, 16) != 0)
+    {
+      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+
+  /* Add a few strings.  */
+  if (asm_addstrz (scn1, "one", 4) != 0)
+    {
+      printf ("cannot insert first string: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_addstrz (scn2, "three", 0) != 0)
+    {
+      printf ("cannot insert second string: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_addstrz (scn1, "two", 4) != 0)
+    {
+      printf ("cannot insert third string: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Check the file.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open generated file: %m\n");
+      result = 1;
+      goto out;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close;
+    }
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      puts ("not a valid ELF file");
+      result = 1;
+      goto out_close2;
+    }
+
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close2;
+    }
+
+  if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
+    {
+      puts ("ELF header does not match");
+      result = 1;
+      goto out_close2;
+    }
+
+  for (cnt = 1; cnt < 3; ++cnt)
+    {
+      Elf_Scn *scn;
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      scn = elf_getscn (elf, cnt);
+      if (scn == NULL)
+	{
+	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get section header for section %zd: %s\n",
+		  cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]) != 0)
+	{
+	  printf ("section %zd's name differs: %s vs %s\n", cnt,
+		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]);
+	  result = 1;
+	}
+
+      if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS))
+	{
+	  printf ("section %zd's type differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
+	  || (cnt == 2 && shdr->sh_flags != 0))
+	{
+	  printf ("section %zd's flags differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_addr != 0)
+	{
+	  printf ("section %zd's address differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15))
+	  || (cnt == 2
+	      && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15)
+				     + strlen ("one") + 1
+				     + strlen ("two") + 1
+				     + strlen ("three") + 1)))
+	{
+	  printf ("section %zd's offset differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_size != (strlen ("one") + 1
+					 + strlen ("two") + 1
+					 + strlen ("three") + 1))
+	  || (cnt == 2 && shdr->sh_size != 17))
+	{
+	  printf ("section %zd's size differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_link != 0)
+	{
+	  printf ("section %zd's link differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_info != 0)
+	{
+	  printf ("section %zd's info differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_addralign != 16)
+	  || (cnt != 1 && shdr->sh_addralign != 1))
+	{
+	  printf ("section %zd's addralign differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_entsize != 0)
+	{
+	  printf ("section %zd's entsize differs\n", cnt);
+	  result = 1;
+	}
+    }
+
+ out_close2:
+  elf_end (elf);
+ out_close:
+  close (fd);
+ out:
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst3.c b/tests/asm-tst3.c
new file mode 100644
index 0000000..e45fa16
--- /dev/null
+++ b/tests/asm-tst3.c
@@ -0,0 +1,340 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static const char fname[] = "asm-tst3-out.o";
+
+
+static const char *scnnames[5] =
+  {
+    [0] = "",
+    [1] = ".data",
+    [2] = ".strtab",
+    [3] = ".symtab",
+    [4] = ".shstrtab"
+  };
+
+
+static unsigned int scntypes[5] =
+  {
+    [0] = SHT_NULL,
+    [1] = SHT_PROGBITS,
+    [2] = SHT_STRTAB,
+    [3] = SHT_SYMTAB,
+    [4] = SHT_STRTAB
+  };
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  AsmScn_t *scn1;
+  AsmScn_t *scn2;
+  int result = 0;
+  int fd;
+  Elf *elf;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  /* Create two sections.  */
+  scn1 = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+  scn2 = asm_newsubscn (scn1, 1);
+  if (scn1 == NULL || scn2 == NULL)
+    {
+      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Special alignment for the .text section.  */
+  if (asm_align (scn1, 16) != 0)
+    {
+      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+
+  /* Add a few strings with names.  */
+  if (asm_newsym (scn1, "one", 4, STT_OBJECT, STB_GLOBAL) == NULL)
+    {
+      printf ("cannot create first name: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_addstrz (scn1, "one", 4) != 0)
+    {
+      printf ("cannot insert first string: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_newsym (scn2, "three", 6, STT_OBJECT, STB_WEAK) == NULL)
+    {
+      printf ("cannot create second name: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_addstrz (scn2, "three", 0) != 0)
+    {
+      printf ("cannot insert second string: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_newsym (scn1, "two", 4, STT_OBJECT, STB_LOCAL) == NULL)
+    {
+      printf ("cannot create third name: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+  if (asm_addstrz (scn1, "two", 4) != 0)
+    {
+      printf ("cannot insert third string: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Check the file.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open generated file: %m\n");
+      result = 1;
+      goto out;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close;
+    }
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      puts ("not a valid ELF file");
+      result = 1;
+      goto out_close2;
+    }
+
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close2;
+    }
+
+  for (cnt = 1; cnt < 5; ++cnt)
+    {
+      Elf_Scn *scn;
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      scn = elf_getscn (elf, cnt);
+      if (scn == NULL)
+	{
+	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get section header for section %zd: %s\n",
+		  cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]) != 0)
+	{
+	  printf ("section %zd's name differs: %s vs %s\n", cnt,
+		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]);
+	  result = 1;
+	}
+
+      if (shdr->sh_type != scntypes[cnt])
+	{
+	  printf ("section %zd's type differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
+	  || (cnt != 1 && shdr->sh_flags != 0))
+	{
+	  printf ("section %zd's flags differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_addr != 0)
+	{
+	  printf ("section %zd's address differs\n", cnt);
+	  result = 1;
+	}
+
+      if (cnt == 3)
+	{
+	  Elf_Data *data;
+
+	  if (shdr->sh_link != 2)
+	    {
+	      puts ("symbol table has incorrect link");
+	      result = 1;
+	    }
+
+	  data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    {
+	      puts ("cannot get data of symbol table");
+	      result = 1;
+	    }
+	  else
+	    {
+	      size_t inner;
+
+	      for (inner = 1;
+		   inner < (shdr->sh_size
+			    / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
+		   ++inner)
+		{
+		  GElf_Sym sym_mem;
+		  GElf_Sym *sym;
+
+		  sym = gelf_getsym (data, inner, &sym_mem);
+		  if (sym == NULL)
+		    {
+		      printf ("cannot get symbol %zu: %s\n",
+			      inner, elf_errmsg (-1));
+		      result = 1;
+		    }
+		  else
+		    {
+		      /* The order of the third and fourth entry depends
+			 on how the hash table is organized.  */
+		      static const char *names[4] =
+			{
+			  [0] = "",
+			  [1] = "two",
+			  [2] = "one",
+			  [3] = "three"
+			};
+		      static const int info[4] =
+			{
+			  [0] = GELF_ST_INFO (STB_LOCAL, STT_NOTYPE),
+			  [1] = GELF_ST_INFO (STB_LOCAL, STT_OBJECT),
+			  [2] = GELF_ST_INFO (STB_GLOBAL, STT_OBJECT),
+			  [3] = GELF_ST_INFO (STB_WEAK, STT_OBJECT)
+			};
+		      static const unsigned value[4] =
+			{
+			  [0] = 0,
+			  [1] = 4,
+			  [2] = 0,
+			  [3] = 8
+			};
+
+		      if (strcmp (names[inner],
+				  elf_strptr (elf, shdr->sh_link,
+					      sym->st_name)) != 0)
+			{
+			  printf ("symbol %zu has different name\n", inner);
+			  result = 1;
+			}
+
+		      if (sym->st_value != value[inner])
+			{
+			  printf ("symbol %zu has wrong value\n", inner);
+			  result = 1;
+			}
+
+		      if (sym->st_other != 0)
+			{
+			  printf ("symbol %zu has wrong other info\n", inner);
+			  result = 1;
+			}
+
+		      if (sym->st_shndx != 1)
+			{
+			  printf ("symbol %zu has wrong section reference\n",
+				  inner);
+			  result = 1;
+			}
+
+		      if (sym->st_info != info[inner])
+			{
+			  printf ("symbol %zu has wrong type or binding\n",
+				  inner);
+			  result = 1;
+			}
+
+		      if ((inner != 3 && sym->st_size != 4)
+			  || (inner == 3 && sym->st_size != 6))
+			{
+			  printf ("symbol %zu has wrong size\n", inner);
+			  result = 1;
+			}
+		    }
+		}
+	    }
+	}
+    }
+
+ out_close2:
+  elf_end (elf);
+ out_close:
+  close (fd);
+ out:
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst4.c b/tests/asm-tst4.c
new file mode 100644
index 0000000..1a05bfc
--- /dev/null
+++ b/tests/asm-tst4.c
@@ -0,0 +1,105 @@
+/* Copyright (C) 2002-2012 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+
+static const char fname[] = "asm-tst4-out.o";
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  int result = 0;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  /* Create 66000 sections.  */
+  for (cnt = 0; cnt < 66000; ++cnt)
+    {
+      char buf[20];
+      AsmScn_t *scn;
+
+      /* Create a unique name.  */
+      snprintf (buf, sizeof (buf), ".data.%zu", cnt);
+
+      /* Create the section.  */
+      scn = asm_newscn (ctx, buf, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+      if (scn == NULL)
+	{
+	  printf ("cannot create section \"%s\" in output file: %s\n",
+		  buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Add some content.  */
+      if (asm_adduint32 (scn, cnt) != 0)
+	{
+	  printf ("cannot create content of section \"%s\": %s\n",
+		  buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  if (result == 0)
+    result = WEXITSTATUS (system ("../src/elflint -q asm-tst4-out.o"));
+
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst5.c b/tests/asm-tst5.c
new file mode 100644
index 0000000..256873f
--- /dev/null
+++ b/tests/asm-tst5.c
@@ -0,0 +1,117 @@
+/* Copyright (C) 2002-2012 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include "system.h"
+
+
+static const char fname[] = "asm-tst5-out.o";
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  int result = 0;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  /* Create 66000 sections.  */
+  for (cnt = 0; cnt < 66000; ++cnt)
+    {
+      char buf[20];
+      AsmScn_t *scn;
+
+      /* Create a unique name.  */
+      snprintf (buf, sizeof (buf), ".data.%zu", cnt);
+
+      /* Create the section.  */
+      scn = asm_newscn (ctx, buf, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+      if (scn == NULL)
+	{
+	  printf ("cannot create section \"%s\" in output file: %s\n",
+		  buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Add a name.  */
+      snprintf (buf, sizeof (buf), "%zu", cnt);
+      if (asm_newsym (scn, buf, sizeof (uint32_t), STT_OBJECT,
+		      STB_GLOBAL) == NULL)
+	{
+	  printf ("cannot create symbol \"%s\": %s\n", buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Add some content.  */
+      if (asm_adduint32 (scn, cnt) != 0)
+	{
+	  printf ("cannot create content of section \"%s\": %s\n",
+		  buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  if (result == 0)
+    result = WEXITSTATUS (system ("../src/elflint -q asm-tst5-out.o"));
+
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst6.c b/tests/asm-tst6.c
new file mode 100644
index 0000000..4a665ed
--- /dev/null
+++ b/tests/asm-tst6.c
@@ -0,0 +1,151 @@
+/* Copyright (C) 2002-2012 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/wait.h>
+
+#include <system.h>
+
+
+static const char fname[] = "asm-tst6-out.o";
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  int result = 0;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  for (cnt = 0; cnt < 22000; ++cnt)
+    {
+      char buf[512];
+      AsmScnGrp_t *grp;
+      AsmScn_t *scn;
+      AsmSym_t *sym;
+
+      snprintf (buf, sizeof (buf), ".grp%zu", cnt);
+      grp = asm_newscngrp (ctx, buf, NULL, 0);
+      if (grp == NULL)
+	{
+	  printf ("cannot section group %zu: %s\n", cnt, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      scn = asm_newscn_ingrp (ctx, ".data", SHT_PROGBITS,
+			      SHF_ALLOC | SHF_WRITE, grp);
+      if (scn == NULL)
+	{
+	  printf ("cannot data section for group %zu: %s\n",
+		  cnt, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Add a name.  */
+      snprintf (buf, sizeof (buf), "%zu", cnt);
+      sym = asm_newsym (scn, buf, sizeof (uint32_t), STT_OBJECT,
+			STB_GLOBAL);
+      if (sym == NULL)
+	{
+	  printf ("cannot create symbol \"%s\": %s\n", buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Add some content.  */
+      if (asm_adduint32 (scn, cnt) != 0)
+	{
+	  printf ("cannot create content of section \"%s\": %s\n",
+		  buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Now we have a symbol, use it as the signature.  */
+      if (asm_scngrp_newsignature (grp, sym) != 0)
+	{
+	  printf ("cannot set signature for section group %zu: %s\n",
+		  cnt, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Create a phony debug info section.  */
+      scn = asm_newscn_ingrp (ctx, ".stab", SHT_PROGBITS, 0, grp);
+      if (scn == NULL)
+	{
+	  printf ("cannot stab section for group %zu: %s\n",
+		  cnt, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+
+      /* Add some content.  */
+      if (asm_adduint32 (scn, cnt) != 0)
+	{
+	  printf ("cannot create content of section \"%s\": %s\n",
+		  buf, asm_errmsg (-1));
+	  asm_abort (ctx);
+	  return 1;
+	}
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  if (result == 0)
+    result = WEXITSTATUS (system ("../src/elflint -q asm-tst6-out.o"));
+
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst7.c b/tests/asm-tst7.c
new file mode 100644
index 0000000..87c2148
--- /dev/null
+++ b/tests/asm-tst7.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static const char fname[] = "asm-tst7-out.o";
+
+
+int
+main (void)
+{
+  int result = 0;
+  size_t cnt;
+  AsmCtx_t *ctx;
+  Elf *elf;
+  int fd;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  if (asm_newcomsym (ctx, "commsym", 4, 16) == NULL)
+    {
+      printf ("cannot create common symbol: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Check the file.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open generated file: %m\n");
+      result = 1;
+      goto out;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close;
+    }
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      puts ("not a valid ELF file");
+      result = 1;
+      goto out_close2;
+    }
+
+  for (cnt = 1; 1; ++cnt)
+    {
+      Elf_Scn *scn;
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      scn = elf_getscn (elf, cnt);
+      if (scn == NULL)
+	{
+	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get section header for section %zd: %s\n",
+		  cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+      /* We are looking for the symbol table.  */
+      if (shdr->sh_type != SHT_SYMTAB)
+	continue;
+
+      for (cnt = 1; cnt< (shdr->sh_size
+			  / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
+	   ++cnt)
+	{
+	  GElf_Sym sym_mem;
+	  GElf_Sym *sym;
+
+	  if (cnt > 1)
+	    {
+	      puts ("too many symbol");
+	      result = 1;
+	      break;
+	    }
+
+	  sym = gelf_getsym (elf_getdata (scn, NULL), cnt, &sym_mem);
+	  if (sym == NULL)
+	    {
+	      printf ("cannot get symbol %zu: %s\n", cnt, elf_errmsg (-1));
+	      result = 1;
+	    }
+	  else
+	    {
+	      if (sym->st_shndx != SHN_COMMON)
+		{
+		  printf ("expected common symbol, got section %u\n",
+			  (unsigned int) sym->st_shndx);
+		  result = 1;
+		}
+
+	      if (sym->st_value != 16)
+		{
+		  printf ("requested alignment 16, is %" PRIuMAX "\n",
+			  (uintmax_t) sym->st_value);
+		  result = 1;
+		}
+
+	      if (sym->st_size != 4)
+		{
+		  printf ("requested size 4, is %" PRIuMAX "\n",
+			  (uintmax_t) sym->st_value);
+		  result = 1;
+		}
+	    }
+	}
+
+      break;
+    }
+
+ out_close2:
+  elf_end (elf);
+ out_close:
+  close (fd);
+ out:
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst8.c b/tests/asm-tst8.c
new file mode 100644
index 0000000..7dbac10
--- /dev/null
+++ b/tests/asm-tst8.c
@@ -0,0 +1,190 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+static const char fname[] = "asm-tst8-out.o";
+
+
+int
+main (void)
+{
+  int result = 0;
+  size_t cnt;
+  AsmCtx_t *ctx;
+  Elf *elf;
+  int fd;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  if (asm_newabssym (ctx, "tst8-out.s", 4, 0xfeedbeef, STT_FILE, STB_LOCAL)
+      == NULL)
+    {
+      printf ("cannot create absolute symbol: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Check the file.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open generated file: %m\n");
+      result = 1;
+      goto out;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close;
+    }
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      puts ("not a valid ELF file");
+      result = 1;
+      goto out_close2;
+    }
+
+  for (cnt = 1; 1; ++cnt)
+    {
+      Elf_Scn *scn;
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      scn = elf_getscn (elf, cnt);
+      if (scn == NULL)
+	{
+	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get section header for section %zd: %s\n",
+		  cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+      /* We are looking for the symbol table.  */
+      if (shdr->sh_type != SHT_SYMTAB)
+	continue;
+
+      for (cnt = 1; cnt< (shdr->sh_size
+			  / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
+	   ++cnt)
+	{
+	  GElf_Sym sym_mem;
+	  GElf_Sym *sym;
+
+	  if (cnt > 1)
+	    {
+	      puts ("too many symbol");
+	      result = 1;
+	      break;
+	    }
+
+	  sym = gelf_getsym (elf_getdata (scn, NULL), cnt, &sym_mem);
+	  if (sym == NULL)
+	    {
+	      printf ("cannot get symbol %zu: %s\n", cnt, elf_errmsg (-1));
+	      result = 1;
+	    }
+	  else
+	    {
+	      if (sym->st_shndx != SHN_ABS)
+		{
+		  printf ("expected common symbol, got section %u\n",
+			  (unsigned int) sym->st_shndx);
+		  result = 1;
+		}
+
+	      if (sym->st_value != 0xfeedbeef)
+		{
+		  printf ("requested value 0xfeedbeef, is %#" PRIxMAX "\n",
+			  (uintmax_t) sym->st_value);
+		  result = 1;
+		}
+
+	      if (sym->st_size != 4)
+		{
+		  printf ("requested size 4, is %" PRIuMAX "\n",
+			  (uintmax_t) sym->st_value);
+		  result = 1;
+		}
+
+	      if (GELF_ST_TYPE (sym->st_info) != STT_FILE)
+		{
+		  printf ("requested type FILE, is %u\n",
+			  (unsigned int) GELF_ST_TYPE (sym->st_info));
+		  result = 1;
+		}
+	    }
+	}
+
+      break;
+    }
+
+ out_close2:
+  elf_end (elf);
+ out_close:
+  close (fd);
+ out:
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/asm-tst9.c b/tests/asm-tst9.c
new file mode 100644
index 0000000..6bec3f6
--- /dev/null
+++ b/tests/asm-tst9.c
@@ -0,0 +1,336 @@
+/* Copyright (C) 2002-2010 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(asm)
+#include ELFUTILS_HEADER(ebl)
+#include <libelf.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+static const char fname[] = "asm-tst9-out.o";
+
+
+static int32_t input[] =
+  {
+    0, 1, 129, 510, 2000, 33000, 0x7ffffff, 0x7fffffff
+  };
+#define ninput (sizeof (input) / sizeof (input[0]))
+
+
+static const GElf_Ehdr expected_ehdr =
+  {
+    .e_ident = { [EI_MAG0] = ELFMAG0,
+		 [EI_MAG1] = ELFMAG1,
+		 [EI_MAG2] = ELFMAG2,
+		 [EI_MAG3] = ELFMAG3,
+		 [EI_CLASS] = ELFCLASS32,
+		 [EI_DATA] = ELFDATA2LSB,
+		 [EI_VERSION] = EV_CURRENT },
+    .e_type = ET_REL,
+    .e_machine = EM_386,
+    .e_version = EV_CURRENT,
+    .e_shoff = 180,
+    .e_ehsize = sizeof (Elf32_Ehdr),
+    .e_shentsize = sizeof (Elf32_Shdr),
+    .e_shnum = 3,
+    .e_shstrndx = 2
+  };
+
+
+static const char *scnnames[3] =
+  {
+    [0] = "",
+    [1] = ".data",
+    [2] = ".shstrtab"
+  };
+
+
+static const char expecteddata[] =
+  {
+    0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x7f,
+    0x81, 0x01, 0x81, 0x01, 0xff, 0xfe, 0xff, 0xff, 0x0f, 0xff, 0x7e, 0xfe,
+    0x03, 0xfe, 0x03, 0x82, 0xfc, 0xff, 0xff, 0x0f, 0x82, 0x7c, 0xd0, 0x0f,
+    0xd0, 0x0f, 0xb0, 0xf0, 0xff, 0xff, 0x0f, 0xb0, 0x70, 0xe8, 0x81, 0x02,
+    0xe8, 0x81, 0x02, 0x98, 0xfe, 0xfd, 0xff, 0x0f, 0x98, 0xfe, 0x7d, 0xff,
+    0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x3f, 0x81, 0x80, 0x80, 0xc0, 0x0f,
+    0x81, 0x80, 0x80, 0x40, 0xff, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff,
+    0xff, 0x07, 0x81, 0x80, 0x80, 0x80, 0x08, 0x81, 0x80, 0x80, 0x80, 0x78
+  };
+
+
+int
+main (void)
+{
+  AsmCtx_t *ctx;
+  AsmScn_t *scn;
+  int result = 0;
+  int fd;
+  Elf *elf;
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  size_t cnt;
+
+  elf_version (EV_CURRENT);
+
+  Ebl *ebl = ebl_openbackend_machine (EM_386);
+  if (ebl == NULL)
+    {
+      puts ("cannot open backend library");
+      return 1;
+    }
+
+  ctx = asm_begin (fname, ebl, false);
+  if (ctx == NULL)
+    {
+      printf ("cannot create assembler context: %s\n", asm_errmsg (-1));
+      return 1;
+    }
+
+  /* Create two sections.  */
+  scn = asm_newscn (ctx, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
+  if (scn == NULL)
+    {
+      printf ("cannot create section in output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Special alignment for the .text section.  */
+  if (asm_align (scn, 16) != 0)
+    {
+      printf ("cannot align .text section: %s\n", asm_errmsg (-1));
+      result = 1;
+    }
+
+  /* Add a few ULEB128 and SLEB128 numbers.  */
+  for (cnt = 0; cnt < ninput; ++cnt)
+    {
+      if (asm_adduleb128 (scn, input[cnt]) != 0)
+	{
+	  printf ("cannot insert uleb %" PRIu32 ": %s\n",
+		  (uint32_t) input[cnt], asm_errmsg (-1));
+	  result = 1;
+	}
+
+      if (asm_addsleb128 (scn, input[cnt]) != 0)
+	{
+	  printf ("cannot insert sleb %" PRId32 ": %s\n",
+		  input[cnt], asm_errmsg (-1));
+	  result = 1;
+	}
+
+      if (asm_adduleb128 (scn, -input[cnt]) != 0)
+	{
+	  printf ("cannot insert uleb %" PRIu32 ": %s\n",
+		  (uint32_t) -input[cnt], asm_errmsg (-1));
+	  result = 1;
+	}
+
+      if (asm_addsleb128 (scn, -input[cnt]) != 0)
+	{
+	  printf ("cannot insert sleb %" PRId32 ": %s\n",
+		  -input[cnt], asm_errmsg (-1));
+	  result = 1;
+	}
+    }
+
+  /* Create the output file.  */
+  if (asm_end (ctx) != 0)
+    {
+      printf ("cannot create output file: %s\n", asm_errmsg (-1));
+      asm_abort (ctx);
+      return 1;
+    }
+
+  /* Check the file.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open generated file: %m\n");
+      result = 1;
+      goto out;
+    }
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close;
+    }
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      puts ("not a valid ELF file");
+      result = 1;
+      goto out_close2;
+    }
+
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      result = 1;
+      goto out_close2;
+    }
+
+  if (memcmp (ehdr, &expected_ehdr, sizeof (GElf_Ehdr)) != 0)
+    {
+      puts ("ELF header does not match");
+      result = 1;
+      goto out_close2;
+    }
+
+  for (cnt = 1; cnt < 3; ++cnt)
+    {
+      Elf_Scn *escn;
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr;
+
+      escn = elf_getscn (elf, cnt);
+      if (escn == NULL)
+	{
+	  printf ("cannot get section %zd: %s\n", cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      shdr = gelf_getshdr (escn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get section header for section %zd: %s\n",
+		  cnt, elf_errmsg (-1));
+	  result = 1;
+	  continue;
+	}
+
+      if (strcmp (elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]) != 0)
+	{
+	  printf ("section %zd's name differs: %s vs %s\n", cnt,
+		  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+		  scnnames[cnt]);
+	  result = 1;
+	}
+
+      if (shdr->sh_type != (cnt == 2 ? SHT_STRTAB : SHT_PROGBITS))
+	{
+	  printf ("section %zd's type differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_flags != (SHF_ALLOC | SHF_WRITE))
+	  || (cnt == 2 && shdr->sh_flags != 0))
+	{
+	  printf ("section %zd's flags differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_addr != 0)
+	{
+	  printf ("section %zd's address differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_offset != ((sizeof (Elf32_Ehdr) + 15) & ~15))
+	  || (cnt == 2
+	      && shdr->sh_offset != (((sizeof (Elf32_Ehdr) + 15) & ~15)
+				     + sizeof (expecteddata))))
+	{
+	  printf ("section %zd's offset differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_size != sizeof (expecteddata))
+	  || (cnt == 2 && shdr->sh_size != 17))
+	{
+	  printf ("section %zd's size differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_link != 0)
+	{
+	  printf ("section %zd's link differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_info != 0)
+	{
+	  printf ("section %zd's info differs\n", cnt);
+	  result = 1;
+	}
+
+      if ((cnt == 1 && shdr->sh_addralign != 16)
+	  || (cnt != 1 && shdr->sh_addralign != 1))
+	{
+	  printf ("section %zd's addralign differs\n", cnt);
+	  result = 1;
+	}
+
+      if (shdr->sh_entsize != 0)
+	{
+	  printf ("section %zd's entsize differs\n", cnt);
+	  result = 1;
+	}
+
+      if (cnt == 1)
+	{
+	  Elf_Data *data = elf_getdata (escn, NULL);
+
+	  if (data == NULL)
+	    {
+	      printf ("cannot get data of section %zd\n", cnt);
+	      result = 1;
+	    }
+	  else
+	    {
+	      if (data->d_size != sizeof (expecteddata))
+		{
+		  printf ("data block size of section %zd wrong: got %zd, "
+			  "expected 96\n", cnt, data->d_size);
+		  result = 1;
+		}
+
+	      if (memcmp (data->d_buf, expecteddata, sizeof (expecteddata))
+		  != 0)
+		{
+		  printf ("data block content of section %zd wrong\n", cnt);
+		  result = 1;
+		}
+	    }
+	}
+    }
+
+ out_close2:
+  elf_end (elf);
+ out_close:
+  close (fd);
+ out:
+  /* We don't need the file anymore.  */
+  unlink (fname);
+
+  ebl_closebackend (ebl);
+
+  return result;
+}
diff --git a/tests/attr-integrate-skel.c b/tests/attr-integrate-skel.c
new file mode 100644
index 0000000..644cd27
--- /dev/null
+++ b/tests/attr-integrate-skel.c
@@ -0,0 +1,109 @@
+/* Test dwarf_get_units finds split DWO CUs.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; i++)
+    {
+      printf ("file: %s\n", argv[i]);
+      int fd = open (argv[i], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      Dwarf_CU *cu = NULL;
+      Dwarf_Die cudie, subdie;
+      uint8_t unit_type;
+      Dwarf_Half version;
+      int count = 0;
+      while (dwarf_get_units (dbg, cu, &cu, &version,
+			      &unit_type, &cudie, &subdie) == 0)
+	{
+	  count++;
+	  if (unit_type == DW_UT_skeleton)
+	    {
+	      Dwarf_Attribute attr;
+	      Dwarf_Word word;
+	      Dwarf_Addr addr;
+
+	      printf ("Split DIE: %s\n", dwarf_diename (&subdie));
+
+	      if (dwarf_attr_integrate (&subdie,
+					DW_AT_GNU_addr_base, &attr) == NULL
+		  && dwarf_attr_integrate (&subdie,
+					   DW_AT_addr_base, &attr) == NULL)
+		printf ("No addr_base");
+	      else if (dwarf_formudata (&attr, &word) != 0)
+		printf ("Bad addr_base: %s\n", dwarf_errmsg (-1));
+	      else
+		printf ("addr_base secoff: 0x%" PRIx64 "\n", word);
+
+	      if (dwarf_attr (&subdie, DW_AT_low_pc, &attr) != NULL)
+		printf ("Unexpected low_pc on split DIE.\n");
+
+	      if (dwarf_attr_integrate (&subdie,
+					DW_AT_low_pc, &attr) == NULL)
+		printf ("No low_pc");
+	      else if (dwarf_formaddr (&attr, &addr) != 0)
+		printf ("Bad low_pc: %s\n", dwarf_errmsg (-1));
+	      else
+		printf ("low_pc addr: 0x%" PRIx64 "\n", addr);
+
+	      if (dwarf_hasattr (&subdie, DW_AT_high_pc))
+		printf ("Unexpected highpc on split DIE\n");
+	      if (dwarf_hasattr (&subdie, DW_AT_ranges))
+		printf ("Unexpected ranges on split DIE\n");
+
+	      if (dwarf_hasattr_integrate (&subdie, DW_AT_high_pc))
+		printf ("Skel has high_pc.\n");
+	      if (dwarf_hasattr_integrate (&subdie, DW_AT_ranges))
+		printf ("Skel has ranges.\n");
+
+	      printf ("\n");
+	    }
+	}
+
+      if (count == 0)
+	{
+	  printf ("No units found\n");
+	  return -1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/backtrace-child.c b/tests/backtrace-child.c
new file mode 100644
index 0000000..8bfed47
--- /dev/null
+++ b/tests/backtrace-child.c
@@ -0,0 +1,248 @@
+/* Test child for parent backtrace test.
+   Copyright (C) 2013, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Command line syntax: ./backtrace-child [--ptraceme|--gencore]
+   --ptraceme will call ptrace (PTRACE_TRACEME) in the two threads.
+   --gencore will call abort () at its end.
+   Main thread will signal SIGUSR2.  Other thread will signal SIGUSR1.
+   There used to be a difference between x86_64 and other architectures.
+   To test getting a signal at the very first instruction of a function:
+     PC will get changed to function 'jmp' by backtrace.c function
+     prepare_thread.  Then SIGUSR2 will be signalled to backtrace-child
+     which will invoke function sigusr2.
+     This is all done so that signal interrupts execution of the very first
+     instruction of a function.  Properly handled unwind should not slip into
+     the previous unrelated function.
+     The tested functionality is arch-independent but the code reproducing it
+     has to be arch-specific.
+   On non-x86_64:
+     sigusr2 gets called by normal function call from function stdarg.
+   On any arch then sigusr2 calls raise (SIGUSR1) for --ptraceme.
+   abort () is called otherwise, expected for --gencore core dump.
+
+   Expected x86_64 output:
+   TID 10276:
+   # 0 0x7f7ab61e9e6b      raise
+   # 1 0x7f7ab661af47 - 1  main
+   # 2 0x7f7ab5e3bb45 - 1  __libc_start_main
+   # 3 0x7f7ab661aa09 - 1  _start
+   TID 10278:
+   # 0 0x7f7ab61e9e6b      raise
+   # 1 0x7f7ab661ab3c - 1  sigusr2
+   # 2 0x7f7ab5e4fa60      __restore_rt
+   # 3 0x7f7ab661ab47      jmp
+   # 4 0x7f7ab661ac92 - 1  stdarg
+   # 5 0x7f7ab661acba - 1  backtracegen
+   # 6 0x7f7ab661acd1 - 1  start
+   # 7 0x7f7ab61e2c53 - 1  start_thread
+   # 8 0x7f7ab5f0fdbd - 1  __clone
+
+   Expected non-x86_64 (i386) output; __kernel_vsyscall are skipped if found:
+   TID 10408:
+   # 0 0xf779f430          __kernel_vsyscall
+   # 1 0xf7771466 - 1      raise
+   # 2 0xf77c1d07 - 1      main
+   # 3 0xf75bd963 - 1      __libc_start_main
+   # 4 0xf77c1761 - 1      _start
+   TID 10412:
+   # 0 0xf779f430          __kernel_vsyscall
+   # 1 0xf7771466 - 1      raise
+   # 2 0xf77c18f4 - 1      sigusr2
+   # 3 0xf77c1a10 - 1      stdarg
+   # 4 0xf77c1a2c - 1      backtracegen
+   # 5 0xf77c1a48 - 1      start
+   # 6 0xf77699da - 1      start_thread
+   # 7 0xf769bbfe - 1      __clone
+
+   But the raise jmp patching was unreliable. It depends on the CFI for the raise()
+   function in glibc to be the same as for the jmp() function. This is not always
+   the case. Some newer glibc versions rewrote raise() and now the CFA is calculated
+   differently. So we disable raise jmp patching everywhere.
+   */
+
+#ifdef __x86_64__
+/* #define RAISE_JMP_PATCHING 1 */
+#endif
+
+#include <config.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#ifndef __linux__
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
+           argv[0]);
+  return 77;
+}
+
+#else /* __linux__ */
+#include <sys/ptrace.h>
+#include <signal.h>
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define NOINLINE_NOCLONE __attribute__ ((noinline, noclone))
+#else
+#define NOINLINE_NOCLONE __attribute__ ((noinline))
+#endif
+
+#define NORETURN __attribute__ ((noreturn))
+#define UNUSED __attribute__ ((unused))
+#define USED __attribute__ ((used))
+
+static int ptraceme, gencore;
+
+/* Execution will arrive here from jmp by an artificial ptrace-spawn signal.  */
+
+static NOINLINE_NOCLONE void
+sigusr2 (int signo)
+{
+  assert (signo == SIGUSR2);
+  if (! gencore)
+    {
+      raise (SIGUSR1);
+      /* Do not return as stack may be invalid due to ptrace-patched PC to the
+	 jmp function.  */
+      pthread_exit (NULL);
+      /* Not reached.  */
+      abort ();
+    }
+  /* Here we dump the core for --gencore.  */
+  raise (SIGABRT);
+  /* Avoid tail call optimization for the raise call.  */
+  asm volatile ("");
+}
+
+static NOINLINE_NOCLONE void
+dummy1 (void)
+{
+  asm volatile ("");
+}
+
+#ifdef RAISE_JMP_PATCHING
+static NOINLINE_NOCLONE USED void
+jmp (void)
+{
+  /* Not reached, signal will get ptrace-spawn to jump into sigusr2.  */
+  abort ();
+}
+#endif
+
+static NOINLINE_NOCLONE void
+dummy2 (void)
+{
+  asm volatile ("");
+}
+
+static NOINLINE_NOCLONE NORETURN void
+stdarg (int f UNUSED, ...)
+{
+  sighandler_t sigusr2_orig = signal (SIGUSR2, sigusr2);
+  assert (sigusr2_orig == SIG_DFL);
+  errno = 0;
+  if (ptraceme)
+    {
+      long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+      assert (l == 0);
+    }
+#ifdef RAISE_JMP_PATCHING
+  if (! gencore)
+    {
+      /* Execution will get PC patched into function jmp.  */
+      raise (SIGUSR1);
+    }
+#endif
+  sigusr2 (SIGUSR2);
+  /* Not reached.  */
+  abort ();
+}
+
+static NOINLINE_NOCLONE void
+dummy3 (void)
+{
+  asm volatile ("");
+}
+
+static NOINLINE_NOCLONE void
+backtracegen (void)
+{
+  stdarg (1);
+  /* Here should be no instruction after the stdarg call as it is noreturn
+     function.  It must be stdarg so that it is a call and not jump (jump as
+     a tail-call).  */
+}
+
+static NOINLINE_NOCLONE void
+dummy4 (void)
+{
+  asm volatile ("");
+}
+
+static void *
+start (void *arg UNUSED)
+{
+  backtracegen ();
+  /* Not reached.  */
+  abort ();
+}
+
+int
+main (int argc UNUSED, char **argv)
+{
+  setbuf (stdout, NULL);
+  assert (*argv++);
+  ptraceme = (*argv && strcmp (*argv, "--ptraceme") == 0);
+  argv += ptraceme;
+  gencore = (*argv && strcmp (*argv, "--gencore") == 0);
+  argv += gencore;
+  assert (!*argv);
+  /* These dummy* functions are there so that each of their surrounding
+     functions has some unrelated code around.  The purpose of some of the
+     tests is verify unwinding the very first / after the very last instruction
+     does not inappropriately slip into the unrelated code around.  */
+  dummy1 ();
+  dummy2 ();
+  dummy3 ();
+  dummy4 ();
+  if (gencore)
+    printf ("%ld\n", (long) getpid ());
+  pthread_t thread;
+  int i = pthread_create (&thread, NULL, start, NULL);
+  // pthread_* functions do not set errno.
+  assert (i == 0);
+  if (ptraceme)
+    {
+      errno = 0;
+      long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+      assert (l == 0);
+    }
+  if (gencore)
+    pthread_join (thread, NULL);
+  else
+    raise (SIGUSR2);
+  return 0;
+}
+
+#endif /* ! __linux__ */
+
diff --git a/tests/backtrace-data.c b/tests/backtrace-data.c
new file mode 100644
index 0000000..c81880d
--- /dev/null
+++ b/tests/backtrace-data.c
@@ -0,0 +1,332 @@
+/* Test custom provided Dwfl_Thread_Callbacks vector.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Test custom provided Dwfl_Thread_Callbacks vector.  Test mimics what
+   a ptrace based vector would do.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dwarf.h>
+#if defined(__x86_64__) && defined(__linux__)
+#include <sys/resource.h>
+#include <sys/ptrace.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <string.h>
+#include ELFUTILS_HEADER(dwfl)
+#endif
+#include "system.h"
+
+#if !defined(__x86_64__) || !defined(__linux__)
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  fprintf (stderr, "%s: x86_64 linux only test\n",
+          argv[0]);
+  return 77;
+}
+
+#else /* __x86_64__ && __linux__ */
+
+/* The only arch specific code is set_initial_registers.  */
+
+static int
+find_elf (Dwfl_Module *mod __attribute__ ((unused)),
+	  void **userdata __attribute__ ((unused)),
+	  const char *modname __attribute__ ((unused)),
+	  Dwarf_Addr base __attribute__ ((unused)),
+	  char **file_name __attribute__ ((unused)),
+	  Elf **elfp __attribute__ ((unused)))
+{
+  /* Not used as modules are reported explicitly.  */
+  assert (0);
+}
+
+static bool
+memory_read (Dwfl *dwfl, Dwarf_Addr addr, Dwarf_Word *result,
+	     void *dwfl_arg __attribute__ ((unused)))
+{
+  pid_t child = dwfl_pid (dwfl);
+
+  errno = 0;
+  long l = ptrace (PTRACE_PEEKDATA, child, (void *) (uintptr_t) addr, NULL);
+
+  // The unwinder can ask for an invalid address.
+  // Don't assert on that but just politely refuse.
+  if (errno != 0) {
+      errno = 0;
+      return false;
+  }
+  *result = l;
+
+  return true;
+}
+
+/* Return filename and VMA address *BASEP where its mapping starts which
+   contains ADDR.  */
+
+static char *
+maps_lookup (pid_t pid, Dwarf_Addr addr, GElf_Addr *basep)
+{
+  char *fname;
+  int i = asprintf (&fname, "/proc/%ld/maps", (long) pid);
+  assert (i > 0);
+  FILE *f = fopen (fname, "r");
+  assert (f);
+  free (fname);
+  for (;;)
+    {
+      // 37e3c22000-37e3c23000 rw-p 00022000 00:11 49532 /lib64/ld-2.14.90.so */
+      unsigned long start, end, offset;
+      i = fscanf (f, "%lx-%lx %*s %lx %*x:%*x %*u", &start, &end, &offset);
+      if (i != 3)
+          break;
+      char *filename = strdup ("");
+      assert (filename);
+      size_t filename_len = 0;
+      for (;;)
+	{
+	  int c = fgetc (f);
+	  assert (c != EOF);
+	  if (c == '\n')
+	    break;
+	  if (c == ' ' && *filename == '\0')
+	    continue;
+	  filename = realloc (filename, filename_len + 2);
+	  assert (filename);
+	  filename[filename_len++] = c;
+	  filename[filename_len] = '\0';
+	}
+      if (start <= addr && addr < end)
+	{
+	  i = fclose (f);
+	  assert (i == 0);
+
+	  *basep = start - offset;
+	  return filename;
+	}
+      free (filename);
+    }
+  *basep = 0;
+  return NULL;
+}
+
+/* Add module containing ADDR to the DWFL address space.
+
+   dwfl_report_elf call here violates Dwfl manipulation as one should call
+   dwfl_report only between dwfl_report_begin_add and dwfl_report_end.
+   Current elfutils implementation does not mind as dwfl_report_begin_add is
+   empty.  */
+
+static Dwfl_Module *
+report_module (Dwfl *dwfl, pid_t child, Dwarf_Addr addr)
+{
+  GElf_Addr base;
+  char *long_name = maps_lookup (child, addr, &base);
+  if (!long_name)
+      return NULL; // not found
+  Dwfl_Module *mod = dwfl_report_elf (dwfl, long_name, long_name, -1,
+				      base, false /* add_p_vaddr */);
+  assert (mod);
+  free (long_name);
+  assert (dwfl_addrmodule (dwfl, addr) == mod);
+  return mod;
+}
+
+static pid_t
+next_thread (Dwfl *dwfl, void *dwfl_arg __attribute__ ((unused)),
+	     void **thread_argp)
+{
+  if (*thread_argp != NULL)
+    return 0;
+  /* Put arbitrary non-NULL value into *THREAD_ARGP as a marker so that this
+     function returns non-zero PID only once.  */
+  *thread_argp = thread_argp;
+  return dwfl_pid (dwfl);
+}
+
+static bool
+set_initial_registers (Dwfl_Thread *thread,
+		       void *thread_arg __attribute__ ((unused)))
+{
+  pid_t child = dwfl_pid (dwfl_thread_dwfl (thread));
+
+  struct user_regs_struct user_regs;
+  long l = ptrace (PTRACE_GETREGS, child, NULL, &user_regs);
+  assert (l == 0);
+
+  Dwarf_Word dwarf_regs[17];
+  dwarf_regs[0] = user_regs.rax;
+  dwarf_regs[1] = user_regs.rdx;
+  dwarf_regs[2] = user_regs.rcx;
+  dwarf_regs[3] = user_regs.rbx;
+  dwarf_regs[4] = user_regs.rsi;
+  dwarf_regs[5] = user_regs.rdi;
+  dwarf_regs[6] = user_regs.rbp;
+  dwarf_regs[7] = user_regs.rsp;
+  dwarf_regs[8] = user_regs.r8;
+  dwarf_regs[9] = user_regs.r9;
+  dwarf_regs[10] = user_regs.r10;
+  dwarf_regs[11] = user_regs.r11;
+  dwarf_regs[12] = user_regs.r12;
+  dwarf_regs[13] = user_regs.r13;
+  dwarf_regs[14] = user_regs.r14;
+  dwarf_regs[15] = user_regs.r15;
+  dwarf_regs[16] = user_regs.rip;
+  bool ok = dwfl_thread_state_registers (thread, 0, 17, dwarf_regs);
+  assert (ok);
+
+  /* x86_64 has PC contained in its CFI subset of DWARF register set so
+     elfutils will figure out the real PC value from REGS.
+     So no need to explicitly call dwfl_thread_state_register_pc.  */
+
+  return true;
+}
+
+static const Dwfl_Thread_Callbacks callbacks =
+{
+  next_thread,
+  NULL, /* get_thread */
+  memory_read,
+  set_initial_registers,
+  NULL, /* detach */
+  NULL, /* thread_detach */
+};
+
+static int
+frame_callback (Dwfl_Frame *state, void *arg)
+{
+  unsigned *framenop = arg;
+  Dwarf_Addr pc;
+  bool isactivation;
+  if (! dwfl_frame_pc (state, &pc, &isactivation))
+    {
+      error (1, 0, "%s", dwfl_errmsg (-1));
+      return 1;
+    }
+  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+  /* Get PC->SYMNAME.  */
+  Dwfl *dwfl = dwfl_thread_dwfl (dwfl_frame_thread (state));
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+  if (mod == NULL)
+    mod = report_module (dwfl, dwfl_pid (dwfl), pc_adjusted);
+  const char *symname = NULL;
+  symname = dwfl_module_addrname (mod, pc_adjusted);
+
+  printf ("#%2u %#" PRIx64 "%4s\t%s\n", (*framenop)++, (uint64_t) pc,
+	  ! isactivation ? "- 1" : "", symname);
+  return DWARF_CB_OK;
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg __attribute__ ((unused)))
+{
+  unsigned frameno = 0;
+  switch (dwfl_thread_getframes (thread, frame_callback, &frameno))
+    {
+    case 0:
+      break;
+    case -1:
+      error (1, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+      break;
+    default:
+      abort ();
+    }
+  return DWARF_CB_OK;
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  elf_version (EV_CURRENT);
+
+  pid_t child = fork ();
+  switch (child)
+  {
+    case -1:
+      assert (0);
+      break;
+    case 0:;
+      long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+      assert (l == 0);
+      raise (SIGUSR1);
+      return 0;
+    default:
+      break;
+  }
+
+  int status;
+  pid_t pid = waitpid (child, &status, 0);
+  assert (pid == child);
+  assert (WIFSTOPPED (status));
+  assert (WSTOPSIG (status) == SIGUSR1);
+
+  static char *debuginfo_path;
+  static const Dwfl_Callbacks offline_callbacks =
+    {
+      .find_debuginfo = dwfl_standard_find_debuginfo,
+      .debuginfo_path = &debuginfo_path,
+      .section_address = dwfl_offline_section_address,
+      .find_elf = find_elf,
+    };
+  Dwfl *dwfl = dwfl_begin (&offline_callbacks);
+  assert (dwfl);
+
+  struct user_regs_struct user_regs;
+  long l = ptrace (PTRACE_GETREGS, child, NULL, &user_regs);
+  assert (l == 0);
+  report_module (dwfl, child, user_regs.rip);
+
+  bool ok = dwfl_attach_state (dwfl, EM_NONE, child, &callbacks, NULL);
+  assert (ok);
+
+  /* Multiple threads are not handled here.  */
+  int err = dwfl_getthreads (dwfl, thread_callback, NULL);
+  assert (! err);
+
+  dwfl_end (dwfl);
+  kill (child, SIGKILL);
+  pid = waitpid (child, &status, 0);
+  assert (pid == child);
+  assert (WIFSIGNALED (status));
+  assert (WTERMSIG (status) == SIGKILL);
+
+  return EXIT_SUCCESS;
+}
+
+#endif /* x86_64 */
diff --git a/tests/backtrace-dwarf.c b/tests/backtrace-dwarf.c
new file mode 100644
index 0000000..f446bc3
--- /dev/null
+++ b/tests/backtrace-dwarf.c
@@ -0,0 +1,181 @@
+/* Test program for unwinding of complicated DWARF expressions.
+   Copyright (C) 2013, 2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <inttypes.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include ELFUTILS_HEADER(dwfl)
+#include "system.h"
+
+#ifndef __linux__
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
+           argv[0]);
+  return 77;
+}
+
+#else /* __linux__ */
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <signal.h>
+
+#define main cleanup_13_main
+#include "cleanup-13.c"
+#undef main
+
+static void
+report_pid (Dwfl *dwfl, pid_t pid)
+{
+  int result = dwfl_linux_proc_report (dwfl, pid);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_report");
+
+  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+  result = dwfl_linux_proc_attach (dwfl, pid, true);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_attach");
+}
+
+static Dwfl *
+pid_to_dwfl (pid_t pid)
+{
+  static char *debuginfo_path;
+  static const Dwfl_Callbacks proc_callbacks =
+    {
+      .find_debuginfo = dwfl_standard_find_debuginfo,
+      .debuginfo_path = &debuginfo_path,
+
+      .find_elf = dwfl_linux_proc_find_elf,
+    };
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+    error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+  report_pid (dwfl, pid);
+  return dwfl;
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *frame_arg)
+{
+  Dwarf_Addr pc;
+  bool isactivation;
+  if (! dwfl_frame_pc (state, &pc, &isactivation))
+    {
+      error (0, 0, "%s", dwfl_errmsg (-1));
+      return DWARF_CB_ABORT;
+    }
+  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+  /* Get PC->SYMNAME.  */
+  Dwfl_Thread *thread = dwfl_frame_thread (state);
+  Dwfl *dwfl = dwfl_thread_dwfl (thread);
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+  const char *symname = NULL;
+  if (mod)
+    symname = dwfl_module_addrname (mod, pc_adjusted);
+
+  printf ("%#" PRIx64 "\t%s\n", (uint64_t) pc, symname ?: "<null>");
+
+  if (symname && (strcmp (symname, "main") == 0
+		  || strcmp (symname, ".main") == 0))
+    {
+      kill (dwfl_pid (dwfl), SIGKILL);
+      exit (0);
+    }
+
+  return DWARF_CB_OK;
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
+{
+  if (dwfl_thread_getframes (thread, frame_callback, NULL) == -1)
+    error (1, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+
+  /* frame_callback shall exit (0) on success.  */
+  printf ("dwfl_thread_getframes returned, main not found\n");
+  return DWARF_CB_ABORT;
+}
+
+int
+__attribute__((section(".main"))) /* Defeat -freorder-blocks-and-partition  */
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  elf_version (EV_CURRENT);
+
+  pid_t pid = fork ();
+  switch (pid)
+  {
+    case -1:
+      perror ("fork failed");
+      exit (-1);
+    case 0:;
+      long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
+      if (l != 0)
+	{
+	  perror ("PTRACE_TRACEME failed");
+	  exit (-1);
+	}
+      cleanup_13_main ();
+      printf ("cleanup_13_main returned, impossible...\n");
+      exit (-1);
+    default:
+      break;
+  }
+
+  errno = 0;
+  int status;
+  pid_t got = waitpid (pid, &status, 0);
+  if (got != pid)
+    error (1, errno, "waitpid returned %d", got);
+  if (!WIFSTOPPED (status))
+    error (1, 0, "unexpected wait status %u", status);
+  if (WSTOPSIG (status) != SIGABRT)
+    error (1, 0, "unexpected signal %u", WSTOPSIG (status));
+
+  Dwfl *dwfl = pid_to_dwfl (pid);
+  if (dwfl_getthreads (dwfl, thread_callback, NULL) == -1)
+    error (1, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+
+  /* There is an exit (0) call if we find the "main" frame,  */
+  printf ("dwfl_getthreads returned, main not found\n");
+  exit (-1);
+}
+
+#endif /* ! __linux__ */
+
diff --git a/tests/backtrace-subr.sh b/tests/backtrace-subr.sh
new file mode 100644
index 0000000..b63e381
--- /dev/null
+++ b/tests/backtrace-subr.sh
@@ -0,0 +1,203 @@
+# Copyright (C) 2013, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Verify one of the backtraced threads contains function 'main'.
+check_main()
+{
+  if grep -w main $1; then
+    return
+  fi
+  echo >&2 $2: no main
+  false
+}
+
+# Without proper ELF symbols resolution we could get inappropriate weak
+# symbol "gsignal" with the same address as the correct symbol "raise".
+# It was fixed by GIT commit 78dec228b3cfb2f9300cd0b682ebf416c9674c91 .
+# [patch] Improve ELF symbols preference (global > weak)
+# https://lists.fedorahosted.org/pipermail/elfutils-devel/2012-October/002624.html
+check_gsignal()
+{
+  if ! grep -w gsignal $1; then
+    return
+  fi
+  echo >&2 $2: found gsignal
+  false
+}
+
+
+# Makes sure we saw the function that initiated the backtrace
+# when the core was generated through the tests backtrace --gencore.
+# This might disappear when frame pointer chasing gone bad.
+check_backtracegen()
+{
+  if grep -w backtracegen $1; then
+    return
+  fi
+  echo >&2 $2: no backtracegen
+  false
+}
+
+# Verify the STDERR output does not contain unexpected errors.
+# In some cases we cannot reliably find out we got behind _start as some
+# operating system do not properly terminate CFI by undefined PC.
+# Ignore it here as it is a bug of OS, not a bug of elfutils.
+check_err()
+{
+  if [ $(grep -E -v <$1 'dwfl_thread_getframes: (No DWARF information found|no matching address range|address out of range|Invalid register|\(null\))$' \
+         | wc -c) \
+       -eq 0 ]
+  then
+    return
+  fi
+  echo >&2 $2: neither empty nor just out of DWARF
+  false
+}
+
+check_all()
+{
+  bt=$1
+  err=$2
+  testname=$3
+  check_main $bt $testname
+  check_gsignal $bt $testname
+  check_err $err $testname
+}
+
+check_unsupported()
+{
+  err=$1
+  testname=$2
+  if grep -q ': Unwinding not supported for this architecture$' $err; then
+    echo >&2 $testname: arch not supported
+    test_cleanup
+    exit 77
+  fi
+}
+
+check_native_unsupported()
+{
+  err=$1
+  testname=$2
+  check_unsupported $err $testname
+
+  # ARM is special. It is supported, but it doesn't use .eh_frame by default
+  # making the native tests fail unless debuginfo (for glibc) is installed
+  # and we can fall back on .debug_frame for the CFI.
+  case "`uname -m`" in
+    arm* )
+      if grep -E 'dwfl_thread_getframes(.*)No DWARF information found' $err; then
+	echo >&2 $testname: arm needs debuginfo installed for all libraries
+	exit 77
+      fi
+    ;;
+  esac
+}
+
+check_core()
+{
+  arch=$1
+  testfiles backtrace.$arch.{exec,core}
+  tempfiles backtrace.$arch.{bt,err}
+  echo ./backtrace ./backtrace.$arch.{exec,core}
+  testrun ${abs_builddir}/backtrace -e ./backtrace.$arch.exec --core=./backtrace.$arch.core 1>backtrace.$arch.bt 2>backtrace.$arch.err || true
+  cat backtrace.$arch.{bt,err}
+  check_unsupported backtrace.$arch.err backtrace.$arch.core
+  check_all backtrace.$arch.{bt,err} backtrace.$arch.core
+  check_backtracegen backtrace.$arch.bt backtrace.$arch.core
+}
+
+# Backtrace live process.
+# Do not abort on non-zero exit code due to some warnings of ./backtrace
+# - see function check_err.
+check_native()
+{
+  child=$1
+  tempfiles $child.{bt,err}
+  (set +ex; testrun ${abs_builddir}/backtrace --backtrace-exec=${abs_builddir}/$child 1>$child.bt 2>$child.err; true)
+  cat $child.{bt,err}
+  check_native_unsupported $child.err $child
+  check_all $child.{bt,err} $child
+}
+
+# Backtrace core file.
+check_native_core()
+{
+# systemd-coredump/coredumpctl doesn't seem to like concurrent core dumps
+# use a lock file (fd 200) tests/core-dump-backtrace.lock
+(
+  child=$1
+
+  # Disable valgrind while dumping core.
+  SAVED_VALGRIND_CMD="$VALGRIND_CMD"
+  unset VALGRIND_CMD
+
+  # Wait for lock for 10 seconds or skip.
+  flock -x -w 10 200 || exit 77;
+
+  # Skip the test if we cannot adjust core ulimit.
+  pid="`ulimit -c unlimited || exit 77; set +ex; testrun ${abs_builddir}/$child --gencore; true`"
+  core="core.$pid"
+  # see if /proc/sys/kernel/core_uses_pid is set to 0
+  if [ -f core ]; then
+    mv core "$core"
+  fi
+  type -P coredumpctl && have_coredumpctl=1 || have_coredumpctl=0
+  if [ ! -f "$core" -a $have_coredumpctl -eq 1 ]; then
+    # Maybe systemd-coredump took it. But give it some time to dump first...
+    sleep 1
+    coredumpctl --output="$core" dump $pid || rm -f $core
+
+    # Try a couple of times after waiting some more if something went wrong...
+    if [ ! -f "$core" ]; then
+      sleep 2
+      coredumpctl --output="$core" dump $pid || rm -f $core
+    fi
+
+    if [ ! -f "$core" ]; then
+      sleep 3
+      coredumpctl --output="$core" dump $pid || rm -f $core
+    fi
+  fi
+  if [ ! -f "$core" ]; then
+    # In some containers our view of pids is confused. Since tests are
+    # run in a new fresh directory any core here is most like is ours.
+    if ls core.[0-9]* 1> /dev/null 2>&1; then
+      mv core.[0-9]* "$core"
+    fi
+  fi
+  if [ ! -f "$core" ]; then
+    echo "No $core file generated";
+    exit 77;
+  fi
+
+  if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
+    VALGRIND_CMD="$SAVED_VALGRIND_CMD"
+    export VALGRIND_CMD
+  fi
+
+  # Do not abort on non-zero exit code due to some warnings of ./backtrace
+  # - see function check_err.
+  tempfiles $core{,.{bt,err}}
+  (set +ex; testrun ${abs_builddir}/backtrace -e ${abs_builddir}/$child --core=$core 1>$core.bt 2>$core.err; true)
+  cat $core.{bt,err}
+  check_native_unsupported $core.err $child-$core
+  check_all $core.{bt,err} $child-$core
+  rm $core{,.{bt,err}}
+) 200>${abs_builddir}/core-dump-backtrace.lock
+}
diff --git a/tests/backtrace.aarch64.core.bz2 b/tests/backtrace.aarch64.core.bz2
new file mode 100644
index 0000000..3082a5a
--- /dev/null
+++ b/tests/backtrace.aarch64.core.bz2
Binary files differ
diff --git a/tests/backtrace.aarch64.exec.bz2 b/tests/backtrace.aarch64.exec.bz2
new file mode 100755
index 0000000..66216b5
--- /dev/null
+++ b/tests/backtrace.aarch64.exec.bz2
Binary files differ
diff --git a/tests/backtrace.aarch64.fp.core.bz2 b/tests/backtrace.aarch64.fp.core.bz2
new file mode 100644
index 0000000..ff86788
--- /dev/null
+++ b/tests/backtrace.aarch64.fp.core.bz2
Binary files differ
diff --git a/tests/backtrace.aarch64.fp.exec.bz2 b/tests/backtrace.aarch64.fp.exec.bz2
new file mode 100644
index 0000000..9d06db1
--- /dev/null
+++ b/tests/backtrace.aarch64.fp.exec.bz2
Binary files differ
diff --git a/tests/backtrace.c b/tests/backtrace.c
new file mode 100644
index 0000000..5555530
--- /dev/null
+++ b/tests/backtrace.c
@@ -0,0 +1,549 @@
+/* Test program for unwinding of frames.
+   Copyright (C) 2013, 2014, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dwarf.h>
+#ifdef __linux__
+#include <sys/resource.h>
+#include <sys/ptrace.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <string.h>
+#include <argp.h>
+#include ELFUTILS_HEADER(dwfl)
+#endif
+#include "system.h"
+
+#ifndef __linux__
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
+	   argv[0]);
+  return 77;
+}
+
+#else /* __linux__ */
+
+static int
+dump_modules (Dwfl_Module *mod, void **userdata __attribute__ ((unused)),
+	      const char *name, Dwarf_Addr start,
+	      void *arg __attribute__ ((unused)))
+{
+  Dwarf_Addr end;
+  dwfl_module_info (mod, NULL, NULL, &end, NULL, NULL, NULL, NULL);
+  printf ("%#" PRIx64 "\t%#" PRIx64 "\t%s\n", (uint64_t) start, (uint64_t) end,
+	  name);
+  return DWARF_CB_OK;
+}
+
+static bool use_raise_jmp_patching;
+static pid_t check_tid;
+
+static void
+callback_verify (pid_t tid, unsigned frameno, Dwarf_Addr pc,
+		 const char *symname, Dwfl *dwfl)
+{
+  static bool seen_main = false;
+  if (symname && *symname == '.')
+    symname++;
+  if (symname && strcmp (symname, "main") == 0)
+    seen_main = true;
+  if (pc == 0)
+    {
+      assert (seen_main);
+      return;
+    }
+  if (check_tid == 0)
+    check_tid = tid;
+  if (tid != check_tid)
+    {
+      // For the main thread we are only interested if we can unwind till
+      // we see the "main" symbol.
+      return;
+    }
+  Dwfl_Module *mod;
+  /* Skip frames for which there isn't a function name.  */
+  static int nulls_seen = 0;
+  if (symname == NULL)
+    {
+      nulls_seen++;
+      return;
+    }
+  frameno -= nulls_seen;
+  /* See case 4. Special case to help out simple frame pointer unwinders. */
+  static bool duplicate_sigusr2 = false;
+  if (duplicate_sigusr2)
+    frameno--;
+  static bool reduce_frameno = false;
+  if (reduce_frameno)
+    frameno--;
+  static bool pthread_kill_seen = false;
+  if (pthread_kill_seen)
+    frameno--;
+  if (! use_raise_jmp_patching && frameno >= 2)
+    frameno += 2;
+  const char *symname2 = NULL;
+  switch (frameno)
+  {
+    case 0:
+      if (! reduce_frameno && symname
+	       && (strcmp (symname, "__kernel_vsyscall") == 0
+		   || strcmp (symname, "__libc_do_syscall") == 0))
+	reduce_frameno = true;
+      else if (! pthread_kill_seen && symname
+	       && strstr (symname, "pthread_kill") != NULL)
+	pthread_kill_seen = true;
+      else
+	{
+	  if (!symname || strcmp (symname, "raise") != 0)
+	    {
+	      fprintf (stderr,
+		       "case 0: expected symname 'raise' got '%s'\n", symname);
+	      abort ();
+	    }
+	}
+      break;
+    case 1:
+      if (symname == NULL || strcmp (symname, "sigusr2") != 0)
+	{
+	  fprintf (stderr,
+		   "case 1: expected symname 'sigusr2' got '%s'\n", symname);
+	  abort ();
+	}
+      break;
+    case 2: // x86_64 only
+      /* __restore_rt - glibc maybe does not have to have this symbol.  */
+      break;
+    case 3: // use_raise_jmp_patching
+      if (use_raise_jmp_patching)
+	{
+	  /* Verify we trapped on the very first instruction of jmp.  */
+	  if (symname == NULL || strcmp (symname, "jmp") != 0)
+	    {
+	      fprintf (stderr,
+		       "case 3: expected symname 'raise' got '%s'\n", symname);
+	      abort ();
+	    }
+	  mod = dwfl_addrmodule (dwfl, pc - 1);
+	  if (mod)
+	    symname2 = dwfl_module_addrname (mod, pc - 1);
+	  if (symname2 == NULL || strcmp (symname2, "jmp") != 0)
+	    {
+	      fprintf (stderr,
+		       "case 3: expected symname2 'jmp' got '%s'\n", symname2);
+	      abort ();
+	    }
+	  break;
+	}
+      FALLTHROUGH;
+    case 4:
+      /* Some simple frame unwinders get this wrong and think sigusr2
+	 is calling itself again. Allow it and just pretend there is
+	 an extra sigusr2 frame. */
+      if (symname != NULL && strcmp (symname, "sigusr2") == 0)
+	{
+	  duplicate_sigusr2 = true;
+	  break;
+	}
+      if (symname == NULL || strcmp (symname, "stdarg") != 0)
+	{
+	  fprintf (stderr,
+		   "case 4: expected symname 'stdarg' got '%s'\n", symname);
+	  abort ();
+	}
+      break;
+    case 5:
+      /* Verify we trapped on the very last instruction of child.  */
+      if (symname == NULL || strcmp (symname, "backtracegen") != 0)
+	{
+	  fprintf (stderr,
+		   "case 5: expected symname 'backtracegen' got '%s'\n",
+		   symname);
+	  abort ();
+	}
+      mod = dwfl_addrmodule (dwfl, pc);
+      if (mod)
+	symname2 = dwfl_module_addrname (mod, pc);
+
+      // Note that the following assert might in theory even fail on x86_64,
+      // there is no guarantee that the compiler doesn't reorder the
+      // instructions or even inserts some padding instructions at the end
+      // (which apparently happens on ppc64).
+      if (use_raise_jmp_patching)
+	{
+          if (symname2 != NULL && strcmp (symname2, "backtracegen") == 0)
+	    {
+	      fprintf (stderr,
+		       "use_raise_jmp_patching didn't expect symname2 "
+		       "'backtracegen'\n");
+	      abort ();
+	    }
+	}
+      break;
+  }
+}
+
+static int
+frame_callback (Dwfl_Frame *state, void *frame_arg)
+{
+  int *framenop = frame_arg;
+  Dwarf_Addr pc;
+  bool isactivation;
+
+  if (*framenop > 16)
+    {
+      error (0, 0, "Too many frames: %d\n", *framenop);
+      return DWARF_CB_ABORT;
+    }
+
+  if (! dwfl_frame_pc (state, &pc, &isactivation))
+    {
+      error (0, 0, "%s", dwfl_errmsg (-1));
+      return DWARF_CB_ABORT;
+    }
+  Dwarf_Addr pc_adjusted = pc - (isactivation ? 0 : 1);
+
+  /* Get PC->SYMNAME.  */
+  Dwfl_Thread *thread = dwfl_frame_thread (state);
+  Dwfl *dwfl = dwfl_thread_dwfl (thread);
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, pc_adjusted);
+  const char *symname = NULL;
+  if (mod)
+    symname = dwfl_module_addrname (mod, pc_adjusted);
+
+  printf ("#%2d %#" PRIx64 "%4s\t%s\n", *framenop, (uint64_t) pc,
+	  ! isactivation ? "- 1" : "", symname ?: "<null>");
+  pid_t tid = dwfl_thread_tid (thread);
+  callback_verify (tid, *framenop, pc, symname, dwfl);
+  (*framenop)++;
+
+  return DWARF_CB_OK;
+}
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg __attribute__((unused)))
+{
+  printf ("TID %ld:\n", (long) dwfl_thread_tid (thread));
+  int frameno = 0;
+  switch (dwfl_thread_getframes (thread, frame_callback, &frameno))
+    {
+    case 0:
+      break;
+    case DWARF_CB_ABORT:
+      return DWARF_CB_ABORT;
+    case -1:
+      error (0, 0, "dwfl_thread_getframes: %s", dwfl_errmsg (-1));
+      /* All platforms do not have yet proper unwind termination.  */
+      break;
+    default:
+      abort ();
+    }
+  return DWARF_CB_OK;
+}
+
+static void
+dump (Dwfl *dwfl)
+{
+  ptrdiff_t ptrdiff = dwfl_getmodules (dwfl, dump_modules, NULL, 0);
+  assert (ptrdiff == 0);
+  bool err = false;
+  switch (dwfl_getthreads (dwfl, thread_callback, NULL))
+    {
+    case 0:
+      break;
+    case DWARF_CB_ABORT:
+      err = true;
+      break;
+    case -1:
+      error (0, 0, "dwfl_getthreads: %s", dwfl_errmsg (-1));
+      err = true;
+      break;
+    default:
+      abort ();
+    }
+  callback_verify (0, 0, 0, NULL, dwfl);
+  if (err)
+    exit (EXIT_FAILURE);
+}
+
+struct see_exec_module
+{
+  Dwfl_Module *mod;
+  char selfpath[PATH_MAX + 1];
+};
+
+static int
+see_exec_module (Dwfl_Module *mod, void **userdata __attribute__ ((unused)),
+		 const char *name __attribute__ ((unused)),
+		 Dwarf_Addr start __attribute__ ((unused)), void *arg)
+{
+  struct see_exec_module *data = arg;
+  if (strcmp (name, data->selfpath) != 0)
+    return DWARF_CB_OK;
+  assert (data->mod == NULL);
+  data->mod = mod;
+  return DWARF_CB_ABORT;
+}
+
+/* We used to do this on x86_64 only (see backtrace-child why we now don't):
+     PC will get changed to function 'jmp' by backtrace.c function
+     prepare_thread.  Then SIGUSR2 will be signalled to backtrace-child
+     which will invoke function sigusr2.
+     This is all done so that signal interrupts execution of the very first
+     instruction of a function.  Properly handled unwind should not slip into
+     the previous unrelated function.  */
+
+#ifdef __x86_64__
+/* #define RAISE_JMP_PATCHING 1 */
+#endif
+
+static void
+prepare_thread (pid_t pid2 __attribute__ ((unused)),
+		void (*jmp) (void) __attribute__ ((unused)))
+{
+#ifndef RAISE_JMP_PATCHING
+  abort ();
+#else /* RAISE_JMP_PATCHING */
+  long l;
+  struct user_regs_struct user_regs;
+  errno = 0;
+  l = ptrace (PTRACE_GETREGS, pid2, 0, (intptr_t) &user_regs);
+  assert (l == 0);
+  user_regs.rip = (intptr_t) jmp;
+  l = ptrace (PTRACE_SETREGS, pid2, 0, (intptr_t) &user_regs);
+  assert (l == 0);
+  l = ptrace (PTRACE_CONT, pid2, NULL, (void *) (intptr_t) SIGUSR2);
+  int status;
+  pid_t got = waitpid (pid2, &status, __WALL);
+  assert (got == pid2);
+  assert (WIFSTOPPED (status));
+  assert (WSTOPSIG (status) == SIGUSR1);
+#endif /* RAISE_JMP_PATCHING */
+}
+
+#include <asm/unistd.h>
+#include <unistd.h>
+
+static void
+report_pid (Dwfl *dwfl, pid_t pid)
+{
+  int result = dwfl_linux_proc_report (dwfl, pid);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_report");
+
+  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+  result = dwfl_linux_proc_attach (dwfl, pid, true);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_attach");
+}
+
+static Dwfl *
+pid_to_dwfl (pid_t pid)
+{
+  static char *debuginfo_path;
+  static const Dwfl_Callbacks proc_callbacks =
+    {
+      .find_debuginfo = dwfl_standard_find_debuginfo,
+      .debuginfo_path = &debuginfo_path,
+
+      .find_elf = dwfl_linux_proc_find_elf,
+    };
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+    error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+  report_pid (dwfl, pid);
+  return dwfl;
+}
+
+static void
+exec_dump (const char *exec)
+{
+  pid_t pid = fork ();
+  switch (pid)
+  {
+    case -1:
+      abort ();
+    case 0:
+      execl (exec, exec, "--ptraceme", NULL);
+      abort ();
+    default:
+      break;
+  }
+
+  /* Catch the main thread.  Catch it first otherwise the /proc evaluation of
+     PID may have caught still ourselves before executing execl above.  */
+  errno = 0;
+  int status;
+  pid_t got = waitpid (pid, &status, 0);
+  assert (got == pid);
+  assert (WIFSTOPPED (status));
+  // Main thread will signal SIGUSR2.  Other thread will signal SIGUSR1.
+  assert (WSTOPSIG (status) == SIGUSR2);
+
+  /* Catch the spawned thread.  Do not use __WCLONE as we could get racy
+     __WCLONE, probably despite pthread_create already had to be called the new
+     task is not yet alive enough for waitpid.  */
+  pid_t pid2 = waitpid (-1, &status, __WALL);
+  assert (pid2 > 0);
+  assert (pid2 != pid);
+  assert (WIFSTOPPED (status));
+  // Main thread will signal SIGUSR2.  Other thread will signal SIGUSR1.
+  assert (WSTOPSIG (status) == SIGUSR1);
+
+  Dwfl *dwfl = pid_to_dwfl (pid);
+  char *selfpathname;
+  int i = asprintf (&selfpathname, "/proc/%ld/exe", (long) pid);
+  assert (i > 0);
+  struct see_exec_module data;
+  ssize_t ssize = readlink (selfpathname, data.selfpath,
+			    sizeof (data.selfpath));
+  free (selfpathname);
+  assert (ssize > 0 && ssize < (ssize_t) sizeof (data.selfpath));
+  data.selfpath[ssize] = '\0';
+  data.mod = NULL;
+  dwfl_getmodules (dwfl, see_exec_module, &data, 0);
+  assert (data.mod != NULL);
+  GElf_Addr loadbase;
+  Elf *elf = dwfl_module_getelf (data.mod, &loadbase);
+  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  assert (ehdr != NULL);
+  /* It is false also on x86_64 with i386 inferior.  */
+#ifndef RAISE_JMP_PATCHING
+  use_raise_jmp_patching = false;
+#else /* RAISE_JMP_PATCHING_ */
+  use_raise_jmp_patching = ehdr->e_machine == EM_X86_64;
+#endif /* __x86_64__ */
+  void (*jmp) (void) = 0;
+  if (use_raise_jmp_patching)
+    {
+      // Find inferior symbol named "jmp".
+      int nsym = dwfl_module_getsymtab (data.mod);
+      int symi;
+      for (symi = 1; symi < nsym; ++symi)
+	{
+	  GElf_Sym symbol;
+	  const char *symbol_name = dwfl_module_getsym (data.mod, symi, &symbol, NULL);
+	  if (symbol_name == NULL)
+	    continue;
+	  switch (GELF_ST_TYPE (symbol.st_info))
+	    {
+	    case STT_SECTION:
+	    case STT_FILE:
+	    case STT_TLS:
+	      continue;
+	    default:
+	      if (strcmp (symbol_name, "jmp") != 0)
+		continue;
+	      break;
+	    }
+	  /* LOADBASE is already applied here.  */
+	  jmp = (void (*) (void)) (uintptr_t) symbol.st_value;
+	  break;
+	}
+      assert (symi < nsym);
+      prepare_thread (pid2, jmp);
+    }
+  dwfl_end (dwfl);
+  check_tid = pid2;
+  dwfl = pid_to_dwfl (pid);
+  dump (dwfl);
+  dwfl_end (dwfl);
+}
+
+#define OPT_BACKTRACE_EXEC 0x100
+
+static const struct argp_option options[] =
+  {
+    { "backtrace-exec", OPT_BACKTRACE_EXEC, "EXEC", 0, N_("Run executable"), 0 },
+    { NULL, 0, NULL, 0, NULL, 0 }
+  };
+
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  switch (key)
+    {
+    case ARGP_KEY_INIT:
+      state->child_inputs[0] = state->input;
+      break;
+
+    case OPT_BACKTRACE_EXEC:
+      exec_dump (arg);
+      exit (0);
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  __fsetlocking (stdin, FSETLOCKING_BYCALLER);
+  __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+  __fsetlocking (stderr, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  elf_version (EV_CURRENT);
+
+  Dwfl *dwfl = NULL;
+  const struct argp_child argp_children[] =
+    {
+      { .argp = dwfl_standard_argp () },
+      { .argp = NULL }
+    };
+  const struct argp argp =
+    {
+      options, parse_opt, NULL, NULL, argp_children, NULL, NULL
+    };
+  (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
+  assert (dwfl != NULL);
+  /* We want to make sure the dwfl was properly attached.  */
+  if (dwfl_pid (dwfl) < 0)
+    error (2, 0, "dwfl_pid: %s", dwfl_errmsg (-1));
+  dump (dwfl);
+  dwfl_end (dwfl);
+  return 0;
+}
+
+#endif /* ! __linux__ */
+
diff --git a/tests/backtrace.i386.core.bz2 b/tests/backtrace.i386.core.bz2
new file mode 100644
index 0000000..e120d9b
--- /dev/null
+++ b/tests/backtrace.i386.core.bz2
Binary files differ
diff --git a/tests/backtrace.i386.exec.bz2 b/tests/backtrace.i386.exec.bz2
new file mode 100644
index 0000000..1b0f001
--- /dev/null
+++ b/tests/backtrace.i386.exec.bz2
Binary files differ
diff --git a/tests/backtrace.i386.fp.core.bz2 b/tests/backtrace.i386.fp.core.bz2
new file mode 100644
index 0000000..3c49e24
--- /dev/null
+++ b/tests/backtrace.i386.fp.core.bz2
Binary files differ
diff --git a/tests/backtrace.i386.fp.exec.bz2 b/tests/backtrace.i386.fp.exec.bz2
new file mode 100755
index 0000000..cb4d32e
--- /dev/null
+++ b/tests/backtrace.i386.fp.exec.bz2
Binary files differ
diff --git a/tests/backtrace.ppc.core.bz2 b/tests/backtrace.ppc.core.bz2
new file mode 100644
index 0000000..3a025d2
--- /dev/null
+++ b/tests/backtrace.ppc.core.bz2
Binary files differ
diff --git a/tests/backtrace.ppc.exec.bz2 b/tests/backtrace.ppc.exec.bz2
new file mode 100644
index 0000000..333c6be
--- /dev/null
+++ b/tests/backtrace.ppc.exec.bz2
Binary files differ
diff --git a/tests/backtrace.ppc64le.fp.core.bz2 b/tests/backtrace.ppc64le.fp.core.bz2
new file mode 100644
index 0000000..e63babf
--- /dev/null
+++ b/tests/backtrace.ppc64le.fp.core.bz2
Binary files differ
diff --git a/tests/backtrace.ppc64le.fp.exec.bz2 b/tests/backtrace.ppc64le.fp.exec.bz2
new file mode 100755
index 0000000..ed1352a
--- /dev/null
+++ b/tests/backtrace.ppc64le.fp.exec.bz2
Binary files differ
diff --git a/tests/backtrace.s390.core.bz2 b/tests/backtrace.s390.core.bz2
new file mode 100644
index 0000000..db34694
--- /dev/null
+++ b/tests/backtrace.s390.core.bz2
Binary files differ
diff --git a/tests/backtrace.s390.exec.bz2 b/tests/backtrace.s390.exec.bz2
new file mode 100644
index 0000000..4c1b4ae
--- /dev/null
+++ b/tests/backtrace.s390.exec.bz2
Binary files differ
diff --git a/tests/backtrace.s390x.core.bz2 b/tests/backtrace.s390x.core.bz2
new file mode 100644
index 0000000..61c23ec
--- /dev/null
+++ b/tests/backtrace.s390x.core.bz2
Binary files differ
diff --git a/tests/backtrace.s390x.exec.bz2 b/tests/backtrace.s390x.exec.bz2
new file mode 100644
index 0000000..8009239
--- /dev/null
+++ b/tests/backtrace.s390x.exec.bz2
Binary files differ
diff --git a/tests/backtrace.sparc.core.bz2 b/tests/backtrace.sparc.core.bz2
new file mode 100644
index 0000000..ad37f75
--- /dev/null
+++ b/tests/backtrace.sparc.core.bz2
Binary files differ
diff --git a/tests/backtrace.sparc.exec.bz2 b/tests/backtrace.sparc.exec.bz2
new file mode 100755
index 0000000..b049ec5
--- /dev/null
+++ b/tests/backtrace.sparc.exec.bz2
Binary files differ
diff --git a/tests/backtrace.x32.core.bz2 b/tests/backtrace.x32.core.bz2
new file mode 100644
index 0000000..c06d70a
--- /dev/null
+++ b/tests/backtrace.x32.core.bz2
Binary files differ
diff --git a/tests/backtrace.x32.exec.bz2 b/tests/backtrace.x32.exec.bz2
new file mode 100644
index 0000000..e89401b
--- /dev/null
+++ b/tests/backtrace.x32.exec.bz2
Binary files differ
diff --git a/tests/backtrace.x86_64.core.bz2 b/tests/backtrace.x86_64.core.bz2
new file mode 100644
index 0000000..1f34e20
--- /dev/null
+++ b/tests/backtrace.x86_64.core.bz2
Binary files differ
diff --git a/tests/backtrace.x86_64.exec.bz2 b/tests/backtrace.x86_64.exec.bz2
new file mode 100644
index 0000000..70a151b
--- /dev/null
+++ b/tests/backtrace.x86_64.exec.bz2
Binary files differ
diff --git a/tests/backtrace.x86_64.fp.core.bz2 b/tests/backtrace.x86_64.fp.core.bz2
new file mode 100644
index 0000000..e773ca2
--- /dev/null
+++ b/tests/backtrace.x86_64.fp.core.bz2
Binary files differ
diff --git a/tests/backtrace.x86_64.fp.exec.bz2 b/tests/backtrace.x86_64.fp.exec.bz2
new file mode 100644
index 0000000..0695845
--- /dev/null
+++ b/tests/backtrace.x86_64.fp.exec.bz2
Binary files differ
diff --git a/tests/buildid.c b/tests/buildid.c
new file mode 100644
index 0000000..2390eff
--- /dev/null
+++ b/tests/buildid.c
@@ -0,0 +1,81 @@
+/* Test program for dwelf_elf_gnu_build_id, print build ID.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <err.h>
+#include <errno.h>
+#include ELFUTILS_HEADER(elf)
+#include ELFUTILS_HEADER(dwelf)
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "system.h"
+
+int
+main (int argc, char *argv[])
+{
+  if (argc < 2)
+    error (EXIT_FAILURE, 0, "No input file given");
+
+  elf_version (EV_CURRENT);
+
+  for (int i = 1; i < argc; i++)
+    {
+      const char *file = argv[i];
+      int fd = open (file, O_RDONLY);
+      if (fd < 0)
+	error (EXIT_FAILURE, errno, "couldn't open file '%s'", file);
+
+      Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+      if (elf == NULL)
+	{
+	  printf("%s: elf_begin failed: %s\n", file, elf_errmsg (-1));
+	  close (fd);
+	  continue;
+	}
+
+      const void *build_id;
+      ssize_t len = dwelf_elf_gnu_build_id (elf, &build_id);
+      switch (len)
+	{
+	case 0:
+	  printf ("%s: <no NT_GNU_BUILD_ID note>\n", file);
+	  break;
+	case -1:
+	  errx (1, "dwelf_elf_gnu_build_id (%s): %s",
+		file, elf_errmsg (-1));
+	default:
+	  printf ("%s: build ID: ", file);
+	  const unsigned char *p = build_id;
+	  const unsigned char *end = p + len;
+	  while (p < end)
+	      printf("%02x", (unsigned)*p++);
+	  putchar('\n');
+	}
+
+      elf_end (elf);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/cleanup-13.c b/tests/cleanup-13.c
new file mode 100644
index 0000000..3919b91
--- /dev/null
+++ b/tests/cleanup-13.c
@@ -0,0 +1,316 @@
+// http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/testsuite/gcc.dg/cleanup-13.c?view=co&content-type=text%2Fplain
+
+/* HP-UX libunwind.so doesn't provide _UA_END_OF_STACK */
+/* { dg-do run } */
+/* { dg-options "-fexceptions" } */
+/* { dg-skip-if "" { "ia64-*-hpux11.*" }  { "*" } { "" } } */
+/* Verify DW_OP_* handling in the unwinder.  */
+
+#include <unwind.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* #define OP_addr(x) 0x06, ... */
+#define OP_deref 0x06,
+#define SLEB128(x) (x)&0x7f	/* Assume here the value is -0x40 ... 0x3f.  */
+#define ULEB128(x) (x)&0x7f	/* Assume here the value is 0 ... 0x7f.  */
+#define VAL1(x) (x)&0xff
+#if defined (__BIG_ENDIAN__)
+#define VAL2(x) ((x)>>8)&0xff,(x)&0xff
+#define VAL4(x) ((x)>>24)&0xff,((x)>>16)&0xff,((x)>>8)&0xff,(x)&0xff
+#define VAL8(x) ((x)>>56)&0xff,((x)>>48)&0xff,((x)>>40)&0xff,((x)>>32)&0xff,((x)>>24)&0xff,((x)>>16)&0xff,((x)>>8)&0xff,(x)&0xff
+#elif defined(__LITTLE_ENDIAN__) || defined(__x86_64__) || defined(__i386__)
+#define VAL2(x) (x)&0xff,((x)>>8)&0xff
+#define VAL4(x) (x)&0xff,((x)>>8)&0xff,((x)>>16)&0xff,((x)>>24)&0xff
+#define VAL8(x) (x)&0xff,((x)>>8)&0xff,((x)>>16)&0xff,((x)>>24)&0xff,((x)>>32)&0xff,((x)>>40)&0xff,((x)>>48)&0xff,((x)>>56)&0xff
+#endif
+#define OP_const1u(x) 0x08,VAL1(x),
+#define OP_const1s(x) 0x09,VAL1(x),
+#define OP_const2u(x) 0x0a,VAL2(x),
+#define OP_const2s(x) 0x0b,VAL2(x),
+#define OP_const4u(x) 0x0c,VAL4(x),
+#define OP_const4s(x) 0x0d,VAL4(x),
+#define OP_const8u(x) 0x0e,VAL8(x),
+#define OP_const8s(x) 0x0f,VAL8(x),
+#define OP_constu(x) 0x10,ULEB128(x),
+#define OP_consts(x) 0x11,SLEB128(x),
+#define OP_dup 0x12,
+#define OP_drop 0x13,
+#define OP_over 0x14,
+#define OP_pick(x) 0x15,VAL1(x),
+#define OP_swap 0x16,
+#define OP_rot 0x17,
+#define OP_xderef 0x18,
+#define OP_abs 0x19,
+#define OP_and 0x1a,
+#define OP_div 0x1b,
+#define OP_minus 0x1c,
+#define OP_mod 0x1d,
+#define OP_mul 0x1e,
+#define OP_neg 0x1f,
+#define OP_not 0x20,
+#define OP_or 0x21,
+#define OP_plus 0x22,
+#define OP_plus_uconst(x) 0x23,ULEB128(x),
+#define OP_shl 0x24,
+#define OP_shr 0x25,
+#define OP_shra 0x26,
+#define OP_xor 0x27,
+#define OP_bra(x) 0x28,VAL2(x),
+#define OP_eq 0x29,
+#define OP_ge 0x2a,
+#define OP_gt 0x2b,
+#define OP_le 0x2c,
+#define OP_lt 0x2d,
+#define OP_ne 0x2e,
+#define OP_skip(x) 0x2f,VAL2(x),
+#define OP_lit0 0x30,
+#define OP_lit1 0x31,
+#define OP_lit2 0x32,
+#define OP_lit3 0x33,
+#define OP_lit4 0x34,
+#define OP_lit5 0x35,
+#define OP_lit6 0x36,
+#define OP_lit7 0x37,
+#define OP_lit8 0x38,
+#define OP_lit9 0x39,
+#define OP_lit10 0x3a,
+#define OP_lit11 0x3b,
+#define OP_lit12 0x3c,
+#define OP_lit13 0x3d,
+#define OP_lit14 0x3e,
+#define OP_lit15 0x3f,
+#define OP_lit16 0x40,
+#define OP_lit17 0x41,
+#define OP_lit18 0x42,
+#define OP_lit19 0x43,
+#define OP_lit20 0x44,
+#define OP_lit21 0x45,
+#define OP_lit22 0x46,
+#define OP_lit23 0x47,
+#define OP_lit24 0x48,
+#define OP_lit25 0x49,
+#define OP_lit26 0x4a,
+#define OP_lit27 0x4b,
+#define OP_lit28 0x4c,
+#define OP_lit29 0x4d,
+#define OP_lit30 0x4e,
+#define OP_lit31 0x4f,
+#define OP_reg0 0x50,
+#define OP_reg1 0x51,
+#define OP_reg2 0x52,
+#define OP_reg3 0x53,
+#define OP_reg4 0x54,
+#define OP_reg5 0x55,
+#define OP_reg6 0x56,
+#define OP_reg7 0x57,
+#define OP_reg8 0x58,
+#define OP_reg9 0x59,
+#define OP_reg10 0x5a,
+#define OP_reg11 0x5b,
+#define OP_reg12 0x5c,
+#define OP_reg13 0x5d,
+#define OP_reg14 0x5e,
+#define OP_reg15 0x5f,
+#define OP_reg16 0x60,
+#define OP_reg17 0x61,
+#define OP_reg18 0x62,
+#define OP_reg19 0x63,
+#define OP_reg20 0x64,
+#define OP_reg21 0x65,
+#define OP_reg22 0x66,
+#define OP_reg23 0x67,
+#define OP_reg24 0x68,
+#define OP_reg25 0x69,
+#define OP_reg26 0x6a,
+#define OP_reg27 0x6b,
+#define OP_reg28 0x6c,
+#define OP_reg29 0x6d,
+#define OP_reg30 0x6e,
+#define OP_reg31 0x6f,
+#define OP_breg0(x) 0x70,SLEB128(x),
+#define OP_breg1(x) 0x71,SLEB128(x),
+#define OP_breg2(x) 0x72,SLEB128(x),
+#define OP_breg3(x) 0x73,SLEB128(x),
+#define OP_breg4(x) 0x74,SLEB128(x),
+#define OP_breg5(x) 0x75,SLEB128(x),
+#define OP_breg6(x) 0x76,SLEB128(x),
+#define OP_breg7(x) 0x77,SLEB128(x),
+#define OP_breg8(x) 0x78,SLEB128(x),
+#define OP_breg9(x) 0x79,SLEB128(x),
+#define OP_breg10(x) 0x7a,SLEB128(x),
+#define OP_breg11(x) 0x7b,SLEB128(x),
+#define OP_breg12(x) 0x7c,SLEB128(x),
+#define OP_breg13(x) 0x7d,SLEB128(x),
+#define OP_breg14(x) 0x7e,SLEB128(x),
+#define OP_breg15(x) 0x7f,SLEB128(x),
+#define OP_breg16(x) 0x80,SLEB128(x),
+#define OP_breg17(x) 0x81,SLEB128(x),
+#define OP_breg18(x) 0x82,SLEB128(x),
+#define OP_breg19(x) 0x83,SLEB128(x),
+#define OP_breg20(x) 0x84,SLEB128(x),
+#define OP_breg21(x) 0x85,SLEB128(x),
+#define OP_breg22(x) 0x86,SLEB128(x),
+#define OP_breg23(x) 0x87,SLEB128(x),
+#define OP_breg24(x) 0x88,SLEB128(x),
+#define OP_breg25(x) 0x89,SLEB128(x),
+#define OP_breg26(x) 0x8a,SLEB128(x),
+#define OP_breg27(x) 0x8b,SLEB128(x),
+#define OP_breg28(x) 0x8c,SLEB128(x),
+#define OP_breg29(x) 0x8d,SLEB128(x),
+#define OP_breg30(x) 0x8e,SLEB128(x),
+#define OP_breg31(x) 0x8f,SLEB128(x),
+#define OP_regx(x) 0x90,SLEB128(x),
+#define OP_fbreg(x) 0x91,SLEB128(x),
+#define OP_bregx(x,y) 0x92,ULEB128(x),SLEB128(y),
+#define OP_piece(x) 0x93,ULEB128(x),
+#define OP_deref_size(x) 0x94,VAL1(x),
+#define OP_xderef_size(x) 0x95,VAL1(x),
+#define OP_nop 0x96,
+#define OP_nop_termination 0x96
+#define OP_push_object_address 0x97,
+#define OP_call2(x) 0x98,VAL2(x),
+#define OP_call4(x) 0x99,VAL4(x),
+/* #define OP_call_ref(x) 0x9a,... */
+#define OP_form_tls_address(x) 0x9b,
+#define OP_call_frame_cfa 0x9c,
+#define OP_bit_piece(x) 0x9d,ULEB128(x),
+/* #define OP_implicit_value(x...) 0x9e,... */
+#define OP_stack_value 0x9f,
+#define OP_GNU_push_tls_address 0xe0,
+/* #define OP_GNU_encoded_addr(x...) 0xf1, */
+
+#define ASSERT_TOS_NON0 OP_bra(3) OP_skip(-3)
+#define ASSERT_TOS_0 OP_lit0 OP_eq ASSERT_TOS_NON0
+
+/* Initially there is CFA value on the stack, we want to
+   keep it there at the end.  */
+#define CFI_PROGRAM \
+OP_lit0 OP_nop ASSERT_TOS_0						\
+OP_lit1 ASSERT_TOS_NON0							\
+OP_lit1 OP_const1u(1) OP_eq ASSERT_TOS_NON0				\
+OP_lit16 OP_const2u(16) OP_eq ASSERT_TOS_NON0				\
+OP_lit31 OP_const4u(31) OP_ne ASSERT_TOS_0				\
+OP_lit1 OP_neg OP_const1s(-1) OP_eq ASSERT_TOS_NON0			\
+OP_lit16 OP_neg OP_const2s(-16) OP_ne ASSERT_TOS_0			\
+OP_lit31 OP_const4s(-31) OP_neg OP_ne ASSERT_TOS_0			\
+OP_lit7 OP_dup OP_plus_uconst(2) OP_lit9 OP_eq ASSERT_TOS_NON0		\
+  OP_lit7 OP_eq ASSERT_TOS_NON0						\
+OP_lit20 OP_lit1 OP_drop OP_lit20 OP_eq ASSERT_TOS_NON0			\
+OP_lit17 OP_lit19 OP_over OP_lit17 OP_eq ASSERT_TOS_NON0		\
+  OP_lit19 OP_eq ASSERT_TOS_NON0 OP_lit17 OP_eq ASSERT_TOS_NON0		\
+OP_lit1 OP_lit2 OP_lit3 OP_lit4 OP_pick(2) OP_lit2 OP_eq ASSERT_TOS_NON0\
+  OP_lit4 OP_eq ASSERT_TOS_NON0 OP_lit3 OP_eq ASSERT_TOS_NON0		\
+  OP_pick(0) OP_lit2 OP_eq ASSERT_TOS_NON0				\
+  OP_lit2 OP_eq ASSERT_TOS_NON0 OP_lit1 OP_eq ASSERT_TOS_NON0		\
+OP_lit6 OP_lit12 OP_swap OP_lit6 OP_eq ASSERT_TOS_NON0			\
+  OP_lit12 OP_eq ASSERT_TOS_NON0					\
+OP_lit7 OP_lit8 OP_lit9 OP_rot OP_lit8 OP_eq ASSERT_TOS_NON0		\
+  OP_lit7 OP_eq ASSERT_TOS_NON0 OP_lit9 OP_eq ASSERT_TOS_NON0		\
+OP_lit7 OP_abs OP_lit7 OP_eq ASSERT_TOS_NON0				\
+OP_const1s(-123) OP_abs OP_const1u(123) OP_eq ASSERT_TOS_NON0		\
+OP_lit3 OP_lit6 OP_and OP_lit2 OP_eq ASSERT_TOS_NON0			\
+OP_lit3 OP_lit6 OP_or OP_lit7 OP_eq ASSERT_TOS_NON0			\
+OP_lit17 OP_lit2 OP_minus OP_lit15 OP_eq ASSERT_TOS_NON0		\
+/* Divide is signed truncating toward zero.  */				\
+OP_const1s(-6) OP_const1s(-2) OP_div OP_lit3 OP_eq ASSERT_TOS_NON0	\
+OP_const1s(-7) OP_const1s(3) OP_div OP_const1s(-2)			\
+  OP_eq ASSERT_TOS_NON0							\
+/* Modulo is unsigned.  */						\
+OP_const1s(-6) OP_const1s(-4) OP_mod OP_const1s(-6)			\
+  OP_eq ASSERT_TOS_NON0							\
+OP_const1s(-6) OP_lit4 OP_mod OP_lit2 OP_eq ASSERT_TOS_NON0		\
+OP_lit6 OP_const1s(-4) OP_mod OP_lit6 OP_eq ASSERT_TOS_NON0		\
+/* Signed modulo can be implemented using "over over div mul minus".  */\
+OP_const1s(-6) OP_const1s(-4) OP_over OP_over OP_div OP_mul OP_minus	\
+  OP_const1s(-2) OP_eq ASSERT_TOS_NON0					\
+OP_const1s(-7) OP_lit3 OP_over OP_over OP_div OP_mul OP_minus		\
+  OP_const1s(-1) OP_eq ASSERT_TOS_NON0					\
+OP_lit7 OP_const1s(-3) OP_over OP_over OP_div OP_mul OP_minus		\
+  OP_lit1 OP_eq ASSERT_TOS_NON0						\
+OP_lit16 OP_lit31 OP_plus_uconst(1) OP_mul OP_const2u(512)		\
+  OP_eq ASSERT_TOS_NON0							\
+OP_lit5 OP_not OP_lit31 OP_and OP_lit26 OP_eq ASSERT_TOS_NON0		\
+OP_lit12 OP_lit31 OP_plus OP_const1u(43) OP_eq ASSERT_TOS_NON0		\
+OP_const1s(-6) OP_lit2 OP_plus OP_const1s(-4) OP_eq ASSERT_TOS_NON0	\
+OP_const1s(-6) OP_plus_uconst(3) OP_const1s(-3) OP_eq ASSERT_TOS_NON0	\
+OP_lit16 OP_lit4 OP_shl OP_const2u(256) OP_eq ASSERT_TOS_NON0		\
+OP_lit16 OP_lit3 OP_shr OP_lit2 OP_eq ASSERT_TOS_NON0			\
+OP_const1s(-16) OP_lit3 OP_shra OP_const1s(-2) OP_eq ASSERT_TOS_NON0	\
+OP_lit3 OP_lit6 OP_xor OP_lit5 OP_eq ASSERT_TOS_NON0			\
+OP_lit3 OP_lit6 OP_le ASSERT_TOS_NON0					\
+OP_lit3 OP_lit3 OP_le ASSERT_TOS_NON0					\
+OP_lit6 OP_lit3 OP_le ASSERT_TOS_0					\
+OP_lit3 OP_lit6 OP_lt ASSERT_TOS_NON0					\
+OP_lit3 OP_lit3 OP_lt ASSERT_TOS_0					\
+OP_lit6 OP_lit3 OP_lt ASSERT_TOS_0					\
+OP_lit3 OP_lit6 OP_ge ASSERT_TOS_0					\
+OP_lit3 OP_lit3 OP_ge ASSERT_TOS_NON0					\
+OP_lit6 OP_lit3 OP_ge ASSERT_TOS_NON0					\
+OP_lit3 OP_lit6 OP_gt ASSERT_TOS_0					\
+OP_lit3 OP_lit3 OP_gt ASSERT_TOS_0					\
+OP_lit6 OP_lit3 OP_gt ASSERT_TOS_NON0					\
+OP_const1s(-6) OP_lit1 OP_shr OP_lit0 OP_gt ASSERT_TOS_NON0		\
+OP_const1s(-6) OP_lit1 OP_shra OP_lit0 OP_lt ASSERT_TOS_NON0
+
+#define CFI_ESCAPE_VAL_2(VALUES...) #VALUES
+#define CFI_ESCAPE_VAL_1(VALUES...) CFI_ESCAPE_VAL_2(VALUES)
+#define CFI_ESCAPE_VAL(VALUES...) CFI_ESCAPE_VAL_1(VALUES)
+#define CFI_ESCAPE do { } while (0)
+#define CFI_ARCH_PROGRAM OP_nop_termination
+#ifdef __GCC_HAVE_DWARF2_CFI_ASM
+#if defined (__x86_64__)
+#undef CFI_ESCAPE
+#undef CFI_ARCH_PROGRAM
+#define CFI_ARCH_PROGRAM CFI_PROGRAM OP_lit8 OP_minus OP_nop_termination
+unsigned char cfi_arch_program[] = { CFI_ARCH_PROGRAM };
+extern char verify_it[sizeof (cfi_arch_program) - 0x80 < 0x3f80 ? 1 : -1];
+/* DW_CFA_expression %rip, uleb128(l2-l1), l1: program DW_OP_lit8 DW_OP_minus DW_OP_nop l2: */
+#define CFI_ESCAPE \
+  asm volatile (".cfi_escape 0x10, 0x10, (%P0&0x7f)+0x80, %P0>>7, " \
+		CFI_ESCAPE_VAL (CFI_ARCH_PROGRAM) \
+		: : "i" (sizeof (cfi_arch_program)))
+#elif defined (__i386__)
+#undef CFI_ESCAPE
+#undef CFI_ARCH_PROGRAM
+#define CFI_ARCH_PROGRAM CFI_PROGRAM OP_lit4 OP_minus OP_nop_termination
+unsigned char cfi_arch_program[] = { CFI_ARCH_PROGRAM };
+extern char verify_it[sizeof (cfi_arch_program) - 0x80 < 0x3f80 ? 1 : -1];
+/* DW_CFA_expression %eip, uleb128(l2-l1), l1: program DW_OP_lit4 DW_OP_minus DW_OP_nop l2: */
+#define CFI_ESCAPE \
+  asm volatile (".cfi_escape 0x10, 8, (%P0&0x7f)+0x80, %P0>>7, " \
+		CFI_ESCAPE_VAL (CFI_ARCH_PROGRAM) \
+		: : "i" (sizeof (cfi_arch_program)))
+#endif
+#endif
+
+/* The original GCC testcase tests the runtime unwinder using
+   _Unwind_ForcedUnwind, we just inspect the child when it aborts.  */
+
+static void force_unwind ()
+{
+  abort ();
+}
+
+static void handler (void *p __attribute__((unused)))
+{
+  exit (0);
+}
+
+__attribute__((noinline)) static void callme ()
+{
+  CFI_ESCAPE;
+  force_unwind ();
+}
+
+__attribute__((noinline)) static void doit ()
+{
+  char dummy __attribute__((cleanup (handler)));
+  callme ();
+}
+
+int main()
+{ 
+  doit ();
+  abort ();
+}
diff --git a/tests/coverage.sh b/tests/coverage.sh
new file mode 100755
index 0000000..448d43b
--- /dev/null
+++ b/tests/coverage.sh
@@ -0,0 +1,40 @@
+#! /usr/bin/env bash
+
+if [ "x$1" = "x-v" ]; then
+  verbose=yes
+else
+  verbose=no
+fi
+
+cd ..
+
+for d in lib libasm libdw libdwfl libebl libelf backends src debuginfod; do
+  tmp=$d-data
+  cd $d
+  unused=0
+  unused_files=
+  for f in *.gcno; do
+    base="$(basename $f .gcno)"
+    if [ -f "$base.c" ]; then fc="$base.c"; else fc="$base.cxx"; fi
+    gcda="$base.gcda"
+    if [ -f "$gcda" ]; then
+      gcov -n -a "$fc" |
+      gawk "/$d.$fc/ { getline; co=gensub(/.*:(.*)% .*/, \"\\\\1\", \"g\"); co=co+0.0; li=\$4+0; printf \"%-35s  %6.2f %5d\n\", \"$d/$fc\", co, li } " >> $tmp
+    else
+      unused=$(($unused + 1))
+      unused_files="$unused_files $fc"
+    fi
+  done
+  if [ -f $tmp ]; then
+    gawk "{ copct=\$2; co=(\$3*copct)/100; toco+=(co+0); toli += (\$3+0); } END { printf \"%-12s %6.2f%% covered       unused files: %3d\n\", \"$d\", (toco*100)/toli, \"$unused\" }" $tmp
+    rm -f $tmp
+  else
+    printf "%-12s   0.00%% covered       unused files: %3d\n" "$d" $unused
+  fi
+  if [ $verbose = yes ]; then
+    for f in $unused_files; do
+      printf '%-42s%s\n' '' $f
+    done
+  fi
+  cd ..
+done
diff --git a/tests/cu-dwp-section-info.c b/tests/cu-dwp-section-info.c
new file mode 100644
index 0000000..f175697
--- /dev/null
+++ b/tests/cu-dwp-section-info.c
@@ -0,0 +1,73 @@
+/* Test program for dwarf_cu_dwp_section_info
+   Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; i++)
+    {
+      printf ("file: %s\n", argv[i]);
+      int fd = open (argv[i], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      Dwarf_CU *cu = NULL;
+      while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
+	{
+#define SECTION_INFO(section) do {					\
+	    printf (#section ": ");					\
+	    Dwarf_Off offset, size;					\
+	    if (dwarf_cu_dwp_section_info (cu, DW_SECT_##section,	\
+					   &offset, &size) == 0)	\
+	      printf ("0x%" PRIx64 " 0x%" PRIx64 "\n", offset, size);	\
+	    else							\
+	      printf ("%s\n", dwarf_errmsg (-1));			\
+	  } while (0)
+	  SECTION_INFO (INFO);
+	  SECTION_INFO (TYPES);
+	  SECTION_INFO (ABBREV);
+	  SECTION_INFO (LINE);
+	  SECTION_INFO (LOCLISTS);
+	  SECTION_INFO (STR_OFFSETS);
+	  SECTION_INFO (MACRO);
+	  SECTION_INFO (RNGLISTS);
+	  printf ("\n");
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/debug-ranges-no-lowpc.o.bz2 b/tests/debug-ranges-no-lowpc.o.bz2
new file mode 100644
index 0000000..871a3fb
--- /dev/null
+++ b/tests/debug-ranges-no-lowpc.o.bz2
Binary files differ
diff --git a/tests/debug-ranges-no-lowpc.s b/tests/debug-ranges-no-lowpc.s
new file mode 100644
index 0000000..879bce2
--- /dev/null
+++ b/tests/debug-ranges-no-lowpc.s
@@ -0,0 +1,49 @@
+        .section .debug_info
+.Lcu1_begin:
+        .4byte        .Lcu1_end - .Lcu1_start
+.Lcu1_start:
+        .2byte        3                 /* Version */
+        .4byte        .Labbrev1_begin   /* Abbrevs */
+        .byte        8                  /* Pointer size */
+        .uleb128        2               /* Abbrev (DW_TAG_compile_unit) */
+        .4byte        0
+.Lcu1_end:
+        .section .note.gnu.build-id, "a", %note
+        .4byte        4
+        .4byte        8
+        .4byte        3
+        .ascii        "GNU\0"
+        .byte        0x01
+        .byte        0x02
+        .byte        0x03
+        .byte        0x04
+        .byte        0x05
+        .byte        0x06
+        .byte        0x07
+        .byte        0x08
+        .section .debug_abbrev
+.Labbrev1_begin:
+        .uleb128        2               /* Abbrev start */
+        .uleb128        0x11            /* DW_TAG_compile_unit */
+        .byte        0                  /* has_children */
+        .uleb128        0x55            /* DW_AT_ranges */
+        .uleb128        0x06            /* DW_FORM_data4 */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+
+	.section .debug_ranges
+
+	.8byte 0xffffffffffffffff
+	.8byte 0
+
+	.8byte 1
+	.8byte 2
+
+	.8byte 3
+	.8byte 4
+
+	.8byte 0
+	.8byte 0
+
diff --git a/tests/debugaltlink.c b/tests/debugaltlink.c
new file mode 100644
index 0000000..e7dc862
--- /dev/null
+++ b/tests/debugaltlink.c
@@ -0,0 +1,83 @@
+/* Test program for dwelf_dwarf_gnu_debugaltlink, print name and build ID.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <err.h>
+#include <errno.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwelf)
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "system.h"
+
+int
+main (int argc, char *argv[])
+{
+  if (argc < 2)
+    error (EXIT_FAILURE, 0, "No input file given");
+
+  elf_version (EV_CURRENT);
+
+  for (int i = 1; i < argc; i++)
+    {
+      const char *file = argv[i];
+      int fd = open (file, O_RDONLY);
+      if (fd < 0)
+	error (EXIT_FAILURE, errno, "couldn't open file '%s'", file);
+
+      Dwarf *dwarf = dwarf_begin (fd, DWARF_C_READ);
+      if (dwarf == NULL)
+	{
+	  printf("%s: dwarf_begin failed: %s\n", file, dwarf_errmsg (-1));
+	  close (fd);
+	  continue;
+	}
+
+      const char *name;
+      const void *build_id;
+      ssize_t ret = dwelf_dwarf_gnu_debugaltlink
+	(dwarf, &name, &build_id);
+      switch (ret)
+	{
+	case 0:
+	  printf ("%s: <no .gnu_debugaltlink section>\n", file);
+	  break;
+	case -1:
+	  errx (1, "dwelf_dwarf_gnu_debugaltlink (%s): %s",
+		file, dwarf_errmsg (-1));
+	default:
+	  printf ("%s: %s, build ID: ", file, name);
+	  const unsigned char *p = build_id;
+	  const unsigned char *end = p + ret;
+	  while (p < end)
+	      printf("%02x", (unsigned)*p++);
+	  putchar('\n');
+	}
+
+      dwarf_end (dwarf);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/debuginfod-debs/hithere-dbgsym_1.0-1_amd64.ddeb b/tests/debuginfod-debs/hithere-dbgsym_1.0-1_amd64.ddeb
new file mode 100644
index 0000000..f9879eb
--- /dev/null
+++ b/tests/debuginfod-debs/hithere-dbgsym_1.0-1_amd64.ddeb
Binary files differ
diff --git a/tests/debuginfod-debs/hithere_1.0-1.debian.tar.xz b/tests/debuginfod-debs/hithere_1.0-1.debian.tar.xz
new file mode 100644
index 0000000..9f0ce68
--- /dev/null
+++ b/tests/debuginfod-debs/hithere_1.0-1.debian.tar.xz
Binary files differ
diff --git a/tests/debuginfod-debs/hithere_1.0-1.dsc b/tests/debuginfod-debs/hithere_1.0-1.dsc
new file mode 100644
index 0000000..d5f72b9
--- /dev/null
+++ b/tests/debuginfod-debs/hithere_1.0-1.dsc
@@ -0,0 +1,19 @@
+Format: 3.0 (quilt)
+Source: hithere
+Binary: hithere
+Architecture: any
+Version: 1.0-1
+Maintainer: Lars Wirzenius <liw@liw.fi>
+Standards-Version: 3.9.2
+Build-Depends: debhelper (>= 9)
+Package-List:
+ hithere deb misc optional arch=any
+Checksums-Sha1:
+ 2dcd65497a12a3ea03223f52186447bd5733dce9 617 hithere_1.0.orig.tar.gz
+ 0b71331ef1c714c5bac67878551864b7356c56ce 764 hithere_1.0-1.debian.tar.xz
+Checksums-Sha256:
+ 63062b582a712f169f37a5f52a41aa3ca9a405aafb8aa837bc906fa413b62cdb 617 hithere_1.0.orig.tar.gz
+ 9afa907e360e626639ccb86b86e799429bea27149034aec5d5c7e500971d651e 764 hithere_1.0-1.debian.tar.xz
+Files:
+ 5b2830fa1fcd44ce489774771625526e 617 hithere_1.0.orig.tar.gz
+ 70106164d9397c70c2c1a4594e9897e4 764 hithere_1.0-1.debian.tar.xz
diff --git a/tests/debuginfod-debs/hithere_1.0-1_amd64.deb b/tests/debuginfod-debs/hithere_1.0-1_amd64.deb
new file mode 100644
index 0000000..11d1e95
--- /dev/null
+++ b/tests/debuginfod-debs/hithere_1.0-1_amd64.deb
Binary files differ
diff --git a/tests/debuginfod-debs/hithere_1.0.orig.tar.gz b/tests/debuginfod-debs/hithere_1.0.orig.tar.gz
new file mode 100644
index 0000000..23abea7
--- /dev/null
+++ b/tests/debuginfod-debs/hithere_1.0.orig.tar.gz
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm b/tests/debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm
new file mode 100644
index 0000000..29a6099
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora30/hello2-1.0-2.src.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..2757e01
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora30/hello2-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..dc6e0f2
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora30/hello2-debuginfo-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora30/hello2-debugsource-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora30/hello2-debugsource-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..f036fa3
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora30/hello2-debugsource-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora30/hello2-two-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora30/hello2-two-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..e1c09da
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora30/hello2-two-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora30/hello2-two-debuginfo-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora30/hello2-two-debuginfo-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..b9a63df
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora30/hello2-two-debuginfo-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm b/tests/debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm
new file mode 100644
index 0000000..d0b3454
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora31/hello3-1.0-2.src.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..8b2fe9b
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora31/hello3-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..ee479ec
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora31/hello3-debuginfo-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..890478e
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora31/hello3-debugsource-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..73fd939
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora31/hello3-two-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..0cc2407
--- /dev/null
+++ b/tests/debuginfod-rpms/fedora31/hello3-two-debuginfo-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/hello2.specfile b/tests/debuginfod-rpms/hello2.specfile
new file mode 100644
index 0000000..0690992
--- /dev/null
+++ b/tests/debuginfod-rpms/hello2.specfile
@@ -0,0 +1,57 @@
+Summary: hello2 -- double hello, world rpm
+Name: hello2
+Version: 1.0
+Release: 2
+Group: Utilities
+License: GPL
+Distribution: RPM ^W Elfutils test suite.
+Vendor: Red Hat Software
+Packager: Red Hat Software <bugs@redhat.com>
+URL: http://www.redhat.com
+BuildRequires: gcc make
+Source0: hello-1.0.tar.gz
+
+%description
+Simple rpm demonstration with an eye to consumption by debuginfod.
+
+%package two
+Summary: hello2two
+License: GPL
+
+%description two
+Dittoish.
+
+%prep
+%setup -q -n hello-1.0
+
+%build
+gcc -g -O1 hello.c -o hello
+gcc -g -O2 -D_FORTIFY_SOURCE=2 hello.c -o hello2
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/local/bin
+cp hello $RPM_BUILD_ROOT/usr/local/bin/
+cp hello2 $RPM_BUILD_ROOT/usr/local/bin/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files 
+%defattr(-,root,root)
+%attr(0751,root,root)   /usr/local/bin/hello
+
+%files two
+%defattr(-,root,root)
+%attr(0751,root,root)   /usr/local/bin/hello2
+
+%changelog
+* Thu Nov 14 2019 Frank Ch. Eigler <fche@redhat.com>
+- Added source code right here to make spec file self-contained.
+- Dropped misc files not relevant to debuginfod testing.
+
+* Wed May 18 2016 Mark Wielaard <mjw@redhat.com>
+- Add hello2 for dwz testing support.
+
+* Tue Oct 20 1998 Jeff Johnson <jbj@redhat.com>
+- create.
diff --git a/tests/debuginfod-rpms/hello3.specfile b/tests/debuginfod-rpms/hello3.specfile
new file mode 100644
index 0000000..ffb9513
--- /dev/null
+++ b/tests/debuginfod-rpms/hello3.specfile
@@ -0,0 +1,60 @@
+Summary: hello3 -- double hello, world rpm
+Name: hello3
+Version: 1.0
+Release: 2
+Group: Utilities
+License: GPL
+Distribution: RPM ^W Elfutils test suite.
+Vendor: Red Hat Software
+Packager: Red Hat Software <bugs@redhat.com>
+URL: http://www.redhat.com
+BuildRequires: gcc make
+Source0: hello-1.0.tar.gz
+
+%description
+Simple rpm demonstration with an eye to consumption by debuginfod.
+
+%package two
+Summary: hello3two
+License: GPL
+
+%description two
+Dittoish.
+
+%prep
+%setup -q -n hello-1.0
+
+%build
+mkdir foobar
+gcc -g -O1 foobar///./../hello.c -o hello
+gcc -g -O2 -D_FORTIFY_SOURCE=2 foobar///./../hello.c -o hello3
+
+%install
+rm -rf $RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/usr/local/bin
+cp hello $RPM_BUILD_ROOT/usr/local/bin/
+cp hello3 $RPM_BUILD_ROOT/usr/local/bin/
+
+%clean
+rm -rf $RPM_BUILD_ROOT
+
+%files 
+%defattr(-,root,root)
+%attr(0751,root,root)   /usr/local/bin/hello
+
+%files two
+%defattr(-,root,root)
+%attr(0751,root,root)   /usr/local/bin/hello3
+
+%changelog
+* Tue Mar 24 2020 Frank Ch. Eigler <fche@redhat.com>
+- New variant of hello2, with crazy source file paths
+
+* Thu Nov 14 2019 Frank Ch. Eigler <fche@redhat.com>
+- Dropped misc files not relevant to debuginfod testing.
+
+* Wed May 18 2016 Mark Wielaard <mjw@redhat.com>
+- Add hello2 for dwz testing support.
+
+* Tue Oct 20 1998 Jeff Johnson <jbj@redhat.com>
+- create.
diff --git a/tests/debuginfod-rpms/rhel6/hello2-1.0-2.i686.rpm b/tests/debuginfod-rpms/rhel6/hello2-1.0-2.i686.rpm
new file mode 100644
index 0000000..cb99fd6
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel6/hello2-1.0-2.i686.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel6/hello2-1.0-2.src.rpm b/tests/debuginfod-rpms/rhel6/hello2-1.0-2.src.rpm
new file mode 100644
index 0000000..603a9b1
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel6/hello2-1.0-2.src.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel6/hello2-debuginfo-1.0-2.i686.rpm b/tests/debuginfod-rpms/rhel6/hello2-debuginfo-1.0-2.i686.rpm
new file mode 100644
index 0000000..19f4360
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel6/hello2-debuginfo-1.0-2.i686.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel6/hello2-two-1.0-2.i686.rpm b/tests/debuginfod-rpms/rhel6/hello2-two-1.0-2.i686.rpm
new file mode 100644
index 0000000..58c77a1
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel6/hello2-two-1.0-2.i686.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel7/hello2-1.0-2.src.rpm b/tests/debuginfod-rpms/rhel7/hello2-1.0-2.src.rpm
new file mode 100644
index 0000000..5ca4d42
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel7/hello2-1.0-2.src.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel7/hello2-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/rhel7/hello2-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..0e6f6cc
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel7/hello2-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel7/hello2-debuginfo-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/rhel7/hello2-debuginfo-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..c1136f3
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel7/hello2-debuginfo-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm b/tests/debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm
new file mode 100644
index 0000000..5e89afd
--- /dev/null
+++ b/tests/debuginfod-rpms/rhel7/hello2-two-1.0-2.x86_64.rpm
Binary files differ
diff --git a/tests/debuginfod-subr.sh b/tests/debuginfod-subr.sh
new file mode 100755
index 0000000..c3b0603
--- /dev/null
+++ b/tests/debuginfod-subr.sh
@@ -0,0 +1,180 @@
+# Copyright (C) 2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# sourced from run-debuginfod-*.sh tests (must be bash scripts)
+
+# We trap ERR and like commands that fail in function to also trap
+set -o functrace
+set -o errtrace
+
+. $srcdir/test-subr.sh  # includes set -e
+
+type curl 2>/dev/null || (echo "need curl"; exit 77)
+type rpm2cpio 2>/dev/null || (echo "need rpm2cpio"; exit 77)
+type cpio 2>/dev/null || (echo "need cpio"; exit 77)
+type bzcat 2>/dev/null || (echo "need bzcat"; exit 77)
+bsdtar --version | grep -q zstd && zstd=true || zstd=false
+echo "zstd=$zstd bsdtar=`bsdtar --version`"
+
+cleanup()
+{
+  # No more cleanups after this cleanup
+  trap - 0
+
+  if [ $PID1 -ne 0 ]; then kill $PID1 || : ; wait $PID1 || :; fi
+  if [ $PID2 -ne 0 ]; then kill $PID2 || : ; wait $PID2 || :; fi
+  rm -rf F R D L Z ${PWD}/foobar ${PWD}/mocktree ${PWD}/.client_cache* ${PWD}/tmp*
+  exit_cleanup
+}
+
+# clean up trash if we exit
+trap cleanup 0
+
+errfiles_list=
+err() {
+    # Don't trap any new errors from now on
+    trap - ERR
+
+    echo ERROR REPORTS
+    for port in $PORT1 $PORT2
+    do
+        echo ERROR REPORT $port metrics
+        curl -s http://127.0.0.1:$port/metrics || :
+        echo
+    done
+    for x in $errfiles_list
+    do
+        echo ERROR REPORT "$x"
+        cat $x
+        echo
+    done
+    cleanup
+    false # trigger set -e
+}
+trap err ERR
+
+errfiles() {
+    errfiles_list="$errfiles_list $*"
+}
+
+# We want to run debuginfod in the background.  We also want to start
+# it with the same check/installcheck-sensitive LD_LIBRARY_PATH stuff
+# that the testrun alias sets.  But: we if we just use
+#    testrun .../debuginfod
+# it runs in a subshell, with different pid, so not helpful.
+#
+# So we gather the LD_LIBRARY_PATH with this cunning trick:
+ldpath=`testrun sh -c 'echo $LD_LIBRARY_PATH'`
+
+wait_ready4()
+{
+  port=$1;
+  what=$2;
+  value=$3;
+  timeout=$4;
+
+  echo "Wait $timeout seconds on $port for metric $what to change to $value"
+  while [ $timeout -gt 0 ]; do
+    mvalue="$(curl -s http://127.0.0.1:$port/metrics \
+              | grep "$what" | awk '{print $NF}')"
+    if [ -z "$mvalue" ]; then mvalue=0; fi
+      echo "metric $what: $mvalue"
+      if [ "$mvalue" -eq "$value" ]; then
+        break;
+    fi
+    sleep 0.5;
+    ((timeout--));
+  done;
+
+  if [ $timeout -eq 0 ]; then
+    echo "metric $what never changed to $value on port $port"
+    err
+  fi
+}
+
+wait_ready()
+{
+  port=$1;
+  what=$2;
+  value=$3;
+  timeout=20;
+  wait_ready4 "$port" "$what" "$value" "$timeout"
+}
+
+
+archive_test() {
+    __BUILDID=$1
+    __SOURCEPATH=$2
+    __SOURCESHA1=$3
+
+    filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $__BUILDID`
+    buildid=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+             -a $filename | grep 'Build ID' | cut -d ' ' -f 7`
+    test $__BUILDID = $buildid
+    # check that timestamps are plausible - older than the near-present (tmpdir mtime)
+    test $filename -ot `pwd`
+
+    # run again to assure that fdcache is being enjoyed
+    filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $__BUILDID`
+    buildid=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+             -a $filename | grep 'Build ID' | cut -d ' ' -f 7`
+    test $__BUILDID = $buildid
+    test $filename -ot `pwd`
+
+    filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $__BUILDID`
+    buildid=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+             -a $filename | grep 'Build ID' | cut -d ' ' -f 7`
+    test $__BUILDID = $buildid
+    test $filename -ot `pwd`
+
+    if test "x$__SOURCEPATH" != "x"; then
+        filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $__BUILDID $__SOURCEPATH`
+        hash=`cat $filename | sha1sum | awk '{print $1}'`
+        test $__SOURCESHA1 = $hash
+        test $filename -ot `pwd`
+    fi
+}
+
+get_ports() {
+  while true; do
+    PORT1=`expr '(' $RANDOM % 50 ')' + $base`
+    ss -atn | grep -F ":$PORT1" || break
+  done
+# Some tests will use two servers, so assign the second var
+  while true; do
+    PORT2=`expr '(' $RANDOM % 50 ')' + $base + 50`
+    ss -atn | grep -F ":$PORT2" || break
+  done
+
+}
+
+VERBOSE=-vvv
+# We gather the LD_LIBRARY_PATH with this cunning trick:
+ldpath=`testrun sh -c 'echo $LD_LIBRARY_PATH'`
+PORT1=0
+PORT2=0
+PID1=0
+PID2=0
+
+
+# run $1 as a sh -c command, invert result code
+xfail() {
+    if sh -c "$1"; then
+        false
+    else
+        true
+    fi
+}
diff --git a/tests/debuginfod-tars/hello-1-1-x86_64.pkg.tar.xz b/tests/debuginfod-tars/hello-1-1-x86_64.pkg.tar.xz
new file mode 100644
index 0000000..fd78433
--- /dev/null
+++ b/tests/debuginfod-tars/hello-1-1-x86_64.pkg.tar.xz
Binary files differ
diff --git a/tests/debuginfod-tars/hello-debug-1-1-x86_64.pkg.tar.bz2 b/tests/debuginfod-tars/hello-debug-1-1-x86_64.pkg.tar.bz2
new file mode 100644
index 0000000..8701861
--- /dev/null
+++ b/tests/debuginfod-tars/hello-debug-1-1-x86_64.pkg.tar.bz2
Binary files differ
diff --git a/tests/debuginfod-tars/pacman-sources/PKGBUILD b/tests/debuginfod-tars/pacman-sources/PKGBUILD
new file mode 100644
index 0000000..0cac170
--- /dev/null
+++ b/tests/debuginfod-tars/pacman-sources/PKGBUILD
@@ -0,0 +1,19 @@
+pkgname=hello
+pkgver=1
+pkgrel=1
+pkgdesc="Simple hello world program to exercise debuginfod"
+arch=('x86_64')
+source=('hello.c')
+sha256sums=('f85badd2007451bbda4791e7fe820b41be0a424172a567573511688bff975235')
+
+# guarantee that split debug packages are turned on
+options=('strip' 'debug')
+
+build() {
+    # implicit Makefile
+    make hello
+}
+
+package() {
+    install -Dm755 hello "${pkgdir}"/usr/bin/hello
+}
diff --git a/tests/debuginfod-tars/pacman-sources/README.md b/tests/debuginfod-tars/pacman-sources/README.md
new file mode 100644
index 0000000..17f59bc
--- /dev/null
+++ b/tests/debuginfod-tars/pacman-sources/README.md
@@ -0,0 +1,19 @@
+# Creating sample pacman packages
+
+You will need:
+- an archlinux installation
+- `pacman -S base-devel` for basic build requirements (like debian "build-essential")
+
+Run `makepkg` inside this directory to produce *.pkg.tar.* archives. This may
+be .xz, .zst, .gz etc. depending on the current defaults, see makepkg.conf(5)
+"PKGEXT" for details. The archives will appear in the current directory, or the
+"PKGDEST" defined by makepkg.conf(5).
+
+# Byte-for-byte reproduction
+
+You will need:
+- an archlinux installation
+- `pacman -S devtools` for the clean chroot builder/reproducer
+
+Run `makerepropkg /path/to/hello-debug-1-1-x86_64.pkg.tar.xz` (or whichever the
+archive filename is) inside this directory.
diff --git a/tests/debuginfod-tars/pacman-sources/hello.c b/tests/debuginfod-tars/pacman-sources/hello.c
new file mode 100644
index 0000000..c1ef155
--- /dev/null
+++ b/tests/debuginfod-tars/pacman-sources/hello.c
@@ -0,0 +1,6 @@
+#include <stdio.h>
+
+int main() {
+    printf("hello\n");
+    return 0;
+}
diff --git a/tests/debuginfod_build_id_find.c b/tests/debuginfod_build_id_find.c
new file mode 100644
index 0000000..753a20c
--- /dev/null
+++ b/tests/debuginfod_build_id_find.c
@@ -0,0 +1,62 @@
+/* Test program for fetching debuginfo with debuginfo-server.
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdio.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <elf.h>
+#include <dwarf.h>
+#include <argp.h>
+#include <assert.h>
+#include <string.h>
+
+static const char *debuginfo_path = "";
+static const Dwfl_Callbacks cb  =
+  {
+    NULL,
+    dwfl_standard_find_debuginfo,
+    NULL,
+    (char **)&debuginfo_path,
+  };
+
+int
+main (int argc __attribute__ ((unused)), char **argv)
+{
+  int expect_pass = strcmp(argv[3], "0");
+  Dwarf_Addr bias = 0;
+  Dwfl *dwfl = dwfl_begin(&cb);
+  dwfl_report_begin(dwfl);
+
+  /* Open an executable.  */
+  Dwfl_Module *mod = dwfl_report_offline(dwfl, argv[2], argv[2], -1);
+
+  /* The corresponding debuginfo will not be found in debuginfo_path
+     (since it's empty), causing the server to be queried.  */
+
+  Dwarf *res = dwfl_module_getdwarf(mod, &bias);
+  if (expect_pass)
+    assert(res);
+  else
+    assert(!res);
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/debuglink.c b/tests/debuglink.c
new file mode 100644
index 0000000..f92b9b5
--- /dev/null
+++ b/tests/debuglink.c
@@ -0,0 +1,64 @@
+/* Test program for dwelf_elf_gnu_debuglink, print name and crc.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <errno.h>
+#include ELFUTILS_HEADER(dwelf)
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "system.h"
+
+int
+main (int argc, char *argv[])
+{
+  if (argc < 2)
+    error (EXIT_FAILURE, 0, "No input file given");
+
+  elf_version (EV_CURRENT);
+
+  for (int i = 1; i < argc; i++)
+    {
+      const char *file = argv[i];
+      int fd = open (file, O_RDONLY);
+      if (fd < 0)
+	error (EXIT_FAILURE, errno, "couldn't open file '%s'", file);
+
+      Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+      if (elf == NULL)
+	error (EXIT_FAILURE, 0, "elf_begin failed for '%s': %s",
+	       file, elf_errmsg (-1));
+
+      GElf_Word crc;
+      const char *debug = dwelf_elf_gnu_debuglink (elf, &crc);
+      if (debug == NULL)
+	printf ("%s: <no gnu_debuglink file>\n", file);
+      else
+	printf ("%s: %s, crc: %" PRIx32 "\n", file, debug, crc);
+
+      elf_end (elf);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/declfiles.c b/tests/declfiles.c
new file mode 100644
index 0000000..0842d63
--- /dev/null
+++ b/tests/declfiles.c
@@ -0,0 +1,90 @@
+/* Test program for dwarf_decl_file
+   Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+
+static void
+walk_tree (Dwarf_Die *dwarf_die, int indent)
+{
+  Dwarf_Die die = *dwarf_die;
+  do
+    {
+      int child_indent = indent;
+      const char *file = dwarf_decl_file (&die);
+      if (file != NULL)
+	{
+	  printf("%*s", indent, "");
+	  const char *name = dwarf_diename (&die) ?: "???";
+	  int line, column;
+	  if (dwarf_decl_line (&die, &line) == 0)
+	    {
+	      if (dwarf_decl_column (&die, &column) == 0)
+		printf ("%s@%s:%d:%d\n", name, file, line, column);
+	      else
+		printf ("%s@%s:%d\n", name, file, line);
+	    }
+	  else
+	    printf ("%s@%s\n", name, file);
+	  child_indent++;
+	}
+
+      Dwarf_Die child;
+      if (dwarf_child (&die, &child) == 0)
+	walk_tree (&child, child_indent);
+    }
+  while (dwarf_siblingof (&die, &die) == 0);
+}
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; i++)
+    {
+      printf ("file: %s\n", argv[i]);
+      int fd = open (argv[i], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      Dwarf_CU *cu = NULL;
+      Dwarf_Die cudie, subdie;
+      uint8_t unit_type;
+      while (dwarf_get_units (dbg, cu, &cu, NULL, &unit_type, &cudie, &subdie)
+	     == 0)
+	{
+	  Dwarf_Die *die = unit_type == DW_UT_skeleton ? &subdie : &cudie;
+	  printf (" cu: %s\n", dwarf_diename (die) ?: "???");
+	  walk_tree (die, 2);
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/deleted-lib.c b/tests/deleted-lib.c
new file mode 100644
index 0000000..1ff411b
--- /dev/null
+++ b/tests/deleted-lib.c
@@ -0,0 +1,27 @@
+/* Test program for opening already deleted running binaries.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <unistd.h>
+
+void
+libfunc (void)
+{
+  sleep (60000);
+  /* Avoid tail call optimization for the sleep call.  */
+  asm volatile ("");
+}
diff --git a/tests/deleted.c b/tests/deleted.c
new file mode 100644
index 0000000..f4e8f76
--- /dev/null
+++ b/tests/deleted.c
@@ -0,0 +1,57 @@
+/* Test program for opening already deleted running binaries.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+#include <stdio.h>
+#include <errno.h>
+#ifdef __linux__
+#include <sys/prctl.h>
+#endif
+
+extern void libfunc (void);
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  pid_t pid = fork ();
+  assert (pid != -1);
+  if (pid == 0)
+    {
+      int err = close (0);
+      assert (!err);
+      err = close (1);
+      assert (!err);
+      err = close (2);
+      assert (!err);
+      /* Make sure eu-stack -p works on this process even with
+	 "restricted ptrace".  */
+#ifdef PR_SET_PTRACER_ANY
+      prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY, 0, 0, 0);
+#endif
+      libfunc ();
+      abort ();
+    }
+  printf ("%d\n", pid);
+  return EXIT_SUCCESS;
+}
diff --git a/tests/dwarf-die-addr-die.c b/tests/dwarf-die-addr-die.c
new file mode 100644
index 0000000..24bfbeb
--- /dev/null
+++ b/tests/dwarf-die-addr-die.c
@@ -0,0 +1,186 @@
+/* Test program for dwarf_die_addr_die.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+/* The main Dwarf file.  */
+static Dwarf *dwarf;
+
+int
+check_die (Dwarf_Die *die)
+{
+  if (dwarf_tag (die) == DW_TAG_invalid)
+    {
+      printf ("Invalid die\n");
+      return -1;
+    }
+
+  int res = 0;
+  void *addr = die->addr;
+  Dwarf_Die die2;
+  if (dwarf_die_addr_die (dwarf, addr, &die2) == NULL)
+    {
+      printf ("Bad die addr die at offset %" PRIx64 "\n",
+	      dwarf_dieoffset (die));
+      res = -1;
+    }
+
+  if (dwarf_tag (die) != dwarf_tag (&die2))
+    {
+      printf ("Tags differ for die at offset %" PRIx64 "\n",
+	      dwarf_dieoffset (die));
+      res = -1;
+    }
+
+  if (dwarf_cuoffset (die) != dwarf_cuoffset (&die2))
+    {
+      printf ("CU offsets differ for die at offset %" PRIx64 "\n",
+	      dwarf_dieoffset (die));
+      res = -1;
+    }
+
+  Dwarf_Die child;
+  if (dwarf_child (die, &child) == 0)
+    res |= check_die (&child);
+
+  Dwarf_Die sibling;
+  if (dwarf_siblingof (die, &sibling) == 0)
+    res |= check_die (&sibling);
+
+  return res;
+}
+
+int
+check_dbg (Dwarf *dbg)
+{
+  int res = 0;
+  Dwarf_Off off = 0;
+  Dwarf_Off old_off = 0;
+  size_t hsize;
+  Dwarf_Off abbrev;
+  uint8_t addresssize;
+  uint8_t offsetsize;
+  while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize,
+                       &offsetsize) == 0)
+    {
+      Dwarf_Die die;
+      if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL)
+	{
+	  printf ("checking CU at %" PRIx64 "\n", old_off);
+	  res |= check_die (&die);
+	}
+
+      old_off = off;
+    }
+
+  // Same for type...
+  Dwarf_Half version;
+  uint64_t typesig;
+  Dwarf_Off typeoff;
+  off = 0;
+  old_off = 0;
+  while (dwarf_next_unit (dbg, off, &off, &hsize, &version, &abbrev,
+			  &addresssize, &offsetsize, &typesig, &typeoff) == 0)
+    {
+      Dwarf_Die die;
+      if (dwarf_offdie_types (dbg, old_off + hsize, &die) != NULL)
+	{
+	  printf ("checking TU at %" PRIx64 "\n", old_off);
+	  res |= check_die (&die);
+	}
+
+      // We should have seen this already, but double check...
+      if (dwarf_offdie_types (dbg, old_off + typeoff, &die) != NULL)
+	{
+	  printf ("checking Type DIE at %" PRIx64 "\n",
+		  old_off + hsize + typeoff);
+	  res |= check_die (&die);
+	}
+
+      old_off = off;
+    }
+
+  Dwarf *alt = dwarf_getalt (dbg);
+  if (alt != NULL)
+    {
+      printf ("checking alt debug\n");
+      res |= check_dbg (alt);
+    }
+
+  // Split or Type Dwarf_Dies gotten through dwarf_get_units.
+  Dwarf_CU *cu = NULL;
+  Dwarf_Die subdie;
+  uint8_t unit_type;
+  while (dwarf_get_units (dbg, cu, &cu, NULL,
+                          &unit_type, NULL, &subdie) == 0)
+    {
+      if (dwarf_tag (&subdie) != DW_TAG_invalid)
+        {
+	  printf ("checking %" PRIx8 " subdie\n", unit_type);
+	  res |= check_die (&subdie);
+	}
+    }
+
+  return res;
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc < 2)
+    {
+      printf ("No file given.\n");
+      return -1;
+    }
+
+  const char *name = argv[1];
+  int fd = open (name, O_RDONLY);
+  if (fd < 0)
+    {
+      printf ("Cannot open '%s': %s\n", name, strerror (errno));
+      return -1;
+    }
+
+  dwarf = dwarf_begin (fd, DWARF_C_READ);
+  if (dwarf == NULL)
+    {
+      printf ("Not a Dwarf file '%s': %s\n", name, dwarf_errmsg (-1));
+      close (fd);
+      return -1;
+    }
+
+  printf ("checking %s\n", name);
+  int res = check_dbg (dwarf);
+
+  dwarf_end (dwarf);
+  close (fd);
+
+  return res;
+}
diff --git a/tests/dwarf-getmacros.c b/tests/dwarf-getmacros.c
new file mode 100644
index 0000000..8381d42
--- /dev/null
+++ b/tests/dwarf-getmacros.c
@@ -0,0 +1,179 @@
+/* Test program for dwarf_getmacros and related
+   Copyright (C) 2009, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+
+static void include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token);
+
+static int
+mac (Dwarf_Macro *macro, void *dbg)
+{
+  static int level = 0;
+
+  unsigned int opcode;
+  dwarf_macro_opcode (macro, &opcode);
+  switch (opcode)
+    {
+    case DW_MACRO_import:
+      {
+	Dwarf_Attribute at;
+	int r = dwarf_macro_param (macro, 0, &at);
+	assert (r == 0);
+
+	Dwarf_Word w;
+	r = dwarf_formudata (&at, &w);
+	assert (r == 0);
+
+	printf ("%*sinclude %#" PRIx64 "\n", level, "", w);
+	++level;
+	include (dbg, w, DWARF_GETMACROS_START);
+	--level;
+	printf ("%*s/include\n", level, "");
+	break;
+      }
+
+    case DW_MACRO_start_file:
+      {
+	Dwarf_Files *files;
+	size_t nfiles;
+	if (dwarf_macro_getsrcfiles (dbg, macro, &files, &nfiles) < 0)
+	  printf ("dwarf_macro_getsrcfiles: %s\n",
+		  dwarf_errmsg (dwarf_errno ()));
+
+	Dwarf_Word w = 0;
+	dwarf_macro_param2 (macro, &w, NULL);
+
+	const char *name = dwarf_filesrc (files, (size_t) w, NULL, NULL);
+	printf ("%*sfile %s\n", level, "", name);
+	++level;
+	break;
+      }
+
+    case DW_MACRO_end_file:
+      {
+	--level;
+	printf ("%*s/file\n", level, "");
+	break;
+      }
+
+    case DW_MACINFO_define:
+    case DW_MACRO_define_strp:
+    case DW_MACRO_define_sup:
+    case DW_MACRO_define_strx:
+      {
+	const char *value;
+	dwarf_macro_param2 (macro, NULL, &value);
+	printf ("%*s%s\n", level, "", value);
+	break;
+      }
+
+    case DW_MACINFO_undef:
+    case DW_MACRO_undef_strp:
+    case DW_MACRO_undef_sup:
+    case DW_MACRO_undef_strx:
+      break;
+
+    default:
+      {
+	size_t paramcnt;
+	dwarf_macro_getparamcnt (macro, &paramcnt);
+	printf ("%*sopcode %u with %zd arguments\n",
+		level, "", opcode, paramcnt);
+	break;
+      }
+    }
+
+  return DWARF_CB_ABORT;
+}
+
+static void
+include (Dwarf *dbg, Dwarf_Off macoff, ptrdiff_t token)
+{
+  while ((token = dwarf_getmacros_off (dbg, macoff, mac, dbg, token)) != 0)
+    if (token == -1)
+      {
+	puts (dwarf_errmsg (dwarf_errno ()));
+	break;
+      }
+}
+
+static void
+getmacros (Dwarf *dbg, Dwarf_Die *die, bool new_style)
+{
+  for (ptrdiff_t off = new_style ? DWARF_GETMACROS_START : 0;
+       (off = dwarf_getmacros (die, mac, dbg, off)); )
+    if (off == -1)
+      {
+	puts (dwarf_errmsg (-1));
+	break;
+      }
+}
+
+int
+main (int argc, char *argv[])
+{
+  assert (argc >= 3);
+  const char *name = argv[1];
+  bool new_style = argc > 3;
+
+  int fd = open (name, O_RDONLY);
+  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+
+  if (argv[2][0] == '\0')
+    {
+      Dwarf_CU *cu = NULL;
+      Dwarf_Die cudie, subdie;
+      uint8_t unit_type;
+      while (dwarf_get_units (dbg, cu, &cu, NULL,
+			      &unit_type, &cudie, &subdie) == 0)
+	{
+	  Dwarf_Die *die = (unit_type == DW_UT_skeleton
+			    ? &subdie : &cudie);
+	  if (! dwarf_hasattr (die, DW_AT_macro_info)
+	      && ! dwarf_hasattr (die, DW_AT_GNU_macros)
+	      && ! dwarf_hasattr (die, DW_AT_macros))
+	    continue;
+	  printf ("CU %s\n", dwarf_diename (die));
+	  getmacros (dbg, die, new_style);
+	}
+    }
+  else
+    {
+      ptrdiff_t cuoff = strtol (argv[2], NULL, 0);
+      Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);
+      if (cudie == NULL)
+	{
+	  puts (dwarf_errmsg (-1));
+	  return 1;
+	}
+      getmacros (dbg, cudie, new_style);
+    }
+
+  dwarf_end (dbg);
+
+  return 0;
+}
diff --git a/tests/dwarf-getstring.c b/tests/dwarf-getstring.c
new file mode 100644
index 0000000..ffa3e37
--- /dev/null
+++ b/tests/dwarf-getstring.c
@@ -0,0 +1,78 @@
+/* Copyright (C) 2011 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Marek Polacek <mpolacek@redhat.com>, 2011.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include ELFUTILS_HEADER(dwfl)
+#include <assert.h>
+#include <dwarf.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      Dwarf_Off offset = 0;
+      size_t len;
+
+      int fd = open (argv[cnt], O_RDONLY);
+      if (fd == -1)
+	{
+	  printf ("cannot open '%s': %m\n", argv[cnt]);
+	  return 1;
+	}
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  close (fd);
+	  return 1;
+	}
+
+      /* Try to use NULL Dwarf object.  */
+      const char *str = dwarf_getstring (NULL, offset, &len);
+      assert (str == NULL);
+
+      /* Use insane offset.  */
+      str = dwarf_getstring (dbg, ~0UL, &len);
+      assert (str == NULL);
+
+      /* Now do some real work.  */
+      for (int i = 0; i < 100; ++i)
+	{
+	  str = dwarf_getstring (dbg, offset, &len);
+	  puts (str);
+
+	  /* Advance.  */
+	  offset += len + 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/dwarf-ranges.c b/tests/dwarf-ranges.c
new file mode 100644
index 0000000..4bcf96c
--- /dev/null
+++ b/tests/dwarf-ranges.c
@@ -0,0 +1,57 @@
+/* Test program for dwarf_ranges
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <inttypes.h>
+
+int
+main (int argc, char *argv[])
+{
+  assert (argc >= 3);
+  const char *name = argv[1];
+  ptrdiff_t cuoff = strtol (argv[2], NULL, 0);
+
+  int fd = open (name, O_RDONLY);
+  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+
+  Dwarf_Die cudie_mem, *cudie = dwarf_offdie (dbg, cuoff, &cudie_mem);
+
+  Dwarf_Addr base, start, end;
+  for (ptrdiff_t off = 0;
+       (off = dwarf_ranges (cudie, off, &base, &start, &end)); )
+    if (off == -1)
+      {
+	puts (dwarf_errmsg (dwarf_errno ()));
+	break;
+      }
+    else
+      fprintf (stderr, "%"PRIx64"..%"PRIx64" (base %"PRIx64")\n",
+	       start, end, base);
+
+  dwarf_end (dbg);
+
+  return 0;
+}
diff --git a/tests/dwarf_default_lower_bound.c b/tests/dwarf_default_lower_bound.c
new file mode 100644
index 0000000..d57424f
--- /dev/null
+++ b/tests/dwarf_default_lower_bound.c
@@ -0,0 +1,83 @@
+/* Test all DW_LANG constants are handled by dwarf_default_lower_bound.
+
+   Copyright (C) 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+#include "../libdw/known-dwarf.h"
+
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+static void
+test_lang (const char *name, int lang)
+{
+  Dwarf_Sword low;
+  int res = dwarf_default_lower_bound (lang, &low);
+
+  /* Assembler is special, it doesn't really have arrays.  */
+  if (lang == DW_LANG_Mips_Assembler)
+    {
+      if (res == 0)
+	{
+	  printf ("%s shouldn't have a known lower bound\n", name);
+	  exit (-1);
+	}
+      printf ("%s: <unknown>\n", name);
+      return;
+    }
+
+  if (res != 0)
+    {
+      printf ("dwarf_default_lower_bound failed (%d) for %s\n", res, name);
+      exit (-1);
+    }
+
+  /* All currently known lower bounds are either zero or one, but
+     they don't have to.  Update test once one is a different value.  */
+  if (low != 0 && low != 1)
+    {
+      printf ("unexpected lower bound %" PRId64 " for %s\n", low, name);
+      exit (-1);
+    }
+
+  printf ("%s: %" PRId64 "\n", name, low);
+}
+
+int
+main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
+{
+  Dwarf_Sword low;
+  /* Bad language code must fail.  */
+  if (dwarf_default_lower_bound (-1, &low) == 0)
+    {
+      printf ("Bad lang code -1 succeeded (%" PRId64 ")\n", low);
+      exit (-1);
+    }
+
+  /* Test all known language codes.  */
+#define DWARF_ONE_KNOWN_DW_LANG(NAME, CODE) test_lang (#NAME, CODE);
+  DWARF_ALL_KNOWN_DW_LANG
+#undef DWARF_ONE_KNOWN_DW_LANG
+
+  return 0;
+}
diff --git a/tests/dwarfcfi.c b/tests/dwarfcfi.c
new file mode 100644
index 0000000..29849e7
--- /dev/null
+++ b/tests/dwarfcfi.c
@@ -0,0 +1,175 @@
+/* Test program for DWARF (.debug_frame) CFI handling.
+   Copyright (C) 2009-2010, 2013, 2015, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "system.h"
+#include "../libdw/known-dwarf.h"
+
+static const char *
+op_name (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return NULL;
+}
+
+static void
+print_detail (int result, const Dwarf_Op *ops, size_t nops)
+{
+  if (result < 0)
+    printf ("indeterminate (%s)\n", dwarf_errmsg (-1));
+  else if (nops == 0)
+    printf ("%s\n", ops == NULL ? "same_value" : "undefined");
+  else
+    {
+      printf ("%s expression:", result == 0 ? "location" : "value");
+      for (size_t i = 0; i < nops; ++i)
+	{
+	  printf (" %s", op_name(ops[i].atom));
+	  if (ops[i].number2 == 0)
+	    {
+	      if (ops[i].atom == DW_OP_addr)
+		printf ("(%#" PRIx64 ")", ops[i].number);
+	      else if (ops[i].number != 0)
+		printf ("(%" PRId64 ")", ops[i].number);
+	    }
+	  else
+	    printf ("(%" PRId64 ",%" PRId64 ")",
+		    ops[i].number, ops[i].number2);
+	}
+      puts ("");
+    }
+}
+
+static int
+handle_address (Dwarf_CFI *cfi, GElf_Addr pc)
+{
+  Dwarf_Frame *frame;
+  int result = dwarf_cfi_addrframe (cfi, pc, &frame);
+  if (result != 0)
+    {
+      printf ("dwarf_cfi_addrframe: %s\n", dwarf_errmsg (-1));
+      return 1;
+    }
+
+  Dwarf_Addr start = pc;
+  Dwarf_Addr end = pc;
+  bool signalp;
+  int ra_regno = dwarf_frame_info (frame, &start, &end, &signalp);
+
+  printf ("%#" PRIx64 " => [%#" PRIx64 ", %#" PRIx64 "):\n",
+	  pc, start, end);
+
+  if (ra_regno < 0)
+    printf ("\treturn address register unavailable (%s)\n",
+	    dwarf_errmsg (-1));
+  else
+    printf ("\treturn address in reg%u%s\n",
+	    ra_regno, signalp ? " (signal frame)" : "");
+
+  // Point cfa_ops to dummy to match print_detail expectations.
+  // (nops == 0 && cfa_ops != NULL => "undefined")
+  Dwarf_Op dummy;
+  Dwarf_Op *cfa_ops = &dummy;
+  size_t cfa_nops;
+  result = dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops);
+
+  printf ("\tCFA ");
+  print_detail (result, cfa_ops, cfa_nops);
+
+  // Print the location of the first 10 (DWARF nr) registers
+  for (int r = 0; r < 10; r++)
+    {
+      Dwarf_Op ops_mem[3];
+      Dwarf_Op *ops;
+      size_t nops;
+      printf ("\treg%d: ", r);
+      int reg_result = dwarf_frame_register (frame, r, ops_mem, &ops, &nops);
+      print_detail (reg_result, ops, nops);
+      result |= reg_result;
+    }
+
+  free (frame);
+  return result;
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc <= 2)
+    error (EXIT_FAILURE, 0, "need file name argument and addresses");
+
+  int fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, "cannot open input file `%s'", argv[1]);
+
+  elf_version (EV_CURRENT);
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    error (EXIT_FAILURE, 0, "cannot create ELF descriptor: %s",
+	   elf_errmsg (-1));
+
+  Dwarf *dwarf = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
+  if (dwarf == NULL)
+    error (EXIT_FAILURE, 0, "cannot create DWARF descriptor: %s",
+	   dwarf_errmsg (-1));
+
+  Dwarf_CFI *cfi = dwarf_getcfi (dwarf);
+  if (cfi == NULL)
+    error (EXIT_FAILURE, 0, "cannot get DWARF CFI from .dwarf_frame: %s",
+	   dwarf_errmsg (-1));
+
+  int result = 0;
+  int args = 2;
+  do
+    {
+      char *endp;
+      uintmax_t addr = strtoumax (argv[args], &endp, 0);
+      if (endp != argv[args])
+	result |= handle_address (cfi, addr);
+      else
+	result = 1;
+    }
+  while (args++ < argc - 1);
+
+  dwarf_end (dwarf);
+  elf_end (elf);
+
+  return result;
+}
diff --git a/tests/dwelf_elf_e_machine_string.c b/tests/dwelf_elf_e_machine_string.c
new file mode 100644
index 0000000..30599c3
--- /dev/null
+++ b/tests/dwelf_elf_e_machine_string.c
@@ -0,0 +1,67 @@
+/* Test program for dwelf_elf_e_machine_string
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(dwelf)
+
+int
+main (int argc, char **argv)
+{
+  int i;
+  for (i = 1; i < argc; i++)
+    {
+      long val;
+      int em;
+      const char *machine;
+
+      errno = 0;
+      if (startswith (argv[i], "0x"))
+	val = strtol (&argv[i][2], NULL, 16);
+      else
+	val = strtol (argv[i], NULL, 10);
+
+      if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
+           || (errno != 0 && val == 0))
+	{
+          perror ("strtol");
+          exit (EXIT_FAILURE);
+	}
+
+      em = val;
+      assert (em == val);
+
+      machine = dwelf_elf_e_machine_string (em);
+      printf ("0x%x %s\n", em, machine);
+      assert (machine != NULL);
+    }
+
+  return 0;
+}
diff --git a/tests/dwelfgnucompressed.c b/tests/dwelfgnucompressed.c
new file mode 100644
index 0000000..447f3d5
--- /dev/null
+++ b/tests/dwelfgnucompressed.c
@@ -0,0 +1,106 @@
+/* Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include ELFUTILS_HEADER(elf)
+#include ELFUTILS_HEADER(dwelf)
+#include <gelf.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  elf_version (EV_CURRENT);
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+      if (elf == NULL)
+	{
+	  printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      size_t shdrstrndx;
+      if (elf_getshdrstrndx (elf, &shdrstrndx) == -1)
+	{
+	  printf ("elf_getshdrstrnd failed %s\n", elf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  int idx = elf_ndxscn (scn);
+	  GElf_Shdr shdr;
+	  if (gelf_getshdr (scn, &shdr) == NULL)
+	    {
+	      printf ("gelf_getshdr failed: %s\n", elf_errmsg (-1));
+	      result = 1;
+	      break;
+	    }
+
+	  const char *sname = elf_strptr (elf, shdrstrndx, shdr.sh_name);
+	  if (sname == NULL)
+	    {
+	      printf ("couldn't get section name: %s\n", elf_errmsg (-1));
+	      result = 1;
+	      break;
+	    }
+
+	  if (startswith (sname, ".zdebug"))
+	    {
+	      ssize_t size;
+	      if ((size = dwelf_scn_gnu_compressed_size (scn)) == -1)
+		{
+		  printf ("dwelf_scn_gnu_compressed_size failed: %s\n",
+			  elf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+	      printf ("section %d: GNU Compressed size: %zx\n", idx, size);
+	    }
+	}
+
+      elf_end (elf);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/dwfl-addr-sect.c b/tests/dwfl-addr-sect.c
new file mode 100644
index 0000000..4d85c00
--- /dev/null
+++ b/tests/dwfl-addr-sect.c
@@ -0,0 +1,80 @@
+/* Test program for libdwfl ... foo
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <argp.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include "system.h"
+
+static int
+handle_address (Dwfl *dwfl, Dwarf_Addr address)
+{
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, address);
+  Dwarf_Addr adjusted = address;
+  Dwarf_Addr bias;
+  Elf_Scn *scn = dwfl_module_address_section (mod, &adjusted, &bias);
+  if (scn == NULL)
+    {
+      error (0, 0, "%#" PRIx64 ": dwfl_module_address_section: %s",
+	     address, dwfl_errmsg (-1));
+      return 1;
+    }
+  printf ("address %#" PRIx64 " => module \"%s\" section %zu + %#" PRIx64 "\n",
+	  address,
+	  dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL),
+	  elf_ndxscn (scn), adjusted);
+  return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  int remaining;
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
+  assert (dwfl != NULL);
+
+  int result = 0;
+  for (; remaining < argc; ++remaining)
+    {
+      char *endp;
+      uintmax_t addr = strtoumax (argv[remaining], &endp, 0);
+      if (endp != argv[remaining])
+	result |= handle_address (dwfl, addr);
+      else
+	result = 1;
+    }
+
+  dwfl_end (dwfl);
+
+  return result;
+}
diff --git a/tests/dwfl-bug-addr-overflow.c b/tests/dwfl-bug-addr-overflow.c
new file mode 100644
index 0000000..9a3373a
--- /dev/null
+++ b/tests/dwfl-bug-addr-overflow.c
@@ -0,0 +1,72 @@
+/* Test program for libdwfl basic module tracking, relocation.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include ELFUTILS_HEADER(dwfl)
+
+
+static const Dwfl_Callbacks offline_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .section_address = INTUSE(dwfl_offline_section_address),
+  };
+
+
+int
+main (void)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = dwfl_begin (&offline_callbacks);
+  assert (dwfl != NULL);
+
+  Dwfl_Module *high = dwfl_report_module (dwfl, "high",
+					  UINT64_C (0xffffffff00010000),
+					  UINT64_C (0xffffffff00020000));
+  assert (high);
+  Dwfl_Module *low = dwfl_report_module (dwfl, "low",
+					 UINT64_C (0x00010000),
+					 UINT64_C (0x00020000));
+  assert (low);
+  Dwfl_Module *middle = dwfl_report_module (dwfl, "middle",
+					    UINT64_C (0xffff00010000),
+					    UINT64_C (0xffff00020000));
+  assert (middle);
+
+  int ret = dwfl_report_end (dwfl, NULL, NULL);
+  assert (ret == 0);
+
+  Dwfl_Module *mod = dwfl_addrmodule (dwfl, UINT64_C (0xffffffff00010123));
+  assert (mod == high);
+  mod = dwfl_addrmodule (dwfl, UINT64_C (0x00010123));
+  assert (mod == low);
+  mod = dwfl_addrmodule (dwfl, UINT64_C (0xffff00010123));
+  assert (mod == middle);
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwfl-bug-fd-leak.c b/tests/dwfl-bug-fd-leak.c
new file mode 100644
index 0000000..7554d6e
--- /dev/null
+++ b/tests/dwfl-bug-fd-leak.c
@@ -0,0 +1,123 @@
+/* Test program for libdwfl file descriptors leakage.
+   Copyright (C) 2007, 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#include <dwarf.h>
+#include "system.h"
+
+#ifndef __linux__
+int
+main (void)
+{
+  return 77; /* dwfl_linux_proc_report is linux specific.  */
+}
+#else
+
+#include <sys/resource.h>
+#include ELFUTILS_HEADER(dwfl)
+
+
+static Dwfl *
+elfutils_open (pid_t pid, Dwarf_Addr address)
+{
+  static char *debuginfo_path;
+  static const Dwfl_Callbacks proc_callbacks =
+    {
+      .find_debuginfo = dwfl_standard_find_debuginfo,
+      .debuginfo_path = &debuginfo_path,
+
+      .find_elf = dwfl_linux_proc_find_elf,
+    };
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+    error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+
+  int result = dwfl_linux_proc_report (dwfl, pid);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_report");
+
+  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+  Dwarf_Addr bias;
+  Dwarf *dbg = dwfl_addrdwarf (dwfl, address, &bias);
+  if (dbg != NULL)
+    {
+      Elf *elf = dwarf_getelf (dbg);
+      if (elf == NULL)
+	error (2, 0, "dwarf_getelf: %s", dwarf_errmsg (-1));
+    }
+  else
+    {
+      Dwfl_Module *module = dwfl_addrmodule (dwfl, address);
+      if (module == NULL)
+	error (2, 0, "dwfl_addrmodule: no module available for 0x%" PRIx64 "",
+	       address);
+      Elf *elf = dwfl_module_getelf (module, &bias);
+      if (elf == NULL)
+	error (2, 0, "dwfl_module_getelf: %s", dwfl_errmsg (-1));
+    }
+
+  return dwfl;
+}
+
+static void
+elfutils_close (Dwfl *dwfl)
+{
+  dwfl_end (dwfl);
+}
+
+int
+main (void)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  /* Get both the soft and hard limits first. The soft limit is what
+     will be enforced against the process.  The hard limit is the max
+     that can be set for the soft limit.  We don't want to lower it
+     because we might not be able to (under valgrind).  */
+  struct rlimit fd_limit;
+  if (getrlimit (RLIMIT_NOFILE, &fd_limit) < 0)
+    error (2, errno, "getrlimit");
+  fd_limit.rlim_cur = 32;
+  if (setrlimit (RLIMIT_NOFILE, &fd_limit) < 0)
+    error (2, errno, "setrlimit");
+
+  for (int i = 0; i < 5000; ++i)
+    {
+      Dwfl *dwfl = elfutils_open (getpid (), (Dwarf_Addr) (uintptr_t) &main);
+      elfutils_close (dwfl);
+    }
+
+  return 0;
+}
+#endif
diff --git a/tests/dwfl-bug-getmodules.c b/tests/dwfl-bug-getmodules.c
new file mode 100644
index 0000000..2783f65
--- /dev/null
+++ b/tests/dwfl-bug-getmodules.c
@@ -0,0 +1,66 @@
+/* Test program for dwfl_getmodules bug.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dwfl)
+#include "system.h"
+
+
+static const Dwfl_Callbacks callbacks =
+  {
+    .find_elf = dwfl_linux_proc_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+  };
+
+static int
+iterate (Dwfl_Module *mod __attribute__ ((unused)),
+	 void **userdata __attribute__ ((unused)),
+	 const char *name __attribute__ ((unused)),
+	 Dwarf_Addr base, void *arg)
+{
+  if (base != 0x2000)
+    return DWARF_CB_OK;
+
+  if (dwfl_addrmodule (arg, 0x2100) == NULL)
+    error (1, 0, "dwfl_addrmodule: %s", dwfl_errmsg (-1));
+
+  return DWARF_CB_ABORT;
+}
+
+int
+main (void)
+{
+  Dwfl *dwfl = dwfl_begin (&callbacks);
+
+  dwfl_report_module (dwfl, "m1", 0, 0x1000);
+  dwfl_report_module (dwfl, "m2", 0x2000, 0x3000);
+  dwfl_report_module (dwfl, "m3", 0x4000, 0x5000);
+
+  dwfl_report_end (dwfl, NULL, NULL);
+
+  ptrdiff_t offset = dwfl_getmodules (dwfl, &iterate, dwfl, 0);
+  if (offset <= 0)
+    error (1, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+
+  offset = dwfl_getmodules (dwfl, &iterate, NULL, offset);
+  if (offset != 0)
+    error (1, 0, "dwfl_getmodules (%d): %s", (int) offset, dwfl_errmsg (-1));
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwfl-bug-report.c b/tests/dwfl-bug-report.c
new file mode 100644
index 0000000..80ff806
--- /dev/null
+++ b/tests/dwfl-bug-report.c
@@ -0,0 +1,48 @@
+/* Test program for dwfl_report_end bug.
+   Copyright (C) 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include ELFUTILS_HEADER(dwfl)
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+static const Dwfl_Callbacks callbacks =
+  {
+    .find_elf = dwfl_linux_proc_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+  };
+
+int
+main (void)
+{
+  Dwfl *dwfl = dwfl_begin (&callbacks);
+
+  for (int i = 0; i < 5; ++i)
+    {
+      dwfl_report_begin (dwfl);
+      dwfl_report_module (dwfl, "module1", 0, 10);
+      dwfl_report_end (dwfl, NULL, NULL);
+    }
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwfl-core-noncontig.c b/tests/dwfl-core-noncontig.c
new file mode 100644
index 0000000..04558e2
--- /dev/null
+++ b/tests/dwfl-core-noncontig.c
@@ -0,0 +1,82 @@
+/* Test program for dwfl_getmodules bug.
+   Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <assert.h>
+#include ELFUTILS_HEADER(dwfl)
+#include ELFUTILS_HEADER(elf)
+
+static const Dwfl_Callbacks cb =
+{
+  NULL,
+  NULL,
+  NULL,
+  NULL,
+};
+
+int
+main (int argc, char **argv)
+{
+  assert (argc == 2);
+
+  Dwfl *dwfl = dwfl_begin (&cb);
+
+  int fd = open (argv[1], O_RDONLY);
+  assert (fd != -1);
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  (void) dwfl_core_file_report (dwfl, elf, argv[0]);
+
+  /* testcore-noncontig contains a shared library mapped between 
+     non-contiguous segments of another shared library:
+
+     [...]
+     7f14e458c000-7f14e45ae000 00000000 139264      /usr/lib64/ld-2.17.so             (1)
+     7f14e4795000-7f14e4798000 00000000 12288       /usr/lib64/firefox/liblgpllibs.so (2)
+     7f14e4798000-7f14e479d000 00003000 20480       /usr/lib64/firefox/liblgpllibs.so
+     7f14e479d000-7f14e479f000 00008000 8192        /usr/lib64/firefox/liblgpllibs.so
+     7f14e479f000-7f14e47a0000 00009000 4096        /usr/lib64/firefox/liblgpllibs.so
+     7f14e47a0000-7f14e47a1000 0000a000 4096        /usr/lib64/firefox/liblgpllibs.so (3)
+     7f14e47ad000-7f14e47ae000 00021000 4096        /usr/lib64/ld-2.17.so             (4)
+     7f14e47ae000-7f14e47af000 00022000 4096        /usr/lib64/ld-2.17.so  */
+
+  /* First segment of the non-contiguous module (1).  */
+  int seg = dwfl_addrsegment (dwfl, 0x7f14e458c000, NULL);
+  assert (seg == 32);
+
+  /* First segment of the module within the non-contiguous module's address
+     range (2).  */
+  seg = dwfl_addrsegment (dwfl, 0x7f14e4795000, NULL);
+  assert (seg == 33);
+
+  /* Last segment of the module within the non-contiguous module's
+     address range (3).  */
+  seg = dwfl_addrsegment (dwfl, 0x7f14e47a0000, NULL);
+  assert (seg == 37);
+
+  /* First segment of non-contiguous module following its address space
+     gap (4).  */
+  seg = dwfl_addrsegment (dwfl, 0x7f14e47ad000, NULL);
+  assert (seg == 40);
+
+  dwfl_end (dwfl);
+  elf_end (elf);
+
+  return 0;
+}
diff --git a/tests/dwfl-proc-attach.c b/tests/dwfl-proc-attach.c
new file mode 100644
index 0000000..d02e9fc
--- /dev/null
+++ b/tests/dwfl-proc-attach.c
@@ -0,0 +1,122 @@
+/* Test dwfl_linux_proc_attach works without any modules.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+#ifdef __linux__
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/user.h>
+#include <fcntl.h>
+#include <string.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <pthread.h>
+#endif
+#include "system.h"
+
+#ifndef __linux__
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  printf ("dwfl_linux_proc_attach unsupported.\n");
+  return 77;
+}
+#else /* __linux__ */
+
+static pthread_t thread1;
+static pthread_t thread2;
+
+static void *
+sleeper (void* d __attribute__ ((unused)))
+{
+  sleep (60);
+  return NULL;
+}
+
+static char *debuginfo_path = NULL;
+
+static const Dwfl_Callbacks proc_callbacks =
+  {
+    .find_elf = dwfl_linux_proc_find_elf,
+    .find_debuginfo = dwfl_standard_find_debuginfo,
+    .debuginfo_path = &debuginfo_path,
+  };
+
+static int
+thread_callback (Dwfl_Thread *thread, void *thread_arg)
+{
+  int *threads = (int *) thread_arg;
+  pid_t tid = dwfl_thread_tid (thread);
+  printf ("thread tid: %d\n", tid);
+  (*threads)++;
+
+  return DWARF_CB_OK;
+}
+
+int
+main (int argc __attribute__ ((unused)),
+      char **argv __attribute__ ((unused)))
+{
+  /* Create two extra threads to iterate through.  */
+  int err;
+  if ((err = pthread_create (&thread1, NULL, sleeper, NULL)) != 0)
+    error (-1, err, "Couldn't create thread1");
+  if ((err = pthread_create (&thread2, NULL, sleeper, NULL)) != 0)
+    error (-1, err, "Couldn't create thread2");
+
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+    error (-1, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+
+  pid_t pid = getpid ();
+  /* This used to fail, since we don't have any modules yet.  */
+  if (dwfl_linux_proc_attach (dwfl, pid, false) < 0)
+    error (-1, 0, "dwfl_linux_proc_attach pid %d: %s", pid,
+	   dwfl_errmsg (-1));
+
+  /* Did we see all 3 threads?  */
+  int threads = 0;
+  if (dwfl_getthreads (dwfl, thread_callback, &threads) != DWARF_CB_OK)
+    error (-1, 0, "dwfl_getthreads failed: %s", dwfl_errmsg (-1));
+
+  dwfl_end (dwfl);
+
+  pthread_cancel (thread1);
+  pthread_cancel (thread2);
+  pthread_join (thread1, NULL);
+  pthread_join (thread2, NULL);
+
+  return (threads == 3) ? 0 : -1;
+}
+
+/* HACK. This is a simple workaround for a combination of old glibc
+   and valgrind. libdw will try to dlopen libdebuginfod this causes
+   some unsuppressable memory leak warnings when the process is
+   multi-threaded under valgrind because of some bad backtraces.
+   So simply override dlopen and always return NULL so libdebuginfod
+   (and libcurl) are never loaded.  This test doesn't rely on
+   libdebuginfod anyway.  */
+void *dlopen (void)
+{
+  return NULL;
+}
+
+#endif /* __linux__ */
diff --git a/tests/dwfl-report-elf-align.c b/tests/dwfl-report-elf-align.c
new file mode 100644
index 0000000..6558ab8
--- /dev/null
+++ b/tests/dwfl-report-elf-align.c
@@ -0,0 +1,72 @@
+/* Test program for dwfl_report_elf incorrect BASE alignment.
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <string.h>
+#include <stdlib.h>
+#include ELFUTILS_HEADER(dwfl)
+#include "system.h"
+
+
+static const Dwfl_Callbacks offline_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .section_address = INTUSE(dwfl_offline_section_address),
+  };
+
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  if (argc != 5)
+    error (1, 0, "dwfl-report-elf-align shlib.so base funcaddr funcname");
+    
+  Dwfl *dwfl = dwfl_begin (&offline_callbacks);
+  assert (dwfl != NULL);
+
+  char *endptr;
+  uintptr_t base = strtoull (argv[2], &endptr, 0);
+  assert (endptr && !*endptr);
+
+  Dwfl_Module *mod = dwfl_report_elf (dwfl, argv[1], argv[1], -1, base, false);
+  assert (mod != NULL);
+
+  uintptr_t funcaddr = strtoull (argv[3], &endptr, 0);
+  assert (endptr && !*endptr);
+
+  Dwfl_Module *mod_found = dwfl_addrmodule (dwfl, funcaddr);
+  assert (mod_found == mod);
+
+  const char *symname = dwfl_module_addrname (mod, funcaddr);
+  assert (symname != NULL);
+  assert (strcmp (symname, argv[4]) == 0);
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwfl-report-offline-memory.c b/tests/dwfl-report-offline-memory.c
new file mode 100644
index 0000000..3ecb66b
--- /dev/null
+++ b/tests/dwfl-report-offline-memory.c
@@ -0,0 +1,133 @@
+/* Test program for dwfl_report_offline_memory.
+   Copyright (C) 2022 Google LLC
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <error.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(dwfl)
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+static const Dwfl_Callbacks offline_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .section_address = INTUSE(dwfl_offline_section_address),
+  };
+
+static int
+count_modules (Dwfl_Module *mod __attribute__ ((unused)),
+	       void **userdata __attribute__ ((unused)),
+	       const char *name __attribute__ ((unused)),
+	       Dwarf_Addr base __attribute__ ((unused)), void *arg)
+{
+  unsigned long long *counter = arg;
+  ++(*counter);
+  return DWARF_CB_OK;
+}
+
+static int
+count_sections (Elf *elf)
+{
+  int result = 0;
+  Elf_Scn *section = NULL;
+  GElf_Shdr header;
+  while ((section = elf_nextscn (elf, section)) != NULL)
+    {
+      assert (gelf_getshdr (section, &header) != NULL);
+      result += 1;
+    }
+  return result;
+}
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  if (argc != 4)
+    error (-1, 0,
+	   "usage: dwfl_report_offline_memory [filename] "
+	   "[expected number of modules] "
+	   "[expected number of sections]");
+
+  const char *fname = argv[1];
+  int fd = open (fname, O_RDONLY);
+  if (fd < 0)
+    error (-1, 0, "can't open file %s: %s", fname, strerror (errno));
+  off_t size = lseek (fd, 0, SEEK_END);
+  if (size < 0)
+    error (-1, 0, "can't lseek file %s: %s", fname, strerror (errno));
+  lseek (fd, 0, SEEK_SET);
+  char *data = malloc (size);
+  if (data == NULL)
+    error (-1, 0, "can't malloc: %s", strerror (errno));
+  ssize_t bytes_read = read (fd, data, size);
+  assert (bytes_read == size);
+  close (fd);
+
+  Dwfl *dwfl = dwfl_begin (&offline_callbacks);
+  assert (dwfl != NULL);
+
+  Dwfl_Module *mod;
+
+  /* Check error handling by suppling zero data */
+  mod = dwfl_report_offline_memory(dwfl, argv[1], argv[1], NULL, 0);
+  assert(mod == NULL);
+
+  mod = dwfl_report_offline_memory(dwfl, argv[1], argv[1], data, size);
+  assert (mod != NULL);
+  dwfl_report_end (dwfl, NULL, NULL);
+
+  unsigned long long number_of_modules = 0;
+  ptrdiff_t offset =
+      dwfl_getmodules (dwfl, &count_modules, &number_of_modules, 0);
+  if (offset < 0)
+    error (1, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+  assert (offset == 0);
+
+  char *endptr;
+  unsigned long long expected_number_of_modules =
+      strtoull (argv[2], &endptr, 0);
+  assert (endptr && !*endptr);
+  assert (number_of_modules == expected_number_of_modules);
+
+  GElf_Addr loadbase = 0;
+  Elf *elf = dwfl_module_getelf (mod, &loadbase);
+  int number_of_sections = count_sections (elf);
+  int expected_number_of_sections = atoi (argv[3]);
+  assert (number_of_sections == expected_number_of_sections);
+
+  dwfl_end (dwfl);
+  free (data);
+
+  return 0;
+}
diff --git a/tests/dwfl-report-segment-contiguous.c b/tests/dwfl-report-segment-contiguous.c
new file mode 100644
index 0000000..61e6bfe
--- /dev/null
+++ b/tests/dwfl-report-segment-contiguous.c
@@ -0,0 +1,82 @@
+/* Test bug in dwfl_report_segment() coalescing.
+   Copyright (C) 2019 Facebook
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include ELFUTILS_HEADER(dwfl)
+
+
+static const Dwfl_Callbacks offline_callbacks =
+  {
+    .find_debuginfo = INTUSE(dwfl_standard_find_debuginfo),
+    .section_address = INTUSE(dwfl_offline_section_address),
+  };
+
+
+int
+main (void)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = dwfl_begin (&offline_callbacks);
+  assert (dwfl != NULL);
+
+  GElf_Phdr phdr1 =
+    {
+      .p_type = PT_LOAD,
+      .p_flags = PF_R,
+      .p_offset = 0xf00,
+      .p_vaddr = 0xf00,
+      .p_filesz = 0x100,
+      .p_memsz = 0x100,
+      .p_align = 4,
+    };
+
+  int ndx = dwfl_report_segment (dwfl, 1, &phdr1, 0, dwfl);
+  assert(ndx == 1);
+
+  ndx = dwfl_addrsegment (dwfl, 0xf00, NULL);
+  assert(ndx == 1);
+
+  GElf_Phdr phdr2 =
+    {
+      .p_type = PT_LOAD,
+      .p_flags = PF_R | PF_W,
+      .p_offset = 0x1000,
+      .p_vaddr = 0x1000,
+      .p_filesz = 0x100,
+      .p_memsz = 0x100,
+      .p_align = 4,
+    };
+  ndx = dwfl_report_segment (dwfl, 2, &phdr2, 0, dwfl);
+  assert(ndx == 2);
+
+  ndx = dwfl_addrsegment (dwfl, 0x1000, NULL);
+  assert(ndx == 1 || ndx == 2);
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwfllines.c b/tests/dwfllines.c
new file mode 100644
index 0000000..d732e40
--- /dev/null
+++ b/tests/dwfllines.c
@@ -0,0 +1,164 @@
+/* Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <assert.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "system.h"
+
+int
+main (int argc, char *argv[])
+{
+  int cnt;
+
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &cnt, &dwfl);
+  assert (dwfl != NULL);
+
+  Dwarf_Die *cu = NULL;
+  Dwarf_Addr bias;
+  do
+    {
+      cu = dwfl_nextcu (dwfl, cu, &bias);
+      if (cu != NULL)
+	{
+	  Dwfl_Module *mod = dwfl_cumodule (cu);
+	  const char *modname = (dwfl_module_info (mod, NULL, NULL, NULL,
+						   NULL, NULL, NULL, NULL)
+				 ?: "<unknown>");
+	  const char *cuname = (dwarf_diename (cu) ?: "<unknown>");
+
+	  printf ("mod: %s CU: [%" PRIx64 "] %s\n", modname,
+		  dwarf_dieoffset (cu), cuname);
+
+	  size_t lines;
+	  if (dwfl_getsrclines (cu, &lines) != 0)
+	    continue; // No lines...
+
+	  for (size_t i = 0; i < lines; i++)
+	    {
+	      Dwfl_Line *line = dwfl_onesrcline (cu, i);
+
+	      Dwarf_Addr addr;
+	      int lineno;
+	      int colno;
+	      Dwarf_Word mtime;
+	      Dwarf_Word length;
+	      const char *src = dwfl_lineinfo (line, &addr, &lineno, &colno,
+					       &mtime, &length);
+
+	      Dwarf_Addr dw_bias;
+	      Dwarf_Line *dw_line = dwfl_dwarf_line (line, &dw_bias);
+	      assert (bias == dw_bias);
+
+	      Dwarf_Addr dw_addr;
+	      if (dwarf_lineaddr (dw_line, &dw_addr) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineaddr: %s",
+		       dwarf_errmsg (-1));
+	      assert (addr == dw_addr + dw_bias);
+
+	      unsigned int dw_op_index;
+	      if (dwarf_lineop_index (dw_line, &dw_op_index) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineop_index: %s",
+		       dwarf_errmsg (-1));
+
+	      int dw_lineno;
+	      if (dwarf_lineno (dw_line, &dw_lineno) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineno: %s",
+		       dwarf_errmsg (-1));
+	      assert (lineno == dw_lineno);
+
+	      int dw_colno;
+	      if (dwarf_linecol (dw_line, &dw_colno) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineno: %s",
+		       dwarf_errmsg (-1));
+	      assert (colno == dw_colno);
+
+	      bool begin;
+	      if (dwarf_linebeginstatement (dw_line, &begin) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_linebeginstatement: %s",
+		       dwarf_errmsg (-1));
+
+	      bool end;
+	      if (dwarf_lineendsequence (dw_line, &end) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineendsequence: %s",
+		       dwarf_errmsg (-1));
+
+	      bool pend;
+	      if (dwarf_lineprologueend (dw_line, &pend) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineprologueend: %s",
+		       dwarf_errmsg (-1));
+
+	      bool ebegin;
+	      if (dwarf_lineepiloguebegin (dw_line, &ebegin) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineepiloguebegin: %s",
+		       dwarf_errmsg (-1));
+
+	      bool block;
+	      if (dwarf_lineblock (dw_line, &block) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineblock: %s",
+		       dwarf_errmsg (-1));
+
+	      unsigned int isa;
+	      if (dwarf_lineisa (dw_line, &isa) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_lineisa: %s",
+		       dwarf_errmsg (-1));
+
+	      unsigned int disc;
+	      if (dwarf_linediscriminator (dw_line, &disc) != 0)
+		error (EXIT_FAILURE, 0, "dwarf_linediscriminator: %s",
+		       dwarf_errmsg (-1));
+
+	      const char *dw_src;
+	      Dwarf_Word dw_mtime;
+	      Dwarf_Word dw_length;
+	      dw_src = dwarf_linesrc (dw_line, &dw_mtime, &dw_length);
+	      assert (strcmp (src, dw_src) == 0);
+	      assert (mtime == dw_mtime);
+	      assert (length == dw_length);
+
+	      printf ("%zd %#" PRIx64 " %s:%d:%d\n"
+		      " time: %#" PRIX64 ", len: %" PRIu64
+		      ", idx: %d, b: %d, e: %d"
+		      ", pe: %d, eb: %d, block: %d"
+		      ", isa: %d, disc: %d\n",
+		      i, addr, src, lineno, colno, mtime, length,
+		      dw_op_index, begin, end, pend, ebegin, block, isa, disc);
+
+	      Dwarf_Die *linecu = dwfl_linecu (line);
+	      assert (cu == linecu);
+
+	      Dwfl_Module *linemod = dwfl_linemodule (line);
+	      assert (mod == linemod);
+	    }
+	}
+    }
+  while (cu != NULL);
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwflmodtest.c b/tests/dwflmodtest.c
new file mode 100644
index 0000000..bec8a07
--- /dev/null
+++ b/tests/dwflmodtest.c
@@ -0,0 +1,283 @@
+/* Test program for libdwfl basic module tracking, relocation.
+   Copyright (C) 2005, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+#include <locale.h>
+#include <argp.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include "system.h"
+
+static bool show_inlines;
+
+struct info
+{
+  Dwarf_Die *cudie;
+  Dwarf_Addr dwbias;
+};
+
+static int
+print_instance (Dwarf_Die *instance, void *arg)
+{
+  const struct info *info = arg;
+
+  printf ("    inlined");
+
+  Dwarf_Files *files;
+  if (dwarf_getsrcfiles (info->cudie, &files, NULL) == 0)
+    {
+      Dwarf_Attribute attr_mem;
+      Dwarf_Word val;
+      if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_file,
+				       &attr_mem), &val) == 0)
+	{
+	  const char *file = dwarf_filesrc (files, val, NULL, NULL);
+	  int lineno = 0, colno = 0;
+	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_line,
+					   &attr_mem), &val) == 0)
+	    lineno = val;
+	  if (dwarf_formudata (dwarf_attr (instance, DW_AT_call_column,
+					   &attr_mem), &val) == 0)
+	    colno = val;
+	  if (lineno == 0)
+	    {
+	      if (file != NULL)
+		printf (" from %s", file);
+	    }
+	  else if (colno == 0)
+	    printf (" at %s:%u", file, lineno);
+	  else
+	    printf (" at %s:%u:%u", file, lineno, colno);
+	}
+    }
+
+  Dwarf_Addr lo = -1, hi = -1, entry = -1;
+  if (dwarf_lowpc (instance, &lo) == 0)
+    lo += info->dwbias;
+  else
+    printf (" (lowpc => %s)", dwarf_errmsg (-1));
+  if (dwarf_highpc (instance, &hi) == 0)
+    hi += info->dwbias;
+  else
+    printf (" (highpc => %s)", dwarf_errmsg (-1));
+
+  Dwarf_Attribute attr_mem;
+  Dwarf_Attribute *attr = dwarf_attr (instance, DW_AT_entry_pc, &attr_mem);
+  if (attr != NULL)
+    {
+      if (dwarf_formaddr (attr, &entry) == 0)
+	entry += info->dwbias;
+      else
+	printf (" (entrypc => %s)", dwarf_errmsg (-1));
+    }
+
+  if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1)
+    printf (" %#" PRIx64 "..%#" PRIx64, lo, hi);
+  if (entry != (Dwarf_Addr) -1)
+    printf (" => %#" PRIx64 "\n", entry);
+  else
+    puts ("");
+
+  return DWARF_CB_OK;
+}
+
+static void
+print_inline (Dwarf_Die *func, void *arg)
+{
+  if (dwarf_func_inline_instances (func, &print_instance, arg) != 0)
+    printf ("  error finding instances: %s\n", dwarf_errmsg (-1));
+}
+
+static int
+print_func (Dwarf_Die *func, void *arg)
+{
+  const struct info *info = arg;
+
+  const char *file = dwarf_decl_file (func);
+  int line = -1;
+  dwarf_decl_line (func, &line);
+  const char *fct = dwarf_diename (func);
+
+  printf ("  %s:%d: %s:", file, line, fct);
+
+  if (dwarf_func_inline (func))
+    {
+      puts (" inline function");
+      if (show_inlines)
+	print_inline (func, arg);
+    }
+  else
+    {
+      Dwarf_Addr lo = -1, hi = -1, entry = -1;
+      if (dwarf_lowpc (func, &lo) == 0)
+	lo += info->dwbias;
+      else
+	printf (" (lowpc => %s)", dwarf_errmsg (-1));
+      if (dwarf_highpc (func, &hi) == 0)
+	hi += info->dwbias;
+      else
+	printf (" (highpc => %s)", dwarf_errmsg (-1));
+      if (dwarf_entrypc (func, &entry) == 0)
+	entry += info->dwbias;
+      else
+	printf (" (entrypc => %s)", dwarf_errmsg (-1));
+
+      if (lo != (Dwarf_Addr) -1 || hi != (Dwarf_Addr) -1
+	  || entry != (Dwarf_Addr) -1)
+	printf (" %#" PRIx64 "..%#" PRIx64 " => %#" PRIx64 "\n",
+		lo, hi, entry);
+      else
+	puts ("");
+    }
+
+  return DWARF_CB_OK;
+}
+
+static int
+list_module (Dwfl_Module *mod __attribute__ ((unused)),
+	     void **userdata __attribute__ ((unused)),
+	     const char *name, Dwarf_Addr base,
+	     void *arg __attribute__ ((unused)))
+{
+  Dwarf_Addr start;
+  Dwarf_Addr end;
+  const char *file;
+  const char *debug;
+  if (dwfl_module_info (mod, NULL, &start, &end,
+			NULL, NULL, &file, &debug) != name
+      || start != base)
+    abort ();
+  printf ("module: %30s %08" PRIx64 "..%08" PRIx64 " %s %s\n",
+	  name, start, end, file, debug);
+  return DWARF_CB_OK;
+}
+
+static int
+print_module (Dwfl_Module *mod __attribute__ ((unused)),
+	      void **userdata __attribute__ ((unused)),
+	      const char *name, Dwarf_Addr base,
+	      Dwarf *dw, Dwarf_Addr bias,
+	      void *arg)
+{
+  printf ("module: %30s %08" PRIx64 " %s %" PRIx64 " (%s)\n",
+	  name, base, dw == NULL ? "no" : "DWARF", bias, dwfl_errmsg (-1));
+
+  if (dw != NULL && *(const bool *) arg)
+    {
+      Dwarf_Off off = 0;
+      size_t cuhl;
+      Dwarf_Off noff;
+
+      while (dwarf_nextcu (dw, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+	{
+	  Dwarf_Die die_mem;
+	  struct info info = { dwarf_offdie (dw, off + cuhl, &die_mem), bias };
+	  (void) dwarf_getfuncs (info.cudie, print_func, &info, 0);
+
+	  off = noff;
+	}
+    }
+
+  return DWARF_CB_OK;
+}
+
+static bool show_functions;
+
+static const struct argp_option options[] =
+  {
+    { "functions", 'f', NULL, 0, N_("Additionally show function names"), 0 },
+    { "inlines", 'i', NULL, 0, N_("Show instances of inlined functions"), 0 },
+    { NULL, 0, NULL, 0, NULL, 0 }
+  };
+
+static error_t
+parse_opt (int key, char *arg __attribute__ ((unused)),
+	   struct argp_state *state __attribute__ ((unused)))
+{
+  switch (key)
+    {
+    case ARGP_KEY_INIT:
+      state->child_inputs[0] = state->input;
+      break;
+
+    case 'f':
+      show_functions = true;
+      break;
+
+    case 'i':
+      show_inlines = show_functions = true;
+      break;
+
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+int
+main (int argc, char **argv)
+{
+  /* We use no threads here which can interfere with handling a stream.  */
+  (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER);
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = NULL;
+  const struct argp_child argp_children[] =
+    {
+      { .argp = dwfl_standard_argp () },
+      { .argp = NULL }
+    };
+  const struct argp argp =
+    {
+      options, parse_opt, NULL, NULL, argp_children, NULL, NULL
+    };
+  (void) argp_parse (&argp, argc, argv, 0, NULL, &dwfl);
+  assert (dwfl != NULL);
+
+  ptrdiff_t p = 0;
+  do
+    p = dwfl_getmodules (dwfl, &list_module, NULL, p);
+  while (p > 0);
+  if (p < 0)
+    error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+
+  do
+    p = dwfl_getdwarf (dwfl, &print_module, &show_functions, p);
+  while (p > 0);
+  if (p < 0)
+    error (2, 0, "dwfl_getdwarf: %s", dwfl_errmsg (-1));
+
+  p = 0;
+  do
+    p = dwfl_getmodules (dwfl, &list_module, NULL, p);
+  while (p > 0);
+  if (p < 0)
+    error (2, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/dwflsyms.c b/tests/dwflsyms.c
new file mode 100644
index 0000000..bc23cb6
--- /dev/null
+++ b/tests/dwflsyms.c
@@ -0,0 +1,225 @@
+/* Test program for libdwfl symbol resolving
+   Copyright (C) 2013 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <elf.h>
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <stdlib.h>
+#include <string.h>
+
+static const char *
+gelf_type (GElf_Sym *sym)
+{
+  switch (GELF_ST_TYPE (sym->st_info))
+    {
+    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:
+      return "UNKNOWN";
+    }
+}
+
+static const char *
+gelf_bind (GElf_Sym *sym)
+{
+  switch (GELF_ST_BIND (sym->st_info))
+    {
+    case STB_LOCAL:
+      return "LOCAL";
+    case STB_GLOBAL:
+      return "GLOBAL";
+    case STB_WEAK:
+      return "WEAK";
+    default:
+      return "UNKNOWN";
+    }
+}
+
+static int
+gelf_bind_order (GElf_Sym *sym)
+{
+  switch (GELF_ST_BIND (sym->st_info))
+    {
+    case STB_LOCAL:
+      return 1;
+    case STB_WEAK:
+      return 2;
+    case STB_GLOBAL:
+      return 3;
+    default:
+      return 0;
+    }
+}
+
+static const char *
+elf_section_name (Elf *elf, GElf_Word shndx)
+{
+  GElf_Ehdr ehdr;
+  GElf_Shdr shdr;
+  Elf_Scn *scn = elf_getscn (elf, shndx);
+  gelf_getshdr (scn, &shdr);
+  gelf_getehdr (elf, &ehdr);
+  return elf_strptr (elf, ehdr.e_shstrndx, shdr.sh_name);
+}
+
+bool
+addr_in_section (Elf *elf, GElf_Word shndx, GElf_Addr addr)
+{
+  GElf_Shdr shdr;
+  Elf_Scn *scn = elf_getscn (elf, shndx);
+  gelf_getshdr (scn, &shdr);
+  return addr >= shdr.sh_addr && addr < shdr.sh_addr + shdr.sh_size;
+}
+
+static int
+list_syms (struct Dwfl_Module *mod,
+	   void **user __attribute__ ((unused)), const char *mod_name,
+	   Dwarf_Addr low_addr __attribute__ ((unused)),
+	   void *arg __attribute__ ((unused)))
+{
+  int syms = dwfl_module_getsymtab (mod);
+  if (syms < 0)
+    {
+      printf ("%s: %s\n", mod_name, dwfl_errmsg (-1));
+      return DWARF_CB_OK;
+    }
+
+  for (int ndx = 0; ndx < syms; ndx++)
+    {
+      GElf_Sym sym;
+      GElf_Word shndxp;
+      Elf *elf;
+      Dwarf_Addr bias;
+      const char *name = dwfl_module_getsym (mod, ndx, &sym, &shndxp);
+
+      printf("%4d: %s\t%s\t%s (%" PRIu64 ") %#" PRIx64,
+	     ndx, gelf_type (&sym), gelf_bind (&sym), name,
+	     sym.st_size, sym.st_value);
+
+      /* The info variant doesn't adjust st_value but returns the (possible)
+	 adjusted value separately. */
+      GElf_Addr value;
+      GElf_Sym isym;
+      name = dwfl_module_getsym_info (mod, ndx, &isym, &value, &shndxp,
+				      &elf, &bias);
+
+      GElf_Ehdr ehdr;
+      gelf_getehdr (elf, &ehdr);
+
+      // getsym st_values might or might not be adjusted depending on section.
+      // For ET_REL the adjustment is section relative.
+      assert (sym.st_value == isym.st_value
+	      || sym.st_value == isym.st_value + bias
+	      || ehdr.e_type == ET_REL);
+
+      /* And the reverse, which works for function symbols at least.
+	 Note this only works because the st.value is adjusted by
+	 dwfl_module_getsym ().  */
+      if (GELF_ST_TYPE (sym.st_info) == STT_FUNC && shndxp != SHN_UNDEF)
+	{
+	  /* Make sure the adjusted value really falls in the elf section. */
+          assert (addr_in_section (elf, shndxp, sym.st_value - bias));
+
+	  GElf_Addr addr = value;
+	  GElf_Sym asym;
+	  GElf_Word ashndxp;
+	  Elf *aelf;
+	  Dwarf_Addr abias;
+	  GElf_Off off;
+	  const char *aname = dwfl_module_addrinfo (mod, addr, &off, &asym,
+						    &ashndxp, &aelf, &abias);
+
+	  /* Make sure the adjusted value really falls in the elf section. */
+          assert (addr_in_section (aelf, ashndxp, asym.st_value)
+		  || ehdr.e_type == ET_REL);
+
+	  /* Either they are the same symbol (name), the binding of
+	     asym is "stronger" (or equal) to sym or asym is more specific
+	     (has a lower address) than sym.  */
+	  assert ((strcmp (name, aname) == 0
+		   || gelf_bind_order (&asym) >= gelf_bind_order (&sym))
+		  && value <= sym.st_value);
+
+	  addr = sym.st_value;
+	  int res = dwfl_module_relocate_address (mod, &addr);
+	  assert (res != -1);
+	  if (shndxp < SHN_LORESERVE)
+	    printf(", rel: %#" PRIx64 " (%s)", addr,
+		   elf_section_name (elf, shndxp));
+	  else
+	    printf(", rel: %#" PRIx64 "", addr);
+
+	  /* Print the section of the actual value if different from sym.  */
+	  if (value != isym.st_value + bias && ehdr.e_type != ET_REL)
+	    {
+	      GElf_Addr ebias;
+	      addr = value;
+	      Elf_Scn *scn = dwfl_module_address_section (mod, &addr, &ebias);
+	      GElf_Shdr shdr_mem;
+	      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+	      Elf *melf = dwfl_module_getelf (mod, &ebias);
+	      gelf_getehdr (melf, &ehdr);
+	      const char *sname = elf_strptr (melf, ehdr.e_shstrndx,
+					      shdr->sh_name);
+	      printf (" [%#" PRIx64 ", rel: %#" PRIx64 " (%s)]",
+		      value, addr, sname);
+	    }
+
+	}
+      printf ("\n");
+    }
+
+  return DWARF_CB_OK;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+  Dwfl *dwfl;
+  error_t res;
+
+  res = argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining, &dwfl);
+  assert (res == 0 && dwfl != NULL);
+
+  ptrdiff_t off = 0;
+  do
+    off = dwfl_getmodules (dwfl, list_syms, NULL, off);
+  while (off > 0);
+
+  dwfl_end (dwfl);
+
+  return off;
+}
diff --git a/tests/early-offscn.c b/tests/early-offscn.c
new file mode 100644
index 0000000..af29da5
--- /dev/null
+++ b/tests/early-offscn.c
@@ -0,0 +1,52 @@
+/* Copyright (C) 2008 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "system.h"
+
+int
+main (int argc, char *argv[])
+{
+  if (argc < 2)
+    error (1, 0, "Usage: %s FILE OFFSET", argv[0]);
+
+  /* Set the ELF version.  */
+  elf_version (EV_CURRENT);
+
+  /* Open the archive.  */
+  int fd = open (argv[1], O_RDONLY);
+  if (fd < 0)
+    error (1, errno, "cannot open '%s'", argv[1]);
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    error (2, 0, "elf_begin: %s", elf_errmsg (-1));
+
+  Elf_Scn *scn = gelf_offscn (elf, strtoull (argv[2], NULL, 0));
+  if (scn == NULL)
+    error (3, 0, "gelf_offscn: %s", elf_errmsg (-1));
+
+  elf_end (elf);
+  return 0;
+}
diff --git a/tests/ecp.c b/tests/ecp.c
new file mode 100644
index 0000000..44a7bda
--- /dev/null
+++ b/tests/ecp.c
@@ -0,0 +1,99 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "system.h"
+
+int
+main (int argc, char *argv[])
+{
+  if (argc < 3)
+    error (EXIT_FAILURE, 0, "usage: %s FROMNAME TONAME", argv[0]);
+
+  elf_version (EV_CURRENT);
+
+  int infd = open (argv[1], O_RDONLY);
+  if (infd == -1)
+    error (EXIT_FAILURE, errno, "cannot open input file '%s'", argv[1]);
+
+  Elf *inelf = elf_begin (infd, ELF_C_READ, NULL);
+  if (inelf == NULL)
+    error (EXIT_FAILURE, 0, "problems opening '%s' as ELF file: %s",
+	   argv[1], elf_errmsg (-1));
+
+  int outfd = creat (argv[2], DEFFILEMODE);
+  if (outfd == -1)
+    error (EXIT_FAILURE, errno, "cannot open output file '%s'", argv[2]);
+
+  Elf *outelf = elf_begin (outfd, ELF_C_WRITE, NULL);
+  if (outelf == NULL)
+    error (EXIT_FAILURE, 0, "problems opening '%s' as ELF file: %s",
+	   argv[2], elf_errmsg (-1));
+
+  gelf_newehdr (outelf, gelf_getclass (inelf));
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr;
+  gelf_update_ehdr (outelf, (ehdr = gelf_getehdr (inelf, &ehdr_mem)));
+
+  if (ehdr->e_phnum > 0)
+    {
+      int cnt;
+
+      if (gelf_newphdr (outelf, ehdr->e_phnum) == 0)
+	error (EXIT_FAILURE, 0, "cannot create program header: %s",
+	       elf_errmsg (-1));
+
+      for (cnt = 0; cnt < ehdr->e_phnum; ++cnt)
+	{
+	  GElf_Phdr phdr_mem;
+
+	  gelf_update_phdr (outelf, cnt, gelf_getphdr (inelf, cnt, &phdr_mem));
+	}
+    }
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (inelf, scn)) != NULL)
+    {
+      Elf_Scn *newscn = elf_newscn (outelf);
+
+      GElf_Shdr shdr_mem;
+      gelf_update_shdr (newscn, gelf_getshdr (scn, &shdr_mem));
+
+      *elf_newdata (newscn) = *elf_getdata (scn, NULL);
+    }
+
+  elf_flagelf (outelf, ELF_C_SET, ELF_F_LAYOUT);
+
+  if (elf_update (outelf, ELF_C_WRITE) == -1)
+    error (EXIT_FAILURE, 0, "elf_update failed: %s", elf_errmsg (-1));
+
+  elf_end (outelf);
+  close (outfd);
+
+  elf_end (inelf);
+
+  return 0;
+}
diff --git a/tests/elf-print-reloc-syms.c b/tests/elf-print-reloc-syms.c
new file mode 100644
index 0000000..b9453f6
--- /dev/null
+++ b/tests/elf-print-reloc-syms.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2024 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <assert.h>
+
+static void
+print_reloc_symnames (Elf *elf, Elf_Scn *scn, GElf_Shdr *shdr, size_t sh_entsize)
+{
+  int nentries = shdr->sh_size / sh_entsize;
+
+  /* Get the data of the section.  */
+  Elf_Data *data = elf_getdata (scn, NULL);
+  assert (data != NULL);
+
+  /* Get the symbol table information.  */
+  Elf_Scn *symscn = elf_getscn (elf, shdr->sh_link);
+  GElf_Shdr symshdr_mem;
+  GElf_Shdr *symshdr = gelf_getshdr (symscn, &symshdr_mem);
+  Elf_Data *symdata = elf_getdata (symscn, NULL);
+  assert (symshdr != NULL);
+  assert (symdata != NULL);
+
+  /* Search for the optional extended section index table.  */
+  Elf_Data *xndxdata = NULL;
+  int xndxscnidx = elf_scnshndx (scn);
+  if (xndxscnidx)
+    xndxdata = elf_getdata (elf_getscn (elf, xndxscnidx), NULL);
+
+  /* Get the section header string table index.  */
+  size_t shstrndx;
+  assert (elf_getshdrstrndx (elf, &shstrndx) >= 0);
+
+  printf("Section: %s\n", elf_strptr (elf, shstrndx, shdr->sh_name));
+  for (int cnt = 0; cnt < nentries; ++cnt)
+    {
+      GElf_Rel relmem;
+      GElf_Rel *rel = gelf_getrel (data, cnt, &relmem);
+
+
+      if (likely (rel != NULL))
+        {
+          GElf_Sym symmem;
+          Elf32_Word xndx;
+          GElf_Sym *sym = gelf_getsymshndx (symdata, xndxdata,
+                                            GELF_R_SYM (rel->r_info),
+                                            &symmem, &xndx);
+
+	  if (sym == NULL)
+	    {
+	      printf ("<SYM NOT FOUND>\n");
+	      continue;
+	    }
+
+          if (GELF_ST_TYPE (sym->st_info) != STT_SECTION)
+            printf ("%s\n", elf_strptr (elf, symshdr->sh_link, sym->st_name));
+          else
+            {
+              /* This is a relocation against a STT_SECTION symbol.  */
+              GElf_Shdr secshdr_mem;
+              GElf_Shdr *secshdr;
+              secshdr = gelf_getshdr (elf_getscn (elf,
+                                                  sym->st_shndx == SHN_XINDEX
+                                                  ? xndx : sym->st_shndx),
+                                      &secshdr_mem);
+
+	      if (secshdr == NULL)
+		printf("<SECTION NOT FOUND>\n");
+              else
+                printf ("%s\n",
+			elf_strptr (elf, shstrndx, secshdr->sh_name));
+            }
+        }
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 2)
+    {
+      printf ("Usage: elf_print_reloc_syms FILE\n");
+      return -1;
+    }
+
+  elf_version (EV_CURRENT);
+
+  int fd = open(argv[1], O_RDONLY);
+  assert (fd != -1);
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  assert (elf != NULL);
+
+  size_t shnums;
+  assert (elf_getshdrnum (elf, &shnums) >= 0);
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+      if (shdr != NULL)
+	{
+	  /* Print the names of symbols referred to by relocations.  */
+	  if (shdr->sh_type == SHT_REL)
+	    {
+	      size_t sh_entsize = gelf_fsize (elf, ELF_T_REL, 1, EV_CURRENT);
+	      print_reloc_symnames (elf, scn, shdr, sh_entsize);
+	    }
+	  else if (shdr->sh_type == SHT_RELA)
+	    {
+	      size_t sh_entsize = gelf_fsize (elf, ELF_T_RELA, 1, EV_CURRENT);
+	      print_reloc_symnames (elf, scn, shdr, sh_entsize);
+	    }
+	}
+    }
+
+  elf_end (elf);
+  close (fd);
+  return 0;
+}
diff --git a/tests/elfcopy.c b/tests/elfcopy.c
new file mode 100644
index 0000000..10b2d36
--- /dev/null
+++ b/tests/elfcopy.c
@@ -0,0 +1,369 @@
+/* Test program for copying a whole ELF file using libelf.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+/* shstrndx is special, might overflow into section zero header sh_link.  */
+static int
+setshstrndx (Elf *elf, size_t ndx)
+{
+  printf ("setshstrndx: %zd\n", ndx);
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    return -1;
+
+  if (ndx < SHN_LORESERVE)
+    ehdr->e_shstrndx = ndx;
+  else
+    {
+      ehdr->e_shstrndx = SHN_XINDEX;
+      Elf_Scn *zscn = elf_getscn (elf, 0);
+      GElf_Shdr zshdr_mem;
+      GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
+      if (zshdr == NULL)
+	return -1;
+      zshdr->sh_link = ndx;
+      if (gelf_update_shdr (zscn, zshdr) == 0)
+	return -1;
+    }
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    return -1;
+
+  return 0;
+}
+
+/* Copies all elements of an ELF file either using mmap or read.  */
+static void
+copy_elf (const char *in, const char *out, bool use_mmap, bool reverse_offs)
+{
+  printf ("\ncopy_elf: %s -> %s (%s,%s)\n", in, out,
+	  use_mmap ? "mmap" : "read",
+	  reverse_offs ? "reverse" : "same");
+
+  /* Existing ELF file.  */
+  int fda = open (in, O_RDONLY);
+  if (fda < 0)
+    {
+      fprintf (stderr, "Couldn't open file '%s': %s\n",
+	       in, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elfa = elf_begin (fda, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elfa == NULL)
+    {
+      fprintf (stderr, "Couldn't open ELF file '%s': %s\n",
+	       in, elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Open new file.  */
+  int fdb = open (out, O_RDWR | O_CREAT | O_TRUNC, 0644);
+  if (fdb < 0)
+    {
+      fprintf (stderr, "Couldn't create file '%s': %s\n",
+	       out, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elfb = elf_begin (fdb, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+  if (elfb == NULL)
+    {
+      fprintf (stderr, "Couldn't create ELF file '%s': %s\n",
+	       out, elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Copy ELF header.
+  GElf_Ehdr ehdr_mema;
+  GElf_Ehdr *ehdra = gelf_getehdr (elfa, &ehdr_mema);
+  if (ehdra == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  int class = gelf_getclass (elfa);
+  // Create an ELF header.
+  if (gelf_newehdr (elfb, class) == 0)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* New elf header is an exact copy.  */
+  GElf_Ehdr ehdr_memb;
+  GElf_Ehdr *ehdrb = &ehdr_memb;
+  *ehdrb = *ehdra;
+  if (gelf_update_ehdr (elfb, ehdrb) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* shstrndx is special.  (Technically phdrnum and shdrnum are also
+     special, but they are handled by libelf.)  */
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elfa, &shstrndx) < 0)
+    {
+      printf ("cannot get shstrndx: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  if (setshstrndx (elfb, shstrndx) < 0)
+    {
+      printf ("cannot set shstrndx: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* If there are phdrs, copy them over.  */
+  size_t phnum;
+  if (elf_getphdrnum (elfa, &phnum) != 0)
+    {
+      printf ("cannot get phdrs: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (phnum > 0)
+    {
+      if (gelf_newphdr (elfb, phnum) == 0)
+	{
+	  printf ("cannot create phdrs: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      for (size_t cnt = 0; cnt < phnum; ++cnt)
+	{
+	  GElf_Phdr phdr_mem;
+	  GElf_Phdr *phdr = gelf_getphdr (elfa, cnt, &phdr_mem);
+	  if (phdr == NULL)
+	    {
+	      printf ("couldn't get phdr %zd: %s\n", cnt, elf_errmsg (-1));
+	      exit (1);
+	    }
+
+	  if (gelf_update_phdr (elfb, cnt, phdr) == 0)
+	    {
+	      printf ("couldn't update phdr %zd: %s\n", cnt, elf_errmsg (-1));
+	      exit (1);
+	    }
+	}
+    }
+
+  GElf_Off *offs = NULL;
+  size_t shnum;
+  if (reverse_offs)
+    {
+      if (elf_getshdrnum (elfa, &shnum) < 0)
+	{
+	  printf ("couldn't get shdrnum: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      offs = malloc (shnum * sizeof (GElf_Off));
+      if (offs == NULL)
+	{
+	  printf ("couldn't allocate memory for offs\n");
+	  exit (1);
+	}
+    }
+
+  /* Copy all sections, headers and data.  */
+  Elf_Scn *scn = NULL;
+  size_t last_off = 0;
+  GElf_Shdr last_shdr = { .sh_type = SHT_NULL };
+  while ((scn = elf_nextscn (elfa, scn)) != NULL)
+    {
+      /* Get the header.  */
+      GElf_Shdr shdr;
+      if (gelf_getshdr (scn, &shdr) == NULL)
+	{
+	  printf ("couldn't get shdr: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      if (reverse_offs)
+	{
+	  offs[last_off] = shdr.sh_offset;
+
+	  if (last_shdr.sh_type != SHT_NULL
+	      && last_shdr.sh_addralign == shdr.sh_addralign
+	      && shdr.sh_addralign == 1
+	      && last_shdr.sh_type != SHT_NOBITS
+	      && shdr.sh_type != SHT_NOBITS
+	      && last_shdr.sh_offset + last_shdr.sh_size == shdr.sh_offset
+	      && (phnum == 0
+		  || ((shdr.sh_flags & SHF_ALLOC) == 0
+		      && (last_shdr.sh_flags & SHF_ALLOC) == 0)))
+	    {
+	      printf ("Swapping offsets of section %zd and %zd\n",
+		      last_off, last_off + 1);
+	      GElf_Word off = offs[last_off - 1];
+	      offs[last_off - 1] = off + shdr.sh_size;
+	      offs[last_off] = off;
+	      last_shdr.sh_type = SHT_NULL;
+	    }
+	  else
+	    {
+	      last_shdr = shdr;
+	      offs[last_off] = shdr.sh_offset;
+	    }
+	  last_off++;
+	}
+
+      /* Create new section.  */
+      Elf_Scn *new_scn = elf_newscn (elfb);
+      if (new_scn == NULL)
+	{
+	  printf ("couldn't create new section: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      if (gelf_update_shdr (new_scn, &shdr) == 0)
+	{
+	  printf ("couldn't update shdr: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      /* Copy over section data.  */
+      Elf_Data *data = NULL;
+      while ((data = elf_getdata (scn, data)) != NULL)
+	{
+	  Elf_Data *new_data = elf_newdata (new_scn);
+	  if (new_data == NULL)
+	    {
+	      printf ("couldn't create new section data: %s\n",
+		      elf_errmsg (-1));
+	      exit (1);
+	    }
+	  *new_data = *data;
+	}
+    }
+
+  if (reverse_offs)
+    {
+      last_off = 0;
+      scn = NULL;
+      while ((scn = elf_nextscn (elfb, scn)) != NULL)
+	{
+	  GElf_Shdr shdr;
+	  if (gelf_getshdr (scn, &shdr) == NULL)
+	    {
+	      printf ("couldn't get shdr for updating: %s\n", elf_errmsg (-1));
+	      exit (1);
+	    }
+
+	  shdr.sh_offset = offs[last_off++];
+
+	  if (gelf_update_shdr (scn, &shdr) == 0)
+	    {
+	      printf ("couldn't update shdr sh_off: %s\n", elf_errmsg (-1));
+	      exit (1);
+	    }
+	}
+      free (offs);
+    }
+
+  /* Write everything to disk.  If there are any phdrs, or we want to
+     update the offsets, then we want the exact same layout.  Do we
+     want ELF_F_PERMISSIVE?  */
+  if (phnum > 0 || reverse_offs)
+    elf_flagelf (elfb, ELF_C_SET, ELF_F_LAYOUT);
+  if (elf_update (elfb, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elfa) != 0)
+    {
+      printf ("couldn't cleanup elf '%s': %s\n", in, elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (close (fda) != 0)
+    {
+      printf ("couldn't close '%s': %s\n", in, strerror (errno));
+      exit (1);
+    }
+
+  if (elf_end (elfb) != 0)
+    {
+      printf ("couldn't cleanup elf '%s': %s\n", out, elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (close (fdb) != 0)
+    {
+      printf ("couldn't close '%s': %s\n", out, strerror (errno));
+      exit (1);
+    }
+}
+
+int
+main (int argc, const char *argv[])
+{
+  elf_version (EV_CURRENT);
+
+  /* Takes the given file, and create a new identical one.  */
+  if (argc < 3 || argc > 5)
+    {
+      fprintf (stderr, "elfcopy [--mmap] [--reverse-offs] in.elf out.elf\n");
+      exit (1);
+    }
+
+  int argn = 1;
+  bool use_mmap = false;
+  if (strcmp (argv[argn], "--mmap") == 0)
+    {
+      use_mmap = true;
+      argn++;
+    }
+
+  bool reverse_offs = false;
+  if (strcmp (argv[argn], "--reverse-offs") == 0)
+    {
+      reverse_offs = true;
+      argn++;
+    }
+
+  const char *in = argv[argn++];
+  const char *out = argv[argn];
+  copy_elf (in, out, use_mmap, reverse_offs);
+
+  return 0;
+}
diff --git a/tests/elfgetchdr.c b/tests/elfgetchdr.c
new file mode 100644
index 0000000..171c4df
--- /dev/null
+++ b/tests/elfgetchdr.c
@@ -0,0 +1,126 @@
+/* Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+
+#include ELFUTILS_HEADER(elf)
+#include ELFUTILS_HEADER(dwelf)
+#include <gelf.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  elf_version (EV_CURRENT);
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+      if (elf == NULL)
+	{
+	  printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      size_t shdrstrndx;
+      if (elf_getshdrstrndx (elf, &shdrstrndx) == -1)
+	{
+	  printf ("elf_getshdrstrnd failed %s\n", elf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  int idx = elf_ndxscn (scn);
+	  GElf_Shdr shdr;
+	  if (gelf_getshdr (scn, &shdr) == NULL)
+	    {
+	      printf ("gelf_getshdr failed: %s\n", elf_errmsg (-1));
+	      result = 1;
+	      break;
+	    }
+
+	  if ((shdr.sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      GElf_Chdr chdr;
+	      if (gelf_getchdr (scn, &chdr) == NULL)
+		{
+		  printf ("gelf_getchdr failed: %s\n", elf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+
+	      printf ("section %d: ELF Compressed ch_type: %" PRId32
+		      ", ch_size: %" PRIx64 ", ch_addralign: %" PRIx64 "\n",
+		      idx, chdr.ch_type, chdr.ch_size, chdr.ch_addralign);
+	    }
+	  else
+	    {
+	      const char *sname = elf_strptr (elf, shdrstrndx, shdr.sh_name);
+	      if (sname == NULL)
+		{
+		  printf ("couldn't get section name: %s\n", elf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+
+	      /* This duplicates what the dwelfgnucompressed testcase does.  */
+	      if (startswith (sname, ".zdebug"))
+		{
+		  ssize_t size;
+		  if ((size = dwelf_scn_gnu_compressed_size (scn)) == -1)
+		    {
+		      printf ("dwelf_scn_gnu_compressed_size failed: %s\n",
+			      elf_errmsg (-1));
+		      result = 1;
+		      break;
+		    }
+		  printf ("section %d: GNU Compressed size: %zx\n", idx, size);
+		}
+	      else
+		printf ("section %d: NOT Compressed\n", idx);
+	    }
+	}
+
+      elf_end (elf);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/elfgetzdata.c b/tests/elfgetzdata.c
new file mode 100644
index 0000000..0af6c22
--- /dev/null
+++ b/tests/elfgetzdata.c
@@ -0,0 +1,173 @@
+/* Copyright (C) 2015 Red Hat, Inc.
+   Copyright (C) 2024 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include <errno.h>
+#include <gelf.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/mman.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  if (argc < 3
+      || (strcmp (argv[1], "read") != 0
+          && strcmp (argv[1], "mmap") != 0
+          && strcmp (argv[1], "mem") != 0))
+    {
+      printf ("Usage: (read|mmap|mem) files...\n");
+      return -1;
+    }
+
+  bool do_read = strcmp (argv[1], "read") == 0;
+  bool do_mmap = strcmp (argv[1], "mmap") == 0;
+  bool do_mem = strcmp (argv[1], "mem") == 0;
+
+  elf_version (EV_CURRENT);
+
+  for (cnt = 2; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+      void *map_address = NULL;
+      size_t map_size = 0;
+
+      Elf *elf;
+      if (do_read)
+	elf = elf_begin (fd, ELF_C_READ, NULL);
+      else if (do_mmap)
+	elf = elf_begin (fd, ELF_C_READ_MMAP, NULL);
+      else
+        {
+	  assert (do_mem);
+	  // We mmap the memory ourselves, explicitly PROT_READ only
+	  struct stat st;
+	  if (fstat (fd, &st) != 0)
+	    {
+	      printf ("%s cannot stat %s\n", argv[cnt], strerror (errno));
+	      result = 1;
+	      close (fd);
+	      continue;
+	    }
+	  map_size = st.st_size;
+	  map_address = mmap (NULL, map_size, PROT_READ, MAP_PRIVATE, fd, 0);
+	  if (map_address == MAP_FAILED)
+	    {
+	      printf ("%s cannot mmap %s\n", argv[cnt], strerror (errno));
+	      result = 1;
+	      close (fd);
+	      continue;
+	    }
+	  if (map_size < EI_NIDENT
+	      || memcmp (map_address, ELFMAG, SELFMAG) != 0)
+	    {
+	      printf ("%s isn't an ELF file\n", argv[cnt]);
+	      result = 1;
+	      munmap (map_address, map_size);
+	      close (fd);
+	      continue;
+	    }
+	  elf = elf_memory (map_address, map_size);
+        }
+      if (elf == NULL)
+	{
+	  printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      /* To get the section names.  */
+      size_t strndx;
+      elf_getshdrstrndx (elf, &strndx);
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  size_t idx = elf_ndxscn (scn);
+	  GElf_Shdr mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &mem);
+	  const char *name = elf_strptr (elf, strndx, shdr->sh_name);
+	  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+	    {
+	      /* Real compressed section.  */
+	      if (elf_compress (scn, 0, 0) < 0)
+		{
+		  printf ("elf_compress failed for section %zd: %s\n",
+			  idx, elf_errmsg (-1));
+		  return -1;
+		}
+	      Elf_Data *d = elf_getdata (scn, NULL);
+	      printf ("%zd: %s, ELF compressed, size: %zx\n",
+		      idx, name, d->d_size);
+	    }
+	  else
+	    {
+	      /* Maybe an old GNU compressed .z section?  */
+	      if (name[0] == '.' && name[1] == 'z')
+		{
+		  if (elf_compress_gnu (scn, 0, 0) < 0)
+		    {
+		      printf ("elf_compress_gnu failed for section %zd: %s\n",
+			      idx, elf_errmsg (-1));
+		      return -1;
+		    }
+		  Elf_Data *d = elf_getdata (scn, NULL);
+		  printf ("%zd: %s, GNU compressed, size: %zx\n",
+			  idx, name, d->d_size);
+		}
+	      else
+		printf ("%zd: %s, NOT compressed\n", idx, name);
+	    }
+	}
+
+      elf_end (elf);
+      close (fd);
+
+      if (do_mem)
+        {
+          /* Make sure we can still get at the memory.  */
+	  if (memcmp (map_address, ELFMAG, SELFMAG) != 0)
+	    {
+	      printf ("%s isn't an ELF file anymore???\n", argv[cnt]);
+	      result = 1;
+	    }
+	  if (munmap (map_address, map_size) != 0)
+	    {
+	      printf ("%s cannot munmap %s\n", argv[cnt], strerror (errno));
+	      result = 1;
+	    }
+        }
+    }
+
+  return result;
+}
diff --git a/tests/elfputzdata.c b/tests/elfputzdata.c
new file mode 100644
index 0000000..0ff363f
--- /dev/null
+++ b/tests/elfputzdata.c
@@ -0,0 +1,244 @@
+/* Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <system.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include <gelf.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  if (argc < 3
+      || (strcmp (argv[1], "elf") != 0
+	  && strcmp (argv[1], "gnu") != 0))
+    {
+      printf ("Usage: (elf|gnu) files...\n");
+      return -1;
+    }
+
+  int gnu;
+  if (strcmp (argv[1], "gnu") == 0)
+    gnu = 1;
+  else
+    gnu = 0;
+
+  elf_version (EV_CURRENT);
+
+  for (cnt = 2; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+      if (elf == NULL)
+	{
+	  printf ("%s not usable %s\n", argv[cnt], elf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      /* To get the section names.  */
+      size_t strndx;
+      elf_getshdrstrndx (elf, &strndx);
+
+      Elf_Scn *scn = NULL;
+      while ((scn = elf_nextscn (elf, scn)) != NULL)
+	{
+	  size_t idx = elf_ndxscn (scn);
+	  GElf_Shdr mem;
+	  GElf_Shdr *shdr = gelf_getshdr (scn, &mem);
+	  const char *name = elf_strptr (elf, strndx, shdr->sh_name);
+	  if (shdr->sh_type == SHT_NOBITS
+	      || (shdr->sh_flags & SHF_ALLOC) != 0)
+	    {
+	      printf ("Cannot compress %zd %s\n", idx, name);
+	    }
+	  else if ((shdr->sh_flags & SHF_COMPRESSED) != 0
+		   || startswith (name, ".zdebug"))
+	    {
+	      printf ("Already compressed %zd %s\n", idx, name);
+	    }
+	  else
+	    {
+	      size_t orig_size = shdr->sh_size;
+	      printf ("Lets compress %zd %s, size: %" PRId64 "\n",
+		      idx, name, shdr->sh_size);
+	      Elf_Data *d = elf_getdata (scn, NULL);
+	      if (d == NULL)
+		{
+		  printf ("Couldn't get orig data for section %zd\n", idx);
+		  return -1;
+		}
+	      /* Make a copy so we can compare after
+		 compression/decompression.  */
+	      if (d->d_size != orig_size)
+		{
+		  printf ("Unexpected data size for orig section %zd\n", idx);
+		  return -1;
+		}
+	      char *orig_buf = NULL;
+	      if (orig_size > 0)
+		{
+		  orig_buf = malloc (d->d_size);
+		  if (orig_buf == NULL)
+		    {
+		      printf ("No memory to copy section %zd data\n", idx);
+		      return -1;
+		    }
+		  memcpy (orig_buf, d->d_buf, orig_size);
+		}
+
+	      bool forced = false;
+	      if (gnu)
+		{
+		  int res = elf_compress_gnu (scn, 1, 0);
+		  if (res == 0)
+		    {
+		      forced = true;
+		      res = elf_compress_gnu (scn, 1, ELF_CHF_FORCE);
+		    }
+		  if (res < 0)
+		    {
+		      printf ("elf_compress_gnu%sfailed for section %zd: %s\n",
+			      forced ? " (forced) " : " ",
+			      idx, elf_errmsg (-1));
+		      return -1;
+		    }
+		}
+	      else
+		{
+		  int res = elf_compress (scn, ELFCOMPRESS_ZLIB, 0);
+		  if (res == 0)
+		    {
+		      forced = true;
+		      res = elf_compress (scn, ELFCOMPRESS_ZLIB, ELF_CHF_FORCE);
+		    }
+		  if (res < 0)
+		    {
+		      printf ("elf_compress%sfailed for section %zd: %s\n",
+			      forced ? " (forced) " : " ",
+			      idx, elf_errmsg (-1));
+		      return -1;
+		    }
+		}
+	      GElf_Shdr newmem;
+	      GElf_Shdr *newshdr = gelf_getshdr (scn, &newmem);
+	      size_t new_size = newshdr->sh_size;
+	      d = elf_getdata (scn, NULL);
+	      // Don't check this, might depend on zlib implementation.
+	      // fprintf (stderr, "  new_size: %zd\n", new_size);
+	      if (d->d_size != new_size)
+		{
+		  printf ("Unexpected data size for compressed section %zd\n",
+			  idx);
+		  return -1;
+		}
+
+	      if (forced && new_size < orig_size)
+		{
+		  printf ("section %zd forced to compress, but size smaller\n",
+			  idx);
+		  return -1;
+		}
+
+	      if (! forced && new_size >= orig_size)
+		{
+		  printf ("section %zd compressed to bigger size\n",
+			  idx);
+		  return -1;
+		}
+
+	      if (new_size == orig_size
+		  && (orig_buf == NULL
+		      || memcmp (orig_buf, d->d_buf, orig_size) == 0))
+		{
+		  printf ("section %zd didn't compress\n", idx);
+		  return -1;
+		}
+
+	      if (gnu)
+		{
+		  if (elf_compress_gnu (scn, 0, 0) < 0)
+		    {
+		      printf ("elf_[un]compress_gnu failed for section %zd: %s\n",
+			      idx, elf_errmsg (-1));
+		      return -1;
+		    }
+		}
+	      else
+		{
+		  if (elf_compress (scn, 0, 0) < 0)
+		    {
+		      printf ("elf_[un]compress failed for section %zd: %s\n",
+			      idx, elf_errmsg (-1));
+		      return -1;
+		    }
+		}
+	      GElf_Shdr newermem;
+	      GElf_Shdr *newershdr = gelf_getshdr (scn, &newermem);
+	      size_t newer_size = newershdr->sh_size;
+	      d = elf_getdata (scn, NULL);
+	      // fprintf (stderr, "  newer_size: %zd\n", newer_size);
+	      if (d->d_size != newer_size)
+		{
+		  printf ("Unexpected data size for compressed section %zd\n",
+			  idx);
+		  return -1;
+		}
+	      if (newer_size != orig_size
+		  && (orig_buf == NULL
+		      || memcmp (orig_buf, d->d_buf, orig_size) != 0))
+		{
+		  printf ("section %zd didn't correctly uncompress\n", idx);
+		  return -1;
+		}
+	      free (orig_buf);
+	      // Recompress the string table, just to make sure
+	      // everything keeps working. See elf_strptr above.
+	      if (! gnu && idx == strndx
+		  && elf_compress (scn, ELFCOMPRESS_ZLIB, 0) < 0)
+		{
+		  printf ("couldn't recompress section header strings: %s\n",
+			  elf_errmsg (-1));
+		  return -1;
+		}
+	    }
+	}
+
+      elf_end (elf);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/elfrdwrnop.c b/tests/elfrdwrnop.c
new file mode 100644
index 0000000..997150b
--- /dev/null
+++ b/tests/elfrdwrnop.c
@@ -0,0 +1,100 @@
+/* Test program for reading and writing out the same file in-place
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+int
+main (int argc, const char *argv[])
+{
+  /* Takes the given file, and create a new identical one.  */
+  if (argc != 2)
+    {
+      fprintf (stderr, "elfrdwrnop elf-file\n");
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  const char *name = argv[1];
+  printf ("elfrdwrdnop %s\n", name);
+
+  int fd = open (name, O_RDWR);
+  if (fd < 0)
+    {
+      fprintf (stderr, "Couldn't open file '%s': %s\n",
+	       name, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, ELF_C_RDWR, NULL);
+  if (elf == NULL)
+    {
+      fprintf (stderr, "Couldn't open ELF file '%s': %s\n",
+	       name, elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Write everything to disk.  If there are any phdrs, then we want
+     the exact same layout.  */
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    {
+      printf ("cannot get phdrs: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (phnum > 0)
+    elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
+
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("couldn't cleanup elf '%s': %s\n", name, elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (close (fd) != 0)
+    {
+      printf ("couldn't close '%s': %s\n", name, strerror (errno));
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/tests/elfshphehdr.c b/tests/elfshphehdr.c
new file mode 100644
index 0000000..8183937
--- /dev/null
+++ b/tests/elfshphehdr.c
@@ -0,0 +1,182 @@
+/* Test program for adding section and program headers and ehdr updates.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <stdbool.h>
+
+void
+check (const char *msg, bool statement)
+{
+  if (! statement)
+    {
+      fprintf (stderr, "%s FAILED\n", msg);
+      exit (-1);
+    }
+  else
+    fprintf (stderr, "%s OK\n", msg);
+}
+
+void
+check_elf (const char *msg, bool statement)
+{
+  if (! statement)
+    {
+      fprintf (stderr, "%s: %s\n", msg, elf_errmsg (-1));
+      exit (-1);
+    }
+  else
+    fprintf (stderr, "%s OK\n", msg);
+}
+
+void
+test (Elf *elf, int class, bool layout)
+{
+  fprintf (stderr, "testing ELF class: %d, layout: %d\n", class, layout);
+
+  check_elf ("gelf_newehdr", gelf_newehdr (elf, class) != 0);
+  check_elf ("gelf_getclass", gelf_getclass (elf) == class);
+
+  check_elf ("elf_flagelf", elf_flagelf (elf, layout ? ELF_C_SET : ELF_C_CLR,
+					 ELF_F_LAYOUT) != 0);
+
+  GElf_Ehdr ehdr;
+  check_elf ("gelf_getehdr", gelf_getehdr (elf, &ehdr) != NULL);
+  check ("e_shnum == 0", ehdr.e_shnum == 0);
+  check ("e_phnum == 0", ehdr.e_phnum == 0);
+  check ("e_shoff == 0", ehdr.e_shoff == 0);
+  check ("e_phoff == 0", ehdr.e_phoff == 0);
+
+  size_t shnum;
+  check_elf ("elf_getshdrnum", elf_getshdrnum (elf, &shnum) == 0);
+  check ("shnum == 0", shnum == 0);
+
+  size_t phnum;
+  check_elf ("elf_getphdrnum", elf_getphdrnum (elf, &phnum) == 0);
+  check ("phnum == 0", phnum == 0);
+
+  /* Lets fill in some info we are always responsible for.  */
+  ehdr.e_ident[EI_DATA] = ELFDATANONE; /* Ask for native encoding.  */
+  ehdr.e_type = ET_EXEC;
+  ehdr.e_machine = EM_386;
+  ehdr.e_version = EV_NONE; /* Ask for current version. */
+  check_elf ("gelf_update_ehdr", gelf_update_ehdr (elf, &ehdr) != 0);
+
+  check_elf ("elf_update", elf_update (elf, ELF_C_NULL) > 0);
+
+  check_elf ("gelf_getehdr", gelf_getehdr (elf, &ehdr) != NULL);
+  check ("EI_DATA", ehdr.e_ident[EI_DATA] != ELFDATANONE);
+  check ("e_version", ehdr.e_version == EV_CURRENT);
+
+  /* The sh/ph values shouldn't have changed.  */
+  check ("e_shnum == 0", ehdr.e_shnum == 0);
+  check ("e_phnum == 0", ehdr.e_phnum == 0);
+  check ("e_shoff == 0", ehdr.e_shoff == 0);
+  check ("e_phoff == 0", ehdr.e_phoff == 0);
+
+  check_elf ("elf_getshdrnum", elf_getshdrnum (elf, &shnum) == 0);
+  check ("shnum == 0", shnum == 0);
+
+  check_elf ("elf_getphdrnum", elf_getphdrnum (elf, &phnum) == 0);
+  check ("phnum == 0", phnum == 0);
+
+  /* Lets add a header.  */
+  check_elf ("elf_newscn", elf_newscn (elf) != NULL);
+  check_elf ("gelf_newphdr", gelf_newphdr (elf, 1) != 0);
+
+  /* If we are responsible for the layout ourselves we should also
+     tell where to put them.  */
+  if (layout)
+    {
+      check_elf ("gelf_getehdr", gelf_getehdr (elf, &ehdr) != NULL);
+      /* phdrs go right after the ehdr.  */
+      ehdr.e_phoff = ehdr.e_ehsize;
+      /* shdrs go right after the phdrs.  */
+      ehdr.e_shoff = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize;
+      check_elf ("gelf_update_ehdr", gelf_update_ehdr (elf, &ehdr) != 0);
+    }
+
+  check_elf ("elf_update", elf_update (elf, ELF_C_NULL) > 0);
+
+  check_elf ("elf_getshdrnum", elf_getshdrnum (elf, &shnum) == 0);
+  check ("shnum == 1", shnum == 2); /* section zero is also created.  */
+
+  check_elf ("elf_getphdrnum", elf_getphdrnum (elf, &phnum) == 0);
+  check ("phnum == 1", phnum == 1);
+
+  check_elf ("gelf_getehdr", gelf_getehdr (elf, &ehdr) != NULL);
+
+  check ("EI_DATA", ehdr.e_ident[EI_DATA] != ELFDATANONE);
+  check ("e_version", ehdr.e_version == EV_CURRENT);
+
+  check ("e_shnum == 2", ehdr.e_shnum == 2);
+  check ("e_phnum == 1", ehdr.e_phnum == 1);
+  check ("e_shoff != 0", ehdr.e_shoff != 0);
+  check ("e_phoff != 0", ehdr.e_phoff != 0);
+
+  size_t shentsize = (class == ELFCLASS32
+		      ? sizeof (Elf32_Shdr) : sizeof (Elf64_Shdr));
+  check ("e_shentsize", ehdr.e_shentsize == shentsize);
+  size_t phentsize = (class == ELFCLASS32
+		      ? sizeof (Elf32_Phdr) : sizeof (Elf64_Phdr));
+  check ("e_phentsize", ehdr.e_phentsize == phentsize);
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute ((unused)))
+{
+  elf_version (EV_CURRENT);
+
+  int fd = open("/dev/null", O_WRONLY);
+  check ("open", fd >= 0);
+
+  Elf *elf;
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  check_elf ("elf_begin", elf != NULL);
+  test (elf, ELFCLASS32, false);
+  elf_end (elf);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  check_elf ("elf_begin", elf != NULL);
+  test (elf, ELFCLASS32, true);
+  elf_end (elf);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  check_elf ("elf_begin", elf != NULL);
+  test (elf, ELFCLASS64, false);
+  elf_end (elf);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  check_elf ("elf_begin", elf != NULL);
+  test (elf, ELFCLASS64, true);
+  elf_end (elf);
+
+  close (fd);
+  return 0;
+}
diff --git a/tests/elfstrmerge.c b/tests/elfstrmerge.c
new file mode 100644
index 0000000..4eb58bb
--- /dev/null
+++ b/tests/elfstrmerge.c
@@ -0,0 +1,684 @@
+/* Merge string sections.
+   Copyright (C) 2015, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <unistd.h>
+
+#include <system.h>
+#include <gelf.h>
+#include ELFUTILS_HEADER(dwelf)
+#include "elf-knowledge.h"
+
+/* The original ELF file.  */
+static int fd = -1;
+static Elf *elf = NULL;
+static bool replace;
+
+/* The new ELF file.  */
+static char *fnew = NULL;
+static int fdnew = -1;
+static Elf *elfnew = NULL;
+
+/* The merged string table.  */
+static Dwelf_Strtab *strings = NULL;
+
+/* Section name strents.  */
+static Dwelf_Strent **scnstrents = NULL;
+
+/* Symbol name strends.  */
+static Dwelf_Strent **symstrents = NULL;
+
+/* New ELF file buffers.  */
+static Elf_Data newstrtabdata = { .d_buf = NULL };
+static size_t newshnums = 0;
+static void **newscnbufs = NULL;
+
+/* Release all files and resources allocated.  */
+static void
+release (void)
+{
+  /* The new string table.  */
+  if (strings != NULL)
+    dwelf_strtab_free (strings);
+
+  free (scnstrents);
+  free (symstrents);
+  free (newstrtabdata.d_buf);
+
+  /* Any new data buffers allocated.  */
+  for (size_t i = 0; i < newshnums; i++)
+    free (newscnbufs[i]);
+  free (newscnbufs);
+
+  /* The new ELF file.  */
+  if (fdnew != -1)
+    {
+      unlink (fnew);
+      elf_end (elfnew);
+      close (fdnew);
+    }
+  // Don't release, we might need it in the error message.
+  // if (replace)
+  //   free (fnew);
+
+  /* The original ELF file.  */
+  elf_end (elf);
+  close (fd);
+}
+
+/* The various ways we can fail... Cleanup and show some message to
+   the user.  The file name may be NULL.  */
+static void __attribute__ ((noreturn))
+fail (const char *msg, const char *fname)
+{
+  release ();
+  if (fname != NULL)
+    error (1, 0, "%s: %s", fname, msg);
+  else
+    error (1, 0, "%s", msg);
+  abort();
+}
+
+static void __attribute__ ((noreturn))
+fail_errno (const char *msg, const char *fname)
+{
+  release ();
+  if (fname != NULL)
+    error (1, errno, "%s: %s", fname, msg);
+  else
+    error (1, errno, "%s", msg);
+  abort();
+}
+
+static void __attribute__ ((noreturn))
+fail_idx (const char *msg, const char *fname, size_t idx)
+{
+  release ();
+  if (fname != NULL)
+    error (1, 0, "%s: %s %zd", fname, msg, idx);
+  else
+    error (1, 0, "%s %zd", msg, idx);
+  abort();
+}
+
+static void __attribute__ ((noreturn))
+fail_elf (const char *msg, const char *fname)
+{
+  release ();
+  if (fname != NULL)
+    error (1, 0, "%s: %s: %s", fname, msg, elf_errmsg (-1));
+  else
+    error (1, 0, "%s: %s", msg, elf_errmsg (-1));
+  abort();
+}
+
+static void __attribute__ ((noreturn))
+fail_elf_idx (const char *msg, const char *fname, size_t idx)
+{
+  release ();
+  if (fname != NULL)
+    error (1, 0, "%s: %s %zd: %s", fname, msg, idx, elf_errmsg (-1));
+  else
+    error (1, 0, "%s %zd: %s", msg, idx, elf_errmsg (-1));
+  abort();
+}
+
+/* section index mapping and sanity checking.  */
+static size_t
+newsecndx (size_t secndx, size_t shdrstrndx, size_t shdrnum,
+	   const char *fname,
+	   const char *what, size_t widx,
+	   const char *member, size_t midx)
+{
+  if (unlikely (secndx == 0 || secndx == shdrstrndx || secndx >= shdrnum))
+    {
+      /* Don't use fail... too specialized messages.  Call release
+	 ourselves and then error.  Ignores midx if widx is
+	 zero.  */
+      release ();
+      if (widx == 0)
+	error (1, 0, "%s: bad section index %zd in %s for %s",
+	       fname, secndx, what, member);
+      else if (midx == 0)
+	error (1, 0, "%s: bad section index %zd in %s %zd for %s",
+	       fname, secndx, what, widx, member);
+      else
+	error (1, 0, "%s: bad section index %zd in %s %zd for %s %zd",
+	       fname, secndx, what, widx, member, midx);
+    }
+
+  return secndx < shdrstrndx ? secndx : secndx - 1;
+}
+
+static void
+new_data_buf (Elf_Data *d, const char *fname,
+	      size_t ndx, size_t shdrstrndx, size_t shdrnum)
+{
+  size_t s = d->d_size;
+  if (s == 0)
+    fail_idx ("Expected data in section", fname, ndx);
+  void *b = malloc (d->d_size);
+  if (b == NULL)
+    fail_idx ("Couldn't allocated buffer for section", NULL, ndx);
+  newscnbufs[newsecndx (ndx, shdrstrndx, shdrnum, fname,
+			"section", ndx, "d_buf", 0)] = d->d_buf = b;
+}
+
+int
+main (int argc, char **argv)
+{
+  elf_version (EV_CURRENT);
+
+  /* Basic command line handling.  Need to replace the input file?  */
+  if ((argc != 2 && argc != 4)
+      || (argc == 4 && strcmp (argv[1], "-o") != 0))
+    fail ("Usage argument: [-o <outputfile>] <inputfile>", NULL);
+  replace = argc == 2;
+
+  /* Get the ELF file.  */
+  const char *fname;
+  if (replace)
+    fname = argv[1];
+  else
+    fname = argv[3];
+  fd = open (fname, O_RDONLY);
+  if (fd < 0)
+    fail_errno ("couldn't open", fname);
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    fail_elf ("couldn't open ELF file for reading", fname);
+
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    fail_elf ("Couldn't get ehdr", fname);
+
+  /* Get the section header string table.  */
+  size_t shdrstrndx;
+  if (elf_getshdrstrndx (elf, &shdrstrndx) != 0)
+    fail_elf ("couldn't get section header string table index", fname);
+
+  Elf_Scn *shdrstrscn = elf_getscn (elf, shdrstrndx);
+  GElf_Shdr shdrstrshdr_mem;
+  GElf_Shdr *shdrstrshdr = gelf_getshdr (shdrstrscn, &shdrstrshdr_mem);
+  if (shdrstrshdr == NULL)
+    fail_elf ("couldn't get section header string table section", fname);
+
+  if ((shdrstrshdr->sh_flags & SHF_ALLOC) != 0)
+    fail ("section header string table is an allocated section", fname);
+
+  /* Get the symtab section.  */
+  size_t symtabndx = 0;
+  Elf_Scn *symtabscn = NULL;
+  GElf_Shdr symtabshdr_mem;
+  GElf_Shdr *symtabshdr = NULL;
+  while ((symtabscn = elf_nextscn (elf, symtabscn)) != NULL)
+    {
+      symtabshdr = gelf_getshdr (symtabscn, &symtabshdr_mem);
+      if (symtabshdr == NULL)
+	fail_elf ("couldn't get shdr", fname);
+
+      if (symtabshdr->sh_type == SHT_SYMTAB)
+	{
+	  /* Just pick the first, we don't expect more than one. */
+	  symtabndx = elf_ndxscn (symtabscn);
+	  break;
+	}
+    }
+
+  if (symtabshdr == NULL)
+    fail ("No symtab found", fname);
+
+  if ((symtabshdr->sh_flags & SHF_ALLOC) != 0)
+    fail ("symtab is an allocated section", fname);
+
+  /* Get the strtab of the symtab.  */
+  size_t strtabndx = symtabshdr->sh_link;
+  Elf_Scn *strtabscn = elf_getscn (elf, strtabndx);
+  GElf_Shdr strtabshdr_mem;
+  GElf_Shdr *strtabshdr = gelf_getshdr (strtabscn, &strtabshdr_mem);
+  if (strtabshdr == NULL)
+    fail_elf ("Couldn't get strtab section", fname);
+
+  if (shdrstrndx == strtabndx)
+    {
+      error (0, 0, "%s: Nothing to do, shstrtab == strtab", fname);
+      release ();
+      return 0;
+    }
+
+  if ((strtabshdr->sh_flags & SHF_ALLOC) != 0)
+    fail ("strtab is an allocated section", fname);
+
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    fail_elf ("Couldn't get number of phdrs", fname);
+
+  /* If there are phdrs we want to maintain the layout of the
+     allocated sections in the file.  */
+  bool layout = phnum != 0;
+
+  /* Create a new merged strings table that starts with the empty string.  */
+  strings = dwelf_strtab_init (true);
+  if (strings == NULL)
+    fail ("No memory to create merged string table", NULL);
+
+  /* Add the strings from all the sections.  */
+  size_t shdrnum;
+  if (elf_getshdrnum (elf, &shdrnum) != 0)
+    fail_elf ("Couldn't get number of sections", fname);
+  scnstrents = malloc (shdrnum * sizeof (Dwelf_Strent *));
+  if (scnstrents == NULL)
+    fail ("couldn't allocate memory for section strings", NULL);
+
+  /* While going through all sections keep track of last allocated
+     offset if needed to keep the layout.  We'll put any unallocated
+     sections behind those (strtab is unallocated and will change
+     size).  */
+  GElf_Off last_offset = 0;
+  if (layout)
+    last_offset = (ehdr.e_phoff
+		   + gelf_fsize (elf, ELF_T_PHDR, phnum, EV_CURRENT));
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      size_t scnnum = elf_ndxscn (scn);
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	fail_elf_idx ("couldn't get shdr", fname, scnnum);
+      /* Don't add the .shstrtab section itself, we'll not use it.  */
+      if (shdr->sh_name != 0 && scnnum != shdrstrndx)
+	{
+	  const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+	  if (sname == NULL)
+	    fail_elf_idx ("couldn't get section name", fname, scnnum);
+	  if ((scnstrents[scnnum] = dwelf_strtab_add (strings, sname)) == NULL)
+	    fail ("No memory to add to merged string table", NULL);
+	}
+
+      if (layout)
+	if ((shdr->sh_flags & SHF_ALLOC) != 0)
+	  {
+	    GElf_Off off = shdr->sh_offset + (shdr->sh_type != SHT_NOBITS
+					      ? shdr->sh_size : 0);
+	    if (last_offset < off)
+	      last_offset = off;
+	  }
+    }
+
+  /* Add the strings from all the symbols.  */
+  size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT);
+  Elf_Data *symd = elf_getdata (symtabscn, NULL);
+  if (symd == NULL)
+    fail_elf ("couldn't get symtab data", fname);
+  size_t symsnum = symd->d_size / elsize;
+  symstrents = malloc (symsnum * sizeof (Dwelf_Strent *));
+  if (symstrents == NULL)
+    fail_errno ("Couldn't allocate memory for symbol strings", NULL);
+  for (size_t i = 0; i < symsnum; i++)
+    {
+      GElf_Sym sym_mem;
+      GElf_Sym *sym = gelf_getsym (symd, i, &sym_mem);
+      if (sym == NULL)
+	fail_elf_idx ("Couldn't get symbol", fname, i);
+      if (sym->st_name != 0)
+	{
+	  const char *sname = elf_strptr (elf, strtabndx, sym->st_name);
+	  if (sname == NULL)
+	    fail_elf_idx ("Couldn't get symbol name", fname, i);
+	  if ((symstrents[i] = dwelf_strtab_add (strings, sname)) == NULL)
+	    fail_idx ("No memory to add to merged string table symbol",
+		      fname, i);
+	}
+    }
+
+  /* We got all strings, build the new string table and store it as
+     new strtab.  */
+  dwelf_strtab_finalize (strings, &newstrtabdata);
+
+  /* We share at least the empty string so the result is at least 1
+     byte smaller.  */
+  if (newstrtabdata.d_size >= shdrstrshdr->sh_size + strtabshdr->sh_size)
+    fail ("Impossible, merged string table is larger", fname);
+
+  struct stat st;
+  if (fstat (fd, &st) != 0)
+    fail_errno("Couldn't fstat", fname);
+
+  /* Create a new (temporary) ELF file for the result.  */
+  if (replace)
+    {
+      size_t fname_len = strlen (fname);
+      fnew = malloc (fname_len + sizeof (".XXXXXX"));
+      if (fnew == NULL)
+	fail_errno ("couldn't allocate memory for new file name", NULL);
+      strcpy (mempcpy (fnew, fname, fname_len), ".XXXXXX");
+
+      fdnew = mkstemp (fnew);
+    }
+  else
+    {
+      fnew = argv[2];
+      fdnew = open (fnew, O_WRONLY | O_CREAT, st.st_mode & ALLPERMS);
+    }
+
+  if (fdnew < 0)
+    fail_errno ("couldn't create output file", fnew);
+
+  elfnew = elf_begin (fdnew, ELF_C_WRITE, NULL);
+  if (elfnew == NULL)
+    fail_elf ("couldn't open new ELF for writing", fnew);
+
+  /* Create the new ELF header and copy over all the data.  */
+  if (gelf_newehdr (elfnew, gelf_getclass (elf)) == 0)
+    fail_elf ("Couldn't create new ehdr", fnew);
+  GElf_Ehdr newehdr;
+  if (gelf_getehdr (elfnew, &newehdr) == NULL)
+    fail_elf ("Couldn't get ehdr", fnew);
+
+  newehdr.e_ident[EI_DATA] = ehdr.e_ident[EI_DATA];
+  newehdr.e_type = ehdr.e_type;
+  newehdr.e_machine = ehdr.e_machine;
+  newehdr.e_version = ehdr.e_version;
+  newehdr.e_entry = ehdr.e_entry;
+  newehdr.e_flags = ehdr.e_flags;
+
+  /* The new file uses the new strtab as shstrtab.  */
+  size_t newstrtabndx = newsecndx (strtabndx, shdrstrndx, shdrnum,
+				   fname, "ehdr", 0, "e_shstrndx", 0);
+  if (newstrtabndx < SHN_LORESERVE)
+    newehdr.e_shstrndx = newstrtabndx;
+  else
+    {
+      Elf_Scn *zscn = elf_getscn (elfnew, 0);
+      GElf_Shdr zshdr_mem;
+      GElf_Shdr *zshdr = gelf_getshdr (zscn, &zshdr_mem);
+      if (zshdr == NULL)
+	fail_elf ("Couldn't get section zero", fnew);
+      zshdr->sh_link = strtabndx;
+      if (gelf_update_shdr (zscn, zshdr) == 0)
+	fail_elf ("Couldn't update section zero", fnew);
+      newehdr.e_shstrndx = SHN_XINDEX;
+    }
+
+  if (gelf_update_ehdr (elfnew, &newehdr) == 0)
+    fail ("Couldn't update ehdr", fnew);
+
+  /* Copy the program headers if any.  */
+  if (phnum != 0)
+    {
+      if (gelf_newphdr (elfnew, phnum) == 0)
+	fail_elf ("Couldn't create phdrs", fnew);
+
+      for (size_t cnt = 0; cnt < phnum; ++cnt)
+	{
+	  GElf_Phdr phdr_mem;
+	  GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &phdr_mem);
+	  if (phdr == NULL)
+	    fail_elf_idx ("Couldn't get phdr", fname, cnt);
+	  if (gelf_update_phdr (elfnew, cnt, phdr) == 0)
+	    fail_elf_idx ("Couldn't create phdr", fnew, cnt);
+	}
+    }
+
+  newshnums = shdrnum - 1;
+  newscnbufs = calloc (newshnums, sizeof (void *));
+  if (newscnbufs == NULL)
+    fail_errno ("Couldn't allocate memory for new section buffers", NULL);
+
+  /* Copy the sections, except the shstrtab, fill the strtab with the
+     combined strings and adjust section references.  */
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      size_t ndx = elf_ndxscn (scn);
+
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	fail_elf_idx ("Couldn't get shdr", fname, ndx);
+
+      /* Section zero is always created.  Skip the shtrtab.  */
+      if (ndx == 0 || ndx == shdrstrndx)
+	continue;
+
+      Elf_Scn *newscn = elf_newscn (elfnew);
+      if (newscn == NULL)
+	fail_elf_idx ("couldn't create new section", fnew, ndx);
+
+      GElf_Shdr newshdr;
+      newshdr.sh_name = (shdr->sh_name != 0
+			 ? dwelf_strent_off (scnstrents[ndx]) : 0);
+      newshdr.sh_type = shdr->sh_type;
+      newshdr.sh_flags = shdr->sh_flags;
+      newshdr.sh_addr = shdr->sh_addr;
+      newshdr.sh_size = shdr->sh_size;
+      if (shdr->sh_link != 0)
+	newshdr.sh_link = newsecndx (shdr->sh_link, shdrstrndx, shdrnum,
+				     fname, "shdr", ndx, "sh_link", 0);
+      else
+	newshdr.sh_link = 0;
+      if (SH_INFO_LINK_P (shdr) && shdr->sh_info != 0)
+	newshdr.sh_info = newsecndx (shdr->sh_info, shdrstrndx, shdrnum,
+				     fname, "shdr", ndx, "sh_info", 0);
+
+      else
+	newshdr.sh_info = shdr->sh_info;
+      newshdr.sh_entsize = shdr->sh_entsize;
+
+      /* Some sections need a new data buffer because they need to
+	 manipulate the original data.  Allocate and check here, so we
+	 have a list of all data buffers we might need to release when
+	 done.  */
+      Elf_Data *newdata = elf_newdata (newscn);
+      if (newdata == NULL)
+	fail_elf_idx ("Couldn't create new data for section", fnew, ndx);
+      if (ndx == strtabndx)
+	*newdata = newstrtabdata;
+      else
+	{
+	  /* The symtab, dynsym, group and symtab_shndx sections
+	     contain section indexes. Symbol tables (symtab and
+	     dynsym) contain indexes to strings. Update both if
+	     necessary.  */
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    fail_elf_idx ("Couldn't get data from section", fname, ndx);
+	  *newdata = *data;
+	  switch (shdr->sh_type)
+	    {
+	    case SHT_SYMTAB:
+	    case SHT_DYNSYM:
+	      {
+		/* We need to update the section numbers of the
+		   symbols and if this symbol table uses the strtab
+		   section also the name indexes.  */
+		const bool update_name = shdr->sh_link == strtabndx;
+		if (update_name && ndx != symtabndx)
+		  fail ("Only one symbol table using strtab expected", fname);
+		new_data_buf (newdata, fname, ndx, shdrstrndx, shdrnum);
+		size_t syms = (data->d_size
+			       / gelf_fsize (elf, ELF_T_SYM, 1, EV_CURRENT));
+		for (size_t i = 0; i < syms; i++)
+		  {
+		    GElf_Sym sym;
+		    if (gelf_getsym (data, i, &sym) == NULL)
+		      fail_elf_idx ("Couldn't get symbol", fname, i);
+
+		    if (GELF_ST_TYPE (sym.st_info) == STT_SECTION
+			&& sym.st_shndx == shdrstrndx)
+		      fprintf (stderr, "WARNING:"
+			       " symbol table [%zd] contains section symbol %zd"
+			       " for old shdrstrndx %zd\n", ndx, i, shdrstrndx);
+		    else if (sym.st_shndx != SHN_UNDEF
+			     && sym.st_shndx < SHN_LORESERVE)
+		      sym.st_shndx = newsecndx (sym.st_shndx, shdrstrndx, shdrnum,
+					 fname, "section", ndx, "symbol", i);
+		    if (update_name && sym.st_name != 0)
+		      sym.st_name = dwelf_strent_off (symstrents[i]);
+
+		    /* We explicitly don't update the SHNDX table at
+		       the same time, we do that below.  */
+		    if (gelf_update_sym (newdata, i, &sym) == 0)
+		      fail_elf_idx ("Couldn't update symbol", fnew, i);
+		  }
+	      }
+	      break;
+
+	    case SHT_GROUP:
+	      {
+		new_data_buf (newdata, fname, ndx, shdrstrndx, shdrnum);
+		/* A section group contains Elf32_Words. The first
+		   word is a flag value, the rest of the words are
+		   indexes of the sections belonging to the group.  */
+		Elf32_Word *group = (Elf32_Word *) data->d_buf;
+		Elf32_Word *newgroup = (Elf32_Word *) newdata->d_buf;
+		size_t words = data->d_size / sizeof (Elf32_Word);
+		if (words == 0)
+		  fail_idx ("Not enough data in group section", fname, ndx);
+		newgroup[0] = group[0];
+		for (size_t i = 1; i < words; i++)
+		  newgroup[i] = newsecndx (group[i], shdrstrndx, shdrnum,
+					   fname, "section", ndx, "group", i);
+	      }
+	      break;
+
+	    case SHT_SYMTAB_SHNDX:
+	      {
+		new_data_buf (newdata, fname, ndx, shdrstrndx, shdrnum);
+		/* A SHNDX just contains an array of section indexes
+		   for the corresponding symbol table.  The entry is
+		   SHN_UNDEF unless the corresponding symbol is
+		   SHN_XINDEX.  */
+		Elf32_Word *shndx = (Elf32_Word *) data->d_buf;
+		Elf32_Word *newshndx = (Elf32_Word *) newdata->d_buf;
+		size_t words = data->d_size / sizeof (Elf32_Word);
+		for (size_t i = 0; i < words; i++)
+		  if (shndx[i] == SHN_UNDEF)
+		    newshndx[i] = SHN_UNDEF;
+		  else
+		    newshndx[i] = newsecndx (shndx[i], shdrstrndx, shdrnum,
+					     fname, "section", ndx, "shndx", i);
+	      }
+	      break;
+
+	    case SHT_DYNAMIC:
+	      FALLTHROUGH;
+	      /* There are string indexes in here, but
+		 they (should) point to a allocated string table,
+		 which we don't alter.  */
+	    default:
+	      /* Nothing to do.  Section data doesn't contain section
+		 or strtab indexes.  */
+	      break;
+	    }
+	}
+
+      /* When we are responsible for the layout explicitly set
+	 sh_addralign, sh_size and sh_offset.  Otherwise libelf will
+	 calculate those from the Elf_Data.  */
+      if (layout)
+	{
+	  /* We have just one Elf_Data.  */
+	  newshdr.sh_size = newdata->d_size;
+	  newshdr.sh_addralign = newdata->d_align;
+
+	  /* Keep the offset of allocated sections so they are at the
+	     same place in the file. Add unallocated ones after the
+	     allocated ones.  */
+	  if ((shdr->sh_flags & SHF_ALLOC) != 0)
+	    newshdr.sh_offset = shdr->sh_offset;
+	  else
+	    {
+	      /* Zero means one.  No alignment constraints.  */
+	      size_t addralign = newshdr.sh_addralign ?: 1;
+	      last_offset = (last_offset + addralign - 1) & ~(addralign - 1);
+	      newshdr.sh_offset = last_offset;
+	      if (newshdr.sh_type != SHT_NOBITS)
+		last_offset += newshdr.sh_size;
+	    }
+	}
+      else
+	{
+	  newshdr.sh_addralign = 0;
+	  newshdr.sh_size = 0;
+	  newshdr.sh_offset = 0;
+	}
+
+      if (gelf_update_shdr (newscn, &newshdr) == 0)
+	fail_elf_idx ("Couldn't update section header", fnew, ndx);
+    }
+
+  /* If we have phdrs we want elf_update to layout the SHF_ALLOC
+     sections precisely as in the original file.  In that case we are
+     also responsible for setting phoff and shoff */
+  if (layout)
+    {
+      /* Position the shdrs after the last (unallocated) section.  */
+      if (gelf_getehdr (elfnew, &newehdr) == NULL)
+	fail_elf ("Couldn't get ehdr", fnew);
+      const size_t offsize = gelf_fsize (elf, ELF_T_OFF, 1, EV_CURRENT);
+      newehdr.e_shoff = ((last_offset + offsize - 1)
+			 & ~((GElf_Off) (offsize - 1)));
+
+      /* The phdrs go in the same place as in the original file.
+	 Normally right after the ELF header.  */
+      newehdr.e_phoff = ehdr.e_phoff;
+
+      if (gelf_update_ehdr (elfnew, &newehdr) == 0)
+	fail_elf ("Couldn't update ehdr", fnew);
+
+      elf_flagelf (elfnew, ELF_C_SET, ELF_F_LAYOUT);
+    }
+
+  if (elf_update (elfnew, ELF_C_WRITE) == -1)
+    fail_elf ("Couldn't write ELF", fnew);
+
+  elf_end (elfnew);
+  elfnew = NULL;
+
+  /* Try to match mode and owner.group of the original file.  */
+  if (fchmod (fdnew, st.st_mode & ALLPERMS) != 0)
+    error (0, errno, "Couldn't fchmod %s", fnew);
+  if (fchown (fdnew, st.st_uid, st.st_gid) != 0)
+    error (0, errno, "Couldn't fchown %s", fnew);
+
+  /* Finally replace the old file with the new merged strings file.  */
+  if (replace)
+    if (rename (fnew, fname) != 0)
+      fail_errno ("rename", fnew);
+
+  /* We are finally done with the new file, don't unlink it now.  */
+  close (fdnew);
+  if (replace)
+    free (fnew);
+  fnew = NULL;
+  fdnew = -1;
+
+  release ();
+  return 0;
+}
diff --git a/tests/elfstrtab.c b/tests/elfstrtab.c
new file mode 100644
index 0000000..5fae37e
--- /dev/null
+++ b/tests/elfstrtab.c
@@ -0,0 +1,397 @@
+/* Test program for elf_strptr function.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+/* Index of last string added.  Returned by add_string ().  */
+static size_t stridx = 0;
+
+/* Some random strings.  */
+static char *str1;
+static size_t str1_off;
+static char *str2;
+static size_t str2_off;
+static char *str3;
+static size_t str3_off;
+
+/* First three strings we write out. They should always be there.  */
+static char *orig_str1;
+static size_t orig_str1_off;
+static char *orig_str2;
+static size_t orig_str2_off;
+static char *orig_str3;
+static size_t orig_str3_off;
+
+static void
+check_orig_strings (Elf *elf, int ndx, const char *msg)
+{
+  printf ("checking orig strings: %s\n", msg);
+
+  const char *str = elf_strptr (elf, ndx, 0);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp ("", str) != 0)
+    exit (1);
+
+  str = elf_strptr (elf, ndx, 1);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (".strings", str) != 0)
+    exit (1);
+
+  str = elf_strptr (elf, ndx, orig_str1_off);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (orig_str1, str) != 0)
+    exit (1);
+
+  str = elf_strptr (elf, ndx, orig_str2_off);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (orig_str2, str) != 0)
+    exit (1);
+
+  str = elf_strptr (elf, ndx, orig_str3_off);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (orig_str3, str) != 0)
+    exit (1);
+}
+
+static void
+check_strings (Elf *elf, int ndx, const char *msg)
+{
+  check_orig_strings (elf, ndx, msg);
+
+  const char *str = elf_strptr (elf, ndx, str1_off);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (str1, str) != 0)
+    exit (1);
+
+  str = elf_strptr (elf, ndx, str2_off);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (str2, str) != 0)
+    exit (1);
+
+  str = elf_strptr (elf, ndx, str3_off);
+  printf ("\t'%s'\n", str);
+  if (str == NULL || strcmp (str3, str) != 0)
+    exit (1);
+}
+
+/* Adds a string and returns the offset in the section.  */
+static size_t
+add_string (Elf_Scn *scn, char *str)
+{
+  size_t lastidx = stridx;
+  size_t size = strlen (str) + 1;
+  
+  Elf_Data *data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = str;
+  data->d_type = ELF_T_BYTE;
+  data->d_size = size;
+  data->d_align = 1;
+  data->d_version = EV_CURRENT;
+
+  stridx += size;
+  printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n",
+	  str, stridx, lastidx);
+  return lastidx;
+}
+
+static void
+check_elf (const char *fname, int class, int use_mmap)
+{
+  printf ("\nfname: %s\n", fname);
+  stridx = 0;
+
+  int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create an ELF header.
+  if (gelf_newehdr (elf, class) == 0)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Initialize header.
+  ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB;
+  ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+  ehdr->e_type = ET_NONE;
+  ehdr->e_machine = EM_X86_64;
+  ehdr->e_version = EV_CURRENT;
+
+  // Create strings section.
+  Elf_Scn *scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Add an empty string to the table as NUL entry for section zero.
+  add_string (scn, "");
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 1;
+  shdr->sh_entsize = 0;
+  shdr->sh_name = add_string (scn, ".strings");
+
+  // We have to store the section strtab index in the ELF header.
+  // So sections have actual names.
+  int ndx = elf_ndxscn (scn);
+  ehdr->e_shstrndx = ndx;
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Add some random strings. These are the original ones. They should
+  // always be there (together with the empty "" and .strings section
+  // name strings.
+  orig_str1 = "elfutils";
+  orig_str1_off = add_string (scn, orig_str1);
+  orig_str2 = "strtabelf";
+  orig_str2_off = add_string (scn, orig_str2);
+  orig_str3 = "three";
+  orig_str3_off = add_string (scn, orig_str3);
+
+  // Finished strings section, update the header.
+  if (gelf_update_shdr (scn, shdr) == 0)
+    {
+      printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Let the library compute the internal structure information.
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Check our strings are there.
+  check_orig_strings (elf, ndx, "first elf_update, before write");
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Check out strings are there.
+  check_orig_strings (elf, ndx, "first elf_update, after write");
+
+  // Add some more random strings.  These will not be written to disk.
+  scn = elf_getscn (elf, ndx);
+  if (scn == NULL)
+    {
+      printf ("couldn't re-get strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  str1 = "elfutils2";
+  str1_off = add_string (scn, str1);
+  str2 = "strtabelf2";
+  str2_off = add_string (scn, str2);
+  str3 = "three2";
+  str3_off = add_string (scn, str3);
+
+  // Update internal structure information again.
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in re-elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Check our new strings are there.
+  check_strings (elf, ndx, "first extra strings");
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  /* Read the ELF from disk now.  */
+  fd = open (fname, O_RDWR);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Are our strings there?  */
+  check_orig_strings (elf, ndx, "read ELF file, orig strings");
+
+  // Add some more random strings.
+  scn = elf_getscn (elf, ndx);
+  if (scn == NULL)
+    {
+      printf ("couldn't re-get strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Reset stridx to end of section.
+  printf ("sh_size: %" PRIu64 "\n", shdr->sh_size);
+  stridx = shdr->sh_size;
+
+  str1 = "0123456789";
+  str1_off = add_string (scn, str1);
+  str2 = "supercalifragilisticexpialidocious";
+  str2_off = add_string (scn, str2);
+  str3 = "forty-two";
+  str3_off = add_string (scn, str3);
+
+  // Update internal structure information.
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in rw-elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Check our new strings are there.  */
+  check_strings (elf, ndx, "read file, added strings");
+
+  // Write updated ELF file.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in re-elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  // And read it in one last time.
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Are all our strings there?  */
+  check_strings (elf, ndx, "all together now");
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
+{
+  elf_version (EV_CURRENT);
+
+  // Fill holes with something non-zero to more easily spot
+  // unterminated strings.
+  elf_fill ('X');
+
+  check_elf ("strtab.elf.32", ELFCLASS32, 0);
+  check_elf ("strtab.elf.32.mmap", ELFCLASS32, 1);
+  check_elf ("strtab.elf.64", ELFCLASS64, 0);
+  check_elf ("strtab.elf.64.mmap", ELFCLASS64, 1);
+
+  return 0;
+}
+
diff --git a/tests/emptyfile.c b/tests/emptyfile.c
new file mode 100644
index 0000000..9124c39
--- /dev/null
+++ b/tests/emptyfile.c
@@ -0,0 +1,278 @@
+/* Test program for adding a section to an empty ELF file.
+   Copyright (C) 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+/* Index of last string added.  Returned by add_string ().  */
+static size_t stridx = 0;
+
+/* Adds a string and returns the offset in the section.  */
+static size_t
+add_string (Elf_Scn *scn, char *str)
+{
+  size_t lastidx = stridx;
+  size_t size = strlen (str) + 1;
+
+  Elf_Data *data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = str;
+  data->d_type = ELF_T_BYTE;
+  data->d_size = size;
+  data->d_align = 1;
+  data->d_version = EV_CURRENT;
+
+  stridx += size;
+  printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n",
+	  str, stridx, lastidx);
+  return lastidx;
+}
+
+static void
+check_elf (const char *fname, int class, int use_mmap)
+{
+  printf ("\nfname: %s\n", fname);
+  stridx = 0; // Reset strtab strings index
+
+  int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create an ELF header.
+  if (gelf_newehdr (elf, class) == 0)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Initialize header.
+  ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB;
+  ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+  ehdr->e_type = ET_NONE;
+  ehdr->e_machine = EM_X86_64;
+  ehdr->e_version = EV_CURRENT;
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  /* Reread the ELF from disk now.  */
+  fd = open (fname, O_RDWR);
+  if (fd == -1)
+    {
+      printf ("cannot (re)open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // There are no sections yet.
+  if (elf_nextscn (elf, NULL) != NULL)
+    {
+      printf ("Empty elf had a section???\n");
+      exit (1);
+    }
+
+  // Create strtab section.
+  Elf_Scn *scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Add an empty string to the table as NUL entry for section zero.
+  add_string (scn, "");
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 1;
+  shdr->sh_entsize = 0;
+  shdr->sh_name = add_string (scn, ".strtab");
+
+  // We have to store the section strtab index in the ELF header.
+  // So sections have actual names.
+  int ndx = elf_ndxscn (scn);
+  ehdr->e_shstrndx = ndx;
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Finished strtab section, update the header.
+  if (gelf_update_shdr (scn, shdr) == 0)
+    {
+      printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  // And read it in one last time.
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Is our new section there?
+  scn = elf_nextscn (elf, NULL);
+  if (scn == NULL)
+    {
+      printf ("cannot get new section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for new section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  size_t shstrndx;
+  if (elf_getshdrstrndx (elf, &shstrndx) < 0)
+    {
+      printf ("elf_getshdrstrndx: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  const char *sname = elf_strptr (elf, shstrndx, shdr->sh_name);
+  if (sname == NULL || strcmp (sname, ".strtab") != 0)
+    {
+      printf ("Bad section name: %s\n", sname);
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)),
+      char *argv[] __attribute__ ((unused)))
+{
+  elf_version (EV_CURRENT);
+
+  check_elf ("empty.elf.32", ELFCLASS32, 0);
+  check_elf ("empty.elf.32.mmap", ELFCLASS32, 1);
+  check_elf ("empty.elf.64", ELFCLASS64, 0);
+  check_elf ("empty.elf.64.mmap", ELFCLASS64, 1);
+
+  return 0;
+}
diff --git a/tests/fillfile.c b/tests/fillfile.c
new file mode 100644
index 0000000..7f62253
--- /dev/null
+++ b/tests/fillfile.c
@@ -0,0 +1,449 @@
+/* Test program for changing data in one section (but not others) with gaps.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+
+/* Index of last string added.  Returned by add_string ().  */
+static size_t stridx = 0;
+
+/* Adds a string and returns the offset in the section.  */
+static size_t
+add_strtab_entry (Elf_Scn *strtab, const char *str)
+{
+  size_t lastidx = stridx;
+  size_t size = strlen (str) + 1;
+
+  Elf_Data *data = elf_newdata (strtab);
+  if (data == NULL)
+    {
+      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = (char *) str; /* Discards const, but we will not change. */
+  data->d_type = ELF_T_BYTE;
+  data->d_size = size;
+  data->d_align = 1;
+  data->d_version = EV_CURRENT;
+
+  stridx += size;
+  printf ("add_string: '%s', stridx: %zd, lastidx: %zd\n",
+	  str, stridx, lastidx);
+  return lastidx;
+}
+
+static Elf_Scn *
+create_strtab (Elf *elf)
+{
+  // Create strtab section.
+  Elf_Scn *scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Add an empty string to the table as NUL entry for section zero.
+  add_strtab_entry (scn, "");
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for new strtab section: %s\n",
+	      elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 1;
+  shdr->sh_entsize = 0;
+  shdr->sh_name = add_strtab_entry (scn, ".strtab");
+
+  // We have to store the section strtab index in the ELF header.
+  // So sections have actual names.
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  int ndx = elf_ndxscn (scn);
+  ehdr->e_shstrndx = ndx;
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Finished strtab section, update the header.
+  if (gelf_update_shdr (scn, shdr) == 0)
+    {
+      printf ("cannot update STRTAB section header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  return scn;
+}
+
+static char sec_data[] = { 1, 2, 3, 4, 5 };
+static char new_data[] = { 5, 4, 3, 2, 1 };
+
+static void
+add_data_section (Elf *elf, Elf_Scn *strtab, const char *sname)
+{
+  printf ("Add data section %s\n", sname);
+  Elf_Scn *scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create strings section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for new %s section: %s\n",
+	      sname, elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr->sh_type = SHT_PROGBITS;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 128;  // Large alignment to force gap between sections.
+  shdr->sh_entsize = 1;
+  shdr->sh_name = add_strtab_entry (strtab, sname);
+
+  if (gelf_update_shdr (scn, shdr) == 0)
+    {
+      printf ("cannot update %s section header: %s\n", sname, elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Add some data, but less than alignment. */
+  Elf_Data *data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot update %s section header: %s\n", sname, elf_errmsg (-1));
+      exit (1);
+    }
+  data->d_buf = sec_data;
+  data->d_size = 5;
+}
+
+static void
+check_data (const char *sname, Elf_Data *data, char *buf)
+{
+  printf ("check data %s [", sname);
+  for (int i = 0; i < 5; i++)
+    printf ("%d%s", buf[i], i < 4 ? "," : "");
+  printf ("]\n");
+  if (data == NULL || data->d_buf == NULL)
+    {
+      printf ("No data in section %s\n", sname);
+      exit (1);
+    }
+
+  if (data->d_size != 5 || memcmp (data->d_buf, buf, 5) != 0)
+    {
+      printf ("Wrong data in section %s [", sname);
+      for (size_t i = 0; i < data->d_size; i++)
+	printf ("%d%s", ((char *)data->d_buf)[i],
+		i < data->d_size - 1 ? "," : "");
+      printf ("]\n");
+      exit(1);
+    }
+}
+
+static void
+check_elf (const char *fname, int class, int use_mmap)
+{
+  printf ("\nfname: %s\n", fname);
+  stridx = 0; // Reset strtab strings index
+
+  int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create an ELF header.
+  if (gelf_newehdr (elf, class) == 0)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Initialize header.
+  ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB;
+  ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+  ehdr->e_type = ET_NONE;
+  ehdr->e_machine = EM_X86_64;
+  ehdr->e_version = EV_CURRENT;
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  Elf_Scn *strtab = create_strtab (elf);
+  add_data_section (elf, strtab, ".data1");
+  add_data_section (elf, strtab, ".data2");
+  add_data_section (elf, strtab, ".data3");
+  add_data_section (elf, strtab, ".data4");
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  /* Reread the ELF from disk now.  */
+  printf ("Rereading %s\n", fname);
+  fd = open (fname, O_RDWR);
+  if (fd == -1)
+    {
+      printf ("cannot (re)open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* We are going to change some data (in-place), but want the layout
+     to stay exactly the same. */
+  elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT);
+
+  size_t shdrstrndx;
+  if (elf_getshdrstrndx (elf, &shdrstrndx) != 0)
+    {
+      printf ("cannot get shdr str ndx\n");
+      exit (1);
+    }
+  printf ("shdrstrndx: %zd\n", shdrstrndx);
+
+  // Get third data section and change it.
+  Elf_Scn *checkscn = NULL;
+  Elf_Scn *scn = elf_nextscn (elf, NULL);
+  while (scn != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get header for section: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+      const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+      if (sname != NULL && strcmp (".data3", sname) == 0)
+	checkscn = scn;
+
+      // Get all data, but don't really use it
+      // (this triggered the original bug).
+      Elf_Data *data = elf_getdata (scn, NULL);
+      if (data != NULL && data->d_buf != NULL && data->d_size == 0)
+	{
+	  printf ("Bad data...n");
+	  exit (1);
+	}
+      scn = elf_nextscn (elf, scn);
+    }
+
+  if (checkscn == NULL)
+    {
+      printf ("ELF file doesn't have a .data3 section\n");
+      exit (1);
+    }
+
+  Elf_Data *data = elf_getdata (checkscn, NULL);
+  check_data (".data3", data, sec_data);
+  memcpy (data->d_buf, new_data, 5);
+  elf_flagdata (data, ELF_C_SET, ELF_F_DIRTY);
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  // And read it in one last time.
+  printf ("Rereading %s again\n", fname);
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Get all .data sections and check them.
+  Elf_Scn *scn1 = NULL;
+  Elf_Scn *scn2 = NULL;
+  Elf_Scn *scn3 = NULL;
+  Elf_Scn *scn4 = NULL;
+  scn = elf_nextscn (elf, NULL);
+  while (scn != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      if (shdr == NULL)
+	{
+	  printf ("cannot get header for section: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+      const char *sname = elf_strptr (elf, shdrstrndx, shdr->sh_name);
+      if (sname != NULL && strcmp (".data1", sname) == 0)
+	scn1 = scn;
+      else if (sname != NULL && strcmp (".data2", sname) == 0)
+	scn2 = scn;
+      else if (sname != NULL && strcmp (".data3", sname) == 0)
+	scn3 = scn;
+      else if (sname != NULL && strcmp (".data4", sname) == 0)
+	scn4 = scn;
+      scn = elf_nextscn (elf, scn);
+    }
+
+  if (scn1 == NULL)
+    {
+      printf ("ELF file doesn't have a .data1 section\n");
+      exit (1);
+    }
+  data = elf_getdata (scn1, NULL);
+  check_data (".data1", data, sec_data);
+
+  if (scn2 == NULL)
+    {
+      printf ("ELF file doesn't have a .data2 section\n");
+      exit (1);
+    }
+  data = elf_getdata (scn2, NULL);
+  check_data (".data2", data, sec_data);
+
+  if (scn3 == NULL)
+    {
+      printf ("ELF file doesn't have a .data3 section\n");
+      exit (1);
+    }
+  data = elf_getdata (scn3, NULL);
+  check_data (".data3", data, new_data);
+
+  if (scn4 == NULL)
+    {
+      printf ("ELF file doesn't have a .data4 section\n");
+      exit (1);
+    }
+  data = elf_getdata (scn4, NULL);
+  check_data (".data4", data, sec_data);
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)),
+      char *argv[] __attribute__ ((unused)))
+{
+  elf_version (EV_CURRENT);
+
+  elf_fill (0xA);
+
+  check_elf ("fill.elf.32", ELFCLASS32, 0);
+  check_elf ("fill.elf.32.mmap", ELFCLASS32, 1);
+  check_elf ("fill.elf.64", ELFCLASS64, 0);
+  check_elf ("fill.elf.64.mmap", ELFCLASS64, 1);
+
+  return 0;
+}
diff --git a/tests/find-prologues.c b/tests/find-prologues.c
new file mode 100644
index 0000000..b0bf936
--- /dev/null
+++ b/tests/find-prologues.c
@@ -0,0 +1,108 @@
+/* Test program for dwarf_entry_breakpoints.
+   Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fnmatch.h>
+#include "system.h"
+
+
+struct args
+{
+  Dwfl *dwfl;
+  Dwarf_Die *cu;
+  Dwarf_Addr dwbias;
+  char **argv;
+};
+
+static int
+handle_function (Dwarf_Die *func, void *arg)
+{
+  struct args *a = arg;
+
+  const char *name = dwarf_diename (func);
+  char **argv = a->argv;
+  if (argv[0] != NULL)
+    {
+      bool match;
+      do
+	match = fnmatch (*argv, name, 0) == 0;
+      while (!match && *++argv);
+      if (!match)
+	return 0;
+    }
+
+  if (dwarf_func_inline (func))
+    return 0;
+
+  Dwarf_Addr entrypc;
+  if (dwarf_entrypc (func, &entrypc) != 0)
+    error (EXIT_FAILURE, 0, "dwarf_entrypc: %s: %s",
+	   dwarf_diename (func), dwarf_errmsg (-1));
+  entrypc += a->dwbias;
+
+  printf ("%-16s %#.16" PRIx64, dwarf_diename (func), entrypc);
+
+  Dwarf_Addr *bkpts = NULL;
+  int result = dwarf_entry_breakpoints (func, &bkpts);
+  if (result <= 0)
+    printf ("\t%s\n", dwarf_errmsg (-1));
+  else
+    {
+      for (int i = 0; i < result; ++i)
+	printf (" %#.16" PRIx64 "%s", bkpts[i] + a->dwbias,
+		i == result - 1 ? "\n" : "");
+      free (bkpts);
+    }
+
+  return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  struct args a = { .dwfl = NULL, .cu = NULL };
+
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+		     &a.dwfl);
+  assert (a.dwfl != NULL);
+  a.argv = &argv[remaining];
+
+  int result = 0;
+
+  while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
+    dwarf_getfuncs (a.cu, &handle_function, &a, 0);
+
+  dwfl_end (a.dwfl);
+
+  return result;
+}
diff --git a/tests/funcretval.c b/tests/funcretval.c
new file mode 100644
index 0000000..41198ab
--- /dev/null
+++ b/tests/funcretval.c
@@ -0,0 +1,118 @@
+/* Test program for dwfl_module_return_value_location.
+   Copyright (C) 2005 Red Hat, Inc.
+   Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fnmatch.h>
+#include "system.h"
+
+
+struct args
+{
+  Dwfl *dwfl;
+  Dwarf_Die *cu;
+  Dwarf_Addr dwbias;
+  char **argv;
+};
+
+static int
+handle_function (Dwarf_Die *funcdie, void *arg)
+{
+  struct args *a = arg;
+
+  const char *name = dwarf_diename (funcdie);
+  char **argv = a->argv;
+  if (argv[0] != NULL)
+    {
+      bool match;
+      do
+	match = fnmatch (*argv, name, 0) == 0;
+      while (!match && *++argv);
+      if (!match)
+	return 0;
+    }
+
+  printf ("(%s) %s: ", dwfl_module_info (dwfl_cumodule (a->cu), NULL,
+					 NULL, NULL,
+					 NULL, NULL,
+					 NULL, NULL), name);
+
+  const Dwarf_Op *locops;
+  int nlocops = dwfl_module_return_value_location (dwfl_cumodule (a->cu),
+						   funcdie, &locops);
+  if (nlocops < 0)
+    error (EXIT_FAILURE, 0, "dwfl_module_return_value_location: %s",
+	   dwfl_errmsg (-1));
+  else if (nlocops == 0)
+    {
+      // Check if this is the special unspecified type
+      // https://sourceware.org/bugzilla/show_bug.cgi?id=30047
+      Dwarf_Die die_mem, *typedie = &die_mem;
+      Dwarf_Attribute attr_mem, *attr;
+      attr = dwarf_attr_integrate (funcdie, DW_AT_type, &attr_mem);
+      if (dwarf_formref_die (attr, typedie) != NULL
+	  && dwarf_tag (typedie) == DW_TAG_unspecified_type)
+	puts ("returns unspecified type");
+      else
+	puts ("returns no value");
+    }
+  else
+    {
+      printf ("return value location:");
+      for (int i = 0; i < nlocops; ++i)
+	printf (" {%#x, %#" PRIx64 "}", locops[i].atom, locops[i].number);
+      puts ("");
+    }
+
+  return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  struct args a = { .dwfl = NULL, .cu = NULL };
+
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+		     &a.dwfl);
+  assert (a.dwfl != NULL);
+  a.argv = &argv[remaining];
+
+  int result = 0;
+
+  while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
+    dwarf_getfuncs (a.cu, &handle_function, &a, 0);
+
+  dwfl_end (a.dwfl);
+
+  return result;
+}
diff --git a/tests/funcretval_test++11.cxx b/tests/funcretval_test++11.cxx
new file mode 100644
index 0000000..69e25bf
--- /dev/null
+++ b/tests/funcretval_test++11.cxx
@@ -0,0 +1,37 @@
+/* Copyright (C) 2023 IBM Corporation
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <utility>
+
+int &
+foo ()
+{
+  static int tmp;
+  return tmp;
+}
+
+int &&
+bar ()
+{
+  static int tmp;
+  return std::move(tmp);
+}
+
+int
+main ()
+{
+  return 0;
+}
diff --git a/tests/funcretval_test.c b/tests/funcretval_test.c
new file mode 100644
index 0000000..7e20f52
--- /dev/null
+++ b/tests/funcretval_test.c
@@ -0,0 +1,828 @@
+signed char fun_char (void) { return 5; }
+short fun_short (void) { return 6; }
+int fun_int (void) { return 7; }
+void *fun_ptr (void) { return &fun_ptr; }
+int fun_iptr (void) { return 8; }
+long fun_long (void) { return 9; }
+__int128 fun_int128 (void) { return 10; }
+
+typedef struct { int i[10]; } large_struct1_t;
+large_struct1_t fun_large_struct1 (void) {
+  large_struct1_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } };
+  return ret;
+}
+
+typedef struct { int i1; int i2; int i3; int i4; int i5;
+  int i6; int i7; int i8; int i9; int i10; } large_struct2_t;
+large_struct2_t fun_large_struct2 (void) {
+  large_struct2_t ret = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
+  return ret;
+}
+
+float fun_float (void) { return 1.5; }
+float _Complex fun_float_complex (void) { return 1.5 + 2.5i; }
+
+double fun_double (void) { return 2.5; }
+double _Complex fun_double_complex (void) { return 2.5 + 3.5i; }
+
+long double fun_long_double (void) { return 3.5; }
+long double _Complex fun_long_double_complex (void) { return 4.5 + 5.5i; }
+
+#ifdef FLOAT128
+__float128 fun_float128 (void) { return 3.5; }
+#endif
+
+// 8 byte vectors.
+
+typedef signed char __attribute__ ((vector_size (8))) vec_char_8_t;
+vec_char_8_t fun_vec_char_8 (void) {
+  vec_char_8_t ret = { 1, 2, 3, 4, 5, 6, 7, 8 };
+  return ret;
+}
+
+typedef short __attribute__ ((vector_size (8))) vec_short_8_t;
+vec_short_8_t fun_vec_short_8 (void) {
+  vec_short_8_t ret = { 2, 3, 4, 5 };
+  return ret;
+}
+
+typedef int __attribute__ ((vector_size (8))) vec_int_8_t;
+vec_int_8_t fun_vec_int_8 (void) {
+  vec_int_8_t ret = { 3, 4 };
+  return ret;
+}
+
+typedef long __attribute__ ((vector_size (8))) vec_long_8_t;
+vec_long_8_t fun_vec_long_8 (void) {
+  vec_long_8_t ret = { 5 };
+  return ret;
+}
+
+typedef float __attribute__ ((vector_size (8))) vec_float_8_t;
+vec_float_8_t fun_vec_float_8 (void) {
+  vec_float_8_t ret = { 1.5, 2.5 };
+  return ret;
+}
+
+typedef double __attribute__ ((vector_size (8))) vec_double_8_t;
+#ifndef AARCH64_BUG_1032854
+// https://bugzilla.redhat.com/show_bug.cgi?id=1032854
+vec_double_8_t fun_vec_double_8 (void) {
+  vec_double_8_t ret = { 3.5 };
+  return ret;
+}
+#endif
+
+// 16 byte vectors.
+
+typedef signed char __attribute__ ((vector_size (16))) vec_char_16_t;
+vec_char_16_t fun_vec_char_16 (void) {
+  vec_char_16_t ret = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
+  return ret;
+}
+
+typedef short __attribute__ ((vector_size (16))) vec_short_16_t;
+vec_short_16_t fun_vec_short_16 (void) {
+  vec_short_16_t ret = { 2, 3, 4, 5, 6, 7, 8 };
+  return ret;
+}
+
+typedef int __attribute__ ((vector_size (16))) vec_int_16_t;
+vec_int_16_t fun_vec_int_16 (void) {
+  vec_int_16_t ret = { 2, 3, 4 };
+  return ret;
+}
+
+typedef long __attribute__ ((vector_size (16))) vec_long_16_t;
+vec_long_16_t fun_vec_long_16 (void) {
+  vec_long_16_t ret = { 3, 4 };
+  return ret;
+}
+
+typedef __int128 __attribute__ ((vector_size (16))) vec_int128_16_t;
+vec_int128_16_t fun_vec_int128_16 (void) {
+  vec_int128_16_t ret = { 999 };
+  return ret;
+}
+
+typedef float __attribute__ ((vector_size (16))) vec_float_16_t;
+vec_float_16_t fun_vec_float_16 (void) {
+  vec_float_16_t ret = { 1.5, 2.5, 3.5, 4.5 };
+  return ret;
+}
+
+typedef double __attribute__ ((vector_size (16))) vec_double_16_t;
+vec_double_16_t fun_vec_double_16 (void) {
+  vec_double_16_t ret = { 2.5, 5 };
+  return ret;
+}
+
+#ifdef FLOAT128
+typedef __float128 __attribute__ ((vector_size (16))) vec_float128_16_t;
+vec_float128_16_t fun_vec_float128_16 (void) {
+  vec_float128_16_t ret = { 7.5 };
+  return ret;
+}
+#endif
+
+// Homogeneous floating-point aggregates.
+
+typedef struct { float f; } hfa1_float_t;
+hfa1_float_t fun_hfa1_float (void) {
+  hfa1_float_t ret = { 1.5 };
+  return ret;
+}
+
+typedef struct { double f; } hfa1_double_t;
+hfa1_double_t fun_hfa1_double (void) {
+  hfa1_double_t ret = { 3.0 };
+  return ret;
+}
+
+typedef struct { long double f; } hfa1_long_double_t;
+hfa1_long_double_t fun_hfa1_long_double (void) {
+  hfa1_long_double_t ret = { 3.0 };
+  return ret;
+}
+
+typedef struct { float f[1]; } hfa1_float_a_t;
+hfa1_float_a_t fun_hfa1_float_a (void) {
+  hfa1_float_a_t ret = { { 1.5 } };
+  return ret;
+}
+
+typedef struct { double f[1]; } hfa1_double_a_t;
+hfa1_double_a_t fun_hfa1_double_a (void) {
+  hfa1_double_a_t ret = { { 3.0 } };
+  return ret;
+}
+
+typedef struct { long double f[1]; } hfa1_long_double_a_t;
+hfa1_long_double_a_t fun_hfa1_long_double_a (void) {
+  hfa1_long_double_a_t ret = { { 3.0 } };
+  return ret;
+}
+
+typedef struct { float f; float g; } hfa2_float_t;
+hfa2_float_t fun_hfa2_float (void) {
+  hfa2_float_t ret = { 1.5, 3.0 };
+  return ret;
+}
+
+typedef struct { double f; double g; } hfa2_double_t;
+hfa2_double_t fun_hfa2_double (void) {
+  hfa2_double_t ret = { 3.0, 4.5 };
+  return ret;
+}
+
+typedef struct { long double f; long double g; } hfa2_long_double_t;
+hfa2_long_double_t fun_hfa2_long_double (void) {
+  hfa2_long_double_t ret = { 3.0, 4.5 };
+  return ret;
+}
+
+typedef struct { float f[2]; } hfa2_float_a_t;
+hfa2_float_a_t fun_hfa2_float_a (void) {
+  hfa2_float_a_t ret = { { 2.5, 3.5 } };
+  return ret;
+}
+
+typedef struct { double f[2]; } hfa2_double_a_t;
+hfa2_double_a_t fun_hfa2_double_a (void) {
+  hfa2_double_a_t ret = { { 3.0, 3.5 } };
+  return ret;
+}
+
+typedef struct { long double f[2]; } hfa2_long_double_a_t;
+hfa2_long_double_a_t fun_hfa2_long_double_a (void) {
+  hfa2_long_double_a_t ret = { { 3.0, 4.0 } };
+  return ret;
+}
+
+typedef struct { float f; float g; float h; } hfa3_float_t;
+hfa3_float_t fun_hfa3_float (void) {
+  hfa3_float_t ret = { 1.5, 3.0, 4.5 };
+  return ret;
+}
+
+typedef struct { double f; double g; double h; } hfa3_double_t;
+hfa3_double_t fun_hfa3_double (void) {
+  hfa3_double_t ret = { 3.0, 4.5, 9.5 };
+  return ret;
+}
+
+typedef struct { long double f; long double g; long double h; } hfa3_long_double_t;
+hfa3_long_double_t fun_hfa3_long_double (void) {
+  hfa3_long_double_t ret = { 3.0, 4.5, 9.5 };
+  return ret;
+}
+
+typedef struct { float f[3]; } hfa3_float_a_t;
+hfa3_float_a_t fun_hfa3_float_a (void) {
+  hfa3_float_a_t ret = { { 3.5, 4.5, 5.5 } };
+  return ret;
+}
+
+typedef struct { double f[3]; } hfa3_double_a_t;
+hfa3_double_a_t fun_hfa3_double_a (void) {
+  hfa3_double_a_t ret = { { 3.0, 3.5, 4.0 } };
+  return ret;
+}
+
+typedef struct { long double f[3]; } hfa3_long_double_a_t;
+hfa3_long_double_a_t fun_hfa3_long_double_a (void) {
+  hfa3_long_double_a_t ret = { { 3.0, 4.0, 5.0 } };
+  return ret;
+}
+
+typedef struct { float f; float g; float h; float i; } hfa4_float_t;
+hfa4_float_t fun_hfa4_float (void) {
+  hfa4_float_t ret = { 1.5, 3.5, 4.5, 9.5 };
+  return ret;
+}
+
+typedef struct { double f; double g; double h; double i; } hfa4_double_t;
+hfa4_double_t fun_hfa4_double (void) {
+  hfa4_double_t ret = { 3.5, 4.5, 9.5, 1.5 };
+  return ret;
+}
+
+typedef struct { long double f; long double g; long double h; long double i; } hfa4_long_double_t;
+hfa4_long_double_t fun_hfa4_long_double (void) {
+  hfa4_long_double_t ret = { 3.5, 4.5, 9.5, 1.5 };
+  return ret;
+}
+
+typedef struct { float f[4]; } hfa4_float_a_t;
+hfa4_float_a_t fun_hfa4_float_a (void) {
+  hfa4_float_a_t ret = { { 4.5, 5.5, 6.5, 7.5 } };
+  return ret;
+}
+
+typedef struct { double f[4]; } hfa4_double_a_t;
+hfa4_double_a_t fun_hfa4_double_a (void) {
+  hfa4_double_a_t ret = { { 3.0, 4.5, 5.0, 5.5 } };
+  return ret;
+}
+
+typedef struct { long double f[4]; } hfa4_long_double_a_t;
+hfa4_long_double_a_t fun_hfa4_long_double_a (void) {
+  hfa4_long_double_a_t ret = { { 3.0, 4.0, 5.0, 6.0 } };
+  return ret;
+}
+
+typedef struct { float f; float g; float h; float i; float j; } nfa5_float_t;
+nfa5_float_t fun_nfa5_float (void) {
+  nfa5_float_t ret = { 1.5, 3.5, 4.5, 9.5, 10.5 };
+  return ret;
+}
+
+typedef struct { double f; double g; double h; double i; double j; } nfa5_double_t;
+nfa5_double_t fun_nfa5_double (void) {
+  nfa5_double_t ret = { 3.5, 4.5, 9.5, 1.5, 2.5 };
+  return ret;
+}
+
+typedef struct { long double f; long double g; long double h; long double i; long double j; } nfa5_long_double_t;
+nfa5_long_double_t fun_nfa5_long_double (void) {
+  nfa5_long_double_t ret = { 3.5, 4.5, 9.5, 1.5, 2.5 };
+  return ret;
+}
+
+typedef struct { float f[5]; } nfa5_float_a_t;
+nfa5_float_a_t fun_nfa5_float_a (void) {
+  nfa5_float_a_t ret = { { 4.5, 5.5, 6.5, 7.5, 9.5 } };
+  return ret;
+}
+
+typedef struct { double f[5]; } nfa5_double_a_t;
+nfa5_double_a_t fun_nfa5_double_a (void) {
+  nfa5_double_a_t ret = { { 3.0, 4.5, 5.0, 5.5, 6.5 } };
+  return ret;
+}
+
+typedef struct { long double f[5]; } nfa5_long_double_a_t;
+nfa5_long_double_a_t fun_nfa5_long_double_a (void) {
+  nfa5_long_double_a_t ret = { { 3.0, 4.0, 5.0, 6.0, 7.0 } };
+  return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { __float128 f; } hfa1_float128_t;
+hfa1_float128_t fun_hfa1_float128 (void) {
+  hfa1_float128_t ret = { 4.5 };
+  return ret;
+}
+
+typedef struct { __float128 f; __float128 g; } hfa2_float128_t;
+hfa2_float128_t fun_hfa2_float128 (void) {
+  hfa2_float128_t ret = { 4.5, 9.5 };
+  return ret;
+}
+
+typedef struct { __float128 f; __float128 g; __float128 h; } hfa3_float128_t;
+hfa3_float128_t fun_hfa3_float128 (void) {
+  hfa3_float128_t ret = { 4.5, 9.5, 12.5 };
+  return ret;
+}
+
+typedef struct { __float128 f; __float128 g; __float128 h; __float128 i; } hfa4_float128_t;
+hfa4_float128_t fun_hfa4_float128 (void) {
+  hfa4_float128_t ret = { 4.5, 9.5, 3.5, 1.5 };
+  return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 1 element.
+
+typedef struct { vec_char_8_t a; } hva1_vec_char_8_t;
+hva1_vec_char_8_t fun_hva1_vec_char_8 (void) {
+  hva1_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 } };
+  return ret;
+}
+
+typedef struct { vec_short_8_t a; } hva1_vec_short_8_t;
+hva1_vec_short_8_t fun_hva1_vec_short_8 (void) {
+  hva1_vec_short_8_t ret = { { 2, 3, 4, 5 } };
+  return ret;
+}
+
+typedef struct { vec_int_8_t a; } hva1_vec_int_8_t;
+hva1_vec_int_8_t fun_hva1_vec_int_8 (void) {
+  hva1_vec_int_8_t ret = { { 3, 4 } };
+  return ret;
+}
+
+typedef struct { vec_long_8_t a; } hva1_vec_long_8_t;
+hva1_vec_long_8_t fun_hva1_vec_long_8 (void) {
+  hva1_vec_long_8_t ret = { { 5 } };
+  return ret;
+}
+
+typedef struct { vec_float_8_t a; } hva1_vec_float_8_t;
+hva1_vec_float_8_t fun_hva1_vec_float_8 (void) {
+  hva1_vec_float_8_t ret = { { 1.5, 2.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_8_t a; } hva1_vec_double_8_t;
+hva1_vec_double_8_t fun_hva1_vec_double_8 (void) {
+  hva1_vec_double_8_t ret = { { 3.5 } };
+  return ret;
+}
+
+typedef struct { vec_char_16_t a; } hva1_vec_char_16_t;
+hva1_vec_char_16_t fun_hva1_vec_char_16_t (void) {
+  hva1_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+			       9, 10, 11, 12, 13, 14, 15, 16 } };
+  return ret;
+}
+
+typedef struct { vec_short_16_t a; } hva1_vec_short_16_t;
+hva1_vec_short_16_t fun_hva1_vec_short_16_t (void) {
+  hva1_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 } };
+  return ret;
+}
+
+typedef struct { vec_int_16_t a; } hva1_vec_int_16_t;
+hva1_vec_int_16_t fun_hva1_vec_int_16_t (void) {
+  hva1_vec_int_16_t ret = { { 3, 4, 5, 6 } };
+  return ret;
+}
+
+typedef struct { vec_long_16_t a; } hva1_vec_long_16_t;
+hva1_vec_long_16_t fun_hva1_vec_long_16_t (void) {
+  hva1_vec_long_16_t ret = { { 4, 5 } };
+  return ret;
+}
+
+typedef struct { vec_int128_16_t a; } hva1_vec_int128_16_t;
+hva1_vec_int128_16_t fun_hva1_vec_int128_16_t (void) {
+  hva1_vec_int128_16_t ret = { { 6 } };
+  return ret;
+}
+
+typedef struct { vec_float_16_t a; } hva1_vec_float_16_t;
+hva1_vec_float_16_t fun_hva1_vec_float_16_t (void) {
+  hva1_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_16_t a; } hva1_vec_double_16_t;
+hva1_vec_double_16_t fun_hva1_vec_double_16_t (void) {
+  hva1_vec_double_16_t ret = { { 2.5, 3.5 } };
+  return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; } hva1_vec_float128_16_t;
+hva1_vec_float128_16_t fun_hva1_vec_float128_16_t (void) {
+  hva1_vec_float128_16_t ret = { { 4.5 } };
+  return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 2 elements.
+
+typedef struct { vec_char_8_t a; vec_char_8_t b; } hva2_vec_char_8_t;
+hva2_vec_char_8_t fun_hva2_vec_char_8 (void) {
+  hva2_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 },
+			    { 2, 3, 4, 5, 6, 7, 8, 9 } };
+  return ret;
+}
+
+typedef struct { vec_short_8_t a; vec_short_8_t b; } hva2_vec_short_8_t;
+hva2_vec_short_8_t fun_hva2_vec_short_8 (void) {
+  hva2_vec_short_8_t ret = { { 2, 3, 4, 5 },
+			     { 3, 4, 5, 6 } };
+  return ret;
+}
+
+typedef struct { vec_int_8_t a; vec_int_8_t b; } hva2_vec_int_8_t;
+hva2_vec_int_8_t fun_hva2_vec_int_8 (void) {
+  hva2_vec_int_8_t ret = { { 3, 4 },
+			   { 4, 5 } };
+  return ret;
+}
+
+typedef struct { vec_long_8_t a; vec_long_8_t b; } hva2_vec_long_8_t;
+hva2_vec_long_8_t fun_hva2_vec_long_8 (void) {
+  hva2_vec_long_8_t ret = { { 5 },
+			    { 6 } };
+  return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_float_8_t b; } hva2_vec_float_8_t;
+hva2_vec_float_8_t fun_hva2_vec_float_8 (void) {
+  hva2_vec_float_8_t ret = { { 1.5, 2.5 },
+			     { 2.5, 3.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_8_t a; vec_double_8_t b; } hva2_vec_double_8_t;
+hva2_vec_double_8_t fun_hva2_vec_double_8 (void) {
+  hva2_vec_double_8_t ret = { { 3.5 },
+			      { 4.5 } };
+  return ret;
+}
+
+typedef struct { vec_char_16_t a; vec_char_16_t b; } hva2_vec_char_16_t;
+hva2_vec_char_16_t fun_hva2_vec_char_16_t (void) {
+  hva2_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+			       9, 10, 11, 12, 13, 14, 15, 16 },
+			     { 2, 3, 4, 5, 6, 7, 8, 9,
+			       10, 11, 12, 13, 14, 15, 16, 17 } };
+  return ret;
+}
+
+typedef struct { vec_short_16_t a; vec_short_16_t b; } hva2_vec_short_16_t;
+hva2_vec_short_16_t fun_hva2_vec_short_16_t (void) {
+  hva2_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 },
+			      { 3, 4, 5, 6, 7, 8, 9, 10 } };
+  return ret;
+}
+
+typedef struct { vec_int_16_t a; vec_int_16_t b; } hva2_vec_int_16_t;
+hva2_vec_int_16_t fun_hva2_vec_int_16_t (void) {
+  hva2_vec_int_16_t ret = { { 3, 4, 5, 6 },
+			    { 4, 5, 6, 7 } };
+  return ret;
+}
+
+typedef struct { vec_long_16_t a; vec_long_16_t b; } hva2_vec_long_16_t;
+hva2_vec_long_16_t fun_hva2_vec_long_16_t (void) {
+  hva2_vec_long_16_t ret = { { 4, 5 },
+			     { 5, 6 } };
+  return ret;
+}
+
+typedef struct { vec_int128_16_t a; vec_int128_16_t b; } hva2_vec_int128_16_t;
+hva2_vec_int128_16_t fun_hva2_vec_int128_16_t (void) {
+  hva2_vec_int128_16_t ret = { { 6 },
+			       { 7 } };
+  return ret;
+}
+
+typedef struct { vec_float_16_t a; vec_float_16_t b; } hva2_vec_float_16_t;
+hva2_vec_float_16_t fun_hva2_vec_float_16_t (void) {
+  hva2_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 },
+			      { 2.5, 3.5, 4.5, 5.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_16_t a; vec_double_16_t b; } hva2_vec_double_16_t;
+hva2_vec_double_16_t fun_hva2_vec_double_16_t (void) {
+  hva2_vec_double_16_t ret = { { 2.5, 3.5 },
+			       { 3.5, 4.5 } };
+  return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; vec_float128_16_t b; } hva2_vec_float128_16_t;
+hva2_vec_float128_16_t fun_hva2_vec_float128_16_t (void) {
+  hva2_vec_float128_16_t ret = { { 4.5 },
+				 { 5.5 } };
+  return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 3 elements.
+
+typedef struct { vec_char_8_t a; vec_char_8_t b; vec_char_8_t c; } hva3_vec_char_8_t;
+hva3_vec_char_8_t fun_hva3_vec_char_8 (void) {
+  hva3_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 },
+			    { 2, 3, 4, 5, 6, 7, 8, 9 },
+			    { 3, 4, 5, 6, 7, 8, 9, 10 } };
+  return ret;
+}
+
+typedef struct { vec_short_8_t a; vec_short_8_t b; vec_short_8_t c; } hva3_vec_short_8_t;
+hva3_vec_short_8_t fun_hva3_vec_short_8 (void) {
+  hva3_vec_short_8_t ret = { { 2, 3, 4, 5 },
+			     { 3, 4, 5, 6 },
+			     { 4, 5, 6, 7 } };
+  return ret;
+}
+
+typedef struct { vec_int_8_t a; vec_int_8_t b; vec_int_8_t c; } hva3_vec_int_8_t;
+hva3_vec_int_8_t fun_hva3_vec_int_8 (void) {
+  hva3_vec_int_8_t ret = { { 3, 4 },
+			   { 4, 5 },
+			   { 5, 6 } };
+  return ret;
+}
+
+typedef struct { vec_long_8_t a; vec_long_8_t b; vec_long_8_t c; } hva3_vec_long_8_t;
+hva3_vec_long_8_t fun_hva3_vec_long_8 (void) {
+  hva3_vec_long_8_t ret = { { 5 },
+			    { 6 },
+			    { 7 } };
+  return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_float_8_t b; vec_float_8_t c; } hva3_vec_float_8_t;
+hva3_vec_float_8_t fun_hva3_vec_float_8 (void) {
+  hva3_vec_float_8_t ret = { { 1.5, 2.5 },
+			     { 2.5, 3.5 },
+			     { 3.5, 4.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_8_t a; vec_double_8_t b; vec_double_8_t c; } hva3_vec_double_8_t;
+hva3_vec_double_8_t fun_hva3_vec_double_8 (void) {
+  hva3_vec_double_8_t ret = { { 3.5 },
+			      { 4.5 },
+			      { 5.5 } };
+  return ret;
+}
+
+typedef struct { vec_char_16_t a; vec_char_16_t b; vec_char_16_t c; } hva3_vec_char_16_t;
+hva3_vec_char_16_t fun_hva3_vec_char_16_t (void) {
+  hva3_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+			       9, 10, 11, 12, 13, 14, 15, 16 },
+			     { 2, 3, 4, 5, 6, 7, 8, 9,
+			       10, 11, 12, 13, 14, 15, 16, 17 },
+			     { 3, 4, 5, 6, 7, 8, 9, 10,
+			       11, 12, 13, 14, 15, 16, 17, 18 } };
+  return ret;
+}
+
+typedef struct { vec_short_16_t a; vec_short_16_t b; vec_short_16_t c; } hva3_vec_short_16_t;
+hva3_vec_short_16_t fun_hva3_vec_short_16_t (void) {
+  hva3_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 },
+			      { 3, 4, 5, 6, 7, 8, 9, 10 },
+			      { 4, 5, 6, 7, 8, 9, 10, 11 } };
+  return ret;
+}
+
+typedef struct { vec_int_16_t a; vec_int_16_t b; vec_int_16_t c; } hva3_vec_int_16_t;
+hva3_vec_int_16_t fun_hva3_vec_int_16_t (void) {
+  hva3_vec_int_16_t ret = { { 3, 4, 5, 6 },
+			    { 4, 5, 6, 7 },
+			    { 5, 6, 7, 8 } };
+  return ret;
+}
+
+typedef struct { vec_long_16_t a; vec_long_16_t b; vec_long_16_t c; } hva3_vec_long_16_t;
+hva3_vec_long_16_t fun_hva3_vec_long_16_t (void) {
+  hva3_vec_long_16_t ret = { { 3, 4 },
+			     { 4, 5 },
+			     { 5, 6 } };
+  return ret;
+}
+
+typedef struct { vec_int128_16_t a; vec_int128_16_t b; vec_int128_16_t c; } hva3_vec_int128_16_t;
+hva3_vec_int128_16_t fun_hva3_vec_int128_16_t (void) {
+  hva3_vec_int128_16_t ret = { { 6 },
+			       { 7 },
+			       { 8 } };
+  return ret;
+}
+
+typedef struct { vec_float_16_t a; vec_float_16_t b; vec_float_16_t c; } hva3_vec_float_16_t;
+hva3_vec_float_16_t fun_hva3_vec_float_16_t (void) {
+  hva3_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 },
+			      { 2.5, 3.5, 4.5, 5.5 },
+			      { 3.5, 4.5, 5.5, 6.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_16_t a; vec_double_16_t b; vec_double_16_t c; } hva3_vec_double_16_t;
+hva3_vec_double_16_t fun_hva3_vec_double_16_t (void) {
+  hva3_vec_double_16_t ret = { { 2.5, 3.5 },
+			       { 3.5, 4.5 },
+			       { 4.5, 5.5 } };
+  return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; vec_float128_16_t b; vec_float128_16_t c; } hva3_vec_float128_16_t;
+hva3_vec_float128_16_t fun_hva3_vec_float128_16_t (void) {
+  hva3_vec_float128_16_t ret = { { 4.5 },
+				 { 5.5 },
+				 { 6.5 } };
+  return ret;
+}
+#endif
+
+// Homogeneous vector aggregates of 3 elements.
+
+typedef struct { vec_char_8_t a; vec_char_8_t b; vec_char_8_t c; vec_char_8_t d; } hva4_vec_char_8_t;
+hva4_vec_char_8_t fun_hva4_vec_char_8 (void) {
+  hva4_vec_char_8_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8 },
+			    { 2, 3, 4, 5, 6, 7, 8, 9 },
+			    { 3, 4, 5, 6, 7, 8, 9, 10 },
+			    { 4, 5, 6, 7, 8, 9, 10, 11 } };
+  return ret;
+}
+
+typedef struct { vec_short_8_t a; vec_short_8_t b; vec_short_8_t c; vec_short_8_t d; } hva4_vec_short_8_t;
+hva4_vec_short_8_t fun_hva4_vec_short_8 (void) {
+  hva4_vec_short_8_t ret = { { 2, 3, 4, 5 },
+			     { 3, 4, 5, 6 },
+			     { 4, 5, 6, 7 },
+			     { 5, 6, 7, 8 } };
+  return ret;
+}
+
+typedef struct { vec_int_8_t a; vec_int_8_t b; vec_int_8_t c; vec_int_8_t d; } hva4_vec_int_8_t;
+hva4_vec_int_8_t fun_hva4_vec_int_8 (void) {
+  hva4_vec_int_8_t ret = { { 3, 4 },
+			   { 4, 5 },
+			   { 5, 6 },
+			   { 6, 7 } };
+  return ret;
+}
+
+typedef struct { vec_long_8_t a; vec_long_8_t b; vec_long_8_t c; vec_long_8_t d; } hva4_vec_long_8_t;
+hva4_vec_long_8_t fun_hva4_vec_long_8 (void) {
+  hva4_vec_long_8_t ret = { { 5 },
+			    { 6 },
+			    { 7 },
+			    { 8 } };
+  return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_float_8_t b; vec_float_8_t c; vec_float_8_t d; } hva4_vec_float_8_t;
+hva4_vec_float_8_t fun_hva4_vec_float_8 (void) {
+  hva4_vec_float_8_t ret = { { 1.5, 2.5 },
+			     { 2.5, 3.5 },
+			     { 3.5, 4.5 },
+			     { 4.5, 5.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_8_t a; vec_double_8_t b; vec_double_8_t c; vec_double_8_t d; } hva4_vec_double_8_t;
+hva4_vec_double_8_t fun_hva4_vec_double_8 (void) {
+  hva4_vec_double_8_t ret = { { 3.5 },
+			      { 4.5 },
+			      { 5.5 },
+			      { 6.5 } };
+  return ret;
+}
+
+typedef struct { vec_char_16_t a; vec_char_16_t b; vec_char_16_t c; vec_char_16_t d; } hva4_vec_char_16_t;
+hva4_vec_char_16_t fun_hva4_vec_char_16_t (void) {
+  hva4_vec_char_16_t ret = { { 1, 2, 3, 4, 5, 6, 7, 8,
+			       9, 10, 11, 12, 13, 14, 15, 16 },
+			     { 2, 3, 4, 5, 6, 7, 8, 9,
+			       10, 11, 12, 13, 14, 15, 16, 17 },
+			     { 3, 4, 5, 6, 7, 8, 9, 10,
+			       11, 12, 13, 14, 15, 16, 17, 18 },
+			     { 4, 5, 6, 7, 8, 9, 10, 11,
+			       12, 13, 14, 15, 16, 17, 18, 19 } };
+  return ret;
+}
+
+typedef struct { vec_short_16_t a; vec_short_16_t b; vec_short_16_t c; vec_short_16_t d; } hva4_vec_short_16_t;
+hva4_vec_short_16_t fun_hva4_vec_short_16_t (void) {
+  hva4_vec_short_16_t ret = { { 2, 3, 4, 5, 6, 7, 8, 9 },
+			      { 3, 4, 5, 6, 7, 8, 9, 10 },
+			      { 4, 5, 6, 7, 8, 9, 10, 11 },
+			      { 5, 6, 7, 8, 9, 10, 11, 12 } };
+  return ret;
+}
+
+typedef struct { vec_int_16_t a; vec_int_16_t b; vec_int_16_t c; vec_int_16_t d; } hva4_vec_int_16_t;
+hva4_vec_int_16_t fun_hva4_vec_int_16_t (void) {
+  hva4_vec_int_16_t ret = { { 3, 4, 5, 6 },
+			    { 4, 5, 6, 7 },
+			    { 5, 6, 7, 8 },
+			    { 6, 7, 8, 9 } };
+  return ret;
+}
+
+typedef struct { vec_long_16_t a; vec_long_16_t b; vec_long_16_t c; vec_long_16_t d; } hva4_vec_long_16_t;
+hva4_vec_long_16_t fun_hva4_vec_long_16_t (void) {
+  hva4_vec_long_16_t ret = { { 3, 4 },
+			     { 4, 5 },
+			     { 5, 6 },
+			     { 6, 7 } };
+  return ret;
+}
+
+typedef struct { vec_int128_16_t a; vec_int128_16_t b; vec_int128_16_t c; vec_int128_16_t d; } hva4_vec_int128_16_t;
+hva4_vec_int128_16_t fun_hva4_vec_int128_16_t (void) {
+  hva4_vec_int128_16_t ret = { { 6 },
+			       { 7 },
+			       { 8 },
+			       { 9 } };
+  return ret;
+}
+
+typedef struct { vec_float_16_t a; vec_float_16_t b; vec_float_16_t c; vec_float_16_t d; } hva4_vec_float_16_t;
+hva4_vec_float_16_t fun_hva4_vec_float_16_t (void) {
+  hva4_vec_float_16_t ret = { { 1.5, 2.5, 3.5, 4.5 },
+			      { 2.5, 3.5, 4.5, 5.5 },
+			      { 3.5, 4.5, 5.5, 6.5 },
+			      { 4.5, 5.5, 6.5, 7.5 } };
+  return ret;
+}
+
+typedef struct { vec_double_16_t a; vec_double_16_t b; vec_double_16_t c; vec_double_16_t d; } hva4_vec_double_16_t;
+hva4_vec_double_16_t fun_hva4_vec_double_16_t (void) {
+  hva4_vec_double_16_t ret = { { 2.5, 3.5 },
+			       { 3.5, 4.5 },
+			       { 4.5, 5.5 },
+			       { 5.5, 6.5 } };
+  return ret;
+}
+
+#ifdef FLOAT128
+typedef struct { vec_float128_16_t a; vec_float128_16_t b; vec_float128_16_t c; vec_float128_16_t d; } hva4_vec_float128_16_t;
+hva4_vec_float128_16_t fun_hva4_vec_float128_16_t (void) {
+  hva4_vec_float128_16_t ret = { { 4.5 },
+				 { 5.5 },
+				 { 6.5 },
+				 { 7.5 } };
+  return ret;
+}
+#endif
+
+// Mixed HFA.
+typedef struct { float _Complex a; float b; } mixed_hfa3_cff_t;
+mixed_hfa3_cff_t fun_mixed_hfa3_cff (void) {
+  mixed_hfa3_cff_t ret = { 1.5 + 2.5i, 3.5 };
+  return ret;
+}
+
+typedef struct { double _Complex a; double b; } mixed_hfa3_cdd_t;
+mixed_hfa3_cdd_t fun_mixed_hfa3_cdd (void) {
+  mixed_hfa3_cdd_t ret = { 1.5 + 2.5i, 3.5 };
+  return ret;
+}
+
+typedef struct { long double _Complex a; long double b; } mixed_hfa3_cldld_t;
+mixed_hfa3_cldld_t fun_mixed_hfa3_cldld (void) {
+  mixed_hfa3_cldld_t ret = { 1.5 + 2.5i, 3.5 };
+  return ret;
+}
+
+typedef struct { float b; float _Complex a; } mixed_hfa3_fcf_t;
+mixed_hfa3_fcf_t fun_mixed_hfa3_fcf (void) {
+  mixed_hfa3_fcf_t ret = { 3.5, 1.5 + 2.5i };
+  return ret;
+}
+
+typedef struct { double b; double _Complex a; } mixed_hfa3_dcd_t;
+mixed_hfa3_dcd_t fun_mixed_hfa3_dcd (void) {
+  mixed_hfa3_dcd_t ret = { 3.5, 1.5 + 2.5i };
+  return ret;
+}
+
+typedef struct { long double b; long double _Complex a; } mixed_hfa3_ldcld_t;
+mixed_hfa3_ldcld_t fun_mixed_hfa3_ldcld (void) {
+  mixed_hfa3_ldcld_t ret = { 3.5, 1.5 + 2.5i };
+  return ret;
+}
+
+typedef struct { vec_float_8_t a; vec_short_8_t b; } mixed_hfa2_fltsht_t;
+mixed_hfa2_fltsht_t fun_mixed_hfa2_fltsht_t (void) {
+  mixed_hfa2_fltsht_t ret = { { 3.5, 4.5 }, { 1, 2, 3, 4 } };
+  return ret;
+}
+
+int main(int argc, char *argv[])
+{
+  return 0;
+}
diff --git a/tests/funcretval_test_aarch64.bz2 b/tests/funcretval_test_aarch64.bz2
new file mode 100755
index 0000000..5494e10
--- /dev/null
+++ b/tests/funcretval_test_aarch64.bz2
Binary files differ
diff --git a/tests/funcscopes.c b/tests/funcscopes.c
new file mode 100644
index 0000000..689d376
--- /dev/null
+++ b/tests/funcscopes.c
@@ -0,0 +1,195 @@
+/* Test program for dwarf_getscopes.
+   Copyright (C) 2005, 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fnmatch.h>
+#include "system.h"
+
+
+static void
+paddr (const char *prefix, Dwarf_Addr addr, Dwfl_Line *line)
+{
+  const char *src;
+  int lineno, linecol;
+  if (line != NULL
+      && (src = dwfl_lineinfo (line, &addr, &lineno, &linecol,
+			       NULL, NULL)) != NULL)
+    {
+      if (linecol != 0)
+	printf ("%s%#" PRIx64 " (%s:%d:%d)",
+		prefix, addr, src, lineno, linecol);
+      else
+	printf ("%s%#" PRIx64 " (%s:%d)",
+		prefix, addr, src, lineno);
+    }
+  else
+    printf ("%s%#" PRIx64, prefix, addr);
+}
+
+
+static void
+print_vars (unsigned int indent, Dwarf_Die *die)
+{
+  Dwarf_Die child;
+  if (dwarf_child (die, &child) == 0)
+    do
+      switch (dwarf_tag (&child))
+	{
+	case DW_TAG_variable:
+	case DW_TAG_formal_parameter:
+	  printf ("%*s%-30s[%6" PRIx64 "]\n", indent, "",
+		  dwarf_diename (&child),
+		  (uint64_t) dwarf_dieoffset (&child));
+	  break;
+	default:
+	  break;
+	}
+    while (dwarf_siblingof (&child, &child) == 0);
+
+  Dwarf_Attribute attr_mem;
+  Dwarf_Die origin;
+  if (dwarf_hasattr (die, DW_AT_abstract_origin)
+      && dwarf_formref_die (dwarf_attr (die, DW_AT_abstract_origin, &attr_mem),
+			    &origin) != NULL
+      && dwarf_child (&origin, &child) == 0)
+    do
+      switch (dwarf_tag (&child))
+	{
+	case DW_TAG_variable:
+	case DW_TAG_formal_parameter:
+	  printf ("%*s%s (abstract)\n", indent, "",
+		  dwarf_diename (&child));
+	  break;
+	default:
+	  break;
+	}
+    while (dwarf_siblingof (&child, &child) == 0);
+}
+
+
+#define INDENT 4
+
+struct args
+{
+  Dwfl *dwfl;
+  Dwarf_Die *cu;
+  Dwarf_Addr dwbias;
+  char **argv;
+};
+
+static int
+handle_function (Dwarf_Die *funcdie, void *arg)
+{
+  struct args *a = arg;
+
+  const char *name = dwarf_diename (funcdie);
+  char **argv = a->argv;
+  if (argv[0] != NULL)
+    {
+      bool match;
+      do
+	match = fnmatch (*argv, name, 0) == 0;
+      while (!match && *++argv);
+      if (!match)
+	return 0;
+    }
+
+  Dwarf_Die *scopes;
+  int n = dwarf_getscopes_die (funcdie, &scopes);
+  if (n <= 0)
+    error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
+  else
+    {
+      Dwarf_Addr start, end;
+      const char *fname;
+      const char *modname = dwfl_module_info (dwfl_cumodule (a->cu), NULL,
+					      &start, &end,
+					      NULL, NULL,
+					      &fname, NULL);
+      if (modname == NULL)
+	error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
+      if (modname[0] == '\0')
+	modname = fname;
+      printf ("%s: %#" PRIx64 " .. %#" PRIx64 "\n", modname, start, end);
+
+      unsigned int indent = 0;
+      while (n-- > 0)
+	{
+	  Dwarf_Die *const die = &scopes[n];
+
+	  indent += INDENT;
+	  printf ("%*s%s (%#x)", indent, "",
+		  dwarf_diename (die) ?: "<unnamed>",
+		  dwarf_tag (die));
+
+	  Dwarf_Addr lowpc, highpc;
+	  if (dwarf_lowpc (die, &lowpc) == 0
+	      && dwarf_highpc (die, &highpc) == 0)
+	    {
+	      lowpc += a->dwbias;
+	      highpc += a->dwbias;
+	      Dwfl_Line *loline = dwfl_getsrc (a->dwfl, lowpc);
+	      Dwfl_Line *hiline = dwfl_getsrc (a->dwfl, highpc - 1);
+	      paddr (": ", lowpc, loline);
+	      if (highpc != lowpc)
+		paddr (" .. ", highpc - 1, hiline == loline ? NULL : hiline);
+	    }
+	  puts ("");
+
+	  print_vars (indent + INDENT, die);
+	}
+      free (scopes);
+    }
+
+  return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  struct args a = { .dwfl = NULL, .cu = NULL };
+
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+		     &a.dwfl);
+  assert (a.dwfl != NULL);
+  a.argv = &argv[remaining];
+
+  int result = 0;
+
+  while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
+    dwarf_getfuncs (a.cu, &handle_function, &a, 0);
+
+  dwfl_end (a.dwfl);
+
+  return result;
+}
diff --git a/tests/get-aranges.c b/tests/get-aranges.c
new file mode 100644
index 0000000..7f85cda
--- /dev/null
+++ b/tests/get-aranges.c
@@ -0,0 +1,142 @@
+/* Copyright (C) 2002, 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+
+
+static const Dwarf_Addr testaddr[] =
+{
+  0x804842b, 0x804842c, 0x804843c, 0x8048459, 0x804845a,
+  0x804845b, 0x804845c, 0x8048460, 0x8048465, 0x8048466,
+  0x8048467, 0x8048468, 0x8048470, 0x8048471, 0x8048472
+};
+#define ntestaddr (sizeof (testaddr) / sizeof (testaddr[0]))
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable\n", argv[cnt]);
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      Dwarf_Aranges *aranges;
+      size_t naranges;
+      if (dwarf_getaranges (dbg, &aranges, &naranges) != 0)
+	printf ("%s: cannot get aranges\n", argv[cnt]);
+      else
+	{
+	  for (size_t i = 0; i < ntestaddr; ++i)
+	    {
+	      Dwarf_Arange *found;
+
+	      found = dwarf_getarange_addr (aranges, testaddr[i]);
+	      if (found != NULL)
+		{
+		  Dwarf_Off cu_offset;
+
+		  if (dwarf_getarangeinfo (found, NULL, NULL, &cu_offset) != 0)
+		    {
+		      puts ("failed to get CU die offset");
+		      result = 1;
+		    }
+		  else
+		    {
+		      const char *cuname;
+		      Dwarf_Die cu_die;
+
+		      if (dwarf_offdie (dbg, cu_offset, &cu_die) == NULL
+			  || (cuname = dwarf_diename (&cu_die)) == NULL)
+			{
+			  puts ("failed to get CU die");
+			  result = 1;
+			}
+		      else
+			printf ("CU name: \"%s\"\n", cuname);
+		    }
+		}
+	      else
+		printf ("%#llx: not in range\n",
+			(unsigned long long int) testaddr[i]);
+	    }
+
+	  for (size_t i = 0; i < naranges; ++i)
+	    {
+	      Dwarf_Arange *arange = dwarf_onearange (aranges, i);
+	      if (arange == NULL)
+		{
+		  printf ("cannot get arange %zu: %s\n", i, dwarf_errmsg (-1));
+		  break;
+		}
+
+	      Dwarf_Addr start;
+	      Dwarf_Word length;
+	      Dwarf_Off cu_offset;
+
+	      if (dwarf_getarangeinfo (arange, &start, &length, &cu_offset)
+		  != 0)
+		{
+		  printf ("cannot get info from aranges[%zu]\n", i);
+		  result = 1;
+		}
+	      else
+		{
+		  printf (" [%2zu] start: %#llx, length: %llu, cu: %llu\n",
+			  i, (unsigned long long int) start,
+			  (unsigned long long int) length,
+			  (unsigned long long int) cu_offset);
+
+		  const char *cuname;
+		  Dwarf_Die cu_die;
+		  if (dwarf_offdie (dbg, cu_offset, &cu_die) == NULL
+		      || (cuname = dwarf_diename (&cu_die)) == NULL)
+		    {
+		      puts ("failed to get CU die");
+		      result = 1;
+		    }
+		  else
+		    printf ("CU name: \"%s\"\n", cuname);
+		}
+	    }
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/get-files.c b/tests/get-files.c
new file mode 100644
index 0000000..0409173
--- /dev/null
+++ b/tests/get-files.c
@@ -0,0 +1,107 @@
+/* Copyright (C) 2002, 2004, 2005, 2007 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable\n", argv[cnt]);
+	  result = 1;
+	  if (fd != -1)
+	    close (fd);
+	  continue;
+	}
+
+      Dwarf_Off o = 0;
+      Dwarf_Off ncu;
+      Dwarf_Off ao;
+      size_t cuhl;
+      uint8_t asz;
+      uint8_t osz;
+      while (dwarf_nextcu (dbg, o, &ncu, &cuhl, &ao, &asz, &osz) == 0)
+	{
+	  printf ("cuhl = %zu, o = %llu, asz = %hhu, osz = %hhu, ncu = %llu\n",
+		  cuhl, (unsigned long long int) ao,
+		  asz, osz, (unsigned long long int) ncu);
+
+	  Dwarf_Die die_mem;
+	  Dwarf_Die *die = dwarf_offdie (dbg, o + cuhl, &die_mem);
+	  if (die == NULL)
+	    {
+	      printf ("%s: cannot get CU die\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+
+	  Dwarf_Files *files;
+	  size_t nfiles;
+	  if (dwarf_getsrcfiles (die, &files, &nfiles) != 0)
+	    {
+	      printf ("%s: cannot get files\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+
+	  const char *const *dirs;
+	  size_t ndirs;
+	  if (dwarf_getsrcdirs (files, &dirs, &ndirs) != 0)
+	    {
+	      printf ("%s: cannot get include directories\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+
+	  if (dirs[0] == NULL)
+	    puts (" dirs[0] = (null)");
+	  else
+	    printf (" dirs[0] = \"%s\"\n", dirs[0]);
+	  for (size_t i = 1; i < ndirs; ++i)
+	    printf (" dirs[%zu] = \"%s\"\n", i, dirs[i]);
+
+	  for (size_t i = 0; i < nfiles; ++i)
+	    printf (" file[%zu] = \"%s\"\n", i,
+		    dwarf_filesrc (files, i, NULL, NULL));
+
+	  o = ncu;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/get-lines.c b/tests/get-lines.c
new file mode 100644
index 0000000..188d016
--- /dev/null
+++ b/tests/get-lines.c
@@ -0,0 +1,160 @@
+/* Copyright (C) 2002, 2004 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if  (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  close  (fd);
+	  continue;
+	}
+
+      Dwarf_Off cuoff = 0;
+      Dwarf_Off old_cuoff = 0;
+      size_t hsize;
+      Dwarf_Off ao;
+      uint8_t asz;
+      uint8_t osz;
+      while (dwarf_nextcu (dbg, cuoff, &cuoff, &hsize, &ao, &asz, &osz) == 0)
+	{
+	  printf ("cuhl = %zu, o = %llu, asz = %hhu, osz = %hhu, ncu = %llu\n",
+		  hsize, (unsigned long long int) ao,
+		  asz, osz, (unsigned long long int) cuoff);
+
+	  /* Get the DIE for the CU.  */
+	  Dwarf_Die die;
+ 	  if (dwarf_offdie (dbg, old_cuoff + hsize, &die) == NULL)
+	    {
+	      /* Something went wrong.  */
+	      printf ("%s: cannot get CU die\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+	  old_cuoff = cuoff;
+
+	  Dwarf_Lines *lb;
+	  size_t nlb;
+	  if (dwarf_getsrclines (&die, &lb, &nlb) != 0)
+	    {
+	      printf ("%s: cannot get lines\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+
+	  printf (" %zu lines\n", nlb);
+
+	  for (size_t i = 0; i < nlb; ++i)
+	    {
+	      Dwarf_Line *l = dwarf_onesrcline (lb, i);
+	      if (l == NULL)
+		{
+		  printf ("%s: cannot get individual line\n", argv[cnt]);
+		  result = 1;
+		  break;
+		}
+
+	      Dwarf_Addr addr;
+	      if (dwarf_lineaddr (l, &addr) != 0)
+		addr = 0;
+	      const char *file = dwarf_linesrc (l, NULL, NULL);
+	      int line;
+	      if (dwarf_lineno (l, &line) != 0)
+		line = 0;
+
+	      printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr,
+		      file ?: "???", line);
+
+	      /* Getting the file path through the Dwarf_Files should
+		 result in the same path.  */
+	      Dwarf_Files *files;
+	      size_t idx;
+	      if (dwarf_line_file (l, &files, &idx) != 0)
+		{
+		  printf ("%s: cannot get file from line (%zd): %s\n",
+			  argv[cnt], i, dwarf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+	      const char *path = dwarf_filesrc (files, idx, NULL, NULL);
+	      if ((path == NULL && file != NULL)
+		  || (path != NULL && file == NULL)
+		  || (strcmp (file, path) != 0))
+		{
+		  printf ("%s: line %zd srcline (%s) != file srcline (%s)\n",
+			  argv[cnt], i, file ?: "???", path ?: "???");
+		  result = 1;
+		  break;
+		}
+
+	      int column;
+	      if (dwarf_linecol (l, &column) != 0)
+		column = 0;
+	      if (column >= 0)
+		printf ("%d:", column);
+
+	      bool is_stmt;
+	      if (dwarf_linebeginstatement (l, &is_stmt) != 0)
+		is_stmt = false;
+	      bool end_sequence;
+	      if (dwarf_lineendsequence (l, &end_sequence) != 0)
+		end_sequence = false;
+	      bool basic_block;
+	      if (dwarf_lineblock (l, &basic_block) != 0)
+		basic_block = false;
+	      bool prologue_end;
+	      if (dwarf_lineprologueend (l, &prologue_end) != 0)
+		prologue_end = false;
+	      bool epilogue_begin;
+	      if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0)
+		epilogue_begin = false;
+
+	      printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n",
+		      is_stmt ? "yes" : "no", end_sequence ? "yes" : "no",
+		      basic_block ? "yes" : "no", prologue_end  ? "yes" : "no",
+		      epilogue_begin ? "yes" : "no");
+	    }
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/get-pubnames.c b/tests/get-pubnames.c
new file mode 100644
index 0000000..4777f49
--- /dev/null
+++ b/tests/get-pubnames.c
@@ -0,0 +1,98 @@
+/* Copyright (C) 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+
+
+static int globcnt;
+
+static int
+callback (Dwarf *dbg, Dwarf_Global *gl, void *arg __attribute__ ((unused)))
+{
+  int result = DWARF_CB_OK;
+
+  printf (" [%2d] \"%s\", die: %llu, cu: %llu\n",
+	  globcnt++, gl->name, (unsigned long long int) gl->die_offset,
+	  (unsigned long long int) gl->cu_offset);
+
+  Dwarf_Die cu_die;
+  const char *cuname;
+  if (dwarf_offdie (dbg, gl->cu_offset, &cu_die) == NULL
+      || (cuname = dwarf_diename (&cu_die)) == NULL)
+    {
+      puts ("failed to get CU die");
+      result = DWARF_CB_ABORT;
+    }
+  else
+    printf ("CU name: \"%s\"\n", cuname);
+
+  const char *diename;
+  Dwarf_Die die;
+  if (dwarf_offdie (dbg, gl->die_offset, &die) == NULL
+      || (diename = dwarf_diename (&die)) == NULL)
+    {
+      puts ("failed to get object die");
+      result = DWARF_CB_ABORT;
+    }
+  else
+    printf ("object name: \"%s\"\n", diename);
+
+  return result;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  result = 1;
+	  close (fd);
+	  continue;
+	}
+
+      globcnt = 0;
+
+      if (dwarf_getpubnames (dbg, callback, NULL, 0) != 0)
+	{
+	  printf ("dwarf_get_pubnames didn't return zero: %s\n",
+		  dwarf_errmsg (-1));
+	  result = 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/get-units-invalid.c b/tests/get-units-invalid.c
new file mode 100644
index 0000000..155e12d
--- /dev/null
+++ b/tests/get-units-invalid.c
@@ -0,0 +1,121 @@
+/* Test cudie and subdie properties.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; i++)
+    {
+      printf ("file: %s\n", argv[i]);
+      int fd = open (argv[i], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      Dwarf_CU *cu = NULL;
+      Dwarf_Die cudie, subdie;
+      uint8_t unit_type;
+      while (dwarf_get_units (dbg, cu, &cu, NULL,
+			      &unit_type, &cudie, &subdie) == 0)
+	{
+	  printf ("Got cudie: %s, unit_type: %" PRIx8 "\n",
+		  dwarf_diename (&cudie), unit_type);
+
+	  int tag = dwarf_tag (&subdie);
+	  if (unit_type == DW_UT_compile)
+	    {
+	      if (tag != DW_TAG_invalid)
+		{
+		  printf ("Not invalid: %x\n", dwarf_tag (&subdie));
+		  return -1;
+		}
+	      if (dwarf_diename (&subdie) != NULL)
+		{
+		  printf ("Should have NULL name: %s\n",
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	      Dwarf_Die result;
+	      if (dwarf_siblingof (&subdie, &result) != -1)
+		{
+		  printf ("Should NOT have a valid sibling: %s\n",
+			  dwarf_diename (&result));
+		  return -1;
+		}
+	      if (dwarf_child (&subdie, &result) != -1)
+		{
+		  printf ("Should NOT have a valid child: %s\n",
+			  dwarf_diename (&result));
+		  return -1;
+		}
+	      Dwarf_Addr base, start, end;
+	      if (dwarf_ranges (&subdie, 0, &base, &start, &end) != -1)
+		{
+		  printf ("Should NOT have a ranges: %s\n",
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	      if (dwarf_cuoffset (&subdie) != (Dwarf_Off) -1)
+		{
+		  printf ("Should NOT have a cuoffset: %s\n",
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	      if (dwarf_dieoffset (&subdie) != (Dwarf_Off) -1)
+		{
+		  printf ("Should NOT have a die offset: %s\n",
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	      if (dwarf_getabbrev (&subdie, 0, NULL) != NULL)
+		{
+		  printf ("Should NOT have an abbrev: %s\n",
+			  dwarf_diename (&subdie));
+		  return -1;
+		}
+	    }
+	  else if (unit_type == DW_UT_type)
+	    printf ("subdie: %s\n", dwarf_diename (&subdie));
+	  else
+	    printf ("subdie tag: %x\n", dwarf_tag (&subdie));
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+
+      printf ("\n");
+    }
+
+  return 0;
+}
diff --git a/tests/get-units-split.c b/tests/get-units-split.c
new file mode 100644
index 0000000..410483a
--- /dev/null
+++ b/tests/get-units-split.c
@@ -0,0 +1,101 @@
+/* Test dwarf_get_units finds split DWO CUs.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; i++)
+    {
+      printf ("file: %s\n", argv[i]);
+      int fd = open (argv[i], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      Dwarf_CU *cu = NULL;
+      Dwarf_Die cudie, subdie;
+      uint8_t unit_type;
+      int count = 0;
+      while (dwarf_get_units (dbg, cu, &cu, NULL,
+			      &unit_type, &cudie, &subdie) == 0)
+	{
+	  count++;
+	  printf ("Got cudie unit_type: %" PRIx8 "\n", unit_type);
+
+	  if (unit_type == DW_UT_skeleton)
+	    {
+	      Dwarf_CU *skel_cu = cudie.cu;
+	      Dwarf_CU *split_cu = subdie.cu;
+	      Dwarf_Die skel_die, split_die;
+	      uint64_t skel_id, split_id;
+
+	      printf ("Found a skeleton unit, with split die: %s\n",
+		      dwarf_diename (&subdie));
+
+	      if (dwarf_cu_die (skel_cu, &skel_die, NULL, NULL, NULL, NULL,
+				&skel_id, NULL) == NULL)
+		{
+		  printf ("bad skel_cu: %s\n", dwarf_errmsg (-1));
+		  return -1;
+		}
+
+	      if (dwarf_cu_die (split_cu, &split_die, NULL, NULL, NULL, NULL,
+				&split_id, NULL) == NULL)
+		{
+		  printf ("bad skel_cu: %s\n", dwarf_errmsg (-1));
+		  return -1;
+		}
+
+	      if (skel_id != split_id)
+		{
+		  printf ("Skeleton id and Split id not equal!\n");
+		  return -1;
+		}
+	    }
+	}
+
+      if (count == 0)
+	{
+	  printf ("No units found\n");
+	  return -1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+
+      printf ("\n");
+    }
+
+  return 0;
+}
diff --git a/tests/getphdrnum.c b/tests/getphdrnum.c
new file mode 100644
index 0000000..07f75db
--- /dev/null
+++ b/tests/getphdrnum.c
@@ -0,0 +1,48 @@
+#include "config.h"
+
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+int main (int argc, const char **argv)
+{
+  int fd;
+  Elf *elf;
+  size_t phnum;
+
+  if (argc != 2)
+    {
+      fprintf (stderr, "usage: %s FILE\n", argv[0]);
+      return EXIT_FAILURE;
+    }
+
+  fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    {
+      perror ("open");
+      return EXIT_FAILURE;
+    }
+  elf_version (EV_CURRENT);
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (!elf)
+    {
+      fprintf (stderr, "elf_begin: %s\n", elf_errmsg (-1));
+      return EXIT_FAILURE;
+    }
+  if (elf_getphdrnum (elf, &phnum))
+    {
+      fprintf(stderr, "elf_getphdrnum: %s\n", elf_errmsg (-1));
+      return EXIT_FAILURE;
+    }
+
+  printf("%zu\n", phnum);
+
+  elf_end (elf);
+  close (fd);
+
+  return EXIT_SUCCESS;
+}
diff --git a/tests/getsrc_die.c b/tests/getsrc_die.c
new file mode 100644
index 0000000..f878fa6
--- /dev/null
+++ b/tests/getsrc_die.c
@@ -0,0 +1,72 @@
+/* Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "system.h"
+
+
+int
+main (int argc, char *argv[])
+{
+  /* file addr+ */
+  int fd = open (argv[1], O_RDONLY);
+  Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+  if  (dbg == NULL)
+    error (-1, 0, "dwarf_begin (%s): %s\n", argv[1], dwarf_errmsg (-1));
+
+  for (int i = 2; i < argc; i++)
+    {
+      Dwarf_Addr addr;
+      char *endptr;
+      Dwarf_Die cudie;
+      Dwarf_Line *line;
+
+      errno = 0;
+      addr = strtoull (argv[i], &endptr, 16);
+      if (errno != 0)
+	error (-1, errno, "Cannot parrse '%s'", argv[1]);
+
+      if (dwarf_addrdie (dbg, addr, &cudie) == NULL)
+	error (-1, 0, "dwarf_addrdie (%s): %s", argv[i], dwarf_errmsg (-1));
+
+      line = dwarf_getsrc_die (&cudie, addr);
+      if (line == NULL)
+	error (-1, 0, "dwarf_getsrc_die (%s): %s", argv[i], dwarf_errmsg (-1));
+
+      const char *f = dwarf_linesrc (line, NULL, NULL);
+      int l;
+      if (dwarf_lineno (line, &l) != 0)
+	l = 0;
+
+      printf ("%s:%d\n", f ?: "???", l);
+    }
+
+  dwarf_end (dbg);
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/hash.c b/tests/hash.c
new file mode 100644
index 0000000..86b6ad8
--- /dev/null
+++ b/tests/hash.c
@@ -0,0 +1,45 @@
+/* Copyright (C) 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <libelf.h>
+#include <stdio.h>
+
+
+static int
+check (const char *name, unsigned long int expected)
+{
+  unsigned long int actual = elf_hash (name);
+
+  return actual != expected;
+}
+
+
+int
+main (void)
+{
+  int status;
+
+  /* Check some names.  We know what the expected result is.  */
+  status = check ("_DYNAMIC", 165832675);
+  status |= check ("_GLOBAL_OFFSET_TABLE_", 102264335);
+
+  return status;
+}
diff --git a/tests/hello_aarch64.ko.bz2 b/tests/hello_aarch64.ko.bz2
new file mode 100644
index 0000000..431d89f
--- /dev/null
+++ b/tests/hello_aarch64.ko.bz2
Binary files differ
diff --git a/tests/hello_arc_hs4.ko.bz2 b/tests/hello_arc_hs4.ko.bz2
new file mode 100644
index 0000000..56ccb3c
--- /dev/null
+++ b/tests/hello_arc_hs4.ko.bz2
Binary files differ
diff --git a/tests/hello_csky.ko.bz2 b/tests/hello_csky.ko.bz2
new file mode 100644
index 0000000..ed98c7f
--- /dev/null
+++ b/tests/hello_csky.ko.bz2
Binary files differ
diff --git a/tests/hello_i386.ko.bz2 b/tests/hello_i386.ko.bz2
new file mode 100644
index 0000000..f89b292
--- /dev/null
+++ b/tests/hello_i386.ko.bz2
Binary files differ
diff --git a/tests/hello_m68k.ko.bz2 b/tests/hello_m68k.ko.bz2
new file mode 100644
index 0000000..2da3d17
--- /dev/null
+++ b/tests/hello_m68k.ko.bz2
Binary files differ
diff --git a/tests/hello_ppc64.ko.bz2 b/tests/hello_ppc64.ko.bz2
new file mode 100644
index 0000000..f4d3ff2
--- /dev/null
+++ b/tests/hello_ppc64.ko.bz2
Binary files differ
diff --git a/tests/hello_riscv64.ko.bz2 b/tests/hello_riscv64.ko.bz2
new file mode 100644
index 0000000..a086c38
--- /dev/null
+++ b/tests/hello_riscv64.ko.bz2
Binary files differ
diff --git a/tests/hello_s390.ko.bz2 b/tests/hello_s390.ko.bz2
new file mode 100644
index 0000000..41525bf
--- /dev/null
+++ b/tests/hello_s390.ko.bz2
Binary files differ
diff --git a/tests/hello_x86_64.ko.bz2 b/tests/hello_x86_64.ko.bz2
new file mode 100644
index 0000000..ba06f91
--- /dev/null
+++ b/tests/hello_x86_64.ko.bz2
Binary files differ
diff --git a/tests/leb128.c b/tests/leb128.c
new file mode 100644
index 0000000..03090d8
--- /dev/null
+++ b/tests/leb128.c
@@ -0,0 +1,200 @@
+/* Test program for leb128
+   Copyright (C) 2020 Tom Tromey
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <stddef.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <libdw.h>
+#include "../libdw/libdwP.h"
+#include "../libdw/memory-access.h"
+
+#define OK 0
+#define FAIL 1
+
+static const unsigned char v0[] = { 0x0 };
+static const unsigned char v1[] = { 0x1 };
+static const unsigned char v23[] = { 23 };
+static const unsigned char vm_1[] = { 0x7f };
+static const unsigned char vm_2[] = { 0x7e };
+static const unsigned char s127[] = { 0xff, 0x00 };
+static const unsigned char v128[] = { 0x80, 0x01 };
+static const unsigned char v129[] = { 0x81, 0x01 };
+static const unsigned char vm_127[] = { 0x81, 0x7f };
+static const unsigned char vm_128[] = { 0x80, 0x7f };
+static const unsigned char vm_129[] = { 0xff, 0x7e };
+static const unsigned char vhuge[] =
+  {
+    0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0x0
+  };
+static const unsigned char most_positive[] =
+  {
+    0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x3f
+  };
+static const unsigned char most_negative[] =
+  {
+    0x80, 0x80, 0x80, 0x80, 0x80,
+    0x80, 0x80, 0x80, 0x40
+  };
+static const unsigned char minus_one[] =
+  {
+    0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0x7f
+  };
+static const unsigned char int64_max_m1[] =
+  {
+    0xfe, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0x00
+  };
+static const unsigned char int64_min_p1[] =
+  {
+    0x81, 0x80, 0x80, 0x80, 0x80,
+    0x80, 0x80, 0x80, 0x80, 0x7f
+  };
+
+static int
+test_one_sleb (const unsigned char *data, size_t len, int64_t expect)
+{
+  int64_t value;
+  const unsigned char *p;
+
+  p = data;
+  get_sleb128 (value, p, p + len);
+  if (value != expect || p != data + len)
+    return FAIL;
+
+  p = data;
+  get_sleb128_unchecked (value, p);
+  if (value != expect || p != data + len)
+    return FAIL;
+
+  return OK;
+}
+
+static int
+test_sleb (void)
+{
+#define TEST(ARRAY, V)				      \
+  if (test_one_sleb (ARRAY, sizeof (ARRAY), V) != OK) \
+    return FAIL;
+
+  TEST (v0, 0);
+  TEST (v1, 1);
+  TEST (v23, 23);
+  TEST (vm_1, -1);
+  TEST (vm_2, -2);
+  TEST (s127, 127);
+  TEST (v128, 128);
+  TEST (v129, 129);
+  TEST (vm_127, -127);
+  TEST (vm_128, -128);
+  TEST (vm_129, -129);
+  TEST (vhuge, 9223372036854775807ll);
+  TEST (most_positive, 4611686018427387903ll);
+  TEST (most_negative, -4611686018427387904ll);
+  TEST (minus_one, -1);
+  TEST (int64_max_m1, INT64_MAX - 1);
+  TEST (int64_min_p1, INT64_MIN + 1);
+
+#undef TEST
+
+  return OK;
+}
+
+static int
+test_sleb_safety (void)
+{
+  const int64_t expected_error = INT64_MAX;
+  int64_t value;
+  const unsigned char *test = NULL;
+  get_sleb128 (value, test, test);
+  if (value != expected_error)
+    return FAIL;
+
+  return OK;
+}
+
+static int
+test_one_uleb (const unsigned char *data, size_t len, uint64_t expect)
+{
+  uint64_t value;
+  const unsigned char *p;
+
+  p = data;
+  get_uleb128 (value, p, p + len);
+  if (value != expect || p != data + len)
+    return FAIL;
+
+  p = data;
+  get_uleb128_unchecked (value, p);
+  if (value != expect || p != data + len)
+    return FAIL;
+
+  return OK;
+}
+
+static int
+test_uleb (void)
+{
+#define TEST(ARRAY, V)				      \
+  if (test_one_uleb (ARRAY, sizeof (ARRAY), V) != OK) \
+    return FAIL;
+
+  TEST (v0, 0);
+  TEST (v1, 1);
+  TEST (v23, 23);
+  TEST (vm_1, 127);
+  TEST (vm_2, 126);
+  TEST (s127, 127);
+  TEST (v128, 128);
+  TEST (v129, 129);
+  TEST (vm_127, 16257);
+  TEST (vm_128, 16256);
+  TEST (vm_129, 16255);
+  TEST (vhuge, 9223372036854775807ull);
+  TEST (most_positive, 4611686018427387903ull);
+  TEST (most_negative, 4611686018427387904ull);
+  TEST (minus_one, 9223372036854775807ull);
+  TEST (int64_max_m1, INT64_MAX - 1);
+  TEST (int64_min_p1, INT64_MIN + 1);
+
+#undef TEST
+
+  return OK;
+}
+
+static int
+test_uleb_safety (void)
+{
+  const uint64_t expected_error = UINT64_MAX;
+  uint64_t value;
+  const unsigned char *test = NULL;
+  get_uleb128 (value, test, test);
+  if (value != expected_error)
+    return FAIL;
+
+  return OK;
+}
+
+int
+main (void)
+{
+  return test_sleb () || test_sleb_safety () || test_uleb ()
+	 || test_uleb_safety ();
+}
diff --git a/tests/lfs-symbols b/tests/lfs-symbols
new file mode 100644
index 0000000..282a4ad
--- /dev/null
+++ b/tests/lfs-symbols
@@ -0,0 +1,73 @@
+# Imported from lintian/data/binaries/lfs-symbols
+#
+# Exceptions:
+#   fts* - linux-kernel-modules.c is careful with FTS_NOSTAT
+
+# Manually maintained list of non-lfs symbols
+#
+# List was found by grepping around in /usr/include on an i386 system
+# with build-essential installed
+#
+# Please keep this sorted by key.
+
+__fxstat
+__fxstatat
+__lxstat
+__xstat
+aio_cancel
+aio_error
+aio_fsync
+aio_read
+aio_return
+aio_suspend
+aio_write
+alphasort
+creat
+fallocate
+fgetpos
+fopen
+freopen
+fseeko
+fsetpos
+fstatfs
+fstatvfs
+ftello
+ftruncate
+#fts_open
+#fts_read
+#fts_children
+#fts_set
+#fts_close
+ftw
+getdirentries
+getrlimit
+glob
+globfree
+lio_listio
+lockf
+lseek
+mkostemp
+mkostemps
+mkstemp
+mkstemps
+mmap
+nftw
+open
+openat
+posix_fadvise
+posix_fallocate
+pread
+preadv
+prlimit
+pwrite
+pwritev
+readdir
+readdir_r
+scandir
+sendfile
+setrlimit
+statfs
+statvfs
+tmpfile
+truncate
+versionsort
diff --git a/tests/libtestfile_multi_shared.so.bz2 b/tests/libtestfile_multi_shared.so.bz2
new file mode 100755
index 0000000..e9eb6a7
--- /dev/null
+++ b/tests/libtestfile_multi_shared.so.bz2
Binary files differ
diff --git a/tests/line2addr.c b/tests/line2addr.c
new file mode 100644
index 0000000..663746f
--- /dev/null
+++ b/tests/line2addr.c
@@ -0,0 +1,148 @@
+/* Copyright (C) 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <inttypes.h>
+#include <assert.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <argp.h>
+#include <stdio.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include "system.h"
+
+
+static void
+print_address (Dwfl_Module *mod, Dwarf_Addr address)
+{
+  int n = dwfl_module_relocations (mod);
+  if (n < 0)
+    error (0, 0, "dwfl_module_relocations: %s", dwfl_errmsg (-1));
+  else if (n > 0)
+    {
+      int i = dwfl_module_relocate_address (mod, &address);
+      if (i < 0)
+	error (0, 0, "dwfl_module_relocate_address: %s", dwfl_errmsg (-1));
+      else
+	{
+	  const char *modname = dwfl_module_info (mod, NULL, NULL, NULL,
+						  NULL, NULL, NULL, NULL);
+	  const char *secname = dwfl_module_relocation_info (mod, i, NULL);
+	  if (n > 1 || secname[0] != '\0')
+	    printf ("%s(%s)+%#" PRIx64, modname, secname, address);
+	  else
+	    printf ("%s+%#" PRIx64, modname, address);
+	  return;
+	}
+    }
+
+  printf ("%#" PRIx64, address);
+}
+
+
+struct args
+{
+  const char *arg;
+  char *file;
+  int line;
+};
+
+static int
+handle_module (Dwfl_Module *mod __attribute__ ((unused)),
+	       void **udata __attribute__ ((unused)),
+	       const char *modname, Dwarf_Addr base __attribute__ ((unused)),
+	       Dwarf *dbg __attribute__ ((unused)),
+	       Dwarf_Addr bias __attribute__ ((unused)), void *arg)
+{
+  const struct args *const a = arg;
+
+  Dwfl_Line **lines = NULL;
+  size_t nlines = 0;
+
+  if (dwfl_module_getsrc_file (mod, a->file, a->line, 0, &lines, &nlines) == 0)
+    {
+      for (size_t inner = 0; inner < nlines; ++inner)
+	{
+	  Dwarf_Addr addr;
+	  int line = a->line, col = 0;
+	  const char *file = dwfl_lineinfo (lines[inner], &addr, &line, &col,
+					    NULL, NULL);
+	  if (file != NULL)
+	    {
+	      printf ("%s -> ", a->arg);
+	      print_address (mod, addr);
+	      if (modname[0] != '\0')
+		printf (" (%s:", modname);
+	      if (strcmp (file, a->file) || line != a->line || col != 0)
+		printf (" %s%s:%d", modname[0] != '\0' ? "" : "(",
+			file, line);
+	      if (col != 0)
+		printf (":%d", col);
+	      if (modname[0] != '\0'
+		  || strcmp (file, a->file) || line != a->line || col != 0)
+		puts (")");
+	      else
+		puts ("");
+	    }
+	}
+      free (lines);
+    }
+
+  return DWARF_CB_OK;
+}
+
+int
+main (int argc, char *argv[])
+{
+  int cnt;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  Dwfl *dwfl = NULL;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &cnt, &dwfl);
+  assert (dwfl != NULL);
+
+  for (; cnt < argc; ++cnt)
+    {
+      struct args a = { .arg = argv[cnt] };
+
+      switch (sscanf (a.arg, "%m[^:]:%d", &a.file, &a.line))
+	{
+	default:
+	case 0:
+	  printf ("ignored %s\n", argv[cnt]);
+	  continue;
+	case 1:
+	  a.line = 0;
+	  break;
+	case 2:
+	  break;
+	}
+
+      (void) dwfl_getdwarf (dwfl, &handle_module, &a, 0);
+
+      free (a.file);
+    }
+
+  dwfl_end (dwfl);
+
+  return 0;
+}
diff --git a/tests/linkmap-cut-lib.so.bz2 b/tests/linkmap-cut-lib.so.bz2
new file mode 100644
index 0000000..a1bda5c
--- /dev/null
+++ b/tests/linkmap-cut-lib.so.bz2
Binary files differ
diff --git a/tests/linkmap-cut.bz2 b/tests/linkmap-cut.bz2
new file mode 100644
index 0000000..f2ccd7c
--- /dev/null
+++ b/tests/linkmap-cut.bz2
Binary files differ
diff --git a/tests/linkmap-cut.core.bz2 b/tests/linkmap-cut.core.bz2
new file mode 100644
index 0000000..b55b2f2
--- /dev/null
+++ b/tests/linkmap-cut.core.bz2
Binary files differ
diff --git a/tests/low_high_pc.c b/tests/low_high_pc.c
new file mode 100644
index 0000000..cd022b1
--- /dev/null
+++ b/tests/low_high_pc.c
@@ -0,0 +1,132 @@
+/* Test program for dwarf_lowpc and dwarf_highpc
+   Copyright (C) 2012, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdio.h>
+#include <stdio_ext.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fnmatch.h>
+
+struct args
+{
+  Dwfl *dwfl;
+  Dwarf_Die *cu;
+  Dwarf_Addr dwbias;
+  char **argv;
+  const char *file;
+};
+
+static struct args *args;
+
+static void
+fail(Dwarf_Off off, const char *name, const char *msg)
+{
+  printf("%s: [%" PRIx64 "] '%s' %s\n", args->file, off, name, msg);
+  exit(-1);
+}
+
+static int
+handle_die (Dwarf_Die *die, void *arg)
+{
+  args = arg;
+  Dwarf_Off off = dwarf_dieoffset (die);
+
+  const char *name = dwarf_diename (die);
+  if (name == NULL)
+    name = "<no name>";
+
+  printf ("[%" PRIx64 "] %s\n", off, name);
+
+  Dwarf_Addr lowpc = 0;
+  Dwarf_Addr highpc = 0;
+  if (dwarf_lowpc (die, &lowpc) != 0 && dwarf_hasattr (die, DW_AT_low_pc))
+    fail (off, name, "has DW_AT_low_pc but dwarf_lowpc fails");
+  if (dwarf_highpc (die, &highpc) != 0 && dwarf_hasattr (die, DW_AT_high_pc))
+    fail (off, name, "has DW_AT_high_pc but dwarf_highpc fails");
+
+  /* GCC < 4.7 had a bug where no code CUs got a highpc == lowpc.
+     Allow that, because it is not the main purpose of this test.  */
+  if (dwarf_hasattr (die, DW_AT_low_pc)
+      && dwarf_hasattr (die, DW_AT_high_pc)
+      && highpc <= lowpc
+      && ! (dwarf_tag (die) == DW_TAG_compile_unit && highpc == lowpc))
+    {
+      printf("lowpc: %" PRIx64 ", highpc: %" PRIx64 "\n", lowpc, highpc);
+      fail (off, name, "highpc <= lowpc");
+    }
+
+  return 0;
+}
+
+
+int
+main (int argc, char *argv[])
+{
+  int remaining;
+
+  /* Set locale.  */
+  (void) setlocale (LC_ALL, "");
+
+  struct args a = { .dwfl = NULL, .cu = NULL };
+
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+		     &a.dwfl);
+  assert (a.dwfl != NULL);
+  a.argv = &argv[remaining];
+
+  int result = 0;
+
+  while ((a.cu = dwfl_nextcu (a.dwfl, a.cu, &a.dwbias)) != NULL)
+    {
+      a.file = dwarf_diename (a.cu);
+      handle_die (a.cu, &a);
+      dwarf_getfuncs (a.cu, &handle_die, &a, 0);
+
+      uint8_t unit_type;
+      Dwarf_Die subdie;
+      if (dwarf_cu_info (a.cu->cu, NULL, &unit_type, NULL, &subdie,
+			 NULL, NULL, NULL) != 0)
+	{
+	  Dwarf_Off off = dwarf_dieoffset (a.cu);
+	  fail (off, "dwarf_cu_info", dwarf_errmsg (-1));
+	}
+
+      if (unit_type == DW_UT_skeleton)
+	{
+	  const char *name = dwarf_diename (&subdie) ?: "<unknown>";
+	  printf ("Following split subdie: %s\n", name);
+	  struct args b = a;
+	  b.cu = &subdie;
+	  handle_die (b.cu, &b);
+	  dwarf_getfuncs (b.cu, &handle_die, &b, 0);
+	  printf ("Done subdie: %s\n", name);
+	}
+    }
+
+  dwfl_end (a.dwfl);
+
+  printf ("\n");
+
+  return result;
+}
diff --git a/tests/msg_tst.c b/tests/msg_tst.c
new file mode 100644
index 0000000..aa974d0
--- /dev/null
+++ b/tests/msg_tst.c
@@ -0,0 +1,112 @@
+/* Copyright (C) 2002, 2005, 2006 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <libelfP.h>
+
+static struct
+{
+  int id;
+  const char *expected;
+} libelf_msgs[ELF_E_NUM] =
+  {
+    { ELF_E_NOERROR, "no error" },
+    { ELF_E_UNKNOWN_ERROR, "unknown error" },
+    { ELF_E_UNKNOWN_VERSION, "unknown version" },
+    { ELF_E_UNKNOWN_TYPE, "unknown type" },
+    { ELF_E_INVALID_HANDLE, "invalid `Elf' handle" },
+    { ELF_E_SOURCE_SIZE, "invalid size of source operand" },
+    { ELF_E_DEST_SIZE, "invalid size of destination operand" },
+    { ELF_E_INVALID_ENCODING, "invalid encoding" },
+    { ELF_E_NOMEM, "out of memory" },
+    { ELF_E_INVALID_FILE, "invalid file descriptor" },
+    { ELF_E_INVALID_ELF, "invalid ELF file data" },
+    { ELF_E_INVALID_OP, "invalid operation" },
+    { ELF_E_NO_VERSION, "ELF version not set" },
+    { ELF_E_INVALID_CMD, "invalid command" },
+    { ELF_E_RANGE, "offset out of range" },
+    { ELF_E_ARCHIVE_FMAG, "invalid fmag field in archive header" },
+    { ELF_E_INVALID_ARCHIVE, "invalid archive file" },
+    { ELF_E_NO_ARCHIVE, "descriptor is not for an archive" },
+    { ELF_E_NO_INDEX, "no index available" },
+    { ELF_E_READ_ERROR, "cannot read data from file" },
+    { ELF_E_WRITE_ERROR, "cannot write data to file" },
+    { ELF_E_INVALID_CLASS, "invalid binary class" },
+    { ELF_E_INVALID_INDEX, "invalid section index" },
+    { ELF_E_INVALID_OPERAND, "invalid operand" },
+    { ELF_E_INVALID_SECTION, "invalid section" },
+    { ELF_E_INVALID_COMMAND, "invalid command" },
+    { ELF_E_WRONG_ORDER_EHDR, "executable header not created first" },
+    { ELF_E_FD_DISABLED, "file descriptor disabled" },
+    { ELF_E_FD_MISMATCH, "archive/member file descriptor mismatch" },
+    { ELF_E_OFFSET_RANGE, "offset out of range" },
+    { ELF_E_NOT_NUL_SECTION, "cannot manipulate null section" },
+    { ELF_E_DATA_MISMATCH, "data/scn mismatch" },
+    { ELF_E_INVALID_SECTION_HEADER, "invalid section header" },
+    { ELF_E_INVALID_DATA, "invalid data" },
+    { ELF_E_DATA_ENCODING, "unknown data encoding" },
+    { ELF_E_SECTION_TOO_SMALL, "section `sh_size' too small for data" },
+    { ELF_E_INVALID_ALIGN, "invalid section alignment" },
+    { ELF_E_INVALID_SHENTSIZE, "invalid section entry size" },
+    { ELF_E_UPDATE_RO, "update() for write on read-only file" },
+    { ELF_E_NOFILE, "no such file" },
+    { ELF_E_GROUP_NOT_REL,
+      "only relocatable files can contain section groups" },
+    { ELF_E_INVALID_PHDR,
+      "program header only allowed in executables, shared objects, \
+and core files" },
+    { ELF_E_NO_PHDR, "file has no program header" },
+    { ELF_E_INVALID_OFFSET, "invalid offset" },
+    { ELF_E_INVALID_SECTION_TYPE , "invalid section type" },
+    { ELF_E_INVALID_SECTION_FLAGS , "invalid section flags" },
+    { ELF_E_NOT_COMPRESSED, "section does not contain compressed data" },
+    { ELF_E_ALREADY_COMPRESSED, "section contains compressed data" },
+    { ELF_E_UNKNOWN_COMPRESSION_TYPE, "unknown compression type" },
+    { ELF_E_COMPRESS_ERROR, "cannot compress data" },
+    { ELF_E_DECOMPRESS_ERROR, "cannot decompress data" }
+  };
+
+
+int
+main (void)
+{
+  size_t cnt;
+  int result = EXIT_SUCCESS;
+
+  /* Clear the error state.  */
+  (void) elf_errno ();
+
+  /* Check all the messages of libelf.  */
+  for (cnt = 1; cnt < ELF_E_NUM; ++cnt)
+    {
+      const char *str = elf_errmsg (libelf_msgs[cnt].id);
+
+      if (strcmp (str, libelf_msgs[cnt].expected) != 0)
+	{
+	  printf ("libelf msg %zu: expected \"%s\", got \"%s\"\n",
+		  cnt, libelf_msgs[cnt].expected, str);
+	  result = EXIT_FAILURE;
+	}
+    }
+
+  return result;
+}
diff --git a/tests/newdata.c b/tests/newdata.c
new file mode 100644
index 0000000..fcf26ac
--- /dev/null
+++ b/tests/newdata.c
@@ -0,0 +1,404 @@
+/* Test program for elf_newdata function.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+// Random data string (16 bytes).
+static char *DATA = "123456789ABCDEF";
+static size_t DATA_LEN = 16;
+
+static void
+add_section_data (Elf *elf, char *buf, size_t len)
+{
+  printf ("Adding %zd bytes.\n", len);
+
+  Elf_Scn *scn = elf_getscn (elf, 1);
+  if (scn == NULL)
+    {
+      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  Elf_Data *data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create newdata for section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = buf;
+  data->d_type = ELF_T_BYTE;
+  data->d_size = len;
+  data->d_align = 1;
+  data->d_version = EV_CURRENT;
+
+  // Let the library compute the internal structure information.
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+}
+
+static Elf *
+create_elf (int fd, int class, int use_mmap)
+{
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create an ELF header.
+  if (gelf_newehdr (elf, class) == 0)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Initialize header.
+  ehdr->e_ident[EI_DATA] = class == ELFCLASS32 ? ELFDATA2LSB : ELFDATA2MSB;
+  ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+  ehdr->e_type = ET_NONE;
+  ehdr->e_machine = class == ELFCLASS32 ? EM_PPC : EM_X86_64;
+  ehdr->e_version = EV_CURRENT;
+
+  // Update the ELF header.
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create a section.
+  Elf_Scn *scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create new section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for data section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shdr->sh_type = SHT_PROGBITS;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 1;
+  shdr->sh_entsize = 1;
+  shdr->sh_name = 0;
+
+  // Finish section, update the header.
+  if (gelf_update_shdr (scn, shdr) == 0)
+    {
+      printf ("cannot update header for DATA section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Add some data to the section.
+  add_section_data (elf, DATA, DATA_LEN);
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  return elf;
+}
+
+static Elf *
+read_elf (int fd, int use_mmap)
+{
+  printf ("Reading ELF file\n");
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_RDWR_MMAP : ELF_C_RDWR, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-again: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  return elf;
+}
+
+static void
+check_section_size (Elf *elf, size_t size)
+{
+  Elf_Scn *scn = elf_getscn (elf, 1);
+  if (scn == NULL)
+    {
+      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for DATA section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (shdr->sh_size == size)
+    printf ("OK %zd bytes.\n", size);
+  else
+    {
+      printf ("BAD size, expected %zd, got %" PRIu64 "\n",
+	      size, shdr->sh_size);
+      exit (-1);
+    }
+}
+
+static void
+check_section_data (Elf *elf, char *data, size_t len, size_t times)
+{
+  Elf_Scn *scn = elf_getscn (elf, 1);
+  if (scn == NULL)
+    {
+      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  Elf_Data *d = NULL;
+  for (size_t i = 0; i < times; i++)
+    {
+      if (d == NULL || i * len >= d->d_off + d->d_size)
+	{
+	  d = elf_getdata (scn, d);
+	  if (d == NULL)
+	    {
+	      printf ("cannot get data for section item %zd: %s\n",
+		      i, elf_errmsg (-1));
+	      exit (1);
+	    }
+	  else
+	    printf ("OK, section data item %zd (d_off: %" PRId64
+		    ", d_size: %zd)\n", i, d->d_off, d->d_size);
+	}
+      char *d_data = (char *) d->d_buf + (len * i) - d->d_off;
+      printf ("%zd data (d_off: %" PRId64
+	      ", len * i: %zd): (%p + %" PRId64 ") %s\n",
+	      i, d->d_off, len * i, d->d_buf, (len * i) - d->d_off, d_data);
+      if (memcmp (data, d_data, len) != 0)
+	{
+	  printf ("Got bad data in section for item %zd.\n", i);
+	  exit (1);
+	}
+    }
+}
+
+static void
+check_elf (int class, int use_mmap)
+{
+  static const char *fname;
+  if (class == ELFCLASS32)
+    fname = use_mmap ? "newdata.elf32.mmap" : "newdata.elf32";
+  else
+    fname = use_mmap ? "newdata.elf64.mmap" : "newdata.elf64";
+
+  printf ("\ncheck_elf: %s\n", fname);
+
+  int fd = open (fname, O_RDWR|O_CREAT|O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot create `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = create_elf (fd, class, use_mmap);
+  check_section_size (elf, DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 1);
+
+  // Add some more data (won't be written to disk).
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 2 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 2);
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  // Read the ELF from disk now.  And add new data directly.
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = read_elf (fd, use_mmap);
+  check_section_size (elf, DATA_LEN);
+  // But don't check contents, that would read the data...
+
+  // Add some more data.
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 2 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 2);
+
+  // And some more.
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 3 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 3);
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  // Read the ELF from disk now.  And add new data after raw reading.
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = read_elf (fd, use_mmap);
+  check_section_size (elf, DATA_LEN);
+  // But don't check contents, that would read the data...
+
+  // Get raw data before adding new data.
+  Elf_Scn *scn = elf_getscn (elf, 1);
+  if (scn == NULL)
+    {
+      printf ("couldn't get data section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  printf ("elf_rawdata\n");
+  Elf_Data *data = elf_rawdata (scn, NULL);
+  if (data == NULL)
+    {
+      printf ("couldn't get raw data from section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (data->d_size != DATA_LEN)
+    {
+      printf ("Unexpected Elf_Data: %zd", data->d_size);
+      exit (1);
+    }
+
+  // Now add more data.
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 2 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 2);
+
+  // And some more.
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 3 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 3);
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  // Read the ELF from disk now.  And add new data after data reading.
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = read_elf (fd, use_mmap);
+  check_section_size (elf, DATA_LEN);
+  // Get (converted) data before adding new data.
+  check_section_data (elf, DATA, DATA_LEN, 1);
+
+  printf ("elf_getdata\n");
+
+  // Now add more data.
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 2 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 2);
+
+  // And some more.
+  add_section_data (elf, DATA, DATA_LEN);
+  check_section_size (elf, 3 * DATA_LEN);
+  check_section_data (elf, DATA, DATA_LEN, 3);
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)), char *argv[] __attribute__ ((unused)))
+{
+  // Initialize libelf.
+  elf_version (EV_CURRENT);
+
+  // Fill holes with something non-zero to more easily spot bad data.
+  elf_fill ('X');
+
+  check_elf (ELFCLASS32, 0);
+  check_elf (ELFCLASS32, 1);
+  check_elf (ELFCLASS64, 0);
+  check_elf (ELFCLASS64, 1);
+
+  return 0;
+}
diff --git a/tests/newfile.c b/tests/newfile.c
new file mode 100644
index 0000000..5eabdcb
--- /dev/null
+++ b/tests/newfile.c
@@ -0,0 +1,170 @@
+/* Copyright (C) 1999, 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static void
+print_ehdr (Elf32_Ehdr *ehdr)
+{
+  int n;
+
+  for (n = 0; n < EI_NIDENT; ++n)
+    printf (" %02x", ehdr->e_ident[n]);
+
+  printf ("\ntype = %d\nmachine = %d\nversion = %d\nentry = %d\n"
+          "phoff = %d\nshoff = %d\nflags = %d\nehsize = %d\n"
+          "phentsize = %d\nphnum = %d\nshentsize = %d\nshnum = %d\n"
+          "shstrndx = %d\n",
+          ehdr->e_type,
+          ehdr->e_machine,
+          ehdr->e_version,
+          ehdr->e_entry,
+          ehdr->e_phoff,
+          ehdr->e_shoff,
+          ehdr->e_flags,
+          ehdr->e_ehsize,
+          ehdr->e_phentsize,
+          ehdr->e_phnum,
+          ehdr->e_shentsize,
+          ehdr->e_shnum,
+          ehdr->e_shstrndx);
+}
+
+int
+main (int argc, char *argv[] __attribute__ ((unused)))
+{
+  Elf *elf;
+  int result = 0;
+  int fd;
+  char fname[] = "newfile-XXXXXX";
+
+  fd = mkstemp (fname);
+  if (fd == -1)
+    {
+      printf ("cannot create temporary file: %m\n");
+      exit (1);
+    }
+  /* Remove the file when we exit.  */
+  unlink (fname);
+
+  elf_version (EV_CURRENT);
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("elf_begin: %s\n", elf_errmsg (-1));
+      result = 1;
+    }
+  else
+    {
+      if (elf32_newehdr (elf) == NULL)
+	{
+	  printf ("elf32_newehdr: %s\n", elf_errmsg (-1));
+	  result = 1;
+	}
+      else
+        {
+	  Elf32_Ehdr *ehdr = elf32_getehdr (elf);
+
+	  if (ehdr == NULL)
+	    {
+	      printf ("elf32_getehdr: %s\n", elf_errmsg (-1));
+	      result = 1;
+	    }
+	  else
+	    {
+	      int i;
+
+	      if (argc > 1)
+		/* Use argc as a debugging flag.  */
+		print_ehdr (ehdr);
+
+	      /* Some tests.  */
+	      for (i = 0; i < EI_NIDENT; ++i)
+		if (ehdr->e_ident[i] != 0)
+		  {
+		    printf ("ehdr->e_ident[%d] != 0\n", i);
+		    result = 1;
+		    break;
+		  }
+
+#define VALUE_TEST(name, val) \
+	      if (ehdr->name != val)					      \
+	        {							      \
+		  printf ("ehdr->%s != %d\n", #name, val);		      \
+		  result = 1;						      \
+		}
+#define ZERO_TEST(name) VALUE_TEST (name, 0)
+	      ZERO_TEST (e_type);
+	      ZERO_TEST (e_machine);
+	      ZERO_TEST (e_version);
+	      ZERO_TEST (e_entry);
+	      ZERO_TEST (e_phoff);
+	      ZERO_TEST (e_shoff);
+	      ZERO_TEST (e_flags);
+	      ZERO_TEST (e_ehsize);
+	      ZERO_TEST (e_phentsize);
+	      ZERO_TEST (e_phnum);
+	      ZERO_TEST (e_shentsize);
+	      ZERO_TEST (e_shnum);
+	      ZERO_TEST (e_shstrndx);
+
+	      if (elf32_newphdr (elf, 10) == NULL)
+		{
+		  printf ("elf32_newphdr: %s\n", elf_errmsg (-1));
+		  result = 1;
+		}
+	      else
+		{
+		  if (argc > 1)
+		    print_ehdr (ehdr);
+
+		  ehdr = elf32_getehdr (elf);
+		  if (ehdr == NULL)
+		    {
+		      printf ("elf32_getehdr (#2): %s\n", elf_errmsg (-1));
+		      result = 1;
+		    }
+		  else
+		    {
+		      ZERO_TEST (e_type);
+		      ZERO_TEST (e_machine);
+		      ZERO_TEST (e_version);
+		      ZERO_TEST (e_entry);
+		      ZERO_TEST (e_phoff);
+		      ZERO_TEST (e_shoff);
+		      ZERO_TEST (e_flags);
+		      ZERO_TEST (e_ehsize);
+		      VALUE_TEST (e_phentsize, (int) sizeof (Elf32_Phdr));
+		      VALUE_TEST (e_phnum, 10);
+		      ZERO_TEST (e_shentsize);
+		      ZERO_TEST (e_shnum);
+		      ZERO_TEST (e_shstrndx);
+		    }
+		}
+	    }
+        }
+
+      (void) elf_end (elf);
+    }
+
+  return result;
+}
diff --git a/tests/newscn.c b/tests/newscn.c
new file mode 100644
index 0000000..466f2f6
--- /dev/null
+++ b/tests/newscn.c
@@ -0,0 +1,66 @@
+/* Copyright (C) 1999, 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+
+int
+main (void)
+{
+  Elf *elf;
+  int fd;
+  Elf_Scn *section;
+
+  if (elf_version (EV_CURRENT) == EV_NONE)
+    {
+      fprintf (stderr, "library fd of date\n");
+      exit (1);
+    }
+
+  char name[] = "test.XXXXXX";
+  fd = mkstemp (name);
+  if (fd < 0)
+    {
+      fprintf (stderr, "Failed to open fdput file: %s\n", name);
+      exit (1);
+    }
+  unlink (name);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      fprintf (stderr, "Failed to elf_begin fdput file: %s\n", name);
+      exit (1);
+    }
+
+  section = elf_newscn (elf);
+  section = elf_nextscn (elf, section);
+  assert (section == NULL);
+
+  elf_end (elf);
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/next-files.c b/tests/next-files.c
new file mode 100644
index 0000000..9de5c8b
--- /dev/null
+++ b/tests/next-files.c
@@ -0,0 +1,93 @@
+/* A variant of get-files test that uses dwarf_next_lines.
+   Copyright (C) 2002, 2004, 2005, 2007, 2014, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable\n", argv[cnt]);
+	  result = 1;
+	  if (fd != -1)
+	    close (fd);
+	  continue;
+	}
+
+      Dwarf_Off off;
+      Dwarf_Off next_off = 0;
+      Dwarf_CU *cu = NULL;
+      Dwarf_Files *files;
+      size_t nfiles;
+      int res;
+      while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
+				      &files, &nfiles, NULL, NULL)) == 0)
+	{
+	  printf ("off = %" PRIu64 "\n", off);
+
+	  const char *const *dirs;
+	  size_t ndirs;
+	  if (dwarf_getsrcdirs (files, &dirs, &ndirs) != 0)
+	    {
+	      printf ("%s: cannot get include directories\n", argv[cnt]);
+	      result = 1;
+	      break;
+	    }
+
+	  if (dirs[0] == NULL)
+	    puts (" dirs[0] = (null)");
+	  else
+	    printf (" dirs[0] = \"%s\"\n", dirs[0]);
+	  for (size_t i = 1; i < ndirs; ++i)
+	    printf (" dirs[%zu] = \"%s\"\n", i, dirs[i]);
+
+	  for (size_t i = 0; i < nfiles; ++i)
+	    printf (" file[%zu] = \"%s\"\n", i,
+		    dwarf_filesrc (files, i, NULL, NULL));
+	}
+
+      if (res < 0)
+	{
+	  printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1));
+	  result = 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/next-lines.c b/tests/next-lines.c
new file mode 100644
index 0000000..cfb74cd
--- /dev/null
+++ b/tests/next-lines.c
@@ -0,0 +1,144 @@
+/* A variant of get-lines that uses dwarf_next_lines.
+   Copyright (C) 2002, 2004, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if  (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  close  (fd);
+	  continue;
+	}
+
+      Dwarf_Off off;
+      Dwarf_Off next_off = 0;
+      Dwarf_CU *cu = NULL;
+      Dwarf_Lines *lb;
+      size_t nlb;
+      int res;
+      while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
+				      NULL, NULL, &lb, &nlb)) == 0)
+	{
+	  printf ("off = %" PRIu64 "\n", off);
+	  printf (" %zu lines\n", nlb);
+
+	  for (size_t i = 0; i < nlb; ++i)
+	    {
+	      Dwarf_Line *l = dwarf_onesrcline (lb, i);
+	      if (l == NULL)
+		{
+		  printf ("%s: cannot get individual line\n", argv[cnt]);
+		  result = 1;
+		  break;
+		}
+
+	      Dwarf_Addr addr;
+	      if (dwarf_lineaddr (l, &addr) != 0)
+		addr = 0;
+	      const char *file = dwarf_linesrc (l, NULL, NULL);
+	      int line;
+	      if (dwarf_lineno (l, &line) != 0)
+		line = 0;
+
+	      printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr,
+		      file ?: "???", line);
+
+	      /* Getting the file path through the Dwarf_Files should
+		 result in the same path.  */
+	      Dwarf_Files *files;
+	      size_t idx;
+	      if (dwarf_line_file (l, &files, &idx) != 0)
+		{
+		  printf ("%s: cannot get file from line (%zd): %s\n",
+			  argv[cnt], i, dwarf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+	      const char *path = dwarf_filesrc (files, idx, NULL, NULL);
+	      if ((path == NULL && file != NULL)
+		  || (path != NULL && file == NULL)
+		  || (strcmp (file, path) != 0))
+		{
+		  printf ("%s: line %zd srcline (%s) != file srcline (%s)\n",
+			  argv[cnt], i, file ?: "???", path ?: "???");
+		  result = 1;
+		  break;
+		}
+
+	      int column;
+	      if (dwarf_linecol (l, &column) != 0)
+		column = 0;
+	      if (column >= 0)
+		printf ("%d:", column);
+
+	      bool is_stmt;
+	      if (dwarf_linebeginstatement (l, &is_stmt) != 0)
+		is_stmt = false;
+	      bool end_sequence;
+	      if (dwarf_lineendsequence (l, &end_sequence) != 0)
+		end_sequence = false;
+	      bool basic_block;
+	      if (dwarf_lineblock (l, &basic_block) != 0)
+		basic_block = false;
+	      bool prologue_end;
+	      if (dwarf_lineprologueend (l, &prologue_end) != 0)
+		prologue_end = false;
+	      bool epilogue_begin;
+	      if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0)
+		epilogue_begin = false;
+
+	      printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n",
+		      is_stmt ? "yes" : "no", end_sequence ? "yes" : "no",
+		      basic_block ? "yes" : "no", prologue_end  ? "yes" : "no",
+		      epilogue_begin ? "yes" : "no");
+	    }
+	}
+
+      if (res < 0)
+	{
+	  printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1));
+	  result = 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/next_cfi.c b/tests/next_cfi.c
new file mode 100644
index 0000000..6a847b4
--- /dev/null
+++ b/tests/next_cfi.c
@@ -0,0 +1,150 @@
+/* Test program for dwarf_next_cfi
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dw)
+#include <dwarf.h>
+#include <argp.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+void
+handle_section (char *name, const unsigned char e_ident[],
+		Elf_Scn *scn, const bool is_eh)
+{
+  if (is_eh)
+    printf (".eh_frame\n");
+  else
+    printf (".debug_frame\n");
+
+  GElf_Shdr mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &mem);
+  if (shdr == NULL)
+    error (EXIT_FAILURE, 0, "Couldn't get section header: %s",
+	   elf_errmsg (-1));
+  if ((shdr->sh_flags & SHF_COMPRESSED) != 0)
+    {
+      if (elf_compress (scn, 0, 0) < 0)
+	error (EXIT_FAILURE, 0, "Couldn't decompress section: %s",
+	       elf_errmsg (-1));
+    }
+  else if (name[0] == '.' && name[1] == 'z')
+    {
+      if (elf_compress_gnu (scn, 0, 0) < 0)
+	error (EXIT_FAILURE, 0, "Couldn't decompress section: %s",
+	       elf_errmsg (-1));
+    }
+
+  Elf_Data *data = elf_getdata (scn, NULL);
+  if (data == NULL || data->d_buf == NULL)
+    error (EXIT_FAILURE, 0, "no section data");
+
+  int res;
+  Dwarf_Off off;
+  Dwarf_Off next_off = 0;
+  Dwarf_CFI_Entry entry;
+  while ((res = dwarf_next_cfi (e_ident, data, is_eh, off = next_off,
+				&next_off, &entry)) == 0)
+    {
+      printf ("[%" PRId64 "] ", off);
+      if (dwarf_cfi_cie_p (&entry))
+	printf ("CIE augmentation=\"%s\"\n", entry.cie.augmentation);
+      else
+	{
+	  printf ("FDE cie=[%" PRId64 "]\n", entry.fde.CIE_pointer);
+
+	  Dwarf_Off cie_off = entry.fde.CIE_pointer;
+	  Dwarf_Off cie_off_next;
+	  Dwarf_CFI_Entry cie_entry;
+	  if (dwarf_next_cfi (e_ident, data, is_eh, cie_off, &cie_off_next,
+			      &cie_entry) != 0
+	      || !dwarf_cfi_cie_p (&cie_entry))
+	    error (EXIT_FAILURE, 0, "FDE doesn't point to CIE");
+	}
+    }
+
+  if (res < 0)
+    error (EXIT_FAILURE, 0, "dwarf_next_cfi failed: %s\n",
+	   dwarf_errmsg (-1));
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 2)
+    error (EXIT_FAILURE, 0, "need file name argument");
+
+  const char *file = argv[1];
+  printf ("%s\n", file);
+
+  int fd = open (file, O_RDONLY);
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, "cannot open input file `%s'", file);
+
+  elf_version (EV_CURRENT);
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    error (EXIT_FAILURE, 0, "cannot create ELF descriptor: %s",
+	   elf_errmsg (-1));
+
+  size_t esize;
+  const unsigned char *ident = (const unsigned char *) elf_getident (elf,
+								     &esize);
+  if (ident == NULL || esize < EI_NIDENT)
+    error (EXIT_FAILURE, 0, "no, or too small, ELF ident");
+
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    error (EXIT_FAILURE, 0, "cannot get the ELF header: %s\n",
+	   elf_errmsg (-1));
+
+  size_t strndx = ehdr.e_shstrndx;
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr;
+      if (gelf_getshdr (scn, &shdr) != NULL)
+	{
+	  char *name = elf_strptr (elf, strndx, (size_t) shdr.sh_name);
+	  if (name != NULL && shdr.sh_type == SHT_PROGBITS)
+	    {
+	      if (strcmp (name, ".eh_frame") == 0)
+		handle_section (name, ident, scn, true);
+	      if (strcmp (name, ".debug_frame") == 0
+		  || strcmp (name, ".zdebug_frame") == 0)
+		handle_section (name, ident, scn, false);
+	    }
+	}
+    }
+
+  elf_end (elf);
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/nvidia_extended_linemap_libdw.c b/tests/nvidia_extended_linemap_libdw.c
new file mode 100644
index 0000000..20d8d40
--- /dev/null
+++ b/tests/nvidia_extended_linemap_libdw.c
@@ -0,0 +1,166 @@
+/* Inspect nvidia extended linemap with dwarf_next_lines.
+   Copyright (C) 2002, 2004, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int result = 0;
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if  (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  close  (fd);
+	  continue;
+	}
+
+      Dwarf_Off off;
+      Dwarf_Off next_off = 0;
+      Dwarf_CU *cu = NULL;
+      Dwarf_Lines *lb;
+      size_t nlb;
+      int res;
+      while ((res = dwarf_next_lines (dbg, off = next_off, &next_off, &cu,
+				      NULL, NULL, &lb, &nlb)) == 0)
+	{
+	  printf ("off = %" PRIu64 "\n", off);
+	  printf (" %zu lines\n", nlb);
+
+	  for (size_t i = 0; i < nlb; ++i)
+	    {
+	      Dwarf_Line *l = dwarf_onesrcline (lb, i);
+	      if (l == NULL)
+		{
+		  printf ("%s: cannot get individual line\n", argv[cnt]);
+		  result = 1;
+		  break;
+		}
+
+	      Dwarf_Addr addr;
+	      if (dwarf_lineaddr (l, &addr) != 0)
+		addr = 0;
+	      const char *file = dwarf_linesrc (l, NULL, NULL);
+	      int line;
+	      if (dwarf_lineno (l, &line) != 0)
+		line = 0;
+
+	      printf ("%" PRIx64 ": %s:%d:", (uint64_t) addr,
+		      file ?: "???", line);
+
+	      /* Getting the file path through the Dwarf_Files should
+		 result in the same path.  */
+	      Dwarf_Files *files;
+	      size_t idx;
+	      if (dwarf_line_file (l, &files, &idx) != 0)
+		{
+		  printf ("%s: cannot get file from line (%zd): %s\n",
+			  argv[cnt], i, dwarf_errmsg (-1));
+		  result = 1;
+		  break;
+		}
+	      const char *path = dwarf_filesrc (files, idx, NULL, NULL);
+	      if ((path == NULL && file != NULL)
+		  || (path != NULL && file == NULL)
+		  || (strcmp (file, path) != 0))
+		{
+		  printf ("%s: line %zd srcline (%s) != file srcline (%s)\n",
+			  argv[cnt], i, file ?: "???", path ?: "???");
+		  result = 1;
+		  break;
+		}
+
+	      int column;
+	      if (dwarf_linecol (l, &column) != 0)
+		column = 0;
+	      if (column >= 0)
+		printf ("%d:", column);
+
+	      bool is_stmt;
+	      if (dwarf_linebeginstatement (l, &is_stmt) != 0)
+		is_stmt = false;
+	      bool end_sequence;
+	      if (dwarf_lineendsequence (l, &end_sequence) != 0)
+		end_sequence = false;
+	      bool basic_block;
+	      if (dwarf_lineblock (l, &basic_block) != 0)
+		basic_block = false;
+	      bool prologue_end;
+	      if (dwarf_lineprologueend (l, &prologue_end) != 0)
+		prologue_end = false;
+	      bool epilogue_begin;
+	      if (dwarf_lineepiloguebegin (l, &epilogue_begin) != 0)
+		epilogue_begin = false;
+	      printf (" is_stmt:%s, end_seq:%s, bb:%s, prologue:%s, epilogue:%s\n",
+		      is_stmt ? "yes" : "no", end_sequence ? "yes" : "no",
+		      basic_block ? "yes" : "no", prologue_end  ? "yes" : "no",
+		      epilogue_begin ? "yes" : "no");
+
+	      Dwarf_Line* callee_context = l;
+	      Dwarf_Line* caller_context = dwarf_linecontext (lb, l);
+	      unsigned int depth = 0;
+	      while (caller_context != NULL)
+		{
+		  depth++;
+		  for (unsigned int x = 0; x < depth; x++)
+		    printf ("  ");
+
+		  const char *inlined_file = dwarf_linesrc (caller_context,
+							    NULL, NULL);
+		  int inlined_line;
+		  if (dwarf_lineno (caller_context, &inlined_line) != 0)
+		    inlined_line = 0;
+
+		  printf ("%s inlined at %s:%d\n",
+			  dwarf_linefunctionname(dbg, callee_context),
+			  inlined_file ?: "???", inlined_line);
+
+		  callee_context = caller_context;
+		  caller_context = dwarf_linecontext (lb, callee_context);
+	        }
+	    }
+	}
+
+      if (res < 0)
+	{
+	  printf ("dwarf_next_lines failed: %s\n", dwarf_errmsg (-1));
+	  result = 1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return result;
+}
diff --git a/tests/peel_type.c b/tests/peel_type.c
new file mode 100644
index 0000000..bccce32
--- /dev/null
+++ b/tests/peel_type.c
@@ -0,0 +1,119 @@
+/* Test program for dwarf_peel_type. Peels type of top-level vars.
+   Copyright (C) 2017 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <assert.h>
+#include <argp.h>
+#include <inttypes.h>
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwfl)
+#include <stdio.h>
+#include <unistd.h>
+#include <dwarf.h>
+
+#include "../libdw/known-dwarf.h"
+
+static const char *
+dwarf_tag_string (unsigned int tag)
+{
+  switch (tag)
+    {
+#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_TAG
+#undef DWARF_ONE_KNOWN_DW_TAG
+    default:
+      return NULL;
+    }
+}
+
+void
+print_var_raw_type (Dwarf_Die *var)
+{
+  Dwarf_Attribute attr_mem;
+  Dwarf_Die type_mem;
+  Dwarf_Die *type;
+  const char *name = dwarf_diename (var);
+
+  type = dwarf_formref_die (dwarf_attr (var, DW_AT_type, &attr_mem),
+			    &type_mem);
+  if (type != NULL)
+    {
+      /* Test twice, once with a separate result DIE. Then with the
+	 DIE itself. The resulting tag should be the same. */
+      Dwarf_Die result_mem;
+      Dwarf_Die *result = &result_mem;
+      int res = dwarf_peel_type (type, result);
+      if (res < 0)
+        printf ("%s error peeling type: %s\n", name, dwarf_errmsg (-1));
+      else if (res > 0)
+	printf ("%s missing DW_TAG_TYPE, could peel further: %s\n",
+		name, dwarf_tag_string (dwarf_tag (result)));
+      else
+	{
+	  int tag = dwarf_tag (result);
+	  printf ("%s raw type %s\n", name, dwarf_tag_string (tag));
+	  res = dwarf_peel_type (type, type);
+	  if (res < 0)
+	    printf ("%s cannot peel type itself: %s\n", name,
+		    dwarf_errmsg (-1));
+	  else if (res > 0)
+	printf ("%s missing DW_TAG_TYPE, could peel type further: %s\n",
+		name, dwarf_tag_string (dwarf_tag (type)));
+	  else if (dwarf_tag (type) != tag)
+	    printf ("%s doesn't resolve the same: %s != %s\n", name,
+		    dwarf_tag_string (tag),
+		    dwarf_tag_string (dwarf_tag (type)));
+	}
+    }
+  else
+    printf ("%s has no type.\n", name);
+}
+
+int
+main (int argc, char *argv[])
+{
+
+  int remaining;
+  Dwfl *dwfl;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+                     &dwfl);
+  assert (dwfl != NULL);
+
+  Dwarf_Die *cu = NULL;
+  Dwarf_Addr dwbias;
+  while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
+    {
+      Dwarf_Die die_mem;
+      Dwarf_Die *die = &die_mem;
+      dwarf_child (cu, &die_mem);
+
+      while (1)
+	{
+	  if (dwarf_tag (die) == DW_TAG_variable)
+	    print_var_raw_type (die);
+
+	  if (dwarf_siblingof (die, &die_mem) != 0)
+	    break;
+	}
+    }
+
+  dwfl_end (dwfl);
+}
diff --git a/tests/rdwrmmap.c b/tests/rdwrmmap.c
new file mode 100644
index 0000000..490a4ee
--- /dev/null
+++ b/tests/rdwrmmap.c
@@ -0,0 +1,49 @@
+/* Copyright (C) 2006 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <libelf.h>
+#include "system.h"
+
+int
+main (int argc __attribute__ ((unused)), char *argv[])
+{
+  int fd = open (argv[1], O_RDWR);
+  if (fd < 0)
+    error (2, errno, "open: %s", argv[1]);
+
+  if (elf_version (EV_CURRENT) == EV_NONE)
+    error (1, 0, "libelf version mismatch");
+
+  Elf *elf = elf_begin (fd, ELF_C_RDWR_MMAP, NULL);
+  if (elf == NULL)
+    error (1, 0, "elf_begin: %s", elf_errmsg (-1));
+
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    error (1, 0, "elf_update: %s", elf_errmsg (-1));
+
+  elf_end (elf);
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/read_unaligned.c b/tests/read_unaligned.c
new file mode 100644
index 0000000..15e0c00
--- /dev/null
+++ b/tests/read_unaligned.c
@@ -0,0 +1,564 @@
+/* Test program for read_[type]_unaligned.
+   Copyright (C) 2020, Red Hat Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <endian.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdio.h>
+
+#include "../libdw/libdwP.h"
+#include "../libdw/memory-access.h"
+
+union u8
+{
+  uint8_t v;
+  unsigned char c[1];
+};
+
+union s8
+{
+  int8_t v;
+  unsigned char c[1];
+};
+
+union u16
+{
+  uint16_t v;
+  unsigned char c[2];
+};
+
+union s16
+{
+  int16_t v;
+  unsigned char c[2];
+};
+
+union u24
+{
+  uint32_t v:24;
+  unsigned char c[3];
+} __attribute__((packed));
+
+union u32
+{
+  uint32_t v;
+  unsigned char c[4];
+};
+
+union s32
+{
+  int32_t v;
+  unsigned char c[4];
+};
+
+union u64
+{
+  uint64_t v;
+  unsigned char c[8];
+};
+
+union s64
+{
+  uint64_t v;
+  unsigned char c[8];
+};
+
+uint8_t u8_nums[] =
+  {
+   0,
+   1,
+   UINT8_MAX / 2 - 1,
+   UINT8_MAX / 2,
+   UINT8_MAX / 2 + 1,
+   UINT8_MAX,
+   UINT8_MAX -1
+  };
+
+int8_t s8_nums[] =
+  {
+   INT8_MIN,
+   INT8_MIN + 1,
+   -1,
+   0,
+   1,
+   INT8_MAX,
+   INT8_MAX - 1
+  };
+
+uint16_t u16_nums[] =
+  {
+   0,
+   1,
+   UINT16_MAX / 2 - 1,
+   UINT16_MAX / 2,
+   UINT16_MAX / 2 + 1,
+   UINT16_MAX,
+   UINT16_MAX -1
+  };
+
+int16_t s16_nums[] =
+  {
+   INT16_MIN,
+   INT16_MIN + 1,
+   -1,
+   0,
+   1,
+   INT16_MAX,
+   INT16_MAX - 1
+  };
+
+#define UINT24_MAX 0xffffff
+
+uint32_t u24_nums[] =
+  {
+   0,
+   1,
+   UINT24_MAX / 2 - 1,
+   UINT24_MAX / 2,
+   UINT24_MAX / 2 + 1,
+   UINT24_MAX,
+   UINT24_MAX -1
+  };
+
+uint32_t u32_nums[] =
+  {
+   0,
+   1,
+   UINT32_MAX / 2 - 1,
+   UINT32_MAX / 2,
+   UINT32_MAX / 2 + 1,
+   UINT32_MAX,
+   UINT32_MAX -1
+  };
+
+int32_t s32_nums[] =
+  {
+   INT32_MIN,
+   INT32_MIN + 1,
+   -1,
+   0,
+   1,
+   INT32_MAX,
+   INT32_MAX - 1
+  };
+
+uint64_t u64_nums[] =
+  {
+   0,
+   1,
+   UINT64_MAX / 2 - 1,
+   UINT64_MAX / 2,
+   UINT64_MAX / 2 + 1,
+   UINT64_MAX,
+   UINT64_MAX -1
+  };
+
+int64_t s64_nums[] =
+  {
+   INT64_MIN,
+   INT64_MIN + 1,
+   -1,
+   0,
+   1,
+   INT64_MAX,
+   INT64_MAX - 1
+  };
+
+static unsigned char le_mem[] =
+  {
+    /* u8 */
+    0x00,
+    0x01,
+    0x7e,
+    0x7f,
+    0x80,
+    0xff,
+    0xfe,
+    /* s8 */
+    0x80,
+    0x81,
+    0xff,
+    0x00,
+    0x01,
+    0x7f,
+    0x7e,
+    /* u16 */
+    0x00, 0x00,
+    0x01, 0x00,
+    0xfe, 0x7f,
+    0xff, 0x7f,
+    0x00, 0x80,
+    0xff, 0xff,
+    0xfe, 0xff,
+    /* s16 */
+    0x00, 0x80,
+    0x01, 0x80,
+    0xff, 0xff,
+    0x00, 0x00,
+    0x01, 0x00,
+    0xff, 0x7f,
+    0xfe, 0x7f,
+    /* u24 */
+    0x00, 0x00, 0x00,
+    0x01, 0x00, 0x00,
+    0xfe, 0xff, 0x7f,
+    0xff, 0xff, 0x7f,
+    0x00, 0x00, 0x80,
+    0xff, 0xff, 0xff,
+    0xfe, 0xff, 0xff,
+    /* u32 */
+    0x00, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x00, 0x00,
+    0xfe, 0xff, 0xff, 0x7f,
+    0xff, 0xff, 0xff, 0x7f,
+    0x00, 0x00, 0x00, 0x80,
+    0xff, 0xff, 0xff, 0xff,
+    0xfe, 0xff, 0xff, 0xff,
+    /* s32 */
+    0x00, 0x00, 0x00, 0x80,
+    0x01, 0x00, 0x00, 0x80,
+    0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0x7f,
+    0xfe, 0xff, 0xff, 0x7f,
+    /* u64 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    /* s64 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+    0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+  };
+
+static unsigned char be_mem[] =
+  {
+    /* u8 */
+    0x00,
+    0x01,
+    0x7e,
+    0x7f,
+    0x80,
+    0xff,
+    0xfe,
+    /* s8 */
+    0x80,
+    0x81,
+    0xff,
+    0x00,
+    0x01,
+    0x7f,
+    0x7e,
+    /* u16 */
+    0x00, 0x00,
+    0x00, 0x01,
+    0x7f, 0xfe,
+    0x7f, 0xff,
+    0x80, 0x00,
+    0xff, 0xff,
+    0xff, 0xfe,
+    /* s16 */
+    0x80, 0x00,
+    0x80, 0x01,
+    0xff, 0xff,
+    0x00, 0x00,
+    0x00, 0x01,
+    0x7f, 0xff,
+    0x7f, 0xfe,
+    /* u24 */
+    0x00, 0x00, 0x00,
+    0x00, 0x00, 0x01,
+    0x7f, 0xff, 0xfe,
+    0x7f, 0xff, 0xff,
+    0x80, 0x00, 0x00,
+    0xff, 0xff, 0xff,
+    0xff, 0xff, 0xfe,
+    /* u32 */
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01,
+    0x7f, 0xff, 0xff, 0xfe,
+    0x7f, 0xff, 0xff, 0xff,
+    0x80, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xfe,
+    /* s32 */
+    0x80, 0x00, 0x00, 0x00,
+    0x80, 0x00, 0x00, 0x01,
+    0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x01,
+    0x7f, 0xff, 0xff, 0xff,
+    0x7f, 0xff, 0xff, 0xfe,
+    /* u64 */
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+    /* s64 */
+    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+    0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe,
+  };
+
+int
+main (int argc, char **argv __attribute__((unused)))
+{
+  /* No arguments means check, otherwise Write out the memory array.  */
+  bool write = false;
+  if (argc > 1)
+    write = true;
+
+  bool is_le = (BYTE_ORDER == LITTLE_ENDIAN);
+
+  if (write)
+    {
+      if (is_le)
+	printf ("static unsigned char le_mem[] =\n");
+      else
+	printf ("static unsigned char be_mem[] =\n");
+      printf ("  {\n");
+    }
+
+  Dwarf dbg_le = { .other_byte_order = !is_le };
+  Dwarf dbg_be = { .other_byte_order = is_le };
+
+  unsigned char *p_le = le_mem;
+  unsigned char *p_be = be_mem;
+
+  union u8 u8;
+  if (write)
+    printf ("    /* u8 */\n");
+  for (size_t i = 0; i < sizeof (u8_nums) / sizeof (u8); i++)
+    {
+      if (write)
+	{
+	  u8.v = u8_nums[i];
+	  printf ("    0x%02" PRIx8 ",\n", u8.c[0]);
+	}
+      else
+	{
+	  uint8_t v = *p_le++;
+	  assert (v == u8_nums[i]);
+	  v = *p_be++;
+	  assert (v == u8_nums[i]);
+	}
+    }
+
+  union s8 s8;
+  if (write)
+    printf ("    /* s8 */\n");
+  for (size_t i = 0; i < sizeof (s8_nums) / sizeof (s8); i++)
+    {
+      if (write)
+	{
+	  s8.v = s8_nums[i];
+	  printf ("    0x%02" PRIx8 ",\n", s8.c[0]);
+	}
+      else
+	{
+	  int8_t v = *p_le++;
+	  assert (v == s8_nums[i]);
+	  v = *p_be++;
+	  assert (v == s8_nums[i]);
+	}
+    }
+
+  union u16 u16;
+  if (write)
+    printf ("    /* u16 */\n");
+  for (size_t i = 0; i < sizeof (u16_nums) / sizeof (u16); i++)
+    {
+      if (write)
+	{
+	  u16.v = u16_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", u16.c[0]);
+	  printf ("0x%02" PRIx8 ",\n", u16.c[1]);
+	}
+      else
+	{
+	  uint16_t v = read_2ubyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == u16_nums[i]);
+	  v = read_2ubyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == u16_nums[i]);
+	}
+    }
+
+  union s16 s16;
+  if (write)
+    printf ("    /* s16 */\n");
+  for (size_t i = 0; i < sizeof (s16_nums) / sizeof (s16); i++)
+    {
+      if (write)
+	{
+	  s16.v = s16_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", s16.c[0]);
+	  printf ("0x%02" PRIx8 ",\n", s16.c[1]);
+	}
+      else
+	{
+	  int16_t v = read_2sbyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == s16_nums[i]);
+	  v = read_2sbyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == s16_nums[i]);
+	}
+    }
+
+  union u24 u24;
+  if (write)
+    printf ("    /* u24 */\n");
+  for (size_t i = 0; i < sizeof (u24_nums) / sizeof (uint32_t); i++)
+    {
+      if (write)
+	{
+	  u24.v = u24_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", u24.c[0]);
+	  printf ("0x%02" PRIx8 ", ", u24.c[1]);
+	  printf ("0x%02" PRIx8 ",\n", u24.c[2]);
+	}
+      else
+	{
+	  uint32_t v = read_3ubyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == u24_nums[i]);
+	  v = read_3ubyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == u24_nums[i]);
+	}
+    }
+
+  union u32 u32;
+  if (write)
+    printf ("    /* u32 */\n");
+  for (size_t i = 0; i < sizeof (u32_nums) / sizeof (u32); i++)
+    {
+      if (write)
+	{
+	  u32.v = u32_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", u32.c[0]);
+	  printf ("0x%02" PRIx8 ", ", u32.c[1]);
+	  printf ("0x%02" PRIx8 ", ", u32.c[2]);
+	  printf ("0x%02" PRIx8 ",\n", u32.c[3]);
+	}
+      else
+	{
+	  uint32_t v = read_4ubyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == u32_nums[i]);
+	  v = read_4ubyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == u32_nums[i]);
+	}
+    }
+
+  union s32 s32;
+  if (write)
+    printf ("    /* s32 */\n");
+  for (size_t i = 0; i < sizeof (s32_nums) / sizeof (s32); i++)
+    {
+      if (write)
+	{
+	  s32.v = s32_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", s32.c[0]);
+	  printf ("0x%02" PRIx8 ", ", s32.c[1]);
+	  printf ("0x%02" PRIx8 ", ", s32.c[2]);
+	  printf ("0x%02" PRIx8 ",\n", s32.c[3]);
+	}
+      else
+	{
+	  int32_t v = read_4sbyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == s32_nums[i]);
+	  v = read_4sbyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == s32_nums[i]);
+	}
+    }
+
+  union u64 u64;
+  if (write)
+    printf ("    /* u64 */\n");
+  for (size_t i = 0; i < sizeof (u64_nums) / sizeof (u64); i++)
+    {
+      if (write)
+	{
+	  u64.v = u64_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", u64.c[0]);
+	  printf ("0x%02" PRIx8 ", ", u64.c[1]);
+	  printf ("0x%02" PRIx8 ", ", u64.c[2]);
+	  printf ("0x%02" PRIx8 ", ", u64.c[3]);
+	  printf ("0x%02" PRIx8 ", ", u64.c[4]);
+	  printf ("0x%02" PRIx8 ", ", u64.c[5]);
+	  printf ("0x%02" PRIx8 ", ", u64.c[6]);
+	  printf ("0x%02" PRIx8 ",\n", u64.c[7]);
+	}
+      else
+	{
+	  uint64_t v = read_8ubyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == u64_nums[i]);
+	  v = read_8ubyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == u64_nums[i]);
+	}
+    }
+
+  union s64 s64;
+  if (write)
+    printf ("    /* s64 */\n");
+  for (size_t i = 0; i < sizeof (s64_nums) / sizeof (s64); i++)
+    {
+      if (write)
+	{
+	  s64.v = s64_nums[i];
+	  printf ("    0x%02" PRIx8 ", ", s64.c[0]);
+	  printf ("0x%02" PRIx8 ", ", s64.c[1]);
+	  printf ("0x%02" PRIx8 ", ", s64.c[2]);
+	  printf ("0x%02" PRIx8 ", ", s64.c[3]);
+	  printf ("0x%02" PRIx8 ", ", s64.c[4]);
+	  printf ("0x%02" PRIx8 ", ", s64.c[5]);
+	  printf ("0x%02" PRIx8 ", ", s64.c[6]);
+	  printf ("0x%02" PRIx8 ",\n", s64.c[7]);
+	}
+      else
+	{
+	  int64_t v = read_8sbyte_unaligned_inc (&dbg_le, p_le);
+	  assert (v == s64_nums[i]);
+	  v = read_8sbyte_unaligned_inc (&dbg_be, p_be);
+	  assert (v == s64_nums[i]);
+	}
+    }
+
+  if (write)
+    printf ("  };\n");
+  else
+    {
+      assert (p_le == le_mem + sizeof (le_mem));
+      assert (p_be == be_mem + sizeof (be_mem));
+    }
+
+  return 0;
+}
diff --git a/tests/rerequest_tag.c b/tests/rerequest_tag.c
new file mode 100644
index 0000000..b4d4627
--- /dev/null
+++ b/tests/rerequest_tag.c
@@ -0,0 +1,47 @@
+/* Copyright (C) 2011 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include ELFUTILS_HEADER(dw)
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+int
+main (int argc, char **argv)
+{
+  assert (argc > 1);
+
+  int i = open (argv[1], O_RDONLY);
+  assert (i >= 0);
+
+  Dwarf *dw = dwarf_begin (i, DWARF_C_READ);
+  assert (dw != NULL);
+
+  Dwarf_Die die_mem, *die;
+  die = dwarf_offdie (dw, 11, &die_mem);
+  assert (die == &die_mem);
+  assert (dwarf_tag (die) == 0);
+
+  die = dwarf_offdie (dw, 11, &die_mem);
+  assert (die == &die_mem);
+  assert (dwarf_tag (die) == 0);
+
+  dwarf_end (dw);
+  return 0;
+}
diff --git a/tests/run-addr2line-C-test.sh b/tests/run-addr2line-C-test.sh
new file mode 100755
index 0000000..1780157
--- /dev/null
+++ b/tests/run-addr2line-C-test.sh
@@ -0,0 +1,96 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+  echo "demangler unsupported"
+  exit 77
+fi
+
+# See run-addr2line-i-test.sh
+testfiles testfile-inlines
+
+# Three variants -Cfi, -fCi -fiC all the same (with demangle)
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty-print -a -Cfi -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+0x00000000000005a0: foobar at /tmp/x.cpp:5
+0x00000000000005a1: foobar at /tmp/x.cpp:6
+0x00000000000005b0: fubar at /tmp/x.cpp:10
+0x00000000000005b1: fubar at /tmp/x.cpp:11
+0x00000000000005c0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+0x00000000000005d0: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+0x00000000000005e0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+ (inlined by) foo() at /tmp/x.cpp:25
+0x00000000000005e1: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+ (inlined by) foo() at /tmp/x.cpp:26
+0x00000000000005f0: fu() at /tmp/x.cpp:31
+0x00000000000005f1: fubar at /tmp/x.cpp:10
+ (inlined by) fu() at /tmp/x.cpp:32
+0x00000000000005f2: foobar at /tmp/x.cpp:5
+ (inlined by) fu() at /tmp/x.cpp:33
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty-print -a -fCi -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+0x00000000000005a0: foobar at /tmp/x.cpp:5
+0x00000000000005a1: foobar at /tmp/x.cpp:6
+0x00000000000005b0: fubar at /tmp/x.cpp:10
+0x00000000000005b1: fubar at /tmp/x.cpp:11
+0x00000000000005c0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+0x00000000000005d0: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+0x00000000000005e0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+ (inlined by) foo() at /tmp/x.cpp:25
+0x00000000000005e1: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+ (inlined by) foo() at /tmp/x.cpp:26
+0x00000000000005f0: fu() at /tmp/x.cpp:31
+0x00000000000005f1: fubar at /tmp/x.cpp:10
+ (inlined by) fu() at /tmp/x.cpp:32
+0x00000000000005f2: foobar at /tmp/x.cpp:5
+ (inlined by) fu() at /tmp/x.cpp:33
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty-print -a -fiC -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+0x00000000000005a0: foobar at /tmp/x.cpp:5
+0x00000000000005a1: foobar at /tmp/x.cpp:6
+0x00000000000005b0: fubar at /tmp/x.cpp:10
+0x00000000000005b1: fubar at /tmp/x.cpp:11
+0x00000000000005c0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+0x00000000000005d0: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+0x00000000000005e0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+ (inlined by) foo() at /tmp/x.cpp:25
+0x00000000000005e1: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+ (inlined by) foo() at /tmp/x.cpp:26
+0x00000000000005f0: fu() at /tmp/x.cpp:31
+0x00000000000005f1: fubar at /tmp/x.cpp:10
+ (inlined by) fu() at /tmp/x.cpp:32
+0x00000000000005f2: foobar at /tmp/x.cpp:5
+ (inlined by) fu() at /tmp/x.cpp:33
+EOF
+
+exit 0
diff --git a/tests/run-addr2line-alt-debugpath.sh b/tests/run-addr2line-alt-debugpath.sh
new file mode 100755
index 0000000..b508700
--- /dev/null
+++ b/tests/run-addr2line-alt-debugpath.sh
@@ -0,0 +1,67 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-addr2line-i-test.sh
+testfiles testfile-inlines
+
+# Split off the debuginfo and put it under a separate subdir from the
+# original binary.  Use --debuginfo-path to connect the dots again.
+# Note that we use separate subdirs/roots for the binaries and debug files.
+abs_test_bindir=$(pwd)/bindir
+abs_test_debugdir=$(pwd)/debugdir
+
+mkdir ${abs_test_bindir}
+mkdir ${abs_test_bindir}/bin
+mkdir ${abs_test_debugdir}
+mkdir ${abs_test_debugdir}/bin
+
+testrun ${abs_top_builddir}/src/strip -f ${abs_test_debugdir}/bin/testfile-inlines.debug -o ${abs_test_bindir}/bin/testfile-inlines testfile-inlines
+
+# Can we find the separate debuginfo file now?
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty-print -a -f -i -e ${abs_test_bindir}/bin/testfile-inlines --debuginfo-path=${abs_test_debugdir} 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+0x00000000000005a0: foobar at /tmp/x.cpp:5
+0x00000000000005a1: foobar at /tmp/x.cpp:6
+0x00000000000005b0: fubar at /tmp/x.cpp:10
+0x00000000000005b1: fubar at /tmp/x.cpp:11
+0x00000000000005c0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+0x00000000000005d0: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+0x00000000000005e0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+ (inlined by) _Z3foov at /tmp/x.cpp:25
+0x00000000000005e1: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+ (inlined by) _Z3foov at /tmp/x.cpp:26
+0x00000000000005f0: _Z2fuv at /tmp/x.cpp:31
+0x00000000000005f1: fubar at /tmp/x.cpp:10
+ (inlined by) _Z2fuv at /tmp/x.cpp:32
+0x00000000000005f2: foobar at /tmp/x.cpp:5
+ (inlined by) _Z2fuv at /tmp/x.cpp:33
+EOF
+
+# Cleanup
+rm ${abs_test_bindir}/bin/testfile-inlines
+rm ${abs_test_debugdir}/bin/testfile-inlines.debug
+rmdir ${abs_test_bindir}/bin
+rmdir ${abs_test_bindir}
+rmdir ${abs_test_debugdir}/bin
+rmdir ${abs_test_debugdir}
+
+exit 0
diff --git a/tests/run-addr2line-i-demangle-test.sh b/tests/run-addr2line-i-demangle-test.sh
new file mode 100755
index 0000000..1af8562
--- /dev/null
+++ b/tests/run-addr2line-i-demangle-test.sh
@@ -0,0 +1,70 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+  echo "demangler unsupported"
+  exit 77
+fi
+
+. $srcdir/test-subr.sh
+
+# See run-addr2line-i-test.sh for how to generate test files.
+testfiles testfile-inlines
+
+# All together now plus (demangled) function names.
+testrun_compare ${abs_top_builddir}/src/addr2line -C -f -i -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+foobar
+/tmp/x.cpp:5
+foobar
+/tmp/x.cpp:6
+fubar
+/tmp/x.cpp:10
+fubar
+/tmp/x.cpp:11
+foobar inlined at /tmp/x.cpp:15 in bar()
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+fubar inlined at /tmp/x.cpp:20 in baz()
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+foobar inlined at /tmp/x.cpp:15 in foo()
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+foo()
+/tmp/x.cpp:25
+fubar inlined at /tmp/x.cpp:20 in foo()
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+foo()
+/tmp/x.cpp:26
+fu()
+/tmp/x.cpp:31
+fubar inlined at /tmp/x.cpp:32 in fu()
+/tmp/x.cpp:10
+fu()
+/tmp/x.cpp:32
+foobar inlined at /tmp/x.cpp:33 in fu()
+/tmp/x.cpp:5
+fu()
+/tmp/x.cpp:33
+EOF
+
+exit 0
diff --git a/tests/run-addr2line-i-lex-test.sh b/tests/run-addr2line-i-lex-test.sh
new file mode 100755
index 0000000..c391fd9
--- /dev/null
+++ b/tests/run-addr2line-i-lex-test.sh
@@ -0,0 +1,71 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# // g++ x.cpp -g -fPIC -olibx.so -shared -O3 -fvisibility=hidden
+#
+# void foobar()
+# {
+#   __asm__ ( "nop" ::: );
+# }
+#
+# void foo()
+# {
+#   {
+#     void (*bar) () = foobar;
+#     bar();
+#   }
+# }
+
+testfiles testfile-lex-inlines
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-lex-inlines 0x0000000000000680 <<\EOF
+/tmp/x.cpp:5
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-lex-inlines 0x0000000000000681 <<\EOF
+/tmp/x.cpp:5
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-lex-inlines 0x0000000000000690 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:12
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-lex-inlines 0x0000000000000691 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:12
+EOF
+
+# All together now (plus function names).
+testrun_compare ${abs_top_builddir}/src/addr2line -f -i -e testfile-lex-inlines 0x0000000000000680 0x0000000000000681 0x0000000000000690 0x0000000000000691 <<\EOF
+_Z6foobarv
+/tmp/x.cpp:5
+_Z6foobarv
+/tmp/x.cpp:5
+foobar inlined at /tmp/x.cpp:12 in _Z3foov
+/tmp/x.cpp:5
+_Z3foov
+/tmp/x.cpp:12
+foobar inlined at /tmp/x.cpp:12 in _Z3foov
+/tmp/x.cpp:5
+_Z3foov
+/tmp/x.cpp:12
+EOF
+
+exit 0
diff --git a/tests/run-addr2line-i-test.sh b/tests/run-addr2line-i-test.sh
new file mode 100755
index 0000000..e7b8908
--- /dev/null
+++ b/tests/run-addr2line-i-test.sh
@@ -0,0 +1,266 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# // g++ x.cpp -g -fPIC -olibx.so -shared -O3 -fvisibility=hidden
+#
+# void foobar()
+# {
+#   __asm__ ( "nop" ::: );
+# }
+#
+# void fubar()
+# {
+#   __asm__ ( "nop" ::: );
+# }
+#
+# void bar()
+# {
+#   foobar();
+# }
+#
+# void baz()
+# {
+#   fubar();
+# }
+#
+# void foo()
+# {
+#   bar();
+#   baz();
+# }
+#
+# void fu()
+# {
+#   __asm__ ( "nop" ::: );
+#   fubar();
+#   foobar();
+# }
+
+testfiles testfile-inlines
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005a0 <<\EOF
+/tmp/x.cpp:5
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005a1 <<\EOF
+/tmp/x.cpp:6
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005b0 <<\EOF
+/tmp/x.cpp:10
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005b1 <<\EOF
+/tmp/x.cpp:11
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005c0 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:15
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005d0 <<\EOF
+/tmp/x.cpp:10
+/tmp/x.cpp:20
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005e0 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:15
+/tmp/x.cpp:25
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005e1 <<\EOF
+/tmp/x.cpp:10
+/tmp/x.cpp:20
+/tmp/x.cpp:26
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005f1 <<\EOF
+/tmp/x.cpp:10
+/tmp/x.cpp:32
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -i -e testfile-inlines 0x00000000000005f2 <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:33
+EOF
+
+# All together now (plus function names).
+testrun_compare ${abs_top_builddir}/src/addr2line -f -i -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+foobar
+/tmp/x.cpp:5
+foobar
+/tmp/x.cpp:6
+fubar
+/tmp/x.cpp:10
+fubar
+/tmp/x.cpp:11
+foobar inlined at /tmp/x.cpp:15 in _Z3barv
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+fubar inlined at /tmp/x.cpp:20 in _Z3bazv
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+foobar inlined at /tmp/x.cpp:15 in _Z3foov
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+_Z3foov
+/tmp/x.cpp:25
+fubar inlined at /tmp/x.cpp:20 in _Z3foov
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+_Z3foov
+/tmp/x.cpp:26
+_Z2fuv
+/tmp/x.cpp:31
+fubar inlined at /tmp/x.cpp:32 in _Z2fuv
+/tmp/x.cpp:10
+_Z2fuv
+/tmp/x.cpp:32
+foobar inlined at /tmp/x.cpp:33 in _Z2fuv
+/tmp/x.cpp:5
+_Z2fuv
+/tmp/x.cpp:33
+EOF
+
+# All together now (plus function names plus addresses).
+testrun_compare ${abs_top_builddir}/src/addr2line -a -f -i -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+0x00000000000005a0
+foobar
+/tmp/x.cpp:5
+0x00000000000005a1
+foobar
+/tmp/x.cpp:6
+0x00000000000005b0
+fubar
+/tmp/x.cpp:10
+0x00000000000005b1
+fubar
+/tmp/x.cpp:11
+0x00000000000005c0
+foobar inlined at /tmp/x.cpp:15 in _Z3barv
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+0x00000000000005d0
+fubar inlined at /tmp/x.cpp:20 in _Z3bazv
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+0x00000000000005e0
+foobar inlined at /tmp/x.cpp:15 in _Z3foov
+/tmp/x.cpp:5
+bar
+/tmp/x.cpp:15
+_Z3foov
+/tmp/x.cpp:25
+0x00000000000005e1
+fubar inlined at /tmp/x.cpp:20 in _Z3foov
+/tmp/x.cpp:10
+baz
+/tmp/x.cpp:20
+_Z3foov
+/tmp/x.cpp:26
+0x00000000000005f0
+_Z2fuv
+/tmp/x.cpp:31
+0x00000000000005f1
+fubar inlined at /tmp/x.cpp:32 in _Z2fuv
+/tmp/x.cpp:10
+_Z2fuv
+/tmp/x.cpp:32
+0x00000000000005f2
+foobar inlined at /tmp/x.cpp:33 in _Z2fuv
+/tmp/x.cpp:5
+_Z2fuv
+/tmp/x.cpp:33
+EOF
+
+# All together now (plus function names and addresses and pretty)
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty-print -a -f -i -e testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f0 0x00000000000005f1 0x00000000000005f2 <<\EOF
+0x00000000000005a0: foobar at /tmp/x.cpp:5
+0x00000000000005a1: foobar at /tmp/x.cpp:6
+0x00000000000005b0: fubar at /tmp/x.cpp:10
+0x00000000000005b1: fubar at /tmp/x.cpp:11
+0x00000000000005c0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+0x00000000000005d0: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+0x00000000000005e0: foobar at /tmp/x.cpp:5
+ (inlined by) bar at /tmp/x.cpp:15
+ (inlined by) _Z3foov at /tmp/x.cpp:25
+0x00000000000005e1: fubar at /tmp/x.cpp:10
+ (inlined by) baz at /tmp/x.cpp:20
+ (inlined by) _Z3foov at /tmp/x.cpp:26
+0x00000000000005f0: _Z2fuv at /tmp/x.cpp:31
+0x00000000000005f1: fubar at /tmp/x.cpp:10
+ (inlined by) _Z2fuv at /tmp/x.cpp:32
+0x00000000000005f2: foobar at /tmp/x.cpp:5
+ (inlined by) _Z2fuv at /tmp/x.cpp:33
+EOF
+
+# == x.cpp ==
+# g++ x.cpp -g -fPIC -olibx.so -shared -O0 -flto
+#
+# __attribute__((always_inline)) inline
+# int foobar(int i)
+# {
+#   return i + 1;
+# }
+#
+# __attribute__((always_inline)) inline
+# int fubar(int i)
+# {
+#   return i + 1;
+# }
+#
+# __attribute__((always_inline)) inline
+# int bar(int i)
+# {
+#   return fubar(i++);
+# }
+#
+# __attribute__((always_inline)) inline
+# int foo(int i)
+# {
+#   return foobar(i++);
+# }
+#
+# int fu(int i)
+# {
+#   return foo(i++) + bar(i++);
+# }
+
+testfiles testfile-inlines-lto
+
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty -fi -e testfile-inlines-lto 0x1118 0x1137 <<\EOF
+_Z6foobari at /tmp/x.cpp:4:14
+ (inlined by) _Z3fooi at /tmp/x.cpp:22:16
+ (inlined by) _Z2fui at /tmp/x.cpp:27:13
+_Z5fubari at /tmp/x.cpp:10:14
+ (inlined by) _Z3bari at /tmp/x.cpp:16:15
+ (inlined by) _Z2fui at /tmp/x.cpp:27:24
+EOF
+
+exit 0
diff --git a/tests/run-addr2line-test.sh b/tests/run-addr2line-test.sh
new file mode 100755
index 0000000..1079c3e
--- /dev/null
+++ b/tests/run-addr2line-test.sh
@@ -0,0 +1,116 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile
+tempfiles good.out stdin.nl stdin.nl.out stdin.nonl stdin.nonl.out foo.out
+tempfiles addr2line.out
+
+cat > good.out <<\EOF
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+EOF
+
+echo "# Everything on the command line"
+cat good.out | testrun_compare ${abs_top_builddir}/src/addr2line -f -e testfile 0x08048468 0x0804845c foo bar foo+0x0 bar+0x0 foo-0x0 bar-0x0
+
+cat > stdin.nl <<\EOF
+0x08048468
+0x0804845c
+foo
+bar
+foo+0x0
+bar+0x0
+foo-0x0
+bar-0x0
+EOF
+
+echo "# Everything from stdin (with newlines)."
+cat stdin.nl | testrun ${abs_top_builddir}/src/addr2line -f -e testfile > stdin.nl.out || exit 1
+cmp good.out stdin.nl.out || exit 1
+
+cat > foo.out <<\EOF
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+EOF
+
+echo "# stdin without newline address, just EOF."
+echo -n "0x08048468" | testrun ${abs_top_builddir}/src/addr2line -f -e testfile > stdin.nonl.out || exit 1
+cmp foo.out stdin.nonl.out || exit 1
+
+echo "# stdin without newline symbol, just EOF."
+echo -n "foo" | testrun ${abs_top_builddir}/src/addr2line -f -e testfile > stdin.nl.out || exit 1
+cmp foo.out stdin.nonl.out || exit 1
+
+tempfiles good.addr.out
+
+cat > good.addr.out <<\EOF
+0x08048468
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+0x0804845c
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+0x08048468
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+0x0804845c
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+0x08048468
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+0x0804845c
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+0x08048468
+foo
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+0x0804845c
+bar
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+EOF
+
+echo "# Everything on the command line with addresses"
+cat good.addr.out | testrun_compare ${abs_top_builddir}/src/addr2line -a -f -e testfile 0x08048468 0x0804845c foo bar foo+0x0 bar+0x0 foo-0x0 bar-0x0
+
+echo "# Everything from stdin (with newlines) with addresses."
+cat stdin.nl | testrun ${abs_top_builddir}/src/addr2line -a -f -e testfile > stdin.nl.out || exit 1
+cmp good.addr.out stdin.nl.out || exit 1
+
+echo "# Pretty with functions and addresses."
+testrun_compare ${abs_top_builddir}/src/addr2line --pretty -a -f -e testfile 0x08048468 0x0804845c << EOF
+0x08048468: foo at /home/drepper/gnu/new-bu/build/ttt/f.c:3
+0x0804845c: bar at /home/drepper/gnu/new-bu/build/ttt/b.c:4
+EOF
+
+exit 0
diff --git a/tests/run-addrcfi.sh b/tests/run-addrcfi.sh
new file mode 100755
index 0000000..64fa24d
--- /dev/null
+++ b/tests/run-addrcfi.sh
@@ -0,0 +1,3792 @@
+#! /bin/sh
+# Copyright (C) 2013
+# Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Note some testfiles are also used in run-allregs.sh.
+
+# Shows return address, CFA location expression and register rules
+# from ABI's default CFI program as setup by arch ebl backend hook
+# abi_cfi unless overridden by CIE and FDE program at given address.
+
+# EM_386 (function main 0x080489b8)
+testfiles testfile11
+testrun_compare ${abs_builddir}/addrcfi -e testfile11 0x080489b8 <<\EOF
+.eh_frame has 0x80489b8 => [0x80489b8, 0x80489b9):
+	return address in reg8
+	CFA location expression: bregx(4,4)
+	integer reg0 (%eax): undefined
+	integer reg1 (%ecx): undefined
+	integer reg2 (%edx): undefined
+	integer reg3 (%ebx): same_value
+	integer reg4 (%esp): location expression: call_frame_cfa stack_value
+	integer reg5 (%ebp): same_value
+	integer reg6 (%esi): same_value
+	integer reg7 (%edi): same_value
+	integer reg8 (%eip): location expression: call_frame_cfa plus_uconst(-4)
+	integer reg9 (%eflags): undefined
+	integer reg10 (%trapno): undefined
+	x87 reg11 (%st0): undefined
+	x87 reg12 (%st1): undefined
+	x87 reg13 (%st2): undefined
+	x87 reg14 (%st3): undefined
+	x87 reg15 (%st4): undefined
+	x87 reg16 (%st5): undefined
+	x87 reg17 (%st6): undefined
+	x87 reg18 (%st7): undefined
+	SSE reg21 (%xmm0): undefined
+	SSE reg22 (%xmm1): undefined
+	SSE reg23 (%xmm2): undefined
+	SSE reg24 (%xmm3): undefined
+	SSE reg25 (%xmm4): undefined
+	SSE reg26 (%xmm5): undefined
+	SSE reg27 (%xmm6): undefined
+	SSE reg28 (%xmm7): undefined
+	MMX reg29 (%mm0): undefined
+	MMX reg30 (%mm1): undefined
+	MMX reg31 (%mm2): undefined
+	MMX reg32 (%mm3): undefined
+	MMX reg33 (%mm4): undefined
+	MMX reg34 (%mm5): undefined
+	MMX reg35 (%mm6): undefined
+	MMX reg36 (%mm7): undefined
+	FPU-control reg37 (%fctrl): undefined
+	FPU-control reg38 (%fstat): undefined
+	FPU-control reg39 (%mxcsr): undefined
+	segment reg40 (%es): same_value
+	segment reg41 (%cs): same_value
+	segment reg42 (%ss): same_value
+	segment reg43 (%ds): same_value
+	segment reg44 (%fs): same_value
+	segment reg45 (%gs): same_value
+.debug_frame has 0x80489b8 => [0x80489b8, 0x80489b9):
+	return address in reg8
+	CFA location expression: bregx(4,4)
+	integer reg0 (%eax): undefined
+	integer reg1 (%ecx): undefined
+	integer reg2 (%edx): undefined
+	integer reg3 (%ebx): same_value
+	integer reg4 (%esp): location expression: call_frame_cfa stack_value
+	integer reg5 (%ebp): same_value
+	integer reg6 (%esi): same_value
+	integer reg7 (%edi): same_value
+	integer reg8 (%eip): location expression: call_frame_cfa plus_uconst(-4)
+	integer reg9 (%eflags): undefined
+	integer reg10 (%trapno): undefined
+	x87 reg11 (%st0): undefined
+	x87 reg12 (%st1): undefined
+	x87 reg13 (%st2): undefined
+	x87 reg14 (%st3): undefined
+	x87 reg15 (%st4): undefined
+	x87 reg16 (%st5): undefined
+	x87 reg17 (%st6): undefined
+	x87 reg18 (%st7): undefined
+	SSE reg21 (%xmm0): undefined
+	SSE reg22 (%xmm1): undefined
+	SSE reg23 (%xmm2): undefined
+	SSE reg24 (%xmm3): undefined
+	SSE reg25 (%xmm4): undefined
+	SSE reg26 (%xmm5): undefined
+	SSE reg27 (%xmm6): undefined
+	SSE reg28 (%xmm7): undefined
+	MMX reg29 (%mm0): undefined
+	MMX reg30 (%mm1): undefined
+	MMX reg31 (%mm2): undefined
+	MMX reg32 (%mm3): undefined
+	MMX reg33 (%mm4): undefined
+	MMX reg34 (%mm5): undefined
+	MMX reg35 (%mm6): undefined
+	MMX reg36 (%mm7): undefined
+	FPU-control reg37 (%fctrl): undefined
+	FPU-control reg38 (%fstat): undefined
+	FPU-control reg39 (%mxcsr): undefined
+	segment reg40 (%es): same_value
+	segment reg41 (%cs): same_value
+	segment reg42 (%ss): same_value
+	segment reg43 (%ds): same_value
+	segment reg44 (%fs): same_value
+	segment reg45 (%gs): same_value
+EOF
+
+# EM_X86_64 (function foo 0x00000000000009d0)
+testfiles testfile12
+testrun_compare ${abs_builddir}/addrcfi -e testfile12 0x00000000000009d0 <<\EOF
+.eh_frame has 0x9d0 => [0x9d0, 0x9d1):
+	return address in reg16
+	CFA location expression: bregx(7,8)
+	integer reg0 (%rax): same_value
+	integer reg1 (%rdx): undefined
+	integer reg2 (%rcx): undefined
+	integer reg3 (%rbx): undefined
+	integer reg4 (%rsi): undefined
+	integer reg5 (%rdi): undefined
+	integer reg6 (%rbp): same_value
+	integer reg7 (%rsp): location expression: call_frame_cfa stack_value
+	integer reg8 (%r8): undefined
+	integer reg9 (%r9): undefined
+	integer reg10 (%r10): undefined
+	integer reg11 (%r11): undefined
+	integer reg12 (%r12): same_value
+	integer reg13 (%r13): same_value
+	integer reg14 (%r14): same_value
+	integer reg15 (%r15): same_value
+	integer reg16 (%rip): location expression: call_frame_cfa plus_uconst(-8)
+	SSE reg17 (%xmm0): undefined
+	SSE reg18 (%xmm1): undefined
+	SSE reg19 (%xmm2): undefined
+	SSE reg20 (%xmm3): undefined
+	SSE reg21 (%xmm4): undefined
+	SSE reg22 (%xmm5): undefined
+	SSE reg23 (%xmm6): undefined
+	SSE reg24 (%xmm7): undefined
+	SSE reg25 (%xmm8): undefined
+	SSE reg26 (%xmm9): undefined
+	SSE reg27 (%xmm10): undefined
+	SSE reg28 (%xmm11): undefined
+	SSE reg29 (%xmm12): undefined
+	SSE reg30 (%xmm13): undefined
+	SSE reg31 (%xmm14): undefined
+	SSE reg32 (%xmm15): undefined
+	x87 reg33 (%st0): undefined
+	x87 reg34 (%st1): undefined
+	x87 reg35 (%st2): undefined
+	x87 reg36 (%st3): undefined
+	x87 reg37 (%st4): undefined
+	x87 reg38 (%st5): undefined
+	x87 reg39 (%st6): undefined
+	x87 reg40 (%st7): undefined
+	MMX reg41 (%mm0): undefined
+	MMX reg42 (%mm1): undefined
+	MMX reg43 (%mm2): undefined
+	MMX reg44 (%mm3): undefined
+	MMX reg45 (%mm4): undefined
+	MMX reg46 (%mm5): undefined
+	MMX reg47 (%mm6): undefined
+	MMX reg48 (%mm7): undefined
+	integer reg49 (%rflags): undefined
+	segment reg50 (%es): undefined
+	segment reg51 (%cs): undefined
+	segment reg52 (%ss): undefined
+	segment reg53 (%ds): undefined
+	segment reg54 (%fs): undefined
+	segment reg55 (%gs): undefined
+	segment reg58 (%fs.base): undefined
+	segment reg59 (%gs.base): undefined
+	control reg62 (%tr): undefined
+	control reg63 (%ldtr): undefined
+	control reg64 (%mxcsr): undefined
+	control reg65 (%fcw): undefined
+	control reg66 (%fsw): undefined
+.debug_frame has 0x9d0 => [0x9d0, 0x9d1):
+	return address in reg16
+	CFA location expression: bregx(7,8)
+	integer reg0 (%rax): same_value
+	integer reg1 (%rdx): undefined
+	integer reg2 (%rcx): undefined
+	integer reg3 (%rbx): undefined
+	integer reg4 (%rsi): undefined
+	integer reg5 (%rdi): undefined
+	integer reg6 (%rbp): same_value
+	integer reg7 (%rsp): location expression: call_frame_cfa stack_value
+	integer reg8 (%r8): undefined
+	integer reg9 (%r9): undefined
+	integer reg10 (%r10): undefined
+	integer reg11 (%r11): undefined
+	integer reg12 (%r12): same_value
+	integer reg13 (%r13): same_value
+	integer reg14 (%r14): same_value
+	integer reg15 (%r15): same_value
+	integer reg16 (%rip): location expression: call_frame_cfa plus_uconst(-8)
+	SSE reg17 (%xmm0): undefined
+	SSE reg18 (%xmm1): undefined
+	SSE reg19 (%xmm2): undefined
+	SSE reg20 (%xmm3): undefined
+	SSE reg21 (%xmm4): undefined
+	SSE reg22 (%xmm5): undefined
+	SSE reg23 (%xmm6): undefined
+	SSE reg24 (%xmm7): undefined
+	SSE reg25 (%xmm8): undefined
+	SSE reg26 (%xmm9): undefined
+	SSE reg27 (%xmm10): undefined
+	SSE reg28 (%xmm11): undefined
+	SSE reg29 (%xmm12): undefined
+	SSE reg30 (%xmm13): undefined
+	SSE reg31 (%xmm14): undefined
+	SSE reg32 (%xmm15): undefined
+	x87 reg33 (%st0): undefined
+	x87 reg34 (%st1): undefined
+	x87 reg35 (%st2): undefined
+	x87 reg36 (%st3): undefined
+	x87 reg37 (%st4): undefined
+	x87 reg38 (%st5): undefined
+	x87 reg39 (%st6): undefined
+	x87 reg40 (%st7): undefined
+	MMX reg41 (%mm0): undefined
+	MMX reg42 (%mm1): undefined
+	MMX reg43 (%mm2): undefined
+	MMX reg44 (%mm3): undefined
+	MMX reg45 (%mm4): undefined
+	MMX reg46 (%mm5): undefined
+	MMX reg47 (%mm6): undefined
+	MMX reg48 (%mm7): undefined
+	integer reg49 (%rflags): undefined
+	segment reg50 (%es): undefined
+	segment reg51 (%cs): undefined
+	segment reg52 (%ss): undefined
+	segment reg53 (%ds): undefined
+	segment reg54 (%fs): undefined
+	segment reg55 (%gs): undefined
+	segment reg58 (%fs.base): undefined
+	segment reg59 (%gs.base): undefined
+	control reg62 (%tr): undefined
+	control reg63 (%ldtr): undefined
+	control reg64 (%mxcsr): undefined
+	control reg65 (%fcw): undefined
+	control reg66 (%fsw): undefined
+EOF
+
+# EM_PPC (function bar 0x100004c0)
+# Note. First only in .debug_frame, second only in .eh_frame.
+#
+# = bar.c =
+#
+# static int b1 = 1;
+# int b2 = 1;
+#
+# static int
+# foo (int a)
+# {
+#   return a + b2;
+# }
+#
+# int bar (int b)
+# {
+#   return b - foo (b - b1);
+# }
+#
+# = foo.c =
+#
+# extern int bar (int b);
+# extern int b2;
+#
+# int
+# main (int argc, char ** argv)
+# {
+#   return bar (argc + b2);
+# }
+#
+# gcc -g -O2 -m32 -c foo.c
+# gcc -g -O2 -m32 -c bar.c
+# gcc -g -O2 m32 -o testfileppc32 foo.o bar.o
+testfiles testfileppc32
+testrun_compare ${abs_builddir}/addrcfi -e testfileppc32 0x100004c0 <<\EOF
+dwarf_cfi_addrframe (.eh_frame): no matching address range
+.debug_frame has 0x100004c0 => [0x100004c0, 0x100004d0):
+	return address in reg65
+	CFA location expression: bregx(1)
+	integer reg0 (r0): undefined
+	integer reg1 (r1): location expression: call_frame_cfa stack_value
+	integer reg2 (r2): same_value
+	integer reg3 (r3): undefined
+	integer reg4 (r4): undefined
+	integer reg5 (r5): undefined
+	integer reg6 (r6): undefined
+	integer reg7 (r7): undefined
+	integer reg8 (r8): undefined
+	integer reg9 (r9): undefined
+	integer reg10 (r10): undefined
+	integer reg11 (r11): undefined
+	integer reg12 (r12): undefined
+	integer reg13 (r13): same_value
+	integer reg14 (r14): same_value
+	integer reg15 (r15): same_value
+	integer reg16 (r16): same_value
+	integer reg17 (r17): same_value
+	integer reg18 (r18): same_value
+	integer reg19 (r19): same_value
+	integer reg20 (r20): same_value
+	integer reg21 (r21): same_value
+	integer reg22 (r22): same_value
+	integer reg23 (r23): same_value
+	integer reg24 (r24): same_value
+	integer reg25 (r25): same_value
+	integer reg26 (r26): same_value
+	integer reg27 (r27): same_value
+	integer reg28 (r28): same_value
+	integer reg29 (r29): same_value
+	integer reg30 (r30): same_value
+	integer reg31 (r31): same_value
+	FPU reg32 (f0): undefined
+	FPU reg33 (f1): undefined
+	FPU reg34 (f2): undefined
+	FPU reg35 (f3): undefined
+	FPU reg36 (f4): undefined
+	FPU reg37 (f5): undefined
+	FPU reg38 (f6): undefined
+	FPU reg39 (f7): undefined
+	FPU reg40 (f8): undefined
+	FPU reg41 (f9): undefined
+	FPU reg42 (f10): undefined
+	FPU reg43 (f11): undefined
+	FPU reg44 (f12): undefined
+	FPU reg45 (f13): undefined
+	FPU reg46 (f14): undefined
+	FPU reg47 (f15): undefined
+	FPU reg48 (f16): undefined
+	FPU reg49 (f17): undefined
+	FPU reg50 (f18): undefined
+	FPU reg51 (f19): undefined
+	FPU reg52 (f20): undefined
+	FPU reg53 (f21): undefined
+	FPU reg54 (f22): undefined
+	FPU reg55 (f23): undefined
+	FPU reg56 (f24): undefined
+	FPU reg57 (f25): undefined
+	FPU reg58 (f26): undefined
+	FPU reg59 (f27): undefined
+	FPU reg60 (f28): undefined
+	FPU reg61 (f29): undefined
+	FPU reg62 (f30): undefined
+	FPU reg63 (f31): undefined
+	integer reg64 (cr): undefined
+	FPU reg65 (fpscr): same_value
+	integer reg66 (msr): undefined
+	vector reg67 (vscr): undefined
+	privileged reg70 (sr0): undefined
+	privileged reg71 (sr1): undefined
+	privileged reg72 (sr2): undefined
+	privileged reg73 (sr3): undefined
+	privileged reg74 (sr4): undefined
+	privileged reg75 (sr5): undefined
+	privileged reg76 (sr6): undefined
+	privileged reg77 (sr7): undefined
+	privileged reg78 (sr8): undefined
+	privileged reg79 (sr9): undefined
+	privileged reg80 (sr10): undefined
+	privileged reg81 (sr11): undefined
+	privileged reg82 (sr12): undefined
+	privileged reg83 (sr13): undefined
+	privileged reg84 (sr14): undefined
+	privileged reg85 (sr15): undefined
+	privileged reg100 (mq): undefined
+	privileged reg101 (xer): undefined
+	privileged reg102 (spr2): undefined
+	privileged reg103 (spr3): undefined
+	privileged reg104 (spr4): undefined
+	privileged reg105 (spr5): undefined
+	privileged reg106 (spr6): undefined
+	privileged reg107 (spr7): undefined
+	privileged reg108 (lr): undefined
+	privileged reg109 (ctr): undefined
+	privileged reg110 (spr10): undefined
+	privileged reg111 (spr11): undefined
+	privileged reg112 (spr12): undefined
+	privileged reg113 (spr13): undefined
+	privileged reg114 (tfhar): undefined
+	privileged reg115 (tfiar): undefined
+	privileged reg116 (texasr): undefined
+	privileged reg117 (spr17): undefined
+	privileged reg118 (dsisr): undefined
+	privileged reg119 (dar): undefined
+	privileged reg120 (spr20): undefined
+	privileged reg121 (spr21): undefined
+	privileged reg122 (dec): undefined
+	privileged reg123 (spr23): undefined
+	privileged reg124 (spr24): undefined
+	privileged reg125 (spr25): undefined
+	privileged reg126 (spr26): undefined
+	privileged reg127 (spr27): undefined
+	privileged reg128 (spr28): undefined
+	privileged reg129 (spr29): undefined
+	privileged reg130 (spr30): undefined
+	privileged reg131 (spr31): undefined
+	privileged reg132 (spr32): undefined
+	privileged reg133 (spr33): undefined
+	privileged reg134 (spr34): undefined
+	privileged reg135 (spr35): undefined
+	privileged reg136 (spr36): undefined
+	privileged reg137 (spr37): undefined
+	privileged reg138 (spr38): undefined
+	privileged reg139 (spr39): undefined
+	privileged reg140 (spr40): undefined
+	privileged reg141 (spr41): undefined
+	privileged reg142 (spr42): undefined
+	privileged reg143 (spr43): undefined
+	privileged reg144 (spr44): undefined
+	privileged reg145 (spr45): undefined
+	privileged reg146 (spr46): undefined
+	privileged reg147 (spr47): undefined
+	privileged reg148 (spr48): undefined
+	privileged reg149 (spr49): undefined
+	privileged reg150 (spr50): undefined
+	privileged reg151 (spr51): undefined
+	privileged reg152 (spr52): undefined
+	privileged reg153 (spr53): undefined
+	privileged reg154 (spr54): undefined
+	privileged reg155 (spr55): undefined
+	privileged reg156 (spr56): undefined
+	privileged reg157 (spr57): undefined
+	privileged reg158 (spr58): undefined
+	privileged reg159 (spr59): undefined
+	privileged reg160 (spr60): undefined
+	privileged reg161 (spr61): undefined
+	privileged reg162 (spr62): undefined
+	privileged reg163 (spr63): undefined
+	privileged reg164 (spr64): undefined
+	privileged reg165 (spr65): undefined
+	privileged reg166 (spr66): undefined
+	privileged reg167 (spr67): undefined
+	privileged reg168 (spr68): undefined
+	privileged reg169 (spr69): undefined
+	privileged reg170 (spr70): undefined
+	privileged reg171 (spr71): undefined
+	privileged reg172 (spr72): undefined
+	privileged reg173 (spr73): undefined
+	privileged reg174 (spr74): undefined
+	privileged reg175 (spr75): undefined
+	privileged reg176 (spr76): undefined
+	privileged reg177 (spr77): undefined
+	privileged reg178 (spr78): undefined
+	privileged reg179 (spr79): undefined
+	privileged reg180 (spr80): undefined
+	privileged reg181 (spr81): undefined
+	privileged reg182 (spr82): undefined
+	privileged reg183 (spr83): undefined
+	privileged reg184 (spr84): undefined
+	privileged reg185 (spr85): undefined
+	privileged reg186 (spr86): undefined
+	privileged reg187 (spr87): undefined
+	privileged reg188 (spr88): undefined
+	privileged reg189 (spr89): undefined
+	privileged reg190 (spr90): undefined
+	privileged reg191 (spr91): undefined
+	privileged reg192 (spr92): undefined
+	privileged reg193 (spr93): undefined
+	privileged reg194 (spr94): undefined
+	privileged reg195 (spr95): undefined
+	privileged reg196 (spr96): undefined
+	privileged reg197 (spr97): undefined
+	privileged reg198 (spr98): undefined
+	privileged reg199 (spr99): undefined
+	privileged reg200 (spr100): undefined
+	privileged reg201 (spr101): undefined
+	privileged reg202 (spr102): undefined
+	privileged reg203 (spr103): undefined
+	privileged reg204 (spr104): undefined
+	privileged reg205 (spr105): undefined
+	privileged reg206 (spr106): undefined
+	privileged reg207 (spr107): undefined
+	privileged reg208 (spr108): undefined
+	privileged reg209 (spr109): undefined
+	privileged reg210 (spr110): undefined
+	privileged reg211 (spr111): undefined
+	privileged reg212 (spr112): undefined
+	privileged reg213 (spr113): undefined
+	privileged reg214 (spr114): undefined
+	privileged reg215 (spr115): undefined
+	privileged reg216 (spr116): undefined
+	privileged reg217 (spr117): undefined
+	privileged reg218 (spr118): undefined
+	privileged reg219 (spr119): undefined
+	privileged reg220 (spr120): undefined
+	privileged reg221 (spr121): undefined
+	privileged reg222 (spr122): undefined
+	privileged reg223 (spr123): undefined
+	privileged reg224 (spr124): undefined
+	privileged reg225 (spr125): undefined
+	privileged reg226 (spr126): undefined
+	privileged reg227 (spr127): undefined
+	privileged reg228 (spr128): undefined
+	privileged reg229 (spr129): undefined
+	privileged reg230 (spr130): undefined
+	privileged reg231 (spr131): undefined
+	privileged reg232 (spr132): undefined
+	privileged reg233 (spr133): undefined
+	privileged reg234 (spr134): undefined
+	privileged reg235 (spr135): undefined
+	privileged reg236 (spr136): undefined
+	privileged reg237 (spr137): undefined
+	privileged reg238 (spr138): undefined
+	privileged reg239 (spr139): undefined
+	privileged reg240 (spr140): undefined
+	privileged reg241 (spr141): undefined
+	privileged reg242 (spr142): undefined
+	privileged reg243 (spr143): undefined
+	privileged reg244 (spr144): undefined
+	privileged reg245 (spr145): undefined
+	privileged reg246 (spr146): undefined
+	privileged reg247 (spr147): undefined
+	privileged reg248 (spr148): undefined
+	privileged reg249 (spr149): undefined
+	privileged reg250 (spr150): undefined
+	privileged reg251 (spr151): undefined
+	privileged reg252 (spr152): undefined
+	privileged reg253 (spr153): undefined
+	privileged reg254 (spr154): undefined
+	privileged reg255 (spr155): undefined
+	privileged reg256 (spr156): undefined
+	privileged reg257 (spr157): undefined
+	privileged reg258 (spr158): undefined
+	privileged reg259 (spr159): undefined
+	privileged reg260 (spr160): undefined
+	privileged reg261 (spr161): undefined
+	privileged reg262 (spr162): undefined
+	privileged reg263 (spr163): undefined
+	privileged reg264 (spr164): undefined
+	privileged reg265 (spr165): undefined
+	privileged reg266 (spr166): undefined
+	privileged reg267 (spr167): undefined
+	privileged reg268 (spr168): undefined
+	privileged reg269 (spr169): undefined
+	privileged reg270 (spr170): undefined
+	privileged reg271 (spr171): undefined
+	privileged reg272 (spr172): undefined
+	privileged reg273 (spr173): undefined
+	privileged reg274 (spr174): undefined
+	privileged reg275 (spr175): undefined
+	privileged reg276 (spr176): undefined
+	privileged reg277 (spr177): undefined
+	privileged reg278 (spr178): undefined
+	privileged reg279 (spr179): undefined
+	privileged reg280 (spr180): undefined
+	privileged reg281 (spr181): undefined
+	privileged reg282 (spr182): undefined
+	privileged reg283 (spr183): undefined
+	privileged reg284 (spr184): undefined
+	privileged reg285 (spr185): undefined
+	privileged reg286 (spr186): undefined
+	privileged reg287 (spr187): undefined
+	privileged reg288 (spr188): undefined
+	privileged reg289 (spr189): undefined
+	privileged reg290 (spr190): undefined
+	privileged reg291 (spr191): undefined
+	privileged reg292 (spr192): undefined
+	privileged reg293 (spr193): undefined
+	privileged reg294 (spr194): undefined
+	privileged reg295 (spr195): undefined
+	privileged reg296 (spr196): undefined
+	privileged reg297 (spr197): undefined
+	privileged reg298 (spr198): undefined
+	privileged reg299 (spr199): undefined
+	privileged reg300 (spr200): undefined
+	privileged reg301 (spr201): undefined
+	privileged reg302 (spr202): undefined
+	privileged reg303 (spr203): undefined
+	privileged reg304 (spr204): undefined
+	privileged reg305 (spr205): undefined
+	privileged reg306 (spr206): undefined
+	privileged reg307 (spr207): undefined
+	privileged reg308 (spr208): undefined
+	privileged reg309 (spr209): undefined
+	privileged reg310 (spr210): undefined
+	privileged reg311 (spr211): undefined
+	privileged reg312 (spr212): undefined
+	privileged reg313 (spr213): undefined
+	privileged reg314 (spr214): undefined
+	privileged reg315 (spr215): undefined
+	privileged reg316 (spr216): undefined
+	privileged reg317 (spr217): undefined
+	privileged reg318 (spr218): undefined
+	privileged reg319 (spr219): undefined
+	privileged reg320 (spr220): undefined
+	privileged reg321 (spr221): undefined
+	privileged reg322 (spr222): undefined
+	privileged reg323 (spr223): undefined
+	privileged reg324 (spr224): undefined
+	privileged reg325 (spr225): undefined
+	privileged reg326 (spr226): undefined
+	privileged reg327 (spr227): undefined
+	privileged reg328 (spr228): undefined
+	privileged reg329 (spr229): undefined
+	privileged reg330 (spr230): undefined
+	privileged reg331 (spr231): undefined
+	privileged reg332 (spr232): undefined
+	privileged reg333 (spr233): undefined
+	privileged reg334 (spr234): undefined
+	privileged reg335 (spr235): undefined
+	privileged reg336 (spr236): undefined
+	privileged reg337 (spr237): undefined
+	privileged reg338 (spr238): undefined
+	privileged reg339 (spr239): undefined
+	privileged reg340 (spr240): undefined
+	privileged reg341 (spr241): undefined
+	privileged reg342 (spr242): undefined
+	privileged reg343 (spr243): undefined
+	privileged reg344 (spr244): undefined
+	privileged reg345 (spr245): undefined
+	privileged reg346 (spr246): undefined
+	privileged reg347 (spr247): undefined
+	privileged reg348 (spr248): undefined
+	privileged reg349 (spr249): undefined
+	privileged reg350 (spr250): undefined
+	privileged reg351 (spr251): undefined
+	privileged reg352 (spr252): undefined
+	privileged reg353 (spr253): undefined
+	privileged reg354 (spr254): undefined
+	privileged reg355 (spr255): undefined
+	vector reg356 (vrsave): undefined
+	privileged reg357 (spr257): undefined
+	privileged reg358 (spr258): undefined
+	privileged reg359 (spr259): undefined
+	privileged reg360 (spr260): undefined
+	privileged reg361 (spr261): undefined
+	privileged reg362 (spr262): undefined
+	privileged reg363 (spr263): undefined
+	privileged reg364 (spr264): undefined
+	privileged reg365 (spr265): undefined
+	privileged reg366 (spr266): undefined
+	privileged reg367 (spr267): undefined
+	privileged reg368 (spr268): undefined
+	privileged reg369 (spr269): undefined
+	privileged reg370 (spr270): undefined
+	privileged reg371 (spr271): undefined
+	privileged reg372 (spr272): undefined
+	privileged reg373 (spr273): undefined
+	privileged reg374 (spr274): undefined
+	privileged reg375 (spr275): undefined
+	privileged reg376 (spr276): undefined
+	privileged reg377 (spr277): undefined
+	privileged reg378 (spr278): undefined
+	privileged reg379 (spr279): undefined
+	privileged reg380 (spr280): undefined
+	privileged reg381 (spr281): undefined
+	privileged reg382 (spr282): undefined
+	privileged reg383 (spr283): undefined
+	privileged reg384 (spr284): undefined
+	privileged reg385 (spr285): undefined
+	privileged reg386 (spr286): undefined
+	privileged reg387 (spr287): undefined
+	privileged reg388 (spr288): undefined
+	privileged reg389 (spr289): undefined
+	privileged reg390 (spr290): undefined
+	privileged reg391 (spr291): undefined
+	privileged reg392 (spr292): undefined
+	privileged reg393 (spr293): undefined
+	privileged reg394 (spr294): undefined
+	privileged reg395 (spr295): undefined
+	privileged reg396 (spr296): undefined
+	privileged reg397 (spr297): undefined
+	privileged reg398 (spr298): undefined
+	privileged reg399 (spr299): undefined
+	privileged reg400 (spr300): undefined
+	privileged reg401 (spr301): undefined
+	privileged reg402 (spr302): undefined
+	privileged reg403 (spr303): undefined
+	privileged reg404 (spr304): undefined
+	privileged reg405 (spr305): undefined
+	privileged reg406 (spr306): undefined
+	privileged reg407 (spr307): undefined
+	privileged reg408 (spr308): undefined
+	privileged reg409 (spr309): undefined
+	privileged reg410 (spr310): undefined
+	privileged reg411 (spr311): undefined
+	privileged reg412 (spr312): undefined
+	privileged reg413 (spr313): undefined
+	privileged reg414 (spr314): undefined
+	privileged reg415 (spr315): undefined
+	privileged reg416 (spr316): undefined
+	privileged reg417 (spr317): undefined
+	privileged reg418 (spr318): undefined
+	privileged reg419 (spr319): undefined
+	privileged reg420 (spr320): undefined
+	privileged reg421 (spr321): undefined
+	privileged reg422 (spr322): undefined
+	privileged reg423 (spr323): undefined
+	privileged reg424 (spr324): undefined
+	privileged reg425 (spr325): undefined
+	privileged reg426 (spr326): undefined
+	privileged reg427 (spr327): undefined
+	privileged reg428 (spr328): undefined
+	privileged reg429 (spr329): undefined
+	privileged reg430 (spr330): undefined
+	privileged reg431 (spr331): undefined
+	privileged reg432 (spr332): undefined
+	privileged reg433 (spr333): undefined
+	privileged reg434 (spr334): undefined
+	privileged reg435 (spr335): undefined
+	privileged reg436 (spr336): undefined
+	privileged reg437 (spr337): undefined
+	privileged reg438 (spr338): undefined
+	privileged reg439 (spr339): undefined
+	privileged reg440 (spr340): undefined
+	privileged reg441 (spr341): undefined
+	privileged reg442 (spr342): undefined
+	privileged reg443 (spr343): undefined
+	privileged reg444 (spr344): undefined
+	privileged reg445 (spr345): undefined
+	privileged reg446 (spr346): undefined
+	privileged reg447 (spr347): undefined
+	privileged reg448 (spr348): undefined
+	privileged reg449 (spr349): undefined
+	privileged reg450 (spr350): undefined
+	privileged reg451 (spr351): undefined
+	privileged reg452 (spr352): undefined
+	privileged reg453 (spr353): undefined
+	privileged reg454 (spr354): undefined
+	privileged reg455 (spr355): undefined
+	privileged reg456 (spr356): undefined
+	privileged reg457 (spr357): undefined
+	privileged reg458 (spr358): undefined
+	privileged reg459 (spr359): undefined
+	privileged reg460 (spr360): undefined
+	privileged reg461 (spr361): undefined
+	privileged reg462 (spr362): undefined
+	privileged reg463 (spr363): undefined
+	privileged reg464 (spr364): undefined
+	privileged reg465 (spr365): undefined
+	privileged reg466 (spr366): undefined
+	privileged reg467 (spr367): undefined
+	privileged reg468 (spr368): undefined
+	privileged reg469 (spr369): undefined
+	privileged reg470 (spr370): undefined
+	privileged reg471 (spr371): undefined
+	privileged reg472 (spr372): undefined
+	privileged reg473 (spr373): undefined
+	privileged reg474 (spr374): undefined
+	privileged reg475 (spr375): undefined
+	privileged reg476 (spr376): undefined
+	privileged reg477 (spr377): undefined
+	privileged reg478 (spr378): undefined
+	privileged reg479 (spr379): undefined
+	privileged reg480 (spr380): undefined
+	privileged reg481 (spr381): undefined
+	privileged reg482 (spr382): undefined
+	privileged reg483 (spr383): undefined
+	privileged reg484 (spr384): undefined
+	privileged reg485 (spr385): undefined
+	privileged reg486 (spr386): undefined
+	privileged reg487 (spr387): undefined
+	privileged reg488 (spr388): undefined
+	privileged reg489 (spr389): undefined
+	privileged reg490 (spr390): undefined
+	privileged reg491 (spr391): undefined
+	privileged reg492 (spr392): undefined
+	privileged reg493 (spr393): undefined
+	privileged reg494 (spr394): undefined
+	privileged reg495 (spr395): undefined
+	privileged reg496 (spr396): undefined
+	privileged reg497 (spr397): undefined
+	privileged reg498 (spr398): undefined
+	privileged reg499 (spr399): undefined
+	privileged reg500 (spr400): undefined
+	privileged reg501 (spr401): undefined
+	privileged reg502 (spr402): undefined
+	privileged reg503 (spr403): undefined
+	privileged reg504 (spr404): undefined
+	privileged reg505 (spr405): undefined
+	privileged reg506 (spr406): undefined
+	privileged reg507 (spr407): undefined
+	privileged reg508 (spr408): undefined
+	privileged reg509 (spr409): undefined
+	privileged reg510 (spr410): undefined
+	privileged reg511 (spr411): undefined
+	privileged reg512 (spr412): undefined
+	privileged reg513 (spr413): undefined
+	privileged reg514 (spr414): undefined
+	privileged reg515 (spr415): undefined
+	privileged reg516 (spr416): undefined
+	privileged reg517 (spr417): undefined
+	privileged reg518 (spr418): undefined
+	privileged reg519 (spr419): undefined
+	privileged reg520 (spr420): undefined
+	privileged reg521 (spr421): undefined
+	privileged reg522 (spr422): undefined
+	privileged reg523 (spr423): undefined
+	privileged reg524 (spr424): undefined
+	privileged reg525 (spr425): undefined
+	privileged reg526 (spr426): undefined
+	privileged reg527 (spr427): undefined
+	privileged reg528 (spr428): undefined
+	privileged reg529 (spr429): undefined
+	privileged reg530 (spr430): undefined
+	privileged reg531 (spr431): undefined
+	privileged reg532 (spr432): undefined
+	privileged reg533 (spr433): undefined
+	privileged reg534 (spr434): undefined
+	privileged reg535 (spr435): undefined
+	privileged reg536 (spr436): undefined
+	privileged reg537 (spr437): undefined
+	privileged reg538 (spr438): undefined
+	privileged reg539 (spr439): undefined
+	privileged reg540 (spr440): undefined
+	privileged reg541 (spr441): undefined
+	privileged reg542 (spr442): undefined
+	privileged reg543 (spr443): undefined
+	privileged reg544 (spr444): undefined
+	privileged reg545 (spr445): undefined
+	privileged reg546 (spr446): undefined
+	privileged reg547 (spr447): undefined
+	privileged reg548 (spr448): undefined
+	privileged reg549 (spr449): undefined
+	privileged reg550 (spr450): undefined
+	privileged reg551 (spr451): undefined
+	privileged reg552 (spr452): undefined
+	privileged reg553 (spr453): undefined
+	privileged reg554 (spr454): undefined
+	privileged reg555 (spr455): undefined
+	privileged reg556 (spr456): undefined
+	privileged reg557 (spr457): undefined
+	privileged reg558 (spr458): undefined
+	privileged reg559 (spr459): undefined
+	privileged reg560 (spr460): undefined
+	privileged reg561 (spr461): undefined
+	privileged reg562 (spr462): undefined
+	privileged reg563 (spr463): undefined
+	privileged reg564 (spr464): undefined
+	privileged reg565 (spr465): undefined
+	privileged reg566 (spr466): undefined
+	privileged reg567 (spr467): undefined
+	privileged reg568 (spr468): undefined
+	privileged reg569 (spr469): undefined
+	privileged reg570 (spr470): undefined
+	privileged reg571 (spr471): undefined
+	privileged reg572 (spr472): undefined
+	privileged reg573 (spr473): undefined
+	privileged reg574 (spr474): undefined
+	privileged reg575 (spr475): undefined
+	privileged reg576 (spr476): undefined
+	privileged reg577 (spr477): undefined
+	privileged reg578 (spr478): undefined
+	privileged reg579 (spr479): undefined
+	privileged reg580 (spr480): undefined
+	privileged reg581 (spr481): undefined
+	privileged reg582 (spr482): undefined
+	privileged reg583 (spr483): undefined
+	privileged reg584 (spr484): undefined
+	privileged reg585 (spr485): undefined
+	privileged reg586 (spr486): undefined
+	privileged reg587 (spr487): undefined
+	privileged reg588 (spr488): undefined
+	privileged reg589 (spr489): undefined
+	privileged reg590 (spr490): undefined
+	privileged reg591 (spr491): undefined
+	privileged reg592 (spr492): undefined
+	privileged reg593 (spr493): undefined
+	privileged reg594 (spr494): undefined
+	privileged reg595 (spr495): undefined
+	privileged reg596 (spr496): undefined
+	privileged reg597 (spr497): undefined
+	privileged reg598 (spr498): undefined
+	privileged reg599 (spr499): undefined
+	privileged reg600 (spr500): undefined
+	privileged reg601 (spr501): undefined
+	privileged reg602 (spr502): undefined
+	privileged reg603 (spr503): undefined
+	privileged reg604 (spr504): undefined
+	privileged reg605 (spr505): undefined
+	privileged reg606 (spr506): undefined
+	privileged reg607 (spr507): undefined
+	privileged reg608 (spr508): undefined
+	privileged reg609 (spr509): undefined
+	privileged reg610 (spr510): undefined
+	privileged reg611 (spr511): undefined
+	vector reg612 (spefscr): undefined
+	privileged reg613 (spr513): undefined
+	privileged reg614 (spr514): undefined
+	privileged reg615 (spr515): undefined
+	privileged reg616 (spr516): undefined
+	privileged reg617 (spr517): undefined
+	privileged reg618 (spr518): undefined
+	privileged reg619 (spr519): undefined
+	privileged reg620 (spr520): undefined
+	privileged reg621 (spr521): undefined
+	privileged reg622 (spr522): undefined
+	privileged reg623 (spr523): undefined
+	privileged reg624 (spr524): undefined
+	privileged reg625 (spr525): undefined
+	privileged reg626 (spr526): undefined
+	privileged reg627 (spr527): undefined
+	privileged reg628 (spr528): undefined
+	privileged reg629 (spr529): undefined
+	privileged reg630 (spr530): undefined
+	privileged reg631 (spr531): undefined
+	privileged reg632 (spr532): undefined
+	privileged reg633 (spr533): undefined
+	privileged reg634 (spr534): undefined
+	privileged reg635 (spr535): undefined
+	privileged reg636 (spr536): undefined
+	privileged reg637 (spr537): undefined
+	privileged reg638 (spr538): undefined
+	privileged reg639 (spr539): undefined
+	privileged reg640 (spr540): undefined
+	privileged reg641 (spr541): undefined
+	privileged reg642 (spr542): undefined
+	privileged reg643 (spr543): undefined
+	privileged reg644 (spr544): undefined
+	privileged reg645 (spr545): undefined
+	privileged reg646 (spr546): undefined
+	privileged reg647 (spr547): undefined
+	privileged reg648 (spr548): undefined
+	privileged reg649 (spr549): undefined
+	privileged reg650 (spr550): undefined
+	privileged reg651 (spr551): undefined
+	privileged reg652 (spr552): undefined
+	privileged reg653 (spr553): undefined
+	privileged reg654 (spr554): undefined
+	privileged reg655 (spr555): undefined
+	privileged reg656 (spr556): undefined
+	privileged reg657 (spr557): undefined
+	privileged reg658 (spr558): undefined
+	privileged reg659 (spr559): undefined
+	privileged reg660 (spr560): undefined
+	privileged reg661 (spr561): undefined
+	privileged reg662 (spr562): undefined
+	privileged reg663 (spr563): undefined
+	privileged reg664 (spr564): undefined
+	privileged reg665 (spr565): undefined
+	privileged reg666 (spr566): undefined
+	privileged reg667 (spr567): undefined
+	privileged reg668 (spr568): undefined
+	privileged reg669 (spr569): undefined
+	privileged reg670 (spr570): undefined
+	privileged reg671 (spr571): undefined
+	privileged reg672 (spr572): undefined
+	privileged reg673 (spr573): undefined
+	privileged reg674 (spr574): undefined
+	privileged reg675 (spr575): undefined
+	privileged reg676 (spr576): undefined
+	privileged reg677 (spr577): undefined
+	privileged reg678 (spr578): undefined
+	privileged reg679 (spr579): undefined
+	privileged reg680 (spr580): undefined
+	privileged reg681 (spr581): undefined
+	privileged reg682 (spr582): undefined
+	privileged reg683 (spr583): undefined
+	privileged reg684 (spr584): undefined
+	privileged reg685 (spr585): undefined
+	privileged reg686 (spr586): undefined
+	privileged reg687 (spr587): undefined
+	privileged reg688 (spr588): undefined
+	privileged reg689 (spr589): undefined
+	privileged reg690 (spr590): undefined
+	privileged reg691 (spr591): undefined
+	privileged reg692 (spr592): undefined
+	privileged reg693 (spr593): undefined
+	privileged reg694 (spr594): undefined
+	privileged reg695 (spr595): undefined
+	privileged reg696 (spr596): undefined
+	privileged reg697 (spr597): undefined
+	privileged reg698 (spr598): undefined
+	privileged reg699 (spr599): undefined
+	privileged reg700 (spr600): undefined
+	privileged reg701 (spr601): undefined
+	privileged reg702 (spr602): undefined
+	privileged reg703 (spr603): undefined
+	privileged reg704 (spr604): undefined
+	privileged reg705 (spr605): undefined
+	privileged reg706 (spr606): undefined
+	privileged reg707 (spr607): undefined
+	privileged reg708 (spr608): undefined
+	privileged reg709 (spr609): undefined
+	privileged reg710 (spr610): undefined
+	privileged reg711 (spr611): undefined
+	privileged reg712 (spr612): undefined
+	privileged reg713 (spr613): undefined
+	privileged reg714 (spr614): undefined
+	privileged reg715 (spr615): undefined
+	privileged reg716 (spr616): undefined
+	privileged reg717 (spr617): undefined
+	privileged reg718 (spr618): undefined
+	privileged reg719 (spr619): undefined
+	privileged reg720 (spr620): undefined
+	privileged reg721 (spr621): undefined
+	privileged reg722 (spr622): undefined
+	privileged reg723 (spr623): undefined
+	privileged reg724 (spr624): undefined
+	privileged reg725 (spr625): undefined
+	privileged reg726 (spr626): undefined
+	privileged reg727 (spr627): undefined
+	privileged reg728 (spr628): undefined
+	privileged reg729 (spr629): undefined
+	privileged reg730 (spr630): undefined
+	privileged reg731 (spr631): undefined
+	privileged reg732 (spr632): undefined
+	privileged reg733 (spr633): undefined
+	privileged reg734 (spr634): undefined
+	privileged reg735 (spr635): undefined
+	privileged reg736 (spr636): undefined
+	privileged reg737 (spr637): undefined
+	privileged reg738 (spr638): undefined
+	privileged reg739 (spr639): undefined
+	privileged reg740 (spr640): undefined
+	privileged reg741 (spr641): undefined
+	privileged reg742 (spr642): undefined
+	privileged reg743 (spr643): undefined
+	privileged reg744 (spr644): undefined
+	privileged reg745 (spr645): undefined
+	privileged reg746 (spr646): undefined
+	privileged reg747 (spr647): undefined
+	privileged reg748 (spr648): undefined
+	privileged reg749 (spr649): undefined
+	privileged reg750 (spr650): undefined
+	privileged reg751 (spr651): undefined
+	privileged reg752 (spr652): undefined
+	privileged reg753 (spr653): undefined
+	privileged reg754 (spr654): undefined
+	privileged reg755 (spr655): undefined
+	privileged reg756 (spr656): undefined
+	privileged reg757 (spr657): undefined
+	privileged reg758 (spr658): undefined
+	privileged reg759 (spr659): undefined
+	privileged reg760 (spr660): undefined
+	privileged reg761 (spr661): undefined
+	privileged reg762 (spr662): undefined
+	privileged reg763 (spr663): undefined
+	privileged reg764 (spr664): undefined
+	privileged reg765 (spr665): undefined
+	privileged reg766 (spr666): undefined
+	privileged reg767 (spr667): undefined
+	privileged reg768 (spr668): undefined
+	privileged reg769 (spr669): undefined
+	privileged reg770 (spr670): undefined
+	privileged reg771 (spr671): undefined
+	privileged reg772 (spr672): undefined
+	privileged reg773 (spr673): undefined
+	privileged reg774 (spr674): undefined
+	privileged reg775 (spr675): undefined
+	privileged reg776 (spr676): undefined
+	privileged reg777 (spr677): undefined
+	privileged reg778 (spr678): undefined
+	privileged reg779 (spr679): undefined
+	privileged reg780 (spr680): undefined
+	privileged reg781 (spr681): undefined
+	privileged reg782 (spr682): undefined
+	privileged reg783 (spr683): undefined
+	privileged reg784 (spr684): undefined
+	privileged reg785 (spr685): undefined
+	privileged reg786 (spr686): undefined
+	privileged reg787 (spr687): undefined
+	privileged reg788 (spr688): undefined
+	privileged reg789 (spr689): undefined
+	privileged reg790 (spr690): undefined
+	privileged reg791 (spr691): undefined
+	privileged reg792 (spr692): undefined
+	privileged reg793 (spr693): undefined
+	privileged reg794 (spr694): undefined
+	privileged reg795 (spr695): undefined
+	privileged reg796 (spr696): undefined
+	privileged reg797 (spr697): undefined
+	privileged reg798 (spr698): undefined
+	privileged reg799 (spr699): undefined
+	privileged reg800 (spr700): undefined
+	privileged reg801 (spr701): undefined
+	privileged reg802 (spr702): undefined
+	privileged reg803 (spr703): undefined
+	privileged reg804 (spr704): undefined
+	privileged reg805 (spr705): undefined
+	privileged reg806 (spr706): undefined
+	privileged reg807 (spr707): undefined
+	privileged reg808 (spr708): undefined
+	privileged reg809 (spr709): undefined
+	privileged reg810 (spr710): undefined
+	privileged reg811 (spr711): undefined
+	privileged reg812 (spr712): undefined
+	privileged reg813 (spr713): undefined
+	privileged reg814 (spr714): undefined
+	privileged reg815 (spr715): undefined
+	privileged reg816 (spr716): undefined
+	privileged reg817 (spr717): undefined
+	privileged reg818 (spr718): undefined
+	privileged reg819 (spr719): undefined
+	privileged reg820 (spr720): undefined
+	privileged reg821 (spr721): undefined
+	privileged reg822 (spr722): undefined
+	privileged reg823 (spr723): undefined
+	privileged reg824 (spr724): undefined
+	privileged reg825 (spr725): undefined
+	privileged reg826 (spr726): undefined
+	privileged reg827 (spr727): undefined
+	privileged reg828 (spr728): undefined
+	privileged reg829 (spr729): undefined
+	privileged reg830 (spr730): undefined
+	privileged reg831 (spr731): undefined
+	privileged reg832 (spr732): undefined
+	privileged reg833 (spr733): undefined
+	privileged reg834 (spr734): undefined
+	privileged reg835 (spr735): undefined
+	privileged reg836 (spr736): undefined
+	privileged reg837 (spr737): undefined
+	privileged reg838 (spr738): undefined
+	privileged reg839 (spr739): undefined
+	privileged reg840 (spr740): undefined
+	privileged reg841 (spr741): undefined
+	privileged reg842 (spr742): undefined
+	privileged reg843 (spr743): undefined
+	privileged reg844 (spr744): undefined
+	privileged reg845 (spr745): undefined
+	privileged reg846 (spr746): undefined
+	privileged reg847 (spr747): undefined
+	privileged reg848 (spr748): undefined
+	privileged reg849 (spr749): undefined
+	privileged reg850 (spr750): undefined
+	privileged reg851 (spr751): undefined
+	privileged reg852 (spr752): undefined
+	privileged reg853 (spr753): undefined
+	privileged reg854 (spr754): undefined
+	privileged reg855 (spr755): undefined
+	privileged reg856 (spr756): undefined
+	privileged reg857 (spr757): undefined
+	privileged reg858 (spr758): undefined
+	privileged reg859 (spr759): undefined
+	privileged reg860 (spr760): undefined
+	privileged reg861 (spr761): undefined
+	privileged reg862 (spr762): undefined
+	privileged reg863 (spr763): undefined
+	privileged reg864 (spr764): undefined
+	privileged reg865 (spr765): undefined
+	privileged reg866 (spr766): undefined
+	privileged reg867 (spr767): undefined
+	privileged reg868 (spr768): undefined
+	privileged reg869 (spr769): undefined
+	privileged reg870 (spr770): undefined
+	privileged reg871 (spr771): undefined
+	privileged reg872 (spr772): undefined
+	privileged reg873 (spr773): undefined
+	privileged reg874 (spr774): undefined
+	privileged reg875 (spr775): undefined
+	privileged reg876 (spr776): undefined
+	privileged reg877 (spr777): undefined
+	privileged reg878 (spr778): undefined
+	privileged reg879 (spr779): undefined
+	privileged reg880 (spr780): undefined
+	privileged reg881 (spr781): undefined
+	privileged reg882 (spr782): undefined
+	privileged reg883 (spr783): undefined
+	privileged reg884 (spr784): undefined
+	privileged reg885 (spr785): undefined
+	privileged reg886 (spr786): undefined
+	privileged reg887 (spr787): undefined
+	privileged reg888 (spr788): undefined
+	privileged reg889 (spr789): undefined
+	privileged reg890 (spr790): undefined
+	privileged reg891 (spr791): undefined
+	privileged reg892 (spr792): undefined
+	privileged reg893 (spr793): undefined
+	privileged reg894 (spr794): undefined
+	privileged reg895 (spr795): undefined
+	privileged reg896 (spr796): undefined
+	privileged reg897 (spr797): undefined
+	privileged reg898 (spr798): undefined
+	privileged reg899 (spr799): undefined
+	privileged reg900 (spr800): undefined
+	privileged reg901 (spr801): undefined
+	privileged reg902 (spr802): undefined
+	privileged reg903 (spr803): undefined
+	privileged reg904 (spr804): undefined
+	privileged reg905 (spr805): undefined
+	privileged reg906 (spr806): undefined
+	privileged reg907 (spr807): undefined
+	privileged reg908 (spr808): undefined
+	privileged reg909 (spr809): undefined
+	privileged reg910 (spr810): undefined
+	privileged reg911 (spr811): undefined
+	privileged reg912 (spr812): undefined
+	privileged reg913 (spr813): undefined
+	privileged reg914 (spr814): undefined
+	privileged reg915 (spr815): undefined
+	privileged reg916 (spr816): undefined
+	privileged reg917 (spr817): undefined
+	privileged reg918 (spr818): undefined
+	privileged reg919 (spr819): undefined
+	privileged reg920 (spr820): undefined
+	privileged reg921 (spr821): undefined
+	privileged reg922 (spr822): undefined
+	privileged reg923 (spr823): undefined
+	privileged reg924 (spr824): undefined
+	privileged reg925 (spr825): undefined
+	privileged reg926 (spr826): undefined
+	privileged reg927 (spr827): undefined
+	privileged reg928 (spr828): undefined
+	privileged reg929 (spr829): undefined
+	privileged reg930 (spr830): undefined
+	privileged reg931 (spr831): undefined
+	privileged reg932 (spr832): undefined
+	privileged reg933 (spr833): undefined
+	privileged reg934 (spr834): undefined
+	privileged reg935 (spr835): undefined
+	privileged reg936 (spr836): undefined
+	privileged reg937 (spr837): undefined
+	privileged reg938 (spr838): undefined
+	privileged reg939 (spr839): undefined
+	privileged reg940 (spr840): undefined
+	privileged reg941 (spr841): undefined
+	privileged reg942 (spr842): undefined
+	privileged reg943 (spr843): undefined
+	privileged reg944 (spr844): undefined
+	privileged reg945 (spr845): undefined
+	privileged reg946 (spr846): undefined
+	privileged reg947 (spr847): undefined
+	privileged reg948 (spr848): undefined
+	privileged reg949 (spr849): undefined
+	privileged reg950 (spr850): undefined
+	privileged reg951 (spr851): undefined
+	privileged reg952 (spr852): undefined
+	privileged reg953 (spr853): undefined
+	privileged reg954 (spr854): undefined
+	privileged reg955 (spr855): undefined
+	privileged reg956 (spr856): undefined
+	privileged reg957 (spr857): undefined
+	privileged reg958 (spr858): undefined
+	privileged reg959 (spr859): undefined
+	privileged reg960 (spr860): undefined
+	privileged reg961 (spr861): undefined
+	privileged reg962 (spr862): undefined
+	privileged reg963 (spr863): undefined
+	privileged reg964 (spr864): undefined
+	privileged reg965 (spr865): undefined
+	privileged reg966 (spr866): undefined
+	privileged reg967 (spr867): undefined
+	privileged reg968 (spr868): undefined
+	privileged reg969 (spr869): undefined
+	privileged reg970 (spr870): undefined
+	privileged reg971 (spr871): undefined
+	privileged reg972 (spr872): undefined
+	privileged reg973 (spr873): undefined
+	privileged reg974 (spr874): undefined
+	privileged reg975 (spr875): undefined
+	privileged reg976 (spr876): undefined
+	privileged reg977 (spr877): undefined
+	privileged reg978 (spr878): undefined
+	privileged reg979 (spr879): undefined
+	privileged reg980 (spr880): undefined
+	privileged reg981 (spr881): undefined
+	privileged reg982 (spr882): undefined
+	privileged reg983 (spr883): undefined
+	privileged reg984 (spr884): undefined
+	privileged reg985 (spr885): undefined
+	privileged reg986 (spr886): undefined
+	privileged reg987 (spr887): undefined
+	privileged reg988 (spr888): undefined
+	privileged reg989 (spr889): undefined
+	privileged reg990 (spr890): undefined
+	privileged reg991 (spr891): undefined
+	privileged reg992 (spr892): undefined
+	privileged reg993 (spr893): undefined
+	privileged reg994 (spr894): undefined
+	privileged reg995 (spr895): undefined
+	privileged reg996 (spr896): undefined
+	privileged reg997 (spr897): undefined
+	privileged reg998 (spr898): undefined
+	privileged reg999 (spr899): undefined
+	vector reg1124 (vr0): undefined
+	vector reg1125 (vr1): undefined
+	vector reg1126 (vr2): undefined
+	vector reg1127 (vr3): undefined
+	vector reg1128 (vr4): undefined
+	vector reg1129 (vr5): undefined
+	vector reg1130 (vr6): undefined
+	vector reg1131 (vr7): undefined
+	vector reg1132 (vr8): undefined
+	vector reg1133 (vr9): undefined
+	vector reg1134 (vr10): undefined
+	vector reg1135 (vr11): undefined
+	vector reg1136 (vr12): undefined
+	vector reg1137 (vr13): undefined
+	vector reg1138 (vr14): undefined
+	vector reg1139 (vr15): undefined
+	vector reg1140 (vr16): undefined
+	vector reg1141 (vr17): undefined
+	vector reg1142 (vr18): undefined
+	vector reg1143 (vr19): undefined
+	vector reg1144 (vr20): undefined
+	vector reg1145 (vr21): undefined
+	vector reg1146 (vr22): undefined
+	vector reg1147 (vr23): undefined
+	vector reg1148 (vr24): undefined
+	vector reg1149 (vr25): undefined
+	vector reg1150 (vr26): undefined
+	vector reg1151 (vr27): undefined
+	vector reg1152 (vr28): undefined
+	vector reg1153 (vr29): undefined
+	vector reg1154 (vr30): undefined
+	vector reg1155 (vr31): undefined
+EOF
+
+testrun_compare ${abs_builddir}/addrcfi -e testfileppc32 0x100004d2 <<\EOF
+.eh_frame has 0x100004d2 => [0x100004d0, 0x100004d4):
+	return address in reg65
+	CFA location expression: bregx(1)
+	integer reg0 (r0): undefined
+	integer reg1 (r1): location expression: call_frame_cfa stack_value
+	integer reg2 (r2): same_value
+	integer reg3 (r3): undefined
+	integer reg4 (r4): undefined
+	integer reg5 (r5): undefined
+	integer reg6 (r6): undefined
+	integer reg7 (r7): undefined
+	integer reg8 (r8): undefined
+	integer reg9 (r9): undefined
+	integer reg10 (r10): undefined
+	integer reg11 (r11): undefined
+	integer reg12 (r12): undefined
+	integer reg13 (r13): same_value
+	integer reg14 (r14): same_value
+	integer reg15 (r15): same_value
+	integer reg16 (r16): same_value
+	integer reg17 (r17): same_value
+	integer reg18 (r18): same_value
+	integer reg19 (r19): same_value
+	integer reg20 (r20): same_value
+	integer reg21 (r21): same_value
+	integer reg22 (r22): same_value
+	integer reg23 (r23): same_value
+	integer reg24 (r24): same_value
+	integer reg25 (r25): same_value
+	integer reg26 (r26): same_value
+	integer reg27 (r27): same_value
+	integer reg28 (r28): same_value
+	integer reg29 (r29): same_value
+	integer reg30 (r30): same_value
+	integer reg31 (r31): same_value
+	FPU reg32 (f0): undefined
+	FPU reg33 (f1): undefined
+	FPU reg34 (f2): undefined
+	FPU reg35 (f3): undefined
+	FPU reg36 (f4): undefined
+	FPU reg37 (f5): undefined
+	FPU reg38 (f6): undefined
+	FPU reg39 (f7): undefined
+	FPU reg40 (f8): undefined
+	FPU reg41 (f9): undefined
+	FPU reg42 (f10): undefined
+	FPU reg43 (f11): undefined
+	FPU reg44 (f12): undefined
+	FPU reg45 (f13): undefined
+	FPU reg46 (f14): undefined
+	FPU reg47 (f15): undefined
+	FPU reg48 (f16): undefined
+	FPU reg49 (f17): undefined
+	FPU reg50 (f18): undefined
+	FPU reg51 (f19): undefined
+	FPU reg52 (f20): undefined
+	FPU reg53 (f21): undefined
+	FPU reg54 (f22): undefined
+	FPU reg55 (f23): undefined
+	FPU reg56 (f24): undefined
+	FPU reg57 (f25): undefined
+	FPU reg58 (f26): undefined
+	FPU reg59 (f27): undefined
+	FPU reg60 (f28): undefined
+	FPU reg61 (f29): undefined
+	FPU reg62 (f30): undefined
+	FPU reg63 (f31): undefined
+	integer reg64 (cr): undefined
+	FPU reg65 (fpscr): same_value
+	integer reg66 (msr): undefined
+	vector reg67 (vscr): undefined
+	privileged reg70 (sr0): undefined
+	privileged reg71 (sr1): undefined
+	privileged reg72 (sr2): undefined
+	privileged reg73 (sr3): undefined
+	privileged reg74 (sr4): undefined
+	privileged reg75 (sr5): undefined
+	privileged reg76 (sr6): undefined
+	privileged reg77 (sr7): undefined
+	privileged reg78 (sr8): undefined
+	privileged reg79 (sr9): undefined
+	privileged reg80 (sr10): undefined
+	privileged reg81 (sr11): undefined
+	privileged reg82 (sr12): undefined
+	privileged reg83 (sr13): undefined
+	privileged reg84 (sr14): undefined
+	privileged reg85 (sr15): undefined
+	privileged reg100 (mq): undefined
+	privileged reg101 (xer): undefined
+	privileged reg102 (spr2): undefined
+	privileged reg103 (spr3): undefined
+	privileged reg104 (spr4): undefined
+	privileged reg105 (spr5): undefined
+	privileged reg106 (spr6): undefined
+	privileged reg107 (spr7): undefined
+	privileged reg108 (lr): undefined
+	privileged reg109 (ctr): undefined
+	privileged reg110 (spr10): undefined
+	privileged reg111 (spr11): undefined
+	privileged reg112 (spr12): undefined
+	privileged reg113 (spr13): undefined
+	privileged reg114 (tfhar): undefined
+	privileged reg115 (tfiar): undefined
+	privileged reg116 (texasr): undefined
+	privileged reg117 (spr17): undefined
+	privileged reg118 (dsisr): undefined
+	privileged reg119 (dar): undefined
+	privileged reg120 (spr20): undefined
+	privileged reg121 (spr21): undefined
+	privileged reg122 (dec): undefined
+	privileged reg123 (spr23): undefined
+	privileged reg124 (spr24): undefined
+	privileged reg125 (spr25): undefined
+	privileged reg126 (spr26): undefined
+	privileged reg127 (spr27): undefined
+	privileged reg128 (spr28): undefined
+	privileged reg129 (spr29): undefined
+	privileged reg130 (spr30): undefined
+	privileged reg131 (spr31): undefined
+	privileged reg132 (spr32): undefined
+	privileged reg133 (spr33): undefined
+	privileged reg134 (spr34): undefined
+	privileged reg135 (spr35): undefined
+	privileged reg136 (spr36): undefined
+	privileged reg137 (spr37): undefined
+	privileged reg138 (spr38): undefined
+	privileged reg139 (spr39): undefined
+	privileged reg140 (spr40): undefined
+	privileged reg141 (spr41): undefined
+	privileged reg142 (spr42): undefined
+	privileged reg143 (spr43): undefined
+	privileged reg144 (spr44): undefined
+	privileged reg145 (spr45): undefined
+	privileged reg146 (spr46): undefined
+	privileged reg147 (spr47): undefined
+	privileged reg148 (spr48): undefined
+	privileged reg149 (spr49): undefined
+	privileged reg150 (spr50): undefined
+	privileged reg151 (spr51): undefined
+	privileged reg152 (spr52): undefined
+	privileged reg153 (spr53): undefined
+	privileged reg154 (spr54): undefined
+	privileged reg155 (spr55): undefined
+	privileged reg156 (spr56): undefined
+	privileged reg157 (spr57): undefined
+	privileged reg158 (spr58): undefined
+	privileged reg159 (spr59): undefined
+	privileged reg160 (spr60): undefined
+	privileged reg161 (spr61): undefined
+	privileged reg162 (spr62): undefined
+	privileged reg163 (spr63): undefined
+	privileged reg164 (spr64): undefined
+	privileged reg165 (spr65): undefined
+	privileged reg166 (spr66): undefined
+	privileged reg167 (spr67): undefined
+	privileged reg168 (spr68): undefined
+	privileged reg169 (spr69): undefined
+	privileged reg170 (spr70): undefined
+	privileged reg171 (spr71): undefined
+	privileged reg172 (spr72): undefined
+	privileged reg173 (spr73): undefined
+	privileged reg174 (spr74): undefined
+	privileged reg175 (spr75): undefined
+	privileged reg176 (spr76): undefined
+	privileged reg177 (spr77): undefined
+	privileged reg178 (spr78): undefined
+	privileged reg179 (spr79): undefined
+	privileged reg180 (spr80): undefined
+	privileged reg181 (spr81): undefined
+	privileged reg182 (spr82): undefined
+	privileged reg183 (spr83): undefined
+	privileged reg184 (spr84): undefined
+	privileged reg185 (spr85): undefined
+	privileged reg186 (spr86): undefined
+	privileged reg187 (spr87): undefined
+	privileged reg188 (spr88): undefined
+	privileged reg189 (spr89): undefined
+	privileged reg190 (spr90): undefined
+	privileged reg191 (spr91): undefined
+	privileged reg192 (spr92): undefined
+	privileged reg193 (spr93): undefined
+	privileged reg194 (spr94): undefined
+	privileged reg195 (spr95): undefined
+	privileged reg196 (spr96): undefined
+	privileged reg197 (spr97): undefined
+	privileged reg198 (spr98): undefined
+	privileged reg199 (spr99): undefined
+	privileged reg200 (spr100): undefined
+	privileged reg201 (spr101): undefined
+	privileged reg202 (spr102): undefined
+	privileged reg203 (spr103): undefined
+	privileged reg204 (spr104): undefined
+	privileged reg205 (spr105): undefined
+	privileged reg206 (spr106): undefined
+	privileged reg207 (spr107): undefined
+	privileged reg208 (spr108): undefined
+	privileged reg209 (spr109): undefined
+	privileged reg210 (spr110): undefined
+	privileged reg211 (spr111): undefined
+	privileged reg212 (spr112): undefined
+	privileged reg213 (spr113): undefined
+	privileged reg214 (spr114): undefined
+	privileged reg215 (spr115): undefined
+	privileged reg216 (spr116): undefined
+	privileged reg217 (spr117): undefined
+	privileged reg218 (spr118): undefined
+	privileged reg219 (spr119): undefined
+	privileged reg220 (spr120): undefined
+	privileged reg221 (spr121): undefined
+	privileged reg222 (spr122): undefined
+	privileged reg223 (spr123): undefined
+	privileged reg224 (spr124): undefined
+	privileged reg225 (spr125): undefined
+	privileged reg226 (spr126): undefined
+	privileged reg227 (spr127): undefined
+	privileged reg228 (spr128): undefined
+	privileged reg229 (spr129): undefined
+	privileged reg230 (spr130): undefined
+	privileged reg231 (spr131): undefined
+	privileged reg232 (spr132): undefined
+	privileged reg233 (spr133): undefined
+	privileged reg234 (spr134): undefined
+	privileged reg235 (spr135): undefined
+	privileged reg236 (spr136): undefined
+	privileged reg237 (spr137): undefined
+	privileged reg238 (spr138): undefined
+	privileged reg239 (spr139): undefined
+	privileged reg240 (spr140): undefined
+	privileged reg241 (spr141): undefined
+	privileged reg242 (spr142): undefined
+	privileged reg243 (spr143): undefined
+	privileged reg244 (spr144): undefined
+	privileged reg245 (spr145): undefined
+	privileged reg246 (spr146): undefined
+	privileged reg247 (spr147): undefined
+	privileged reg248 (spr148): undefined
+	privileged reg249 (spr149): undefined
+	privileged reg250 (spr150): undefined
+	privileged reg251 (spr151): undefined
+	privileged reg252 (spr152): undefined
+	privileged reg253 (spr153): undefined
+	privileged reg254 (spr154): undefined
+	privileged reg255 (spr155): undefined
+	privileged reg256 (spr156): undefined
+	privileged reg257 (spr157): undefined
+	privileged reg258 (spr158): undefined
+	privileged reg259 (spr159): undefined
+	privileged reg260 (spr160): undefined
+	privileged reg261 (spr161): undefined
+	privileged reg262 (spr162): undefined
+	privileged reg263 (spr163): undefined
+	privileged reg264 (spr164): undefined
+	privileged reg265 (spr165): undefined
+	privileged reg266 (spr166): undefined
+	privileged reg267 (spr167): undefined
+	privileged reg268 (spr168): undefined
+	privileged reg269 (spr169): undefined
+	privileged reg270 (spr170): undefined
+	privileged reg271 (spr171): undefined
+	privileged reg272 (spr172): undefined
+	privileged reg273 (spr173): undefined
+	privileged reg274 (spr174): undefined
+	privileged reg275 (spr175): undefined
+	privileged reg276 (spr176): undefined
+	privileged reg277 (spr177): undefined
+	privileged reg278 (spr178): undefined
+	privileged reg279 (spr179): undefined
+	privileged reg280 (spr180): undefined
+	privileged reg281 (spr181): undefined
+	privileged reg282 (spr182): undefined
+	privileged reg283 (spr183): undefined
+	privileged reg284 (spr184): undefined
+	privileged reg285 (spr185): undefined
+	privileged reg286 (spr186): undefined
+	privileged reg287 (spr187): undefined
+	privileged reg288 (spr188): undefined
+	privileged reg289 (spr189): undefined
+	privileged reg290 (spr190): undefined
+	privileged reg291 (spr191): undefined
+	privileged reg292 (spr192): undefined
+	privileged reg293 (spr193): undefined
+	privileged reg294 (spr194): undefined
+	privileged reg295 (spr195): undefined
+	privileged reg296 (spr196): undefined
+	privileged reg297 (spr197): undefined
+	privileged reg298 (spr198): undefined
+	privileged reg299 (spr199): undefined
+	privileged reg300 (spr200): undefined
+	privileged reg301 (spr201): undefined
+	privileged reg302 (spr202): undefined
+	privileged reg303 (spr203): undefined
+	privileged reg304 (spr204): undefined
+	privileged reg305 (spr205): undefined
+	privileged reg306 (spr206): undefined
+	privileged reg307 (spr207): undefined
+	privileged reg308 (spr208): undefined
+	privileged reg309 (spr209): undefined
+	privileged reg310 (spr210): undefined
+	privileged reg311 (spr211): undefined
+	privileged reg312 (spr212): undefined
+	privileged reg313 (spr213): undefined
+	privileged reg314 (spr214): undefined
+	privileged reg315 (spr215): undefined
+	privileged reg316 (spr216): undefined
+	privileged reg317 (spr217): undefined
+	privileged reg318 (spr218): undefined
+	privileged reg319 (spr219): undefined
+	privileged reg320 (spr220): undefined
+	privileged reg321 (spr221): undefined
+	privileged reg322 (spr222): undefined
+	privileged reg323 (spr223): undefined
+	privileged reg324 (spr224): undefined
+	privileged reg325 (spr225): undefined
+	privileged reg326 (spr226): undefined
+	privileged reg327 (spr227): undefined
+	privileged reg328 (spr228): undefined
+	privileged reg329 (spr229): undefined
+	privileged reg330 (spr230): undefined
+	privileged reg331 (spr231): undefined
+	privileged reg332 (spr232): undefined
+	privileged reg333 (spr233): undefined
+	privileged reg334 (spr234): undefined
+	privileged reg335 (spr235): undefined
+	privileged reg336 (spr236): undefined
+	privileged reg337 (spr237): undefined
+	privileged reg338 (spr238): undefined
+	privileged reg339 (spr239): undefined
+	privileged reg340 (spr240): undefined
+	privileged reg341 (spr241): undefined
+	privileged reg342 (spr242): undefined
+	privileged reg343 (spr243): undefined
+	privileged reg344 (spr244): undefined
+	privileged reg345 (spr245): undefined
+	privileged reg346 (spr246): undefined
+	privileged reg347 (spr247): undefined
+	privileged reg348 (spr248): undefined
+	privileged reg349 (spr249): undefined
+	privileged reg350 (spr250): undefined
+	privileged reg351 (spr251): undefined
+	privileged reg352 (spr252): undefined
+	privileged reg353 (spr253): undefined
+	privileged reg354 (spr254): undefined
+	privileged reg355 (spr255): undefined
+	vector reg356 (vrsave): undefined
+	privileged reg357 (spr257): undefined
+	privileged reg358 (spr258): undefined
+	privileged reg359 (spr259): undefined
+	privileged reg360 (spr260): undefined
+	privileged reg361 (spr261): undefined
+	privileged reg362 (spr262): undefined
+	privileged reg363 (spr263): undefined
+	privileged reg364 (spr264): undefined
+	privileged reg365 (spr265): undefined
+	privileged reg366 (spr266): undefined
+	privileged reg367 (spr267): undefined
+	privileged reg368 (spr268): undefined
+	privileged reg369 (spr269): undefined
+	privileged reg370 (spr270): undefined
+	privileged reg371 (spr271): undefined
+	privileged reg372 (spr272): undefined
+	privileged reg373 (spr273): undefined
+	privileged reg374 (spr274): undefined
+	privileged reg375 (spr275): undefined
+	privileged reg376 (spr276): undefined
+	privileged reg377 (spr277): undefined
+	privileged reg378 (spr278): undefined
+	privileged reg379 (spr279): undefined
+	privileged reg380 (spr280): undefined
+	privileged reg381 (spr281): undefined
+	privileged reg382 (spr282): undefined
+	privileged reg383 (spr283): undefined
+	privileged reg384 (spr284): undefined
+	privileged reg385 (spr285): undefined
+	privileged reg386 (spr286): undefined
+	privileged reg387 (spr287): undefined
+	privileged reg388 (spr288): undefined
+	privileged reg389 (spr289): undefined
+	privileged reg390 (spr290): undefined
+	privileged reg391 (spr291): undefined
+	privileged reg392 (spr292): undefined
+	privileged reg393 (spr293): undefined
+	privileged reg394 (spr294): undefined
+	privileged reg395 (spr295): undefined
+	privileged reg396 (spr296): undefined
+	privileged reg397 (spr297): undefined
+	privileged reg398 (spr298): undefined
+	privileged reg399 (spr299): undefined
+	privileged reg400 (spr300): undefined
+	privileged reg401 (spr301): undefined
+	privileged reg402 (spr302): undefined
+	privileged reg403 (spr303): undefined
+	privileged reg404 (spr304): undefined
+	privileged reg405 (spr305): undefined
+	privileged reg406 (spr306): undefined
+	privileged reg407 (spr307): undefined
+	privileged reg408 (spr308): undefined
+	privileged reg409 (spr309): undefined
+	privileged reg410 (spr310): undefined
+	privileged reg411 (spr311): undefined
+	privileged reg412 (spr312): undefined
+	privileged reg413 (spr313): undefined
+	privileged reg414 (spr314): undefined
+	privileged reg415 (spr315): undefined
+	privileged reg416 (spr316): undefined
+	privileged reg417 (spr317): undefined
+	privileged reg418 (spr318): undefined
+	privileged reg419 (spr319): undefined
+	privileged reg420 (spr320): undefined
+	privileged reg421 (spr321): undefined
+	privileged reg422 (spr322): undefined
+	privileged reg423 (spr323): undefined
+	privileged reg424 (spr324): undefined
+	privileged reg425 (spr325): undefined
+	privileged reg426 (spr326): undefined
+	privileged reg427 (spr327): undefined
+	privileged reg428 (spr328): undefined
+	privileged reg429 (spr329): undefined
+	privileged reg430 (spr330): undefined
+	privileged reg431 (spr331): undefined
+	privileged reg432 (spr332): undefined
+	privileged reg433 (spr333): undefined
+	privileged reg434 (spr334): undefined
+	privileged reg435 (spr335): undefined
+	privileged reg436 (spr336): undefined
+	privileged reg437 (spr337): undefined
+	privileged reg438 (spr338): undefined
+	privileged reg439 (spr339): undefined
+	privileged reg440 (spr340): undefined
+	privileged reg441 (spr341): undefined
+	privileged reg442 (spr342): undefined
+	privileged reg443 (spr343): undefined
+	privileged reg444 (spr344): undefined
+	privileged reg445 (spr345): undefined
+	privileged reg446 (spr346): undefined
+	privileged reg447 (spr347): undefined
+	privileged reg448 (spr348): undefined
+	privileged reg449 (spr349): undefined
+	privileged reg450 (spr350): undefined
+	privileged reg451 (spr351): undefined
+	privileged reg452 (spr352): undefined
+	privileged reg453 (spr353): undefined
+	privileged reg454 (spr354): undefined
+	privileged reg455 (spr355): undefined
+	privileged reg456 (spr356): undefined
+	privileged reg457 (spr357): undefined
+	privileged reg458 (spr358): undefined
+	privileged reg459 (spr359): undefined
+	privileged reg460 (spr360): undefined
+	privileged reg461 (spr361): undefined
+	privileged reg462 (spr362): undefined
+	privileged reg463 (spr363): undefined
+	privileged reg464 (spr364): undefined
+	privileged reg465 (spr365): undefined
+	privileged reg466 (spr366): undefined
+	privileged reg467 (spr367): undefined
+	privileged reg468 (spr368): undefined
+	privileged reg469 (spr369): undefined
+	privileged reg470 (spr370): undefined
+	privileged reg471 (spr371): undefined
+	privileged reg472 (spr372): undefined
+	privileged reg473 (spr373): undefined
+	privileged reg474 (spr374): undefined
+	privileged reg475 (spr375): undefined
+	privileged reg476 (spr376): undefined
+	privileged reg477 (spr377): undefined
+	privileged reg478 (spr378): undefined
+	privileged reg479 (spr379): undefined
+	privileged reg480 (spr380): undefined
+	privileged reg481 (spr381): undefined
+	privileged reg482 (spr382): undefined
+	privileged reg483 (spr383): undefined
+	privileged reg484 (spr384): undefined
+	privileged reg485 (spr385): undefined
+	privileged reg486 (spr386): undefined
+	privileged reg487 (spr387): undefined
+	privileged reg488 (spr388): undefined
+	privileged reg489 (spr389): undefined
+	privileged reg490 (spr390): undefined
+	privileged reg491 (spr391): undefined
+	privileged reg492 (spr392): undefined
+	privileged reg493 (spr393): undefined
+	privileged reg494 (spr394): undefined
+	privileged reg495 (spr395): undefined
+	privileged reg496 (spr396): undefined
+	privileged reg497 (spr397): undefined
+	privileged reg498 (spr398): undefined
+	privileged reg499 (spr399): undefined
+	privileged reg500 (spr400): undefined
+	privileged reg501 (spr401): undefined
+	privileged reg502 (spr402): undefined
+	privileged reg503 (spr403): undefined
+	privileged reg504 (spr404): undefined
+	privileged reg505 (spr405): undefined
+	privileged reg506 (spr406): undefined
+	privileged reg507 (spr407): undefined
+	privileged reg508 (spr408): undefined
+	privileged reg509 (spr409): undefined
+	privileged reg510 (spr410): undefined
+	privileged reg511 (spr411): undefined
+	privileged reg512 (spr412): undefined
+	privileged reg513 (spr413): undefined
+	privileged reg514 (spr414): undefined
+	privileged reg515 (spr415): undefined
+	privileged reg516 (spr416): undefined
+	privileged reg517 (spr417): undefined
+	privileged reg518 (spr418): undefined
+	privileged reg519 (spr419): undefined
+	privileged reg520 (spr420): undefined
+	privileged reg521 (spr421): undefined
+	privileged reg522 (spr422): undefined
+	privileged reg523 (spr423): undefined
+	privileged reg524 (spr424): undefined
+	privileged reg525 (spr425): undefined
+	privileged reg526 (spr426): undefined
+	privileged reg527 (spr427): undefined
+	privileged reg528 (spr428): undefined
+	privileged reg529 (spr429): undefined
+	privileged reg530 (spr430): undefined
+	privileged reg531 (spr431): undefined
+	privileged reg532 (spr432): undefined
+	privileged reg533 (spr433): undefined
+	privileged reg534 (spr434): undefined
+	privileged reg535 (spr435): undefined
+	privileged reg536 (spr436): undefined
+	privileged reg537 (spr437): undefined
+	privileged reg538 (spr438): undefined
+	privileged reg539 (spr439): undefined
+	privileged reg540 (spr440): undefined
+	privileged reg541 (spr441): undefined
+	privileged reg542 (spr442): undefined
+	privileged reg543 (spr443): undefined
+	privileged reg544 (spr444): undefined
+	privileged reg545 (spr445): undefined
+	privileged reg546 (spr446): undefined
+	privileged reg547 (spr447): undefined
+	privileged reg548 (spr448): undefined
+	privileged reg549 (spr449): undefined
+	privileged reg550 (spr450): undefined
+	privileged reg551 (spr451): undefined
+	privileged reg552 (spr452): undefined
+	privileged reg553 (spr453): undefined
+	privileged reg554 (spr454): undefined
+	privileged reg555 (spr455): undefined
+	privileged reg556 (spr456): undefined
+	privileged reg557 (spr457): undefined
+	privileged reg558 (spr458): undefined
+	privileged reg559 (spr459): undefined
+	privileged reg560 (spr460): undefined
+	privileged reg561 (spr461): undefined
+	privileged reg562 (spr462): undefined
+	privileged reg563 (spr463): undefined
+	privileged reg564 (spr464): undefined
+	privileged reg565 (spr465): undefined
+	privileged reg566 (spr466): undefined
+	privileged reg567 (spr467): undefined
+	privileged reg568 (spr468): undefined
+	privileged reg569 (spr469): undefined
+	privileged reg570 (spr470): undefined
+	privileged reg571 (spr471): undefined
+	privileged reg572 (spr472): undefined
+	privileged reg573 (spr473): undefined
+	privileged reg574 (spr474): undefined
+	privileged reg575 (spr475): undefined
+	privileged reg576 (spr476): undefined
+	privileged reg577 (spr477): undefined
+	privileged reg578 (spr478): undefined
+	privileged reg579 (spr479): undefined
+	privileged reg580 (spr480): undefined
+	privileged reg581 (spr481): undefined
+	privileged reg582 (spr482): undefined
+	privileged reg583 (spr483): undefined
+	privileged reg584 (spr484): undefined
+	privileged reg585 (spr485): undefined
+	privileged reg586 (spr486): undefined
+	privileged reg587 (spr487): undefined
+	privileged reg588 (spr488): undefined
+	privileged reg589 (spr489): undefined
+	privileged reg590 (spr490): undefined
+	privileged reg591 (spr491): undefined
+	privileged reg592 (spr492): undefined
+	privileged reg593 (spr493): undefined
+	privileged reg594 (spr494): undefined
+	privileged reg595 (spr495): undefined
+	privileged reg596 (spr496): undefined
+	privileged reg597 (spr497): undefined
+	privileged reg598 (spr498): undefined
+	privileged reg599 (spr499): undefined
+	privileged reg600 (spr500): undefined
+	privileged reg601 (spr501): undefined
+	privileged reg602 (spr502): undefined
+	privileged reg603 (spr503): undefined
+	privileged reg604 (spr504): undefined
+	privileged reg605 (spr505): undefined
+	privileged reg606 (spr506): undefined
+	privileged reg607 (spr507): undefined
+	privileged reg608 (spr508): undefined
+	privileged reg609 (spr509): undefined
+	privileged reg610 (spr510): undefined
+	privileged reg611 (spr511): undefined
+	vector reg612 (spefscr): undefined
+	privileged reg613 (spr513): undefined
+	privileged reg614 (spr514): undefined
+	privileged reg615 (spr515): undefined
+	privileged reg616 (spr516): undefined
+	privileged reg617 (spr517): undefined
+	privileged reg618 (spr518): undefined
+	privileged reg619 (spr519): undefined
+	privileged reg620 (spr520): undefined
+	privileged reg621 (spr521): undefined
+	privileged reg622 (spr522): undefined
+	privileged reg623 (spr523): undefined
+	privileged reg624 (spr524): undefined
+	privileged reg625 (spr525): undefined
+	privileged reg626 (spr526): undefined
+	privileged reg627 (spr527): undefined
+	privileged reg628 (spr528): undefined
+	privileged reg629 (spr529): undefined
+	privileged reg630 (spr530): undefined
+	privileged reg631 (spr531): undefined
+	privileged reg632 (spr532): undefined
+	privileged reg633 (spr533): undefined
+	privileged reg634 (spr534): undefined
+	privileged reg635 (spr535): undefined
+	privileged reg636 (spr536): undefined
+	privileged reg637 (spr537): undefined
+	privileged reg638 (spr538): undefined
+	privileged reg639 (spr539): undefined
+	privileged reg640 (spr540): undefined
+	privileged reg641 (spr541): undefined
+	privileged reg642 (spr542): undefined
+	privileged reg643 (spr543): undefined
+	privileged reg644 (spr544): undefined
+	privileged reg645 (spr545): undefined
+	privileged reg646 (spr546): undefined
+	privileged reg647 (spr547): undefined
+	privileged reg648 (spr548): undefined
+	privileged reg649 (spr549): undefined
+	privileged reg650 (spr550): undefined
+	privileged reg651 (spr551): undefined
+	privileged reg652 (spr552): undefined
+	privileged reg653 (spr553): undefined
+	privileged reg654 (spr554): undefined
+	privileged reg655 (spr555): undefined
+	privileged reg656 (spr556): undefined
+	privileged reg657 (spr557): undefined
+	privileged reg658 (spr558): undefined
+	privileged reg659 (spr559): undefined
+	privileged reg660 (spr560): undefined
+	privileged reg661 (spr561): undefined
+	privileged reg662 (spr562): undefined
+	privileged reg663 (spr563): undefined
+	privileged reg664 (spr564): undefined
+	privileged reg665 (spr565): undefined
+	privileged reg666 (spr566): undefined
+	privileged reg667 (spr567): undefined
+	privileged reg668 (spr568): undefined
+	privileged reg669 (spr569): undefined
+	privileged reg670 (spr570): undefined
+	privileged reg671 (spr571): undefined
+	privileged reg672 (spr572): undefined
+	privileged reg673 (spr573): undefined
+	privileged reg674 (spr574): undefined
+	privileged reg675 (spr575): undefined
+	privileged reg676 (spr576): undefined
+	privileged reg677 (spr577): undefined
+	privileged reg678 (spr578): undefined
+	privileged reg679 (spr579): undefined
+	privileged reg680 (spr580): undefined
+	privileged reg681 (spr581): undefined
+	privileged reg682 (spr582): undefined
+	privileged reg683 (spr583): undefined
+	privileged reg684 (spr584): undefined
+	privileged reg685 (spr585): undefined
+	privileged reg686 (spr586): undefined
+	privileged reg687 (spr587): undefined
+	privileged reg688 (spr588): undefined
+	privileged reg689 (spr589): undefined
+	privileged reg690 (spr590): undefined
+	privileged reg691 (spr591): undefined
+	privileged reg692 (spr592): undefined
+	privileged reg693 (spr593): undefined
+	privileged reg694 (spr594): undefined
+	privileged reg695 (spr595): undefined
+	privileged reg696 (spr596): undefined
+	privileged reg697 (spr597): undefined
+	privileged reg698 (spr598): undefined
+	privileged reg699 (spr599): undefined
+	privileged reg700 (spr600): undefined
+	privileged reg701 (spr601): undefined
+	privileged reg702 (spr602): undefined
+	privileged reg703 (spr603): undefined
+	privileged reg704 (spr604): undefined
+	privileged reg705 (spr605): undefined
+	privileged reg706 (spr606): undefined
+	privileged reg707 (spr607): undefined
+	privileged reg708 (spr608): undefined
+	privileged reg709 (spr609): undefined
+	privileged reg710 (spr610): undefined
+	privileged reg711 (spr611): undefined
+	privileged reg712 (spr612): undefined
+	privileged reg713 (spr613): undefined
+	privileged reg714 (spr614): undefined
+	privileged reg715 (spr615): undefined
+	privileged reg716 (spr616): undefined
+	privileged reg717 (spr617): undefined
+	privileged reg718 (spr618): undefined
+	privileged reg719 (spr619): undefined
+	privileged reg720 (spr620): undefined
+	privileged reg721 (spr621): undefined
+	privileged reg722 (spr622): undefined
+	privileged reg723 (spr623): undefined
+	privileged reg724 (spr624): undefined
+	privileged reg725 (spr625): undefined
+	privileged reg726 (spr626): undefined
+	privileged reg727 (spr627): undefined
+	privileged reg728 (spr628): undefined
+	privileged reg729 (spr629): undefined
+	privileged reg730 (spr630): undefined
+	privileged reg731 (spr631): undefined
+	privileged reg732 (spr632): undefined
+	privileged reg733 (spr633): undefined
+	privileged reg734 (spr634): undefined
+	privileged reg735 (spr635): undefined
+	privileged reg736 (spr636): undefined
+	privileged reg737 (spr637): undefined
+	privileged reg738 (spr638): undefined
+	privileged reg739 (spr639): undefined
+	privileged reg740 (spr640): undefined
+	privileged reg741 (spr641): undefined
+	privileged reg742 (spr642): undefined
+	privileged reg743 (spr643): undefined
+	privileged reg744 (spr644): undefined
+	privileged reg745 (spr645): undefined
+	privileged reg746 (spr646): undefined
+	privileged reg747 (spr647): undefined
+	privileged reg748 (spr648): undefined
+	privileged reg749 (spr649): undefined
+	privileged reg750 (spr650): undefined
+	privileged reg751 (spr651): undefined
+	privileged reg752 (spr652): undefined
+	privileged reg753 (spr653): undefined
+	privileged reg754 (spr654): undefined
+	privileged reg755 (spr655): undefined
+	privileged reg756 (spr656): undefined
+	privileged reg757 (spr657): undefined
+	privileged reg758 (spr658): undefined
+	privileged reg759 (spr659): undefined
+	privileged reg760 (spr660): undefined
+	privileged reg761 (spr661): undefined
+	privileged reg762 (spr662): undefined
+	privileged reg763 (spr663): undefined
+	privileged reg764 (spr664): undefined
+	privileged reg765 (spr665): undefined
+	privileged reg766 (spr666): undefined
+	privileged reg767 (spr667): undefined
+	privileged reg768 (spr668): undefined
+	privileged reg769 (spr669): undefined
+	privileged reg770 (spr670): undefined
+	privileged reg771 (spr671): undefined
+	privileged reg772 (spr672): undefined
+	privileged reg773 (spr673): undefined
+	privileged reg774 (spr674): undefined
+	privileged reg775 (spr675): undefined
+	privileged reg776 (spr676): undefined
+	privileged reg777 (spr677): undefined
+	privileged reg778 (spr678): undefined
+	privileged reg779 (spr679): undefined
+	privileged reg780 (spr680): undefined
+	privileged reg781 (spr681): undefined
+	privileged reg782 (spr682): undefined
+	privileged reg783 (spr683): undefined
+	privileged reg784 (spr684): undefined
+	privileged reg785 (spr685): undefined
+	privileged reg786 (spr686): undefined
+	privileged reg787 (spr687): undefined
+	privileged reg788 (spr688): undefined
+	privileged reg789 (spr689): undefined
+	privileged reg790 (spr690): undefined
+	privileged reg791 (spr691): undefined
+	privileged reg792 (spr692): undefined
+	privileged reg793 (spr693): undefined
+	privileged reg794 (spr694): undefined
+	privileged reg795 (spr695): undefined
+	privileged reg796 (spr696): undefined
+	privileged reg797 (spr697): undefined
+	privileged reg798 (spr698): undefined
+	privileged reg799 (spr699): undefined
+	privileged reg800 (spr700): undefined
+	privileged reg801 (spr701): undefined
+	privileged reg802 (spr702): undefined
+	privileged reg803 (spr703): undefined
+	privileged reg804 (spr704): undefined
+	privileged reg805 (spr705): undefined
+	privileged reg806 (spr706): undefined
+	privileged reg807 (spr707): undefined
+	privileged reg808 (spr708): undefined
+	privileged reg809 (spr709): undefined
+	privileged reg810 (spr710): undefined
+	privileged reg811 (spr711): undefined
+	privileged reg812 (spr712): undefined
+	privileged reg813 (spr713): undefined
+	privileged reg814 (spr714): undefined
+	privileged reg815 (spr715): undefined
+	privileged reg816 (spr716): undefined
+	privileged reg817 (spr717): undefined
+	privileged reg818 (spr718): undefined
+	privileged reg819 (spr719): undefined
+	privileged reg820 (spr720): undefined
+	privileged reg821 (spr721): undefined
+	privileged reg822 (spr722): undefined
+	privileged reg823 (spr723): undefined
+	privileged reg824 (spr724): undefined
+	privileged reg825 (spr725): undefined
+	privileged reg826 (spr726): undefined
+	privileged reg827 (spr727): undefined
+	privileged reg828 (spr728): undefined
+	privileged reg829 (spr729): undefined
+	privileged reg830 (spr730): undefined
+	privileged reg831 (spr731): undefined
+	privileged reg832 (spr732): undefined
+	privileged reg833 (spr733): undefined
+	privileged reg834 (spr734): undefined
+	privileged reg835 (spr735): undefined
+	privileged reg836 (spr736): undefined
+	privileged reg837 (spr737): undefined
+	privileged reg838 (spr738): undefined
+	privileged reg839 (spr739): undefined
+	privileged reg840 (spr740): undefined
+	privileged reg841 (spr741): undefined
+	privileged reg842 (spr742): undefined
+	privileged reg843 (spr743): undefined
+	privileged reg844 (spr744): undefined
+	privileged reg845 (spr745): undefined
+	privileged reg846 (spr746): undefined
+	privileged reg847 (spr747): undefined
+	privileged reg848 (spr748): undefined
+	privileged reg849 (spr749): undefined
+	privileged reg850 (spr750): undefined
+	privileged reg851 (spr751): undefined
+	privileged reg852 (spr752): undefined
+	privileged reg853 (spr753): undefined
+	privileged reg854 (spr754): undefined
+	privileged reg855 (spr755): undefined
+	privileged reg856 (spr756): undefined
+	privileged reg857 (spr757): undefined
+	privileged reg858 (spr758): undefined
+	privileged reg859 (spr759): undefined
+	privileged reg860 (spr760): undefined
+	privileged reg861 (spr761): undefined
+	privileged reg862 (spr762): undefined
+	privileged reg863 (spr763): undefined
+	privileged reg864 (spr764): undefined
+	privileged reg865 (spr765): undefined
+	privileged reg866 (spr766): undefined
+	privileged reg867 (spr767): undefined
+	privileged reg868 (spr768): undefined
+	privileged reg869 (spr769): undefined
+	privileged reg870 (spr770): undefined
+	privileged reg871 (spr771): undefined
+	privileged reg872 (spr772): undefined
+	privileged reg873 (spr773): undefined
+	privileged reg874 (spr774): undefined
+	privileged reg875 (spr775): undefined
+	privileged reg876 (spr776): undefined
+	privileged reg877 (spr777): undefined
+	privileged reg878 (spr778): undefined
+	privileged reg879 (spr779): undefined
+	privileged reg880 (spr780): undefined
+	privileged reg881 (spr781): undefined
+	privileged reg882 (spr782): undefined
+	privileged reg883 (spr783): undefined
+	privileged reg884 (spr784): undefined
+	privileged reg885 (spr785): undefined
+	privileged reg886 (spr786): undefined
+	privileged reg887 (spr787): undefined
+	privileged reg888 (spr788): undefined
+	privileged reg889 (spr789): undefined
+	privileged reg890 (spr790): undefined
+	privileged reg891 (spr791): undefined
+	privileged reg892 (spr792): undefined
+	privileged reg893 (spr793): undefined
+	privileged reg894 (spr794): undefined
+	privileged reg895 (spr795): undefined
+	privileged reg896 (spr796): undefined
+	privileged reg897 (spr797): undefined
+	privileged reg898 (spr798): undefined
+	privileged reg899 (spr799): undefined
+	privileged reg900 (spr800): undefined
+	privileged reg901 (spr801): undefined
+	privileged reg902 (spr802): undefined
+	privileged reg903 (spr803): undefined
+	privileged reg904 (spr804): undefined
+	privileged reg905 (spr805): undefined
+	privileged reg906 (spr806): undefined
+	privileged reg907 (spr807): undefined
+	privileged reg908 (spr808): undefined
+	privileged reg909 (spr809): undefined
+	privileged reg910 (spr810): undefined
+	privileged reg911 (spr811): undefined
+	privileged reg912 (spr812): undefined
+	privileged reg913 (spr813): undefined
+	privileged reg914 (spr814): undefined
+	privileged reg915 (spr815): undefined
+	privileged reg916 (spr816): undefined
+	privileged reg917 (spr817): undefined
+	privileged reg918 (spr818): undefined
+	privileged reg919 (spr819): undefined
+	privileged reg920 (spr820): undefined
+	privileged reg921 (spr821): undefined
+	privileged reg922 (spr822): undefined
+	privileged reg923 (spr823): undefined
+	privileged reg924 (spr824): undefined
+	privileged reg925 (spr825): undefined
+	privileged reg926 (spr826): undefined
+	privileged reg927 (spr827): undefined
+	privileged reg928 (spr828): undefined
+	privileged reg929 (spr829): undefined
+	privileged reg930 (spr830): undefined
+	privileged reg931 (spr831): undefined
+	privileged reg932 (spr832): undefined
+	privileged reg933 (spr833): undefined
+	privileged reg934 (spr834): undefined
+	privileged reg935 (spr835): undefined
+	privileged reg936 (spr836): undefined
+	privileged reg937 (spr837): undefined
+	privileged reg938 (spr838): undefined
+	privileged reg939 (spr839): undefined
+	privileged reg940 (spr840): undefined
+	privileged reg941 (spr841): undefined
+	privileged reg942 (spr842): undefined
+	privileged reg943 (spr843): undefined
+	privileged reg944 (spr844): undefined
+	privileged reg945 (spr845): undefined
+	privileged reg946 (spr846): undefined
+	privileged reg947 (spr847): undefined
+	privileged reg948 (spr848): undefined
+	privileged reg949 (spr849): undefined
+	privileged reg950 (spr850): undefined
+	privileged reg951 (spr851): undefined
+	privileged reg952 (spr852): undefined
+	privileged reg953 (spr853): undefined
+	privileged reg954 (spr854): undefined
+	privileged reg955 (spr855): undefined
+	privileged reg956 (spr856): undefined
+	privileged reg957 (spr857): undefined
+	privileged reg958 (spr858): undefined
+	privileged reg959 (spr859): undefined
+	privileged reg960 (spr860): undefined
+	privileged reg961 (spr861): undefined
+	privileged reg962 (spr862): undefined
+	privileged reg963 (spr863): undefined
+	privileged reg964 (spr864): undefined
+	privileged reg965 (spr865): undefined
+	privileged reg966 (spr866): undefined
+	privileged reg967 (spr867): undefined
+	privileged reg968 (spr868): undefined
+	privileged reg969 (spr869): undefined
+	privileged reg970 (spr870): undefined
+	privileged reg971 (spr871): undefined
+	privileged reg972 (spr872): undefined
+	privileged reg973 (spr873): undefined
+	privileged reg974 (spr874): undefined
+	privileged reg975 (spr875): undefined
+	privileged reg976 (spr876): undefined
+	privileged reg977 (spr877): undefined
+	privileged reg978 (spr878): undefined
+	privileged reg979 (spr879): undefined
+	privileged reg980 (spr880): undefined
+	privileged reg981 (spr881): undefined
+	privileged reg982 (spr882): undefined
+	privileged reg983 (spr883): undefined
+	privileged reg984 (spr884): undefined
+	privileged reg985 (spr885): undefined
+	privileged reg986 (spr886): undefined
+	privileged reg987 (spr887): undefined
+	privileged reg988 (spr888): undefined
+	privileged reg989 (spr889): undefined
+	privileged reg990 (spr890): undefined
+	privileged reg991 (spr891): undefined
+	privileged reg992 (spr892): undefined
+	privileged reg993 (spr893): undefined
+	privileged reg994 (spr894): undefined
+	privileged reg995 (spr895): undefined
+	privileged reg996 (spr896): undefined
+	privileged reg997 (spr897): undefined
+	privileged reg998 (spr898): undefined
+	privileged reg999 (spr899): undefined
+	vector reg1124 (vr0): undefined
+	vector reg1125 (vr1): undefined
+	vector reg1126 (vr2): undefined
+	vector reg1127 (vr3): undefined
+	vector reg1128 (vr4): undefined
+	vector reg1129 (vr5): undefined
+	vector reg1130 (vr6): undefined
+	vector reg1131 (vr7): undefined
+	vector reg1132 (vr8): undefined
+	vector reg1133 (vr9): undefined
+	vector reg1134 (vr10): undefined
+	vector reg1135 (vr11): undefined
+	vector reg1136 (vr12): undefined
+	vector reg1137 (vr13): undefined
+	vector reg1138 (vr14): undefined
+	vector reg1139 (vr15): undefined
+	vector reg1140 (vr16): undefined
+	vector reg1141 (vr17): undefined
+	vector reg1142 (vr18): undefined
+	vector reg1143 (vr19): undefined
+	vector reg1144 (vr20): undefined
+	vector reg1145 (vr21): undefined
+	vector reg1146 (vr22): undefined
+	vector reg1147 (vr23): undefined
+	vector reg1148 (vr24): undefined
+	vector reg1149 (vr25): undefined
+	vector reg1150 (vr26): undefined
+	vector reg1151 (vr27): undefined
+	vector reg1152 (vr28): undefined
+	vector reg1153 (vr29): undefined
+	vector reg1154 (vr30): undefined
+	vector reg1155 (vr31): undefined
+dwarf_cfi_addrframe (.debug_frame): no matching address range
+EOF
+
+# EM_PPC64 (function bar 0x00000000100005b0)
+# Note. Only in .debug_frame, not in .eh_frame.
+# Same as testfileppc32 but without -m32.
+testfiles testfileppc64
+testrun_compare ${abs_builddir}/addrcfi -e testfileppc64 0x00000000100005b0 <<\EOF
+dwarf_cfi_addrframe (.eh_frame): no matching address range
+.debug_frame has 0x100005b0 => [0x100005b0, 0x100005d0):
+	return address in reg65
+	CFA location expression: bregx(1)
+	integer reg0 (r0): undefined
+	integer reg1 (r1): location expression: call_frame_cfa stack_value
+	integer reg2 (r2): same_value
+	integer reg3 (r3): undefined
+	integer reg4 (r4): undefined
+	integer reg5 (r5): undefined
+	integer reg6 (r6): undefined
+	integer reg7 (r7): undefined
+	integer reg8 (r8): undefined
+	integer reg9 (r9): undefined
+	integer reg10 (r10): undefined
+	integer reg11 (r11): undefined
+	integer reg12 (r12): undefined
+	integer reg13 (r13): same_value
+	integer reg14 (r14): same_value
+	integer reg15 (r15): same_value
+	integer reg16 (r16): same_value
+	integer reg17 (r17): same_value
+	integer reg18 (r18): same_value
+	integer reg19 (r19): same_value
+	integer reg20 (r20): same_value
+	integer reg21 (r21): same_value
+	integer reg22 (r22): same_value
+	integer reg23 (r23): same_value
+	integer reg24 (r24): same_value
+	integer reg25 (r25): same_value
+	integer reg26 (r26): same_value
+	integer reg27 (r27): same_value
+	integer reg28 (r28): same_value
+	integer reg29 (r29): same_value
+	integer reg30 (r30): same_value
+	integer reg31 (r31): same_value
+	FPU reg32 (f0): undefined
+	FPU reg33 (f1): undefined
+	FPU reg34 (f2): undefined
+	FPU reg35 (f3): undefined
+	FPU reg36 (f4): undefined
+	FPU reg37 (f5): undefined
+	FPU reg38 (f6): undefined
+	FPU reg39 (f7): undefined
+	FPU reg40 (f8): undefined
+	FPU reg41 (f9): undefined
+	FPU reg42 (f10): undefined
+	FPU reg43 (f11): undefined
+	FPU reg44 (f12): undefined
+	FPU reg45 (f13): undefined
+	FPU reg46 (f14): undefined
+	FPU reg47 (f15): undefined
+	FPU reg48 (f16): undefined
+	FPU reg49 (f17): undefined
+	FPU reg50 (f18): undefined
+	FPU reg51 (f19): undefined
+	FPU reg52 (f20): undefined
+	FPU reg53 (f21): undefined
+	FPU reg54 (f22): undefined
+	FPU reg55 (f23): undefined
+	FPU reg56 (f24): undefined
+	FPU reg57 (f25): undefined
+	FPU reg58 (f26): undefined
+	FPU reg59 (f27): undefined
+	FPU reg60 (f28): undefined
+	FPU reg61 (f29): undefined
+	FPU reg62 (f30): undefined
+	FPU reg63 (f31): undefined
+	integer reg64 (cr): undefined
+	FPU reg65 (fpscr): same_value
+	integer reg66 (msr): undefined
+	vector reg67 (vscr): undefined
+	privileged reg70 (sr0): undefined
+	privileged reg71 (sr1): undefined
+	privileged reg72 (sr2): undefined
+	privileged reg73 (sr3): undefined
+	privileged reg74 (sr4): undefined
+	privileged reg75 (sr5): undefined
+	privileged reg76 (sr6): undefined
+	privileged reg77 (sr7): undefined
+	privileged reg78 (sr8): undefined
+	privileged reg79 (sr9): undefined
+	privileged reg80 (sr10): undefined
+	privileged reg81 (sr11): undefined
+	privileged reg82 (sr12): undefined
+	privileged reg83 (sr13): undefined
+	privileged reg84 (sr14): undefined
+	privileged reg85 (sr15): undefined
+	privileged reg100 (spr0): undefined
+	privileged reg101 (xer): undefined
+	privileged reg102 (spr2): undefined
+	privileged reg103 (spr3): undefined
+	privileged reg104 (spr4): undefined
+	privileged reg105 (spr5): undefined
+	privileged reg106 (spr6): undefined
+	privileged reg107 (spr7): undefined
+	privileged reg108 (lr): undefined
+	privileged reg109 (ctr): undefined
+	privileged reg110 (spr10): undefined
+	privileged reg111 (spr11): undefined
+	privileged reg112 (spr12): undefined
+	privileged reg113 (spr13): undefined
+	privileged reg114 (tfhar): undefined
+	privileged reg115 (tfiar): undefined
+	privileged reg116 (texasr): undefined
+	privileged reg117 (spr17): undefined
+	privileged reg118 (dsisr): undefined
+	privileged reg119 (dar): undefined
+	privileged reg120 (spr20): undefined
+	privileged reg121 (spr21): undefined
+	privileged reg122 (dec): undefined
+	privileged reg123 (spr23): undefined
+	privileged reg124 (spr24): undefined
+	privileged reg125 (spr25): undefined
+	privileged reg126 (spr26): undefined
+	privileged reg127 (spr27): undefined
+	privileged reg128 (spr28): undefined
+	privileged reg129 (spr29): undefined
+	privileged reg130 (spr30): undefined
+	privileged reg131 (spr31): undefined
+	privileged reg132 (spr32): undefined
+	privileged reg133 (spr33): undefined
+	privileged reg134 (spr34): undefined
+	privileged reg135 (spr35): undefined
+	privileged reg136 (spr36): undefined
+	privileged reg137 (spr37): undefined
+	privileged reg138 (spr38): undefined
+	privileged reg139 (spr39): undefined
+	privileged reg140 (spr40): undefined
+	privileged reg141 (spr41): undefined
+	privileged reg142 (spr42): undefined
+	privileged reg143 (spr43): undefined
+	privileged reg144 (spr44): undefined
+	privileged reg145 (spr45): undefined
+	privileged reg146 (spr46): undefined
+	privileged reg147 (spr47): undefined
+	privileged reg148 (spr48): undefined
+	privileged reg149 (spr49): undefined
+	privileged reg150 (spr50): undefined
+	privileged reg151 (spr51): undefined
+	privileged reg152 (spr52): undefined
+	privileged reg153 (spr53): undefined
+	privileged reg154 (spr54): undefined
+	privileged reg155 (spr55): undefined
+	privileged reg156 (spr56): undefined
+	privileged reg157 (spr57): undefined
+	privileged reg158 (spr58): undefined
+	privileged reg159 (spr59): undefined
+	privileged reg160 (spr60): undefined
+	privileged reg161 (spr61): undefined
+	privileged reg162 (spr62): undefined
+	privileged reg163 (spr63): undefined
+	privileged reg164 (spr64): undefined
+	privileged reg165 (spr65): undefined
+	privileged reg166 (spr66): undefined
+	privileged reg167 (spr67): undefined
+	privileged reg168 (spr68): undefined
+	privileged reg169 (spr69): undefined
+	privileged reg170 (spr70): undefined
+	privileged reg171 (spr71): undefined
+	privileged reg172 (spr72): undefined
+	privileged reg173 (spr73): undefined
+	privileged reg174 (spr74): undefined
+	privileged reg175 (spr75): undefined
+	privileged reg176 (spr76): undefined
+	privileged reg177 (spr77): undefined
+	privileged reg178 (spr78): undefined
+	privileged reg179 (spr79): undefined
+	privileged reg180 (spr80): undefined
+	privileged reg181 (spr81): undefined
+	privileged reg182 (spr82): undefined
+	privileged reg183 (spr83): undefined
+	privileged reg184 (spr84): undefined
+	privileged reg185 (spr85): undefined
+	privileged reg186 (spr86): undefined
+	privileged reg187 (spr87): undefined
+	privileged reg188 (spr88): undefined
+	privileged reg189 (spr89): undefined
+	privileged reg190 (spr90): undefined
+	privileged reg191 (spr91): undefined
+	privileged reg192 (spr92): undefined
+	privileged reg193 (spr93): undefined
+	privileged reg194 (spr94): undefined
+	privileged reg195 (spr95): undefined
+	privileged reg196 (spr96): undefined
+	privileged reg197 (spr97): undefined
+	privileged reg198 (spr98): undefined
+	privileged reg199 (spr99): undefined
+	privileged reg200 (spr100): undefined
+	privileged reg201 (spr101): undefined
+	privileged reg202 (spr102): undefined
+	privileged reg203 (spr103): undefined
+	privileged reg204 (spr104): undefined
+	privileged reg205 (spr105): undefined
+	privileged reg206 (spr106): undefined
+	privileged reg207 (spr107): undefined
+	privileged reg208 (spr108): undefined
+	privileged reg209 (spr109): undefined
+	privileged reg210 (spr110): undefined
+	privileged reg211 (spr111): undefined
+	privileged reg212 (spr112): undefined
+	privileged reg213 (spr113): undefined
+	privileged reg214 (spr114): undefined
+	privileged reg215 (spr115): undefined
+	privileged reg216 (spr116): undefined
+	privileged reg217 (spr117): undefined
+	privileged reg218 (spr118): undefined
+	privileged reg219 (spr119): undefined
+	privileged reg220 (spr120): undefined
+	privileged reg221 (spr121): undefined
+	privileged reg222 (spr122): undefined
+	privileged reg223 (spr123): undefined
+	privileged reg224 (spr124): undefined
+	privileged reg225 (spr125): undefined
+	privileged reg226 (spr126): undefined
+	privileged reg227 (spr127): undefined
+	privileged reg228 (spr128): undefined
+	privileged reg229 (spr129): undefined
+	privileged reg230 (spr130): undefined
+	privileged reg231 (spr131): undefined
+	privileged reg232 (spr132): undefined
+	privileged reg233 (spr133): undefined
+	privileged reg234 (spr134): undefined
+	privileged reg235 (spr135): undefined
+	privileged reg236 (spr136): undefined
+	privileged reg237 (spr137): undefined
+	privileged reg238 (spr138): undefined
+	privileged reg239 (spr139): undefined
+	privileged reg240 (spr140): undefined
+	privileged reg241 (spr141): undefined
+	privileged reg242 (spr142): undefined
+	privileged reg243 (spr143): undefined
+	privileged reg244 (spr144): undefined
+	privileged reg245 (spr145): undefined
+	privileged reg246 (spr146): undefined
+	privileged reg247 (spr147): undefined
+	privileged reg248 (spr148): undefined
+	privileged reg249 (spr149): undefined
+	privileged reg250 (spr150): undefined
+	privileged reg251 (spr151): undefined
+	privileged reg252 (spr152): undefined
+	privileged reg253 (spr153): undefined
+	privileged reg254 (spr154): undefined
+	privileged reg255 (spr155): undefined
+	privileged reg256 (spr156): undefined
+	privileged reg257 (spr157): undefined
+	privileged reg258 (spr158): undefined
+	privileged reg259 (spr159): undefined
+	privileged reg260 (spr160): undefined
+	privileged reg261 (spr161): undefined
+	privileged reg262 (spr162): undefined
+	privileged reg263 (spr163): undefined
+	privileged reg264 (spr164): undefined
+	privileged reg265 (spr165): undefined
+	privileged reg266 (spr166): undefined
+	privileged reg267 (spr167): undefined
+	privileged reg268 (spr168): undefined
+	privileged reg269 (spr169): undefined
+	privileged reg270 (spr170): undefined
+	privileged reg271 (spr171): undefined
+	privileged reg272 (spr172): undefined
+	privileged reg273 (spr173): undefined
+	privileged reg274 (spr174): undefined
+	privileged reg275 (spr175): undefined
+	privileged reg276 (spr176): undefined
+	privileged reg277 (spr177): undefined
+	privileged reg278 (spr178): undefined
+	privileged reg279 (spr179): undefined
+	privileged reg280 (spr180): undefined
+	privileged reg281 (spr181): undefined
+	privileged reg282 (spr182): undefined
+	privileged reg283 (spr183): undefined
+	privileged reg284 (spr184): undefined
+	privileged reg285 (spr185): undefined
+	privileged reg286 (spr186): undefined
+	privileged reg287 (spr187): undefined
+	privileged reg288 (spr188): undefined
+	privileged reg289 (spr189): undefined
+	privileged reg290 (spr190): undefined
+	privileged reg291 (spr191): undefined
+	privileged reg292 (spr192): undefined
+	privileged reg293 (spr193): undefined
+	privileged reg294 (spr194): undefined
+	privileged reg295 (spr195): undefined
+	privileged reg296 (spr196): undefined
+	privileged reg297 (spr197): undefined
+	privileged reg298 (spr198): undefined
+	privileged reg299 (spr199): undefined
+	privileged reg300 (spr200): undefined
+	privileged reg301 (spr201): undefined
+	privileged reg302 (spr202): undefined
+	privileged reg303 (spr203): undefined
+	privileged reg304 (spr204): undefined
+	privileged reg305 (spr205): undefined
+	privileged reg306 (spr206): undefined
+	privileged reg307 (spr207): undefined
+	privileged reg308 (spr208): undefined
+	privileged reg309 (spr209): undefined
+	privileged reg310 (spr210): undefined
+	privileged reg311 (spr211): undefined
+	privileged reg312 (spr212): undefined
+	privileged reg313 (spr213): undefined
+	privileged reg314 (spr214): undefined
+	privileged reg315 (spr215): undefined
+	privileged reg316 (spr216): undefined
+	privileged reg317 (spr217): undefined
+	privileged reg318 (spr218): undefined
+	privileged reg319 (spr219): undefined
+	privileged reg320 (spr220): undefined
+	privileged reg321 (spr221): undefined
+	privileged reg322 (spr222): undefined
+	privileged reg323 (spr223): undefined
+	privileged reg324 (spr224): undefined
+	privileged reg325 (spr225): undefined
+	privileged reg326 (spr226): undefined
+	privileged reg327 (spr227): undefined
+	privileged reg328 (spr228): undefined
+	privileged reg329 (spr229): undefined
+	privileged reg330 (spr230): undefined
+	privileged reg331 (spr231): undefined
+	privileged reg332 (spr232): undefined
+	privileged reg333 (spr233): undefined
+	privileged reg334 (spr234): undefined
+	privileged reg335 (spr235): undefined
+	privileged reg336 (spr236): undefined
+	privileged reg337 (spr237): undefined
+	privileged reg338 (spr238): undefined
+	privileged reg339 (spr239): undefined
+	privileged reg340 (spr240): undefined
+	privileged reg341 (spr241): undefined
+	privileged reg342 (spr242): undefined
+	privileged reg343 (spr243): undefined
+	privileged reg344 (spr244): undefined
+	privileged reg345 (spr245): undefined
+	privileged reg346 (spr246): undefined
+	privileged reg347 (spr247): undefined
+	privileged reg348 (spr248): undefined
+	privileged reg349 (spr249): undefined
+	privileged reg350 (spr250): undefined
+	privileged reg351 (spr251): undefined
+	privileged reg352 (spr252): undefined
+	privileged reg353 (spr253): undefined
+	privileged reg354 (spr254): undefined
+	privileged reg355 (spr255): undefined
+	vector reg356 (vrsave): undefined
+	privileged reg357 (spr257): undefined
+	privileged reg358 (spr258): undefined
+	privileged reg359 (spr259): undefined
+	privileged reg360 (spr260): undefined
+	privileged reg361 (spr261): undefined
+	privileged reg362 (spr262): undefined
+	privileged reg363 (spr263): undefined
+	privileged reg364 (spr264): undefined
+	privileged reg365 (spr265): undefined
+	privileged reg366 (spr266): undefined
+	privileged reg367 (spr267): undefined
+	privileged reg368 (spr268): undefined
+	privileged reg369 (spr269): undefined
+	privileged reg370 (spr270): undefined
+	privileged reg371 (spr271): undefined
+	privileged reg372 (spr272): undefined
+	privileged reg373 (spr273): undefined
+	privileged reg374 (spr274): undefined
+	privileged reg375 (spr275): undefined
+	privileged reg376 (spr276): undefined
+	privileged reg377 (spr277): undefined
+	privileged reg378 (spr278): undefined
+	privileged reg379 (spr279): undefined
+	privileged reg380 (spr280): undefined
+	privileged reg381 (spr281): undefined
+	privileged reg382 (spr282): undefined
+	privileged reg383 (spr283): undefined
+	privileged reg384 (spr284): undefined
+	privileged reg385 (spr285): undefined
+	privileged reg386 (spr286): undefined
+	privileged reg387 (spr287): undefined
+	privileged reg388 (spr288): undefined
+	privileged reg389 (spr289): undefined
+	privileged reg390 (spr290): undefined
+	privileged reg391 (spr291): undefined
+	privileged reg392 (spr292): undefined
+	privileged reg393 (spr293): undefined
+	privileged reg394 (spr294): undefined
+	privileged reg395 (spr295): undefined
+	privileged reg396 (spr296): undefined
+	privileged reg397 (spr297): undefined
+	privileged reg398 (spr298): undefined
+	privileged reg399 (spr299): undefined
+	privileged reg400 (spr300): undefined
+	privileged reg401 (spr301): undefined
+	privileged reg402 (spr302): undefined
+	privileged reg403 (spr303): undefined
+	privileged reg404 (spr304): undefined
+	privileged reg405 (spr305): undefined
+	privileged reg406 (spr306): undefined
+	privileged reg407 (spr307): undefined
+	privileged reg408 (spr308): undefined
+	privileged reg409 (spr309): undefined
+	privileged reg410 (spr310): undefined
+	privileged reg411 (spr311): undefined
+	privileged reg412 (spr312): undefined
+	privileged reg413 (spr313): undefined
+	privileged reg414 (spr314): undefined
+	privileged reg415 (spr315): undefined
+	privileged reg416 (spr316): undefined
+	privileged reg417 (spr317): undefined
+	privileged reg418 (spr318): undefined
+	privileged reg419 (spr319): undefined
+	privileged reg420 (spr320): undefined
+	privileged reg421 (spr321): undefined
+	privileged reg422 (spr322): undefined
+	privileged reg423 (spr323): undefined
+	privileged reg424 (spr324): undefined
+	privileged reg425 (spr325): undefined
+	privileged reg426 (spr326): undefined
+	privileged reg427 (spr327): undefined
+	privileged reg428 (spr328): undefined
+	privileged reg429 (spr329): undefined
+	privileged reg430 (spr330): undefined
+	privileged reg431 (spr331): undefined
+	privileged reg432 (spr332): undefined
+	privileged reg433 (spr333): undefined
+	privileged reg434 (spr334): undefined
+	privileged reg435 (spr335): undefined
+	privileged reg436 (spr336): undefined
+	privileged reg437 (spr337): undefined
+	privileged reg438 (spr338): undefined
+	privileged reg439 (spr339): undefined
+	privileged reg440 (spr340): undefined
+	privileged reg441 (spr341): undefined
+	privileged reg442 (spr342): undefined
+	privileged reg443 (spr343): undefined
+	privileged reg444 (spr344): undefined
+	privileged reg445 (spr345): undefined
+	privileged reg446 (spr346): undefined
+	privileged reg447 (spr347): undefined
+	privileged reg448 (spr348): undefined
+	privileged reg449 (spr349): undefined
+	privileged reg450 (spr350): undefined
+	privileged reg451 (spr351): undefined
+	privileged reg452 (spr352): undefined
+	privileged reg453 (spr353): undefined
+	privileged reg454 (spr354): undefined
+	privileged reg455 (spr355): undefined
+	privileged reg456 (spr356): undefined
+	privileged reg457 (spr357): undefined
+	privileged reg458 (spr358): undefined
+	privileged reg459 (spr359): undefined
+	privileged reg460 (spr360): undefined
+	privileged reg461 (spr361): undefined
+	privileged reg462 (spr362): undefined
+	privileged reg463 (spr363): undefined
+	privileged reg464 (spr364): undefined
+	privileged reg465 (spr365): undefined
+	privileged reg466 (spr366): undefined
+	privileged reg467 (spr367): undefined
+	privileged reg468 (spr368): undefined
+	privileged reg469 (spr369): undefined
+	privileged reg470 (spr370): undefined
+	privileged reg471 (spr371): undefined
+	privileged reg472 (spr372): undefined
+	privileged reg473 (spr373): undefined
+	privileged reg474 (spr374): undefined
+	privileged reg475 (spr375): undefined
+	privileged reg476 (spr376): undefined
+	privileged reg477 (spr377): undefined
+	privileged reg478 (spr378): undefined
+	privileged reg479 (spr379): undefined
+	privileged reg480 (spr380): undefined
+	privileged reg481 (spr381): undefined
+	privileged reg482 (spr382): undefined
+	privileged reg483 (spr383): undefined
+	privileged reg484 (spr384): undefined
+	privileged reg485 (spr385): undefined
+	privileged reg486 (spr386): undefined
+	privileged reg487 (spr387): undefined
+	privileged reg488 (spr388): undefined
+	privileged reg489 (spr389): undefined
+	privileged reg490 (spr390): undefined
+	privileged reg491 (spr391): undefined
+	privileged reg492 (spr392): undefined
+	privileged reg493 (spr393): undefined
+	privileged reg494 (spr394): undefined
+	privileged reg495 (spr395): undefined
+	privileged reg496 (spr396): undefined
+	privileged reg497 (spr397): undefined
+	privileged reg498 (spr398): undefined
+	privileged reg499 (spr399): undefined
+	privileged reg500 (spr400): undefined
+	privileged reg501 (spr401): undefined
+	privileged reg502 (spr402): undefined
+	privileged reg503 (spr403): undefined
+	privileged reg504 (spr404): undefined
+	privileged reg505 (spr405): undefined
+	privileged reg506 (spr406): undefined
+	privileged reg507 (spr407): undefined
+	privileged reg508 (spr408): undefined
+	privileged reg509 (spr409): undefined
+	privileged reg510 (spr410): undefined
+	privileged reg511 (spr411): undefined
+	privileged reg512 (spr412): undefined
+	privileged reg513 (spr413): undefined
+	privileged reg514 (spr414): undefined
+	privileged reg515 (spr415): undefined
+	privileged reg516 (spr416): undefined
+	privileged reg517 (spr417): undefined
+	privileged reg518 (spr418): undefined
+	privileged reg519 (spr419): undefined
+	privileged reg520 (spr420): undefined
+	privileged reg521 (spr421): undefined
+	privileged reg522 (spr422): undefined
+	privileged reg523 (spr423): undefined
+	privileged reg524 (spr424): undefined
+	privileged reg525 (spr425): undefined
+	privileged reg526 (spr426): undefined
+	privileged reg527 (spr427): undefined
+	privileged reg528 (spr428): undefined
+	privileged reg529 (spr429): undefined
+	privileged reg530 (spr430): undefined
+	privileged reg531 (spr431): undefined
+	privileged reg532 (spr432): undefined
+	privileged reg533 (spr433): undefined
+	privileged reg534 (spr434): undefined
+	privileged reg535 (spr435): undefined
+	privileged reg536 (spr436): undefined
+	privileged reg537 (spr437): undefined
+	privileged reg538 (spr438): undefined
+	privileged reg539 (spr439): undefined
+	privileged reg540 (spr440): undefined
+	privileged reg541 (spr441): undefined
+	privileged reg542 (spr442): undefined
+	privileged reg543 (spr443): undefined
+	privileged reg544 (spr444): undefined
+	privileged reg545 (spr445): undefined
+	privileged reg546 (spr446): undefined
+	privileged reg547 (spr447): undefined
+	privileged reg548 (spr448): undefined
+	privileged reg549 (spr449): undefined
+	privileged reg550 (spr450): undefined
+	privileged reg551 (spr451): undefined
+	privileged reg552 (spr452): undefined
+	privileged reg553 (spr453): undefined
+	privileged reg554 (spr454): undefined
+	privileged reg555 (spr455): undefined
+	privileged reg556 (spr456): undefined
+	privileged reg557 (spr457): undefined
+	privileged reg558 (spr458): undefined
+	privileged reg559 (spr459): undefined
+	privileged reg560 (spr460): undefined
+	privileged reg561 (spr461): undefined
+	privileged reg562 (spr462): undefined
+	privileged reg563 (spr463): undefined
+	privileged reg564 (spr464): undefined
+	privileged reg565 (spr465): undefined
+	privileged reg566 (spr466): undefined
+	privileged reg567 (spr467): undefined
+	privileged reg568 (spr468): undefined
+	privileged reg569 (spr469): undefined
+	privileged reg570 (spr470): undefined
+	privileged reg571 (spr471): undefined
+	privileged reg572 (spr472): undefined
+	privileged reg573 (spr473): undefined
+	privileged reg574 (spr474): undefined
+	privileged reg575 (spr475): undefined
+	privileged reg576 (spr476): undefined
+	privileged reg577 (spr477): undefined
+	privileged reg578 (spr478): undefined
+	privileged reg579 (spr479): undefined
+	privileged reg580 (spr480): undefined
+	privileged reg581 (spr481): undefined
+	privileged reg582 (spr482): undefined
+	privileged reg583 (spr483): undefined
+	privileged reg584 (spr484): undefined
+	privileged reg585 (spr485): undefined
+	privileged reg586 (spr486): undefined
+	privileged reg587 (spr487): undefined
+	privileged reg588 (spr488): undefined
+	privileged reg589 (spr489): undefined
+	privileged reg590 (spr490): undefined
+	privileged reg591 (spr491): undefined
+	privileged reg592 (spr492): undefined
+	privileged reg593 (spr493): undefined
+	privileged reg594 (spr494): undefined
+	privileged reg595 (spr495): undefined
+	privileged reg596 (spr496): undefined
+	privileged reg597 (spr497): undefined
+	privileged reg598 (spr498): undefined
+	privileged reg599 (spr499): undefined
+	privileged reg600 (spr500): undefined
+	privileged reg601 (spr501): undefined
+	privileged reg602 (spr502): undefined
+	privileged reg603 (spr503): undefined
+	privileged reg604 (spr504): undefined
+	privileged reg605 (spr505): undefined
+	privileged reg606 (spr506): undefined
+	privileged reg607 (spr507): undefined
+	privileged reg608 (spr508): undefined
+	privileged reg609 (spr509): undefined
+	privileged reg610 (spr510): undefined
+	privileged reg611 (spr511): undefined
+	vector reg612 (spefscr): undefined
+	privileged reg613 (spr513): undefined
+	privileged reg614 (spr514): undefined
+	privileged reg615 (spr515): undefined
+	privileged reg616 (spr516): undefined
+	privileged reg617 (spr517): undefined
+	privileged reg618 (spr518): undefined
+	privileged reg619 (spr519): undefined
+	privileged reg620 (spr520): undefined
+	privileged reg621 (spr521): undefined
+	privileged reg622 (spr522): undefined
+	privileged reg623 (spr523): undefined
+	privileged reg624 (spr524): undefined
+	privileged reg625 (spr525): undefined
+	privileged reg626 (spr526): undefined
+	privileged reg627 (spr527): undefined
+	privileged reg628 (spr528): undefined
+	privileged reg629 (spr529): undefined
+	privileged reg630 (spr530): undefined
+	privileged reg631 (spr531): undefined
+	privileged reg632 (spr532): undefined
+	privileged reg633 (spr533): undefined
+	privileged reg634 (spr534): undefined
+	privileged reg635 (spr535): undefined
+	privileged reg636 (spr536): undefined
+	privileged reg637 (spr537): undefined
+	privileged reg638 (spr538): undefined
+	privileged reg639 (spr539): undefined
+	privileged reg640 (spr540): undefined
+	privileged reg641 (spr541): undefined
+	privileged reg642 (spr542): undefined
+	privileged reg643 (spr543): undefined
+	privileged reg644 (spr544): undefined
+	privileged reg645 (spr545): undefined
+	privileged reg646 (spr546): undefined
+	privileged reg647 (spr547): undefined
+	privileged reg648 (spr548): undefined
+	privileged reg649 (spr549): undefined
+	privileged reg650 (spr550): undefined
+	privileged reg651 (spr551): undefined
+	privileged reg652 (spr552): undefined
+	privileged reg653 (spr553): undefined
+	privileged reg654 (spr554): undefined
+	privileged reg655 (spr555): undefined
+	privileged reg656 (spr556): undefined
+	privileged reg657 (spr557): undefined
+	privileged reg658 (spr558): undefined
+	privileged reg659 (spr559): undefined
+	privileged reg660 (spr560): undefined
+	privileged reg661 (spr561): undefined
+	privileged reg662 (spr562): undefined
+	privileged reg663 (spr563): undefined
+	privileged reg664 (spr564): undefined
+	privileged reg665 (spr565): undefined
+	privileged reg666 (spr566): undefined
+	privileged reg667 (spr567): undefined
+	privileged reg668 (spr568): undefined
+	privileged reg669 (spr569): undefined
+	privileged reg670 (spr570): undefined
+	privileged reg671 (spr571): undefined
+	privileged reg672 (spr572): undefined
+	privileged reg673 (spr573): undefined
+	privileged reg674 (spr574): undefined
+	privileged reg675 (spr575): undefined
+	privileged reg676 (spr576): undefined
+	privileged reg677 (spr577): undefined
+	privileged reg678 (spr578): undefined
+	privileged reg679 (spr579): undefined
+	privileged reg680 (spr580): undefined
+	privileged reg681 (spr581): undefined
+	privileged reg682 (spr582): undefined
+	privileged reg683 (spr583): undefined
+	privileged reg684 (spr584): undefined
+	privileged reg685 (spr585): undefined
+	privileged reg686 (spr586): undefined
+	privileged reg687 (spr587): undefined
+	privileged reg688 (spr588): undefined
+	privileged reg689 (spr589): undefined
+	privileged reg690 (spr590): undefined
+	privileged reg691 (spr591): undefined
+	privileged reg692 (spr592): undefined
+	privileged reg693 (spr593): undefined
+	privileged reg694 (spr594): undefined
+	privileged reg695 (spr595): undefined
+	privileged reg696 (spr596): undefined
+	privileged reg697 (spr597): undefined
+	privileged reg698 (spr598): undefined
+	privileged reg699 (spr599): undefined
+	privileged reg700 (spr600): undefined
+	privileged reg701 (spr601): undefined
+	privileged reg702 (spr602): undefined
+	privileged reg703 (spr603): undefined
+	privileged reg704 (spr604): undefined
+	privileged reg705 (spr605): undefined
+	privileged reg706 (spr606): undefined
+	privileged reg707 (spr607): undefined
+	privileged reg708 (spr608): undefined
+	privileged reg709 (spr609): undefined
+	privileged reg710 (spr610): undefined
+	privileged reg711 (spr611): undefined
+	privileged reg712 (spr612): undefined
+	privileged reg713 (spr613): undefined
+	privileged reg714 (spr614): undefined
+	privileged reg715 (spr615): undefined
+	privileged reg716 (spr616): undefined
+	privileged reg717 (spr617): undefined
+	privileged reg718 (spr618): undefined
+	privileged reg719 (spr619): undefined
+	privileged reg720 (spr620): undefined
+	privileged reg721 (spr621): undefined
+	privileged reg722 (spr622): undefined
+	privileged reg723 (spr623): undefined
+	privileged reg724 (spr624): undefined
+	privileged reg725 (spr625): undefined
+	privileged reg726 (spr626): undefined
+	privileged reg727 (spr627): undefined
+	privileged reg728 (spr628): undefined
+	privileged reg729 (spr629): undefined
+	privileged reg730 (spr630): undefined
+	privileged reg731 (spr631): undefined
+	privileged reg732 (spr632): undefined
+	privileged reg733 (spr633): undefined
+	privileged reg734 (spr634): undefined
+	privileged reg735 (spr635): undefined
+	privileged reg736 (spr636): undefined
+	privileged reg737 (spr637): undefined
+	privileged reg738 (spr638): undefined
+	privileged reg739 (spr639): undefined
+	privileged reg740 (spr640): undefined
+	privileged reg741 (spr641): undefined
+	privileged reg742 (spr642): undefined
+	privileged reg743 (spr643): undefined
+	privileged reg744 (spr644): undefined
+	privileged reg745 (spr645): undefined
+	privileged reg746 (spr646): undefined
+	privileged reg747 (spr647): undefined
+	privileged reg748 (spr648): undefined
+	privileged reg749 (spr649): undefined
+	privileged reg750 (spr650): undefined
+	privileged reg751 (spr651): undefined
+	privileged reg752 (spr652): undefined
+	privileged reg753 (spr653): undefined
+	privileged reg754 (spr654): undefined
+	privileged reg755 (spr655): undefined
+	privileged reg756 (spr656): undefined
+	privileged reg757 (spr657): undefined
+	privileged reg758 (spr658): undefined
+	privileged reg759 (spr659): undefined
+	privileged reg760 (spr660): undefined
+	privileged reg761 (spr661): undefined
+	privileged reg762 (spr662): undefined
+	privileged reg763 (spr663): undefined
+	privileged reg764 (spr664): undefined
+	privileged reg765 (spr665): undefined
+	privileged reg766 (spr666): undefined
+	privileged reg767 (spr667): undefined
+	privileged reg768 (spr668): undefined
+	privileged reg769 (spr669): undefined
+	privileged reg770 (spr670): undefined
+	privileged reg771 (spr671): undefined
+	privileged reg772 (spr672): undefined
+	privileged reg773 (spr673): undefined
+	privileged reg774 (spr674): undefined
+	privileged reg775 (spr675): undefined
+	privileged reg776 (spr676): undefined
+	privileged reg777 (spr677): undefined
+	privileged reg778 (spr678): undefined
+	privileged reg779 (spr679): undefined
+	privileged reg780 (spr680): undefined
+	privileged reg781 (spr681): undefined
+	privileged reg782 (spr682): undefined
+	privileged reg783 (spr683): undefined
+	privileged reg784 (spr684): undefined
+	privileged reg785 (spr685): undefined
+	privileged reg786 (spr686): undefined
+	privileged reg787 (spr687): undefined
+	privileged reg788 (spr688): undefined
+	privileged reg789 (spr689): undefined
+	privileged reg790 (spr690): undefined
+	privileged reg791 (spr691): undefined
+	privileged reg792 (spr692): undefined
+	privileged reg793 (spr693): undefined
+	privileged reg794 (spr694): undefined
+	privileged reg795 (spr695): undefined
+	privileged reg796 (spr696): undefined
+	privileged reg797 (spr697): undefined
+	privileged reg798 (spr698): undefined
+	privileged reg799 (spr699): undefined
+	privileged reg800 (spr700): undefined
+	privileged reg801 (spr701): undefined
+	privileged reg802 (spr702): undefined
+	privileged reg803 (spr703): undefined
+	privileged reg804 (spr704): undefined
+	privileged reg805 (spr705): undefined
+	privileged reg806 (spr706): undefined
+	privileged reg807 (spr707): undefined
+	privileged reg808 (spr708): undefined
+	privileged reg809 (spr709): undefined
+	privileged reg810 (spr710): undefined
+	privileged reg811 (spr711): undefined
+	privileged reg812 (spr712): undefined
+	privileged reg813 (spr713): undefined
+	privileged reg814 (spr714): undefined
+	privileged reg815 (spr715): undefined
+	privileged reg816 (spr716): undefined
+	privileged reg817 (spr717): undefined
+	privileged reg818 (spr718): undefined
+	privileged reg819 (spr719): undefined
+	privileged reg820 (spr720): undefined
+	privileged reg821 (spr721): undefined
+	privileged reg822 (spr722): undefined
+	privileged reg823 (spr723): undefined
+	privileged reg824 (spr724): undefined
+	privileged reg825 (spr725): undefined
+	privileged reg826 (spr726): undefined
+	privileged reg827 (spr727): undefined
+	privileged reg828 (spr728): undefined
+	privileged reg829 (spr729): undefined
+	privileged reg830 (spr730): undefined
+	privileged reg831 (spr731): undefined
+	privileged reg832 (spr732): undefined
+	privileged reg833 (spr733): undefined
+	privileged reg834 (spr734): undefined
+	privileged reg835 (spr735): undefined
+	privileged reg836 (spr736): undefined
+	privileged reg837 (spr737): undefined
+	privileged reg838 (spr738): undefined
+	privileged reg839 (spr739): undefined
+	privileged reg840 (spr740): undefined
+	privileged reg841 (spr741): undefined
+	privileged reg842 (spr742): undefined
+	privileged reg843 (spr743): undefined
+	privileged reg844 (spr744): undefined
+	privileged reg845 (spr745): undefined
+	privileged reg846 (spr746): undefined
+	privileged reg847 (spr747): undefined
+	privileged reg848 (spr748): undefined
+	privileged reg849 (spr749): undefined
+	privileged reg850 (spr750): undefined
+	privileged reg851 (spr751): undefined
+	privileged reg852 (spr752): undefined
+	privileged reg853 (spr753): undefined
+	privileged reg854 (spr754): undefined
+	privileged reg855 (spr755): undefined
+	privileged reg856 (spr756): undefined
+	privileged reg857 (spr757): undefined
+	privileged reg858 (spr758): undefined
+	privileged reg859 (spr759): undefined
+	privileged reg860 (spr760): undefined
+	privileged reg861 (spr761): undefined
+	privileged reg862 (spr762): undefined
+	privileged reg863 (spr763): undefined
+	privileged reg864 (spr764): undefined
+	privileged reg865 (spr765): undefined
+	privileged reg866 (spr766): undefined
+	privileged reg867 (spr767): undefined
+	privileged reg868 (spr768): undefined
+	privileged reg869 (spr769): undefined
+	privileged reg870 (spr770): undefined
+	privileged reg871 (spr771): undefined
+	privileged reg872 (spr772): undefined
+	privileged reg873 (spr773): undefined
+	privileged reg874 (spr774): undefined
+	privileged reg875 (spr775): undefined
+	privileged reg876 (spr776): undefined
+	privileged reg877 (spr777): undefined
+	privileged reg878 (spr778): undefined
+	privileged reg879 (spr779): undefined
+	privileged reg880 (spr780): undefined
+	privileged reg881 (spr781): undefined
+	privileged reg882 (spr782): undefined
+	privileged reg883 (spr783): undefined
+	privileged reg884 (spr784): undefined
+	privileged reg885 (spr785): undefined
+	privileged reg886 (spr786): undefined
+	privileged reg887 (spr787): undefined
+	privileged reg888 (spr788): undefined
+	privileged reg889 (spr789): undefined
+	privileged reg890 (spr790): undefined
+	privileged reg891 (spr791): undefined
+	privileged reg892 (spr792): undefined
+	privileged reg893 (spr793): undefined
+	privileged reg894 (spr794): undefined
+	privileged reg895 (spr795): undefined
+	privileged reg896 (spr796): undefined
+	privileged reg897 (spr797): undefined
+	privileged reg898 (spr798): undefined
+	privileged reg899 (spr799): undefined
+	privileged reg900 (spr800): undefined
+	privileged reg901 (spr801): undefined
+	privileged reg902 (spr802): undefined
+	privileged reg903 (spr803): undefined
+	privileged reg904 (spr804): undefined
+	privileged reg905 (spr805): undefined
+	privileged reg906 (spr806): undefined
+	privileged reg907 (spr807): undefined
+	privileged reg908 (spr808): undefined
+	privileged reg909 (spr809): undefined
+	privileged reg910 (spr810): undefined
+	privileged reg911 (spr811): undefined
+	privileged reg912 (spr812): undefined
+	privileged reg913 (spr813): undefined
+	privileged reg914 (spr814): undefined
+	privileged reg915 (spr815): undefined
+	privileged reg916 (spr816): undefined
+	privileged reg917 (spr817): undefined
+	privileged reg918 (spr818): undefined
+	privileged reg919 (spr819): undefined
+	privileged reg920 (spr820): undefined
+	privileged reg921 (spr821): undefined
+	privileged reg922 (spr822): undefined
+	privileged reg923 (spr823): undefined
+	privileged reg924 (spr824): undefined
+	privileged reg925 (spr825): undefined
+	privileged reg926 (spr826): undefined
+	privileged reg927 (spr827): undefined
+	privileged reg928 (spr828): undefined
+	privileged reg929 (spr829): undefined
+	privileged reg930 (spr830): undefined
+	privileged reg931 (spr831): undefined
+	privileged reg932 (spr832): undefined
+	privileged reg933 (spr833): undefined
+	privileged reg934 (spr834): undefined
+	privileged reg935 (spr835): undefined
+	privileged reg936 (spr836): undefined
+	privileged reg937 (spr837): undefined
+	privileged reg938 (spr838): undefined
+	privileged reg939 (spr839): undefined
+	privileged reg940 (spr840): undefined
+	privileged reg941 (spr841): undefined
+	privileged reg942 (spr842): undefined
+	privileged reg943 (spr843): undefined
+	privileged reg944 (spr844): undefined
+	privileged reg945 (spr845): undefined
+	privileged reg946 (spr846): undefined
+	privileged reg947 (spr847): undefined
+	privileged reg948 (spr848): undefined
+	privileged reg949 (spr849): undefined
+	privileged reg950 (spr850): undefined
+	privileged reg951 (spr851): undefined
+	privileged reg952 (spr852): undefined
+	privileged reg953 (spr853): undefined
+	privileged reg954 (spr854): undefined
+	privileged reg955 (spr855): undefined
+	privileged reg956 (spr856): undefined
+	privileged reg957 (spr857): undefined
+	privileged reg958 (spr858): undefined
+	privileged reg959 (spr859): undefined
+	privileged reg960 (spr860): undefined
+	privileged reg961 (spr861): undefined
+	privileged reg962 (spr862): undefined
+	privileged reg963 (spr863): undefined
+	privileged reg964 (spr864): undefined
+	privileged reg965 (spr865): undefined
+	privileged reg966 (spr866): undefined
+	privileged reg967 (spr867): undefined
+	privileged reg968 (spr868): undefined
+	privileged reg969 (spr869): undefined
+	privileged reg970 (spr870): undefined
+	privileged reg971 (spr871): undefined
+	privileged reg972 (spr872): undefined
+	privileged reg973 (spr873): undefined
+	privileged reg974 (spr874): undefined
+	privileged reg975 (spr875): undefined
+	privileged reg976 (spr876): undefined
+	privileged reg977 (spr877): undefined
+	privileged reg978 (spr878): undefined
+	privileged reg979 (spr879): undefined
+	privileged reg980 (spr880): undefined
+	privileged reg981 (spr881): undefined
+	privileged reg982 (spr882): undefined
+	privileged reg983 (spr883): undefined
+	privileged reg984 (spr884): undefined
+	privileged reg985 (spr885): undefined
+	privileged reg986 (spr886): undefined
+	privileged reg987 (spr887): undefined
+	privileged reg988 (spr888): undefined
+	privileged reg989 (spr889): undefined
+	privileged reg990 (spr890): undefined
+	privileged reg991 (spr891): undefined
+	privileged reg992 (spr892): undefined
+	privileged reg993 (spr893): undefined
+	privileged reg994 (spr894): undefined
+	privileged reg995 (spr895): undefined
+	privileged reg996 (spr896): undefined
+	privileged reg997 (spr897): undefined
+	privileged reg998 (spr898): undefined
+	privileged reg999 (spr899): undefined
+	vector reg1124 (vr0): undefined
+	vector reg1125 (vr1): undefined
+	vector reg1126 (vr2): undefined
+	vector reg1127 (vr3): undefined
+	vector reg1128 (vr4): undefined
+	vector reg1129 (vr5): undefined
+	vector reg1130 (vr6): undefined
+	vector reg1131 (vr7): undefined
+	vector reg1132 (vr8): undefined
+	vector reg1133 (vr9): undefined
+	vector reg1134 (vr10): undefined
+	vector reg1135 (vr11): undefined
+	vector reg1136 (vr12): undefined
+	vector reg1137 (vr13): undefined
+	vector reg1138 (vr14): undefined
+	vector reg1139 (vr15): undefined
+	vector reg1140 (vr16): undefined
+	vector reg1141 (vr17): undefined
+	vector reg1142 (vr18): undefined
+	vector reg1143 (vr19): undefined
+	vector reg1144 (vr20): undefined
+	vector reg1145 (vr21): undefined
+	vector reg1146 (vr22): undefined
+	vector reg1147 (vr23): undefined
+	vector reg1148 (vr24): undefined
+	vector reg1149 (vr25): undefined
+	vector reg1150 (vr26): undefined
+	vector reg1151 (vr27): undefined
+	vector reg1152 (vr28): undefined
+	vector reg1153 (vr29): undefined
+	vector reg1154 (vr30): undefined
+	vector reg1155 (vr31): undefined
+EOF
+
+# EM_S390 (ELFCLASS32) (function bar 0x4004d8)
+# Note. Only in .eh_frame, there is no .debug_frame.
+# Same as PPC above but with -m31.
+testfiles testfiles390
+testrun_compare ${abs_builddir}/addrcfi -e testfiles390 0x4004d8 <<\EOF
+.eh_frame has 0x4004d8 => [0x4004d8, 0x4004e8):
+	return address in reg14
+	CFA location expression: bregx(15,96)
+	integer reg0 (%r0): undefined
+	integer reg1 (%r1): undefined
+	integer reg2 (%r2): undefined
+	integer reg3 (%r3): undefined
+	integer reg4 (%r4): undefined
+	integer reg5 (%r5): undefined
+	integer reg6 (%r6): same_value
+	integer reg7 (%r7): same_value
+	integer reg8 (%r8): same_value
+	integer reg9 (%r9): same_value
+	integer reg10 (%r10): same_value
+	integer reg11 (%r11): same_value
+	integer reg12 (%r12): same_value
+	integer reg13 (%r13): same_value
+	integer reg14 (%r14): same_value
+	integer reg15 (%r15): same_value
+	FPU reg16 (%f0): undefined
+	FPU reg17 (%f2): undefined
+	FPU reg18 (%f4): undefined
+	FPU reg19 (%f6): undefined
+	FPU reg20 (%f1): undefined
+	FPU reg21 (%f3): undefined
+	FPU reg22 (%f5): undefined
+	FPU reg23 (%f7): undefined
+	FPU reg24 (%f8): same_value
+	FPU reg25 (%f10): same_value
+	FPU reg26 (%f12): same_value
+	FPU reg27 (%f14): same_value
+	FPU reg28 (%f9): same_value
+	FPU reg29 (%f11): same_value
+	FPU reg30 (%f13): same_value
+	FPU reg31 (%f15): same_value
+	control reg32 (%c0): undefined
+	control reg33 (%c1): undefined
+	control reg34 (%c2): undefined
+	control reg35 (%c3): undefined
+	control reg36 (%c4): undefined
+	control reg37 (%c5): undefined
+	control reg38 (%c6): undefined
+	control reg39 (%c7): undefined
+	control reg40 (%c8): undefined
+	control reg41 (%c9): undefined
+	control reg42 (%c10): undefined
+	control reg43 (%c11): undefined
+	control reg44 (%c12): undefined
+	control reg45 (%c13): undefined
+	control reg46 (%c14): undefined
+	control reg47 (%c15): undefined
+	access reg48 (%a0): undefined
+	access reg49 (%a1): undefined
+	access reg50 (%a2): undefined
+	access reg51 (%a3): undefined
+	access reg52 (%a4): undefined
+	access reg53 (%a5): undefined
+	access reg54 (%a6): undefined
+	access reg55 (%a7): undefined
+	access reg56 (%a8): undefined
+	access reg57 (%a9): undefined
+	access reg58 (%a10): undefined
+	access reg59 (%a11): undefined
+	access reg60 (%a12): undefined
+	access reg61 (%a13): undefined
+	access reg62 (%a14): undefined
+	access reg63 (%a15): undefined
+	control reg64 (%pswm): undefined
+	control reg65 (%pswa): undefined
+handle_cfi no CFI (.debug_frame): no error
+EOF
+
+# EM_S390 (ELFCLASS64) (function bar 0x0000000080000510)
+# Note. Only in .eh_frame, there is no .debug_frame.
+# Same as s390 above but without -m31.
+testfiles testfiles390x
+testrun_compare ${abs_builddir}/addrcfi -e testfiles390x 0x0000000080000510 <<\EOF
+.eh_frame has 0x80000510 => [0x80000510, 0x80000524):
+	return address in reg14
+	CFA location expression: bregx(15,160)
+	integer reg0 (%r0): undefined
+	integer reg1 (%r1): undefined
+	integer reg2 (%r2): undefined
+	integer reg3 (%r3): undefined
+	integer reg4 (%r4): undefined
+	integer reg5 (%r5): undefined
+	integer reg6 (%r6): same_value
+	integer reg7 (%r7): same_value
+	integer reg8 (%r8): same_value
+	integer reg9 (%r9): same_value
+	integer reg10 (%r10): same_value
+	integer reg11 (%r11): same_value
+	integer reg12 (%r12): same_value
+	integer reg13 (%r13): same_value
+	integer reg14 (%r14): same_value
+	integer reg15 (%r15): same_value
+	FPU reg16 (%f0): undefined
+	FPU reg17 (%f2): undefined
+	FPU reg18 (%f4): undefined
+	FPU reg19 (%f6): undefined
+	FPU reg20 (%f1): undefined
+	FPU reg21 (%f3): undefined
+	FPU reg22 (%f5): undefined
+	FPU reg23 (%f7): undefined
+	FPU reg24 (%f8): same_value
+	FPU reg25 (%f10): same_value
+	FPU reg26 (%f12): same_value
+	FPU reg27 (%f14): same_value
+	FPU reg28 (%f9): same_value
+	FPU reg29 (%f11): same_value
+	FPU reg30 (%f13): same_value
+	FPU reg31 (%f15): same_value
+	control reg32 (%c0): undefined
+	control reg33 (%c1): undefined
+	control reg34 (%c2): undefined
+	control reg35 (%c3): undefined
+	control reg36 (%c4): undefined
+	control reg37 (%c5): undefined
+	control reg38 (%c6): undefined
+	control reg39 (%c7): undefined
+	control reg40 (%c8): undefined
+	control reg41 (%c9): undefined
+	control reg42 (%c10): undefined
+	control reg43 (%c11): undefined
+	control reg44 (%c12): undefined
+	control reg45 (%c13): undefined
+	control reg46 (%c14): undefined
+	control reg47 (%c15): undefined
+	access reg48 (%a0): undefined
+	access reg49 (%a1): undefined
+	access reg50 (%a2): undefined
+	access reg51 (%a3): undefined
+	access reg52 (%a4): undefined
+	access reg53 (%a5): undefined
+	access reg54 (%a6): undefined
+	access reg55 (%a7): undefined
+	access reg56 (%a8): undefined
+	access reg57 (%a9): undefined
+	access reg58 (%a10): undefined
+	access reg59 (%a11): undefined
+	access reg60 (%a12): undefined
+	access reg61 (%a13): undefined
+	access reg62 (%a14): undefined
+	access reg63 (%a15): undefined
+	control reg64 (%pswm): undefined
+	control reg65 (%pswa): undefined
+handle_cfi no CFI (.debug_frame): no error
+EOF
+
+# EM_ARM (function bar 0x00008510)
+# Note. Only in .debug_frame, the .eh_frame is actually empty.
+# Same as s390 and ppc above.
+testfiles testfilearm
+testrun_compare ${abs_builddir}/addrcfi -e testfilearm 0x00008510 <<\EOF
+dwarf_cfi_addrframe (.eh_frame): no matching address range
+.debug_frame has 0x8510 => [0x8510, 0x8524):
+	return address in reg14
+	CFA location expression: bregx(13)
+	integer reg0 (r0): undefined
+	integer reg1 (r1): undefined
+	integer reg2 (r2): undefined
+	integer reg3 (r3): undefined
+	integer reg4 (r4): same_value
+	integer reg5 (r5): same_value
+	integer reg6 (r6): same_value
+	integer reg7 (r7): same_value
+	integer reg8 (r8): same_value
+	integer reg9 (r9): undefined
+	integer reg10 (r10): same_value
+	integer reg11 (r11): same_value
+	integer reg12 (r12): undefined
+	integer reg13 (sp): location expression: call_frame_cfa stack_value
+	integer reg14 (lr): same_value
+	integer reg15 (pc): location expression: regx(14)
+	FPA reg16 (f0): undefined
+	FPA reg17 (f1): undefined
+	FPA reg18 (f2): undefined
+	FPA reg19 (f3): undefined
+	FPA reg20 (f4): undefined
+	FPA reg21 (f5): undefined
+	FPA reg22 (f6): undefined
+	FPA reg23 (f7): undefined
+	FPA reg96 (f0): undefined
+	FPA reg97 (f1): undefined
+	FPA reg98 (f2): undefined
+	FPA reg99 (f3): undefined
+	FPA reg100 (f4): undefined
+	FPA reg101 (f5): undefined
+	FPA reg102 (f6): undefined
+	FPA reg103 (f7): undefined
+	integer reg128 (spsr): undefined
+	VFP reg256 (d0): undefined
+	VFP reg257 (d1): undefined
+	VFP reg258 (d2): undefined
+	VFP reg259 (d3): undefined
+	VFP reg260 (d4): undefined
+	VFP reg261 (d5): undefined
+	VFP reg262 (d6): undefined
+	VFP reg263 (d7): undefined
+	VFP reg264 (d8): same_value
+	VFP reg265 (d9): same_value
+	VFP reg266 (d10): same_value
+	VFP reg267 (d11): same_value
+	VFP reg268 (d12): same_value
+	VFP reg269 (d13): same_value
+	VFP reg270 (d14): same_value
+	VFP reg271 (d15): same_value
+	VFP reg272 (d16): undefined
+	VFP reg273 (d17): undefined
+	VFP reg274 (d18): undefined
+	VFP reg275 (d19): undefined
+	VFP reg276 (d20): undefined
+	VFP reg277 (d21): undefined
+	VFP reg278 (d22): undefined
+	VFP reg279 (d23): undefined
+	VFP reg280 (d24): undefined
+	VFP reg281 (d25): undefined
+	VFP reg282 (d26): undefined
+	VFP reg283 (d27): undefined
+	VFP reg284 (d28): undefined
+	VFP reg285 (d29): undefined
+	VFP reg286 (d30): undefined
+	VFP reg287 (d31): undefined
+EOF
+
+# EM_AARCH64 (function bar 0x400550)
+# Same as arm, 390 and ppc above.
+# Note missing coverage in .eh_frame.
+testfiles testfileaarch64
+testrun_compare ${abs_builddir}/addrcfi -e testfileaarch64 0x400550 <<\EOF
+dwarf_cfi_addrframe (.eh_frame): no matching address range
+.debug_frame has 0x400550 => [0x400550, 0x400568):
+	return address in reg30
+	CFA location expression: bregx(31)
+	integer reg0 (x0): undefined
+	integer reg1 (x1): undefined
+	integer reg2 (x2): undefined
+	integer reg3 (x3): undefined
+	integer reg4 (x4): undefined
+	integer reg5 (x5): undefined
+	integer reg6 (x6): undefined
+	integer reg7 (x7): undefined
+	integer reg8 (x8): undefined
+	integer reg9 (x9): undefined
+	integer reg10 (x10): undefined
+	integer reg11 (x11): undefined
+	integer reg12 (x12): undefined
+	integer reg13 (x13): undefined
+	integer reg14 (x14): undefined
+	integer reg15 (x15): undefined
+	integer reg16 (x16): undefined
+	integer reg17 (x17): undefined
+	integer reg18 (x18): undefined
+	integer reg19 (x19): same_value
+	integer reg20 (x20): same_value
+	integer reg21 (x21): same_value
+	integer reg22 (x22): same_value
+	integer reg23 (x23): same_value
+	integer reg24 (x24): same_value
+	integer reg25 (x25): same_value
+	integer reg26 (x26): same_value
+	integer reg27 (x27): same_value
+	integer reg28 (x28): same_value
+	integer reg29 (x29): same_value
+	integer reg30 (x30): same_value
+	integer reg31 (sp): location expression: call_frame_cfa stack_value
+	integer reg33 (elr): undefined
+	FP/SIMD reg64 (v0): undefined
+	FP/SIMD reg65 (v1): undefined
+	FP/SIMD reg66 (v2): undefined
+	FP/SIMD reg67 (v3): undefined
+	FP/SIMD reg68 (v4): undefined
+	FP/SIMD reg69 (v5): undefined
+	FP/SIMD reg70 (v6): undefined
+	FP/SIMD reg71 (v7): undefined
+	FP/SIMD reg72 (v8): same_value
+	FP/SIMD reg73 (v9): same_value
+	FP/SIMD reg74 (v10): same_value
+	FP/SIMD reg75 (v11): same_value
+	FP/SIMD reg76 (v12): same_value
+	FP/SIMD reg77 (v13): same_value
+	FP/SIMD reg78 (v14): same_value
+	FP/SIMD reg79 (v15): same_value
+	FP/SIMD reg80 (v16): undefined
+	FP/SIMD reg81 (v17): undefined
+	FP/SIMD reg82 (v18): undefined
+	FP/SIMD reg83 (v19): undefined
+	FP/SIMD reg84 (v20): undefined
+	FP/SIMD reg85 (v21): undefined
+	FP/SIMD reg86 (v22): undefined
+	FP/SIMD reg87 (v23): undefined
+	FP/SIMD reg88 (v24): undefined
+	FP/SIMD reg89 (v25): undefined
+	FP/SIMD reg90 (v26): undefined
+	FP/SIMD reg91 (v27): undefined
+	FP/SIMD reg92 (v28): undefined
+	FP/SIMD reg93 (v29): undefined
+	FP/SIMD reg94 (v30): undefined
+	FP/SIMD reg95 (v31): undefined
+EOF
+
+# EM_X86_64/ELFCLASS32 (function bar 0x00400390)
+#
+# Note. Only in .eh_frame, there is no .debug_frame.
+# Same as PPC above but with -mx32.
+testfiles testfile-x32
+testrun_compare ${abs_builddir}/addrcfi -e testfile-x32 0x00400390 <<\EOF
+.eh_frame has 0x400390 => [0x400390, 0x40039c):
+	return address in reg16
+	CFA location expression: bregx(7,8)
+	integer reg0 (%rax): same_value
+	integer reg1 (%rdx): undefined
+	integer reg2 (%rcx): undefined
+	integer reg3 (%rbx): undefined
+	integer reg4 (%rsi): undefined
+	integer reg5 (%rdi): undefined
+	integer reg6 (%rbp): same_value
+	integer reg7 (%rsp): location expression: call_frame_cfa stack_value
+	integer reg8 (%r8): undefined
+	integer reg9 (%r9): undefined
+	integer reg10 (%r10): undefined
+	integer reg11 (%r11): undefined
+	integer reg12 (%r12): same_value
+	integer reg13 (%r13): same_value
+	integer reg14 (%r14): same_value
+	integer reg15 (%r15): same_value
+	integer reg16 (%rip): location expression: call_frame_cfa plus_uconst(-8)
+	SSE reg17 (%xmm0): undefined
+	SSE reg18 (%xmm1): undefined
+	SSE reg19 (%xmm2): undefined
+	SSE reg20 (%xmm3): undefined
+	SSE reg21 (%xmm4): undefined
+	SSE reg22 (%xmm5): undefined
+	SSE reg23 (%xmm6): undefined
+	SSE reg24 (%xmm7): undefined
+	SSE reg25 (%xmm8): undefined
+	SSE reg26 (%xmm9): undefined
+	SSE reg27 (%xmm10): undefined
+	SSE reg28 (%xmm11): undefined
+	SSE reg29 (%xmm12): undefined
+	SSE reg30 (%xmm13): undefined
+	SSE reg31 (%xmm14): undefined
+	SSE reg32 (%xmm15): undefined
+	x87 reg33 (%st0): undefined
+	x87 reg34 (%st1): undefined
+	x87 reg35 (%st2): undefined
+	x87 reg36 (%st3): undefined
+	x87 reg37 (%st4): undefined
+	x87 reg38 (%st5): undefined
+	x87 reg39 (%st6): undefined
+	x87 reg40 (%st7): undefined
+	MMX reg41 (%mm0): undefined
+	MMX reg42 (%mm1): undefined
+	MMX reg43 (%mm2): undefined
+	MMX reg44 (%mm3): undefined
+	MMX reg45 (%mm4): undefined
+	MMX reg46 (%mm5): undefined
+	MMX reg47 (%mm6): undefined
+	MMX reg48 (%mm7): undefined
+	integer reg49 (%rflags): undefined
+	segment reg50 (%es): undefined
+	segment reg51 (%cs): undefined
+	segment reg52 (%ss): undefined
+	segment reg53 (%ds): undefined
+	segment reg54 (%fs): undefined
+	segment reg55 (%gs): undefined
+	segment reg58 (%fs.base): undefined
+	segment reg59 (%gs.base): undefined
+	control reg62 (%tr): undefined
+	control reg63 (%ldtr): undefined
+	control reg64 (%mxcsr): undefined
+	control reg65 (%fcw): undefined
+	control reg66 (%fsw): undefined
+handle_cfi no CFI (.debug_frame): no error
+EOF
+
+# EM_CSKY (function bar 0x8440)
+testfiles testfilecsky
+testrun_compare ${abs_builddir}/addrcfi -e testfilecsky 0x8440 <<\EOF
+dwarf_cfi_addrframe (.eh_frame): no matching address range
+.debug_frame has 0x8440 => [0x8440, 0x844a):
+	return address in reg15
+	CFA location expression: bregx(14)
+	integer reg0 (r0): undefined
+	integer reg1 (r1): undefined
+	integer reg2 (r2): undefined
+	integer reg3 (r3): undefined
+	integer reg4 (r4): same_value
+	integer reg5 (r5): same_value
+	integer reg6 (r6): same_value
+	integer reg7 (r7): same_value
+	integer reg8 (r8): same_value
+	integer reg9 (r9): same_value
+	integer reg10 (r10): same_value
+	integer reg11 (r11): same_value
+	integer reg12 (r12): undefined
+	integer reg13 (r13): undefined
+	integer reg14 (sp): location expression: call_frame_cfa stack_value
+	integer reg15 (lr): same_value
+	integer reg16 (r16): same_value
+	integer reg17 (r17): same_value
+	integer reg18 (r18): undefined
+	integer reg19 (r19): undefined
+	integer reg20 (r20): undefined
+	integer reg21 (r21): undefined
+	integer reg22 (r22): undefined
+	integer reg23 (r23): undefined
+	integer reg24 (r24): undefined
+	integer reg25 (r25): undefined
+	integer reg26 (r26): undefined
+	integer reg27 (r27): undefined
+	integer reg28 (r28): undefined
+	integer reg29 (r29): undefined
+	integer reg30 (r30): undefined
+	integer reg31 (tls): undefined
+	integer reg36 (hi): undefined
+	integer reg37 (lo): undefined
+EOF
diff --git a/tests/run-addrname-test.sh b/tests/run-addrname-test.sh
new file mode 100755
index 0000000..90e19df
--- /dev/null
+++ b/tests/run-addrname-test.sh
@@ -0,0 +1,360 @@
+#! /bin/sh
+# Copyright (C) 2007, 2008 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile34 testfile38 testfile41 testfile49
+
+testrun_compare ${abs_top_builddir}/src/addr2line -f -e testfile34 \
+				 0x08048074 0x08048075 0x08048076 \
+				 0x08049078 0x08048080 0x08049080 <<\EOF
+foo
+??:0
+bar
+??:0
+_etext
+??:0
+data1
+??:0
+??
+??:0
+_end
+??:0
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile38 0x02 0x10a 0x211 0x31a <<\EOF
+t1_global_outer+0x2
+??:0
+t2_global_symbol+0x2
+??:0
+t3_global_after_0+0x1
+??:0
+(.text)+0x31a
+??:0
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile41 0x1 0x104 <<\EOF
+small_global_at_large_global+0x1
+??:0
+small_global_first_at_large_global+0x1
+??:0
+EOF
+
+testfiles testfile12 testfile14
+tempfiles testmaps
+
+cat > testmaps <<EOF
+00400000-00401000 r-xp 00000000 fd:01 4006812                            `pwd`/testfile14
+00500000-00501000 rw-p 00000000 fd:01 4006812                            `pwd`/testfile14
+01000000-01001000 r-xp 00000000 fd:01 1234567				 `pwd`/testfile12
+01100000-01011000 rw-p 00000000 fd:01 1234567				 `pwd`/testfile12
+2aaaaaaab000-2aaaaaaad000 rw-p 2aaaaaaab000 00:00 0 
+2aaaaaae2000-2aaaaaae3000 rw-p 2aaaaaae2000 00:00 0 
+7fff61068000-7fff6107d000 rw-p 7ffffffea000 00:00 0                      [stack]
+7fff611fe000-7fff61200000 r-xp 7fff611fe000 00:00 0                      [vdso]
+ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -M testmaps 0x40047c 0x10009db <<\EOF
+caller+0x14
+/home/drepper/local/elfutils-build/20050425/v.c:11
+foo+0xb
+/home/drepper/local/elfutils-build/20030710/u.c:5
+EOF
+
+#	.section .text
+#	nop #0
+#sizeless_foo:
+#	nop #1
+#	nop #2
+#sized_bar:
+#	nop #3
+#	nop #4
+#sizeless_baz:
+#	nop #5
+#	nop #6
+#	.size sized_bar, . - sized_bar
+#	nop #7
+#	nop #8
+#sizeless_x:
+#	nop #9
+#	.org 0x100
+#	nop #0
+#	.globl global_outer
+#global_outer:
+#	nop #1
+#	nop #2
+#	.globl global_in_global
+#global_in_global:
+#	nop #3
+#	nop #4
+#	.size global_in_global, . - global_in_global
+#local_in_global:
+#	nop #5 
+#	nop #6 
+#	.size local_in_global, . - local_in_global
+#	nop #7
+#	nop #8
+#.Lsizeless1:
+#	nop #9
+#	nop #10
+#	.size global_outer, . - global_outer
+#	nop #11
+#	.org 0x200
+#	nop #0
+#local_outer:
+#	nop #1
+#	nop #2
+#	.globl global_in_local
+#global_in_local:
+#	nop #3
+#	nop #4
+#	.size global_in_local, . - global_in_local
+#local_in_local:
+#	nop #5 
+#	nop #6 
+#	.size local_in_local, . - local_in_local
+#	nop #7
+#	nop #8
+#.Lsizeless2:
+#	nop #9
+#	nop #10
+#	.size local_outer, . - local_outer
+#	nop #11
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile49 \
+    		0 1 2 3 4 5 6 7 8 9 \
+		0x100 0x101 0x102 0x103 0x104 0x105 \
+		0x106 0x107 0x108 0x109 0x10a 0x10b \
+		0x200 0x201 0x202 0x203 0x204 0x205 \
+		0x206 0x207 0x208 0x209 0x20a 0x20b <<\EOF
+(.text)+0
+??:0
+sizeless_foo
+??:0
+sizeless_foo+0x1
+??:0
+sized_bar
+??:0
+sized_bar+0x1
+??:0
+sized_bar+0x2
+??:0
+sized_bar+0x3
+??:0
+(.text)+0x7
+??:0
+(.text)+0x8
+??:0
+sizeless_x
+??:0
+sizeless_x+0xf7
+??:0
+global_outer
+??:0
+global_outer+0x1
+??:0
+global_in_global
+??:0
+global_in_global+0x1
+??:0
+global_outer+0x4
+??:0
+global_outer+0x5
+??:0
+global_outer+0x6
+??:0
+global_outer+0x7
+??:0
+global_outer+0x8
+??:0
+global_outer+0x9
+??:0
+(.text)+0x10b
+??:0
+(.text)+0x200
+??:0
+local_outer
+??:0
+local_outer+0x1
+??:0
+global_in_local
+??:0
+global_in_local+0x1
+??:0
+local_in_local
+??:0
+local_in_local+0x1
+??:0
+local_outer+0x6
+??:0
+local_outer+0x7
+??:0
+local_outer+0x8
+??:0
+local_outer+0x9
+??:0
+(.text)+0x20b
+??:0
+EOF
+
+#	.macro global label size
+#\label:	.globl \label
+#	.size \label, \size
+#	.endm
+#	.macro weak label size
+#\label:	.weak \label
+#	.size \label, \size
+#	.endm
+#	.macro local label size
+#\label:	.size \label, \size
+#	.endm
+#	.macro offset val
+#	.ifne (. - _start) - \val
+#	.err
+#	.endif
+#	.byte \val
+#	.endm
+#
+#_start:
+#	offset 0
+#
+#	local glocal, 1
+#	weak gweak, 1
+#	global gglobal1, 2
+#	global gglobal2, 1
+#	global gglobal3, 1
+#	offset 1
+#	/* Symbols end here.  */
+#	offset 2
+#	/* gglobal1 ends here.  */
+#	offset 3
+#
+#	local g0local, 0
+#	weak g0weak, 0
+#	global g0global1, 0
+#	global g0global2, 0
+#	offset 4
+#
+#	local wlocal, 1
+#	weak wweak1, 2
+#	weak wweak2, 1
+#	weak wweak3, 1
+#	offset 5
+#	/* Symbols end here.  */
+#	offset 6
+#	/* wweak1 ends here.  */
+#	offset 7
+#
+#	local w0local, 0
+#	weak w0weak1, 0
+#	weak w0weak2, 0
+#	offset 8
+#
+#	local llocal1, 2
+#	local llocal2, 1
+#	local llocal3, 1
+#	offset 9
+#	/* Symbols end here.  */
+#	offset 10
+#	/* llocal1 ends here.  */
+#	offset 11
+#
+#	local l0local1, 0
+#	local l0local2, 0
+#	offset 12
+testfiles testfile64
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile64 1 4 5 8 9 c <<\EOF
+gglobal2
+??:0
+g0global2
+??:0
+wweak2
+??:0
+w0weak2
+??:0
+llocal2
+??:0
+l0local2
+??:0
+EOF
+
+testfiles testfile65
+testrun_compare ${abs_top_builddir}/src/addr2line -S --core=testfile65 0x7fff94bffa30 <<\EOF
+__vdso_time
+??:0
+EOF
+
+#	.section	".text"
+#	.globl _start
+#	.section	".opd","aw"
+#_start:	.quad	.L._start,.TOC.@tocbase
+#	.previous
+#	.type	_start, @function
+#.L._start:
+#	.byte	0x7d, 0x82, 0x10, 0x08
+#	.size	_start,.-.L._start
+testfiles testfile66 testfile66.core
+testrun_compare ${abs_top_builddir}/src/addr2line -x -e testfile66 _start 0x2d8 0x2db 0x2dc 0x103d0 0x103d3 0x103d4<<EOF
+_start (.text)
+??:0
+_start (.text)
+??:0
+_start+0x3 (.text)
+??:0
+()+0x2dc
+??:0
+_start (.opd)
+??:0
+_start+0x3 (.opd)
+??:0
+()+0x103d4
+??:0
+EOF
+testrun_compare ${abs_top_builddir}/src/addr2line -x -e testfile66 --core=testfile66.core _start 0x461b02d8 0x461c03d0<<\EOF
+_start (.text)
+??:0
+_start (.text)
+??:0
+_start (.opd)
+??:0
+EOF
+
+testfiles testfile69.core testfile69.so
+testrun_compare ${abs_top_builddir}/src/addr2line --core=./testfile69.core -S 0x7f0bc6a33535 0x7f0bc6a33546 <<\EOF
+libstatic+0x9
+??:0
+libglobal+0x9
+??:0
+EOF
+
+testfiles testfile70.exec testfile70.core
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile70.exec --core=testfile70.core 0x7ff2cfe9b6b5 <<\EOF
+main+0x9
+??:0
+EOF
+testrun_compare ${abs_top_builddir}/src/addr2line -S --core=testfile70.core -e testfile70.exec 0x7ff2cfe9b6b5 <<\EOF
+main+0x9
+??:0
+EOF
+
+testfiles test-core-lib.so test-core.core test-core.exec
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e test-core.exec --core=test-core.core 0x7f67f2aaf619 <<\EOF
+libfunc+0x9
+??:0
+EOF
+
+exit 0
diff --git a/tests/run-addrscopes.sh b/tests/run-addrscopes.sh
new file mode 100755
index 0000000..8f1bf0e
--- /dev/null
+++ b/tests/run-addrscopes.sh
@@ -0,0 +1,43 @@
+#! /bin/sh
+# Copyright (C) 2005, 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile22
+
+testrun_compare ${abs_builddir}/addrscopes -e testfile22 0x8048353 <<\EOF
+0x8048353:
+    tests/foo.c (0x11): 0x8048348 (tests/foo.c:5) .. 0x804837c (tests/foo.c:16)
+        global                        [    be]
+        function (0x2e): 0x8048348 (tests/foo.c:5) .. 0x8048359 (tests/foo.c:11)
+            local                         [    8f]
+EOF
+
+test_cleanup
+
+testfiles testfile24
+testrun_compare ${abs_builddir}/addrscopes -e testfile24 0x804834e <<\EOF
+0x804834e:
+    inline-test.c (0x11): 0x8048348 (/home/roland/build/stock-elfutils/inline-test.c:7) .. 0x8048360 (/home/roland/build/stock-elfutils/inline-test.c:16)
+        add (0x1d): 0x804834e (/home/roland/build/stock-elfutils/inline-test.c:3) .. 0x804834f
+            y                             [    9d]
+            x                             [    a2]
+            x (abstract)
+            y (abstract)
+EOF
+
+exit 0
diff --git a/tests/run-aggregate-size.sh b/tests/run-aggregate-size.sh
new file mode 100755
index 0000000..08d57bb
--- /dev/null
+++ b/tests/run-aggregate-size.sh
@@ -0,0 +1,113 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# char c;
+# int i;
+# long l;
+#
+# void *v;
+#
+# struct s
+# {
+#   char *a;
+#   int i;
+# } s;
+#
+# char ca[16];
+# int ia[32];
+# void *va[64];
+# struct s sa[8];
+
+# On x86_64 (LP64):
+# gcc -g -c -o testfile-sizes1.o sizes.c
+# clang -g -c -o testfile-sizes2.o sizes.c
+
+# const char c;
+# volatile int i;
+# const volatile long l;
+#
+# void * restrict v;
+#
+# struct s
+# {
+#   const char *a;
+#   volatile int i;
+# } s;
+#
+# const char ca[16];
+# volatile int ia[32];
+# const volatile void * const volatile restrict va[64];
+# struct s sa[8];
+# double d3d[3][4][5];
+#
+# typedef const int foo;
+# typedef volatile foo bar;
+# foo f;
+# bar b;
+#
+# gcc -std=c99 -g -c -o testfile-sizes3.o sizes.c
+
+# The file testfile-size4.o is hand-crafted.
+
+testfiles testfile-sizes1.o testfile-sizes2.o testfile-sizes3.o testfile-sizes4.o
+
+testrun_compare ${abs_builddir}/aggregate_size -e testfile-sizes1.o <<\EOF
+c size 1
+i size 4
+l size 8
+v size 8
+s size 16
+ca size 16
+ia size 128
+va size 512
+sa size 128
+EOF
+
+testrun_compare ${abs_builddir}/aggregate_size -e testfile-sizes2.o <<\EOF
+c size 1
+i size 4
+l size 8
+v size 8
+s size 16
+ca size 16
+ia size 128
+va size 512
+sa size 128
+EOF
+
+testrun_compare ${abs_builddir}/aggregate_size -e testfile-sizes3.o <<\EOF
+c size 1
+i size 4
+l size 8
+v size 8
+s size 16
+ca size 16
+ia size 128
+va size 512
+sa size 128
+d3d size 480
+f size 4
+b size 4
+EOF
+
+testrun_compare ${abs_builddir}/aggregate_size -e testfile-sizes4.o <<\EOF
+v size 257
+EOF
+
+exit 0
diff --git a/tests/run-all-dwarf-ranges.sh b/tests/run-all-dwarf-ranges.sh
new file mode 100755
index 0000000..61141cf
--- /dev/null
+++ b/tests/run-all-dwarf-ranges.sh
@@ -0,0 +1,243 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-dwarf-ranges.sh
+# Compiled with:
+# gcc -c -O2 -o testfile-ranges-hello.o -gsplit-dwarf -gdwarf-4 hello.c
+# gcc -c -O2 -o testfile-ranges-world.o -gsplit-dwarf -gdwarf-4 world.c
+# gcc -o testfilesplitranges4 -O2 \
+#        testfile-ranges-hello.o testfile-ranges-world.o
+# eu-strip -f testfilesplitranges4.debug testfilesplitranges4
+
+testfiles testfilesplitranges4.debug
+testfiles testfile-ranges-hello.dwo testfile-ranges-world.dwo
+
+testrun_compare ${abs_builddir}/all-dwarf-ranges testfilesplitranges4.debug <<\EOF
+die: hello.c (11)
+ 4004e0..4004ff
+ 4003e0..4003f7
+
+die: no_say (2e)
+ 4004f0..4004ff
+
+die: main (2e)
+ 4003e0..4003f7
+
+die: subject (1d)
+ 4003e3..4003ef
+
+die: subject (2e)
+ 4004e0..4004f0
+
+die: world.c (11)
+ 400500..400567
+
+die: no_main (2e)
+ 400550..400567
+
+die: no_subject (1d)
+ 400553..40055f
+
+die: say (2e)
+ 400500..400540
+
+die: happy (1d)
+ 40051c..400526
+ 400530..400534
+ 400535..40053f
+
+die: sad (1d)
+ 40051c..400526
+ 400535..40053f
+
+die: no_subject (2e)
+ 400540..400550
+
+EOF
+
+# Same with -gdwarf-5
+# gcc -c -O2 -o testfile-ranges-hello5.o -gsplit-dwarf -gdwarf-5 hello.c
+# gcc -c -O2 -o testfile-ranges-world5.o -gsplit-dwarf -gdwarf-5 world.c
+# gcc -o testfilesplitranges5 -O2 testfile-ranges-hello5.o testfile-ranges-world5.o
+# eu-strip -f testfilesplitranges5.debug testfilesplitranges5
+
+testfiles testfilesplitranges5.debug
+testfiles testfile-ranges-hello5.dwo testfile-ranges-world5.dwo
+
+testrun_compare ${abs_builddir}/all-dwarf-ranges testfilesplitranges5.debug <<\EOF
+die: hello.c (11)
+ 401150..40117a
+ 401050..401067
+
+die: no_say (2e)
+ 401160..40117a
+
+die: main (2e)
+ 401050..401067
+
+die: subject (1d)
+ 401053..40105f
+
+die: subject (2e)
+ 401150..401160
+
+die: world.c (11)
+ 401180..4011e7
+
+die: no_main (2e)
+ 4011d0..4011e7
+
+die: no_subject (1d)
+ 4011d3..4011df
+
+die: say (2e)
+ 401180..4011c0
+
+die: happy (1d)
+ 40119b..40119b
+ 40119c..4011a6
+ 4011b0..4011b4
+ 4011b5..4011bf
+
+die: sad (1d)
+ 40119b..40119b
+ 40119c..4011a6
+ 4011b4..4011b4
+ 4011b5..4011bf
+
+die: no_subject (2e)
+ 4011c0..4011d0
+
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+
+testrun_compare ${abs_builddir}/all-dwarf-ranges testfile-dwp-5 << EOF
+die: foo.cc (11)
+ 401190..401200
+
+die: foo (2e)
+ 4011c0..401200
+
+die: x_x (1d)
+ 4011cb..4011eb
+ 4011f8..401200
+
+die: <unknown> (b)
+ 4011cb..4011eb
+ 4011f8..401200
+
+die: x_x (2e)
+ 401190..4011bd
+
+die: <unknown> (b)
+ 401190..401190
+ 401192..4011bb
+
+die: bar.cc (11)
+ 401200..40121b
+
+die: bar (2e)
+ 401200..40121b
+
+die: main.cc (11)
+ 401020..4010a0
+
+die: main (2e)
+ 401020..4010a0
+
+die: fibonacci (1d)
+ 401030..401032
+ 401036..401060
+ 401099..4010a0
+
+die: fibonacci (1d)
+ 40103a..401060
+ 401099..4010a0
+
+die: <unknown> (b)
+ 40103a..401060
+ 401099..4010a0
+
+die: <unknown> (b)
+ 40103a..401044
+ 401050..401060
+
+die: <unknown> (b)
+ 401050..401053
+ 401056..401059
+
+EOF
+
+testrun_compare ${abs_builddir}/all-dwarf-ranges testfile-dwp-4 << EOF
+die: foo.cc (11)
+ 401190..401200
+
+die: foo (2e)
+ 4011c0..401200
+
+die: x_x (1d)
+ 4011cb..4011eb
+ 4011f8..401200
+
+die: <unknown> (b)
+ 4011cb..4011eb
+ 4011f8..401200
+
+die: x_x (2e)
+ 401190..4011bd
+
+die: bar.cc (11)
+ 401200..40121b
+
+die: bar (2e)
+ 401200..40121b
+
+die: main.cc (11)
+ 401020..4010a0
+
+die: main (2e)
+ 401020..4010a0
+
+die: fibonacci (1d)
+ 401030..401032
+ 401036..401060
+ 401099..4010a0
+
+die: fibonacci (1d)
+ 40103a..401060
+ 401099..4010a0
+
+die: <unknown> (b)
+ 40103a..401060
+ 401099..4010a0
+
+die: <unknown> (b)
+ 40103a..401044
+ 401050..401060
+
+die: <unknown> (b)
+ 401050..401053
+ 401056..401059
+
+EOF
+
+exit 0
diff --git a/tests/run-alldts.sh b/tests/run-alldts.sh
new file mode 100755
index 0000000..ce3630b
--- /dev/null
+++ b/tests/run-alldts.sh
@@ -0,0 +1,98 @@
+#! /bin/sh
+# Copyright (C) 2011 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles testfile-alldts
+
+# This will produce "testfile-alldts" file
+testrun ${abs_builddir}/alldts
+
+testrun_compare ${abs_top_builddir}/src/readelf -d testfile-alldts <<\EOF
+
+Dynamic segment contains 66 entries:
+ Addr: 0x000001a0  Offset: 0x000078  Link to section: [ 0] ''
+  Type              Value
+  NEEDED            Shared library: [(null)]
+  PLTRELSZ          3735928559 (bytes)
+  PLTGOT            0xdeadbeef
+  HASH              0xdeadbeef
+  STRTAB            0xdeadbeef
+  SYMTAB            0xdeadbeef
+  RELA              0xdeadbeef
+  RELASZ            3735928559 (bytes)
+  RELAENT           3735928559 (bytes)
+  STRSZ             3735928559 (bytes)
+  SYMENT            3735928559 (bytes)
+  INIT              0xdeadbeef
+  FINI              0xdeadbeef
+  SONAME            Library soname: [(null)]
+  RPATH             Library rpath: [(null)]
+  SYMBOLIC          0xdeadbeef
+  REL               0xdeadbeef
+  RELSZ             3735928559 (bytes)
+  RELENT            3735928559 (bytes)
+  PLTREL            ???
+  DEBUG             
+  TEXTREL           
+  JMPREL            0xdeadbeef
+  BIND_NOW          
+  INIT_ARRAY        0xdeadbeef
+  FINI_ARRAY        0xdeadbeef
+  INIT_ARRAYSZ      3735928559 (bytes)
+  FINI_ARRAYSZ      3735928559 (bytes)
+  RUNPATH           Library runpath: [(null)]
+  FLAGS             ORIGIN SYMBOLIC TEXTREL BIND_NOW 0xdeadbee0
+  PREINIT_ARRAY     0xdeadbeef
+  PREINIT_ARRAY     0xdeadbeef
+  PREINIT_ARRAYSZ   0xdeadbeef
+  VERSYM            0xdeadbeef
+  GNU_PRELINKED     0xdeadbeef
+  GNU_CONFLICTSZ    3735928559 (bytes)
+  GNU_LIBLISTSZ     3735928559 (bytes)
+  CHECKSUM          0xdeadbeef
+  PLTPADSZ          3735928559 (bytes)
+  MOVEENT           3735928559 (bytes)
+  MOVESZ            3735928559 (bytes)
+  FEATURE_1         PARINIT CONFEXP 0xdeadbeec
+  POSFLAG_1         LAZYLOAD GROUPPERM 0xdeadbeec
+  SYMINSZ           3735928559 (bytes)
+  SYMINENT          3735928559 (bytes)
+  GNU_HASH          0xdeadbeef
+  TLSDESC_PLT       0xdeadbeef
+  TLSDESC_GOT       0xdeadbeef
+  GNU_CONFLICT      0xdeadbeef
+  GNU_LIBLIST       0xdeadbeef
+  CONFIG            0xdeadbeef
+  DEPAUDIT          0xdeadbeef
+  AUDIT             0xdeadbeef
+  PLTPAD            0xdeadbeef
+  MOVETAB           0xdeadbeef
+  SYMINFO           0xdeadbeef
+  RELACOUNT         3735928559
+  RELCOUNT          3735928559
+  FLAGS_1           NOW GLOBAL GROUP NODELETE INITFIRST NOOPEN ORIGIN TRANS INTERPOSE NODEFLIB NODUMP CONFALT DISPRELDNE DISPRELPND 0xdeac0000
+  VERDEF            0xdeadbeef
+  VERDEFNUM         3735928559
+  VERNEED           0xdeadbeef
+  VERNEEDNUM        3735928559
+  AUXILIARY         0xdeadbeef
+  FILTER            0xdeadbeef
+  NULL              
+EOF
+
+exit 0
diff --git a/tests/run-allfcts-multi.sh b/tests/run-allfcts-multi.sh
new file mode 100755
index 0000000..ef7bb30
--- /dev/null
+++ b/tests/run-allfcts-multi.sh
@@ -0,0 +1,72 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-readelf-dwz-multi.sh
+testfiles libtestfile_multi_shared.so testfile_multi_main testfile_multi.dwz
+testfiles testfile-dwzstr testfile-dwzstr.multi
+
+testrun_compare ${abs_builddir}/allfcts testfile_multi_main libtestfile_multi_shared.so testfile-dwzstr <<\EOF
+/home/mark/src/tests/dwz/main.c:3:main
+/home/mark/src/tests/dwz/shared.c:3:call_foo
+/home/mark/src/tests/main.c:8:main
+EOF
+
+# - test-offset-loop.c
+#
+# #include <stdbool.h>
+# #include <string.h>
+# #include <errno.h>
+# void padding (int x, int y, int z) { }
+# static inline bool is_error (int err) { return err != 0; }
+# static inline int get_errno (void) { return errno; }
+# int main () { return is_error (get_errno ()); }
+#
+# gcc -g -O2 test-offset-loop.c -o test-offset-loop
+# cp test-offset-loop test-offset-loop2
+# dwz test-offset-loop test-offset-loop2 -m test-offset-loop.alt
+
+testfiles test-offset-loop test-offset-loop.alt
+tempfiles allfcts.out
+
+# Use head to capture output because the output could be infinite...
+testrun ${abs_builddir}/allfcts test-offset-loop | head -n 20 > allfcts.out
+testrun_compare cat allfcts.out <<\EOF
+/tmp/test-offset-loop.c:6:get_errno
+/tmp/test-offset-loop.c:5:is_error
+/tmp/test-offset-loop.c:4:padding
+/tmp/test-offset-loop.c:7:main
+EOF
+
+# allfcts has a too simple mechanism for setting the alt file.
+# check that if we don't set it, things still work (because libdw will
+# find the alt file for us).
+mkdir subdir
+mv test-offset-loop test-offset-loop.alt subdir/
+testrun ${abs_builddir}/allfcts subdir/test-offset-loop > allfcts.out
+testrun_compare cat allfcts.out <<\EOF
+Warning: no alt file found.
+/tmp/test-offset-loop.c:6:get_errno
+/tmp/test-offset-loop.c:5:is_error
+/tmp/test-offset-loop.c:4:padding
+/tmp/test-offset-loop.c:7:main
+EOF
+
+rm -rf subdir
+
+exit 0
diff --git a/tests/run-allfcts.sh b/tests/run-allfcts.sh
new file mode 100755
index 0000000..4dd0284
--- /dev/null
+++ b/tests/run-allfcts.sh
@@ -0,0 +1,190 @@
+#! /bin/sh
+# Copyright (C) 2005, 2013 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2 testfile8
+
+testrun_compare ${abs_builddir}/allfcts testfile testfile2 testfile8 <<\EOF
+/home/drepper/gnu/new-bu/build/ttt/m.c:5:main
+/home/drepper/gnu/new-bu/build/ttt/b.c:4:bar
+/home/drepper/gnu/new-bu/build/ttt/f.c:3:foo
+/shoggoth/drepper/b.c:4:bar
+/shoggoth/drepper/f.c:3:foo
+/shoggoth/drepper/m.c:5:main
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:107:main
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:159:print_version
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:173:parse_opt
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:201:more_help
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:217:process_file
+/usr/include/sys/stat.h:375:stat64
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:291:crc32_file
+/home/drepper/gnu/elfutils/build/src/../../src/strip.c:313:handle_elf
+EOF
+
+# = nested_funcs.c =
+#
+# static int
+# foo (int x)
+# {
+#   int bar (int y)
+#   {
+#     return x - y;
+#   }
+# 
+#   return bar (x * 2);
+# }
+#
+# int
+# main (int argc, char ** argv)
+# {
+#   return foo (argc);
+# }
+#
+# gcc -g -o nested_funcs nested_funcs.c
+
+# = class_func.cxx =
+#
+# namespace foobar
+# {
+#   class Foo
+#   {
+#   public:
+#     int bar(int x);
+#   };
+#
+#   int Foo::bar(int x) { return x - 42; }
+# };
+#
+# int
+# main (int argc, char **argv)
+# {
+#   foobar::Foo foo;
+#
+#   return foo.bar (42);
+# }
+#
+# clang++ -g -o class_func class_func.cxx
+
+testfiles testfile_nested_funcs testfile_class_func
+
+testrun_compare ${abs_builddir}/allfcts testfile_nested_funcs testfile_class_func <<\EOF
+/home/mark/src/tests/nested/nested_funcs.c:2:foo
+/home/mark/src/tests/nested/nested_funcs.c:4:bar
+/home/mark/src/tests/nested/nested_funcs.c:13:main
+/home/mark/src/tests/nested/class_func.cxx:6:bar
+/home/mark/src/tests/nested/class_func.cxx:13:main
+EOF
+
+# = testfile-lto.h =
+# struct t
+# {
+#   int *p;
+#   int c;
+# };
+#
+# extern int foo (int i, struct t *t);
+
+# = testfile-lto-func.c =
+# #include "testfile-lto.h"
+#
+# int
+# foo (int i, struct t *t)
+# {
+#   int j, res = 0;
+#   for (j = 0; j < i && j < t->c; j++)
+#     res += t->p[j];
+#
+#   return res;
+# }
+
+# = testfile-lto-main.c =
+# #include "testfile-lto.h"
+#
+# static struct t g;
+#
+# int
+# main (int argc, char **argv)
+# {
+#   int i;
+#   int j[argc];
+#   g.c = argc;
+#   g.p = j;
+#   for (i = 0; i < argc; i++)
+#     j[i] = (int) argv[i][0];
+#   return foo (3, &g);
+# }
+
+# Using gcc (GCC) 10.0.1 20200430 (Red Hat 10.0.1-0.13)
+# gcc -g -O2 -flto -c testfile-lto-func.c
+# gcc -g -O2 -flto -c testfile-lto-main.c
+# gcc -g -O2 -flto -o testfile-lto-gcc10 testfile-lto-func.o testfile-lto-main.o
+
+testfiles testfile-lto-gcc10
+
+testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc10 <<\EOF
+/home/mark/src/tests/testfile-lto-main.c:6:main
+/home/mark/src/tests/testfile-lto-func.c:4:foo
+/home/mark/src/tests/testfile-lto-main.c:6:main
+EOF
+
+# Using gcc (GCC) 8.3.1 20190311 (Red Hat 8.3.1-3)
+# gcc -g -O2 -flto -c testfile-lto-func.c
+# gcc -g -O2 -flto -c testfile-lto-main.c
+# gcc -g -O2 -flto -o testfile-lto-gcc8 testfile-lto-func.o testfile-lto-main.o
+
+testfiles testfile-lto-gcc8
+
+testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc8 <<\EOF
+/home/mark/src/tests/testfile-lto-func.c:4:foo
+/home/mark/src/tests/testfile-lto-main.c:6:main
+/home/mark/src/tests/testfile-lto-main.c:6:main
+/home/mark/src/tests/testfile-lto-func.c:4:foo
+EOF
+
+# gcc (GCC) 9.1.1 20190605 (Red Hat 9.1.1-2)
+# gcc -g -O2 -flto -c testfile-lto-func.c
+# gcc -g -O2 -flto -c testfile-lto-main.c
+# gcc -g -O2 -flto -o testfile-lto-gcc9 testfile-lto-func.o testfile-lto-main.o
+
+testfiles testfile-lto-gcc9
+
+testrun_compare ${abs_builddir}/allfcts testfile-lto-gcc9 <<\EOF
+/home/mark/src/tests/testfile-lto-main.c:6:main
+/home/mark/src/tests/testfile-lto-func.c:4:foo
+/home/mark/src/tests/testfile-lto-main.c:6:main
+EOF
+
+# = dwarf5-line.c =
+# int
+# main (int argc, char **argv)
+# {
+#   return 0;
+# }
+
+# Using clang version 17.0.4 (Fedora 17.0.4-1.fc39)
+# clang -gdwarf-5 -o testfile-dwarf5-line-clang dwarf5-line.c
+
+testfiles testfile-dwarf5-line-clang
+
+# Check that dwarf_decl_file can handle .debug_line file table index 0
+testrun_compare ${abs_builddir}/allfcts testfile-dwarf5-line-clang <<\EOF
+/home/amerey/test/dwarf5-line.c:2:main
+EOF
+
+exit 0
diff --git a/tests/run-allregs.sh b/tests/run-allregs.sh
new file mode 100755
index 0000000..87b16c9
--- /dev/null
+++ b/tests/run-allregs.sh
@@ -0,0 +1,2907 @@
+#! /bin/sh
+# Copyright (C) 2005, 2006, 2007, 2012, 2013 Red Hat, Inc.
+# Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+regs_test()
+{
+  tempfiles good.regs
+  cat > good.regs
+  testfiles "$@"
+  for f; do testrun_compare ${abs_builddir}/allregs -e $f < good.regs; done
+  test_cleanup
+}
+
+regs_test testfile11 <<\EOF
+integer registers:
+	  0: %eax (eax), signed 32 bits
+	  1: %ecx (ecx), signed 32 bits
+	  2: %edx (edx), signed 32 bits
+	  3: %ebx (ebx), signed 32 bits
+	  4: %esp (esp), address 32 bits
+	  5: %ebp (ebp), address 32 bits
+	  6: %esi (esi), signed 32 bits
+	  7: %edi (edi), signed 32 bits
+	  8: %eip (eip), address 32 bits
+	  9: %eflags (eflags), unsigned 32 bits
+	 10: %trapno (trapno), unsigned 32 bits
+FPU-control registers:
+	 37: %fctrl (fctrl), unsigned 16 bits
+	 38: %fstat (fstat), unsigned 16 bits
+	 39: %mxcsr (mxcsr), unsigned 32 bits
+MMX registers:
+	 29: %mm0 (mm0), unsigned 64 bits
+	 30: %mm1 (mm1), unsigned 64 bits
+	 31: %mm2 (mm2), unsigned 64 bits
+	 32: %mm3 (mm3), unsigned 64 bits
+	 33: %mm4 (mm4), unsigned 64 bits
+	 34: %mm5 (mm5), unsigned 64 bits
+	 35: %mm6 (mm6), unsigned 64 bits
+	 36: %mm7 (mm7), unsigned 64 bits
+SSE registers:
+	 21: %xmm0 (xmm0), unsigned 128 bits
+	 22: %xmm1 (xmm1), unsigned 128 bits
+	 23: %xmm2 (xmm2), unsigned 128 bits
+	 24: %xmm3 (xmm3), unsigned 128 bits
+	 25: %xmm4 (xmm4), unsigned 128 bits
+	 26: %xmm5 (xmm5), unsigned 128 bits
+	 27: %xmm6 (xmm6), unsigned 128 bits
+	 28: %xmm7 (xmm7), unsigned 128 bits
+segment registers:
+	 40: %es (es), unsigned 16 bits
+	 41: %cs (cs), unsigned 16 bits
+	 42: %ss (ss), unsigned 16 bits
+	 43: %ds (ds), unsigned 16 bits
+	 44: %fs (fs), unsigned 16 bits
+	 45: %gs (gs), unsigned 16 bits
+x87 registers:
+	 11: %st0 (st0), float 80 bits
+	 12: %st1 (st1), float 80 bits
+	 13: %st2 (st2), float 80 bits
+	 14: %st3 (st3), float 80 bits
+	 15: %st4 (st4), float 80 bits
+	 16: %st5 (st5), float 80 bits
+	 17: %st6 (st6), float 80 bits
+	 18: %st7 (st7), float 80 bits
+EOF
+
+regs_test testfile12 <<\EOF
+integer registers:
+	  0: %rax (rax), signed 64 bits
+	  1: %rdx (rdx), signed 64 bits
+	  2: %rcx (rcx), signed 64 bits
+	  3: %rbx (rbx), signed 64 bits
+	  4: %rsi (rsi), signed 64 bits
+	  5: %rdi (rdi), signed 64 bits
+	  6: %rbp (rbp), address 64 bits
+	  7: %rsp (rsp), address 64 bits
+	  8: %r8 (r8), signed 64 bits
+	  9: %r9 (r9), signed 64 bits
+	 10: %r10 (r10), signed 64 bits
+	 11: %r11 (r11), signed 64 bits
+	 12: %r12 (r12), signed 64 bits
+	 13: %r13 (r13), signed 64 bits
+	 14: %r14 (r14), signed 64 bits
+	 15: %r15 (r15), signed 64 bits
+	 16: %rip (rip), address 64 bits
+	 49: %rflags (rflags), unsigned 64 bits
+MMX registers:
+	 41: %mm0 (mm0), unsigned 64 bits
+	 42: %mm1 (mm1), unsigned 64 bits
+	 43: %mm2 (mm2), unsigned 64 bits
+	 44: %mm3 (mm3), unsigned 64 bits
+	 45: %mm4 (mm4), unsigned 64 bits
+	 46: %mm5 (mm5), unsigned 64 bits
+	 47: %mm6 (mm6), unsigned 64 bits
+	 48: %mm7 (mm7), unsigned 64 bits
+SSE registers:
+	 17: %xmm0 (xmm0), unsigned 128 bits
+	 18: %xmm1 (xmm1), unsigned 128 bits
+	 19: %xmm2 (xmm2), unsigned 128 bits
+	 20: %xmm3 (xmm3), unsigned 128 bits
+	 21: %xmm4 (xmm4), unsigned 128 bits
+	 22: %xmm5 (xmm5), unsigned 128 bits
+	 23: %xmm6 (xmm6), unsigned 128 bits
+	 24: %xmm7 (xmm7), unsigned 128 bits
+	 25: %xmm8 (xmm8), unsigned 128 bits
+	 26: %xmm9 (xmm9), unsigned 128 bits
+	 27: %xmm10 (xmm10), unsigned 128 bits
+	 28: %xmm11 (xmm11), unsigned 128 bits
+	 29: %xmm12 (xmm12), unsigned 128 bits
+	 30: %xmm13 (xmm13), unsigned 128 bits
+	 31: %xmm14 (xmm14), unsigned 128 bits
+	 32: %xmm15 (xmm15), unsigned 128 bits
+control registers:
+	 62: %tr (tr), unsigned 64 bits
+	 63: %ldtr (ldtr), unsigned 64 bits
+	 64: %mxcsr (mxcsr), unsigned 64 bits
+	 65: %fcw (fcw), unsigned 16 bits
+	 66: %fsw (fsw), unsigned 16 bits
+segment registers:
+	 50: %es (es), unsigned 16 bits
+	 51: %cs (cs), unsigned 16 bits
+	 52: %ss (ss), unsigned 16 bits
+	 53: %ds (ds), unsigned 16 bits
+	 54: %fs (fs), unsigned 16 bits
+	 55: %gs (gs), unsigned 16 bits
+	 58: %fs.base (fs.base), address 64 bits
+	 59: %gs.base (gs.base), address 64 bits
+x87 registers:
+	 33: %st0 (st0), float 80 bits
+	 34: %st1 (st1), float 80 bits
+	 35: %st2 (st2), float 80 bits
+	 36: %st3 (st3), float 80 bits
+	 37: %st4 (st4), float 80 bits
+	 38: %st5 (st5), float 80 bits
+	 39: %st6 (st6), float 80 bits
+	 40: %st7 (st7), float 80 bits
+EOF
+
+regs_test testfile2 <<\EOF
+integer registers:
+	  0: r0 (r0), signed 32 bits
+	  1: r1 (r1), signed 32 bits
+	  2: r2 (r2), signed 32 bits
+	  3: r3 (r3), signed 32 bits
+	  4: r4 (r4), signed 32 bits
+	  5: r5 (r5), signed 32 bits
+	  6: r6 (r6), signed 32 bits
+	  7: r7 (r7), signed 32 bits
+	  8: r8 (r8), signed 32 bits
+	  9: r9 (r9), signed 32 bits
+	 10: r10 (r10), signed 32 bits
+	 11: r11 (r11), signed 32 bits
+	 12: r12 (r12), signed 32 bits
+	 13: r13 (r13), signed 32 bits
+	 14: r14 (r14), signed 32 bits
+	 15: r15 (r15), signed 32 bits
+	 16: r16 (r16), signed 32 bits
+	 17: r17 (r17), signed 32 bits
+	 18: r18 (r18), signed 32 bits
+	 19: r19 (r19), signed 32 bits
+	 20: r20 (r20), signed 32 bits
+	 21: r21 (r21), signed 32 bits
+	 22: r22 (r22), signed 32 bits
+	 23: r23 (r23), signed 32 bits
+	 24: r24 (r24), signed 32 bits
+	 25: r25 (r25), signed 32 bits
+	 26: r26 (r26), signed 32 bits
+	 27: r27 (r27), signed 32 bits
+	 28: r28 (r28), signed 32 bits
+	 29: r29 (r29), signed 32 bits
+	 30: r30 (r30), signed 32 bits
+	 31: r31 (r31), signed 32 bits
+	 64: cr (cr), unsigned 32 bits
+	 66: msr (msr), unsigned 32 bits
+FPU registers:
+	 32: f0 (f0), float 64 bits
+	 33: f1 (f1), float 64 bits
+	 34: f2 (f2), float 64 bits
+	 35: f3 (f3), float 64 bits
+	 36: f4 (f4), float 64 bits
+	 37: f5 (f5), float 64 bits
+	 38: f6 (f6), float 64 bits
+	 39: f7 (f7), float 64 bits
+	 40: f8 (f8), float 64 bits
+	 41: f9 (f9), float 64 bits
+	 42: f10 (f10), float 64 bits
+	 43: f11 (f11), float 64 bits
+	 44: f12 (f12), float 64 bits
+	 45: f13 (f13), float 64 bits
+	 46: f14 (f14), float 64 bits
+	 47: f15 (f15), float 64 bits
+	 48: f16 (f16), float 64 bits
+	 49: f17 (f17), float 64 bits
+	 50: f18 (f18), float 64 bits
+	 51: f19 (f19), float 64 bits
+	 52: f20 (f20), float 64 bits
+	 53: f21 (f21), float 64 bits
+	 54: f22 (f22), float 64 bits
+	 55: f23 (f23), float 64 bits
+	 56: f24 (f24), float 64 bits
+	 57: f25 (f25), float 64 bits
+	 58: f26 (f26), float 64 bits
+	 59: f27 (f27), float 64 bits
+	 60: f28 (f28), float 64 bits
+	 61: f29 (f29), float 64 bits
+	 62: f30 (f30), float 64 bits
+	 63: f31 (f31), float 64 bits
+	 65: fpscr (fpscr), unsigned 32 bits
+privileged registers:
+	 70: sr0 (sr0), unsigned 32 bits
+	 71: sr1 (sr1), unsigned 32 bits
+	 72: sr2 (sr2), unsigned 32 bits
+	 73: sr3 (sr3), unsigned 32 bits
+	 74: sr4 (sr4), unsigned 32 bits
+	 75: sr5 (sr5), unsigned 32 bits
+	 76: sr6 (sr6), unsigned 32 bits
+	 77: sr7 (sr7), unsigned 32 bits
+	 78: sr8 (sr8), unsigned 32 bits
+	 79: sr9 (sr9), unsigned 32 bits
+	 80: sr10 (sr10), unsigned 32 bits
+	 81: sr11 (sr11), unsigned 32 bits
+	 82: sr12 (sr12), unsigned 32 bits
+	 83: sr13 (sr13), unsigned 32 bits
+	 84: sr14 (sr14), unsigned 32 bits
+	 85: sr15 (sr15), unsigned 32 bits
+	100: mq (mq), unsigned 32 bits
+	101: xer (xer), unsigned 32 bits
+	102: spr2 (spr2), unsigned 32 bits
+	103: spr3 (spr3), unsigned 32 bits
+	104: spr4 (spr4), unsigned 32 bits
+	105: spr5 (spr5), unsigned 32 bits
+	106: spr6 (spr6), unsigned 32 bits
+	107: spr7 (spr7), unsigned 32 bits
+	108: lr (lr), unsigned 32 bits
+	109: ctr (ctr), unsigned 32 bits
+	110: spr10 (spr10), unsigned 32 bits
+	111: spr11 (spr11), unsigned 32 bits
+	112: spr12 (spr12), unsigned 32 bits
+	113: spr13 (spr13), unsigned 32 bits
+	114: tfhar (tfhar), unsigned 32 bits
+	115: tfiar (tfiar), unsigned 32 bits
+	116: texasr (texasr), unsigned 32 bits
+	117: spr17 (spr17), unsigned 32 bits
+	118: dsisr (dsisr), unsigned 32 bits
+	119: dar (dar), unsigned 32 bits
+	120: spr20 (spr20), unsigned 32 bits
+	121: spr21 (spr21), unsigned 32 bits
+	122: dec (dec), unsigned 32 bits
+	123: spr23 (spr23), unsigned 32 bits
+	124: spr24 (spr24), unsigned 32 bits
+	125: spr25 (spr25), unsigned 32 bits
+	126: spr26 (spr26), unsigned 32 bits
+	127: spr27 (spr27), unsigned 32 bits
+	128: spr28 (spr28), unsigned 32 bits
+	129: spr29 (spr29), unsigned 32 bits
+	130: spr30 (spr30), unsigned 32 bits
+	131: spr31 (spr31), unsigned 32 bits
+	132: spr32 (spr32), unsigned 32 bits
+	133: spr33 (spr33), unsigned 32 bits
+	134: spr34 (spr34), unsigned 32 bits
+	135: spr35 (spr35), unsigned 32 bits
+	136: spr36 (spr36), unsigned 32 bits
+	137: spr37 (spr37), unsigned 32 bits
+	138: spr38 (spr38), unsigned 32 bits
+	139: spr39 (spr39), unsigned 32 bits
+	140: spr40 (spr40), unsigned 32 bits
+	141: spr41 (spr41), unsigned 32 bits
+	142: spr42 (spr42), unsigned 32 bits
+	143: spr43 (spr43), unsigned 32 bits
+	144: spr44 (spr44), unsigned 32 bits
+	145: spr45 (spr45), unsigned 32 bits
+	146: spr46 (spr46), unsigned 32 bits
+	147: spr47 (spr47), unsigned 32 bits
+	148: spr48 (spr48), unsigned 32 bits
+	149: spr49 (spr49), unsigned 32 bits
+	150: spr50 (spr50), unsigned 32 bits
+	151: spr51 (spr51), unsigned 32 bits
+	152: spr52 (spr52), unsigned 32 bits
+	153: spr53 (spr53), unsigned 32 bits
+	154: spr54 (spr54), unsigned 32 bits
+	155: spr55 (spr55), unsigned 32 bits
+	156: spr56 (spr56), unsigned 32 bits
+	157: spr57 (spr57), unsigned 32 bits
+	158: spr58 (spr58), unsigned 32 bits
+	159: spr59 (spr59), unsigned 32 bits
+	160: spr60 (spr60), unsigned 32 bits
+	161: spr61 (spr61), unsigned 32 bits
+	162: spr62 (spr62), unsigned 32 bits
+	163: spr63 (spr63), unsigned 32 bits
+	164: spr64 (spr64), unsigned 32 bits
+	165: spr65 (spr65), unsigned 32 bits
+	166: spr66 (spr66), unsigned 32 bits
+	167: spr67 (spr67), unsigned 32 bits
+	168: spr68 (spr68), unsigned 32 bits
+	169: spr69 (spr69), unsigned 32 bits
+	170: spr70 (spr70), unsigned 32 bits
+	171: spr71 (spr71), unsigned 32 bits
+	172: spr72 (spr72), unsigned 32 bits
+	173: spr73 (spr73), unsigned 32 bits
+	174: spr74 (spr74), unsigned 32 bits
+	175: spr75 (spr75), unsigned 32 bits
+	176: spr76 (spr76), unsigned 32 bits
+	177: spr77 (spr77), unsigned 32 bits
+	178: spr78 (spr78), unsigned 32 bits
+	179: spr79 (spr79), unsigned 32 bits
+	180: spr80 (spr80), unsigned 32 bits
+	181: spr81 (spr81), unsigned 32 bits
+	182: spr82 (spr82), unsigned 32 bits
+	183: spr83 (spr83), unsigned 32 bits
+	184: spr84 (spr84), unsigned 32 bits
+	185: spr85 (spr85), unsigned 32 bits
+	186: spr86 (spr86), unsigned 32 bits
+	187: spr87 (spr87), unsigned 32 bits
+	188: spr88 (spr88), unsigned 32 bits
+	189: spr89 (spr89), unsigned 32 bits
+	190: spr90 (spr90), unsigned 32 bits
+	191: spr91 (spr91), unsigned 32 bits
+	192: spr92 (spr92), unsigned 32 bits
+	193: spr93 (spr93), unsigned 32 bits
+	194: spr94 (spr94), unsigned 32 bits
+	195: spr95 (spr95), unsigned 32 bits
+	196: spr96 (spr96), unsigned 32 bits
+	197: spr97 (spr97), unsigned 32 bits
+	198: spr98 (spr98), unsigned 32 bits
+	199: spr99 (spr99), unsigned 32 bits
+	200: spr100 (spr100), unsigned 32 bits
+	201: spr101 (spr101), unsigned 32 bits
+	202: spr102 (spr102), unsigned 32 bits
+	203: spr103 (spr103), unsigned 32 bits
+	204: spr104 (spr104), unsigned 32 bits
+	205: spr105 (spr105), unsigned 32 bits
+	206: spr106 (spr106), unsigned 32 bits
+	207: spr107 (spr107), unsigned 32 bits
+	208: spr108 (spr108), unsigned 32 bits
+	209: spr109 (spr109), unsigned 32 bits
+	210: spr110 (spr110), unsigned 32 bits
+	211: spr111 (spr111), unsigned 32 bits
+	212: spr112 (spr112), unsigned 32 bits
+	213: spr113 (spr113), unsigned 32 bits
+	214: spr114 (spr114), unsigned 32 bits
+	215: spr115 (spr115), unsigned 32 bits
+	216: spr116 (spr116), unsigned 32 bits
+	217: spr117 (spr117), unsigned 32 bits
+	218: spr118 (spr118), unsigned 32 bits
+	219: spr119 (spr119), unsigned 32 bits
+	220: spr120 (spr120), unsigned 32 bits
+	221: spr121 (spr121), unsigned 32 bits
+	222: spr122 (spr122), unsigned 32 bits
+	223: spr123 (spr123), unsigned 32 bits
+	224: spr124 (spr124), unsigned 32 bits
+	225: spr125 (spr125), unsigned 32 bits
+	226: spr126 (spr126), unsigned 32 bits
+	227: spr127 (spr127), unsigned 32 bits
+	228: spr128 (spr128), unsigned 32 bits
+	229: spr129 (spr129), unsigned 32 bits
+	230: spr130 (spr130), unsigned 32 bits
+	231: spr131 (spr131), unsigned 32 bits
+	232: spr132 (spr132), unsigned 32 bits
+	233: spr133 (spr133), unsigned 32 bits
+	234: spr134 (spr134), unsigned 32 bits
+	235: spr135 (spr135), unsigned 32 bits
+	236: spr136 (spr136), unsigned 32 bits
+	237: spr137 (spr137), unsigned 32 bits
+	238: spr138 (spr138), unsigned 32 bits
+	239: spr139 (spr139), unsigned 32 bits
+	240: spr140 (spr140), unsigned 32 bits
+	241: spr141 (spr141), unsigned 32 bits
+	242: spr142 (spr142), unsigned 32 bits
+	243: spr143 (spr143), unsigned 32 bits
+	244: spr144 (spr144), unsigned 32 bits
+	245: spr145 (spr145), unsigned 32 bits
+	246: spr146 (spr146), unsigned 32 bits
+	247: spr147 (spr147), unsigned 32 bits
+	248: spr148 (spr148), unsigned 32 bits
+	249: spr149 (spr149), unsigned 32 bits
+	250: spr150 (spr150), unsigned 32 bits
+	251: spr151 (spr151), unsigned 32 bits
+	252: spr152 (spr152), unsigned 32 bits
+	253: spr153 (spr153), unsigned 32 bits
+	254: spr154 (spr154), unsigned 32 bits
+	255: spr155 (spr155), unsigned 32 bits
+	256: spr156 (spr156), unsigned 32 bits
+	257: spr157 (spr157), unsigned 32 bits
+	258: spr158 (spr158), unsigned 32 bits
+	259: spr159 (spr159), unsigned 32 bits
+	260: spr160 (spr160), unsigned 32 bits
+	261: spr161 (spr161), unsigned 32 bits
+	262: spr162 (spr162), unsigned 32 bits
+	263: spr163 (spr163), unsigned 32 bits
+	264: spr164 (spr164), unsigned 32 bits
+	265: spr165 (spr165), unsigned 32 bits
+	266: spr166 (spr166), unsigned 32 bits
+	267: spr167 (spr167), unsigned 32 bits
+	268: spr168 (spr168), unsigned 32 bits
+	269: spr169 (spr169), unsigned 32 bits
+	270: spr170 (spr170), unsigned 32 bits
+	271: spr171 (spr171), unsigned 32 bits
+	272: spr172 (spr172), unsigned 32 bits
+	273: spr173 (spr173), unsigned 32 bits
+	274: spr174 (spr174), unsigned 32 bits
+	275: spr175 (spr175), unsigned 32 bits
+	276: spr176 (spr176), unsigned 32 bits
+	277: spr177 (spr177), unsigned 32 bits
+	278: spr178 (spr178), unsigned 32 bits
+	279: spr179 (spr179), unsigned 32 bits
+	280: spr180 (spr180), unsigned 32 bits
+	281: spr181 (spr181), unsigned 32 bits
+	282: spr182 (spr182), unsigned 32 bits
+	283: spr183 (spr183), unsigned 32 bits
+	284: spr184 (spr184), unsigned 32 bits
+	285: spr185 (spr185), unsigned 32 bits
+	286: spr186 (spr186), unsigned 32 bits
+	287: spr187 (spr187), unsigned 32 bits
+	288: spr188 (spr188), unsigned 32 bits
+	289: spr189 (spr189), unsigned 32 bits
+	290: spr190 (spr190), unsigned 32 bits
+	291: spr191 (spr191), unsigned 32 bits
+	292: spr192 (spr192), unsigned 32 bits
+	293: spr193 (spr193), unsigned 32 bits
+	294: spr194 (spr194), unsigned 32 bits
+	295: spr195 (spr195), unsigned 32 bits
+	296: spr196 (spr196), unsigned 32 bits
+	297: spr197 (spr197), unsigned 32 bits
+	298: spr198 (spr198), unsigned 32 bits
+	299: spr199 (spr199), unsigned 32 bits
+	300: spr200 (spr200), unsigned 32 bits
+	301: spr201 (spr201), unsigned 32 bits
+	302: spr202 (spr202), unsigned 32 bits
+	303: spr203 (spr203), unsigned 32 bits
+	304: spr204 (spr204), unsigned 32 bits
+	305: spr205 (spr205), unsigned 32 bits
+	306: spr206 (spr206), unsigned 32 bits
+	307: spr207 (spr207), unsigned 32 bits
+	308: spr208 (spr208), unsigned 32 bits
+	309: spr209 (spr209), unsigned 32 bits
+	310: spr210 (spr210), unsigned 32 bits
+	311: spr211 (spr211), unsigned 32 bits
+	312: spr212 (spr212), unsigned 32 bits
+	313: spr213 (spr213), unsigned 32 bits
+	314: spr214 (spr214), unsigned 32 bits
+	315: spr215 (spr215), unsigned 32 bits
+	316: spr216 (spr216), unsigned 32 bits
+	317: spr217 (spr217), unsigned 32 bits
+	318: spr218 (spr218), unsigned 32 bits
+	319: spr219 (spr219), unsigned 32 bits
+	320: spr220 (spr220), unsigned 32 bits
+	321: spr221 (spr221), unsigned 32 bits
+	322: spr222 (spr222), unsigned 32 bits
+	323: spr223 (spr223), unsigned 32 bits
+	324: spr224 (spr224), unsigned 32 bits
+	325: spr225 (spr225), unsigned 32 bits
+	326: spr226 (spr226), unsigned 32 bits
+	327: spr227 (spr227), unsigned 32 bits
+	328: spr228 (spr228), unsigned 32 bits
+	329: spr229 (spr229), unsigned 32 bits
+	330: spr230 (spr230), unsigned 32 bits
+	331: spr231 (spr231), unsigned 32 bits
+	332: spr232 (spr232), unsigned 32 bits
+	333: spr233 (spr233), unsigned 32 bits
+	334: spr234 (spr234), unsigned 32 bits
+	335: spr235 (spr235), unsigned 32 bits
+	336: spr236 (spr236), unsigned 32 bits
+	337: spr237 (spr237), unsigned 32 bits
+	338: spr238 (spr238), unsigned 32 bits
+	339: spr239 (spr239), unsigned 32 bits
+	340: spr240 (spr240), unsigned 32 bits
+	341: spr241 (spr241), unsigned 32 bits
+	342: spr242 (spr242), unsigned 32 bits
+	343: spr243 (spr243), unsigned 32 bits
+	344: spr244 (spr244), unsigned 32 bits
+	345: spr245 (spr245), unsigned 32 bits
+	346: spr246 (spr246), unsigned 32 bits
+	347: spr247 (spr247), unsigned 32 bits
+	348: spr248 (spr248), unsigned 32 bits
+	349: spr249 (spr249), unsigned 32 bits
+	350: spr250 (spr250), unsigned 32 bits
+	351: spr251 (spr251), unsigned 32 bits
+	352: spr252 (spr252), unsigned 32 bits
+	353: spr253 (spr253), unsigned 32 bits
+	354: spr254 (spr254), unsigned 32 bits
+	355: spr255 (spr255), unsigned 32 bits
+	357: spr257 (spr257), unsigned 32 bits
+	358: spr258 (spr258), unsigned 32 bits
+	359: spr259 (spr259), unsigned 32 bits
+	360: spr260 (spr260), unsigned 32 bits
+	361: spr261 (spr261), unsigned 32 bits
+	362: spr262 (spr262), unsigned 32 bits
+	363: spr263 (spr263), unsigned 32 bits
+	364: spr264 (spr264), unsigned 32 bits
+	365: spr265 (spr265), unsigned 32 bits
+	366: spr266 (spr266), unsigned 32 bits
+	367: spr267 (spr267), unsigned 32 bits
+	368: spr268 (spr268), unsigned 32 bits
+	369: spr269 (spr269), unsigned 32 bits
+	370: spr270 (spr270), unsigned 32 bits
+	371: spr271 (spr271), unsigned 32 bits
+	372: spr272 (spr272), unsigned 32 bits
+	373: spr273 (spr273), unsigned 32 bits
+	374: spr274 (spr274), unsigned 32 bits
+	375: spr275 (spr275), unsigned 32 bits
+	376: spr276 (spr276), unsigned 32 bits
+	377: spr277 (spr277), unsigned 32 bits
+	378: spr278 (spr278), unsigned 32 bits
+	379: spr279 (spr279), unsigned 32 bits
+	380: spr280 (spr280), unsigned 32 bits
+	381: spr281 (spr281), unsigned 32 bits
+	382: spr282 (spr282), unsigned 32 bits
+	383: spr283 (spr283), unsigned 32 bits
+	384: spr284 (spr284), unsigned 32 bits
+	385: spr285 (spr285), unsigned 32 bits
+	386: spr286 (spr286), unsigned 32 bits
+	387: spr287 (spr287), unsigned 32 bits
+	388: spr288 (spr288), unsigned 32 bits
+	389: spr289 (spr289), unsigned 32 bits
+	390: spr290 (spr290), unsigned 32 bits
+	391: spr291 (spr291), unsigned 32 bits
+	392: spr292 (spr292), unsigned 32 bits
+	393: spr293 (spr293), unsigned 32 bits
+	394: spr294 (spr294), unsigned 32 bits
+	395: spr295 (spr295), unsigned 32 bits
+	396: spr296 (spr296), unsigned 32 bits
+	397: spr297 (spr297), unsigned 32 bits
+	398: spr298 (spr298), unsigned 32 bits
+	399: spr299 (spr299), unsigned 32 bits
+	400: spr300 (spr300), unsigned 32 bits
+	401: spr301 (spr301), unsigned 32 bits
+	402: spr302 (spr302), unsigned 32 bits
+	403: spr303 (spr303), unsigned 32 bits
+	404: spr304 (spr304), unsigned 32 bits
+	405: spr305 (spr305), unsigned 32 bits
+	406: spr306 (spr306), unsigned 32 bits
+	407: spr307 (spr307), unsigned 32 bits
+	408: spr308 (spr308), unsigned 32 bits
+	409: spr309 (spr309), unsigned 32 bits
+	410: spr310 (spr310), unsigned 32 bits
+	411: spr311 (spr311), unsigned 32 bits
+	412: spr312 (spr312), unsigned 32 bits
+	413: spr313 (spr313), unsigned 32 bits
+	414: spr314 (spr314), unsigned 32 bits
+	415: spr315 (spr315), unsigned 32 bits
+	416: spr316 (spr316), unsigned 32 bits
+	417: spr317 (spr317), unsigned 32 bits
+	418: spr318 (spr318), unsigned 32 bits
+	419: spr319 (spr319), unsigned 32 bits
+	420: spr320 (spr320), unsigned 32 bits
+	421: spr321 (spr321), unsigned 32 bits
+	422: spr322 (spr322), unsigned 32 bits
+	423: spr323 (spr323), unsigned 32 bits
+	424: spr324 (spr324), unsigned 32 bits
+	425: spr325 (spr325), unsigned 32 bits
+	426: spr326 (spr326), unsigned 32 bits
+	427: spr327 (spr327), unsigned 32 bits
+	428: spr328 (spr328), unsigned 32 bits
+	429: spr329 (spr329), unsigned 32 bits
+	430: spr330 (spr330), unsigned 32 bits
+	431: spr331 (spr331), unsigned 32 bits
+	432: spr332 (spr332), unsigned 32 bits
+	433: spr333 (spr333), unsigned 32 bits
+	434: spr334 (spr334), unsigned 32 bits
+	435: spr335 (spr335), unsigned 32 bits
+	436: spr336 (spr336), unsigned 32 bits
+	437: spr337 (spr337), unsigned 32 bits
+	438: spr338 (spr338), unsigned 32 bits
+	439: spr339 (spr339), unsigned 32 bits
+	440: spr340 (spr340), unsigned 32 bits
+	441: spr341 (spr341), unsigned 32 bits
+	442: spr342 (spr342), unsigned 32 bits
+	443: spr343 (spr343), unsigned 32 bits
+	444: spr344 (spr344), unsigned 32 bits
+	445: spr345 (spr345), unsigned 32 bits
+	446: spr346 (spr346), unsigned 32 bits
+	447: spr347 (spr347), unsigned 32 bits
+	448: spr348 (spr348), unsigned 32 bits
+	449: spr349 (spr349), unsigned 32 bits
+	450: spr350 (spr350), unsigned 32 bits
+	451: spr351 (spr351), unsigned 32 bits
+	452: spr352 (spr352), unsigned 32 bits
+	453: spr353 (spr353), unsigned 32 bits
+	454: spr354 (spr354), unsigned 32 bits
+	455: spr355 (spr355), unsigned 32 bits
+	456: spr356 (spr356), unsigned 32 bits
+	457: spr357 (spr357), unsigned 32 bits
+	458: spr358 (spr358), unsigned 32 bits
+	459: spr359 (spr359), unsigned 32 bits
+	460: spr360 (spr360), unsigned 32 bits
+	461: spr361 (spr361), unsigned 32 bits
+	462: spr362 (spr362), unsigned 32 bits
+	463: spr363 (spr363), unsigned 32 bits
+	464: spr364 (spr364), unsigned 32 bits
+	465: spr365 (spr365), unsigned 32 bits
+	466: spr366 (spr366), unsigned 32 bits
+	467: spr367 (spr367), unsigned 32 bits
+	468: spr368 (spr368), unsigned 32 bits
+	469: spr369 (spr369), unsigned 32 bits
+	470: spr370 (spr370), unsigned 32 bits
+	471: spr371 (spr371), unsigned 32 bits
+	472: spr372 (spr372), unsigned 32 bits
+	473: spr373 (spr373), unsigned 32 bits
+	474: spr374 (spr374), unsigned 32 bits
+	475: spr375 (spr375), unsigned 32 bits
+	476: spr376 (spr376), unsigned 32 bits
+	477: spr377 (spr377), unsigned 32 bits
+	478: spr378 (spr378), unsigned 32 bits
+	479: spr379 (spr379), unsigned 32 bits
+	480: spr380 (spr380), unsigned 32 bits
+	481: spr381 (spr381), unsigned 32 bits
+	482: spr382 (spr382), unsigned 32 bits
+	483: spr383 (spr383), unsigned 32 bits
+	484: spr384 (spr384), unsigned 32 bits
+	485: spr385 (spr385), unsigned 32 bits
+	486: spr386 (spr386), unsigned 32 bits
+	487: spr387 (spr387), unsigned 32 bits
+	488: spr388 (spr388), unsigned 32 bits
+	489: spr389 (spr389), unsigned 32 bits
+	490: spr390 (spr390), unsigned 32 bits
+	491: spr391 (spr391), unsigned 32 bits
+	492: spr392 (spr392), unsigned 32 bits
+	493: spr393 (spr393), unsigned 32 bits
+	494: spr394 (spr394), unsigned 32 bits
+	495: spr395 (spr395), unsigned 32 bits
+	496: spr396 (spr396), unsigned 32 bits
+	497: spr397 (spr397), unsigned 32 bits
+	498: spr398 (spr398), unsigned 32 bits
+	499: spr399 (spr399), unsigned 32 bits
+	500: spr400 (spr400), unsigned 32 bits
+	501: spr401 (spr401), unsigned 32 bits
+	502: spr402 (spr402), unsigned 32 bits
+	503: spr403 (spr403), unsigned 32 bits
+	504: spr404 (spr404), unsigned 32 bits
+	505: spr405 (spr405), unsigned 32 bits
+	506: spr406 (spr406), unsigned 32 bits
+	507: spr407 (spr407), unsigned 32 bits
+	508: spr408 (spr408), unsigned 32 bits
+	509: spr409 (spr409), unsigned 32 bits
+	510: spr410 (spr410), unsigned 32 bits
+	511: spr411 (spr411), unsigned 32 bits
+	512: spr412 (spr412), unsigned 32 bits
+	513: spr413 (spr413), unsigned 32 bits
+	514: spr414 (spr414), unsigned 32 bits
+	515: spr415 (spr415), unsigned 32 bits
+	516: spr416 (spr416), unsigned 32 bits
+	517: spr417 (spr417), unsigned 32 bits
+	518: spr418 (spr418), unsigned 32 bits
+	519: spr419 (spr419), unsigned 32 bits
+	520: spr420 (spr420), unsigned 32 bits
+	521: spr421 (spr421), unsigned 32 bits
+	522: spr422 (spr422), unsigned 32 bits
+	523: spr423 (spr423), unsigned 32 bits
+	524: spr424 (spr424), unsigned 32 bits
+	525: spr425 (spr425), unsigned 32 bits
+	526: spr426 (spr426), unsigned 32 bits
+	527: spr427 (spr427), unsigned 32 bits
+	528: spr428 (spr428), unsigned 32 bits
+	529: spr429 (spr429), unsigned 32 bits
+	530: spr430 (spr430), unsigned 32 bits
+	531: spr431 (spr431), unsigned 32 bits
+	532: spr432 (spr432), unsigned 32 bits
+	533: spr433 (spr433), unsigned 32 bits
+	534: spr434 (spr434), unsigned 32 bits
+	535: spr435 (spr435), unsigned 32 bits
+	536: spr436 (spr436), unsigned 32 bits
+	537: spr437 (spr437), unsigned 32 bits
+	538: spr438 (spr438), unsigned 32 bits
+	539: spr439 (spr439), unsigned 32 bits
+	540: spr440 (spr440), unsigned 32 bits
+	541: spr441 (spr441), unsigned 32 bits
+	542: spr442 (spr442), unsigned 32 bits
+	543: spr443 (spr443), unsigned 32 bits
+	544: spr444 (spr444), unsigned 32 bits
+	545: spr445 (spr445), unsigned 32 bits
+	546: spr446 (spr446), unsigned 32 bits
+	547: spr447 (spr447), unsigned 32 bits
+	548: spr448 (spr448), unsigned 32 bits
+	549: spr449 (spr449), unsigned 32 bits
+	550: spr450 (spr450), unsigned 32 bits
+	551: spr451 (spr451), unsigned 32 bits
+	552: spr452 (spr452), unsigned 32 bits
+	553: spr453 (spr453), unsigned 32 bits
+	554: spr454 (spr454), unsigned 32 bits
+	555: spr455 (spr455), unsigned 32 bits
+	556: spr456 (spr456), unsigned 32 bits
+	557: spr457 (spr457), unsigned 32 bits
+	558: spr458 (spr458), unsigned 32 bits
+	559: spr459 (spr459), unsigned 32 bits
+	560: spr460 (spr460), unsigned 32 bits
+	561: spr461 (spr461), unsigned 32 bits
+	562: spr462 (spr462), unsigned 32 bits
+	563: spr463 (spr463), unsigned 32 bits
+	564: spr464 (spr464), unsigned 32 bits
+	565: spr465 (spr465), unsigned 32 bits
+	566: spr466 (spr466), unsigned 32 bits
+	567: spr467 (spr467), unsigned 32 bits
+	568: spr468 (spr468), unsigned 32 bits
+	569: spr469 (spr469), unsigned 32 bits
+	570: spr470 (spr470), unsigned 32 bits
+	571: spr471 (spr471), unsigned 32 bits
+	572: spr472 (spr472), unsigned 32 bits
+	573: spr473 (spr473), unsigned 32 bits
+	574: spr474 (spr474), unsigned 32 bits
+	575: spr475 (spr475), unsigned 32 bits
+	576: spr476 (spr476), unsigned 32 bits
+	577: spr477 (spr477), unsigned 32 bits
+	578: spr478 (spr478), unsigned 32 bits
+	579: spr479 (spr479), unsigned 32 bits
+	580: spr480 (spr480), unsigned 32 bits
+	581: spr481 (spr481), unsigned 32 bits
+	582: spr482 (spr482), unsigned 32 bits
+	583: spr483 (spr483), unsigned 32 bits
+	584: spr484 (spr484), unsigned 32 bits
+	585: spr485 (spr485), unsigned 32 bits
+	586: spr486 (spr486), unsigned 32 bits
+	587: spr487 (spr487), unsigned 32 bits
+	588: spr488 (spr488), unsigned 32 bits
+	589: spr489 (spr489), unsigned 32 bits
+	590: spr490 (spr490), unsigned 32 bits
+	591: spr491 (spr491), unsigned 32 bits
+	592: spr492 (spr492), unsigned 32 bits
+	593: spr493 (spr493), unsigned 32 bits
+	594: spr494 (spr494), unsigned 32 bits
+	595: spr495 (spr495), unsigned 32 bits
+	596: spr496 (spr496), unsigned 32 bits
+	597: spr497 (spr497), unsigned 32 bits
+	598: spr498 (spr498), unsigned 32 bits
+	599: spr499 (spr499), unsigned 32 bits
+	600: spr500 (spr500), unsigned 32 bits
+	601: spr501 (spr501), unsigned 32 bits
+	602: spr502 (spr502), unsigned 32 bits
+	603: spr503 (spr503), unsigned 32 bits
+	604: spr504 (spr504), unsigned 32 bits
+	605: spr505 (spr505), unsigned 32 bits
+	606: spr506 (spr506), unsigned 32 bits
+	607: spr507 (spr507), unsigned 32 bits
+	608: spr508 (spr508), unsigned 32 bits
+	609: spr509 (spr509), unsigned 32 bits
+	610: spr510 (spr510), unsigned 32 bits
+	611: spr511 (spr511), unsigned 32 bits
+	613: spr513 (spr513), unsigned 32 bits
+	614: spr514 (spr514), unsigned 32 bits
+	615: spr515 (spr515), unsigned 32 bits
+	616: spr516 (spr516), unsigned 32 bits
+	617: spr517 (spr517), unsigned 32 bits
+	618: spr518 (spr518), unsigned 32 bits
+	619: spr519 (spr519), unsigned 32 bits
+	620: spr520 (spr520), unsigned 32 bits
+	621: spr521 (spr521), unsigned 32 bits
+	622: spr522 (spr522), unsigned 32 bits
+	623: spr523 (spr523), unsigned 32 bits
+	624: spr524 (spr524), unsigned 32 bits
+	625: spr525 (spr525), unsigned 32 bits
+	626: spr526 (spr526), unsigned 32 bits
+	627: spr527 (spr527), unsigned 32 bits
+	628: spr528 (spr528), unsigned 32 bits
+	629: spr529 (spr529), unsigned 32 bits
+	630: spr530 (spr530), unsigned 32 bits
+	631: spr531 (spr531), unsigned 32 bits
+	632: spr532 (spr532), unsigned 32 bits
+	633: spr533 (spr533), unsigned 32 bits
+	634: spr534 (spr534), unsigned 32 bits
+	635: spr535 (spr535), unsigned 32 bits
+	636: spr536 (spr536), unsigned 32 bits
+	637: spr537 (spr537), unsigned 32 bits
+	638: spr538 (spr538), unsigned 32 bits
+	639: spr539 (spr539), unsigned 32 bits
+	640: spr540 (spr540), unsigned 32 bits
+	641: spr541 (spr541), unsigned 32 bits
+	642: spr542 (spr542), unsigned 32 bits
+	643: spr543 (spr543), unsigned 32 bits
+	644: spr544 (spr544), unsigned 32 bits
+	645: spr545 (spr545), unsigned 32 bits
+	646: spr546 (spr546), unsigned 32 bits
+	647: spr547 (spr547), unsigned 32 bits
+	648: spr548 (spr548), unsigned 32 bits
+	649: spr549 (spr549), unsigned 32 bits
+	650: spr550 (spr550), unsigned 32 bits
+	651: spr551 (spr551), unsigned 32 bits
+	652: spr552 (spr552), unsigned 32 bits
+	653: spr553 (spr553), unsigned 32 bits
+	654: spr554 (spr554), unsigned 32 bits
+	655: spr555 (spr555), unsigned 32 bits
+	656: spr556 (spr556), unsigned 32 bits
+	657: spr557 (spr557), unsigned 32 bits
+	658: spr558 (spr558), unsigned 32 bits
+	659: spr559 (spr559), unsigned 32 bits
+	660: spr560 (spr560), unsigned 32 bits
+	661: spr561 (spr561), unsigned 32 bits
+	662: spr562 (spr562), unsigned 32 bits
+	663: spr563 (spr563), unsigned 32 bits
+	664: spr564 (spr564), unsigned 32 bits
+	665: spr565 (spr565), unsigned 32 bits
+	666: spr566 (spr566), unsigned 32 bits
+	667: spr567 (spr567), unsigned 32 bits
+	668: spr568 (spr568), unsigned 32 bits
+	669: spr569 (spr569), unsigned 32 bits
+	670: spr570 (spr570), unsigned 32 bits
+	671: spr571 (spr571), unsigned 32 bits
+	672: spr572 (spr572), unsigned 32 bits
+	673: spr573 (spr573), unsigned 32 bits
+	674: spr574 (spr574), unsigned 32 bits
+	675: spr575 (spr575), unsigned 32 bits
+	676: spr576 (spr576), unsigned 32 bits
+	677: spr577 (spr577), unsigned 32 bits
+	678: spr578 (spr578), unsigned 32 bits
+	679: spr579 (spr579), unsigned 32 bits
+	680: spr580 (spr580), unsigned 32 bits
+	681: spr581 (spr581), unsigned 32 bits
+	682: spr582 (spr582), unsigned 32 bits
+	683: spr583 (spr583), unsigned 32 bits
+	684: spr584 (spr584), unsigned 32 bits
+	685: spr585 (spr585), unsigned 32 bits
+	686: spr586 (spr586), unsigned 32 bits
+	687: spr587 (spr587), unsigned 32 bits
+	688: spr588 (spr588), unsigned 32 bits
+	689: spr589 (spr589), unsigned 32 bits
+	690: spr590 (spr590), unsigned 32 bits
+	691: spr591 (spr591), unsigned 32 bits
+	692: spr592 (spr592), unsigned 32 bits
+	693: spr593 (spr593), unsigned 32 bits
+	694: spr594 (spr594), unsigned 32 bits
+	695: spr595 (spr595), unsigned 32 bits
+	696: spr596 (spr596), unsigned 32 bits
+	697: spr597 (spr597), unsigned 32 bits
+	698: spr598 (spr598), unsigned 32 bits
+	699: spr599 (spr599), unsigned 32 bits
+	700: spr600 (spr600), unsigned 32 bits
+	701: spr601 (spr601), unsigned 32 bits
+	702: spr602 (spr602), unsigned 32 bits
+	703: spr603 (spr603), unsigned 32 bits
+	704: spr604 (spr604), unsigned 32 bits
+	705: spr605 (spr605), unsigned 32 bits
+	706: spr606 (spr606), unsigned 32 bits
+	707: spr607 (spr607), unsigned 32 bits
+	708: spr608 (spr608), unsigned 32 bits
+	709: spr609 (spr609), unsigned 32 bits
+	710: spr610 (spr610), unsigned 32 bits
+	711: spr611 (spr611), unsigned 32 bits
+	712: spr612 (spr612), unsigned 32 bits
+	713: spr613 (spr613), unsigned 32 bits
+	714: spr614 (spr614), unsigned 32 bits
+	715: spr615 (spr615), unsigned 32 bits
+	716: spr616 (spr616), unsigned 32 bits
+	717: spr617 (spr617), unsigned 32 bits
+	718: spr618 (spr618), unsigned 32 bits
+	719: spr619 (spr619), unsigned 32 bits
+	720: spr620 (spr620), unsigned 32 bits
+	721: spr621 (spr621), unsigned 32 bits
+	722: spr622 (spr622), unsigned 32 bits
+	723: spr623 (spr623), unsigned 32 bits
+	724: spr624 (spr624), unsigned 32 bits
+	725: spr625 (spr625), unsigned 32 bits
+	726: spr626 (spr626), unsigned 32 bits
+	727: spr627 (spr627), unsigned 32 bits
+	728: spr628 (spr628), unsigned 32 bits
+	729: spr629 (spr629), unsigned 32 bits
+	730: spr630 (spr630), unsigned 32 bits
+	731: spr631 (spr631), unsigned 32 bits
+	732: spr632 (spr632), unsigned 32 bits
+	733: spr633 (spr633), unsigned 32 bits
+	734: spr634 (spr634), unsigned 32 bits
+	735: spr635 (spr635), unsigned 32 bits
+	736: spr636 (spr636), unsigned 32 bits
+	737: spr637 (spr637), unsigned 32 bits
+	738: spr638 (spr638), unsigned 32 bits
+	739: spr639 (spr639), unsigned 32 bits
+	740: spr640 (spr640), unsigned 32 bits
+	741: spr641 (spr641), unsigned 32 bits
+	742: spr642 (spr642), unsigned 32 bits
+	743: spr643 (spr643), unsigned 32 bits
+	744: spr644 (spr644), unsigned 32 bits
+	745: spr645 (spr645), unsigned 32 bits
+	746: spr646 (spr646), unsigned 32 bits
+	747: spr647 (spr647), unsigned 32 bits
+	748: spr648 (spr648), unsigned 32 bits
+	749: spr649 (spr649), unsigned 32 bits
+	750: spr650 (spr650), unsigned 32 bits
+	751: spr651 (spr651), unsigned 32 bits
+	752: spr652 (spr652), unsigned 32 bits
+	753: spr653 (spr653), unsigned 32 bits
+	754: spr654 (spr654), unsigned 32 bits
+	755: spr655 (spr655), unsigned 32 bits
+	756: spr656 (spr656), unsigned 32 bits
+	757: spr657 (spr657), unsigned 32 bits
+	758: spr658 (spr658), unsigned 32 bits
+	759: spr659 (spr659), unsigned 32 bits
+	760: spr660 (spr660), unsigned 32 bits
+	761: spr661 (spr661), unsigned 32 bits
+	762: spr662 (spr662), unsigned 32 bits
+	763: spr663 (spr663), unsigned 32 bits
+	764: spr664 (spr664), unsigned 32 bits
+	765: spr665 (spr665), unsigned 32 bits
+	766: spr666 (spr666), unsigned 32 bits
+	767: spr667 (spr667), unsigned 32 bits
+	768: spr668 (spr668), unsigned 32 bits
+	769: spr669 (spr669), unsigned 32 bits
+	770: spr670 (spr670), unsigned 32 bits
+	771: spr671 (spr671), unsigned 32 bits
+	772: spr672 (spr672), unsigned 32 bits
+	773: spr673 (spr673), unsigned 32 bits
+	774: spr674 (spr674), unsigned 32 bits
+	775: spr675 (spr675), unsigned 32 bits
+	776: spr676 (spr676), unsigned 32 bits
+	777: spr677 (spr677), unsigned 32 bits
+	778: spr678 (spr678), unsigned 32 bits
+	779: spr679 (spr679), unsigned 32 bits
+	780: spr680 (spr680), unsigned 32 bits
+	781: spr681 (spr681), unsigned 32 bits
+	782: spr682 (spr682), unsigned 32 bits
+	783: spr683 (spr683), unsigned 32 bits
+	784: spr684 (spr684), unsigned 32 bits
+	785: spr685 (spr685), unsigned 32 bits
+	786: spr686 (spr686), unsigned 32 bits
+	787: spr687 (spr687), unsigned 32 bits
+	788: spr688 (spr688), unsigned 32 bits
+	789: spr689 (spr689), unsigned 32 bits
+	790: spr690 (spr690), unsigned 32 bits
+	791: spr691 (spr691), unsigned 32 bits
+	792: spr692 (spr692), unsigned 32 bits
+	793: spr693 (spr693), unsigned 32 bits
+	794: spr694 (spr694), unsigned 32 bits
+	795: spr695 (spr695), unsigned 32 bits
+	796: spr696 (spr696), unsigned 32 bits
+	797: spr697 (spr697), unsigned 32 bits
+	798: spr698 (spr698), unsigned 32 bits
+	799: spr699 (spr699), unsigned 32 bits
+	800: spr700 (spr700), unsigned 32 bits
+	801: spr701 (spr701), unsigned 32 bits
+	802: spr702 (spr702), unsigned 32 bits
+	803: spr703 (spr703), unsigned 32 bits
+	804: spr704 (spr704), unsigned 32 bits
+	805: spr705 (spr705), unsigned 32 bits
+	806: spr706 (spr706), unsigned 32 bits
+	807: spr707 (spr707), unsigned 32 bits
+	808: spr708 (spr708), unsigned 32 bits
+	809: spr709 (spr709), unsigned 32 bits
+	810: spr710 (spr710), unsigned 32 bits
+	811: spr711 (spr711), unsigned 32 bits
+	812: spr712 (spr712), unsigned 32 bits
+	813: spr713 (spr713), unsigned 32 bits
+	814: spr714 (spr714), unsigned 32 bits
+	815: spr715 (spr715), unsigned 32 bits
+	816: spr716 (spr716), unsigned 32 bits
+	817: spr717 (spr717), unsigned 32 bits
+	818: spr718 (spr718), unsigned 32 bits
+	819: spr719 (spr719), unsigned 32 bits
+	820: spr720 (spr720), unsigned 32 bits
+	821: spr721 (spr721), unsigned 32 bits
+	822: spr722 (spr722), unsigned 32 bits
+	823: spr723 (spr723), unsigned 32 bits
+	824: spr724 (spr724), unsigned 32 bits
+	825: spr725 (spr725), unsigned 32 bits
+	826: spr726 (spr726), unsigned 32 bits
+	827: spr727 (spr727), unsigned 32 bits
+	828: spr728 (spr728), unsigned 32 bits
+	829: spr729 (spr729), unsigned 32 bits
+	830: spr730 (spr730), unsigned 32 bits
+	831: spr731 (spr731), unsigned 32 bits
+	832: spr732 (spr732), unsigned 32 bits
+	833: spr733 (spr733), unsigned 32 bits
+	834: spr734 (spr734), unsigned 32 bits
+	835: spr735 (spr735), unsigned 32 bits
+	836: spr736 (spr736), unsigned 32 bits
+	837: spr737 (spr737), unsigned 32 bits
+	838: spr738 (spr738), unsigned 32 bits
+	839: spr739 (spr739), unsigned 32 bits
+	840: spr740 (spr740), unsigned 32 bits
+	841: spr741 (spr741), unsigned 32 bits
+	842: spr742 (spr742), unsigned 32 bits
+	843: spr743 (spr743), unsigned 32 bits
+	844: spr744 (spr744), unsigned 32 bits
+	845: spr745 (spr745), unsigned 32 bits
+	846: spr746 (spr746), unsigned 32 bits
+	847: spr747 (spr747), unsigned 32 bits
+	848: spr748 (spr748), unsigned 32 bits
+	849: spr749 (spr749), unsigned 32 bits
+	850: spr750 (spr750), unsigned 32 bits
+	851: spr751 (spr751), unsigned 32 bits
+	852: spr752 (spr752), unsigned 32 bits
+	853: spr753 (spr753), unsigned 32 bits
+	854: spr754 (spr754), unsigned 32 bits
+	855: spr755 (spr755), unsigned 32 bits
+	856: spr756 (spr756), unsigned 32 bits
+	857: spr757 (spr757), unsigned 32 bits
+	858: spr758 (spr758), unsigned 32 bits
+	859: spr759 (spr759), unsigned 32 bits
+	860: spr760 (spr760), unsigned 32 bits
+	861: spr761 (spr761), unsigned 32 bits
+	862: spr762 (spr762), unsigned 32 bits
+	863: spr763 (spr763), unsigned 32 bits
+	864: spr764 (spr764), unsigned 32 bits
+	865: spr765 (spr765), unsigned 32 bits
+	866: spr766 (spr766), unsigned 32 bits
+	867: spr767 (spr767), unsigned 32 bits
+	868: spr768 (spr768), unsigned 32 bits
+	869: spr769 (spr769), unsigned 32 bits
+	870: spr770 (spr770), unsigned 32 bits
+	871: spr771 (spr771), unsigned 32 bits
+	872: spr772 (spr772), unsigned 32 bits
+	873: spr773 (spr773), unsigned 32 bits
+	874: spr774 (spr774), unsigned 32 bits
+	875: spr775 (spr775), unsigned 32 bits
+	876: spr776 (spr776), unsigned 32 bits
+	877: spr777 (spr777), unsigned 32 bits
+	878: spr778 (spr778), unsigned 32 bits
+	879: spr779 (spr779), unsigned 32 bits
+	880: spr780 (spr780), unsigned 32 bits
+	881: spr781 (spr781), unsigned 32 bits
+	882: spr782 (spr782), unsigned 32 bits
+	883: spr783 (spr783), unsigned 32 bits
+	884: spr784 (spr784), unsigned 32 bits
+	885: spr785 (spr785), unsigned 32 bits
+	886: spr786 (spr786), unsigned 32 bits
+	887: spr787 (spr787), unsigned 32 bits
+	888: spr788 (spr788), unsigned 32 bits
+	889: spr789 (spr789), unsigned 32 bits
+	890: spr790 (spr790), unsigned 32 bits
+	891: spr791 (spr791), unsigned 32 bits
+	892: spr792 (spr792), unsigned 32 bits
+	893: spr793 (spr793), unsigned 32 bits
+	894: spr794 (spr794), unsigned 32 bits
+	895: spr795 (spr795), unsigned 32 bits
+	896: spr796 (spr796), unsigned 32 bits
+	897: spr797 (spr797), unsigned 32 bits
+	898: spr798 (spr798), unsigned 32 bits
+	899: spr799 (spr799), unsigned 32 bits
+	900: spr800 (spr800), unsigned 32 bits
+	901: spr801 (spr801), unsigned 32 bits
+	902: spr802 (spr802), unsigned 32 bits
+	903: spr803 (spr803), unsigned 32 bits
+	904: spr804 (spr804), unsigned 32 bits
+	905: spr805 (spr805), unsigned 32 bits
+	906: spr806 (spr806), unsigned 32 bits
+	907: spr807 (spr807), unsigned 32 bits
+	908: spr808 (spr808), unsigned 32 bits
+	909: spr809 (spr809), unsigned 32 bits
+	910: spr810 (spr810), unsigned 32 bits
+	911: spr811 (spr811), unsigned 32 bits
+	912: spr812 (spr812), unsigned 32 bits
+	913: spr813 (spr813), unsigned 32 bits
+	914: spr814 (spr814), unsigned 32 bits
+	915: spr815 (spr815), unsigned 32 bits
+	916: spr816 (spr816), unsigned 32 bits
+	917: spr817 (spr817), unsigned 32 bits
+	918: spr818 (spr818), unsigned 32 bits
+	919: spr819 (spr819), unsigned 32 bits
+	920: spr820 (spr820), unsigned 32 bits
+	921: spr821 (spr821), unsigned 32 bits
+	922: spr822 (spr822), unsigned 32 bits
+	923: spr823 (spr823), unsigned 32 bits
+	924: spr824 (spr824), unsigned 32 bits
+	925: spr825 (spr825), unsigned 32 bits
+	926: spr826 (spr826), unsigned 32 bits
+	927: spr827 (spr827), unsigned 32 bits
+	928: spr828 (spr828), unsigned 32 bits
+	929: spr829 (spr829), unsigned 32 bits
+	930: spr830 (spr830), unsigned 32 bits
+	931: spr831 (spr831), unsigned 32 bits
+	932: spr832 (spr832), unsigned 32 bits
+	933: spr833 (spr833), unsigned 32 bits
+	934: spr834 (spr834), unsigned 32 bits
+	935: spr835 (spr835), unsigned 32 bits
+	936: spr836 (spr836), unsigned 32 bits
+	937: spr837 (spr837), unsigned 32 bits
+	938: spr838 (spr838), unsigned 32 bits
+	939: spr839 (spr839), unsigned 32 bits
+	940: spr840 (spr840), unsigned 32 bits
+	941: spr841 (spr841), unsigned 32 bits
+	942: spr842 (spr842), unsigned 32 bits
+	943: spr843 (spr843), unsigned 32 bits
+	944: spr844 (spr844), unsigned 32 bits
+	945: spr845 (spr845), unsigned 32 bits
+	946: spr846 (spr846), unsigned 32 bits
+	947: spr847 (spr847), unsigned 32 bits
+	948: spr848 (spr848), unsigned 32 bits
+	949: spr849 (spr849), unsigned 32 bits
+	950: spr850 (spr850), unsigned 32 bits
+	951: spr851 (spr851), unsigned 32 bits
+	952: spr852 (spr852), unsigned 32 bits
+	953: spr853 (spr853), unsigned 32 bits
+	954: spr854 (spr854), unsigned 32 bits
+	955: spr855 (spr855), unsigned 32 bits
+	956: spr856 (spr856), unsigned 32 bits
+	957: spr857 (spr857), unsigned 32 bits
+	958: spr858 (spr858), unsigned 32 bits
+	959: spr859 (spr859), unsigned 32 bits
+	960: spr860 (spr860), unsigned 32 bits
+	961: spr861 (spr861), unsigned 32 bits
+	962: spr862 (spr862), unsigned 32 bits
+	963: spr863 (spr863), unsigned 32 bits
+	964: spr864 (spr864), unsigned 32 bits
+	965: spr865 (spr865), unsigned 32 bits
+	966: spr866 (spr866), unsigned 32 bits
+	967: spr867 (spr867), unsigned 32 bits
+	968: spr868 (spr868), unsigned 32 bits
+	969: spr869 (spr869), unsigned 32 bits
+	970: spr870 (spr870), unsigned 32 bits
+	971: spr871 (spr871), unsigned 32 bits
+	972: spr872 (spr872), unsigned 32 bits
+	973: spr873 (spr873), unsigned 32 bits
+	974: spr874 (spr874), unsigned 32 bits
+	975: spr875 (spr875), unsigned 32 bits
+	976: spr876 (spr876), unsigned 32 bits
+	977: spr877 (spr877), unsigned 32 bits
+	978: spr878 (spr878), unsigned 32 bits
+	979: spr879 (spr879), unsigned 32 bits
+	980: spr880 (spr880), unsigned 32 bits
+	981: spr881 (spr881), unsigned 32 bits
+	982: spr882 (spr882), unsigned 32 bits
+	983: spr883 (spr883), unsigned 32 bits
+	984: spr884 (spr884), unsigned 32 bits
+	985: spr885 (spr885), unsigned 32 bits
+	986: spr886 (spr886), unsigned 32 bits
+	987: spr887 (spr887), unsigned 32 bits
+	988: spr888 (spr888), unsigned 32 bits
+	989: spr889 (spr889), unsigned 32 bits
+	990: spr890 (spr890), unsigned 32 bits
+	991: spr891 (spr891), unsigned 32 bits
+	992: spr892 (spr892), unsigned 32 bits
+	993: spr893 (spr893), unsigned 32 bits
+	994: spr894 (spr894), unsigned 32 bits
+	995: spr895 (spr895), unsigned 32 bits
+	996: spr896 (spr896), unsigned 32 bits
+	997: spr897 (spr897), unsigned 32 bits
+	998: spr898 (spr898), unsigned 32 bits
+	999: spr899 (spr899), unsigned 32 bits
+vector registers:
+	 67: vscr (vscr), unsigned 32 bits
+	356: vrsave (vrsave), unsigned 32 bits
+	612: spefscr (spefscr), unsigned 32 bits
+	1124: vr0 (vr0), unsigned 128 bits
+	1125: vr1 (vr1), unsigned 128 bits
+	1126: vr2 (vr2), unsigned 128 bits
+	1127: vr3 (vr3), unsigned 128 bits
+	1128: vr4 (vr4), unsigned 128 bits
+	1129: vr5 (vr5), unsigned 128 bits
+	1130: vr6 (vr6), unsigned 128 bits
+	1131: vr7 (vr7), unsigned 128 bits
+	1132: vr8 (vr8), unsigned 128 bits
+	1133: vr9 (vr9), unsigned 128 bits
+	1134: vr10 (vr10), unsigned 128 bits
+	1135: vr11 (vr11), unsigned 128 bits
+	1136: vr12 (vr12), unsigned 128 bits
+	1137: vr13 (vr13), unsigned 128 bits
+	1138: vr14 (vr14), unsigned 128 bits
+	1139: vr15 (vr15), unsigned 128 bits
+	1140: vr16 (vr16), unsigned 128 bits
+	1141: vr17 (vr17), unsigned 128 bits
+	1142: vr18 (vr18), unsigned 128 bits
+	1143: vr19 (vr19), unsigned 128 bits
+	1144: vr20 (vr20), unsigned 128 bits
+	1145: vr21 (vr21), unsigned 128 bits
+	1146: vr22 (vr22), unsigned 128 bits
+	1147: vr23 (vr23), unsigned 128 bits
+	1148: vr24 (vr24), unsigned 128 bits
+	1149: vr25 (vr25), unsigned 128 bits
+	1150: vr26 (vr26), unsigned 128 bits
+	1151: vr27 (vr27), unsigned 128 bits
+	1152: vr28 (vr28), unsigned 128 bits
+	1153: vr29 (vr29), unsigned 128 bits
+	1154: vr30 (vr30), unsigned 128 bits
+	1155: vr31 (vr31), unsigned 128 bits
+EOF
+
+regs_test testfile23 <<\EOF
+integer registers:
+	  0: r0 (r0), signed 64 bits
+	  1: r1 (r1), signed 64 bits
+	  2: r2 (r2), signed 64 bits
+	  3: r3 (r3), signed 64 bits
+	  4: r4 (r4), signed 64 bits
+	  5: r5 (r5), signed 64 bits
+	  6: r6 (r6), signed 64 bits
+	  7: r7 (r7), signed 64 bits
+	  8: r8 (r8), signed 64 bits
+	  9: r9 (r9), signed 64 bits
+	 10: r10 (r10), signed 64 bits
+	 11: r11 (r11), signed 64 bits
+	 12: r12 (r12), signed 64 bits
+	 13: r13 (r13), signed 64 bits
+	 14: r14 (r14), signed 64 bits
+	 15: r15 (r15), signed 64 bits
+	 16: r16 (r16), signed 64 bits
+	 17: r17 (r17), signed 64 bits
+	 18: r18 (r18), signed 64 bits
+	 19: r19 (r19), signed 64 bits
+	 20: r20 (r20), signed 64 bits
+	 21: r21 (r21), signed 64 bits
+	 22: r22 (r22), signed 64 bits
+	 23: r23 (r23), signed 64 bits
+	 24: r24 (r24), signed 64 bits
+	 25: r25 (r25), signed 64 bits
+	 26: r26 (r26), signed 64 bits
+	 27: r27 (r27), signed 64 bits
+	 28: r28 (r28), signed 64 bits
+	 29: r29 (r29), signed 64 bits
+	 30: r30 (r30), signed 64 bits
+	 31: r31 (r31), signed 64 bits
+	 64: cr (cr), unsigned 64 bits
+	 66: msr (msr), unsigned 64 bits
+FPU registers:
+	 32: f0 (f0), float 64 bits
+	 33: f1 (f1), float 64 bits
+	 34: f2 (f2), float 64 bits
+	 35: f3 (f3), float 64 bits
+	 36: f4 (f4), float 64 bits
+	 37: f5 (f5), float 64 bits
+	 38: f6 (f6), float 64 bits
+	 39: f7 (f7), float 64 bits
+	 40: f8 (f8), float 64 bits
+	 41: f9 (f9), float 64 bits
+	 42: f10 (f10), float 64 bits
+	 43: f11 (f11), float 64 bits
+	 44: f12 (f12), float 64 bits
+	 45: f13 (f13), float 64 bits
+	 46: f14 (f14), float 64 bits
+	 47: f15 (f15), float 64 bits
+	 48: f16 (f16), float 64 bits
+	 49: f17 (f17), float 64 bits
+	 50: f18 (f18), float 64 bits
+	 51: f19 (f19), float 64 bits
+	 52: f20 (f20), float 64 bits
+	 53: f21 (f21), float 64 bits
+	 54: f22 (f22), float 64 bits
+	 55: f23 (f23), float 64 bits
+	 56: f24 (f24), float 64 bits
+	 57: f25 (f25), float 64 bits
+	 58: f26 (f26), float 64 bits
+	 59: f27 (f27), float 64 bits
+	 60: f28 (f28), float 64 bits
+	 61: f29 (f29), float 64 bits
+	 62: f30 (f30), float 64 bits
+	 63: f31 (f31), float 64 bits
+	 65: fpscr (fpscr), unsigned 64 bits
+privileged registers:
+	 70: sr0 (sr0), unsigned 64 bits
+	 71: sr1 (sr1), unsigned 64 bits
+	 72: sr2 (sr2), unsigned 64 bits
+	 73: sr3 (sr3), unsigned 64 bits
+	 74: sr4 (sr4), unsigned 64 bits
+	 75: sr5 (sr5), unsigned 64 bits
+	 76: sr6 (sr6), unsigned 64 bits
+	 77: sr7 (sr7), unsigned 64 bits
+	 78: sr8 (sr8), unsigned 64 bits
+	 79: sr9 (sr9), unsigned 64 bits
+	 80: sr10 (sr10), unsigned 64 bits
+	 81: sr11 (sr11), unsigned 64 bits
+	 82: sr12 (sr12), unsigned 64 bits
+	 83: sr13 (sr13), unsigned 64 bits
+	 84: sr14 (sr14), unsigned 64 bits
+	 85: sr15 (sr15), unsigned 64 bits
+	100: spr0 (spr0), unsigned 64 bits
+	101: xer (xer), unsigned 64 bits
+	102: spr2 (spr2), unsigned 64 bits
+	103: spr3 (spr3), unsigned 64 bits
+	104: spr4 (spr4), unsigned 64 bits
+	105: spr5 (spr5), unsigned 64 bits
+	106: spr6 (spr6), unsigned 64 bits
+	107: spr7 (spr7), unsigned 64 bits
+	108: lr (lr), unsigned 64 bits
+	109: ctr (ctr), unsigned 64 bits
+	110: spr10 (spr10), unsigned 64 bits
+	111: spr11 (spr11), unsigned 64 bits
+	112: spr12 (spr12), unsigned 64 bits
+	113: spr13 (spr13), unsigned 64 bits
+	114: tfhar (tfhar), unsigned 64 bits
+	115: tfiar (tfiar), unsigned 64 bits
+	116: texasr (texasr), unsigned 64 bits
+	117: spr17 (spr17), unsigned 64 bits
+	118: dsisr (dsisr), unsigned 64 bits
+	119: dar (dar), unsigned 64 bits
+	120: spr20 (spr20), unsigned 64 bits
+	121: spr21 (spr21), unsigned 64 bits
+	122: dec (dec), unsigned 64 bits
+	123: spr23 (spr23), unsigned 64 bits
+	124: spr24 (spr24), unsigned 64 bits
+	125: spr25 (spr25), unsigned 64 bits
+	126: spr26 (spr26), unsigned 64 bits
+	127: spr27 (spr27), unsigned 64 bits
+	128: spr28 (spr28), unsigned 64 bits
+	129: spr29 (spr29), unsigned 64 bits
+	130: spr30 (spr30), unsigned 64 bits
+	131: spr31 (spr31), unsigned 64 bits
+	132: spr32 (spr32), unsigned 64 bits
+	133: spr33 (spr33), unsigned 64 bits
+	134: spr34 (spr34), unsigned 64 bits
+	135: spr35 (spr35), unsigned 64 bits
+	136: spr36 (spr36), unsigned 64 bits
+	137: spr37 (spr37), unsigned 64 bits
+	138: spr38 (spr38), unsigned 64 bits
+	139: spr39 (spr39), unsigned 64 bits
+	140: spr40 (spr40), unsigned 64 bits
+	141: spr41 (spr41), unsigned 64 bits
+	142: spr42 (spr42), unsigned 64 bits
+	143: spr43 (spr43), unsigned 64 bits
+	144: spr44 (spr44), unsigned 64 bits
+	145: spr45 (spr45), unsigned 64 bits
+	146: spr46 (spr46), unsigned 64 bits
+	147: spr47 (spr47), unsigned 64 bits
+	148: spr48 (spr48), unsigned 64 bits
+	149: spr49 (spr49), unsigned 64 bits
+	150: spr50 (spr50), unsigned 64 bits
+	151: spr51 (spr51), unsigned 64 bits
+	152: spr52 (spr52), unsigned 64 bits
+	153: spr53 (spr53), unsigned 64 bits
+	154: spr54 (spr54), unsigned 64 bits
+	155: spr55 (spr55), unsigned 64 bits
+	156: spr56 (spr56), unsigned 64 bits
+	157: spr57 (spr57), unsigned 64 bits
+	158: spr58 (spr58), unsigned 64 bits
+	159: spr59 (spr59), unsigned 64 bits
+	160: spr60 (spr60), unsigned 64 bits
+	161: spr61 (spr61), unsigned 64 bits
+	162: spr62 (spr62), unsigned 64 bits
+	163: spr63 (spr63), unsigned 64 bits
+	164: spr64 (spr64), unsigned 64 bits
+	165: spr65 (spr65), unsigned 64 bits
+	166: spr66 (spr66), unsigned 64 bits
+	167: spr67 (spr67), unsigned 64 bits
+	168: spr68 (spr68), unsigned 64 bits
+	169: spr69 (spr69), unsigned 64 bits
+	170: spr70 (spr70), unsigned 64 bits
+	171: spr71 (spr71), unsigned 64 bits
+	172: spr72 (spr72), unsigned 64 bits
+	173: spr73 (spr73), unsigned 64 bits
+	174: spr74 (spr74), unsigned 64 bits
+	175: spr75 (spr75), unsigned 64 bits
+	176: spr76 (spr76), unsigned 64 bits
+	177: spr77 (spr77), unsigned 64 bits
+	178: spr78 (spr78), unsigned 64 bits
+	179: spr79 (spr79), unsigned 64 bits
+	180: spr80 (spr80), unsigned 64 bits
+	181: spr81 (spr81), unsigned 64 bits
+	182: spr82 (spr82), unsigned 64 bits
+	183: spr83 (spr83), unsigned 64 bits
+	184: spr84 (spr84), unsigned 64 bits
+	185: spr85 (spr85), unsigned 64 bits
+	186: spr86 (spr86), unsigned 64 bits
+	187: spr87 (spr87), unsigned 64 bits
+	188: spr88 (spr88), unsigned 64 bits
+	189: spr89 (spr89), unsigned 64 bits
+	190: spr90 (spr90), unsigned 64 bits
+	191: spr91 (spr91), unsigned 64 bits
+	192: spr92 (spr92), unsigned 64 bits
+	193: spr93 (spr93), unsigned 64 bits
+	194: spr94 (spr94), unsigned 64 bits
+	195: spr95 (spr95), unsigned 64 bits
+	196: spr96 (spr96), unsigned 64 bits
+	197: spr97 (spr97), unsigned 64 bits
+	198: spr98 (spr98), unsigned 64 bits
+	199: spr99 (spr99), unsigned 64 bits
+	200: spr100 (spr100), unsigned 64 bits
+	201: spr101 (spr101), unsigned 64 bits
+	202: spr102 (spr102), unsigned 64 bits
+	203: spr103 (spr103), unsigned 64 bits
+	204: spr104 (spr104), unsigned 64 bits
+	205: spr105 (spr105), unsigned 64 bits
+	206: spr106 (spr106), unsigned 64 bits
+	207: spr107 (spr107), unsigned 64 bits
+	208: spr108 (spr108), unsigned 64 bits
+	209: spr109 (spr109), unsigned 64 bits
+	210: spr110 (spr110), unsigned 64 bits
+	211: spr111 (spr111), unsigned 64 bits
+	212: spr112 (spr112), unsigned 64 bits
+	213: spr113 (spr113), unsigned 64 bits
+	214: spr114 (spr114), unsigned 64 bits
+	215: spr115 (spr115), unsigned 64 bits
+	216: spr116 (spr116), unsigned 64 bits
+	217: spr117 (spr117), unsigned 64 bits
+	218: spr118 (spr118), unsigned 64 bits
+	219: spr119 (spr119), unsigned 64 bits
+	220: spr120 (spr120), unsigned 64 bits
+	221: spr121 (spr121), unsigned 64 bits
+	222: spr122 (spr122), unsigned 64 bits
+	223: spr123 (spr123), unsigned 64 bits
+	224: spr124 (spr124), unsigned 64 bits
+	225: spr125 (spr125), unsigned 64 bits
+	226: spr126 (spr126), unsigned 64 bits
+	227: spr127 (spr127), unsigned 64 bits
+	228: spr128 (spr128), unsigned 64 bits
+	229: spr129 (spr129), unsigned 64 bits
+	230: spr130 (spr130), unsigned 64 bits
+	231: spr131 (spr131), unsigned 64 bits
+	232: spr132 (spr132), unsigned 64 bits
+	233: spr133 (spr133), unsigned 64 bits
+	234: spr134 (spr134), unsigned 64 bits
+	235: spr135 (spr135), unsigned 64 bits
+	236: spr136 (spr136), unsigned 64 bits
+	237: spr137 (spr137), unsigned 64 bits
+	238: spr138 (spr138), unsigned 64 bits
+	239: spr139 (spr139), unsigned 64 bits
+	240: spr140 (spr140), unsigned 64 bits
+	241: spr141 (spr141), unsigned 64 bits
+	242: spr142 (spr142), unsigned 64 bits
+	243: spr143 (spr143), unsigned 64 bits
+	244: spr144 (spr144), unsigned 64 bits
+	245: spr145 (spr145), unsigned 64 bits
+	246: spr146 (spr146), unsigned 64 bits
+	247: spr147 (spr147), unsigned 64 bits
+	248: spr148 (spr148), unsigned 64 bits
+	249: spr149 (spr149), unsigned 64 bits
+	250: spr150 (spr150), unsigned 64 bits
+	251: spr151 (spr151), unsigned 64 bits
+	252: spr152 (spr152), unsigned 64 bits
+	253: spr153 (spr153), unsigned 64 bits
+	254: spr154 (spr154), unsigned 64 bits
+	255: spr155 (spr155), unsigned 64 bits
+	256: spr156 (spr156), unsigned 64 bits
+	257: spr157 (spr157), unsigned 64 bits
+	258: spr158 (spr158), unsigned 64 bits
+	259: spr159 (spr159), unsigned 64 bits
+	260: spr160 (spr160), unsigned 64 bits
+	261: spr161 (spr161), unsigned 64 bits
+	262: spr162 (spr162), unsigned 64 bits
+	263: spr163 (spr163), unsigned 64 bits
+	264: spr164 (spr164), unsigned 64 bits
+	265: spr165 (spr165), unsigned 64 bits
+	266: spr166 (spr166), unsigned 64 bits
+	267: spr167 (spr167), unsigned 64 bits
+	268: spr168 (spr168), unsigned 64 bits
+	269: spr169 (spr169), unsigned 64 bits
+	270: spr170 (spr170), unsigned 64 bits
+	271: spr171 (spr171), unsigned 64 bits
+	272: spr172 (spr172), unsigned 64 bits
+	273: spr173 (spr173), unsigned 64 bits
+	274: spr174 (spr174), unsigned 64 bits
+	275: spr175 (spr175), unsigned 64 bits
+	276: spr176 (spr176), unsigned 64 bits
+	277: spr177 (spr177), unsigned 64 bits
+	278: spr178 (spr178), unsigned 64 bits
+	279: spr179 (spr179), unsigned 64 bits
+	280: spr180 (spr180), unsigned 64 bits
+	281: spr181 (spr181), unsigned 64 bits
+	282: spr182 (spr182), unsigned 64 bits
+	283: spr183 (spr183), unsigned 64 bits
+	284: spr184 (spr184), unsigned 64 bits
+	285: spr185 (spr185), unsigned 64 bits
+	286: spr186 (spr186), unsigned 64 bits
+	287: spr187 (spr187), unsigned 64 bits
+	288: spr188 (spr188), unsigned 64 bits
+	289: spr189 (spr189), unsigned 64 bits
+	290: spr190 (spr190), unsigned 64 bits
+	291: spr191 (spr191), unsigned 64 bits
+	292: spr192 (spr192), unsigned 64 bits
+	293: spr193 (spr193), unsigned 64 bits
+	294: spr194 (spr194), unsigned 64 bits
+	295: spr195 (spr195), unsigned 64 bits
+	296: spr196 (spr196), unsigned 64 bits
+	297: spr197 (spr197), unsigned 64 bits
+	298: spr198 (spr198), unsigned 64 bits
+	299: spr199 (spr199), unsigned 64 bits
+	300: spr200 (spr200), unsigned 64 bits
+	301: spr201 (spr201), unsigned 64 bits
+	302: spr202 (spr202), unsigned 64 bits
+	303: spr203 (spr203), unsigned 64 bits
+	304: spr204 (spr204), unsigned 64 bits
+	305: spr205 (spr205), unsigned 64 bits
+	306: spr206 (spr206), unsigned 64 bits
+	307: spr207 (spr207), unsigned 64 bits
+	308: spr208 (spr208), unsigned 64 bits
+	309: spr209 (spr209), unsigned 64 bits
+	310: spr210 (spr210), unsigned 64 bits
+	311: spr211 (spr211), unsigned 64 bits
+	312: spr212 (spr212), unsigned 64 bits
+	313: spr213 (spr213), unsigned 64 bits
+	314: spr214 (spr214), unsigned 64 bits
+	315: spr215 (spr215), unsigned 64 bits
+	316: spr216 (spr216), unsigned 64 bits
+	317: spr217 (spr217), unsigned 64 bits
+	318: spr218 (spr218), unsigned 64 bits
+	319: spr219 (spr219), unsigned 64 bits
+	320: spr220 (spr220), unsigned 64 bits
+	321: spr221 (spr221), unsigned 64 bits
+	322: spr222 (spr222), unsigned 64 bits
+	323: spr223 (spr223), unsigned 64 bits
+	324: spr224 (spr224), unsigned 64 bits
+	325: spr225 (spr225), unsigned 64 bits
+	326: spr226 (spr226), unsigned 64 bits
+	327: spr227 (spr227), unsigned 64 bits
+	328: spr228 (spr228), unsigned 64 bits
+	329: spr229 (spr229), unsigned 64 bits
+	330: spr230 (spr230), unsigned 64 bits
+	331: spr231 (spr231), unsigned 64 bits
+	332: spr232 (spr232), unsigned 64 bits
+	333: spr233 (spr233), unsigned 64 bits
+	334: spr234 (spr234), unsigned 64 bits
+	335: spr235 (spr235), unsigned 64 bits
+	336: spr236 (spr236), unsigned 64 bits
+	337: spr237 (spr237), unsigned 64 bits
+	338: spr238 (spr238), unsigned 64 bits
+	339: spr239 (spr239), unsigned 64 bits
+	340: spr240 (spr240), unsigned 64 bits
+	341: spr241 (spr241), unsigned 64 bits
+	342: spr242 (spr242), unsigned 64 bits
+	343: spr243 (spr243), unsigned 64 bits
+	344: spr244 (spr244), unsigned 64 bits
+	345: spr245 (spr245), unsigned 64 bits
+	346: spr246 (spr246), unsigned 64 bits
+	347: spr247 (spr247), unsigned 64 bits
+	348: spr248 (spr248), unsigned 64 bits
+	349: spr249 (spr249), unsigned 64 bits
+	350: spr250 (spr250), unsigned 64 bits
+	351: spr251 (spr251), unsigned 64 bits
+	352: spr252 (spr252), unsigned 64 bits
+	353: spr253 (spr253), unsigned 64 bits
+	354: spr254 (spr254), unsigned 64 bits
+	355: spr255 (spr255), unsigned 64 bits
+	357: spr257 (spr257), unsigned 64 bits
+	358: spr258 (spr258), unsigned 64 bits
+	359: spr259 (spr259), unsigned 64 bits
+	360: spr260 (spr260), unsigned 64 bits
+	361: spr261 (spr261), unsigned 64 bits
+	362: spr262 (spr262), unsigned 64 bits
+	363: spr263 (spr263), unsigned 64 bits
+	364: spr264 (spr264), unsigned 64 bits
+	365: spr265 (spr265), unsigned 64 bits
+	366: spr266 (spr266), unsigned 64 bits
+	367: spr267 (spr267), unsigned 64 bits
+	368: spr268 (spr268), unsigned 64 bits
+	369: spr269 (spr269), unsigned 64 bits
+	370: spr270 (spr270), unsigned 64 bits
+	371: spr271 (spr271), unsigned 64 bits
+	372: spr272 (spr272), unsigned 64 bits
+	373: spr273 (spr273), unsigned 64 bits
+	374: spr274 (spr274), unsigned 64 bits
+	375: spr275 (spr275), unsigned 64 bits
+	376: spr276 (spr276), unsigned 64 bits
+	377: spr277 (spr277), unsigned 64 bits
+	378: spr278 (spr278), unsigned 64 bits
+	379: spr279 (spr279), unsigned 64 bits
+	380: spr280 (spr280), unsigned 64 bits
+	381: spr281 (spr281), unsigned 64 bits
+	382: spr282 (spr282), unsigned 64 bits
+	383: spr283 (spr283), unsigned 64 bits
+	384: spr284 (spr284), unsigned 64 bits
+	385: spr285 (spr285), unsigned 64 bits
+	386: spr286 (spr286), unsigned 64 bits
+	387: spr287 (spr287), unsigned 64 bits
+	388: spr288 (spr288), unsigned 64 bits
+	389: spr289 (spr289), unsigned 64 bits
+	390: spr290 (spr290), unsigned 64 bits
+	391: spr291 (spr291), unsigned 64 bits
+	392: spr292 (spr292), unsigned 64 bits
+	393: spr293 (spr293), unsigned 64 bits
+	394: spr294 (spr294), unsigned 64 bits
+	395: spr295 (spr295), unsigned 64 bits
+	396: spr296 (spr296), unsigned 64 bits
+	397: spr297 (spr297), unsigned 64 bits
+	398: spr298 (spr298), unsigned 64 bits
+	399: spr299 (spr299), unsigned 64 bits
+	400: spr300 (spr300), unsigned 64 bits
+	401: spr301 (spr301), unsigned 64 bits
+	402: spr302 (spr302), unsigned 64 bits
+	403: spr303 (spr303), unsigned 64 bits
+	404: spr304 (spr304), unsigned 64 bits
+	405: spr305 (spr305), unsigned 64 bits
+	406: spr306 (spr306), unsigned 64 bits
+	407: spr307 (spr307), unsigned 64 bits
+	408: spr308 (spr308), unsigned 64 bits
+	409: spr309 (spr309), unsigned 64 bits
+	410: spr310 (spr310), unsigned 64 bits
+	411: spr311 (spr311), unsigned 64 bits
+	412: spr312 (spr312), unsigned 64 bits
+	413: spr313 (spr313), unsigned 64 bits
+	414: spr314 (spr314), unsigned 64 bits
+	415: spr315 (spr315), unsigned 64 bits
+	416: spr316 (spr316), unsigned 64 bits
+	417: spr317 (spr317), unsigned 64 bits
+	418: spr318 (spr318), unsigned 64 bits
+	419: spr319 (spr319), unsigned 64 bits
+	420: spr320 (spr320), unsigned 64 bits
+	421: spr321 (spr321), unsigned 64 bits
+	422: spr322 (spr322), unsigned 64 bits
+	423: spr323 (spr323), unsigned 64 bits
+	424: spr324 (spr324), unsigned 64 bits
+	425: spr325 (spr325), unsigned 64 bits
+	426: spr326 (spr326), unsigned 64 bits
+	427: spr327 (spr327), unsigned 64 bits
+	428: spr328 (spr328), unsigned 64 bits
+	429: spr329 (spr329), unsigned 64 bits
+	430: spr330 (spr330), unsigned 64 bits
+	431: spr331 (spr331), unsigned 64 bits
+	432: spr332 (spr332), unsigned 64 bits
+	433: spr333 (spr333), unsigned 64 bits
+	434: spr334 (spr334), unsigned 64 bits
+	435: spr335 (spr335), unsigned 64 bits
+	436: spr336 (spr336), unsigned 64 bits
+	437: spr337 (spr337), unsigned 64 bits
+	438: spr338 (spr338), unsigned 64 bits
+	439: spr339 (spr339), unsigned 64 bits
+	440: spr340 (spr340), unsigned 64 bits
+	441: spr341 (spr341), unsigned 64 bits
+	442: spr342 (spr342), unsigned 64 bits
+	443: spr343 (spr343), unsigned 64 bits
+	444: spr344 (spr344), unsigned 64 bits
+	445: spr345 (spr345), unsigned 64 bits
+	446: spr346 (spr346), unsigned 64 bits
+	447: spr347 (spr347), unsigned 64 bits
+	448: spr348 (spr348), unsigned 64 bits
+	449: spr349 (spr349), unsigned 64 bits
+	450: spr350 (spr350), unsigned 64 bits
+	451: spr351 (spr351), unsigned 64 bits
+	452: spr352 (spr352), unsigned 64 bits
+	453: spr353 (spr353), unsigned 64 bits
+	454: spr354 (spr354), unsigned 64 bits
+	455: spr355 (spr355), unsigned 64 bits
+	456: spr356 (spr356), unsigned 64 bits
+	457: spr357 (spr357), unsigned 64 bits
+	458: spr358 (spr358), unsigned 64 bits
+	459: spr359 (spr359), unsigned 64 bits
+	460: spr360 (spr360), unsigned 64 bits
+	461: spr361 (spr361), unsigned 64 bits
+	462: spr362 (spr362), unsigned 64 bits
+	463: spr363 (spr363), unsigned 64 bits
+	464: spr364 (spr364), unsigned 64 bits
+	465: spr365 (spr365), unsigned 64 bits
+	466: spr366 (spr366), unsigned 64 bits
+	467: spr367 (spr367), unsigned 64 bits
+	468: spr368 (spr368), unsigned 64 bits
+	469: spr369 (spr369), unsigned 64 bits
+	470: spr370 (spr370), unsigned 64 bits
+	471: spr371 (spr371), unsigned 64 bits
+	472: spr372 (spr372), unsigned 64 bits
+	473: spr373 (spr373), unsigned 64 bits
+	474: spr374 (spr374), unsigned 64 bits
+	475: spr375 (spr375), unsigned 64 bits
+	476: spr376 (spr376), unsigned 64 bits
+	477: spr377 (spr377), unsigned 64 bits
+	478: spr378 (spr378), unsigned 64 bits
+	479: spr379 (spr379), unsigned 64 bits
+	480: spr380 (spr380), unsigned 64 bits
+	481: spr381 (spr381), unsigned 64 bits
+	482: spr382 (spr382), unsigned 64 bits
+	483: spr383 (spr383), unsigned 64 bits
+	484: spr384 (spr384), unsigned 64 bits
+	485: spr385 (spr385), unsigned 64 bits
+	486: spr386 (spr386), unsigned 64 bits
+	487: spr387 (spr387), unsigned 64 bits
+	488: spr388 (spr388), unsigned 64 bits
+	489: spr389 (spr389), unsigned 64 bits
+	490: spr390 (spr390), unsigned 64 bits
+	491: spr391 (spr391), unsigned 64 bits
+	492: spr392 (spr392), unsigned 64 bits
+	493: spr393 (spr393), unsigned 64 bits
+	494: spr394 (spr394), unsigned 64 bits
+	495: spr395 (spr395), unsigned 64 bits
+	496: spr396 (spr396), unsigned 64 bits
+	497: spr397 (spr397), unsigned 64 bits
+	498: spr398 (spr398), unsigned 64 bits
+	499: spr399 (spr399), unsigned 64 bits
+	500: spr400 (spr400), unsigned 64 bits
+	501: spr401 (spr401), unsigned 64 bits
+	502: spr402 (spr402), unsigned 64 bits
+	503: spr403 (spr403), unsigned 64 bits
+	504: spr404 (spr404), unsigned 64 bits
+	505: spr405 (spr405), unsigned 64 bits
+	506: spr406 (spr406), unsigned 64 bits
+	507: spr407 (spr407), unsigned 64 bits
+	508: spr408 (spr408), unsigned 64 bits
+	509: spr409 (spr409), unsigned 64 bits
+	510: spr410 (spr410), unsigned 64 bits
+	511: spr411 (spr411), unsigned 64 bits
+	512: spr412 (spr412), unsigned 64 bits
+	513: spr413 (spr413), unsigned 64 bits
+	514: spr414 (spr414), unsigned 64 bits
+	515: spr415 (spr415), unsigned 64 bits
+	516: spr416 (spr416), unsigned 64 bits
+	517: spr417 (spr417), unsigned 64 bits
+	518: spr418 (spr418), unsigned 64 bits
+	519: spr419 (spr419), unsigned 64 bits
+	520: spr420 (spr420), unsigned 64 bits
+	521: spr421 (spr421), unsigned 64 bits
+	522: spr422 (spr422), unsigned 64 bits
+	523: spr423 (spr423), unsigned 64 bits
+	524: spr424 (spr424), unsigned 64 bits
+	525: spr425 (spr425), unsigned 64 bits
+	526: spr426 (spr426), unsigned 64 bits
+	527: spr427 (spr427), unsigned 64 bits
+	528: spr428 (spr428), unsigned 64 bits
+	529: spr429 (spr429), unsigned 64 bits
+	530: spr430 (spr430), unsigned 64 bits
+	531: spr431 (spr431), unsigned 64 bits
+	532: spr432 (spr432), unsigned 64 bits
+	533: spr433 (spr433), unsigned 64 bits
+	534: spr434 (spr434), unsigned 64 bits
+	535: spr435 (spr435), unsigned 64 bits
+	536: spr436 (spr436), unsigned 64 bits
+	537: spr437 (spr437), unsigned 64 bits
+	538: spr438 (spr438), unsigned 64 bits
+	539: spr439 (spr439), unsigned 64 bits
+	540: spr440 (spr440), unsigned 64 bits
+	541: spr441 (spr441), unsigned 64 bits
+	542: spr442 (spr442), unsigned 64 bits
+	543: spr443 (spr443), unsigned 64 bits
+	544: spr444 (spr444), unsigned 64 bits
+	545: spr445 (spr445), unsigned 64 bits
+	546: spr446 (spr446), unsigned 64 bits
+	547: spr447 (spr447), unsigned 64 bits
+	548: spr448 (spr448), unsigned 64 bits
+	549: spr449 (spr449), unsigned 64 bits
+	550: spr450 (spr450), unsigned 64 bits
+	551: spr451 (spr451), unsigned 64 bits
+	552: spr452 (spr452), unsigned 64 bits
+	553: spr453 (spr453), unsigned 64 bits
+	554: spr454 (spr454), unsigned 64 bits
+	555: spr455 (spr455), unsigned 64 bits
+	556: spr456 (spr456), unsigned 64 bits
+	557: spr457 (spr457), unsigned 64 bits
+	558: spr458 (spr458), unsigned 64 bits
+	559: spr459 (spr459), unsigned 64 bits
+	560: spr460 (spr460), unsigned 64 bits
+	561: spr461 (spr461), unsigned 64 bits
+	562: spr462 (spr462), unsigned 64 bits
+	563: spr463 (spr463), unsigned 64 bits
+	564: spr464 (spr464), unsigned 64 bits
+	565: spr465 (spr465), unsigned 64 bits
+	566: spr466 (spr466), unsigned 64 bits
+	567: spr467 (spr467), unsigned 64 bits
+	568: spr468 (spr468), unsigned 64 bits
+	569: spr469 (spr469), unsigned 64 bits
+	570: spr470 (spr470), unsigned 64 bits
+	571: spr471 (spr471), unsigned 64 bits
+	572: spr472 (spr472), unsigned 64 bits
+	573: spr473 (spr473), unsigned 64 bits
+	574: spr474 (spr474), unsigned 64 bits
+	575: spr475 (spr475), unsigned 64 bits
+	576: spr476 (spr476), unsigned 64 bits
+	577: spr477 (spr477), unsigned 64 bits
+	578: spr478 (spr478), unsigned 64 bits
+	579: spr479 (spr479), unsigned 64 bits
+	580: spr480 (spr480), unsigned 64 bits
+	581: spr481 (spr481), unsigned 64 bits
+	582: spr482 (spr482), unsigned 64 bits
+	583: spr483 (spr483), unsigned 64 bits
+	584: spr484 (spr484), unsigned 64 bits
+	585: spr485 (spr485), unsigned 64 bits
+	586: spr486 (spr486), unsigned 64 bits
+	587: spr487 (spr487), unsigned 64 bits
+	588: spr488 (spr488), unsigned 64 bits
+	589: spr489 (spr489), unsigned 64 bits
+	590: spr490 (spr490), unsigned 64 bits
+	591: spr491 (spr491), unsigned 64 bits
+	592: spr492 (spr492), unsigned 64 bits
+	593: spr493 (spr493), unsigned 64 bits
+	594: spr494 (spr494), unsigned 64 bits
+	595: spr495 (spr495), unsigned 64 bits
+	596: spr496 (spr496), unsigned 64 bits
+	597: spr497 (spr497), unsigned 64 bits
+	598: spr498 (spr498), unsigned 64 bits
+	599: spr499 (spr499), unsigned 64 bits
+	600: spr500 (spr500), unsigned 64 bits
+	601: spr501 (spr501), unsigned 64 bits
+	602: spr502 (spr502), unsigned 64 bits
+	603: spr503 (spr503), unsigned 64 bits
+	604: spr504 (spr504), unsigned 64 bits
+	605: spr505 (spr505), unsigned 64 bits
+	606: spr506 (spr506), unsigned 64 bits
+	607: spr507 (spr507), unsigned 64 bits
+	608: spr508 (spr508), unsigned 64 bits
+	609: spr509 (spr509), unsigned 64 bits
+	610: spr510 (spr510), unsigned 64 bits
+	611: spr511 (spr511), unsigned 64 bits
+	613: spr513 (spr513), unsigned 64 bits
+	614: spr514 (spr514), unsigned 64 bits
+	615: spr515 (spr515), unsigned 64 bits
+	616: spr516 (spr516), unsigned 64 bits
+	617: spr517 (spr517), unsigned 64 bits
+	618: spr518 (spr518), unsigned 64 bits
+	619: spr519 (spr519), unsigned 64 bits
+	620: spr520 (spr520), unsigned 64 bits
+	621: spr521 (spr521), unsigned 64 bits
+	622: spr522 (spr522), unsigned 64 bits
+	623: spr523 (spr523), unsigned 64 bits
+	624: spr524 (spr524), unsigned 64 bits
+	625: spr525 (spr525), unsigned 64 bits
+	626: spr526 (spr526), unsigned 64 bits
+	627: spr527 (spr527), unsigned 64 bits
+	628: spr528 (spr528), unsigned 64 bits
+	629: spr529 (spr529), unsigned 64 bits
+	630: spr530 (spr530), unsigned 64 bits
+	631: spr531 (spr531), unsigned 64 bits
+	632: spr532 (spr532), unsigned 64 bits
+	633: spr533 (spr533), unsigned 64 bits
+	634: spr534 (spr534), unsigned 64 bits
+	635: spr535 (spr535), unsigned 64 bits
+	636: spr536 (spr536), unsigned 64 bits
+	637: spr537 (spr537), unsigned 64 bits
+	638: spr538 (spr538), unsigned 64 bits
+	639: spr539 (spr539), unsigned 64 bits
+	640: spr540 (spr540), unsigned 64 bits
+	641: spr541 (spr541), unsigned 64 bits
+	642: spr542 (spr542), unsigned 64 bits
+	643: spr543 (spr543), unsigned 64 bits
+	644: spr544 (spr544), unsigned 64 bits
+	645: spr545 (spr545), unsigned 64 bits
+	646: spr546 (spr546), unsigned 64 bits
+	647: spr547 (spr547), unsigned 64 bits
+	648: spr548 (spr548), unsigned 64 bits
+	649: spr549 (spr549), unsigned 64 bits
+	650: spr550 (spr550), unsigned 64 bits
+	651: spr551 (spr551), unsigned 64 bits
+	652: spr552 (spr552), unsigned 64 bits
+	653: spr553 (spr553), unsigned 64 bits
+	654: spr554 (spr554), unsigned 64 bits
+	655: spr555 (spr555), unsigned 64 bits
+	656: spr556 (spr556), unsigned 64 bits
+	657: spr557 (spr557), unsigned 64 bits
+	658: spr558 (spr558), unsigned 64 bits
+	659: spr559 (spr559), unsigned 64 bits
+	660: spr560 (spr560), unsigned 64 bits
+	661: spr561 (spr561), unsigned 64 bits
+	662: spr562 (spr562), unsigned 64 bits
+	663: spr563 (spr563), unsigned 64 bits
+	664: spr564 (spr564), unsigned 64 bits
+	665: spr565 (spr565), unsigned 64 bits
+	666: spr566 (spr566), unsigned 64 bits
+	667: spr567 (spr567), unsigned 64 bits
+	668: spr568 (spr568), unsigned 64 bits
+	669: spr569 (spr569), unsigned 64 bits
+	670: spr570 (spr570), unsigned 64 bits
+	671: spr571 (spr571), unsigned 64 bits
+	672: spr572 (spr572), unsigned 64 bits
+	673: spr573 (spr573), unsigned 64 bits
+	674: spr574 (spr574), unsigned 64 bits
+	675: spr575 (spr575), unsigned 64 bits
+	676: spr576 (spr576), unsigned 64 bits
+	677: spr577 (spr577), unsigned 64 bits
+	678: spr578 (spr578), unsigned 64 bits
+	679: spr579 (spr579), unsigned 64 bits
+	680: spr580 (spr580), unsigned 64 bits
+	681: spr581 (spr581), unsigned 64 bits
+	682: spr582 (spr582), unsigned 64 bits
+	683: spr583 (spr583), unsigned 64 bits
+	684: spr584 (spr584), unsigned 64 bits
+	685: spr585 (spr585), unsigned 64 bits
+	686: spr586 (spr586), unsigned 64 bits
+	687: spr587 (spr587), unsigned 64 bits
+	688: spr588 (spr588), unsigned 64 bits
+	689: spr589 (spr589), unsigned 64 bits
+	690: spr590 (spr590), unsigned 64 bits
+	691: spr591 (spr591), unsigned 64 bits
+	692: spr592 (spr592), unsigned 64 bits
+	693: spr593 (spr593), unsigned 64 bits
+	694: spr594 (spr594), unsigned 64 bits
+	695: spr595 (spr595), unsigned 64 bits
+	696: spr596 (spr596), unsigned 64 bits
+	697: spr597 (spr597), unsigned 64 bits
+	698: spr598 (spr598), unsigned 64 bits
+	699: spr599 (spr599), unsigned 64 bits
+	700: spr600 (spr600), unsigned 64 bits
+	701: spr601 (spr601), unsigned 64 bits
+	702: spr602 (spr602), unsigned 64 bits
+	703: spr603 (spr603), unsigned 64 bits
+	704: spr604 (spr604), unsigned 64 bits
+	705: spr605 (spr605), unsigned 64 bits
+	706: spr606 (spr606), unsigned 64 bits
+	707: spr607 (spr607), unsigned 64 bits
+	708: spr608 (spr608), unsigned 64 bits
+	709: spr609 (spr609), unsigned 64 bits
+	710: spr610 (spr610), unsigned 64 bits
+	711: spr611 (spr611), unsigned 64 bits
+	712: spr612 (spr612), unsigned 64 bits
+	713: spr613 (spr613), unsigned 64 bits
+	714: spr614 (spr614), unsigned 64 bits
+	715: spr615 (spr615), unsigned 64 bits
+	716: spr616 (spr616), unsigned 64 bits
+	717: spr617 (spr617), unsigned 64 bits
+	718: spr618 (spr618), unsigned 64 bits
+	719: spr619 (spr619), unsigned 64 bits
+	720: spr620 (spr620), unsigned 64 bits
+	721: spr621 (spr621), unsigned 64 bits
+	722: spr622 (spr622), unsigned 64 bits
+	723: spr623 (spr623), unsigned 64 bits
+	724: spr624 (spr624), unsigned 64 bits
+	725: spr625 (spr625), unsigned 64 bits
+	726: spr626 (spr626), unsigned 64 bits
+	727: spr627 (spr627), unsigned 64 bits
+	728: spr628 (spr628), unsigned 64 bits
+	729: spr629 (spr629), unsigned 64 bits
+	730: spr630 (spr630), unsigned 64 bits
+	731: spr631 (spr631), unsigned 64 bits
+	732: spr632 (spr632), unsigned 64 bits
+	733: spr633 (spr633), unsigned 64 bits
+	734: spr634 (spr634), unsigned 64 bits
+	735: spr635 (spr635), unsigned 64 bits
+	736: spr636 (spr636), unsigned 64 bits
+	737: spr637 (spr637), unsigned 64 bits
+	738: spr638 (spr638), unsigned 64 bits
+	739: spr639 (spr639), unsigned 64 bits
+	740: spr640 (spr640), unsigned 64 bits
+	741: spr641 (spr641), unsigned 64 bits
+	742: spr642 (spr642), unsigned 64 bits
+	743: spr643 (spr643), unsigned 64 bits
+	744: spr644 (spr644), unsigned 64 bits
+	745: spr645 (spr645), unsigned 64 bits
+	746: spr646 (spr646), unsigned 64 bits
+	747: spr647 (spr647), unsigned 64 bits
+	748: spr648 (spr648), unsigned 64 bits
+	749: spr649 (spr649), unsigned 64 bits
+	750: spr650 (spr650), unsigned 64 bits
+	751: spr651 (spr651), unsigned 64 bits
+	752: spr652 (spr652), unsigned 64 bits
+	753: spr653 (spr653), unsigned 64 bits
+	754: spr654 (spr654), unsigned 64 bits
+	755: spr655 (spr655), unsigned 64 bits
+	756: spr656 (spr656), unsigned 64 bits
+	757: spr657 (spr657), unsigned 64 bits
+	758: spr658 (spr658), unsigned 64 bits
+	759: spr659 (spr659), unsigned 64 bits
+	760: spr660 (spr660), unsigned 64 bits
+	761: spr661 (spr661), unsigned 64 bits
+	762: spr662 (spr662), unsigned 64 bits
+	763: spr663 (spr663), unsigned 64 bits
+	764: spr664 (spr664), unsigned 64 bits
+	765: spr665 (spr665), unsigned 64 bits
+	766: spr666 (spr666), unsigned 64 bits
+	767: spr667 (spr667), unsigned 64 bits
+	768: spr668 (spr668), unsigned 64 bits
+	769: spr669 (spr669), unsigned 64 bits
+	770: spr670 (spr670), unsigned 64 bits
+	771: spr671 (spr671), unsigned 64 bits
+	772: spr672 (spr672), unsigned 64 bits
+	773: spr673 (spr673), unsigned 64 bits
+	774: spr674 (spr674), unsigned 64 bits
+	775: spr675 (spr675), unsigned 64 bits
+	776: spr676 (spr676), unsigned 64 bits
+	777: spr677 (spr677), unsigned 64 bits
+	778: spr678 (spr678), unsigned 64 bits
+	779: spr679 (spr679), unsigned 64 bits
+	780: spr680 (spr680), unsigned 64 bits
+	781: spr681 (spr681), unsigned 64 bits
+	782: spr682 (spr682), unsigned 64 bits
+	783: spr683 (spr683), unsigned 64 bits
+	784: spr684 (spr684), unsigned 64 bits
+	785: spr685 (spr685), unsigned 64 bits
+	786: spr686 (spr686), unsigned 64 bits
+	787: spr687 (spr687), unsigned 64 bits
+	788: spr688 (spr688), unsigned 64 bits
+	789: spr689 (spr689), unsigned 64 bits
+	790: spr690 (spr690), unsigned 64 bits
+	791: spr691 (spr691), unsigned 64 bits
+	792: spr692 (spr692), unsigned 64 bits
+	793: spr693 (spr693), unsigned 64 bits
+	794: spr694 (spr694), unsigned 64 bits
+	795: spr695 (spr695), unsigned 64 bits
+	796: spr696 (spr696), unsigned 64 bits
+	797: spr697 (spr697), unsigned 64 bits
+	798: spr698 (spr698), unsigned 64 bits
+	799: spr699 (spr699), unsigned 64 bits
+	800: spr700 (spr700), unsigned 64 bits
+	801: spr701 (spr701), unsigned 64 bits
+	802: spr702 (spr702), unsigned 64 bits
+	803: spr703 (spr703), unsigned 64 bits
+	804: spr704 (spr704), unsigned 64 bits
+	805: spr705 (spr705), unsigned 64 bits
+	806: spr706 (spr706), unsigned 64 bits
+	807: spr707 (spr707), unsigned 64 bits
+	808: spr708 (spr708), unsigned 64 bits
+	809: spr709 (spr709), unsigned 64 bits
+	810: spr710 (spr710), unsigned 64 bits
+	811: spr711 (spr711), unsigned 64 bits
+	812: spr712 (spr712), unsigned 64 bits
+	813: spr713 (spr713), unsigned 64 bits
+	814: spr714 (spr714), unsigned 64 bits
+	815: spr715 (spr715), unsigned 64 bits
+	816: spr716 (spr716), unsigned 64 bits
+	817: spr717 (spr717), unsigned 64 bits
+	818: spr718 (spr718), unsigned 64 bits
+	819: spr719 (spr719), unsigned 64 bits
+	820: spr720 (spr720), unsigned 64 bits
+	821: spr721 (spr721), unsigned 64 bits
+	822: spr722 (spr722), unsigned 64 bits
+	823: spr723 (spr723), unsigned 64 bits
+	824: spr724 (spr724), unsigned 64 bits
+	825: spr725 (spr725), unsigned 64 bits
+	826: spr726 (spr726), unsigned 64 bits
+	827: spr727 (spr727), unsigned 64 bits
+	828: spr728 (spr728), unsigned 64 bits
+	829: spr729 (spr729), unsigned 64 bits
+	830: spr730 (spr730), unsigned 64 bits
+	831: spr731 (spr731), unsigned 64 bits
+	832: spr732 (spr732), unsigned 64 bits
+	833: spr733 (spr733), unsigned 64 bits
+	834: spr734 (spr734), unsigned 64 bits
+	835: spr735 (spr735), unsigned 64 bits
+	836: spr736 (spr736), unsigned 64 bits
+	837: spr737 (spr737), unsigned 64 bits
+	838: spr738 (spr738), unsigned 64 bits
+	839: spr739 (spr739), unsigned 64 bits
+	840: spr740 (spr740), unsigned 64 bits
+	841: spr741 (spr741), unsigned 64 bits
+	842: spr742 (spr742), unsigned 64 bits
+	843: spr743 (spr743), unsigned 64 bits
+	844: spr744 (spr744), unsigned 64 bits
+	845: spr745 (spr745), unsigned 64 bits
+	846: spr746 (spr746), unsigned 64 bits
+	847: spr747 (spr747), unsigned 64 bits
+	848: spr748 (spr748), unsigned 64 bits
+	849: spr749 (spr749), unsigned 64 bits
+	850: spr750 (spr750), unsigned 64 bits
+	851: spr751 (spr751), unsigned 64 bits
+	852: spr752 (spr752), unsigned 64 bits
+	853: spr753 (spr753), unsigned 64 bits
+	854: spr754 (spr754), unsigned 64 bits
+	855: spr755 (spr755), unsigned 64 bits
+	856: spr756 (spr756), unsigned 64 bits
+	857: spr757 (spr757), unsigned 64 bits
+	858: spr758 (spr758), unsigned 64 bits
+	859: spr759 (spr759), unsigned 64 bits
+	860: spr760 (spr760), unsigned 64 bits
+	861: spr761 (spr761), unsigned 64 bits
+	862: spr762 (spr762), unsigned 64 bits
+	863: spr763 (spr763), unsigned 64 bits
+	864: spr764 (spr764), unsigned 64 bits
+	865: spr765 (spr765), unsigned 64 bits
+	866: spr766 (spr766), unsigned 64 bits
+	867: spr767 (spr767), unsigned 64 bits
+	868: spr768 (spr768), unsigned 64 bits
+	869: spr769 (spr769), unsigned 64 bits
+	870: spr770 (spr770), unsigned 64 bits
+	871: spr771 (spr771), unsigned 64 bits
+	872: spr772 (spr772), unsigned 64 bits
+	873: spr773 (spr773), unsigned 64 bits
+	874: spr774 (spr774), unsigned 64 bits
+	875: spr775 (spr775), unsigned 64 bits
+	876: spr776 (spr776), unsigned 64 bits
+	877: spr777 (spr777), unsigned 64 bits
+	878: spr778 (spr778), unsigned 64 bits
+	879: spr779 (spr779), unsigned 64 bits
+	880: spr780 (spr780), unsigned 64 bits
+	881: spr781 (spr781), unsigned 64 bits
+	882: spr782 (spr782), unsigned 64 bits
+	883: spr783 (spr783), unsigned 64 bits
+	884: spr784 (spr784), unsigned 64 bits
+	885: spr785 (spr785), unsigned 64 bits
+	886: spr786 (spr786), unsigned 64 bits
+	887: spr787 (spr787), unsigned 64 bits
+	888: spr788 (spr788), unsigned 64 bits
+	889: spr789 (spr789), unsigned 64 bits
+	890: spr790 (spr790), unsigned 64 bits
+	891: spr791 (spr791), unsigned 64 bits
+	892: spr792 (spr792), unsigned 64 bits
+	893: spr793 (spr793), unsigned 64 bits
+	894: spr794 (spr794), unsigned 64 bits
+	895: spr795 (spr795), unsigned 64 bits
+	896: spr796 (spr796), unsigned 64 bits
+	897: spr797 (spr797), unsigned 64 bits
+	898: spr798 (spr798), unsigned 64 bits
+	899: spr799 (spr799), unsigned 64 bits
+	900: spr800 (spr800), unsigned 64 bits
+	901: spr801 (spr801), unsigned 64 bits
+	902: spr802 (spr802), unsigned 64 bits
+	903: spr803 (spr803), unsigned 64 bits
+	904: spr804 (spr804), unsigned 64 bits
+	905: spr805 (spr805), unsigned 64 bits
+	906: spr806 (spr806), unsigned 64 bits
+	907: spr807 (spr807), unsigned 64 bits
+	908: spr808 (spr808), unsigned 64 bits
+	909: spr809 (spr809), unsigned 64 bits
+	910: spr810 (spr810), unsigned 64 bits
+	911: spr811 (spr811), unsigned 64 bits
+	912: spr812 (spr812), unsigned 64 bits
+	913: spr813 (spr813), unsigned 64 bits
+	914: spr814 (spr814), unsigned 64 bits
+	915: spr815 (spr815), unsigned 64 bits
+	916: spr816 (spr816), unsigned 64 bits
+	917: spr817 (spr817), unsigned 64 bits
+	918: spr818 (spr818), unsigned 64 bits
+	919: spr819 (spr819), unsigned 64 bits
+	920: spr820 (spr820), unsigned 64 bits
+	921: spr821 (spr821), unsigned 64 bits
+	922: spr822 (spr822), unsigned 64 bits
+	923: spr823 (spr823), unsigned 64 bits
+	924: spr824 (spr824), unsigned 64 bits
+	925: spr825 (spr825), unsigned 64 bits
+	926: spr826 (spr826), unsigned 64 bits
+	927: spr827 (spr827), unsigned 64 bits
+	928: spr828 (spr828), unsigned 64 bits
+	929: spr829 (spr829), unsigned 64 bits
+	930: spr830 (spr830), unsigned 64 bits
+	931: spr831 (spr831), unsigned 64 bits
+	932: spr832 (spr832), unsigned 64 bits
+	933: spr833 (spr833), unsigned 64 bits
+	934: spr834 (spr834), unsigned 64 bits
+	935: spr835 (spr835), unsigned 64 bits
+	936: spr836 (spr836), unsigned 64 bits
+	937: spr837 (spr837), unsigned 64 bits
+	938: spr838 (spr838), unsigned 64 bits
+	939: spr839 (spr839), unsigned 64 bits
+	940: spr840 (spr840), unsigned 64 bits
+	941: spr841 (spr841), unsigned 64 bits
+	942: spr842 (spr842), unsigned 64 bits
+	943: spr843 (spr843), unsigned 64 bits
+	944: spr844 (spr844), unsigned 64 bits
+	945: spr845 (spr845), unsigned 64 bits
+	946: spr846 (spr846), unsigned 64 bits
+	947: spr847 (spr847), unsigned 64 bits
+	948: spr848 (spr848), unsigned 64 bits
+	949: spr849 (spr849), unsigned 64 bits
+	950: spr850 (spr850), unsigned 64 bits
+	951: spr851 (spr851), unsigned 64 bits
+	952: spr852 (spr852), unsigned 64 bits
+	953: spr853 (spr853), unsigned 64 bits
+	954: spr854 (spr854), unsigned 64 bits
+	955: spr855 (spr855), unsigned 64 bits
+	956: spr856 (spr856), unsigned 64 bits
+	957: spr857 (spr857), unsigned 64 bits
+	958: spr858 (spr858), unsigned 64 bits
+	959: spr859 (spr859), unsigned 64 bits
+	960: spr860 (spr860), unsigned 64 bits
+	961: spr861 (spr861), unsigned 64 bits
+	962: spr862 (spr862), unsigned 64 bits
+	963: spr863 (spr863), unsigned 64 bits
+	964: spr864 (spr864), unsigned 64 bits
+	965: spr865 (spr865), unsigned 64 bits
+	966: spr866 (spr866), unsigned 64 bits
+	967: spr867 (spr867), unsigned 64 bits
+	968: spr868 (spr868), unsigned 64 bits
+	969: spr869 (spr869), unsigned 64 bits
+	970: spr870 (spr870), unsigned 64 bits
+	971: spr871 (spr871), unsigned 64 bits
+	972: spr872 (spr872), unsigned 64 bits
+	973: spr873 (spr873), unsigned 64 bits
+	974: spr874 (spr874), unsigned 64 bits
+	975: spr875 (spr875), unsigned 64 bits
+	976: spr876 (spr876), unsigned 64 bits
+	977: spr877 (spr877), unsigned 64 bits
+	978: spr878 (spr878), unsigned 64 bits
+	979: spr879 (spr879), unsigned 64 bits
+	980: spr880 (spr880), unsigned 64 bits
+	981: spr881 (spr881), unsigned 64 bits
+	982: spr882 (spr882), unsigned 64 bits
+	983: spr883 (spr883), unsigned 64 bits
+	984: spr884 (spr884), unsigned 64 bits
+	985: spr885 (spr885), unsigned 64 bits
+	986: spr886 (spr886), unsigned 64 bits
+	987: spr887 (spr887), unsigned 64 bits
+	988: spr888 (spr888), unsigned 64 bits
+	989: spr889 (spr889), unsigned 64 bits
+	990: spr890 (spr890), unsigned 64 bits
+	991: spr891 (spr891), unsigned 64 bits
+	992: spr892 (spr892), unsigned 64 bits
+	993: spr893 (spr893), unsigned 64 bits
+	994: spr894 (spr894), unsigned 64 bits
+	995: spr895 (spr895), unsigned 64 bits
+	996: spr896 (spr896), unsigned 64 bits
+	997: spr897 (spr897), unsigned 64 bits
+	998: spr898 (spr898), unsigned 64 bits
+	999: spr899 (spr899), unsigned 64 bits
+vector registers:
+	 67: vscr (vscr), unsigned 32 bits
+	356: vrsave (vrsave), unsigned 32 bits
+	612: spefscr (spefscr), unsigned 32 bits
+	1124: vr0 (vr0), unsigned 128 bits
+	1125: vr1 (vr1), unsigned 128 bits
+	1126: vr2 (vr2), unsigned 128 bits
+	1127: vr3 (vr3), unsigned 128 bits
+	1128: vr4 (vr4), unsigned 128 bits
+	1129: vr5 (vr5), unsigned 128 bits
+	1130: vr6 (vr6), unsigned 128 bits
+	1131: vr7 (vr7), unsigned 128 bits
+	1132: vr8 (vr8), unsigned 128 bits
+	1133: vr9 (vr9), unsigned 128 bits
+	1134: vr10 (vr10), unsigned 128 bits
+	1135: vr11 (vr11), unsigned 128 bits
+	1136: vr12 (vr12), unsigned 128 bits
+	1137: vr13 (vr13), unsigned 128 bits
+	1138: vr14 (vr14), unsigned 128 bits
+	1139: vr15 (vr15), unsigned 128 bits
+	1140: vr16 (vr16), unsigned 128 bits
+	1141: vr17 (vr17), unsigned 128 bits
+	1142: vr18 (vr18), unsigned 128 bits
+	1143: vr19 (vr19), unsigned 128 bits
+	1144: vr20 (vr20), unsigned 128 bits
+	1145: vr21 (vr21), unsigned 128 bits
+	1146: vr22 (vr22), unsigned 128 bits
+	1147: vr23 (vr23), unsigned 128 bits
+	1148: vr24 (vr24), unsigned 128 bits
+	1149: vr25 (vr25), unsigned 128 bits
+	1150: vr26 (vr26), unsigned 128 bits
+	1151: vr27 (vr27), unsigned 128 bits
+	1152: vr28 (vr28), unsigned 128 bits
+	1153: vr29 (vr29), unsigned 128 bits
+	1154: vr30 (vr30), unsigned 128 bits
+	1155: vr31 (vr31), unsigned 128 bits
+EOF
+
+regs_test testfile26 <<\EOF
+integer registers:
+	  0: %r0 (r0), signed 32 bits
+	  1: %r1 (r1), signed 32 bits
+	  2: %r2 (r2), signed 32 bits
+	  3: %r3 (r3), signed 32 bits
+	  4: %r4 (r4), signed 32 bits
+	  5: %r5 (r5), signed 32 bits
+	  6: %r6 (r6), signed 32 bits
+	  7: %r7 (r7), signed 32 bits
+	  8: %r8 (r8), signed 32 bits
+	  9: %r9 (r9), signed 32 bits
+	 10: %r10 (r10), signed 32 bits
+	 11: %r11 (r11), signed 32 bits
+	 12: %r12 (r12), signed 32 bits
+	 13: %r13 (r13), signed 32 bits
+	 14: %r14 (r14), signed 32 bits
+	 15: %r15 (r15), signed 32 bits
+FPU registers:
+	 16: %f0 (f0), float 64 bits
+	 17: %f2 (f2), float 64 bits
+	 18: %f4 (f4), float 64 bits
+	 19: %f6 (f6), float 64 bits
+	 20: %f1 (f1), float 64 bits
+	 21: %f3 (f3), float 64 bits
+	 22: %f5 (f5), float 64 bits
+	 23: %f7 (f7), float 64 bits
+	 24: %f8 (f8), float 64 bits
+	 25: %f10 (f10), float 64 bits
+	 26: %f12 (f12), float 64 bits
+	 27: %f14 (f14), float 64 bits
+	 28: %f9 (f9), float 64 bits
+	 29: %f11 (f11), float 64 bits
+	 30: %f13 (f13), float 64 bits
+	 31: %f15 (f15), float 64 bits
+access registers:
+	 48: %a0 (a0), unsigned 32 bits
+	 49: %a1 (a1), unsigned 32 bits
+	 50: %a2 (a2), unsigned 32 bits
+	 51: %a3 (a3), unsigned 32 bits
+	 52: %a4 (a4), unsigned 32 bits
+	 53: %a5 (a5), unsigned 32 bits
+	 54: %a6 (a6), unsigned 32 bits
+	 55: %a7 (a7), unsigned 32 bits
+	 56: %a8 (a8), unsigned 32 bits
+	 57: %a9 (a9), unsigned 32 bits
+	 58: %a10 (a10), unsigned 32 bits
+	 59: %a11 (a11), unsigned 32 bits
+	 60: %a12 (a12), unsigned 32 bits
+	 61: %a13 (a13), unsigned 32 bits
+	 62: %a14 (a14), unsigned 32 bits
+	 63: %a15 (a15), unsigned 32 bits
+control registers:
+	 32: %c0 (c0), unsigned 32 bits
+	 33: %c1 (c1), unsigned 32 bits
+	 34: %c2 (c2), unsigned 32 bits
+	 35: %c3 (c3), unsigned 32 bits
+	 36: %c4 (c4), unsigned 32 bits
+	 37: %c5 (c5), unsigned 32 bits
+	 38: %c6 (c6), unsigned 32 bits
+	 39: %c7 (c7), unsigned 32 bits
+	 40: %c8 (c8), unsigned 32 bits
+	 41: %c9 (c9), unsigned 32 bits
+	 42: %c10 (c10), unsigned 32 bits
+	 43: %c11 (c11), unsigned 32 bits
+	 44: %c12 (c12), unsigned 32 bits
+	 45: %c13 (c13), unsigned 32 bits
+	 46: %c14 (c14), unsigned 32 bits
+	 47: %c15 (c15), unsigned 32 bits
+	 64: %pswm (pswm), unsigned 32 bits
+	 65: %pswa (pswa), address 32 bits
+EOF
+
+regs_test testfile27 <<\EOF
+integer registers:
+	  0: %r0 (r0), signed 64 bits
+	  1: %r1 (r1), signed 64 bits
+	  2: %r2 (r2), signed 64 bits
+	  3: %r3 (r3), signed 64 bits
+	  4: %r4 (r4), signed 64 bits
+	  5: %r5 (r5), signed 64 bits
+	  6: %r6 (r6), signed 64 bits
+	  7: %r7 (r7), signed 64 bits
+	  8: %r8 (r8), signed 64 bits
+	  9: %r9 (r9), signed 64 bits
+	 10: %r10 (r10), signed 64 bits
+	 11: %r11 (r11), signed 64 bits
+	 12: %r12 (r12), signed 64 bits
+	 13: %r13 (r13), signed 64 bits
+	 14: %r14 (r14), signed 64 bits
+	 15: %r15 (r15), signed 64 bits
+FPU registers:
+	 16: %f0 (f0), float 64 bits
+	 17: %f2 (f2), float 64 bits
+	 18: %f4 (f4), float 64 bits
+	 19: %f6 (f6), float 64 bits
+	 20: %f1 (f1), float 64 bits
+	 21: %f3 (f3), float 64 bits
+	 22: %f5 (f5), float 64 bits
+	 23: %f7 (f7), float 64 bits
+	 24: %f8 (f8), float 64 bits
+	 25: %f10 (f10), float 64 bits
+	 26: %f12 (f12), float 64 bits
+	 27: %f14 (f14), float 64 bits
+	 28: %f9 (f9), float 64 bits
+	 29: %f11 (f11), float 64 bits
+	 30: %f13 (f13), float 64 bits
+	 31: %f15 (f15), float 64 bits
+access registers:
+	 48: %a0 (a0), unsigned 32 bits
+	 49: %a1 (a1), unsigned 32 bits
+	 50: %a2 (a2), unsigned 32 bits
+	 51: %a3 (a3), unsigned 32 bits
+	 52: %a4 (a4), unsigned 32 bits
+	 53: %a5 (a5), unsigned 32 bits
+	 54: %a6 (a6), unsigned 32 bits
+	 55: %a7 (a7), unsigned 32 bits
+	 56: %a8 (a8), unsigned 32 bits
+	 57: %a9 (a9), unsigned 32 bits
+	 58: %a10 (a10), unsigned 32 bits
+	 59: %a11 (a11), unsigned 32 bits
+	 60: %a12 (a12), unsigned 32 bits
+	 61: %a13 (a13), unsigned 32 bits
+	 62: %a14 (a14), unsigned 32 bits
+	 63: %a15 (a15), unsigned 32 bits
+control registers:
+	 32: %c0 (c0), unsigned 64 bits
+	 33: %c1 (c1), unsigned 64 bits
+	 34: %c2 (c2), unsigned 64 bits
+	 35: %c3 (c3), unsigned 64 bits
+	 36: %c4 (c4), unsigned 64 bits
+	 37: %c5 (c5), unsigned 64 bits
+	 38: %c6 (c6), unsigned 64 bits
+	 39: %c7 (c7), unsigned 64 bits
+	 40: %c8 (c8), unsigned 64 bits
+	 41: %c9 (c9), unsigned 64 bits
+	 42: %c10 (c10), unsigned 64 bits
+	 43: %c11 (c11), unsigned 64 bits
+	 44: %c12 (c12), unsigned 64 bits
+	 45: %c13 (c13), unsigned 64 bits
+	 46: %c14 (c14), unsigned 64 bits
+	 47: %c15 (c15), unsigned 64 bits
+	 64: %pswm (pswm), unsigned 64 bits
+	 65: %pswa (pswa), address 64 bits
+EOF
+
+regs_test testfile30 <<\EOF
+integer registers:
+	  0: %g0 (g0), signed 32 bits
+	  1: %g1 (g1), signed 32 bits
+	  2: %g2 (g2), signed 32 bits
+	  3: %g3 (g3), signed 32 bits
+	  4: %g4 (g4), signed 32 bits
+	  5: %g5 (g5), signed 32 bits
+	  6: %g6 (g6), signed 32 bits
+	  7: %g7 (g7), signed 32 bits
+	  8: %o0 (o0), signed 32 bits
+	  9: %o1 (o1), signed 32 bits
+	 10: %o2 (o2), signed 32 bits
+	 11: %o3 (o3), signed 32 bits
+	 12: %o4 (o4), signed 32 bits
+	 13: %o5 (o5), signed 32 bits
+	 14: %o6 (o6), address 32 bits
+	 15: %o7 (o7), signed 32 bits
+	 16: %l0 (l0), signed 32 bits
+	 17: %l1 (l1), signed 32 bits
+	 18: %l2 (l2), signed 32 bits
+	 19: %l3 (l3), signed 32 bits
+	 20: %l4 (l4), signed 32 bits
+	 21: %l5 (l5), signed 32 bits
+	 22: %l6 (l6), signed 32 bits
+	 23: %l7 (l7), signed 32 bits
+	 24: %i0 (i0), signed 32 bits
+	 25: %i1 (i1), signed 32 bits
+	 26: %i2 (i2), signed 32 bits
+	 27: %i3 (i3), signed 32 bits
+	 28: %i4 (i4), signed 32 bits
+	 29: %i5 (i5), signed 32 bits
+	 30: %i6 (i6), address 32 bits
+	 31: %i7 (i7), signed 32 bits
+FPU registers:
+	 32: %f0 (f0), float 32 bits
+	 33: %f1 (f1), float 32 bits
+	 34: %f2 (f2), float 32 bits
+	 35: %f3 (f3), float 32 bits
+	 36: %f4 (f4), float 32 bits
+	 37: %f5 (f5), float 32 bits
+	 38: %f6 (f6), float 32 bits
+	 39: %f7 (f7), float 32 bits
+	 40: %f8 (f8), float 32 bits
+	 41: %f9 (f9), float 32 bits
+	 42: %f10 (f10), float 32 bits
+	 43: %f11 (f11), float 32 bits
+	 44: %f12 (f12), float 32 bits
+	 45: %f13 (f13), float 32 bits
+	 46: %f14 (f14), float 32 bits
+	 47: %f15 (f15), float 32 bits
+	 48: %f16 (f16), float 32 bits
+	 49: %f17 (f17), float 32 bits
+	 50: %f18 (f18), float 32 bits
+	 51: %f19 (f19), float 32 bits
+	 52: %f20 (f20), float 32 bits
+	 53: %f21 (f21), float 32 bits
+	 54: %f22 (f22), float 32 bits
+	 55: %f23 (f23), float 32 bits
+	 56: %f24 (f24), float 32 bits
+	 57: %f25 (f25), float 32 bits
+	 58: %f26 (f26), float 32 bits
+	 59: %f27 (f27), float 32 bits
+	 60: %f28 (f28), float 32 bits
+	 61: %f29 (f29), float 32 bits
+	 62: %f30 (f30), float 32 bits
+	 63: %f31 (f31), float 32 bits
+control registers:
+	 64: %y (y), unsigned 32 bits
+	 65: %psr (psr), unsigned 32 bits
+	 66: %wim (wim), unsigned 32 bits
+	 67: %tbr (tbr), unsigned 32 bits
+	 68: %pc (pc), address 32 bits
+	 69: %npc (npc), address 32 bits
+	 70: %fsr (fsr), unsigned 32 bits
+	 71: %csr (csr), unsigned 32 bits
+EOF
+
+regs_test testfile31 <<\EOF
+integer registers:
+	  0: %g0 (g0), signed 64 bits
+	  1: %g1 (g1), signed 64 bits
+	  2: %g2 (g2), signed 64 bits
+	  3: %g3 (g3), signed 64 bits
+	  4: %g4 (g4), signed 64 bits
+	  5: %g5 (g5), signed 64 bits
+	  6: %g6 (g6), signed 64 bits
+	  7: %g7 (g7), signed 64 bits
+	  8: %o0 (o0), signed 64 bits
+	  9: %o1 (o1), signed 64 bits
+	 10: %o2 (o2), signed 64 bits
+	 11: %o3 (o3), signed 64 bits
+	 12: %o4 (o4), signed 64 bits
+	 13: %o5 (o5), signed 64 bits
+	 14: %o6 (o6), address 64 bits
+	 15: %o7 (o7), signed 64 bits
+	 16: %l0 (l0), signed 64 bits
+	 17: %l1 (l1), signed 64 bits
+	 18: %l2 (l2), signed 64 bits
+	 19: %l3 (l3), signed 64 bits
+	 20: %l4 (l4), signed 64 bits
+	 21: %l5 (l5), signed 64 bits
+	 22: %l6 (l6), signed 64 bits
+	 23: %l7 (l7), signed 64 bits
+	 24: %i0 (i0), signed 64 bits
+	 25: %i1 (i1), signed 64 bits
+	 26: %i2 (i2), signed 64 bits
+	 27: %i3 (i3), signed 64 bits
+	 28: %i4 (i4), signed 64 bits
+	 29: %i5 (i5), signed 64 bits
+	 30: %i6 (i6), address 64 bits
+	 31: %i7 (i7), signed 64 bits
+FPU registers:
+	 32: %f0 (f0), float 32 bits
+	 33: %f1 (f1), float 32 bits
+	 34: %f2 (f2), float 32 bits
+	 35: %f3 (f3), float 32 bits
+	 36: %f4 (f4), float 32 bits
+	 37: %f5 (f5), float 32 bits
+	 38: %f6 (f6), float 32 bits
+	 39: %f7 (f7), float 32 bits
+	 40: %f8 (f8), float 32 bits
+	 41: %f9 (f9), float 32 bits
+	 42: %f10 (f10), float 32 bits
+	 43: %f11 (f11), float 32 bits
+	 44: %f12 (f12), float 32 bits
+	 45: %f13 (f13), float 32 bits
+	 46: %f14 (f14), float 32 bits
+	 47: %f15 (f15), float 32 bits
+	 48: %f16 (f16), float 32 bits
+	 49: %f17 (f17), float 32 bits
+	 50: %f18 (f18), float 32 bits
+	 51: %f19 (f19), float 32 bits
+	 52: %f20 (f20), float 32 bits
+	 53: %f21 (f21), float 32 bits
+	 54: %f22 (f22), float 32 bits
+	 55: %f23 (f23), float 32 bits
+	 56: %f24 (f24), float 32 bits
+	 57: %f25 (f25), float 32 bits
+	 58: %f26 (f26), float 32 bits
+	 59: %f27 (f27), float 32 bits
+	 60: %f28 (f28), float 32 bits
+	 61: %f29 (f29), float 32 bits
+	 62: %f30 (f30), float 32 bits
+	 63: %f31 (f31), float 32 bits
+	 64: %f32 (f32), float 64 bits
+	 65: %f34 (f34), float 64 bits
+	 66: %f36 (f36), float 64 bits
+	 67: %f38 (f38), float 64 bits
+	 68: %f40 (f40), float 64 bits
+	 69: %f42 (f42), float 64 bits
+	 70: %f44 (f44), float 64 bits
+	 71: %f46 (f46), float 64 bits
+	 72: %f48 (f48), float 64 bits
+	 73: %f50 (f50), float 64 bits
+	 74: %f52 (f52), float 64 bits
+	 75: %f54 (f54), float 64 bits
+	 76: %f56 (f56), float 64 bits
+	 77: %f58 (f58), float 64 bits
+	 78: %f60 (f60), float 64 bits
+	 79: %f62 (f62), float 64 bits
+control registers:
+	 80: %pc (pc), address 64 bits
+	 81: %npc (npc), address 64 bits
+	 82: %state (state), unsigned 64 bits
+	 83: %fsr (fsr), unsigned 64 bits
+	 84: %fprs (fprs), unsigned 64 bits
+	 85: %y (y), unsigned 64 bits
+EOF
+
+regs_test testfile10 <<\EOF
+integer registers:
+	  0: $v0 (v0), signed 64 bits
+	  1: $t0 (t0), signed 64 bits
+	  2: $t1 (t1), signed 64 bits
+	  3: $t2 (t2), signed 64 bits
+	  4: $t3 (t3), signed 64 bits
+	  5: $t4 (t4), signed 64 bits
+	  6: $t5 (t5), signed 64 bits
+	  7: $t6 (t6), signed 64 bits
+	  8: $t7 (t7), signed 64 bits
+	  9: $s0 (s0), signed 64 bits
+	 10: $s1 (s1), signed 64 bits
+	 11: $s2 (s2), signed 64 bits
+	 12: $s3 (s3), signed 64 bits
+	 13: $s4 (s4), signed 64 bits
+	 14: $s5 (s5), signed 64 bits
+	 15: $s6 (s6), signed 64 bits
+	 16: $a0 (a0), signed 64 bits
+	 17: $a1 (a1), signed 64 bits
+	 18: $a2 (a2), signed 64 bits
+	 19: $a3 (a3), signed 64 bits
+	 20: $a4 (a4), signed 64 bits
+	 21: $a5 (a5), signed 64 bits
+	 22: $t8 (t8), signed 64 bits
+	 23: $t9 (t9), signed 64 bits
+	 24: $t10 (t10), signed 64 bits
+	 25: $t11 (t11), signed 64 bits
+	 26: $ra (ra), address 64 bits
+	 27: $t12 (t12), signed 64 bits
+	 28: $at (at), signed 64 bits
+	 29: $gp (gp), address 64 bits
+	 30: $sp (sp), address 64 bits
+	 31: $zero (zero), signed 64 bits
+	 64: $pc (pc), address 64 bits
+	 66: $unique (unique), address 64 bits
+FPU registers:
+	 32: $f0 (f0), float 64 bits
+	 33: $f1 (f1), float 64 bits
+	 34: $f2 (f2), float 64 bits
+	 35: $f3 (f3), float 64 bits
+	 36: $f4 (f4), float 64 bits
+	 37: $f5 (f5), float 64 bits
+	 38: $f6 (f6), float 64 bits
+	 39: $f7 (f7), float 64 bits
+	 40: $f8 (f8), float 64 bits
+	 41: $f9 (f9), float 64 bits
+	 42: $f10 (f10), float 64 bits
+	 43: $f11 (f11), float 64 bits
+	 44: $f12 (f12), float 64 bits
+	 45: $f13 (f13), float 64 bits
+	 46: $f14 (f14), float 64 bits
+	 47: $f15 (f15), float 64 bits
+	 48: $f16 (f16), float 64 bits
+	 49: $f17 (f17), float 64 bits
+	 50: $f18 (f18), float 64 bits
+	 51: $f19 (f19), float 64 bits
+	 52: $f20 (f20), float 64 bits
+	 53: $f21 (f21), float 64 bits
+	 54: $f22 (f22), float 64 bits
+	 55: $f23 (f23), float 64 bits
+	 56: $f24 (f24), float 64 bits
+	 57: $f25 (f25), float 64 bits
+	 58: $f26 (f26), float 64 bits
+	 59: $f27 (f27), float 64 bits
+	 60: $f28 (f28), float 64 bits
+	 61: $f29 (f29), float 64 bits
+	 62: $f30 (f30), float 64 bits
+	 63: $fpcr (fpcr), unsigned 64 bits
+EOF
+
+regs_test testfile61 <<\EOF
+integer registers:
+	  0: r0 (r0), signed 32 bits
+	  1: r1 (r1), signed 32 bits
+	  2: r2 (r2), signed 32 bits
+	  3: r3 (r3), signed 32 bits
+	  4: r4 (r4), signed 32 bits
+	  5: r5 (r5), signed 32 bits
+	  6: r6 (r6), signed 32 bits
+	  7: r7 (r7), signed 32 bits
+	  8: r8 (r8), signed 32 bits
+	  9: r9 (r9), signed 32 bits
+	 10: r10 (r10), signed 32 bits
+	 11: r11 (r11), signed 32 bits
+	 12: r12 (r12), signed 32 bits
+	 13: sp (sp), address 32 bits
+	 14: lr (lr), address 32 bits
+	 15: pc (pc), address 32 bits
+	128: spsr (spsr), unsigned 32 bits
+FPA registers:
+	 16: f0 (f0), float 96 bits
+	 17: f1 (f1), float 96 bits
+	 18: f2 (f2), float 96 bits
+	 19: f3 (f3), float 96 bits
+	 20: f4 (f4), float 96 bits
+	 21: f5 (f5), float 96 bits
+	 22: f6 (f6), float 96 bits
+	 23: f7 (f7), float 96 bits
+	 96: f0 (f0), float 96 bits
+	 97: f1 (f1), float 96 bits
+	 98: f2 (f2), float 96 bits
+	 99: f3 (f3), float 96 bits
+	100: f4 (f4), float 96 bits
+	101: f5 (f5), float 96 bits
+	102: f6 (f6), float 96 bits
+	103: f7 (f7), float 96 bits
+VFP registers:
+	256: d0 (d0), float 64 bits
+	257: d1 (d1), float 64 bits
+	258: d2 (d2), float 64 bits
+	259: d3 (d3), float 64 bits
+	260: d4 (d4), float 64 bits
+	261: d5 (d5), float 64 bits
+	262: d6 (d6), float 64 bits
+	263: d7 (d7), float 64 bits
+	264: d8 (d8), float 64 bits
+	265: d9 (d9), float 64 bits
+	266: d10 (d10), float 64 bits
+	267: d11 (d11), float 64 bits
+	268: d12 (d12), float 64 bits
+	269: d13 (d13), float 64 bits
+	270: d14 (d14), float 64 bits
+	271: d15 (d15), float 64 bits
+	272: d16 (d16), float 64 bits
+	273: d17 (d17), float 64 bits
+	274: d18 (d18), float 64 bits
+	275: d19 (d19), float 64 bits
+	276: d20 (d20), float 64 bits
+	277: d21 (d21), float 64 bits
+	278: d22 (d22), float 64 bits
+	279: d23 (d23), float 64 bits
+	280: d24 (d24), float 64 bits
+	281: d25 (d25), float 64 bits
+	282: d26 (d26), float 64 bits
+	283: d27 (d27), float 64 bits
+	284: d28 (d28), float 64 bits
+	285: d29 (d29), float 64 bits
+	286: d30 (d30), float 64 bits
+	287: d31 (d31), float 64 bits
+EOF
+
+# See run-readelf-mixed-corenote.sh for instructions to regenerate
+# this core file.
+regs_test testfile_aarch64_core <<\EOF
+integer registers:
+	  0: x0 (x0), signed 64 bits
+	  1: x1 (x1), signed 64 bits
+	  2: x2 (x2), signed 64 bits
+	  3: x3 (x3), signed 64 bits
+	  4: x4 (x4), signed 64 bits
+	  5: x5 (x5), signed 64 bits
+	  6: x6 (x6), signed 64 bits
+	  7: x7 (x7), signed 64 bits
+	  8: x8 (x8), signed 64 bits
+	  9: x9 (x9), signed 64 bits
+	 10: x10 (x10), signed 64 bits
+	 11: x11 (x11), signed 64 bits
+	 12: x12 (x12), signed 64 bits
+	 13: x13 (x13), signed 64 bits
+	 14: x14 (x14), signed 64 bits
+	 15: x15 (x15), signed 64 bits
+	 16: x16 (x16), signed 64 bits
+	 17: x17 (x17), signed 64 bits
+	 18: x18 (x18), signed 64 bits
+	 19: x19 (x19), signed 64 bits
+	 20: x20 (x20), signed 64 bits
+	 21: x21 (x21), signed 64 bits
+	 22: x22 (x22), signed 64 bits
+	 23: x23 (x23), signed 64 bits
+	 24: x24 (x24), signed 64 bits
+	 25: x25 (x25), signed 64 bits
+	 26: x26 (x26), signed 64 bits
+	 27: x27 (x27), signed 64 bits
+	 28: x28 (x28), signed 64 bits
+	 29: x29 (x29), signed 64 bits
+	 30: x30 (x30), signed 64 bits
+	 31: sp (sp), address 64 bits
+	 33: elr (elr), address 64 bits
+FP/SIMD registers:
+	 64: v0 (v0), unsigned 128 bits
+	 65: v1 (v1), unsigned 128 bits
+	 66: v2 (v2), unsigned 128 bits
+	 67: v3 (v3), unsigned 128 bits
+	 68: v4 (v4), unsigned 128 bits
+	 69: v5 (v5), unsigned 128 bits
+	 70: v6 (v6), unsigned 128 bits
+	 71: v7 (v7), unsigned 128 bits
+	 72: v8 (v8), unsigned 128 bits
+	 73: v9 (v9), unsigned 128 bits
+	 74: v10 (v10), unsigned 128 bits
+	 75: v11 (v11), unsigned 128 bits
+	 76: v12 (v12), unsigned 128 bits
+	 77: v13 (v13), unsigned 128 bits
+	 78: v14 (v14), unsigned 128 bits
+	 79: v15 (v15), unsigned 128 bits
+	 80: v16 (v16), unsigned 128 bits
+	 81: v17 (v17), unsigned 128 bits
+	 82: v18 (v18), unsigned 128 bits
+	 83: v19 (v19), unsigned 128 bits
+	 84: v20 (v20), unsigned 128 bits
+	 85: v21 (v21), unsigned 128 bits
+	 86: v22 (v22), unsigned 128 bits
+	 87: v23 (v23), unsigned 128 bits
+	 88: v24 (v24), unsigned 128 bits
+	 89: v25 (v25), unsigned 128 bits
+	 90: v26 (v26), unsigned 128 bits
+	 91: v27 (v27), unsigned 128 bits
+	 92: v28 (v28), unsigned 128 bits
+	 93: v29 (v29), unsigned 128 bits
+	 94: v30 (v30), unsigned 128 bits
+	 95: v31 (v31), unsigned 128 bits
+EOF
+
+# See run-readelf-mixed-corenote.sh for instructions to regenerate
+# this core file.
+regs_test testfile-x32-core <<\EOF
+integer registers:
+	  0: %rax (rax), signed 64 bits
+	  1: %rdx (rdx), signed 64 bits
+	  2: %rcx (rcx), signed 64 bits
+	  3: %rbx (rbx), signed 64 bits
+	  4: %rsi (rsi), signed 64 bits
+	  5: %rdi (rdi), signed 64 bits
+	  6: %rbp (rbp), address 64 bits
+	  7: %rsp (rsp), address 64 bits
+	  8: %r8 (r8), signed 64 bits
+	  9: %r9 (r9), signed 64 bits
+	 10: %r10 (r10), signed 64 bits
+	 11: %r11 (r11), signed 64 bits
+	 12: %r12 (r12), signed 64 bits
+	 13: %r13 (r13), signed 64 bits
+	 14: %r14 (r14), signed 64 bits
+	 15: %r15 (r15), signed 64 bits
+	 16: %rip (rip), address 64 bits
+	 49: %rflags (rflags), unsigned 64 bits
+MMX registers:
+	 41: %mm0 (mm0), unsigned 64 bits
+	 42: %mm1 (mm1), unsigned 64 bits
+	 43: %mm2 (mm2), unsigned 64 bits
+	 44: %mm3 (mm3), unsigned 64 bits
+	 45: %mm4 (mm4), unsigned 64 bits
+	 46: %mm5 (mm5), unsigned 64 bits
+	 47: %mm6 (mm6), unsigned 64 bits
+	 48: %mm7 (mm7), unsigned 64 bits
+SSE registers:
+	 17: %xmm0 (xmm0), unsigned 128 bits
+	 18: %xmm1 (xmm1), unsigned 128 bits
+	 19: %xmm2 (xmm2), unsigned 128 bits
+	 20: %xmm3 (xmm3), unsigned 128 bits
+	 21: %xmm4 (xmm4), unsigned 128 bits
+	 22: %xmm5 (xmm5), unsigned 128 bits
+	 23: %xmm6 (xmm6), unsigned 128 bits
+	 24: %xmm7 (xmm7), unsigned 128 bits
+	 25: %xmm8 (xmm8), unsigned 128 bits
+	 26: %xmm9 (xmm9), unsigned 128 bits
+	 27: %xmm10 (xmm10), unsigned 128 bits
+	 28: %xmm11 (xmm11), unsigned 128 bits
+	 29: %xmm12 (xmm12), unsigned 128 bits
+	 30: %xmm13 (xmm13), unsigned 128 bits
+	 31: %xmm14 (xmm14), unsigned 128 bits
+	 32: %xmm15 (xmm15), unsigned 128 bits
+control registers:
+	 62: %tr (tr), unsigned 64 bits
+	 63: %ldtr (ldtr), unsigned 64 bits
+	 64: %mxcsr (mxcsr), unsigned 64 bits
+	 65: %fcw (fcw), unsigned 16 bits
+	 66: %fsw (fsw), unsigned 16 bits
+segment registers:
+	 50: %es (es), unsigned 16 bits
+	 51: %cs (cs), unsigned 16 bits
+	 52: %ss (ss), unsigned 16 bits
+	 53: %ds (ds), unsigned 16 bits
+	 54: %fs (fs), unsigned 16 bits
+	 55: %gs (gs), unsigned 16 bits
+	 58: %fs.base (fs.base), address 64 bits
+	 59: %gs.base (gs.base), address 64 bits
+x87 registers:
+	 33: %st0 (st0), float 80 bits
+	 34: %st1 (st1), float 80 bits
+	 35: %st2 (st2), float 80 bits
+	 36: %st3 (st3), float 80 bits
+	 37: %st4 (st4), float 80 bits
+	 38: %st5 (st5), float 80 bits
+	 39: %st6 (st6), float 80 bits
+	 40: %st7 (st7), float 80 bits
+EOF
+
+# See run-readelf-mixed-corenote.sh for instructions to regenerate
+# this core file.
+regs_test testfile-m68k-core <<\EOF
+integer registers:
+	  0: %d0 (d0), signed 32 bits
+	  1: %d1 (d1), signed 32 bits
+	  2: %d2 (d2), signed 32 bits
+	  3: %d3 (d3), signed 32 bits
+	  4: %d4 (d4), signed 32 bits
+	  5: %d5 (d5), signed 32 bits
+	  6: %d6 (d6), signed 32 bits
+	  7: %d7 (d7), signed 32 bits
+	  8: %a0 (a0), address 32 bits
+	  9: %a1 (a1), address 32 bits
+	 10: %a2 (a2), address 32 bits
+	 11: %a3 (a3), address 32 bits
+	 12: %a4 (a4), address 32 bits
+	 13: %a5 (a5), address 32 bits
+	 14: %a6 (a6), address 32 bits
+	 15: %a7 (a7), address 32 bits
+	 24: %pc (pc), address 32 bits
+FPU registers:
+	 16: %fp0 (fp0), float 96 bits
+	 17: %fp1 (fp1), float 96 bits
+	 18: %fp2 (fp2), float 96 bits
+	 19: %fp3 (fp3), float 96 bits
+	 20: %fp4 (fp4), float 96 bits
+	 21: %fp5 (fp5), float 96 bits
+	 22: %fp6 (fp6), float 96 bits
+	 23: %fp7 (fp7), float 96 bits
+EOF
+
+# See run-readelf-mixed-corenote.sh for instructions to regenerate
+# this core file.
+regs_test testfile-riscv64-core <<\EOF
+integer registers:
+	  0: zero (zero), signed 64 bits
+	  1: ra (ra), address 64 bits
+	  2: sp (sp), address 64 bits
+	  3: gp (gp), address 64 bits
+	  4: tp (tp), address 64 bits
+	  5: t0 (t0), signed 64 bits
+	  6: t1 (t1), signed 64 bits
+	  7: t2 (t2), signed 64 bits
+	  8: s0 (s0), signed 64 bits
+	  9: s1 (s1), signed 64 bits
+	 10: a0 (a0), signed 64 bits
+	 11: a1 (a1), signed 64 bits
+	 12: a2 (a2), signed 64 bits
+	 13: a3 (a3), signed 64 bits
+	 14: a4 (a4), signed 64 bits
+	 15: a5 (a5), signed 64 bits
+	 16: a6 (a6), signed 64 bits
+	 17: a7 (a7), signed 64 bits
+	 18: s2 (s2), signed 64 bits
+	 19: s3 (s3), signed 64 bits
+	 20: s4 (s4), signed 64 bits
+	 21: s5 (s5), signed 64 bits
+	 22: s6 (s6), signed 64 bits
+	 23: s7 (s7), signed 64 bits
+	 24: s8 (s8), signed 64 bits
+	 25: s9 (s9), signed 64 bits
+	 26: s10 (s10), signed 64 bits
+	 27: s11 (s11), signed 64 bits
+	 28: t3 (t3), signed 64 bits
+	 29: t4 (t4), signed 64 bits
+	 30: t5 (t5), signed 64 bits
+	 31: t6 (t6), signed 64 bits
+FPU registers:
+	 32: ft0 (ft0), float 64 bits
+	 33: ft1 (ft1), float 64 bits
+	 34: ft2 (ft2), float 64 bits
+	 35: ft3 (ft3), float 64 bits
+	 36: ft4 (ft4), float 64 bits
+	 37: ft5 (ft5), float 64 bits
+	 38: ft6 (ft6), float 64 bits
+	 39: ft7 (ft7), float 64 bits
+	 40: fs0 (fs0), float 64 bits
+	 41: fs1 (fs1), float 64 bits
+	 42: fa0 (fa0), float 64 bits
+	 43: fa1 (fa1), float 64 bits
+	 44: fa2 (fa2), float 64 bits
+	 45: fa3 (fa3), float 64 bits
+	 46: fa4 (fa4), float 64 bits
+	 47: fa5 (fa5), float 64 bits
+	 48: fa6 (fa6), float 64 bits
+	 49: fa7 (fa7), float 64 bits
+	 50: fs2 (fs2), float 64 bits
+	 51: fs3 (fs3), float 64 bits
+	 52: fs4 (fs4), float 64 bits
+	 53: fs5 (fs5), float 64 bits
+	 54: fs6 (fs6), float 64 bits
+	 55: fs7 (fs7), float 64 bits
+	 56: fs8 (fs8), float 64 bits
+	 57: fs9 (fs9), float 64 bits
+	 58: fs10 (fs10), float 64 bits
+	 59: fs11 (fs11), float 64 bits
+	 60: ft8 (ft8), float 64 bits
+	 61: ft9 (ft9), float 64 bits
+	 62: ft10 (ft10), float 64 bits
+	 63: ft11 (ft11), float 64 bits
+EOF
+exit 0
diff --git a/tests/run-annobingroup.sh b/tests/run-annobingroup.sh
new file mode 100755
index 0000000..16b031a
--- /dev/null
+++ b/tests/run-annobingroup.sh
@@ -0,0 +1,156 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Testfile generated by annobin, creates group.
+# strip and unstrip it. Check group symbol/name is correct.
+
+# echo "int __attribute__((cold)) foo (void) { return 42; }" \
+#      > testfile-annobingroup.c
+# gcc -g -O2 -fplugin=annobin -c testfile-annobingroup.c
+testfiles testfile-annobingroup.o
+
+tempfiles merged.elf stripped.elf debugfile1.elf debugfile2.elf debugfile3.elf remerged.elf
+
+testrun_compare ${abs_top_builddir}/src/readelf -g testfile-annobingroup.o << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 7] .gnu.build.attributes..text.unlikely
+  [ 8] .rela.gnu.build.attributes..text.unlikely
+  [ 9] .text.unlikely
+EOF
+
+testrun ${abs_top_builddir}/src/strip -o stripped.elf -f debugfile1.elf testfile-annobingroup.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -g stripped.elf << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 7] .gnu.build.attributes..text.unlikely
+  [ 8] .rela.gnu.build.attributes..text.unlikely
+  [ 9] .text.unlikely
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -g debugfile1.elf << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 7] .gnu.build.attributes..text.unlikely
+  [ 8] .rela.gnu.build.attributes..text.unlikely
+  [ 9] .text.unlikely
+EOF
+
+testrun ${abs_top_builddir}/src/unstrip -o remerged.elf stripped.elf debugfile1.elf
+
+testrun_compare ${abs_top_builddir}/src/readelf -g remerged.elf << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 7] .gnu.build.attributes..text.unlikely
+  [ 8] .rela.gnu.build.attributes..text.unlikely
+  [ 9] .text.unlikely
+EOF
+
+testrun ${abs_top_builddir}/src/elfcmp testfile-annobingroup.o remerged.elf
+
+# echo "void * __attribute__((cold)) foo (void) { return foo; }"
+#      > testfile-annobingroup-i386.c
+# gcc -fpic -g -O2 -fplugin=annobin -c testfile-annobingroup-i386.c
+testfiles testfile-annobingroup-i386.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -g testfile-annobingroup-i386.o << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 8] .gnu.build.attributes..text.unlikely
+  [ 9] .rel.gnu.build.attributes..text.unlikely
+  [10] .text.unlikely
+
+COMDAT section group [ 2] '.group' with signature '__x86.get_pc_thunk.ax' contains 1 entry:
+  [13] .text.__x86.get_pc_thunk.ax
+EOF
+
+testrun ${abs_top_builddir}/src/strip -o stripped.elf -f debugfile2.elf testfile-annobingroup-i386.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -g stripped.elf << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 8] .gnu.build.attributes..text.unlikely
+  [ 9] .rel.gnu.build.attributes..text.unlikely
+  [10] .text.unlikely
+
+COMDAT section group [ 2] '.group' with signature '__x86.get_pc_thunk.ax' contains 1 entry:
+  [13] .text.__x86.get_pc_thunk.ax
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -g debugfile2.elf << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 8] .gnu.build.attributes..text.unlikely
+  [ 9] .rel.gnu.build.attributes..text.unlikely
+  [10] .text.unlikely
+
+COMDAT section group [ 2] '.group' with signature '__x86.get_pc_thunk.ax' contains 1 entry:
+  [13] .text.__x86.get_pc_thunk.ax
+EOF
+
+testrun ${abs_top_builddir}/src/unstrip -o remerged.elf stripped.elf debugfile2.elf
+
+testrun_compare ${abs_top_builddir}/src/readelf -g remerged.elf << EOF
+
+Section group [ 1] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [ 8] .gnu.build.attributes..text.unlikely
+  [ 9] .rel.gnu.build.attributes..text.unlikely
+  [10] .text.unlikely
+
+COMDAT section group [ 2] '.group' with signature '__x86.get_pc_thunk.ax' contains 1 entry:
+  [13] .text.__x86.get_pc_thunk.ax
+EOF
+
+testrun ${abs_top_builddir}/src/elfcmp testfile-annobingroup-i386.o remerged.elf
+
+# echo "void * foo (void) { return foo; }" > testfile-annobingroup-x86_64.c
+# gcc -g -O2 -fplugin=annobin -c testfile-annobingroup-x86_64.c
+testfiles testfile-annobingroup-x86_64.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -g testfile-annobingroup-x86_64.o << EOF
+
+Section group [ 1] '.group' with signature '.text.hot.group' contains 3 entries:
+  [11] .text.hot
+  [12] .gnu.build.attributes.hot
+  [13] .rela.gnu.build.attributes.hot
+
+Section group [ 2] '.group' with signature '.text.unlikely.group' contains 3 entries:
+  [14] .text.unlikely
+  [15] .gnu.build.attributes.unlikely
+  [16] .rela.gnu.build.attributes.unlikely
+
+Section group [ 3] '.group' with signature '.text.hot..group' contains 1 entry:
+  [26] .text.hot
+
+Section group [ 4] '.group' with signature '.text.unlikely..group' contains 1 entry:
+  [27] .text.unlikely
+EOF
+
+testrun ${abs_top_builddir}/src/strip -o stripped.elf -f debugfile3.elf testfile-annobingroup-x86_64.o
+
+# This would/should work, except for the unknown NOTEs.
+# testrun ${abs_top_builddir}/src/elflint --gnu stripped.elf
+# testrun ${abs_top_builddir}/src/elflint --gnu --debug debugfile3.elf
+
+testrun ${abs_top_builddir}/src/unstrip -o remerged.elf stripped.elf debugfile3.elf
+
+testrun ${abs_top_builddir}/src/elfcmp testfile-annobingroup-x86_64.o remerged.elf
+
+exit 0
diff --git a/tests/run-ar-N.sh b/tests/run-ar-N.sh
new file mode 100755
index 0000000..de8f62b
--- /dev/null
+++ b/tests/run-ar-N.sh
@@ -0,0 +1,65 @@
+#! /usr/bin/env bash
+# Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles testfile test.ar
+
+echo create test.ar with 3 testfile
+echo 1 > testfile
+testrun ${abs_top_builddir}/src/ar -vr test.ar testfile
+echo 2 > testfile
+testrun ${abs_top_builddir}/src/ar -vq test.ar testfile
+testrun ${abs_top_builddir}/src/ar -t test.ar
+echo 3 > testfile
+testrun ${abs_top_builddir}/src/ar -vq test.ar testfile
+testrun_compare ${abs_top_builddir}/src/ar -t test.ar << EOF
+testfile
+testfile
+testfile
+EOF
+
+echo list content of testfile 1 2 3
+testrun ${abs_top_builddir}/src/ar -vx -N 1 test.ar testfile
+diff -u testfile - << EOF
+1
+EOF
+testrun ${abs_top_builddir}/src/ar -vx -N 2 test.ar testfile
+diff -u testfile - << EOF
+2
+EOF
+testrun ${abs_top_builddir}/src/ar -vx -N 3 test.ar testfile
+diff -u testfile - << EOF
+3
+EOF
+
+echo delete testfile 2
+testrun ${abs_top_builddir}/src/ar -vd -N 2 test.ar testfile
+testrun_compare ${abs_top_builddir}/src/ar -t test.ar << EOF
+testfile
+testfile
+EOF
+testrun ${abs_top_builddir}/src/ar -vx -N 1 test.ar testfile
+diff -u testfile - << EOF
+1
+EOF
+testrun ${abs_top_builddir}/src/ar -vx -N 2 test.ar testfile
+diff -u testfile - << EOF
+3
+EOF
+
+exit 0
diff --git a/tests/run-ar.sh b/tests/run-ar.sh
new file mode 100755
index 0000000..656f1d1
--- /dev/null
+++ b/tests/run-ar.sh
@@ -0,0 +1,40 @@
+#! /usr/bin/env bash
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles objects.list test.ar
+
+echo Make a sorted list of the just build src .o files.
+(cd ${abs_top_builddir}/src; ls *.o | sort) > objects.list
+cat objects.list
+
+echo Create a new ar file with the .o files.
+testrun ${abs_top_builddir}/src/ar -r test.ar \
+	$(echo ${abs_top_builddir}/src/*.o | sort)
+
+echo List the ar file contents.
+testrun_compare ${abs_top_builddir}/src/ar -t test.ar < objects.list
+
+echo Delete all objects again.
+testrun ${abs_top_builddir}/src/ar -d test.ar $(cat objects.list)
+
+echo Check new ar file is now empty
+testrun_compare ${abs_top_builddir}/src/ar -t test.ar << EOF
+EOF
+
+exit 0
diff --git a/tests/run-arextract.sh b/tests/run-arextract.sh
new file mode 100755
index 0000000..44f4a52
--- /dev/null
+++ b/tests/run-arextract.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2005, 2006 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles arextract.test
+
+archive=${abs_top_builddir}/libelf/libelf.a
+if test -f $archive; then
+    # The file is really available (i.e., no shared-only built).
+    echo -n "Extracting symbols... $ac_c"
+
+    # The files we are looking at.
+    for f in ${abs_top_builddir}/libelf/*.o; do
+	testrun ${abs_builddir}/arextract $archive `basename $f` arextract.test || exit 1
+	cmp $f arextract.test || {
+	    echo "Extraction of $1 failed"
+	    exit 1
+	}
+    done
+
+    echo "done"
+fi
+
+exit 0
diff --git a/tests/run-arsymtest.sh b/tests/run-arsymtest.sh
new file mode 100755
index 0000000..b0fdfcd
--- /dev/null
+++ b/tests/run-arsymtest.sh
@@ -0,0 +1,47 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2006 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+lib=${abs_top_builddir}/libelf/libelf.a
+okfile=arsymtest.ok
+tmpfile=arsymtest.tmp
+testfile=arsymtest.test
+
+tempfiles $okfile $tmpfile $testfile
+
+result=77
+if test -f $lib; then
+    # Generate list using `nm' we check against.
+    ${NM} -s $lib |
+    sed -e '1,/^Arch/d' -e '/^$/,$d' |
+    sort > $okfile
+
+    # Now run our program using libelf.
+    testrun ${abs_builddir}/arsymtest $lib $tmpfile || exit 1
+    sort $tmpfile > $testfile
+
+    # Compare the outputs.
+    if cmp $okfile $testfile; then
+	result=0
+    else
+	result=1
+    fi
+fi
+
+exit $result
diff --git a/tests/run-attr-integrate-skel.sh b/tests/run-attr-integrate-skel.sh
new file mode 100755
index 0000000..a9a9409
--- /dev/null
+++ b/tests/run-attr-integrate-skel.sh
@@ -0,0 +1,52 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun_compare ${abs_builddir}/attr-integrate-skel testfile-splitdwarf-4 << EOF
+file: testfile-splitdwarf-4
+Split DIE: hello.c
+addr_base secoff: 0x0
+low_pc addr: 0x401160
+Skel has high_pc.
+
+Split DIE: world.c
+addr_base secoff: 0x98
+low_pc addr: 0x0
+Skel has ranges.
+
+EOF
+
+testrun_compare ${abs_builddir}/attr-integrate-skel testfile-splitdwarf-5 << EOF
+file: testfile-splitdwarf-5
+Split DIE: hello.c
+addr_base secoff: 0x8
+low_pc addr: 0x401160
+Skel has high_pc.
+
+Split DIE: world.c
+addr_base secoff: 0xa8
+low_pc addr: 0x0
+Skel has ranges.
+
+EOF
+
+exit 0
diff --git a/tests/run-backtrace-core-aarch64.sh b/tests/run-backtrace-core-aarch64.sh
new file mode 100755
index 0000000..41221d3
--- /dev/null
+++ b/tests/run-backtrace-core-aarch64.sh
@@ -0,0 +1,23 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# backtrace.aarch64.exe is a -static binary of backtrace-child.
+# backtrace.aarch64.core was generated by running the static backtrace-child
+# with --gencore.
+check_core aarch64
diff --git a/tests/run-backtrace-core-i386.sh b/tests/run-backtrace-core-i386.sh
new file mode 100755
index 0000000..c497f4a
--- /dev/null
+++ b/tests/run-backtrace-core-i386.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core i386
diff --git a/tests/run-backtrace-core-ppc.sh b/tests/run-backtrace-core-ppc.sh
new file mode 100755
index 0000000..1a51046
--- /dev/null
+++ b/tests/run-backtrace-core-ppc.sh
@@ -0,0 +1,29 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# executable generated by:
+#
+# gcc -D_GNU_SOURCE -I. -I.. -I../lib -m32 -pthread -static -g \
+#     -o backtrace.ppc.exec backtrace-child.c
+#
+# core generated by:
+#
+# ./backtrace.ppc.exec --gencore
+
+check_core ppc
diff --git a/tests/run-backtrace-core-s390.sh b/tests/run-backtrace-core-s390.sh
new file mode 100755
index 0000000..ce3afb9
--- /dev/null
+++ b/tests/run-backtrace-core-s390.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core s390
diff --git a/tests/run-backtrace-core-s390x.sh b/tests/run-backtrace-core-s390x.sh
new file mode 100755
index 0000000..39450c1
--- /dev/null
+++ b/tests/run-backtrace-core-s390x.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core s390x
diff --git a/tests/run-backtrace-core-sparc.sh b/tests/run-backtrace-core-sparc.sh
new file mode 100755
index 0000000..2f39e74
--- /dev/null
+++ b/tests/run-backtrace-core-sparc.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2015 Oracle, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core sparc
diff --git a/tests/run-backtrace-core-x32.sh b/tests/run-backtrace-core-x32.sh
new file mode 100755
index 0000000..e6144b3
--- /dev/null
+++ b/tests/run-backtrace-core-x32.sh
@@ -0,0 +1,23 @@
+#! /usr/bin/env bash
+# Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# backtrace.x32.exec is created by
+# gcc -mx32 -static -o backtrace.x32.exec backtrace_child-backtrace-child.o -lpthread
+# backtrace.x32.core was generated by running "backtrace.x32.exec --gencore"
+check_core x32
diff --git a/tests/run-backtrace-core-x86_64.sh b/tests/run-backtrace-core-x86_64.sh
new file mode 100755
index 0000000..4924801
--- /dev/null
+++ b/tests/run-backtrace-core-x86_64.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_core x86_64
diff --git a/tests/run-backtrace-data.sh b/tests/run-backtrace-data.sh
new file mode 100755
index 0000000..f67a43e
--- /dev/null
+++ b/tests/run-backtrace-data.sh
@@ -0,0 +1,32 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# This test really cannot be run under valgrind, it tries to introspect
+# its own maps and registers and will find valgrinds instead.
+unset VALGRIND_CMD
+
+tempfiles data.{bt,err}
+(set +ex;
+ testrun ${abs_builddir}/backtrace-data 1>data.bt 2>data.err;
+ if test $? == 77; then cat data.{bt,err}; exit 77; fi
+ true)
+
+cat data.{bt,err}
+check_unsupported data.err data
+check_all data.{bt,err} data
diff --git a/tests/run-backtrace-demangle.sh b/tests/run-backtrace-demangle.sh
new file mode 100755
index 0000000..403a485
--- /dev/null
+++ b/tests/run-backtrace-demangle.sh
@@ -0,0 +1,58 @@
+#! /usr/bin/env bash
+# Copyright (C) 2014, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+  echo "demangler unsupported"
+  exit 77
+fi
+
+. $srcdir/backtrace-subr.sh
+
+child=testfile-backtrace-demangle
+testfiles $child{,.core}
+tempfiles $child.{bt,err}
+
+# Disable valgrind while dumping because of a bug unmapping libc.so.
+# https://bugs.kde.org/show_bug.cgi?id=327427
+SAVED_VALGRIND_CMD="$VALGRIND_CMD"
+unset VALGRIND_CMD
+
+# There can be more than 3 frames, but depending on the system/installed
+# glibc we might not be able to unwind fully till the end.
+# cxxfunc -> f -> main
+# Expect to see the top two and a warning that there are more frames
+# (exit code 1)
+testrun ${abs_top_builddir}/src/stack -n 2 -e $child --core $child.core >$child.bt 2>$child.err || exitcode=$?
+cat $child.{bt,err}
+
+if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
+  VALGRIND_CMD="$SAVED_VALGRIND_CMD"
+  export VALGRIND_CMD
+fi
+
+if test $exitcode != 1 || ! grep "shown max number of frames" $child.err; then
+  echo >&2 $2: expected more than 2 frames
+  false
+fi
+if ! grep -w f $child.bt; then
+  echo >&2 $2: no f
+  false
+fi
+if ! grep ' cxxfunc(int)' $child.bt; then
+  echo >&2 $2: no cxxfunc
+  false
+fi
diff --git a/tests/run-backtrace-dwarf.sh b/tests/run-backtrace-dwarf.sh
new file mode 100755
index 0000000..7ed795d
--- /dev/null
+++ b/tests/run-backtrace-dwarf.sh
@@ -0,0 +1,30 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# This test really cannot be run under valgrind, it tries to introspect
+# itself through ptrace and will find bits and pieces of valgrind.
+# On top of that valgrind also tries to read all the unwind info and
+# will warn and complain about various opcodes it doesn't understand...
+unset VALGRIND_CMD
+
+tempfiles dwarf.{bt,err}
+(set +ex; testrun ${abs_builddir}/backtrace-dwarf 1>dwarf.bt 2>dwarf.err; true)
+cat dwarf.{bt,err}
+check_native_unsupported dwarf.err dwarf
+check_main dwarf.bt dwarf
diff --git a/tests/run-backtrace-fp-core-aarch64.sh b/tests/run-backtrace-fp-core-aarch64.sh
new file mode 100755
index 0000000..397e3c3
--- /dev/null
+++ b/tests/run-backtrace-fp-core-aarch64.sh
@@ -0,0 +1,28 @@
+#! /usr/bin/env bash
+# Copyright (C) 2017 The Qt Company
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# The binary is generated by compiling with eh_frame CFI, but with frame
+# pointers.
+#
+# gcc -static -O2 -fno-omit-frame-pointer -fno-asynchronous-unwind-tables \
+#     -D_GNU_SOURCE -pthread -o tests/backtrace.aarch64.fp.exec -I. -Ilib \
+#     tests/backtrace-child.c
+# The core is generated by calling the binary with --gencore
+
+check_core aarch64.fp
diff --git a/tests/run-backtrace-fp-core-i386.sh b/tests/run-backtrace-fp-core-i386.sh
new file mode 100755
index 0000000..43f859f
--- /dev/null
+++ b/tests/run-backtrace-fp-core-i386.sh
@@ -0,0 +1,29 @@
+#! /usr/bin/env bash
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# The binary is generated by compiling backtrace-child without unwind
+# information, but with -fno-omit-frame-pointer.
+#
+# gcc -static -O2 -fno-omit-frame-pointer -fno-asynchronous-unwind-tables \
+#     -D_GNU_SOURCE -pthread -o tests/backtrace.i386.fp.exec -I. -Ilib \
+#     tests/backtrace-child.c
+#
+# The core is generated by calling tests/backtrace.i386.fp.exec --gencore
+
+check_core i386.fp
diff --git a/tests/run-backtrace-fp-core-ppc64le.sh b/tests/run-backtrace-fp-core-ppc64le.sh
new file mode 100755
index 0000000..345b8db
--- /dev/null
+++ b/tests/run-backtrace-fp-core-ppc64le.sh
@@ -0,0 +1,29 @@
+#! /usr/bin/env bash
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# The binary is generated by compiling backtrace-child without unwind
+# information, but with -fno-omit-frame-pointer.
+#
+# gcc -static -O2 -fno-omit-frame-pointer -fno-asynchronous-unwind-tables \
+#     -D_GNU_SOURCE -pthread -o tests/backtrace.ppc64le.fp.exec -I. -Ilib \
+#     tests/backtrace-child.c
+#
+# The core is generated by calling tests/backtrace.ppc64le.fp.exec --gencore
+
+check_core ppc64le.fp
diff --git a/tests/run-backtrace-fp-core-x86_64.sh b/tests/run-backtrace-fp-core-x86_64.sh
new file mode 100755
index 0000000..12f44c4
--- /dev/null
+++ b/tests/run-backtrace-fp-core-x86_64.sh
@@ -0,0 +1,29 @@
+#! /usr/bin/env bash
+# Copyright (C) 2017 The Qt Company
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+# The binary is generated by compiling with eh_frame CFI, but with frame
+# pointers.
+#
+# gcc -static -O2 -fno-omit-frame-pointer -fno-asynchronous-unwind-tables \
+#     -D_GNU_SOURCE -pthread -o tests/backtrace.x86_64.fp.exec -I. -Ilib \
+#     tests/backtrace-child.c
+#
+# The core is generated by calling the binary with --gencore
+
+check_core x86_64.fp
diff --git a/tests/run-backtrace-native-biarch.sh b/tests/run-backtrace-native-biarch.sh
new file mode 100755
index 0000000..9286983
--- /dev/null
+++ b/tests/run-backtrace-native-biarch.sh
@@ -0,0 +1,25 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test -n "$ELFUTILS_DISABLE_BIARCH"; then
+  echo "biarch testing disabled"
+  exit 77
+fi
+
+. $srcdir/backtrace-subr.sh
+
+check_native backtrace-child-biarch
diff --git a/tests/run-backtrace-native-core-biarch.sh b/tests/run-backtrace-native-core-biarch.sh
new file mode 100755
index 0000000..2327425
--- /dev/null
+++ b/tests/run-backtrace-native-core-biarch.sh
@@ -0,0 +1,25 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test -n "$ELFUTILS_DISABLE_BIARCH"; then
+  echo "biarch testing disabled"
+  exit 77
+fi
+
+. $srcdir/backtrace-subr.sh
+
+check_native_core backtrace-child-biarch
diff --git a/tests/run-backtrace-native-core.sh b/tests/run-backtrace-native-core.sh
new file mode 100755
index 0000000..db95895
--- /dev/null
+++ b/tests/run-backtrace-native-core.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_native_core backtrace-child
diff --git a/tests/run-backtrace-native.sh b/tests/run-backtrace-native.sh
new file mode 100755
index 0000000..823c411
--- /dev/null
+++ b/tests/run-backtrace-native.sh
@@ -0,0 +1,20 @@
+#! /usr/bin/env bash
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+check_native backtrace-child
diff --git a/tests/run-bug1-test.sh b/tests/run-bug1-test.sh
new file mode 100755
index 0000000..1e78a18
--- /dev/null
+++ b/tests/run-bug1-test.sh
@@ -0,0 +1,34 @@
+#! /bin/sh
+# Copyright (C) 2006 Red Hat, Inc.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2006.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile28 testfile28.rdwr
+
+testrun ${abs_builddir}/rdwrmmap testfile28
+
+cmp testfile28 testfile28.rdwr
+
+test_cleanup
+
+testfiles testfile29 testfile29.rdwr
+
+testrun ${abs_builddir}/rdwrmmap testfile29
+
+cmp testfile29 testfile29.rdwr
+
+exit 0
diff --git a/tests/run-buildid.sh b/tests/run-buildid.sh
new file mode 100755
index 0000000..31cec24
--- /dev/null
+++ b/tests/run-buildid.sh
@@ -0,0 +1,38 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Just some random testfiles, four with, one without build-id,
+# and one without shdrs forcing reading the notes through phdrs.
+# eu-strip --strip-sections -g --output=testfile42_noshdrs testfile42
+# See also run-debugaltlink.sh.
+testfiles testfile42 testfile_multi.dwz testfile-dwzstr.multi \
+    test-offset-loop.alt testfile14 testfile42_noshdrs
+
+testrun_compare  ${abs_builddir}/buildid testfile42 testfile42_noshdrs \
+    testfile_multi.dwz testfile-dwzstr.multi \
+    test-offset-loop.alt testfile14 <<\EOF
+testfile42: build ID: d826d96c4d097bdc5c254b1f7344a907e36b0439
+testfile42_noshdrs: build ID: d826d96c4d097bdc5c254b1f7344a907e36b0439
+testfile_multi.dwz: build ID: a0d6c06e0d912d74033b6fe2808753cae8f6f594
+testfile-dwzstr.multi: build ID: 6da22627dae55c1d62cf9122827c665e240a056b
+test-offset-loop.alt: build ID: 066bbf1a7bc5676f5015ee1966a088f23bdb83ae
+testfile14: <no NT_GNU_BUILD_ID note>
+EOF
+
+exit 0
diff --git a/tests/run-compress-test.sh b/tests/run-compress-test.sh
new file mode 100755
index 0000000..2d4eebd
--- /dev/null
+++ b/tests/run-compress-test.sh
@@ -0,0 +1,130 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# uncompress -> gnucompress -> uncompress -> elfcompress -> uncompress
+testrun_elfcompress_file()
+{
+    infile="$1"
+    uncompressedfile="${infile}.uncompressed"
+    tempfiles "$uncompressedfile"
+    
+    echo "uncompress $infile -> $uncompressedfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t none -o ${uncompressedfile} ${infile}
+    testrun ${abs_top_builddir}/src/elflint --gnu-ld ${uncompressedfile}
+
+    SIZE_uncompressed=$(stat -c%s $uncompressedfile)
+
+    gnucompressedfile="${infile}.gnu"
+    tempfiles "$gnucompressedfile"
+    echo "compress gnu $uncompressedfile -> $gnucompressedfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t gnu -o ${gnucompressedfile} ${uncompressedfile}
+    testrun ${abs_top_builddir}/src/elflint --gnu-ld ${gnucompressedfile}
+
+    SIZE_gnucompressed=$(stat -c%s $gnucompressedfile)
+    test $SIZE_gnucompressed -lt $SIZE_uncompressed ||
+	{ echo "*** failure $gnucompressedfile not smaller"; exit -1; }
+    
+    gnuuncompressedfile="${infile}.gnu.uncompressed"
+    tempfiles "$gnuuncompressedfile"
+    echo "uncompress $gnucompressedfile -> $gnuuncompressedfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t none -o ${gnuuncompressedfile} ${gnucompressedfile}
+    testrun ${abs_top_builddir}/src/elfcmp ${uncompressedfile} ${gnuuncompressedfile}
+
+    elfcompressedfile="${infile}.gabi"
+    tempfiles "$elfcompressedfile"
+    echo "compress gabi $uncompressedfile -> $elfcompressedfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t zlib -o ${elfcompressedfile} ${uncompressedfile}
+    testrun ${abs_top_builddir}/src/elflint --gnu-ld ${elfcompressedfile}
+
+    SIZE_elfcompressed=$(stat -c%s $elfcompressedfile)
+    test $SIZE_elfcompressed -lt $SIZE_uncompressed ||
+	{ echo "*** failure $elfcompressedfile not smaller"; exit -1; }
+    
+    elfuncompressedfile="${infile}.gabi.uncompressed"
+    tempfiles "$elfuncompressedfile"
+    echo "uncompress $elfcompressedfile -> $elfuncompressedfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t none -o ${elfuncompressedfile} ${elfcompressedfile}
+    testrun ${abs_top_builddir}/src/elfcmp ${uncompressedfile} ${elfuncompressedfile}
+
+    if test -z "$ELFUTILS_ZSTD"; then
+      return;
+    fi
+
+    outputfile="${infile}.gabi.zstd"
+    tempfiles "$outputfile"
+    echo "zstd compress $elfcompressedfile -> $outputfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t zstd -o ${outputfile} ${elfcompressedfile}
+    testrun ${abs_top_builddir}/src/elfcmp ${uncompressedfile} ${outputfile}
+    echo "checking compressed section header" $outputfile
+    testrun ${abs_top_builddir}/src/readelf -Sz ${outputfile} | grep "ELF ZSTD" >/dev/null
+
+    zstdfile="${infile}.zstd"
+    tempfiles "$zstdfile"
+    echo "zstd compress $uncompressedfile -> $zstdfile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t zstd -o ${zstdfile} ${elfuncompressedfile}
+    testrun ${abs_top_builddir}/src/elfcmp ${uncompressedfile} ${zstdfile}
+    echo "checking compressed section header" $zstdfile
+    testrun ${abs_top_builddir}/src/readelf -Sz ${zstdfile} | grep "ELF ZSTD" >/dev/null
+
+    zstdgnufile="${infile}.zstd.gnu"
+    tempfiles "$zstdgnufile"
+    echo "zstd re-compress to GNU ZLIB $zstdfile -> $zstdgnufile"
+    testrun ${abs_top_builddir}/src/elfcompress -v -t zlib-gnu -o ${zstdgnufile} ${zstdfile}
+    testrun ${abs_top_builddir}/src/elfcmp ${uncompressedfile} ${zstdgnufile}
+    echo "checking .zdebug section name" $zstdgnufile
+    testrun ${abs_top_builddir}/src/readelf -S ${zstdgnufile} | grep ".zdebug" >/dev/null
+}
+
+testrun_elfcompress()
+{
+    testfile="$1"
+    testfiles ${testfile}
+    testrun_elfcompress_file ${testfile}
+
+    # Merge the string tables to make things a little more interesting.
+    mergedfile="${testfile}.merged"
+    tempfiles ${mergedfile}
+    echo "merging string tables ${testfile} -> ${mergedfile}"
+    testrun ${abs_top_builddir}/tests/elfstrmerge -o ${mergedfile} ${testfile}
+    testrun_elfcompress_file ${mergedfile}
+}
+
+# Random ELF32 testfile
+testrun_elfcompress testfile4
+
+# Random ELF64 testfile
+testrun_elfcompress testfile12
+
+# Random ELF64BE testfile
+testrun_elfcompress testfileppc64
+
+# Random ELF32BE testfile
+testrun_elfcompress testfileppc32
+
+# Already compressed files
+testrun_elfcompress testfile-zgnu64
+testrun_elfcompress testfile-zgnu64be
+testrun_elfcompress testfile-zgabi64
+testrun_elfcompress testfile-zgabi64be
+testrun_elfcompress testfile-zgnu32
+testrun_elfcompress testfile-zgnu32be
+testrun_elfcompress testfile-zgabi32
+testrun_elfcompress testfile-zgabi32be
+
+exit 0
diff --git a/tests/run-copyadd-sections.sh b/tests/run-copyadd-sections.sh
new file mode 100755
index 0000000..bc20f6e
--- /dev/null
+++ b/tests/run-copyadd-sections.sh
@@ -0,0 +1,87 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+test_copy_and_add ()
+{
+  in_file="$1"
+  out_file="${in_file}.copy"
+  out_file_mmap="${out_file}.mmap"
+
+  testfiles ${in_file}
+  tempfiles ${out_file} ${out_file_mmap} readelf.out
+
+  # Can we copy the file?
+  testrun ${abs_builddir}/elfcopy ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file}
+
+  # Can we add a section (in-place)?
+  testrun ${abs_builddir}/addsections 3 ${out_file}
+  testrun ${abs_top_builddir}/src/readelf -S ${out_file} > readelf.out
+  nr=$(grep '.extra' readelf.out | wc -l)
+  if test ${nr} != 3; then
+    # Show what went wrong
+    testrun ${abs_top_builddir}/src/readelf -S ${out_file}
+    exit 1
+  fi
+
+  # Can we add a section (in-place) using ELF_C_WRITE_MMAP?
+  testrun ${abs_builddir}/elfcopy --mmap ${in_file} ${out_file_mmap}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file_mmap}
+
+  # Can we add a section (in-place) using ELF_C_RDWR_MMAP?
+  # Note we are only adding one sections, adding more might fail
+  # because mremap cannot extend too much.
+  testrun ${abs_builddir}/addsections --mmap 1 ${out_file_mmap}
+  testrun ${abs_top_builddir}/src/readelf -S ${out_file_mmap} > readelf.out
+  nr=$(grep '.extra' readelf.out | wc -l)
+  if test ${nr} != 1; then
+    # Show what went wrong
+    testrun ${abs_top_builddir}/src/readelf -S ${out_file_mmap}
+    exit 1
+  fi
+}
+
+# A collection of random testfiles to test 32/64bit, little/big endian
+# and non-ET_REL (with phdrs)/ET_REL (without phdrs).
+
+# 32bit, big endian, rel
+test_copy_and_add testfile29
+
+# 64bit, big endian, rel
+test_copy_and_add testfile23
+
+# 32bit, little endian, rel
+test_copy_and_add testfile9
+
+# 64bit, little endian, rel
+test_copy_and_add testfile38
+
+# 32bit, big endian, non-rel
+test_copy_and_add testfile26
+
+# 64bit, big endian, non-rel
+test_copy_and_add testfile27
+
+# 32bit, little endian, non-rel
+test_copy_and_add testfile
+
+# 64bit, little endian, non-rel
+test_copy_and_add testfile10
+
+exit 0
diff --git a/tests/run-copymany-be32.sh b/tests/run-copymany-be32.sh
new file mode 100755
index 0000000..dc32e7a
--- /dev/null
+++ b/tests/run-copymany-be32.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $srcdir/test-copymany-subr.sh
+
+# 32bit, big endian, rel
+testfiles testfile29
+test_copy_and_add testfile29
+test_copy_and_add testfile29.copy
+
+# 32bit, big endian, non-rel
+testfiles testfile26
+test_copy_and_add testfile26
+test_copy_and_add testfile26.copy
+
+exit 0
diff --git a/tests/run-copymany-be64.sh b/tests/run-copymany-be64.sh
new file mode 100755
index 0000000..1f06e07
--- /dev/null
+++ b/tests/run-copymany-be64.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $srcdir/test-copymany-subr.sh
+
+# 64bit, big endian, rel
+testfiles testfile23
+test_copy_and_add testfile23
+test_copy_and_add testfile23.copy
+
+# 64bit, big endian, non-rel
+testfiles testfile27
+test_copy_and_add testfile27
+test_copy_and_add testfile27.copy
+
+exit 0
diff --git a/tests/run-copymany-le32.sh b/tests/run-copymany-le32.sh
new file mode 100755
index 0000000..d47a90e
--- /dev/null
+++ b/tests/run-copymany-le32.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $srcdir/test-copymany-subr.sh
+
+# 32bit, little endian, rel
+testfiles testfile9
+test_copy_and_add testfile9
+test_copy_and_add testfile9.copy
+
+# 32bit, little endian, non-rel
+testfiles testfile
+test_copy_and_add testfile
+test_copy_and_add testfile.copy
+
+exit 0
diff --git a/tests/run-copymany-le64.sh b/tests/run-copymany-le64.sh
new file mode 100755
index 0000000..b563d9d
--- /dev/null
+++ b/tests/run-copymany-le64.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $srcdir/test-copymany-subr.sh
+
+# 64bit, little endian, rel
+testfiles testfile38
+test_copy_and_add testfile38
+test_copy_and_add testfile38.copy
+
+# 64bit, little endian, non-rel
+testfiles testfile10
+test_copy_and_add testfile10
+test_copy_and_add testfile10.copy
+
+exit 0
diff --git a/tests/run-cu-dwp-section-info.sh b/tests/run-cu-dwp-section-info.sh
new file mode 100755
index 0000000..202319c
--- /dev/null
+++ b/tests/run-cu-dwp-section-info.sh
@@ -0,0 +1,168 @@
+#! /bin/sh
+# Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5.dwp testfile-dwp-4.dwp testfile-dwp-4-strict.dwp
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-5.dwp << EOF
+file: testfile-dwp-5.dwp
+INFO: 0x0 0x70
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x160
+LINE: 0x0 0x7f
+LOCLISTS: 0x0 0xdb
+STR_OFFSETS: 0x0 0x75c
+MACRO: 0x0 0x6c6
+RNGLISTS: 0x0 0x22
+
+INFO: 0x70 0x108
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x160
+LINE: 0x0 0x7f
+LOCLISTS: 0x0 0xdb
+STR_OFFSETS: 0x0 0x75c
+MACRO: 0x0 0x6c6
+RNGLISTS: 0x0 0x22
+
+INFO: 0x178 0x6e
+TYPES: 0x0 0x0
+ABBREV: 0x160 0xca
+LINE: 0x7f 0x7f
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x75c 0x758
+MACRO: 0x6c6 0x6c5
+RNGLISTS: 0x0 0x0
+
+INFO: 0x1e6 0x78
+TYPES: 0x0 0x0
+ABBREV: 0x160 0xca
+LINE: 0x7f 0x7f
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x75c 0x758
+MACRO: 0x6c6 0x6c5
+RNGLISTS: 0x0 0x0
+
+INFO: 0x25e 0x193
+TYPES: 0x0 0x0
+ABBREV: 0x22a 0x18a
+LINE: 0xfe 0x81
+LOCLISTS: 0xdb 0xc9
+STR_OFFSETS: 0xeb4 0x77c
+MACRO: 0xd8b 0x6c6
+RNGLISTS: 0x22 0x43
+
+EOF
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-4.dwp << EOF
+file: testfile-dwp-4.dwp
+INFO: 0x0 0x11e
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x172
+LINE: 0x0 0x52
+LOCLISTS: 0x0 0x11b
+STR_OFFSETS: 0x0 0x754
+MACRO: 0x0 0x6c7
+RNGLISTS: 0x0 0x0
+
+INFO: 0x11e 0x76
+TYPES: 0x0 0x0
+ABBREV: 0x172 0xd7
+LINE: 0x52 0x52
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x754 0x750
+MACRO: 0x6c7 0x6c6
+RNGLISTS: 0x0 0x0
+
+INFO: 0x194 0x1c5
+TYPES: 0x0 0x0
+ABBREV: 0x249 0x19e
+LINE: 0xa4 0x53
+LOCLISTS: 0x11b 0xf1
+STR_OFFSETS: 0xea4 0x774
+MACRO: 0xd8d 0x6c7
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x0 0x6f
+ABBREV: 0x0 0x172
+LINE: 0x0 0x52
+LOCLISTS: 0x0 0x11b
+STR_OFFSETS: 0x0 0x754
+MACRO: 0x0 0x6c7
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x6f 0x6d
+ABBREV: 0x172 0xd7
+LINE: 0x52 0x52
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x754 0x750
+MACRO: 0x6c7 0x6c6
+RNGLISTS: 0x0 0x0
+
+EOF
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-4-strict.dwp << EOF
+file: testfile-dwp-4-strict.dwp
+INFO: 0x0 0x105
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x15f
+LINE: 0x0 0x52
+LOCLISTS: 0x0 0xe2
+STR_OFFSETS: 0x0 0x24
+MACRO: 0x0 0x38e4
+RNGLISTS: 0x0 0x0
+
+INFO: 0x105 0x72
+TYPES: 0x0 0x0
+ABBREV: 0x15f 0xd3
+LINE: 0x52 0x52
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x24 0x20
+MACRO: 0x38e4 0x38db
+RNGLISTS: 0x0 0x0
+
+INFO: 0x177 0x17b
+TYPES: 0x0 0x0
+ABBREV: 0x232 0x157
+LINE: 0xa4 0x53
+LOCLISTS: 0xe2 0xb1
+STR_OFFSETS: 0x44 0x44
+MACRO: 0x71bf 0x38f5
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x0 0x6e
+ABBREV: 0x0 0x15f
+LINE: 0x0 0x52
+LOCLISTS: 0x0 0xe2
+STR_OFFSETS: 0x0 0x24
+MACRO: 0x0 0x38e4
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x6e 0x6b
+ABBREV: 0x15f 0xd3
+LINE: 0x52 0x52
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x24 0x20
+MACRO: 0x38e4 0x38db
+RNGLISTS: 0x0 0x0
+
+EOF
diff --git a/tests/run-debugaltlink.sh b/tests/run-debugaltlink.sh
new file mode 100755
index 0000000..fa7dd26
--- /dev/null
+++ b/tests/run-debugaltlink.sh
@@ -0,0 +1,34 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Just some random testfiles, four with, one without .gnu_debugaltlink
+testfiles testfile42 testfile_multi_main testfile-dwzstr \
+    test-offset-loop libtestfile_multi_shared.so
+
+testrun_compare  ${abs_builddir}/debugaltlink testfile42 \
+    testfile_multi_main testfile-dwzstr \
+    test-offset-loop libtestfile_multi_shared.so <<\EOF
+testfile42: <no .gnu_debugaltlink section>
+testfile_multi_main: testfile_multi.dwz, build ID: a0d6c06e0d912d74033b6fe2808753cae8f6f594
+testfile-dwzstr: testfile-dwzstr.multi, build ID: 6da22627dae55c1d62cf9122827c665e240a056b
+test-offset-loop: test-offset-loop.alt, build ID: 066bbf1a7bc5676f5015ee1966a088f23bdb83ae
+libtestfile_multi_shared.so: testfile_multi.dwz, build ID: a0d6c06e0d912d74033b6fe2808753cae8f6f594
+EOF
+
+exit 0
diff --git a/tests/run-debuginfod-IXr.sh b/tests/run-debuginfod-IXr.sh
new file mode 100755
index 0000000..631b7bb
--- /dev/null
+++ b/tests/run-debuginfod-IXr.sh
@@ -0,0 +1,94 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2023 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+mkdir R Z
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=10100
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+    rpms=0
+    tarxz=1
+    groomed=2
+else
+    rpms=6
+    tarxz=1
+    groomed=8
+fi
+
+cp -rvp ${abs_srcdir}/debuginfod-tars Z
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d $DB -X 'hello2' -I 'hello' -R -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT1 -t0 -g0 -v R Z > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# Confirm that the hello3 files are excluded
+
+wait_ready $PORT1 'scanned_files_total{source=".rpm archive"}' $rpms
+wait_ready $PORT1 'scanned_files_total{source=".tar.xz archive"}' $tarxz
+
+
+kill $PID1
+wait $PID1
+PID1=0
+
+# Start second debuginfod, with exclusion of everything
+
+echo 'RERUN WITH -r and -X everything' >> vlog$PORT1
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d $DB -r -X '.*' -F -R -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT1 -t0 -g0 -v R Z >> vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+
+wait_ready $PORT1 'thread_work_total{role="groom"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+wait_ready $PORT1 'groomed_total{decision="stale"}' $groomed
+wait_ready $PORT1 'groom{statistic="files scanned (#)"}' 0
+
+kill $PID1
+wait $PID1
+PID1=0
+
+exit 0
diff --git a/tests/run-debuginfod-archive-groom.sh b/tests/run-debuginfod-archive-groom.sh
new file mode 100755
index 0000000..e2c394e
--- /dev/null
+++ b/tests/run-debuginfod-archive-groom.sh
@@ -0,0 +1,166 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8100
+get_ports
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+# Clean old dirictories
+mkdir R ${PWD}/F
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE \
+    -F -R -d $DB -p $PORT1 -t0 -g0 -v R ${PWD}/F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# Be patient when run on a busy machine things might take a bit.
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# wait till the initial scan is done before triggering a new one
+# and before dropping new file into the scan dirs
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+# Same for the initial groom cycle, we don't want it to be done
+# half way initializing the file setup
+wait_ready $PORT1 'thread_work_total{role="groom"}' 1
+
+# Build a non-stripped binary
+echo "int main() { return 0; }" > ${PWD}/F/prog.c
+gcc -Wl,--build-id -g -o ${PWD}/F/prog ${PWD}/F/prog.c
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a ${PWD}/F/prog | grep 'Build ID' | cut -d ' ' -f 7`
+tempfiles ${PWD}/F/prog ${PWD}/F/prog.c
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+kill -USR1 $PID1
+# Now there should be 1 files in the index
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+tempfiles vlog3
+cp -rvp ${abs_srcdir}/debuginfod-tars Z
+kill -USR1 $PID1
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 3
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+########################################################################
+# All rpms need to be in the index, except the dummy permission-000 one
+rpms=$(find R -name \*rpm | grep -v nothing | wc -l)
+wait_ready $PORT1 'scanned_files_total{source=".rpm archive"}' $rpms
+txz=$(find Z -name \*tar.xz | wc -l)
+
+kill -USR1 $PID1  # two hits of SIGUSR1 may be needed to resolve .debug->dwz->srefs
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 4
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# Expect all source files found in the rpms (they are all called hello.c :)
+# We will need to extract all rpms (in their own directory) and could all
+# sources referenced in the .debug files.
+mkdir extracted
+cd extracted
+subdir=0;
+newrpms=$(find ../R -name \*\.rpm | grep -v nothing)
+for i in $newrpms; do
+    subdir=$[$subdir+1];
+    mkdir $subdir;
+    cd $subdir;
+    ls -lah ../$i
+    rpm2cpio ../$i | cpio -ivd;
+    cd ..;
+done
+sourcefiles=$(find -name \*\\.debug \
+              | env LD_LIBRARY_PATH=$ldpath xargs \
+                ${abs_top_builddir}/src/readelf --debug-dump=decodedline \
+              | grep mtime: | wc --lines)
+cd ..
+rm -rf extracted
+
+wait_ready $PORT1 'found_sourcerefs_total{source=".rpm archive"}' $sourcefiles
+
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+
+# common source file sha1
+SHA=f4a1a8062be998ae93b8f1cd744a398c6de6dbb1
+# fedora31
+if [ $zstd = true ]; then
+    # fedora31 uses zstd compression on rpms, older rpm2cpio/libarchive can't handle it
+    # and we're not using the fancy -Z '.rpm=(rpm2cpio|zstdcat)<' workaround in this testsuite
+    archive_test 420e9e3308971f4b817cc5bf83928b41a6909d88 /usr/src/debug/hello3-1.0-2.x86_64/foobar////./../hello.c $SHA
+    archive_test 87c08d12c78174f1082b7c888b3238219b0eb265 /usr/src/debug/hello3-1.0-2.x86_64///foobar/./..//hello.c $SHA
+fi
+# fedora30
+archive_test c36708a78618d597dee15d0dc989f093ca5f9120 /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA
+archive_test 41a236eb667c362a1c4196018cc4581e09722b1b /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA
+# rhel7
+archive_test bc1febfd03ca05e030f0d205f7659db29f8a4b30 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test f0aa15b8aba4f3c28cac3c2a73801fefa644a9f2 /usr/src/debug/hello-1.0/hello.c $SHA
+# rhel6
+archive_test bbbf92ebee5228310e398609c23c2d7d53f6e2f9 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test d44d42cbd7d915bc938c81333a21e355a6022fb7 /usr/src/debug/hello-1.0/hello.c $SHA
+RPM_BUILDID=d44d42cbd7d915bc938c81333a21e355a6022fb7 # in rhel6/ subdir
+
+# Drop some of the artifacts, run a groom cycle; confirm that
+# debuginfod has forgotten them, but remembers others
+rm -r R/debuginfod-rpms/rhel6/*
+
+kill -USR2 $PID1  # groom cycle
+## 1 groom cycle already took place at/soon-after startup, so -USR2 makes 2
+wait_ready $PORT1 'thread_work_total{role="groom"}' 2
+# Expect 4 rpms containing 2 buildids to be deleted by the groom
+wait_ready $PORT1 'groomed_total{decision="stale"}' 4
+# Expect no more groom actions pending
+wait_ready $PORT1 'thread_work_pending{role="groom"}' 0
+
+rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
+
+# this is one of the buildids from the groom-deleted rpms
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $RPM_BUILDID && false || true
+
+# but this one was not deleted so should be still around
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID || true
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-archive-rename.sh b/tests/run-debuginfod-archive-rename.sh
new file mode 100755
index 0000000..71f7742
--- /dev/null
+++ b/tests/run-debuginfod-archive-rename.sh
@@ -0,0 +1,103 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8200
+get_ports
+DB=${PWD}/.debuginfod_tmp.sqlite
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+tempfiles $DEBUGINFOD_CACHE_PATH $DB
+# Clean old dirictories
+mkdir R ${PWD}/F
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE \
+    -F -R -d $DB -p $PORT1 -t0 -g0 -v R ${PWD}/F > vlog$PORT1 2>&1 &
+
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# wait till the initial scan is done before triggering a new one
+# and before dropping new file into the scan dirs
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+# Same for the initial groom cycle, we don't want it to be done
+# half way initializing the file setup
+wait_ready $PORT1 'thread_work_total{role="groom"}' 1
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+kill -USR1 $PID1
+# Now there should be 1 files in the index
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# common source file sha1
+SHA=f4a1a8062be998ae93b8f1cd744a398c6de6dbb1
+
+########################################################################
+## PR26810: Now rename some files in the R directory, then rescan, so
+# there are two copies of the same buildid in the index, one for the
+# no-longer-existing file name, and one under the new name.
+
+# run a groom cycle to force server to drop its fdcache
+kill -USR2 $PID1  # groom cycle
+wait_ready $PORT1 'thread_work_total{role="groom"}' 2
+# move it around a couple of times to make it likely to hit a nonexistent entry during iteration
+mv R/debuginfod-rpms/rhel7 R/debuginfod-rpms/rhel7renamed
+kill -USR1 $PID1  # scan cycle
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 3
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+mv R/debuginfod-rpms/rhel7renamed R/debuginfod-rpms/rhel7renamed2
+kill -USR1 $PID1  # scan cycle
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 4
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+mv R/debuginfod-rpms/rhel7renamed2 R/debuginfod-rpms/rhel7renamed3
+kill -USR1 $PID1  # scan cycle
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 5
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+
+# retest rhel7
+archive_test bc1febfd03ca05e030f0d205f7659db29f8a4b30 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test f0aa15b8aba4f3c28cac3c2a73801fefa644a9f2 /usr/src/debug/hello-1.0/hello.c $SHA
+
+grep -E '(libc.error.*rhel7)|(bc1febfd03ca)|(f0aa15b8aba)' vlog$PORT1
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0;
diff --git a/tests/run-debuginfod-archive-test.sh b/tests/run-debuginfod-archive-test.sh
new file mode 100755
index 0000000..5f24ea7
--- /dev/null
+++ b/tests/run-debuginfod-archive-test.sh
@@ -0,0 +1,87 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+# find an unused port number
+mkdir R
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8300
+get_ports
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -R -p $PORT1 -d $DB -t0 -g0 -v R > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And make sure first scan is done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+# Be patient when run on a busy machine things might take a bit.
+export DEBUGINFOD_URLS='http://127.0.0.1:'$PORT1
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+kill -USR1 $PID1
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# common source file sha1
+SHA=f4a1a8062be998ae93b8f1cd744a398c6de6dbb1
+# fedora31
+if [ $zstd = true ]; then
+    # fedora31 uses zstd compression on rpms, older rpm2cpio/libarchive can't handle it
+    # and we're not using the fancy -Z '.rpm=(rpm2cpio|zstdcat)<' workaround in this testsuite
+    archive_test 420e9e3308971f4b817cc5bf83928b41a6909d88 /usr/src/debug/hello3-1.0-2.x86_64/foobar////./../hello.c $SHA
+    archive_test 87c08d12c78174f1082b7c888b3238219b0eb265 /usr/src/debug/hello3-1.0-2.x86_64///foobar/./..//hello.c $SHA
+fi
+# fedora30
+archive_test c36708a78618d597dee15d0dc989f093ca5f9120 /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA
+archive_test 41a236eb667c362a1c4196018cc4581e09722b1b /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA
+# rhel7
+archive_test bc1febfd03ca05e030f0d205f7659db29f8a4b30 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test f0aa15b8aba4f3c28cac3c2a73801fefa644a9f2 /usr/src/debug/hello-1.0/hello.c $SHA
+# rhel6
+archive_test bbbf92ebee5228310e398609c23c2d7d53f6e2f9 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test d44d42cbd7d915bc938c81333a21e355a6022fb7 /usr/src/debug/hello-1.0/hello.c $SHA
+# arch
+#archive_test cee13b2ea505a7f37bd20d271c6bc7e5f8d2dfcb /usr/src/debug/hello.c 7a1334e086b97e5f124003a6cfb3ed792d10cdf4
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-artifact-running.sh b/tests/run-debuginfod-artifact-running.sh
new file mode 100755
index 0000000..8b9aed3
--- /dev/null
+++ b/tests/run-debuginfod-artifact-running.sh
@@ -0,0 +1,119 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8400
+get_ports
+mkdir F
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+echo 'int main(int argc, char * argv){ return 0; }' > ${PWD}/prog.c
+gcc -Wl,--build-id -g -o prog ${PWD}/prog.c
+testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+tempfiles prog prog.debug prog.c
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a prog | grep 'Build ID' | cut -d ' ' -f 7`
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d $DB -F -p $PORT1 -t0 -g0 -v F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And the initial scan should have been done before moving
+# files under the scan dirs.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+mv prog F
+mv prog.debug F
+tempfiles prog/F
+
+kill -USR1 $PID1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# Add artifacts to the search paths and test whether debuginfod finds them while already running.
+# Build another, non-stripped binary
+echo "int main() { return 0; }" > ${PWD}/prog2.c
+tempfiles prog2.c
+gcc -Wl,--build-id -g -o prog2 ${PWD}/prog2.c
+#testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+BUILDID2=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a prog2 | grep 'Build ID' | cut -d ' ' -f 7`
+mv prog2 F
+#mv prog2.debug F
+tempfiles F/prog2 F/prog2.debug
+
+kill -USR1 $PID1
+# Now there should be 3 files in the index
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 3
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+########################################################################
+
+# Test whether debuginfod-find is able to fetch those files.
+rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID`
+cmp $filename F/prog.debug
+
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find executable F/prog`
+cmp $filename F/prog
+
+# raw source filename
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID ${PWD}/foobar///./../prog.c`
+cmp $filename  ${PWD}/prog.c
+
+# and also the canonicalized one
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID ${PWD}/prog.c`
+cmp $filename  ${PWD}/prog.c
+
+# Rerun same tests for the prog2 binary
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find -v debuginfo $BUILDID2 2>vlog`
+cmp $filename F/prog2
+grep -q Progress vlog
+grep -q Downloaded.from vlog
+tempfiles vlog
+filename=`testrun env DEBUGINFOD_PROGRESS=1 ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID2 2>vlog2`
+cmp $filename F/prog2
+grep -q 'Downloading.*http' vlog2
+tempfiles vlog2
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source $BUILDID2 ${PWD}/prog2.c`
+cmp $filename ${PWD}/prog2.c
+
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-dlopen.sh b/tests/run-debuginfod-dlopen.sh
new file mode 100755
index 0000000..7279b02
--- /dev/null
+++ b/tests/run-debuginfod-dlopen.sh
@@ -0,0 +1,91 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+mkdir F
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8500
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod -F -R $VERBOSE -p $PORT1 -d $DB \
+    -t0 -g0 -v F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/   # or without trailing /
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a'
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# Make sure the initial scan has finished.
+# Before moving files under the scan dirs.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+# We use -t0 and -g0 here to turn off time-based scanning & grooming.
+# For testing purposes, we just sic SIGUSR1 / SIGUSR2 at the process.
+
+########################################################################
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/p+r%o\$g.c
+tempfiles p+r%o\$g.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o p+r%o\$g ${PWD}/foobar///./../p+r%o\$g.c
+testrun ${abs_top_builddir}/src/strip -g -f p+r%o\$g.debug ${PWD}/p+r%o\$g
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a p+r%o\\$g | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv p+r%o\$g F
+mv p+r%o\$g.debug F
+
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+########################################################################
+
+# Test whether elfutils, via the debuginfod client library dlopen hooks,
+# is able to fetch debuginfo from the local debuginfod.
+testrun ${abs_builddir}/debuginfod_build_id_find -e F/p+r%o\$g 1
+
+kill $PID1
+wait $PID1
+PID1=0
+
+exit 0
diff --git a/tests/run-debuginfod-duplicate-urls.sh b/tests/run-debuginfod-duplicate-urls.sh
new file mode 100755
index 0000000..50e39cb
--- /dev/null
+++ b/tests/run-debuginfod-duplicate-urls.sh
@@ -0,0 +1,56 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8600
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod \
+    $VERBOSE -F -p $PORT1 -t0 -g0 -d ${DB} F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+wait_ready $PORT1 'ready' 1
+
+########################################################################
+## PR27983
+# Ensure no duplicate urls are used in when querying servers for files
+rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
+env DEBUGINFOD_URLS="http://127.0.0.1:$PORT1 http://127.0.0.1:$PORT1 http://127.0.0.1:$PORT1 http://127.0.0.1:7999" \
+ LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find -vvv executable 0 > vlog1 2>&1 || true
+tempfiles vlog1
+cat vlog1
+if [ $( grep -c 'duplicate url: http://127.0.0.1:'$PORT1'.*' vlog1 ) -ne 2 ]; then
+  echo "Duplicate servers remain";
+  err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-extraction-passive.sh b/tests/run-debuginfod-extraction-passive.sh
new file mode 100755
index 0000000..26618f5
--- /dev/null
+++ b/tests/run-debuginfod-extraction-passive.sh
@@ -0,0 +1,77 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+
+mkdir Z
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=11000
+get_ports
+
+DB=${PWD}/.debuginfod.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+cp -rvp ${abs_srcdir}/debuginfod-tars Z
+tempfiles Z
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d $DB -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT1 -t0 -g0 -v Z > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+wait_ready $PORT1 'ready' 1
+
+# Start second passive server with same database
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE --passive -d $DB -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT2 -v > vlog$PORT2 2>&1 &
+PID2=$!
+
+tempfiles vlog$PORT2
+errfiles vlog$PORT2
+
+wait_ready $PORT2 'ready' 1
+
+# Wait for first server to finish indexing
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# No similar metrics for the passive server
+! (curl http://localhost:$PORT2/metrics | grep -E 'role="scan"|role="groom"|role="traverse"')
+
+# Confirm no active threads
+! (ps -q $PID2 -e -L -o '%p %c %a' | grep -E 'scan|groom|traverse')
+
+# Do a random lookup via passive server
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://localhost:$PORT2 ${abs_builddir}/../debuginfod/debuginfod-find debuginfo cee13b2ea505a7f37bd20d271c6bc7e5f8d2dfcb
+
+tempfiles $DB*
+
+kill $PID1
+wait $PID1
+PID1=0
+
+kill $PID2
+wait $PID2
+PID2=0
+
+exit 0
diff --git a/tests/run-debuginfod-extraction.sh b/tests/run-debuginfod-extraction.sh
new file mode 100755
index 0000000..da6b25c
--- /dev/null
+++ b/tests/run-debuginfod-extraction.sh
@@ -0,0 +1,109 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+mkdir R Z
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8700
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d $DB -F -R -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT1 --scan-checkpoint=1 -t0 -g0 -v R Z > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# Make sure the initial scan has finished before copying the new files in
+# We might remove some, which we don't want to be accidentally scanned.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+cp -rvp ${abs_srcdir}/debuginfod-tars Z
+
+kill -USR1 $PID1
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# Take a dump if possible
+type sqlite3 2>/dev/null && sqlite3 $DB '.d'
+
+########################################################################
+# All rpms need to be in the index, except the dummy permission-000 one
+rpms=$(find R -name \*rpm | grep -v nothing | wc -l)
+wait_ready $PORT1 'scanned_files_total{source=".rpm archive"}' $rpms
+txz=$(find Z -name \*tar.xz | wc -l)
+wait_ready $PORT1 'scanned_files_total{source=".tar.xz archive"}' $txz
+tb2=$(find Z -name \*tar.bz2 | wc -l)
+wait_ready $PORT1 'scanned_files_total{source=".tar.bz2 archive"}' $tb2
+
+kill -USR1 $PID1  # two hits of SIGUSR1 may be needed to resolve .debug->dwz->srefs
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 3
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# Expect all source files found in the rpms (they are all called hello.c :)
+# We will need to extract all rpms (in their own directory) and could all
+# sources referenced in the .debug files.
+mkdir extracted
+cd extracted
+subdir=0;
+newrpms=$(find ../R -name \*\.rpm | grep -v nothing)
+for i in $newrpms; do
+    subdir=$[$subdir+1];
+    mkdir $subdir;
+    cd $subdir;
+    ls -lah ../$i
+    rpm2cpio ../$i | cpio -ivd;
+    cd ..;
+done
+sourcefiles=$(find -name \*\\.debug \
+              | env LD_LIBRARY_PATH=$ldpath xargs \
+                ${abs_top_builddir}/src/readelf --debug-dump=decodedline \
+              | grep mtime: | wc --lines)
+cd ..
+rm -rf extracted
+
+wait_ready $PORT1 'found_sourcerefs_total{source=".rpm archive"}' $sourcefiles
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-fd-prefetch-caches.sh b/tests/run-debuginfod-fd-prefetch-caches.sh
new file mode 100755
index 0000000..3db78ad
--- /dev/null
+++ b/tests/run-debuginfod-fd-prefetch-caches.sh
@@ -0,0 +1,150 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+# Set up archive folders for scanning
+mkdir R Z
+cp -rvp ${abs_srcdir}/debuginfod-tars Z
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+# Set up maximums. 1 is just a convenient cap to test on.
+FDCACHE_MBS=1
+FDCACHE_FDS=1
+PREFETCH_FDS=1
+PREFETCH=2
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8800
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+######
+# Test fd limits of fd and prefetch cache
+######
+rm -rf $DEBUGINFOD_CACHE_PATH
+rm -rf $DB
+# Testing prefetch fd maximum (Set mb maximums to be beyond consideration)
+# Set --fdcache-mintmp=0 so we don't accidentally trigger an fdcache
+# emergency flush for filling tmpdir
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -p $PORT1 -d $DB \
+    --fdcache-fds=$FDCACHE_FDS --fdcache-prefetch-fds=$PREFETCH_FDS  -vvvvv -g 0 -t 0 \
+    -Z .tar.bz2=bzcat Z  --fdcache-mbs=100  --fdcache-prefetch-mbs=100 \
+    --fdcache-mintmp=0 --fdcache-prefetch=$PREFETCH > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+########################################################################
+kill -USR1 $PID1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/
+# load prefetch cache with debuginfod-tars/usr/src/debug/hello.c
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo cee13b2ea505a7f37bd20d271c6bc7e5f8d2dfcb
+metrics=$(curl http://127.0.0.1:$PORT1/metrics)
+regex="fdcache_prefetch_count ([0-9])+"
+# Check to see if prefetch cache is maximally loaded. Note fdcache-prefetch (2) > prefetch-fds (1),
+# so the debuginfod will try to load the prefetch cache with 2 files. We want prefetch-fds to cap that
+# off
+if [[ $metrics =~ $regex ]]; then
+  if [[ ${BASH_REMATCH[1]} -ne $PREFETCH_FDS ]]; then
+    err
+  fi
+else
+  err
+fi 
+
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find source cee13b2ea505a7f37bd20d271c6bc7e5f8d2dfcb /usr/src/debug/hello.c
+metrics=$(curl http://127.0.0.1:$PORT1/metrics)
+regex="fdcache_op_count\{op=\"prefetch_access\"\} ([0-9])+"
+if [[ $metrics =~ $regex ]]; then
+  # In the test above hello.c should've been loaded into the prefetch cache.
+  # Ensure that searching for hello.c a second time accesses the prefetch cache once
+  if [[  ${BASH_REMATCH[1]} -ne 1 ]]; then
+    err
+  fi
+else
+  err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+
+#########
+# Test mb limit on fd cache
+#########
+rm -rf $DEBUGINFOD_CACHE_PATH
+rm -rf $DB
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -p $PORT1 -d $DB \
+    --fdcache-mbs=$FDCACHE_MBS -vvvvv -g 0 -t 0 -R R > vlog2$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog2$PORT1
+errfiles vlog2$PORT1
+wait_ready $PORT1 'ready' 1
+########################################################################
+kill -USR1 $PID1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+# All rpms need to be in the index, except the dummy permission-000 one
+rpms=$(find R -name \*rpm | grep -v nothing | wc -l)
+wait_ready $PORT1 'scanned_files_total{source=".rpm archive"}' $rpms
+kill -USR1 $PID1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# This many archives cause the fd cache to be loaded with just over 1mb of
+# files. So we expect the 1mb cap off
+SHA=f4a1a8062be998ae93b8f1cd744a398c6de6dbb1
+archive_test bc1febfd03ca05e030f0d205f7659db29f8a4b30 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test c36708a78618d597dee15d0dc989f093ca5f9120 /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA
+archive_test 41a236eb667c362a1c4196018cc4581e09722b1b /usr/src/debug/hello2-1.0-2.x86_64/hello.c $SHA
+archive_test bc1febfd03ca05e030f0d205f7659db29f8a4b30 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test f0aa15b8aba4f3c28cac3c2a73801fefa644a9f2 /usr/src/debug/hello-1.0/hello.c $SHA
+archive_test bbbf92ebee5228310e398609c23c2d7d53f6e2f9 /usr/src/debug/hello-1.0/hello.c $SHA
+metrics=$(curl http://127.0.0.1:$PORT1/metrics)
+regex="fdcache_bytes ([0-9]+)"
+# Since the server metrics report in bytes, $mb is just the total number of bytes allocated
+# to the fd cache. Ensure that this cap isn't crossed
+mb=$(($FDCACHE_MBS*1024*1024))
+if [[ $metrics =~ $regex ]]; then
+  fdbytes=${BASH_REMATCH[1]}
+  if [ $fdbytes -gt $mb ] ; then
+    err
+  fi
+else
+  err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-federation-link.sh b/tests/run-debuginfod-federation-link.sh
new file mode 100755
index 0000000..d782743
--- /dev/null
+++ b/tests/run-debuginfod-federation-link.sh
@@ -0,0 +1,164 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+tempfiles $DB
+
+# Clean old dirictories
+mkdir D L F
+mkdir -p $DEBUGINFOD_CACHE_PATH
+# not tempfiles F R L D Z - they are directories which we clean up manually
+ln -s ${abs_builddir}/dwfllines L/foo   # any program not used elsewhere in this test
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8900
+get_ports
+# Launch server which will be unable to follow symlinks
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d ${DB} -F -U -t0 -g0 -p $PORT1 L D F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+wait_ready $PORT1 'ready' 1
+# Make sure initial scan was done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+########################################################################
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/prog.c
+tempfiles prog.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c
+testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a prog | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv prog F
+mv prog.debug F
+
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+wait_ready $PORT1 'thread_busy{role="http-buildid"}' 0
+wait_ready $PORT1 'thread_busy{role="http-metrics"}' 1
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache2
+mkdir -p $DEBUGINFOD_CACHE_PATH
+
+# NB: run in -L symlink-following mode for the L subdir
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://127.0.0.1:$PORT1 ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d ${DB}_2 -F -U -p $PORT2 -L L D > vlog$PORT2 2>&1 &
+PID2=$!
+tempfiles vlog$PORT2
+errfiles vlog$PORT2
+tempfiles ${DB}_2
+
+wait_ready $PORT2 'ready' 1
+
+# Make sure initial scan was done
+wait_ready $PORT2 'thread_work_total{role="traverse"}' 1
+kill -USR1 $PID2
+# Wait till both files are in the index.
+wait_ready $PORT2 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT2 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT2 'thread_busy{role="scan"}' 0
+
+wait_ready $PORT2 'thread_busy{role="http-buildid"}' 0
+wait_ready $PORT2 'thread_busy{role="http-metrics"}' 1
+
+# have clients contact the new server
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
+# Use fresh cache for debuginfod-find client requests
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache3
+mkdir -p $DEBUGINFOD_CACHE_PATH
+
+if type bsdtar 2>/dev/null; then
+    # copy in the deb files
+    cp -rvp ${abs_srcdir}/debuginfod-debs/*deb D
+    kill -USR1 $PID2
+    wait_ready $PORT2 'thread_work_total{role="traverse"}' 3
+    wait_ready $PORT2 'thread_work_pending{role="scan"}' 0
+    wait_ready $PORT2 'thread_busy{role="scan"}' 0
+
+    # All debs need to be in the index
+    debs=$(find D -name \*.deb | wc -l)
+    wait_ready $PORT2 'scanned_files_total{source=".deb archive"}' `expr $debs`
+    ddebs=$(find D -name \*.ddeb | wc -l)
+    wait_ready $PORT2 'scanned_files_total{source=".ddeb archive"}' `expr $ddebs`
+
+    # ubuntu
+    archive_test f17a29b5a25bd4960531d82aa6b07c8abe84fa66 "" ""
+fi
+
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# send a request to stress XFF and User-Agent federation relay;
+# we'll grep for the two patterns in vlog$PORT1
+curl -s -H 'User-Agent: TESTCURL' -H 'X-Forwarded-For: TESTXFF' $DEBUGINFOD_URLS/buildid/deaddeadbeef00000000/debuginfo -o /dev/null || true
+
+grep UA:TESTCURL vlog$PORT1
+grep XFF:TESTXFF vlog$PORT1
+
+# confirm that first server can't resolve symlinked info in L/ but second can
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+         -a L/foo | grep 'Build ID' | cut -d ' ' -f 7`
+file L/foo
+file -L L/foo
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# test again with scheme free url
+export DEBUGINFOD_URLS=127.0.0.1:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
+export DEBUGINFOD_URLS=127.0.0.1:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# test parallel queries in client
+rm -rf $DEBUGINFOD_CACHE_PATH
+export DEBUGINFOD_URLS="BAD http://127.0.0.1:$PORT1 127.0.0.1:$PORT1 http://127.0.0.1:$PORT2 DNE"
+
+testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog 1
+
+kill $PID1
+kill $PID2
+wait $PID1
+wait $PID2
+PID1=0
+PID2=0
+
+exit 0
diff --git a/tests/run-debuginfod-federation-metrics.sh b/tests/run-debuginfod-federation-metrics.sh
new file mode 100755
index 0000000..60fe69c
--- /dev/null
+++ b/tests/run-debuginfod-federation-metrics.sh
@@ -0,0 +1,211 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+export DEBUGINFOD_URLS='http://127.0.0.1:0' # Note invalid, will trigger error_count metric
+tempfiles $DB
+# Clean old dirictories
+mkdir D L F
+
+# not tempfiles F R L D Z - they are directories which we clean up manually
+ln -s ${abs_builddir}/dwfllines L/foo   # any program not used elsewhere in this test
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9000
+get_ports
+
+# Launch server which will be unable to follow symlinks
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d ${DB} -F -U -t0 -g0 -p $PORT1 L D F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+wait_ready $PORT1 'ready' 1
+
+# Wait till initial scan is done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+########################################################################
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/prog.c
+tempfiles prog.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c
+testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a prog | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv prog F
+mv prog.debug F
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+wait_ready $PORT1 'thread_busy{role="http-buildid"}' 0
+wait_ready $PORT1 'thread_busy{role="http-metrics"}' 1
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache2
+mkdir -p $DEBUGINFOD_CACHE_PATH
+# NB: run in -L symlink-following mode for the L subdir
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://127.0.0.1:$PORT1 ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d ${DB}_2 -F -U -p $PORT2 -L L D > vlog$PORT2 2>&1 &
+PID2=$!
+tempfiles vlog$PORT2
+errfiles vlog$PORT2
+tempfiles ${DB}_2
+
+wait_ready $PORT2 'ready' 1
+wait_ready $PORT2 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT2 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT2 'thread_busy{role="scan"}' 0
+
+wait_ready $PORT2 'thread_busy{role="http-buildid"}' 0
+wait_ready $PORT2 'thread_busy{role="http-metrics"}' 1
+
+# have clients contact the new server
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
+# Use fresh cache for debuginfod-find client requests
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache3
+mkdir -p $DEBUGINFOD_CACHE_PATH
+
+if type bsdtar 2>/dev/null; then
+    # copy in the deb files
+    cp -rvp ${abs_srcdir}/debuginfod-debs/*deb D
+    kill -USR1 $PID2
+    wait_ready $PORT2 'thread_work_total{role="traverse"}' 2
+    wait_ready $PORT2 'thread_work_pending{role="scan"}' 0
+    wait_ready $PORT2 'thread_busy{role="scan"}' 0
+
+    # All debs need to be in the index
+    debs=$(find D -name \*.deb | wc -l)
+    wait_ready $PORT2 'scanned_files_total{source=".deb archive"}' `expr $debs`
+    ddebs=$(find D -name \*.ddeb | wc -l)
+    wait_ready $PORT2 'scanned_files_total{source=".ddeb archive"}' `expr $ddebs`
+
+    # ubuntu
+    archive_test f17a29b5a25bd4960531d82aa6b07c8abe84fa66 "" ""
+fi
+
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# send a request to stress XFF and User-Agent federation relay;
+# we'll grep for the two patterns in vlog$PORT1
+curl -s -H 'User-Agent: TESTCURL' -H 'X-Forwarded-For: TESTXFF' $DEBUGINFOD_URLS/buildid/deaddeadbeef00000000/debuginfo -o /dev/null || true
+
+grep UA:TESTCURL vlog$PORT1
+grep XFF:TESTXFF vlog$PORT1
+
+# confirm that first server can't resolve symlinked info in L/ but second can
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+         -a L/foo | grep 'Build ID' | cut -d ' ' -f 7`
+file L/foo
+file -L L/foo
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# test again with scheme free url
+export DEBUGINFOD_URLS=127.0.0.1:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
+export DEBUGINFOD_URLS=127.0.0.1:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+# test parallel queries in client
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache3
+mkdir -p $DEBUGINFOD_CACHE_PATH
+export DEBUGINFOD_URLS="BAD http://127.0.0.1:$PORT1 127.0.0.1:$PORT1 http://127.0.0.1:$PORT2 DNE"
+
+testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog 1
+
+########################################################################
+# Fetch some metrics
+curl -s http://127.0.0.1:$PORT1/badapi
+curl -s http://127.0.0.1:$PORT1/metrics
+curl -s http://127.0.0.1:$PORT2/metrics
+curl -s http://127.0.0.1:$PORT1/metrics | grep -q 'http_responses_total.*result.*error'
+curl -s http://127.0.0.1:$PORT2/metrics | grep -q 'http_responses_total.*result.*upstream'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_duration_milliseconds_count'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_duration_milliseconds_sum'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_count'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_sum'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'fdcache_'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'error_count'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'traversed_total'
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'scanned_bytes_total'
+
+# And generate a few errors into the second debuginfod's logs, for analysis just below
+curl -s http://127.0.0.1:$PORT2/badapi > /dev/null || true
+curl -s http://127.0.0.1:$PORT2/buildid/deadbeef/debuginfo > /dev/null || true
+# NB: this error is used to seed the 404 failure for the survive-404 tests
+
+# Confirm bad artifact types are rejected without leaving trace
+curl -s http://127.0.0.1:$PORT2/buildid/deadbeef/badtype > /dev/null || true
+(curl -s http://127.0.0.1:$PORT2/metrics | grep 'badtype') && false
+
+# Confirm that reused curl connections survive 404 errors.
+# The rm's force an uncached fetch (in both servers and client cache)
+rm -f .client_cache*/$BUILDID/debuginfo
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+rm -f .client_cache*/$BUILDID/debuginfo
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+rm -f .client_cache*/$BUILDID/debuginfo
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# Confirm that some debuginfod client pools are being used
+curl -s http://127.0.0.1:$PORT2/metrics | grep 'dc_pool_op.*reuse'
+
+# Trigger a flood of requests against the same archive content file.
+# Use a file that hasn't been previously extracted in to make it
+# likely that even this test debuginfod will experience concurrency
+# and impose some "after-you" delays.
+maxreq=256
+(for i in `seq $maxreq`; do
+    curl -s http://127.0.0.1:$PORT1/buildid/87c08d12c78174f1082b7c888b3238219b0eb265/executable >/dev/null &
+ done;
+ wait)
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_after_you.*'
+# If we could guarantee some minimum number of seconds of CPU time, we
+# could assert that the after_you metrics show some nonzero amount of
+# waiting.  A few hundred ms is typical on this developer's workstation.
+
+kill $PID1
+kill $PID2
+wait $PID1
+wait $PID2
+PID1=0
+PID2=0
+exit 0
+
diff --git a/tests/run-debuginfod-federation-sqlite.sh b/tests/run-debuginfod-federation-sqlite.sh
new file mode 100755
index 0000000..6b09007
--- /dev/null
+++ b/tests/run-debuginfod-federation-sqlite.sh
@@ -0,0 +1,204 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+tempfiles $DB
+
+# Clean old dirictories
+mkdir D L F
+# not tempfiles F R L D Z - they are directories which we clean up manually
+ln -s ${abs_builddir}/dwfllines L/foo   # any program not used elsewhere in this test
+
+########################################################################
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/prog.c
+tempfiles prog.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c
+testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a prog | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv prog F
+mv prog.debug F
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9100
+get_ports
+# Launch server which will be unable to follow symlinks
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d ${DB} -F -U -t0 -g0 -p $PORT1 L D F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+wait_ready $PORT1 'ready' 1
+
+# Wait till initial scan is done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache2
+mkdir -p $DEBUGINFOD_CACHE_PATH
+# NB: run in -L symlink-following mode for the L subdir
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://127.0.0.1:$PORT1 ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d ${DB}_2 -F -U -p $PORT2 -L L D F > vlog$PORT2 2>&1 &
+PID2=$!
+tempfiles vlog$PORT2
+errfiles vlog$PORT2
+tempfiles ${DB}_2
+wait_ready $PORT2 'ready' 1
+# Wait till initial scan is done
+wait_ready $PORT2 'thread_work_total{role="traverse"}' 1
+# And initial groom cycle
+wait_ready $PORT1 'thread_work_total{role="groom"}' 1
+
+export DEBUGINFOD_URLS='http://127.0.0.1:'$PORT2
+# Use fresh cache for debuginfod-find client requests
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache3
+mkdir -p $DEBUGINFOD_CACHE_PATH
+
+if type bsdtar 2>/dev/null; then
+    # copy in the deb files
+    cp -rvp ${abs_srcdir}/debuginfod-debs/*deb D
+    kill -USR1 $PID2
+    wait_ready $PORT2 'thread_work_total{role="traverse"}' 2
+    wait_ready $PORT2 'thread_work_pending{role="scan"}' 0
+    wait_ready $PORT2 'thread_busy{role="scan"}' 0
+
+    # All debs need to be in the index
+    debs=$(find D -name \*.deb | wc -l)
+    wait_ready $PORT2 'scanned_files_total{source=".deb archive"}' `expr $debs`
+    ddebs=$(find D -name \*.ddeb | wc -l)
+    wait_ready $PORT2 'scanned_files_total{source=".ddeb archive"}' `expr $ddebs`
+
+    # ubuntu
+    archive_test f17a29b5a25bd4960531d82aa6b07c8abe84fa66 "" ""
+fi
+
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# send a request to stress XFF and User-Agent federation relay;
+# we'll grep for the two patterns in vlog$PORT1
+curl -s -H 'User-Agent: TESTCURL' -H 'X-Forwarded-For: TESTXFF' $DEBUGINFOD_URLS/buildid/deaddeadbeef00000000/debuginfo -o /dev/null || true
+
+grep UA:TESTCURL vlog$PORT1
+grep XFF:TESTXFF vlog$PORT1
+
+# confirm that first server can't resolve symlinked info in L/ but second can
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+         -a L/foo | grep 'Build ID' | cut -d ' ' -f 7`
+file L/foo
+file -L L/foo
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+
+# test again with scheme free url
+export DEBUGINFOD_URLS=127.0.0.1:$PORT1
+rm -rf $DEBUGINFOD_CACHE_PATH
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+rm -f $DEBUGINFOD_CACHE_PATH/$BUILDID/debuginfo # drop negative-hit file
+export DEBUGINFOD_URLS=127.0.0.1:$PORT2
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+# test parallel queries in client
+rm -rf $DEBUGINFOD_CACHE_PATH
+export DEBUGINFOD_URLS="BAD http://127.0.0.1:$PORT1 127.0.0.1:$PORT1 http://127.0.0.1:$PORT2 DNE"
+
+testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog 1
+
+# And generate a few errors into the second debuginfod's logs, for analysis just below
+curl -s http://127.0.0.1:$PORT2/badapi > /dev/null || true
+curl -s http://127.0.0.1:$PORT2/buildid/deadbeef/debuginfo > /dev/null || true
+# NB: this error is used to seed the 404 failure for the survive-404 tests
+
+# Confirm bad artifact types are rejected without leaving trace
+curl -s http://127.0.0.1:$PORT2/buildid/deadbeef/badtype > /dev/null || true
+(curl -s http://127.0.0.1:$PORT2/metrics | grep 'badtype') && false
+
+# Confirm that reused curl connections survive 404 errors.
+# The rm's force an uncached fetch (in both servers and client cache)
+rm -f .client_cache*/$BUILDID/debuginfo
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+rm -f .client_cache*/$BUILDID/debuginfo
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+rm -f .client_cache*/$BUILDID/debuginfo
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+# Trigger a flood of requests against the same archive content file.
+# Use a file that hasn't been previously extracted in to make it
+# likely that even this test debuginfod will experience concurrency
+# and impose some "after-you" delays.
+maxreq=$[$(nproc) * 4]
+maxreq=$(( $maxreq > 64 ? 64 : $maxreq ))
+(for i in `seq $maxreq`; do
+    curl -s http://127.0.0.1:$PORT1/buildid/87c08d12c78174f1082b7c888b3238219b0eb265/executable >/dev/null &
+ done;
+ wait)
+curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_after_you.*'
+# If we could guarantee some minimum number of seconds of CPU time, we
+# could assert that the after_you metrics show some nonzero amount of
+# waiting.  A few hundred ms is typical on this developer's workstation.
+
+########################################################################
+# Trigger some some random activity, then trigger a clean shutdown.
+# We used to try to corrupt the database while the debuginfod server
+# was running and check it detected errors, but that was unreliably
+# and slightly dangerous since part of the database was already mapped
+# into memory.
+kill -USR1 $PID1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+kill -USR2 $PID1
+wait_ready $PORT1 'thread_work_total{role="groom"}' 2
+curl -s http://127.0.0.1:$PORT1/buildid/beefbeefbeefd00dd00d/debuginfo > /dev/null || true
+
+kill -INT $PID1 $PID2
+wait $PID1 $PID2
+PID1=0
+PID2=0
+
+# Run the tests again without the servers running. The target file should
+# be found in the cache.
+
+tempfiles .debuginfod_*
+
+testrun ${abs_builddir}/debuginfod_build_id_find -e F/prog 1
+
+# check out the debuginfod logs for the new style status lines
+cat vlog$PORT2
+grep -q 'UA:.*XFF:.*GET /buildid/.* 200 ' vlog$PORT2
+grep -q 'UA:.*XFF:.*GET /metrics 200 ' vlog$PORT2
+grep -q 'UA:.*XFF:.*GET /badapi 503 ' vlog$PORT2
+grep -q 'UA:.*XFF:.*GET /buildid/deadbeef.* 404 ' vlog$PORT2
+
+exit 0
diff --git a/tests/run-debuginfod-file.sh b/tests/run-debuginfod-file.sh
new file mode 100755
index 0000000..341bbc6
--- /dev/null
+++ b/tests/run-debuginfod-file.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+# Test fetching a file using file:// . No debuginfod server needs to be run for
+# this test.
+local_dir=${PWD}/mocktree/buildid/aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd/source/my/path
+mkdir -p ${local_dir}
+echo "int main() { return 0; }" > ${local_dir}/main.c
+# first test that is doesn't work, when no DEBUGINFOD_URLS is set
+export DEBUGINFOD_URLS=""
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find source aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd /my/path/main.c && false || true
+
+# Now test is with proper DEBUGINFOD_URLS
+export DEBUGINFOD_URLS="file://${PWD}/mocktree/"
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find source aaaaaaaaaabbbbbbbbbbccccccccccdddddddddd /my/path/main.c`
+cmp $filename ${local_dir}/main.c
+
+exit 0
diff --git a/tests/run-debuginfod-malformed.sh b/tests/run-debuginfod-malformed.sh
new file mode 100755
index 0000000..83e6a3a
--- /dev/null
+++ b/tests/run-debuginfod-malformed.sh
@@ -0,0 +1,111 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9200
+# find an unused port number
+get_ports
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+mkdir F
+mkdir -p $DEBUGINFOD_CACHE_PATH
+
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -p $PORT1 -d $DB \
+    -t0 -g0 -v F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And an initial scan should be done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/   # or without trailing /
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# We use -t0 and -g0 here to turn off time-based scanning & grooming.
+# For testing purposes, we just sic SIGUSR1 / SIGUSR2 at the process.
+########################################################################
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/p+r%o\$g.c
+tempfiles p+r%o\$g.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o p+r%o\$g ${PWD}/foobar///./../p+r%o\$g.c
+testrun ${abs_top_builddir}/src/strip -g -f p+r%o\$g.debug ${PWD}/p+r%o\$g
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a p+r%o\\$g | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv p+r%o\$g F
+mv p+r%o\$g.debug F
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+########################################################################
+# Add some files to the cache that do not fit its naming format.
+# They should survive cache cleaning.
+mkdir $DEBUGINFOD_CACHE_PATH/malformed
+touch $DEBUGINFOD_CACHE_PATH/malformed0
+touch $DEBUGINFOD_CACHE_PATH/malformed/malformed1
+
+# A valid format for an empty buildid subdirectory
+mkdir $DEBUGINFOD_CACHE_PATH/00000000
+touch -d '1970-01-01' $DEBUGINFOD_CACHE_PATH/00000000 # old enough to guarantee nukage
+
+# Trigger a cache clean and run the tests again. The clients should be unable to
+# find the target.
+echo 0 > $DEBUGINFOD_CACHE_PATH/cache_clean_interval_s
+echo 0 > $DEBUGINFOD_CACHE_PATH/max_unused_age_s
+
+testrun ${abs_builddir}/debuginfod_build_id_find -e F/p+r%o\$g 1
+
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID && false || true
+
+if [ ! -f $DEBUGINFOD_CACHE_PATH/malformed0 ] \
+    || [ ! -f $DEBUGINFOD_CACHE_PATH/malformed/malformed1 ]; then
+  echo "unrelated files did not survive cache cleaning"
+  err
+fi
+
+if [ -d $DEBUGINFOD_CACHE_PATH/00000000 ]; then
+    echo "failed to rmdir old cache dir"
+    err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-negative-cache.sh b/tests/run-debuginfod-negative-cache.sh
new file mode 100755
index 0000000..f40e99c
--- /dev/null
+++ b/tests/run-debuginfod-negative-cache.sh
@@ -0,0 +1,83 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=8000
+get_ports
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -p $PORT1 -d $DB \
+    -t0 -g0 -v ${PWD} > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/   # or without trailing /
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+########################################################################
+# PR25628
+rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
+
+# The query is designed to fail, while the empty file should be created.
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567 || true
+if [ ! -f $DEBUGINFOD_CACHE_PATH/01234567/debuginfo ]; then
+  echo "could not find cache in $DEBUGINFOD_CACHE_PATH"
+  err
+fi
+
+if [ `stat -c "%s" $DEBUGINFOD_CACHE_PATH/01234567/debuginfo` != 0 ]; then
+  echo "The cache $DEBUGINFOD_CACHE_PATH/01234567/debuginfo is not empty"
+  err
+fi
+
+bytecount_before=`curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_count{code="404",type="debuginfo"}'`
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567 || true
+bytecount_after=`curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_count{code="404",type="debuginfo"}'`
+if [ "$bytecount_before" != "$bytecount_after" ]; then
+  echo "http_responses_transfer_bytes_count{code="404",type="debuginfo"} has changed."
+  err
+fi
+
+# set cache_miss_s to 0 and sleep 1 to make the mtime expire.
+echo 0 > $DEBUGINFOD_CACHE_PATH/cache_miss_s
+sleep 1
+bytecount_before=`curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_count{code="404",type="debuginfo"}'`
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567 || true
+bytecount_after=`curl -s http://127.0.0.1:$PORT1/metrics | grep 'http_responses_transfer_bytes_count{code="404",type="debuginfo"}'`
+if [ "$bytecount_before" == "$bytecount_after" ]; then
+  echo "http_responses_transfer_bytes_count{code="404",type="debuginfo"} should be incremented."
+  err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-no-urls.sh b/tests/run-debuginfod-no-urls.sh
new file mode 100755
index 0000000..7e3ffef
--- /dev/null
+++ b/tests/run-debuginfod-no-urls.sh
@@ -0,0 +1,41 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+########################################################################
+# Test debuginfod without a path list
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9300
+get_ports
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -U -d :memory: -p $PORT1 -L -F &
+PID1=$!
+
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+kill -int $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-percent-escape.sh b/tests/run-debuginfod-percent-escape.sh
new file mode 100755
index 0000000..cd86742
--- /dev/null
+++ b/tests/run-debuginfod-percent-escape.sh
@@ -0,0 +1,61 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh  # includes set -e
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=10000
+get_ports
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+mkdir F
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE \
+    -F -R -d $DB -p $PORT1 -t0 -g0 -v R ${PWD}/F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And initial scan should be done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+# Build a non-stripped binary
+echo "int main() { return 0; }" > ${PWD}/F/p++r\$\#o^^g.c
+gcc -Wl,--build-id -g -o ${PWD}/F/p++r\$\#o^^g ${PWD}/F/p++r\$\#o^^g.c
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a ${PWD}/F/p++r\\$\#o^^g | grep 'Build ID' | cut -d ' ' -f 7`
+tempfiles ${PWD}/F/p++r\$\#o^^g.c ${PWD}/F/p++r\$\#o^^g
+kill -USR1 $PID1
+# Now there should be 1 files in the index
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
+ls F
+env DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache DEBUGINFOD_URLS="http://127.0.0.1:$PORT1" \
+    LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find -vvv source F/p++r\$\#o^^g ${abs_builddir}/F/p++r\$\#o^^g.c > vlog1 2>&1 || true
+tempfiles vlog1
+grep 'F/p%2B%2Br%24%23o%5E%5Eg.c' vlog1
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-query-retry.sh b/tests/run-debuginfod-query-retry.sh
new file mode 100755
index 0000000..d2cdfd6
--- /dev/null
+++ b/tests/run-debuginfod-query-retry.sh
@@ -0,0 +1,36 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+########################################################################
+# set up tests for retrying failed queries.
+retry_attempts=`(testrun env DEBUGINFOD_URLS=http://255.255.255.255/JUNKJUNK DEBUGINFOD_RETRY_LIMIT=10 DEBUGINFOD_VERBOSE=1 DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache \
+    ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo \
+    ${abs_top_builddir}/debuginfod/debuginfod-find || true) \
+    2>&1 >/dev/null | grep -c 'Retry failed query'`
+if [ $retry_attempts -ne 10 ]; then
+    echo "retry mechanism failed."
+    exit 1;
+fi
+
+exit 0;
diff --git a/tests/run-debuginfod-regex.sh b/tests/run-debuginfod-regex.sh
new file mode 100755
index 0000000..6837ea8
--- /dev/null
+++ b/tests/run-debuginfod-regex.sh
@@ -0,0 +1,101 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+mkdir F
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9400
+get_ports
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod \
+    $VERBOSE -F -p $PORT1 -t0 -g0 -d ${DB} F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+
+# Wait till the server is ready and an initial scan has been done
+wait_ready $PORT1 'ready' 1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/prog.c
+tempfiles prog.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c
+testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+
+mv prog F
+mv prog.debug F
+tempfiles F/prog.debug F/prog
+
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+cp ${DB} ${DB}.backup
+tempfiles ${DB}.backup
+
+kill $PID1
+wait $PID1
+PID1=0
+
+#######################################################################
+## PR27711
+# Test to ensure that the --include="^$" --exclude=".*" options remove all files from a database backup
+#
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod \
+    $VERBOSE -p $PORT2 -t0 -g0 --regex-groom --include="^$" --exclude=".*" -d ${DB}.backup > vlog$PORT2 2>&1 &
+
+#reuse PID1
+PID1=$!
+tempfiles vlog$PORT2
+errfiles vlog$PORT2
+# Server must become ready
+wait_ready $PORT2 'ready' 1
+
+# Wait till the initial groom cycle has been done
+wait_ready $PORT2 'thread_work_total{role="groom"}' 1
+wait_ready $PORT2 'groom{statistic="archive d/e"}'  0
+wait_ready $PORT2 'groom{statistic="archive sdef"}' 0
+wait_ready $PORT2 'groom{statistic="archive sref"}' 0
+wait_ready $PORT2 'groom{statistic="buildids"}' 0
+wait_ready $PORT2 'groom{statistic="file d/e"}' 0
+wait_ready $PORT2 'groom{statistic="file s"}' 0
+wait_ready $PORT2 'groom{statistic="files scanned (#)"}' 0
+wait_ready $PORT2 'groom{statistic="files scanned (mb)"}' 0
+
+kill $PID1
+wait $PID1
+PID1=0
+
+exit 0;
+
diff --git a/tests/run-debuginfod-response-headers.sh b/tests/run-debuginfod-response-headers.sh
new file mode 100755
index 0000000..ea516ce
--- /dev/null
+++ b/tests/run-debuginfod-response-headers.sh
@@ -0,0 +1,142 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2022 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+type socat 2>/dev/null || exit 77
+
+. $srcdir/debuginfod-subr.sh  # includes set -e
+
+# for test case debugging, uncomment:
+set -x
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9500
+get_ports
+mkdir F R
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/prog.c
+tempfiles prog.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c
+
+mv prog F
+
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+if [ "$zstd" = "false" ]; then  # nuke the zstd fedora 31 ones
+    rm -vrf R/debuginfod-rpms/fedora31
+fi
+
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -R -d $DB -p $PORT1 -t0 -g0 -v R F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/   # or without trailing /
+########################################################################
+
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'ready' 1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+# All rpms need to be in the index, except the dummy permission-000 one
+rpms=$(find R -name \*rpm | grep -v nothing | wc -l)
+wait_ready $PORT1 'scanned_files_total{source=".rpm archive"}' $rpms
+
+kill -USR1 $PID1  # two hits of SIGUSR1 may be needed to resolve .debug->dwz->srefs
+# Wait till both files are in the index and scan/index fully finished
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+
+########################################################################
+## PR27277
+# Make a simple request to the debuginfod server and check debuginfod-find's vlog to see if
+# the custom HTTP headers are received.
+rm -rf $DEBUGINFOD_CACHE_PATH
+env DEBUGINFOD_URLS="http://127.0.0.1:"$PORT1 LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find\
+    -vvv executable F/prog > vlog-find$PORT1.1 2>&1
+tempfiles vlog-find$PORT1.1
+errfiles vlog-find$PORT1.1
+cat vlog-find$PORT1.1
+grep 'Headers:' vlog-find$PORT1.1
+grep -i 'X-DEBUGINFOD-FILE: .*/prog' vlog-find$PORT1.1
+grep -i 'X-DEBUGINFOD-SIZE: '        vlog-find$PORT1.1
+
+# Check to see if an executable file located in an archive prints the file's description and archive
+env DEBUGINFOD_URLS="http://127.0.0.1:"$PORT1 LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find\
+    -vvv executable c36708a78618d597dee15d0dc989f093ca5f9120 > vlog-find$PORT1.2 2>&1
+tempfiles vlog-find$PORT1.2
+errfiles vlog-find$PORT1.2
+cat vlog-find$PORT1.2
+grep 'Headers:'               vlog-find$PORT1.2
+grep -i 'X-DEBUGINFOD-FILE: .*/.*'    vlog-find$PORT1.2
+grep -i 'X-DEBUGINFOD-SIZE: '    vlog-find$PORT1.2
+grep -i 'X-DEBUGINFOD-ARCHIVE: .*/.*' vlog-find$PORT1.2
+
+# Check that X-DEBUGINFOD-SIZE matches the size of each file
+for file in vlog-find$PORT1.1 vlog-find$PORT1.2
+do
+    st_size=$(stat -c%s $(tail -n 1 $file))
+    x_debuginfod_size=$(grep -i 'X-DEBUGINFOD-SIZE' $file | head -1 | grep -E -o '[0-9]+')
+    test $st_size -eq $x_debuginfod_size
+done
+
+rm -rf $DEBUGINFOD_CACHE_PATH
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a F/prog | grep 'Build ID' | cut -d ' ' -f 7`
+netcat_dir="buildid/$BUILDID/"
+mkdir -p ${PWD}/$netcat_dir
+cp F/prog ${PWD}/$netcat_dir/executable
+tempfiles F/prog
+
+# socat should after answering one request
+(echo -e "HTTP/1.1 200 OK\r\nX-DEBUGINFOD-SIZE: ba:d_size\nX-DEBUGINFOD-\rFILE:\=\+ \r213\n\n $(date)" | socat -u - tcp-listen:$PORT2) &
+PID2=$!
+# Wait a bit until the netcat port is in use. Otherwise debuginfod-find can query
+# before netcat is ready.
+sleep 5
+
+touch vlog-find$PORT2
+errfiles vlog-find$PORT2
+tempfiles vlog-find$PORT2
+
+# calling out to valgrind deliberately, because this process will be forced to parse broken http headers
+${VALGRIND_CMD} env DEBUGINFOD_URLS="http://127.0.0.1:"$PORT2 LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find\
+    -vvv executable $BUILDID > vlog-find$PORT2 2>&1 || true # permit curl rejection of the bad headers
+cat vlog-find$PORT2 # won't have any valid x-debuginfod* headers
+rm -f "$netcat_dir"executable
+rmdir -p $netcat_dir
+
+kill $PID2 || true
+wait $PID2 || true
+PID2=0
+
+kill $PID1
+wait $PID1
+PID1=0
+
+exit 0
diff --git a/tests/run-debuginfod-section.sh b/tests/run-debuginfod-section.sh
new file mode 100755
index 0000000..66e53e8
--- /dev/null
+++ b/tests/run-debuginfod-section.sh
@@ -0,0 +1,135 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+# Set up directories for scanning
+mkdir F
+mkdir R
+cp -rvp ${abs_srcdir}/debuginfod-rpms R
+
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=13000
+get_ports
+
+# We use -t0 and -g0 here to turn off time-based scanning & grooming.
+# For testing purposes, we just sic SIGUSR1 at the process.
+
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE \
+    -R R -F F -p $PORT1 -d $DB -t0 -g0 -v F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And initial scan should be done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+########################################################################
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+tempfiles prog.c
+echo "int main() { return 0; }" > ${PWD}/prog.c
+
+gcc -Wl,--build-id -g -o F/prog ${PWD}/prog.c
+
+testrun ${abs_top_builddir}/src/strip -g -f F/prog.debug ${PWD}/F/prog
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a F/prog | grep 'Build ID' | cut -d ' ' -f 7`
+
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+########################################################################
+
+# Build-id for a file in the one of the testsuite's F31 rpms
+RPM_BUILDID=d44d42cbd7d915bc938c81333a21e355a6022fb7
+
+# Download sections from files indexed with -F
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $BUILDID .debug_info
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $BUILDID .text
+
+# Download sections from files indexed with -R
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $RPM_BUILDID .debug_info
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $RPM_BUILDID .text
+
+# Verify that the downloaded files match the contents of the original sections
+tempfiles ${BUILDID}.debug_info
+objcopy F/prog.debug -O binary --only-section=.debug_info --set-section-flags .debug_info=alloc $BUILDID.debug_info
+cmp ${BUILDID}.debug_info ${DEBUGINFOD_CACHE_PATH}/${BUILDID}/section-.debug_info
+
+tempfiles ${BUILDID}.text
+objcopy F/prog -O binary --only-section=.text ${BUILDID}.text
+cmp ${BUILDID}.text ${DEBUGINFOD_CACHE_PATH}/${BUILDID}/section-.text
+
+# Download the original debuginfo/executable files.
+DEBUGFILE=`env LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $RPM_BUILDID`
+EXECFILE=`env LD_LIBRARY_PATH=$ldpath ${abs_top_builddir}/debuginfod/debuginfod-find executable $RPM_BUILDID`
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv debuginfo $BUILDID
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv executable $BUILDID
+
+if test "$(arch)" == "x86_64"; then
+  tempfiles DEBUGFILE.debug_info
+  objcopy $DEBUGFILE -O binary --only-section=.debug_info --set-section-flags .debug_info=alloc DEBUGFILE.debug_info
+  testrun diff -u DEBUGFILE.debug_info ${DEBUGINFOD_CACHE_PATH}/${RPM_BUILDID}/section-.debug_info
+
+  tempfiles EXECFILE.text
+  objcopy $EXECFILE -O binary --only-section=.text EXECFILE.text
+  testrun diff -u EXECFILE.text ${DEBUGINFOD_CACHE_PATH}/${RPM_BUILDID}/section-.text
+fi
+
+# Kill the server.
+kill $PID1
+wait $PID1
+PID1=0
+
+# Delete the section files from the cache.
+rm -f ${DEBUGINFOD_CACHE_PATH}/${RPM_BUILDID}/section-.text
+rm -f ${DEBUGINFOD_CACHE_PATH}/${RPM_BUILDID}/section-.debug_info
+rm -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID}/section-.text
+rm -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID}/section-.debug_info
+
+# Verify that the client can extract sections from the debuginfo or executable
+# if they're already in the cache.
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $BUILDID .debug_info
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $BUILDID .text
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $RPM_BUILDID .debug_info
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find -vvv section $RPM_BUILDID .text
+
+exit 0
diff --git a/tests/run-debuginfod-sizetime.sh b/tests/run-debuginfod-sizetime.sh
new file mode 100755
index 0000000..17307c0
--- /dev/null
+++ b/tests/run-debuginfod-sizetime.sh
@@ -0,0 +1,82 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+set -x
+unset VALGRIND_CMD
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9600
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+echo "int main() { return 0; }" > ${PWD}/prog.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o prog ${PWD}/foobar///./../prog.c
+testrun ${abs_top_builddir}/src/strip -g -f prog.debug ${PWD}/prog
+tempfiles prog prog.debug prog.c
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a prog | grep 'Build ID' | cut -d ' ' -f 7`
+
+env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -p $PORT1 -d $DB -t0 -g0 ${PWD} > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles  vlog$PORT1
+wait_ready $PORT1 'ready' 1
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+## PR27892
+# Ensure DEBUGINFOD_MAXSIZE is functional and sends back the correct http
+# code
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_RETRY_LIMIT=1 DEBUGINFOD_URLS="http://127.0.0.1:$PORT1/" DEBUGINFOD_MAXSIZE=1 \
+    ${abs_top_builddir}/debuginfod/debuginfod-find -v -v executable ${PWD}/prog 2> find-vlog$PORT1 || true
+tempfiles find-vlog$PORT1
+errfiles  find-vlog$PORT1
+echo "Checking maxsize"
+grep "using max size 1B" find-vlog$PORT1
+echo "Checking maxsize"
+grep 'serving file '$(realpath ${PWD})'/prog' vlog$PORT1
+echo "Checking maxsize"
+grep 'File too large' vlog$PORT1
+if [ -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID} ]; then
+  echo "File cached after maxsize check"
+  err
+fi
+# Ensure no file is downloaded for longer than DEBUGINFOD_MAXTIME
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS="http://127.0.0.1:$PORT1/" DEBUGINFOD_MAXTIME=1 \
+    ${abs_top_builddir}/debuginfod/debuginfod-find -v -v debuginfo ${PWD}/prog.debug 2> find-vlog$PORT1 || true
+tempfiles find-vlog$PORT1
+grep 'using max time' find-vlog$PORT1
+# Ensure p+r%o\$g.debug is NOT cached
+if [ -f ${DEBUGINFOD_CACHE_PATH}/${BUILDID} ]; then
+  echo "File cached after maxtime check"
+  err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+
+exit 0;
diff --git a/tests/run-debuginfod-tmp-home.sh b/tests/run-debuginfod-tmp-home.sh
new file mode 100755
index 0000000..5946777
--- /dev/null
+++ b/tests/run-debuginfod-tmp-home.sh
@@ -0,0 +1,126 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+mkdir F
+mkdir -p $DEBUGINFOD_CACHE_PATH
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9700
+get_ports
+
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -p $PORT1 -d $DB \
+    -t0 -g0 -v F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And initial scan should be done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/   # or without trailing /
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+# We use -t0 and -g0 here to turn off time-based scanning & grooming.
+# For testing purposes, we just sic SIGUSR1 / SIGUSR2 at the process.
+
+########################################################################
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/p+r%o\$g.c
+tempfiles p+r%o\$g.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o p+r%o\$g ${PWD}/foobar///./../p+r%o\$g.c
+testrun ${abs_top_builddir}/src/strip -g -f p+r%o\$g.debug ${PWD}/p+r%o\$g
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a p+r%o\\$g | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv p+r%o\$g F
+mv p+r%o\$g.debug F
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+########################################################################
+
+# Test whether the cache default locations are correct
+mkdir tmphome
+
+# $HOME/.cache should be created.
+testrun env HOME=$PWD/tmphome XDG_CACHE_HOME= DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+if [ ! -f $PWD/tmphome/.cache/debuginfod_client/$BUILDID/debuginfo ]; then
+  echo "could not find cache in $PWD/tmphome/.cache"
+  err
+fi
+
+# $HOME/.cache should be found.
+testrun env HOME=$PWD/tmphome XDG_CACHE_HOME= DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find executable $BUILDID
+if [ ! -f $PWD/tmphome/.cache/debuginfod_client/$BUILDID/executable ]; then
+  echo "could not find cache in $PWD/tmphome/.cache"
+  err
+fi
+# $XDG_CACHE_HOME should take priority over $HOME.cache.
+testrun env HOME=$PWD/tmphome XDG_CACHE_HOME=$PWD/tmpxdg DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+if [ ! -f $PWD/tmpxdg/debuginfod_client/$BUILDID/debuginfo ]; then
+  echo "could not find cache in $PWD/tmpxdg/"
+  err
+fi
+
+# A cache at the old default location ($HOME/.debuginfod_client_cache) should take
+# priority over $HOME/.cache, $XDG_CACHE_HOME.
+cp -vr $DEBUGINFOD_CACHE_PATH tmphome/.debuginfod_client_cache || true
+# ||true is for tolerating errors, such a valgrind or something else
+#        leaving negative-hit files in there
+
+# Add a file that doesn't exist in $HOME/.cache, $XDG_CACHE_HOME.
+mkdir tmphome/.debuginfod_client_cache/deadbeef
+echo ELF... > tmphome/.debuginfod_client_cache/deadbeef/debuginfo
+filename=`testrun env HOME=$PWD/tmphome XDG_CACHE_HOME=$PWD/tmpxdg DEBUGINFOD_CACHE_PATH= ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo deadbeef`
+cmp $filename tmphome/.debuginfod_client_cache/deadbeef/debuginfo
+
+# $DEBUGINFO_CACHE_PATH should take priority over all else.
+testrun env HOME=$PWD/tmphome XDG_CACHE_HOME=$PWD/tmpxdg DEBUGINFOD_CACHE_PATH=$PWD/tmpcache ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID
+if [ ! -f $PWD/tmpcache/$BUILDID/debuginfo ]; then
+  echo "could not find cache in $PWD/tmpcache/"
+  err
+fi
+rm -rf ${PWD}/tmphome/ ${PWD}/tmpxdg ${PWD}/tmpcache
+
+kill $PID1
+wait $PID1
+PID1=0
+exit 0
diff --git a/tests/run-debuginfod-webapi-concurrency.sh b/tests/run-debuginfod-webapi-concurrency.sh
new file mode 100755
index 0000000..5c2440f
--- /dev/null
+++ b/tests/run-debuginfod-webapi-concurrency.sh
@@ -0,0 +1,69 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+
+mkdir Z
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=12000
+get_ports
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+cp -rvp ${abs_srcdir}/debuginfod-tars Z
+tempfiles Z
+
+
+for Cnum in "" "-C" "-C10" "-C100"
+do
+    env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod $VERBOSE $Cnum -d :memory: -Z .tar.xz -Z .tar.bz2=bzcat -p $PORT1 -t0 -g0 -v --fdcache-fds=0 --fdcache-prefetch-fds=0 Z >> vlog$PORT1 2>&1 &
+    PID1=$!
+    tempfiles vlog$PORT1
+    errfiles vlog$PORT1
+    
+    wait_ready $PORT1 'ready' 1
+    # Wait for server to finish indexing
+    wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+    wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+    wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+    # Do a bunch of lookups in parallel
+    lookup_nr=64
+    for jobs in `seq $lookup_nr`; do
+        curl -s http://localhost:$PORT1/buildid/cee13b2ea505a7f37bd20d271c6bc7e5f8d2dfcb/debuginfo > /dev/null &
+    done
+
+    # all curls should succeed
+    wait_ready $PORT1 'http_responses_transfer_bytes_count{code="200",type="debuginfo"}' $lookup_nr
+    
+    (sleep 5;
+     curl -s http://localhost:$PORT1/metrics | grep -E 'error|responses';
+     kill $PID1) &
+    wait # for all curls, the ()& from just above, and for debuginfod
+    PID1=0
+done
+
+# Note this xfail comes too late, the above wait_ready for
+# http_responses_transfer_bytes_count will have failed.
+xfail "grep Server.reached.connection vlog$PORT1" # PR28661
+
+exit 0
diff --git a/tests/run-debuginfod-writable.sh b/tests/run-debuginfod-writable.sh
new file mode 100755
index 0000000..c521a57
--- /dev/null
+++ b/tests/run-debuginfod-writable.sh
@@ -0,0 +1,88 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2019-2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+mkdir F
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9800
+get_ports
+
+DB=${PWD}/.debuginfod_tmp.sqlite
+tempfiles $DB
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS= ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -F -p $PORT1 -d $DB \
+    -t0 -g0 -v F > vlog$PORT1 2>&1 &
+PID1=$!
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+# Server must become ready
+wait_ready $PORT1 'ready' 1
+# And initial scan should be done
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+
+export DEBUGINFOD_URLS=http://127.0.0.1:$PORT1/   # or without trailing /
+
+# Check thread comm names
+ps -q $PID1 -e -L -o '%p %c %a' | grep groom
+ps -q $PID1 -e -L -o '%p %c %a' | grep scan
+ps -q $PID1 -e -L -o '%p %c %a' | grep traverse
+
+########################################################################
+
+# Compile a simple program, strip its debuginfo and save the build-id.
+# Also move the debuginfo into another directory so that elfutils
+# cannot find it without debuginfod.
+echo "int main() { return 0; }" > ${PWD}/p+r%o\$g.c
+tempfiles p+r%o\$g.c
+# Create a subdirectory to confound source path names
+mkdir foobar
+gcc -Wl,--build-id -g -o p+r%o\$g ${PWD}/foobar///./../p+r%o\$g.c
+testrun ${abs_top_builddir}/src/strip -g -f p+r%o\$g.debug ${PWD}/p+r%o\$g
+BUILDID=`env LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../src/readelf \
+          -a p+r%o\\$g | grep 'Build ID' | cut -d ' ' -f 7`
+
+mv p+r%o\$g F
+mv p+r%o\$g.debug F
+kill -USR1 $PID1
+# Wait till both files are in the index.
+wait_ready $PORT1 'thread_work_total{role="traverse"}' 2
+wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+wait_ready $PORT1 'thread_busy{role="scan"}' 0
+
+#######################################################################
+# Test whether debuginfod-find is able to fetch those files.
+rm -rf $DEBUGINFOD_CACHE_PATH # clean it from previous tests
+filename=`testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo $BUILDID`
+cmp $filename F/p+r%o\$g.debug
+if [  `stat -c "%A" $filename` != "-r--------" ]; then
+    echo "cache file writable, boo"
+    err
+fi
+
+kill $PID1
+wait $PID1
+PID1=0
+
+exit 0
diff --git a/tests/run-debuginfod-x-forwarded-for.sh b/tests/run-debuginfod-x-forwarded-for.sh
new file mode 100755
index 0000000..5b756b2
--- /dev/null
+++ b/tests/run-debuginfod-x-forwarded-for.sh
@@ -0,0 +1,63 @@
+#!/usr/bin/env bash
+#
+# Copyright (C) 2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+set -x
+unset VALGRIND_CMD
+
+export DEBUGINFOD_CACHE_PATH=${PWD}/.client_cache
+# This variable is essential and ensures no time-race for claiming ports occurs
+# set base to a unique multiple of 100 not used in any other 'run-debuginfod-*' test
+base=9900
+get_ports
+
+# Test when debuginfod hitting X-Forwarded-For hops limit.
+# This test will start two servers (as a loop) with two different hop limits.
+
+tempfiles vlog$PORT1
+errfiles vlog$PORT1
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://127.0.0.1:$PORT2 ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d :memory: --forwarded-ttl-limit 0 -p $PORT1 > vlog$PORT1 2>&1 &
+PID1=$!
+
+tempfiles vlog$PORT2
+errfiles vlog$PORT2
+env LD_LIBRARY_PATH=$ldpath DEBUGINFOD_URLS=http://127.0.0.1:$PORT1 ${abs_builddir}/../debuginfod/debuginfod $VERBOSE -d :memory: --forwarded-ttl-limit 1 -p $PORT2 > vlog$PORT2 2>&1 &
+PID2=$!
+
+wait_ready $PORT1 'ready' 1
+wait_ready $PORT2 'ready' 1
+
+export DEBUGINFOD_URLS="http://127.0.0.1:$PORT1/"
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 01234567 || true
+
+# Use a different buildid to avoid using same cache.
+export DEBUGINFOD_URLS="http://127.0.0.1:$PORT2/"
+testrun ${abs_top_builddir}/debuginfod/debuginfod-find debuginfo 11234567 || true
+
+grep "forwared-ttl-limit reached and will not query the upstream servers" vlog$PORT1
+grep -v "forwared-ttl-limit reached and will not query the upstream servers" vlog$PORT2 | grep "not found" vlog$PORT2
+
+kill $PID1 $PID2
+wait $PID1 $PID2
+
+PID1=0
+PID2=0
+
+exit 0
diff --git a/tests/run-debuglink.sh b/tests/run-debuglink.sh
new file mode 100755
index 0000000..42a816c
--- /dev/null
+++ b/tests/run-debuglink.sh
@@ -0,0 +1,29 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Just some random testfiles, two with, one without .gnu_debuglink
+testfiles testfile36 testfile52-32.so testfile42
+
+testrun_compare  ${abs_builddir}/debuglink testfile36 testfile52-32.so testfile42 <<\EOF
+testfile36: testfile36.debug, crc: 8c5c20a3
+testfile52-32.so: testfile52-32.so.debug, crc: b835a71d
+testfile42: <no gnu_debuglink file>
+EOF
+
+exit 0
diff --git a/tests/run-declfiles.sh b/tests/run-declfiles.sh
new file mode 100755
index 0000000..5aa1b97
--- /dev/null
+++ b/tests/run-declfiles.sh
@@ -0,0 +1,323 @@
+#! /bin/sh
+# Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-4 testfile-dwarf-5
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun_compare ${abs_builddir}/declfiles testfile-dwarf-4 << EOF
+file: testfile-dwarf-4
+ cu: hello.c
+  wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24
+  m@/var/tmp/hello/hello.h:1:12
+  m@/var/tmp/hello/hello.c:5:5
+  foo@/var/tmp/hello/hello.c:20:1
+   f@/var/tmp/hello/hello.c:20:14
+  baz@/var/tmp/hello/hello.c:8:5
+   x@/var/tmp/hello/hello.c:8:14
+   r@/var/tmp/hello/hello.c:10:7
+  frob@/var/tmp/hello/hello.h:5:1
+   a@/var/tmp/hello/hello.h:5:11
+   b@/var/tmp/hello/hello.h:5:18
+   c@/var/tmp/hello/hello.h:7:7
+  foo@/var/tmp/hello/hello.c:20:1
+   f@/var/tmp/hello/hello.c:20:14
+   frob@/var/tmp/hello/hello.h:5:1
+    b@/var/tmp/hello/hello.h:5:18
+    a@/var/tmp/hello/hello.h:5:11
+    c@/var/tmp/hello/hello.h:7:7
+    baz@/var/tmp/hello/hello.c:8:5
+     x@/var/tmp/hello/hello.c:8:14
+     r@/var/tmp/hello/hello.c:10:7
+   foo@/var/tmp/hello/hello.c:20:1
+    f@/var/tmp/hello/hello.c:20:14
+    main@/var/tmp/hello/hello.c:4:12
+  baz@/var/tmp/hello/hello.c:8:5
+   x@/var/tmp/hello/hello.c:8:14
+   r@/var/tmp/hello/hello.c:10:7
+   foo@/var/tmp/hello/hello.c:20:1
+  main@/var/tmp/hello/hello.c:4:12
+ cu: world.c
+  m@/var/tmp/hello/hello.h:1:12
+  main@/var/tmp/hello/world.c:14:1
+   argc@/var/tmp/hello/world.c:14:11
+   argv@/var/tmp/hello/world.c:14:30
+   n@/var/tmp/hello/world.c:16:15
+   calc@/var/tmp/hello/world.c:5:1
+   exit@/usr/include/stdlib.h:542:13
+  calc@/var/tmp/hello/world.c:5:1
+   word@/var/tmp/hello/world.c:5:19
+   frob@/var/tmp/hello/hello.h:5:1
+    b@/var/tmp/hello/hello.h:5:18
+    a@/var/tmp/hello/hello.h:5:11
+    c@/var/tmp/hello/hello.h:7:7
+    baz@/var/tmp/hello/hello.h:2:12
+  frob@/var/tmp/hello/hello.h:5:1
+   a@/var/tmp/hello/hello.h:5:11
+   b@/var/tmp/hello/hello.h:5:18
+   c@/var/tmp/hello/hello.h:7:7
+  exit@/usr/include/stdlib.h:542:13
+  baz@/var/tmp/hello/hello.h:2:12
+EOF
+
+testrun_compare ${abs_builddir}/declfiles testfile-dwarf-5 << EOF
+file: testfile-dwarf-5
+ cu: hello.c
+  wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24
+  m@/var/tmp/hello/hello.h:1:12
+  m@/var/tmp/hello/hello.c:5:5
+  foo@/var/tmp/hello/hello.c:20:1
+   f@/var/tmp/hello/hello.c:20:14
+  baz@/var/tmp/hello/hello.c:8:5
+   x@/var/tmp/hello/hello.c:8:14
+   r@/var/tmp/hello/hello.c:10:7
+  frob@/var/tmp/hello/hello.h:5:1
+   a@/var/tmp/hello/hello.h:5:11
+   b@/var/tmp/hello/hello.h:5:18
+   c@/var/tmp/hello/hello.h:7:7
+  foo@/var/tmp/hello/hello.c:20:1
+   f@/var/tmp/hello/hello.c:20:14
+   frob@/var/tmp/hello/hello.h:5:1
+    b@/var/tmp/hello/hello.h:5:18
+    a@/var/tmp/hello/hello.h:5:11
+    c@/var/tmp/hello/hello.h:7:7
+    baz@/var/tmp/hello/hello.c:8:5
+     x@/var/tmp/hello/hello.c:8:14
+     r@/var/tmp/hello/hello.c:10:7
+   foo@/var/tmp/hello/hello.c:20:1
+    f@/var/tmp/hello/hello.c:20:14
+  baz@/var/tmp/hello/hello.c:8:5
+   x@/var/tmp/hello/hello.c:8:14
+   r@/var/tmp/hello/hello.c:10:7
+  main@/var/tmp/hello/hello.c:4:12
+ cu: world.c
+  m@/var/tmp/hello/hello.h:1:12
+  main@/var/tmp/hello/world.c:14:1
+   argc@/var/tmp/hello/world.c:14:11
+   argv@/var/tmp/hello/world.c:14:30
+   n@/var/tmp/hello/world.c:16:15
+  calc@/var/tmp/hello/world.c:5:1
+   word@/var/tmp/hello/world.c:5:19
+   frob@/var/tmp/hello/hello.h:5:1
+    b@/var/tmp/hello/hello.h:5:18
+    a@/var/tmp/hello/hello.h:5:11
+    c@/var/tmp/hello/hello.h:7:7
+  frob@/var/tmp/hello/hello.h:5:1
+   a@/var/tmp/hello/hello.h:5:11
+   b@/var/tmp/hello/hello.h:5:18
+   c@/var/tmp/hello/hello.h:7:7
+  exit@/usr/include/stdlib.h:542:13
+  baz@/var/tmp/hello/hello.h:2:12
+EOF
+
+testrun_compare ${abs_builddir}/declfiles testfile-splitdwarf-4 << EOF
+file: testfile-splitdwarf-4
+ cu: hello.c
+  wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24
+  m@/home/mark/src/elfutils/tests/hello.h:1:12
+  m@/home/mark/src/elfutils/tests/hello.c:5:5
+  foo@/home/mark/src/elfutils/tests/hello.c:20:1
+   f@/home/mark/src/elfutils/tests/hello.c:20:14
+  baz@/home/mark/src/elfutils/tests/hello.c:8:5
+   x@/home/mark/src/elfutils/tests/hello.c:8:14
+   r@/home/mark/src/elfutils/tests/hello.c:10:7
+  frob@/home/mark/src/elfutils/tests/hello.h:5:1
+   a@/home/mark/src/elfutils/tests/hello.h:5:11
+   b@/home/mark/src/elfutils/tests/hello.h:5:18
+   c@/home/mark/src/elfutils/tests/hello.h:7:7
+  foo@/home/mark/src/elfutils/tests/hello.c:20:1
+   f@/home/mark/src/elfutils/tests/hello.c:20:14
+   frob@/home/mark/src/elfutils/tests/hello.h:5:1
+    b@/home/mark/src/elfutils/tests/hello.h:5:18
+    a@/home/mark/src/elfutils/tests/hello.h:5:11
+    c@/home/mark/src/elfutils/tests/hello.h:7:7
+    baz@/home/mark/src/elfutils/tests/hello.c:8:5
+     x@/home/mark/src/elfutils/tests/hello.c:8:14
+     r@/home/mark/src/elfutils/tests/hello.c:10:7
+   foo@/home/mark/src/elfutils/tests/hello.c:20:1
+    f@/home/mark/src/elfutils/tests/hello.c:20:14
+    main@/home/mark/src/elfutils/tests/hello.c:4:12
+  baz@/home/mark/src/elfutils/tests/hello.c:8:5
+   x@/home/mark/src/elfutils/tests/hello.c:8:14
+   r@/home/mark/src/elfutils/tests/hello.c:10:7
+   foo@/home/mark/src/elfutils/tests/hello.c:20:1
+  main@/home/mark/src/elfutils/tests/hello.c:4:12
+ cu: world.c
+  m@/home/mark/src/elfutils/tests/hello.h:1:12
+  main@/home/mark/src/elfutils/tests/world.c:14:1
+   argc@/home/mark/src/elfutils/tests/world.c:14:11
+   argv@/home/mark/src/elfutils/tests/world.c:14:30
+   n@/home/mark/src/elfutils/tests/world.c:16:15
+   calc@/home/mark/src/elfutils/tests/world.c:5:1
+   exit@/usr/include/stdlib.h:542:13
+  calc@/home/mark/src/elfutils/tests/world.c:5:1
+   word@/home/mark/src/elfutils/tests/world.c:5:19
+   frob@/home/mark/src/elfutils/tests/hello.h:5:1
+    b@/home/mark/src/elfutils/tests/hello.h:5:18
+    a@/home/mark/src/elfutils/tests/hello.h:5:11
+    c@/home/mark/src/elfutils/tests/hello.h:7:7
+    baz@/home/mark/src/elfutils/tests/hello.h:2:12
+  frob@/home/mark/src/elfutils/tests/hello.h:5:1
+   a@/home/mark/src/elfutils/tests/hello.h:5:11
+   b@/home/mark/src/elfutils/tests/hello.h:5:18
+   c@/home/mark/src/elfutils/tests/hello.h:7:7
+  exit@/usr/include/stdlib.h:542:13
+  baz@/home/mark/src/elfutils/tests/hello.h:2:12
+EOF
+
+testrun_compare ${abs_builddir}/declfiles testfile-splitdwarf-5 << EOF
+file: testfile-splitdwarf-5
+ cu: hello.c
+  wchar_t@/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h:328:24
+  m@/home/mark/src/elfutils/tests/hello.h:1:12
+  m@/home/mark/src/elfutils/tests/hello.c:5:5
+  foo@/home/mark/src/elfutils/tests/hello.c:20:1
+   f@/home/mark/src/elfutils/tests/hello.c:20:14
+  baz@/home/mark/src/elfutils/tests/hello.c:8:5
+   x@/home/mark/src/elfutils/tests/hello.c:8:14
+   r@/home/mark/src/elfutils/tests/hello.c:10:7
+  frob@/home/mark/src/elfutils/tests/hello.h:5:1
+   a@/home/mark/src/elfutils/tests/hello.h:5:11
+   b@/home/mark/src/elfutils/tests/hello.h:5:18
+   c@/home/mark/src/elfutils/tests/hello.h:7:7
+  foo@/home/mark/src/elfutils/tests/hello.c:20:1
+   f@/home/mark/src/elfutils/tests/hello.c:20:14
+   frob@/home/mark/src/elfutils/tests/hello.h:5:1
+    b@/home/mark/src/elfutils/tests/hello.h:5:18
+    a@/home/mark/src/elfutils/tests/hello.h:5:11
+    c@/home/mark/src/elfutils/tests/hello.h:7:7
+    baz@/home/mark/src/elfutils/tests/hello.c:8:5
+     x@/home/mark/src/elfutils/tests/hello.c:8:14
+     r@/home/mark/src/elfutils/tests/hello.c:10:7
+   foo@/home/mark/src/elfutils/tests/hello.c:20:1
+    f@/home/mark/src/elfutils/tests/hello.c:20:14
+  baz@/home/mark/src/elfutils/tests/hello.c:8:5
+   x@/home/mark/src/elfutils/tests/hello.c:8:14
+   r@/home/mark/src/elfutils/tests/hello.c:10:7
+  main@/home/mark/src/elfutils/tests/hello.c:4:12
+ cu: world.c
+  m@/home/mark/src/elfutils/tests/hello.h:1:12
+  main@/home/mark/src/elfutils/tests/world.c:14:1
+   argc@/home/mark/src/elfutils/tests/world.c:14:11
+   argv@/home/mark/src/elfutils/tests/world.c:14:30
+   n@/home/mark/src/elfutils/tests/world.c:16:15
+  calc@/home/mark/src/elfutils/tests/world.c:5:1
+   word@/home/mark/src/elfutils/tests/world.c:5:19
+   frob@/home/mark/src/elfutils/tests/hello.h:5:1
+    b@/home/mark/src/elfutils/tests/hello.h:5:18
+    a@/home/mark/src/elfutils/tests/hello.h:5:11
+    c@/home/mark/src/elfutils/tests/hello.h:7:7
+  frob@/home/mark/src/elfutils/tests/hello.h:5:1
+   a@/home/mark/src/elfutils/tests/hello.h:5:11
+   b@/home/mark/src/elfutils/tests/hello.h:5:18
+   c@/home/mark/src/elfutils/tests/hello.h:7:7
+  exit@/usr/include/stdlib.h:542:13
+  baz@/home/mark/src/elfutils/tests/hello.h:2:12
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+
+testrun_compare ${abs_builddir}/declfiles testfile-dwp-5 << EOF
+file: testfile-dwp-5
+ cu: foo.cc
+  foo@/home/osandov/src/elfutils/tests/foobar.h:4:7
+  foo@/home/osandov/src/elfutils/tests/foo.cc:14:1
+   x@/home/osandov/src/elfutils/tests/foo.cc:16:7
+   x_x@/home/osandov/src/elfutils/tests/foo.cc:6:1
+    x@/home/osandov/src/elfutils/tests/foo.cc:6:10
+    i@/home/osandov/src/elfutils/tests/foo.cc:8:12
+  x_x@/home/osandov/src/elfutils/tests/foo.cc:6:1
+   x@/home/osandov/src/elfutils/tests/foo.cc:6:10
+   i@/home/osandov/src/elfutils/tests/foo.cc:8:12
+  x_x@/home/osandov/src/elfutils/tests/foo.cc:6:1
+   x@/home/osandov/src/elfutils/tests/foo.cc:6:10
+   i@/home/osandov/src/elfutils/tests/foo.cc:8:12
+ cu: bar.cc
+  bar@/home/osandov/src/elfutils/tests/foobar.h:10:8
+  bar@/home/osandov/src/elfutils/tests/bar.cc:6:1
+ cu: main.cc
+  foo@/home/osandov/src/elfutils/tests/foobar.h:4:7
+  bar@/home/osandov/src/elfutils/tests/foobar.h:10:8
+  main@/home/osandov/src/elfutils/tests/main.cc:6:1
+   argc@/home/osandov/src/elfutils/tests/main.cc:6:6
+   argv@/home/osandov/src/elfutils/tests/main.cc:6:6
+   myfoo@/home/osandov/src/elfutils/tests/main.cc:8:14
+   mybar@/home/osandov/src/elfutils/tests/main.cc:9:14
+   fibonacci@/home/osandov/src/elfutils/tests/foobar.h:17:1
+    n@/home/osandov/src/elfutils/tests/foobar.h:17:25
+    fibonacci@/home/osandov/src/elfutils/tests/foobar.h:17:1
+     n@/home/osandov/src/elfutils/tests/foobar.h:17:25
+     a@/home/osandov/src/elfutils/tests/foobar.h:23:12
+     b@/home/osandov/src/elfutils/tests/foobar.h:24:12
+     i@/home/osandov/src/elfutils/tests/foobar.h:25:25
+     tmp@/home/osandov/src/elfutils/tests/foobar.h:27:9
+  fibonacci@/home/osandov/src/elfutils/tests/foobar.h:17:1
+   n@/home/osandov/src/elfutils/tests/foobar.h:17:25
+   a@/home/osandov/src/elfutils/tests/foobar.h:23:12
+   b@/home/osandov/src/elfutils/tests/foobar.h:24:12
+   i@/home/osandov/src/elfutils/tests/foobar.h:25:25
+   tmp@/home/osandov/src/elfutils/tests/foobar.h:27:9
+EOF
+
+testrun_compare ${abs_builddir}/declfiles testfile-dwp-4 << EOF
+file: testfile-dwp-4
+ cu: foo.cc
+  foo@/home/osandov/src/elfutils/tests/foobar.h:4:7
+  foo@/home/osandov/src/elfutils/tests/foo.cc:14:1
+   x@/home/osandov/src/elfutils/tests/foo.cc:16:7
+   x_x@/home/osandov/src/elfutils/tests/foo.cc:6:1
+    x@/home/osandov/src/elfutils/tests/foo.cc:6:10
+    i@/home/osandov/src/elfutils/tests/foo.cc:8:12
+  x_x@/home/osandov/src/elfutils/tests/foo.cc:6:1
+   x@/home/osandov/src/elfutils/tests/foo.cc:6:10
+   i@/home/osandov/src/elfutils/tests/foo.cc:8:12
+  x_x@/home/osandov/src/elfutils/tests/foo.cc:6:1
+   x@/home/osandov/src/elfutils/tests/foo.cc:6:10
+   i@/home/osandov/src/elfutils/tests/foo.cc:8:12
+ cu: bar.cc
+  bar@/home/osandov/src/elfutils/tests/foobar.h:10:8
+  bar@/home/osandov/src/elfutils/tests/bar.cc:6:1
+ cu: main.cc
+  foo@/home/osandov/src/elfutils/tests/foobar.h:4:7
+  bar@/home/osandov/src/elfutils/tests/foobar.h:10:8
+  main@/home/osandov/src/elfutils/tests/main.cc:6:1
+   argc@/home/osandov/src/elfutils/tests/main.cc:6:6
+   argv@/home/osandov/src/elfutils/tests/main.cc:6:6
+   myfoo@/home/osandov/src/elfutils/tests/main.cc:8:14
+   mybar@/home/osandov/src/elfutils/tests/main.cc:9:14
+   fibonacci@/home/osandov/src/elfutils/tests/foobar.h:17:1
+    n@/home/osandov/src/elfutils/tests/foobar.h:17:25
+    fibonacci@/home/osandov/src/elfutils/tests/foobar.h:17:1
+     n@/home/osandov/src/elfutils/tests/foobar.h:17:25
+     a@/home/osandov/src/elfutils/tests/foobar.h:23:12
+     b@/home/osandov/src/elfutils/tests/foobar.h:24:12
+     i@/home/osandov/src/elfutils/tests/foobar.h:25:25
+     tmp@/home/osandov/src/elfutils/tests/foobar.h:27:9
+   foo@/home/osandov/src/elfutils/tests/foobar.h:4:7
+   bar@/home/osandov/src/elfutils/tests/foobar.h:10:8
+  fibonacci@/home/osandov/src/elfutils/tests/foobar.h:17:1
+   n@/home/osandov/src/elfutils/tests/foobar.h:17:25
+   a@/home/osandov/src/elfutils/tests/foobar.h:23:12
+   b@/home/osandov/src/elfutils/tests/foobar.h:24:12
+   i@/home/osandov/src/elfutils/tests/foobar.h:25:25
+   tmp@/home/osandov/src/elfutils/tests/foobar.h:27:9
+EOF
diff --git a/tests/run-deleted.sh b/tests/run-deleted.sh
new file mode 100755
index 0000000..a1ec1ec
--- /dev/null
+++ b/tests/run-deleted.sh
@@ -0,0 +1,52 @@
+#! /usr/bin/env bash
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/backtrace-subr.sh
+
+tempfiles deleted deleted-lib.so
+cp -p ${abs_builddir}/deleted ${abs_builddir}/deleted-lib.so .
+
+# We don't want to run the deleted process under valgrind then
+# stack will see the valgrind process backtrace.
+OLD_VALGRIND_CMD="$VALGRIND_CMD"
+unset VALGRIND_CMD
+
+pid=$(testrun ${abs_builddir}/deleted)
+sleep 1
+rm -f deleted deleted-lib.so
+tempfiles bt bt.err
+
+set VALGRIND_CMD="$OLD_VALGRIND_CMD"
+# It may have non-zero exit code with:
+# .../elfutils/src/stack: dwfl_thread_getframes tid 26376 at 0x4006c8 in .../elfutils/tests/deleted: no matching address range
+testrun ${abs_top_builddir}/src/stack -p $pid 1>bt 2>bt.err || true
+cat bt bt.err
+kill -9 $pid
+wait
+check_native_unsupported bt.err deleted
+if grep -q -E ': dwfl_linux_proc_attach pid ([[:digit:]]+): Function not implemented$' bt.err; then
+  echo >&2 deleted: OS not supported
+  exit 77
+fi
+# For PPC64 we need access to the OPD table which we get through the shdrs
+# (see backends/ppc64_init.c) but for the deleted-lib we only have phdrs.
+# So we don't have the name of the function. But since we should find
+# the EH_FRAME through phdrs just fine, we can unwind into main.
+if test "`uname -m`" != "ppc64"; then
+  grep -qw libfunc bt
+fi
+grep -qw main bt
diff --git a/tests/run-disasm-bpf.sh b/tests/run-disasm-bpf.sh
new file mode 100755
index 0000000..8ca89d5
--- /dev/null
+++ b/tests/run-disasm-bpf.sh
@@ -0,0 +1,63 @@
+#! /bin/sh
+# Copyright (C) 2016 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# This test file is created with
+#
+# #include <linux/bpf.h>
+# #include <stdio.h>
+#
+# int main()
+# {
+#   int i;
+#
+#   printf("\t.text\n");
+#
+#   for (i = 0; i < 256; ++i)
+#     if (i == (BPF_LD | BPF_IMM | BPF_DW))
+#       printf("\t.byte\t%d, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0\n", i);
+#     else
+#       {
+#         int regs = 0;
+#         switch (BPF_CLASS(i))
+#           {
+#           case BPF_ALU:
+#           case BPF_ALU64:
+#             if (BPF_SRC(i) == BPF_X
+#                 && BPF_OP(i) != BPF_NEG
+#                 && BPF_OP(i) != BPF_END)
+#               regs = 0x21;
+#             break;
+#           case BPF_LDX:
+#           case BPF_STX:
+#             regs = 0x21;
+#             break;
+#           }
+#         printf("\t.byte\t%d, %d, 0, 0, 0, 0, 0, 0\n", i, regs);
+#       }
+#
+#   return 0;
+# }
+#
+# $ ./a.out | as -o z1.o
+# $ objcopy -j .text z1.o z2.o
+#
+# Then emacs hexl edit e_machine to 0xf7.
+
+testfiles testfile-bpf-dis1.o testfile-bpf-dis1.expect
+testrun_compare ${abs_top_builddir}/src/objdump -d testfile-bpf-dis1.o < testfile-bpf-dis1.expect
diff --git a/tests/run-disasm-riscv64.sh b/tests/run-disasm-riscv64.sh
new file mode 100755
index 0000000..5353e81
--- /dev/null
+++ b/tests/run-disasm-riscv64.sh
@@ -0,0 +1,529 @@
+#! /bin/sh
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile-riscv64-dis1.o testfile-riscv64-dis1.expect
+testrun_compare ${abs_top_builddir}/src/objdump -d testfile-riscv64-dis1.o < testfile-riscv64-dis1.expect
+
+exit $?
+
+# The following code is used to generate the test file.
+cat <<EOF | riscv64-linux-gnu-as -c -o testfile-riscv64-dis1.o -
+.text
+.word 0x80000037
+.word 0x800000b7
+.word 0x40300137
+.word 0x90000017
+.word 0x01003317
+.word 0x000000ef
+.word 0x0000116f
+.word 0x000021ef
+.word 0x0000426f
+.word 0x000082ef
+.word 0x0001036f
+.word 0x000203ef
+.word 0x0004046f
+.word 0x000804ef
+.word 0x0010056f
+.word 0x002005ef
+.word 0x0040066f
+.word 0x008006ef
+.word 0x0100076f
+.word 0x020007ef
+.word 0x0400086f
+.word 0x080008ef
+.word 0x1000096f
+.word 0x200009ef
+.word 0x40000a6f
+.word 0x80000aef
+.word 0x00000067
+.word 0x80008567
+.word 0x050109e7
+.word 0x00d30863
+.word 0x80c41463
+.word 0x40d348e3
+.word 0x20d35263
+.word 0x10d364e3
+.word 0x08d37463
+.word 0x00000003
+.word 0x83050703
+.word 0x00001003
+.word 0x850c1383
+.word 0x04012003
+.word 0xa50c2383
+.word 0x05013003
+.word 0xf50c3383
+.word 0x00004003
+.word 0x83054703
+.word 0x00005003
+.word 0x850c5383
+.word 0x04016003
+.word 0xa50c6383
+.word 0x00000023
+.word 0x5f430323
+.word 0x00001023
+.word 0x5f431323
+.word 0x00002023
+.word 0x5f432323
+.word 0x00003023
+.word 0x5f433323
+.word 0x00000013
+.word 0x00000093
+.word 0x00300093
+.word 0x00310093
+.word 0x00002013
+.word 0x00002093
+.word 0x00302093
+.word 0x00312093
+.word 0x00003013
+.word 0x00003093
+.word 0x00303093
+.word 0x00313093
+.word 0x00004013
+.word 0x00004093
+.word 0x00304093
+.word 0x00314093
+.word 0x00006013
+.word 0x00006093
+.word 0x00306093
+.word 0x00316093
+.word 0x00007013
+.word 0x00007093
+.word 0x00307093
+.word 0x00317093
+.word 0x00311093
+.word 0x00315093
+.word 0x40315093
+.word 0x00000033
+.word 0x010000b3
+.word 0x40000033
+.word 0x410000b3
+.word 0x40010033
+.word 0x410200b3
+.word 0x00001033
+.word 0x010010b3
+.word 0x00002033
+.word 0x010020b3
+.word 0x00012033
+.word 0x010220b3
+.word 0x00003033
+.word 0x010030b3
+.word 0x00043033
+.word 0x010530b3
+.word 0x00004033
+.word 0x010040b3
+.word 0x00005033
+.word 0x010050b3
+.word 0x40005033
+.word 0x410050b3
+.word 0x00006033
+.word 0x010060b3
+.word 0x00007033
+.word 0x010070b3
+.word 0x0000000f
+.word 0x0210000f
+.word 0x00000073
+.word 0x00100073
+.word 0x0000001b
+.word 0x0010001b
+.word 0x0000101b
+.word 0x0010101b
+.word 0x0000501b
+.word 0x0000501b
+.word 0x4010501b
+.word 0x4010501b
+.word 0x0000003b
+.word 0x0000003b
+.word 0x00d0833b
+.word 0x00d0833b
+.word 0x40d0833b
+.word 0x40d0833b
+.word 0x00d0933b
+.word 0x00d0933b
+.word 0x00d0d33b
+.word 0x00d0d33b
+.word 0x40d0d33b
+.word 0x40d0d33b
+.word 0x0000100f
+.word 0x00431073
+.word 0x00431ff3
+.word 0xc0132ff3
+.word 0xc8133ff3
+.word 0x00435ff3
+.word 0xc0136ff3
+.word 0xc8137ff3
+.word 0x02000033
+.word 0x02e40733
+.word 0x02001033
+.word 0x02e41733
+.word 0x02002033
+.word 0x02e42733
+.word 0x02003033
+.word 0x02e43733
+.word 0x02004033
+.word 0x02e44733
+.word 0x02005033
+.word 0x02e45733
+.word 0x02006033
+.word 0x02e46733
+.word 0x02007033
+.word 0x02e47733
+.word 0x0200003b
+.word 0x02e4073b
+.word 0x0200403b
+.word 0x02e4473b
+.word 0x0200503b
+.word 0x02e4573b
+.word 0x0200603b
+.word 0x02e4673b
+.word 0x0200703b
+.word 0x02e4773b
+.word 0x1000202f
+.word 0x1800202f
+.word 0x1000302f
+.word 0x1800302f
+.word 0x0800202f
+.word 0x0800302f
+.word 0x0000202f
+.word 0x0000302f
+.word 0x2000202f
+.word 0x2000302f
+.word 0x6000202f
+.word 0x6000302f
+.word 0x4000202f
+.word 0x4000302f
+.word 0x8000202f
+.word 0x8000302f
+.word 0xa000202f
+.word 0xa000302f
+.word 0xc000202f
+.word 0xc000302f
+.word 0xe000202f
+.word 0xe000302f
+.word 0x00002007
+.word 0x00003007
+.word 0x00004007
+.word 0x00002027
+.word 0x00003027
+.word 0x00004027
+.word 0x00002043
+.word 0x02002043
+.word 0x06002043
+.word 0x00002047
+.word 0x02002047
+.word 0x06002047
+.word 0x0000204b
+.word 0x0200204b
+.word 0x0600204b
+.word 0x0000204f
+.word 0x0200204f
+.word 0x0600204f
+.word 0x00000053
+.word 0x00001053
+.word 0x00002053
+.word 0x00003053
+.word 0x00004053
+.word 0x00007053
+.word 0x02000053
+.word 0x06000053
+.word 0x08000053
+.word 0x0a000053
+.word 0x0e000053
+.word 0x10000053
+.word 0x12000053
+.word 0x16000053
+.word 0x18000053
+.word 0x1a000053
+.word 0x1e000053
+.word 0x58000053
+.word 0x5a000053
+.word 0x5e000053
+.word 0x20000053
+.word 0x20300053
+.word 0x22000053
+.word 0x22300053
+.word 0x26000053
+.word 0x26300053
+.word 0x20001053
+.word 0x20401053
+.word 0x22001053
+.word 0x22401053
+.word 0x26001053
+.word 0x26401053
+.word 0x20002053
+.word 0x20702053
+.word 0x22002053
+.word 0x22702053
+.word 0x26002053
+.word 0x26702053
+.word 0x29700053
+.word 0x2b700053
+.word 0x2f700053
+.word 0x29701053
+.word 0x2b701053
+.word 0x2f701053
+.word 0xc00332d3
+.word 0xc02332d3
+.word 0xc20342d3
+.word 0xc22342d3
+.word 0xc60222d3
+.word 0xc62222d3
+.word 0xc01332d3
+.word 0xc03332d3
+.word 0xc21342d3
+.word 0xc23342d3
+.word 0xc61222d3
+.word 0xc63222d3
+.word 0xe00503d3
+.word 0xe20504d3
+.word 0xe60509d3
+.word 0xa0340753
+.word 0xa0341753
+.word 0xa0342753
+.word 0xa2340753
+.word 0xa2341753
+.word 0xa2342753
+.word 0xa6340753
+.word 0xa6341753
+.word 0xa6342753
+.word 0xe0091d53
+.word 0xe2091d53
+.word 0xe6091d53
+.word 0xd00e2453
+.word 0xd02e2453
+.word 0xd01e1453
+.word 0xd03e1453
+.word 0xd2030553
+.word 0xd2130553
+.word 0xd6030553
+.word 0xd6130553
+.word 0xd22e2453
+.word 0xd23e1453
+.word 0xd62e2453
+.word 0xd63e2453
+.word 0xf00c0753
+.word 0xf20c0753
+.word 0xf60c0753
+.short 0x1000
+.short 0x0800
+.short 0x0400
+.short 0x0200
+.short 0x0100
+.short 0x0080
+.short 0x0040
+.short 0x0020
+.short 0x3100
+.short 0x2900
+.short 0x2500
+.short 0x2140
+.short 0x2120
+.short 0x5100
+.short 0x4900
+.short 0x4500
+.short 0x4140
+.short 0x4120
+.short 0x7100
+.short 0x6900
+.short 0x6500
+.short 0x6140
+.short 0x6120
+.short 0xb100
+.short 0xa900
+.short 0xa500
+.short 0xa140
+.short 0xa120
+.short 0xd100
+.short 0xc900
+.short 0xc500
+.short 0xc140
+.short 0xc120
+.short 0xf100
+.short 0xe900
+.short 0xe500
+.short 0xe140
+.short 0xe120
+.short 0x1001
+.short 0x1301
+.short 0x0341
+.short 0x0321
+.short 0x0311
+.short 0x0309
+.short 0x0305
+.short 0x2081
+.short 0x3081
+.short 0x20c1
+.short 0x20a1
+.short 0x2091
+.short 0x2089
+.short 0x2085
+.short 0x2105
+.short 0x2185
+.short 0x2205
+.short 0x2285
+.short 0x2305
+.short 0x2385
+.short 0x2405
+.short 0x2485
+.short 0x2505
+.short 0x2585
+.short 0x2605
+.short 0x2685
+.short 0x2705
+.short 0x2785
+.short 0x2805
+.short 0x2885
+.short 0x2905
+.short 0x2985
+.short 0x2a05
+.short 0x2a85
+.short 0x2b05
+.short 0x2b85
+.short 0x2c05
+.short 0x2c85
+.short 0x2d05
+.short 0x2d85
+.short 0x2e05
+.short 0x2e85
+.short 0x2f05
+.short 0x2f85
+.short 0x4081
+.short 0x5081
+.short 0x40c1
+.short 0x40a1
+.short 0x4091
+.short 0x4089
+.short 0x4085
+.short 0x7101
+.short 0x6141
+.short 0x6121
+.short 0x6111
+.short 0x6109
+.short 0x6105
+.short 0x7301
+.short 0x6341
+.short 0x6321
+.short 0x6311
+.short 0x6309
+.short 0x6305
+.short 0x9001
+.short 0x8041
+.short 0x8021
+.short 0x8011
+.short 0x8009
+.short 0x8005
+.short 0x8405
+.short 0x8801
+.short 0x9801
+.short 0x8941
+.short 0x8921
+.short 0x8911
+.short 0x8909
+.short 0x8905
+.short 0x8f11
+.short 0x8f31
+.short 0x8f51
+.short 0x8f71
+.short 0x9f11
+.short 0x9f31
+.short 0xa001
+.short 0xb001
+.short 0xa801
+.short 0xa401
+.short 0xa201
+.short 0xa101
+.short 0xa081
+.short 0xa041
+.short 0xa021
+.short 0xa011
+.short 0xa009
+.short 0xa005
+.short 0xc301
+.short 0xd301
+.short 0xcb01
+.short 0xc701
+.short 0xc341
+.short 0xc321
+.short 0xc311
+.short 0xc309
+.short 0xc305
+.short 0xe301
+.short 0xf301
+.short 0xeb01
+.short 0xe701
+.short 0xe341
+.short 0xe321
+.short 0xe311
+.short 0xe309
+.short 0xe305
+.short 0x1302
+.short 0x0342
+.short 0x0322
+.short 0x0312
+.short 0x030a
+.short 0x0306
+.short 0x2702
+.short 0x3702
+.short 0x2742
+.short 0x2722
+.short 0x2712
+.short 0x270a
+.short 0x2706
+.short 0x4702
+.short 0x5702
+.short 0x4742
+.short 0x4722
+.short 0x4712
+.short 0x470a
+.short 0x4706
+.short 0x6702
+.short 0x7702
+.short 0x6742
+.short 0x6722
+.short 0x6712
+.short 0x670a
+.short 0x6706
+.short 0x8302
+.short 0x8342
+.short 0x9002
+.short 0x9502
+.short 0x9572
+.short 0xa062
+.short 0xb062
+.short 0xa862
+.short 0xa462
+.short 0xa262
+.short 0xa162
+.short 0xa0e2
+.short 0xc062
+.short 0xd062
+.short 0xc862
+.short 0xc462
+.short 0xc262
+.short 0xc162
+.short 0xc0e2
+.short 0xe062
+.short 0xf062
+.short 0xe862
+.short 0xe462
+.short 0xe262
+.short 0xe162
+.short 0xe0e2
+.word 0x00153073
+.word 0x0011d073
+.word 0x0011e073
+EOF
diff --git a/tests/run-disasm-x86-64.sh b/tests/run-disasm-x86-64.sh
new file mode 100755
index 0000000..07b612b
--- /dev/null
+++ b/tests/run-disasm-x86-64.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# Copyright (C) 2007, 2008 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Run x86-64 test.
+case "`uname -m`" in
+  x86_64)
+    tempfiles testfile45.o
+    testfiles testfile45.S testfile45.expect
+    ${CC} -m64 -c -o testfile45.o testfile45.S
+    testrun_compare ${abs_top_builddir}/src/objdump -d testfile45.o < testfile45.expect
+    ;;
+esac
diff --git a/tests/run-disasm-x86.sh b/tests/run-disasm-x86.sh
new file mode 100755
index 0000000..7ac73ad
--- /dev/null
+++ b/tests/run-disasm-x86.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# Copyright (C) 2007, 2008 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Run x86 test.
+case "`uname -m`" in
+  x86_64 | i?86 )
+    tempfiles testfile44.o
+    testfiles testfile44.S testfile44.expect
+    ${CC} -m32 -c -o testfile44.o testfile44.S
+    testrun_compare ${abs_top_builddir}/src/objdump -d testfile44.o < testfile44.expect
+    ;;
+esac
diff --git a/tests/run-dwarf-die-addr-die.sh b/tests/run-dwarf-die-addr-die.sh
new file mode 100755
index 0000000..951d1c5
--- /dev/null
+++ b/tests/run-dwarf-die-addr-die.sh
@@ -0,0 +1,52 @@
+#! /bin/sh
+# Copyright (C) 2012, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-typeiter.sh
+testfiles testfile-debug-types
+
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-debug-types
+
+# see run-readelf-dwz-multi.sh
+testfiles testfile_multi_main testfile_multi.dwz
+
+testrun ${abs_builddir}/dwarf-die-addr-die testfile_multi_main
+
+# see tests/run-dwflsyms.sh
+testfiles testfilebazdbgppc64.debug
+
+testrun ${abs_builddir}/dwarf-die-addr-die testfilebazdbgppc64.debug
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-4 testfile-dwarf-5
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-dwarf-4
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-dwarf-5
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-splitdwarf-4
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-splitdwarf-5
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-hello4.dwo
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-world4.dwo
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-hello5.dwo
+testrun ${abs_builddir}/dwarf-die-addr-die testfile-world5.dwo
+
+# Self test
+testrun_on_self ${abs_builddir}/dwarf-die-addr-die
+
+exit 0
diff --git a/tests/run-dwarf-getmacros.sh b/tests/run-dwarf-getmacros.sh
new file mode 100755
index 0000000..220c242
--- /dev/null
+++ b/tests/run-dwarf-getmacros.sh
@@ -0,0 +1,2122 @@
+#! /bin/sh
+# Copyright (C) 2009, 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile51
+
+testrun_compare ${abs_builddir}/dwarf-getmacros testfile51 0xb <<\EOF
+file /home/petr/proj/elfutils/pending/elfutils/tests/decom/x.c
+ __STDC__ 1
+ __STDC_HOSTED__ 1
+ __GNUC__ 4
+ __GNUC_MINOR__ 3
+ __GNUC_PATCHLEVEL__ 2
+ __GNUC_RH_RELEASE__ 7
+ __SIZE_TYPE__ long unsigned int
+ __PTRDIFF_TYPE__ long int
+ __WCHAR_TYPE__ int
+ __WINT_TYPE__ unsigned int
+ __INTMAX_TYPE__ long int
+ __UINTMAX_TYPE__ long unsigned int
+ __GXX_ABI_VERSION 1002
+ __SCHAR_MAX__ 127
+ __SHRT_MAX__ 32767
+ __INT_MAX__ 2147483647
+ __LONG_MAX__ 9223372036854775807L
+ __LONG_LONG_MAX__ 9223372036854775807LL
+ __WCHAR_MAX__ 2147483647
+ __CHAR_BIT__ 8
+ __INTMAX_MAX__ 9223372036854775807L
+ __FLT_EVAL_METHOD__ 0
+ __DEC_EVAL_METHOD__ 2
+ __FLT_RADIX__ 2
+ __FLT_MANT_DIG__ 24
+ __FLT_DIG__ 6
+ __FLT_MIN_EXP__ (-125)
+ __FLT_MIN_10_EXP__ (-37)
+ __FLT_MAX_EXP__ 128
+ __FLT_MAX_10_EXP__ 38
+ __FLT_MAX__ 3.40282347e+38F
+ __FLT_MIN__ 1.17549435e-38F
+ __FLT_EPSILON__ 1.19209290e-7F
+ __FLT_DENORM_MIN__ 1.40129846e-45F
+ __FLT_HAS_DENORM__ 1
+ __FLT_HAS_INFINITY__ 1
+ __FLT_HAS_QUIET_NAN__ 1
+ __DBL_MANT_DIG__ 53
+ __DBL_DIG__ 15
+ __DBL_MIN_EXP__ (-1021)
+ __DBL_MIN_10_EXP__ (-307)
+ __DBL_MAX_EXP__ 1024
+ __DBL_MAX_10_EXP__ 308
+ __DBL_MAX__ 1.7976931348623157e+308
+ __DBL_MIN__ 2.2250738585072014e-308
+ __DBL_EPSILON__ 2.2204460492503131e-16
+ __DBL_DENORM_MIN__ 4.9406564584124654e-324
+ __DBL_HAS_DENORM__ 1
+ __DBL_HAS_INFINITY__ 1
+ __DBL_HAS_QUIET_NAN__ 1
+ __LDBL_MANT_DIG__ 64
+ __LDBL_DIG__ 18
+ __LDBL_MIN_EXP__ (-16381)
+ __LDBL_MIN_10_EXP__ (-4931)
+ __LDBL_MAX_EXP__ 16384
+ __LDBL_MAX_10_EXP__ 4932
+ __DECIMAL_DIG__ 21
+ __LDBL_MAX__ 1.18973149535723176502e+4932L
+ __LDBL_MIN__ 3.36210314311209350626e-4932L
+ __LDBL_EPSILON__ 1.08420217248550443401e-19L
+ __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+ __LDBL_HAS_DENORM__ 1
+ __LDBL_HAS_INFINITY__ 1
+ __LDBL_HAS_QUIET_NAN__ 1
+ __DEC32_MANT_DIG__ 7
+ __DEC32_MIN_EXP__ (-95)
+ __DEC32_MAX_EXP__ 96
+ __DEC32_MIN__ 1E-95DF
+ __DEC32_MAX__ 9.999999E96DF
+ __DEC32_EPSILON__ 1E-6DF
+ __DEC32_DEN__ 0.000001E-95DF
+ __DEC64_MANT_DIG__ 16
+ __DEC64_MIN_EXP__ (-383)
+ __DEC64_MAX_EXP__ 384
+ __DEC64_MIN__ 1E-383DD
+ __DEC64_MAX__ 9.999999999999999E384DD
+ __DEC64_EPSILON__ 1E-15DD
+ __DEC64_DEN__ 0.000000000000001E-383DD
+ __DEC128_MANT_DIG__ 34
+ __DEC128_MIN_EXP__ (-6143)
+ __DEC128_MAX_EXP__ 6144
+ __DEC128_MIN__ 1E-6143DL
+ __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+ __DEC128_EPSILON__ 1E-33DL
+ __DEC128_DEN__ 0.000000000000000000000000000000001E-6143DL
+ __REGISTER_PREFIX__ 
+ __USER_LABEL_PREFIX__ 
+ __VERSION__ "4.3.2 20081105 (Red Hat 4.3.2-7)"
+ __GNUC_GNU_INLINE__ 1
+ _LP64 1
+ __LP64__ 1
+ __NO_INLINE__ 1
+ __FINITE_MATH_ONLY__ 0
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+ __SIZEOF_INT__ 4
+ __SIZEOF_LONG__ 8
+ __SIZEOF_LONG_LONG__ 8
+ __SIZEOF_SHORT__ 2
+ __SIZEOF_FLOAT__ 4
+ __SIZEOF_DOUBLE__ 8
+ __SIZEOF_LONG_DOUBLE__ 16
+ __SIZEOF_SIZE_T__ 8
+ __SIZEOF_WCHAR_T__ 4
+ __SIZEOF_WINT_T__ 4
+ __SIZEOF_PTRDIFF_T__ 8
+ __SIZEOF_POINTER__ 8
+ __amd64 1
+ __amd64__ 1
+ __x86_64 1
+ __x86_64__ 1
+ __k8 1
+ __k8__ 1
+ __MMX__ 1
+ __SSE__ 1
+ __SSE2__ 1
+ __SSE_MATH__ 1
+ __SSE2_MATH__ 1
+ __gnu_linux__ 1
+ __linux 1
+ __linux__ 1
+ linux 1
+ __unix 1
+ __unix__ 1
+ unix 1
+ __ELF__ 1
+ __DECIMAL_BID_FORMAT__ 1
+ macro1 ble
+/file
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-getmacros testfile51 0x84 <<\EOF
+file /home/petr/proj/elfutils/pending/elfutils/tests/decom/y.c
+ __STDC__ 1
+ __STDC_HOSTED__ 1
+ __GNUC__ 4
+ __GNUC_MINOR__ 3
+ __GNUC_PATCHLEVEL__ 2
+ __GNUC_RH_RELEASE__ 7
+ __SIZE_TYPE__ long unsigned int
+ __PTRDIFF_TYPE__ long int
+ __WCHAR_TYPE__ int
+ __WINT_TYPE__ unsigned int
+ __INTMAX_TYPE__ long int
+ __UINTMAX_TYPE__ long unsigned int
+ __GXX_ABI_VERSION 1002
+ __SCHAR_MAX__ 127
+ __SHRT_MAX__ 32767
+ __INT_MAX__ 2147483647
+ __LONG_MAX__ 9223372036854775807L
+ __LONG_LONG_MAX__ 9223372036854775807LL
+ __WCHAR_MAX__ 2147483647
+ __CHAR_BIT__ 8
+ __INTMAX_MAX__ 9223372036854775807L
+ __FLT_EVAL_METHOD__ 0
+ __DEC_EVAL_METHOD__ 2
+ __FLT_RADIX__ 2
+ __FLT_MANT_DIG__ 24
+ __FLT_DIG__ 6
+ __FLT_MIN_EXP__ (-125)
+ __FLT_MIN_10_EXP__ (-37)
+ __FLT_MAX_EXP__ 128
+ __FLT_MAX_10_EXP__ 38
+ __FLT_MAX__ 3.40282347e+38F
+ __FLT_MIN__ 1.17549435e-38F
+ __FLT_EPSILON__ 1.19209290e-7F
+ __FLT_DENORM_MIN__ 1.40129846e-45F
+ __FLT_HAS_DENORM__ 1
+ __FLT_HAS_INFINITY__ 1
+ __FLT_HAS_QUIET_NAN__ 1
+ __DBL_MANT_DIG__ 53
+ __DBL_DIG__ 15
+ __DBL_MIN_EXP__ (-1021)
+ __DBL_MIN_10_EXP__ (-307)
+ __DBL_MAX_EXP__ 1024
+ __DBL_MAX_10_EXP__ 308
+ __DBL_MAX__ 1.7976931348623157e+308
+ __DBL_MIN__ 2.2250738585072014e-308
+ __DBL_EPSILON__ 2.2204460492503131e-16
+ __DBL_DENORM_MIN__ 4.9406564584124654e-324
+ __DBL_HAS_DENORM__ 1
+ __DBL_HAS_INFINITY__ 1
+ __DBL_HAS_QUIET_NAN__ 1
+ __LDBL_MANT_DIG__ 64
+ __LDBL_DIG__ 18
+ __LDBL_MIN_EXP__ (-16381)
+ __LDBL_MIN_10_EXP__ (-4931)
+ __LDBL_MAX_EXP__ 16384
+ __LDBL_MAX_10_EXP__ 4932
+ __DECIMAL_DIG__ 21
+ __LDBL_MAX__ 1.18973149535723176502e+4932L
+ __LDBL_MIN__ 3.36210314311209350626e-4932L
+ __LDBL_EPSILON__ 1.08420217248550443401e-19L
+ __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+ __LDBL_HAS_DENORM__ 1
+ __LDBL_HAS_INFINITY__ 1
+ __LDBL_HAS_QUIET_NAN__ 1
+ __DEC32_MANT_DIG__ 7
+ __DEC32_MIN_EXP__ (-95)
+ __DEC32_MAX_EXP__ 96
+ __DEC32_MIN__ 1E-95DF
+ __DEC32_MAX__ 9.999999E96DF
+ __DEC32_EPSILON__ 1E-6DF
+ __DEC32_DEN__ 0.000001E-95DF
+ __DEC64_MANT_DIG__ 16
+ __DEC64_MIN_EXP__ (-383)
+ __DEC64_MAX_EXP__ 384
+ __DEC64_MIN__ 1E-383DD
+ __DEC64_MAX__ 9.999999999999999E384DD
+ __DEC64_EPSILON__ 1E-15DD
+ __DEC64_DEN__ 0.000000000000001E-383DD
+ __DEC128_MANT_DIG__ 34
+ __DEC128_MIN_EXP__ (-6143)
+ __DEC128_MAX_EXP__ 6144
+ __DEC128_MIN__ 1E-6143DL
+ __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+ __DEC128_EPSILON__ 1E-33DL
+ __DEC128_DEN__ 0.000000000000000000000000000000001E-6143DL
+ __REGISTER_PREFIX__ 
+ __USER_LABEL_PREFIX__ 
+ __VERSION__ "4.3.2 20081105 (Red Hat 4.3.2-7)"
+ __GNUC_GNU_INLINE__ 1
+ _LP64 1
+ __LP64__ 1
+ __NO_INLINE__ 1
+ __FINITE_MATH_ONLY__ 0
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+ __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+ __SIZEOF_INT__ 4
+ __SIZEOF_LONG__ 8
+ __SIZEOF_LONG_LONG__ 8
+ __SIZEOF_SHORT__ 2
+ __SIZEOF_FLOAT__ 4
+ __SIZEOF_DOUBLE__ 8
+ __SIZEOF_LONG_DOUBLE__ 16
+ __SIZEOF_SIZE_T__ 8
+ __SIZEOF_WCHAR_T__ 4
+ __SIZEOF_WINT_T__ 4
+ __SIZEOF_PTRDIFF_T__ 8
+ __SIZEOF_POINTER__ 8
+ __amd64 1
+ __amd64__ 1
+ __x86_64 1
+ __x86_64__ 1
+ __k8 1
+ __k8__ 1
+ __MMX__ 1
+ __SSE__ 1
+ __SSE2__ 1
+ __SSE_MATH__ 1
+ __SSE2_MATH__ 1
+ __gnu_linux__ 1
+ __linux 1
+ __linux__ 1
+ linux 1
+ __unix 1
+ __unix__ 1
+ unix 1
+ __ELF__ 1
+ __DECIMAL_BID_FORMAT__ 1
+ macro2 ble
+/file
+EOF
+
+testfiles testfile-macros
+
+testrun_compare ${abs_builddir}/dwarf-getmacros testfile-macros 0xb <<\EOF
+__STDC__ 1
+__STDC_HOSTED__ 1
+__GNUC__ 4
+__GNUC_MINOR__ 7
+__GNUC_PATCHLEVEL__ 0
+__VERSION__ "4.7.0 20120507 (Red Hat 4.7.0-5)"
+__GNUC_RH_RELEASE__ 5
+__ATOMIC_RELAXED 0
+__ATOMIC_SEQ_CST 5
+__ATOMIC_ACQUIRE 2
+__ATOMIC_RELEASE 3
+__ATOMIC_ACQ_REL 4
+__ATOMIC_CONSUME 1
+__FINITE_MATH_ONLY__ 0
+_LP64 1
+__LP64__ 1
+__SIZEOF_INT__ 4
+__SIZEOF_LONG__ 8
+__SIZEOF_LONG_LONG__ 8
+__SIZEOF_SHORT__ 2
+__SIZEOF_FLOAT__ 4
+__SIZEOF_DOUBLE__ 8
+__SIZEOF_LONG_DOUBLE__ 16
+__SIZEOF_SIZE_T__ 8
+__CHAR_BIT__ 8
+__BIGGEST_ALIGNMENT__ 16
+__ORDER_LITTLE_ENDIAN__ 1234
+__ORDER_BIG_ENDIAN__ 4321
+__ORDER_PDP_ENDIAN__ 3412
+__BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+__FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+__SIZEOF_POINTER__ 8
+__SIZE_TYPE__ long unsigned int
+__PTRDIFF_TYPE__ long int
+__WCHAR_TYPE__ int
+__WINT_TYPE__ unsigned int
+__INTMAX_TYPE__ long int
+__UINTMAX_TYPE__ long unsigned int
+__CHAR16_TYPE__ short unsigned int
+__CHAR32_TYPE__ unsigned int
+__SIG_ATOMIC_TYPE__ int
+__INT8_TYPE__ signed char
+__INT16_TYPE__ short int
+__INT32_TYPE__ int
+__INT64_TYPE__ long int
+__UINT8_TYPE__ unsigned char
+__UINT16_TYPE__ short unsigned int
+__UINT32_TYPE__ unsigned int
+__UINT64_TYPE__ long unsigned int
+__INT_LEAST8_TYPE__ signed char
+__INT_LEAST16_TYPE__ short int
+__INT_LEAST32_TYPE__ int
+__INT_LEAST64_TYPE__ long int
+__UINT_LEAST8_TYPE__ unsigned char
+__UINT_LEAST16_TYPE__ short unsigned int
+__UINT_LEAST32_TYPE__ unsigned int
+__UINT_LEAST64_TYPE__ long unsigned int
+__INT_FAST8_TYPE__ signed char
+__INT_FAST16_TYPE__ long int
+__INT_FAST32_TYPE__ long int
+__INT_FAST64_TYPE__ long int
+__UINT_FAST8_TYPE__ unsigned char
+__UINT_FAST16_TYPE__ long unsigned int
+__UINT_FAST32_TYPE__ long unsigned int
+__UINT_FAST64_TYPE__ long unsigned int
+__INTPTR_TYPE__ long int
+__UINTPTR_TYPE__ long unsigned int
+__GXX_ABI_VERSION 1002
+__SCHAR_MAX__ 127
+__SHRT_MAX__ 32767
+__INT_MAX__ 2147483647
+__LONG_MAX__ 9223372036854775807L
+__LONG_LONG_MAX__ 9223372036854775807LL
+__WCHAR_MAX__ 2147483647
+__WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+__WINT_MAX__ 4294967295U
+__WINT_MIN__ 0U
+__PTRDIFF_MAX__ 9223372036854775807L
+__SIZE_MAX__ 18446744073709551615UL
+__INTMAX_MAX__ 9223372036854775807L
+__INTMAX_C(c) c ## L
+__UINTMAX_MAX__ 18446744073709551615UL
+__UINTMAX_C(c) c ## UL
+__SIG_ATOMIC_MAX__ 2147483647
+__SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+__INT8_MAX__ 127
+__INT16_MAX__ 32767
+__INT32_MAX__ 2147483647
+__INT64_MAX__ 9223372036854775807L
+__UINT8_MAX__ 255
+__UINT16_MAX__ 65535
+__UINT32_MAX__ 4294967295U
+__UINT64_MAX__ 18446744073709551615UL
+__INT_LEAST8_MAX__ 127
+__INT8_C(c) c
+__INT_LEAST16_MAX__ 32767
+__INT16_C(c) c
+__INT_LEAST32_MAX__ 2147483647
+__INT32_C(c) c
+__INT_LEAST64_MAX__ 9223372036854775807L
+__INT64_C(c) c ## L
+__UINT_LEAST8_MAX__ 255
+__UINT8_C(c) c
+__UINT_LEAST16_MAX__ 65535
+__UINT16_C(c) c
+__UINT_LEAST32_MAX__ 4294967295U
+__UINT32_C(c) c ## U
+__UINT_LEAST64_MAX__ 18446744073709551615UL
+__UINT64_C(c) c ## UL
+__INT_FAST8_MAX__ 127
+__INT_FAST16_MAX__ 9223372036854775807L
+__INT_FAST32_MAX__ 9223372036854775807L
+__INT_FAST64_MAX__ 9223372036854775807L
+__UINT_FAST8_MAX__ 255
+__UINT_FAST16_MAX__ 18446744073709551615UL
+__UINT_FAST32_MAX__ 18446744073709551615UL
+__UINT_FAST64_MAX__ 18446744073709551615UL
+__INTPTR_MAX__ 9223372036854775807L
+__UINTPTR_MAX__ 18446744073709551615UL
+__FLT_EVAL_METHOD__ 0
+__DEC_EVAL_METHOD__ 2
+__FLT_RADIX__ 2
+__FLT_MANT_DIG__ 24
+__FLT_DIG__ 6
+__FLT_MIN_EXP__ (-125)
+__FLT_MIN_10_EXP__ (-37)
+__FLT_MAX_EXP__ 128
+__FLT_MAX_10_EXP__ 38
+__FLT_DECIMAL_DIG__ 9
+__FLT_MAX__ 3.40282346638528859812e+38F
+__FLT_MIN__ 1.17549435082228750797e-38F
+__FLT_EPSILON__ 1.19209289550781250000e-7F
+__FLT_DENORM_MIN__ 1.40129846432481707092e-45F
+__FLT_HAS_DENORM__ 1
+__FLT_HAS_INFINITY__ 1
+__FLT_HAS_QUIET_NAN__ 1
+__DBL_MANT_DIG__ 53
+__DBL_DIG__ 15
+__DBL_MIN_EXP__ (-1021)
+__DBL_MIN_10_EXP__ (-307)
+__DBL_MAX_EXP__ 1024
+__DBL_MAX_10_EXP__ 308
+__DBL_DECIMAL_DIG__ 17
+__DBL_MAX__ ((double)1.79769313486231570815e+308L)
+__DBL_MIN__ ((double)2.22507385850720138309e-308L)
+__DBL_EPSILON__ ((double)2.22044604925031308085e-16L)
+__DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L)
+__DBL_HAS_DENORM__ 1
+__DBL_HAS_INFINITY__ 1
+__DBL_HAS_QUIET_NAN__ 1
+__LDBL_MANT_DIG__ 64
+__LDBL_DIG__ 18
+__LDBL_MIN_EXP__ (-16381)
+__LDBL_MIN_10_EXP__ (-4931)
+__LDBL_MAX_EXP__ 16384
+__LDBL_MAX_10_EXP__ 4932
+__DECIMAL_DIG__ 21
+__LDBL_MAX__ 1.18973149535723176502e+4932L
+__LDBL_MIN__ 3.36210314311209350626e-4932L
+__LDBL_EPSILON__ 1.08420217248550443401e-19L
+__LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+__LDBL_HAS_DENORM__ 1
+__LDBL_HAS_INFINITY__ 1
+__LDBL_HAS_QUIET_NAN__ 1
+__DEC32_MANT_DIG__ 7
+__DEC32_MIN_EXP__ (-94)
+__DEC32_MAX_EXP__ 97
+__DEC32_MIN__ 1E-95DF
+__DEC32_MAX__ 9.999999E96DF
+__DEC32_EPSILON__ 1E-6DF
+__DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+__DEC64_MANT_DIG__ 16
+__DEC64_MIN_EXP__ (-382)
+__DEC64_MAX_EXP__ 385
+__DEC64_MIN__ 1E-383DD
+__DEC64_MAX__ 9.999999999999999E384DD
+__DEC64_EPSILON__ 1E-15DD
+__DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+__DEC128_MANT_DIG__ 34
+__DEC128_MIN_EXP__ (-6142)
+__DEC128_MAX_EXP__ 6145
+__DEC128_MIN__ 1E-6143DL
+__DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+__DEC128_EPSILON__ 1E-33DL
+__DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+__REGISTER_PREFIX__ 
+__USER_LABEL_PREFIX__ 
+__GNUC_GNU_INLINE__ 1
+__NO_INLINE__ 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+__GCC_ATOMIC_BOOL_LOCK_FREE 2
+__GCC_ATOMIC_CHAR_LOCK_FREE 2
+__GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+__GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+__GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+__GCC_ATOMIC_SHORT_LOCK_FREE 2
+__GCC_ATOMIC_INT_LOCK_FREE 2
+__GCC_ATOMIC_LONG_LOCK_FREE 2
+__GCC_ATOMIC_LLONG_LOCK_FREE 2
+__GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+__GCC_ATOMIC_POINTER_LOCK_FREE 2
+__GCC_HAVE_DWARF2_CFI_ASM 1
+__PRAGMA_REDEFINE_EXTNAME 1
+__SIZEOF_INT128__ 16
+__SIZEOF_WCHAR_T__ 4
+__SIZEOF_WINT_T__ 4
+__SIZEOF_PTRDIFF_T__ 8
+__amd64 1
+__amd64__ 1
+__x86_64 1
+__x86_64__ 1
+__k8 1
+__k8__ 1
+__MMX__ 1
+__SSE__ 1
+__SSE2__ 1
+__SSE_MATH__ 1
+__SSE2_MATH__ 1
+__gnu_linux__ 1
+__linux 1
+__linux__ 1
+linux 1
+__unix 1
+__unix__ 1
+unix 1
+__ELF__ 1
+__DECIMAL_BID_FORMAT__ 1
+file /home/mark/src/tests/macro.c
+ file /usr/include/string.h
+  _STRING_H 1
+  file /usr/include/features.h
+   include 0x5d8
+    _FEATURES_H 1
+    __KERNEL_STRICT_NAMES 
+    __USE_ANSI 1
+    __GNUC_PREREQ(maj,min) ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
+    _BSD_SOURCE 1
+    _SVID_SOURCE 1
+    _POSIX_SOURCE 1
+    _POSIX_C_SOURCE 200809L
+    __USE_POSIX_IMPLICITLY 1
+    __USE_POSIX 1
+    __USE_POSIX2 1
+    __USE_POSIX199309 1
+    __USE_POSIX199506 1
+    __USE_XOPEN2K 1
+    __USE_ISOC95 1
+    __USE_ISOC99 1
+    __USE_XOPEN2K8 1
+    _ATFILE_SOURCE 1
+    __USE_MISC 1
+    __USE_BSD 1
+    __USE_SVID 1
+    __USE_ATFILE 1
+    __USE_FORTIFY_LEVEL 0
+   /include
+   file /usr/include/stdc-predef.h
+    include 0x733
+     _STDC_PREDEF_H 1
+     __STDC_IEC_559__ 1
+     __STDC_IEC_559_COMPLEX__ 1
+     __STDC_ISO_10646__ 201103L
+     __STDC_NO_THREADS__ 1
+    /include
+   /file
+   include 0x755
+    __GNU_LIBRARY__ 6
+    __GLIBC__ 2
+    __GLIBC_MINOR__ 15
+    __GLIBC_PREREQ(maj,min) ((__GLIBC__ << 16) + __GLIBC_MINOR__ >= ((maj) << 16) + (min))
+    __GLIBC_HAVE_LONG_LONG 1
+   /include
+   file /usr/include/sys/cdefs.h
+    include 0x783
+     _SYS_CDEFS_H 1
+     __LEAF , __leaf__
+     __LEAF_ATTR __attribute__ ((__leaf__))
+     __THROW __attribute__ ((__nothrow__ __LEAF))
+     __THROWNL __attribute__ ((__nothrow__))
+     __NTH(fct) __attribute__ ((__nothrow__ __LEAF)) fct
+     __P(args) args
+     __PMT(args) args
+     __CONCAT(x,y) x ## y
+     __STRING(x) #x
+     __ptr_t void *
+     __long_double_t long double
+     __BEGIN_DECLS 
+     __END_DECLS 
+     __BEGIN_NAMESPACE_STD 
+     __END_NAMESPACE_STD 
+     __USING_NAMESPACE_STD(name) 
+     __BEGIN_NAMESPACE_C99 
+     __END_NAMESPACE_C99 
+     __USING_NAMESPACE_C99(name) 
+     __bounded 
+     __unbounded 
+     __ptrvalue 
+     __bos(ptr) __builtin_object_size (ptr, __USE_FORTIFY_LEVEL > 1)
+     __bos0(ptr) __builtin_object_size (ptr, 0)
+     __fortify_function __extern_always_inline __attribute_artificial__
+     __warndecl(name,msg) extern void name (void) __attribute__((__warning__ (msg)))
+     __warnattr(msg) __attribute__((__warning__ (msg)))
+     __errordecl(name,msg) extern void name (void) __attribute__((__error__ (msg)))
+     __flexarr []
+     __REDIRECT(name,proto,alias) name proto __asm__ (__ASMNAME (#alias))
+     __REDIRECT_NTH(name,proto,alias) name proto __asm__ (__ASMNAME (#alias)) __THROW
+     __REDIRECT_NTHNL(name,proto,alias) name proto __asm__ (__ASMNAME (#alias)) __THROWNL
+     __ASMNAME(cname) __ASMNAME2 (__USER_LABEL_PREFIX__, cname)
+     __ASMNAME2(prefix,cname) __STRING (prefix) cname
+     __attribute_malloc__ __attribute__ ((__malloc__))
+     __attribute_pure__ __attribute__ ((__pure__))
+     __attribute_const__ __attribute__ ((__const__))
+     __attribute_used__ __attribute__ ((__used__))
+     __attribute_noinline__ __attribute__ ((__noinline__))
+     __attribute_deprecated__ __attribute__ ((__deprecated__))
+     __attribute_format_arg__(x) __attribute__ ((__format_arg__ (x)))
+     __attribute_format_strfmon__(a,b) __attribute__ ((__format__ (__strfmon__, a, b)))
+     __nonnull(params) __attribute__ ((__nonnull__ params))
+     __attribute_warn_unused_result__ __attribute__ ((__warn_unused_result__))
+     __wur 
+     __always_inline __inline __attribute__ ((__always_inline__))
+     __attribute_artificial__ __attribute__ ((__artificial__))
+     __extern_inline extern __inline
+     __extern_always_inline extern __always_inline
+     __va_arg_pack() __builtin_va_arg_pack ()
+     __va_arg_pack_len() __builtin_va_arg_pack_len ()
+     __restrict_arr __restrict
+     __glibc_unlikely(cond) __builtin_expect((cond), 0)
+    /include
+    file /usr/include/bits/wordsize.h
+     include 0x8fa
+      __WORDSIZE 64
+      __WORDSIZE_TIME64_COMPAT32 1
+      __SYSCALL_WORDSIZE 64
+     /include
+    /file
+    include 0x910
+     __LDBL_REDIR1(name,proto,alias) name proto
+     __LDBL_REDIR(name,proto) name proto
+     __LDBL_REDIR1_NTH(name,proto,alias) name proto __THROW
+     __LDBL_REDIR_NTH(name,proto) name proto __THROW
+     __LDBL_REDIR_DECL(name) 
+     __REDIRECT_LDBL(name,proto,alias) __REDIRECT (name, proto, alias)
+     __REDIRECT_NTH_LDBL(name,proto,alias) __REDIRECT_NTH (name, proto, alias)
+    /include
+   /file
+   file /usr/include/gnu/stubs.h
+    file /usr/include/gnu/stubs-64.h
+     include 0x945
+      __stub_bdflush 
+      __stub_chflags 
+      __stub_fattach 
+      __stub_fchflags 
+      __stub_fdetach 
+      __stub_getmsg 
+      __stub_gtty 
+      __stub_lchmod 
+      __stub_putmsg 
+      __stub_revoke 
+      __stub_setlogin 
+      __stub_sigreturn 
+      __stub_sstk 
+      __stub_stty 
+     /include
+    /file
+   /file
+  /file
+  include 0x99d
+   __need_size_t 
+   __need_NULL 
+  /include
+  file /usr/lib/gcc/x86_64-redhat-linux/4.7.0/include/stddef.h
+   include 0x9ad
+    __size_t__ 
+    __SIZE_T__ 
+    _SIZE_T 
+    _SYS_SIZE_T_H 
+    _T_SIZE_ 
+    _T_SIZE 
+    __SIZE_T 
+    _SIZE_T_ 
+    _BSD_SIZE_T_ 
+    _SIZE_T_DEFINED_ 
+    _SIZE_T_DEFINED 
+    _BSD_SIZE_T_DEFINED_ 
+    _SIZE_T_DECLARED 
+    ___int_size_t_h 
+    _GCC_SIZE_T 
+    _SIZET_ 
+    __size_t 
+    NULL ((void *)0)
+   /include
+  /file
+  file /usr/include/xlocale.h
+   _XLOCALE_H 1
+  /file
+ /file
+ HELLO "world"
+/file
+EOF
+
+testfiles testfile-macros-0xff
+testrun_compare ${abs_builddir}/dwarf-getmacros testfile-macros-0xff 0xb <<\EOF
+invalid opcode
+EOF
+testrun_compare ${abs_builddir}/dwarf-getmacros testfile-macros-0xff 0xb '' <<\EOF
+opcode 255 with 0 arguments
+file /home/petr/proj/elfutils/master/elfutils/x.c
+ FOO 0
+/file
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4-strict testfile-dwp-4-strict.dwp
+
+# Not testfile-dwp-4 because it's unclear what to do about
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99319.
+for file in testfile-dwp-5 testfile-dwp-4-strict; do
+	testrun_compare ${abs_builddir}/dwarf-getmacros "$file" '' '' << EOF
+CU foo.cc
+__STDC__ 1
+__cplusplus 201703L
+__STDC_UTF_16__ 1
+__STDC_UTF_32__ 1
+__STDC_HOSTED__ 1
+__GNUC__ 14
+__GNUC_MINOR__ 0
+__GNUC_PATCHLEVEL__ 0
+__VERSION__ "14.0.0 20230920 (experimental)"
+__ATOMIC_RELAXED 0
+__ATOMIC_SEQ_CST 5
+__ATOMIC_ACQUIRE 2
+__ATOMIC_RELEASE 3
+__ATOMIC_ACQ_REL 4
+__ATOMIC_CONSUME 1
+__OPTIMIZE__ 1
+__FINITE_MATH_ONLY__ 0
+_LP64 1
+__LP64__ 1
+__SIZEOF_INT__ 4
+__SIZEOF_LONG__ 8
+__SIZEOF_LONG_LONG__ 8
+__SIZEOF_SHORT__ 2
+__SIZEOF_FLOAT__ 4
+__SIZEOF_DOUBLE__ 8
+__SIZEOF_LONG_DOUBLE__ 16
+__SIZEOF_SIZE_T__ 8
+__CHAR_BIT__ 8
+__BIGGEST_ALIGNMENT__ 16
+__ORDER_LITTLE_ENDIAN__ 1234
+__ORDER_BIG_ENDIAN__ 4321
+__ORDER_PDP_ENDIAN__ 3412
+__BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+__FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+__SIZEOF_POINTER__ 8
+__GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+__GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+__GNUG__ 14
+__SIZE_TYPE__ long unsigned int
+__PTRDIFF_TYPE__ long int
+__WCHAR_TYPE__ int
+__WINT_TYPE__ unsigned int
+__INTMAX_TYPE__ long int
+__UINTMAX_TYPE__ long unsigned int
+__CHAR16_TYPE__ short unsigned int
+__CHAR32_TYPE__ unsigned int
+__SIG_ATOMIC_TYPE__ int
+__INT8_TYPE__ signed char
+__INT16_TYPE__ short int
+__INT32_TYPE__ int
+__INT64_TYPE__ long int
+__UINT8_TYPE__ unsigned char
+__UINT16_TYPE__ short unsigned int
+__UINT32_TYPE__ unsigned int
+__UINT64_TYPE__ long unsigned int
+__INT_LEAST8_TYPE__ signed char
+__INT_LEAST16_TYPE__ short int
+__INT_LEAST32_TYPE__ int
+__INT_LEAST64_TYPE__ long int
+__UINT_LEAST8_TYPE__ unsigned char
+__UINT_LEAST16_TYPE__ short unsigned int
+__UINT_LEAST32_TYPE__ unsigned int
+__UINT_LEAST64_TYPE__ long unsigned int
+__INT_FAST8_TYPE__ signed char
+__INT_FAST16_TYPE__ long int
+__INT_FAST32_TYPE__ long int
+__INT_FAST64_TYPE__ long int
+__UINT_FAST8_TYPE__ unsigned char
+__UINT_FAST16_TYPE__ long unsigned int
+__UINT_FAST32_TYPE__ long unsigned int
+__UINT_FAST64_TYPE__ long unsigned int
+__INTPTR_TYPE__ long int
+__UINTPTR_TYPE__ long unsigned int
+__GXX_WEAK__ 1
+__DEPRECATED 1
+__GXX_RTTI 1
+__cpp_rtti 199711L
+__GXX_EXPERIMENTAL_CXX0X__ 1
+__cpp_binary_literals 201304L
+__cpp_hex_float 201603L
+__cpp_runtime_arrays 198712L
+__cpp_raw_strings 200710L
+__cpp_unicode_literals 200710L
+__cpp_user_defined_literals 200809L
+__cpp_lambdas 200907L
+__cpp_decltype 200707L
+__cpp_attributes 200809L
+__cpp_rvalue_reference 200610L
+__cpp_rvalue_references 200610L
+__cpp_variadic_templates 200704L
+__cpp_initializer_lists 200806L
+__cpp_delegating_constructors 200604L
+__cpp_nsdmi 200809L
+__cpp_inheriting_constructors 201511L
+__cpp_ref_qualifiers 200710L
+__cpp_alias_templates 200704L
+__cpp_return_type_deduction 201304L
+__cpp_init_captures 201304L
+__cpp_generic_lambdas 201304L
+__cpp_decltype_auto 201304L
+__cpp_aggregate_nsdmi 201304L
+__cpp_variable_templates 201304L
+__cpp_digit_separators 201309L
+__cpp_unicode_characters 201411L
+__cpp_static_assert 201411L
+__cpp_namespace_attributes 201411L
+__cpp_enumerator_attributes 201411L
+__cpp_nested_namespace_definitions 201411L
+__cpp_fold_expressions 201603L
+__cpp_nontype_template_args 201411L
+__cpp_range_based_for 201603L
+__cpp_constexpr 201603L
+__cpp_if_constexpr 201606L
+__cpp_capture_star_this 201603L
+__cpp_inline_variables 201606L
+__cpp_aggregate_bases 201603L
+__cpp_deduction_guides 201703L
+__cpp_noexcept_function_type 201510L
+__cpp_template_auto 201606L
+__cpp_structured_bindings 201606L
+__cpp_variadic_using 201611L
+__cpp_guaranteed_copy_elision 201606L
+__cpp_nontype_template_parameter_auto 201606L
+__cpp_sized_deallocation 201309L
+__cpp_aligned_new 201606L
+__STDCPP_DEFAULT_NEW_ALIGNMENT__ 16
+__cpp_template_template_args 201611L
+__cpp_threadsafe_static_init 200806L
+__STDCPP_THREADS__ 1
+__EXCEPTIONS 1
+__cpp_exceptions 199711L
+__GXX_ABI_VERSION 1019
+__SCHAR_MAX__ 0x7f
+__SHRT_MAX__ 0x7fff
+__INT_MAX__ 0x7fffffff
+__LONG_MAX__ 0x7fffffffffffffffL
+__LONG_LONG_MAX__ 0x7fffffffffffffffLL
+__WCHAR_MAX__ 0x7fffffff
+__WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+__WINT_MAX__ 0xffffffffU
+__WINT_MIN__ 0U
+__PTRDIFF_MAX__ 0x7fffffffffffffffL
+__SIZE_MAX__ 0xffffffffffffffffUL
+__SCHAR_WIDTH__ 8
+__SHRT_WIDTH__ 16
+__INT_WIDTH__ 32
+__LONG_WIDTH__ 64
+__LONG_LONG_WIDTH__ 64
+__WCHAR_WIDTH__ 32
+__WINT_WIDTH__ 32
+__PTRDIFF_WIDTH__ 64
+__SIZE_WIDTH__ 64
+__GLIBCXX_TYPE_INT_N_0 __int128
+__GLIBCXX_BITSIZE_INT_N_0 128
+__INTMAX_MAX__ 0x7fffffffffffffffL
+__INTMAX_C(c) c ## L
+__UINTMAX_MAX__ 0xffffffffffffffffUL
+__UINTMAX_C(c) c ## UL
+__INTMAX_WIDTH__ 64
+__SIG_ATOMIC_MAX__ 0x7fffffff
+__SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+__SIG_ATOMIC_WIDTH__ 32
+__INT8_MAX__ 0x7f
+__INT16_MAX__ 0x7fff
+__INT32_MAX__ 0x7fffffff
+__INT64_MAX__ 0x7fffffffffffffffL
+__UINT8_MAX__ 0xff
+__UINT16_MAX__ 0xffff
+__UINT32_MAX__ 0xffffffffU
+__UINT64_MAX__ 0xffffffffffffffffUL
+__INT_LEAST8_MAX__ 0x7f
+__INT8_C(c) c
+__INT_LEAST8_WIDTH__ 8
+__INT_LEAST16_MAX__ 0x7fff
+__INT16_C(c) c
+__INT_LEAST16_WIDTH__ 16
+__INT_LEAST32_MAX__ 0x7fffffff
+__INT32_C(c) c
+__INT_LEAST32_WIDTH__ 32
+__INT_LEAST64_MAX__ 0x7fffffffffffffffL
+__INT64_C(c) c ## L
+__INT_LEAST64_WIDTH__ 64
+__UINT_LEAST8_MAX__ 0xff
+__UINT8_C(c) c
+__UINT_LEAST16_MAX__ 0xffff
+__UINT16_C(c) c
+__UINT_LEAST32_MAX__ 0xffffffffU
+__UINT32_C(c) c ## U
+__UINT_LEAST64_MAX__ 0xffffffffffffffffUL
+__UINT64_C(c) c ## UL
+__INT_FAST8_MAX__ 0x7f
+__INT_FAST8_WIDTH__ 8
+__INT_FAST16_MAX__ 0x7fffffffffffffffL
+__INT_FAST16_WIDTH__ 64
+__INT_FAST32_MAX__ 0x7fffffffffffffffL
+__INT_FAST32_WIDTH__ 64
+__INT_FAST64_MAX__ 0x7fffffffffffffffL
+__INT_FAST64_WIDTH__ 64
+__UINT_FAST8_MAX__ 0xff
+__UINT_FAST16_MAX__ 0xffffffffffffffffUL
+__UINT_FAST32_MAX__ 0xffffffffffffffffUL
+__UINT_FAST64_MAX__ 0xffffffffffffffffUL
+__INTPTR_MAX__ 0x7fffffffffffffffL
+__INTPTR_WIDTH__ 64
+__UINTPTR_MAX__ 0xffffffffffffffffUL
+__GCC_IEC_559 2
+__GCC_IEC_559_COMPLEX 2
+__FLT_EVAL_METHOD__ 0
+__FLT_EVAL_METHOD_TS_18661_3__ 0
+__DEC_EVAL_METHOD__ 2
+__FLT_RADIX__ 2
+__FLT_MANT_DIG__ 24
+__FLT_DIG__ 6
+__FLT_MIN_EXP__ (-125)
+__FLT_MIN_10_EXP__ (-37)
+__FLT_MAX_EXP__ 128
+__FLT_MAX_10_EXP__ 38
+__FLT_DECIMAL_DIG__ 9
+__FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+__FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+__FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+__FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+__FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+__FLT_HAS_DENORM__ 1
+__FLT_HAS_INFINITY__ 1
+__FLT_HAS_QUIET_NAN__ 1
+__FLT_IS_IEC_60559__ 1
+__DBL_MANT_DIG__ 53
+__DBL_DIG__ 15
+__DBL_MIN_EXP__ (-1021)
+__DBL_MIN_10_EXP__ (-307)
+__DBL_MAX_EXP__ 1024
+__DBL_MAX_10_EXP__ 308
+__DBL_DECIMAL_DIG__ 17
+__DBL_MAX__ double(1.79769313486231570814527423731704357e+308L)
+__DBL_NORM_MAX__ double(1.79769313486231570814527423731704357e+308L)
+__DBL_MIN__ double(2.22507385850720138309023271733240406e-308L)
+__DBL_EPSILON__ double(2.22044604925031308084726333618164062e-16L)
+__DBL_DENORM_MIN__ double(4.94065645841246544176568792868221372e-324L)
+__DBL_HAS_DENORM__ 1
+__DBL_HAS_INFINITY__ 1
+__DBL_HAS_QUIET_NAN__ 1
+__DBL_IS_IEC_60559__ 1
+__LDBL_MANT_DIG__ 64
+__LDBL_DIG__ 18
+__LDBL_MIN_EXP__ (-16381)
+__LDBL_MIN_10_EXP__ (-4931)
+__LDBL_MAX_EXP__ 16384
+__LDBL_MAX_10_EXP__ 4932
+__DECIMAL_DIG__ 21
+__LDBL_DECIMAL_DIG__ 21
+__LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+__LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+__LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+__LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+__LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+__LDBL_HAS_DENORM__ 1
+__LDBL_HAS_INFINITY__ 1
+__LDBL_HAS_QUIET_NAN__ 1
+__LDBL_IS_IEC_60559__ 1
+__FLT16_MANT_DIG__ 11
+__FLT16_DIG__ 3
+__FLT16_MIN_EXP__ (-13)
+__FLT16_MIN_10_EXP__ (-4)
+__FLT16_MAX_EXP__ 16
+__FLT16_MAX_10_EXP__ 4
+__FLT16_DECIMAL_DIG__ 5
+__FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+__FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+__FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+__FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+__FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+__FLT16_HAS_DENORM__ 1
+__FLT16_HAS_INFINITY__ 1
+__FLT16_HAS_QUIET_NAN__ 1
+__FLT16_IS_IEC_60559__ 1
+__FLT32_MANT_DIG__ 24
+__FLT32_DIG__ 6
+__FLT32_MIN_EXP__ (-125)
+__FLT32_MIN_10_EXP__ (-37)
+__FLT32_MAX_EXP__ 128
+__FLT32_MAX_10_EXP__ 38
+__FLT32_DECIMAL_DIG__ 9
+__FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+__FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+__FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+__FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+__FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+__FLT32_HAS_DENORM__ 1
+__FLT32_HAS_INFINITY__ 1
+__FLT32_HAS_QUIET_NAN__ 1
+__FLT32_IS_IEC_60559__ 1
+__FLT64_MANT_DIG__ 53
+__FLT64_DIG__ 15
+__FLT64_MIN_EXP__ (-1021)
+__FLT64_MIN_10_EXP__ (-307)
+__FLT64_MAX_EXP__ 1024
+__FLT64_MAX_10_EXP__ 308
+__FLT64_DECIMAL_DIG__ 17
+__FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+__FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+__FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+__FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+__FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+__FLT64_HAS_DENORM__ 1
+__FLT64_HAS_INFINITY__ 1
+__FLT64_HAS_QUIET_NAN__ 1
+__FLT64_IS_IEC_60559__ 1
+__FLT128_MANT_DIG__ 113
+__FLT128_DIG__ 33
+__FLT128_MIN_EXP__ (-16381)
+__FLT128_MIN_10_EXP__ (-4931)
+__FLT128_MAX_EXP__ 16384
+__FLT128_MAX_10_EXP__ 4932
+__FLT128_DECIMAL_DIG__ 36
+__FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+__FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+__FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+__FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+__FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+__FLT128_HAS_DENORM__ 1
+__FLT128_HAS_INFINITY__ 1
+__FLT128_HAS_QUIET_NAN__ 1
+__FLT128_IS_IEC_60559__ 1
+__FLT32X_MANT_DIG__ 53
+__FLT32X_DIG__ 15
+__FLT32X_MIN_EXP__ (-1021)
+__FLT32X_MIN_10_EXP__ (-307)
+__FLT32X_MAX_EXP__ 1024
+__FLT32X_MAX_10_EXP__ 308
+__FLT32X_DECIMAL_DIG__ 17
+__FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+__FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+__FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+__FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+__FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+__FLT32X_HAS_DENORM__ 1
+__FLT32X_HAS_INFINITY__ 1
+__FLT32X_HAS_QUIET_NAN__ 1
+__FLT32X_IS_IEC_60559__ 1
+__FLT64X_MANT_DIG__ 64
+__FLT64X_DIG__ 18
+__FLT64X_MIN_EXP__ (-16381)
+__FLT64X_MIN_10_EXP__ (-4931)
+__FLT64X_MAX_EXP__ 16384
+__FLT64X_MAX_10_EXP__ 4932
+__FLT64X_DECIMAL_DIG__ 21
+__FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+__FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+__FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+__FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+__FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+__FLT64X_HAS_DENORM__ 1
+__FLT64X_HAS_INFINITY__ 1
+__FLT64X_HAS_QUIET_NAN__ 1
+__FLT64X_IS_IEC_60559__ 1
+__BFLT16_MANT_DIG__ 8
+__BFLT16_DIG__ 2
+__BFLT16_MIN_EXP__ (-125)
+__BFLT16_MIN_10_EXP__ (-37)
+__BFLT16_MAX_EXP__ 128
+__BFLT16_MAX_10_EXP__ 38
+__BFLT16_DECIMAL_DIG__ 4
+__BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+__BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+__BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+__BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+__BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+__BFLT16_HAS_DENORM__ 1
+__BFLT16_HAS_INFINITY__ 1
+__BFLT16_HAS_QUIET_NAN__ 1
+__BFLT16_IS_IEC_60559__ 0
+__DEC32_MANT_DIG__ 7
+__DEC32_MIN_EXP__ (-94)
+__DEC32_MAX_EXP__ 97
+__DEC32_MIN__ 1E-95DF
+__DEC32_MAX__ 9.999999E96DF
+__DEC32_EPSILON__ 1E-6DF
+__DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+__DEC64_MANT_DIG__ 16
+__DEC64_MIN_EXP__ (-382)
+__DEC64_MAX_EXP__ 385
+__DEC64_MIN__ 1E-383DD
+__DEC64_MAX__ 9.999999999999999E384DD
+__DEC64_EPSILON__ 1E-15DD
+__DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+__DEC128_MANT_DIG__ 34
+__DEC128_MIN_EXP__ (-6142)
+__DEC128_MAX_EXP__ 6145
+__DEC128_MIN__ 1E-6143DL
+__DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+__DEC128_EPSILON__ 1E-33DL
+__DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+__REGISTER_PREFIX__ 
+__USER_LABEL_PREFIX__ 
+__GNUC_STDC_INLINE__ 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+__GCC_ATOMIC_BOOL_LOCK_FREE 2
+__GCC_ATOMIC_CHAR_LOCK_FREE 2
+__GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+__GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+__GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+__GCC_ATOMIC_SHORT_LOCK_FREE 2
+__GCC_ATOMIC_INT_LOCK_FREE 2
+__GCC_ATOMIC_LONG_LOCK_FREE 2
+__GCC_ATOMIC_LLONG_LOCK_FREE 2
+__GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+__GCC_DESTRUCTIVE_SIZE 64
+__GCC_CONSTRUCTIVE_SIZE 64
+__GCC_ATOMIC_POINTER_LOCK_FREE 2
+__HAVE_SPECULATION_SAFE_VALUE 1
+__GCC_HAVE_DWARF2_CFI_ASM 1
+__PRAGMA_REDEFINE_EXTNAME 1
+__SIZEOF_INT128__ 16
+__SIZEOF_WCHAR_T__ 4
+__SIZEOF_WINT_T__ 4
+__SIZEOF_PTRDIFF_T__ 8
+__amd64 1
+__amd64__ 1
+__x86_64 1
+__x86_64__ 1
+__SIZEOF_FLOAT80__ 16
+__SIZEOF_FLOAT128__ 16
+__ATOMIC_HLE_ACQUIRE 65536
+__ATOMIC_HLE_RELEASE 131072
+__GCC_ASM_FLAG_OUTPUTS__ 1
+__k8 1
+__k8__ 1
+__code_model_small__ 1
+__MMX__ 1
+__SSE__ 1
+__SSE2__ 1
+__FXSR__ 1
+__SSE_MATH__ 1
+__SSE2_MATH__ 1
+__MMX_WITH_SSE__ 1
+__SEG_FS 1
+__SEG_GS 1
+__gnu_linux__ 1
+__linux 1
+__linux__ 1
+linux 1
+__unix 1
+__unix__ 1
+unix 1
+__ELF__ 1
+__DECIMAL_BID_FORMAT__ 1
+_GNU_SOURCE 1
+file /home/osandov/src/elfutils/tests/foo.cc
+ file /usr/include/stdc-predef.h
+  _STDC_PREDEF_H 1
+  __STDC_IEC_559__ 1
+  __STDC_IEC_60559_BFP__ 201404L
+  __STDC_IEC_559_COMPLEX__ 1
+  __STDC_IEC_60559_COMPLEX__ 201404L
+  __STDC_ISO_10646__ 201706L
+ /file
+ file /home/osandov/src/elfutils/tests/foobar.h
+  FROB(x) ((x) ^ 0x2a2a2a2a)
+  FRY(x) ((x) * 0x100000001b3)
+ /file
+ ZERO() (1 - 1)
+/file
+CU bar.cc
+__STDC__ 1
+__cplusplus 201703L
+__STDC_UTF_16__ 1
+__STDC_UTF_32__ 1
+__STDC_HOSTED__ 1
+__GNUC__ 14
+__GNUC_MINOR__ 0
+__GNUC_PATCHLEVEL__ 0
+__VERSION__ "14.0.0 20230920 (experimental)"
+__ATOMIC_RELAXED 0
+__ATOMIC_SEQ_CST 5
+__ATOMIC_ACQUIRE 2
+__ATOMIC_RELEASE 3
+__ATOMIC_ACQ_REL 4
+__ATOMIC_CONSUME 1
+__OPTIMIZE__ 1
+__FINITE_MATH_ONLY__ 0
+_LP64 1
+__LP64__ 1
+__SIZEOF_INT__ 4
+__SIZEOF_LONG__ 8
+__SIZEOF_LONG_LONG__ 8
+__SIZEOF_SHORT__ 2
+__SIZEOF_FLOAT__ 4
+__SIZEOF_DOUBLE__ 8
+__SIZEOF_LONG_DOUBLE__ 16
+__SIZEOF_SIZE_T__ 8
+__CHAR_BIT__ 8
+__BIGGEST_ALIGNMENT__ 16
+__ORDER_LITTLE_ENDIAN__ 1234
+__ORDER_BIG_ENDIAN__ 4321
+__ORDER_PDP_ENDIAN__ 3412
+__BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+__FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+__SIZEOF_POINTER__ 8
+__GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+__GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+__GNUG__ 14
+__SIZE_TYPE__ long unsigned int
+__PTRDIFF_TYPE__ long int
+__WCHAR_TYPE__ int
+__WINT_TYPE__ unsigned int
+__INTMAX_TYPE__ long int
+__UINTMAX_TYPE__ long unsigned int
+__CHAR16_TYPE__ short unsigned int
+__CHAR32_TYPE__ unsigned int
+__SIG_ATOMIC_TYPE__ int
+__INT8_TYPE__ signed char
+__INT16_TYPE__ short int
+__INT32_TYPE__ int
+__INT64_TYPE__ long int
+__UINT8_TYPE__ unsigned char
+__UINT16_TYPE__ short unsigned int
+__UINT32_TYPE__ unsigned int
+__UINT64_TYPE__ long unsigned int
+__INT_LEAST8_TYPE__ signed char
+__INT_LEAST16_TYPE__ short int
+__INT_LEAST32_TYPE__ int
+__INT_LEAST64_TYPE__ long int
+__UINT_LEAST8_TYPE__ unsigned char
+__UINT_LEAST16_TYPE__ short unsigned int
+__UINT_LEAST32_TYPE__ unsigned int
+__UINT_LEAST64_TYPE__ long unsigned int
+__INT_FAST8_TYPE__ signed char
+__INT_FAST16_TYPE__ long int
+__INT_FAST32_TYPE__ long int
+__INT_FAST64_TYPE__ long int
+__UINT_FAST8_TYPE__ unsigned char
+__UINT_FAST16_TYPE__ long unsigned int
+__UINT_FAST32_TYPE__ long unsigned int
+__UINT_FAST64_TYPE__ long unsigned int
+__INTPTR_TYPE__ long int
+__UINTPTR_TYPE__ long unsigned int
+__GXX_WEAK__ 1
+__DEPRECATED 1
+__GXX_RTTI 1
+__cpp_rtti 199711L
+__GXX_EXPERIMENTAL_CXX0X__ 1
+__cpp_binary_literals 201304L
+__cpp_hex_float 201603L
+__cpp_runtime_arrays 198712L
+__cpp_raw_strings 200710L
+__cpp_unicode_literals 200710L
+__cpp_user_defined_literals 200809L
+__cpp_lambdas 200907L
+__cpp_decltype 200707L
+__cpp_attributes 200809L
+__cpp_rvalue_reference 200610L
+__cpp_rvalue_references 200610L
+__cpp_variadic_templates 200704L
+__cpp_initializer_lists 200806L
+__cpp_delegating_constructors 200604L
+__cpp_nsdmi 200809L
+__cpp_inheriting_constructors 201511L
+__cpp_ref_qualifiers 200710L
+__cpp_alias_templates 200704L
+__cpp_return_type_deduction 201304L
+__cpp_init_captures 201304L
+__cpp_generic_lambdas 201304L
+__cpp_decltype_auto 201304L
+__cpp_aggregate_nsdmi 201304L
+__cpp_variable_templates 201304L
+__cpp_digit_separators 201309L
+__cpp_unicode_characters 201411L
+__cpp_static_assert 201411L
+__cpp_namespace_attributes 201411L
+__cpp_enumerator_attributes 201411L
+__cpp_nested_namespace_definitions 201411L
+__cpp_fold_expressions 201603L
+__cpp_nontype_template_args 201411L
+__cpp_range_based_for 201603L
+__cpp_constexpr 201603L
+__cpp_if_constexpr 201606L
+__cpp_capture_star_this 201603L
+__cpp_inline_variables 201606L
+__cpp_aggregate_bases 201603L
+__cpp_deduction_guides 201703L
+__cpp_noexcept_function_type 201510L
+__cpp_template_auto 201606L
+__cpp_structured_bindings 201606L
+__cpp_variadic_using 201611L
+__cpp_guaranteed_copy_elision 201606L
+__cpp_nontype_template_parameter_auto 201606L
+__cpp_sized_deallocation 201309L
+__cpp_aligned_new 201606L
+__STDCPP_DEFAULT_NEW_ALIGNMENT__ 16
+__cpp_template_template_args 201611L
+__cpp_threadsafe_static_init 200806L
+__STDCPP_THREADS__ 1
+__EXCEPTIONS 1
+__cpp_exceptions 199711L
+__GXX_ABI_VERSION 1019
+__SCHAR_MAX__ 0x7f
+__SHRT_MAX__ 0x7fff
+__INT_MAX__ 0x7fffffff
+__LONG_MAX__ 0x7fffffffffffffffL
+__LONG_LONG_MAX__ 0x7fffffffffffffffLL
+__WCHAR_MAX__ 0x7fffffff
+__WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+__WINT_MAX__ 0xffffffffU
+__WINT_MIN__ 0U
+__PTRDIFF_MAX__ 0x7fffffffffffffffL
+__SIZE_MAX__ 0xffffffffffffffffUL
+__SCHAR_WIDTH__ 8
+__SHRT_WIDTH__ 16
+__INT_WIDTH__ 32
+__LONG_WIDTH__ 64
+__LONG_LONG_WIDTH__ 64
+__WCHAR_WIDTH__ 32
+__WINT_WIDTH__ 32
+__PTRDIFF_WIDTH__ 64
+__SIZE_WIDTH__ 64
+__GLIBCXX_TYPE_INT_N_0 __int128
+__GLIBCXX_BITSIZE_INT_N_0 128
+__INTMAX_MAX__ 0x7fffffffffffffffL
+__INTMAX_C(c) c ## L
+__UINTMAX_MAX__ 0xffffffffffffffffUL
+__UINTMAX_C(c) c ## UL
+__INTMAX_WIDTH__ 64
+__SIG_ATOMIC_MAX__ 0x7fffffff
+__SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+__SIG_ATOMIC_WIDTH__ 32
+__INT8_MAX__ 0x7f
+__INT16_MAX__ 0x7fff
+__INT32_MAX__ 0x7fffffff
+__INT64_MAX__ 0x7fffffffffffffffL
+__UINT8_MAX__ 0xff
+__UINT16_MAX__ 0xffff
+__UINT32_MAX__ 0xffffffffU
+__UINT64_MAX__ 0xffffffffffffffffUL
+__INT_LEAST8_MAX__ 0x7f
+__INT8_C(c) c
+__INT_LEAST8_WIDTH__ 8
+__INT_LEAST16_MAX__ 0x7fff
+__INT16_C(c) c
+__INT_LEAST16_WIDTH__ 16
+__INT_LEAST32_MAX__ 0x7fffffff
+__INT32_C(c) c
+__INT_LEAST32_WIDTH__ 32
+__INT_LEAST64_MAX__ 0x7fffffffffffffffL
+__INT64_C(c) c ## L
+__INT_LEAST64_WIDTH__ 64
+__UINT_LEAST8_MAX__ 0xff
+__UINT8_C(c) c
+__UINT_LEAST16_MAX__ 0xffff
+__UINT16_C(c) c
+__UINT_LEAST32_MAX__ 0xffffffffU
+__UINT32_C(c) c ## U
+__UINT_LEAST64_MAX__ 0xffffffffffffffffUL
+__UINT64_C(c) c ## UL
+__INT_FAST8_MAX__ 0x7f
+__INT_FAST8_WIDTH__ 8
+__INT_FAST16_MAX__ 0x7fffffffffffffffL
+__INT_FAST16_WIDTH__ 64
+__INT_FAST32_MAX__ 0x7fffffffffffffffL
+__INT_FAST32_WIDTH__ 64
+__INT_FAST64_MAX__ 0x7fffffffffffffffL
+__INT_FAST64_WIDTH__ 64
+__UINT_FAST8_MAX__ 0xff
+__UINT_FAST16_MAX__ 0xffffffffffffffffUL
+__UINT_FAST32_MAX__ 0xffffffffffffffffUL
+__UINT_FAST64_MAX__ 0xffffffffffffffffUL
+__INTPTR_MAX__ 0x7fffffffffffffffL
+__INTPTR_WIDTH__ 64
+__UINTPTR_MAX__ 0xffffffffffffffffUL
+__GCC_IEC_559 2
+__GCC_IEC_559_COMPLEX 2
+__FLT_EVAL_METHOD__ 0
+__FLT_EVAL_METHOD_TS_18661_3__ 0
+__DEC_EVAL_METHOD__ 2
+__FLT_RADIX__ 2
+__FLT_MANT_DIG__ 24
+__FLT_DIG__ 6
+__FLT_MIN_EXP__ (-125)
+__FLT_MIN_10_EXP__ (-37)
+__FLT_MAX_EXP__ 128
+__FLT_MAX_10_EXP__ 38
+__FLT_DECIMAL_DIG__ 9
+__FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+__FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+__FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+__FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+__FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+__FLT_HAS_DENORM__ 1
+__FLT_HAS_INFINITY__ 1
+__FLT_HAS_QUIET_NAN__ 1
+__FLT_IS_IEC_60559__ 1
+__DBL_MANT_DIG__ 53
+__DBL_DIG__ 15
+__DBL_MIN_EXP__ (-1021)
+__DBL_MIN_10_EXP__ (-307)
+__DBL_MAX_EXP__ 1024
+__DBL_MAX_10_EXP__ 308
+__DBL_DECIMAL_DIG__ 17
+__DBL_MAX__ double(1.79769313486231570814527423731704357e+308L)
+__DBL_NORM_MAX__ double(1.79769313486231570814527423731704357e+308L)
+__DBL_MIN__ double(2.22507385850720138309023271733240406e-308L)
+__DBL_EPSILON__ double(2.22044604925031308084726333618164062e-16L)
+__DBL_DENORM_MIN__ double(4.94065645841246544176568792868221372e-324L)
+__DBL_HAS_DENORM__ 1
+__DBL_HAS_INFINITY__ 1
+__DBL_HAS_QUIET_NAN__ 1
+__DBL_IS_IEC_60559__ 1
+__LDBL_MANT_DIG__ 64
+__LDBL_DIG__ 18
+__LDBL_MIN_EXP__ (-16381)
+__LDBL_MIN_10_EXP__ (-4931)
+__LDBL_MAX_EXP__ 16384
+__LDBL_MAX_10_EXP__ 4932
+__DECIMAL_DIG__ 21
+__LDBL_DECIMAL_DIG__ 21
+__LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+__LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+__LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+__LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+__LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+__LDBL_HAS_DENORM__ 1
+__LDBL_HAS_INFINITY__ 1
+__LDBL_HAS_QUIET_NAN__ 1
+__LDBL_IS_IEC_60559__ 1
+__FLT16_MANT_DIG__ 11
+__FLT16_DIG__ 3
+__FLT16_MIN_EXP__ (-13)
+__FLT16_MIN_10_EXP__ (-4)
+__FLT16_MAX_EXP__ 16
+__FLT16_MAX_10_EXP__ 4
+__FLT16_DECIMAL_DIG__ 5
+__FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+__FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+__FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+__FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+__FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+__FLT16_HAS_DENORM__ 1
+__FLT16_HAS_INFINITY__ 1
+__FLT16_HAS_QUIET_NAN__ 1
+__FLT16_IS_IEC_60559__ 1
+__FLT32_MANT_DIG__ 24
+__FLT32_DIG__ 6
+__FLT32_MIN_EXP__ (-125)
+__FLT32_MIN_10_EXP__ (-37)
+__FLT32_MAX_EXP__ 128
+__FLT32_MAX_10_EXP__ 38
+__FLT32_DECIMAL_DIG__ 9
+__FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+__FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+__FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+__FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+__FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+__FLT32_HAS_DENORM__ 1
+__FLT32_HAS_INFINITY__ 1
+__FLT32_HAS_QUIET_NAN__ 1
+__FLT32_IS_IEC_60559__ 1
+__FLT64_MANT_DIG__ 53
+__FLT64_DIG__ 15
+__FLT64_MIN_EXP__ (-1021)
+__FLT64_MIN_10_EXP__ (-307)
+__FLT64_MAX_EXP__ 1024
+__FLT64_MAX_10_EXP__ 308
+__FLT64_DECIMAL_DIG__ 17
+__FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+__FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+__FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+__FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+__FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+__FLT64_HAS_DENORM__ 1
+__FLT64_HAS_INFINITY__ 1
+__FLT64_HAS_QUIET_NAN__ 1
+__FLT64_IS_IEC_60559__ 1
+__FLT128_MANT_DIG__ 113
+__FLT128_DIG__ 33
+__FLT128_MIN_EXP__ (-16381)
+__FLT128_MIN_10_EXP__ (-4931)
+__FLT128_MAX_EXP__ 16384
+__FLT128_MAX_10_EXP__ 4932
+__FLT128_DECIMAL_DIG__ 36
+__FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+__FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+__FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+__FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+__FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+__FLT128_HAS_DENORM__ 1
+__FLT128_HAS_INFINITY__ 1
+__FLT128_HAS_QUIET_NAN__ 1
+__FLT128_IS_IEC_60559__ 1
+__FLT32X_MANT_DIG__ 53
+__FLT32X_DIG__ 15
+__FLT32X_MIN_EXP__ (-1021)
+__FLT32X_MIN_10_EXP__ (-307)
+__FLT32X_MAX_EXP__ 1024
+__FLT32X_MAX_10_EXP__ 308
+__FLT32X_DECIMAL_DIG__ 17
+__FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+__FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+__FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+__FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+__FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+__FLT32X_HAS_DENORM__ 1
+__FLT32X_HAS_INFINITY__ 1
+__FLT32X_HAS_QUIET_NAN__ 1
+__FLT32X_IS_IEC_60559__ 1
+__FLT64X_MANT_DIG__ 64
+__FLT64X_DIG__ 18
+__FLT64X_MIN_EXP__ (-16381)
+__FLT64X_MIN_10_EXP__ (-4931)
+__FLT64X_MAX_EXP__ 16384
+__FLT64X_MAX_10_EXP__ 4932
+__FLT64X_DECIMAL_DIG__ 21
+__FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+__FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+__FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+__FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+__FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+__FLT64X_HAS_DENORM__ 1
+__FLT64X_HAS_INFINITY__ 1
+__FLT64X_HAS_QUIET_NAN__ 1
+__FLT64X_IS_IEC_60559__ 1
+__BFLT16_MANT_DIG__ 8
+__BFLT16_DIG__ 2
+__BFLT16_MIN_EXP__ (-125)
+__BFLT16_MIN_10_EXP__ (-37)
+__BFLT16_MAX_EXP__ 128
+__BFLT16_MAX_10_EXP__ 38
+__BFLT16_DECIMAL_DIG__ 4
+__BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+__BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+__BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+__BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+__BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+__BFLT16_HAS_DENORM__ 1
+__BFLT16_HAS_INFINITY__ 1
+__BFLT16_HAS_QUIET_NAN__ 1
+__BFLT16_IS_IEC_60559__ 0
+__DEC32_MANT_DIG__ 7
+__DEC32_MIN_EXP__ (-94)
+__DEC32_MAX_EXP__ 97
+__DEC32_MIN__ 1E-95DF
+__DEC32_MAX__ 9.999999E96DF
+__DEC32_EPSILON__ 1E-6DF
+__DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+__DEC64_MANT_DIG__ 16
+__DEC64_MIN_EXP__ (-382)
+__DEC64_MAX_EXP__ 385
+__DEC64_MIN__ 1E-383DD
+__DEC64_MAX__ 9.999999999999999E384DD
+__DEC64_EPSILON__ 1E-15DD
+__DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+__DEC128_MANT_DIG__ 34
+__DEC128_MIN_EXP__ (-6142)
+__DEC128_MAX_EXP__ 6145
+__DEC128_MIN__ 1E-6143DL
+__DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+__DEC128_EPSILON__ 1E-33DL
+__DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+__REGISTER_PREFIX__ 
+__USER_LABEL_PREFIX__ 
+__GNUC_STDC_INLINE__ 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+__GCC_ATOMIC_BOOL_LOCK_FREE 2
+__GCC_ATOMIC_CHAR_LOCK_FREE 2
+__GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+__GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+__GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+__GCC_ATOMIC_SHORT_LOCK_FREE 2
+__GCC_ATOMIC_INT_LOCK_FREE 2
+__GCC_ATOMIC_LONG_LOCK_FREE 2
+__GCC_ATOMIC_LLONG_LOCK_FREE 2
+__GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+__GCC_DESTRUCTIVE_SIZE 64
+__GCC_CONSTRUCTIVE_SIZE 64
+__GCC_ATOMIC_POINTER_LOCK_FREE 2
+__HAVE_SPECULATION_SAFE_VALUE 1
+__GCC_HAVE_DWARF2_CFI_ASM 1
+__PRAGMA_REDEFINE_EXTNAME 1
+__SIZEOF_INT128__ 16
+__SIZEOF_WCHAR_T__ 4
+__SIZEOF_WINT_T__ 4
+__SIZEOF_PTRDIFF_T__ 8
+__amd64 1
+__amd64__ 1
+__x86_64 1
+__x86_64__ 1
+__SIZEOF_FLOAT80__ 16
+__SIZEOF_FLOAT128__ 16
+__ATOMIC_HLE_ACQUIRE 65536
+__ATOMIC_HLE_RELEASE 131072
+__GCC_ASM_FLAG_OUTPUTS__ 1
+__k8 1
+__k8__ 1
+__code_model_small__ 1
+__MMX__ 1
+__SSE__ 1
+__SSE2__ 1
+__FXSR__ 1
+__SSE_MATH__ 1
+__SSE2_MATH__ 1
+__MMX_WITH_SSE__ 1
+__SEG_FS 1
+__SEG_GS 1
+__gnu_linux__ 1
+__linux 1
+__linux__ 1
+linux 1
+__unix 1
+__unix__ 1
+unix 1
+__ELF__ 1
+__DECIMAL_BID_FORMAT__ 1
+_GNU_SOURCE 1
+file /home/osandov/src/elfutils/tests/bar.cc
+ file /usr/include/stdc-predef.h
+  _STDC_PREDEF_H 1
+  __STDC_IEC_559__ 1
+  __STDC_IEC_60559_BFP__ 201404L
+  __STDC_IEC_559_COMPLEX__ 1
+  __STDC_IEC_60559_COMPLEX__ 201404L
+  __STDC_ISO_10646__ 201706L
+ /file
+ file /home/osandov/src/elfutils/tests/foobar.h
+  FROB(x) ((x) ^ 0x2a2a2a2a)
+  FRY(x) ((x) * 0x100000001b3)
+ /file
+ ONE 1
+/file
+CU main.cc
+__STDC__ 1
+__cplusplus 201703L
+__STDC_UTF_16__ 1
+__STDC_UTF_32__ 1
+__STDC_HOSTED__ 1
+__GNUC__ 14
+__GNUC_MINOR__ 0
+__GNUC_PATCHLEVEL__ 0
+__VERSION__ "14.0.0 20230920 (experimental)"
+__ATOMIC_RELAXED 0
+__ATOMIC_SEQ_CST 5
+__ATOMIC_ACQUIRE 2
+__ATOMIC_RELEASE 3
+__ATOMIC_ACQ_REL 4
+__ATOMIC_CONSUME 1
+__OPTIMIZE__ 1
+__FINITE_MATH_ONLY__ 0
+_LP64 1
+__LP64__ 1
+__SIZEOF_INT__ 4
+__SIZEOF_LONG__ 8
+__SIZEOF_LONG_LONG__ 8
+__SIZEOF_SHORT__ 2
+__SIZEOF_FLOAT__ 4
+__SIZEOF_DOUBLE__ 8
+__SIZEOF_LONG_DOUBLE__ 16
+__SIZEOF_SIZE_T__ 8
+__CHAR_BIT__ 8
+__BIGGEST_ALIGNMENT__ 16
+__ORDER_LITTLE_ENDIAN__ 1234
+__ORDER_BIG_ENDIAN__ 4321
+__ORDER_PDP_ENDIAN__ 3412
+__BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+__FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+__SIZEOF_POINTER__ 8
+__GNUC_EXECUTION_CHARSET_NAME "UTF-8"
+__GNUC_WIDE_EXECUTION_CHARSET_NAME "UTF-32LE"
+__GNUG__ 14
+__SIZE_TYPE__ long unsigned int
+__PTRDIFF_TYPE__ long int
+__WCHAR_TYPE__ int
+__WINT_TYPE__ unsigned int
+__INTMAX_TYPE__ long int
+__UINTMAX_TYPE__ long unsigned int
+__CHAR16_TYPE__ short unsigned int
+__CHAR32_TYPE__ unsigned int
+__SIG_ATOMIC_TYPE__ int
+__INT8_TYPE__ signed char
+__INT16_TYPE__ short int
+__INT32_TYPE__ int
+__INT64_TYPE__ long int
+__UINT8_TYPE__ unsigned char
+__UINT16_TYPE__ short unsigned int
+__UINT32_TYPE__ unsigned int
+__UINT64_TYPE__ long unsigned int
+__INT_LEAST8_TYPE__ signed char
+__INT_LEAST16_TYPE__ short int
+__INT_LEAST32_TYPE__ int
+__INT_LEAST64_TYPE__ long int
+__UINT_LEAST8_TYPE__ unsigned char
+__UINT_LEAST16_TYPE__ short unsigned int
+__UINT_LEAST32_TYPE__ unsigned int
+__UINT_LEAST64_TYPE__ long unsigned int
+__INT_FAST8_TYPE__ signed char
+__INT_FAST16_TYPE__ long int
+__INT_FAST32_TYPE__ long int
+__INT_FAST64_TYPE__ long int
+__UINT_FAST8_TYPE__ unsigned char
+__UINT_FAST16_TYPE__ long unsigned int
+__UINT_FAST32_TYPE__ long unsigned int
+__UINT_FAST64_TYPE__ long unsigned int
+__INTPTR_TYPE__ long int
+__UINTPTR_TYPE__ long unsigned int
+__GXX_WEAK__ 1
+__DEPRECATED 1
+__GXX_RTTI 1
+__cpp_rtti 199711L
+__GXX_EXPERIMENTAL_CXX0X__ 1
+__cpp_binary_literals 201304L
+__cpp_hex_float 201603L
+__cpp_runtime_arrays 198712L
+__cpp_raw_strings 200710L
+__cpp_unicode_literals 200710L
+__cpp_user_defined_literals 200809L
+__cpp_lambdas 200907L
+__cpp_decltype 200707L
+__cpp_attributes 200809L
+__cpp_rvalue_reference 200610L
+__cpp_rvalue_references 200610L
+__cpp_variadic_templates 200704L
+__cpp_initializer_lists 200806L
+__cpp_delegating_constructors 200604L
+__cpp_nsdmi 200809L
+__cpp_inheriting_constructors 201511L
+__cpp_ref_qualifiers 200710L
+__cpp_alias_templates 200704L
+__cpp_return_type_deduction 201304L
+__cpp_init_captures 201304L
+__cpp_generic_lambdas 201304L
+__cpp_decltype_auto 201304L
+__cpp_aggregate_nsdmi 201304L
+__cpp_variable_templates 201304L
+__cpp_digit_separators 201309L
+__cpp_unicode_characters 201411L
+__cpp_static_assert 201411L
+__cpp_namespace_attributes 201411L
+__cpp_enumerator_attributes 201411L
+__cpp_nested_namespace_definitions 201411L
+__cpp_fold_expressions 201603L
+__cpp_nontype_template_args 201411L
+__cpp_range_based_for 201603L
+__cpp_constexpr 201603L
+__cpp_if_constexpr 201606L
+__cpp_capture_star_this 201603L
+__cpp_inline_variables 201606L
+__cpp_aggregate_bases 201603L
+__cpp_deduction_guides 201703L
+__cpp_noexcept_function_type 201510L
+__cpp_template_auto 201606L
+__cpp_structured_bindings 201606L
+__cpp_variadic_using 201611L
+__cpp_guaranteed_copy_elision 201606L
+__cpp_nontype_template_parameter_auto 201606L
+__cpp_sized_deallocation 201309L
+__cpp_aligned_new 201606L
+__STDCPP_DEFAULT_NEW_ALIGNMENT__ 16
+__cpp_template_template_args 201611L
+__cpp_threadsafe_static_init 200806L
+__STDCPP_THREADS__ 1
+__EXCEPTIONS 1
+__cpp_exceptions 199711L
+__GXX_ABI_VERSION 1019
+__SCHAR_MAX__ 0x7f
+__SHRT_MAX__ 0x7fff
+__INT_MAX__ 0x7fffffff
+__LONG_MAX__ 0x7fffffffffffffffL
+__LONG_LONG_MAX__ 0x7fffffffffffffffLL
+__WCHAR_MAX__ 0x7fffffff
+__WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+__WINT_MAX__ 0xffffffffU
+__WINT_MIN__ 0U
+__PTRDIFF_MAX__ 0x7fffffffffffffffL
+__SIZE_MAX__ 0xffffffffffffffffUL
+__SCHAR_WIDTH__ 8
+__SHRT_WIDTH__ 16
+__INT_WIDTH__ 32
+__LONG_WIDTH__ 64
+__LONG_LONG_WIDTH__ 64
+__WCHAR_WIDTH__ 32
+__WINT_WIDTH__ 32
+__PTRDIFF_WIDTH__ 64
+__SIZE_WIDTH__ 64
+__GLIBCXX_TYPE_INT_N_0 __int128
+__GLIBCXX_BITSIZE_INT_N_0 128
+__INTMAX_MAX__ 0x7fffffffffffffffL
+__INTMAX_C(c) c ## L
+__UINTMAX_MAX__ 0xffffffffffffffffUL
+__UINTMAX_C(c) c ## UL
+__INTMAX_WIDTH__ 64
+__SIG_ATOMIC_MAX__ 0x7fffffff
+__SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+__SIG_ATOMIC_WIDTH__ 32
+__INT8_MAX__ 0x7f
+__INT16_MAX__ 0x7fff
+__INT32_MAX__ 0x7fffffff
+__INT64_MAX__ 0x7fffffffffffffffL
+__UINT8_MAX__ 0xff
+__UINT16_MAX__ 0xffff
+__UINT32_MAX__ 0xffffffffU
+__UINT64_MAX__ 0xffffffffffffffffUL
+__INT_LEAST8_MAX__ 0x7f
+__INT8_C(c) c
+__INT_LEAST8_WIDTH__ 8
+__INT_LEAST16_MAX__ 0x7fff
+__INT16_C(c) c
+__INT_LEAST16_WIDTH__ 16
+__INT_LEAST32_MAX__ 0x7fffffff
+__INT32_C(c) c
+__INT_LEAST32_WIDTH__ 32
+__INT_LEAST64_MAX__ 0x7fffffffffffffffL
+__INT64_C(c) c ## L
+__INT_LEAST64_WIDTH__ 64
+__UINT_LEAST8_MAX__ 0xff
+__UINT8_C(c) c
+__UINT_LEAST16_MAX__ 0xffff
+__UINT16_C(c) c
+__UINT_LEAST32_MAX__ 0xffffffffU
+__UINT32_C(c) c ## U
+__UINT_LEAST64_MAX__ 0xffffffffffffffffUL
+__UINT64_C(c) c ## UL
+__INT_FAST8_MAX__ 0x7f
+__INT_FAST8_WIDTH__ 8
+__INT_FAST16_MAX__ 0x7fffffffffffffffL
+__INT_FAST16_WIDTH__ 64
+__INT_FAST32_MAX__ 0x7fffffffffffffffL
+__INT_FAST32_WIDTH__ 64
+__INT_FAST64_MAX__ 0x7fffffffffffffffL
+__INT_FAST64_WIDTH__ 64
+__UINT_FAST8_MAX__ 0xff
+__UINT_FAST16_MAX__ 0xffffffffffffffffUL
+__UINT_FAST32_MAX__ 0xffffffffffffffffUL
+__UINT_FAST64_MAX__ 0xffffffffffffffffUL
+__INTPTR_MAX__ 0x7fffffffffffffffL
+__INTPTR_WIDTH__ 64
+__UINTPTR_MAX__ 0xffffffffffffffffUL
+__GCC_IEC_559 2
+__GCC_IEC_559_COMPLEX 2
+__FLT_EVAL_METHOD__ 0
+__FLT_EVAL_METHOD_TS_18661_3__ 0
+__DEC_EVAL_METHOD__ 2
+__FLT_RADIX__ 2
+__FLT_MANT_DIG__ 24
+__FLT_DIG__ 6
+__FLT_MIN_EXP__ (-125)
+__FLT_MIN_10_EXP__ (-37)
+__FLT_MAX_EXP__ 128
+__FLT_MAX_10_EXP__ 38
+__FLT_DECIMAL_DIG__ 9
+__FLT_MAX__ 3.40282346638528859811704183484516925e+38F
+__FLT_NORM_MAX__ 3.40282346638528859811704183484516925e+38F
+__FLT_MIN__ 1.17549435082228750796873653722224568e-38F
+__FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F
+__FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F
+__FLT_HAS_DENORM__ 1
+__FLT_HAS_INFINITY__ 1
+__FLT_HAS_QUIET_NAN__ 1
+__FLT_IS_IEC_60559__ 1
+__DBL_MANT_DIG__ 53
+__DBL_DIG__ 15
+__DBL_MIN_EXP__ (-1021)
+__DBL_MIN_10_EXP__ (-307)
+__DBL_MAX_EXP__ 1024
+__DBL_MAX_10_EXP__ 308
+__DBL_DECIMAL_DIG__ 17
+__DBL_MAX__ double(1.79769313486231570814527423731704357e+308L)
+__DBL_NORM_MAX__ double(1.79769313486231570814527423731704357e+308L)
+__DBL_MIN__ double(2.22507385850720138309023271733240406e-308L)
+__DBL_EPSILON__ double(2.22044604925031308084726333618164062e-16L)
+__DBL_DENORM_MIN__ double(4.94065645841246544176568792868221372e-324L)
+__DBL_HAS_DENORM__ 1
+__DBL_HAS_INFINITY__ 1
+__DBL_HAS_QUIET_NAN__ 1
+__DBL_IS_IEC_60559__ 1
+__LDBL_MANT_DIG__ 64
+__LDBL_DIG__ 18
+__LDBL_MIN_EXP__ (-16381)
+__LDBL_MIN_10_EXP__ (-4931)
+__LDBL_MAX_EXP__ 16384
+__LDBL_MAX_10_EXP__ 4932
+__DECIMAL_DIG__ 21
+__LDBL_DECIMAL_DIG__ 21
+__LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L
+__LDBL_NORM_MAX__ 1.18973149535723176502126385303097021e+4932L
+__LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L
+__LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L
+__LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L
+__LDBL_HAS_DENORM__ 1
+__LDBL_HAS_INFINITY__ 1
+__LDBL_HAS_QUIET_NAN__ 1
+__LDBL_IS_IEC_60559__ 1
+__FLT16_MANT_DIG__ 11
+__FLT16_DIG__ 3
+__FLT16_MIN_EXP__ (-13)
+__FLT16_MIN_10_EXP__ (-4)
+__FLT16_MAX_EXP__ 16
+__FLT16_MAX_10_EXP__ 4
+__FLT16_DECIMAL_DIG__ 5
+__FLT16_MAX__ 6.55040000000000000000000000000000000e+4F16
+__FLT16_NORM_MAX__ 6.55040000000000000000000000000000000e+4F16
+__FLT16_MIN__ 6.10351562500000000000000000000000000e-5F16
+__FLT16_EPSILON__ 9.76562500000000000000000000000000000e-4F16
+__FLT16_DENORM_MIN__ 5.96046447753906250000000000000000000e-8F16
+__FLT16_HAS_DENORM__ 1
+__FLT16_HAS_INFINITY__ 1
+__FLT16_HAS_QUIET_NAN__ 1
+__FLT16_IS_IEC_60559__ 1
+__FLT32_MANT_DIG__ 24
+__FLT32_DIG__ 6
+__FLT32_MIN_EXP__ (-125)
+__FLT32_MIN_10_EXP__ (-37)
+__FLT32_MAX_EXP__ 128
+__FLT32_MAX_10_EXP__ 38
+__FLT32_DECIMAL_DIG__ 9
+__FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32
+__FLT32_NORM_MAX__ 3.40282346638528859811704183484516925e+38F32
+__FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32
+__FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32
+__FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32
+__FLT32_HAS_DENORM__ 1
+__FLT32_HAS_INFINITY__ 1
+__FLT32_HAS_QUIET_NAN__ 1
+__FLT32_IS_IEC_60559__ 1
+__FLT64_MANT_DIG__ 53
+__FLT64_DIG__ 15
+__FLT64_MIN_EXP__ (-1021)
+__FLT64_MIN_10_EXP__ (-307)
+__FLT64_MAX_EXP__ 1024
+__FLT64_MAX_10_EXP__ 308
+__FLT64_DECIMAL_DIG__ 17
+__FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64
+__FLT64_NORM_MAX__ 1.79769313486231570814527423731704357e+308F64
+__FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64
+__FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64
+__FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64
+__FLT64_HAS_DENORM__ 1
+__FLT64_HAS_INFINITY__ 1
+__FLT64_HAS_QUIET_NAN__ 1
+__FLT64_IS_IEC_60559__ 1
+__FLT128_MANT_DIG__ 113
+__FLT128_DIG__ 33
+__FLT128_MIN_EXP__ (-16381)
+__FLT128_MIN_10_EXP__ (-4931)
+__FLT128_MAX_EXP__ 16384
+__FLT128_MAX_10_EXP__ 4932
+__FLT128_DECIMAL_DIG__ 36
+__FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128
+__FLT128_NORM_MAX__ 1.18973149535723176508575932662800702e+4932F128
+__FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128
+__FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128
+__FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128
+__FLT128_HAS_DENORM__ 1
+__FLT128_HAS_INFINITY__ 1
+__FLT128_HAS_QUIET_NAN__ 1
+__FLT128_IS_IEC_60559__ 1
+__FLT32X_MANT_DIG__ 53
+__FLT32X_DIG__ 15
+__FLT32X_MIN_EXP__ (-1021)
+__FLT32X_MIN_10_EXP__ (-307)
+__FLT32X_MAX_EXP__ 1024
+__FLT32X_MAX_10_EXP__ 308
+__FLT32X_DECIMAL_DIG__ 17
+__FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x
+__FLT32X_NORM_MAX__ 1.79769313486231570814527423731704357e+308F32x
+__FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x
+__FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x
+__FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x
+__FLT32X_HAS_DENORM__ 1
+__FLT32X_HAS_INFINITY__ 1
+__FLT32X_HAS_QUIET_NAN__ 1
+__FLT32X_IS_IEC_60559__ 1
+__FLT64X_MANT_DIG__ 64
+__FLT64X_DIG__ 18
+__FLT64X_MIN_EXP__ (-16381)
+__FLT64X_MIN_10_EXP__ (-4931)
+__FLT64X_MAX_EXP__ 16384
+__FLT64X_MAX_10_EXP__ 4932
+__FLT64X_DECIMAL_DIG__ 21
+__FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+__FLT64X_NORM_MAX__ 1.18973149535723176502126385303097021e+4932F64x
+__FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x
+__FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x
+__FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x
+__FLT64X_HAS_DENORM__ 1
+__FLT64X_HAS_INFINITY__ 1
+__FLT64X_HAS_QUIET_NAN__ 1
+__FLT64X_IS_IEC_60559__ 1
+__BFLT16_MANT_DIG__ 8
+__BFLT16_DIG__ 2
+__BFLT16_MIN_EXP__ (-125)
+__BFLT16_MIN_10_EXP__ (-37)
+__BFLT16_MAX_EXP__ 128
+__BFLT16_MAX_10_EXP__ 38
+__BFLT16_DECIMAL_DIG__ 4
+__BFLT16_MAX__ 3.38953138925153547590470800371487867e+38BF16
+__BFLT16_NORM_MAX__ 3.38953138925153547590470800371487867e+38BF16
+__BFLT16_MIN__ 1.17549435082228750796873653722224568e-38BF16
+__BFLT16_EPSILON__ 7.81250000000000000000000000000000000e-3BF16
+__BFLT16_DENORM_MIN__ 9.18354961579912115600575419704879436e-41BF16
+__BFLT16_HAS_DENORM__ 1
+__BFLT16_HAS_INFINITY__ 1
+__BFLT16_HAS_QUIET_NAN__ 1
+__BFLT16_IS_IEC_60559__ 0
+__DEC32_MANT_DIG__ 7
+__DEC32_MIN_EXP__ (-94)
+__DEC32_MAX_EXP__ 97
+__DEC32_MIN__ 1E-95DF
+__DEC32_MAX__ 9.999999E96DF
+__DEC32_EPSILON__ 1E-6DF
+__DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+__DEC64_MANT_DIG__ 16
+__DEC64_MIN_EXP__ (-382)
+__DEC64_MAX_EXP__ 385
+__DEC64_MIN__ 1E-383DD
+__DEC64_MAX__ 9.999999999999999E384DD
+__DEC64_EPSILON__ 1E-15DD
+__DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+__DEC128_MANT_DIG__ 34
+__DEC128_MIN_EXP__ (-6142)
+__DEC128_MAX_EXP__ 6145
+__DEC128_MIN__ 1E-6143DL
+__DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+__DEC128_EPSILON__ 1E-33DL
+__DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+__REGISTER_PREFIX__ 
+__USER_LABEL_PREFIX__ 
+__GNUC_STDC_INLINE__ 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+__GCC_ATOMIC_BOOL_LOCK_FREE 2
+__GCC_ATOMIC_CHAR_LOCK_FREE 2
+__GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+__GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+__GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+__GCC_ATOMIC_SHORT_LOCK_FREE 2
+__GCC_ATOMIC_INT_LOCK_FREE 2
+__GCC_ATOMIC_LONG_LOCK_FREE 2
+__GCC_ATOMIC_LLONG_LOCK_FREE 2
+__GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+__GCC_DESTRUCTIVE_SIZE 64
+__GCC_CONSTRUCTIVE_SIZE 64
+__GCC_ATOMIC_POINTER_LOCK_FREE 2
+__HAVE_SPECULATION_SAFE_VALUE 1
+__GCC_HAVE_DWARF2_CFI_ASM 1
+__PRAGMA_REDEFINE_EXTNAME 1
+__SIZEOF_INT128__ 16
+__SIZEOF_WCHAR_T__ 4
+__SIZEOF_WINT_T__ 4
+__SIZEOF_PTRDIFF_T__ 8
+__amd64 1
+__amd64__ 1
+__x86_64 1
+__x86_64__ 1
+__SIZEOF_FLOAT80__ 16
+__SIZEOF_FLOAT128__ 16
+__ATOMIC_HLE_ACQUIRE 65536
+__ATOMIC_HLE_RELEASE 131072
+__GCC_ASM_FLAG_OUTPUTS__ 1
+__k8 1
+__k8__ 1
+__code_model_small__ 1
+__MMX__ 1
+__SSE__ 1
+__SSE2__ 1
+__FXSR__ 1
+__SSE_MATH__ 1
+__SSE2_MATH__ 1
+__MMX_WITH_SSE__ 1
+__SEG_FS 1
+__SEG_GS 1
+__gnu_linux__ 1
+__linux 1
+__linux__ 1
+linux 1
+__unix 1
+__unix__ 1
+unix 1
+__ELF__ 1
+__DECIMAL_BID_FORMAT__ 1
+_GNU_SOURCE 1
+file /home/osandov/src/elfutils/tests/main.cc
+ file /usr/include/stdc-predef.h
+  _STDC_PREDEF_H 1
+  __STDC_IEC_559__ 1
+  __STDC_IEC_60559_BFP__ 201404L
+  __STDC_IEC_559_COMPLEX__ 1
+  __STDC_IEC_60559_COMPLEX__ 201404L
+  __STDC_ISO_10646__ 201706L
+ /file
+ file /home/osandov/src/elfutils/tests/foobar.h
+  FROB(x) ((x) ^ 0x2a2a2a2a)
+  FRY(x) ((x) * 0x100000001b3)
+ /file
+ MAIN_ARGS int argc, char **argv
+/file
+EOF
+done
+
+exit 0
diff --git a/tests/run-dwarf-getstring.sh b/tests/run-dwarf-getstring.sh
new file mode 100755
index 0000000..f18f628
--- /dev/null
+++ b/tests/run-dwarf-getstring.sh
@@ -0,0 +1,125 @@
+#! /bin/sh
+# Copyright (C) 2011 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile11
+
+testrun_compare ${abs_builddir}/dwarf-getstring testfile11 <<\EOF
+_ZNSbIwSt11char_traitsIwESaIwEE13_S_copy_charsEPwS3_S3_
+itimerspec
+_G_int32_t
+_IO_last_state
+antiquities
+_ZNSbIwSt11char_traitsIwESaIwEEpLEw
+insert
+_ZNSbIwSt11char_traitsIwESaIwEE12_M_leak_hardEv
+__lockkind
+_ZNKSbIwSt11char_traitsIwESaIwEE8capacityEv
+_ZNSs7_M_leakEv
+_M_ref_count
+_ZNSt11char_traitsIwE6assignEPwjw
+_ZNKSs13find_first_ofEPKcj
+._14
+._15
+._16
+._17
+_ZNKSs16find_last_not_ofEPKcj
+_G_iconv_t
+_ZN10__gnu_test9gnu_obj_2IlEaSERKS1_
+_ZN11random_dataaSERKS_
+_ZNSt11char_traitsIcE7not_eofERKi
+__class_type_info
+tm_sec
+_ZNKSbIwSt11char_traitsIwESaIwEE5c_strEv
+__rlim64_t
+seek
+pthread_mutex_t
+_ZNSs5eraseEN9__gnu_cxx17__normal_iteratorIPcSsEE
+_ZNSsaSEc
+__not_va_list__
+_ZNKSs12find_last_ofEPKcj
+_ZNSs7replaceEN9__gnu_cxx17__normal_iteratorIPcSsEES2_S2_S2_
+__gconv_info
+_ZNSt11__ios_flags12_S_showpointE
+output_iterator_tag
+gnu_obj_2<long int>
+_ZNSs6insertEjRKSsjj
+_ZN13__type_traitsIbEaSERKS0_
+_ZNKSbIwSt11char_traitsIwESaIwEE4copyEPwjj
+_ZNSs9_M_mutateEjjj
+__ios_flags
+short unsigned int
+_ZNKSs4findEPKcj
+compare
+_ZNSbIwSt11char_traitsIwESaIwEE4_Rep7_M_grabERKS1_S5_
+tm_yday
+unsigned char
+__stacksize
+__gconv_init_fct
+_IO_FILE
+__counter
+._26
+._27
+bidirectional_iterator_tag
+._29
+it_value
+const_iterator
+_ZNSt11__ios_flags6_S_outE
+_M_set_leaked
+_Is_integer<unsigned int>
+__value
+timeval
+_IO_jump_t
+_ZN11sched_paramaSERKS_
+__normal_iterator<char*,std::basic_string<char, std::char_traits<char>, std::allocator<char> > >
+_ZNSs4_Rep7_M_grabERKSaIcES2_
+_wide_vtable
+__codecvt_destr
+_STL_mutex_lock
+_ZNSt24__default_alloc_templateILb1ELi0EE17_S_freelist_indexEj
+_ZNSbIwSt11char_traitsIwESaIwEE7replaceEjjjw
+_ZN17__gconv_step_dataaSERKS_
+__w_stopval
+__int64_t
+__type_traits<double>
+~_Lock
+_ZNKSbIwSt11char_traitsIwESaIwEE5beginEv
+ptrdiff_t
+test
+_Integral
+cookie_seek_function_t
+__vmi_class_type_info
+_ZNSs7replaceEjjjc
+__int32_t
+register_t
+~_STL_auto_lock
+_ZNKSbIwSt11char_traitsIwESaIwEE16find_last_not_ofEPKwjj
+__arg
+_ZNSs7replaceEjjPKcj
+_ZNSbIwSt11char_traitsIwESaIwEE7replaceEjjRKS2_jj
+_ZNKSbIwSt11char_traitsIwESaIwEE12find_last_ofEPKwjj
+_ZN11_Is_integerImEaSERKS0_
+__default_alloc_template
+_S_hex
+__statep
+_ZNSt11char_traitsIwE2ltERKwS2_
+_M_p
+_ZNKSs4sizeEv
+EOF
+
+exit 0
diff --git a/tests/run-dwarf-ranges.sh b/tests/run-dwarf-ranges.sh
new file mode 100755
index 0000000..ae25d6e
--- /dev/null
+++ b/tests/run-dwarf-ranges.sh
@@ -0,0 +1,126 @@
+#! /bin/sh
+# Copyright (C) 2015, 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles debug-ranges-no-lowpc.o
+
+testrun_compare ${abs_builddir}/dwarf-ranges debug-ranges-no-lowpc.o 0xb <<\EOF
+1..2 (base 0)
+3..4 (base 0)
+EOF
+
+# - hello.c
+# int say (const char *prefix);
+#
+# char *
+# subject (char *word, int count)
+# {
+#    return count > 0 ? word : (word + count);
+# }
+#
+# int
+# main (int argc, char **argv)
+# {
+#    return say (subject (argv[0], argc));
+# }
+#
+# int
+# no_say (const char *prefix)
+# {
+#   const char *world = subject ("World", 42);
+#   return prefix ? say (prefix) : say (world);
+# }
+#
+# - world.c
+# char * subject (char *word, int count);
+# int no_say (const char *prefix);
+#
+# static int
+# sad (char c)
+# {
+#   return c > 0 ? c : c + 1;
+# }
+#
+# static int
+# happy (const char *w)
+# {
+#   return sad (w[1]);
+# }
+#
+# int
+# say (const char *prefix)
+# {
+#   const char *world = subject ("World", 42);;
+#   return prefix ? sad (prefix[0]) : happy (world);
+# }
+#
+# char *
+# no_subject (char *word, int count)
+# {
+#    return count > 0 ? word : (word + count);
+# }
+#
+# int
+# no_main (int argc, char **argv)
+# {
+#    return no_say (no_subject (argv[0], argc));
+# }
+#
+# - gcc -c -O2 -gdwarf-4 hello.c
+# - gcc -c -O2 -gdwarf-4 world.c
+# - gcc -o testfileranges4 -O2 -gdwarf-4 hello.o world.o
+# - eu-strip -f testfileranges4.debug testfileranges4
+
+testfiles testfileranges4.debug
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges4.debug 0xb <<\EOF
+400500..40053a (base 0)
+400400..400415 (base 0)
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges4.debug 0xcd <<\EOF
+400400..400402 (base 0)
+400405..40040d (base 0)
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges4.debug 0x374 <<\EOF
+4005a0..4005a2 (base 400540)
+4005a5..4005ad (base 400540)
+EOF
+
+# Like above, but with -gdwarf-5.
+testfiles testfileranges5.debug
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0xc <<\EOF
+401150..40117a (base 0)
+401050..401067 (base 0)
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0x2ce <<\EOF
+40119b..40119b (base 401180)
+40119c..4011a6 (base 401180)
+4011b0..4011b4 (base 401180)
+4011b5..4011bf (base 401180)
+EOF
+
+testrun_compare ${abs_builddir}/dwarf-ranges testfileranges5.debug 0x2ef <<\EOF
+40119b..40119b (base 401180)
+40119c..4011a6 (base 401180)
+4011b4..4011b4 (base 401180)
+4011b5..4011bf (base 401180)
+EOF
+
+exit 0
diff --git a/tests/run-dwarfcfi.sh b/tests/run-dwarfcfi.sh
new file mode 100755
index 0000000..98fa171
--- /dev/null
+++ b/tests/run-dwarfcfi.sh
@@ -0,0 +1,133 @@
+#! /bin/sh
+# Test for dwarf_getcfi.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Test files come from run-addrcfi with all sections stripped except
+# the .debug_frame.
+# for i in <testfiles>
+#   eu-strip -f $i-debugframe $i
+#   eu-strip -g --remove-comment --keep-section=.debug_frame $i-debugframe
+# done
+testfiles testfile11-debugframe testfile12-debugframe
+testfiles testfileaarch64-debugframe
+testfiles testfilearm-debugframe
+testfiles testfileppc32-debugframe
+testfiles testfileppc64-debugframe
+
+testfiles testfile11-debugframe
+testrun_compare ${abs_builddir}/dwarfcfi testfile11-debugframe 0x080489b8 <<\EOF
+0x80489b8 => [0x80489b8, 0x80489b9):
+	return address in reg8
+	CFA location expression: bregx(4,4)
+	reg0: undefined
+	reg1: undefined
+	reg2: undefined
+	reg3: same_value
+	reg4: location expression: call_frame_cfa stack_value
+	reg5: same_value
+	reg6: same_value
+	reg7: same_value
+	reg8: location expression: call_frame_cfa plus_uconst(-4)
+	reg9: undefined
+EOF
+
+testfiles testfile12-debugframe
+testrun_compare ${abs_builddir}/dwarfcfi testfile12-debugframe 0x00000000000009d0 <<\EOF
+0x9d0 => [0x9d0, 0x9d1):
+	return address in reg16
+	CFA location expression: bregx(7,8)
+	reg0: same_value
+	reg1: undefined
+	reg2: undefined
+	reg3: undefined
+	reg4: undefined
+	reg5: undefined
+	reg6: same_value
+	reg7: location expression: call_frame_cfa stack_value
+	reg8: undefined
+	reg9: undefined
+EOF
+
+testfiles testfileppc32-debugframe
+testrun_compare ${abs_builddir}/dwarfcfi testfileppc32-debugframe 0x100004c0 <<\EOF
+0x100004c0 => [0x100004c0, 0x100004d0):
+	return address in reg65
+	CFA location expression: bregx(1)
+	reg0: undefined
+	reg1: location expression: call_frame_cfa stack_value
+	reg2: same_value
+	reg3: undefined
+	reg4: undefined
+	reg5: undefined
+	reg6: undefined
+	reg7: undefined
+	reg8: undefined
+	reg9: undefined
+EOF
+
+testfiles testfileppc64-debugframe
+testrun_compare ${abs_builddir}/dwarfcfi testfileppc64-debugframe 0x00000000100005b0 <<\EOF
+0x100005b0 => [0x100005b0, 0x100005d0):
+	return address in reg65
+	CFA location expression: bregx(1)
+	reg0: undefined
+	reg1: location expression: call_frame_cfa stack_value
+	reg2: same_value
+	reg3: undefined
+	reg4: undefined
+	reg5: undefined
+	reg6: undefined
+	reg7: undefined
+	reg8: undefined
+	reg9: undefined
+EOF
+
+testfiles testfilearm-debugframe
+testrun_compare ${abs_builddir}/dwarfcfi testfilearm-debugframe 0x00008510 <<\EOF
+0x8510 => [0x8510, 0x8524):
+	return address in reg14
+	CFA location expression: bregx(13)
+	reg0: undefined
+	reg1: undefined
+	reg2: undefined
+	reg3: undefined
+	reg4: same_value
+	reg5: same_value
+	reg6: same_value
+	reg7: same_value
+	reg8: same_value
+	reg9: undefined
+EOF
+
+testfiles testfileaarch64-debugframe
+testrun_compare ${abs_builddir}/dwarfcfi testfileaarch64-debugframe 0x400550 <<\EOF
+0x400550 => [0x400550, 0x400568):
+	return address in reg30
+	CFA location expression: bregx(31)
+	reg0: undefined
+	reg1: undefined
+	reg2: undefined
+	reg3: undefined
+	reg4: undefined
+	reg5: undefined
+	reg6: undefined
+	reg7: undefined
+	reg8: undefined
+	reg9: undefined
+EOF
diff --git a/tests/run-dwelf_elf_e_machine_string.sh b/tests/run-dwelf_elf_e_machine_string.sh
new file mode 100755
index 0000000..658f229
--- /dev/null
+++ b/tests/run-dwelf_elf_e_machine_string.sh
@@ -0,0 +1,31 @@
+#! /usr/bin/env bash
+# Test to make sure all EM values in elf.h are recognized
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Get all known EM values from elf.h and pass them through the
+# preprocessor to get the numbers. Call dwelf_elf_e_machine_string on
+# all of them.
+EM_VALUES=$(grep ^\#define\ EM_ ${abs_srcdir}/../libelf/elf.h \
+            | cut -f2 -d\  | cut -f1 | grep -v ^EM_NUM$ | xargs echo)
+# echo "EM_VALUES: $EM_VALUES"
+EM_NUMBERS=$((cat ${abs_srcdir}/../libelf/elf.h; echo "$EM_VALUES") \
+             | gcc -E - | tail -1)
+# echo "EM_NUMBERS: $EM_NUMBERS"
+
+testrun ${abs_top_builddir}/tests/dwelf_elf_e_machine_string $EM_NUMBERS
diff --git a/tests/run-dwelfgnucompressed.sh b/tests/run-dwelfgnucompressed.sh
new file mode 100755
index 0000000..b93a56f
--- /dev/null
+++ b/tests/run-dwelfgnucompressed.sh
@@ -0,0 +1,108 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# = funcs.s =
+# .globl testfunc
+# testfunc:
+# 	nop
+# 	ret
+# .type testfunc, @function
+# .size testfunc, .-testfunc
+#
+# .globl testfunc2
+# testfunc2:
+# 	call testfunc
+# 	nop
+# 	nop
+# 	ret
+# .type testfunc2, @function
+# .size testfunc2, .-testfunc2
+#
+# .globl functest3
+# functest3:
+# 	jmp local
+# 	nop
+# 	nop
+# local:
+# 	call testfunc2
+# 	ret
+# .type functest3, @function
+# .size functest3, .-functest3
+
+# = start.s =
+# .global _start
+# _start:
+# 	call functest3
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	ret
+# .type _start, @function
+# .size _start, .-_start
+
+# gas --compress-debug-sections=zlib-gnu -32 -g -o start.o start.s
+# gas --compress-debug-sections=zlib-gnu -32 -g -o funcs.o funcs.s
+# ld --compress-debug-sections=zlib-gnu -melf_i386 -g -o zgnu32 funcs.o start.o
+
+# gas --compress-debug-sections=zlib-gnu -64 -g -o start.o start.s
+# gas --compress-debug-sections=zlib-gnu -64 -g -o funcs.o funcs.s
+# ld --compress-debug-sections=zlib-gnu -g -o zgnu32 funcs.o start.o
+
+testfiles testfile-zgnu64
+testrun_compare ${abs_top_builddir}/tests/dwelfgnucompressed testfile-zgnu64 <<\EOF
+section 2: GNU Compressed size: 60
+section 3: GNU Compressed size: aa
+section 5: GNU Compressed size: 8d
+EOF
+
+testfiles testfile-zgnu64be
+testrun_compare ${abs_top_builddir}/tests/dwelfgnucompressed testfile-zgnu64be <<\EOF
+section 3: GNU Compressed size: 60
+section 4: GNU Compressed size: 7e
+section 6: GNU Compressed size: 8d
+EOF
+
+testfiles testfile-zgnu32
+testrun_compare ${abs_top_builddir}/tests/dwelfgnucompressed testfile-zgnu32 <<\EOF
+section 2: GNU Compressed size: 40
+section 3: GNU Compressed size: 9a
+section 5: GNU Compressed size: 85
+EOF
+
+testfiles testfile-zgnu32be
+testrun_compare ${abs_top_builddir}/tests/dwelfgnucompressed testfile-zgnu32be <<\EOF
+section 3: GNU Compressed size: 40
+section 4: GNU Compressed size: 6e
+section 6: GNU Compressed size: 85
+EOF
+
+exit 0
diff --git a/tests/run-dwfl-addr-sect.sh b/tests/run-dwfl-addr-sect.sh
new file mode 100755
index 0000000..80da008
--- /dev/null
+++ b/tests/run-dwfl-addr-sect.sh
@@ -0,0 +1,32 @@
+#! /bin/sh
+# Copyright (C) 2007-2009 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile43 testfile50
+
+testrun_compare ${abs_builddir}/dwfl-addr-sect -e testfile43 0x64 0x8 0x98 <<\EOF
+address 0x64 => module "" section 4 + 0
+address 0x8 => module "" section 1 + 0x8
+address 0x98 => module "" section 7 + 0
+EOF
+
+testrun_compare ${abs_builddir}/dwfl-addr-sect -e testfile50 0x1 <<\EOF
+address 0x1 => module "" section 1 + 0x1
+EOF
+
+exit 0
diff --git a/tests/run-dwfl-bug-offline-rel.sh b/tests/run-dwfl-bug-offline-rel.sh
new file mode 100755
index 0000000..fa476c4
--- /dev/null
+++ b/tests/run-dwfl-bug-offline-rel.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# Copyright (C) 2007 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile36 testfile36.debug
+
+testrun_compare ${abs_builddir}/dwflmodtest -e testfile36 <<\EOF
+module:                                00000000..00002308 testfile36 (null)
+module:                                00000000 DWARF 0 (no error)
+module:                                00000000..00002308 testfile36 testfile36.debug
+EOF
+
+exit 0
diff --git a/tests/run-dwfl-core-noncontig.sh b/tests/run-dwfl-core-noncontig.sh
new file mode 100755
index 0000000..1245b67
--- /dev/null
+++ b/tests/run-dwfl-core-noncontig.sh
@@ -0,0 +1,63 @@
+#! /bin/sh
+# Copyright (C) 2023 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Test whether libdwfl can handle corefiles containing non-contiguous
+# segments where multiple modules are contained within the address
+# space of some other module.
+
+# testcore-noncontig was generated from the following program with
+# systemd-coredump on RHEL 7.9 Workstation, kernel
+# 3.10.0-1160.105.1.el7.x86_64. liblgpllibs.so was packaged with
+# firefox-115.4.0-1.el7_9.x86_64.rpm.
+
+# #include <unistd.h>
+# #include <dlfcn.h>
+#
+# int main () {
+#   dlopen ("/usr/lib64/firefox/liblgpllibs.so", RTLD_GLOBAL | RTLD_NOW);
+#   sleep (60);
+#   return 0;
+# }
+#
+# gcc -ldl -o test test.c
+
+tempfiles out
+testfiles testcore-noncontig
+
+testrun ${abs_builddir}/dwfl-core-noncontig testcore-noncontig
+
+# Remove parts of the output that could change depending on which
+# libraries are locally installed.
+testrun ${abs_top_builddir}/src/unstrip -n --core testcore-noncontig \
+  | sed 's/+/ /g' | cut -d " " -f1,3 | sort > out
+
+testrun_compare cat out <<\EOF
+0x400000 3a1748a544b40a38b3be3d2d13ffa34a2a5a71c0@0x400284
+0x7f14e357e000 edf51350c7f71496149d064aa8b1441f786df88a@0x7f14e357e1d8
+0x7f14e3794000 7615604eaf4a068dfae5085444d15c0dee93dfbd@0x7f14e37941d8
+0x7f14e3a96000 09cfb171310110bc7ea9f4476c9fa044d85baff4@0x7f14e3a96210
+0x7f14e3d9e000 e10cc8f2b932fc3daeda22f8dac5ebb969524e5b@0x7f14e3d9e248
+0x7f14e3fba000 fc4fa58e47a5acc137eadb7689bce4357c557a96@0x7f14e3fba280
+0x7f14e4388000 7f2e9cb0769d7e57bd669b485a74b537b63a57c4@0x7f14e43881d8
+0x7f14e458c000 62c449974331341bb08dcce3859560a22af1e172@0x7f14e458c1d8
+0x7f14e4795000 175efdcef445455872a86a6fbee7567ca16a513e@0x7f14e4795248
+0x7ffcfe59f000 80d79b32785868a2dc10047b39a80d1daec8923d@0x7ffcfe59f328
+EOF
+
+exit 0
diff --git a/tests/run-dwfl-report-elf-align.sh b/tests/run-dwfl-report-elf-align.sh
new file mode 100755
index 0000000..3849753
--- /dev/null
+++ b/tests/run-dwfl-report-elf-align.sh
@@ -0,0 +1,44 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile-dwfl-report-elf-align-shlib.so
+
+# /proc/PID/maps when the process was running:
+# 7f3560c92000-7f3560c93000 r-xp 00000000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so
+# 7f3560c93000-7f3560e92000 ---p 00001000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so
+# 7f3560e92000-7f3560e93000 rw-p 00000000 fd:02 25037063 testfile-dwfl-report-elf-align-shlib.so
+# testfile-dwfl-report-elf-align-shlib.so:
+# Program Headers:
+#   Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+#   LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x00065c 0x00065c R E 0x200000
+#   LOAD           0x000660 0x0000000000200660 0x0000000000200660 0x0001f0 0x000200 RW  0x200000
+# Symbol table '.dynsym' contains 12 entries:
+#    Num:    Value          Size Type    Bind   Vis      Ndx Name
+#      8: 000000000000057c    11 FUNC    GLOBAL DEFAULT   11 shlib
+# GDB output showing proper relocation:
+# #1  0x00007f3560c92585 in shlib () from ./testfile-dwfl-report-elf-align-shlib.so
+#
+# 0x7f3560c92000 is VMA address of first byte of testfile-dwfl-report-elf-align-shlib.so.
+# 0x7f3560c92585 = 0x7f3560c92000 + 0x585
+# where 0x585 is any address inside the shlib function: 0x57c .. 0x57c + 11 -1
+
+testrun ${abs_builddir}/dwfl-report-elf-align ./testfile-dwfl-report-elf-align-shlib.so \
+				0x7f3560c92000 0x7f3560c92585 shlib
+
+exit 0
diff --git a/tests/run-dwfl-report-offline-memory.sh b/tests/run-dwfl-report-offline-memory.sh
new file mode 100755
index 0000000..84c7f99
--- /dev/null
+++ b/tests/run-dwfl-report-offline-memory.sh
@@ -0,0 +1,33 @@
+#! /bin/sh
+# Copyright (C) 2022 Google LLC
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile-dwfl-report-elf-align-shlib.so
+testfiles testarchive64.a
+
+# echo "int _start(void) { return 0; }" > test.c
+# gcc test.c -nostdlib -static -o test.o
+# ar -r test-ar-duplicates.a test.o test.o test.o
+# bzip2 -zf test-ar-duplicates.a
+testfiles test-ar-duplicates.a
+
+testrun ${abs_builddir}/dwfl-report-offline-memory ./testfile-dwfl-report-elf-align-shlib.so 1 24
+testrun ${abs_builddir}/dwfl-report-offline-memory ./testarchive64.a 3 10
+testrun ${abs_builddir}/dwfl-report-offline-memory ./test-ar-duplicates.a 1 7
+
+exit 0
diff --git a/tests/run-dwfllines.sh b/tests/run-dwfllines.sh
new file mode 100755
index 0000000..b384de0
--- /dev/null
+++ b/tests/run-dwfllines.sh
@@ -0,0 +1,88 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/dwfllines -e testfile <<\EOF
+mod:  CU: [b] m.c
+0 0x804842c /home/drepper/gnu/new-bu/build/ttt/m.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+1 0x8048432 /home/drepper/gnu/new-bu/build/ttt/m.c:6:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+2 0x804844d /home/drepper/gnu/new-bu/build/ttt/m.c:7:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+3 0x8048458 /home/drepper/gnu/new-bu/build/ttt/m.c:8:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+4 0x804845a /home/drepper/gnu/new-bu/build/ttt/m.c:8:0
+ time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+mod:  CU: [ca] b.c
+0 0x804845c /home/drepper/gnu/new-bu/build/ttt/b.c:4:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+1 0x804845f /home/drepper/gnu/new-bu/build/ttt/b.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+2 0x8048464 /home/drepper/gnu/new-bu/build/ttt/b.c:6:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+3 0x8048466 /home/drepper/gnu/new-bu/build/ttt/b.c:6:0
+ time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+mod:  CU: [15fc] f.c
+0 0x8048468 /home/drepper/gnu/new-bu/build/ttt/f.c:3:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+1 0x804846b /home/drepper/gnu/new-bu/build/ttt/f.c:4:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+2 0x8048470 /home/drepper/gnu/new-bu/build/ttt/f.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+3 0x8048472 /home/drepper/gnu/new-bu/build/ttt/f.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+EOF
+
+testrun_compare ${abs_builddir}/dwfllines -e testfile2 <<\EOF
+mod:  CU: [b] b.c
+0 0x10000470 /shoggoth/drepper/b.c:4:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+1 0x1000047c /shoggoth/drepper/b.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+2 0x10000480 /shoggoth/drepper/b.c:6:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+3 0x10000490 /shoggoth/drepper/b.c:6:0
+ time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+mod:  CU: [97d] f.c
+0 0x10000490 /shoggoth/drepper/f.c:3:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+1 0x1000049c /shoggoth/drepper/f.c:4:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+2 0x100004a0 /shoggoth/drepper/f.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+3 0x100004b0 /shoggoth/drepper/f.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+mod:  CU: [9e4] m.c
+0 0x100004b0 /shoggoth/drepper/m.c:5:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+1 0x100004cc /shoggoth/drepper/m.c:6:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+2 0x100004e8 /shoggoth/drepper/m.c:7:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+3 0x100004f4 /shoggoth/drepper/m.c:8:0
+ time: 0, len: 0, idx: 0, b: 1, e: 0, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+4 0x10000514 /shoggoth/drepper/m.c:8:0
+ time: 0, len: 0, idx: 0, b: 1, e: 1, pe: 0, eb: 0, block: 0, isa: 0, disc: 0
+EOF
+
+testrun_on_self_quiet ${abs_builddir}/dwfllines -e
+
+exit 0
diff --git a/tests/run-dwflsyms.sh b/tests/run-dwflsyms.sh
new file mode 100755
index 0000000..9726bcf
--- /dev/null
+++ b/tests/run-dwflsyms.sh
@@ -0,0 +1,826 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Tests dwfl_module_{addrsym,getsym,relocate_address}
+# See run-readelf-s.sh for how to generate test binaries.
+# In addition, *_pl files were created from their base file
+# with prelink -N, and *_plr with prelink -r 0x4200000000.
+
+testfiles testfilebaztab
+testfiles testfilebazdbg testfilebazdbg.debug
+testfiles testfilebazdbg_pl
+testfiles testfilebazdbg_plr
+testfiles testfilebazdyn
+testfiles testfilebazmdb
+testfiles testfilebazmin
+testfiles testfilebazmin_pl
+testfiles testfilebazmin_plr
+testfiles testfilebasmin
+testfiles testfilebaxmin
+
+tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in dwflsyms.out
+tempfiles testfile.symtab_pl.in testfile.minsym_pl.in 
+
+cat > testfile.symtab.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x238
+   2: SECTION	LOCAL	 (0) 0x254
+   3: SECTION	LOCAL	 (0) 0x274
+   4: SECTION	LOCAL	 (0) 0x298
+   5: SECTION	LOCAL	 (0) 0x2d8
+   6: SECTION	LOCAL	 (0) 0x428
+   7: SECTION	LOCAL	 (0) 0x4f2
+   8: SECTION	LOCAL	 (0) 0x510
+   9: SECTION	LOCAL	 (0) 0x530
+  10: SECTION	LOCAL	 (0) 0x638
+  11: SECTION	LOCAL	 (0) 0x680
+  12: SECTION	LOCAL	 (0) 0x6a0
+  13: SECTION	LOCAL	 (0) 0x6e0
+  14: SECTION	LOCAL	 (0) 0x8f4
+  15: SECTION	LOCAL	 (0) 0x900
+  16: SECTION	LOCAL	 (0) 0x904
+  17: SECTION	LOCAL	 (0) 0x948
+  18: SECTION	LOCAL	 (0) 0x200dd0
+  19: SECTION	LOCAL	 (0) 0x200dd8
+  20: SECTION	LOCAL	 (0) 0x200de0
+  21: SECTION	LOCAL	 (0) 0x200de8
+  22: SECTION	LOCAL	 (0) 0x200df0
+  23: SECTION	LOCAL	 (0) 0x200fc0
+  24: SECTION	LOCAL	 (0) 0x201000
+  25: SECTION	LOCAL	 (0) 0x201030
+  26: SECTION	LOCAL	 (0) 0x20103c
+  27: SECTION	LOCAL	 (0) 0
+  28: SECTION	LOCAL	 (0) 0
+  29: SECTION	LOCAL	 (0) 0
+  30: SECTION	LOCAL	 (0) 0
+  31: SECTION	LOCAL	 (0) 0
+  32: SECTION	LOCAL	 (0) 0
+  33: FILE	LOCAL	crtstuff.c (0) 0
+  34: OBJECT	LOCAL	__JCR_LIST__ (0) 0x200de0
+  35: FUNC	LOCAL	deregister_tm_clones (0) 0x710, rel: 0x710 (.text)
+  36: FUNC	LOCAL	register_tm_clones (0) 0x740, rel: 0x740 (.text)
+  37: FUNC	LOCAL	__do_global_dtors_aux (0) 0x780, rel: 0x780 (.text)
+  38: OBJECT	LOCAL	completed.6137 (1) 0x20103c
+  39: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x200dd8
+  40: FUNC	LOCAL	frame_dummy (0) 0x7c0, rel: 0x7c0 (.text)
+  41: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x200dd0
+  42: FILE	LOCAL	foo.c (0) 0
+  43: FILE	LOCAL	bar.c (0) 0
+  44: OBJECT	LOCAL	b1 (4) 0x201034
+  45: FUNC	LOCAL	foo (20) 0x814, rel: 0x814 (.text)
+  46: FILE	LOCAL	crtstuff.c (0) 0
+  47: OBJECT	LOCAL	__FRAME_END__ (0) 0xa58
+  48: OBJECT	LOCAL	__JCR_END__ (0) 0x200de0
+  49: FILE	LOCAL	 (0) 0
+  50: NOTYPE	LOCAL	__init_array_end (0) 0x200dd8
+  51: OBJECT	LOCAL	_DYNAMIC (0) 0x200df0
+  52: NOTYPE	LOCAL	__init_array_start (0) 0x200dd0
+  53: OBJECT	LOCAL	_GLOBAL_OFFSET_TABLE_ (0) 0x201000
+  54: FUNC	GLOBAL	__libc_csu_fini (2) 0x8f0, rel: 0x8f0 (.text)
+  55: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  56: NOTYPE	WEAK	data_start (0) 0x201030
+  57: NOTYPE	GLOBAL	_edata (0) 0x20103c
+  58: FUNC	GLOBAL	bar (44) 0x828, rel: 0x828 (.text)
+  59: FUNC	GLOBAL	_fini (0) 0x8f4, rel: 0x8f4 (.fini)
+  60: FUNC	GLOBAL	__libc_start_main@@GLIBC_2.2.5 (0) 0
+  61: NOTYPE	GLOBAL	__data_start (0) 0x201030
+  62: NOTYPE	WEAK	__gmon_start__ (0) 0
+  63: OBJECT	GLOBAL	__dso_handle (0) 0x200de8
+  64: OBJECT	GLOBAL	_IO_stdin_used (4) 0x900
+  65: OBJECT	GLOBAL	b2 (4) 0x201038
+  66: FUNC	GLOBAL	__libc_csu_init (137) 0x860, rel: 0x860 (.text)
+  67: NOTYPE	GLOBAL	_end (0) 0x201040
+  68: FUNC	GLOBAL	_start (0) 0x6e0, rel: 0x6e0 (.text)
+  69: NOTYPE	GLOBAL	__bss_start (0) 0x20103c
+  70: FUNC	GLOBAL	main (35) 0x7f0, rel: 0x7f0 (.text)
+  71: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  72: OBJECT	GLOBAL	__TMC_END__ (0) 0x201040
+  73: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  74: FUNC	WEAK	__cxa_finalize@@GLIBC_2.2.5 (0) 0
+  75: FUNC	GLOBAL	_init (0) 0x680, rel: 0x680 (.init)
+EOF
+
+cat > testfile.symtab_pl.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x3000000238
+   2: SECTION	LOCAL	 (0) 0x3000000254
+   3: SECTION	LOCAL	 (0) 0x3000000274
+   4: SECTION	LOCAL	 (0) 0x3000000298
+   5: SECTION	LOCAL	 (0) 0x30000002d8
+   6: SECTION	LOCAL	 (0) 0x3000000428
+   7: SECTION	LOCAL	 (0) 0x30000004f2
+   8: SECTION	LOCAL	 (0) 0x3000000510
+   9: SECTION	LOCAL	 (0) 0x3000000530
+  10: SECTION	LOCAL	 (0) 0x3000000638
+  11: SECTION	LOCAL	 (0) 0x3000000680
+  12: SECTION	LOCAL	 (0) 0x30000006a0
+  13: SECTION	LOCAL	 (0) 0x30000006e0
+  14: SECTION	LOCAL	 (0) 0x30000008f4
+  15: SECTION	LOCAL	 (0) 0x3000000900
+  16: SECTION	LOCAL	 (0) 0x3000000904
+  17: SECTION	LOCAL	 (0) 0x3000000948
+  18: SECTION	LOCAL	 (0) 0x3000200dd0
+  19: SECTION	LOCAL	 (0) 0x3000200dd8
+  20: SECTION	LOCAL	 (0) 0x3000200de0
+  21: SECTION	LOCAL	 (0) 0x3000200de8
+  22: SECTION	LOCAL	 (0) 0x3000200df0
+  23: SECTION	LOCAL	 (0) 0x3000200fc0
+  24: SECTION	LOCAL	 (0) 0x3000201000
+  25: SECTION	LOCAL	 (0) 0x3000201030
+  26: SECTION	LOCAL	 (0) 0x300020103c
+  27: SECTION	LOCAL	 (0) 0
+  28: SECTION	LOCAL	 (0) 0
+  29: SECTION	LOCAL	 (0) 0
+  30: SECTION	LOCAL	 (0) 0
+  31: SECTION	LOCAL	 (0) 0
+  32: SECTION	LOCAL	 (0) 0
+  33: FILE	LOCAL	crtstuff.c (0) 0
+  34: OBJECT	LOCAL	__JCR_LIST__ (0) 0x3000200de0
+  35: FUNC	LOCAL	deregister_tm_clones (0) 0x3000000710, rel: 0x710 (.text)
+  36: FUNC	LOCAL	register_tm_clones (0) 0x3000000740, rel: 0x740 (.text)
+  37: FUNC	LOCAL	__do_global_dtors_aux (0) 0x3000000780, rel: 0x780 (.text)
+  38: OBJECT	LOCAL	completed.6137 (1) 0x300020103c
+  39: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x3000200dd8
+  40: FUNC	LOCAL	frame_dummy (0) 0x30000007c0, rel: 0x7c0 (.text)
+  41: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x3000200dd0
+  42: FILE	LOCAL	foo.c (0) 0
+  43: FILE	LOCAL	bar.c (0) 0
+  44: OBJECT	LOCAL	b1 (4) 0x3000201034
+  45: FUNC	LOCAL	foo (20) 0x3000000814, rel: 0x814 (.text)
+  46: FILE	LOCAL	crtstuff.c (0) 0
+  47: OBJECT	LOCAL	__FRAME_END__ (0) 0x3000000a58
+  48: OBJECT	LOCAL	__JCR_END__ (0) 0x3000200de0
+  49: FILE	LOCAL	 (0) 0
+  50: NOTYPE	LOCAL	__init_array_end (0) 0x3000200dd8
+  51: OBJECT	LOCAL	_DYNAMIC (0) 0x3000200df0
+  52: NOTYPE	LOCAL	__init_array_start (0) 0x3000200dd0
+  53: OBJECT	LOCAL	_GLOBAL_OFFSET_TABLE_ (0) 0x3000201000
+  54: FUNC	GLOBAL	__libc_csu_fini (2) 0x30000008f0, rel: 0x8f0 (.text)
+  55: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  56: NOTYPE	WEAK	data_start (0) 0x3000201030
+  57: NOTYPE	GLOBAL	_edata (0) 0x300020103c
+  58: FUNC	GLOBAL	bar (44) 0x3000000828, rel: 0x828 (.text)
+  59: FUNC	GLOBAL	_fini (0) 0x30000008f4, rel: 0x8f4 (.fini)
+  60: FUNC	GLOBAL	__libc_start_main@@GLIBC_2.2.5 (0) 0
+  61: NOTYPE	GLOBAL	__data_start (0) 0x3000201030
+  62: NOTYPE	WEAK	__gmon_start__ (0) 0
+  63: OBJECT	GLOBAL	__dso_handle (0) 0x3000200de8
+  64: OBJECT	GLOBAL	_IO_stdin_used (4) 0x3000000900
+  65: OBJECT	GLOBAL	b2 (4) 0x3000201038
+  66: FUNC	GLOBAL	__libc_csu_init (137) 0x3000000860, rel: 0x860 (.text)
+  67: NOTYPE	GLOBAL	_end (0) 0x3000201040
+  68: FUNC	GLOBAL	_start (0) 0x30000006e0, rel: 0x6e0 (.text)
+  69: NOTYPE	GLOBAL	__bss_start (0) 0x300020103c
+  70: FUNC	GLOBAL	main (35) 0x30000007f0, rel: 0x7f0 (.text)
+  71: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  72: OBJECT	GLOBAL	__TMC_END__ (0) 0x3000201040
+  73: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  74: FUNC	WEAK	__cxa_finalize@@GLIBC_2.2.5 (0) 0
+  75: FUNC	GLOBAL	_init (0) 0x3000000680, rel: 0x680 (.init)
+EOF
+
+cat > testfile.dynsym.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x238
+   2: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+   3: FUNC	GLOBAL	__libc_start_main (0) 0
+   4: NOTYPE	WEAK	__gmon_start__ (0) 0
+   5: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+   6: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+   7: FUNC	WEAK	__cxa_finalize (0) 0
+   8: NOTYPE	GLOBAL	_edata (0) 0x20103c
+   9: NOTYPE	GLOBAL	_end (0) 0x201040
+  10: FUNC	GLOBAL	__libc_csu_init (137) 0x860, rel: 0x860 (.text)
+  11: NOTYPE	GLOBAL	__bss_start (0) 0x20103c
+  12: FUNC	GLOBAL	main (35) 0x7f0, rel: 0x7f0 (.text)
+  13: FUNC	GLOBAL	__libc_csu_fini (2) 0x8f0, rel: 0x8f0 (.text)
+EOF
+
+cat > testfile.minsym.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x238
+   2: FUNC	LOCAL	deregister_tm_clones (0) 0x710, rel: 0x710 (.text)
+   3: FUNC	LOCAL	register_tm_clones (0) 0x740, rel: 0x740 (.text)
+   4: FUNC	LOCAL	__do_global_dtors_aux (0) 0x780, rel: 0x780 (.text)
+   5: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x200dd8
+   6: FUNC	LOCAL	frame_dummy (0) 0x7c0, rel: 0x7c0 (.text)
+   7: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x200dd0
+   8: FUNC	LOCAL	foo (20) 0x814, rel: 0x814 (.text)
+   9: NOTYPE	LOCAL	__init_array_end (0) 0x200dd8
+  10: NOTYPE	LOCAL	__init_array_start (0) 0x200dd0
+  11: SECTION	LOCAL	 (0) 0x238
+  12: SECTION	LOCAL	 (0) 0x254
+  13: SECTION	LOCAL	 (0) 0x274
+  14: SECTION	LOCAL	 (0) 0x298
+  15: SECTION	LOCAL	 (0) 0x2d8
+  16: SECTION	LOCAL	 (0) 0x428
+  17: SECTION	LOCAL	 (0) 0x4f2
+  18: SECTION	LOCAL	 (0) 0x510
+  19: SECTION	LOCAL	 (0) 0x530
+  20: SECTION	LOCAL	 (0) 0x638
+  21: SECTION	LOCAL	 (0) 0x680
+  22: SECTION	LOCAL	 (0) 0x6a0
+  23: SECTION	LOCAL	 (0) 0x6e0
+  24: SECTION	LOCAL	 (0) 0x8f4
+  25: SECTION	LOCAL	 (0) 0x900
+  26: SECTION	LOCAL	 (0) 0x904
+  27: SECTION	LOCAL	 (0) 0x948
+  28: SECTION	LOCAL	 (0) 0x200dd0
+  29: SECTION	LOCAL	 (0) 0x200dd8
+  30: SECTION	LOCAL	 (0) 0x200de0
+  31: SECTION	LOCAL	 (0) 0x200de8
+  32: SECTION	LOCAL	 (0) 0x200df0
+  33: SECTION	LOCAL	 (0) 0x200fc0
+  34: SECTION	LOCAL	 (0) 0x201000
+  35: SECTION	LOCAL	 (0) 0x201030
+  36: SECTION	LOCAL	 (0) 0x20103c
+  37: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  38: FUNC	GLOBAL	__libc_start_main (0) 0
+  39: NOTYPE	WEAK	__gmon_start__ (0) 0
+  40: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  41: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  42: FUNC	WEAK	__cxa_finalize (0) 0
+  43: NOTYPE	GLOBAL	_edata (0) 0x20103c
+  44: NOTYPE	GLOBAL	_end (0) 0x201040
+  45: FUNC	GLOBAL	__libc_csu_init (137) 0x860, rel: 0x860 (.text)
+  46: NOTYPE	GLOBAL	__bss_start (0) 0x20103c
+  47: FUNC	GLOBAL	main (35) 0x7f0, rel: 0x7f0 (.text)
+  48: FUNC	GLOBAL	__libc_csu_fini (2) 0x8f0, rel: 0x8f0 (.text)
+  49: FUNC	GLOBAL	bar (44) 0x828, rel: 0x828 (.text)
+  50: FUNC	GLOBAL	_fini (0) 0x8f4, rel: 0x8f4 (.fini)
+  51: FUNC	GLOBAL	_start (0) 0x6e0, rel: 0x6e0 (.text)
+  52: FUNC	GLOBAL	_init (0) 0x680, rel: 0x680 (.init)
+EOF
+
+cat > testfile.minsym_pl.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x3000000238
+   2: FUNC	LOCAL	deregister_tm_clones (0) 0x3000000710, rel: 0x710 (.text)
+   3: FUNC	LOCAL	register_tm_clones (0) 0x3000000740, rel: 0x740 (.text)
+   4: FUNC	LOCAL	__do_global_dtors_aux (0) 0x3000000780, rel: 0x780 (.text)
+   5: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x3000200dd8
+   6: FUNC	LOCAL	frame_dummy (0) 0x30000007c0, rel: 0x7c0 (.text)
+   7: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x3000200dd0
+   8: FUNC	LOCAL	foo (20) 0x3000000814, rel: 0x814 (.text)
+   9: NOTYPE	LOCAL	__init_array_end (0) 0x3000200dd8
+  10: NOTYPE	LOCAL	__init_array_start (0) 0x3000200dd0
+  11: SECTION	LOCAL	 (0) 0x3000000238
+  12: SECTION	LOCAL	 (0) 0x3000000254
+  13: SECTION	LOCAL	 (0) 0x3000000274
+  14: SECTION	LOCAL	 (0) 0x3000000298
+  15: SECTION	LOCAL	 (0) 0x30000002d8
+  16: SECTION	LOCAL	 (0) 0x3000000428
+  17: SECTION	LOCAL	 (0) 0x30000004f2
+  18: SECTION	LOCAL	 (0) 0x3000000510
+  19: SECTION	LOCAL	 (0) 0x3000000530
+  20: SECTION	LOCAL	 (0) 0x3000000638
+  21: SECTION	LOCAL	 (0) 0x3000000680
+  22: SECTION	LOCAL	 (0) 0x30000006a0
+  23: SECTION	LOCAL	 (0) 0x30000006e0
+  24: SECTION	LOCAL	 (0) 0x30000008f4
+  25: SECTION	LOCAL	 (0) 0x3000000900
+  26: SECTION	LOCAL	 (0) 0x3000000904
+  27: SECTION	LOCAL	 (0) 0x3000000948
+  28: SECTION	LOCAL	 (0) 0x3000200dd0
+  29: SECTION	LOCAL	 (0) 0x3000200dd8
+  30: SECTION	LOCAL	 (0) 0x3000200de0
+  31: SECTION	LOCAL	 (0) 0x3000200de8
+  32: SECTION	LOCAL	 (0) 0x3000200df0
+  33: SECTION	LOCAL	 (0) 0x3000200fc0
+  34: SECTION	LOCAL	 (0) 0x3000201000
+  35: SECTION	LOCAL	 (0) 0x3000201030
+  36: SECTION	LOCAL	 (0) 0x300020103c
+  37: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  38: FUNC	GLOBAL	__libc_start_main (0) 0
+  39: NOTYPE	WEAK	__gmon_start__ (0) 0
+  40: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  41: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  42: FUNC	WEAK	__cxa_finalize (0) 0
+  43: NOTYPE	GLOBAL	_edata (0) 0x300020103c
+  44: NOTYPE	GLOBAL	_end (0) 0x3000201040
+  45: FUNC	GLOBAL	__libc_csu_init (137) 0x3000000860, rel: 0x860 (.text)
+  46: NOTYPE	GLOBAL	__bss_start (0) 0x300020103c
+  47: FUNC	GLOBAL	main (35) 0x30000007f0, rel: 0x7f0 (.text)
+  48: FUNC	GLOBAL	__libc_csu_fini (2) 0x30000008f0, rel: 0x8f0 (.text)
+  49: FUNC	GLOBAL	bar (44) 0x3000000828, rel: 0x828 (.text)
+  50: FUNC	GLOBAL	_fini (0) 0x30000008f4, rel: 0x8f4 (.fini)
+  51: FUNC	GLOBAL	_start (0) 0x30000006e0, rel: 0x6e0 (.text)
+  52: FUNC	GLOBAL	_init (0) 0x3000000680, rel: 0x680 (.init)
+EOF
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebaztab
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg
+
+cat testfile.symtab_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg_pl
+
+sed s/0x3000/0x4200/g testfile.symtab_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbg_plr
+
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdyn
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmdb
+
+cat testfile.minsym.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin
+
+cat testfile.minsym_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin_pl
+
+sed s/0x3000/0x4200/g testfile.minsym_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmin_plr
+
+testrun_compare ${abs_builddir}/dwflsyms -e testfilebasmin <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: FUNC	LOCAL	foo (18) 0x400168, rel: 0x400168 (.text)
+   2: SECTION	LOCAL	 (0) 0x400120
+   3: SECTION	LOCAL	 (0) 0x400144
+   4: SECTION	LOCAL	 (0) 0x4001c0
+   5: SECTION	LOCAL	 (0) 0x600258
+   6: FUNC	GLOBAL	_start (21) 0x4001a8, rel: 0x4001a8 (.text)
+   7: FUNC	GLOBAL	main (33) 0x400144, rel: 0x400144 (.text)
+   8: FUNC	GLOBAL	bar (44) 0x40017a, rel: 0x40017a (.text)
+EOF
+
+testrun_compare ${abs_builddir}/dwflsyms -e testfilebaxmin <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: FUNC	LOCAL	deregister_tm_clones (0) 0x400430, rel: 0x400430 (.text)
+   2: FUNC	LOCAL	register_tm_clones (0) 0x400460, rel: 0x400460 (.text)
+   3: FUNC	LOCAL	__do_global_dtors_aux (0) 0x4004a0, rel: 0x4004a0 (.text)
+   4: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x600e18
+   5: FUNC	LOCAL	frame_dummy (0) 0x4004c0, rel: 0x4004c0 (.text)
+   6: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x600e10
+   7: FUNC	LOCAL	foo (20) 0x4004f0, rel: 0x4004f0 (.text)
+   8: NOTYPE	LOCAL	__init_array_end (0) 0x600e18
+   9: NOTYPE	LOCAL	__init_array_start (0) 0x600e10
+  10: SECTION	LOCAL	 (0) 0x400238
+  11: SECTION	LOCAL	 (0) 0x400254
+  12: SECTION	LOCAL	 (0) 0x400274
+  13: SECTION	LOCAL	 (0) 0x400298
+  14: SECTION	LOCAL	 (0) 0x4002b8
+  15: SECTION	LOCAL	 (0) 0x400300
+  16: SECTION	LOCAL	 (0) 0x400338
+  17: SECTION	LOCAL	 (0) 0x400340
+  18: SECTION	LOCAL	 (0) 0x400360
+  19: SECTION	LOCAL	 (0) 0x400378
+  20: SECTION	LOCAL	 (0) 0x4003a8
+  21: SECTION	LOCAL	 (0) 0x4003d0
+  22: SECTION	LOCAL	 (0) 0x400400
+  23: SECTION	LOCAL	 (0) 0x4005c4
+  24: SECTION	LOCAL	 (0) 0x4005d0
+  25: SECTION	LOCAL	 (0) 0x4005e0
+  26: SECTION	LOCAL	 (0) 0x400628
+  27: SECTION	LOCAL	 (0) 0x600e10
+  28: SECTION	LOCAL	 (0) 0x600e18
+  29: SECTION	LOCAL	 (0) 0x600e20
+  30: SECTION	LOCAL	 (0) 0x600e28
+  31: SECTION	LOCAL	 (0) 0x600ff8
+  32: SECTION	LOCAL	 (0) 0x601000
+  33: SECTION	LOCAL	 (0) 0x601028
+  34: SECTION	LOCAL	 (0) 0x601034
+  35: FUNC	GLOBAL	__libc_start_main (0) 0
+  36: NOTYPE	WEAK	__gmon_start__ (0) 0
+  37: FUNC	GLOBAL	__libc_csu_fini (2) 0x4005c0, rel: 0x4005c0 (.text)
+  38: FUNC	GLOBAL	bar (40) 0x400504, rel: 0x400504 (.text)
+  39: FUNC	GLOBAL	_fini (0) 0x4005c4, rel: 0x4005c4 (.fini)
+  40: FUNC	GLOBAL	__libc_csu_init (101) 0x400550, rel: 0x400550 (.text)
+  41: FUNC	GLOBAL	_start (0) 0x400400, rel: 0x400400 (.text)
+  42: FUNC	GLOBAL	main (35) 0x40052c, rel: 0x40052c (.text)
+  43: FUNC	GLOBAL	_init (0) 0x4003a8, rel: 0x4003a8 (.init)
+EOF
+
+testfiles testfile66
+testrun_compare ${abs_builddir}/dwflsyms -e testfile66 <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x190
+   2: SECTION	LOCAL	 (0) 0x1a4
+   3: SECTION	LOCAL	 (0) 0x1c8
+   4: SECTION	LOCAL	 (0) 0x1f8
+   5: SECTION	LOCAL	 (0) 0x288
+   6: SECTION	LOCAL	 (0) 0x2a8
+   7: SECTION	LOCAL	 (0) 0x2d8
+   8: SECTION	LOCAL	 (0) 0x102e0
+   9: SECTION	LOCAL	 (0) 0x103d0
+  10: SECTION	LOCAL	 (0) 0x103e8
+  11: SECTION	LOCAL	 (0) 0x103e8
+  12: OBJECT	LOCAL	_DYNAMIC (0) 0x102e0
+  13: FUNC	GLOBAL	_start (4) 0x103d0, rel: 0x103d0 (.opd) [0x2d8, rel: 0 (.text)]
+  14: NOTYPE	GLOBAL	__bss_start (0) 0x103f0
+  15: NOTYPE	GLOBAL	_edata (0) 0x103f0
+  16: NOTYPE	GLOBAL	_end (0) 0x103f0
+EOF
+
+testfiles testfile66.core
+testrun_compare ${abs_builddir}/dwflsyms -e testfile66 --core=testfile66.core <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0xfffb1af0410
+   2: NOTYPE	GLOBAL	__kernel_datapage_offset (0) 0xfffb1af05dc
+   3: OBJECT	GLOBAL	LINUX_2.6.15 (0) 0
+   4: NOTYPE	GLOBAL	__kernel_clock_getres (64) 0xfffb1af052c
+   5: NOTYPE	GLOBAL	__kernel_get_tbfreq (24) 0xfffb1af0620
+   6: NOTYPE	GLOBAL	__kernel_gettimeofday (84) 0xfffb1af0440
+   7: NOTYPE	GLOBAL	__kernel_sync_dicache (20) 0xfffb1af06c4
+   8: NOTYPE	GLOBAL	__kernel_sync_dicache_p5 (20) 0xfffb1af06c4
+   9: NOTYPE	GLOBAL	__kernel_sigtramp_rt64 (12) 0xfffb1af0418
+  10: NOTYPE	GLOBAL	__kernel_clock_gettime (152) 0xfffb1af0494
+  11: NOTYPE	GLOBAL	__kernel_get_syscall_map (44) 0xfffb1af05f4
+ld64.so.1: Callback returned failure
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x461b0190
+   2: SECTION	LOCAL	 (0) 0x461b01a4
+   3: SECTION	LOCAL	 (0) 0x461b01c8
+   4: SECTION	LOCAL	 (0) 0x461b01f8
+   5: SECTION	LOCAL	 (0) 0x461b0288
+   6: SECTION	LOCAL	 (0) 0x461b02a8
+   7: SECTION	LOCAL	 (0) 0x461b02d8
+   8: SECTION	LOCAL	 (0) 0x461c02e0
+   9: SECTION	LOCAL	 (0) 0x461c03d0
+  10: SECTION	LOCAL	 (0) 0x461c03e8
+  11: SECTION	LOCAL	 (0) 0x461c03e8
+  12: OBJECT	LOCAL	_DYNAMIC (0) 0x102e0
+  13: FUNC	GLOBAL	_start (4) 0x461c03d0, rel: 0x103d0 (.opd) [0x461b02d8, rel: 0 (.text)]
+  14: NOTYPE	GLOBAL	__bss_start (0) 0x103f0
+  15: NOTYPE	GLOBAL	_edata (0) 0x103f0
+  16: NOTYPE	GLOBAL	_end (0) 0x103f0
+EOF
+
+# Test the already present dot-prefixed names do not get duplicated.
+testfiles hello_ppc64.ko
+testrun_compare ${abs_builddir}/dwflsyms -e hello_ppc64.ko <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0
+   2: SECTION	LOCAL	 (0) 0x94
+   3: SECTION	LOCAL	 (0) 0xba
+   4: SECTION	LOCAL	 (0) 0xd0
+   5: SECTION	LOCAL	 (0) 0x13a
+   6: SECTION	LOCAL	 (0) 0x13a
+   7: SECTION	LOCAL	 (0) 0x150
+   8: SECTION	LOCAL	 (0) 0x170
+   9: SECTION	LOCAL	 (0) 0x188
+  10: SECTION	LOCAL	 (0) 0x410
+  11: SECTION	LOCAL	 (0) 0x434
+  12: SECTION	LOCAL	 (0) 0x438
+  13: SECTION	LOCAL	 (0) 0x438
+  14: SECTION	LOCAL	 (0) 0
+  15: SECTION	LOCAL	 (0) 0
+  16: SECTION	LOCAL	 (0) 0
+  17: SECTION	LOCAL	 (0) 0
+  18: SECTION	LOCAL	 (0) 0
+  19: SECTION	LOCAL	 (0) 0
+  20: SECTION	LOCAL	 (0) 0
+  21: SECTION	LOCAL	 (0) 0
+  22: SECTION	LOCAL	 (0) 0
+  23: SECTION	LOCAL	 (0) 0
+  24: FILE	LOCAL	init.c (0) 0
+  25: FILE	LOCAL	exit.c (0) 0
+  26: FILE	LOCAL	hello.mod.c (0) 0
+  27: OBJECT	LOCAL	__mod_srcversion23 (35) 0xd0
+  28: OBJECT	LOCAL	__module_depends (9) 0xf8
+  29: OBJECT	LOCAL	__mod_vermagic5 (50) 0x108
+  30: OBJECT	GLOBAL	__this_module (648) 0x188
+  31: FUNC	GLOBAL	.cleanup_module (72) 0x4c, rel: 0x4c (.text)
+  32: FUNC	GLOBAL	cleanup_module (24) 0x160, rel: 0x10 (.opd)
+  33: NOTYPE	GLOBAL	.printk (0) 0
+  34: FUNC	GLOBAL	init_module (24) 0x150, rel: 0 (.opd)
+  35: NOTYPE	GLOBAL	._mcount (0) 0
+  36: FUNC	GLOBAL	.init_module (76) 0, rel: 0 (.text)
+  37: NOTYPE	GLOBAL	_mcount (0) 0
+EOF
+
+# Same test files as above, but now generated on ppc64.
+# ppc64 uses function descriptors to make things more "interesting".
+
+testfiles testfilebaztabppc64
+testfiles testfilebazdbgppc64 testfilebazdbgppc64.debug
+testfiles testfilebazdbgppc64_pl
+testfiles testfilebazdbgppc64_plr
+testfiles testfilebazdynppc64
+testfiles testfilebazmdbppc64
+testfiles testfilebazminppc64
+testfiles testfilebazminppc64_pl
+testfiles testfilebazminppc64_plr
+
+cat > testfile.symtab.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x238
+   2: SECTION	LOCAL	 (0) 0x24c
+   3: SECTION	LOCAL	 (0) 0x26c
+   4: SECTION	LOCAL	 (0) 0x290
+   5: SECTION	LOCAL	 (0) 0x2c0
+   6: SECTION	LOCAL	 (0) 0x3e0
+   7: SECTION	LOCAL	 (0) 0x488
+   8: SECTION	LOCAL	 (0) 0x4a0
+   9: SECTION	LOCAL	 (0) 0x4c0
+  10: SECTION	LOCAL	 (0) 0x820
+  11: SECTION	LOCAL	 (0) 0x850
+  12: SECTION	LOCAL	 (0) 0x8a0
+  13: SECTION	LOCAL	 (0) 0xd30
+  14: SECTION	LOCAL	 (0) 0xd4c
+  15: SECTION	LOCAL	 (0) 0xd50
+  16: SECTION	LOCAL	 (0) 0xd70
+  17: SECTION	LOCAL	 (0) 0x1fde0
+  18: SECTION	LOCAL	 (0) 0x1fde8
+  19: SECTION	LOCAL	 (0) 0x1fdf0
+  20: SECTION	LOCAL	 (0) 0x1fdf8
+  21: SECTION	LOCAL	 (0) 0x1fe20
+  22: SECTION	LOCAL	 (0) 0x20000
+  23: SECTION	LOCAL	 (0) 0x20010
+  24: SECTION	LOCAL	 (0) 0x200d8
+  25: SECTION	LOCAL	 (0) 0x20110
+  26: SECTION	LOCAL	 (0) 0x20158
+  27: SECTION	LOCAL	 (0) 0
+  28: SECTION	LOCAL	 (0) 0
+  29: SECTION	LOCAL	 (0) 0
+  30: SECTION	LOCAL	 (0) 0
+  31: SECTION	LOCAL	 (0) 0
+  32: SECTION	LOCAL	 (0) 0
+  33: SECTION	LOCAL	 (0) 0
+  34: FILE	LOCAL	crtstuff.c (0) 0
+  35: OBJECT	LOCAL	__JCR_LIST__ (0) 0x1fdf0
+  36: FUNC	LOCAL	deregister_tm_clones (0) 0x20040, rel: 0x20040 (.opd) [0x910, rel: 0x70 (.text)]
+  37: FUNC	LOCAL	register_tm_clones (0) 0x20050, rel: 0x20050 (.opd) [0x980, rel: 0xe0 (.text)]
+  38: FUNC	LOCAL	__do_global_dtors_aux (0) 0x20060, rel: 0x20060 (.opd) [0x9f0, rel: 0x150 (.text)]
+  39: OBJECT	LOCAL	completed.7711 (1) 0x20158
+  40: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x1fde8
+  41: FUNC	LOCAL	frame_dummy (0) 0x20070, rel: 0x20070 (.opd) [0xa50, rel: 0x1b0 (.text)]
+  42: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x1fde0
+  43: FILE	LOCAL	foo.c (0) 0
+  44: FILE	LOCAL	bar.c (0) 0
+  45: OBJECT	LOCAL	b1 (4) 0x20004
+  46: FUNC	LOCAL	foo (76) 0x20090, rel: 0x20090 (.opd) [0xb34, rel: 0x294 (.text)]
+  47: FILE	LOCAL	crtstuff.c (0) 0
+  48: OBJECT	LOCAL	__FRAME_END__ (0) 0xe18
+  49: OBJECT	LOCAL	__JCR_END__ (0) 0x1fdf0
+  50: FILE	LOCAL	 (0) 0
+  51: NOTYPE	LOCAL	__glink_PLTresolve (0) 0xce8
+  52: NOTYPE	LOCAL	00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x8a0
+  53: NOTYPE	LOCAL	00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x8b4
+  54: NOTYPE	LOCAL	__init_array_end (0) 0x1fde8
+  55: OBJECT	LOCAL	_DYNAMIC (0) 0x1fe20
+  56: NOTYPE	LOCAL	__init_array_start (0) 0x1fde0
+  57: FUNC	GLOBAL	__libc_csu_fini (16) 0x200c0, rel: 0x200c0 (.opd) [0xcd0, rel: 0x430 (.text)]
+  58: FUNC	GLOBAL	__libc_start_main@@GLIBC_2.3 (0) 0
+  59: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  60: NOTYPE	WEAK	data_start (0) 0x20000
+  61: NOTYPE	GLOBAL	_edata (0) 0x20110
+  62: FUNC	GLOBAL	bar (116) 0x200a0, rel: 0x200a0 (.opd) [0xb80, rel: 0x2e0 (.text)]
+  63: FUNC	GLOBAL	_fini (0) 0x20030, rel: 0x20030 (.opd) [0xd30, rel: 0 (.fini)]
+  64: NOTYPE	GLOBAL	__data_start (0) 0x20000
+  65: NOTYPE	WEAK	__gmon_start__ (0) 0
+  66: OBJECT	GLOBAL	__dso_handle (0) 0x1fe18
+  67: OBJECT	GLOBAL	_IO_stdin_used (4) 0xd4c
+  68: OBJECT	GLOBAL	b2 (4) 0x20008
+  69: FUNC	WEAK	__cxa_finalize@@GLIBC_2.3 (0) 0
+  70: FUNC	GLOBAL	__libc_csu_init (204) 0x200b0, rel: 0x200b0 (.opd) [0xc00, rel: 0x360 (.text)]
+  71: NOTYPE	GLOBAL	_end (0) 0x20160
+  72: FUNC	GLOBAL	_start (60) 0x20010, rel: 0x20010 (.opd) [0x8c8, rel: 0x28 (.text)]
+  73: NOTYPE	GLOBAL	__bss_start (0) 0x20110
+  74: FUNC	GLOBAL	main (128) 0x20080, rel: 0x20080 (.opd) [0xab4, rel: 0x214 (.text)]
+  75: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  76: OBJECT	GLOBAL	__TMC_END__ (0) 0x20010
+  77: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  78: FUNC	GLOBAL	_init (0) 0x20020, rel: 0x20020 (.opd) [0x850, rel: 0 (.init)]
+EOF
+
+cat > testfile.symtab_pl.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x8001000238
+   2: SECTION	LOCAL	 (0) 0x800100024c
+   3: SECTION	LOCAL	 (0) 0x800100026c
+   4: SECTION	LOCAL	 (0) 0x8001000290
+   5: SECTION	LOCAL	 (0) 0x80010002c0
+   6: SECTION	LOCAL	 (0) 0x80010003e0
+   7: SECTION	LOCAL	 (0) 0x8001000488
+   8: SECTION	LOCAL	 (0) 0x80010004a0
+   9: SECTION	LOCAL	 (0) 0x80010004c0
+  10: SECTION	LOCAL	 (0) 0x8001000820
+  11: SECTION	LOCAL	 (0) 0x8001000850
+  12: SECTION	LOCAL	 (0) 0x80010008a0
+  13: SECTION	LOCAL	 (0) 0x8001000d30
+  14: SECTION	LOCAL	 (0) 0x8001000d4c
+  15: SECTION	LOCAL	 (0) 0x8001000d50
+  16: SECTION	LOCAL	 (0) 0x8001000d70
+  17: SECTION	LOCAL	 (0) 0x800101fde0
+  18: SECTION	LOCAL	 (0) 0x800101fde8
+  19: SECTION	LOCAL	 (0) 0x800101fdf0
+  20: SECTION	LOCAL	 (0) 0x800101fdf8
+  21: SECTION	LOCAL	 (0) 0x800101fe20
+  22: SECTION	LOCAL	 (0) 0x8001020000
+  23: SECTION	LOCAL	 (0) 0x8001020010
+  24: SECTION	LOCAL	 (0) 0x80010200d8
+  25: SECTION	LOCAL	 (0) 0x8001020110
+  26: SECTION	LOCAL	 (0) 0x8001020158
+  27: SECTION	LOCAL	 (0) 0
+  28: SECTION	LOCAL	 (0) 0
+  29: SECTION	LOCAL	 (0) 0
+  30: SECTION	LOCAL	 (0) 0
+  31: SECTION	LOCAL	 (0) 0
+  32: SECTION	LOCAL	 (0) 0
+  33: SECTION	LOCAL	 (0) 0
+  34: FILE	LOCAL	crtstuff.c (0) 0
+  35: OBJECT	LOCAL	__JCR_LIST__ (0) 0x800101fdf0
+  36: FUNC	LOCAL	deregister_tm_clones (0) 0x8001020040, rel: 0x20040 (.opd) [0x8001000910, rel: 0x70 (.text)]
+  37: FUNC	LOCAL	register_tm_clones (0) 0x8001020050, rel: 0x20050 (.opd) [0x8001000980, rel: 0xe0 (.text)]
+  38: FUNC	LOCAL	__do_global_dtors_aux (0) 0x8001020060, rel: 0x20060 (.opd) [0x80010009f0, rel: 0x150 (.text)]
+  39: OBJECT	LOCAL	completed.7711 (1) 0x8001020158
+  40: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x800101fde8
+  41: FUNC	LOCAL	frame_dummy (0) 0x8001020070, rel: 0x20070 (.opd) [0x8001000a50, rel: 0x1b0 (.text)]
+  42: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x800101fde0
+  43: FILE	LOCAL	foo.c (0) 0
+  44: FILE	LOCAL	bar.c (0) 0
+  45: OBJECT	LOCAL	b1 (4) 0x8001020004
+  46: FUNC	LOCAL	foo (76) 0x8001020090, rel: 0x20090 (.opd) [0x8001000b34, rel: 0x294 (.text)]
+  47: FILE	LOCAL	crtstuff.c (0) 0
+  48: OBJECT	LOCAL	__FRAME_END__ (0) 0x8001000e18
+  49: OBJECT	LOCAL	__JCR_END__ (0) 0x800101fdf0
+  50: FILE	LOCAL	 (0) 0
+  51: NOTYPE	LOCAL	__glink_PLTresolve (0) 0x8001000ce8
+  52: NOTYPE	LOCAL	00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x80010008a0
+  53: NOTYPE	LOCAL	00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x80010008b4
+  54: NOTYPE	LOCAL	__init_array_end (0) 0x800101fde8
+  55: OBJECT	LOCAL	_DYNAMIC (0) 0x800101fe20
+  56: NOTYPE	LOCAL	__init_array_start (0) 0x800101fde0
+  57: FUNC	GLOBAL	__libc_csu_fini (16) 0x80010200c0, rel: 0x200c0 (.opd) [0x8001000cd0, rel: 0x430 (.text)]
+  58: FUNC	GLOBAL	__libc_start_main@@GLIBC_2.3 (0) 0
+  59: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  60: NOTYPE	WEAK	data_start (0) 0x8001020000
+  61: NOTYPE	GLOBAL	_edata (0) 0x8001020110
+  62: FUNC	GLOBAL	bar (116) 0x80010200a0, rel: 0x200a0 (.opd) [0x8001000b80, rel: 0x2e0 (.text)]
+  63: FUNC	GLOBAL	_fini (0) 0x8001020030, rel: 0x20030 (.opd) [0x8001000d30, rel: 0 (.fini)]
+  64: NOTYPE	GLOBAL	__data_start (0) 0x8001020000
+  65: NOTYPE	WEAK	__gmon_start__ (0) 0
+  66: OBJECT	GLOBAL	__dso_handle (0) 0x800101fe18
+  67: OBJECT	GLOBAL	_IO_stdin_used (4) 0x8001000d4c
+  68: OBJECT	GLOBAL	b2 (4) 0x8001020008
+  69: FUNC	WEAK	__cxa_finalize@@GLIBC_2.3 (0) 0
+  70: FUNC	GLOBAL	__libc_csu_init (204) 0x80010200b0, rel: 0x200b0 (.opd) [0x8001000c00, rel: 0x360 (.text)]
+  71: NOTYPE	GLOBAL	_end (0) 0x8001020160
+  72: FUNC	GLOBAL	_start (60) 0x8001020010, rel: 0x20010 (.opd) [0x80010008c8, rel: 0x28 (.text)]
+  73: NOTYPE	GLOBAL	__bss_start (0) 0x8001020110
+  74: FUNC	GLOBAL	main (128) 0x8001020080, rel: 0x20080 (.opd) [0x8001000ab4, rel: 0x214 (.text)]
+  75: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  76: OBJECT	GLOBAL	__TMC_END__ (0) 0x8001020010
+  77: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  78: FUNC	GLOBAL	_init (0) 0x8001020020, rel: 0x20020 (.opd) [0x8001000850, rel: 0 (.init)]
+EOF
+
+cat > testfile.dynsym.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x238
+   2: SECTION	LOCAL	 (0) 0x1fdf0
+   3: FUNC	GLOBAL	__libc_start_main (0) 0
+   4: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+   5: NOTYPE	WEAK	__gmon_start__ (0) 0
+   6: FUNC	WEAK	__cxa_finalize (0) 0
+   7: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+   8: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+   9: NOTYPE	GLOBAL	_edata (0) 0x20110
+  10: NOTYPE	GLOBAL	_end (0) 0x20160
+  11: NOTYPE	GLOBAL	__bss_start (0) 0x20110
+EOF
+
+cat > testfile.minsym.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x238
+   2: SECTION	LOCAL	 (0) 0x1fdf0
+   3: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x1fde8
+   4: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x1fde0
+   5: NOTYPE	LOCAL	__glink_PLTresolve (0) 0xce8
+   6: NOTYPE	LOCAL	00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x8a0
+   7: NOTYPE	LOCAL	00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x8b4
+   8: NOTYPE	LOCAL	__init_array_end (0) 0x1fde8
+   9: NOTYPE	LOCAL	__init_array_start (0) 0x1fde0
+  10: SECTION	LOCAL	 (0) 0x238
+  11: SECTION	LOCAL	 (0) 0x24c
+  12: SECTION	LOCAL	 (0) 0x26c
+  13: SECTION	LOCAL	 (0) 0x290
+  14: SECTION	LOCAL	 (0) 0x2c0
+  15: SECTION	LOCAL	 (0) 0x3e0
+  16: SECTION	LOCAL	 (0) 0x488
+  17: SECTION	LOCAL	 (0) 0x4a0
+  18: SECTION	LOCAL	 (0) 0x4c0
+  19: SECTION	LOCAL	 (0) 0x820
+  20: SECTION	LOCAL	 (0) 0x850
+  21: SECTION	LOCAL	 (0) 0x8a0
+  22: SECTION	LOCAL	 (0) 0xd30
+  23: SECTION	LOCAL	 (0) 0xd4c
+  24: SECTION	LOCAL	 (0) 0xd50
+  25: SECTION	LOCAL	 (0) 0xd70
+  26: SECTION	LOCAL	 (0) 0x1fde0
+  27: SECTION	LOCAL	 (0) 0x1fde8
+  28: SECTION	LOCAL	 (0) 0x1fdf0
+  29: SECTION	LOCAL	 (0) 0x1fdf8
+  30: SECTION	LOCAL	 (0) 0x1fe20
+  31: SECTION	LOCAL	 (0) 0x20000
+  32: SECTION	LOCAL	 (0) 0x20010
+  33: SECTION	LOCAL	 (0) 0x200d8
+  34: SECTION	LOCAL	 (0) 0x20110
+  35: SECTION	LOCAL	 (0) 0x20158
+  36: FUNC	GLOBAL	__libc_start_main (0) 0
+  37: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  38: NOTYPE	WEAK	__gmon_start__ (0) 0
+  39: FUNC	WEAK	__cxa_finalize (0) 0
+  40: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  41: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  42: NOTYPE	GLOBAL	_edata (0) 0x20110
+  43: NOTYPE	GLOBAL	_end (0) 0x20160
+  44: NOTYPE	GLOBAL	__bss_start (0) 0x20110
+EOF
+
+cat > testfile.minsym_pl.in <<\EOF
+   0: NOTYPE	LOCAL	 (0) 0
+   1: SECTION	LOCAL	 (0) 0x8001000238
+   2: SECTION	LOCAL	 (0) 0x800101fdf0
+   3: OBJECT	LOCAL	__do_global_dtors_aux_fini_array_entry (0) 0x800101fde8
+   4: OBJECT	LOCAL	__frame_dummy_init_array_entry (0) 0x800101fde0
+   5: NOTYPE	LOCAL	__glink_PLTresolve (0) 0x8001000ce8
+   6: NOTYPE	LOCAL	00000011.plt_call.__libc_start_main@@GLIBC_2.3 (0) 0x80010008a0
+   7: NOTYPE	LOCAL	00000011.plt_call.__cxa_finalize@@GLIBC_2.3 (0) 0x80010008b4
+   8: NOTYPE	LOCAL	__init_array_end (0) 0x800101fde8
+   9: NOTYPE	LOCAL	__init_array_start (0) 0x800101fde0
+  10: SECTION	LOCAL	 (0) 0x8001000238
+  11: SECTION	LOCAL	 (0) 0x800100024c
+  12: SECTION	LOCAL	 (0) 0x800100026c
+  13: SECTION	LOCAL	 (0) 0x8001000290
+  14: SECTION	LOCAL	 (0) 0x80010002c0
+  15: SECTION	LOCAL	 (0) 0x80010003e0
+  16: SECTION	LOCAL	 (0) 0x8001000488
+  17: SECTION	LOCAL	 (0) 0x80010004a0
+  18: SECTION	LOCAL	 (0) 0x80010004c0
+  19: SECTION	LOCAL	 (0) 0x8001000820
+  20: SECTION	LOCAL	 (0) 0x8001000850
+  21: SECTION	LOCAL	 (0) 0x80010008a0
+  22: SECTION	LOCAL	 (0) 0x8001000d30
+  23: SECTION	LOCAL	 (0) 0x8001000d4c
+  24: SECTION	LOCAL	 (0) 0x8001000d50
+  25: SECTION	LOCAL	 (0) 0x8001000d70
+  26: SECTION	LOCAL	 (0) 0x800101fde0
+  27: SECTION	LOCAL	 (0) 0x800101fde8
+  28: SECTION	LOCAL	 (0) 0x800101fdf0
+  29: SECTION	LOCAL	 (0) 0x800101fdf8
+  30: SECTION	LOCAL	 (0) 0x800101fe20
+  31: SECTION	LOCAL	 (0) 0x8001020000
+  32: SECTION	LOCAL	 (0) 0x8001020010
+  33: SECTION	LOCAL	 (0) 0x80010200d8
+  34: SECTION	LOCAL	 (0) 0x8001020110
+  35: SECTION	LOCAL	 (0) 0x8001020158
+  36: FUNC	GLOBAL	__libc_start_main (0) 0
+  37: NOTYPE	WEAK	_ITM_deregisterTMCloneTable (0) 0
+  38: NOTYPE	WEAK	__gmon_start__ (0) 0
+  39: FUNC	WEAK	__cxa_finalize (0) 0
+  40: NOTYPE	WEAK	_Jv_RegisterClasses (0) 0
+  41: NOTYPE	WEAK	_ITM_registerTMCloneTable (0) 0
+  42: NOTYPE	GLOBAL	_edata (0) 0x8001020110
+  43: NOTYPE	GLOBAL	_end (0) 0x8001020160
+  44: NOTYPE	GLOBAL	__bss_start (0) 0x8001020110
+EOF
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebaztabppc64
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbgppc64
+
+cat testfile.symtab_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbgppc64_pl
+
+sed s/0x8001/0x4200/g testfile.symtab_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdbgppc64_plr
+
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazdynppc64
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazmdbppc64
+
+cat testfile.minsym.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazminppc64
+
+cat testfile.minsym_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazminppc64_pl
+
+sed s/0x8001/0x4200/g testfile.minsym_pl.in \
+  | testrun_compare ${abs_builddir}/dwflsyms -e testfilebazminppc64_plr
+
+exit 0
diff --git a/tests/run-early-offscn.sh b/tests/run-early-offscn.sh
new file mode 100755
index 0000000..3757bcf
--- /dev/null
+++ b/tests/run-early-offscn.sh
@@ -0,0 +1,24 @@
+#! /bin/sh
+# Copyright (C) 2008 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile
+
+testrun ${abs_builddir}/early-offscn testfile 0x500
+
+exit 0
diff --git a/tests/run-ecp-test.sh b/tests/run-ecp-test.sh
new file mode 100755
index 0000000..d5e376a
--- /dev/null
+++ b/tests/run-ecp-test.sh
@@ -0,0 +1,28 @@
+#! /bin/sh
+# Copyright (C) 2002, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Jakub Jelinek <jakub@redhat.com>, 2002.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile10
+tempfiles testfile10.tmp
+
+testrun ${abs_builddir}/ecp testfile10 testfile10.tmp
+
+cmp testfile10 testfile10.tmp
+
+exit 0
diff --git a/tests/run-ecp-test2.sh b/tests/run-ecp-test2.sh
new file mode 100755
index 0000000..864e0a5
--- /dev/null
+++ b/tests/run-ecp-test2.sh
@@ -0,0 +1,26 @@
+#! /bin/sh
+# Copyright (C) 2002, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Jakub Jelinek <jakub@redhat.com>, 2002.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile2
+tempfiles testfile2.tmp
+
+testrun ${abs_builddir}/ecp testfile2 testfile2.tmp
+
+exit 0
diff --git a/tests/run-elf_cntl_gelf_getshdr.sh b/tests/run-elf_cntl_gelf_getshdr.sh
new file mode 100755
index 0000000..94b477c
--- /dev/null
+++ b/tests/run-elf_cntl_gelf_getshdr.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles test_shdr.out
+
+# However we open the elf file, the shdrs should be the same.
+testrun ${abs_builddir}/test-elf_cntl_gelf_getshdr READ ${abs_builddir}/test-elf_cntl_gelf_getshdr \
+  > test_shdr.out
+
+testrun_compare ${abs_builddir}/test-elf_cntl_gelf_getshdr MMAP ${abs_builddir}/test-elf_cntl_gelf_getshdr \
+  < test_shdr.out
+
+testrun_compare ${abs_builddir}/test-elf_cntl_gelf_getshdr FDREAD ${abs_builddir}/test-elf_cntl_gelf_getshdr \
+  < test_shdr.out
diff --git a/tests/run-elfclassify-self.sh b/tests/run-elfclassify-self.sh
new file mode 100755
index 0000000..c48ab9c
--- /dev/null
+++ b/tests/run-elfclassify-self.sh
@@ -0,0 +1,36 @@
+#!/bin/sh
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testrun_on_self ${abs_top_builddir}/src/elfclassify --elf-file
+testrun_on_self ${abs_top_builddir}/src/elfclassify --not-core
+testrun_on_self ${abs_top_builddir}/src/elfclassify --unstripped
+testrun_on_self ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module
+
+testrun_on_self_lib ${abs_top_builddir}/src/elfclassify --shared
+testrun_on_self_lib ${abs_top_builddir}/src/elfclassify --loadable
+testrun_on_self_lib ${abs_top_builddir}/src/elfclassify --not-executable
+testrun_on_self_lib ${abs_top_builddir}/src/elfclassify --not-program
+
+testrun_on_self_exe ${abs_top_builddir}/src/elfclassify --executable
+testrun_on_self_exe ${abs_top_builddir}/src/elfclassify --program
+testrun_on_self_exe ${abs_top_builddir}/src/elfclassify --loadable
+testrun_on_self_exe ${abs_top_builddir}/src/elfclassify --not-shared
+
+testrun ${abs_top_builddir}/src/elfclassify --not-shared $self_test_files_obj
+testrun ${abs_top_builddir}/src/elfclassify --not-executable $self_test_files_obj
diff --git a/tests/run-elfclassify.sh b/tests/run-elfclassify.sh
new file mode 100755
index 0000000..fb14139
--- /dev/null
+++ b/tests/run-elfclassify.sh
@@ -0,0 +1,327 @@
+#!/bin/sh
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+core_files=\
+"testfile_aarch64_core \
+ testfile-backtrace-demangle.core \
+ testfiledwarfinlines.core \
+ testfile_i686_core \
+ testfile-m68k-core \
+ testfile-riscv64-core \
+ backtrace.aarch64.core \
+ backtrace.i386.core \
+ backtrace.ppc.core \
+ backtrace.s390.core"
+
+testfiles $core_files
+
+echo "elfclassify --core"
+testrun ${abs_top_builddir}/src/elfclassify --core $core_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --core --print $core_files <<EOF
+$(echo $core_files | sed -e "s/ /\n/g")
+EOF
+
+echo "core files are not programs"
+testrun ${abs_top_builddir}/src/elfclassify --not-program $core_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-program --print $core_files <<EOF
+$(echo $core_files | sed -e "s/ /\n/g")
+EOF
+
+echo "core files are not shared"
+testrun ${abs_top_builddir}/src/elfclassify --not-shared $core_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-shared --print $core_files <<EOF
+$(echo $core_files | sed -e "s/ /\n/g")
+EOF
+
+echo "core files are not kernel-modules"
+testrun ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module $core_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module --print $core_files <<EOF
+$(echo $core_files | sed -e "s/ /\n/g")
+EOF
+
+echo "core files are not debug-only"
+testrun ${abs_top_builddir}/src/elfclassify --not-debug-only $core_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-debug-only --print $core_files <<EOF
+$(echo $core_files | sed -e "s/ /\n/g")
+EOF
+
+object_files=\
+"debug-ranges-no-lowpc.o \
+ testfile-annobingroup-i386.o \
+ testfile-bpf-dis1.o \
+ testfile-debug-rel-g.o \
+ testfile-gnu-property-note.o"
+
+testfiles $object_files
+
+echo "elfclassify --elf-file"
+testrun ${abs_top_builddir}/src/elfclassify --elf-file $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --elf-file --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+echo "object files are not archives"
+testrun ${abs_top_builddir}/src/elfclassify --not-elf-archive $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-elf-archive --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+echo "object files are not core files"
+testrun ${abs_top_builddir}/src/elfclassify --not-core $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-core --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+echo "object files are not program files"
+testrun ${abs_top_builddir}/src/elfclassify --not-program $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-program --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+echo "object files are not shared files"
+testrun ${abs_top_builddir}/src/elfclassify --not-shared $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-shared --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+echo "object files are not kernel modules"
+testrun ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+echo "object files are not debug-only files"
+testrun ${abs_top_builddir}/src/elfclassify --not-debug-only $object_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-debug-only --print $object_files <<EOF
+$(echo $object_files | sed -e "s/ /\n/g")
+EOF
+
+ar_files="testarchive64.a"
+
+testfiles $ar_files
+
+echo "elfclassify --elf-archive"
+testrun ${abs_top_builddir}/src/elfclassify --elf-archive $ar_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --elf-archive --print $ar_files <<EOF
+$(echo $ar_files | sed -e "s/ /\n/g")
+EOF
+
+echo "archives are not elf-files"
+testrun ${abs_top_builddir}/src/elfclassify --not-elf-file $ar_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-elf-file --print $ar_files <<EOF
+$(echo $ar_files | sed -e "s/ /\n/g")
+EOF
+
+echo "archives are not core files"
+testrun ${abs_top_builddir}/src/elfclassify --not-core $ar_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-core --print $ar_files <<EOF
+$(echo $ar_files | sed -e "s/ /\n/g")
+EOF
+
+echo "archives are not program files"
+testrun ${abs_top_builddir}/src/elfclassify --not-program $ar_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-program --print $ar_files <<EOF
+$(echo $ar_files | sed -e "s/ /\n/g")
+EOF
+
+echo "archives are not shared files"
+testrun ${abs_top_builddir}/src/elfclassify --not-shared $ar_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-shared --print $ar_files <<EOF
+$(echo $ar_files | sed -e "s/ /\n/g")
+EOF
+
+lib_files=\
+"testfile52-32.noshdrs.so \
+ libtestfile_multi_shared.so \
+ testfile52-32.prelink.so \
+ testfile52-32.so
+ testfile54-64.noshdrs.so \
+ testfile54-64.prelink.so \
+ testfile54-64.so \
+ testlib_dynseg.so"
+
+testfiles $lib_files
+
+echo "elfclassify --shared"
+testrun ${abs_top_builddir}/src/elfclassify --shared $lib_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --shared --print $lib_files <<EOF
+$(echo $lib_files | sed -e "s/ /\n/g")
+EOF
+
+echo "shared files are loadable"
+testrun ${abs_top_builddir}/src/elfclassify --loadable $lib_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --loadable --print $lib_files <<EOF
+$(echo $lib_files | sed -e "s/ /\n/g")
+EOF
+
+echo "shared files are not executables"
+testrun ${abs_top_builddir}/src/elfclassify --not-executable $lib_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-executable --print $lib_files <<EOF
+$(echo $lib_files | sed -e "s/ /\n/g")
+EOF
+
+echo "shared files are not debug-only"
+testrun ${abs_top_builddir}/src/elfclassify --not-debug-only $lib_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-debug-only --print $lib_files <<EOF
+$(echo $lib_files | sed -e "s/ /\n/g")
+EOF
+
+echo "shared files are not kernel modules"
+testrun ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module $lib_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module --print $lib_files <<EOF
+$(echo $lib_files | sed -e "s/ /\n/g")
+EOF
+
+exe_files=\
+"backtrace.aarch64.exec \
+ backtrace.i386.exec \
+ backtrace.ppc.exec \
+ backtrace.s390x.exec \
+ testfile70.exec \
+ test-offset-loop \
+ testfilebaztab \
+ testfilebaztabppc64"
+
+testfiles $exe_files
+
+echo "elfclassify --program"
+testrun ${abs_top_builddir}/src/elfclassify --program $exe_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --program --print $exe_files <<EOF
+$(echo $exe_files | sed -e "s/ /\n/g")
+EOF
+
+echo "programs are executables (in this case)"
+testrun ${abs_top_builddir}/src/elfclassify --executable $exe_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --executable --print $exe_files <<EOF
+$(echo $exe_files | sed -e "s/ /\n/g")
+EOF
+
+echo "programs are not shared libraries (in this case)"
+testrun ${abs_top_builddir}/src/elfclassify --not-shared $exe_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-shared --print $exe_files <<EOF
+$(echo $exe_files | sed -e "s/ /\n/g")
+EOF
+
+echo "programs are not kernel-modules"
+testrun ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module $exe_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-linux-kernel-module --print $exe_files <<EOF
+$(echo $exe_files | sed -e "s/ /\n/g")
+EOF
+
+echo "programs are not debug-only"
+testrun ${abs_top_builddir}/src/elfclassify --not-debug-only $exe_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-debug-only --print $exe_files <<EOF
+$(echo $exe_files | sed -e "s/ /\n/g")
+EOF
+
+kmod_files=\
+"hello_aarch64.ko \
+ hello_csky.ko \
+ hello_i386.ko \
+ hello_m68k.ko \
+ hello_ppc64.ko \
+ hello_riscv64.ko \
+ hello_s390.ko \
+ hello_x86_64.ko"
+
+testfiles $kmod_files
+
+echo "elfclassify --linux-kernel-module"
+testrun ${abs_top_builddir}/src/elfclassify --linux-kernel-module $kmod_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --linux-kernel-module --print $kmod_files <<EOF
+$(echo $kmod_files | sed -e "s/ /\n/g")
+EOF
+
+echo "kmods are unstripped"
+testrun ${abs_top_builddir}/src/elfclassify --unstripped $kmod_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --unstripped --print $kmod_files <<EOF
+$(echo $kmod_files | sed -e "s/ /\n/g")
+EOF
+
+echo "kmods are not debug-only"
+testrun ${abs_top_builddir}/src/elfclassify --not-debug-only $kmod_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-debug-only --print $kmod_files <<EOF
+$(echo $kmod_files | sed -e "s/ /\n/g")
+EOF
+
+echo "kmods are not loabable (in the normal sense)"
+testrun ${abs_top_builddir}/src/elfclassify --not-loadable $kmod_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-loadable --print $kmod_files <<EOF
+$(echo $kmod_files | sed -e "s/ /\n/g")
+EOF
+
+echo "gnu compressed kmods are unstripped"
+testrun ${abs_top_builddir}/src/elfcompress -t gnu --force $kmod_files
+testrun ${abs_top_builddir}/src/elfclassify --unstripped $kmod_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --unstripped --print $kmod_files <<EOF
+$(echo $kmod_files | sed -e "s/ /\n/g")
+EOF
+
+debug_files=\
+"testfile15.debug \
+ testfile35.debug \
+ testfile40.debug \
+ testfile48.debug \
+ testfile53-32.debug \
+ testfile53-64.debug \
+ testfilebazdbg.debug \
+ testfilebazdbgppc64.debug \
+ addrx_constx-4.dwo \
+ addrx_constx-5.dwo"
+
+testfiles $debug_files
+
+echo "elfclassify --debug-only"
+testrun ${abs_top_builddir}/src/elfclassify --debug-only $debug_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --debug-only --print $debug_files <<EOF
+$(echo $debug_files | sed -e "s/ /\n/g")
+EOF
+
+echo "debug-only files are unstripped"
+testrun ${abs_top_builddir}/src/elfclassify --unstripped $debug_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --unstripped --print $debug_files <<EOF
+$(echo $debug_files | sed -e "s/ /\n/g")
+EOF
+
+echo "debug-only files are not programs"
+testrun ${abs_top_builddir}/src/elfclassify --not-program $debug_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-program --print $debug_files <<EOF
+$(echo $debug_files | sed -e "s/ /\n/g")
+EOF
+
+echo "debug-only files are not shared"
+testrun ${abs_top_builddir}/src/elfclassify --not-shared $debug_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --not-shared --print $debug_files <<EOF
+$(echo $debug_files | sed -e "s/ /\n/g")
+EOF
+
+echo "compress the debug sections and try again"
+testrun ${abs_top_builddir}/src/elfcompress -t gnu --force $debug_files
+
+echo "again unstripped"
+testrun ${abs_top_builddir}/src/elfclassify --unstripped $debug_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --unstripped --print $debug_files <<EOF
+$(echo $debug_files | sed -e "s/ /\n/g")
+EOF
+
+echo "again debug-only"
+testrun ${abs_top_builddir}/src/elfclassify --debug-only $debug_files
+testrun_compare ${abs_top_builddir}/src/elfclassify --debug-only --print $debug_files <<EOF
+$(echo $debug_files | sed -e "s/ /\n/g")
+EOF
diff --git a/tests/run-elfgetchdr.sh b/tests/run-elfgetchdr.sh
new file mode 100755
index 0000000..7a422f3
--- /dev/null
+++ b/tests/run-elfgetchdr.sh
@@ -0,0 +1,188 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# = funcs.s =
+# .globl testfunc
+# testfunc:
+# 	nop
+# 	ret
+# .type testfunc, @function
+# .size testfunc, .-testfunc
+#
+# .globl testfunc2
+# testfunc2:
+# 	call testfunc
+# 	nop
+# 	nop
+# 	ret
+# .type testfunc2, @function
+# .size testfunc2, .-testfunc2
+#
+# .globl functest3
+# functest3:
+# 	jmp local
+# 	nop
+# 	nop
+# local:
+# 	call testfunc2
+# 	ret
+# .type functest3, @function
+# .size functest3, .-functest3
+
+# = start.s =
+# .global _start
+# _start:
+# 	call functest3
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	nop
+# 	ret
+# .type _start, @function
+# .size _start, .-_start
+
+# gas --compress-debug-sections=zlib-gnu -32 -g -o start.o start.s
+# gas --compress-debug-sections=zlib-gnu -32 -g -o funcs.o funcs.s
+# ld --compress-debug-sections=zlib-gnu -melf_i386 -g -o zgnu32 funcs.o start.o
+
+# gas --compress-debug-sections=zlib-gnu -64 -g -o start.o start.s
+# gas --compress-debug-sections=zlib-gnu -64 -g -o funcs.o funcs.s
+# ld --compress-debug-sections=zlib-gnu -g -o zgnu64 funcs.o start.o
+
+# gas --compress-debug-sections=zlib-gabi -32 -g -o start.o start.s
+# gas --compress-debug-sections=zlib-gabi -32 -g -o funcs.o funcs.s
+# ld --compress-debug-sections=zlib-gabi -melf_i386 -g -o zgabi32 funcs.o start.o
+
+# gas --compress-debug-sections=zlib-gabi -64 -g -o start.o start.s
+# gas --compress-debug-sections=zlib-gabi -64 -g -o funcs.o funcs.s
+# ld --compress-debug-sections=zlib-gabi -g -o zgabi64 funcs.o start.o
+
+testfiles testfile-zgnu64
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgnu64 <<\EOF
+section 1: NOT Compressed
+section 2: GNU Compressed size: 60
+section 3: GNU Compressed size: aa
+section 4: NOT Compressed
+section 5: GNU Compressed size: 8d
+section 6: NOT Compressed
+section 7: NOT Compressed
+section 8: NOT Compressed
+EOF
+
+testfiles testfile-zgabi64
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgabi64 <<\EOF
+section 1: NOT Compressed
+section 2: ELF Compressed ch_type: 1, ch_size: 60, ch_addralign: 10
+section 3: ELF Compressed ch_type: 1, ch_size: aa, ch_addralign: 1
+section 4: NOT Compressed
+section 5: ELF Compressed ch_type: 1, ch_size: 8d, ch_addralign: 1
+section 6: NOT Compressed
+section 7: NOT Compressed
+section 8: NOT Compressed
+EOF
+
+testfiles testfile-zgnu32
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgnu32 <<\EOF
+section 1: NOT Compressed
+section 2: GNU Compressed size: 40
+section 3: GNU Compressed size: 9a
+section 4: NOT Compressed
+section 5: GNU Compressed size: 85
+section 6: NOT Compressed
+section 7: NOT Compressed
+section 8: NOT Compressed
+EOF
+
+testfiles testfile-zgabi32
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgabi32 <<\EOF
+section 1: NOT Compressed
+section 2: ELF Compressed ch_type: 1, ch_size: 40, ch_addralign: 8
+section 3: ELF Compressed ch_type: 1, ch_size: 9a, ch_addralign: 1
+section 4: NOT Compressed
+section 5: ELF Compressed ch_type: 1, ch_size: 85, ch_addralign: 1
+section 6: NOT Compressed
+section 7: NOT Compressed
+section 8: NOT Compressed
+EOF
+
+testfiles testfile-zgnu64be
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgnu64be <<\EOF
+section 1: NOT Compressed
+section 2: NOT Compressed
+section 3: GNU Compressed size: 60
+section 4: GNU Compressed size: 7e
+section 5: NOT Compressed
+section 6: GNU Compressed size: 8d
+section 7: NOT Compressed
+section 8: NOT Compressed
+section 9: NOT Compressed
+EOF
+
+testfiles testfile-zgabi64be
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgabi64be <<\EOF
+section 1: NOT Compressed
+section 2: NOT Compressed
+section 3: ELF Compressed ch_type: 1, ch_size: 60, ch_addralign: 10
+section 4: ELF Compressed ch_type: 1, ch_size: 7e, ch_addralign: 1
+section 5: NOT Compressed
+section 6: ELF Compressed ch_type: 1, ch_size: 8d, ch_addralign: 1
+section 7: NOT Compressed
+section 8: NOT Compressed
+section 9: NOT Compressed
+EOF
+
+testfiles testfile-zgnu32be
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgnu32be <<\EOF
+section 1: NOT Compressed
+section 2: NOT Compressed
+section 3: GNU Compressed size: 40
+section 4: GNU Compressed size: 6e
+section 5: NOT Compressed
+section 6: GNU Compressed size: 85
+section 7: NOT Compressed
+section 8: NOT Compressed
+section 9: NOT Compressed
+EOF
+
+testfiles testfile-zgabi32be
+testrun_compare ${abs_top_builddir}/tests/elfgetchdr testfile-zgabi32be <<\EOF
+section 1: NOT Compressed
+section 2: NOT Compressed
+section 3: ELF Compressed ch_type: 1, ch_size: 40, ch_addralign: 8
+section 4: ELF Compressed ch_type: 1, ch_size: 6e, ch_addralign: 1
+section 5: NOT Compressed
+section 6: ELF Compressed ch_type: 1, ch_size: 85, ch_addralign: 1
+section 7: NOT Compressed
+section 8: NOT Compressed
+section 9: NOT Compressed
+EOF
+
+exit 0
diff --git a/tests/run-elfgetzdata.sh b/tests/run-elfgetzdata.sh
new file mode 100755
index 0000000..7d3d1a5
--- /dev/null
+++ b/tests/run-elfgetzdata.sh
@@ -0,0 +1,306 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-elfgetchdr.sh for testfiles.
+
+testfiles testfile-zgnu64
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgnu64 <<\EOF
+1: .text, NOT compressed
+2: .zdebug_aranges, GNU compressed, size: 60
+3: .zdebug_info, GNU compressed, size: aa
+4: .debug_abbrev, NOT compressed
+5: .zdebug_line, GNU compressed, size: 8d
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgnu64 <<\EOF
+1: .text, NOT compressed
+2: .zdebug_aranges, GNU compressed, size: 60
+3: .zdebug_info, GNU compressed, size: aa
+4: .debug_abbrev, NOT compressed
+5: .zdebug_line, GNU compressed, size: 8d
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgnu64 <<\EOF
+1: .text, NOT compressed
+2: .zdebug_aranges, GNU compressed, size: 60
+3: .zdebug_info, GNU compressed, size: aa
+4: .debug_abbrev, NOT compressed
+5: .zdebug_line, GNU compressed, size: 8d
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgnu64be
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgnu64be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .zdebug_aranges, GNU compressed, size: 60
+4: .zdebug_info, GNU compressed, size: 7e
+5: .debug_abbrev, NOT compressed
+6: .zdebug_line, GNU compressed, size: 8d
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgnu64be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .zdebug_aranges, GNU compressed, size: 60
+4: .zdebug_info, GNU compressed, size: 7e
+5: .debug_abbrev, NOT compressed
+6: .zdebug_line, GNU compressed, size: 8d
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgnu64be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .zdebug_aranges, GNU compressed, size: 60
+4: .zdebug_info, GNU compressed, size: 7e
+5: .debug_abbrev, NOT compressed
+6: .zdebug_line, GNU compressed, size: 8d
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgabi64
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgabi64 <<\EOF
+1: .text, NOT compressed
+2: .debug_aranges, ELF compressed, size: 60
+3: .debug_info, ELF compressed, size: aa
+4: .debug_abbrev, NOT compressed
+5: .debug_line, ELF compressed, size: 8d
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgabi64 <<\EOF
+1: .text, NOT compressed
+2: .debug_aranges, ELF compressed, size: 60
+3: .debug_info, ELF compressed, size: aa
+4: .debug_abbrev, NOT compressed
+5: .debug_line, ELF compressed, size: 8d
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgabi64 <<\EOF
+1: .text, NOT compressed
+2: .debug_aranges, ELF compressed, size: 60
+3: .debug_info, ELF compressed, size: aa
+4: .debug_abbrev, NOT compressed
+5: .debug_line, ELF compressed, size: 8d
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgabi64be
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgabi64be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .debug_aranges, ELF compressed, size: 60
+4: .debug_info, ELF compressed, size: 7e
+5: .debug_abbrev, NOT compressed
+6: .debug_line, ELF compressed, size: 8d
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgabi64be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .debug_aranges, ELF compressed, size: 60
+4: .debug_info, ELF compressed, size: 7e
+5: .debug_abbrev, NOT compressed
+6: .debug_line, ELF compressed, size: 8d
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgabi64be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .debug_aranges, ELF compressed, size: 60
+4: .debug_info, ELF compressed, size: 7e
+5: .debug_abbrev, NOT compressed
+6: .debug_line, ELF compressed, size: 8d
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgnu32
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgnu32 <<\EOF
+1: .text, NOT compressed
+2: .zdebug_aranges, GNU compressed, size: 40
+3: .zdebug_info, GNU compressed, size: 9a
+4: .debug_abbrev, NOT compressed
+5: .zdebug_line, GNU compressed, size: 85
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgnu32 <<\EOF
+1: .text, NOT compressed
+2: .zdebug_aranges, GNU compressed, size: 40
+3: .zdebug_info, GNU compressed, size: 9a
+4: .debug_abbrev, NOT compressed
+5: .zdebug_line, GNU compressed, size: 85
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgnu32 <<\EOF
+1: .text, NOT compressed
+2: .zdebug_aranges, GNU compressed, size: 40
+3: .zdebug_info, GNU compressed, size: 9a
+4: .debug_abbrev, NOT compressed
+5: .zdebug_line, GNU compressed, size: 85
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgnu32be
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgnu32be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .zdebug_aranges, GNU compressed, size: 40
+4: .zdebug_info, GNU compressed, size: 6e
+5: .debug_abbrev, NOT compressed
+6: .zdebug_line, GNU compressed, size: 85
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgnu32be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .zdebug_aranges, GNU compressed, size: 40
+4: .zdebug_info, GNU compressed, size: 6e
+5: .debug_abbrev, NOT compressed
+6: .zdebug_line, GNU compressed, size: 85
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgnu32be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .zdebug_aranges, GNU compressed, size: 40
+4: .zdebug_info, GNU compressed, size: 6e
+5: .debug_abbrev, NOT compressed
+6: .zdebug_line, GNU compressed, size: 85
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgabi32
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgabi32 <<\EOF
+1: .text, NOT compressed
+2: .debug_aranges, ELF compressed, size: 40
+3: .debug_info, ELF compressed, size: 9a
+4: .debug_abbrev, NOT compressed
+5: .debug_line, ELF compressed, size: 85
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgabi32 <<\EOF
+1: .text, NOT compressed
+2: .debug_aranges, ELF compressed, size: 40
+3: .debug_info, ELF compressed, size: 9a
+4: .debug_abbrev, NOT compressed
+5: .debug_line, ELF compressed, size: 85
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgabi32 <<\EOF
+1: .text, NOT compressed
+2: .debug_aranges, ELF compressed, size: 40
+3: .debug_info, ELF compressed, size: 9a
+4: .debug_abbrev, NOT compressed
+5: .debug_line, ELF compressed, size: 85
+6: .shstrtab, NOT compressed
+7: .symtab, NOT compressed
+8: .strtab, NOT compressed
+EOF
+
+testfiles testfile-zgabi32be
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata read testfile-zgabi32be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .debug_aranges, ELF compressed, size: 40
+4: .debug_info, ELF compressed, size: 6e
+5: .debug_abbrev, NOT compressed
+6: .debug_line, ELF compressed, size: 85
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mmap testfile-zgabi32be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .debug_aranges, ELF compressed, size: 40
+4: .debug_info, ELF compressed, size: 6e
+5: .debug_abbrev, NOT compressed
+6: .debug_line, ELF compressed, size: 85
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfgetzdata mem testfile-zgabi32be <<\EOF
+1: .text, NOT compressed
+2: .eh_frame, NOT compressed
+3: .debug_aranges, ELF compressed, size: 40
+4: .debug_info, ELF compressed, size: 6e
+5: .debug_abbrev, NOT compressed
+6: .debug_line, ELF compressed, size: 85
+7: .shstrtab, NOT compressed
+8: .symtab, NOT compressed
+9: .strtab, NOT compressed
+EOF
+
+exit 0
diff --git a/tests/run-elflint-self.sh b/tests/run-elflint-self.sh
new file mode 100755
index 0000000..58fa7d0
--- /dev/null
+++ b/tests/run-elflint-self.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) 2005, 2007, 2017 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testrun_on_self ${abs_top_builddir}/src/elflint --quiet --gnu-ld
+testrun_on_self_compressed ${abs_top_builddir}/src/elflint --quiet --gnu-ld
diff --git a/tests/run-elflint-test.sh b/tests/run-elflint-test.sh
new file mode 100755
index 0000000..caf172a
--- /dev/null
+++ b/tests/run-elflint-test.sh
@@ -0,0 +1,60 @@
+#! /bin/sh
+# Copyright (C) 2005, 2007, 2008, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile18
+
+testrun_compare ${abs_top_builddir}/src/elflint --gnu-ld testfile18 <<\EOF
+section [ 8] '.rela.dyn': relocation 1: copy relocation against symbol of type FUNC
+EOF
+
+testfiles testfile32
+testrun ${abs_top_builddir}/src/elflint -q testfile32
+
+testfiles testfile33
+testrun ${abs_top_builddir}/src/elflint -q testfile33
+
+testfiles testfile42
+testrun ${abs_top_builddir}/src/elflint -q --gnu-ld testfile42
+
+# Contains debuginfo, compress it, recheck
+tempfiles testfile42z
+testrun ${abs_top_builddir}/src/elfcompress -f -q -o testfile42z testfile42
+testrun ${abs_top_builddir}/src/elflint -q --gnu-ld testfile42z
+
+testfiles testfile46
+testrun ${abs_top_builddir}/src/elflint -q testfile46
+
+# see also run-readelf-d.sh
+testfiles testlib_dynseg.so
+testrun ${abs_top_builddir}/src/elflint -q --gnu-ld testlib_dynseg.so
+
+# s390x has SHT_HASH with sh_entsize 8 (really should be 4, but see common.h)
+# This was wrongly checked when comparing .gnu.hash and .hash.
+# Simple "int main (int argc, char **argv) { return 0; }"
+# gcc -Xlinker --hash-style=both -o testfile-s390x-hash-both s390x-hash-both.c
+testfiles testfile-s390x-hash-both
+testrun ${abs_top_builddir}/src/elflint -q --gnu-ld testfile-s390x-hash-both
+
+# Compress the symtab/strtab just because and recheck
+tempfiles testfile-s390x-hash-bothz
+testrun ${abs_top_builddir}/src/elfcompress -f -q --name='.s??tab' -o testfile-s390x-hash-bothz testfile-s390x-hash-both
+testrun ${abs_top_builddir}/src/elflint -q --gnu-ld testfile-s390x-hash-bothz
+
+exit 0
diff --git a/tests/run-elfputzdata.sh b/tests/run-elfputzdata.sh
new file mode 100755
index 0000000..b882b3f
--- /dev/null
+++ b/tests/run-elfputzdata.sh
@@ -0,0 +1,340 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Random ELF32 testfile
+testfiles testfile4
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata gnu testfile4 <<\EOF
+Cannot compress 1 .interp
+Cannot compress 2 .note.ABI-tag
+Cannot compress 3 .hash
+Cannot compress 4 .dynsym
+Cannot compress 5 .dynstr
+Cannot compress 6 .gnu.version
+Cannot compress 7 .gnu.version_r
+Cannot compress 8 .rel.got
+Cannot compress 9 .rel.plt
+Cannot compress 10 .init
+Cannot compress 11 .plt
+Cannot compress 12 .text
+Cannot compress 13 .fini
+Cannot compress 14 .rodata
+Cannot compress 15 .data
+Cannot compress 16 .eh_frame
+Cannot compress 17 .gcc_except_table
+Cannot compress 18 .ctors
+Cannot compress 19 .dtors
+Cannot compress 20 .got
+Cannot compress 21 .dynamic
+Lets compress 22 .sbss, size: 0
+Cannot compress 23 .bss
+Lets compress 24 .stab, size: 21540
+Lets compress 25 .stabstr, size: 57297
+Lets compress 26 .comment, size: 648
+Lets compress 27 .debug_aranges, size: 56
+Lets compress 28 .debug_pubnames, size: 93
+Lets compress 29 .debug_info, size: 960
+Lets compress 30 .debug_abbrev, size: 405
+Lets compress 31 .debug_line, size: 189
+Lets compress 32 .note, size: 240
+Lets compress 33 .shstrtab, size: 320
+Lets compress 34 .symtab, size: 5488
+Lets compress 35 .strtab, size: 5727
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata elf testfile4 <<\EOF
+Cannot compress 1 .interp
+Cannot compress 2 .note.ABI-tag
+Cannot compress 3 .hash
+Cannot compress 4 .dynsym
+Cannot compress 5 .dynstr
+Cannot compress 6 .gnu.version
+Cannot compress 7 .gnu.version_r
+Cannot compress 8 .rel.got
+Cannot compress 9 .rel.plt
+Cannot compress 10 .init
+Cannot compress 11 .plt
+Cannot compress 12 .text
+Cannot compress 13 .fini
+Cannot compress 14 .rodata
+Cannot compress 15 .data
+Cannot compress 16 .eh_frame
+Cannot compress 17 .gcc_except_table
+Cannot compress 18 .ctors
+Cannot compress 19 .dtors
+Cannot compress 20 .got
+Cannot compress 21 .dynamic
+Lets compress 22 .sbss, size: 0
+Cannot compress 23 .bss
+Lets compress 24 .stab, size: 21540
+Lets compress 25 .stabstr, size: 57297
+Lets compress 26 .comment, size: 648
+Lets compress 27 .debug_aranges, size: 56
+Lets compress 28 .debug_pubnames, size: 93
+Lets compress 29 .debug_info, size: 960
+Lets compress 30 .debug_abbrev, size: 405
+Lets compress 31 .debug_line, size: 189
+Lets compress 32 .note, size: 240
+Lets compress 33 .shstrtab, size: 320
+Lets compress 34 .symtab, size: 5488
+Lets compress 35 .strtab, size: 5727
+EOF
+
+# Random ELF64 testfile
+testfiles testfile12
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata gnu testfile12 <<\EOF
+Cannot compress 1 .hash
+Cannot compress 2 .dynsym
+Cannot compress 3 .dynstr
+Cannot compress 4 .gnu.version
+Cannot compress 5 .gnu.version_r
+Cannot compress 6 .rela.dyn
+Cannot compress 7 .rela.plt
+Cannot compress 8 .init
+Cannot compress 9 .plt
+Cannot compress 10 .text
+Cannot compress 11 .fini
+Cannot compress 12 .rodata
+Cannot compress 13 .eh_frame_hdr
+Cannot compress 14 .eh_frame
+Cannot compress 15 .data
+Cannot compress 16 .dynamic
+Cannot compress 17 .ctors
+Cannot compress 18 .dtors
+Cannot compress 19 .jcr
+Cannot compress 20 .got
+Cannot compress 21 .bss
+Lets compress 22 .comment, size: 246
+Lets compress 23 .debug_aranges, size: 192
+Lets compress 24 .debug_pubnames, size: 26
+Lets compress 25 .debug_info, size: 3468
+Lets compress 26 .debug_abbrev, size: 341
+Lets compress 27 .debug_line, size: 709
+Lets compress 28 .debug_frame, size: 56
+Lets compress 29 .debug_str, size: 2235
+Lets compress 30 .debug_macinfo, size: 10518
+Lets compress 31 .shstrtab, size: 308
+Lets compress 32 .symtab, size: 1944
+Lets compress 33 .strtab, size: 757
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata elf testfile12 <<\EOF
+Cannot compress 1 .hash
+Cannot compress 2 .dynsym
+Cannot compress 3 .dynstr
+Cannot compress 4 .gnu.version
+Cannot compress 5 .gnu.version_r
+Cannot compress 6 .rela.dyn
+Cannot compress 7 .rela.plt
+Cannot compress 8 .init
+Cannot compress 9 .plt
+Cannot compress 10 .text
+Cannot compress 11 .fini
+Cannot compress 12 .rodata
+Cannot compress 13 .eh_frame_hdr
+Cannot compress 14 .eh_frame
+Cannot compress 15 .data
+Cannot compress 16 .dynamic
+Cannot compress 17 .ctors
+Cannot compress 18 .dtors
+Cannot compress 19 .jcr
+Cannot compress 20 .got
+Cannot compress 21 .bss
+Lets compress 22 .comment, size: 246
+Lets compress 23 .debug_aranges, size: 192
+Lets compress 24 .debug_pubnames, size: 26
+Lets compress 25 .debug_info, size: 3468
+Lets compress 26 .debug_abbrev, size: 341
+Lets compress 27 .debug_line, size: 709
+Lets compress 28 .debug_frame, size: 56
+Lets compress 29 .debug_str, size: 2235
+Lets compress 30 .debug_macinfo, size: 10518
+Lets compress 31 .shstrtab, size: 308
+Lets compress 32 .symtab, size: 1944
+Lets compress 33 .strtab, size: 757
+EOF
+
+# Random ELF64BE testfile
+testfiles testfileppc64
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata gnu testfileppc64 <<\EOF
+Cannot compress 1 .interp
+Cannot compress 2 .note.ABI-tag
+Cannot compress 3 .note.gnu.build-id
+Cannot compress 4 .gnu.hash
+Cannot compress 5 .dynsym
+Cannot compress 6 .dynstr
+Cannot compress 7 .gnu.version
+Cannot compress 8 .gnu.version_r
+Cannot compress 9 .rela.plt
+Cannot compress 10 .init
+Cannot compress 11 .text
+Cannot compress 12 .fini
+Cannot compress 13 .rodata
+Cannot compress 14 .eh_frame_hdr
+Cannot compress 15 .eh_frame
+Cannot compress 16 .init_array
+Cannot compress 17 .fini_array
+Cannot compress 18 .jcr
+Cannot compress 19 .dynamic
+Cannot compress 20 .data
+Cannot compress 21 .opd
+Cannot compress 22 .got
+Cannot compress 23 .plt
+Cannot compress 24 .bss
+Lets compress 25 .comment, size: 88
+Lets compress 26 .debug_aranges, size: 96
+Lets compress 27 .debug_info, size: 363
+Lets compress 28 .debug_abbrev, size: 315
+Lets compress 29 .debug_line, size: 119
+Lets compress 30 .debug_frame, size: 96
+Lets compress 31 .debug_str, size: 174
+Lets compress 32 .debug_loc, size: 171
+Lets compress 33 .debug_ranges, size: 32
+Lets compress 34 .shstrtab, size: 352
+Lets compress 35 .symtab, size: 1800
+Lets compress 36 .strtab, size: 602
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata elf testfileppc64 <<\EOF
+Cannot compress 1 .interp
+Cannot compress 2 .note.ABI-tag
+Cannot compress 3 .note.gnu.build-id
+Cannot compress 4 .gnu.hash
+Cannot compress 5 .dynsym
+Cannot compress 6 .dynstr
+Cannot compress 7 .gnu.version
+Cannot compress 8 .gnu.version_r
+Cannot compress 9 .rela.plt
+Cannot compress 10 .init
+Cannot compress 11 .text
+Cannot compress 12 .fini
+Cannot compress 13 .rodata
+Cannot compress 14 .eh_frame_hdr
+Cannot compress 15 .eh_frame
+Cannot compress 16 .init_array
+Cannot compress 17 .fini_array
+Cannot compress 18 .jcr
+Cannot compress 19 .dynamic
+Cannot compress 20 .data
+Cannot compress 21 .opd
+Cannot compress 22 .got
+Cannot compress 23 .plt
+Cannot compress 24 .bss
+Lets compress 25 .comment, size: 88
+Lets compress 26 .debug_aranges, size: 96
+Lets compress 27 .debug_info, size: 363
+Lets compress 28 .debug_abbrev, size: 315
+Lets compress 29 .debug_line, size: 119
+Lets compress 30 .debug_frame, size: 96
+Lets compress 31 .debug_str, size: 174
+Lets compress 32 .debug_loc, size: 171
+Lets compress 33 .debug_ranges, size: 32
+Lets compress 34 .shstrtab, size: 352
+Lets compress 35 .symtab, size: 1800
+Lets compress 36 .strtab, size: 602
+EOF
+
+# Random ELF32BE testfile
+testfiles testfileppc32
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata gnu testfileppc32 <<\EOF
+Cannot compress 1 .interp
+Cannot compress 2 .note.ABI-tag
+Cannot compress 3 .note.gnu.build-id
+Cannot compress 4 .gnu.hash
+Cannot compress 5 .dynsym
+Cannot compress 6 .dynstr
+Cannot compress 7 .gnu.version
+Cannot compress 8 .gnu.version_r
+Cannot compress 9 .rela.dyn
+Cannot compress 10 .rela.plt
+Cannot compress 11 .init
+Cannot compress 12 .text
+Cannot compress 13 .fini
+Cannot compress 14 .rodata
+Cannot compress 15 .eh_frame_hdr
+Cannot compress 16 .eh_frame
+Cannot compress 17 .init_array
+Cannot compress 18 .fini_array
+Cannot compress 19 .jcr
+Cannot compress 20 .got2
+Cannot compress 21 .dynamic
+Cannot compress 22 .got
+Cannot compress 23 .plt
+Cannot compress 24 .data
+Cannot compress 25 .sdata
+Cannot compress 26 .bss
+Lets compress 27 .comment, size: 88
+Lets compress 28 .debug_aranges, size: 64
+Lets compress 29 .debug_info, size: 319
+Lets compress 30 .debug_abbrev, size: 318
+Lets compress 31 .debug_line, size: 109
+Lets compress 32 .debug_frame, size: 64
+Lets compress 33 .debug_str, size: 179
+Lets compress 34 .debug_loc, size: 99
+Lets compress 35 .debug_ranges, size: 16
+Lets compress 36 .shstrtab, size: 370
+Lets compress 37 .symtab, size: 1232
+Lets compress 38 .strtab, size: 569
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/elfputzdata elf testfileppc32 <<\EOF
+Cannot compress 1 .interp
+Cannot compress 2 .note.ABI-tag
+Cannot compress 3 .note.gnu.build-id
+Cannot compress 4 .gnu.hash
+Cannot compress 5 .dynsym
+Cannot compress 6 .dynstr
+Cannot compress 7 .gnu.version
+Cannot compress 8 .gnu.version_r
+Cannot compress 9 .rela.dyn
+Cannot compress 10 .rela.plt
+Cannot compress 11 .init
+Cannot compress 12 .text
+Cannot compress 13 .fini
+Cannot compress 14 .rodata
+Cannot compress 15 .eh_frame_hdr
+Cannot compress 16 .eh_frame
+Cannot compress 17 .init_array
+Cannot compress 18 .fini_array
+Cannot compress 19 .jcr
+Cannot compress 20 .got2
+Cannot compress 21 .dynamic
+Cannot compress 22 .got
+Cannot compress 23 .plt
+Cannot compress 24 .data
+Cannot compress 25 .sdata
+Cannot compress 26 .bss
+Lets compress 27 .comment, size: 88
+Lets compress 28 .debug_aranges, size: 64
+Lets compress 29 .debug_info, size: 319
+Lets compress 30 .debug_abbrev, size: 318
+Lets compress 31 .debug_line, size: 109
+Lets compress 32 .debug_frame, size: 64
+Lets compress 33 .debug_str, size: 179
+Lets compress 34 .debug_loc, size: 99
+Lets compress 35 .debug_ranges, size: 16
+Lets compress 36 .shstrtab, size: 370
+Lets compress 37 .symtab, size: 1232
+Lets compress 38 .strtab, size: 569
+EOF
+
+exit 0
diff --git a/tests/run-elfstrmerge-test.sh b/tests/run-elfstrmerge-test.sh
new file mode 100755
index 0000000..d08b6fc
--- /dev/null
+++ b/tests/run-elfstrmerge-test.sh
@@ -0,0 +1,40 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Merge string tables of file and check result with elflint.
+testrun_elfcompress()
+{
+    testfile="$1"
+    testfiles ${testfile}
+
+    mergedfile="${testfile}.merged"
+    tempfiles ${mergedfile}
+
+    echo "merging string tables ${testfile} -> ${mergedfile}"
+    testrun ${abs_top_builddir}/tests/elfstrmerge -o ${mergedfile} ${testfile}
+    testrun ${abs_top_builddir}/src/elflint --gnu-ld ${mergedfile}
+}
+
+# Random ELF32 testfile with extra STT_SECTION symbols
+testrun_elfcompress testfile4
+
+# Random ELF64 testfile with extra STT_SECTION symbols
+testrun_elfcompress testfile12
+
+exit 0
diff --git a/tests/run-exprlocs-self.sh b/tests/run-exprlocs-self.sh
new file mode 100755
index 0000000..73d3ab9
--- /dev/null
+++ b/tests/run-exprlocs-self.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Just makes sure exprlocs doesn't crash, triggers self-check/asserts
+# or leaks memory under valgrind.
+testrun_on_self_quiet ${abs_top_builddir}/tests/varlocs --exprlocs -e
diff --git a/tests/run-exprlocs.sh b/tests/run-exprlocs.sh
new file mode 100755
index 0000000..379ca52
--- /dev/null
+++ b/tests/run-exprlocs.sh
@@ -0,0 +1,180 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77589
+#
+# program repro
+#   type small_stride
+#      character*40 long_string
+#      integer      small_pad
+#   end type small_stride
+#   type(small_stride), dimension (20), target :: unpleasant
+#   character*40, pointer, dimension(:):: c40pt
+#   integer i
+#   do i = 0,19
+#      unpleasant(i+1)%small_pad = i+1
+#      unpleasant(i+1)%long_string = char (ichar('0') + i) // '-hello'
+#   end do
+#   c40pt => unpleasant%long_string
+#   print *, c40pt  ! break-here
+# end program repro
+#
+# Needs GCC7+
+# gfortran -o testfile-stridex dwarf-stridex.f90 -Wall -g
+
+testfiles testfile-stridex
+
+testrun_compare ${abs_top_builddir}/tests/varlocs --exprlocs -e testfile-stridex <<\EOF
+module 'testfile-stridex'
+[b] CU 'dwarf-stridex.f90'@400717
+  producer (strp)
+  language (data1)
+  identifier_case (data1)
+  name (strp)
+  comp_dir (strp)
+  low_pc (addr)
+  high_pc (data8)
+  stmt_list (sec_offset)
+  [2e] base_type "integer(kind=8)"
+    byte_size (data1)
+    encoding (data1)
+    name (strp)
+  [35] structure_type "small_stride"
+    name (strp)
+    byte_size (data1)
+    decl_file (data1)
+    decl_line (data1)
+    sibling (ref4)
+    [41] member "long_string"
+      name (strp)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      data_member_location (data1) {plus_uconst(0)}
+    [4d] member "small_pad"
+      name (strp)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      data_member_location (data1) {plus_uconst(40)}
+  [5a] string_type
+    byte_size (data1)
+  [5c] base_type "integer(kind=4)"
+    byte_size (data1)
+    encoding (data1)
+    name (strp)
+  [63] const_type
+    type (ref4)
+  [68] subprogram "main"
+    external (flag_present)
+    name (strp)
+    decl_file (data1)
+    decl_line (data1)
+    type (ref4)
+    low_pc (addr)
+    high_pc (data8)
+    frame_base (exprloc) {call_frame_cfa {bregx(7,8)}}
+    GNU_all_tail_call_sites (flag_present)
+    sibling (ref4)
+    [89] formal_parameter "argc"
+      name (strp)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      location (exprloc) {fbreg(-20)}
+    [97] formal_parameter "argv"
+      name (strp)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      location (exprloc) {fbreg(-32), deref}
+  [a7] pointer_type
+    byte_size (data1)
+    type (ref4)
+  [ad] base_type "character(kind=1)"
+    byte_size (data1)
+    encoding (data1)
+    name (strp)
+  [b4] subprogram "repro"
+    name (strp)
+    decl_file (data1)
+    decl_line (data1)
+    main_subprogram (flag_present)
+    calling_convention (data1)
+    low_pc (addr)
+    high_pc (data8)
+    frame_base (exprloc) {call_frame_cfa {bregx(7,8)}}
+    GNU_all_tail_call_sites (flag_present)
+    sibling (ref4)
+    [d2] variable "c40pt"
+      name (strp)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      location (exprloc) {fbreg(-128)}
+    [e1] variable "span.0"
+      name (strp)
+      type (ref4)
+      artificial (flag_present)
+      location (exprloc) {fbreg(-80)}
+    [ee] variable "i"
+      name (string)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      location (exprloc) {fbreg(-68)}
+    [fb] variable "unpleasant"
+      name (strp)
+      decl_file (data1)
+      decl_line (data1)
+      type (ref4)
+      location (exprloc) {fbreg(-1008)}
+    [10a] lexical_block
+      low_pc (addr)
+      high_pc (data8)
+      sibling (ref4)
+      [11f] lexical_block
+        low_pc (addr)
+        high_pc (data8)
+    [131] lexical_block
+      low_pc (addr)
+      high_pc (data8)
+      [142] lexical_block
+        low_pc (addr)
+        high_pc (data8)
+        [153] lexical_block
+          low_pc (addr)
+          high_pc (data8)
+  [167] array_type
+    data_location (exprloc) {push_object_address, deref}
+    associated (exprloc) {push_object_address, deref, lit0, ne}
+    type (ref4)
+    sibling (ref4)
+    [178] subrange_type
+      lower_bound (exprloc) {push_object_address, plus_uconst(32), deref}
+      upper_bound (exprloc) {push_object_address, plus_uconst(40), deref}
+      byte_stride (exprloc) {push_object_address, plus_uconst(24), deref, GNU_variable_value([e1]) {fbreg(-80)}, mul}
+  [18f] array_type
+    type (ref4)
+    [194] subrange_type
+      type (ref4)
+      upper_bound (sdata)
+EOF
+
+exit 0
diff --git a/tests/run-find-prologues.sh b/tests/run-find-prologues.sh
new file mode 100755
index 0000000..160f07d
--- /dev/null
+++ b/tests/run-find-prologues.sh
@@ -0,0 +1,85 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile11 testfile22 testfile24 \
+	  testfile25 testfile3 testfile4 testfile5 testfile6
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile <<\EOF
+main             0x000000000804842c 0x0000000008048432
+bar              0x000000000804845c 0x000000000804845f
+foo              0x0000000008048468 0x000000000804846b
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile11 <<\EOF
+main             0x00000000080489b8 0x00000000080489cd
+gnu_obj_2        0x0000000008048c9e 0x0000000008048ca4
+gnu_obj_3        0x0000000008048cd8 0x0000000008048cde
+gnu_obj_2        0x0000000008048cf4 0x0000000008048cfa
+~invalid_argument 0x0000000008048d2e 0x0000000008048d34
+gnu_obj_1        0x0000000008048d62 0x0000000008048d65
+gnu_obj_1        0x0000000008048d8a 0x0000000008048d8d
+~invalid_argument 0x0000000008048db2 0x0000000008048db8
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile22 <<\EOF
+function         0x0000000008048348 0x000000000804834e
+main             0x000000000804835b 0x0000000008048377
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile24 <<\EOF
+incr             0x0000000008048348 0x000000000804834e
+main             0x0000000008048354 0x0000000008048360
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile25 <<\EOF
+incr             0x0000000008048348 0x000000000804834c
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile3 <<\EOF
+main             0x000000000804842c 0x0000000008048433
+bar              0x0000000008048458 0x000000000804845b
+foo              0x0000000008048464 0x0000000008048467
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile4 <<\EOF
+get              0x00000000080493fc 0x0000000008049402
+main             0x0000000008049498 0x000000000804949e
+a                0x000000000804d85c 0x000000000804d85c
+__tfPCc          0x000000000804d86c 0x000000000804d872
+__tfCc           0x000000000804d8a4 0x000000000804d8a4
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile5 <<\EOF
+bar              0x000000000804842c 0x000000000804842f
+foo              0x0000000008048438 0x000000000804843b
+main             0x0000000008048444 0x000000000804844a
+EOF
+
+testrun_compare ${abs_builddir}/find-prologues -e testfile6 <<\EOF
+main             0x00000000080489b8 0x00000000080489cd
+gnu_obj_2        0x0000000008048c9e 0x0000000008048ca4
+gnu_obj_3        0x0000000008048cd8 0x0000000008048cde
+gnu_obj_2        0x0000000008048cf4 0x0000000008048cfa
+~invalid_argument 0x0000000008048d2e 0x0000000008048d34
+gnu_obj_1        0x0000000008048d62 0x0000000008048d65
+gnu_obj_1        0x0000000008048d8a 0x0000000008048d8d
+~invalid_argument 0x0000000008048db2 0x0000000008048db8
+EOF
+
+exit 0
diff --git a/tests/run-funcretval++11.sh b/tests/run-funcretval++11.sh
new file mode 100755
index 0000000..fcfefe1
--- /dev/null
+++ b/tests/run-funcretval++11.sh
@@ -0,0 +1,21 @@
+#! /bin/sh
+# Copyright (C) 2023 IBM Corporation
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testrun $abs_builddir/funcretval -e $abs_builddir/funcretval_test++11 \
+    > /dev/null
diff --git a/tests/run-funcretval.sh b/tests/run-funcretval.sh
new file mode 100755
index 0000000..779bd47
--- /dev/null
+++ b/tests/run-funcretval.sh
@@ -0,0 +1,153 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# The following files were obtaining by compiling funcretval_test.c
+# from this directory as follows:
+#
+#   gcc -g funcretval_test.c -o funcretval_test_<YOURARCH>
+#
+# Pass -DFLOAT128 if the given arch supports __float128.
+
+testfiles funcretval_test_aarch64
+
+# funcretval_test_aarch64 was built with additional flag:
+#   -DAARCH64_BUG_1032854
+# hence no fun_vec_double_8.
+testrun_compare ${abs_top_builddir}/tests/funcretval \
+	-e funcretval_test_aarch64 <<\EOF
+() fun_char: return value location: {0x50, 0}
+() fun_short: return value location: {0x50, 0}
+() fun_int: return value location: {0x50, 0}
+() fun_ptr: return value location: {0x50, 0}
+() fun_iptr: return value location: {0x50, 0}
+() fun_long: return value location: {0x50, 0}
+() fun_int128: return value location: {0x50, 0} {0x93, 0x8} {0x51, 0} {0x93, 0x8}
+() fun_large_struct1: return value location: {0x70, 0}
+() fun_large_struct2: return value location: {0x70, 0}
+() fun_float: return value location: {0x90, 0x40}
+() fun_float_complex: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4}
+() fun_double: return value location: {0x90, 0x40}
+() fun_double_complex: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_long_double: return value location: {0x90, 0x40}
+() fun_long_double_complex: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_vec_char_8: return value location: {0x90, 0x40}
+() fun_vec_short_8: return value location: {0x90, 0x40}
+() fun_vec_int_8: return value location: {0x90, 0x40}
+() fun_vec_long_8: return value location: {0x90, 0x40}
+() fun_vec_float_8: return value location: {0x90, 0x40}
+() fun_vec_char_16: return value location: {0x90, 0x40}
+() fun_vec_short_16: return value location: {0x90, 0x40}
+() fun_vec_int_16: return value location: {0x90, 0x40}
+() fun_vec_long_16: return value location: {0x90, 0x40}
+() fun_vec_int128_16: return value location: {0x90, 0x40}
+() fun_vec_float_16: return value location: {0x90, 0x40}
+() fun_vec_double_16: return value location: {0x90, 0x40}
+() fun_hfa1_float: return value location: {0x90, 0x40}
+() fun_hfa1_double: return value location: {0x90, 0x40}
+() fun_hfa1_long_double: return value location: {0x90, 0x40}
+() fun_hfa1_float_a: return value location: {0x90, 0x40}
+() fun_hfa1_double_a: return value location: {0x90, 0x40}
+() fun_hfa1_long_double_a: return value location: {0x90, 0x40}
+() fun_hfa2_float: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4}
+() fun_hfa2_double: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hfa2_long_double: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hfa2_float_a: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4}
+() fun_hfa2_double_a: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hfa2_long_double_a: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hfa3_float: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_hfa3_double: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hfa3_long_double: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hfa3_float_a: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_hfa3_double_a: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hfa3_long_double_a: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hfa4_float: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4} {0x90, 0x43} {0x93, 0x4}
+() fun_hfa4_double: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hfa4_long_double: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hfa4_float_a: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4} {0x90, 0x43} {0x93, 0x4}
+() fun_hfa4_double_a: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hfa4_long_double_a: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_nfa5_float: return value location: {0x70, 0}
+() fun_nfa5_double: return value location: {0x70, 0}
+() fun_nfa5_long_double: return value location: {0x70, 0}
+() fun_nfa5_float_a: return value location: {0x70, 0}
+() fun_nfa5_double_a: return value location: {0x70, 0}
+() fun_nfa5_long_double_a: return value location: {0x70, 0}
+() fun_hva1_vec_char_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_short_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_int_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_long_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_float_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_double_8: return value location: {0x90, 0x40}
+() fun_hva1_vec_char_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_short_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_int_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_long_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_int128_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_float_16_t: return value location: {0x90, 0x40}
+() fun_hva1_vec_double_16_t: return value location: {0x90, 0x40}
+() fun_hva2_vec_char_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_short_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_int_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_long_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_float_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_double_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() fun_hva2_vec_char_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_short_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_int_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_long_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_int128_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_float_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva2_vec_double_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10}
+() fun_hva3_vec_char_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_short_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_int_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_long_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_float_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_double_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_hva3_vec_char_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_short_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_int_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_long_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_int128_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_float_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva3_vec_double_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_hva4_vec_char_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_short_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_int_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_long_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_float_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_double_8: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8} {0x90, 0x43} {0x93, 0x8}
+() fun_hva4_vec_char_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_short_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_int_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_long_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_int128_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_float_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_hva4_vec_double_16_t: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10} {0x90, 0x43} {0x93, 0x10}
+() fun_mixed_hfa3_cff: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_mixed_hfa3_cdd: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_mixed_hfa3_cldld: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_mixed_hfa3_fcf: return value location: {0x90, 0x40} {0x93, 0x4} {0x90, 0x41} {0x93, 0x4} {0x90, 0x42} {0x93, 0x4}
+() fun_mixed_hfa3_dcd: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8} {0x90, 0x42} {0x93, 0x8}
+() fun_mixed_hfa3_ldcld: return value location: {0x90, 0x40} {0x93, 0x10} {0x90, 0x41} {0x93, 0x10} {0x90, 0x42} {0x93, 0x10}
+() fun_mixed_hfa2_fltsht_t: return value location: {0x90, 0x40} {0x93, 0x8} {0x90, 0x41} {0x93, 0x8}
+() main: return value location: {0x50, 0}
+EOF
+
+exit 0
diff --git a/tests/run-funcscopes.sh b/tests/run-funcscopes.sh
new file mode 100755
index 0000000..367729a
--- /dev/null
+++ b/tests/run-funcscopes.sh
@@ -0,0 +1,29 @@
+#! /bin/sh
+# Copyright (C) 2005, 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile25
+
+testrun_compare ${abs_builddir}/funcscopes -e testfile25 incr <<\EOF
+testfile25: 0x8048000 .. 0x8049528
+    inline-test.c (0x11): 0x8048348 (/home/roland/build/stock-elfutils/inline-test.c:7) .. 0x804834e (/home/roland/build/stock-elfutils/inline-test.c:9)
+        incr (0x2e): 0x8048348 (/home/roland/build/stock-elfutils/inline-test.c:7) .. 0x804834e (/home/roland/build/stock-elfutils/inline-test.c:9)
+            x                             [    66]
+EOF
+
+exit 0
diff --git a/tests/run-get-aranges.sh b/tests/run-get-aranges.sh
new file mode 100755
index 0000000..62cae5f
--- /dev/null
+++ b/tests/run-get-aranges.sh
@@ -0,0 +1,68 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/get-aranges testfile testfile2 <<\EOF
+0x804842b: not in range
+CU name: "m.c"
+CU name: "m.c"
+CU name: "m.c"
+0x804845a: not in range
+0x804845b: not in range
+CU name: "b.c"
+CU name: "b.c"
+CU name: "b.c"
+0x8048466: not in range
+0x8048467: not in range
+CU name: "f.c"
+CU name: "f.c"
+CU name: "f.c"
+0x8048472: not in range
+ [ 0] start: 0x804842c, length: 46, cu: 11
+CU name: "m.c"
+ [ 1] start: 0x804845c, length: 10, cu: 202
+CU name: "b.c"
+ [ 2] start: 0x8048468, length: 10, cu: 5628
+CU name: "f.c"
+0x804842b: not in range
+0x804842c: not in range
+0x804843c: not in range
+0x8048459: not in range
+0x804845a: not in range
+0x804845b: not in range
+0x804845c: not in range
+0x8048460: not in range
+0x8048465: not in range
+0x8048466: not in range
+0x8048467: not in range
+0x8048468: not in range
+0x8048470: not in range
+0x8048471: not in range
+0x8048472: not in range
+ [ 0] start: 0x10000470, length: 32, cu: 11
+CU name: "b.c"
+ [ 1] start: 0x10000490, length: 32, cu: 2429
+CU name: "f.c"
+ [ 2] start: 0x100004b0, length: 100, cu: 2532
+CU name: "m.c"
+EOF
+
+exit 0
diff --git a/tests/run-get-files.sh b/tests/run-get-files.sh
new file mode 100755
index 0000000..1306544
--- /dev/null
+++ b/tests/run-get-files.sh
@@ -0,0 +1,248 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2004, 2005, 2007 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/get-files testfile testfile2 <<\EOF
+cuhl = 11, o = 0, asz = 4, osz = 4, ncu = 191
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/m.c"
+cuhl = 11, o = 114, asz = 4, osz = 4, ncu = 5617
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/b.c"
+ file[2] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h"
+ file[3] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h"
+ file[4] = "/usr/include/bits/types.h"
+ file[5] = "/usr/include/bits/sched.h"
+ file[6] = "/usr/include/bits/pthreadtypes.h"
+ file[7] = "/usr/include/stdio.h"
+ file[8] = "/usr/include/libio.h"
+ file[9] = "/usr/include/wchar.h"
+ file[10] = "/usr/include/_G_config.h"
+ file[11] = "/usr/include/gconv.h"
+cuhl = 11, o = 412, asz = 4, osz = 4, ncu = 5752
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/f.c"
+cuhl = 11, o = 0, asz = 4, osz = 4, ncu = 2418
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/b.c"
+ file[2] = "/home/geoffk/objs/laurel-000912-branch/lib/gcc-lib/powerpc-unknown-linux-gnu/2.96-laurel-000912/include/stddef.h"
+ file[3] = "/home/geoffk/objs/laurel-000912-branch/lib/gcc-lib/powerpc-unknown-linux-gnu/2.96-laurel-000912/include/stdarg.h"
+ file[4] = "/shoggoth/drepper/<built-in>"
+ file[5] = "/usr/include/bits/types.h"
+ file[6] = "/usr/include/stdio.h"
+ file[7] = "/usr/include/libio.h"
+ file[8] = "/usr/include/_G_config.h"
+cuhl = 11, o = 213, asz = 4, osz = 4, ncu = 2521
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/f.c"
+cuhl = 11, o = 267, asz = 4, osz = 4, ncu = 2680
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/m.c"
+EOF
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun_compare ${abs_builddir}/get-files testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo <<\EOF
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 52
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+cuhl = 11, o = 26, asz = 8, osz = 4, ncu = 104
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 414
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 331
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+EOF
+
+testrun_compare ${abs_builddir}/get-files testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo <<\EOF
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 53
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "/home/mark/src/elfutils/tests/hello.c"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+cuhl = 20, o = 21, asz = 8, osz = 4, ncu = 106
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/mark/src/elfutils/tests/world.c"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 386
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "/home/mark/src/elfutils/tests/hello.c"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 296
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/mark/src/elfutils/tests/world.c"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+
+testrun_compare ${abs_builddir}/get-files testfile-dwp-5 << EOF
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 53
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 20, o = 21, asz = 8, osz = 4, ncu = 106
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 20, o = 42, asz = 8, osz = 4, ncu = 155
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+# Note that this one includes the type units in .debug_info.dwo as expected.
+testrun_compare ${abs_builddir}/get-files testfile-dwp-5.dwp << EOF
+cuhl = 24, o = 0, asz = 8, osz = 4, ncu = 112
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 376
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 24, o = 0, asz = 8, osz = 4, ncu = 486
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 606
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 1009
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+testrun_compare ${abs_builddir}/get-files testfile-dwp-4 << EOF
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 56
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 11, o = 29, asz = 8, osz = 4, ncu = 108
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 11, o = 55, asz = 8, osz = 4, ncu = 160
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+testrun_compare ${abs_builddir}/get-files testfile-dwp-4.dwp << EOF
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 286
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 404
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 857
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+exit 0
diff --git a/tests/run-get-lines.sh b/tests/run-get-lines.sh
new file mode 100755
index 0000000..0c4e338
--- /dev/null
+++ b/tests/run-get-lines.sh
@@ -0,0 +1,335 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2004, 2005, 2013 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2 testfilenolines
+
+testrun_compare ${abs_builddir}/get-lines testfile testfile2 <<\EOF
+cuhl = 11, o = 0, asz = 4, osz = 4, ncu = 191
+ 5 lines
+804842c: /home/drepper/gnu/new-bu/build/ttt/m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048432: /home/drepper/gnu/new-bu/build/ttt/m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804844d: /home/drepper/gnu/new-bu/build/ttt/m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048458: /home/drepper/gnu/new-bu/build/ttt/m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845a: /home/drepper/gnu/new-bu/build/ttt/m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 114, asz = 4, osz = 4, ncu = 5617
+ 4 lines
+804845c: /home/drepper/gnu/new-bu/build/ttt/b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845f: /home/drepper/gnu/new-bu/build/ttt/b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048464: /home/drepper/gnu/new-bu/build/ttt/b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048466: /home/drepper/gnu/new-bu/build/ttt/b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 412, asz = 4, osz = 4, ncu = 5752
+ 4 lines
+8048468: /home/drepper/gnu/new-bu/build/ttt/f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804846b: /home/drepper/gnu/new-bu/build/ttt/f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048470: /home/drepper/gnu/new-bu/build/ttt/f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048472: /home/drepper/gnu/new-bu/build/ttt/f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 0, asz = 4, osz = 4, ncu = 2418
+ 4 lines
+10000470: /shoggoth/drepper/b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1000047c: /shoggoth/drepper/b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000480: /shoggoth/drepper/b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000490: /shoggoth/drepper/b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 213, asz = 4, osz = 4, ncu = 2521
+ 4 lines
+10000490: /shoggoth/drepper/f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1000049c: /shoggoth/drepper/f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004a0: /shoggoth/drepper/f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004b0: /shoggoth/drepper/f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 267, asz = 4, osz = 4, ncu = 2680
+ 5 lines
+100004b0: /shoggoth/drepper/m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004cc: /shoggoth/drepper/m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004e8: /shoggoth/drepper/m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004f4: /shoggoth/drepper/m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000514: /shoggoth/drepper/m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+# - lines.c
+# int ft;
+#
+# int
+# main (int argc, char **argv)
+# {
+#   return ft - 42;
+# }
+#
+# - nolines.c
+# int ft = 42;
+#
+# gcc -g -c lines.c
+# gcc -g -c nolines.c
+# gcc -g -o testfilenolines lines.o nolines.o
+
+testrun_compare ${abs_builddir}/get-lines testfilenolines <<\EOF
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 169
+ 4 lines
+400474: /home/mark/src/tests/lines.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40047f: /home/mark/src/tests/lines.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+400488: /home/mark/src/tests/lines.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40048a: /home/mark/src/tests/lines.c:7:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 125, asz = 8, osz = 4, ncu = 243
+ 0 lines
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+
+testrun_compare ${abs_builddir}/get-lines testfile-dwp-5 << EOF
+cuhl = 20, o = 0, asz = 8, osz = 4, ncu = 53
+ 63 lines
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401192: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401196: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bc: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:15:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:11: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c5: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cd: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d7: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:19:10: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f0: /home/osandov/src/elfutils/tests/foo.cc:20:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011fc: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 20, o = 21, asz = 8, osz = 4, ncu = 106
+ 7 lines
+401200: /home/osandov/src/elfutils/tests/bar.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401204: /home/osandov/src/elfutils/tests/bar.cc:8:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401207: /home/osandov/src/elfutils/tests/bar.cc:11:18: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121a: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121b: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 20, o = 42, asz = 8, osz = 4, ncu = 155
+ 41 lines
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401021: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401028: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40102c: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/main.cc:9:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:17:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:20:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401032: /home/osandov/src/elfutils/tests/main.cc:8:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401036: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40103f: /home/osandov/src/elfutils/tests/foobar.h:25:25: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401044: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401049: /home/osandov/src/elfutils/tests/foobar.h:23:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401050: /home/osandov/src/elfutils/tests/foobar.h:27:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401053: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401056: /home/osandov/src/elfutils/tests/foobar.h:27:9: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:28:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401065: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401068: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401076: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401080: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401085: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108a: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108c: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401091: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401095: /home/osandov/src/elfutils/tests/main.cc:10:22: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401097: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401099: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4010a0: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+testrun_compare ${abs_builddir}/get-lines testfile-dwp-4 << EOF
+cuhl = 11, o = 0, asz = 8, osz = 4, ncu = 56
+ 63 lines
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401192: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401196: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bc: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:15:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:11: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c5: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cd: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d7: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:19:10: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f0: /home/osandov/src/elfutils/tests/foo.cc:20:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011fc: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 29, asz = 8, osz = 4, ncu = 108
+ 7 lines
+401200: /home/osandov/src/elfutils/tests/bar.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401204: /home/osandov/src/elfutils/tests/bar.cc:8:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401207: /home/osandov/src/elfutils/tests/bar.cc:11:18: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121a: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121b: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+cuhl = 11, o = 55, asz = 8, osz = 4, ncu = 160
+ 41 lines
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401021: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401028: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40102c: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/main.cc:9:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:17:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:20:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401032: /home/osandov/src/elfutils/tests/main.cc:8:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401036: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40103f: /home/osandov/src/elfutils/tests/foobar.h:25:25: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401044: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401049: /home/osandov/src/elfutils/tests/foobar.h:23:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401050: /home/osandov/src/elfutils/tests/foobar.h:27:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401053: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401056: /home/osandov/src/elfutils/tests/foobar.h:27:9: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:28:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401065: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401068: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401076: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401080: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401085: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108a: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108c: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401091: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401095: /home/osandov/src/elfutils/tests/main.cc:10:22: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401097: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401099: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4010a0: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+exit 0
diff --git a/tests/run-get-pubnames.sh b/tests/run-get-pubnames.sh
new file mode 100755
index 0000000..912793e
--- /dev/null
+++ b/tests/run-get-pubnames.sh
@@ -0,0 +1,50 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2003, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/get-pubnames testfile testfile2 <<\EOF
+ [ 0] "main", die: 104, cu: 11
+CU name: "m.c"
+object name: "main"
+ [ 1] "a", die: 174, cu: 11
+CU name: "m.c"
+object name: "a"
+ [ 2] "bar", die: 295, cu: 202
+CU name: "b.c"
+object name: "bar"
+ [ 3] "foo", die: 5721, cu: 5628
+CU name: "f.c"
+object name: "foo"
+ [ 0] "bar", die: 72, cu: 11
+CU name: "b.c"
+object name: "bar"
+ [ 1] "foo", die: 2490, cu: 2429
+CU name: "f.c"
+object name: "foo"
+ [ 2] "main", die: 2593, cu: 2532
+CU name: "m.c"
+object name: "main"
+ [ 3] "a", die: 2663, cu: 2532
+CU name: "m.c"
+object name: "a"
+EOF
+
+exit 0
diff --git a/tests/run-get-units-invalid.sh b/tests/run-get-units-invalid.sh
new file mode 100755
index 0000000..66ef944
--- /dev/null
+++ b/tests/run-get-units-invalid.sh
@@ -0,0 +1,44 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-typeiter.sh
+testfiles testfile-debug-types
+
+testrun ${abs_builddir}/get-units-invalid testfile-debug-types
+
+# see run-readelf-dwz-multi.sh
+testfiles testfile_multi_main testfile_multi.dwz
+
+testrun ${abs_builddir}/get-units-invalid testfile_multi_main
+
+# see tests/run-dwflsyms.sh
+testfiles testfilebazdbgppc64.debug
+
+testrun ${abs_builddir}/get-units-invalid testfilebazdbgppc64.debug
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-4 testfile-dwarf-5
+
+testrun ${abs_builddir}/get-units-invalid testfile-dwarf-4
+testrun ${abs_builddir}/get-units-invalid testfile-dwarf-5
+
+# Self test
+testrun_on_self ${abs_builddir}/get-units-invalid
+
+exit 0
diff --git a/tests/run-get-units-split.sh b/tests/run-get-units-split.sh
new file mode 100755
index 0000000..6c7a4f2
--- /dev/null
+++ b/tests/run-get-units-split.sh
@@ -0,0 +1,84 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-typeiter.sh
+testfiles testfile-debug-types
+
+testrun ${abs_builddir}/get-units-split testfile-debug-types
+
+# see run-readelf-dwz-multi.sh
+testfiles testfile_multi_main testfile_multi.dwz
+
+testrun ${abs_builddir}/get-units-split testfile_multi_main
+
+# see tests/run-dwflsyms.sh
+testfiles testfilebazdbgppc64.debug
+
+testrun ${abs_builddir}/get-units-split testfilebazdbgppc64.debug
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-4 testfile-dwarf-5
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun ${abs_builddir}/get-units-split testfile-dwarf-4
+testrun ${abs_builddir}/get-units-split testfile-dwarf-5
+
+# These two files are the only ones that actually have skeleton units.
+testrun_compare ${abs_builddir}/get-units-split testfile-splitdwarf-4 << \EOF
+file: testfile-splitdwarf-4
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: hello.c
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: world.c
+
+EOF
+
+testrun_compare ${abs_builddir}/get-units-split testfile-splitdwarf-5 << \EOF
+file: testfile-splitdwarf-5
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: hello.c
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: world.c
+
+EOF
+
+# Self test (Not on obj files since those need relocation first).
+testrun_on_self_exe ${abs_builddir}/get-units-split
+testrun_on_self_lib ${abs_builddir}/get-units-split
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+testfiles testfile-dwp-4-strict testfile-dwp-4-strict.dwp
+
+for file in testfile-dwp-5 testfile-dwp-4 testfile-dwp-4-strict; do
+	testrun_compare ${abs_builddir}/get-units-split "$file" << EOF
+file: $file
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: foo.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: bar.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: main.cc
+
+EOF
+done
+
+exit 0
diff --git a/tests/run-getphdrnum.sh b/tests/run-getphdrnum.sh
new file mode 100755
index 0000000..889cdaf
--- /dev/null
+++ b/tests/run-getphdrnum.sh
@@ -0,0 +1,137 @@
+#! /bin/sh
+
+# testfile-phdrs.elf generated with python3 script
+# import struct
+# import sys
+# 
+# phnum = 66000
+# 
+# sys.stdout.buffer.write(
+#     struct.pack(
+#         "<16BHHIQQQIHHHHHH",
+#         # EI_MAG
+#         *b"\x7fELF",
+#         # EI_CLASS = ELFCLASS64
+#         2,
+#         # EI_DATA = ELFDATA2LSB
+#         1,
+#         # EI_VERSION
+#         1,
+#         # EI_OSABI = ELFOSABI_SYSV
+#         0,
+#         # EI_ABIVERSION
+#         0,
+#         # EI_PAD
+#         *bytes(7),
+#         # e_type = ET_CORE
+#         4,
+#         # e_machine = EM_X86_64
+#         62,
+#         # e_version
+#         1,
+#         # e_entry
+#         0,
+#         # e_phoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Shdr)
+#         128,
+#         # e_shoff = sizeof(Elf64_Ehdr)
+#         64,
+#         # e_flags
+#         0,
+#         # e_ehsize
+#         64,
+#         # e_phentsize
+#         56,
+#         # e_phnum = PN_XNUM
+#         0xFFFF,
+#         # e_shentsize
+#         64,
+#         # e_shnum
+#         1,
+#         # e_shstrndx
+#         0,
+#     )
+# )
+# 
+# sys.stdout.buffer.write(
+#     struct.pack(
+#         "<IIQQQQIIQQ",
+#         # sh_name
+#         0,
+#         # sh_type = SHT_NULL
+#         0,
+#         # sh_flags
+#         0,
+#         # sh_addr
+#         0,
+#         # sh_offset
+#         0,
+#         # sh_size
+#         0,
+#         # sh_link
+#         0,
+#         # sh_info
+#         phnum,
+#         # sh_addralign
+#         0,
+#         # sh_entsize
+#         0,
+#     )
+# )
+# 
+# for i in range(phnum):
+#     sys.stdout.buffer.write(
+#         struct.pack(
+#             "<IIQQQQQQ",
+#             # p_type = PT_LOAD
+#             1,
+#             # p_flags = PF_X|PF_W|PF_R
+#             0x7,
+#             # p_offset
+#             0,
+#             # p_vaddr
+#             # i * 4096,
+#             4096,
+#             # p_paddr
+#             0,
+#             # p_filesz
+#             0,
+#             # p_memsz
+#             4096,
+#             # p_align
+#             0,
+#         )
+#     )
+
+. $srcdir/test-subr.sh
+
+testfiles testfile-phdrs.elf
+
+testrun_compare ${abs_top_builddir}/src/readelf -h testfile-phdrs.elf<<\EOF
+ELF Header:
+  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
+  Class:                             ELF64
+  Data:                              2's complement, little endian
+  Ident Version:                     1 (current)
+  OS/ABI:                            UNIX - System V
+  ABI Version:                       0
+  Type:                              CORE (Core file)
+  Machine:                           AMD x86-64
+  Version:                           1 (current)
+  Entry point address:               0
+  Start of program headers:          128 (bytes into file)
+  Start of section headers:          64 (bytes into file)
+  Flags:                             
+  Size of this header:               64 (bytes)
+  Size of program header entries:    56 (bytes)
+  Number of program headers entries: 65535 (66000 in [0].sh_info)
+  Size of section header entries:    64 (bytes)
+  Number of section headers entries: 1
+  Section header string table index: 0
+
+EOF
+
+testrun_compare ${abs_builddir}/getphdrnum testfile-phdrs.elf<<\EOF
+66000
+EOF
+
+exit 0
diff --git a/tests/run-getsrc-die.sh b/tests/run-getsrc-die.sh
new file mode 100755
index 0000000..6740e5d
--- /dev/null
+++ b/tests/run-getsrc-die.sh
@@ -0,0 +1,71 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-addr2line-test.sh run-addr2line-i-test.sh run-addr2line-i-lex-test.sh
+# Output/files/lines matched should equal what is done through addr2line
+# which uses dwfl_module_getsrc. This test uses dwarf_addrdie and
+# dwarf_getsrc_die
+testfiles testfile testfile-inlines testfile-lex-inlines
+tempfiles testfile-no-aranges testfile-inlines-no-aranges getsrc_die.out
+tempfiles testfile-lex-inlines-no-aranges good1.out good2.out good3.out
+
+cat > good1.out <<\EOF
+/home/drepper/gnu/new-bu/build/ttt/f.c:3
+/home/drepper/gnu/new-bu/build/ttt/b.c:4
+EOF
+
+cat good1.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile 0x08048468 0x0804845c
+
+cat > good2.out <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:6
+/tmp/x.cpp:10
+/tmp/x.cpp:11
+/tmp/x.cpp:5
+/tmp/x.cpp:10
+/tmp/x.cpp:5
+/tmp/x.cpp:10
+/tmp/x.cpp:10
+/tmp/x.cpp:5
+EOF
+
+cat good2.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-inlines 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f1 0x00000000000005f2
+
+cat > good3.out <<\EOF
+/tmp/x.cpp:5
+/tmp/x.cpp:5
+/tmp/x.cpp:5
+/tmp/x.cpp:5
+EOF
+
+cat good3.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-lex-inlines 0x0000000000000680 0x0000000000000681 0x0000000000000690 0x0000000000000691
+
+# Each test should also pass with no .debug_aranges present.  If objcopy cannot
+# strip the testfiles then skip the remaining tests.
+objcopy --remove-section .debug_aranges testfile testfile-no-aranges || exit 0
+objcopy --remove-section .debug_aranges testfile-inlines testfile-inlines-no-aranges || exit 0
+objcopy --remove-section .debug_aranges testfile-lex-inlines testfile-lex-inlines-no-aranges || exit 0
+
+cat good1.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-no-aranges 0x08048468 0x0804845c
+
+cat good2.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-inlines-no-aranges 0x00000000000005a0 0x00000000000005a1 0x00000000000005b0 0x00000000000005b1 0x00000000000005c0 0x00000000000005d0 0x00000000000005e0 0x00000000000005e1 0x00000000000005f1 0x00000000000005f2
+
+cat good3.out | testrun_compare ${abs_top_builddir}/tests/getsrc_die testfile-lex-inlines-no-aranges 0x0000000000000680 0x0000000000000681 0x0000000000000690 0x0000000000000691
+
+exit 0
diff --git a/tests/run-large-elf-file.sh b/tests/run-large-elf-file.sh
new file mode 100755
index 0000000..8108cb4
--- /dev/null
+++ b/tests/run-large-elf-file.sh
@@ -0,0 +1,299 @@
+#! /usr/bin/env bash
+# Copyright (C) 2019 Red Hat, Inc.
+# Copyright (C) 2022 Mark J. Wielaard <mark@klomp.org>
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Only run on 64bit systems, 32bit systems don't support > 4GB
+# ELF files.
+long_bit=$(getconf LONG_BIT)
+echo "long_bit: $long_bit"
+if test $long_bit -ne 64; then
+  echo "Only 64bit systems can create > 4GB ELF files"
+  exit 77
+fi
+
+# The test binary also needs to be 64bits itself
+elfclass=64
+testrun ${abs_top_builddir}/src/readelf -h ${abs_builddir}/addsections | grep ELF32 \
+	&& elfclass=32
+echo elfclass: $elfclass
+if test $elfclass -ne 64; then
+  echo "Only 64bit binaries can create > 4GB ELF files"
+  exit 77
+fi
+
+# These tests need lots of disk space since they test files > 4GB.
+# Skip if there just isn't enough (2.5 * 4 = 10GB).
+space_available=$[$(stat -f --format="%a*%S" .)/(1024 * 1024 * 1024)]
+echo "space_available: $space_available"
+if test $space_available -lt 10; then
+  echo "Not enough disk space, need at least 10GB available"
+  exit 77
+fi
+
+# Make sure the files fit into memory, assume 6GB needed (2.5 * 2 + 1 extra).
+# Running under valgrind might need even more.
+mem_needed=6
+if [ "x$VALGRIND_CMD" != "x" ]; then
+  mem_needed=$[${mem_needed} + 2]
+fi
+echo "mem_needed: $mem_needed"
+mem_available=$(free -g 2>/dev/null | grep ^Mem: | awk -F ' +' '{print $7}')
+echo "mem_available: $mem_available"
+if test -z "$mem_available" || test $mem_available -lt $mem_needed; then
+  echo "Need at least ${mem_needed}GB free available memory"
+  exit 77
+fi
+
+# Make sure the disk is reasonably fast, should be able to write 100MB/s
+fast_disk=1
+timeout -s9 10s dd conv=fsync if=/dev/zero of=tempfile bs=1M count=1K \
+  || fast_disk=0; rm tempfile
+if test $fast_disk -eq 0; then
+  echo "File system not fast enough, need at least 100MB/s"
+  exit 77
+fi
+
+# NOTE: test file will be mangled and removed!
+test_file ()
+{
+  in_file="$1"
+  readelf_out="${in_file}.readelf.out"
+  out_file_strip="${in_file}.strip"
+  out_file_debug="${in_file}.debug"
+
+  testfiles ${in_file}
+  tempfiles ${readelf_out} ${out_file_mmap} ${out_file_strip} ${out_file_debug}
+
+  # Add two 2GB sections to the file.
+  echo "addsections 2 ${in_file} 2147483648"
+  testrun ${abs_builddir}/addsections 2 ${in_file} 2147483648
+  testrun ${abs_top_builddir}/src/readelf -S ${in_file} > ${readelf_out}
+  nr=$(grep '.extra' ${readelf_out} | wc -l)
+  if test ${nr} != 2; then
+    # Show what went wrong
+    cat ${readelf_out}
+    exit 1
+  fi
+
+  echo "strip -o ${out_file_strip} -f ${out_file_debug} ${in_file}"
+  testrun ${abs_top_builddir}/src/strip -o ${out_file_strip} \
+                                        -f ${out_file_debug} ${in_file}
+
+  echo "elflint --gnu ${out_file_strip}"
+  testrun ${abs_top_builddir}/src/elflint --gnu ${out_file_strip}
+
+  echo "elflint --gnu -d ${out_file_debug}"
+  testrun ${abs_top_builddir}/src/elflint --gnu -d ${out_file_debug}
+
+  # Now test unstrip recombining those files.
+  echo "unstrip ${out_file_strip} ${out_file_debug}"
+  testrun ${abs_top_builddir}/src/unstrip ${out_file_strip} ${out_file_debug}
+
+  echo "elfcmp ${out_file} ${out_file_strip}"
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file_debug}
+
+  # Remove the temp files immediately, they are big...
+  rm -f ${in_file} ${out_file_strip} ${out_file_debug}
+}
+
+# A collection of random testfiles to test 64bit, little/big endian
+# and non-ET_REL (with phdrs)/ET_REL (without phdrs).
+# Don't test 32bit, they cannot go beyond 4GB.
+
+# 64bit, little endian, rel
+test_file testfile38
+
+# 64bit, big endian, non-rel
+test_file testfile27
+
+# See testfile-dwp-cu-index-overflow.source
+testfiles testfile-dwp-5-cu-index-overflow testfile-dwp-5-cu-index-overflow.dwp
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-5-cu-index-overflow.dwp << EOF
+file: testfile-dwp-5-cu-index-overflow.dwp
+INFO: 0x0 0x8000004c
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x50
+LINE: 0x0 0x61
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x0 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x8000004c 0x6f
+TYPES: 0x0 0x0
+ABBREV: 0x50 0x15e
+LINE: 0x61 0x63
+LOCLISTS: 0x0 0xd4
+STR_OFFSETS: 0x1c 0x24
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x22
+
+INFO: 0x800000bb 0xff
+TYPES: 0x0 0x0
+ABBREV: 0x50 0x15e
+LINE: 0x61 0x63
+LOCLISTS: 0x0 0xd4
+STR_OFFSETS: 0x1c 0x24
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x22
+
+INFO: 0x800001ba 0x8000004c
+TYPES: 0x0 0x0
+ABBREV: 0x1ae 0x50
+LINE: 0xc4 0x61
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x40 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x100000206 0x6c
+TYPES: 0x0 0x0
+ABBREV: 0x1fe 0xc8
+LINE: 0x125 0x63
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x5c 0x20
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x100000272 0x6f
+TYPES: 0x0 0x0
+ABBREV: 0x1fe 0xc8
+LINE: 0x125 0x63
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x5c 0x20
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x1000002e1 0x182
+TYPES: 0x0 0x0
+ABBREV: 0x2c6 0x188
+LINE: 0x188 0x65
+LOCLISTS: 0xd4 0xee
+STR_OFFSETS: 0x7c 0x44
+MACRO: 0x0 0x0
+RNGLISTS: 0x22 0x43
+
+EOF
+
+testrun_compare ${abs_builddir}/get-units-split testfile-dwp-5-cu-index-overflow << EOF
+file: testfile-dwp-5-cu-index-overflow
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler1.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: foo.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler2.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: bar.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: main.cc
+
+EOF
+
+rm -f testfile-dwp-5-cu-index-overflow testfile-dwp-5-cu-index-overflow.dwp
+
+# See testfile-dwp-cu-index-overflow.source
+testfiles testfile-dwp-4-cu-index-overflow testfile-dwp-4-cu-index-overflow.dwp
+
+testrun_compare ${abs_builddir}/cu-dwp-section-info testfile-dwp-4-cu-index-overflow.dwp << EOF
+file: testfile-dwp-4-cu-index-overflow.dwp
+INFO: 0x0 0x8000004b
+TYPES: 0x0 0x0
+ABBREV: 0x0 0x58
+LINE: 0x0 0x2c
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x0 0x14
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x8000004b 0x116
+TYPES: 0x0 0x0
+ABBREV: 0x58 0x16f
+LINE: 0x2c 0x34
+LOCLISTS: 0x0 0x110
+STR_OFFSETS: 0x14 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x80000161 0x8000004b
+TYPES: 0x0 0x0
+ABBREV: 0x1c7 0x58
+LINE: 0x60 0x2c
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x30 0x14
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x1000001ac 0x6e
+TYPES: 0x0 0x0
+ABBREV: 0x21f 0xd4
+LINE: 0x8c 0x34
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x44 0x18
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x10000021a 0x1b5
+TYPES: 0x0 0x0
+ABBREV: 0x2f3 0x19b
+LINE: 0xc0 0x35
+LOCLISTS: 0x110 0x12a
+STR_OFFSETS: 0x5c 0x3c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x0 0x6e
+ABBREV: 0x58 0x16f
+LINE: 0x2c 0x34
+LOCLISTS: 0x0 0x110
+STR_OFFSETS: 0x14 0x1c
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+INFO: 0x0 0x0
+TYPES: 0x6e 0x6b
+ABBREV: 0x21f 0xd4
+LINE: 0x8c 0x34
+LOCLISTS: 0x0 0x0
+STR_OFFSETS: 0x44 0x18
+MACRO: 0x0 0x0
+RNGLISTS: 0x0 0x0
+
+EOF
+
+testrun_compare ${abs_builddir}/get-units-split testfile-dwp-4-cu-index-overflow << EOF
+file: testfile-dwp-4-cu-index-overflow
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler1.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: foo.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: filler2.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: bar.cc
+Got cudie unit_type: 4
+Found a skeleton unit, with split die: main.cc
+
+EOF
+
+rm -f testfile-dwp-4-cu-index-overflow testfile-dwp-4-cu-index-overflow.dwp
+
+exit 0
diff --git a/tests/run-lfs-symbols.sh b/tests/run-lfs-symbols.sh
new file mode 100755
index 0000000..88c6270
--- /dev/null
+++ b/tests/run-lfs-symbols.sh
@@ -0,0 +1,89 @@
+#! /usr/bin/env bash
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if ! grep -q -F '#define _FILE_OFFSET_BITS' ${abs_top_builddir}/config.h; then
+  echo "LFS testing is irrelevant on this system"
+  exit 77
+fi
+
+# #include <stdio.h>
+# int main () {
+#     FILE *f = fopen ("/dev/null", "r");
+#     return f == NULL;
+# }
+#
+# Built for Linux i686, without setting _FILE_OFFSET_BITS.
+# $ gcc -m32 -O2 nolfs.c -o testfile-nolfs
+testfiles testfile-nolfs
+
+LFS_FORMAT='BEGIN {
+  while ((getline < "%s") > 0)
+    /^\w/ && bad[$0]
+  FS="@"
+}
+/@@GLIBC_/ && $1 in bad { print $1 }'
+
+LFS=$(printf "$LFS_FORMAT" "${abs_srcdir}/lfs-symbols")
+
+makeprint() {
+  make print-$1 -C $2 |& gawk -F= "/^$1=/{ print \$2 }"
+}
+
+testrun_lfs() {
+  echo "checking $1"
+  if [ -e "$1" ]; then
+    bad=$(testrun ${abs_top_builddir}/src/nm -u "$1" | gawk "$LFS")
+    if [ -n "$bad" ]; then
+      echo "$1 contains non-lfs symbols:" $bad
+      exit_status=1
+    fi
+  else
+    echo "$1 doesn't exist"
+    exit_status=1
+  fi
+}
+
+echo First sanity-check that LFS detection works.
+exit_status=0
+testrun_lfs ./testfile-nolfs
+if [ $exit_status -eq 0 ]; then
+  echo "Didn't detect any problem with testfile-nolfs!"
+  exit 99
+fi
+echo
+
+exit_status=0
+
+echo Check all normal build targets.
+for dir in libelf libdw libasm libcpu src; do
+  dir=${abs_top_builddir}/$dir
+  for program in $(makeprint PROGRAMS $dir); do
+    testrun_lfs $dir/$program
+  done
+done
+echo
+
+echo Check all test programs.
+dir=${abs_builddir}
+for program in $(makeprint check_PROGRAMS $dir); do
+  testrun_lfs $dir/$program
+done
+echo
+
+exit $exit_status
diff --git a/tests/run-line2addr.sh b/tests/run-line2addr.sh
new file mode 100755
index 0000000..3b6c445
--- /dev/null
+++ b/tests/run-line2addr.sh
@@ -0,0 +1,49 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2 testfile8 testfile14 testfile23
+
+testrun_compare ${abs_builddir}/line2addr -e testfile f.c:4 testfile f.c:8 <<\EOF
+f.c:4 -> 0x804846b (/home/drepper/gnu/new-bu/build/ttt/f.c:4)
+EOF
+
+testrun_compare ${abs_builddir}/line2addr -e testfile2 m.c:6 b.c:1 <<\EOF
+m.c:6 -> 0x100004cc (/shoggoth/drepper/m.c:6)
+b.c:1 -> 0x10000470 (/shoggoth/drepper/b.c:4)
+EOF
+
+testrun_compare ${abs_builddir}/line2addr -e testfile8 strip.c:953 strip.c:365 <<\EOF
+strip.c:953 -> (.text)+0x169f (/home/drepper/gnu/elfutils/build/src/../../src/strip.c:953)
+strip.c:953 -> (.text)+0x16aa (/home/drepper/gnu/elfutils/build/src/../../src/strip.c:953)
+strip.c:365 -> (.text)+0x278b (/home/drepper/gnu/elfutils/build/src/../../src/strip.c:365)
+strip.c:365 -> (.text)+0x2797 (/home/drepper/gnu/elfutils/build/src/../../src/strip.c:365)
+EOF
+
+testrun_compare ${abs_builddir}/line2addr -e testfile14 v.c:6 <<\EOF
+v.c:6 -> 0x400468 (/home/drepper/local/elfutils-build/20050425/v.c:6)
+v.c:6 -> 0x400487 (/home/drepper/local/elfutils-build/20050425/v.c:6)
+EOF
+
+testrun_compare ${abs_builddir}/line2addr -e testfile23 foo.c:2 foo.c:6 <<\EOF
+foo.c:2 -> (.init.text)+0xc (/home/roland/stock-elfutils-build/foo.c:2)
+foo.c:6 -> (.text)+0xc (/home/roland/stock-elfutils-build/foo.c:6)
+EOF
+
+exit 0
diff --git a/tests/run-linkmap-cut.sh b/tests/run-linkmap-cut.sh
new file mode 100755
index 0000000..053b96d
--- /dev/null
+++ b/tests/run-linkmap-cut.sh
@@ -0,0 +1,32 @@
+#! /usr/bin/env bash
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# The core file has patched:
+# * _r_debug.r_map.l_next.l_next (vma 0x3fdf621718, offset 0x7718) = NULL,
+#   therefore all libraries after the main executable and vDSO are removed.
+# * NT_FILE absolute filenames are relativized to: ./////basename
+
+testfiles linkmap-cut-lib.so linkmap-cut linkmap-cut.core
+tempfiles bt
+# It may have non-zero exit code with:
+# .../elfutils/src/stack: dwfl_thread_getframes tid 3130 at 0x3fdf821d64 in /usr/lib64/libc-2.18.so: no matching address range
+testrun ${abs_top_builddir}/src/stack --core=linkmap-cut.core -e linkmap-cut -m >bt || true
+cat bt
+grep -q '^#0  0x00007f08bc24d681 libfunc - .////////////////////////////////////linkmap-cut-lib\.so$' bt
+grep -q '^#1  0x00000000004006b4 main - linkmap-cut$' bt
diff --git a/tests/run-low_high_pc-dw-form-indirect.sh b/tests/run-low_high_pc-dw-form-indirect.sh
new file mode 100755
index 0000000..6902982
--- /dev/null
+++ b/tests/run-low_high_pc-dw-form-indirect.sh
@@ -0,0 +1,23 @@
+#! /bin/sh
+# Copyright (C) 2021 Facebook
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-readelf-dw-form-indirect
+testfiles testfile-dw-form-indirect
+
+testrun ${abs_builddir}/low_high_pc -e ./testfile-dw-form-indirect
diff --git a/tests/run-low_high_pc.sh b/tests/run-low_high_pc.sh
new file mode 100755
index 0000000..41ec420
--- /dev/null
+++ b/tests/run-low_high_pc.sh
@@ -0,0 +1,41 @@
+#! /bin/sh
+# Copyright (C) 2005, 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# int
+# main (int argc, char **argv)
+# {
+#   return 0;
+# }
+# gcc -g -o main main.c
+testfiles testfile_low_high_pc
+
+testrun ${abs_builddir}/low_high_pc -e ./testfile_low_high_pc
+testrun ${abs_builddir}/low_high_pc -e ${abs_builddir}/low_high_pc
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-splitdwarf-5
+testfiles testfile-hello4.dwo testfile-hello5.dwo
+testfiles testfile-world4.dwo testfile-world5.dwo
+
+testrun ${abs_builddir}/low_high_pc -e testfile-splitdwarf-4
+testrun ${abs_builddir}/low_high_pc -e testfile-splitdwarf-5
+
+testrun_on_self ${abs_builddir}/low_high_pc -e
+
+exit 0
diff --git a/tests/run-macro-test.sh b/tests/run-macro-test.sh
new file mode 100755
index 0000000..79b0d88
--- /dev/null
+++ b/tests/run-macro-test.sh
@@ -0,0 +1,52 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# #include <string.h>
+#
+# #define HELLO "world"
+#
+# int
+# main(int argc, char ** argv)
+# {
+#   return strlen (HELLO);
+# }
+#
+# gcc -gdwarf-4 -g3 -o testfile-macros macro.c
+# gcc -gstrict-dwarf -gdwarf-4 -g3 -o testfile-macinfo macro.c
+
+testfiles testfile-macinfo testfile-macros
+tempfiles readelf.macros.out
+
+status=0
+
+testrun ${abs_top_builddir}/src/readelf --debug-dump=info testfile-macinfo \
+	| grep macro_info > readelf.macros.out ||
+  { echo "*** failure readelf --debug-dump=info testfile-macinfo"; status=1; }
+testrun_compare cat readelf.macros.out <<\EOF
+           macro_info           (sec_offset) 0
+EOF
+
+testrun ${abs_top_builddir}/src/readelf --debug-dump=info testfile-macros \
+	| grep GNU_macros > readelf.macros.out ||
+  { echo "*** failure readelf --debug-dump=info testfile-macros"; status=1; }
+testrun_compare cat readelf.macros.out <<\EOF
+           GNU_macros           (sec_offset) 0
+EOF
+
+exit $status
diff --git a/tests/run-native-test.sh b/tests/run-native-test.sh
new file mode 100755
index 0000000..01a52e8
--- /dev/null
+++ b/tests/run-native-test.sh
@@ -0,0 +1,92 @@
+#! /bin/sh
+# Copyright (C) 2005, 2006, 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+. $srcdir/test-subr.sh
+
+# This tests all the miscellaneous components of backend support
+# against whatever this build is running on.  A platform will fail
+# this test if it is missing parts of the backend implementation.
+#
+# As new backend code is added to satisfy the test, be sure to update
+# the fixed test cases (run-allregs.sh et al) to test that backend
+# in all builds.
+
+tempfiles native.c native
+printf '#include <unistd.h>\nint main (void) { while (1) pause (); }\n' \
+  > native.c
+
+native=0
+kill_native()
+{
+  test $native -eq 0 || {
+    kill -9 $native 2> /dev/null || :
+    wait $native 2> /dev/null || :
+  }
+  native=0
+}
+
+native_cleanup()
+{
+  kill_native
+  test_cleanup
+}
+
+native_exit()
+{
+  native_cleanup
+  exit_cleanup
+}
+
+trap native_cleanup 1 2 15
+trap native_exit 0
+
+for cc in "$HOSTCC" "$HOST_CC" cc gcc "$CC"; do
+  test "x$cc" != x || continue
+  $cc -o native -g native.c &&
+  # Some shell versions don't do this right without the braces.
+  { ./native & native=$! ; } &&
+  sleep 1 && kill -0 $native &&
+  break ||
+  native=0
+done
+
+native_test()
+{
+  # Try the build against itself, i.e. $config_host.
+  echo "Try the build against itself: $@ -e $1"
+  testrun "$@" -e $1
+
+  # Try the build against a presumed native process, running this sh.
+  # For tests requiring debug information, this may not test anything.
+  echo "Try the build against a presumed native process: $@ -p $$"
+  testrun "$@" -p $$
+
+  # Try the build against the trivial native program we just built with -g.
+  echo "Try the build against the trivial native program: $@ -p $native"
+  test $native -eq 0 || testrun "$@" -p $native
+}
+
+native_test ${abs_builddir}/allregs
+native_test ${abs_builddir}/funcretval
+
+# We do this explicitly rather than letting the trap 0 cover it,
+# because as of version 3.1 bash prints the "Killed" report for
+# $native when we do the kill inside the exit handler.
+native_cleanup
+
+exit 0
diff --git a/tests/run-next-cfi-self.sh b/tests/run-next-cfi-self.sh
new file mode 100755
index 0000000..2c42ea3
--- /dev/null
+++ b/tests/run-next-cfi-self.sh
@@ -0,0 +1,21 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Sanity check toolchain/dwarf_next_cfi
+testrun_on_self ${abs_builddir}/next_cfi
diff --git a/tests/run-next-cfi.sh b/tests/run-next-cfi.sh
new file mode 100755
index 0000000..23c0d7d
--- /dev/null
+++ b/tests/run-next-cfi.sh
@@ -0,0 +1,108 @@
+#! /bin/sh
+# Test for dwarf_next_cfi.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Test files come from run-addrcfi
+testfiles testfile11 testfile12
+testfiles testfilearm testfileaarch64
+testfiles testfileppc32 testfileppc64
+
+testrun_compare ${abs_builddir}/next_cfi testfile11 <<\EOF
+testfile11
+.eh_frame
+[0] CIE augmentation="zPL"
+[28] FDE cie=[0]
+[64] FDE cie=[0]
+[96] FDE cie=[0]
+[128] FDE cie=[0]
+.debug_frame
+[0] CIE augmentation=""
+[20] FDE cie=[0]
+[52] FDE cie=[0]
+[76] FDE cie=[0]
+[100] FDE cie=[0]
+[124] FDE cie=[0]
+[148] FDE cie=[0]
+[172] FDE cie=[0]
+[196] FDE cie=[0]
+EOF
+
+testrun_compare ${abs_builddir}/next_cfi testfile12 <<\EOF
+testfile12
+.eh_frame
+[0] CIE augmentation=""
+[16] CIE augmentation="zR"
+[40] FDE cie=[16]
+.debug_frame
+[0] CIE augmentation=""
+[24] FDE cie=[0]
+EOF
+
+testrun_compare ${abs_builddir}/next_cfi testfilearm <<\EOF
+testfilearm
+.eh_frame
+.debug_frame
+[0] CIE augmentation=""
+[16] FDE cie=[0]
+[32] CIE augmentation=""
+[48] FDE cie=[32]
+EOF
+
+testrun_compare ${abs_builddir}/next_cfi testfileaarch64 <<\EOF
+testfileaarch64
+.eh_frame
+[0] CIE augmentation="zR"
+[24] FDE cie=[0]
+[80] FDE cie=[0]
+.debug_frame
+[0] CIE augmentation=""
+[16] FDE cie=[0]
+[40] CIE augmentation=""
+[56] FDE cie=[40]
+EOF
+
+testrun_compare ${abs_builddir}/next_cfi testfileppc32 <<\EOF
+testfileppc32
+.eh_frame
+[0] CIE augmentation="zR"
+[20] FDE cie=[0]
+[40] FDE cie=[0]
+[96] FDE cie=[0]
+.debug_frame
+[0] CIE augmentation=""
+[16] FDE cie=[0]
+[32] CIE augmentation=""
+[48] FDE cie=[32]
+EOF
+
+testrun_compare ${abs_builddir}/next_cfi testfileppc64 <<\EOF
+testfileppc64
+.eh_frame
+[0] CIE augmentation="zR"
+[20] FDE cie=[0]
+[40] FDE cie=[0]
+[64] CIE augmentation="zR"
+[88] FDE cie=[64]
+[144] FDE cie=[64]
+.debug_frame
+[0] CIE augmentation=""
+[16] FDE cie=[0]
+[56] CIE augmentation=""
+[72] FDE cie=[56]
+EOF
diff --git a/tests/run-next-files.sh b/tests/run-next-files.sh
new file mode 100755
index 0000000..150a6a1
--- /dev/null
+++ b/tests/run-next-files.sh
@@ -0,0 +1,265 @@
+#! /bin/sh
+# Variant of run-get-files that uses dwarf_next_lines.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/next-files testfile testfile2 <<\EOF
+off = 0
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/m.c"
+off = 75
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/b.c"
+ file[2] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h"
+ file[3] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h"
+ file[4] = "/usr/include/bits/types.h"
+ file[5] = "/usr/include/bits/sched.h"
+ file[6] = "/usr/include/bits/pthreadtypes.h"
+ file[7] = "/usr/include/stdio.h"
+ file[8] = "/usr/include/libio.h"
+ file[9] = "/usr/include/wchar.h"
+ file[10] = "/usr/include/_G_config.h"
+ file[11] = "/usr/include/gconv.h"
+off = 480
+ dirs[0] = "/home/drepper/gnu/new-bu/build/ttt"
+ file[0] = "???"
+ file[1] = "/home/drepper/gnu/new-bu/build/ttt/f.c"
+off = 0
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/b.c"
+ file[2] = "/home/geoffk/objs/laurel-000912-branch/lib/gcc-lib/powerpc-unknown-linux-gnu/2.96-laurel-000912/include/stddef.h"
+ file[3] = "/home/geoffk/objs/laurel-000912-branch/lib/gcc-lib/powerpc-unknown-linux-gnu/2.96-laurel-000912/include/stdarg.h"
+ file[4] = "/shoggoth/drepper/<built-in>"
+ file[5] = "/usr/include/bits/types.h"
+ file[6] = "/usr/include/stdio.h"
+ file[7] = "/usr/include/libio.h"
+ file[8] = "/usr/include/_G_config.h"
+off = 418
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/f.c"
+off = 485
+ dirs[0] = "/shoggoth/drepper"
+ file[0] = "???"
+ file[1] = "/shoggoth/drepper/m.c"
+EOF
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+
+testrun_compare ${abs_builddir}/next-files testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo <<\EOF
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 612
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+EOF
+
+# No problem with dirs[0] for DWARF5 line tables.
+testrun_compare ${abs_builddir}/next-files testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo <<\EOF
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "/home/mark/src/elfutils/tests/hello.c"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 655
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/mark/src/elfutils/tests/world.c"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include"
+ file[0] = "/home/mark/src/elfutils/tests/hello.c"
+ file[1] = "/home/mark/src/elfutils/tests/hello.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include/stddef.h"
+off = 0
+ dirs[0] = "/home/mark/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/mark/src/elfutils/tests/world.c"
+ file[1] = "/home/mark/src/elfutils/tests/world.c"
+ file[2] = "/home/mark/src/elfutils/tests/hello.h"
+ file[3] = "/usr/include/stdlib.h"
+EOF
+
+# Created from testfile using
+# cp testfile testfile-only-debug-line
+# eu-strip -g --keep-section .debug_line
+#
+# Note how the comp dir cannot be retrieved and some files become relative.
+testfiles testfile-only-debug-line
+testrun_compare ${abs_builddir}/next-files testfile-only-debug-line <<\EOF
+off = 0
+ dirs[0] = (null)
+ file[0] = "???"
+ file[1] = "m.c"
+off = 75
+ dirs[0] = (null)
+ file[0] = "???"
+ file[1] = "b.c"
+ file[2] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stddef.h"
+ file[3] = "/usr/lib/gcc-lib/i386-redhat-linux/2.96/include/stdarg.h"
+ file[4] = "/usr/include/bits/types.h"
+ file[5] = "/usr/include/bits/sched.h"
+ file[6] = "/usr/include/bits/pthreadtypes.h"
+ file[7] = "/usr/include/stdio.h"
+ file[8] = "/usr/include/libio.h"
+ file[9] = "/usr/include/wchar.h"
+ file[10] = "/usr/include/_G_config.h"
+ file[11] = "/usr/include/gconv.h"
+off = 480
+ dirs[0] = (null)
+ file[0] = "???"
+ file[1] = "f.c"
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+
+testrun_compare ${abs_builddir}/next-files testfile-dwp-5 << EOF
+off = 0
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 383
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 487
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+testrun_compare ${abs_builddir}/next-files testfile-dwp-5.dwp << EOF
+off = 0
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 127
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 254
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+testrun_compare ${abs_builddir}/next-files testfile-dwp-4 << EOF
+off = 0
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 397
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 515
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+testrun_compare ${abs_builddir}/next-files testfile-dwp-4.dwp << EOF
+off = 0
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/foo.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 82
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/bar.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+off = 164
+ dirs[0] = "/home/osandov/src/elfutils/tests"
+ dirs[1] = "/usr/include"
+ file[0] = "???"
+ file[1] = "/home/osandov/src/elfutils/tests/main.cc"
+ file[2] = "/home/osandov/src/elfutils/tests/foobar.h"
+ file[3] = "/usr/include/stdc-predef.h"
+EOF
+
+exit 0
diff --git a/tests/run-next-lines.sh b/tests/run-next-lines.sh
new file mode 100755
index 0000000..551b438
--- /dev/null
+++ b/tests/run-next-lines.sh
@@ -0,0 +1,358 @@
+#! /bin/sh
+# Variant of run-get-lines that uses dwarf_next_lines.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2 testfilenolines
+
+testrun_compare ${abs_builddir}/next-lines testfile testfile2 <<\EOF
+off = 0
+ 5 lines
+804842c: /home/drepper/gnu/new-bu/build/ttt/m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048432: /home/drepper/gnu/new-bu/build/ttt/m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804844d: /home/drepper/gnu/new-bu/build/ttt/m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048458: /home/drepper/gnu/new-bu/build/ttt/m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845a: /home/drepper/gnu/new-bu/build/ttt/m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 75
+ 4 lines
+804845c: /home/drepper/gnu/new-bu/build/ttt/b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845f: /home/drepper/gnu/new-bu/build/ttt/b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048464: /home/drepper/gnu/new-bu/build/ttt/b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048466: /home/drepper/gnu/new-bu/build/ttt/b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 480
+ 4 lines
+8048468: /home/drepper/gnu/new-bu/build/ttt/f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804846b: /home/drepper/gnu/new-bu/build/ttt/f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048470: /home/drepper/gnu/new-bu/build/ttt/f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048472: /home/drepper/gnu/new-bu/build/ttt/f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 0
+ 4 lines
+10000470: /shoggoth/drepper/b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1000047c: /shoggoth/drepper/b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000480: /shoggoth/drepper/b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000490: /shoggoth/drepper/b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 418
+ 4 lines
+10000490: /shoggoth/drepper/f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1000049c: /shoggoth/drepper/f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004a0: /shoggoth/drepper/f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004b0: /shoggoth/drepper/f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 485
+ 5 lines
+100004b0: /shoggoth/drepper/m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004cc: /shoggoth/drepper/m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004e8: /shoggoth/drepper/m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100004f4: /shoggoth/drepper/m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10000514: /shoggoth/drepper/m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+# - lines.c
+# int ft;
+#
+# int
+# main (int argc, char **argv)
+# {
+#   return ft - 42;
+# }
+#
+# - nolines.c
+# int ft = 42;
+#
+# gcc -g -c lines.c
+# gcc -g -c nolines.c
+# gcc -g -o testfilenolines lines.o nolines.o
+
+testrun_compare ${abs_builddir}/next-lines testfilenolines <<\EOF
+off = 0
+ 4 lines
+400474: /home/mark/src/tests/lines.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40047f: /home/mark/src/tests/lines.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+400488: /home/mark/src/tests/lines.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40048a: /home/mark/src/tests/lines.c:7:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 59
+ 0 lines
+EOF
+
+# See run-next-files.
+# Note no, comp_dir, so all paths are relative.
+testfiles testfile-only-debug-line
+testrun_compare ${abs_builddir}/next-lines testfile-only-debug-line <<\EOF
+off = 0
+ 5 lines
+804842c: m.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048432: m.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804844d: m.c:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048458: m.c:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845a: m.c:8:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 75
+ 4 lines
+804845c: b.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804845f: b.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048464: b.c:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048466: b.c:6:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 480
+ 4 lines
+8048468: f.c:3:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+804846b: f.c:4:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048470: f.c:5:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+8048472: f.c:5:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testrun_compare ${abs_builddir}/next-lines testfile-dwp-5 << EOF
+off = 0
+ 63 lines
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401192: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401196: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bc: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:15:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:11: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c5: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cd: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d7: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:19:10: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f0: /home/osandov/src/elfutils/tests/foo.cc:20:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011fc: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 383
+ 7 lines
+401200: /home/osandov/src/elfutils/tests/bar.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401204: /home/osandov/src/elfutils/tests/bar.cc:8:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401207: /home/osandov/src/elfutils/tests/bar.cc:11:18: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121a: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121b: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 487
+ 41 lines
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401021: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401028: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40102c: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/main.cc:9:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:17:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:20:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401032: /home/osandov/src/elfutils/tests/main.cc:8:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401036: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40103f: /home/osandov/src/elfutils/tests/foobar.h:25:25: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401044: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401049: /home/osandov/src/elfutils/tests/foobar.h:23:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401050: /home/osandov/src/elfutils/tests/foobar.h:27:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401053: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401056: /home/osandov/src/elfutils/tests/foobar.h:27:9: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:28:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401065: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401068: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401076: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401080: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401085: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108a: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108c: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401091: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401095: /home/osandov/src/elfutils/tests/main.cc:10:22: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401097: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401099: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4010a0: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+testrun_compare ${abs_builddir}/next-lines testfile-dwp-4 << EOF
+off = 0
+ 63 lines
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401190: /home/osandov/src/elfutils/tests/foo.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401192: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401196: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40119e: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a1: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011a4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011b9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bb: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011bc: /home/osandov/src/elfutils/tests/foo.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:15:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c0: /home/osandov/src/elfutils/tests/foo.cc:16:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c2: /home/osandov/src/elfutils/tests/foo.cc:17:11: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c5: /home/osandov/src/elfutils/tests/foo.cc:17:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011c9: /home/osandov/src/elfutils/tests/foo.cc:18:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cb: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011cd: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d1: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d4: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011d7: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e0: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:5: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e3: /home/osandov/src/elfutils/tests/foo.cc:9:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e6: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011e9: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:10:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011eb: /home/osandov/src/elfutils/tests/foo.cc:19:10: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f0: /home/osandov/src/elfutils/tests/foo.cc:20:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:6:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011f8: /home/osandov/src/elfutils/tests/foo.cc:8:21: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+4011fc: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/foo.cc:8:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 397
+ 7 lines
+401200: /home/osandov/src/elfutils/tests/bar.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401200: /home/osandov/src/elfutils/tests/bar.cc:8:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401204: /home/osandov/src/elfutils/tests/bar.cc:8:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401207: /home/osandov/src/elfutils/tests/bar.cc:11:18: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121a: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40121b: /home/osandov/src/elfutils/tests/bar.cc:12:1: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+off = 515
+ 41 lines
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:8:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401020: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401021: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401028: /home/osandov/src/elfutils/tests/main.cc:7:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40102c: /home/osandov/src/elfutils/tests/main.cc:8:28: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/main.cc:9:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:17:1: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401030: /home/osandov/src/elfutils/tests/foobar.h:20:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401032: /home/osandov/src/elfutils/tests/main.cc:8:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401036: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:19:3: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40103a: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40103f: /home/osandov/src/elfutils/tests/foobar.h:25:25: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401044: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401049: /home/osandov/src/elfutils/tests/foobar.h:23:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401050: /home/osandov/src/elfutils/tests/foobar.h:27:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401053: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401056: /home/osandov/src/elfutils/tests/foobar.h:27:9: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:28:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:29:4: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:7: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401059: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/foobar.h:25:34: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401060: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401065: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401068: /home/osandov/src/elfutils/tests/main.cc:9:40: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401076: /home/osandov/src/elfutils/tests/main.cc:9:51: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:3: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40107b: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401080: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401085: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108a: /home/osandov/src/elfutils/tests/main.cc:10:19: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+40108c: /home/osandov/src/elfutils/tests/main.cc:10:33: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401091: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401095: /home/osandov/src/elfutils/tests/main.cc:10:22: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401097: /home/osandov/src/elfutils/tests/main.cc:11:1: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+401099: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:no, bb:no, prologue:no, epilogue:no
+4010a0: /home/osandov/src/elfutils/tests/foobar.h:24:12: is_stmt:no, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
+
+exit 0
diff --git a/tests/run-nm-self.sh b/tests/run-nm-self.sh
new file mode 100755
index 0000000..6a31afc
--- /dev/null
+++ b/tests/run-nm-self.sh
@@ -0,0 +1,36 @@
+#! /bin/sh
+# Copyright (C) 2012, 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Test different command line combinations on the nm binary itself.
+# Test on nm ET_REL, ET_EXEC and ET_DYN files.
+ET_REL=${abs_top_builddir}/src/nm.o
+ET_EXEC=${abs_top_builddir}/src/nm
+ET_DYN=${abs_top_builddir}/libelf/libelf.so
+for what_arg in --debug-syms --defined-only --dynamic --extern-only; do
+  for format_arg in --format=bsd --format=sysv --format=posix; do
+    for out_arg in --numeric-sort --no-sort --reverse-sort; do
+      for self_file in $ET_REL $ET_EXEC $ET_DYN; do
+	# --dynamic doesn't make sense for ET_REL.
+	if ! test "$what_arg" = "--dynamic" -a "$self_file" = "$ET_REL"; then
+	  testrun ${abs_top_builddir}/src/nm $what_arg $format_arg $out_arg $self_file > /dev/null
+	fi
+      done
+    done
+  done
+done
diff --git a/tests/run-nm-syms.sh b/tests/run-nm-syms.sh
new file mode 100755
index 0000000..ddf0922
--- /dev/null
+++ b/tests/run-nm-syms.sh
@@ -0,0 +1,166 @@
+#! /bin/sh
+# Copyright (C) 2020 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# void *SYM1;
+# void *SYM2 = 0;
+# extern void *SYM3;
+# static void *SYM4;
+#
+# void *SYM6 = &SYM3;
+# static void *SYM7 = &SYM3;
+#
+# void *SYM8 __attribute__((__weak__));
+#
+# void FUN1 (void) { }
+# static void FUN2 (void) { }
+# extern void FUN3 (void);
+#
+# void *FREF = FUN3;
+#
+# void __attribute__((__weak__)) FUN4 (void) { };
+#
+# int NUM0 = 0; __asm__(".type NUM0,%gnu_unique_object");
+# int __thread NUM1 = 1;
+#
+# gcc -m64 -c syms.c -o testfilesyms64
+# gcc -m32 -c syms.c -o testfilesyms32
+
+testfiles testfilesyms32 testfilesyms64
+
+testrun_compare ${abs_top_builddir}/src/nm --format=bsd testfilesyms32 <<\EOF
+00000008 D FREF
+00000000 T FUN1
+00000010 t FUN2
+         U FUN3
+00000020 W FUN4
+00000008 u NUM0
+00000000 D NUM1
+00000004 C SYM1
+00000000 B SYM2
+         U SYM3
+0000000c b SYM4
+00000000 D SYM6
+00000004 d SYM7
+00000004 V SYM8
+         U _GLOBAL_OFFSET_TABLE_
+00000000 T __x86.get_pc_thunk.ax
+EOF
+
+testrun_compare ${abs_top_builddir}/src/nm --format=posix testfilesyms32 <<\EOF
+FREF D 00000008 00000004
+FUN1 T 00000000 00000010
+FUN2 t 00000010 00000010
+FUN3 U
+FUN4 W 00000020 00000010
+NUM0 u 00000008 00000004
+NUM1 D 00000000 00000004
+SYM1 C 00000004 00000004
+SYM2 B 00000000 00000004
+SYM3 U
+SYM4 b 0000000c 00000004
+SYM6 D 00000000 00000004
+SYM7 d 00000004 00000004
+SYM8 V 00000004 00000004
+_GLOBAL_OFFSET_TABLE_ U
+__x86.get_pc_thunk.ax T 00000000 00000000
+EOF
+
+testrun_compare ${abs_top_builddir}/src/nm --format=sysv testfilesyms32 <<\EOF
+
+
+Symbols from testfilesyms32:
+
+Name                  Value    Class  Type     Size     Line Section
+
+FREF                 |00000008|GLOBAL|OBJECT  |00000004|    |.data.rel
+FUN1                 |00000000|GLOBAL|FUNC    |00000010|    |.text
+FUN2                 |00000010|LOCAL |FUNC    |00000010|    |.text
+FUN3                 |        |GLOBAL|NOTYPE  |        |    |UNDEF
+FUN4                 |00000020|WEAK  |FUNC    |00000010|    |.text
+NUM0                 |00000008|UNIQUE|OBJECT  |00000004|    |.bss
+NUM1                 |00000000|GLOBAL|TLS     |00000004|    |.tdata
+SYM1                 |00000004|GLOBAL|OBJECT  |00000004|    |COMMON
+SYM2                 |00000000|GLOBAL|OBJECT  |00000004|    |.bss
+SYM3                 |        |GLOBAL|NOTYPE  |        |    |UNDEF
+SYM4                 |0000000c|LOCAL |OBJECT  |00000004|    |.bss
+SYM6                 |00000000|GLOBAL|OBJECT  |00000004|    |.data.rel
+SYM7                 |00000004|LOCAL |OBJECT  |00000004|    |.data.rel
+SYM8                 |00000004|WEAK  |OBJECT  |00000004|    |.bss
+_GLOBAL_OFFSET_TABLE_|        |GLOBAL|NOTYPE  |        |    |UNDEF
+__x86.get_pc_thunk.ax|00000000|GLOBAL|FUNC    |00000000|    |.text.__x86.get_pc_thunk.ax
+EOF
+
+testrun_compare ${abs_top_builddir}/src/nm --format=bsd testfilesyms64 <<\EOF
+0000000000000010 D FREF
+0000000000000000 T FUN1
+0000000000000007 t FUN2
+                 U FUN3
+000000000000000e W FUN4
+0000000000000010 u NUM0
+0000000000000000 D NUM1
+0000000000000008 C SYM1
+0000000000000000 B SYM2
+                 U SYM3
+0000000000000018 b SYM4
+0000000000000000 D SYM6
+0000000000000008 d SYM7
+0000000000000008 V SYM8
+EOF
+
+testrun_compare ${abs_top_builddir}/src/nm --format=posix testfilesyms64 <<\EOF
+FREF D 0000000000000010 0000000000000008
+FUN1 T 0000000000000000 0000000000000007
+FUN2 t 0000000000000007 0000000000000007
+FUN3 U
+FUN4 W 000000000000000e 0000000000000007
+NUM0 u 0000000000000010 0000000000000004
+NUM1 D 0000000000000000 0000000000000004
+SYM1 C 0000000000000008 0000000000000008
+SYM2 B 0000000000000000 0000000000000008
+SYM3 U
+SYM4 b 0000000000000018 0000000000000008
+SYM6 D 0000000000000000 0000000000000008
+SYM7 d 0000000000000008 0000000000000008
+SYM8 V 0000000000000008 0000000000000008
+EOF
+
+testrun_compare ${abs_top_builddir}/src/nm --format=sysv testfilesyms64 <<\EOF
+
+
+Symbols from testfilesyms64:
+
+Name   Value            Class  Type     Size             Line Section
+
+FREF  |0000000000000010|GLOBAL|OBJECT  |0000000000000008|    |.data.rel
+FUN1  |0000000000000000|GLOBAL|FUNC    |0000000000000007|    |.text
+FUN2  |0000000000000007|LOCAL |FUNC    |0000000000000007|    |.text
+FUN3  |                |GLOBAL|NOTYPE  |                |    |UNDEF
+FUN4  |000000000000000e|WEAK  |FUNC    |0000000000000007|    |.text
+NUM0  |0000000000000010|UNIQUE|OBJECT  |0000000000000004|    |.bss
+NUM1  |0000000000000000|GLOBAL|TLS     |0000000000000004|    |.tdata
+SYM1  |0000000000000008|GLOBAL|OBJECT  |0000000000000008|    |COMMON
+SYM2  |0000000000000000|GLOBAL|OBJECT  |0000000000000008|    |.bss
+SYM3  |                |GLOBAL|NOTYPE  |                |    |UNDEF
+SYM4  |0000000000000018|LOCAL |OBJECT  |0000000000000008|    |.bss
+SYM6  |0000000000000000|GLOBAL|OBJECT  |0000000000000008|    |.data.rel
+SYM7  |0000000000000008|LOCAL |OBJECT  |0000000000000008|    |.data.rel
+SYM8  |0000000000000008|WEAK  |OBJECT  |0000000000000008|    |.bss
+EOF
+
+exit 0
diff --git a/tests/run-nvidia-extended-linemap-libdw.sh b/tests/run-nvidia-extended-linemap-libdw.sh
new file mode 100755
index 0000000..d1df2cf
--- /dev/null
+++ b/tests/run-nvidia-extended-linemap-libdw.sh
@@ -0,0 +1,60 @@
+# Copyright (C) 2011 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# NOTE: 
+#   the file testfile_nvidia_linemap is a CUDA binary for an NVIDIA A100 generated as follows using CUDA 11.2
+#   nvcc -o main main.cu  -Xcompiler "-g -fopenmp" -O3 -lineinfo -arch sm_80  -lcudart -lcuda -lstdc++ -lm
+#   cuobjdump -xelf all main
+#   mv main.sm_80.cubin testfile_nvidia_linemap
+
+testfiles testfile_nvidia_linemap
+testrun_compare ${abs_top_builddir}/tests/nvidia_extended_linemap_libdw testfile_nvidia_linemap << EOF
+off = 0
+ 18 lines
+0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:25:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+10: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:26:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+40: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:27:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+90: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:25:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+a0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:28:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:28:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+100: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  foo inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:28
+150: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:9:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  foo inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:28
+1e0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+1e0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:6:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+1e0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  foo inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:6
+    bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+220: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:9:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  foo inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:6
+    bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+2b0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:7:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+2f0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:8:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+2f0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:18:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  _Z1aPiS_S_ inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:8
+    bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+330: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:19:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+  _Z1aPiS_S_ inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/bar.h:8
+    bar inlined at /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:31
+3c0: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:33:0: is_stmt:yes, end_seq:no, bb:no, prologue:no, epilogue:no
+480: /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4/main.cu:33:0: is_stmt:yes, end_seq:yes, bb:no, prologue:no, epilogue:no
+EOF
diff --git a/tests/run-nvidia-extended-linemap-readelf.sh b/tests/run-nvidia-extended-linemap-readelf.sh
new file mode 100755
index 0000000..1fa9b7b
--- /dev/null
+++ b/tests/run-nvidia-extended-linemap-readelf.sh
@@ -0,0 +1,120 @@
+# Copyright (C) 2011 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# NOTE:
+#   the file testfile_nvidia_linemap is a CUDA binary for an NVIDIA A100 generated as follows using CUDA 11.2
+#   nvcc -o main main.cu  -Xcompiler "-g -fopenmp" -O3 -lineinfo -arch sm_80  -lcudart -lcuda -lstdc++ -lm
+#   cuobjdump -xelf all main
+#   mv main.sm_80.cubin testfile_nvidia_linemap
+
+testfiles testfile_nvidia_linemap
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile_nvidia_linemap << EOF
+
+DWARF section [ 5] '.debug_line' at offset 0x3e0:
+
+Table at offset 0:
+
+ Length:                         253
+ DWARF version:                  2
+ Prologue length:                111
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    10
+
+Opcodes:
+  [1]  0 arguments
+  [2]  1 argument
+  [3]  1 argument
+  [4]  1 argument
+  [5]  1 argument
+  [6]  0 arguments
+  [7]  0 arguments
+  [8]  0 arguments
+  [9]  1 argument
+
+Directory table:
+ /home/johnmc/hpctoolkit-gpu-samples/nvidia_extended_linemap4
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     1     1626104146 1819      main.cu
+ 2     1     1626104111 211       bar.h
+
+Line number statements:
+ [    79] extended opcode 2:  set address to 0 <kernel>
+ [    84] set file to 1
+ [    86] advance line by constant 24 to 25
+ [    88] copy
+ [    89] special opcode 240: address+16 = 0x10 <kernel+0x10>, line+1 = 26
+ [    8a] advance line by constant 1 to 27
+ [    8c] advance address by 48 to 0x40 <kernel+0x40>
+ [    8e] copy
+ [    8f] advance line by constant -2 to 25
+ [    91] advance address by 80 to 0x90 <kernel+0x90>
+ [    94] copy
+ [    95] special opcode 242: address+16 = 0xa0 <kernel+0xa0>, line+3 = 28
+ [    96] advance address by 96 to 0x100 <kernel+0x100>
+ [    99] copy
+ [    9a] extended opcode 144:  set inlined context 6, function name foo (0x0)
+ [    9f] advance line by constant -20 to 8
+ [    a1] copy
+ [    a2] advance line by constant 1 to 9
+ [    a4] advance address by 80 to 0x150 <kernel+0x150>
+ [    a7] copy
+ [    a8] extended opcode 144:  set inlined context 0, function name foo (0x0)
+ [    ad] advance line by constant 22 to 31
+ [    af] advance address by 144 to 0x1e0 <kernel+0x1e0>
+ [    b2] copy
+ [    b3] set file to 2
+ [    b5] extended opcode 144:  set inlined context 9, function name bar (0x4)
+ [    ba] advance line by constant -25 to 6
+ [    bc] copy
+ [    bd] set file to 1
+ [    bf] extended opcode 144:  set inlined context 10, function name foo (0x0)
+ [    c4] advance line by constant 2 to 8
+ [    c6] copy
+ [    c7] advance line by constant 1 to 9
+ [    c9] advance address by 64 to 0x220 <kernel+0x220>
+ [    cc] copy
+ [    cd] set file to 2
+ [    cf] extended opcode 144:  set inlined context 9, function name bar (0x4)
+ [    d4] advance line by constant -2 to 7
+ [    d6] advance address by 144 to 0x2b0 <kernel+0x2b0>
+ [    d9] copy
+ [    da] advance line by constant 1 to 8
+ [    dc] advance address by 64 to 0x2f0 <kernel+0x2f0>
+ [    df] copy
+ [    e0] set file to 1
+ [    e2] extended opcode 144:  set inlined context 14, function name _Z1aPiS_S_ (0x8)
+ [    e7] advance line by constant 10 to 18
+ [    e9] copy
+ [    ea] advance line by constant 1 to 19
+ [    ec] advance address by 64 to 0x330 <kernel+0x330>
+ [    ef] copy
+ [    f0] extended opcode 144:  set inlined context 0, function name foo (0x0)
+ [    f5] advance line by constant 14 to 33
+ [    f7] advance address by 144 to 0x3c0 <kernel+0x3c0>
+ [    fa] copy
+ [    fb] advance address by 192 to 0x480
+ [    fe] extended opcode 1:  end of sequence
+EOF
diff --git a/tests/run-peel-type.sh b/tests/run-peel-type.sh
new file mode 100755
index 0000000..668e316
--- /dev/null
+++ b/tests/run-peel-type.sh
@@ -0,0 +1,63 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-aggregate-size.sh for how to generate testfiles.
+
+testfiles testfile-sizes1.o testfile-sizes2.o testfile-sizes3.o
+
+testrun_compare ${abs_builddir}/peel_type -e testfile-sizes1.o <<\EOF
+c raw type base_type
+i raw type base_type
+l raw type base_type
+v raw type pointer_type
+s raw type structure_type
+ca raw type array_type
+ia raw type array_type
+va raw type array_type
+sa raw type array_type
+EOF
+
+testrun_compare ${abs_builddir}/peel_type -e testfile-sizes2.o <<\EOF
+c raw type base_type
+i raw type base_type
+l raw type base_type
+v raw type pointer_type
+s raw type structure_type
+ca raw type array_type
+ia raw type array_type
+va raw type array_type
+sa raw type array_type
+EOF
+
+testrun_compare ${abs_builddir}/peel_type -e testfile-sizes3.o <<\EOF
+c raw type base_type
+i raw type base_type
+l raw type base_type
+v raw type pointer_type
+s raw type structure_type
+ca raw type array_type
+ia raw type array_type
+va raw type array_type
+sa raw type array_type
+d3d raw type array_type
+f raw type base_type
+b raw type base_type
+EOF
+
+exit 0
diff --git a/tests/run-prelink-addr-test.sh b/tests/run-prelink-addr-test.sh
new file mode 100755
index 0000000..3398c0d
--- /dev/null
+++ b/tests/run-prelink-addr-test.sh
@@ -0,0 +1,252 @@
+#! /bin/sh
+# Copyright (C) 2011-2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+
+# testfile52.c:
+#   #include <stdlib.h>
+#   int foo() { exit(0); }
+#
+# gcc -m32 -g -shared testfile52-32.c -o testfile52-32.so
+# eu-strip -f testfile52-32.so.debug testfile52-32.so
+# cp testfile52-32.so testfile52-32.prelink.so
+# prelink -N testfile52-32.prelink.so
+# cp testfile52-32.so testfile52-32.noshdrs.so
+# prelink -r 0x42000000 testfile52-32.noshdrs.so
+# eu-strip --remove-comment --strip-sections testfile52-32.noshdrs.so
+
+testfiles testfile52-32.so testfile52-32.so.debug
+testfiles testfile52-32.prelink.so testfile52-32.noshdrs.so
+tempfiles testmaps52-32 testfile52-32.noshdrs.so.debug
+ln -snf testfile52-32.so.debug testfile52-32.noshdrs.so.debug
+
+cat > testmaps52-32 <<EOF
+00111000-00112000 r-xp 00000000 fd:01 1 `pwd`/testfile52-32.so
+00112000-00113000 rw-p 00000000 fd:01 1 `pwd`/testfile52-32.so
+41000000-41001000 r-xp 00000000 fd:01 2 `pwd`/testfile52-32.prelink.so
+41001000-41002000 rw-p 00000000 fd:01 2 `pwd`/testfile52-32.prelink.so
+42000000-42001000 r-xp 00000000 fd:01 3 `pwd`/testfile52-32.noshdrs.so
+42001000-42002000 rw-p 00000000 fd:01 3 `pwd`/testfile52-32.noshdrs.so
+EOF
+
+# Prior to commit 1743d7f, libdwfl would fail on the second address,
+# because it didn't notice that prelink added a 0x20-byte offset from
+# what the .debug file reports.
+testrun_compare ${abs_top_builddir}/src/addr2line -S -M testmaps52-32 \
+    0x11140c 0x4100042d 0x4200040e <<\EOF
+foo
+/home/jistone/src/elfutils/tests/testfile52-32.c:2
+foo+0x1
+/home/jistone/src/elfutils/tests/testfile52-32.c:2
+foo+0x2
+/home/jistone/src/elfutils/tests/testfile52-32.c:2
+EOF
+
+# Repeat testfile52 for -m64.  The particular REL>RELA issue doesn't exist, but
+# we'll make sure the rest works anyway.
+testfiles testfile52-64.so testfile52-64.so.debug
+testfiles testfile52-64.prelink.so testfile52-64.noshdrs.so
+tempfiles testmaps52-64 testfile52-64.noshdrs.so.debug
+ln -snf testfile52-64.so.debug testfile52-64.noshdrs.so.debug
+
+cat > testmaps52-64 <<EOF
+1000000000-1000001000 r-xp 00000000 fd:11 1 `pwd`/testfile52-64.so
+1000001000-1000200000 ---p 00001000 fd:11 1 `pwd`/testfile52-64.so
+1000200000-1000201000 rw-p 00000000 fd:11 1 `pwd`/testfile52-64.so
+3000000000-3000001000 r-xp 00000000 fd:11 2 `pwd`/testfile52-64.prelink.so
+3000001000-3000200000 ---p 00001000 fd:11 2 `pwd`/testfile52-64.prelink.so
+3000200000-3000201000 rw-p 00000000 fd:11 2 `pwd`/testfile52-64.prelink.so
+3800000000-3800001000 r-xp 00000000 fd:11 3 `pwd`/testfile52-64.noshdrs.so
+3800001000-3800200000 ---p 00001000 fd:11 3 `pwd`/testfile52-64.noshdrs.so
+3800200000-3800201000 rw-p 00000000 fd:11 3 `pwd`/testfile52-64.noshdrs.so
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -M testmaps52-64 \
+    0x100000056c 0x300000056d 0x380000056e <<\EOF
+foo
+/home/jistone/src/elfutils/tests/testfile52-64.c:2
+foo+0x1
+/home/jistone/src/elfutils/tests/testfile52-64.c:2
+foo+0x2
+/home/jistone/src/elfutils/tests/testfile52-64.c:2
+EOF
+
+
+# testfile53.c:
+#   char foo[0x1000];
+#   int main() { return 0; }
+#
+# gcc -m32 -g testfile53-32.c -o testfile53-32
+# eu-strip -f testfile53-32.debug testfile53-32
+# cp testfile53-32 testfile53-32.prelink
+# prelink -N testfile53-32.prelink
+testfiles testfile53-32 testfile53-32.debug testfile53-32.prelink
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile53-32 0x8048394 0x8048395 <<\EOF
+main
+/home/jistone/src/elfutils/tests/testfile53-32.c:2
+main+0x1
+/home/jistone/src/elfutils/tests/testfile53-32.c:2
+EOF
+
+# prelink shuffled some of the sections, but .text is in the same place.
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile53-32.prelink 0x8048396 0x8048397 <<\EOF
+main+0x2
+/home/jistone/src/elfutils/tests/testfile53-32.c:2
+main+0x3
+/home/jistone/src/elfutils/tests/testfile53-32.c:2
+EOF
+
+# Repeat testfile53 in 64-bit, except use foo[0x800] to achieve the same
+# prelink section shuffling.
+testfiles testfile53-64 testfile53-64.debug testfile53-64.prelink
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile53-64 0x400474 0x400475 <<\EOF
+main
+/home/jistone/src/elfutils/tests/testfile53-64.c:2
+main+0x1
+/home/jistone/src/elfutils/tests/testfile53-64.c:2
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile53-64.prelink 0x400476 0x400477 <<\EOF
+main+0x2
+/home/jistone/src/elfutils/tests/testfile53-64.c:2
+main+0x3
+/home/jistone/src/elfutils/tests/testfile53-64.c:2
+EOF
+
+
+# testfile54.c:
+#   extern void * stdin;
+#   static void * pstdin = &stdin;
+#   void * const foo = &pstdin;
+#
+# gcc -m32 -g -shared -nostartfiles testfile54-32.c -o testfile54-32.so
+# eu-strip -f testfile54-32.so.debug testfile54-32.so
+# cp testfile54-32.so testfile54-32.prelink.so
+# prelink -N testfile54-32.prelink.so
+# cp testfile54-32.so testfile54-32.noshdrs.so
+# prelink -r 0x42000000 testfile54-32.noshdrs.so
+# eu-strip --remove-comment --strip-sections testfile54-32.noshdrs.so
+testfiles testfile54-32.so testfile54-32.so.debug
+testfiles testfile54-32.prelink.so testfile54-32.noshdrs.so
+tempfiles testmaps54-32
+
+# Note we have no testfile54-32.noshdrs.so.debug link here, so
+# this is testing finding the symbols in .dynsym via PT_DYNAMIC.
+
+cat > testmaps54-32 <<EOF
+00111000-00112000 r--p 00000000 fd:01 1 `pwd`/testfile54-32.so
+00112000-00113000 rw-p 00000000 fd:01 1 `pwd`/testfile54-32.so
+41000000-41001000 r--p 00000000 fd:01 2 `pwd`/testfile54-32.prelink.so
+41001000-41002000 rw-p 00000000 fd:01 2 `pwd`/testfile54-32.prelink.so
+42000000-42001000 r--p 00000000 fd:01 3 `pwd`/testfile54-32.noshdrs.so
+42001000-42002000 rw-p 00000000 fd:01 3 `pwd`/testfile54-32.noshdrs.so
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -M testmaps54-32 \
+    0x1111fc 0x1122a4 0x410001fd 0x410012a5 0x420001fe <<\EOF
+foo
+??:0
+pstdin
+??:0
+foo+0x1
+??:0
+pstdin+0x1
+??:0
+foo+0x2
+??:0
+EOF
+
+# Repeat testfile64 in 64-bit
+testfiles testfile54-64.so testfile54-64.so.debug
+testfiles testfile54-64.prelink.so testfile54-64.noshdrs.so
+tempfiles testmaps54-64
+
+# Note we have no testfile54-64.noshdrs.so.debug link here, so
+# this is testing finding the symbols in .dynsym via PT_DYNAMIC.
+
+cat > testmaps54-64 <<EOF
+1000000000-1000001000 r--p 00000000 fd:11 1 `pwd`/testfile54-64.so
+1000001000-1000200000 ---p 00001000 fd:11 1 `pwd`/testfile54-64.so
+1000200000-1000201000 rw-p 00000000 fd:11 1 `pwd`/testfile54-64.so
+3000000000-3000001000 r--p 00000000 fd:11 2 `pwd`/testfile54-64.prelink.so
+3000001000-3000200000 ---p 00001000 fd:11 2 `pwd`/testfile54-64.prelink.so
+3000200000-3000201000 rw-p 00000000 fd:11 2 `pwd`/testfile54-64.prelink.so
+3800000000-3800001000 r--p 00000000 fd:11 3 `pwd`/testfile54-64.noshdrs.so
+3800001000-3800200000 ---p 00001000 fd:11 3 `pwd`/testfile54-64.noshdrs.so
+3800200000-3800201000 rw-p 00000000 fd:11 3 `pwd`/testfile54-64.noshdrs.so
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -M testmaps54-64 \
+    0x10000002f8 0x1000200448 0x30000002f9 0x3000200449 0x38000002fa <<\EOF
+foo
+??:0
+pstdin
+??:0
+foo+0x1
+??:0
+pstdin+0x1
+??:0
+foo+0x2
+??:0
+EOF
+
+
+# testfile55.c:
+#   extern void *stdin;
+#   int main() { return !stdin; }
+#
+# gcc -m32 -g testfile55-32.c -o testfile55-32
+# eu-strip -f testfile55-32.debug testfile55-32
+# cp testfile55-32 testfile55-32.prelink
+# prelink -N testfile55-32.prelink
+testfiles testfile55-32 testfile55-32.debug testfile55-32.prelink
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile55-32 0x80483b4 0x80483b5 <<\EOF
+main
+/home/jistone/src/elfutils/tests/testfile55-32.c:2
+main+0x1
+/home/jistone/src/elfutils/tests/testfile55-32.c:2
+EOF
+
+# prelink splits .bss into .dynbss+.bss, so the start of .bss changes, but the
+# total size remains the same, and .text doesn't move at all.
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile55-32.prelink 0x80483b6 0x80483b7 <<\EOF
+main+0x2
+/home/jistone/src/elfutils/tests/testfile55-32.c:2
+main+0x3
+/home/jistone/src/elfutils/tests/testfile55-32.c:2
+EOF
+
+# Repeat testfile55 in 64-bit
+testfiles testfile55-64 testfile55-64.debug testfile55-64.prelink
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile55-64 0x4004b4 0x4004b5 <<\EOF
+main
+/home/jistone/src/elfutils/tests/testfile55-64.c:2
+main+0x1
+/home/jistone/src/elfutils/tests/testfile55-64.c:2
+EOF
+
+testrun_compare ${abs_top_builddir}/src/addr2line -S -e testfile55-64.prelink 0x4004b6 0x4004b7 <<\EOF
+main+0x2
+/home/jistone/src/elfutils/tests/testfile55-64.c:2
+main+0x3
+/home/jistone/src/elfutils/tests/testfile55-64.c:2
+EOF
diff --git a/tests/run-pt_gnu_prop-tests.sh b/tests/run-pt_gnu_prop-tests.sh
new file mode 100755
index 0000000..a9a8d91
--- /dev/null
+++ b/tests/run-pt_gnu_prop-tests.sh
@@ -0,0 +1,135 @@
+#! /bin/sh
+# Copyright (C) 2020 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# On Fedora 31 with GCC 9.2.1 and binutils 2.32-31
+# echo "int main () { }" | \
+# gcc -o testfile_pt_gnu_prop \
+#     -Os -fstack-clash-protection -fcf-protection=full -xc - && \
+# eu-strip --remove-comment -R .gnu.build.attributes testfile_pt_gnu_prop
+#
+# echo "int main () { }" | \
+# gcc -m32 -o testfile_pt_gnu_prop \
+#     -Os -fstack-clash-protection -fcf-protection=full -xc - && \
+# eu-strip --remove-comment -R .gnu.build.attributes testfile_pt_gnu_prop32
+
+testfiles testfile_pt_gnu_prop testfile_pt_gnu_prop32
+
+testrun_compare ${abs_top_builddir}/src/readelf -ln testfile_pt_gnu_prop32 <<\EOF
+Program Headers:
+  Type           Offset   VirtAddr   PhysAddr   FileSiz  MemSiz   Flg Align
+  PHDR           0x000034 0x08048034 0x08048034 0x000180 0x000180 R   0x4
+  INTERP         0x0001b4 0x080481b4 0x080481b4 0x000013 0x000013 R   0x1
+	[Requesting program interpreter: /lib/ld-linux.so.2]
+  LOAD           0x000000 0x08048000 0x08048000 0x000308 0x000308 R   0x1000
+  LOAD           0x001000 0x08049000 0x08049000 0x000224 0x000224 R E 0x1000
+  LOAD           0x002000 0x0804a000 0x0804a000 0x00015c 0x00015c R   0x1000
+  LOAD           0x002f0c 0x0804bf0c 0x0804bf0c 0x000108 0x00010c RW  0x1000
+  DYNAMIC        0x002f14 0x0804bf14 0x0804bf14 0x0000e8 0x0000e8 RW  0x4
+  NOTE           0x0001c8 0x080481c8 0x080481c8 0x000060 0x000060 R   0x4
+  GNU_PROPERTY   0x0001ec 0x080481ec 0x080481ec 0x00001c 0x00001c R   0x4
+  GNU_EH_FRAME   0x00200c 0x0804a00c 0x0804a00c 0x00004c 0x00004c R   0x4
+  GNU_STACK      0x000000 0x00000000 0x00000000 0x000000 0x000000 RW  0x10
+  GNU_RELRO      0x002f0c 0x0804bf0c 0x0804bf0c 0x0000f4 0x0000f4 R   0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     
+   01      [RO: .interp]
+   02      [RO: .interp .note.gnu.build-id .note.gnu.property .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt]
+   03      [RO: .init .plt .plt.sec .text .fini]
+   04      [RO: .rodata .eh_frame_hdr .eh_frame]
+   05      [RELRO: .init_array .fini_array .dynamic .got] .got.plt .data .bss
+   06      [RELRO: .dynamic]
+   07      [RO: .note.gnu.build-id .note.gnu.property .note.ABI-tag]
+   08      [RO: .note.gnu.property]
+   09      [RO: .eh_frame_hdr]
+   10     
+   11      [RELRO: .init_array .fini_array .dynamic .got]
+
+Note section [ 2] '.note.gnu.build-id' of 36 bytes at offset 0x1c8:
+  Owner          Data size  Type
+  GNU                   20  GNU_BUILD_ID
+    Build ID: 2fcce91f5c2532f78b00a9f5f565354d2f44bc19
+
+Note section [ 3] '.note.gnu.property' of 28 bytes at offset 0x1ec:
+  Owner          Data size  Type
+  GNU                   12  GNU_PROPERTY_TYPE_0
+    X86 FEATURE_1_AND: 00000003 IBT SHSTK
+
+Note section [ 4] '.note.ABI-tag' of 32 bytes at offset 0x208:
+  Owner          Data size  Type
+  GNU                   16  GNU_ABI_TAG
+    OS: Linux, ABI: 3.2.0
+EOF
+
+testrun ${abs_top_builddir}/src/elflint --gnu testfile_pt_gnu_prop32
+
+testrun_compare ${abs_top_builddir}/src/readelf -ln testfile_pt_gnu_prop <<\EOF
+Program Headers:
+  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
+  PHDR           0x000040 0x0000000000400040 0x0000000000400040 0x0002d8 0x0002d8 R   0x8
+  INTERP         0x000318 0x0000000000400318 0x0000000000400318 0x00001c 0x00001c R   0x1
+	[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
+  LOAD           0x000000 0x0000000000400000 0x0000000000400000 0x000498 0x000498 R   0x1000
+  LOAD           0x001000 0x0000000000401000 0x0000000000401000 0x0001a5 0x0001a5 R E 0x1000
+  LOAD           0x002000 0x0000000000402000 0x0000000000402000 0x000100 0x000100 R   0x1000
+  LOAD           0x002e50 0x0000000000403e50 0x0000000000403e50 0x0001cc 0x0001d0 RW  0x1000
+  DYNAMIC        0x002e60 0x0000000000403e60 0x0000000000403e60 0x000190 0x000190 RW  0x8
+  NOTE           0x000338 0x0000000000400338 0x0000000000400338 0x000020 0x000020 R   0x8
+  NOTE           0x000358 0x0000000000400358 0x0000000000400358 0x000044 0x000044 R   0x4
+  GNU_PROPERTY   0x000338 0x0000000000400338 0x0000000000400338 0x000020 0x000020 R   0x8
+  GNU_EH_FRAME   0x002010 0x0000000000402010 0x0000000000402010 0x000034 0x000034 R   0x4
+  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
+  GNU_RELRO      0x002e50 0x0000000000403e50 0x0000000000403e50 0x0001b0 0x0001b0 R   0x1
+
+ Section to Segment mapping:
+  Segment Sections...
+   00     
+   01      [RO: .interp]
+   02      [RO: .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn]
+   03      [RO: .init .text .fini]
+   04      [RO: .rodata .eh_frame_hdr .eh_frame]
+   05      [RELRO: .init_array .fini_array .dynamic .got] .got.plt .data .bss
+   06      [RELRO: .dynamic]
+   07      [RO: .note.gnu.property]
+   08      [RO: .note.gnu.build-id .note.ABI-tag]
+   09      [RO: .note.gnu.property]
+   10      [RO: .eh_frame_hdr]
+   11     
+   12      [RELRO: .init_array .fini_array .dynamic .got]
+
+Note section [ 2] '.note.gnu.property' of 32 bytes at offset 0x338:
+  Owner          Data size  Type
+  GNU                   16  GNU_PROPERTY_TYPE_0
+    X86 FEATURE_1_AND: 00000003 IBT SHSTK
+
+Note section [ 3] '.note.gnu.build-id' of 36 bytes at offset 0x358:
+  Owner          Data size  Type
+  GNU                   20  GNU_BUILD_ID
+    Build ID: 84fa4d40bad074bc82431575821902da624a5b22
+
+Note section [ 4] '.note.ABI-tag' of 32 bytes at offset 0x37c:
+  Owner          Data size  Type
+  GNU                   16  GNU_ABI_TAG
+    OS: Linux, ABI: 3.2.0
+EOF
+
+testrun ${abs_top_builddir}/src/elflint --gnu testfile_pt_gnu_prop
+
+exit 0
diff --git a/tests/run-ranlib-test.sh b/tests/run-ranlib-test.sh
new file mode 100755
index 0000000..0b34cbb
--- /dev/null
+++ b/tests/run-ranlib-test.sh
@@ -0,0 +1,38 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+tempfiles ranlib-test.a ranlib-test.a-copy
+
+cat > ranlib-test.a <<"EOF"
+!<arch>
+foo/            1124128960  500   500   100664  4         `
+foo
+bar/            1124128965  500   500   100664  4         `
+bar
+EOF
+
+cp ranlib-test.a ranlib-test.a-copy
+
+testrun ${abs_top_builddir}/src/ranlib ranlib-test.a
+
+# The ranlib call should not have changed anything.
+cmp ranlib-test.a ranlib-test.a-copy
+
+exit 0
diff --git a/tests/run-ranlib-test2.sh b/tests/run-ranlib-test2.sh
new file mode 100755
index 0000000..dbc57ec
--- /dev/null
+++ b/tests/run-ranlib-test2.sh
@@ -0,0 +1,37 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+original=${original:-testfile19}
+indexed=${indexed:-testfile19.index}
+
+testfiles $original $indexed
+
+testrun ${abs_top_builddir}/src/ranlib $original
+
+if test -z "$noindex"; then
+  # The date in the index is different.  The reference file has it blanked
+  # out, we do the same here.
+  echo "            " |
+  dd of=$original seek=24 bs=1 count=12 conv=notrunc 2>/dev/null
+fi
+
+cmp $original $indexed
+
+exit 0
diff --git a/tests/run-ranlib-test3.sh b/tests/run-ranlib-test3.sh
new file mode 100755
index 0000000..1fc21cd
--- /dev/null
+++ b/tests/run-ranlib-test3.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+original=testfile20
+indexed=testfile20.index
+. $srcdir/run-ranlib-test2.sh
diff --git a/tests/run-ranlib-test4.sh b/tests/run-ranlib-test4.sh
new file mode 100755
index 0000000..8070415
--- /dev/null
+++ b/tests/run-ranlib-test4.sh
@@ -0,0 +1,23 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+original=testfile21
+indexed=testfile21.index
+noindex=1
+. $srcdir/run-ranlib-test2.sh
diff --git a/tests/run-readelf-A.sh b/tests/run-readelf-A.sh
new file mode 100755
index 0000000..b7432be
--- /dev/null
+++ b/tests/run-readelf-A.sh
@@ -0,0 +1,96 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# Copyright (C) 2016 Oracle, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-addrcfi.sh for testfilearm.
+
+# = testfileppc32attrs.s =
+# .gnu_attribute 8,1
+# .gnu_attribute 12,1
+#
+# gcc -m32 -c testfileppc32attrs.s
+
+# = testfilesparc64attrs.s =
+# .gnu_attribute 4,0x0aaaaaaa
+# .gnu_attribute 8,0x00000055
+#
+# gcc -c testfilesparc64attrs.s
+
+# = testfileppc64attrs.s =
+# .gnu_attribute 4,3
+#
+# gcc -c testfileppc64attrs.s
+
+testfiles testfilearm testfileppc32attrs.o testfilesparc64attrs.o testfileppc64attrs.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -A testfilearm <<\EOF
+
+Object attributes section [27] '.ARM.attributes' of 53 bytes at offset 0x718:
+  Owner          Size
+  aeabi            52
+    File:          42
+      CPU_name: 7-A
+      CPU_arch: v7
+      CPU_arch_profile: Application
+      ARM_ISA_use: Yes
+      THUMB_ISA_use: Thumb-2
+      VFP_arch: VFPv3-D16
+      ABI_PCS_wchar_t: 4
+      ABI_FP_rounding: Needed
+      ABI_FP_denormal: Needed
+      ABI_FP_exceptions: Needed
+      ABI_FP_number_model: IEEE 754
+      ABI_align8_needed: Yes
+      ABI_align8_preserved: Yes, except leaf SP
+      ABI_enum_size: int
+      ABI_HardFP_use: SP and DP
+      ABI_VFP_args: VFP registers
+      CPU_unaligned_access: v6
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -A testfileppc32attrs.o <<\EOF
+
+Object attributes section [ 4] '.gnu.attributes' of 18 bytes at offset 0x34:
+  Owner          Size
+  gnu              17
+    File:           9
+      GNU_Power_ABI_Vector: Generic
+      GNU_Power_ABI_Struct_Return: r3/r4
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -A testfilesparc64attrs.o <<\EOF
+
+Object attributes section [ 4] '.gnu.attributes' of 21 bytes at offset 0x40:
+  Owner          Size
+  gnu              20
+    File:          12
+      GNU_Sparc_HWCAPS: div32,v8plus,vis,asi_blk_init,vis3,random,fjfmau,asi_cache_sparing,des,camellia,sha1,sha512,mont,cbcond
+      GNU_Sparc_HWCAPS2: fjathplus,adp,mwait,xmont
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -A testfileppc64attrs.o <<\EOF
+
+Object attributes section [ 4] '.gnu.attributes' of 16 bytes at offset 0x40:
+  Owner          Size
+  gnu              15
+    File:           7
+      GNU_Power_ABI_FP: Single-precision hard float
+EOF
+
+exit 0
diff --git a/tests/run-readelf-Dd.sh b/tests/run-readelf-Dd.sh
new file mode 100755
index 0000000..8c69993
--- /dev/null
+++ b/tests/run-readelf-Dd.sh
@@ -0,0 +1,66 @@
+#! /bin/sh
+# Copyright (C) 2022 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# #include <stdio.h>
+#
+# __thread int i;
+#
+# void print_i ()
+# {
+#   printf("%d\n", i);
+# }
+#
+# gcc -fPIC -shared -o testlib_dynseg.so testlib_dynseg.c
+# With ld --version
+# GNU gold (GNU Binutils 2.22.52.20120402) 1.11
+
+# The same testfile is used in run-readelf-d.sh
+testfiles testlib_dynseg.so
+
+testrun_compare ${abs_top_builddir}/src/readelf -Dd testlib_dynseg.so <<\EOF
+
+Dynamic segment contains 23 entries:
+ Addr: 0x00000000000017e0  Offset: 0x0007e0
+  Type              Value
+  PLTGOT            0x00000000000019c8
+  PLTRELSZ          72 (bytes)
+  JMPREL            0x0000000000000568
+  PLTREL            RELA
+  RELA              0x00000000000004d8
+  RELASZ            144 (bytes)
+  RELAENT           24 (bytes)
+  RELACOUNT         1
+  SYMTAB            0x0000000000000228
+  SYMENT            24 (bytes)
+  STRTAB            0x0000000000000360
+  STRSZ             190 (bytes)
+  GNU_HASH          0x0000000000000420
+  NEEDED            Shared library: [libc.so.6]
+  NEEDED            Shared library: [ld-linux-x86-64.so.2]
+  INIT              0x00000000000005b0
+  FINI              0x0000000000000748
+  VERSYM            0x0000000000000460
+  VERDEF            0x000000000000047c
+  VERDEFNUM         1
+  VERNEED           0x0000000000000498
+  VERNEEDNUM        2
+  NULL              
+EOF
+
+exit 0
diff --git a/tests/run-readelf-addr.sh b/tests/run-readelf-addr.sh
new file mode 100755
index 0000000..ea723c2
--- /dev/null
+++ b/tests/run-readelf-addr.sh
@@ -0,0 +1,143 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-splitdwarf-5
+
+# DWARF4 GNU DebugFission No real table header.
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=addr testfile-splitdwarf-4<<\EOF
+
+DWARF section [33] '.debug_addr' at offset 0x3671:
+Table at offset 0 for CU [     b]:
+
+ Length:              152
+ DWARF version:         4
+ Address size:          8
+ Segment size:          0
+
+ Addresses start at offset 0x0:
+ [ 0] 0x000000000040116a <foo+0xa>
+ [ 1] 0x0000000000401189 <foo+0x29>
+ [ 2] 0x000000000040118d <foo+0x2d>
+ [ 3] 0x0000000000401194
+ [ 4] 0x0000000000401181 <foo+0x21>
+ [ 5] 0x00000000004011af <baz+0xf>
+ [ 6] 0x00000000004011b1
+ [ 7] 0x00000000004011a0 <baz>
+ [ 8] 0x0000000000401160 <foo>
+ [ 9] 0x00000000004011a0 <baz>
+ [10] 0x000000000040117b <foo+0x1b>
+ [11] 0x000000000040117b <foo+0x1b>
+ [12] 0x0000000000401181 <foo+0x21>
+ [13] 0x0000000000401181 <foo+0x21>
+ [14] 0x000000000040118d <foo+0x2d>
+ [15] 0x0000000000401160 <foo>
+ [16] 0x0000000000401060 <main>
+ [17] 0x000000000040117b <foo+0x1b>
+ [18] 0x0000000000404038 <m>
+
+Table at offset 98 for CU [    3f]:
+
+ Length:              136
+ DWARF version:         4
+ Address size:          8
+ Segment size:          0
+
+ Addresses start at offset 0x98:
+ [ 0] 0x00000000004011df <calc+0x1f>
+ [ 1] 0x00000000004011e4 <calc+0x24>
+ [ 2] 0x0000000000401060 <main>
+ [ 3] 0x0000000000401071 <main+0x11>
+ [ 4] 0x0000000000401074 <main+0x14>
+ [ 5] 0x0000000000401079 <main+0x19>
+ [ 6] 0x00000000004011d3 <calc+0x13>
+ [ 7] 0x0000000000401078 <main+0x18>
+ [ 8] 0x00000000004011a0 <baz>
+ [ 9] 0x0000000000401040
+ [10] 0x0000000000401080 <_start>
+ [11] 0x00000000004011c0 <calc>
+ [12] 0x0000000000401060 <main>
+ [13] 0x00000000004011c0 <calc>
+ [14] 0x00000000004011c8 <calc+0x8>
+ [15] 0x00000000004011d8 <calc+0x18>
+ [16] 0x00000000004011da <calc+0x1a>
+
+EOF
+
+# DWARF5 Real table header.
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=addr testfile-splitdwarf-5<<\EOF
+
+DWARF section [32] '.debug_addr' at offset 0x365e:
+Table at offset 0 for CU [    14]:
+
+ Length:              156
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+
+ Addresses start at offset 0x8:
+ [ 0] 0x000000000040116a <foo+0xa>
+ [ 1] 0x0000000000401189 <foo+0x29>
+ [ 2] 0x000000000040118d <foo+0x2d>
+ [ 3] 0x0000000000401194
+ [ 4] 0x0000000000401181 <foo+0x21>
+ [ 5] 0x00000000004011af <baz+0xf>
+ [ 6] 0x00000000004011b1
+ [ 7] 0x00000000004011a0 <baz>
+ [ 8] 0x0000000000401160 <foo>
+ [ 9] 0x00000000004011a0 <baz>
+ [10] 0x000000000040117b <foo+0x1b>
+ [11] 0x000000000040117b <foo+0x1b>
+ [12] 0x0000000000401181 <foo+0x21>
+ [13] 0x0000000000401181 <foo+0x21>
+ [14] 0x000000000040118d <foo+0x2d>
+ [15] 0x0000000000401160 <foo>
+ [16] 0x0000000000401060 <main>
+ [17] 0x000000000040117b <foo+0x1b>
+ [18] 0x0000000000404038 <m>
+
+Table at offset a0 for CU [    49]:
+
+ Length:              140
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+
+ Addresses start at offset 0xa8:
+ [ 0] 0x00000000004011df <calc+0x1f>
+ [ 1] 0x00000000004011e4 <calc+0x24>
+ [ 2] 0x0000000000401060 <main>
+ [ 3] 0x0000000000401071 <main+0x11>
+ [ 4] 0x0000000000401074 <main+0x14>
+ [ 5] 0x0000000000401079 <main+0x19>
+ [ 6] 0x00000000004011d3 <calc+0x13>
+ [ 7] 0x0000000000401078 <main+0x18>
+ [ 8] 0x00000000004011a0 <baz>
+ [ 9] 0x0000000000401040
+ [10] 0x0000000000401080 <_start>
+ [11] 0x00000000004011c0 <calc>
+ [12] 0x0000000000401060 <main>
+ [13] 0x00000000004011c0 <calc>
+ [14] 0x00000000004011c8 <calc+0x8>
+ [15] 0x00000000004011d8 <calc+0x18>
+ [16] 0x00000000004011da <calc+0x1a>
+
+EOF
+
+exit 0
diff --git a/tests/run-readelf-aranges.sh b/tests/run-readelf-aranges.sh
new file mode 100755
index 0000000..3fc3c54
--- /dev/null
+++ b/tests/run-readelf-aranges.sh
@@ -0,0 +1,161 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Tests readelf --debug-dump=aranges and --debug-dump=decodedaranges
+#
+# - foobarbaz.h
+#
+# int bar ();
+# int baz (int i);
+#
+# - bar.c
+#
+# #include "foobarbaz.h"
+#
+# static int bi;
+#
+# static int
+# barbaz (int i)
+# {
+#   return i * 2 - 1;
+# }
+#
+# __attribute__ ((constructor)) void
+# nobar ()
+# {
+#   bi = 1;
+# }
+#
+# int
+# bar ()
+# {
+#   bi++;
+#   return barbaz (bi);
+# }
+#
+# - foo.c
+#
+# include "foobarbaz.h"
+#
+# static int fi = 0;
+#
+# static int
+# foo (int i, int j)
+# {
+#   if (i > j)
+#     return i - j + fi;
+#   else
+#     return (2 * j) - i + fi;
+# }
+#
+# int
+# main (int argc, char **argv)
+# {
+#   int a = bar ();
+#   int b = baz (a + argc);
+#   int r = foo (a, b) - 1;
+#
+#   return r - 48;
+# }
+#
+# - baz.c
+# include "foobarbaz.h"
+#
+# static int bj;
+#
+# static int
+# bazbaz (int j)
+# {
+#   return bj * j - bar ();
+# }
+#
+# __attribute__ ((constructor)) void
+# nobaz ()
+# {
+#   bj = 1;
+# }
+#
+# int
+# baz (int i)
+# {
+#   if (i < 0)
+#     return bazbaz (i);
+#   else
+#     {
+#       while (i-- > 0)
+#         bj += bar ();
+#     }
+#   return bazbaz (i);
+# }
+#
+# gcc -g -O2 -m32 -c baz.c
+# gcc -g -O2 -m32 -c bar.c
+# gcc -g -O2 -m32 -c foo.c
+# gcc -g -O2 -m32 -o testfilefoobarbaz foo.o bar.o baz.o
+
+testfiles testfilefoobarbaz
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=aranges testfilefoobarbaz <<EOF
+
+DWARF section [27] '.debug_aranges' at offset 0x1044:
+
+Table at offset 0:
+
+ Length:            28
+ DWARF version:      2
+ CU offset:          0
+ Address size:       4
+ Segment size:       0
+
+   0x080482f0 <main>..0x08048323 <main+0x33>
+
+Table at offset 32:
+
+ Length:            36
+ DWARF version:      2
+ CU offset:        136
+ Address size:       4
+ Segment size:       0
+
+   0x08048440 <bar>..0x08048451 <bar+0x11>
+   0x08048330 <nobar>..0x0804833a <nobar+0xa>
+
+Table at offset 72:
+
+ Length:            36
+ DWARF version:      2
+ CU offset:        1d1
+ Address size:       4
+ Segment size:       0
+
+   0x08048460 <baz>..0x080484bb <baz+0x5b>
+   0x08048340 <nobaz>..0x0804834a <nobaz+0xa>
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedaranges testfilefoobarbaz <<\EOF
+
+DWARF section [27] '.debug_aranges' at offset 0x1044 contains 5 entries:
+ [0] start: 0x080482f0, length:    52, CU DIE offset:     11
+ [1] start: 0x08048330, length:    11, CU DIE offset:    321
+ [2] start: 0x08048340, length:    11, CU DIE offset:    476
+ [3] start: 0x08048440, length:    18, CU DIE offset:    321
+ [4] start: 0x08048460, length:    92, CU DIE offset:    476
+EOF
+
+exit 0
diff --git a/tests/run-readelf-arm-flags.sh b/tests/run-readelf-arm-flags.sh
new file mode 100755
index 0000000..25c5477
--- /dev/null
+++ b/tests/run-readelf-arm-flags.sh
@@ -0,0 +1,30 @@
+#! /bin/sh
+
+. $srcdir/test-subr.sh
+
+# echo "int main () {}" | gcc -xc -o testfile-arm-flags -
+testfiles testfile-arm-flags
+
+testrun_compare ${abs_top_builddir}/src/readelf -h testfile-arm-flags <<\EOF
+ELF Header:
+  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
+  Class:                             ELF32
+  Data:                              2's complement, little endian
+  Ident Version:                     1 (current)
+  OS/ABI:                            UNIX - System V
+  ABI Version:                       0
+  Type:                              DYN (Shared object file)
+  Machine:                           ARM
+  Version:                           1 (current)
+  Entry point address:               0x3d1
+  Start of program headers:          52 (bytes into file)
+  Start of section headers:          6920 (bytes into file)
+  Flags:                             Version5 EABI, hard-float ABI
+  Size of this header:               52 (bytes)
+  Size of program header entries:    32 (bytes)
+  Number of program headers entries: 9
+  Size of section header entries:    40 (bytes)
+  Number of section headers entries: 29
+  Section header string table index: 28
+
+EOF
diff --git a/tests/run-readelf-compressed-zstd.sh b/tests/run-readelf-compressed-zstd.sh
new file mode 100755
index 0000000..9620809
--- /dev/null
+++ b/tests/run-readelf-compressed-zstd.sh
@@ -0,0 +1,39 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if ! grep -q -F '#define USE_ZSTD' ${abs_top_builddir}/config.h; then
+  echo "elfutils built without zstd support"
+  exit 77
+fi
+
+# See run-strip-reloc.sh
+testfiles hello_i386.ko
+
+tempfiles hello_i386.ko.zst readelf.out.1 readelf.out.2
+
+testrun ${abs_top_builddir}/src/readelf -a hello_i386.ko > readelf.out.1
+zstd hello_i386.ko
+testrun ${abs_top_builddir}/src/readelf -a hello_i386.ko.zst > readelf.out.2
+
+diff -u readelf.out.1 readelf.out.2
+if [ $? != 0 ]; then
+  exit 1;
+fi
+
+exit 0
diff --git a/tests/run-readelf-compressed.sh b/tests/run-readelf-compressed.sh
new file mode 100755
index 0000000..861553f
--- /dev/null
+++ b/tests/run-readelf-compressed.sh
@@ -0,0 +1,39 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if ! grep -q -F '#define USE_BZLIB' ${abs_top_builddir}/config.h; then
+  echo "elfutils built without bzip2 support"
+  exit 77
+fi
+
+# See run-strip-reloc.sh
+testfiles hello_i386.ko
+
+tempfiles hello_i386.ko.bz2 readelf.out.1 readelf.out.2
+
+testrun ${abs_top_builddir}/src/readelf -a hello_i386.ko > readelf.out.1
+bzip2 hello_i386.ko
+testrun ${abs_top_builddir}/src/readelf -a hello_i386.ko.bz2 > readelf.out.2
+
+diff -u readelf.out.1 readelf.out.2
+if [ $? != 0 ]; then
+  exit 1;
+fi
+
+exit 0
diff --git a/tests/run-readelf-const-values.sh b/tests/run-readelf-const-values.sh
new file mode 100755
index 0000000..0a6356f
--- /dev/null
+++ b/tests/run-readelf-const-values.sh
@@ -0,0 +1,230 @@
+#! /bin/sh
+# Test for displaying DW_AT_const_types with the "correct" sign.
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# = s.c
+#
+# int s()
+# {
+#   int i = -1;
+#   int j = -1;
+#
+#   return i - j;
+# }
+#
+# = m.c
+#
+# extern int s();
+#
+# int
+# main ()
+# {
+#   const signed char sc = -2;
+#   const unsigned char uc = 254;
+#
+#   const signed short ss = -16;
+#   const unsigned short us = 65520;
+#
+#   const signed int si = -3;
+#   const unsigned int ui = 4200000000;
+#
+#   signed long sl = -1;
+#   unsigned long ul = 0xffffffffffffffffUL;
+#
+#   return s ();
+# }
+#
+# gcc -gdwarf-5 -O2 -c s.c
+# gcc -gdwarf-4 -O2 -c m.c
+# gcc -o testfile-const-values s.o m.o
+# eu-strip -g -f testfile-const-values.debug testfile-const-values
+
+testfiles testfile-const-values.debug
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile-const-values.debug << EOF
+
+DWARF section [28] '.debug_info' at offset 0x2e0:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 5, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ Unit type: compile (1)
+ [     c]  compile_unit         abbrev: 2
+           producer             (strp) "GNU C11 7.3.1 20180303 (Red Hat 7.3.1-5) -mtune=generic -march=x86-64 -gdwarf-5 -O2"
+           language             (data1) C11 (29)
+           name                 (string) "s.c"
+           comp_dir             (strp) "/home/mark/build/elfutils-obj"
+           low_pc               (addr) 0x00000000004004d0
+           high_pc              (data8) 3 (0x00000000004004d3)
+           stmt_list            (sec_offset) 0
+ [    2e]    subprogram           abbrev: 3
+             external             (flag_present) yes
+             name                 (string) "s"
+             decl_file            (data1) s.c (1)
+             decl_line            (data1) 1
+             type                 (ref4) [    5e]
+             low_pc               (addr) 0x00000000004004d0
+             high_pc              (data8) 3 (0x00000000004004d3)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             call_all_calls       (flag_present) yes
+             sibling              (ref4) [    5e]
+ [    4d]      variable             abbrev: 1
+               name                 (string) "i"
+               decl_file            (implicit_const) s.c (1)
+               decl_line            (data1) 3
+               type                 (ref4) [    5e]
+               const_value          (implicit_const) -1
+ [    55]      variable             abbrev: 1
+               name                 (string) "j"
+               decl_file            (implicit_const) s.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    5e]
+               const_value          (implicit_const) -1
+ [    5e]    base_type            abbrev: 4
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ Compilation unit at offset 102:
+ Version: 4, Abbreviation section offset: 73, Address size: 8, Offset size: 4
+ [    71]  compile_unit         abbrev: 1
+           producer             (strp) "GNU C11 7.3.1 20180303 (Red Hat 7.3.1-5) -mtune=generic -march=x86-64 -gdwarf-4 -O2"
+           language             (data1) C99 (12)
+           name                 (string) "m.c"
+           comp_dir             (strp) "/home/mark/build/elfutils-obj"
+           ranges               (sec_offset) range list [     0]
+           low_pc               (addr) 000000000000000000
+           stmt_list            (sec_offset) 54
+ [    8f]    subprogram           abbrev: 2
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) m.c (1)
+             decl_line            (data1) 4
+             type                 (ref4) [   119]
+             low_pc               (addr) 0x00000000004003e0
+             high_pc              (data8) 7 (0x00000000004003e7)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [   119]
+ [    b0]      variable             abbrev: 3
+               name                 (string) "sc"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 6
+               type                 (ref4) [   12c]
+               const_value          (sdata) -2
+ [    bb]      variable             abbrev: 3
+               name                 (string) "uc"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 7
+               type                 (ref4) [   138]
+               const_value          (sdata) 254 (-2)
+ [    c6]      variable             abbrev: 3
+               name                 (string) "ss"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 9
+               type                 (ref4) [   144]
+               const_value          (sdata) -16
+ [    d1]      variable             abbrev: 3
+               name                 (string) "us"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 10
+               type                 (ref4) [   150]
+               const_value          (sdata) 65520 (-16)
+ [    dc]      variable             abbrev: 3
+               name                 (string) "si"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 12
+               type                 (ref4) [   120]
+               const_value          (sdata) -3
+ [    e7]      variable             abbrev: 3
+               name                 (string) "ui"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 13
+               type                 (ref4) [   15c]
+               const_value          (sdata) 4200000000 (-94967296)
+ [    f5]      variable             abbrev: 3
+               name                 (string) "sl"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 15
+               type                 (ref4) [   161]
+               const_value          (sdata) -1
+ [   100]      variable             abbrev: 3
+               name                 (string) "ul"
+               decl_file            (data1) m.c (1)
+               decl_line            (data1) 16
+               type                 (ref4) [   168]
+               const_value          (sdata) 18446744073709551615 (-1)
+ [   10b]      GNU_call_site        abbrev: 4
+               low_pc               (addr) 0x00000000004003e7
+               GNU_tail_call        (flag_present) yes
+               abstract_origin      (ref4) [   16f]
+ [   119]    base_type            abbrev: 5
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [   120]    const_type           abbrev: 6
+             type                 (ref4) [   119]
+ [   125]    base_type            abbrev: 7
+             byte_size            (data1) 1
+             encoding             (data1) signed_char (6)
+             name                 (strp) "signed char"
+ [   12c]    const_type           abbrev: 6
+             type                 (ref4) [   125]
+ [   131]    base_type            abbrev: 7
+             byte_size            (data1) 1
+             encoding             (data1) unsigned_char (8)
+             name                 (strp) "unsigned char"
+ [   138]    const_type           abbrev: 6
+             type                 (ref4) [   131]
+ [   13d]    base_type            abbrev: 7
+             byte_size            (data1) 2
+             encoding             (data1) signed (5)
+             name                 (strp) "short int"
+ [   144]    const_type           abbrev: 6
+             type                 (ref4) [   13d]
+ [   149]    base_type            abbrev: 7
+             byte_size            (data1) 2
+             encoding             (data1) unsigned (7)
+             name                 (strp) "short unsigned int"
+ [   150]    const_type           abbrev: 6
+             type                 (ref4) [   149]
+ [   155]    base_type            abbrev: 7
+             byte_size            (data1) 4
+             encoding             (data1) unsigned (7)
+             name                 (strp) "unsigned int"
+ [   15c]    const_type           abbrev: 6
+             type                 (ref4) [   155]
+ [   161]    base_type            abbrev: 7
+             byte_size            (data1) 8
+             encoding             (data1) signed (5)
+             name                 (strp) "long int"
+ [   168]    base_type            abbrev: 7
+             byte_size            (data1) 8
+             encoding             (data1) unsigned (7)
+             name                 (strp) "long unsigned int"
+ [   16f]    subprogram           abbrev: 8
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+             linkage_name         (string) "s"
+             name                 (string) "s"
+             decl_file            (data1) m.c (1)
+             decl_line            (data1) 1
+EOF
+
+exit 0
diff --git a/tests/run-readelf-d.sh b/tests/run-readelf-d.sh
new file mode 100755
index 0000000..69b01c4
--- /dev/null
+++ b/tests/run-readelf-d.sh
@@ -0,0 +1,65 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# #include <stdio.h>
+# 
+# __thread int i;
+# 
+# void print_i ()
+# {
+#   printf("%d\n", i);
+# }
+#
+# gcc -fPIC -shared -o testlib_dynseg.so testlib_dynseg.c
+# With ld --version
+# GNU gold (GNU Binutils 2.22.52.20120402) 1.11
+
+testfiles testlib_dynseg.so
+
+testrun_compare ${abs_top_builddir}/src/readelf -d testlib_dynseg.so <<\EOF
+
+Dynamic segment contains 23 entries:
+ Addr: 0x00000000000017e0  Offset: 0x0007e0  Link to section: [ 3] '.dynstr'
+  Type              Value
+  PLTGOT            0x00000000000019c8
+  PLTRELSZ          72 (bytes)
+  JMPREL            0x0000000000000568
+  PLTREL            RELA
+  RELA              0x00000000000004d8
+  RELASZ            144 (bytes)
+  RELAENT           24 (bytes)
+  RELACOUNT         1
+  SYMTAB            0x0000000000000228
+  SYMENT            24 (bytes)
+  STRTAB            0x0000000000000360
+  STRSZ             190 (bytes)
+  GNU_HASH          0x0000000000000420
+  NEEDED            Shared library: [libc.so.6]
+  NEEDED            Shared library: [ld-linux-x86-64.so.2]
+  INIT              0x00000000000005b0
+  FINI              0x0000000000000748
+  VERSYM            0x0000000000000460
+  VERDEF            0x000000000000047c
+  VERDEFNUM         1
+  VERNEED           0x0000000000000498
+  VERNEEDNUM        2
+  NULL              
+EOF
+
+exit 0
diff --git a/tests/run-readelf-discr.sh b/tests/run-readelf-discr.sh
new file mode 100755
index 0000000..dc84d82
--- /dev/null
+++ b/tests/run-readelf-discr.sh
@@ -0,0 +1,337 @@
+#! /bin/sh
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# = rng.ads =
+# package Rng is
+# 
+#    type Rec (I : Integer) is record
+#       case I is
+#  when Positive =>
+#     case I is
+#        when 1..15 | 17 | 23 =>
+#   null;
+#        when others =>
+#   J : Integer;
+#     end case;
+#  when -52..-1 =>
+#     Q: Integer;
+#  when -64 =>
+#     R: Boolean;
+#  when others =>
+#     null;
+#       end case;
+#    end record;
+# 
+#    R : Rec (1);
+# 
+# end Rng;
+
+# = urng.ads =
+#
+# package Urng is
+# 
+#    type Unsigned is mod 65536;
+#    type Rec (U : Unsigned) is record
+#       case U is
+#  when 17 | 23 | 32768..65535 =>
+#     null;
+#  when 256 => 
+#     B: Boolean;
+#  when others =>
+#     I : Integer;
+#       end case;
+#    end record;
+# 
+#    R : Rec (1);
+# 
+# end Urng;
+
+# gcc -c -g -fgnat-encodings=minimal -gstrict-dwarf rng.ads
+# eu-strip -g -f rng.debug rng.o 
+# gcc -c -g -fgnat-encodings=minimal -gstrict-dwarf urng.ads
+# eu-strip -g -f urng.debug urng.o 
+
+testfiles testfile-rng.debug testfile-urng.debug
+
+testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-rng.debug testfile-urng.debug <<EOF
+
+testfile-rng.debug:
+
+
+DWARF section [ 5] '.debug_info' at offset 0x40:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 1
+           producer             (strp) "GNU Ada 9.1.1 20190503 (Red Hat 9.1.1-1) -g -fgnat-encodings=minimal -gstrict-dwarf -mtune=generic -march=x86-64"
+           language             (data1) Ada95 (13)
+           name                 (strp) "rng.ads"
+           comp_dir             (strp) "/home/mark"
+           low_pc               (addr) 000000000000000000
+           high_pc              (data8) 2016 (0x00000000000007e0)
+           stmt_list            (sec_offset) 0
+ [    2d]    structure_type       abbrev: 2
+             name                 (strp) "rng__rec"
+             byte_size            (exprloc) 
+              [ 0] push_object_address
+              [ 1] deref_size 4
+              [ 3] call4 [    c6]
+              [ 8] plus_uconst 7
+              [10] const1s -4
+              [12] and
+             decl_file            (data1) rng.ads (1)
+             decl_line            (data1) 3
+             decl_column          (data1) 9
+             sibling              (ref4) [    ab]
+ [    47]      member               abbrev: 3
+               name                 (string) "i"
+               decl_file            (data1) rng.ads (1)
+               decl_line            (data1) 3
+               decl_column          (data1) 14
+               type                 (ref4) [    fe]
+               data_member_location (data1) 0
+ [    52]      variant_part         abbrev: 4
+               discr                (ref4) [    47]
+ [    57]        variant              abbrev: 5
+                 discr_list           (block1) range 1..2147483647
+                 sibling              (ref4) [    81]
+ [    64]          variant_part         abbrev: 4
+                   discr                (ref4) [    47]
+ [    69]            variant              abbrev: 6
+                     discr_list           (block1) range 1..15, label 17, label 23
+ [    72]            variant              abbrev: 7
+ [    73]              member               abbrev: 3
+                       name                 (string) "j"
+                       decl_file            (data1) rng.ads (1)
+                       decl_line            (data1) 10
+                       decl_column          (data1) 19
+                       type                 (ref4) [    fe]
+                       data_member_location (data1) 4
+ [    81]        variant              abbrev: 5
+                 discr_list           (block1) range -52..-1
+                 sibling              (ref4) [    96]
+ [    8a]          member               abbrev: 3
+                   name                 (string) "q"
+                   decl_file            (data1) rng.ads (1)
+                   decl_line            (data1) 13
+                   decl_column          (data1) 13
+                   type                 (ref4) [    fe]
+                   data_member_location (data1) 4
+ [    96]        variant              abbrev: 8
+                 discr_value          (sdata) -64
+                 sibling              (ref4) [    a8]
+ [    9c]          member               abbrev: 3
+                   name                 (string) "r"
+                   decl_file            (data1) rng.ads (1)
+                   decl_line            (data1) 15
+                   decl_column          (data1) 13
+                   type                 (ref4) [   105]
+                   data_member_location (data1) 4
+ [    a8]        variant              abbrev: 9
+ [    ab]    dwarf_procedure      abbrev: 10
+             location             (exprloc) 
+              [ 0] dup
+              [ 1] lit0
+              [ 2] gt
+              [ 3] over
+              [ 4] lit15
+              [ 5] le
+              [ 6] and
+              [ 7] over
+              [ 8] lit17
+              [ 9] eq
+              [10] or
+              [11] over
+              [12] lit23
+              [13] eq
+              [14] or
+              [15] bra 22
+              [18] lit4
+              [19] skip 23
+              [22] lit0
+              [23] swap
+              [24] drop
+ [    c6]    dwarf_procedure      abbrev: 10
+             location             (exprloc) 
+              [ 0] dup
+              [ 1] lit0
+              [ 2] gt
+              [ 3] bra 36
+              [ 6] dup
+              [ 7] const1s -52
+              [ 9] lt
+              [10] over
+              [11] lit0
+              [12] ge
+              [13] or
+              [14] bra 21
+              [17] lit4
+              [18] skip 33
+              [21] dup
+              [22] const1s -64
+              [24] eq
+              [25] bra 32
+              [28] lit0
+              [29] skip 33
+              [32] lit4
+              [33] skip 52
+              [36] dup
+              [37] call4 [    ab]
+              [42] plus_uconst 3
+              [44] const1s -4
+              [46] and
+              [47] plus_uconst 3
+              [49] const1s -4
+              [51] and
+              [52] swap
+              [53] drop
+ [    fe]    base_type            abbrev: 11
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (strp) "integer"
+             artificial           (flag_present) yes
+ [   105]    base_type            abbrev: 12
+             byte_size            (data1) 1
+             encoding             (data1) boolean (2)
+             name                 (strp) "boolean"
+ [   10c]    variable             abbrev: 13
+             name                 (strp) "rng__r"
+             decl_file            (data1) rng.ads (1)
+             decl_line            (data1) 21
+             decl_column          (data1) 4
+             type                 (ref4) [    2d]
+             external             (flag_present) yes
+             location             (exprloc) 
+              [ 0] addr 0x7e4
+ [   122]    subprogram           abbrev: 14
+             external             (flag_present) yes
+             name                 (strp) "rng___elabs"
+             artificial           (flag_present) yes
+             low_pc               (addr) 0x0000000000000734
+             high_pc              (data8) 22 (0x000000000000074a)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+
+testfile-urng.debug:
+
+
+DWARF section [ 5] '.debug_info' at offset 0x40:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 1
+           producer             (strp) "GNU Ada 9.1.1 20190503 (Red Hat 9.1.1-1) -g -fgnat-encodings=minimal -gstrict-dwarf -mtune=generic -march=x86-64"
+           language             (data1) Ada95 (13)
+           name                 (strp) "urng.ads"
+           comp_dir             (strp) "/home/mark"
+           low_pc               (addr) 000000000000000000
+           high_pc              (data8) 977 (0x00000000000003d1)
+           stmt_list            (sec_offset) 0
+ [    2d]    base_type            abbrev: 2
+             byte_size            (data1) 2
+             encoding             (data1) unsigned (7)
+             name                 (strp) "urng__unsigned"
+ [    34]    structure_type       abbrev: 3
+             name                 (strp) "urng__rec"
+             byte_size            (exprloc) 
+              [ 0] push_object_address
+              [ 1] deref_size 2
+              [ 3] call4 [    8d]
+              [ 8] plus_uconst 7
+              [10] const1s -4
+              [12] and
+             decl_file            (data1) urng.ads (1)
+             decl_line            (data1) 4
+             decl_column          (data1) 9
+             sibling              (ref4) [    8d]
+ [    4e]      member               abbrev: 4
+               name                 (string) "u"
+               decl_file            (data1) urng.ads (1)
+               decl_line            (data1) 4
+               decl_column          (data1) 14
+               type                 (ref4) [    2d]
+               data_member_location (data1) 0
+ [    59]      variant_part         abbrev: 5
+               discr                (ref4) [    4e]
+ [    5e]        variant              abbrev: 6
+                 discr_list           (block1) label 17, label 23, range 32768..65535
+ [    6b]        variant              abbrev: 7
+                 discr_value          (udata) 256
+                 sibling              (ref4) [    7e]
+ [    72]          member               abbrev: 4
+                   name                 (string) "b"
+                   decl_file            (data1) urng.ads (1)
+                   decl_line            (data1) 9
+                   decl_column          (data1) 13
+                   type                 (ref4) [    a4]
+                   data_member_location (data1) 4
+ [    7e]        variant              abbrev: 8
+ [    7f]          member               abbrev: 4
+                   name                 (string) "i"
+                   decl_file            (data1) urng.ads (1)
+                   decl_line            (data1) 11
+                   decl_column          (data1) 13
+                   type                 (ref4) [    ab]
+                   data_member_location (data1) 4
+ [    8d]    dwarf_procedure      abbrev: 9
+             location             (exprloc) 
+              [ 0] dup
+              [ 1] lit17
+              [ 2] ne
+              [ 3] over
+              [ 4] lit23
+              [ 5] ne
+              [ 6] and
+              [ 7] over
+              [ 8] lit0
+              [ 9] ge
+              [10] and
+              [11] bra 18
+              [14] lit0
+              [15] skip 19
+              [18] lit4
+              [19] swap
+              [20] drop
+ [    a4]    base_type            abbrev: 2
+             byte_size            (data1) 1
+             encoding             (data1) boolean (2)
+             name                 (strp) "boolean"
+ [    ab]    base_type            abbrev: 10
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (strp) "integer"
+             artificial           (flag_present) yes
+ [    b2]    variable             abbrev: 11
+             name                 (strp) "urng__r"
+             decl_file            (data1) urng.ads (1)
+             decl_line            (data1) 15
+             decl_column          (data1) 4
+             type                 (ref4) [    34]
+             external             (flag_present) yes
+             location             (exprloc) 
+              [ 0] addr 0x3d8
+ [    c8]    subprogram           abbrev: 12
+             external             (flag_present) yes
+             name                 (strp) "urng___elabs"
+             artificial           (flag_present) yes
+             low_pc               (addr) 0x0000000000000386
+             high_pc              (data8) 22 (0x000000000000039c)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+EOF
diff --git a/tests/run-readelf-dw-form-indirect.sh b/tests/run-readelf-dw-form-indirect.sh
new file mode 100755
index 0000000..5883848
--- /dev/null
+++ b/tests/run-readelf-dw-form-indirect.sh
@@ -0,0 +1,678 @@
+#! /bin/sh
+# Copyright (C) 2021 Facebook
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# // Program processed by https://github.com/facebookincubator/BOLT.
+# // gcc -g -O2 -fno-reorder-blocks-and-partition -Wl,--emit-relocs primes.c -o primes
+# // perf record -e cycles:u -j any,u -o perf.data -- ./primes 1000 > /dev/null
+# // perf2bolt -p perf.data -o perf.fdata ./primes
+# // llvm-bolt primes -o primes.bolt -data=perf.fdata -reorder-blocks=cache+ -reorder-functions=hfsort -split-functions=2 -split-all-cold -split-eh -dyno-stats -update-debug-sections
+#
+# #include <inttypes.h>
+# #include <stdbool.h>
+# #include <stdio.h>
+# #include <stdlib.h>
+# 
+# bool
+# is_prime (uint32_t n)
+# {
+#   if (n < 2)
+#     return false;
+#   if (n == 2)
+#     return true;
+#   if (n % 2 == 0)
+#     return false;
+#   for (uint32_t i = 3; i <= n / 2; i++)
+#     {
+#       if (n % i == 0)
+# 	return false;
+#     }
+#   return true;
+# }
+# 
+# int
+# main (int argc, char *argv[])
+# {
+#   if (argc != 2)
+#     return EXIT_FAILURE;
+#   int n = atoi (argv[1]);
+#   for (uint32_t i = 2; n > 0; i++)
+#     {
+#       if (is_prime (i))
+# 	{
+# 	  printf ("%" PRIu32 "\n", i);
+# 	  n--;
+# 	}
+#     }
+#   return EXIT_SUCCESS;
+# }
+testfiles testfile-dw-form-indirect
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile-dw-form-indirect << EOF
+
+DWARF section [33] '.debug_info' at offset 0x801db0:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 1
+           producer             (strp) "GNU C17 8.4.1 20200928 (Red Hat 8.4.1-1) -mtune=generic -march=x86-64 -g -O2 -fno-reorder-blocks-and-partition"
+           language             (data1) C99 (12)
+           name                 (strp) "primes.c"
+           comp_dir             (strp) "/home/osandov/bolt"
+           ranges               (sec_offset) range list [    10]
+           low_pc               (addr) 000000000000000000
+           stmt_list            (sec_offset) 0
+ [    29]    base_type            abbrev: 2
+             byte_size            (data1) 1
+             encoding             (data1) unsigned_char (8)
+             name                 (strp) "unsigned char"
+ [    30]    base_type            abbrev: 2
+             byte_size            (data1) 2
+             encoding             (data1) unsigned (7)
+             name                 (strp) "short unsigned int"
+ [    37]    base_type            abbrev: 2
+             byte_size            (data1) 4
+             encoding             (data1) unsigned (7)
+             name                 (strp) "unsigned int"
+ [    3e]    base_type            abbrev: 2
+             byte_size            (data1) 8
+             encoding             (data1) unsigned (7)
+             name                 (strp) "long unsigned int"
+ [    45]    base_type            abbrev: 2
+             byte_size            (data1) 1
+             encoding             (data1) signed_char (6)
+             name                 (strp) "signed char"
+ [    4c]    base_type            abbrev: 2
+             byte_size            (data1) 2
+             encoding             (data1) signed (5)
+             name                 (strp) "short int"
+ [    53]    base_type            abbrev: 3
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [    5a]    typedef              abbrev: 4
+             name                 (strp) "__uint32_t"
+             decl_file            (data1) types.h (3)
+             decl_line            (data1) 41
+             decl_column          (data1) 22
+             type                 (ref4) [    37]
+ [    66]    base_type            abbrev: 2
+             byte_size            (data1) 8
+             encoding             (data1) signed (5)
+             name                 (strp) "long int"
+ [    6d]    typedef              abbrev: 4
+             name                 (strp) "__off_t"
+             decl_file            (data1) types.h (3)
+             decl_line            (data1) 150
+             decl_column          (data1) 25
+             type                 (ref4) [    66]
+ [    79]    typedef              abbrev: 4
+             name                 (strp) "__off64_t"
+             decl_file            (data1) types.h (3)
+             decl_line            (data1) 151
+             decl_column          (data1) 27
+             type                 (ref4) [    66]
+ [    85]    pointer_type         abbrev: 5
+             byte_size            (data1) 8
+ [    87]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [    8d]
+ [    8d]    base_type            abbrev: 2
+             byte_size            (data1) 1
+             encoding             (data1) signed_char (6)
+             name                 (strp) "char"
+ [    94]    const_type           abbrev: 7
+             type                 (ref4) [    8d]
+ [    99]    typedef              abbrev: 4
+             name                 (strp) "uint32_t"
+             decl_file            (data1) stdint-uintn.h (4)
+             decl_line            (data1) 26
+             decl_column          (data1) 20
+             type                 (ref4) [    5a]
+ [    a5]    typedef              abbrev: 4
+             name                 (strp) "size_t"
+             decl_file            (data1) stddef.h (5)
+             decl_line            (data1) 216
+             decl_column          (data1) 23
+             type                 (ref4) [    3e]
+ [    b1]    structure_type       abbrev: 8
+             name                 (strp) "_IO_FILE"
+             byte_size            (data1) 216
+             decl_file            (data1) struct_FILE.h (6)
+             decl_line            (data1) 49
+             decl_column          (data1) 8
+             sibling              (ref4) [   238]
+ [    be]      member               abbrev: 9
+               name                 (strp) "_flags"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 51
+               decl_column          (data1) 7
+               type                 (ref4) [    53]
+               data_member_location (data1) 0
+ [    cb]      member               abbrev: 9
+               name                 (strp) "_IO_read_ptr"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 54
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 8
+ [    d8]      member               abbrev: 9
+               name                 (strp) "_IO_read_end"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 55
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 16
+ [    e5]      member               abbrev: 9
+               name                 (strp) "_IO_read_base"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 56
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 24
+ [    f2]      member               abbrev: 9
+               name                 (strp) "_IO_write_base"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 57
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 32
+ [    ff]      member               abbrev: 9
+               name                 (strp) "_IO_write_ptr"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 58
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 40
+ [   10c]      member               abbrev: 9
+               name                 (strp) "_IO_write_end"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 59
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 48
+ [   119]      member               abbrev: 9
+               name                 (strp) "_IO_buf_base"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 60
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 56
+ [   126]      member               abbrev: 9
+               name                 (strp) "_IO_buf_end"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 61
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 64
+ [   133]      member               abbrev: 9
+               name                 (strp) "_IO_save_base"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 64
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 72
+ [   140]      member               abbrev: 9
+               name                 (strp) "_IO_backup_base"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 65
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 80
+ [   14d]      member               abbrev: 9
+               name                 (strp) "_IO_save_end"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 66
+               decl_column          (data1) 9
+               type                 (ref4) [    87]
+               data_member_location (data1) 88
+ [   15a]      member               abbrev: 9
+               name                 (strp) "_markers"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 68
+               decl_column          (data1) 22
+               type                 (ref4) [   251]
+               data_member_location (data1) 96
+ [   167]      member               abbrev: 9
+               name                 (strp) "_chain"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 70
+               decl_column          (data1) 20
+               type                 (ref4) [   257]
+               data_member_location (data1) 104
+ [   174]      member               abbrev: 9
+               name                 (strp) "_fileno"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 72
+               decl_column          (data1) 7
+               type                 (ref4) [    53]
+               data_member_location (data1) 112
+ [   181]      member               abbrev: 9
+               name                 (strp) "_flags2"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 73
+               decl_column          (data1) 7
+               type                 (ref4) [    53]
+               data_member_location (data1) 116
+ [   18e]      member               abbrev: 9
+               name                 (strp) "_old_offset"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 74
+               decl_column          (data1) 11
+               type                 (ref4) [    6d]
+               data_member_location (data1) 120
+ [   19b]      member               abbrev: 9
+               name                 (strp) "_cur_column"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 77
+               decl_column          (data1) 18
+               type                 (ref4) [    30]
+               data_member_location (data1) 128
+ [   1a8]      member               abbrev: 9
+               name                 (strp) "_vtable_offset"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 78
+               decl_column          (data1) 15
+               type                 (ref4) [    45]
+               data_member_location (data1) 130
+ [   1b5]      member               abbrev: 9
+               name                 (strp) "_shortbuf"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 79
+               decl_column          (data1) 8
+               type                 (ref4) [   25d]
+               data_member_location (data1) 131
+ [   1c2]      member               abbrev: 9
+               name                 (strp) "_lock"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 81
+               decl_column          (data1) 15
+               type                 (ref4) [   26d]
+               data_member_location (data1) 136
+ [   1cf]      member               abbrev: 9
+               name                 (strp) "_offset"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 89
+               decl_column          (data1) 13
+               type                 (ref4) [    79]
+               data_member_location (data1) 144
+ [   1dc]      member               abbrev: 9
+               name                 (strp) "_codecvt"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 91
+               decl_column          (data1) 23
+               type                 (ref4) [   278]
+               data_member_location (data1) 152
+ [   1e9]      member               abbrev: 9
+               name                 (strp) "_wide_data"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 92
+               decl_column          (data1) 25
+               type                 (ref4) [   283]
+               data_member_location (data1) 160
+ [   1f6]      member               abbrev: 9
+               name                 (strp) "_freeres_list"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 93
+               decl_column          (data1) 20
+               type                 (ref4) [   257]
+               data_member_location (data1) 168
+ [   203]      member               abbrev: 9
+               name                 (strp) "_freeres_buf"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 94
+               decl_column          (data1) 9
+               type                 (ref4) [    85]
+               data_member_location (data1) 176
+ [   210]      member               abbrev: 9
+               name                 (strp) "__pad5"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 95
+               decl_column          (data1) 10
+               type                 (ref4) [    a5]
+               data_member_location (data1) 184
+ [   21d]      member               abbrev: 9
+               name                 (strp) "_mode"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 96
+               decl_column          (data1) 7
+               type                 (ref4) [    53]
+               data_member_location (data1) 192
+ [   22a]      member               abbrev: 9
+               name                 (strp) "_unused2"
+               decl_file            (data1) struct_FILE.h (6)
+               decl_line            (data1) 98
+               decl_column          (data1) 8
+               type                 (ref4) [   289]
+               data_member_location (data1) 196
+ [   238]    typedef              abbrev: 4
+             name                 (strp) "FILE"
+             decl_file            (data1) FILE.h (7)
+             decl_line            (data1) 7
+             decl_column          (data1) 25
+             type                 (ref4) [    b1]
+ [   244]    typedef              abbrev: 10
+             name                 (strp) "_IO_lock_t"
+             decl_file            (data1) struct_FILE.h (6)
+             decl_line            (data1) 43
+             decl_column          (data1) 14
+ [   24c]    structure_type       abbrev: 11
+             name                 (strp) "_IO_marker"
+             declaration          (flag_present) yes
+ [   251]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [   24c]
+ [   257]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [    b1]
+ [   25d]    array_type           abbrev: 12
+             type                 (ref4) [    8d]
+             sibling              (ref4) [   26d]
+ [   266]      subrange_type        abbrev: 13
+               type                 (ref4) [    3e]
+               upper_bound          (data1) 0
+ [   26d]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [   244]
+ [   273]    structure_type       abbrev: 11
+             name                 (strp) "_IO_codecvt"
+             declaration          (flag_present) yes
+ [   278]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [   273]
+ [   27e]    structure_type       abbrev: 11
+             name                 (strp) "_IO_wide_data"
+             declaration          (flag_present) yes
+ [   283]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [   27e]
+ [   289]    array_type           abbrev: 12
+             type                 (ref4) [    8d]
+             sibling              (ref4) [   299]
+ [   292]      subrange_type        abbrev: 13
+               type                 (ref4) [    3e]
+               upper_bound          (data1) 19
+ [   299]    variable             abbrev: 14
+             name                 (strp) "stdin"
+             decl_file            (data1) stdio.h (8)
+             decl_line            (data1) 137
+             decl_column          (data1) 14
+             type                 (ref4) [   2a5]
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+ [   2a5]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [   238]
+ [   2ab]    variable             abbrev: 14
+             name                 (strp) "stdout"
+             decl_file            (data1) stdio.h (8)
+             decl_line            (data1) 138
+             decl_column          (data1) 14
+             type                 (ref4) [   2a5]
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+ [   2b7]    variable             abbrev: 14
+             name                 (strp) "stderr"
+             decl_file            (data1) stdio.h (8)
+             decl_line            (data1) 139
+             decl_column          (data1) 14
+             type                 (ref4) [   2a5]
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+ [   2c3]    variable             abbrev: 14
+             name                 (strp) "sys_nerr"
+             decl_file            (data1) sys_errlist.h (9)
+             decl_line            (data1) 26
+             decl_column          (data1) 12
+             type                 (ref4) [    53]
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+ [   2cf]    array_type           abbrev: 12
+             type                 (ref4) [   2e5]
+             sibling              (ref4) [   2da]
+ [   2d8]      subrange_type        abbrev: 15
+ [   2da]    const_type           abbrev: 7
+             type                 (ref4) [   2cf]
+ [   2df]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [    94]
+ [   2e5]    const_type           abbrev: 7
+             type                 (ref4) [   2df]
+ [   2ea]    variable             abbrev: 14
+             name                 (strp) "sys_errlist"
+             decl_file            (data1) sys_errlist.h (9)
+             decl_line            (data1) 27
+             decl_column          (data1) 26
+             type                 (ref4) [   2da]
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+ [   2f6]    base_type            abbrev: 2
+             byte_size            (data1) 8
+             encoding             (data1) signed (5)
+             name                 (strp) "long long int"
+ [   2fd]    base_type            abbrev: 2
+             byte_size            (data1) 8
+             encoding             (data1) unsigned (7)
+             name                 (strp) "long long unsigned int"
+ [   304]    subprogram           abbrev: 16
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) primes.c (1)
+             decl_line            (data1) 24
+             decl_column          (data1) 1
+             prototyped           (flag_present) yes
+             type                 (ref4) [    53]
+             ranges               (sec_offset) range list [    50]
+             low_pc               (addr) 000000000000000000
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [   429]
+ [   326]      formal_parameter     abbrev: 17
+               name                 (strp) "argc"
+               decl_file            (data1) primes.c (1)
+               decl_line            (data1) 24
+               decl_column          (data1) 11
+               type                 (ref4) [    53]
+               location             (sec_offset) location list [    10]
+               GNU_locviews         (sec_offset) location list [     0]
+ [   33a]      formal_parameter     abbrev: 17
+               name                 (strp) "argv"
+               decl_file            (data1) primes.c (1)
+               decl_line            (data1) 24
+               decl_column          (data1) 23
+               type                 (ref4) [   429]
+               location             (sec_offset) location list [    72]
+               GNU_locviews         (sec_offset) location list [    3d]
+ [   34e]      variable             abbrev: 18
+               name                 (string) "n"
+               decl_file            (data1) primes.c (1)
+               decl_line            (data1) 28
+               decl_column          (data1) 7
+               type                 (ref4) [    53]
+               location             (sec_offset) location list [    d4]
+               GNU_locviews         (sec_offset) location list [    7a]
+ [   360]      lexical_block        abbrev: 19
+               ranges               (sec_offset) range list [    80]
+               sibling              (ref4) [   3ed]
+ [   369]        variable             abbrev: 18
+                 name                 (string) "i"
+                 decl_file            (data1) primes.c (1)
+                 decl_line            (data1) 29
+                 decl_column          (data1) 17
+                 type                 (ref4) [    99]
+                 location             (sec_offset) location list [   158]
+                 GNU_locviews         (sec_offset) location list [    f5]
+ [   37b]        inlined_subroutine   abbrev: 20
+                 abstract_origin      (ref4) [   42f]
+                 entry_pc             (addr) 0x0000000000400520
+                 GNU_entry_view       (data1) 6
+                 ranges               (sec_offset) range list [    e0]
+                 call_file            (data1) primes.c (1)
+                 call_line            (data1) 31
+                 call_column          (data1) 11
+                 sibling              (ref4) [   3cb]
+ [   394]          formal_parameter     abbrev: 21
+                   abstract_origin      (ref4) [   440]
+                   location             (sec_offset) location list [   1dd]
+                   GNU_locviews         (sec_offset) location list [   186]
+ [   3a1]          inlined_subroutine   abbrev: 22
+                   abstract_origin      (ref4) [   42f]
+                   ranges               (sec_offset) range list [   120]
+                   call_file            (data1) primes.c (1)
+                   call_line            (data1) 7
+                   call_column          (data1) 1
+ [   3ad]            formal_parameter     abbrev: 23
+                     abstract_origin      (ref4) [   440]
+ [   3b2]            lexical_block        abbrev: 24
+                     abstract_origin      (ref4) [   44a]
+                     ranges               (sec_offset) range list [   120]
+ [   3bb]              variable             abbrev: 25
+                       abstract_origin      (ref4) [   44b]
+                       location             (sec_offset) location list [   250]
+                       GNU_locviews         (sec_offset) location list [   203]
+ [   3cb]        GNU_call_site        abbrev: 26
+                 low_pc               (addr) 0x0000000000a000c7 <.annobin_init.c.unlikely.cold.0+0x47>
+                 abstract_origin      (ref4) [   4e2]
+ [   3d8]          GNU_call_site_parameter abbrev: 27
+                   location             (exprloc) 
+                    [ 0] reg5
+                   GNU_call_site_value  (exprloc) 
+                    [ 0] addr 0x400788 <__dso_handle+0x8>
+ [   3e5]          GNU_call_site_parameter abbrev: 27
+                   location             (exprloc) 
+                    [ 0] reg4
+                   GNU_call_site_value  (exprloc) 
+                    [ 0] breg3 -1
+ [   3ed]      inlined_subroutine   abbrev: 28
+               abstract_origin      (ref4) [   45e]
+               entry_pc             (addr) 0x00000000004004fb
+               GNU_entry_view       (data1) 1
+               ranges               (sec_offset) range list [   150]
+               call_file            (data1) primes.c (1)
+               call_line            (data1) 28
+               call_column          (data1) 11
+ [   402]        formal_parameter     abbrev: 21
+                 abstract_origin      (ref4) [   470]
+                 location             (sec_offset) location list [   2ad]
+                 GNU_locviews         (sec_offset) location list [   268]
+ [   40f]        GNU_call_site        abbrev: 26
+                 low_pc               (addr) 0x0000000000a000a4 <.annobin_init.c.unlikely.cold.0+0x24>
+                 abstract_origin      (ref4) [   4ef]
+ [   41c]          GNU_call_site_parameter abbrev: 27
+                   location             (exprloc) 
+                    [ 0] reg4
+                   GNU_call_site_value  (exprloc) 
+                    [ 0] lit0
+ [   421]          GNU_call_site_parameter abbrev: 27
+                   location             (exprloc) 
+                    [ 0] reg1
+                   GNU_call_site_value  (exprloc) 
+                    [ 0] lit10
+ [   429]    pointer_type         abbrev: 6
+             byte_size            (data1) 8
+             type                 (ref4) [    87]
+ [   42f]    subprogram           abbrev: 29
+             external             (flag_present) yes
+             name                 (strp) "is_prime"
+             decl_file            (data1) primes.c (1)
+             decl_line            (data1) 7
+             decl_column          (data1) 1
+             prototyped           (flag_present) yes
+             type                 (ref4) [   457]
+             inline               (data1) inlined (1)
+             sibling              (ref4) [   457]
+ [   440]      formal_parameter     abbrev: 30
+               name                 (string) "n"
+               decl_file            (data1) primes.c (1)
+               decl_line            (data1) 7
+               decl_column          (data1) 20
+               type                 (ref4) [    99]
+ [   44a]      lexical_block        abbrev: 31
+ [   44b]        variable             abbrev: 32
+                 name                 (string) "i"
+                 decl_file            (data1) primes.c (1)
+                 decl_line            (data1) 15
+                 decl_column          (data1) 17
+                 type                 (ref4) [    99]
+ [   457]    base_type            abbrev: 2
+             byte_size            (data1) 1
+             encoding             (data1) boolean (2)
+             name                 (strp) "_Bool"
+ [   45e]    subprogram           abbrev: 33
+             external             (flag_present) yes
+             name                 (strp) "atoi"
+             decl_file            (data1) stdlib.h (2)
+             decl_line            (data2) 361
+             decl_column          (data1) 1
+             prototyped           (flag_present) yes
+             type                 (ref4) [    53]
+             inline               (data1) declared_inlined (3)
+             sibling              (ref4) [   47e]
+ [   470]      formal_parameter     abbrev: 34
+               name                 (strp) "__nptr"
+               decl_file            (data1) stdlib.h (2)
+               decl_line            (data2) 361
+               decl_column          (data1) 1
+               type                 (ref4) [   2df]
+ [   47e]    subprogram           abbrev: 35
+             abstract_origin      (ref4) [   42f]
+             low_pc               (addr) 0x0000000000400680 <is_prime>
+             high_pc              (data8) 101 (0x00000000004006e5)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [   4e2]
+ [   499]      formal_parameter     abbrev: 36
+               abstract_origin      (ref4) [   440]
+               location             (exprloc) 
+                [ 0] reg5
+ [   4a0]      inlined_subroutine   abbrev: 37
+               abstract_origin      (ref4) [   42f]
+               ranges               (sec_offset) range list [   1a0]
+               low_pc               (addr) 000000000000000000
+               call_file            (data1) primes.c (1)
+               call_line            (data1) 7
+               call_column          (data1) 1
+ [   4b8]        formal_parameter     abbrev: 23
+                 abstract_origin      (ref4) [   440]
+ [   4bd]        lexical_block        abbrev: 38
+                 abstract_origin      (ref4) [   44a]
+                 ranges               (sec_offset) range list [   1a0]
+                 low_pc               (addr) 000000000000000000
+ [   4d2]          variable             abbrev: 25
+                   abstract_origin      (ref4) [   44b]
+                   location             (sec_offset) location list [   2d1]
+                   GNU_locviews         (sec_offset) location list [   28e]
+ [   4e2]    subprogram           abbrev: 39
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+             linkage_name         (strp) "printf"
+             name                 (strp) "printf"
+             decl_file            (data1) stdio.h (8)
+             decl_line            (data2) 332
+             decl_column          (data1) 12
+ [   4ef]    subprogram           abbrev: 40
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+             linkage_name         (strp) "strtol"
+             name                 (strp) "strtol"
+             decl_file            (data1) stdlib.h (2)
+             decl_line            (data1) 176
+             decl_column          (data1) 17
+EOF
diff --git a/tests/run-readelf-dwz-multi.sh b/tests/run-readelf-dwz-multi.sh
new file mode 100755
index 0000000..4f317ac
--- /dev/null
+++ b/tests/run-readelf-dwz-multi.sh
@@ -0,0 +1,332 @@
+#! /bin/sh
+# Copyright (C) 2012, 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# common.h
+#
+# #include <stdio.h>
+#
+# struct foobar
+# {
+#   int foo;
+#   struct foobar *bar;
+# };
+#
+# extern int call_foo(struct foobar *foobar_struct_ptr);
+
+# main.c
+#
+# #include "common.h"
+#
+# int main(int argc, char ** argv)
+# {
+#   struct foobar b;
+#   b.foo = 42;
+#   b.bar = &b;
+#
+#   return call_foo(b.bar);
+# }
+
+# shared.c
+#
+# #include "common.h"
+#
+# int call_foo(struct foobar *fb)
+# {
+#   return fb->bar->foo - 42;
+# }
+
+# gcc -fPIC -g -c -Wall shared.c
+# gcc -shared -o libtestfile_multi_shared.so shared.o
+# gcc -g -o testfile_multi_main -L. -ltestfile_multi_shared main.c -Wl,-rpath,.
+# dwz -m testfile_multi.dwz testfile_multi_main libtestfile_multi_shared.so
+
+# main.c
+#
+# struct foobarbaz
+# {
+#   int counter;
+#   char *bookstore;
+# };
+#
+# int
+# main (int argc, char **argv)
+# {
+#   struct foobarbaz fbb;
+#   return 0;
+# }
+
+# gcc -g -o testfile-dwzstr main.c
+# cp testfile-dwzstr testfile-dwzstr.alt
+# dwz -m testfile-dwzstr.multi testfile-dwzstr testfile-dwzstr.alt
+
+testfiles libtestfile_multi_shared.so testfile_multi_main testfile_multi.dwz
+testfiles testfile-dwzstr testfile-dwzstr.multi
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile_multi_main <<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x1078:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 6
+           producer             (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -mtune=generic -march=x86-64 -g"
+           language             (data1) C89 (1)
+           name                 (strp) "main.c"
+           comp_dir             (GNU_strp_alt) "/home/mark/src/tests/dwz"
+           low_pc               (addr) 0x00000000004006ac <main>
+           high_pc              (udata) 44 (0x00000000004006d8)
+           stmt_list            (sec_offset) 0
+ [    26]    imported_unit        abbrev: 5
+             import               (GNU_ref_alt) [     b]
+ [    2b]    pointer_type         abbrev: 1
+             byte_size            (data1) 8
+             type                 (GNU_ref_alt) [    53]
+ [    31]    subprogram           abbrev: 3
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) main.c (1)
+             decl_line            (data1) 3
+             prototyped           (flag_present) yes
+             type                 (GNU_ref_alt) [    3e]
+             low_pc               (addr) 0x00000000004006ac <main>
+             high_pc              (udata) 44 (0x00000000004006d8)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_tail_call_sites (flag_present) yes
+             sibling              (ref_udata) [    6e]
+ [    48]      formal_parameter     abbrev: 8
+               name                 (strp) "argc"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 3
+               type                 (GNU_ref_alt) [    3e]
+               location             (exprloc) 
+                [ 0] fbreg -36
+ [    56]      formal_parameter     abbrev: 4
+               name                 (strp) "argv"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 3
+               type                 (ref_udata) [    6e]
+               location             (exprloc) 
+                [ 0] fbreg -48
+ [    61]      variable             abbrev: 7
+               name                 (string) "b"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 5
+               type                 (GNU_ref_alt) [    5a]
+               location             (exprloc) 
+                [ 0] fbreg -32
+ [    6e]    pointer_type         abbrev: 2
+             byte_size            (data1) 8
+             type                 (ref_udata) [    2b]
+EOF
+
+# Same as above, but find alt debug file in a .dwz subdir.
+mkdir .dwz
+mv testfile_multi.dwz .dwz
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile_multi_main <<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x1078:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 6
+           producer             (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -mtune=generic -march=x86-64 -g"
+           language             (data1) C89 (1)
+           name                 (strp) "main.c"
+           comp_dir             (GNU_strp_alt) "/home/mark/src/tests/dwz"
+           low_pc               (addr) 0x00000000004006ac <main>
+           high_pc              (udata) 44 (0x00000000004006d8)
+           stmt_list            (sec_offset) 0
+ [    26]    imported_unit        abbrev: 5
+             import               (GNU_ref_alt) [     b]
+ [    2b]    pointer_type         abbrev: 1
+             byte_size            (data1) 8
+             type                 (GNU_ref_alt) [    53]
+ [    31]    subprogram           abbrev: 3
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) main.c (1)
+             decl_line            (data1) 3
+             prototyped           (flag_present) yes
+             type                 (GNU_ref_alt) [    3e]
+             low_pc               (addr) 0x00000000004006ac <main>
+             high_pc              (udata) 44 (0x00000000004006d8)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_tail_call_sites (flag_present) yes
+             sibling              (ref_udata) [    6e]
+ [    48]      formal_parameter     abbrev: 8
+               name                 (strp) "argc"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 3
+               type                 (GNU_ref_alt) [    3e]
+               location             (exprloc) 
+                [ 0] fbreg -36
+ [    56]      formal_parameter     abbrev: 4
+               name                 (strp) "argv"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 3
+               type                 (ref_udata) [    6e]
+               location             (exprloc) 
+                [ 0] fbreg -48
+ [    61]      variable             abbrev: 7
+               name                 (string) "b"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 5
+               type                 (GNU_ref_alt) [    5a]
+               location             (exprloc) 
+                [ 0] fbreg -32
+ [    6e]    pointer_type         abbrev: 2
+             byte_size            (data1) 8
+             type                 (ref_udata) [    2b]
+EOF
+mv .dwz/testfile_multi.dwz .
+rmdir .dwz
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info libtestfile_multi_shared.so <<\EOF
+
+DWARF section [25] '.debug_info' at offset 0x106c:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 3
+           producer             (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -fpreprocessed -mtune=generic -march=x86-64 -g -fPIC"
+           language             (data1) C89 (1)
+           name                 (strp) "shared.c"
+           comp_dir             (GNU_strp_alt) "/home/mark/src/tests/dwz"
+           low_pc               (addr) +0x0000000000000670 <call_foo>
+           high_pc              (udata) 23 (+0x0000000000000687)
+           stmt_list            (sec_offset) 0
+ [    26]    imported_unit        abbrev: 2
+             import               (GNU_ref_alt) [     b]
+ [    2b]    subprogram           abbrev: 1
+             external             (flag_present) yes
+             name                 (strp) "call_foo"
+             decl_file            (data1) shared.c (1)
+             decl_line            (data1) 3
+             prototyped           (flag_present) yes
+             type                 (GNU_ref_alt) [    3e]
+             low_pc               (addr) +0x0000000000000670 <call_foo>
+             high_pc              (udata) 23 (+0x0000000000000687)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+ [    41]      formal_parameter     abbrev: 4
+               name                 (string) "fb"
+               decl_file            (data1) shared.c (1)
+               decl_line            (data1) 3
+               type                 (GNU_ref_alt) [    76]
+               location             (exprloc) 
+                [ 0] fbreg -24
+EOF
+
+# Same as above, but find alt debug file in a .dwz subdir.
+mkdir .dwz
+mv testfile_multi.dwz .dwz
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info libtestfile_multi_shared.so <<\EOF
+
+DWARF section [25] '.debug_info' at offset 0x106c:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 3
+           producer             (strp) "GNU C 4.7.0 20120507 (Red Hat 4.7.0-5) -fpreprocessed -mtune=generic -march=x86-64 -g -fPIC"
+           language             (data1) C89 (1)
+           name                 (strp) "shared.c"
+           comp_dir             (GNU_strp_alt) "/home/mark/src/tests/dwz"
+           low_pc               (addr) +0x0000000000000670 <call_foo>
+           high_pc              (udata) 23 (+0x0000000000000687)
+           stmt_list            (sec_offset) 0
+ [    26]    imported_unit        abbrev: 2
+             import               (GNU_ref_alt) [     b]
+ [    2b]    subprogram           abbrev: 1
+             external             (flag_present) yes
+             name                 (strp) "call_foo"
+             decl_file            (data1) shared.c (1)
+             decl_line            (data1) 3
+             prototyped           (flag_present) yes
+             type                 (GNU_ref_alt) [    3e]
+             low_pc               (addr) +0x0000000000000670 <call_foo>
+             high_pc              (udata) 23 (+0x0000000000000687)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+ [    41]      formal_parameter     abbrev: 4
+               name                 (string) "fb"
+               decl_file            (data1) shared.c (1)
+               decl_line            (data1) 3
+               type                 (GNU_ref_alt) [    76]
+               location             (exprloc) 
+                [ 0] fbreg -24
+EOF
+mv .dwz/testfile_multi.dwz .
+rmdir .dwz
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile-dwzstr <<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x1088:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 5
+           producer             (GNU_strp_alt) "GNU C 4.7.2 20121109 (Red Hat 4.7.2-8) -mtune=generic -march=x86-64 -g"
+           language             (data1) C89 (1)
+           name                 (GNU_strp_alt) "main.c"
+           comp_dir             (GNU_strp_alt) "/home/mark/src/tests"
+           low_pc               (addr) 0x00000000004004ec <main>
+           high_pc              (udata) 18 (0x00000000004004fe)
+           stmt_list            (sec_offset) 0
+ [    26]    imported_unit        abbrev: 2
+             import               (GNU_ref_alt) [     b]
+ [    2b]    subprogram           abbrev: 4
+             external             (flag_present) yes
+             name                 (GNU_strp_alt) "main"
+             decl_file            (data1) main.c (1)
+             decl_line            (data1) 8
+             prototyped           (flag_present) yes
+             type                 (GNU_ref_alt) [    30]
+             low_pc               (addr) 0x00000000004004ec <main>
+             high_pc              (udata) 18 (0x00000000004004fe)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+ [    41]      formal_parameter     abbrev: 1
+               name                 (GNU_strp_alt) "argc"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 8
+               type                 (GNU_ref_alt) [    30]
+               location             (exprloc) 
+                [ 0] fbreg -36
+ [    4f]      formal_parameter     abbrev: 1
+               name                 (GNU_strp_alt) "argv"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 8
+               type                 (GNU_ref_alt) [    41]
+               location             (exprloc) 
+                [ 0] fbreg -48
+ [    5d]      variable             abbrev: 3
+               name                 (string) "fbb"
+               decl_file            (data1) main.c (1)
+               decl_line            (data1) 10
+               type                 (GNU_ref_alt) [    14]
+               location             (exprloc) 
+                [ 0] fbreg -32
+EOF
+
+exit 0
diff --git a/tests/run-readelf-fat-lto.sh b/tests/run-readelf-fat-lto.sh
new file mode 100755
index 0000000..e03cec3
--- /dev/null
+++ b/tests/run-readelf-fat-lto.sh
@@ -0,0 +1,53 @@
+. $srcdir/test-subr.sh
+
+# - s.c
+# int main_argc_remaining;
+#
+# int main_argc() {
+#   int result = 0;
+#   if (main_argc_remaining)
+#     result = 0;
+#
+#   return 0;
+# }
+#
+# gcc -gdwarf-5 -c -o testfile-dwarf5-fat-lto.o -flto -O s.c -g -ffat-lto-objects
+
+testfiles testfile-dwarf5-fat-lto.o
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --debug-dump=ranges -N -U testfile-dwarf5-fat-lto.o << EOF
+
+DWARF section [26] '.debug_loclists' at offset 0x7db:
+Table at Offset 0x0:
+
+ Length:               24
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        0
+ CU [     c] base: 000000000000000000
+
+  Offset: c, Index: 0
+    view pair 2, 3
+
+  Offset: e, Index: 2
+    start_length 0x0, 0
+        [ 0] lit0
+        [ 1] stack_value
+    end_of_list
+
+
+DWARF section [30] '.debug_rnglists' at offset 0x827:
+Table at Offset 0x0:
+
+ Length:               19
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        0
+ CU [     c] base: 000000000000000000
+
+  Offset: c, Index: 0
+    start_length 0x0, 8
+    end_of_list
+
+EOF
diff --git a/tests/run-readelf-frames.sh b/tests/run-readelf-frames.sh
new file mode 100755
index 0000000..f0429d1
--- /dev/null
+++ b/tests/run-readelf-frames.sh
@@ -0,0 +1,173 @@
+#! /bin/sh
+# Copyright (C) 2020 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-readelf-n.sh
+testfiles testfile-gnu-property-note-aarch64
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=frames testfile-gnu-property-note-aarch64 <<\EOF
+
+Call frame search table section [17] '.eh_frame_hdr':
+ version:          1
+ eh_frame_ptr_enc: 0x1b (sdata4 pcrel)
+ fde_count_enc:    0x3 (udata4)
+ table_enc:        0x3b (sdata4 datarel)
+ eh_frame_ptr:     0x44 (offset: 0x758)
+ fde_count:        7
+ Table:
+  0xfffffe70 (offset:  0x580) -> 0x5c fde=[    14]
+  0xfffffea0 (offset:  0x5b0) -> 0x70 fde=[    28]
+  0xfffffee0 (offset:  0x5f0) -> 0x84 fde=[    3c]
+  0xffffff20 (offset:  0x630) -> 0xac fde=[    64]
+  0xffffff28 (offset:  0x638) -> 0xc0 fde=[    78]
+  0xffffff40 (offset:  0x650) -> 0xd8 fde=[    90]
+  0xffffffc0 (offset:  0x6d0) -> 0x110 fde=[    c8]
+
+Call frame information section [18] '.eh_frame' at offset 0x758:
+
+ [     0] CIE length=16
+   CIE_id:                   0
+   version:                  1
+   augmentation:             "zR"
+   code_alignment_factor:    4
+   data_alignment_factor:    -8
+   return_address_register:  30
+   Augmentation data:        0x1b (FDE address encoding: sdata4 pcrel)
+
+   Program:
+     def_cfa r31 (sp) at offset 0
+
+ [    14] FDE length=16 cie=[     0]
+   CIE_pointer:              24
+   initial_location:         0x0000000000400580 (offset: 0x580)
+   address_range:            0x30 (end offset: 0x5b0)
+
+   Program:
+     nop
+     nop
+     nop
+
+ [    28] FDE length=16 cie=[     0]
+   CIE_pointer:              44
+   initial_location:         0x00000000004005b0 (offset: 0x5b0)
+   address_range:            0x3c (end offset: 0x5ec)
+
+   Program:
+     nop
+     nop
+     nop
+
+ [    3c] FDE length=36 cie=[     0]
+   CIE_pointer:              64
+   initial_location:         0x00000000004005f0 (offset: 0x5f0)
+   address_range:            0x38 (end offset: 0x628)
+
+   Program:
+     advance_loc 1 to 0x5f4
+     AARCH64_negate_ra_state
+     advance_loc 1 to 0x5f8
+     def_cfa_offset 32
+     offset r29 (x29) at cfa-32
+     offset r30 (x30) at cfa-24
+     advance_loc 2 to 0x600
+     offset r19 (x19) at cfa-16
+     advance_loc 8 to 0x620
+     restore r30 (x30)
+     restore r29 (x29)
+     restore r19 (x19)
+     def_cfa_offset 0
+     advance_loc 1 to 0x624
+     AARCH64_negate_ra_state
+     nop
+     nop
+     nop
+
+ [    64] FDE length=16 cie=[     0]
+   CIE_pointer:              104
+   initial_location:         0x0000000000400630 (offset: 0x630)
+   address_range:            0x8 (end offset: 0x638)
+
+   Program:
+     nop
+     nop
+     nop
+
+ [    78] FDE length=20 cie=[     0]
+   CIE_pointer:              124
+   initial_location:         0x0000000000400638 (offset: 0x638)
+   address_range:            0xc (end offset: 0x644)
+
+   Program:
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+
+ [    90] FDE length=52 cie=[     0]
+   CIE_pointer:              148
+   initial_location:         0x0000000000400650 (offset: 0x650)
+   address_range:            0x80 (end offset: 0x6d0)
+
+   Program:
+     advance_loc 1 to 0x654
+     AARCH64_negate_ra_state
+     advance_loc 1 to 0x658
+     def_cfa_offset 64
+     offset r29 (x29) at cfa-64
+     offset r30 (x30) at cfa-56
+     advance_loc 2 to 0x660
+     offset r19 (x19) at cfa-48
+     offset r20 (x20) at cfa-40
+     advance_loc 3 to 0x66c
+     offset r21 (x21) at cfa-32
+     offset r22 (x22) at cfa-24
+     advance_loc 5 to 0x680
+     offset r23 (x23) at cfa-16
+     offset r24 (x24) at cfa-8
+     advance_loc 18 to 0x6c8
+     restore r30 (x30)
+     restore r29 (x29)
+     restore r23 (x23)
+     restore r24 (x24)
+     restore r21 (x21)
+     restore r22 (x22)
+     restore r19 (x19)
+     restore r20 (x20)
+     def_cfa_offset 0
+     advance_loc 1 to 0x6cc
+     AARCH64_negate_ra_state
+     nop
+     nop
+
+ [    c8] FDE length=16 cie=[     0]
+   CIE_pointer:              204
+   initial_location:         0x00000000004006d0 (offset: 0x6d0)
+   address_range:            0x8 (end offset: 0x6d8)
+
+   Program:
+     nop
+     nop
+     nop
+
+ [    dc] Zero terminator
+EOF
+
+exit 0
diff --git a/tests/run-readelf-gdb_index.sh b/tests/run-readelf-gdb_index.sh
new file mode 100755
index 0000000..cd437f5
--- /dev/null
+++ b/tests/run-readelf-gdb_index.sh
@@ -0,0 +1,223 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# common.h
+# struct foo
+# {
+#   const char *bar;
+# };
+#
+# extern char *global;
+# int say (struct foo *prefix);
+
+# hello.c
+# #include "common.h"
+#
+# static char *hello = "Hello";
+#
+# int
+# main (int argc, char **argv)
+# {
+#   struct foo baz;
+#   global = hello;
+#   baz.bar = global;
+#   return say(&baz);
+# }
+
+# world.c
+# #include "common.h"
+#
+# char *global;
+#
+# static int hello (const char *bar)
+# {
+#   return bar == global;
+# }
+#
+# int
+# say (struct foo *prefix)
+# {
+#   return hello (prefix->bar);
+# }
+
+# gcc -g -fdebug-types-section -c hello.c
+# gcc -g -fdebug-types-section -c world.c
+# gcc -g -fdebug-types-section -o testfilegdbindex7 hello.o world.o
+# gdb testfilegdbindex7
+# (gdb) save gdb-index .
+# objcopy --add-section .gdb_index=testfilegdbindex7.gdb-index --set-section-flags .gdb_index=readonly testfilegdbindex7 testfilegdbindex7
+
+testfiles testfilegdbindex5 testfilegdbindex7 testfilegdbindex9 testfilegdbindex9-no-maininfo
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex5 <<\EOF
+
+GDB section [33] '.gdb_index' at offset 0xe76 contains 8383 bytes :
+ Version:         5
+ CU offset:       0x18
+ TU offset:       0x38
+ address offset:  0x50
+ symbol offset:   0x78
+ constant offset: 0x2078
+
+ CU list at offset 0x18 contains 2 entries:
+ [   0] start: 00000000, length:   184
+ [   1] start: 0x0000b8, length:   204
+
+ TU list at offset 0x38 contains 1 entries:
+ [   0] CU offset:     0, type offset:    29, signature: 0x87e03f92cc37cdf0
+
+ Address list at offset 0x50 contains 2 entries:
+ [   0] 0x000000000040049c <main>..0x00000000004004d1 <main+0x35>, CU index:     0
+ [   1] 0x00000000004004d4 <hello>..0x000000000040050b <say+0x1c>, CU index:     1
+
+ Symbol table at offset 0x50 contains 1024 slots:
+ [ 123] symbol: global, CUs: 1
+ [ 489] symbol: main, CUs: 0
+ [ 518] symbol: char, CUs: 0
+ [ 661] symbol: foo, CUs: 0T
+ [ 741] symbol: hello, CUs: 0, 1
+ [ 746] symbol: say, CUs: 1
+ [ 754] symbol: int, CUs: 0
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex7 <<\EOF
+
+GDB section [33] '.gdb_index' at offset 0xe76 contains 8399 bytes :
+ Version:         7
+ CU offset:       0x18
+ TU offset:       0x38
+ address offset:  0x50
+ symbol offset:   0x78
+ constant offset: 0x2078
+
+ CU list at offset 0x18 contains 2 entries:
+ [   0] start: 00000000, length:   184
+ [   1] start: 0x0000b8, length:   204
+
+ TU list at offset 0x38 contains 1 entries:
+ [   0] CU offset:     0, type offset:    29, signature: 0x87e03f92cc37cdf0
+
+ Address list at offset 0x50 contains 2 entries:
+ [   0] 0x000000000040049c <main>..0x00000000004004d1 <main+0x35>, CU index:     0
+ [   1] 0x00000000004004d4 <hello>..0x000000000040050b <say+0x1c>, CU index:     1
+
+ Symbol table at offset 0x50 contains 1024 slots:
+ [ 123] symbol: global, CUs: 1 (var:G)
+ [ 489] symbol: main, CUs: 0 (func:G)
+ [ 518] symbol: char, CUs: 0 (type:S)
+ [ 661] symbol: foo, CUs: 0T (type:S)
+ [ 741] symbol: hello, CUs: 0 (var:S), 1 (func:S)
+ [ 746] symbol: say, CUs: 1 (func:G)
+ [ 754] symbol: int, CUs: 0 (type:S)
+EOF
+
+# testfilegdbindex9-no-maininfo is built the same way as testfilegdbindex7.
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex9-no-maininfo <<\EOF
+
+GDB section [33] '.gdb_index' at offset 0x38e1 contains 8415 bytes :
+ Version:         9
+ CU offset:       0x1c
+ TU offset:       0x3c
+ address offset:  0x54
+ symbol offset:   0x7c
+ shortcut offset: 0x207c
+ constant offset: 0x2084
+
+ CU list at offset 0x1c contains 2 entries:
+ [   0] start: 0x00004c, length:   220
+ [   1] start: 0x000128, length:   214
+
+ TU list at offset 0x3c contains 1 entries:
+ [   0] CU offset:     0, type offset:    30, signature: 0x87e03f92cc37cdf0
+
+ Address list at offset 0x54 contains 2 entries:
+ [   0] 0x0000000000401106 <main>..0x000000000040113b <main+0x35>, CU index:     1
+ [   1] 0x000000000040113c <hello>..0x0000000000401173 <say+0x1c>, CU index:     2
+
+ Symbol table at offset 0x54 contains 1024 slots:
+ [ 123] symbol: global, CUs: 1 (var:G), 0T (var:G)
+ [ 489] symbol: main, CUs: 1 (func:G)
+ [ 518] symbol: char, CUs: 0 (type:S)
+ [ 661] symbol: foo, CUs: 0 (type:S)
+ [ 741] symbol: hello, CUs: 1 (var:S), 0T (func:S)
+ [ 746] symbol: say, CUs: 0T (func:G)
+ [ 754] symbol: int, CUs: 1 (type:S)
+
+Shortcut table at offset 0x207c contains 2 slots:
+Language of main: ??? (0)
+Name of main: <unknown>
+EOF
+
+# testfilegdbindex9.f90
+#
+# program repro
+#  type small_stride
+#     character*40 long_string
+#     integer      small_pad
+#  end type small_stride
+#  type(small_stride), dimension (20), target :: unpleasant
+#  character*40, pointer, dimension(:):: c40pt
+#  integer i
+#  do i = 0,19
+#     unpleasant(i+1)%small_pad = i+1
+#     unpleasant(i+1)%long_string = char (ichar('0') + i)
+#  end do
+#  c40pt => unpleasant%long_string
+#  print *, c40pt
+#end program repro
+
+# gfortran -g -o testfilegdbindex9 testfilegdbindex9.f90
+# gdb-add-index testfilegdbindex9
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=gdb_index testfilegdbindex9 <<\EOF
+
+GDB section [35] '.gdb_index' at offset 0x37d9 contains 8395 bytes :
+ Version:         9
+ CU offset:       0x1c
+ TU offset:       0x2c
+ address offset:  0x2c
+ symbol offset:   0x40
+ shortcut offset: 0x2040
+ constant offset: 0x2048
+
+ CU list at offset 0x1c contains 1 entries:
+ [   0] start: 00000000, length:   307
+
+ TU list at offset 0x2c contains 0 entries:
+
+ Address list at offset 0x2c contains 1 entries:
+ [   0] 0x0000000000401166 <MAIN__>..0x00000000004013f0 <main+0x3a>, CU index:     0
+
+ Symbol table at offset 0x2c contains 1024 slots:
+ [  61] symbol: small_stride, CUs: 0 (type:S)
+ [  71] symbol: integer(kind=8), CUs: 0 (type:S)
+ [ 161] symbol: character(kind=1), CUs: 0 (type:S)
+ [ 397] symbol: unpleasant, CUs: 0 (var:S)
+ [ 489] symbol: main, CUs: 0 (func:G)
+ [ 827] symbol: integer(kind=4), CUs: 0 (type:S)
+ [ 858] symbol: c40pt, CUs: 0 (var:S)
+ [ 965] symbol: repro, CUs: 0 (func:S)
+ [1016] symbol: i, CUs: 0 (var:S)
+
+Shortcut table at offset 0x2040 contains 2 slots:
+Language of main: Fortran08
+Name of main: repro
+EOF
+
+exit 0
diff --git a/tests/run-readelf-info-plus.sh b/tests/run-readelf-info-plus.sh
new file mode 100755
index 0000000..ee1db02
--- /dev/null
+++ b/tests/run-readelf-info-plus.sh
@@ -0,0 +1,31 @@
+#! /bin/sh
+# Test for --debug-dump=info+ and finding split unit (in wrong file).
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-5
+testfiles testfile-world5.dwo
+
+# note, wrong file, renamed as if this contains the correct dwo...
+tempfiles testfile-hello5.dwo
+cp testfile-world5.dwo testfile-hello5.dwo
+
+testrun ${abs_top_builddir}/src/readelf --debug-dump=info+ testfile-splitdwarf-5
+
+exit 0
diff --git a/tests/run-readelf-line.sh b/tests/run-readelf-line.sh
new file mode 100755
index 0000000..eef50e9
--- /dev/null
+++ b/tests/run-readelf-line.sh
@@ -0,0 +1,1149 @@
+#! /bin/sh
+# Copyright (C) 2013, 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Tests readelf --debug-dump=line and --debug-dump=decodedline
+# See run-readelf-aranges for testfiles.
+
+testfiles testfilefoobarbaz
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfilefoobarbaz <<EOF
+
+DWARF section [30] '.debug_line' at offset 0x15f6:
+
+Table at offset 0:
+
+ Length:                         83
+ DWARF version:                  2
+ Prologue length:                43
+ Address size:                   4
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         foo.c
+ 2     0     0         0         foobarbaz.h
+
+Line number statements:
+ [    35] extended opcode 2:  set address to 0x80482f0 <main>
+ [    3c] advance line by constant 15 to 16
+ [    3e] copy
+ [    3f] special opcode 159: address+10 = 0x80482fa <main+0xa>, line+1 = 17
+ [    40] special opcode 117: address+7 = 0x8048301 <main+0x11>, line+1 = 18
+ [    41] advance line by constant -9 to 9
+ [    43] special opcode 200: address+13 = 0x804830e <main+0x1e>, line+0 = 9
+ [    44] special opcode 48: address+2 = 0x8048310 <main+0x20>, line+2 = 11
+ [    45] special opcode 58: address+3 = 0x8048313 <main+0x23>, line-2 = 9
+ [    46] special opcode 48: address+2 = 0x8048315 <main+0x25>, line+2 = 11
+ [    47] special opcode 44: address+2 = 0x8048317 <main+0x27>, line-2 = 9
+ [    48] advance line by constant 13 to 22
+ [    4a] special opcode 46: address+2 = 0x8048319 <main+0x29>, line+0 = 22
+ [    4b] advance line by constant -13 to 9
+ [    4d] special opcode 60: address+3 = 0x804831c <main+0x2c>, line+0 = 9
+ [    4e] advance line by constant 12 to 21
+ [    50] special opcode 60: address+3 = 0x804831f <main+0x2f>, line+0 = 21
+ [    51] special opcode 61: address+3 = 0x8048322 <main+0x32>, line+1 = 22
+ [    52] advance address by 2 to 0x8048324
+ [    54] extended opcode 1:  end of sequence
+
+Table at offset 87:
+
+ Length:                         72
+ DWARF version:                  2
+ Prologue length:                28
+ Address size:                   4
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         bar.c
+
+Line number statements:
+ [    7d] extended opcode 2:  set address to 0x8048330 <nobar>
+ [    84] advance line by constant 12 to 13
+ [    86] copy
+ [    87] special opcode 19: address+0 = 0x8048330 <nobar>, line+1 = 14
+ [    88] advance address by 11 to 0x804833b
+ [    8a] extended opcode 1:  end of sequence
+ [    8d] extended opcode 2:  set address to 0x8048440 <bar>
+ [    94] advance line by constant 18 to 19
+ [    96] copy
+ [    97] special opcode 19: address+0 = 0x8048440 <bar>, line+1 = 20
+ [    98] advance line by constant -12 to 8
+ [    9a] special opcode 200: address+13 = 0x804844d <bar+0xd>, line+0 = 8
+ [    9b] advance line by constant 14 to 22
+ [    9d] special opcode 74: address+4 = 0x8048451 <bar+0x11>, line+0 = 22
+ [    9e] advance address by 1 to 0x8048452
+ [    a0] extended opcode 1:  end of sequence
+
+Table at offset 163:
+
+ Length:                         106
+ DWARF version:                  2
+ Prologue length:                43
+ Address size:                   4
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         baz.c
+ 2     0     0         0         foobarbaz.h
+
+Line number statements:
+ [    d8] extended opcode 2:  set address to 0x8048340 <nobaz>
+ [    df] advance line by constant 12 to 13
+ [    e1] copy
+ [    e2] special opcode 19: address+0 = 0x8048340 <nobaz>, line+1 = 14
+ [    e3] advance address by 11 to 0x804834b
+ [    e5] extended opcode 1:  end of sequence
+ [    e8] extended opcode 2:  set address to 0x8048460 <baz>
+ [    ef] advance line by constant 18 to 19
+ [    f1] copy
+ [    f2] special opcode 74: address+4 = 0x8048464 <baz+0x4>, line+0 = 19
+ [    f3] special opcode 75: address+4 = 0x8048468 <baz+0x8>, line+1 = 20
+ [    f4] extended opcode 4:  set discriminator to 1
+ [    f8] special opcode 78: address+4 = 0x804846c <baz+0xc>, line+4 = 24
+ [    f9] special opcode 187: address+12 = 0x8048478 <baz+0x18>, line+1 = 25
+ [    fa] special opcode 87: address+5 = 0x804847d <baz+0x1d>, line-1 = 24
+ [    fb] special opcode 61: address+3 = 0x8048480 <baz+0x20>, line+1 = 25
+ [    fc] special opcode 101: address+6 = 0x8048486 <baz+0x26>, line-1 = 24
+ [    fd] special opcode 61: address+3 = 0x8048489 <baz+0x29>, line+1 = 25
+ [    fe] special opcode 87: address+5 = 0x804848e <baz+0x2e>, line-1 = 24
+ [    ff] advance line by constant -16 to 8
+ [   101] special opcode 46: address+2 = 0x8048490 <baz+0x30>, line+0 = 8
+ [   102] advance line by constant 20 to 28
+ [   104] special opcode 186: address+12 = 0x804849c <baz+0x3c>, line+0 = 28
+ [   105] advance line by constant -20 to 8
+ [   107] special opcode 88: address+5 = 0x80484a1 <baz+0x41>, line+0 = 8
+ [   108] advance line by constant 13 to 21
+ [   10a] advance address by constant 17 to 0x80484b2 <baz+0x52>
+ [   10b] special opcode 32: address+1 = 0x80484b3 <baz+0x53>, line+0 = 21
+ [   10c] advance address by 9 to 0x80484bc
+ [   10e] extended opcode 1:  end of sequence
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfilefoobarbaz <<\EOF
+
+DWARF section [30] '.debug_line' at offset 0x15f6:
+
+ CU [b] foo.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /home/mark/src/tests/foobarbaz/foo.c (mtime: 0, length: 0)
+    16:0   S        0   0  0 0x080482f0 <main>
+    17:0   S        0   0  0 0x080482fa <main+0xa>
+    18:0   S        0   0  0 0x08048301 <main+0x11>
+     9:0   S        0   0  0 0x0804830e <main+0x1e>
+    11:0   S        0   0  0 0x08048310 <main+0x20>
+     9:0   S        0   0  0 0x08048313 <main+0x23>
+    11:0   S        0   0  0 0x08048315 <main+0x25>
+     9:0   S        0   0  0 0x08048317 <main+0x27>
+    22:0   S        0   0  0 0x08048319 <main+0x29>
+     9:0   S        0   0  0 0x0804831c <main+0x2c>
+    21:0   S        0   0  0 0x0804831f <main+0x2f>
+    22:0   S        0   0  0 0x08048322 <main+0x32>
+    22:0   S   *    0   0  0 0x08048323 <main+0x33>
+
+ CU [141] bar.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /home/mark/src/tests/foobarbaz/bar.c (mtime: 0, length: 0)
+    13:0   S        0   0  0 0x08048330 <nobar>
+    14:0   S        0   0  0 0x08048330 <nobar>
+    14:0   S   *    0   0  0 0x0804833a <nobar+0xa>
+
+    19:0   S        0   0  0 0x08048440 <bar>
+    20:0   S        0   0  0 0x08048440 <bar>
+     8:0   S        0   0  0 0x0804844d <bar+0xd>
+    22:0   S        0   0  0 0x08048451 <bar+0x11>
+    22:0   S   *    0   0  0 0x08048451 <bar+0x11>
+
+ CU [1dc] baz.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /home/mark/src/tests/foobarbaz/baz.c (mtime: 0, length: 0)
+    13:0   S        0   0  0 0x08048340 <nobaz>
+    14:0   S        0   0  0 0x08048340 <nobaz>
+    14:0   S   *    0   0  0 0x0804834a <nobaz+0xa>
+
+    19:0   S        0   0  0 0x08048460 <baz>
+    19:0   S        0   0  0 0x08048464 <baz+0x4>
+    20:0   S        0   0  0 0x08048468 <baz+0x8>
+    24:0   S        1   0  0 0x0804846c <baz+0xc>
+    25:0   S        0   0  0 0x08048478 <baz+0x18>
+    24:0   S        0   0  0 0x0804847d <baz+0x1d>
+    25:0   S        0   0  0 0x08048480 <baz+0x20>
+    24:0   S        0   0  0 0x08048486 <baz+0x26>
+    25:0   S        0   0  0 0x08048489 <baz+0x29>
+    24:0   S        0   0  0 0x0804848e <baz+0x2e>
+     8:0   S        0   0  0 0x08048490 <baz+0x30>
+    28:0   S        0   0  0 0x0804849c <baz+0x3c>
+     8:0   S        0   0  0 0x080484a1 <baz+0x41>
+    21:0   S        0   0  0 0x080484b3 <baz+0x53>
+    21:0   S   *    0   0  0 0x080484bb <baz+0x5b>
+
+EOF
+
+# A .debug_line table with minimum instruction length > 1.
+#
+# = hello.c
+# #include <stdio.h>
+#
+# int
+# main (int argc, char **argv)
+# {
+#   printf ("Hello, %s\n", (argc > 0
+# 			  ? argv[1]: "World"));
+#   return 0;
+# }
+#
+# clang version 5.0.1 (tags/RELEASE_501/final)
+# Target: powerpc64-unknown-linux-gnu
+# clang -g -O2 -o testfile-ppc64-min-instr hello.c
+testfiles testfile-ppc64-min-instr
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile-ppc64-min-instr <<\EOF
+
+DWARF section [29] '.debug_line' at offset 0xdf6:
+
+Table at offset 0:
+
+ Length:                         69
+ DWARF version:                  2
+ Prologue length:                30
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         4
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         hello.c
+
+Line number statements:
+ [    28] extended opcode 2:  set address to 0x100005a4 <main>
+ [    33] special opcode 22: address+0 = 0x100005a4 <main>, line+4 = 5
+ [    34] set column to 27
+ [    36] set prologue end flag
+ [    37] special opcode 19: address+0 = 0x100005a4 <main>, line+1 = 6
+ [    38] set column to 8
+ [    3a] special opcode 47: address+8 = 0x100005ac <main+0x8>, line+1 = 7
+ [    3b] set 'is_stmt' to 0
+ [    3c] advance line by constant -7 to 0
+ [    3e] special opcode 32: address+4 = 0x100005b0 <main+0xc>, line+0 = 0
+ [    3f] set column to 3
+ [    41] set 'is_stmt' to 1
+ [    42] special opcode 108: address+24 = 0x100005c8 <main+0x24>, line+6 = 6
+ [    43] special opcode 76: address+16 = 0x100005d8 <main+0x34>, line+2 = 8
+ [    44] advance address by 32 to 0x100005f8
+ [    46] extended opcode 1:  end of sequence
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfile-ppc64-min-instr <<\EOF
+
+DWARF section [29] '.debug_line' at offset 0xdf6:
+
+ CU [b] hello.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /home/fedora/mjw/hello.c (mtime: 0, length: 0)
+     5:0   S        0   0  0 0x00000000100005a4 <main>
+     6:27  S P      0   0  0 0x00000000100005a4 <main>
+     7:8   S        0   0  0 0x00000000100005ac <main+0x8>
+     0:8            0   0  0 0x00000000100005b0 <main+0xc>
+     6:3   S        0   0  0 0x00000000100005c8 <main+0x24>
+     8:3   S        0   0  0 0x00000000100005d8 <main+0x34>
+     8:3   S   *    0   0  0 0x00000000100005f7 <main+0x53>
+
+EOF
+
+# Two tests for the same code but encoded using DWARF4 or DWARF5.
+# Output is identical except for the section offset and CU numbers.
+# See tests/testfile-dwarf-45.source.
+
+testfiles testfile-dwarf-4 testfile-dwarf-5
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfile-dwarf-4 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x1734:
+
+ CU [b] hello.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    21:0   S        0   0  0 0x0000000000400510 <foo>
+    22:1   S        0   0  0 0x0000000000400510 <foo>
+    22:3            0   0  0 0x0000000000400510 <foo>
+    25:6            0   0  0 0x0000000000400514 <foo+0x4>
+    25:34  S        0   0  0 0x000000000040051a <foo+0xa>
+    25:3            0   0  0 0x000000000040051a <foo+0xa>
+    26:34           0   0  0 0x000000000040051e <foo+0xe>
+    25:1            1   0  0 0x0000000000400528 <foo+0x18>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:18  S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3   S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3            0   0  0 0x000000000040052b <foo+0x1b>
+    10:6   S        0   0  0 0x000000000040052f <foo+0x1f>
+    10:5            0   0  0 0x000000000040052f <foo+0x1f>
+    12:7   S        0   0  0 0x0000000000400531 <foo+0x21>
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    10:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3            0   0  0 0x0000000000400531 <foo+0x21>
+    13:6   S        0   0  0 0x0000000000400535 <foo+0x25>
+    13:5            0   0  0 0x0000000000400535 <foo+0x25>
+    15:7   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3            0   0  0 0x0000000000400539 <foo+0x29>
+    23:6   S        0   0  0 0x000000000040053d <foo+0x2d>
+    23:5            0   0  0 0x000000000040053d <foo+0x2d>
+     9:12  S        0   0  0 0x0000000000400550 <baz>
+    10:1   S        0   0  0 0x0000000000400550 <baz>
+    12:3   S        0   0  0 0x0000000000400550 <baz>
+    12:3            0   0  0 0x0000000000400550 <baz>
+    13:9            0   0  0 0x0000000000400556 <baz+0x6>
+    15:7   S        0   0  0 0x000000000040055f <baz+0xf>
+    15:3            0   0  0 0x000000000040055f <baz+0xf>
+    15:7       *    0   0  0 0x0000000000400560 <baz+0x10>
+
+ CU [21c] world.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    15:0   S        0   0  0 0x0000000000400410 <main>
+    16:1   S        0   0  0 0x0000000000400410 <main>
+    17:3   S        0   0  0 0x0000000000400410 <main>
+    15:3            0   0  0 0x0000000000400410 <main>
+    17:1            0   0  0 0x0000000000400419 <main+0x9>
+    18:6   S        0   0  0 0x000000000040041e <main+0xe>
+    18:5            0   0  0 0x000000000040041e <main+0xe>
+    22:7   S        0   0  0 0x0000000000400421 <main+0x11>
+    22:3   S   *    0   0  0 0x000000000040042f <main+0x1f>
+
+     6:0   S        0   0  0 0x0000000000400570 <calc>
+     7:1   S        0   0  0 0x0000000000400570 <calc>
+     7:3            0   0  0 0x0000000000400570 <calc>
+     7:6            1   0  0 0x0000000000400575 <calc+0x5>
+     7:24           0   0  0 0x0000000000400578 <calc+0x8>
+    10:17  S        0   0  0 0x000000000040057d <calc+0xd>
+    10:3            0   0  0 0x000000000040057d <calc+0xd>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+    10:10           0   0  0 0x0000000000400583 <calc+0x13>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    10:7            0   0  0 0x0000000000400585 <calc+0x15>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:10  S        0   0  0 0x0000000000400588 <calc+0x18>
+     9:3   S        0   0  0 0x0000000000400588 <calc+0x18>
+    10:3            0   0  0 0x0000000000400588 <calc+0x18>
+    12:7   S        0   0  0 0x000000000040058f <calc+0x1f>
+    12:3            0   0  0 0x000000000040058f <calc+0x1f>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    11:10           0   0  0 0x0000000000400598 <calc+0x28>
+    11:1       *    0   0  0 0x000000000040059a <calc+0x2a>
+
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfile-dwarf-5 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x171f:
+
+ CU [c] hello.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    21:0   S        0   0  0 0x0000000000400510 <foo>
+    22:1   S        0   0  0 0x0000000000400510 <foo>
+    22:3            0   0  0 0x0000000000400510 <foo>
+    25:6            0   0  0 0x0000000000400514 <foo+0x4>
+    25:34  S        0   0  0 0x000000000040051a <foo+0xa>
+    25:3            0   0  0 0x000000000040051a <foo+0xa>
+    26:34           0   0  0 0x000000000040051e <foo+0xe>
+    25:1            1   0  0 0x0000000000400528 <foo+0x18>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:18  S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3   S        0   0  0 0x000000000040052b <foo+0x1b>
+     9:3            0   0  0 0x000000000040052b <foo+0x1b>
+    10:6   S        0   0  0 0x000000000040052f <foo+0x1f>
+    10:5            0   0  0 0x000000000040052f <foo+0x1f>
+    12:7   S        0   0  0 0x0000000000400531 <foo+0x21>
+  /var/tmp/hello/hello.c (mtime: 0, length: 0)
+    10:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3   S        0   0  0 0x0000000000400531 <foo+0x21>
+    12:3            0   0  0 0x0000000000400531 <foo+0x21>
+    13:6   S        0   0  0 0x0000000000400535 <foo+0x25>
+    13:5            0   0  0 0x0000000000400535 <foo+0x25>
+    15:7   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3   S        0   0  0 0x0000000000400539 <foo+0x29>
+    22:3            0   0  0 0x0000000000400539 <foo+0x29>
+    23:6   S        0   0  0 0x000000000040053d <foo+0x2d>
+    23:5            0   0  0 0x000000000040053d <foo+0x2d>
+     9:12  S        0   0  0 0x0000000000400550 <baz>
+    10:1   S        0   0  0 0x0000000000400550 <baz>
+    12:3   S        0   0  0 0x0000000000400550 <baz>
+    12:3            0   0  0 0x0000000000400550 <baz>
+    13:9            0   0  0 0x0000000000400556 <baz+0x6>
+    15:7   S        0   0  0 0x000000000040055f <baz+0xf>
+    15:3            0   0  0 0x000000000040055f <baz+0xf>
+    15:7       *    0   0  0 0x0000000000400560 <baz+0x10>
+
+ CU [218] world.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    15:0   S        0   0  0 0x0000000000400410 <main>
+    16:1   S        0   0  0 0x0000000000400410 <main>
+    17:3   S        0   0  0 0x0000000000400410 <main>
+    15:3            0   0  0 0x0000000000400410 <main>
+    17:1            0   0  0 0x0000000000400419 <main+0x9>
+    18:6   S        0   0  0 0x000000000040041e <main+0xe>
+    18:5            0   0  0 0x000000000040041e <main+0xe>
+    22:7   S        0   0  0 0x0000000000400421 <main+0x11>
+    22:3   S   *    0   0  0 0x000000000040042f <main+0x1f>
+
+     6:0   S        0   0  0 0x0000000000400570 <calc>
+     7:1   S        0   0  0 0x0000000000400570 <calc>
+     7:3            0   0  0 0x0000000000400570 <calc>
+     7:6            1   0  0 0x0000000000400575 <calc+0x5>
+     7:24           0   0  0 0x0000000000400578 <calc+0x8>
+    10:17  S        0   0  0 0x000000000040057d <calc+0xd>
+    10:3            0   0  0 0x000000000040057d <calc+0xd>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+    10:10           0   0  0 0x0000000000400583 <calc+0x13>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    10:7            0   0  0 0x0000000000400585 <calc+0x15>
+  /var/tmp/hello/hello.h (mtime: 0, length: 0)
+     7:10  S        0   0  0 0x0000000000400588 <calc+0x18>
+     9:3   S        0   0  0 0x0000000000400588 <calc+0x18>
+    10:3            0   0  0 0x0000000000400588 <calc+0x18>
+    12:7   S        0   0  0 0x000000000040058f <calc+0x1f>
+    12:3            0   0  0 0x000000000040058f <calc+0x1f>
+  /var/tmp/hello/world.c (mtime: 0, length: 0)
+    11:10           0   0  0 0x0000000000400598 <calc+0x28>
+    11:1       *    0   0  0 0x000000000040059a <calc+0x2a>
+
+EOF
+
+# After discarding the different offsets in the line number statements,
+# the remaining difference between 4 and 5 is (besides the header/length)
+# Just the representation of the directory and line tables:
+
+#  Directory table:
+# - /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include
+# +      [path(line_strp)]
+# + 0     /var/tmp/hello (90)
+# + 1     /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include (17)
+#
+#  File name table:
+# - Entry Dir   Time      Size      Name
+# - 1     0     0         0         hello.c
+# - 2     0     0         0         hello.h
+# - 3     1     0         0         stddef.h
+# +      [path(line_strp), directory_index(data1)]
+# + 0     hello.c (9),  0
+# + 1     hello.c (9),  0
+# + 2     hello.h (82),  0
+# + 3     stddef.h (0),  1
+#
+#  Directory table:
+# - /usr/include
+# +      [path(line_strp)]
+# + 0     /var/tmp/hello (90)
+# + 1     /usr/include (122)
+#
+#  File name table:
+# - Entry Dir   Time      Size      Name
+# - 1     0     0         0         world.c
+# - 2     0     0         0         hello.h
+# - 3     1     0         0         stdlib.h
+# +      [path(line_strp), directory_index(data1)]
+# + 0     world.c (114),  0
+# + 1     world.c (114),  0
+# + 2     hello.h (82),  0
+# + 3     stdlib.h (105),  1
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile-dwarf-4 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x1734:
+
+Table at offset 0:
+
+ Length:                         608
+ DWARF version:                  4
+ Prologue length:                119
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -10
+ Line range:                     242
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+ /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         hello.c
+ 2     0     0         0         hello.h
+ 3     1     0         0         stddef.h
+
+Line number statements:
+ [    81] extended opcode 2:  set address to 0x400510 <foo>
+ [    8c] special opcode 43: address+0 = 0x400510 <foo>, line+20 = 21
+ [    8d] set column to 1
+ [    8f] extended opcode 2:  set address to 0x400510 <foo>
+ [    9a] special opcode 24: address+0 = 0x400510 <foo>, line+1 = 22
+ [    9b] set column to 3
+ [    9d] extended opcode 2:  set address to 0x400510 <foo>
+ [    a8] set 'is_stmt' to 0
+ [    a9] copy
+ [    aa] set column to 6
+ [    ac] extended opcode 2:  set address to 0x400514 <foo+0x4>
+ [    b7] special opcode 26: address+0 = 0x400514 <foo+0x4>, line+3 = 25
+ [    b8] set column to 34
+ [    ba] extended opcode 2:  set address to 0x40051a <foo+0xa>
+ [    c5] set 'is_stmt' to 1
+ [    c6] copy
+ [    c7] set column to 3
+ [    c9] extended opcode 2:  set address to 0x40051a <foo+0xa>
+ [    d4] set 'is_stmt' to 0
+ [    d5] copy
+ [    d6] set column to 34
+ [    d8] extended opcode 2:  set address to 0x40051e <foo+0xe>
+ [    e3] special opcode 24: address+0 = 0x40051e <foo+0xe>, line+1 = 26
+ [    e4] set column to 1
+ [    e6] extended opcode 2:  set address to 0x400528 <foo+0x18>
+ [    f1] extended opcode 4:  set discriminator to 1
+ [    f5] special opcode 22: address+0 = 0x400528 <foo+0x18>, line-1 = 25
+ [    f6] set column to 18
+ [    f8] extended opcode 2:  set address to 0x40052b <foo+0x1b>
+ [   103] set file to 2
+ [   105] set 'is_stmt' to 1
+ [   106] advance line by constant -18 to 7
+ [   108] copy
+ [   109] set column to 3
+ [   10b] extended opcode 2:  set address to 0x40052b <foo+0x1b>
+ [   116] special opcode 25: address+0 = 0x40052b <foo+0x1b>, line+2 = 9
+ [   117] set column to 3
+ [   119] extended opcode 2:  set address to 0x40052b <foo+0x1b>
+ [   124] set 'is_stmt' to 0
+ [   125] copy
+ [   126] set column to 6
+ [   128] extended opcode 2:  set address to 0x40052f <foo+0x1f>
+ [   133] extended opcode 4:  set discriminator to 0
+ [   137] set 'is_stmt' to 1
+ [   138] special opcode 24: address+0 = 0x40052f <foo+0x1f>, line+1 = 10
+ [   139] set column to 5
+ [   13b] extended opcode 2:  set address to 0x40052f <foo+0x1f>
+ [   146] set 'is_stmt' to 0
+ [   147] copy
+ [   148] set column to 7
+ [   14a] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   155] set 'is_stmt' to 1
+ [   156] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [   157] set column to 3
+ [   159] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   164] set file to 1
+ [   166] special opcode 21: address+0 = 0x400531 <foo+0x21>, line-2 = 10
+ [   167] set column to 3
+ [   169] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   174] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [   175] set column to 3
+ [   177] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   182] set 'is_stmt' to 0
+ [   183] copy
+ [   184] set column to 6
+ [   186] extended opcode 2:  set address to 0x400535 <foo+0x25>
+ [   191] set 'is_stmt' to 1
+ [   192] special opcode 24: address+0 = 0x400535 <foo+0x25>, line+1 = 13
+ [   193] set column to 5
+ [   195] extended opcode 2:  set address to 0x400535 <foo+0x25>
+ [   1a0] set 'is_stmt' to 0
+ [   1a1] copy
+ [   1a2] set column to 7
+ [   1a4] extended opcode 2:  set address to 0x400539 <foo+0x29>
+ [   1af] set 'is_stmt' to 1
+ [   1b0] special opcode 25: address+0 = 0x400539 <foo+0x29>, line+2 = 15
+ [   1b1] set column to 3
+ [   1b3] extended opcode 2:  set address to 0x400539 <foo+0x29>
+ [   1be] special opcode 30: address+0 = 0x400539 <foo+0x29>, line+7 = 22
+ [   1bf] set column to 3
+ [   1c1] extended opcode 2:  set address to 0x400539 <foo+0x29>
+ [   1cc] set 'is_stmt' to 0
+ [   1cd] copy
+ [   1ce] set column to 6
+ [   1d0] extended opcode 2:  set address to 0x40053d <foo+0x2d>
+ [   1db] set 'is_stmt' to 1
+ [   1dc] special opcode 24: address+0 = 0x40053d <foo+0x2d>, line+1 = 23
+ [   1dd] set column to 5
+ [   1df] extended opcode 2:  set address to 0x40053d <foo+0x2d>
+ [   1ea] set 'is_stmt' to 0
+ [   1eb] copy
+ [   1ec] set column to 12
+ [   1ee] extended opcode 2:  set address to 0x400550 <baz>
+ [   1f9] set 'is_stmt' to 1
+ [   1fa] advance line by constant -14 to 9
+ [   1fc] copy
+ [   1fd] set column to 1
+ [   1ff] extended opcode 2:  set address to 0x400550 <baz>
+ [   20a] special opcode 24: address+0 = 0x400550 <baz>, line+1 = 10
+ [   20b] set column to 3
+ [   20d] extended opcode 2:  set address to 0x400550 <baz>
+ [   218] special opcode 25: address+0 = 0x400550 <baz>, line+2 = 12
+ [   219] set column to 3
+ [   21b] extended opcode 2:  set address to 0x400550 <baz>
+ [   226] set 'is_stmt' to 0
+ [   227] copy
+ [   228] set column to 9
+ [   22a] extended opcode 2:  set address to 0x400556 <baz+0x6>
+ [   235] special opcode 24: address+0 = 0x400556 <baz+0x6>, line+1 = 13
+ [   236] set column to 7
+ [   238] extended opcode 2:  set address to 0x40055f <baz+0xf>
+ [   243] set 'is_stmt' to 1
+ [   244] special opcode 25: address+0 = 0x40055f <baz+0xf>, line+2 = 15
+ [   245] set column to 3
+ [   247] extended opcode 2:  set address to 0x40055f <baz+0xf>
+ [   252] set 'is_stmt' to 0
+ [   253] copy
+ [   254] set column to 7
+ [   256] extended opcode 2:  set address to 0x400561
+ [   261] extended opcode 1:  end of sequence
+
+Table at offset 612:
+
+ Length:                         450
+ DWARF version:                  4
+ Prologue length:                67
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -10
+ Line range:                     242
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+ /usr/include
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         world.c
+ 2     0     0         0         hello.h
+ 3     1     0         0         stdlib.h
+
+Line number statements:
+ [   2b1] extended opcode 2:  set address to 0x400410 <main>
+ [   2bc] special opcode 37: address+0 = 0x400410 <main>, line+14 = 15
+ [   2bd] set column to 1
+ [   2bf] extended opcode 2:  set address to 0x400410 <main>
+ [   2ca] special opcode 24: address+0 = 0x400410 <main>, line+1 = 16
+ [   2cb] set column to 3
+ [   2cd] extended opcode 2:  set address to 0x400410 <main>
+ [   2d8] special opcode 24: address+0 = 0x400410 <main>, line+1 = 17
+ [   2d9] set column to 3
+ [   2db] extended opcode 2:  set address to 0x400410 <main>
+ [   2e6] set 'is_stmt' to 0
+ [   2e7] special opcode 21: address+0 = 0x400410 <main>, line-2 = 15
+ [   2e8] set column to 1
+ [   2ea] extended opcode 2:  set address to 0x400419 <main+0x9>
+ [   2f5] special opcode 25: address+0 = 0x400419 <main+0x9>, line+2 = 17
+ [   2f6] set column to 6
+ [   2f8] extended opcode 2:  set address to 0x40041e <main+0xe>
+ [   303] set 'is_stmt' to 1
+ [   304] special opcode 24: address+0 = 0x40041e <main+0xe>, line+1 = 18
+ [   305] set column to 5
+ [   307] extended opcode 2:  set address to 0x40041e <main+0xe>
+ [   312] set 'is_stmt' to 0
+ [   313] copy
+ [   314] set column to 7
+ [   316] extended opcode 2:  set address to 0x400421 <main+0x11>
+ [   321] set 'is_stmt' to 1
+ [   322] special opcode 27: address+0 = 0x400421 <main+0x11>, line+4 = 22
+ [   323] set column to 3
+ [   325] extended opcode 2:  set address to 0x400430 <_start>
+ [   330] extended opcode 1:  end of sequence
+ [   333] extended opcode 2:  set address to 0x400570 <calc>
+ [   33e] special opcode 28: address+0 = 0x400570 <calc>, line+5 = 6
+ [   33f] set column to 1
+ [   341] extended opcode 2:  set address to 0x400570 <calc>
+ [   34c] special opcode 24: address+0 = 0x400570 <calc>, line+1 = 7
+ [   34d] set column to 3
+ [   34f] extended opcode 2:  set address to 0x400570 <calc>
+ [   35a] set 'is_stmt' to 0
+ [   35b] copy
+ [   35c] set column to 6
+ [   35e] extended opcode 2:  set address to 0x400575 <calc+0x5>
+ [   369] extended opcode 4:  set discriminator to 1
+ [   36d] copy
+ [   36e] set column to 24
+ [   370] extended opcode 2:  set address to 0x400578 <calc+0x8>
+ [   37b] copy
+ [   37c] set column to 17
+ [   37e] extended opcode 2:  set address to 0x40057d <calc+0xd>
+ [   389] extended opcode 4:  set discriminator to 0
+ [   38d] set 'is_stmt' to 1
+ [   38e] special opcode 26: address+0 = 0x40057d <calc+0xd>, line+3 = 10
+ [   38f] set column to 3
+ [   391] extended opcode 2:  set address to 0x40057d <calc+0xd>
+ [   39c] set 'is_stmt' to 0
+ [   39d] copy
+ [   39e] set column to 10
+ [   3a0] extended opcode 2:  set address to 0x400583 <calc+0x13>
+ [   3ab] set file to 2
+ [   3ad] copy
+ [   3ae] set column to 7
+ [   3b0] extended opcode 2:  set address to 0x400585 <calc+0x15>
+ [   3bb] set file to 1
+ [   3bd] copy
+ [   3be] set column to 10
+ [   3c0] extended opcode 2:  set address to 0x400588 <calc+0x18>
+ [   3cb] set file to 2
+ [   3cd] set 'is_stmt' to 1
+ [   3ce] special opcode 20: address+0 = 0x400588 <calc+0x18>, line-3 = 7
+ [   3cf] set column to 3
+ [   3d1] extended opcode 2:  set address to 0x400588 <calc+0x18>
+ [   3dc] special opcode 25: address+0 = 0x400588 <calc+0x18>, line+2 = 9
+ [   3dd] set column to 3
+ [   3df] extended opcode 2:  set address to 0x400588 <calc+0x18>
+ [   3ea] set 'is_stmt' to 0
+ [   3eb] special opcode 24: address+0 = 0x400588 <calc+0x18>, line+1 = 10
+ [   3ec] set column to 7
+ [   3ee] extended opcode 2:  set address to 0x40058f <calc+0x1f>
+ [   3f9] set 'is_stmt' to 1
+ [   3fa] special opcode 25: address+0 = 0x40058f <calc+0x1f>, line+2 = 12
+ [   3fb] set column to 3
+ [   3fd] extended opcode 2:  set address to 0x40058f <calc+0x1f>
+ [   408] set 'is_stmt' to 0
+ [   409] copy
+ [   40a] set column to 10
+ [   40c] extended opcode 2:  set address to 0x400598 <calc+0x28>
+ [   417] set file to 1
+ [   419] special opcode 22: address+0 = 0x400598 <calc+0x28>, line-1 = 11
+ [   41a] set column to 1
+ [   41c] extended opcode 2:  set address to 0x40059b
+ [   427] extended opcode 1:  end of sequence
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile-dwarf-5 << \EOF
+
+DWARF section [29] '.debug_line' at offset 0x171f:
+
+Table at offset 0:
+
+ Length:                         547
+ DWARF version:                  5
+ Prologue length:                56
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -10
+ Line range:                     242
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+      [path(line_strp)]
+ 0     /var/tmp/hello (90)
+ 1     /opt/local/install/gcc/lib/gcc/x86_64-pc-linux-gnu/9.0.0/include (17)
+
+File name table:
+      [path(line_strp), directory_index(data1)]
+ 0     hello.c (9),  0
+ 1     hello.c (9),  0
+ 2     hello.h (82),  0
+ 3     stddef.h (0),  1
+
+Line number statements:
+ [    44] extended opcode 2:  set address to 0x400510 <foo>
+ [    4f] special opcode 43: address+0 = 0x400510 <foo>, line+20 = 21
+ [    50] set column to 1
+ [    52] extended opcode 2:  set address to 0x400510 <foo>
+ [    5d] special opcode 24: address+0 = 0x400510 <foo>, line+1 = 22
+ [    5e] set column to 3
+ [    60] extended opcode 2:  set address to 0x400510 <foo>
+ [    6b] set 'is_stmt' to 0
+ [    6c] copy
+ [    6d] set column to 6
+ [    6f] extended opcode 2:  set address to 0x400514 <foo+0x4>
+ [    7a] special opcode 26: address+0 = 0x400514 <foo+0x4>, line+3 = 25
+ [    7b] set column to 34
+ [    7d] extended opcode 2:  set address to 0x40051a <foo+0xa>
+ [    88] set 'is_stmt' to 1
+ [    89] copy
+ [    8a] set column to 3
+ [    8c] extended opcode 2:  set address to 0x40051a <foo+0xa>
+ [    97] set 'is_stmt' to 0
+ [    98] copy
+ [    99] set column to 34
+ [    9b] extended opcode 2:  set address to 0x40051e <foo+0xe>
+ [    a6] special opcode 24: address+0 = 0x40051e <foo+0xe>, line+1 = 26
+ [    a7] set column to 1
+ [    a9] extended opcode 2:  set address to 0x400528 <foo+0x18>
+ [    b4] extended opcode 4:  set discriminator to 1
+ [    b8] special opcode 22: address+0 = 0x400528 <foo+0x18>, line-1 = 25
+ [    b9] set column to 18
+ [    bb] extended opcode 2:  set address to 0x40052b <foo+0x1b>
+ [    c6] set file to 2
+ [    c8] set 'is_stmt' to 1
+ [    c9] advance line by constant -18 to 7
+ [    cb] copy
+ [    cc] set column to 3
+ [    ce] extended opcode 2:  set address to 0x40052b <foo+0x1b>
+ [    d9] special opcode 25: address+0 = 0x40052b <foo+0x1b>, line+2 = 9
+ [    da] set column to 3
+ [    dc] extended opcode 2:  set address to 0x40052b <foo+0x1b>
+ [    e7] set 'is_stmt' to 0
+ [    e8] copy
+ [    e9] set column to 6
+ [    eb] extended opcode 2:  set address to 0x40052f <foo+0x1f>
+ [    f6] extended opcode 4:  set discriminator to 0
+ [    fa] set 'is_stmt' to 1
+ [    fb] special opcode 24: address+0 = 0x40052f <foo+0x1f>, line+1 = 10
+ [    fc] set column to 5
+ [    fe] extended opcode 2:  set address to 0x40052f <foo+0x1f>
+ [   109] set 'is_stmt' to 0
+ [   10a] copy
+ [   10b] set column to 7
+ [   10d] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   118] set 'is_stmt' to 1
+ [   119] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [   11a] set column to 3
+ [   11c] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   127] set file to 1
+ [   129] special opcode 21: address+0 = 0x400531 <foo+0x21>, line-2 = 10
+ [   12a] set column to 3
+ [   12c] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   137] special opcode 25: address+0 = 0x400531 <foo+0x21>, line+2 = 12
+ [   138] set column to 3
+ [   13a] extended opcode 2:  set address to 0x400531 <foo+0x21>
+ [   145] set 'is_stmt' to 0
+ [   146] copy
+ [   147] set column to 6
+ [   149] extended opcode 2:  set address to 0x400535 <foo+0x25>
+ [   154] set 'is_stmt' to 1
+ [   155] special opcode 24: address+0 = 0x400535 <foo+0x25>, line+1 = 13
+ [   156] set column to 5
+ [   158] extended opcode 2:  set address to 0x400535 <foo+0x25>
+ [   163] set 'is_stmt' to 0
+ [   164] copy
+ [   165] set column to 7
+ [   167] extended opcode 2:  set address to 0x400539 <foo+0x29>
+ [   172] set 'is_stmt' to 1
+ [   173] special opcode 25: address+0 = 0x400539 <foo+0x29>, line+2 = 15
+ [   174] set column to 3
+ [   176] extended opcode 2:  set address to 0x400539 <foo+0x29>
+ [   181] special opcode 30: address+0 = 0x400539 <foo+0x29>, line+7 = 22
+ [   182] set column to 3
+ [   184] extended opcode 2:  set address to 0x400539 <foo+0x29>
+ [   18f] set 'is_stmt' to 0
+ [   190] copy
+ [   191] set column to 6
+ [   193] extended opcode 2:  set address to 0x40053d <foo+0x2d>
+ [   19e] set 'is_stmt' to 1
+ [   19f] special opcode 24: address+0 = 0x40053d <foo+0x2d>, line+1 = 23
+ [   1a0] set column to 5
+ [   1a2] extended opcode 2:  set address to 0x40053d <foo+0x2d>
+ [   1ad] set 'is_stmt' to 0
+ [   1ae] copy
+ [   1af] set column to 12
+ [   1b1] extended opcode 2:  set address to 0x400550 <baz>
+ [   1bc] set 'is_stmt' to 1
+ [   1bd] advance line by constant -14 to 9
+ [   1bf] copy
+ [   1c0] set column to 1
+ [   1c2] extended opcode 2:  set address to 0x400550 <baz>
+ [   1cd] special opcode 24: address+0 = 0x400550 <baz>, line+1 = 10
+ [   1ce] set column to 3
+ [   1d0] extended opcode 2:  set address to 0x400550 <baz>
+ [   1db] special opcode 25: address+0 = 0x400550 <baz>, line+2 = 12
+ [   1dc] set column to 3
+ [   1de] extended opcode 2:  set address to 0x400550 <baz>
+ [   1e9] set 'is_stmt' to 0
+ [   1ea] copy
+ [   1eb] set column to 9
+ [   1ed] extended opcode 2:  set address to 0x400556 <baz+0x6>
+ [   1f8] special opcode 24: address+0 = 0x400556 <baz+0x6>, line+1 = 13
+ [   1f9] set column to 7
+ [   1fb] extended opcode 2:  set address to 0x40055f <baz+0xf>
+ [   206] set 'is_stmt' to 1
+ [   207] special opcode 25: address+0 = 0x40055f <baz+0xf>, line+2 = 15
+ [   208] set column to 3
+ [   20a] extended opcode 2:  set address to 0x40055f <baz+0xf>
+ [   215] set 'is_stmt' to 0
+ [   216] copy
+ [   217] set column to 7
+ [   219] extended opcode 2:  set address to 0x400561
+ [   224] extended opcode 1:  end of sequence
+
+Table at offset 551:
+
+ Length:                         441
+ DWARF version:                  5
+ Prologue length:                56
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -10
+ Line range:                     242
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+      [path(line_strp)]
+ 0     /var/tmp/hello (90)
+ 1     /usr/include (122)
+
+File name table:
+      [path(line_strp), directory_index(data1)]
+ 0     world.c (114),  0
+ 1     world.c (114),  0
+ 2     hello.h (82),  0
+ 3     stdlib.h (105),  1
+
+Line number statements:
+ [   26b] extended opcode 2:  set address to 0x400410 <main>
+ [   276] special opcode 37: address+0 = 0x400410 <main>, line+14 = 15
+ [   277] set column to 1
+ [   279] extended opcode 2:  set address to 0x400410 <main>
+ [   284] special opcode 24: address+0 = 0x400410 <main>, line+1 = 16
+ [   285] set column to 3
+ [   287] extended opcode 2:  set address to 0x400410 <main>
+ [   292] special opcode 24: address+0 = 0x400410 <main>, line+1 = 17
+ [   293] set column to 3
+ [   295] extended opcode 2:  set address to 0x400410 <main>
+ [   2a0] set 'is_stmt' to 0
+ [   2a1] special opcode 21: address+0 = 0x400410 <main>, line-2 = 15
+ [   2a2] set column to 1
+ [   2a4] extended opcode 2:  set address to 0x400419 <main+0x9>
+ [   2af] special opcode 25: address+0 = 0x400419 <main+0x9>, line+2 = 17
+ [   2b0] set column to 6
+ [   2b2] extended opcode 2:  set address to 0x40041e <main+0xe>
+ [   2bd] set 'is_stmt' to 1
+ [   2be] special opcode 24: address+0 = 0x40041e <main+0xe>, line+1 = 18
+ [   2bf] set column to 5
+ [   2c1] extended opcode 2:  set address to 0x40041e <main+0xe>
+ [   2cc] set 'is_stmt' to 0
+ [   2cd] copy
+ [   2ce] set column to 7
+ [   2d0] extended opcode 2:  set address to 0x400421 <main+0x11>
+ [   2db] set 'is_stmt' to 1
+ [   2dc] special opcode 27: address+0 = 0x400421 <main+0x11>, line+4 = 22
+ [   2dd] set column to 3
+ [   2df] extended opcode 2:  set address to 0x400430 <_start>
+ [   2ea] extended opcode 1:  end of sequence
+ [   2ed] extended opcode 2:  set address to 0x400570 <calc>
+ [   2f8] special opcode 28: address+0 = 0x400570 <calc>, line+5 = 6
+ [   2f9] set column to 1
+ [   2fb] extended opcode 2:  set address to 0x400570 <calc>
+ [   306] special opcode 24: address+0 = 0x400570 <calc>, line+1 = 7
+ [   307] set column to 3
+ [   309] extended opcode 2:  set address to 0x400570 <calc>
+ [   314] set 'is_stmt' to 0
+ [   315] copy
+ [   316] set column to 6
+ [   318] extended opcode 2:  set address to 0x400575 <calc+0x5>
+ [   323] extended opcode 4:  set discriminator to 1
+ [   327] copy
+ [   328] set column to 24
+ [   32a] extended opcode 2:  set address to 0x400578 <calc+0x8>
+ [   335] copy
+ [   336] set column to 17
+ [   338] extended opcode 2:  set address to 0x40057d <calc+0xd>
+ [   343] extended opcode 4:  set discriminator to 0
+ [   347] set 'is_stmt' to 1
+ [   348] special opcode 26: address+0 = 0x40057d <calc+0xd>, line+3 = 10
+ [   349] set column to 3
+ [   34b] extended opcode 2:  set address to 0x40057d <calc+0xd>
+ [   356] set 'is_stmt' to 0
+ [   357] copy
+ [   358] set column to 10
+ [   35a] extended opcode 2:  set address to 0x400583 <calc+0x13>
+ [   365] set file to 2
+ [   367] copy
+ [   368] set column to 7
+ [   36a] extended opcode 2:  set address to 0x400585 <calc+0x15>
+ [   375] set file to 1
+ [   377] copy
+ [   378] set column to 10
+ [   37a] extended opcode 2:  set address to 0x400588 <calc+0x18>
+ [   385] set file to 2
+ [   387] set 'is_stmt' to 1
+ [   388] special opcode 20: address+0 = 0x400588 <calc+0x18>, line-3 = 7
+ [   389] set column to 3
+ [   38b] extended opcode 2:  set address to 0x400588 <calc+0x18>
+ [   396] special opcode 25: address+0 = 0x400588 <calc+0x18>, line+2 = 9
+ [   397] set column to 3
+ [   399] extended opcode 2:  set address to 0x400588 <calc+0x18>
+ [   3a4] set 'is_stmt' to 0
+ [   3a5] special opcode 24: address+0 = 0x400588 <calc+0x18>, line+1 = 10
+ [   3a6] set column to 7
+ [   3a8] extended opcode 2:  set address to 0x40058f <calc+0x1f>
+ [   3b3] set 'is_stmt' to 1
+ [   3b4] special opcode 25: address+0 = 0x40058f <calc+0x1f>, line+2 = 12
+ [   3b5] set column to 3
+ [   3b7] extended opcode 2:  set address to 0x40058f <calc+0x1f>
+ [   3c2] set 'is_stmt' to 0
+ [   3c3] copy
+ [   3c4] set column to 10
+ [   3c6] extended opcode 2:  set address to 0x400598 <calc+0x28>
+ [   3d1] set file to 1
+ [   3d3] special opcode 22: address+0 = 0x400598 <calc+0x28>, line-1 = 11
+ [   3d4] set column to 1
+ [   3d6] extended opcode 2:  set address to 0x40059b
+ [   3e1] extended opcode 1:  end of sequence
+EOF
+
+exit 0
diff --git a/tests/run-readelf-loc.sh b/tests/run-readelf-loc.sh
new file mode 100755
index 0000000..8594b54
--- /dev/null
+++ b/tests/run-readelf-loc.sh
@@ -0,0 +1,1160 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# - hello.c
+# int say (const char *prefix);
+#
+# static char *
+# subject (char *word, int count)
+# {
+#   return count > 0 ? word : (word + count);
+# }
+#
+# int
+# main (int argc, char **argv)
+# {
+#    return say (subject (argv[0], argc));
+# }
+#
+# - world.c
+# static int
+# sad (char c)
+# {
+#   return c > 0 ? c : c + 1;
+# }
+#
+# static int
+# happy (const char *w)
+# {
+#   return sad (w[1]);
+# }
+#
+# int
+# say (const char *prefix)
+# {
+#   const char *world = "World";
+#   return prefix ? sad (prefix[0]) : happy (world);
+# }
+#
+# gcc -g -O2 -c hello.c
+# gcc -g -O2 -c world.c
+# gcc -g -o testfileloc hello.o world.o
+
+testfiles testfileloc
+
+# Process values as offsets from base addresses and resolve to symbols.
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --debug-dump=ranges \
+  testfileloc<<\EOF
+
+DWARF section [33] '.debug_loc' at offset 0xd2a:
+
+ CU [     b] base: 0x0000000000400480 <main>
+ [     0] range 0, d
+          0x0000000000400480 <main>..
+          0x000000000040048c <main+0xc>
+           [ 0] reg5
+ [    23] range 5, d
+          0x0000000000400485 <main+0x5>..
+          0x000000000040048c <main+0xc>
+           [ 0] reg5
+
+ CU [    e0] base: 0x00000000004004a0 <say>
+ [    46] range 12, 1a
+          0x00000000004004b2 <say+0x12>..
+          0x00000000004004b9 <say+0x19>
+           [ 0] breg5 0
+
+DWARF section [34] '.debug_ranges' at offset 0xd94:
+
+ CU [     b] base: 0x0000000000400480 <main>
+ [     0] range 0, 2
+          0x0000000000400480 <main>..
+          0x0000000000400481 <main+0x1>
+          range 5, d
+          0x0000000000400485 <main+0x5>..
+          0x000000000040048c <main+0xc>
+
+ CU [    e0] base: 0x00000000004004a0 <say>
+ [    30] range d, f
+          0x00000000004004ad <say+0xd>..
+          0x00000000004004ae <say+0xe>
+          range 12, 1a
+          0x00000000004004b2 <say+0x12>..
+          0x00000000004004b9 <say+0x19>
+EOF
+
+# Don't resolve addresses to symbols.
+testrun_compare ${abs_top_builddir}/src/readelf -N --debug-dump=loc --debug-dump=ranges \
+  testfileloc<<\EOF
+
+DWARF section [33] '.debug_loc' at offset 0xd2a:
+
+ CU [     b] base: 0x0000000000400480
+ [     0] range 0, d
+          0x0000000000400480..
+          0x000000000040048c
+           [ 0] reg5
+ [    23] range 5, d
+          0x0000000000400485..
+          0x000000000040048c
+           [ 0] reg5
+
+ CU [    e0] base: 0x00000000004004a0
+ [    46] range 12, 1a
+          0x00000000004004b2..
+          0x00000000004004b9
+           [ 0] breg5 0
+
+DWARF section [34] '.debug_ranges' at offset 0xd94:
+
+ CU [     b] base: 0x0000000000400480
+ [     0] range 0, 2
+          0x0000000000400480..
+          0x0000000000400481
+          range 5, d
+          0x0000000000400485..
+          0x000000000040048c
+
+ CU [    e0] base: 0x00000000004004a0
+ [    30] range d, f
+          0x00000000004004ad..
+          0x00000000004004ae
+          range 12, 1a
+          0x00000000004004b2..
+          0x00000000004004b9
+EOF
+
+# Produce "raw" unprocessed content.
+testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc --debug-dump=ranges \
+  testfileloc<<\EOF
+
+DWARF section [33] '.debug_loc' at offset 0xd2a:
+
+ CU [     b] base: 0x0000000000400480
+ [     0] range 0, d
+           [ 0] reg5
+ [    23] range 5, d
+           [ 0] reg5
+
+ CU [    e0] base: 0x00000000004004a0
+ [    46] range 12, 1a
+           [ 0] breg5 0
+
+DWARF section [34] '.debug_ranges' at offset 0xd94:
+
+ CU [     b] base: 0x0000000000400480
+ [     0] range 0, 2
+          range 5, d
+
+ CU [    e0] base: 0x00000000004004a0
+ [    30] range d, f
+          range 12, 1a
+EOF
+
+# .debug_rnglists (DWARF5), see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-5
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc testfile-dwarf-5<<\EOF
+
+DWARF section [31] '.debug_loclists' at offset 0x1c0c:
+Table at Offset 0x0:
+
+ Length:               96
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        0
+ CU [     c] base: 0x0000000000400510 <foo>
+
+  Offset: c, Index: 0
+    offset_pair 0, a
+      0x0000000000400510 <foo>..
+      0x0000000000400519 <foo+0x9>
+        [ 0] reg5
+    offset_pair a, 34
+      0x000000000040051a <foo+0xa>..
+      0x0000000000400543 <foo+0x33>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 1a, Index: e
+    offset_pair 1b, 2d
+      0x000000000040052b <foo+0x1b>..
+      0x000000000040053c <foo+0x2c>
+        [ 0] addr 0x601038 <m>
+    end_of_list
+
+  Offset: 28, Index: 1c
+    offset_pair 1b, 21
+      0x000000000040052b <foo+0x1b>..
+      0x0000000000400530 <foo+0x20>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 2e, Index: 22
+    offset_pair 1b, 27
+      0x000000000040052b <foo+0x1b>..
+      0x0000000000400536 <foo+0x26>
+        [ 0] reg5
+    offset_pair 29, 2d
+      0x0000000000400539 <foo+0x29>..
+      0x000000000040053c <foo+0x2c>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 39, Index: 2d
+    offset_pair 21, 27
+      0x0000000000400531 <foo+0x21>..
+      0x0000000000400536 <foo+0x26>
+        [ 0] reg5
+    offset_pair 29, 2d
+      0x0000000000400539 <foo+0x29>..
+      0x000000000040053c <foo+0x2c>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 44, Index: 38
+    offset_pair 21, 2d
+      0x0000000000400531 <foo+0x21>..
+      0x000000000040053c <foo+0x2c>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 4a, Index: 3e
+    offset_pair 2d, 33
+      0x000000000040053d <foo+0x2d>..
+      0x0000000000400542 <foo+0x32>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 50, Index: 44
+    offset_pair 40, 4f
+      0x0000000000400550 <baz>..
+      0x000000000040055e <baz+0xe>
+        [ 0] reg5
+    offset_pair 4f, 51
+      0x000000000040055f <baz+0xf>..
+      0x0000000000400560 <baz+0x10>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 5e, Index: 52
+    offset_pair 40, 50
+      0x0000000000400550 <baz>..
+      0x000000000040055f <baz+0xf>
+        [ 0] reg5
+    end_of_list
+
+Table at Offset 0x64:
+
+ Length:              159
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        0
+ CU [   218] base: 000000000000000000
+
+  Offset: 70, Index: 0
+    base_address 0x400410
+      0x0000000000400410 <main>
+    offset_pair 0, 14
+      0x0000000000400410 <main>..
+      0x0000000000400423 <main+0x13>
+        [ 0] reg5
+    offset_pair 14, 20
+      0x0000000000400424 <main+0x14>..
+      0x000000000040042f <main+0x1f>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 87, Index: 17
+    base_address 0x400410
+      0x0000000000400410 <main>
+    offset_pair 0, 18
+      0x0000000000400410 <main>..
+      0x0000000000400427 <main+0x17>
+        [ 0] reg4
+    offset_pair 18, 20
+      0x0000000000400428 <main+0x18>..
+      0x000000000040042f <main+0x1f>
+        [ 0] entry_value:
+             [ 0] reg4
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 9e, Index: 2e
+    start_length 0x400421, 7
+      0x0000000000400421 <main+0x11>..
+      0x0000000000400427 <main+0x17>
+        [ 0] reg0
+    end_of_list
+
+  Offset: ab, Index: 3b
+    base_address 0x400570
+      0x0000000000400570 <calc>
+    offset_pair 0, 8
+      0x0000000000400570 <calc>..
+      0x0000000000400577 <calc+0x7>
+        [ 0] reg5
+    offset_pair 8, 2b
+      0x0000000000400578 <calc+0x8>..
+      0x000000000040059a <calc+0x2a>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: c2, Index: 52
+    start_length 0x400588, b
+      0x0000000000400588 <calc+0x18>..
+      0x0000000000400592 <calc+0x22>
+        [ 0] reg0
+    end_of_list
+
+  Offset: cf, Index: 5f
+    base_address 0x400588
+      0x0000000000400588 <calc+0x18>
+    offset_pair 0, 2
+      0x0000000000400588 <calc+0x18>..
+      0x0000000000400589 <calc+0x19>
+        [ 0] reg1
+    offset_pair 2, 7
+      0x000000000040058a <calc+0x1a>..
+      0x000000000040058e <calc+0x1e>
+        [ 0] reg5
+    offset_pair 7, b
+      0x000000000040058f <calc+0x1f>..
+      0x0000000000400592 <calc+0x22>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] deref_size 1
+        [ 5] const1u 56
+        [ 7] shl
+        [ 8] const1u 56
+        [10] shra
+        [11] stack_value
+    end_of_list
+
+  Offset: f3, Index: 83
+    base_address 0x400588
+      0x0000000000400588 <calc+0x18>
+    offset_pair 0, 2
+      0x0000000000400588 <calc+0x18>..
+      0x0000000000400589 <calc+0x19>
+        [ 0] reg1
+    offset_pair 2, b
+      0x000000000040058a <calc+0x1a>..
+      0x0000000000400592 <calc+0x22>
+        [ 0] reg5
+    end_of_list
+
+EOF
+
+# Same as above, but for DWARF4, note completely different encoding, but
+# the information is the same (check with diff -uwb).
+testfiles testfile-dwarf-4
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc testfile-dwarf-4<<\EOF
+
+DWARF section [31] '.debug_loc' at offset 0x1c86:
+
+ CU [     b] base: 0x0000000000400510 <foo>
+ [     0] range 0, a
+          0x0000000000400510 <foo>..
+          0x0000000000400519 <foo+0x9>
+           [ 0] reg5
+          range a, 34
+          0x000000000040051a <foo+0xa>..
+          0x0000000000400543 <foo+0x33>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [    39] range 1b, 2d
+          0x000000000040052b <foo+0x1b>..
+          0x000000000040053c <foo+0x2c>
+           [ 0] addr 0x601038 <m>
+ [    64] range 1b, 21
+          0x000000000040052b <foo+0x1b>..
+          0x0000000000400530 <foo+0x20>
+           [ 0] reg5
+ [    87] range 1b, 27
+          0x000000000040052b <foo+0x1b>..
+          0x0000000000400536 <foo+0x26>
+           [ 0] reg5
+          range 29, 2d
+          0x0000000000400539 <foo+0x29>..
+          0x000000000040053c <foo+0x2c>
+           [ 0] reg5
+ [    bd] range 21, 27
+          0x0000000000400531 <foo+0x21>..
+          0x0000000000400536 <foo+0x26>
+           [ 0] reg5
+          range 29, 2d
+          0x0000000000400539 <foo+0x29>..
+          0x000000000040053c <foo+0x2c>
+           [ 0] reg5
+ [    f3] range 21, 2d
+          0x0000000000400531 <foo+0x21>..
+          0x000000000040053c <foo+0x2c>
+           [ 0] reg5
+ [   116] range 2d, 33
+          0x000000000040053d <foo+0x2d>..
+          0x0000000000400542 <foo+0x32>
+           [ 0] reg5
+ [   139] range 40, 4f
+          0x0000000000400550 <baz>..
+          0x000000000040055e <baz+0xe>
+           [ 0] reg5
+          range 4f, 51
+          0x000000000040055f <baz+0xf>..
+          0x0000000000400560 <baz+0x10>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [   172] range 40, 50
+          0x0000000000400550 <baz>..
+          0x000000000040055f <baz+0xf>
+           [ 0] reg5
+
+ CU [   21c] base: 000000000000000000
+ [   195] range 400410, 400424
+          0x0000000000400410 <main>..
+          0x0000000000400423 <main+0x13>
+           [ 0] reg5
+          range 400424, 400430
+          0x0000000000400424 <main+0x14>..
+          0x000000000040042f <main+0x1f>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [   1ce] range 400410, 400428
+          0x0000000000400410 <main>..
+          0x0000000000400427 <main+0x17>
+           [ 0] reg4
+          range 400428, 400430
+          0x0000000000400428 <main+0x18>..
+          0x000000000040042f <main+0x1f>
+           [ 0] GNU_entry_value:
+                [ 0] reg4
+           [ 3] stack_value
+ [   207] range 400421, 400428
+          0x0000000000400421 <main+0x11>..
+          0x0000000000400427 <main+0x17>
+           [ 0] reg0
+ [   22a] range 400570, 400578
+          0x0000000000400570 <calc>..
+          0x0000000000400577 <calc+0x7>
+           [ 0] reg5
+          range 400578, 40059b
+          0x0000000000400578 <calc+0x8>..
+          0x000000000040059a <calc+0x2a>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [   263] range 400588, 400593
+          0x0000000000400588 <calc+0x18>..
+          0x0000000000400592 <calc+0x22>
+           [ 0] reg0
+ [   286] range 400588, 40058a
+          0x0000000000400588 <calc+0x18>..
+          0x0000000000400589 <calc+0x19>
+           [ 0] reg1
+          range 40058a, 40058f
+          0x000000000040058a <calc+0x1a>..
+          0x000000000040058e <calc+0x1e>
+           [ 0] reg5
+          range 40058f, 400593
+          0x000000000040058f <calc+0x1f>..
+          0x0000000000400592 <calc+0x22>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] deref_size 1
+           [ 5] const1u 56
+           [ 7] shl
+           [ 8] const1u 56
+           [10] shra
+           [11] stack_value
+ [   2da] range 400588, 40058a
+          0x0000000000400588 <calc+0x18>..
+          0x0000000000400589 <calc+0x19>
+           [ 0] reg1
+          range 40058a, 400593
+          0x000000000040058a <calc+0x1a>..
+          0x0000000000400592 <calc+0x22>
+           [ 0] reg5
+EOF
+
+# Split DWARF5 variant. Note that the .debug_loclists moved to the .dwo file
+# and now uses an index and addrx indirections.
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --dwarf-skeleton=testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo <<\EOF
+
+testfile-hello5.dwo:
+
+
+DWARF section [ 3] '.debug_loclists.dwo' at offset 0x236:
+Table at Offset 0x0:
+
+ Length:              125
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        9
+ CU [    14] base: 0x0000000000401160 <foo>
+
+  Offsets starting at 0xc:
+   [     0] 0x24
+   [     1] 0x32
+   [     2] 0x39
+   [     3] 0x3f
+   [     4] 0x4a
+   [     5] 0x55
+   [     6] 0x5b
+   [     7] 0x61
+   [     8] 0x6f
+
+  Offset: 30, Index: 24
+    startx_length f, a
+      0x0000000000401160 <foo>..
+      0x0000000000401169 <foo+0x9>
+        [ 0] reg5
+    startx_length 0, 2a
+      0x000000000040116a <foo+0xa>..
+      0x0000000000401193 <foo+0x33>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 3e, Index: 32
+    startx_length 11, 12
+      0x000000000040117b <foo+0x1b>..
+      0x000000000040118c <foo+0x2c>
+        [ 0] addrx [18] 0x404038 <m>
+    end_of_list
+
+  Offset: 45, Index: 39
+    startx_length 11, 6
+      0x000000000040117b <foo+0x1b>..
+      0x0000000000401180 <foo+0x20>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 4b, Index: 3f
+    startx_length 11, c
+      0x000000000040117b <foo+0x1b>..
+      0x0000000000401186 <foo+0x26>
+        [ 0] reg5
+    startx_length 1, 4
+      0x0000000000401189 <foo+0x29>..
+      0x000000000040118c <foo+0x2c>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 56, Index: 4a
+    startx_length 4, 6
+      0x0000000000401181 <foo+0x21>..
+      0x0000000000401186 <foo+0x26>
+        [ 0] reg5
+    startx_length 1, 4
+      0x0000000000401189 <foo+0x29>..
+      0x000000000040118c <foo+0x2c>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 61, Index: 55
+    startx_length 4, c
+      0x0000000000401181 <foo+0x21>..
+      0x000000000040118c <foo+0x2c>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 67, Index: 5b
+    startx_length 2, 6
+      0x000000000040118d <foo+0x2d>..
+      0x0000000000401192 <foo+0x32>
+        [ 0] reg5
+    end_of_list
+
+  Offset: 6d, Index: 61
+    startx_length 9, f
+      0x00000000004011a0 <baz>..
+      0x00000000004011ae <baz+0xe>
+        [ 0] reg5
+    startx_length 5, 2
+      0x00000000004011af <baz+0xf>..
+      0x00000000004011b0 <baz+0x10>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 7b, Index: 6f
+    startx_length 9, 10
+      0x00000000004011a0 <baz>..
+      0x00000000004011af <baz+0xf>
+        [ 0] reg5
+    end_of_list
+
+
+testfile-world5.dwo:
+
+
+DWARF section [ 3] '.debug_loclists.dwo' at offset 0x217:
+Table at Offset 0x0:
+
+ Length:              128
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        7
+ CU [    14] base: 000000000000000000
+
+  Offsets starting at 0xc:
+   [     0] 0x1c
+   [     1] 0x2a
+   [     2] 0x38
+   [     3] 0x3e
+   [     4] 0x4c
+   [     5] 0x52
+   [     6] 0x6d
+
+  Offset: 28, Index: 1c
+    startx_length 2, 14
+      0x0000000000401060 <main>..
+      0x0000000000401073 <main+0x13>
+        [ 0] reg5
+    startx_length 4, c
+      0x0000000000401074 <main+0x14>..
+      0x000000000040107f <main+0x1f>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 36, Index: 2a
+    startx_length 2, 18
+      0x0000000000401060 <main>..
+      0x0000000000401077 <main+0x17>
+        [ 0] reg4
+    startx_length 7, 6
+      0x0000000000401078 <main+0x18>..
+      0x000000000040107d <main+0x1d>
+        [ 0] entry_value:
+             [ 0] reg4
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 44, Index: 38
+    startx_length 3, 7
+      0x0000000000401071 <main+0x11>..
+      0x0000000000401077 <main+0x17>
+        [ 0] reg0
+    end_of_list
+
+  Offset: 4a, Index: 3e
+    startx_length d, 8
+      0x00000000004011c0 <calc>..
+      0x00000000004011c7 <calc+0x7>
+        [ 0] reg5
+    startx_length e, 23
+      0x00000000004011c8 <calc+0x8>..
+      0x00000000004011ea <calc+0x2a>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] stack_value
+    end_of_list
+
+  Offset: 58, Index: 4c
+    startx_length f, b
+      0x00000000004011d8 <calc+0x18>..
+      0x00000000004011e2 <calc+0x22>
+        [ 0] reg0
+    end_of_list
+
+  Offset: 5e, Index: 52
+    startx_length f, 2
+      0x00000000004011d8 <calc+0x18>..
+      0x00000000004011d9 <calc+0x19>
+        [ 0] reg1
+    startx_length 10, 5
+      0x00000000004011da <calc+0x1a>..
+      0x00000000004011de <calc+0x1e>
+        [ 0] reg5
+    startx_length 0, 4
+      0x00000000004011df <calc+0x1f>..
+      0x00000000004011e2 <calc+0x22>
+        [ 0] entry_value:
+             [ 0] reg5
+        [ 3] deref_size 1
+        [ 5] const1u 56
+        [ 7] shl
+        [ 8] const1u 56
+        [10] shra
+        [11] stack_value
+    end_of_list
+
+  Offset: 79, Index: 6d
+    startx_length f, 2
+      0x00000000004011d8 <calc+0x18>..
+      0x00000000004011d9 <calc+0x19>
+        [ 0] reg1
+    startx_length 10, 9
+      0x00000000004011da <calc+0x1a>..
+      0x00000000004011e2 <calc+0x22>
+        [ 0] reg5
+    end_of_list
+
+EOF
+
+# GNU DebugFission split-dwarf variant. Still uses .debug_loc, but now in
+# .dwo file, with somewhat similar, but different encoding from DWARF5.
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc --dwarf-skeleton=testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo <<\EOF
+
+testfile-hello4.dwo:
+
+
+DWARF section [ 3] '.debug_loc.dwo' at offset 0x253:
+
+ CU [     b] base: 0x0000000000401160 <foo>
+ [     0] range 401160, 40116a
+          0x0000000000401160 <foo>..
+          0x0000000000401169 <foo+0x9>
+           [ 0] reg5
+          range 40116a, 401194
+          0x000000000040116a <foo+0xa>..
+          0x0000000000401193 <foo+0x33>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [    16] range 40117b, 40118d
+          0x000000000040117b <foo+0x1b>..
+          0x000000000040118c <foo+0x2c>
+           [ 0] GNU_addr_index [18] 0x404038 <m>
+ [    21] range 40117b, 401181
+          0x000000000040117b <foo+0x1b>..
+          0x0000000000401180 <foo+0x20>
+           [ 0] reg5
+ [    2b] range 40117b, 401187
+          0x000000000040117b <foo+0x1b>..
+          0x0000000000401186 <foo+0x26>
+           [ 0] reg5
+          range 401189, 40118d
+          0x0000000000401189 <foo+0x29>..
+          0x000000000040118c <foo+0x2c>
+           [ 0] reg5
+ [    3e] range 401181, 401187
+          0x0000000000401181 <foo+0x21>..
+          0x0000000000401186 <foo+0x26>
+           [ 0] reg5
+          range 401189, 40118d
+          0x0000000000401189 <foo+0x29>..
+          0x000000000040118c <foo+0x2c>
+           [ 0] reg5
+ [    51] range 401181, 40118d
+          0x0000000000401181 <foo+0x21>..
+          0x000000000040118c <foo+0x2c>
+           [ 0] reg5
+ [    5b] range 40118d, 401193
+          0x000000000040118d <foo+0x2d>..
+          0x0000000000401192 <foo+0x32>
+           [ 0] reg5
+ [    65] range 4011a0, 4011af
+          0x00000000004011a0 <baz>..
+          0x00000000004011ae <baz+0xe>
+           [ 0] reg5
+          range 4011af, 4011b1
+          0x00000000004011af <baz+0xf>..
+          0x00000000004011b0 <baz+0x10>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [    7b] range 4011a0, 4011b0
+          0x00000000004011a0 <baz>..
+          0x00000000004011af <baz+0xf>
+           [ 0] reg5
+
+testfile-world4.dwo:
+
+
+DWARF section [ 3] '.debug_loc.dwo' at offset 0x225:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 401060, 401074
+          0x0000000000401060 <main>..
+          0x0000000000401073 <main+0x13>
+           [ 0] reg5
+          range 401074, 401080
+          0x0000000000401074 <main+0x14>..
+          0x000000000040107f <main+0x1f>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [    16] range 401060, 401078
+          0x0000000000401060 <main>..
+          0x0000000000401077 <main+0x17>
+           [ 0] reg4
+          range 401078, 40107e
+          0x0000000000401078 <main+0x18>..
+          0x000000000040107d <main+0x1d>
+           [ 0] GNU_entry_value:
+                [ 0] reg4
+           [ 3] stack_value
+ [    2c] range 401071, 401078
+          0x0000000000401071 <main+0x11>..
+          0x0000000000401077 <main+0x17>
+           [ 0] reg0
+ [    36] range 4011c0, 4011c8
+          0x00000000004011c0 <calc>..
+          0x00000000004011c7 <calc+0x7>
+           [ 0] reg5
+          range 4011c8, 4011eb
+          0x00000000004011c8 <calc+0x8>..
+          0x00000000004011ea <calc+0x2a>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+ [    4c] range 4011d8, 4011e3
+          0x00000000004011d8 <calc+0x18>..
+          0x00000000004011e2 <calc+0x22>
+           [ 0] reg0
+ [    56] range 4011d8, 4011da
+          0x00000000004011d8 <calc+0x18>..
+          0x00000000004011d9 <calc+0x19>
+           [ 0] reg1
+          range 4011da, 4011df
+          0x00000000004011da <calc+0x1a>..
+          0x00000000004011de <calc+0x1e>
+           [ 0] reg5
+          range 4011df, 4011e3
+          0x00000000004011df <calc+0x1f>..
+          0x00000000004011e2 <calc+0x22>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] deref_size 1
+           [ 5] const1u 56
+           [ 7] shl
+           [ 8] const1u 56
+           [10] shra
+           [11] stack_value
+ [    7d] range 4011d8, 4011da
+          0x00000000004011d8 <calc+0x18>..
+          0x00000000004011d9 <calc+0x19>
+           [ 0] reg1
+          range 4011da, 4011e3
+          0x00000000004011da <calc+0x1a>..
+          0x00000000004011e2 <calc+0x22>
+           [ 0] reg5
+EOF
+
+# Partial dwarf-4 and partial GNU DebugFission split-dwarf.
+#
+# = popcount.c =
+#
+# int popcount (unsigned char u)
+# {
+#   int c = 0;
+#   while (u != 0)
+#     {
+#       if ((u & 1) == 1)
+#         c++;
+#       u >>= 1;
+#     }
+#   return c;
+# }
+#
+# = splitdwarf4-not-split4.c =
+#
+# extern int popcount (unsigned char);
+#
+# int main (int argc, char **argv)
+# {
+#   int i;
+#   int p = argc;
+#   for (i = 0; i < argc;  ++i)
+#     p += popcount (argv[i][0]);
+#   i += p;
+#   return i;
+# }
+#
+# gcc -gdwarf-4 -O2 -c popcount.c
+# gcc -gdwarf-4 -gsplit-dwarf -O2 -c splitdwarf4-not-split4.c
+# gcc -o testfile-splitdwarf4-not-split4 splitdwarf4-not-split4.o popcount.o
+# eu-strip -f testfile-splitdwarf4-not-split4.debug \
+#   testfile-splitdwarf4-not-split4
+
+testfiles testfile-splitdwarf4-not-split4.debug
+testfiles splitdwarf4-not-split4.dwo
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info+ --debug-dump=loc testfile-splitdwarf4-not-split4.debug <<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x330:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ Unit type: skeleton (4), Unit id: 0x3d909d7bd0e69c0b
+ [     b]  compile_unit         abbrev: 1
+           ranges               (sec_offset) range list [     0]
+           low_pc               (addr) 000000000000000000
+           stmt_list            (sec_offset) 0
+           GNU_dwo_name         (strp) "splitdwarf4-not-split4.dwo"
+           comp_dir             (strp) "/tmp"
+           GNU_pubnames         (flag_present) yes
+           GNU_addr_base        (sec_offset) address base [     0]
+           GNU_dwo_id           (data8) 0x3d909d7bd0e69c0b
+           GNU_ranges_base      (sec_offset) 0
+ Split compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ Unit type: skeleton (4), Unit id: 0x3d909d7bd0e69c0b
+ {     b}  compile_unit         abbrev: 1
+           producer             (GNU_str_index) "GNU C17 9.0.0 20180528 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -O2"
+           language             (data1) C99 (12)
+           name                 (GNU_str_index) "splitdwarf4-not-split4.c"
+           comp_dir             (GNU_str_index) "/tmp"
+           GNU_dwo_id           (data8) 0x3d909d7bd0e69c0b
+ {    18}    subprogram           abbrev: 2
+             external             (flag_present) yes
+             name                 (GNU_str_index) "main"
+             decl_file            (data1) splitdwarf4-not-split4.c (1)
+             decl_line            (data1) 3
+             decl_column          (data1) 5
+             prototyped           (flag_present) yes
+             type                 (ref4) {    6d}
+             low_pc               (GNU_addr_index) [4] 0x0000000000401050 <main>
+             high_pc              (data8) 76 (0x000000000040109c <_start>)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) {    6d}
+ {    30}      formal_parameter     abbrev: 3
+               name                 (GNU_str_index) "argc"
+               decl_file            (data1) splitdwarf4-not-split4.c (1)
+               decl_line            (data1) 3
+               decl_column          (data1) 15
+               type                 (ref4) {    6d}
+               location             (sec_offset) location list [     0]
+ {    3d}      formal_parameter     abbrev: 3
+               name                 (GNU_str_index) "argv"
+               decl_file            (data1) splitdwarf4-not-split4.c (1)
+               decl_line            (data1) 3
+               decl_column          (data1) 28
+               type                 (ref4) {    74}
+               location             (sec_offset) location list [    28]
+ {    4a}      variable             abbrev: 4
+               name                 (string) "i"
+               decl_file            (data1) splitdwarf4-not-split4.c (1)
+               decl_line            (data1) 5
+               decl_column          (data1) 7
+               type                 (ref4) {    6d}
+               location             (sec_offset) location list [    47]
+ {    58}      variable             abbrev: 4
+               name                 (string) "p"
+               decl_file            (data1) splitdwarf4-not-split4.c (1)
+               decl_line            (data1) 6
+               decl_column          (data1) 7
+               type                 (ref4) {    6d}
+               location             (sec_offset) location list [    73]
+ {    66}      GNU_call_site        abbrev: 5
+               low_pc               (GNU_addr_index) [1] 0x000000000040107f <main+0x2f>
+               abstract_origin      (ref4) {    84}
+ {    6d}    base_type            abbrev: 6
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ {    74}    pointer_type         abbrev: 7
+             byte_size            (data1) 8
+             type                 (ref4) {    7a}
+ {    7a}    pointer_type         abbrev: 7
+             byte_size            (data1) 8
+             type                 (ref4) {    80}
+ {    80}    base_type            abbrev: 8
+             byte_size            (data1) 1
+             encoding             (data1) signed_char (6)
+             name                 (GNU_str_index) "char"
+ {    84}    subprogram           abbrev: 9
+             external             (flag_present) yes
+             declaration          (flag_present) yes
+             linkage_name         (GNU_str_index) "popcount"
+             name                 (GNU_str_index) "popcount"
+             decl_file            (data1) splitdwarf4-not-split4.c (1)
+             decl_line            (data1) 1
+             decl_column          (data1) 12
+ Compilation unit at offset 52:
+ Version: 4, Abbreviation section offset: 29, Address size: 8, Offset size: 4
+ [    3f]  compile_unit         abbrev: 1
+           producer             (strp) "GNU C17 9.0.0 20180528 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -O2"
+           language             (data1) C99 (12)
+           name                 (strp) "popcount.c"
+           comp_dir             (strp) "/tmp"
+           low_pc               (addr) 0x0000000000401180 <popcount>
+           high_pc              (data8) 33 (0x00000000004011a1)
+           stmt_list            (sec_offset) 145
+ [    61]    subprogram           abbrev: 2
+             external             (flag_present) yes
+             name                 (strp) "popcount"
+             decl_file            (data1) popcount.c (1)
+             decl_line            (data1) 1
+             decl_column          (data1) 5
+             prototyped           (flag_present) yes
+             type                 (ref4) [    a0]
+             low_pc               (addr) 0x0000000000401180 <popcount>
+             high_pc              (data8) 33 (0x00000000004011a1)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [    a0]
+ [    83]      formal_parameter     abbrev: 3
+               name                 (string) "u"
+               decl_file            (data1) popcount.c (1)
+               decl_line            (data1) 1
+               decl_column          (data1) 29
+               type                 (ref4) [    a7]
+               location             (sec_offset) location list [     0]
+ [    91]      variable             abbrev: 4
+               name                 (string) "c"
+               decl_file            (data1) popcount.c (1)
+               decl_line            (data1) 3
+               decl_column          (data1) 7
+               type                 (ref4) [    a0]
+               location             (sec_offset) location list [    60]
+ [    a0]    base_type            abbrev: 5
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [    a7]    base_type            abbrev: 6
+             byte_size            (data1) 1
+             encoding             (data1) unsigned_char (8)
+             name                 (strp) "unsigned char"
+
+DWARF section [32] '.debug_loc' at offset 0x5ef:
+
+ CU [    3f] base: 0x0000000000401180 <popcount>
+ [     0] range 0, 9
+          0x0000000000401180 <popcount>..
+          0x0000000000401188 <popcount+0x8>
+           [ 0] reg5
+          range 9, 1b
+          0x0000000000401189 <popcount+0x9>..
+          0x000000000040119a <popcount+0x1a>
+           [ 0] reg1
+          range 1b, 1d
+          0x000000000040119b <popcount+0x1b>..
+          0x000000000040119c <popcount+0x1c>
+           [ 0] breg1 0
+           [ 2] lit1
+           [ 3] shr
+           [ 4] stack_value
+          range 1d, 21
+          0x000000000040119d <popcount+0x1d>..
+          0x00000000004011a0 <popcount+0x20>
+           [ 0] reg1
+ [    60] range 0, 9
+          0x0000000000401180 <popcount>..
+          0x0000000000401188 <popcount+0x8>
+           [ 0] lit0
+           [ 1] stack_value
+          range 9, 20
+          0x0000000000401189 <popcount+0x9>..
+          0x000000000040119f <popcount+0x1f>
+           [ 0] reg0
+          range 20, 21
+          0x00000000004011a0 <popcount+0x20>..
+          0x00000000004011a0 <popcount+0x20>
+           [ 0] lit0
+           [ 1] stack_value
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --dwarf-skeleton=testfile-splitdwarf4-not-split4.debug --debug-dump=loc splitdwarf4-not-split4.dwo <<\EOF
+
+DWARF section [ 3] '.debug_loc.dwo' at offset 0x15b:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 401050, 40106e
+          0x0000000000401050 <main>..
+          0x000000000040106d <main+0x1d>
+           [ 0] reg5
+          range 40106e, 401086
+          0x000000000040106e <main+0x1e>..
+          0x0000000000401085 <main+0x35>
+           [ 0] reg12
+          range 401086, 401095
+          0x0000000000401086 <main+0x36>..
+          0x0000000000401094 <main+0x44>
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+          range 401095, 40109c
+          0x0000000000401095 <main+0x45>..
+          0x000000000040109b <main+0x4b>
+           [ 0] reg5
+ [    28] range 401050, 40106e
+          0x0000000000401050 <main>..
+          0x000000000040106d <main+0x1d>
+           [ 0] reg4
+          range 40106e, 401095
+          0x000000000040106e <main+0x1e>..
+          0x0000000000401094 <main+0x44>
+           [ 0] GNU_entry_value:
+                [ 0] reg4
+           [ 3] stack_value
+          range 401095, 40109c
+          0x0000000000401095 <main+0x45>..
+          0x000000000040109b <main+0x4b>
+           [ 0] reg4
+ [    47] range 401050, 40106e
+          0x0000000000401050 <main>..
+          0x000000000040106d <main+0x1d>
+           [ 0] lit0
+           [ 1] stack_value
+          range 401086, 40108e
+          0x0000000000401086 <main+0x36>..
+          0x000000000040108d <main+0x3d>
+           [ 0] breg12 0
+           [ 2] breg6 0
+           [ 4] plus
+           [ 5] stack_value
+          range 40108e, 401095
+          0x000000000040108e <main+0x3e>..
+          0x0000000000401094 <main+0x44>
+           [ 0] reg0
+          range 401095, 40109c
+          0x0000000000401095 <main+0x45>..
+          0x000000000040109b <main+0x4b>
+           [ 0] lit0
+           [ 1] stack_value
+ [    73] range 401050, 40106e
+          0x0000000000401050 <main>..
+          0x000000000040106d <main+0x1d>
+           [ 0] reg5
+          range 40106e, 401090
+          0x000000000040106e <main+0x1e>..
+          0x000000000040108f <main+0x3f>
+           [ 0] reg6
+          range 401095, 40109c
+          0x0000000000401095 <main+0x45>..
+          0x000000000040109b <main+0x4b>
+           [ 0] reg5
+EOF
+
+exit 0
diff --git a/tests/run-readelf-macro.sh b/tests/run-readelf-macro.sh
new file mode 100755
index 0000000..8b17f7d
--- /dev/null
+++ b/tests/run-readelf-macro.sh
@@ -0,0 +1,345 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# common.h
+# #define ONE 1
+# #define TWO 2
+# #define THREE 3
+#
+# #define WORLD "World"
+#
+# int say (const char *prefix);
+#
+# #define A 'a'
+# #define B b
+# #define C "C"
+#
+# #ifdef THREE
+# #undef THREE
+# #define THREE(ARG1,ARG2,ARG3) ARG3
+# #endif
+
+# hello.c
+# #include "common.h"
+#
+# int
+# main (int argc, char **argv)
+# {
+#   return say (WORLD);
+# }
+
+# world.c
+# #include "common.h"
+#
+# int
+# say (const char *prefix)
+# {
+#   return prefix ? ONE : TWO;
+# }
+
+# gcc -g3 -c hello.c
+# gcc -g3 -c world.c
+# gcc -g3 -o testfilemacro hello.o world.o
+
+testfiles testfilemacro
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=macro testfilemacro <<\EOF
+
+DWARF section [32] '.debug_macro' at offset 0x2480:
+
+ Offset:             0x0
+ Version:            4
+ Flag:               0x2 (debug_line_offset)
+ Offset length:      4
+ .debug_line offset: 0x0
+
+ #include offset 0x1a
+ start_file 0, [1] /home/mark/src/tests/hello.c
+  start_file 1, [2] /home/mark/src/tests/common.h
+   #include offset 0x582
+  end_file
+ end_file
+
+ Offset:             0x1a
+ Version:            4
+ Flag:               0x0
+ Offset length:      4
+
+ #define __STDC__ 1, line 1 (indirect)
+ #define __STDC_HOSTED__ 1, line 1 (indirect)
+ #define __GNUC__ 4, line 1 (indirect)
+ #define __GNUC_MINOR__ 7, line 1 (indirect)
+ #define __GNUC_PATCHLEVEL__ 1, line 1 (indirect)
+ #define __VERSION__ "4.7.1 20120629 (Red Hat 4.7.1-1)", line 1 (indirect)
+ #define __GNUC_RH_RELEASE__ 1, line 1 (indirect)
+ #define __ATOMIC_RELAXED 0, line 1 (indirect)
+ #define __ATOMIC_SEQ_CST 5, line 1 (indirect)
+ #define __ATOMIC_ACQUIRE 2, line 1 (indirect)
+ #define __ATOMIC_RELEASE 3, line 1 (indirect)
+ #define __ATOMIC_ACQ_REL 4, line 1 (indirect)
+ #define __ATOMIC_CONSUME 1, line 1 (indirect)
+ #define __FINITE_MATH_ONLY__ 0, line 1 (indirect)
+ #define _LP64 1, line 1 (indirect)
+ #define __LP64__ 1, line 1 (indirect)
+ #define __SIZEOF_INT__ 4, line 1 (indirect)
+ #define __SIZEOF_LONG__ 8, line 1 (indirect)
+ #define __SIZEOF_LONG_LONG__ 8, line 1 (indirect)
+ #define __SIZEOF_SHORT__ 2, line 1 (indirect)
+ #define __SIZEOF_FLOAT__ 4, line 1 (indirect)
+ #define __SIZEOF_DOUBLE__ 8, line 1 (indirect)
+ #define __SIZEOF_LONG_DOUBLE__ 16, line 1 (indirect)
+ #define __SIZEOF_SIZE_T__ 8, line 1 (indirect)
+ #define __CHAR_BIT__ 8, line 1 (indirect)
+ #define __BIGGEST_ALIGNMENT__ 16, line 1 (indirect)
+ #define __ORDER_LITTLE_ENDIAN__ 1234, line 1 (indirect)
+ #define __ORDER_BIG_ENDIAN__ 4321, line 1 (indirect)
+ #define __ORDER_PDP_ENDIAN__ 3412, line 1 (indirect)
+ #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__, line 1 (indirect)
+ #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__, line 1 (indirect)
+ #define __SIZEOF_POINTER__ 8, line 1 (indirect)
+ #define __SIZE_TYPE__ long unsigned int, line 1 (indirect)
+ #define __PTRDIFF_TYPE__ long int, line 1 (indirect)
+ #define __WCHAR_TYPE__ int, line 1 (indirect)
+ #define __WINT_TYPE__ unsigned int, line 1 (indirect)
+ #define __INTMAX_TYPE__ long int, line 1 (indirect)
+ #define __UINTMAX_TYPE__ long unsigned int, line 1 (indirect)
+ #define __CHAR16_TYPE__ short unsigned int, line 1 (indirect)
+ #define __CHAR32_TYPE__ unsigned int, line 1 (indirect)
+ #define __SIG_ATOMIC_TYPE__ int, line 1 (indirect)
+ #define __INT8_TYPE__ signed char, line 1 (indirect)
+ #define __INT16_TYPE__ short int, line 1 (indirect)
+ #define __INT32_TYPE__ int, line 1 (indirect)
+ #define __INT64_TYPE__ long int, line 1 (indirect)
+ #define __UINT8_TYPE__ unsigned char, line 1 (indirect)
+ #define __UINT16_TYPE__ short unsigned int, line 1 (indirect)
+ #define __UINT32_TYPE__ unsigned int, line 1 (indirect)
+ #define __UINT64_TYPE__ long unsigned int, line 1 (indirect)
+ #define __INT_LEAST8_TYPE__ signed char, line 1 (indirect)
+ #define __INT_LEAST16_TYPE__ short int, line 1 (indirect)
+ #define __INT_LEAST32_TYPE__ int, line 1 (indirect)
+ #define __INT_LEAST64_TYPE__ long int, line 1 (indirect)
+ #define __UINT_LEAST8_TYPE__ unsigned char, line 1 (indirect)
+ #define __UINT_LEAST16_TYPE__ short unsigned int, line 1 (indirect)
+ #define __UINT_LEAST32_TYPE__ unsigned int, line 1 (indirect)
+ #define __UINT_LEAST64_TYPE__ long unsigned int, line 1 (indirect)
+ #define __INT_FAST8_TYPE__ signed char, line 1 (indirect)
+ #define __INT_FAST16_TYPE__ long int, line 1 (indirect)
+ #define __INT_FAST32_TYPE__ long int, line 1 (indirect)
+ #define __INT_FAST64_TYPE__ long int, line 1 (indirect)
+ #define __UINT_FAST8_TYPE__ unsigned char, line 1 (indirect)
+ #define __UINT_FAST16_TYPE__ long unsigned int, line 1 (indirect)
+ #define __UINT_FAST32_TYPE__ long unsigned int, line 1 (indirect)
+ #define __UINT_FAST64_TYPE__ long unsigned int, line 1 (indirect)
+ #define __INTPTR_TYPE__ long int, line 1 (indirect)
+ #define __UINTPTR_TYPE__ long unsigned int, line 1 (indirect)
+ #define __GXX_ABI_VERSION 1002, line 1 (indirect)
+ #define __SCHAR_MAX__ 127, line 1 (indirect)
+ #define __SHRT_MAX__ 32767, line 1 (indirect)
+ #define __INT_MAX__ 2147483647, line 1 (indirect)
+ #define __LONG_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __LONG_LONG_MAX__ 9223372036854775807LL, line 1 (indirect)
+ #define __WCHAR_MAX__ 2147483647, line 1 (indirect)
+ #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1), line 1 (indirect)
+ #define __WINT_MAX__ 4294967295U, line 1 (indirect)
+ #define __WINT_MIN__ 0U, line 1 (indirect)
+ #define __PTRDIFF_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __SIZE_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __INTMAX_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INTMAX_C(c) c ## L, line 1 (indirect)
+ #define __UINTMAX_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINTMAX_C(c) c ## UL, line 1 (indirect)
+ #define __SIG_ATOMIC_MAX__ 2147483647, line 1 (indirect)
+ #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1), line 1 (indirect)
+ #define __INT8_MAX__ 127, line 1 (indirect)
+ #define __INT16_MAX__ 32767, line 1 (indirect)
+ #define __INT32_MAX__ 2147483647, line 1 (indirect)
+ #define __INT64_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __UINT8_MAX__ 255, line 1 (indirect)
+ #define __UINT16_MAX__ 65535, line 1 (indirect)
+ #define __UINT32_MAX__ 4294967295U, line 1 (indirect)
+ #define __UINT64_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __INT_LEAST8_MAX__ 127, line 1 (indirect)
+ #define __INT8_C(c) c, line 1 (indirect)
+ #define __INT_LEAST16_MAX__ 32767, line 1 (indirect)
+ #define __INT16_C(c) c, line 1 (indirect)
+ #define __INT_LEAST32_MAX__ 2147483647, line 1 (indirect)
+ #define __INT32_C(c) c, line 1 (indirect)
+ #define __INT_LEAST64_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INT64_C(c) c ## L, line 1 (indirect)
+ #define __UINT_LEAST8_MAX__ 255, line 1 (indirect)
+ #define __UINT8_C(c) c, line 1 (indirect)
+ #define __UINT_LEAST16_MAX__ 65535, line 1 (indirect)
+ #define __UINT16_C(c) c, line 1 (indirect)
+ #define __UINT_LEAST32_MAX__ 4294967295U, line 1 (indirect)
+ #define __UINT32_C(c) c ## U, line 1 (indirect)
+ #define __UINT_LEAST64_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINT64_C(c) c ## UL, line 1 (indirect)
+ #define __INT_FAST8_MAX__ 127, line 1 (indirect)
+ #define __INT_FAST16_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INT_FAST32_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INT_FAST64_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __UINT_FAST8_MAX__ 255, line 1 (indirect)
+ #define __UINT_FAST16_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINT_FAST32_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINT_FAST64_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __INTPTR_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __UINTPTR_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __FLT_EVAL_METHOD__ 0, line 1 (indirect)
+ #define __DEC_EVAL_METHOD__ 2, line 1 (indirect)
+ #define __FLT_RADIX__ 2, line 1 (indirect)
+ #define __FLT_MANT_DIG__ 24, line 1 (indirect)
+ #define __FLT_DIG__ 6, line 1 (indirect)
+ #define __FLT_MIN_EXP__ (-125), line 1 (indirect)
+ #define __FLT_MIN_10_EXP__ (-37), line 1 (indirect)
+ #define __FLT_MAX_EXP__ 128, line 1 (indirect)
+ #define __FLT_MAX_10_EXP__ 38, line 1 (indirect)
+ #define __FLT_DECIMAL_DIG__ 9, line 1 (indirect)
+ #define __FLT_MAX__ 3.40282346638528859812e+38F, line 1 (indirect)
+ #define __FLT_MIN__ 1.17549435082228750797e-38F, line 1 (indirect)
+ #define __FLT_EPSILON__ 1.19209289550781250000e-7F, line 1 (indirect)
+ #define __FLT_DENORM_MIN__ 1.40129846432481707092e-45F, line 1 (indirect)
+ #define __FLT_HAS_DENORM__ 1, line 1 (indirect)
+ #define __FLT_HAS_INFINITY__ 1, line 1 (indirect)
+ #define __FLT_HAS_QUIET_NAN__ 1, line 1 (indirect)
+ #define __DBL_MANT_DIG__ 53, line 1 (indirect)
+ #define __DBL_DIG__ 15, line 1 (indirect)
+ #define __DBL_MIN_EXP__ (-1021), line 1 (indirect)
+ #define __DBL_MIN_10_EXP__ (-307), line 1 (indirect)
+ #define __DBL_MAX_EXP__ 1024, line 1 (indirect)
+ #define __DBL_MAX_10_EXP__ 308, line 1 (indirect)
+ #define __DBL_DECIMAL_DIG__ 17, line 1 (indirect)
+ #define __DBL_MAX__ ((double)1.79769313486231570815e+308L), line 1 (indirect)
+ #define __DBL_MIN__ ((double)2.22507385850720138309e-308L), line 1 (indirect)
+ #define __DBL_EPSILON__ ((double)2.22044604925031308085e-16L), line 1 (indirect)
+ #define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L), line 1 (indirect)
+ #define __DBL_HAS_DENORM__ 1, line 1 (indirect)
+ #define __DBL_HAS_INFINITY__ 1, line 1 (indirect)
+ #define __DBL_HAS_QUIET_NAN__ 1, line 1 (indirect)
+ #define __LDBL_MANT_DIG__ 64, line 1 (indirect)
+ #define __LDBL_DIG__ 18, line 1 (indirect)
+ #define __LDBL_MIN_EXP__ (-16381), line 1 (indirect)
+ #define __LDBL_MIN_10_EXP__ (-4931), line 1 (indirect)
+ #define __LDBL_MAX_EXP__ 16384, line 1 (indirect)
+ #define __LDBL_MAX_10_EXP__ 4932, line 1 (indirect)
+ #define __DECIMAL_DIG__ 21, line 1 (indirect)
+ #define __LDBL_MAX__ 1.18973149535723176502e+4932L, line 1 (indirect)
+ #define __LDBL_MIN__ 3.36210314311209350626e-4932L, line 1 (indirect)
+ #define __LDBL_EPSILON__ 1.08420217248550443401e-19L, line 1 (indirect)
+ #define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L, line 1 (indirect)
+ #define __LDBL_HAS_DENORM__ 1, line 1 (indirect)
+ #define __LDBL_HAS_INFINITY__ 1, line 1 (indirect)
+ #define __LDBL_HAS_QUIET_NAN__ 1, line 1 (indirect)
+ #define __DEC32_MANT_DIG__ 7, line 1 (indirect)
+ #define __DEC32_MIN_EXP__ (-94), line 1 (indirect)
+ #define __DEC32_MAX_EXP__ 97, line 1 (indirect)
+ #define __DEC32_MIN__ 1E-95DF, line 1 (indirect)
+ #define __DEC32_MAX__ 9.999999E96DF, line 1 (indirect)
+ #define __DEC32_EPSILON__ 1E-6DF, line 1 (indirect)
+ #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF, line 1 (indirect)
+ #define __DEC64_MANT_DIG__ 16, line 1 (indirect)
+ #define __DEC64_MIN_EXP__ (-382), line 1 (indirect)
+ #define __DEC64_MAX_EXP__ 385, line 1 (indirect)
+ #define __DEC64_MIN__ 1E-383DD, line 1 (indirect)
+ #define __DEC64_MAX__ 9.999999999999999E384DD, line 1 (indirect)
+ #define __DEC64_EPSILON__ 1E-15DD, line 1 (indirect)
+ #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD, line 1 (indirect)
+ #define __DEC128_MANT_DIG__ 34, line 1 (indirect)
+ #define __DEC128_MIN_EXP__ (-6142), line 1 (indirect)
+ #define __DEC128_MAX_EXP__ 6145, line 1 (indirect)
+ #define __DEC128_MIN__ 1E-6143DL, line 1 (indirect)
+ #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL, line 1 (indirect)
+ #define __DEC128_EPSILON__ 1E-33DL, line 1 (indirect)
+ #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL, line 1 (indirect)
+ #define __REGISTER_PREFIX__ , line 1 (indirect)
+ #define __USER_LABEL_PREFIX__ , line 1 (indirect)
+ #define __GNUC_GNU_INLINE__ 1, line 1 (indirect)
+ #define __NO_INLINE__ 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1, line 1 (indirect)
+ #define __GCC_ATOMIC_BOOL_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_CHAR_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_SHORT_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_INT_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_LONG_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_LLONG_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1, line 1 (indirect)
+ #define __GCC_ATOMIC_POINTER_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_HAVE_DWARF2_CFI_ASM 1, line 1 (indirect)
+ #define __PRAGMA_REDEFINE_EXTNAME 1, line 1 (indirect)
+ #define __SIZEOF_INT128__ 16, line 1 (indirect)
+ #define __SIZEOF_WCHAR_T__ 4, line 1 (indirect)
+ #define __SIZEOF_WINT_T__ 4, line 1 (indirect)
+ #define __SIZEOF_PTRDIFF_T__ 8, line 1 (indirect)
+ #define __amd64 1, line 1 (indirect)
+ #define __amd64__ 1, line 1 (indirect)
+ #define __x86_64 1, line 1 (indirect)
+ #define __x86_64__ 1, line 1 (indirect)
+ #define __k8 1, line 1 (indirect)
+ #define __k8__ 1, line 1 (indirect)
+ #define __MMX__ 1, line 1 (indirect)
+ #define __SSE__ 1, line 1 (indirect)
+ #define __SSE2__ 1, line 1 (indirect)
+ #define __SSE_MATH__ 1, line 1 (indirect)
+ #define __SSE2_MATH__ 1, line 1 (indirect)
+ #define __gnu_linux__ 1, line 1 (indirect)
+ #define __linux 1, line 1 (indirect)
+ #define __linux__ 1, line 1 (indirect)
+ #define linux 1, line 1 (indirect)
+ #define __unix 1, line 1 (indirect)
+ #define __unix__ 1, line 1 (indirect)
+ #define unix 1, line 1 (indirect)
+ #define __ELF__ 1, line 1 (indirect)
+ #define __DECIMAL_BID_FORMAT__ 1, line 1 (indirect)
+
+ Offset:             0x582
+ Version:            4
+ Flag:               0x0
+ Offset length:      4
+
+ #define ONE 1, line 1 (indirect)
+ #define TWO 2, line 2 (indirect)
+ #define THREE 3, line 3 (indirect)
+ #define WORLD "World", line 5 (indirect)
+ #define A 'a', line 9 (indirect)
+ #define B b, line 10
+ #define C "C", line 11 (indirect)
+ #undef THREE, line 14 (indirect)
+ #define THREE(ARG1,ARG2,ARG3) ARG3, line 15 (indirect)
+
+ Offset:             0x5bc
+ Version:            4
+ Flag:               0x2 (debug_line_offset)
+ Offset length:      4
+ .debug_line offset: 0x47
+
+ #include offset 0x1a
+ start_file 0, [1] /home/mark/src/tests/world.c
+  start_file 1, [2] /home/mark/src/tests/common.h
+   #include offset 0x582
+  end_file
+ end_file
+
+EOF
+
+exit 0
diff --git a/tests/run-readelf-macros.sh b/tests/run-readelf-macros.sh
new file mode 100755
index 0000000..cc311b7
--- /dev/null
+++ b/tests/run-readelf-macros.sh
@@ -0,0 +1,435 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# - testfile-macros-object.c
+#
+# #define SUCCESS 0
+# #define FAILURE 0
+#
+# #include <stdbool.h>
+#
+# bool foo (int input)
+# {
+#   return input == SUCCESS ? SUCCESS : FAILURE;
+# }
+
+# gcc -g3 -gdwarf-5 -O2 -c testfile-macros-object.c
+
+testfiles testfile-macros-object.o
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=macro testfile-macros-object.o <<\EOF
+
+DWARF section [12] '.debug_macro' at offset 0x16f:
+
+ Offset:             0x0
+ Version:            5
+ Flag:               0x2 (debug_line_offset)
+ Offset length:      4
+ .debug_line offset: 0x0
+
+ #include offset 0x0
+ start_file 0, [1] /home/mark/build/elfutils-obj/testfile-macros-object.c
+  start_file 31, [2] /usr/include/stdc-predef.h
+   #include offset 0x0
+  end_file
+  #define SUCCESS 0, line 1 (indirect)
+  #define FAILURE 0, line 2 (indirect)
+  start_file 4, [3] /opt/rh/devtoolset-8/root/usr/lib/gcc/x86_64-redhat-linux/8/include/stdbool.h
+   #include offset 0x0
+  end_file
+ end_file
+
+
+DWARF section [14] '.debug_macro' at offset 0x19e:
+
+ Offset:             0x0
+ Version:            5
+ Flag:               0x0
+ Offset length:      4
+
+ #define __STDC__ 1, line 0 (indirect)
+ #define __STDC_VERSION__ 201710L, line 0 (indirect)
+ #define __STDC_UTF_16__ 1, line 0 (indirect)
+ #define __STDC_UTF_32__ 1, line 0 (indirect)
+ #define __STDC_HOSTED__ 1, line 0 (indirect)
+ #define __GNUC__ 8, line 0 (indirect)
+ #define __GNUC_MINOR__ 2, line 0 (indirect)
+ #define __GNUC_PATCHLEVEL__ 1, line 0 (indirect)
+ #define __VERSION__ "8.2.1 20180905 (Red Hat 8.2.1-3)", line 0 (indirect)
+ #define __GNUC_RH_RELEASE__ 3, line 0 (indirect)
+ #define __ATOMIC_RELAXED 0, line 0 (indirect)
+ #define __ATOMIC_SEQ_CST 5, line 0 (indirect)
+ #define __ATOMIC_ACQUIRE 2, line 0 (indirect)
+ #define __ATOMIC_RELEASE 3, line 0 (indirect)
+ #define __ATOMIC_ACQ_REL 4, line 0 (indirect)
+ #define __ATOMIC_CONSUME 1, line 0 (indirect)
+ #define __OPTIMIZE__ 1, line 0 (indirect)
+ #define __FINITE_MATH_ONLY__ 0, line 0 (indirect)
+ #define _LP64 1, line 0 (indirect)
+ #define __LP64__ 1, line 0 (indirect)
+ #define __SIZEOF_INT__ 4, line 0 (indirect)
+ #define __SIZEOF_LONG__ 8, line 0 (indirect)
+ #define __SIZEOF_LONG_LONG__ 8, line 0 (indirect)
+ #define __SIZEOF_SHORT__ 2, line 0 (indirect)
+ #define __SIZEOF_FLOAT__ 4, line 0 (indirect)
+ #define __SIZEOF_DOUBLE__ 8, line 0 (indirect)
+ #define __SIZEOF_LONG_DOUBLE__ 16, line 0 (indirect)
+ #define __SIZEOF_SIZE_T__ 8, line 0 (indirect)
+ #define __CHAR_BIT__ 8, line 0 (indirect)
+ #define __BIGGEST_ALIGNMENT__ 16, line 0 (indirect)
+ #define __ORDER_LITTLE_ENDIAN__ 1234, line 0 (indirect)
+ #define __ORDER_BIG_ENDIAN__ 4321, line 0 (indirect)
+ #define __ORDER_PDP_ENDIAN__ 3412, line 0 (indirect)
+ #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__, line 0 (indirect)
+ #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__, line 0 (indirect)
+ #define __SIZEOF_POINTER__ 8, line 0 (indirect)
+ #define __SIZE_TYPE__ long unsigned int, line 0 (indirect)
+ #define __PTRDIFF_TYPE__ long int, line 0 (indirect)
+ #define __WCHAR_TYPE__ int, line 0 (indirect)
+ #define __WINT_TYPE__ unsigned int, line 0 (indirect)
+ #define __INTMAX_TYPE__ long int, line 0 (indirect)
+ #define __UINTMAX_TYPE__ long unsigned int, line 0 (indirect)
+ #define __CHAR16_TYPE__ short unsigned int, line 0 (indirect)
+ #define __CHAR32_TYPE__ unsigned int, line 0 (indirect)
+ #define __SIG_ATOMIC_TYPE__ int, line 0 (indirect)
+ #define __INT8_TYPE__ signed char, line 0 (indirect)
+ #define __INT16_TYPE__ short int, line 0 (indirect)
+ #define __INT32_TYPE__ int, line 0 (indirect)
+ #define __INT64_TYPE__ long int, line 0 (indirect)
+ #define __UINT8_TYPE__ unsigned char, line 0 (indirect)
+ #define __UINT16_TYPE__ short unsigned int, line 0 (indirect)
+ #define __UINT32_TYPE__ unsigned int, line 0 (indirect)
+ #define __UINT64_TYPE__ long unsigned int, line 0 (indirect)
+ #define __INT_LEAST8_TYPE__ signed char, line 0 (indirect)
+ #define __INT_LEAST16_TYPE__ short int, line 0 (indirect)
+ #define __INT_LEAST32_TYPE__ int, line 0 (indirect)
+ #define __INT_LEAST64_TYPE__ long int, line 0 (indirect)
+ #define __UINT_LEAST8_TYPE__ unsigned char, line 0 (indirect)
+ #define __UINT_LEAST16_TYPE__ short unsigned int, line 0 (indirect)
+ #define __UINT_LEAST32_TYPE__ unsigned int, line 0 (indirect)
+ #define __UINT_LEAST64_TYPE__ long unsigned int, line 0 (indirect)
+ #define __INT_FAST8_TYPE__ signed char, line 0 (indirect)
+ #define __INT_FAST16_TYPE__ long int, line 0 (indirect)
+ #define __INT_FAST32_TYPE__ long int, line 0 (indirect)
+ #define __INT_FAST64_TYPE__ long int, line 0 (indirect)
+ #define __UINT_FAST8_TYPE__ unsigned char, line 0 (indirect)
+ #define __UINT_FAST16_TYPE__ long unsigned int, line 0 (indirect)
+ #define __UINT_FAST32_TYPE__ long unsigned int, line 0 (indirect)
+ #define __UINT_FAST64_TYPE__ long unsigned int, line 0 (indirect)
+ #define __INTPTR_TYPE__ long int, line 0 (indirect)
+ #define __UINTPTR_TYPE__ long unsigned int, line 0 (indirect)
+ #define __has_include(STR) __has_include__(STR), line 0 (indirect)
+ #define __has_include_next(STR) __has_include_next__(STR), line 0 (indirect)
+ #define __GXX_ABI_VERSION 1013, line 0 (indirect)
+ #define __SCHAR_MAX__ 0x7f, line 0 (indirect)
+ #define __SHRT_MAX__ 0x7fff, line 0 (indirect)
+ #define __INT_MAX__ 0x7fffffff, line 0 (indirect)
+ #define __LONG_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __LONG_LONG_MAX__ 0x7fffffffffffffffLL, line 0 (indirect)
+ #define __WCHAR_MAX__ 0x7fffffff, line 0 (indirect)
+ #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1), line 0 (indirect)
+ #define __WINT_MAX__ 0xffffffffU, line 0 (indirect)
+ #define __WINT_MIN__ 0U, line 0 (indirect)
+ #define __PTRDIFF_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __SIZE_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __SCHAR_WIDTH__ 8, line 0 (indirect)
+ #define __SHRT_WIDTH__ 16, line 0 (indirect)
+ #define __INT_WIDTH__ 32, line 0 (indirect)
+ #define __LONG_WIDTH__ 64, line 0 (indirect)
+ #define __LONG_LONG_WIDTH__ 64, line 0 (indirect)
+ #define __WCHAR_WIDTH__ 32, line 0 (indirect)
+ #define __WINT_WIDTH__ 32, line 0 (indirect)
+ #define __PTRDIFF_WIDTH__ 64, line 0 (indirect)
+ #define __SIZE_WIDTH__ 64, line 0 (indirect)
+ #define __INTMAX_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __INTMAX_C(c) c ## L, line 0 (indirect)
+ #define __UINTMAX_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __UINTMAX_C(c) c ## UL, line 0 (indirect)
+ #define __INTMAX_WIDTH__ 64, line 0 (indirect)
+ #define __SIG_ATOMIC_MAX__ 0x7fffffff, line 0 (indirect)
+ #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1), line 0 (indirect)
+ #define __SIG_ATOMIC_WIDTH__ 32, line 0 (indirect)
+ #define __INT8_MAX__ 0x7f, line 0 (indirect)
+ #define __INT16_MAX__ 0x7fff, line 0 (indirect)
+ #define __INT32_MAX__ 0x7fffffff, line 0 (indirect)
+ #define __INT64_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __UINT8_MAX__ 0xff, line 0 (indirect)
+ #define __UINT16_MAX__ 0xffff, line 0 (indirect)
+ #define __UINT32_MAX__ 0xffffffffU, line 0 (indirect)
+ #define __UINT64_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __INT_LEAST8_MAX__ 0x7f, line 0 (indirect)
+ #define __INT8_C(c) c, line 0 (indirect)
+ #define __INT_LEAST8_WIDTH__ 8, line 0 (indirect)
+ #define __INT_LEAST16_MAX__ 0x7fff, line 0 (indirect)
+ #define __INT16_C(c) c, line 0 (indirect)
+ #define __INT_LEAST16_WIDTH__ 16, line 0 (indirect)
+ #define __INT_LEAST32_MAX__ 0x7fffffff, line 0 (indirect)
+ #define __INT32_C(c) c, line 0 (indirect)
+ #define __INT_LEAST32_WIDTH__ 32, line 0 (indirect)
+ #define __INT_LEAST64_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __INT64_C(c) c ## L, line 0 (indirect)
+ #define __INT_LEAST64_WIDTH__ 64, line 0 (indirect)
+ #define __UINT_LEAST8_MAX__ 0xff, line 0 (indirect)
+ #define __UINT8_C(c) c, line 0 (indirect)
+ #define __UINT_LEAST16_MAX__ 0xffff, line 0 (indirect)
+ #define __UINT16_C(c) c, line 0 (indirect)
+ #define __UINT_LEAST32_MAX__ 0xffffffffU, line 0 (indirect)
+ #define __UINT32_C(c) c ## U, line 0 (indirect)
+ #define __UINT_LEAST64_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __UINT64_C(c) c ## UL, line 0 (indirect)
+ #define __INT_FAST8_MAX__ 0x7f, line 0 (indirect)
+ #define __INT_FAST8_WIDTH__ 8, line 0 (indirect)
+ #define __INT_FAST16_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __INT_FAST16_WIDTH__ 64, line 0 (indirect)
+ #define __INT_FAST32_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __INT_FAST32_WIDTH__ 64, line 0 (indirect)
+ #define __INT_FAST64_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __INT_FAST64_WIDTH__ 64, line 0 (indirect)
+ #define __UINT_FAST8_MAX__ 0xff, line 0 (indirect)
+ #define __UINT_FAST16_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __UINT_FAST32_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __UINT_FAST64_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __INTPTR_MAX__ 0x7fffffffffffffffL, line 0 (indirect)
+ #define __INTPTR_WIDTH__ 64, line 0 (indirect)
+ #define __UINTPTR_MAX__ 0xffffffffffffffffUL, line 0 (indirect)
+ #define __GCC_IEC_559 2, line 0 (indirect)
+ #define __GCC_IEC_559_COMPLEX 2, line 0 (indirect)
+ #define __FLT_EVAL_METHOD__ 0, line 0 (indirect)
+ #define __FLT_EVAL_METHOD_TS_18661_3__ 0, line 0 (indirect)
+ #define __DEC_EVAL_METHOD__ 2, line 0 (indirect)
+ #define __FLT_RADIX__ 2, line 0 (indirect)
+ #define __FLT_MANT_DIG__ 24, line 0 (indirect)
+ #define __FLT_DIG__ 6, line 0 (indirect)
+ #define __FLT_MIN_EXP__ (-125), line 0 (indirect)
+ #define __FLT_MIN_10_EXP__ (-37), line 0 (indirect)
+ #define __FLT_MAX_EXP__ 128, line 0 (indirect)
+ #define __FLT_MAX_10_EXP__ 38, line 0 (indirect)
+ #define __FLT_DECIMAL_DIG__ 9, line 0 (indirect)
+ #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F, line 0 (indirect)
+ #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F, line 0 (indirect)
+ #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F, line 0 (indirect)
+ #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F, line 0 (indirect)
+ #define __FLT_HAS_DENORM__ 1, line 0 (indirect)
+ #define __FLT_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __FLT_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __DBL_MANT_DIG__ 53, line 0 (indirect)
+ #define __DBL_DIG__ 15, line 0 (indirect)
+ #define __DBL_MIN_EXP__ (-1021), line 0 (indirect)
+ #define __DBL_MIN_10_EXP__ (-307), line 0 (indirect)
+ #define __DBL_MAX_EXP__ 1024, line 0 (indirect)
+ #define __DBL_MAX_10_EXP__ 308, line 0 (indirect)
+ #define __DBL_DECIMAL_DIG__ 17, line 0 (indirect)
+ #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L), line 0 (indirect)
+ #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L), line 0 (indirect)
+ #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L), line 0 (indirect)
+ #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L), line 0 (indirect)
+ #define __DBL_HAS_DENORM__ 1, line 0 (indirect)
+ #define __DBL_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __DBL_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __LDBL_MANT_DIG__ 64, line 0 (indirect)
+ #define __LDBL_DIG__ 18, line 0 (indirect)
+ #define __LDBL_MIN_EXP__ (-16381), line 0 (indirect)
+ #define __LDBL_MIN_10_EXP__ (-4931), line 0 (indirect)
+ #define __LDBL_MAX_EXP__ 16384, line 0 (indirect)
+ #define __LDBL_MAX_10_EXP__ 4932, line 0 (indirect)
+ #define __DECIMAL_DIG__ 21, line 0 (indirect)
+ #define __LDBL_DECIMAL_DIG__ 21, line 0 (indirect)
+ #define __LDBL_MAX__ 1.18973149535723176502126385303097021e+4932L, line 0 (indirect)
+ #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L, line 0 (indirect)
+ #define __LDBL_EPSILON__ 1.08420217248550443400745280086994171e-19L, line 0 (indirect)
+ #define __LDBL_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951L, line 0 (indirect)
+ #define __LDBL_HAS_DENORM__ 1, line 0 (indirect)
+ #define __LDBL_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __LDBL_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __FLT32_MANT_DIG__ 24, line 0 (indirect)
+ #define __FLT32_DIG__ 6, line 0 (indirect)
+ #define __FLT32_MIN_EXP__ (-125), line 0 (indirect)
+ #define __FLT32_MIN_10_EXP__ (-37), line 0 (indirect)
+ #define __FLT32_MAX_EXP__ 128, line 0 (indirect)
+ #define __FLT32_MAX_10_EXP__ 38, line 0 (indirect)
+ #define __FLT32_DECIMAL_DIG__ 9, line 0 (indirect)
+ #define __FLT32_MAX__ 3.40282346638528859811704183484516925e+38F32, line 0 (indirect)
+ #define __FLT32_MIN__ 1.17549435082228750796873653722224568e-38F32, line 0 (indirect)
+ #define __FLT32_EPSILON__ 1.19209289550781250000000000000000000e-7F32, line 0 (indirect)
+ #define __FLT32_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F32, line 0 (indirect)
+ #define __FLT32_HAS_DENORM__ 1, line 0 (indirect)
+ #define __FLT32_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __FLT32_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __FLT64_MANT_DIG__ 53, line 0 (indirect)
+ #define __FLT64_DIG__ 15, line 0 (indirect)
+ #define __FLT64_MIN_EXP__ (-1021), line 0 (indirect)
+ #define __FLT64_MIN_10_EXP__ (-307), line 0 (indirect)
+ #define __FLT64_MAX_EXP__ 1024, line 0 (indirect)
+ #define __FLT64_MAX_10_EXP__ 308, line 0 (indirect)
+ #define __FLT64_DECIMAL_DIG__ 17, line 0 (indirect)
+ #define __FLT64_MAX__ 1.79769313486231570814527423731704357e+308F64, line 0 (indirect)
+ #define __FLT64_MIN__ 2.22507385850720138309023271733240406e-308F64, line 0 (indirect)
+ #define __FLT64_EPSILON__ 2.22044604925031308084726333618164062e-16F64, line 0 (indirect)
+ #define __FLT64_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F64, line 0 (indirect)
+ #define __FLT64_HAS_DENORM__ 1, line 0 (indirect)
+ #define __FLT64_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __FLT64_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __FLT128_MANT_DIG__ 113, line 0 (indirect)
+ #define __FLT128_DIG__ 33, line 0 (indirect)
+ #define __FLT128_MIN_EXP__ (-16381), line 0 (indirect)
+ #define __FLT128_MIN_10_EXP__ (-4931), line 0 (indirect)
+ #define __FLT128_MAX_EXP__ 16384, line 0 (indirect)
+ #define __FLT128_MAX_10_EXP__ 4932, line 0 (indirect)
+ #define __FLT128_DECIMAL_DIG__ 36, line 0 (indirect)
+ #define __FLT128_MAX__ 1.18973149535723176508575932662800702e+4932F128, line 0 (indirect)
+ #define __FLT128_MIN__ 3.36210314311209350626267781732175260e-4932F128, line 0 (indirect)
+ #define __FLT128_EPSILON__ 1.92592994438723585305597794258492732e-34F128, line 0 (indirect)
+ #define __FLT128_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966F128, line 0 (indirect)
+ #define __FLT128_HAS_DENORM__ 1, line 0 (indirect)
+ #define __FLT128_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __FLT128_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __FLT32X_MANT_DIG__ 53, line 0 (indirect)
+ #define __FLT32X_DIG__ 15, line 0 (indirect)
+ #define __FLT32X_MIN_EXP__ (-1021), line 0 (indirect)
+ #define __FLT32X_MIN_10_EXP__ (-307), line 0 (indirect)
+ #define __FLT32X_MAX_EXP__ 1024, line 0 (indirect)
+ #define __FLT32X_MAX_10_EXP__ 308, line 0 (indirect)
+ #define __FLT32X_DECIMAL_DIG__ 17, line 0 (indirect)
+ #define __FLT32X_MAX__ 1.79769313486231570814527423731704357e+308F32x, line 0 (indirect)
+ #define __FLT32X_MIN__ 2.22507385850720138309023271733240406e-308F32x, line 0 (indirect)
+ #define __FLT32X_EPSILON__ 2.22044604925031308084726333618164062e-16F32x, line 0 (indirect)
+ #define __FLT32X_DENORM_MIN__ 4.94065645841246544176568792868221372e-324F32x, line 0 (indirect)
+ #define __FLT32X_HAS_DENORM__ 1, line 0 (indirect)
+ #define __FLT32X_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __FLT32X_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __FLT64X_MANT_DIG__ 64, line 0 (indirect)
+ #define __FLT64X_DIG__ 18, line 0 (indirect)
+ #define __FLT64X_MIN_EXP__ (-16381), line 0 (indirect)
+ #define __FLT64X_MIN_10_EXP__ (-4931), line 0 (indirect)
+ #define __FLT64X_MAX_EXP__ 16384, line 0 (indirect)
+ #define __FLT64X_MAX_10_EXP__ 4932, line 0 (indirect)
+ #define __FLT64X_DECIMAL_DIG__ 21, line 0 (indirect)
+ #define __FLT64X_MAX__ 1.18973149535723176502126385303097021e+4932F64x, line 0 (indirect)
+ #define __FLT64X_MIN__ 3.36210314311209350626267781732175260e-4932F64x, line 0 (indirect)
+ #define __FLT64X_EPSILON__ 1.08420217248550443400745280086994171e-19F64x, line 0 (indirect)
+ #define __FLT64X_DENORM_MIN__ 3.64519953188247460252840593361941982e-4951F64x, line 0 (indirect)
+ #define __FLT64X_HAS_DENORM__ 1, line 0 (indirect)
+ #define __FLT64X_HAS_INFINITY__ 1, line 0 (indirect)
+ #define __FLT64X_HAS_QUIET_NAN__ 1, line 0 (indirect)
+ #define __DEC32_MANT_DIG__ 7, line 0 (indirect)
+ #define __DEC32_MIN_EXP__ (-94), line 0 (indirect)
+ #define __DEC32_MAX_EXP__ 97, line 0 (indirect)
+ #define __DEC32_MIN__ 1E-95DF, line 0 (indirect)
+ #define __DEC32_MAX__ 9.999999E96DF, line 0 (indirect)
+ #define __DEC32_EPSILON__ 1E-6DF, line 0 (indirect)
+ #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF, line 0 (indirect)
+ #define __DEC64_MANT_DIG__ 16, line 0 (indirect)
+ #define __DEC64_MIN_EXP__ (-382), line 0 (indirect)
+ #define __DEC64_MAX_EXP__ 385, line 0 (indirect)
+ #define __DEC64_MIN__ 1E-383DD, line 0 (indirect)
+ #define __DEC64_MAX__ 9.999999999999999E384DD, line 0 (indirect)
+ #define __DEC64_EPSILON__ 1E-15DD, line 0 (indirect)
+ #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD, line 0 (indirect)
+ #define __DEC128_MANT_DIG__ 34, line 0 (indirect)
+ #define __DEC128_MIN_EXP__ (-6142), line 0 (indirect)
+ #define __DEC128_MAX_EXP__ 6145, line 0 (indirect)
+ #define __DEC128_MIN__ 1E-6143DL, line 0 (indirect)
+ #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL, line 0 (indirect)
+ #define __DEC128_EPSILON__ 1E-33DL, line 0 (indirect)
+ #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL, line 0 (indirect)
+ #define __REGISTER_PREFIX__ , line 0 (indirect)
+ #define __USER_LABEL_PREFIX__ , line 0 (indirect)
+ #define __GNUC_STDC_INLINE__ 1, line 0 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1, line 0 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1, line 0 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1, line 0 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1, line 0 (indirect)
+ #define __GCC_ATOMIC_BOOL_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_CHAR_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_SHORT_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_INT_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_LONG_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_LLONG_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1, line 0 (indirect)
+ #define __GCC_ATOMIC_POINTER_LOCK_FREE 2, line 0 (indirect)
+ #define __GCC_HAVE_DWARF2_CFI_ASM 1, line 0 (indirect)
+ #define __PRAGMA_REDEFINE_EXTNAME 1, line 0 (indirect)
+ #define __SIZEOF_INT128__ 16, line 0 (indirect)
+ #define __SIZEOF_WCHAR_T__ 4, line 0 (indirect)
+ #define __SIZEOF_WINT_T__ 4, line 0 (indirect)
+ #define __SIZEOF_PTRDIFF_T__ 8, line 0 (indirect)
+ #define __amd64 1, line 0 (indirect)
+ #define __amd64__ 1, line 0 (indirect)
+ #define __x86_64 1, line 0 (indirect)
+ #define __x86_64__ 1, line 0 (indirect)
+ #define __SIZEOF_FLOAT80__ 16, line 0 (indirect)
+ #define __SIZEOF_FLOAT128__ 16, line 0 (indirect)
+ #define __ATOMIC_HLE_ACQUIRE 65536, line 0 (indirect)
+ #define __ATOMIC_HLE_RELEASE 131072, line 0 (indirect)
+ #define __GCC_ASM_FLAG_OUTPUTS__ 1, line 0 (indirect)
+ #define __k8 1, line 0 (indirect)
+ #define __k8__ 1, line 0 (indirect)
+ #define __code_model_small__ 1, line 0 (indirect)
+ #define __MMX__ 1, line 0 (indirect)
+ #define __SSE__ 1, line 0 (indirect)
+ #define __SSE2__ 1, line 0 (indirect)
+ #define __FXSR__ 1, line 0 (indirect)
+ #define __SSE_MATH__ 1, line 0 (indirect)
+ #define __SSE2_MATH__ 1, line 0 (indirect)
+ #define __SEG_FS 1, line 0 (indirect)
+ #define __SEG_GS 1, line 0 (indirect)
+ #define __gnu_linux__ 1, line 0 (indirect)
+ #define __linux 1, line 0 (indirect)
+ #define __linux__ 1, line 0 (indirect)
+ #define linux 1, line 0 (indirect)
+ #define __unix 1, line 0 (indirect)
+ #define __unix__ 1, line 0 (indirect)
+ #define unix 1, line 0 (indirect)
+ #define __ELF__ 1, line 0 (indirect)
+ #define __DECIMAL_BID_FORMAT__ 1, line 0 (indirect)
+
+
+DWARF section [16] '.debug_macro' at offset 0x98e:
+
+ Offset:             0x0
+ Version:            5
+ Flag:               0x0
+ Offset length:      4
+
+ #define _STDC_PREDEF_H 1, line 19 (indirect)
+ #define __STDC_IEC_559__ 1, line 30 (indirect)
+ #define __STDC_IEC_559_COMPLEX__ 1, line 31 (indirect)
+ #define __STDC_ISO_10646__ 201103L, line 35 (indirect)
+ #define __STDC_NO_THREADS__ 1, line 38 (indirect)
+
+
+DWARF section [18] '.debug_macro' at offset 0x9b0:
+
+ Offset:             0x0
+ Version:            5
+ Flag:               0x0
+ Offset length:      4
+
+ #define _STDBOOL_H , line 29 (indirect)
+ #define bool _Bool, line 33 (indirect)
+ #define true 1, line 34 (indirect)
+ #define false 0, line 35 (indirect)
+ #define __bool_true_false_are_defined 1, line 52 (indirect)
+
+EOF
+
+exit 0
diff --git a/tests/run-readelf-mixed-corenote.sh b/tests/run-readelf-mixed-corenote.sh
new file mode 100755
index 0000000..c960f1d
--- /dev/null
+++ b/tests/run-readelf-mixed-corenote.sh
@@ -0,0 +1,719 @@
+#! /bin/sh
+# Copyright (C) 2012, 2013, 2014 Red Hat, Inc.
+# Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile63
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile63 <<\EOF
+
+Note segment of 892 bytes at offset 0x274:
+  Owner          Data size  Type
+  CORE                 148  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 11087, ppid: 11063, pgrp: 11087, sid: 11063
+    utime: 0.000000, stime: 0.010000, cutime: 0.000000, cstime: 0.000000
+    orig_r0: -1, fpvalid: 1
+    r0:             1  r1:   -1091672508  r2:   -1091672500
+    r3:             0  r4:             0  r5:             0
+    r6:         33728  r7:             0  r8:             0
+    r9:             0  r10:  -1225703496  r11:  -1091672844
+    r12:            0  sp:    0xbeee64f4  lr:    0xb6dc3f48
+    pc:    0x00008500  spsr:  0x60000010
+  CORE                 124  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00400500
+    uid: 0, gid: 0, pid: 11087, ppid: 11063, pgrp: 11087, sid: 11063
+    fname: a.out, psargs: ./a.out 
+  CORE                 144  AUXV
+    HWCAP: 0xe8d7  <swp half thumb fast-mult vfp edsp>
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x8034
+    PHENT: 32
+    PHNUM: 8
+    BASE: 0xb6eee000
+    FLAGS: 0
+    ENTRY: 0x83c0
+    UID: 0
+    EUID: 0
+    GID: 0
+    EGID: 0
+    SECURE: 0
+    RANDOM: 0xbeee674e
+    EXECFN: 0xbeee6ff4
+    PLATFORM: 0xbeee675e
+    NULL
+  CORE                 116  FPREGSET
+    f0: 0x000000000000000000000000  f1: 0x000000000000000000000000
+    f2: 0x000000000000000000000000  f3: 0x000000000000000000000000
+    f4: 0x000000000000000000000000  f5: 0x000000000000000000000000
+    f6: 0x000000000000000000000000  f7: 0x000000000000000000000000
+  LINUX                260  ARM_VFP
+    fpscr: 0x00000000
+    d0:  0x0000000000000000  d1:  0x0000000000000000
+    d2:  0x0000000000000000  d3:  0x0000000000000000
+    d4:  0x0000000000000000  d5:  0x0000000000000000
+    d6:  0x0000000000000000  d7:  0x0000000000000000
+    d8:  0x0000000000000000  d9:  0x0000000000000000
+    d10: 0x0000000000000000  d11: 0x0000000000000000
+    d12: 0x0000000000000000  d13: 0x0000000000000000
+    d14: 0x0000000000000000  d15: 0x0000000000000000
+    d16: 0x0000000000000000  d17: 0x0000000000000000
+    d18: 0x0000000000000000  d19: 0x0000000000000000
+    d20: 0x0000000000000000  d21: 0x0000000000000000
+    d22: 0x0000000000000000  d23: 0x0000000000000000
+    d24: 0x0000000000000000  d25: 0x0000000000000000
+    d26: 0x0000000000000000  d27: 0x0000000000000000
+    d28: 0x0000000000000000  d29: 0x0000000000000000
+    d30: 0x0000000000000000  d31: 0x0000000000000000
+EOF
+
+testfiles testfile67
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile67 <<\EOF
+
+Note segment of 1044 bytes at offset 0xe8:
+  Owner          Data size  Type
+  CORE                 336  PRSTATUS
+    info.si_signo: 4, info.si_code: 0, info.si_errno: 0, cursig: 4
+    sigpend: <>
+    sighold: <>
+    pid: 805, ppid: 804, pgrp: 804, sid: 699
+    utime: 0.000042, stime: 0.000103, cutime: 0.000000, cstime: 0.000000
+    orig_r2: 2571552016, fpvalid: 1
+    pswm:   0x0705c00180000000  pswa:   0x00000000800000d6
+    r0:         4393751543808  r1:         4398002544388
+    r2:                    11  r3:            2571578208
+    r4:            2571702016  r5:         4398003235624
+    r6:            2571580768  r7:            2571702016
+    r8:            2571578208  r9:            2571552016
+    r10:           2571552016  r11:                    0
+    r12:        4398003499008  r13:           2148274656
+    r14:                    0  r15:        4398040761216
+    a0:   0x000003ff  a1:   0xfd54a6f0  a2:   0x00000000  a3:   0x00000000
+    a4:   0x00000000  a5:   0x00000000  a6:   0x00000000  a7:   0x00000000
+    a8:   0x00000000  a9:   0x00000000  a10:  0x00000000  a11:  0x00000000
+    a12:  0x00000000  a13:  0x00000000  a14:  0x00000000  a15:  0x00000000
+  CORE                 136  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000400400
+    uid: 0, gid: 0, pid: 805, ppid: 804, pgrp: 804, sid: 699
+    fname: 1, psargs: ./1 
+  CORE                 304  AUXV
+    SYSINFO_EHDR: 0
+    HWCAP: 0x37f
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x80000040
+    PHENT: 56
+    PHNUM: 2
+    BASE: 0
+    FLAGS: 0
+    ENTRY: 0x800000d4
+    UID: 0
+    EUID: 0
+    GID: 0
+    EGID: 0
+    SECURE: 0
+    RANDOM: 0x3ffffa8463c
+    EXECFN: 0x3ffffa85ff4
+    PLATFORM: 0x3ffffa8464c
+    NULL
+  CORE                 136  FPREGSET
+    fpc: 0x00000000
+    f0:  0x0000000000000040  f1:  0x4b00000000000000
+    f2:  0x0000000000000041  f3:  0x3ad50b5555555600
+    f4:  0x0000000000000000  f5:  0x0000000000000000
+    f6:  0x0000000000000000  f7:  0x0000000000000000
+    f8:  0x0000000000000000  f9:  0x0000000000000000
+    f10: 0x0000000000000000  f11: 0x0000000000000000
+    f12: 0x0000000000000000  f13: 0x0000000000000000
+    f14: 0x0000000000000000  f15: 0x0000000000000000
+  LINUX                  8  S390_LAST_BREAK
+    last_break: 0x000003fffd75ccbe
+  LINUX                  4  S390_SYSTEM_CALL
+    system_call: 0
+EOF
+
+testfiles testfile68
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile68 <<\EOF
+
+Note segment of 852 bytes at offset 0x94:
+  Owner          Data size  Type
+  CORE                 224  PRSTATUS
+    info.si_signo: 4, info.si_code: 0, info.si_errno: 0, cursig: 4
+    sigpend: <>
+    sighold: <>
+    pid: 839, ppid: 838, pgrp: 838, sid: 699
+    utime: 0.000043, stime: 0.000102, cutime: 0.000000, cstime: 0.000000
+    orig_r2: -1723388288, fpvalid: 1
+    pswm:  0x070dc000  pswa:  0x8040009a
+    r0:            0  r1:    -43966716  r2:           11  r3:  -1723238816
+    r4:  -1723265280  r5:    -43275480  r6:  -1723245280  r7:  -1723265280
+    r8:  -1723238816  r9:  -1723388288  r10: -1723388288  r11:           0
+    r12:   -43012096  r13: -2146692640  r14:           0  r15:  2139883440
+    a0:   0x000003ff  a1:   0xfd54a6f0  a2:   0x00000000  a3:   0x00000000
+    a4:   0x00000000  a5:   0x00000000  a6:   0x00000000  a7:   0x00000000
+    a8:   0x00000000  a9:   0x00000000  a10:  0x00000000  a11:  0x00000000
+    a12:  0x00000000  a13:  0x00000000  a14:  0x00000000  a15:  0x00000000
+  CORE                 124  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00400400
+    uid: 0, gid: 0, pid: 839, ppid: 838, pgrp: 838, sid: 699
+    fname: 2, psargs: ./2 
+  CORE                 152  AUXV
+    SYSINFO_EHDR: 0
+    HWCAP: 0x37f
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x400034
+    PHENT: 32
+    PHNUM: 2
+    BASE: 0
+    FLAGS: 0
+    ENTRY: 0x400098
+    UID: 0
+    EUID: 0
+    GID: 0
+    EGID: 0
+    SECURE: 0
+    RANDOM: 0x7f8c090c
+    EXECFN: 0x7f8c1ff4
+    PLATFORM: 0x7f8c091c
+    NULL
+  CORE                 136  FPREGSET
+    fpc: 0x00000000
+    f0:  0x0000000000000040  f1:  0x4b00000000000000
+    f2:  0x0000000000000041  f3:  0x3ad50b5555555600
+    f4:  0x0000000000000000  f5:  0x0000000000000000
+    f6:  0x0000000000000000  f7:  0x0000000000000000
+    f8:  0x0000000000000000  f9:  0x0000000000000000
+    f10: 0x0000000000000000  f11: 0x0000000000000000
+    f12: 0x0000000000000000  f13: 0x0000000000000000
+    f14: 0x0000000000000000  f15: 0x0000000000000000
+  LINUX                  8  S390_LAST_BREAK
+    last_break: 0xfd75ccbe
+  LINUX                  4  S390_SYSTEM_CALL
+    system_call: 0
+  LINUX                 64  S390_HIGH_GPRS
+    high_r0: 0x000003ff, high_r1: 0x000003ff, high_r2: 0x00000000
+    high_r3: 0x00000000, high_r4: 0x00000000, high_r5: 0x000003ff
+    high_r6: 0x00000000, high_r7: 0x00000000, high_r8: 0x00000000
+    high_r9: 0x00000000, high_r10: 0x00000000, high_r11: 0x00000000
+    high_r12: 0x000003ff, high_r13: 0x00000000, high_r14: 0x00000000
+    high_r15: 0x00000000
+EOF
+
+# To reproduce this core dump, do this on x86_64 machine with Linux
+# 3.7 or later:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile71
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile71 <<\EOF
+
+Note segment of 1476 bytes at offset 0x430:
+  Owner          Data size  Type
+  CORE                 336  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 9664, ppid: 2868, pgrp: 9664, sid: 2868
+    utime: 0.000000, stime: 0.004000, cutime: 0.000000, cstime: 0.000000
+    orig_rax: -1, fpvalid: 0
+    r15:                       0  r14:                       0
+    r13:         140734971656848  r12:                 4195328
+    rbp:      0x00007fff69fe39b0  rbx:                       0
+    r11:            266286012928  r10:         140734971656256
+    r9:                        0  r8:             266289790592
+    rax:               305419896  rcx:                 4195584
+    rdx:         140734971656872  rsi:         140734971656856
+    rdi:                       1  rip:      0x00000000004004f9
+    rflags:   0x0000000000010246  rsp:      0x00007fff69fe39b0
+    fs.base:   0x00007fa1c8933740  gs.base:   0x0000000000000000
+    cs: 0x0033  ss: 0x002b  ds: 0x0000  es: 0x0000  fs: 0x0000  gs: 0x0000
+  CORE                 136  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000000200
+    uid: 1000, gid: 1000, pid: 9664, ppid: 2868, pgrp: 9664, sid: 2868
+    fname: a.out, psargs: ./a.out 
+  CORE                 128  SIGINFO
+    si_signo: 11, si_errno: 0, si_code: 1
+    fault address: 0x12345678
+  CORE                 304  AUXV
+    SYSINFO_EHDR: 0x7fff69ffe000
+    HWCAP: 0xafebfbff  <fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss tm pbe>
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x400040
+    PHENT: 56
+    PHNUM: 9
+    BASE: 0
+    FLAGS: 0
+    ENTRY: 0x400400
+    UID: 1000
+    EUID: 1000
+    GID: 1000
+    EGID: 1000
+    SECURE: 0
+    RANDOM: 0x7fff69fe3d19
+    EXECFN: 0x7fff69fe4ff0
+    PLATFORM: 0x7fff69fe3d29
+    NULL
+  CORE                 469  FILE
+    10 files:
+      00400000-00401000 00000000 4096                /home/petr/a.out
+      00600000-00601000 00000000 4096                /home/petr/a.out
+      00601000-00602000 00001000 4096                /home/petr/a.out
+      3dffa00000-3dffa21000 00000000 135168          /usr/lib64/ld-2.17.so
+      3dffc20000-3dffc21000 00020000 4096            /usr/lib64/ld-2.17.so
+      3dffc21000-3dffc22000 00021000 4096            /usr/lib64/ld-2.17.so
+      3dffe00000-3dfffb6000 00000000 1794048         /usr/lib64/libc-2.17.so
+      3dfffb6000-3e001b6000 001b6000 2097152         /usr/lib64/libc-2.17.so
+      3e001b6000-3e001ba000 001b6000 16384           /usr/lib64/libc-2.17.so
+      3e001ba000-3e001bc000 001ba000 8192            /usr/lib64/libc-2.17.so
+EOF
+
+# To reproduce this core dump, do this on an aarch64 machine:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile_aarch64_core
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_aarch64_core <<\EOF
+
+Note segment of 2512 bytes at offset 0x270:
+  Owner          Data size  Type
+  CORE                 392  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 16547, ppid: 3822, pgrp: 16547, sid: 3822
+    utime: 0.010000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
+    pc: 0x0000000000400548, pstate: 0x0000000060000000, fpvalid: 1
+    x0:             305419896  x1:          548685596648
+    x2:          548685596664  x3:               4195648
+    x4:                     0  x5:          548536191688
+    x6:                     0  x7:  -6341196323062964528
+    x8:                   135  x9:            4294967295
+    x10:              4195026  x11:               184256
+    x12:                  144  x13:                   15
+    x14:         548536635328  x15:                    0
+    x16:         548534815304  x17:              4262024
+    x18:         548685596000  x19:                    0
+    x20:                    0  x21:              4195296
+    x22:                    0  x23:                    0
+    x24:                    0  x25:                    0
+    x26:                    0  x27:                    0
+    x28:                    0  x29:         548685596320
+    x30:         548534815544  sp:    0x0000007fc035c6a0
+  CORE                 136  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000400400
+    uid: 0, gid: 0, pid: 16547, ppid: 3822, pgrp: 16547, sid: 3822
+    fname: a.out, psargs: ./a.out 
+  CORE                 128  SIGINFO
+    si_signo: 11, si_errno: 0, si_code: 1
+    fault address: 0x12345678
+  CORE                 304  AUXV
+    SYSINFO_EHDR: 0x7fb7500000
+    HWCAP: 0x3
+    PAGESZ: 65536
+    CLKTCK: 100
+    PHDR: 0x400040
+    PHENT: 56
+    PHNUM: 7
+    BASE: 0x7fb7520000
+    FLAGS: 0
+    ENTRY: 0x4003e0
+    UID: 0
+    EUID: 0
+    GID: 0
+    EGID: 0
+    SECURE: 0
+    RANDOM: 0x7fc035c9e8
+    EXECFN: 0x7fc035fff0
+    PLATFORM: 0x7fc035c9f8
+    NULL
+  CORE                 306  FILE
+    6 files:
+      00400000-00410000 00000000 65536               /root/elfutils/build/a.out
+      00410000-00420000 00000000 65536               /root/elfutils/build/a.out
+      7fb7370000-7fb74d0000 00000000 1441792         /usr/lib64/libc-2.17.so
+      7fb74d0000-7fb74f0000 00150000 131072          /usr/lib64/libc-2.17.so
+      7fb7520000-7fb7540000 00000000 131072          /usr/lib64/ld-2.17.so
+      7fb7540000-7fb7550000 00010000 65536           /usr/lib64/ld-2.17.so
+  CORE                 528  FPREGSET
+    fpsr: 0x00000000, fpcr: 0x00000000
+    v0:  0x00000000000af54b000000000000fe02
+    v1:  0x00000000000000000000000000000000
+    v2:  0x00000000000000000000000000000000
+    v3:  0x00000000000000000000000000000000
+    v4:  0x00000000000000000000000000000000
+    v5:  0x00000000000000000000000000000000
+    v6:  0x00000000000000000000000000000000
+    v7:  0x00000000000000000000000000000000
+    v8:  0x00000000000000000000000000000000
+    v9:  0x00000000000000000000000000000000
+    v10: 0x00000000000000000000000000000000
+    v11: 0x00000000000000000000000000000000
+    v12: 0x00000000000000000000000000000000
+    v13: 0x00000000000000000000000000000000
+    v14: 0x00000000000000000000000000000000
+    v15: 0x00000000000000000000000000000000
+    v16: 0x00000000000000000000000000000000
+    v17: 0x00000000000000000000000000000000
+    v18: 0x00000000000000000000000000000000
+    v19: 0x00000000000000000000000000000000
+    v20: 0x00000000000000000000000000000000
+    v21: 0x00000000000000000000000000000000
+    v22: 0x00000000000000000000000000000000
+    v23: 0x00000000000000000000000000000000
+    v24: 0x00000000000000000000000000000000
+    v25: 0x00000000000000000000000000000000
+    v26: 0x00000000000000000000000000000000
+    v27: 0x00000000000000000000000000000000
+    v28: 0x00000000000000000000000000000000
+    v29: 0x00000000000000000000000000000000
+    v30: 0x00000000000000000000000000000000
+    v31: 0x00000000000000000000000000000000
+  LINUX                  8  ARM_TLS
+    tls: 0x0000007fb73606f0
+  LINUX                264  ARM_HW_BREAK
+    dbg_info: 0x00000610
+    DBGBVR0_EL1: 0x0000000000000000, DBGBCR0_EL1: 0x00000000
+    DBGBVR1_EL1: 0x0000000000000000, DBGBCR1_EL1: 0x00000000
+    DBGBVR2_EL1: 0x0000000000000000, DBGBCR2_EL1: 0x00000000
+    DBGBVR3_EL1: 0x0000000000000000, DBGBCR3_EL1: 0x00000000
+    DBGBVR4_EL1: 0x0000000000000000, DBGBCR4_EL1: 0x00000000
+    DBGBVR5_EL1: 0x0000000000000000, DBGBCR5_EL1: 0x00000000
+    DBGBVR6_EL1: 0x0000000000000000, DBGBCR6_EL1: 0x00000000
+    DBGBVR7_EL1: 0x0000000000000000, DBGBCR7_EL1: 0x00000000
+    DBGBVR8_EL1: 0x0000000000000000, DBGBCR8_EL1: 0x00000000
+    DBGBVR9_EL1: 0x0000000000000000, DBGBCR9_EL1: 0x00000000
+    DBGBVR10_EL1: 0x0000000000000000, DBGBCR10_EL1: 0x00000000
+    DBGBVR11_EL1: 0x0000000000000000, DBGBCR11_EL1: 0x00000000
+    DBGBVR12_EL1: 0x0000000000000000, DBGBCR12_EL1: 0x00000000
+    DBGBVR13_EL1: 0x0000000000000000, DBGBCR13_EL1: 0x00000000
+    DBGBVR14_EL1: 0x0000000000000000, DBGBCR14_EL1: 0x00000000
+    DBGBVR15_EL1: 0x0000000000000000, DBGBCR15_EL1: 0x00000000
+  LINUX                264  ARM_HW_WATCH
+    dbg_info: 0x00000610
+    DBGWVR0_EL1: 0x0000000000000000, DBGWCR0_EL1: 0x00000000
+    DBGWVR1_EL1: 0x0000000000000000, DBGWCR1_EL1: 0x00000000
+    DBGWVR2_EL1: 0x0000000000000000, DBGWCR2_EL1: 0x00000000
+    DBGWVR3_EL1: 0x0000000000000000, DBGWCR3_EL1: 0x00000000
+    DBGWVR4_EL1: 0x0000000000000000, DBGWCR4_EL1: 0x00000000
+    DBGWVR5_EL1: 0x0000000000000000, DBGWCR5_EL1: 0x00000000
+    DBGWVR6_EL1: 0x0000000000000000, DBGWCR6_EL1: 0x00000000
+    DBGWVR7_EL1: 0x0000000000000000, DBGWCR7_EL1: 0x00000000
+    DBGWVR8_EL1: 0x0000000000000000, DBGWCR8_EL1: 0x00000000
+    DBGWVR9_EL1: 0x0000000000000000, DBGWCR9_EL1: 0x00000000
+    DBGWVR10_EL1: 0x0000000000000000, DBGWCR10_EL1: 0x00000000
+    DBGWVR11_EL1: 0x0000000000000000, DBGWCR11_EL1: 0x00000000
+    DBGWVR12_EL1: 0x0000000000000000, DBGWCR12_EL1: 0x00000000
+    DBGWVR13_EL1: 0x0000000000000000, DBGWCR13_EL1: 0x00000000
+    DBGWVR14_EL1: 0x0000000000000000, DBGWCR14_EL1: 0x00000000
+    DBGWVR15_EL1: 0x0000000000000000, DBGWCR15_EL1: 0x00000000
+EOF
+
+# To reproduce this core dump, do this on an i686 machine:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile_i686_core
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_i686_core <<\EOF
+
+Note segment of 1000 bytes at offset 0x214:
+  Owner          Data size  Type
+  CORE                 144  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 27395, ppid: 1130, pgrp: 27395, sid: 1130
+    utime: 0.000000, stime: 0.001000, cutime: 0.000000, cstime: 0.000000
+    orig_eax: -1, fpvalid: 0
+    ebx:     1334976512  ecx:    -1239415396  edx:    -1079283900
+    esi:              0  edi:              0  ebp:     0xbfab6f18
+    eax:      305419896  eip:     0x08048408  eflags:  0x00010246
+    esp:     0xbfab6f18
+    ds: 0x007b  es: 0x007b  fs: 0x0000  gs: 0x0033  cs: 0x0073  ss: 0x007b
+  CORE                 124  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00000200
+    uid: 1000, gid: 1000, pid: 27395, ppid: 1130, pgrp: 27395, sid: 1130
+    fname: a.out, psargs: ./a.out 
+  CORE                 128  SIGINFO
+    si_signo: 11, si_errno: 0, si_code: 1
+    fault address: 0x12345678
+  CORE                 160  AUXV
+    SYSINFO: 0xb77fc414
+    SYSINFO_EHDR: 0xb77fc000
+    HWCAP: 0x780abfd  <fpu de pse tsc msr pae mce cx8 apic sep pge cmov mmx fxsr sse sse2>
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x8048034
+    PHENT: 32
+    PHNUM: 9
+    BASE: 0
+    FLAGS: 0
+    ENTRY: 0x80482f0
+    UID: 1000
+    EUID: 1000
+    GID: 1000
+    EGID: 1000
+    SECURE: 0
+    RANDOM: 0xbfab70eb
+    EXECFN: 0xbfab7ff4
+    PLATFORM: 0xbfab70fb
+    NULL
+  CORE                 275  FILE
+    9 files:
+      08048000-08049000 00000000 4096                /tmp/a.out
+      08049000-0804a000 00000000 4096                /tmp/a.out
+      0804a000-0804b000 00001000 4096                /tmp/a.out
+      4f744000-4f763000 00000000 126976              /usr/lib/ld-2.18.so
+      4f764000-4f765000 0001f000 4096                /usr/lib/ld-2.18.so
+      4f765000-4f766000 00020000 4096                /usr/lib/ld-2.18.so
+      4f768000-4f920000 00000000 1802240             /usr/lib/libc-2.18.so
+      4f920000-4f922000 001b8000 8192                /usr/lib/libc-2.18.so
+      4f922000-4f923000 001ba000 4096                /usr/lib/libc-2.18.so
+  LINUX                 48  386_TLS
+    index: 6, base: 0xb77da700, limit: 0x000fffff, flags: 0x00000051
+    index: 7, base: 0x00000000, limit: 0x00000000, flags: 0x00000028
+    index: 8, base: 0x00000000, limit: 0x00000000, flags: 0x00000028
+EOF
+
+# To reproduce this core dump, do this on x86_64 machine with Linux
+# 3.7 or later:
+# $ gcc -mx32 -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile-x32-core
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-x32-core <<\EOF
+
+Note segment of 2548 bytes at offset 0x234:
+  Owner          Data size  Type
+  CORE                 296  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 6885, ppid: 2792, pgrp: 6885, sid: 2792
+    utime: 0.000000, stime: 0.001000, cutime: 0.000000, cstime: 0.000000
+    orig_rax: -1, fpvalid: 1
+    r15:                       0  r14:                       0
+    r13:              4290830656  r12:                 4194960
+    rbp:      0x00000000ffc0e070  rbx:                       0
+    r11:              4145779200  r10:                       0
+    r9:               4149627024  r8:               4149551744
+    rax:               305419896  rcx:                 4195216
+    rdx:              4290830668  rsi:              4290830660
+    rdi:                       1  rip:      0x0000000000400380
+    rflags:   0x0000000000010246  rsp:      0x00000000ffc0e070
+    fs.base:   0x00000000f7754700  gs.base:   0x0000000000000000
+    cs: 0x0033  ss: 0x002b  ds: 0x002b  es: 0x002b  fs: 0x0063  gs: 0x0000
+  CORE                 124  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00406600
+    uid: 1000, gid: 1000, pid: 6885, ppid: 2792, pgrp: 6885, sid: 2792
+    fname: a.out, psargs: ./a.out 
+  CORE                 128  SIGINFO
+    si_signo: 11, si_errno: 0, si_code: 1
+    fault address: 0x12345678
+  CORE                 152  AUXV
+    SYSINFO_EHDR: 0xffd49000
+    HWCAP: 0xbfebfbff  <fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe>
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x400034
+    PHENT: 32
+    PHNUM: 8
+    BASE: 0xf7555000
+    FLAGS: 0
+    ENTRY: 0x400290
+    UID: 1000
+    EUID: 1000
+    GID: 1000
+    EGID: 1000
+    SECURE: 0
+    RANDOM: 0xffc0e2cb
+    EXECFN: 0xffc0fff0
+    PLATFORM: 0xffc0e2db
+    NULL
+  CORE                 361  FILE
+    9 files:
+      00400000-00401000 00000000 4096                /export/home/hjl/bugs/gdb/x32-1/a.out
+      00600000-00601000 00000000 4096                /export/home/hjl/bugs/gdb/x32-1/a.out
+      f71a2000-f734f000 00000000 1757184             /usr/libx32/libc-2.20.so
+      f734f000-f754e000 001ad000 2093056             /usr/libx32/libc-2.20.so
+      f754e000-f7551000 001ac000 12288               /usr/libx32/libc-2.20.so
+      f7551000-f7552000 001af000 4096                /usr/libx32/libc-2.20.so
+      f7555000-f7575000 00000000 131072              /usr/libx32/ld-2.20.so
+      f7774000-f7775000 0001f000 4096                /usr/libx32/ld-2.20.so
+      f7775000-f7776000 00020000 4096                /usr/libx32/ld-2.20.so
+  CORE                 512  FPREGSET
+    xmm0:  0x0000000000000000000000000000ff00
+    xmm1:  0x2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f2f
+    xmm2:  0x00000000000000000000000000000000
+    xmm3:  0x0000000000000000ff00000000000000
+    xmm4:  0x000000000000000000ff000000000000
+    xmm5:  0x00000000000000000000000000000000
+    xmm6:  0x00000000000000000000000000000000
+    xmm7:  0x00000000000000000000000000000000
+    xmm8:  0x00000000000000000000000000000000
+    xmm9:  0x00000000000000000000000000000000
+    xmm10: 0x00000000000000000000000000000000
+    xmm11: 0x00000000000000000000000000000000
+    xmm12: 0x00000000000000000000000000000000
+    xmm13: 0x00000000000000000000000000000000
+    xmm14: 0x00000000000000000000000000000000
+    xmm15: 0x00000000000000000000000000000000
+    st0: 0x00000000000000000000  st1: 0x00000000000000000000
+    st2: 0x00000000000000000000  st3: 0x00000000000000000000
+    st4: 0x00000000000000000000  st5: 0x00000000000000000000
+    st6: 0x00000000000000000000  st7: 0x00000000000000000000
+    mxcsr:   0x0000ffff00001f80
+    fcw: 0x037f  fsw: 0x0000
+  LINUX                832  X86_XSTATE
+EOF
+
+# To reproduce this core dump, do this on an m68k machine:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile-m68k-core
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-m68k-core <<\EOF
+
+Note segment of 1056 bytes at offset 0x1f4:
+  Owner          Data size  Type
+  CORE                 154  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 1963, ppid: 1084, pgrp: 1963, sid: 1084
+    utime: 0.000000, stime: 0.010000, cutime: 0.000000, cstime: 0.000000
+    fpvalid: 1
+    d1:           1  d2:           0  d3: -2146476616  d4: -2146476616
+    d5:           0  d6: -2147393212  d7: -2144827216  a0:  0x12345678
+    a1:  0xefe71460  a2:  0x00000000  a3:  0x80288df8  a4:  0x80000340
+    a5:  0xc017a000  a6:  0xefe71434  d0: -1073595312  a7:  0xefe71434
+    pc:  0x800003fe
+  CORE                 124  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x00400600
+    uid: 1000, gid: 501, pid: 1963, ppid: 1084, pgrp: 1963, sid: 1084
+    fname: a.out, psargs: ./a.out 
+  CORE                 128  SIGINFO
+    si_signo: 11, si_errno: 0, si_code: 1
+    fault address: 0x12345678
+  CORE                 136  AUXV
+    HWCAP: 0
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x80000034
+    PHENT: 32
+    PHNUM: 9
+    BASE: 0xc0000000
+    FLAGS: 0
+    ENTRY: 0x80000340
+    UID: 1000
+    EUID: 1000
+    GID: 501
+    EGID: 501
+    SECURE: 0
+    RANDOM: 0xefe716d9
+    EXECFN: 0xefe71ff4
+    NULL
+  CORE                 281  FILE
+    10 files:
+      80000000-80001000 00000000 4096                /tmp/a.out
+      80003000-80004000 00001000 4096                /tmp/a.out
+      80004000-80005000 00002000 4096                /tmp/a.out
+      c0000000-c001c000 00000000 114688              /lib/ld-2.23.so
+      c001f000-c0020000 0001d000 4096                /lib/ld-2.23.so
+      c0020000-c0021000 0001e000 4096                /lib/ld-2.23.so
+      c0032000-c0177000 00000000 1331200             /lib/libc-2.23.so
+      c0177000-c0178000 00145000 4096                /lib/libc-2.23.so
+      c0178000-c017a000 00144000 8192                /lib/libc-2.23.so
+      c017a000-c017e000 00146000 16384               /lib/libc-2.23.so
+  CORE                 108  FPREGSET
+    fp0: 0x7fff0000ffffffffffffffff  fp1: 0x7fff0000ffffffffffffffff
+    fp2: 0x7fff0000ffffffffffffffff  fp3: 0x7fff0000ffffffffffffffff
+    fp4: 0x7fff0000ffffffffffffffff  fp5: 0x7fff0000ffffffffffffffff
+    fp6: 0x7fff0000ffffffffffffffff  fp7: 0x7fff0000ffffffffffffffff
+EOF
+
+# To reproduce this core dump, do this on a riscv64 machine:
+# $ gcc -x c <(echo 'int main () { return *(int *)0x12345678; }')
+# $ ./a.out
+testfiles testfile-riscv64-core
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-riscv64-core <<\EOF
+
+Note segment of 1408 bytes at offset 0x388:
+  Owner          Data size  Type
+  CORE                 376  PRSTATUS
+    info.si_signo: 11, info.si_code: 0, info.si_errno: 0, cursig: 11
+    sigpend: <>
+    sighold: <>
+    pid: 6801, ppid: 1155, pgrp: 6801, sid: 1155
+    utime: 0.000000, stime: 0.110000, cutime: 0.000000, cstime: 0.000000
+    pc: 0x000000000001049a, fpvalid: 0
+    ra:    0x0000002000051c9a  sp:    0x0000003fff981240
+    gp:    0x0000000000012828  tp:    0x00000020000311d0
+    t0:          137439068496  t1:          137439288314
+    t2:                 74672  s0:          274871095888
+    s1:                 66724  a0:                     1
+    a1:          274871096232  a2:          274871096248
+    a3:                     0  a4:          274871095928
+    a5:             305419896  a6:          137440357656
+    a7:                     0  s2:          183254994416
+    s3:          137439062288  s4:                     0
+    s5:          183257703888  s6:          183256061824
+    s7:                     0  s8:          183252656348
+    s9:          183257666368  s10:         183257700608
+    s11:                    0  t3:                130042
+    t4:                     2  t5:                     3
+    t6:                 15632
+  CORE                 136  PRPSINFO
+    state: 0, sname: R, zomb: 0, nice: 0, flag: 0x0000000000400600
+    uid: 0, gid: 0, pid: 6801, ppid: 1155, pgrp: 6801, sid: 1155
+    fname: a.out, psargs: /tmp/a.out 
+  CORE                 128  SIGINFO
+    si_signo: 11, si_errno: 0, si_code: 1
+    fault address: 0x12345678
+  CORE                 288  AUXV
+    SYSINFO_EHDR: 0x200001d000
+    HWCAP: 0x1105
+    PAGESZ: 4096
+    CLKTCK: 100
+    PHDR: 0x10040
+    PHENT: 56
+    PHNUM: 9
+    BASE: 0x2000000000
+    FLAGS: 0
+    ENTRY: 0x103e0
+    UID: 0
+    EUID: 0
+    GID: 0
+    EGID: 0
+    SECURE: 0
+    RANDOM: 0x3fff9816d6
+    EXECFN: 0x3fff981fed
+    NULL
+  CORE                 379  FILE
+    9 files:
+      00010000-00011000 00000000 4096                /tmp/a.out
+      00011000-00012000 00000000 4096                /tmp/a.out
+      00012000-00013000 00001000 4096                /tmp/a.out
+      2000000000-200001a000 00000000 106496          /lib64/ld-2.27.so
+      200001a000-200001b000 00019000 4096            /lib64/ld-2.27.so
+      200001b000-200001c000 0001a000 4096            /lib64/ld-2.27.so
+      2000032000-2000151000 00000000 1175552         /lib64/libc-2.27.so
+      2000151000-2000155000 0011e000 16384           /lib64/libc-2.27.so
+      2000155000-2000157000 00122000 8192            /lib64/libc-2.27.so
+EOF
+
+exit 0
diff --git a/tests/run-readelf-multi-noline.sh b/tests/run-readelf-multi-noline.sh
new file mode 100755
index 0000000..d72a9fd
--- /dev/null
+++ b/tests/run-readelf-multi-noline.sh
@@ -0,0 +1,170 @@
+#! /bin/sh
+# Copyright (C) 2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# = a.c =
+# int a;
+
+# = b.c =
+# int b;
+
+# = m.c =
+# int main () { }
+
+# gcc -g -o testfile_multi_noline a.c b.c m.c
+
+testfiles testfile_multi_noline
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=line testfile_multi_noline <<\EOF
+
+DWARF section [29] '.debug_line' at offset 0x1221:
+
+Table at offset 0:
+
+ Length:                         32
+ DWARF version:                  3
+ Prologue length:                26
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         4
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         a.c
+
+No line number statements.
+
+Table at offset 36:
+
+ Length:                         32
+ DWARF version:                  3
+ Prologue length:                26
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         4
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         b.c
+
+No line number statements.
+
+Table at offset 72:
+
+ Length:                         54
+ DWARF version:                  3
+ Prologue length:                26
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         4
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         m.c
+
+Line number statements:
+ [    6c] set column to 13
+ [    6e] extended opcode 2:  set address to +0x724 <main>
+ [    79] copy
+ [    7a] set column to 15
+ [    7c] special opcode 32: address+4 = +0x728 <main+0x4>, line+0 = 1
+ [    7d] advance address by 4 to +0x72c
+ [    7f] extended opcode 1:  end of sequence
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=decodedline testfile_multi_noline <<\EOF
+
+DWARF section [29] '.debug_line' at offset 0x1221:
+
+ CU [b] a.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+ CU [44] b.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+ CU [7d] m.c
+  line:col SBPE* disc isa op address (Statement Block Prologue Epilogue *End)
+  /tmp/m.c (mtime: 0, length: 0)
+     1:13  S        0   0  0 +0x0000000000000724 <main>
+     1:15  S        0   0  0 +0x0000000000000728 <main+0x4>
+     1:15  S   *    0   0  0 +0x000000000000072b <main+0x7>
+
+EOF
+
+exit 0
diff --git a/tests/run-readelf-n.sh b/tests/run-readelf-n.sh
new file mode 100755
index 0000000..4c98fd8
--- /dev/null
+++ b/tests/run-readelf-n.sh
@@ -0,0 +1,259 @@
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# - testfile-gnu-property-note.c
+# int
+# main ()
+# {
+#   return 0;
+# }
+#
+# gcc -fcf-protection -c testfile-gnu-property-note.c
+# gcc -o testfile-gnu-property-note testfile-gnu-property-note.o
+# eu-strip --strip-sections testfile-gnu-property-note
+
+testfiles testfile-gnu-property-note.o testfile-gnu-property-note
+
+# Test reading notes through sections
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-gnu-property-note.o << EOF
+
+Note section [ 6] '.note.gnu.property' of 32 bytes at offset 0x80:
+  Owner          Data size  Type
+  GNU                   16  GNU_PROPERTY_TYPE_0
+    X86 FEATURE_1_AND: 00000003 IBT SHSTK
+EOF
+
+# Test reading notes through segments
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-gnu-property-note << EOF
+
+Note segment of 32 bytes at offset 0x300:
+  Owner          Data size  Type
+  GNU                   16  GNU_PROPERTY_TYPE_0
+    X86 FEATURE_1_AND: 00000003 IBT SHSTK
+
+Note segment of 68 bytes at offset 0x320:
+  Owner          Data size  Type
+  GNU                   16  GNU_ABI_TAG
+    OS: Linux, ABI: 3.2.0
+  GNU                   20  GNU_BUILD_ID
+    Build ID: 83cb2229fabd2065d1361f5b46424cd75270f94b
+EOF
+
+# NT_VERSION note type clashes with "GNU" owner type NT_GNU_ABI_TAG.
+# Uses owner name (with zero desc) for version string.
+testfiles testfile11
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile11 << EOF
+
+Note section [ 2] '.note.ABI-tag' of 32 bytes at offset 0x128:
+  Owner          Data size  Type
+  GNU                   16  GNU_ABI_TAG
+    OS: Linux, ABI: 2.2.5
+
+Note section [35] '.note' of 60 bytes at offset 0x13364:
+  Owner          Data size  Type
+  01.01                  0  VERSION
+  01.01                  0  VERSION
+  01.01                  0  VERSION
+EOF
+
+# See run-annobingroup.sh
+testfiles testfile-annobingroup.o
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-annobingroup.o << EOF
+
+Note section [ 5] '.gnu.build.attributes' of 272 bytes at offset 0x50:
+  Owner          Data size  Type
+  GA                    16  GNU Build Attribute OPEN
+    Address Range: 0 - 0
+    VERSION: "3p8"
+  GA                     0  GNU Build Attribute OPEN
+    TOOL: "gcc 8.1.1 20180712"
+  GA                     0  GNU Build Attribute OPEN
+    "GOW": 5
+  GA                     0  GNU Build Attribute OPEN
+    STACK_PROT: 0
+  GA                     0  GNU Build Attribute OPEN
+    "stack_clash": FALSE
+  GA                     0  GNU Build Attribute OPEN
+    "cf_protection": 0
+  GA                     0  GNU Build Attribute OPEN
+    PIC: 0
+  GA                     0  GNU Build Attribute OPEN
+    SHORT_ENUM: FALSE
+  GA                     0  GNU Build Attribute OPEN
+    ABI: c001100000012
+  GA                     0  GNU Build Attribute OPEN
+    "stack_realign": FALSE
+
+Note section [ 7] '.gnu.build.attributes..text.unlikely' of 216 bytes at offset 0x160:
+  Owner          Data size  Type
+  GA                    16  GNU Build Attribute FUNC
+    Address Range: 0 - 0
+    ABI: c001100000012
+  GA                     0  GNU Build Attribute FUNC
+    "stack_realign": FALSE
+  GA                     0  GNU Build Attribute FUNC
+    STACK_PROT: 0
+  GA                     0  GNU Build Attribute FUNC
+    "stack_clash": FALSE
+  GA                     0  GNU Build Attribute FUNC
+    "cf_protection": 0
+  GA                     0  GNU Build Attribute FUNC
+    PIC: 0
+  GA                     0  GNU Build Attribute FUNC
+    "GOW": 5
+  GA                     0  GNU Build Attribute FUNC
+    SHORT_ENUM: FALSE
+
+Note section [22] '.note.gnu.property' of 48 bytes at offset 0x40c:
+  Owner          Data size  Type
+  GNU                   32  GNU_PROPERTY_TYPE_0
+    X86 0xc0000000 data: 00 00 00 00
+    X86 0xc0000001 data: 00 00 00 00
+EOF
+
+#
+# = gnu_props.S
+#
+# #define NT_GNU_PROPERTY_TYPE_0 5
+# #define GNU_PROPERTY_STACK_SIZE 1
+# #define GNU_PROPERTY_NO_COPY_ON_PROTECTED 2
+
+# /* Normal notes always have alignment and padding of 4 bytes,
+#    but GNU Property notes use 4 byte words, with 8 byte padding
+#    for ELFCLASS64.  */
+# #if __SIZEOF_PTRDIFF_T__  == 8
+# # define ALIGN 3
+# #elif __SIZEOF_PTRDIFF_T__  == 4
+# # define ALIGN 2
+# #endif
+#
+# 	.section ".note.gnu.property", "a"
+# 	.p2align ALIGN
+# 	/* First note.  */
+# 	.long 1f - 0f			/* name length.  */
+# 	.long 4f - 2f			/* data length.  */
+# 	.long NT_GNU_PROPERTY_TYPE_0	/* note type.  */
+# 0:
+# 	.asciz "GNU"			/* vendor name.  */
+# 1:
+# 	.p2align ALIGN			/* Padding.  */
+# 2:
+# 	.long GNU_PROPERTY_STACK_SIZE	/* pr_type.  */
+# 	.long 4f - 3f			/* pr_datasz.  */
+# 3:
+# 	.dc.a 0x280000			/* Stack size.  */
+# 4:
+# 	.p2align ALIGN
+#
+# 	/* Second note.  */
+# 	.long 6f - 5f				/* name length.  */
+# 	.long 8f - 7f				/* data length.  */
+# 	.long NT_GNU_PROPERTY_TYPE_0		/* note type.  */
+# 5:
+# 	.asciz "GNU"				/* vendor name.  */
+# 6:
+# 	.p2align ALIGN				/* Padding.  */
+# 7:
+# 	.long GNU_PROPERTY_NO_COPY_ON_PROTECTED /* pr_type.  */
+# 	.long 0					/* pr_datasz.  */
+# 	/* No data.  */
+# 8:
+# 	.p2align ALIGN
+#
+# On x86_64
+# gcc -m64 -c -o testfile_gnu_props_64le.o gnu_props.S
+# gcc -m32 -c -o testfile_gnu_props_32le.o gnu_props.S
+
+testfiles testfile_gnu_props.32le.o testfile_gnu_props.64le.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_gnu_props.32le.o << EOF
+
+Note section [ 4] '.note.gnu.property' of 52 bytes at offset 0x34:
+  Owner          Data size  Type
+  GNU                   12  GNU_PROPERTY_TYPE_0
+    STACK_SIZE 0x280000
+  GNU                    8  GNU_PROPERTY_TYPE_0
+    NO_COPY_ON_PROTECTION
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_gnu_props.64le.o << EOF
+
+Note section [ 4] '.note.gnu.property' of 56 bytes at offset 0x40:
+  Owner          Data size  Type
+  GNU                   16  GNU_PROPERTY_TYPE_0
+    STACK_SIZE 0x280000
+  GNU                    8  GNU_PROPERTY_TYPE_0
+    NO_COPY_ON_PROTECTION
+EOF
+
+# On ppc64
+# gcc -m32 -c -o testfile_gnu_props.32be.o gnu_props.S
+# gcc -m64 -c -o testfile_gnu_props.64be.o gnu_props.S
+
+testfiles testfile_gnu_props.32be.o testfile_gnu_props.64be.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_gnu_props.32be.o << EOF
+
+Note section [ 4] '.note.gnu.property' of 52 bytes at offset 0x34:
+  Owner          Data size  Type
+  GNU                   12  GNU_PROPERTY_TYPE_0
+    STACK_SIZE 0x280000
+  GNU                    8  GNU_PROPERTY_TYPE_0
+    NO_COPY_ON_PROTECTION
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile_gnu_props.64be.o << EOF
+
+Note section [ 4] '.note.gnu.property' of 56 bytes at offset 0x40:
+  Owner          Data size  Type
+  GNU                   16  GNU_PROPERTY_TYPE_0
+    STACK_SIZE 0x280000
+  GNU                    8  GNU_PROPERTY_TYPE_0
+    NO_COPY_ON_PROTECTION
+EOF
+
+# - testfile-gnu-property-note.c
+# int
+# main ()
+# {
+#   return 0;
+# }
+#
+# gcc -mbranch-protection=standard -c testfile-gnu-property-note.c
+# gcc -o testfile-gnu-property-note-aarch64 testfile-gnu-property-note.o
+# eu-strip --remove-section=.gnu.build.attributes \
+#	   testfile-gnu-property-note-aarch64
+
+testfiles testfile-gnu-property-note-aarch64
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile-gnu-property-note-aarch64 << EOF
+
+Note section [ 2] '.note.gnu.property' of 32 bytes at offset 0x2c8:
+  Owner          Data size  Type
+  GNU                   16  GNU_PROPERTY_TYPE_0
+    AARCH64 FEATURE_1_AND: 00000003 BTI PAC
+
+Note section [ 3] '.note.gnu.build-id' of 36 bytes at offset 0x2e8:
+  Owner          Data size  Type
+  GNU                   20  GNU_BUILD_ID
+    Build ID: af82d6df6f3b396487e3e27a826ca9cbbbecbe5f
+
+Note section [ 4] '.note.ABI-tag' of 32 bytes at offset 0x30c:
+  Owner          Data size  Type
+  GNU                   16  GNU_ABI_TAG
+    OS: Linux, ABI: 3.7.0
+EOF
diff --git a/tests/run-readelf-ranges.sh b/tests/run-readelf-ranges.sh
new file mode 100755
index 0000000..ca3e302
--- /dev/null
+++ b/tests/run-readelf-ranges.sh
@@ -0,0 +1,236 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-readelf-loc.sh
+
+testfiles testfileloc
+
+# Process values as offsets from base addresses and resolve to symbols.
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=ranges testfileloc<<\EOF
+
+DWARF section [34] '.debug_ranges' at offset 0xd94:
+
+ CU [     b] base: 0x0000000000400480 <main>
+ [     0] range 0, 2
+          0x0000000000400480 <main>..
+          0x0000000000400481 <main+0x1>
+          range 5, d
+          0x0000000000400485 <main+0x5>..
+          0x000000000040048c <main+0xc>
+
+ CU [    e0] base: 0x00000000004004a0 <say>
+ [    30] range d, f
+          0x00000000004004ad <say+0xd>..
+          0x00000000004004ae <say+0xe>
+          range 12, 1a
+          0x00000000004004b2 <say+0x12>..
+          0x00000000004004b9 <say+0x19>
+EOF
+
+# Don't resolve addresses to symbols.
+testrun_compare ${abs_top_builddir}/src/readelf -N --debug-dump=ranges testfileloc<<\EOF
+
+DWARF section [34] '.debug_ranges' at offset 0xd94:
+
+ CU [     b] base: 0x0000000000400480
+ [     0] range 0, 2
+          0x0000000000400480..
+          0x0000000000400481
+          range 5, d
+          0x0000000000400485..
+          0x000000000040048c
+
+ CU [    e0] base: 0x00000000004004a0
+ [    30] range d, f
+          0x00000000004004ad..
+          0x00000000004004ae
+          range 12, 1a
+          0x00000000004004b2..
+          0x00000000004004b9
+EOF
+
+# Produce "raw" unprocessed content.
+testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=ranges testfileloc<<\EOF
+
+DWARF section [34] '.debug_ranges' at offset 0xd94:
+
+ CU [     b] base: 0x0000000000400480
+ [     0] range 0, 2
+          range 5, d
+
+ CU [    e0] base: 0x00000000004004a0
+ [    30] range d, f
+          range 12, 1a
+EOF
+
+# .debug_rnglists (DWARF5), see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-5
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=ranges testfile-dwarf-5<<\EOF
+
+DWARF section [33] '.debug_rnglists' at offset 0x1d9a:
+Table at Offset 0x0:
+
+ Length:               45
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        0
+ CU [   218] base: 000000000000000000
+
+  Offset: c, Index: 0
+    base_address 0x400583
+      0x0000000000400583 <calc+0x13>
+    offset_pair 0, 2
+      0x0000000000400583 <calc+0x13>..
+      0x0000000000400584 <calc+0x14>
+    offset_pair 5, 15
+      0x0000000000400588 <calc+0x18>..
+      0x0000000000400597 <calc+0x27>
+    end_of_list
+
+  Offset: 1c, Index: 10
+    start_length 0x400570, 2b
+      0x0000000000400570 <calc>..
+      0x000000000040059a <calc+0x2a>
+    start_length 0x400410, 20
+      0x0000000000400410 <main>..
+      0x000000000040042f <main+0x1f>
+    end_of_list
+
+EOF
+
+# Same as above, but for DWARF4, note no header, and base address is not
+# given, but ranges are the same.
+testfiles testfile-dwarf-4
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=ranges testfile-dwarf-4<<\EOF
+
+DWARF section [32] '.debug_ranges' at offset 0x1f96:
+
+ CU [   21c] base: 000000000000000000
+ [     0] range 400583, 400585
+          0x0000000000400583 <calc+0x13>..
+          0x0000000000400584 <calc+0x14>
+          range 400588, 400598
+          0x0000000000400588 <calc+0x18>..
+          0x0000000000400597 <calc+0x27>
+ [    30] range 400570, 40059b
+          0x0000000000400570 <calc>..
+          0x000000000040059a <calc+0x2a>
+          range 400410, 400430
+          0x0000000000400410 <main>..
+          0x000000000040042f <main+0x1f>
+EOF
+
+# Now with split dwarf. See tests/testfile-dwarf-45.source.
+# Note that this will have an offsets table that the .dwo can refer to.
+testfiles testfile-splitdwarf-5 testfile-hello5.dwo testfile-world5.dwo
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=ranges testfile-splitdwarf-5<<\EOF
+
+DWARF section [35] '.debug_rnglists' at offset 0x393a:
+Table at Offset 0x0:
+
+ Length:               53
+ DWARF version:         5
+ Address size:          8
+ Segment size:          0
+ Offset entries:        2
+ CU [    49] base: 000000000000000000
+
+  Offsets starting at 0xc:
+   [     0] 0x8
+   [     1] 0x18
+
+  Offset: 14, Index: 8
+    base_address 0x4011d3
+      0x00000000004011d3 <calc+0x13>
+    offset_pair 0, 2
+      0x00000000004011d3 <calc+0x13>..
+      0x00000000004011d4 <calc+0x14>
+    offset_pair 5, 15
+      0x00000000004011d8 <calc+0x18>..
+      0x00000000004011e7 <calc+0x27>
+    end_of_list
+
+  Offset: 24, Index: 18
+    start_length 0x4011c0, 2b
+      0x00000000004011c0 <calc>..
+      0x00000000004011ea <calc+0x2a>
+    start_length 0x401060, 20
+      0x0000000000401060 <main>..
+      0x000000000040107f <main+0x1f>
+    end_of_list
+
+EOF
+
+# Note that the rnglist_base attribute of the second CU points to the offsets
+# above 0xc [c].
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=info testfile-splitdwarf-5<<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x3102:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 5, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ Unit type: skeleton (4), Unit id: 0xc422aa5c31fec205
+ [    14]  skeleton_unit        abbrev: 1
+           low_pc               (addr) 0x0000000000401160 <foo>
+           high_pc              (data8) 81 (0x00000000004011b1)
+           stmt_list            (sec_offset) 0
+           dwo_name             (strp) "testfile-hello5.dwo"
+           comp_dir             (strp) "/home/mark/src/elfutils/tests"
+           GNU_pubnames         (flag_present) yes
+           addr_base            (sec_offset) address base [     8]
+ Compilation unit at offset 53:
+ Version: 5, Abbreviation section offset: 21, Address size: 8, Offset size: 4
+ Unit type: skeleton (4), Unit id: 0xb6c8b9d97e6dfdfe
+ [    49]  skeleton_unit        abbrev: 1
+           ranges               (sec_offset) range list [    24]
+           low_pc               (addr) 000000000000000000
+           stmt_list            (sec_offset) 655
+           dwo_name             (strp) "testfile-world5.dwo"
+           comp_dir             (strp) "/home/mark/src/elfutils/tests"
+           GNU_pubnames         (flag_present) yes
+           addr_base            (sec_offset) address base [    a8]
+           rnglists_base        (sec_offset) range list [     c]
+EOF
+
+# Same for DWARF4 GNU DebugFission. But now we need to scan the .dwo
+# explicitly to know it will use the first ranges.
+testfiles testfile-splitdwarf-4 testfile-hello4.dwo testfile-world4.dwo
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=ranges testfile-splitdwarf-4<<\EOF
+
+DWARF section [32] '.debug_ranges' at offset 0x3611:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 4011d3, 4011d5
+          0x00000000004011d3 <calc+0x13>..
+          0x00000000004011d4 <calc+0x14>
+          range 4011d8, 4011e8
+          0x00000000004011d8 <calc+0x18>..
+          0x00000000004011e7 <calc+0x27>
+
+ CU [    3f] base: 000000000000000000
+ [    30] range 4011c0, 4011eb
+          0x00000000004011c0 <calc>..
+          0x00000000004011ea <calc+0x2a>
+          range 401060, 401080
+          0x0000000000401060 <main>..
+          0x000000000040107f <main+0x1f>
+EOF
+
+exit 0
diff --git a/tests/run-readelf-s.sh b/tests/run-readelf-s.sh
new file mode 100755
index 0000000..6b218f1
--- /dev/null
+++ b/tests/run-readelf-s.sh
@@ -0,0 +1,401 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Tests readelf -s and readelf --elf-section -s
+# See also run-dwflsyms.sh
+#
+# - bar.c
+#
+# static int b1 = 1;
+# int b2 = 1;
+#
+# static int
+# foo (int a)
+# {
+#   return a + b2;
+# }
+#
+# int bar (int b)
+# {
+#   return b - foo (b - b1);
+# }
+#
+# - foo.c
+#
+# extern int bar (int b);
+# extern int b2;
+#
+# int
+# main (int argc, char ** argv)
+# {
+#   return bar (argc + b2);
+# }
+#
+# gcc -pie -g -c foo.c
+# gcc -pie -g -c bar.c
+# gcc -pie -g -o baz foo.o bar.o
+#
+# - testfilebaztab (dynsym + symtab)
+# cp baz testfilebaztab
+#
+# - testfilebazdbg (dynsym + .debug file)
+# eu-strip --remove-comment -f testfilebazdbg.debug baz
+# cp baz testfilebazdbg
+#
+#-  testfilebazdyn (dynsym only)
+# objcopy --remove-section=.gnu_debuglink baz testfilebazdyn
+#
+# - testfilebazmdb (dynsym + gnu_debugdata + .debug)
+#   This is how rpmbuild does it:
+# nm -D baz --format=posix --defined-only | awk '{ print $1 }' | sort > dynsyms
+# nm baz.debug --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > funcsyms
+# comm -13 dynsyms funcsyms > keep_symbols
+# objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols=keep_symbols baz.debug mini_debuginfo
+# rm -f mini_debuginfo.xz
+# xz mini_debuginfo
+# objcopy --add-section .gnu_debugdata=mini_debuginfo.xz baz
+# cp baz testfilebazmdb
+#
+# - testfilebazmin (dynsym + gnu_debugdata)
+# objcopy --remove-section=.gnu_debuglink baz testfilebazmin
+#
+#
+# Special auxiliary only, can happen with static binaries.
+# - start.c
+#
+# extern int main (int argc, char ** argv);
+# void _start (void) { for (;;) main (1, 0); }
+#
+# gcc -g -c start.c
+# gcc -static -nostdlib -o bas foo.o bar.o start.o
+#
+# eu-strip --remove-comment -f bas.debug bas
+# nm bas.debug --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > funcsyms
+# objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols=funcsyms bas.debug mini_debuginfo
+# rm -f mini_debuginfo.xz
+# xz mini_debuginfo
+# objcopy --add-section .gnu_debugdata=mini_debuginfo.xz bas
+# rm bas.debug
+# mv bas testfilebasmin
+#
+#
+# Make sure that find_aux_sym doesn't corrupt relocations, avoiding a kernel
+# heuristic that forces ET_EXEC->ET_DYN.  NB: ld.gold doesn't seem to produce
+# the mismatched load addrs between the main file and the mini_debuginfo, so
+# this is forcing ld.bfd.
+#
+# gcc -g -o bax foo.c bar.c -fuse-ld=bfd
+# eu-strip --remove-comment -f bax.debug bax
+# nm -D bax --format=posix --defined-only | awk '{ print $1 }' | sort > dynsyms
+# nm bax.debug --format=posix --defined-only | awk '{ if ($2 == "T" || $2 == "t") print $1 }' | sort > funcsyms
+# comm -13 dynsyms funcsyms > keep_symbols
+# objcopy -S --remove-section .gdb_index --remove-section .comment --keep-symbols=keep_symbols bax.debug mini_debuginfo
+# rm -f mini_debuginfo.xz
+# xz mini_debuginfo
+# objcopy --add-section .gnu_debugdata=mini_debuginfo.xz bax
+# objcopy --remove-section=.gnu_debuglink bax testfilebaxmin
+
+
+testfiles testfilebaztab
+testfiles testfilebazdbg testfilebazdbg.debug
+testfiles testfilebazdyn
+testfiles testfilebazmdb
+testfiles testfilebazmin
+testfiles testfilebasmin
+testfiles testfilebaxmin
+
+tempfiles testfile.dynsym.in testfile.symtab.in testfile.minsym.in
+
+cat > testfile.dynsym.in <<\EOF
+
+Symbol table [ 5] '.dynsym' contains 14 entries:
+ 2 local symbols  String table: [ 6] '.dynstr'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000000238      0 SECTION LOCAL  DEFAULT        1 
+    2: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF _ITM_deregisterTMCloneTable
+    3: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF __libc_start_main@GLIBC_2.2.5 (2)
+    4: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF __gmon_start__
+    5: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF _Jv_RegisterClasses
+    6: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF _ITM_registerTMCloneTable
+    7: 0000000000000000      0 FUNC    WEAK   DEFAULT    UNDEF __cxa_finalize@GLIBC_2.2.5 (2)
+    8: 000000000020103c      0 NOTYPE  GLOBAL DEFAULT       25 _edata
+    9: 0000000000201040      0 NOTYPE  GLOBAL DEFAULT       26 _end
+   10: 0000000000000860    137 FUNC    GLOBAL DEFAULT       13 __libc_csu_init
+   11: 000000000020103c      0 NOTYPE  GLOBAL DEFAULT       26 __bss_start
+   12: 00000000000007f0     35 FUNC    GLOBAL DEFAULT       13 main
+   13: 00000000000008f0      2 FUNC    GLOBAL DEFAULT       13 __libc_csu_fini
+EOF
+
+cat > testfile.symtab.in <<\EOF
+
+Symbol table [34] '.symtab' contains 76 entries:
+ 54 local symbols  String table: [35] '.strtab'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000000238      0 SECTION LOCAL  DEFAULT        1 
+    2: 0000000000000254      0 SECTION LOCAL  DEFAULT        2 
+    3: 0000000000000274      0 SECTION LOCAL  DEFAULT        3 
+    4: 0000000000000298      0 SECTION LOCAL  DEFAULT        4 
+    5: 00000000000002d8      0 SECTION LOCAL  DEFAULT        5 
+    6: 0000000000000428      0 SECTION LOCAL  DEFAULT        6 
+    7: 00000000000004f2      0 SECTION LOCAL  DEFAULT        7 
+    8: 0000000000000510      0 SECTION LOCAL  DEFAULT        8 
+    9: 0000000000000530      0 SECTION LOCAL  DEFAULT        9 
+   10: 0000000000000638      0 SECTION LOCAL  DEFAULT       10 
+   11: 0000000000000680      0 SECTION LOCAL  DEFAULT       11 
+   12: 00000000000006a0      0 SECTION LOCAL  DEFAULT       12 
+   13: 00000000000006e0      0 SECTION LOCAL  DEFAULT       13 
+   14: 00000000000008f4      0 SECTION LOCAL  DEFAULT       14 
+   15: 0000000000000900      0 SECTION LOCAL  DEFAULT       15 
+   16: 0000000000000904      0 SECTION LOCAL  DEFAULT       16 
+   17: 0000000000000948      0 SECTION LOCAL  DEFAULT       17 
+   18: 0000000000200dd0      0 SECTION LOCAL  DEFAULT       18 
+   19: 0000000000200dd8      0 SECTION LOCAL  DEFAULT       19 
+   20: 0000000000200de0      0 SECTION LOCAL  DEFAULT       20 
+   21: 0000000000200de8      0 SECTION LOCAL  DEFAULT       21 
+   22: 0000000000200df0      0 SECTION LOCAL  DEFAULT       22 
+   23: 0000000000200fc0      0 SECTION LOCAL  DEFAULT       23 
+   24: 0000000000201000      0 SECTION LOCAL  DEFAULT       24 
+   25: 0000000000201030      0 SECTION LOCAL  DEFAULT       25 
+   26: 000000000020103c      0 SECTION LOCAL  DEFAULT       26 
+   27: 0000000000000000      0 SECTION LOCAL  DEFAULT       27 
+   28: 0000000000000000      0 SECTION LOCAL  DEFAULT       28 
+   29: 0000000000000000      0 SECTION LOCAL  DEFAULT       29 
+   30: 0000000000000000      0 SECTION LOCAL  DEFAULT       30 
+   31: 0000000000000000      0 SECTION LOCAL  DEFAULT       31 
+   32: 0000000000000000      0 SECTION LOCAL  DEFAULT       32 
+   33: 0000000000000000      0 FILE    LOCAL  DEFAULT      ABS crtstuff.c
+   34: 0000000000200de0      0 OBJECT  LOCAL  DEFAULT       20 __JCR_LIST__
+   35: 0000000000000710      0 FUNC    LOCAL  DEFAULT       13 deregister_tm_clones
+   36: 0000000000000740      0 FUNC    LOCAL  DEFAULT       13 register_tm_clones
+   37: 0000000000000780      0 FUNC    LOCAL  DEFAULT       13 __do_global_dtors_aux
+   38: 000000000020103c      1 OBJECT  LOCAL  DEFAULT       26 completed.6137
+   39: 0000000000200dd8      0 OBJECT  LOCAL  DEFAULT       19 __do_global_dtors_aux_fini_array_entry
+   40: 00000000000007c0      0 FUNC    LOCAL  DEFAULT       13 frame_dummy
+   41: 0000000000200dd0      0 OBJECT  LOCAL  DEFAULT       18 __frame_dummy_init_array_entry
+   42: 0000000000000000      0 FILE    LOCAL  DEFAULT      ABS foo.c
+   43: 0000000000000000      0 FILE    LOCAL  DEFAULT      ABS bar.c
+   44: 0000000000201034      4 OBJECT  LOCAL  DEFAULT       25 b1
+   45: 0000000000000814     20 FUNC    LOCAL  DEFAULT       13 foo
+   46: 0000000000000000      0 FILE    LOCAL  DEFAULT      ABS crtstuff.c
+   47: 0000000000000a58      0 OBJECT  LOCAL  DEFAULT       17 __FRAME_END__
+   48: 0000000000200de0      0 OBJECT  LOCAL  DEFAULT       20 __JCR_END__
+   49: 0000000000000000      0 FILE    LOCAL  DEFAULT      ABS 
+   50: 0000000000200dd8      0 NOTYPE  LOCAL  DEFAULT       18 __init_array_end
+   51: 0000000000200df0      0 OBJECT  LOCAL  DEFAULT       22 _DYNAMIC
+   52: 0000000000200dd0      0 NOTYPE  LOCAL  DEFAULT       18 __init_array_start
+   53: 0000000000201000      0 OBJECT  LOCAL  DEFAULT       24 _GLOBAL_OFFSET_TABLE_
+   54: 00000000000008f0      2 FUNC    GLOBAL DEFAULT       13 __libc_csu_fini
+   55: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF _ITM_deregisterTMCloneTable
+   56: 0000000000201030      0 NOTYPE  WEAK   DEFAULT       25 data_start
+   57: 000000000020103c      0 NOTYPE  GLOBAL DEFAULT       25 _edata
+   58: 0000000000000828     44 FUNC    GLOBAL DEFAULT       13 bar
+   59: 00000000000008f4      0 FUNC    GLOBAL DEFAULT       14 _fini
+   60: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF __libc_start_main@@GLIBC_2.2.5
+   61: 0000000000201030      0 NOTYPE  GLOBAL DEFAULT       25 __data_start
+   62: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF __gmon_start__
+   63: 0000000000200de8      0 OBJECT  GLOBAL HIDDEN        21 __dso_handle
+   64: 0000000000000900      4 OBJECT  GLOBAL DEFAULT       15 _IO_stdin_used
+   65: 0000000000201038      4 OBJECT  GLOBAL DEFAULT       25 b2
+   66: 0000000000000860    137 FUNC    GLOBAL DEFAULT       13 __libc_csu_init
+   67: 0000000000201040      0 NOTYPE  GLOBAL DEFAULT       26 _end
+   68: 00000000000006e0      0 FUNC    GLOBAL DEFAULT       13 _start
+   69: 000000000020103c      0 NOTYPE  GLOBAL DEFAULT       26 __bss_start
+   70: 00000000000007f0     35 FUNC    GLOBAL DEFAULT       13 main
+   71: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF _Jv_RegisterClasses
+   72: 0000000000201040      0 OBJECT  GLOBAL HIDDEN        25 __TMC_END__
+   73: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF _ITM_registerTMCloneTable
+   74: 0000000000000000      0 FUNC    WEAK   DEFAULT    UNDEF __cxa_finalize@@GLIBC_2.2.5
+   75: 0000000000000680      0 FUNC    GLOBAL DEFAULT       11 _init
+EOF
+
+cat > testfile.minsym.in <<\EOF
+
+Symbol table [28] '.symtab' contains 40 entries:
+ 36 local symbols  String table: [29] '.strtab'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000000710      0 FUNC    LOCAL  DEFAULT       13 deregister_tm_clones
+    2: 0000000000000740      0 FUNC    LOCAL  DEFAULT       13 register_tm_clones
+    3: 0000000000000780      0 FUNC    LOCAL  DEFAULT       13 __do_global_dtors_aux
+    4: 0000000000200dd8      0 OBJECT  LOCAL  DEFAULT       19 __do_global_dtors_aux_fini_array_entry
+    5: 00000000000007c0      0 FUNC    LOCAL  DEFAULT       13 frame_dummy
+    6: 0000000000200dd0      0 OBJECT  LOCAL  DEFAULT       18 __frame_dummy_init_array_entry
+    7: 0000000000000814     20 FUNC    LOCAL  DEFAULT       13 foo
+    8: 0000000000200dd8      0 NOTYPE  LOCAL  DEFAULT       18 __init_array_end
+    9: 0000000000200dd0      0 NOTYPE  LOCAL  DEFAULT       18 __init_array_start
+   10: 0000000000000238      0 SECTION LOCAL  DEFAULT        1 
+   11: 0000000000000254      0 SECTION LOCAL  DEFAULT        2 
+   12: 0000000000000274      0 SECTION LOCAL  DEFAULT        3 
+   13: 0000000000000298      0 SECTION LOCAL  DEFAULT        4 
+   14: 00000000000002d8      0 SECTION LOCAL  DEFAULT        5 
+   15: 0000000000000428      0 SECTION LOCAL  DEFAULT        6 
+   16: 00000000000004f2      0 SECTION LOCAL  DEFAULT        7 
+   17: 0000000000000510      0 SECTION LOCAL  DEFAULT        8 
+   18: 0000000000000530      0 SECTION LOCAL  DEFAULT        9 
+   19: 0000000000000638      0 SECTION LOCAL  DEFAULT       10 
+   20: 0000000000000680      0 SECTION LOCAL  DEFAULT       11 
+   21: 00000000000006a0      0 SECTION LOCAL  DEFAULT       12 
+   22: 00000000000006e0      0 SECTION LOCAL  DEFAULT       13 
+   23: 00000000000008f4      0 SECTION LOCAL  DEFAULT       14 
+   24: 0000000000000900      0 SECTION LOCAL  DEFAULT       15 
+   25: 0000000000000904      0 SECTION LOCAL  DEFAULT       16 
+   26: 0000000000000948      0 SECTION LOCAL  DEFAULT       17 
+   27: 0000000000200dd0      0 SECTION LOCAL  DEFAULT       18 
+   28: 0000000000200dd8      0 SECTION LOCAL  DEFAULT       19 
+   29: 0000000000200de0      0 SECTION LOCAL  DEFAULT       20 
+   30: 0000000000200de8      0 SECTION LOCAL  DEFAULT       21 
+   31: 0000000000200df0      0 SECTION LOCAL  DEFAULT       22 
+   32: 0000000000200fc0      0 SECTION LOCAL  DEFAULT       23 
+   33: 0000000000201000      0 SECTION LOCAL  DEFAULT       24 
+   34: 0000000000201030      0 SECTION LOCAL  DEFAULT       25 
+   35: 000000000020103c      0 SECTION LOCAL  DEFAULT       26 
+   36: 0000000000000828     44 FUNC    GLOBAL DEFAULT       13 bar
+   37: 00000000000008f4      0 FUNC    GLOBAL DEFAULT       14 _fini
+   38: 00000000000006e0      0 FUNC    GLOBAL DEFAULT       13 _start
+   39: 0000000000000680      0 FUNC    GLOBAL DEFAULT       11 _init
+EOF
+
+# Display all symbol tables.
+cat testfile.dynsym.in testfile.symtab.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf -s testfilebaztab
+
+cat testfile.dynsym.in testfile.symtab.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf --syms testfilebaztab
+
+# Display just .dynsym
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf \
+    --symbols=.dynsym testfilebaztab
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf \
+    --syms=.dynsym testfilebaztab
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf \
+    --dyn-syms testfilebaztab
+
+# Display just .symtab
+cat testfile.symtab.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf \
+    --symbols=.symtab testfilebaztab
+
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf -s testfilebazdbg
+
+cat testfile.symtab.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf -s testfilebazdbg.debug
+
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf -s testfilebazdyn
+
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf -s testfilebazmdb
+
+cat testfile.minsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf --elf-section -s testfilebazmdb
+
+cat testfile.dynsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf -s testfilebazmin
+
+cat testfile.minsym.in \
+  | testrun_compare ${abs_top_builddir}/src/readelf --elf-section -s testfilebazmin
+
+testrun_compare ${abs_top_builddir}/src/readelf -s testfilebasmin <<EOF
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --elf-section -s testfilebasmin <<\EOF
+
+Symbol table [ 6] '.symtab' contains 9 entries:
+ 6 local symbols  String table: [ 7] '.strtab'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000400168     18 FUNC    LOCAL  DEFAULT        2 foo
+    2: 0000000000400120      0 SECTION LOCAL  DEFAULT        1 
+    3: 0000000000400144      0 SECTION LOCAL  DEFAULT        2 
+    4: 00000000004001c0      0 SECTION LOCAL  DEFAULT        3 
+    5: 0000000000600258      0 SECTION LOCAL  DEFAULT        4 
+    6: 00000000004001a8     21 FUNC    GLOBAL DEFAULT        2 _start
+    7: 0000000000400144     33 FUNC    GLOBAL DEFAULT        2 main
+    8: 000000000040017a     44 FUNC    GLOBAL DEFAULT        2 bar
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -s testfilebaxmin <<EOF
+
+Symbol table [ 5] '.dynsym' contains 3 entries:
+ 1 local symbol  String table: [ 6] '.dynstr'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000000000      0 FUNC    GLOBAL DEFAULT    UNDEF __libc_start_main@GLIBC_2.2.5 (2)
+    2: 0000000000000000      0 NOTYPE  WEAK   DEFAULT    UNDEF __gmon_start__
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf --elf-section -s testfilebaxmin <<\EOF
+
+Symbol table [27] '.symtab' contains 42 entries:
+ 35 local symbols  String table: [28] '.strtab'
+  Num:            Value   Size Type    Bind   Vis          Ndx Name
+    0: 0000000000000000      0 NOTYPE  LOCAL  DEFAULT    UNDEF 
+    1: 0000000000400430      0 FUNC    LOCAL  DEFAULT       13 deregister_tm_clones
+    2: 0000000000400460      0 FUNC    LOCAL  DEFAULT       13 register_tm_clones
+    3: 00000000004004a0      0 FUNC    LOCAL  DEFAULT       13 __do_global_dtors_aux
+    4: 0000000000600e18      0 OBJECT  LOCAL  DEFAULT       19 __do_global_dtors_aux_fini_array_entry
+    5: 00000000004004c0      0 FUNC    LOCAL  DEFAULT       13 frame_dummy
+    6: 0000000000600e10      0 OBJECT  LOCAL  DEFAULT       18 __frame_dummy_init_array_entry
+    7: 00000000004004f0     20 FUNC    LOCAL  DEFAULT       13 foo
+    8: 0000000000600e18      0 NOTYPE  LOCAL  DEFAULT       18 __init_array_end
+    9: 0000000000600e10      0 NOTYPE  LOCAL  DEFAULT       18 __init_array_start
+   10: 0000000000400238      0 SECTION LOCAL  DEFAULT        1 
+   11: 0000000000400254      0 SECTION LOCAL  DEFAULT        2 
+   12: 0000000000400274      0 SECTION LOCAL  DEFAULT        3 
+   13: 0000000000400298      0 SECTION LOCAL  DEFAULT        4 
+   14: 00000000004002b8      0 SECTION LOCAL  DEFAULT        5 
+   15: 0000000000400300      0 SECTION LOCAL  DEFAULT        6 
+   16: 0000000000400338      0 SECTION LOCAL  DEFAULT        7 
+   17: 0000000000400340      0 SECTION LOCAL  DEFAULT        8 
+   18: 0000000000400360      0 SECTION LOCAL  DEFAULT        9 
+   19: 0000000000400378      0 SECTION LOCAL  DEFAULT       10 
+   20: 00000000004003a8      0 SECTION LOCAL  DEFAULT       11 
+   21: 00000000004003d0      0 SECTION LOCAL  DEFAULT       12 
+   22: 0000000000400400      0 SECTION LOCAL  DEFAULT       13 
+   23: 00000000004005c4      0 SECTION LOCAL  DEFAULT       14 
+   24: 00000000004005d0      0 SECTION LOCAL  DEFAULT       15 
+   25: 00000000004005e0      0 SECTION LOCAL  DEFAULT       16 
+   26: 0000000000400628      0 SECTION LOCAL  DEFAULT       17 
+   27: 0000000000600e10      0 SECTION LOCAL  DEFAULT       18 
+   28: 0000000000600e18      0 SECTION LOCAL  DEFAULT       19 
+   29: 0000000000600e20      0 SECTION LOCAL  DEFAULT       20 
+   30: 0000000000600e28      0 SECTION LOCAL  DEFAULT       21 
+   31: 0000000000600ff8      0 SECTION LOCAL  DEFAULT       22 
+   32: 0000000000601000      0 SECTION LOCAL  DEFAULT       23 
+   33: 0000000000601028      0 SECTION LOCAL  DEFAULT       24 
+   34: 0000000000601034      0 SECTION LOCAL  DEFAULT       25 
+   35: 00000000004005c0      2 FUNC    GLOBAL DEFAULT       13 __libc_csu_fini
+   36: 0000000000400504     40 FUNC    GLOBAL DEFAULT       13 bar
+   37: 00000000004005c4      0 FUNC    GLOBAL DEFAULT       14 _fini
+   38: 0000000000400550    101 FUNC    GLOBAL DEFAULT       13 __libc_csu_init
+   39: 0000000000400400      0 FUNC    GLOBAL DEFAULT       13 _start
+   40: 000000000040052c     35 FUNC    GLOBAL DEFAULT       13 main
+   41: 00000000004003a8      0 FUNC    GLOBAL DEFAULT       11 _init
+EOF
+
+testrun ${abs_top_builddir}/src/readelf --elf-section -sW testfilebaxmin 2>&1 \
+  | grep "WARNING: cannot find section: 'W'" >/dev/null || exit 2
+
+exit 0
diff --git a/tests/run-readelf-self.sh b/tests/run-readelf-self.sh
new file mode 100755
index 0000000..de528d5
--- /dev/null
+++ b/tests/run-readelf-self.sh
@@ -0,0 +1,26 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if test -n "$ELFUTILS_MEMORY_SANITIZER"; then
+  echo "binaries linked with memory sanitizer are too big"
+  exit 77
+fi
+
+# Just makes sure readelf doesn't crash
+testrun_on_self_quiet ${abs_top_builddir}/src/readelf -N -a -w
diff --git a/tests/run-readelf-str.sh b/tests/run-readelf-str.sh
new file mode 100755
index 0000000..8b894e8
--- /dev/null
+++ b/tests/run-readelf-str.sh
@@ -0,0 +1,211 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See tests/testfile-dwarf-45.source
+testfiles testfile-splitdwarf-4 testfile-splitdwarf-5
+testfiles testfile-hello4.dwo testfile-hello5.dwo
+testfiles testfile-world4.dwo testfile-world5.dwo
+
+# DWARF4 GNU DebugFission No real table header.
+# We don't really need the skeleton, but we don't want any Warnings.
+testrun_compare ${abs_top_builddir}/src/readelf --dwarf-skeleton testfile-splitdwarf-4 --debug-dump=str testfile-hello4.dwo testfile-world4.dwo<<\EOF
+
+testfile-hello4.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x335:
+Table at offset 0 
+ Offsets start at 0x0:
+ [ 0] [       0]  "long long int"
+ [ 1] [       e]  "frob"
+ [ 2] [      13]  "long unsigned int"
+ [ 3] [      25]  "/home/mark/src/elfutils/tests"
+ [ 4] [      43]  "wchar_t"
+ [ 5] [      4b]  "main"
+ [ 6] [      50]  "long int"
+ [ 7] [      59]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 8] [      e9]  "long double"
+ [ 9] [      f5]  "hello.c"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x35d:
+ Offset  String
+ [   0]  "long long int"
+ [   e]  "frob"
+ [  13]  "long unsigned int"
+ [  25]  "/home/mark/src/elfutils/tests"
+ [  43]  "wchar_t"
+ [  4b]  "main"
+ [  50]  "long int"
+ [  59]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [  e9]  "long double"
+ [  f5]  "hello.c"
+
+testfile-world4.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x2e7:
+Table at offset 0 
+ Offsets start at 0x0:
+ [ 0] [       0]  "long long unsigned int"
+ [ 1] [      17]  "/home/mark/src/elfutils/tests"
+ [ 2] [      35]  "long long int"
+ [ 3] [      43]  "signed char"
+ [ 4] [      4f]  "long int"
+ [ 5] [      58]  "world.c"
+ [ 6] [      60]  "unsigned int"
+ [ 7] [      6d]  "long unsigned int"
+ [ 8] [      7f]  "short unsigned int"
+ [ 9] [      92]  "frob"
+ [10] [      97]  "calc"
+ [11] [      9c]  "unsigned char"
+ [12] [      aa]  "short int"
+ [13] [      b4]  "exit"
+ [14] [      b9]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [15] [     149]  "char"
+ [16] [     14e]  "word"
+ [17] [     153]  "argv"
+ [18] [     158]  "argc"
+ [19] [     15d]  "main"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x337:
+ Offset  String
+ [   0]  "long long unsigned int"
+ [  17]  "/home/mark/src/elfutils/tests"
+ [  35]  "long long int"
+ [  43]  "signed char"
+ [  4f]  "long int"
+ [  58]  "world.c"
+ [  60]  "unsigned int"
+ [  6d]  "long unsigned int"
+ [  7f]  "short unsigned int"
+ [  92]  "frob"
+ [  97]  "calc"
+ [  9c]  "unsigned char"
+ [  aa]  "short int"
+ [  b4]  "exit"
+ [  b9]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 149]  "char"
+ [ 14e]  "word"
+ [ 153]  "argv"
+ [ 158]  "argc"
+ [ 15d]  "main"
+EOF
+
+# DWARF5 Real table header.
+# We don't really need the skeleton, but we don't want any Warnings.
+testrun_compare ${abs_top_builddir}/src/readelf --dwarf-skeleton testfile-splitdwarf-5 --debug-dump=str testfile-hello5.dwo testfile-world5.dwo<<\EOF
+
+testfile-hello5.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x353:
+Table at offset 0 
+
+ Length:              44
+ Offset size:          4
+ DWARF version:        5
+ Padding:              0
+
+ Offsets start at 0x8:
+ [ 0] [       0]  "long long int"
+ [ 1] [       e]  "frob"
+ [ 2] [      13]  "long unsigned int"
+ [ 3] [      25]  "/home/mark/src/elfutils/tests"
+ [ 4] [      43]  "wchar_t"
+ [ 5] [      4b]  "main"
+ [ 6] [      50]  "long int"
+ [ 7] [      59]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 8] [      e9]  "long double"
+ [ 9] [      f5]  "hello.c"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x383:
+ Offset  String
+ [   0]  "long long int"
+ [   e]  "frob"
+ [  13]  "long unsigned int"
+ [  25]  "/home/mark/src/elfutils/tests"
+ [  43]  "wchar_t"
+ [  4b]  "main"
+ [  50]  "long int"
+ [  59]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [  e9]  "long double"
+ [  f5]  "hello.c"
+
+testfile-world5.dwo:
+
+
+DWARF section [ 5] '.debug_str_offsets.dwo' at offset 0x313:
+Table at offset 0 
+
+ Length:              84
+ Offset size:          4
+ DWARF version:        5
+ Padding:              0
+
+ Offsets start at 0x8:
+ [ 0] [       0]  "long long unsigned int"
+ [ 1] [      17]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [ 2] [      a7]  "/home/mark/src/elfutils/tests"
+ [ 3] [      c5]  "long long int"
+ [ 4] [      d3]  "signed char"
+ [ 5] [      df]  "long int"
+ [ 6] [      e8]  "world.c"
+ [ 7] [      f0]  "unsigned int"
+ [ 8] [      fd]  "long unsigned int"
+ [ 9] [     10f]  "short unsigned int"
+ [10] [     122]  "frob"
+ [11] [     127]  "calc"
+ [12] [     12c]  "unsigned char"
+ [13] [     13a]  "short int"
+ [14] [     144]  "exit"
+ [15] [     149]  "char"
+ [16] [     14e]  "word"
+ [17] [     153]  "argv"
+ [18] [     158]  "argc"
+ [19] [     15d]  "main"
+
+
+DWARF section [ 6] '.debug_str.dwo' at offset 0x36b:
+ Offset  String
+ [   0]  "long long unsigned int"
+ [  17]  "GNU C17 9.0.0 20180515 (experimental) -mtune=generic -march=x86-64 -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2"
+ [  a7]  "/home/mark/src/elfutils/tests"
+ [  c5]  "long long int"
+ [  d3]  "signed char"
+ [  df]  "long int"
+ [  e8]  "world.c"
+ [  f0]  "unsigned int"
+ [  fd]  "long unsigned int"
+ [ 10f]  "short unsigned int"
+ [ 122]  "frob"
+ [ 127]  "calc"
+ [ 12c]  "unsigned char"
+ [ 13a]  "short int"
+ [ 144]  "exit"
+ [ 149]  "char"
+ [ 14e]  "word"
+ [ 153]  "argv"
+ [ 158]  "argc"
+ [ 15d]  "main"
+EOF
+
+exit 0
diff --git a/tests/run-readelf-test1.sh b/tests/run-readelf-test1.sh
new file mode 100755
index 0000000..4725049
--- /dev/null
+++ b/tests/run-readelf-test1.sh
@@ -0,0 +1,45 @@
+#! /bin/sh
+# Copyright (C) 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+original=${original:-testfile11}
+stripped=${stripped:-testfile7}
+debugout=${debugfile:+-f testfile.debug.temp -F $debugfile}
+
+testfiles testfile3
+
+tempfiles testfile.temp
+
+testrun ${abs_top_builddir}/src/readelf -r testfile3 > testfile.temp
+
+diff -u - testfile.temp <<EOF
+
+Relocation section [ 8] '.rel.got' for section [19] '.got' at offset 0x294 contains 1 entry:
+  Offset      Type                 Value       Name
+  0x08049544  386_GLOB_DAT         0000000000  __gmon_start__
+
+Relocation section [ 9] '.rel.plt' for section [11] '.plt' at offset 0x29c contains 4 entries:
+  Offset      Type                 Value       Name
+  0x08049534  386_JMP_SLOT         0x080482e4  __register_frame_info
+  0x08049538  386_JMP_SLOT         0x080482f4  __deregister_frame_info
+  0x0804953c  386_JMP_SLOT         0x08048304  __libc_start_main
+  0x08049540  386_JMP_SLOT         0x08048314  __cxa_finalize
+EOF
+
+exit 0
diff --git a/tests/run-readelf-test2.sh b/tests/run-readelf-test2.sh
new file mode 100755
index 0000000..e03ee8d
--- /dev/null
+++ b/tests/run-readelf-test2.sh
@@ -0,0 +1,35 @@
+#! /bin/sh
+# Copyright (C) 2007 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile28
+
+testrun_compare ${abs_top_builddir}/src/readelf -x .strtab testfile28 <<\EOF
+
+Hex dump of section [6] '.strtab', 1 bytes at offset 0x290:
+  0x00000000 00                                  .
+EOF
+
+testrun_compare ${abs_top_builddir}/src/readelf -x 6 testfile28 <<\EOF
+
+Hex dump of section [6] '.strtab', 1 bytes at offset 0x290:
+  0x00000000 00                                  .
+EOF
+
+
+exit 0
diff --git a/tests/run-readelf-test3.sh b/tests/run-readelf-test3.sh
new file mode 100755
index 0000000..cc0a191
--- /dev/null
+++ b/tests/run-readelf-test3.sh
@@ -0,0 +1,31 @@
+#! /bin/sh
+# Copyright (C) 2007 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile40.debug
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile40.debug <<\EOF
+
+Note section [ 6] '.note' of 60 bytes at offset 0x120:
+  Owner          Data size  Type
+  GNU                   20  GNU_BUILD_ID
+    Build ID: 34072edcd87ef6728f4b4a7956167b2fcfc3f1d3
+  Linux                  4  <unknown>: 0
+EOF
+
+exit 0
diff --git a/tests/run-readelf-test4.sh b/tests/run-readelf-test4.sh
new file mode 100755
index 0000000..ca0526a
--- /dev/null
+++ b/tests/run-readelf-test4.sh
@@ -0,0 +1,33 @@
+#! /bin/sh
+# Copyright (C) 2007 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile19.index
+
+testrun_compare ${abs_top_builddir}/src/readelf -c testfile19.index <<\EOF
+
+Index of archive 'testfile19.index' has 4 entries:
+Archive member 'u1.o' contains:
+	a
+Archive member 'u2.o' contains:
+	aa
+Archive member 'u3.o' contains:
+	a
+EOF
+
+exit 0
diff --git a/tests/run-readelf-twofiles.sh b/tests/run-readelf-twofiles.sh
new file mode 100755
index 0000000..fc5f3e7
--- /dev/null
+++ b/tests/run-readelf-twofiles.sh
@@ -0,0 +1,65 @@
+#! /bin/sh
+# Copyright (C) 2011, 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile14
+
+testrun >/dev/null ${abs_top_builddir}/src/readelf -w testfile14 testfile14
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=loc testfile14 testfile14 << EOF
+
+testfile14:
+
+
+DWARF section [33] '.debug_loc' at offset 0xca9:
+
+ CU [     b] base: 0x0000000000400468 <caller>
+ [     0] range 34, 35
+          0x000000000040049c <main>..
+          0x000000000040049c <main>
+           [ 0] breg7 -8
+          range 35, 46
+          0x000000000040049d <main+0x1>..
+          0x00000000004004ad <main+0x11>
+           [ 0] breg7 0
+          range 46, 47
+          0x00000000004004ae <main+0x12>..
+          0x00000000004004ae <main+0x12>
+           [ 0] breg7 -8
+
+testfile14:
+
+
+DWARF section [33] '.debug_loc' at offset 0xca9:
+
+ CU [     b] base: 0x0000000000400468 <caller>
+ [     0] range 34, 35
+          0x000000000040049c <main>..
+          0x000000000040049c <main>
+           [ 0] breg7 -8
+          range 35, 46
+          0x000000000040049d <main+0x1>..
+          0x00000000004004ad <main+0x11>
+           [ 0] breg7 0
+          range 46, 47
+          0x00000000004004ae <main+0x12>..
+          0x00000000004004ae <main+0x12>
+           [ 0] breg7 -8
+EOF
+
+exit 0
diff --git a/tests/run-readelf-types.sh b/tests/run-readelf-types.sh
new file mode 100755
index 0000000..4f31269
--- /dev/null
+++ b/tests/run-readelf-types.sh
@@ -0,0 +1,122 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Make sure --debug-dump=info implies .debug_types, even when implicit.
+# See run-typeiter.sh
+testfiles testfile-debug-types
+
+testrun_compare ${abs_top_builddir}/src/readelf --debug-dump=str --debug-dump=info testfile-debug-types<<\EOF
+
+DWARF section [28] '.debug_info' at offset 0x1089:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 8
+           producer             (strp) "GNU C++ 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic -march=x86-64 -g -fdebug-types-section"
+           language             (data1) C_plus_plus (4)
+           comp_dir             (strp) "/home/mark/src/elfutils/tests"
+           low_pc               (addr) 0x00000000004005b0 <main>
+           high_pc              (data8) 11 (0x00000000004005bb)
+           stmt_list            (sec_offset) 0
+ [    29]    subprogram           abbrev: 9
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) <stdin> (1)
+             decl_line            (data1) 1
+             type                 (ref4) [    46]
+             low_pc               (addr) 0x00000000004005b0 <main>
+             high_pc              (data8) 11 (0x00000000004005bb)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+ [    46]    base_type            abbrev: 10
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [    4d]    variable             abbrev: 11
+             name                 (string) "a"
+             decl_file            (data1) <stdin> (1)
+             decl_line            (data1) 1
+             type                 (ref_sig8) {18763953736e2de0}
+             external             (flag_present) yes
+             location             (exprloc) 
+              [ 0] addr 0x601030 <a>
+ [    64]    variable             abbrev: 11
+             name                 (string) "b"
+             decl_file            (data1) <stdin> (1)
+             decl_line            (data1) 1
+             type                 (ref_sig8) {7cf9bbf793fcaf13}
+             external             (flag_present) yes
+             location             (exprloc) 
+              [ 0] addr 0x601031 <b>
+
+DWARF section [31] '.debug_str' at offset 0x11dd:
+ Offset  String
+ [   0]  "/home/mark/src/elfutils/tests"
+ [  1e]  "GNU C++ 4.8.2 20140120 (Red Hat 4.8.2-16) -mtune=generic -march=x86-64 -g -fdebug-types-section"
+ [  7e]  "main"
+
+DWARF section [32] '.debug_types' at offset 0x1260:
+ [Offset]
+ Type unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ Type signature: 0x7cf9bbf793fcaf13, Type offset: 0x38 [38]
+ [    17]  type_unit            abbrev: 1
+           language             (data1) C_plus_plus (4)
+           GNU_odr_signature    (data8) 4783233826607187165
+           stmt_list            (sec_offset) 0
+ [    25]    structure_type       abbrev: 2
+             name                 (string) "A"
+             signature            (ref_sig8) {18763953736e2de0}
+             declaration          (flag_present) yes
+             sibling              (ref4) [    38]
+ [    34]      structure_type       abbrev: 3
+               name                 (string) "B"
+               declaration          (flag_present) yes
+ [    38]    structure_type       abbrev: 4
+             name                 (string) "B"
+             byte_size            (data1) 1
+             decl_file            (data1) <stdin> (1)
+             decl_line            (data1) 1
+             specification        (ref4) [    34]
+ Type unit at offset 67:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ Type signature: 0x18763953736e2de0, Type offset: 0x25 [68]
+ [    5a]  type_unit            abbrev: 1
+           language             (data1) C_plus_plus (4)
+           GNU_odr_signature    (data8) 16005269134005989797
+           stmt_list            (sec_offset) 0
+ [    68]    structure_type       abbrev: 5
+             name                 (string) "A"
+             byte_size            (data1) 1
+             decl_file            (data1) <stdin> (1)
+             decl_line            (data1) 1
+ [    6e]      structure_type       abbrev: 6
+               name                 (string) "B"
+               declaration          (flag_present) yes
+               signature            (ref_sig8) {7cf9bbf793fcaf13}
+ [    79]      member               abbrev: 7
+               name                 (string) "x"
+               decl_file            (data1) <stdin> (1)
+               decl_line            (data1) 1
+               type                 (ref4) [    6e]
+               data_member_location (data1) 0
+EOF
+
+exit 0
diff --git a/tests/run-readelf-variant.sh b/tests/run-readelf-variant.sh
new file mode 100755
index 0000000..dcc0d5e
--- /dev/null
+++ b/tests/run-readelf-variant.sh
@@ -0,0 +1,89 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Tests exprloc for an Ada record variants byte_size.
+
+# = pck.ads
+#
+# with System;
+#
+# package Pck is
+#
+#    type One_To_Five is range 1 .. 5;
+#
+#    type Rec (Discr : One_To_Five) is
+#    record
+#       case Discr is
+#          when 1 => Field1 : Integer;
+#          when 4 => null;
+#          when 3 => Field3 : Boolean;
+#          when 5 => null;
+#          when others => null;
+#       end case;
+#    end record;
+#
+#    procedure Do_Nothing (A : System.Address);
+#
+# end Pck;
+
+# = pck.adb
+#
+# package body Pck is
+#
+#    procedure Do_Nothing (A : System.Address) is
+#    begin
+#       null;
+#    end Do_Nothing;
+#
+# end Pck;
+
+# = foo.adb
+#
+# with Pck; use Pck;
+#
+# procedure Foo is
+#
+#    R : Rec (1);
+#
+# begin
+#    Do_Nothing (R'Address);
+# end Foo;
+
+# gnatmake -g -fgnat-encodings=minimal foo.adb -cargs
+
+testfiles testfile-ada-variant
+
+tempfiles testfile.temp testfile2.temp
+
+testrun ${abs_top_builddir}/src/readelf --debug-dump=info \
+        testfile-ada-variant > testfile.temp
+
+grep -A6 byte_size testfile.temp | grep -A6 exprloc > testfile2.temp
+
+diff -u testfile2.temp - <<EOF
+             byte_size            (exprloc) 
+              [ 0] push_object_address
+              [ 1] deref_size 1
+              [ 3] call4 [    95]
+              [ 8] plus_uconst 7
+              [10] const1s -4
+              [12] and
+EOF
+
+exit 0
diff --git a/tests/run-readelf-vmcoreinfo.sh b/tests/run-readelf-vmcoreinfo.sh
new file mode 100755
index 0000000..b1732fc
--- /dev/null
+++ b/tests/run-readelf-vmcoreinfo.sh
@@ -0,0 +1,114 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile62
+
+testrun_compare ${abs_top_builddir}/src/readelf -n testfile62 <<\EOF
+
+Note segment of 2104 bytes at offset 0x158:
+  Owner          Data size  Type
+  CORE                 336  PRSTATUS
+    info.si_signo: 0, info.si_code: 0, info.si_errno: 0, cursig: 0
+    sigpend: <>
+    sighold: <>
+    pid: 3519, ppid: 0, pgrp: 0, sid: 0
+    utime: 0.000000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
+    orig_rax: -1, fpvalid: 0
+    r15:                     662  r14:                       4
+    r13:             -2119649152  r12:                       0
+    rbp:      0xffff880067e39e48  rbx:                      99
+    r11:        -131940469531936  r10:             -2124150080
+    r9:         -131940469531936  r8:                        0
+    rax:                      16  rcx:                    7813
+    rdx:                       0  rsi:                       0
+    rdi:                      99  rip:      0xffffffff812ba86f
+    rflags:   0x0000000000010096  rsp:      0xffff880067e39e48
+    fs.base:   0x00007f95a7b09720  gs.base:   0x0000000000000000
+    cs: 0x0010  ss: 0x0018  ds: 0x0000  es: 0x0000  fs: 0x0000  gs: 0x0000
+  CORE                 336  PRSTATUS
+    info.si_signo: 0, info.si_code: 0, info.si_errno: 0, cursig: 0
+    sigpend: <>
+    sighold: <>
+    pid: 0, ppid: 0, pgrp: 0, sid: 0
+    utime: 0.000000, stime: 0.000000, cutime: 0.000000, cstime: 0.000000
+    orig_rax: -1, fpvalid: 0
+    r15:                       0  r14:                       0
+    r13:     1348173392195389970  r12:                       1
+    rbp:      0xffff88007a829e48  rbx:                      16
+    r11:        -131940468065880  r10:            435505529489
+    r9:                   158960  r8:                        0
+    rax:                      16  rcx:                       1
+    rdx:                       0  rsi:                       3
+    rdi:        -131939339960320  rip:      0xffffffff810118bb
+    rflags:   0x0000000000000046  rsp:      0xffff88007a829e38
+    fs.base:   0x0000000000000000  gs.base:   0x0000000000000000
+    cs: 0x0010  ss: 0x0018  ds: 0x0000  es: 0x0000  fs: 0x0000  gs: 0x0000
+  VMCOREINFO          1366  <unknown>: 0
+    OSRELEASE=2.6.35.11-83.fc14.x86_64
+    PAGESIZE=4096
+    SYMBOL(init_uts_ns)=ffffffff81a4c5b0
+    SYMBOL(node_online_map)=ffffffff81b840b0
+    SYMBOL(swapper_pg_dir)=ffffffff81a42000
+    SYMBOL(_stext)=ffffffff81000190
+    SYMBOL(vmlist)=ffffffff81db07e8
+    SYMBOL(mem_section)=ffffffff81dbab00
+    LENGTH(mem_section)=4096
+    SIZE(mem_section)=32
+    OFFSET(mem_section.section_mem_map)=0
+    SIZE(page)=56
+    SIZE(pglist_data)=81664
+    SIZE(zone)=1792
+    SIZE(free_area)=88
+    SIZE(list_head)=16
+    SIZE(nodemask_t)=64
+    OFFSET(page.flags)=0
+    OFFSET(page._count)=8
+    OFFSET(page.mapping)=24
+    OFFSET(page.lru)=40
+    OFFSET(pglist_data.node_zones)=0
+    OFFSET(pglist_data.nr_zones)=81472
+    OFFSET(pglist_data.node_start_pfn)=81496
+    OFFSET(pglist_data.node_spanned_pages)=81512
+    OFFSET(pglist_data.node_id)=81520
+    OFFSET(zone.free_area)=112
+    OFFSET(zone.vm_stat)=1328
+    OFFSET(zone.spanned_pages)=1704
+    OFFSET(free_area.free_list)=0
+    OFFSET(list_head.next)=0
+    OFFSET(list_head.prev)=8
+    OFFSET(vm_struct.addr)=8
+    LENGTH(zone.free_area)=11
+    SYMBOL(log_buf)=ffffffff81a532a8
+    SYMBOL(log_end)=ffffffff81d0bc50
+    SYMBOL(log_buf_len)=ffffffff81a532a4
+    SYMBOL(logged_chars)=ffffffff81d0bd70
+    LENGTH(free_area.free_list)=5
+    NUMBER(NR_FREE_PAGES)=0
+    NUMBER(PG_lru)=5
+    NUMBER(PG_private)=11
+    NUMBER(PG_swapcache)=16
+    SYMBOL(phys_base)=ffffffff81a4a010
+    SYMBOL(init_level4_pgt)=ffffffff81a42000
+    SYMBOL(node_data)=ffffffff81b80df0
+    LENGTH(node_data)=512
+    CRASHTIME=1348173392
+
+EOF
+
+exit 0
diff --git a/tests/run-readelf-z.sh b/tests/run-readelf-z.sh
new file mode 100755
index 0000000..6dbd2f1
--- /dev/null
+++ b/tests/run-readelf-z.sh
@@ -0,0 +1,202 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-elfgetchdr.sh for testfiles.
+
+testfiles testfile-zgnu64
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgnu64 <<\EOF
+There are 9 section headers, starting at offset 0x3e0:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+     [Compression  Size     Al]
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .text                PROGBITS     0000000000400078 00000078 0000002a  0 AX     0   0  1
+[ 2] .zdebug_aranges      PROGBITS     0000000000000000 00000260 00000032  0        0   0 16
+     [GNU ZLIB     00000060   ]
+[ 3] .zdebug_info         PROGBITS     0000000000000000 00000292 0000006f  0        0   0  1
+     [GNU ZLIB     000000aa   ]
+[ 4] .debug_abbrev        PROGBITS     0000000000000000 00000301 00000028  0        0   0  1
+[ 5] .zdebug_line         PROGBITS     0000000000000000 00000329 0000005b  0        0   0  1
+     [GNU ZLIB     0000008d   ]
+[ 6] .shstrtab            STRTAB       0000000000000000 00000384 00000059  0        0   0  1
+[ 7] .symtab              SYMTAB       0000000000000000 000000a8 00000168 24        8   8  8
+[ 8] .strtab              STRTAB       0000000000000000 00000210 0000004b  0        0   0  1
+
+EOF
+
+testfiles testfile-zgnu64be
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgnu64be <<\EOF
+There are 10 section headers, starting at offset 0x438:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+     [Compression  Size     Al]
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .text                PROGBITS     0000000010000078 00000078 00000074  0 AX     0   0  8
+[ 2] .eh_frame            PROGBITS     00000000100000ec 000000ec 00000000  0 A      0   0  4
+[ 3] .zdebug_aranges      PROGBITS     0000000000000000 000002c0 00000034  0        0   0 16
+     [GNU ZLIB     00000060   ]
+[ 4] .zdebug_info         PROGBITS     0000000000000000 000002f4 00000059  0        0   0  1
+     [GNU ZLIB     0000007e   ]
+[ 5] .debug_abbrev        PROGBITS     0000000000000000 0000034d 00000028  0        0   0  1
+[ 6] .zdebug_line         PROGBITS     0000000000000000 00000375 0000005b  0        0   0  1
+     [GNU ZLIB     0000008d   ]
+[ 7] .shstrtab            STRTAB       0000000000000000 000003d0 00000063  0        0   0  1
+[ 8] .symtab              SYMTAB       0000000000000000 000000f0 00000180 24        9   9  8
+[ 9] .strtab              STRTAB       0000000000000000 00000270 00000044  0        0   0  1
+
+EOF
+
+testfiles testfile-zgabi64
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgabi64 <<\EOF
+There are 9 section headers, starting at offset 0x400:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+     [Compression  Size     Al]
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .text                PROGBITS     0000000000400078 00000078 0000002a  0 AX     0   0  1
+[ 2] .debug_aranges       PROGBITS     0000000000000000 00000260 0000003e  0 C      0   0 16
+     [ELF ZLIB (1) 00000060 16]
+[ 3] .debug_info          PROGBITS     0000000000000000 0000029e 0000007b  0 C      0   0  1
+     [ELF ZLIB (1) 000000aa  1]
+[ 4] .debug_abbrev        PROGBITS     0000000000000000 00000319 00000028  0        0   0  1
+[ 5] .debug_line          PROGBITS     0000000000000000 00000341 00000067  0 C      0   0  1
+     [ELF ZLIB (1) 0000008d  1]
+[ 6] .shstrtab            STRTAB       0000000000000000 000003a8 00000056  0        0   0  1
+[ 7] .symtab              SYMTAB       0000000000000000 000000a8 00000168 24        8   8  8
+[ 8] .strtab              STRTAB       0000000000000000 00000210 0000004b  0        0   0  1
+
+EOF
+
+testfiles testfile-zgabi64be
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgabi64be <<\EOF
+There are 10 section headers, starting at offset 0x458:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+     [Compression  Size     Al]
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .text                PROGBITS     0000000010000078 00000078 00000074  0 AX     0   0  8
+[ 2] .eh_frame            PROGBITS     00000000100000ec 000000ec 00000000  0 A      0   0  4
+[ 3] .debug_aranges       PROGBITS     0000000000000000 000002c0 00000040  0 C      0   0 16
+     [ELF ZLIB (1) 00000060 16]
+[ 4] .debug_info          PROGBITS     0000000000000000 00000300 00000065  0 C      0   0  1
+     [ELF ZLIB (1) 0000007e  1]
+[ 5] .debug_abbrev        PROGBITS     0000000000000000 00000365 00000028  0        0   0  1
+[ 6] .debug_line          PROGBITS     0000000000000000 0000038d 00000067  0 C      0   0  1
+     [ELF ZLIB (1) 0000008d  1]
+[ 7] .shstrtab            STRTAB       0000000000000000 000003f4 00000060  0        0   0  1
+[ 8] .symtab              SYMTAB       0000000000000000 000000f0 00000180 24        9   9  8
+[ 9] .strtab              STRTAB       0000000000000000 00000270 00000044  0        0   0  1
+
+EOF
+
+testfiles testfile-zgnu32
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgnu32 <<\EOF
+There are 9 section headers, starting at offset 0x33c:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+     [Compression  Size   Al]
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .text                PROGBITS     08048054 000054 00002a  0 AX     0   0  1
+[ 2] .zdebug_aranges      PROGBITS     00000000 0001c0 000031  0        0   0  8
+     [GNU ZLIB     000040   ]
+[ 3] .zdebug_info         PROGBITS     00000000 0001f1 00006f  0        0   0  1
+     [GNU ZLIB     00009a   ]
+[ 4] .debug_abbrev        PROGBITS     00000000 000260 000028  0        0   0  1
+[ 5] .zdebug_line         PROGBITS     00000000 000288 00005a  0        0   0  1
+     [GNU ZLIB     000085   ]
+[ 6] .shstrtab            STRTAB       00000000 0002e2 000059  0        0   0  1
+[ 7] .symtab              SYMTAB       00000000 000080 0000f0 16        8   8  4
+[ 8] .strtab              STRTAB       00000000 000170 00004b  0        0   0  1
+
+EOF
+
+testfiles testfile-zgnu32be
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgnu32be <<\EOF
+There are 10 section headers, starting at offset 0x390:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+     [Compression  Size   Al]
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .text                PROGBITS     01800054 000054 000074  0 AX     0   0  1
+[ 2] .eh_frame            PROGBITS     018000c8 0000c8 000000  0 A      0   0  4
+[ 3] .zdebug_aranges      PROGBITS     00000000 000220 000033  0        0   0  8
+     [GNU ZLIB     000040   ]
+[ 4] .zdebug_info         PROGBITS     00000000 000253 000058  0        0   0  1
+     [GNU ZLIB     00006e   ]
+[ 5] .debug_abbrev        PROGBITS     00000000 0002ab 000028  0        0   0  1
+[ 6] .zdebug_line         PROGBITS     00000000 0002d3 000059  0        0   0  1
+     [GNU ZLIB     000085   ]
+[ 7] .shstrtab            STRTAB       00000000 00032c 000063  0        0   0  1
+[ 8] .symtab              SYMTAB       00000000 0000c8 000110 16        9   9  4
+[ 9] .strtab              STRTAB       00000000 0001d8 000045  0        0   0  1
+
+EOF
+
+testfiles testfile-zgabi32
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgabi32 <<\EOF
+There are 9 section headers, starting at offset 0x338:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+     [Compression  Size   Al]
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .text                PROGBITS     08048054 000054 00002a  0 AX     0   0  1
+[ 2] .debug_aranges       PROGBITS     00000000 0001c0 000031  0 C      0   0  8
+     [ELF ZLIB (1) 000040  8]
+[ 3] .debug_info          PROGBITS     00000000 0001f1 00006f  0 C      0   0  1
+     [ELF ZLIB (1) 00009a  1]
+[ 4] .debug_abbrev        PROGBITS     00000000 000260 000028  0        0   0  1
+[ 5] .debug_line          PROGBITS     00000000 000288 00005a  0 C      0   0  1
+     [ELF ZLIB (1) 000085  1]
+[ 6] .shstrtab            STRTAB       00000000 0002e2 000056  0        0   0  1
+[ 7] .symtab              SYMTAB       00000000 000080 0000f0 16        8   8  4
+[ 8] .strtab              STRTAB       00000000 000170 00004b  0        0   0  1
+
+EOF
+
+testfiles testfile-zgabi32be
+testrun_compare ${abs_top_builddir}/src/readelf -z -S testfile-zgabi32be <<\EOF
+There are 10 section headers, starting at offset 0x38c:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+     [Compression  Size   Al]
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .text                PROGBITS     01800054 000054 000074  0 AX     0   0  1
+[ 2] .eh_frame            PROGBITS     018000c8 0000c8 000000  0 A      0   0  4
+[ 3] .debug_aranges       PROGBITS     00000000 000220 000033  0 C      0   0  8
+     [ELF ZLIB (1) 000040  8]
+[ 4] .debug_info          PROGBITS     00000000 000253 000058  0 C      0   0  1
+     [ELF ZLIB (1) 00006e  1]
+[ 5] .debug_abbrev        PROGBITS     00000000 0002ab 000028  0        0   0  1
+[ 6] .debug_line          PROGBITS     00000000 0002d3 000059  0 C      0   0  1
+     [ELF ZLIB (1) 000085  1]
+[ 7] .shstrtab            STRTAB       00000000 00032c 000060  0        0   0  1
+[ 8] .symtab              SYMTAB       00000000 0000c8 000110 16        9   9  4
+[ 9] .strtab              STRTAB       00000000 0001d8 000045  0        0   0  1
+
+EOF
+
+exit 0
diff --git a/tests/run-readelf-zdebug-rel.sh b/tests/run-readelf-zdebug-rel.sh
new file mode 100755
index 0000000..53fa42a
--- /dev/null
+++ b/tests/run-readelf-zdebug-rel.sh
@@ -0,0 +1,255 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# - testfile-zdebug-rel.c
+# #define UINT64_MAX 18446744073709551615UL
+#
+# int
+# main (int argc, char **argv)
+# {
+#   unsigned long a = UINT64_MAX - 8;
+#   unsigned long b = 42 + argc;
+#
+#   if ( a + b < b )
+#     argc = a + argc;
+#   else
+#      b--;
+#
+#   return a - b;
+# }
+#
+# gcc -Og -g -Xassembler --compress-debug-sections=none \
+#     -c -o testfile-debug-rel.o testfile-zdebug-rel.c
+# gcc -Og -g -Xassembler --compress-debug-sections=zlib-gnu \
+#     -c -o testfile-debug-rel-g.o testfile-zdebug-rel.c
+# gcc -Og -g -Xassembler --compress-debug-sections=zlib-gabi \
+#     -c -o testfile-debug-rel-z.o testfile-zdebug-rel.c
+
+testfiles testfile-debug-rel.o testfile-debug-rel-g.o testfile-debug-rel-z.o
+tempfiles readelf.out
+tempfiles info.out loc.out
+
+cat > info.out << \EOF
+
+DWARF section [ 4] '.debug_info' at offset 0x58:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 1
+           producer             (strp) "GNU C11 5.3.1 20151207 (Red Hat 5.3.1-2) -mtune=generic -march=x86-64 -g -Og"
+           language             (data1) C99 (12)
+           name                 (strp) "testfile-zdebug-rel.c"
+           comp_dir             (strp) "/tmp"
+           low_pc               (addr) 000000000000000000
+           high_pc              (data8) 24 (0x0000000000000018)
+           stmt_list            (sec_offset) 0
+ [    2d]    subprogram           abbrev: 2
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) testfile-zdebug-rel.c (1)
+             decl_line            (data1) 4
+             prototyped           (flag_present) yes
+             type                 (ref4) [    80]
+             low_pc               (addr) 000000000000000000
+             high_pc              (data8) 24 (0x0000000000000018)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [    80]
+ [    4e]      formal_parameter     abbrev: 3
+               name                 (strp) "argc"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    80]
+               location             (sec_offset) location list [     0]
+ [    5d]      formal_parameter     abbrev: 4
+               name                 (strp) "argv"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    87]
+               location             (exprloc) 
+                [ 0] reg4
+ [    6a]      variable             abbrev: 5
+               name                 (string) "a"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 6
+               type                 (ref4) [    9a]
+               const_value          (sdata) 18446744073709551607 (-9)
+ [    74]      variable             abbrev: 6
+               name                 (string) "b"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 7
+               type                 (ref4) [    9a]
+               location             (exprloc) 
+                [ 0] reg5
+ [    80]    base_type            abbrev: 7
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [    87]    pointer_type         abbrev: 8
+             byte_size            (data1) 8
+             type                 (ref4) [    8d]
+ [    8d]    pointer_type         abbrev: 8
+             byte_size            (data1) 8
+             type                 (ref4) [    93]
+ [    93]    base_type            abbrev: 9
+             byte_size            (data1) 1
+             encoding             (data1) signed_char (6)
+             name                 (strp) "char"
+ [    9a]    base_type            abbrev: 9
+             byte_size            (data1) 8
+             encoding             (data1) unsigned (7)
+             name                 (strp) "long unsigned int"
+EOF
+
+cat info.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel.o
+
+cat info.out | sed -e "s/'.debug_info'/'.zdebug_info'/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-g.o
+
+cat info.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-z.o
+
+cat > loc.out << \EOF
+
+DWARF section [ 7] '.debug_loc' at offset 0x185:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 0, 3
+           [ 0] reg5
+          range 3, 10
+           [ 0] breg5 -42
+           [ 2] stack_value
+          range 10, 18
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+EOF
+
+cat loc.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel.o
+
+cat loc.out | sed -e "s/'.debug_loc' at offset 0x185/'.zdebug_loc' at offset 0x138/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-g.o
+
+cat loc.out | sed -e "s/at offset 0x185/at offset 0x150/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-z.o
+
+# Same as above, but on ppc64
+testfiles testfile-debug-rel-ppc64.o
+testfiles testfile-debug-rel-ppc64-g.o testfile-debug-rel-ppc64-z.o
+
+cat > info.out << \EOF
+
+DWARF section [ 6] '.debug_info' at offset 0x80:
+ [Offset]
+ Compilation unit at offset 0:
+ Version: 4, Abbreviation section offset: 0, Address size: 8, Offset size: 4
+ [     b]  compile_unit         abbrev: 1
+           producer             (strp) "GNU C11 7.3.1 20180712 (Red Hat 7.3.1-6) -Asystem=linux -Asystem=unix -Asystem=posix -msecure-plt -g -Og"
+           language             (data1) C99 (12)
+           name                 (strp) "testfile-zdebug-rel.c"
+           comp_dir             (strp) "/home/mjw"
+           low_pc               (addr) 000000000000000000
+           high_pc              (data8) 44 (0x000000000000002c)
+           stmt_list            (sec_offset) 0
+ [    2d]    subprogram           abbrev: 2
+             external             (flag_present) yes
+             name                 (strp) "main"
+             decl_file            (data1) testfile-zdebug-rel.c (1)
+             decl_line            (data1) 4
+             prototyped           (flag_present) yes
+             type                 (ref4) [    82]
+             low_pc               (addr) 000000000000000000
+             high_pc              (data8) 44 (0x000000000000002c)
+             frame_base           (exprloc) 
+              [ 0] call_frame_cfa
+             GNU_all_call_sites   (flag_present) yes
+             sibling              (ref4) [    82]
+ [    4e]      formal_parameter     abbrev: 3
+               name                 (strp) "argc"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    82]
+               location             (sec_offset) location list [     0]
+ [    5d]      formal_parameter     abbrev: 4
+               name                 (strp) "argv"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 4
+               type                 (ref4) [    89]
+               location             (exprloc) 
+                [ 0] reg4
+ [    6a]      variable             abbrev: 5
+               name                 (string) "a"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 6
+               type                 (ref4) [    9c]
+               const_value          (sdata) 18446744073709551607 (-9)
+ [    74]      variable             abbrev: 6
+               name                 (string) "b"
+               decl_file            (data1) testfile-zdebug-rel.c (1)
+               decl_line            (data1) 7
+               type                 (ref4) [    9c]
+               location             (sec_offset) location list [    4e]
+ [    82]    base_type            abbrev: 7
+             byte_size            (data1) 4
+             encoding             (data1) signed (5)
+             name                 (string) "int"
+ [    89]    pointer_type         abbrev: 8
+             byte_size            (data1) 8
+             type                 (ref4) [    8f]
+ [    8f]    pointer_type         abbrev: 8
+             byte_size            (data1) 8
+             type                 (ref4) [    95]
+ [    95]    base_type            abbrev: 9
+             byte_size            (data1) 1
+             encoding             (data1) unsigned_char (8)
+             name                 (strp) "char"
+ [    9c]    base_type            abbrev: 9
+             byte_size            (data1) 8
+             encoding             (data1) unsigned (7)
+             name                 (strp) "long unsigned int"
+EOF
+
+cat info.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-ppc64.o
+
+cat info.out | sed -e "s/'.debug_info'/'.zdebug_info'/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-ppc64-g.o
+
+cat info.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=info testfile-debug-rel-ppc64-z.o
+
+cat > loc.out << \EOF
+
+DWARF section [ 9] '.debug_loc' at offset 0x1af:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 0, 4
+           [ 0] reg3
+          range 4, 14
+           [ 0] breg3 -42
+           [ 2] stack_value
+          range 14, 2c
+           [ 0] GNU_entry_value:
+                [ 0] reg3
+           [ 3] stack_value
+ [    4e] range 8, 18
+           [ 0] reg3
+EOF
+
+cat loc.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-ppc64.o
+
+cat loc.out | sed -e "s/'.debug_loc' at offset 0x1af/'.zdebug_loc' at offset 0x15f/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-ppc64-g.o
+
+cat loc.out | sed -e "s/at offset 0x1af/at offset 0x177/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug-rel-ppc64-z.o
+
+exit 0
diff --git a/tests/run-readelf-zdebug.sh b/tests/run-readelf-zdebug.sh
new file mode 100755
index 0000000..9de68de
--- /dev/null
+++ b/tests/run-readelf-zdebug.sh
@@ -0,0 +1,548 @@
+#! /bin/sh
+# Copyright (C) 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# - testfile-zdebug.c
+# #define UINT64_MAX 18446744073709551615UL
+#
+# int
+# main (int argc, char **argv)
+# {
+#   unsigned long a = UINT64_MAX - 8;
+#   unsigned long b = 42 + argc;
+#
+#   if ( a + b < b )
+#     argc = a + argc;
+#   else
+#      b--;
+#
+#   return a - b;
+# }
+#
+# gcc -g3 -O3 -fuse-ld=gold -Xlinker --compress-debug-sections=none \
+#     -fno-asynchronous-unwind-tables -o testfile-debug testfile-zdebug.c
+# gcc -g3 -O3 -fuse-ld=gold -Xlinker --compress-debug-sections=zlib \
+#     -fno-asynchronous-unwind-tables -o testfile-zdebug testfile-zdebug.c
+
+testfiles testfile-debug testfile-zdebug
+tempfiles readelf.out
+tempfiles loc.out aranges.out ranges.out macro.out line.out frame.out
+
+cat > loc.out << \EOF
+
+DWARF section [30] '.debug_loc' at offset 0xa17:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 4003c0, 4003c3
+           [ 0] reg5
+          range 4003c3, 4003d6
+           [ 0] breg5 -42
+           [ 2] stack_value
+          range 4003d6, 4003d9
+           [ 0] GNU_entry_value:
+                [ 0] reg5
+           [ 3] stack_value
+EOF
+
+cat loc.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-debug
+
+cat loc.out | sed -e "s/.debug_loc' at offset 0xa17/.zdebug_loc' at offset 0x1a27/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=loc testfile-zdebug
+
+cat > aranges.out << \EOF
+
+DWARF section [31] '.debug_aranges' at offset 0xa65:
+
+Table at offset 0:
+
+ Length:            44
+ DWARF version:      2
+ CU offset:          0
+ Address size:       8
+ Segment size:       0
+
+   0x00000000004003c0..0x0000000000000019
+EOF
+
+cat aranges.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=aranges testfile-debug
+
+cat aranges.out | sed -e "s/.debug_aranges' at offset 0xa65/.zdebug_aranges' at offset 0x1a5f/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=aranges testfile-zdebug
+
+cat > ranges.out << \EOF
+
+DWARF section [32] '.debug_ranges' at offset 0xa95:
+
+ CU [     b] base: 000000000000000000
+ [     0] range 4003c0, 4003d9
+EOF
+
+cat ranges.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=ranges testfile-debug
+
+cat ranges.out | sed -e "s/.debug_ranges' at offset 0xa95/.zdebug_ranges' at offset 0x1a87/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=ranges testfile-zdebug
+
+cat > macro.out << \EOF
+
+DWARF section [33] '.debug_macro' at offset 0xab5:
+
+ Offset:             0x0
+ Version:            4
+ Flag:               0x2 (debug_line_offset)
+ Offset length:      4
+ .debug_line offset: 0x0
+
+ #include offset 0x17
+ start_file 0, [1] /tmp/testfile-zdebug.c
+  #define UINT64_MAX 18446744073709551615UL, line 1 (indirect)
+ end_file
+
+ Offset:             0x17
+ Version:            4
+ Flag:               0x0
+ Offset length:      4
+
+ #define __STDC__ 1, line 1 (indirect)
+ #define __STDC_HOSTED__ 1, line 1 (indirect)
+ #define __GNUC__ 4, line 1 (indirect)
+ #define __GNUC_MINOR__ 8, line 1 (indirect)
+ #define __GNUC_PATCHLEVEL__ 2, line 1 (indirect)
+ #define __VERSION__ "4.8.2 20140120 (Red Hat 4.8.2-15)", line 1 (indirect)
+ #define __GNUC_RH_RELEASE__ 15, line 1 (indirect)
+ #define __ATOMIC_RELAXED 0, line 1 (indirect)
+ #define __ATOMIC_SEQ_CST 5, line 1 (indirect)
+ #define __ATOMIC_ACQUIRE 2, line 1 (indirect)
+ #define __ATOMIC_RELEASE 3, line 1 (indirect)
+ #define __ATOMIC_ACQ_REL 4, line 1 (indirect)
+ #define __ATOMIC_CONSUME 1, line 1 (indirect)
+ #define __OPTIMIZE__ 1, line 1 (indirect)
+ #define __FINITE_MATH_ONLY__ 0, line 1 (indirect)
+ #define _LP64 1, line 1 (indirect)
+ #define __LP64__ 1, line 1 (indirect)
+ #define __SIZEOF_INT__ 4, line 1 (indirect)
+ #define __SIZEOF_LONG__ 8, line 1 (indirect)
+ #define __SIZEOF_LONG_LONG__ 8, line 1 (indirect)
+ #define __SIZEOF_SHORT__ 2, line 1 (indirect)
+ #define __SIZEOF_FLOAT__ 4, line 1 (indirect)
+ #define __SIZEOF_DOUBLE__ 8, line 1 (indirect)
+ #define __SIZEOF_LONG_DOUBLE__ 16, line 1 (indirect)
+ #define __SIZEOF_SIZE_T__ 8, line 1 (indirect)
+ #define __CHAR_BIT__ 8, line 1 (indirect)
+ #define __BIGGEST_ALIGNMENT__ 16, line 1 (indirect)
+ #define __ORDER_LITTLE_ENDIAN__ 1234, line 1 (indirect)
+ #define __ORDER_BIG_ENDIAN__ 4321, line 1 (indirect)
+ #define __ORDER_PDP_ENDIAN__ 3412, line 1 (indirect)
+ #define __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__, line 1 (indirect)
+ #define __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__, line 1 (indirect)
+ #define __SIZEOF_POINTER__ 8, line 1 (indirect)
+ #define __SIZE_TYPE__ long unsigned int, line 1 (indirect)
+ #define __PTRDIFF_TYPE__ long int, line 1 (indirect)
+ #define __WCHAR_TYPE__ int, line 1 (indirect)
+ #define __WINT_TYPE__ unsigned int, line 1 (indirect)
+ #define __INTMAX_TYPE__ long int, line 1 (indirect)
+ #define __UINTMAX_TYPE__ long unsigned int, line 1 (indirect)
+ #define __CHAR16_TYPE__ short unsigned int, line 1 (indirect)
+ #define __CHAR32_TYPE__ unsigned int, line 1 (indirect)
+ #define __SIG_ATOMIC_TYPE__ int, line 1 (indirect)
+ #define __INT8_TYPE__ signed char, line 1 (indirect)
+ #define __INT16_TYPE__ short int, line 1 (indirect)
+ #define __INT32_TYPE__ int, line 1 (indirect)
+ #define __INT64_TYPE__ long int, line 1 (indirect)
+ #define __UINT8_TYPE__ unsigned char, line 1 (indirect)
+ #define __UINT16_TYPE__ short unsigned int, line 1 (indirect)
+ #define __UINT32_TYPE__ unsigned int, line 1 (indirect)
+ #define __UINT64_TYPE__ long unsigned int, line 1 (indirect)
+ #define __INT_LEAST8_TYPE__ signed char, line 1 (indirect)
+ #define __INT_LEAST16_TYPE__ short int, line 1 (indirect)
+ #define __INT_LEAST32_TYPE__ int, line 1 (indirect)
+ #define __INT_LEAST64_TYPE__ long int, line 1 (indirect)
+ #define __UINT_LEAST8_TYPE__ unsigned char, line 1 (indirect)
+ #define __UINT_LEAST16_TYPE__ short unsigned int, line 1 (indirect)
+ #define __UINT_LEAST32_TYPE__ unsigned int, line 1 (indirect)
+ #define __UINT_LEAST64_TYPE__ long unsigned int, line 1 (indirect)
+ #define __INT_FAST8_TYPE__ signed char, line 1 (indirect)
+ #define __INT_FAST16_TYPE__ long int, line 1 (indirect)
+ #define __INT_FAST32_TYPE__ long int, line 1 (indirect)
+ #define __INT_FAST64_TYPE__ long int, line 1 (indirect)
+ #define __UINT_FAST8_TYPE__ unsigned char, line 1 (indirect)
+ #define __UINT_FAST16_TYPE__ long unsigned int, line 1 (indirect)
+ #define __UINT_FAST32_TYPE__ long unsigned int, line 1 (indirect)
+ #define __UINT_FAST64_TYPE__ long unsigned int, line 1 (indirect)
+ #define __INTPTR_TYPE__ long int, line 1 (indirect)
+ #define __UINTPTR_TYPE__ long unsigned int, line 1 (indirect)
+ #define __GXX_ABI_VERSION 1002, line 1 (indirect)
+ #define __SCHAR_MAX__ 127, line 1 (indirect)
+ #define __SHRT_MAX__ 32767, line 1 (indirect)
+ #define __INT_MAX__ 2147483647, line 1 (indirect)
+ #define __LONG_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __LONG_LONG_MAX__ 9223372036854775807LL, line 1 (indirect)
+ #define __WCHAR_MAX__ 2147483647, line 1 (indirect)
+ #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1), line 1 (indirect)
+ #define __WINT_MAX__ 4294967295U, line 1 (indirect)
+ #define __WINT_MIN__ 0U, line 1 (indirect)
+ #define __PTRDIFF_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __SIZE_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __INTMAX_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INTMAX_C(c) c ## L, line 1 (indirect)
+ #define __UINTMAX_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINTMAX_C(c) c ## UL, line 1 (indirect)
+ #define __SIG_ATOMIC_MAX__ 2147483647, line 1 (indirect)
+ #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1), line 1 (indirect)
+ #define __INT8_MAX__ 127, line 1 (indirect)
+ #define __INT16_MAX__ 32767, line 1 (indirect)
+ #define __INT32_MAX__ 2147483647, line 1 (indirect)
+ #define __INT64_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __UINT8_MAX__ 255, line 1 (indirect)
+ #define __UINT16_MAX__ 65535, line 1 (indirect)
+ #define __UINT32_MAX__ 4294967295U, line 1 (indirect)
+ #define __UINT64_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __INT_LEAST8_MAX__ 127, line 1 (indirect)
+ #define __INT8_C(c) c, line 1 (indirect)
+ #define __INT_LEAST16_MAX__ 32767, line 1 (indirect)
+ #define __INT16_C(c) c, line 1 (indirect)
+ #define __INT_LEAST32_MAX__ 2147483647, line 1 (indirect)
+ #define __INT32_C(c) c, line 1 (indirect)
+ #define __INT_LEAST64_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INT64_C(c) c ## L, line 1 (indirect)
+ #define __UINT_LEAST8_MAX__ 255, line 1 (indirect)
+ #define __UINT8_C(c) c, line 1 (indirect)
+ #define __UINT_LEAST16_MAX__ 65535, line 1 (indirect)
+ #define __UINT16_C(c) c, line 1 (indirect)
+ #define __UINT_LEAST32_MAX__ 4294967295U, line 1 (indirect)
+ #define __UINT32_C(c) c ## U, line 1 (indirect)
+ #define __UINT_LEAST64_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINT64_C(c) c ## UL, line 1 (indirect)
+ #define __INT_FAST8_MAX__ 127, line 1 (indirect)
+ #define __INT_FAST16_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INT_FAST32_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __INT_FAST64_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __UINT_FAST8_MAX__ 255, line 1 (indirect)
+ #define __UINT_FAST16_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINT_FAST32_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __UINT_FAST64_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __INTPTR_MAX__ 9223372036854775807L, line 1 (indirect)
+ #define __UINTPTR_MAX__ 18446744073709551615UL, line 1 (indirect)
+ #define __FLT_EVAL_METHOD__ 0, line 1 (indirect)
+ #define __DEC_EVAL_METHOD__ 2, line 1 (indirect)
+ #define __FLT_RADIX__ 2, line 1 (indirect)
+ #define __FLT_MANT_DIG__ 24, line 1 (indirect)
+ #define __FLT_DIG__ 6, line 1 (indirect)
+ #define __FLT_MIN_EXP__ (-125), line 1 (indirect)
+ #define __FLT_MIN_10_EXP__ (-37), line 1 (indirect)
+ #define __FLT_MAX_EXP__ 128, line 1 (indirect)
+ #define __FLT_MAX_10_EXP__ 38, line 1 (indirect)
+ #define __FLT_DECIMAL_DIG__ 9, line 1 (indirect)
+ #define __FLT_MAX__ 3.40282346638528859812e+38F, line 1 (indirect)
+ #define __FLT_MIN__ 1.17549435082228750797e-38F, line 1 (indirect)
+ #define __FLT_EPSILON__ 1.19209289550781250000e-7F, line 1 (indirect)
+ #define __FLT_DENORM_MIN__ 1.40129846432481707092e-45F, line 1 (indirect)
+ #define __FLT_HAS_DENORM__ 1, line 1 (indirect)
+ #define __FLT_HAS_INFINITY__ 1, line 1 (indirect)
+ #define __FLT_HAS_QUIET_NAN__ 1, line 1 (indirect)
+ #define __DBL_MANT_DIG__ 53, line 1 (indirect)
+ #define __DBL_DIG__ 15, line 1 (indirect)
+ #define __DBL_MIN_EXP__ (-1021), line 1 (indirect)
+ #define __DBL_MIN_10_EXP__ (-307), line 1 (indirect)
+ #define __DBL_MAX_EXP__ 1024, line 1 (indirect)
+ #define __DBL_MAX_10_EXP__ 308, line 1 (indirect)
+ #define __DBL_DECIMAL_DIG__ 17, line 1 (indirect)
+ #define __DBL_MAX__ ((double)1.79769313486231570815e+308L), line 1 (indirect)
+ #define __DBL_MIN__ ((double)2.22507385850720138309e-308L), line 1 (indirect)
+ #define __DBL_EPSILON__ ((double)2.22044604925031308085e-16L), line 1 (indirect)
+ #define __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L), line 1 (indirect)
+ #define __DBL_HAS_DENORM__ 1, line 1 (indirect)
+ #define __DBL_HAS_INFINITY__ 1, line 1 (indirect)
+ #define __DBL_HAS_QUIET_NAN__ 1, line 1 (indirect)
+ #define __LDBL_MANT_DIG__ 64, line 1 (indirect)
+ #define __LDBL_DIG__ 18, line 1 (indirect)
+ #define __LDBL_MIN_EXP__ (-16381), line 1 (indirect)
+ #define __LDBL_MIN_10_EXP__ (-4931), line 1 (indirect)
+ #define __LDBL_MAX_EXP__ 16384, line 1 (indirect)
+ #define __LDBL_MAX_10_EXP__ 4932, line 1 (indirect)
+ #define __DECIMAL_DIG__ 21, line 1 (indirect)
+ #define __LDBL_MAX__ 1.18973149535723176502e+4932L, line 1 (indirect)
+ #define __LDBL_MIN__ 3.36210314311209350626e-4932L, line 1 (indirect)
+ #define __LDBL_EPSILON__ 1.08420217248550443401e-19L, line 1 (indirect)
+ #define __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L, line 1 (indirect)
+ #define __LDBL_HAS_DENORM__ 1, line 1 (indirect)
+ #define __LDBL_HAS_INFINITY__ 1, line 1 (indirect)
+ #define __LDBL_HAS_QUIET_NAN__ 1, line 1 (indirect)
+ #define __DEC32_MANT_DIG__ 7, line 1 (indirect)
+ #define __DEC32_MIN_EXP__ (-94), line 1 (indirect)
+ #define __DEC32_MAX_EXP__ 97, line 1 (indirect)
+ #define __DEC32_MIN__ 1E-95DF, line 1 (indirect)
+ #define __DEC32_MAX__ 9.999999E96DF, line 1 (indirect)
+ #define __DEC32_EPSILON__ 1E-6DF, line 1 (indirect)
+ #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF, line 1 (indirect)
+ #define __DEC64_MANT_DIG__ 16, line 1 (indirect)
+ #define __DEC64_MIN_EXP__ (-382), line 1 (indirect)
+ #define __DEC64_MAX_EXP__ 385, line 1 (indirect)
+ #define __DEC64_MIN__ 1E-383DD, line 1 (indirect)
+ #define __DEC64_MAX__ 9.999999999999999E384DD, line 1 (indirect)
+ #define __DEC64_EPSILON__ 1E-15DD, line 1 (indirect)
+ #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD, line 1 (indirect)
+ #define __DEC128_MANT_DIG__ 34, line 1 (indirect)
+ #define __DEC128_MIN_EXP__ (-6142), line 1 (indirect)
+ #define __DEC128_MAX_EXP__ 6145, line 1 (indirect)
+ #define __DEC128_MIN__ 1E-6143DL, line 1 (indirect)
+ #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL, line 1 (indirect)
+ #define __DEC128_EPSILON__ 1E-33DL, line 1 (indirect)
+ #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL, line 1 (indirect)
+ #define __REGISTER_PREFIX__ , line 1 (indirect)
+ #define __USER_LABEL_PREFIX__ , line 1 (indirect)
+ #define __GNUC_GNU_INLINE__ 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1, line 1 (indirect)
+ #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1, line 1 (indirect)
+ #define __GCC_ATOMIC_BOOL_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_CHAR_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_SHORT_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_INT_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_LONG_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_LLONG_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1, line 1 (indirect)
+ #define __GCC_ATOMIC_POINTER_LOCK_FREE 2, line 1 (indirect)
+ #define __GCC_HAVE_DWARF2_CFI_ASM 1, line 1 (indirect)
+ #define __PRAGMA_REDEFINE_EXTNAME 1, line 1 (indirect)
+ #define __SIZEOF_INT128__ 16, line 1 (indirect)
+ #define __SIZEOF_WCHAR_T__ 4, line 1 (indirect)
+ #define __SIZEOF_WINT_T__ 4, line 1 (indirect)
+ #define __SIZEOF_PTRDIFF_T__ 8, line 1 (indirect)
+ #define __amd64 1, line 1 (indirect)
+ #define __amd64__ 1, line 1 (indirect)
+ #define __x86_64 1, line 1 (indirect)
+ #define __x86_64__ 1, line 1 (indirect)
+ #define __ATOMIC_HLE_ACQUIRE 65536, line 1 (indirect)
+ #define __ATOMIC_HLE_RELEASE 131072, line 1 (indirect)
+ #define __k8 1, line 1 (indirect)
+ #define __k8__ 1, line 1 (indirect)
+ #define __code_model_small__ 1, line 1 (indirect)
+ #define __MMX__ 1, line 1 (indirect)
+ #define __SSE__ 1, line 1 (indirect)
+ #define __SSE2__ 1, line 1 (indirect)
+ #define __FXSR__ 1, line 1 (indirect)
+ #define __SSE_MATH__ 1, line 1 (indirect)
+ #define __SSE2_MATH__ 1, line 1 (indirect)
+ #define __gnu_linux__ 1, line 1 (indirect)
+ #define __linux 1, line 1 (indirect)
+ #define __linux__ 1, line 1 (indirect)
+ #define linux 1, line 1 (indirect)
+ #define __unix 1, line 1 (indirect)
+ #define __unix__ 1, line 1 (indirect)
+ #define unix 1, line 1 (indirect)
+ #define __ELF__ 1, line 1 (indirect)
+ #define __DECIMAL_BID_FORMAT__ 1, line 1 (indirect)
+
+EOF
+
+cat macro.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=macro testfile-debug
+
+cat macro.out | sed -e "s/.debug_macro' at offset 0xab5/.zdebug_macro' at offset 0x1aa7/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=macro testfile-zdebug
+
+cat > line.out << \EOF
+
+DWARF section [34] '.debug_line' at offset 0x104c:
+
+Table at offset 0:
+
+ Length:                         70
+ DWARF version:                  2
+ Prologue length:                40
+ Address size:                   8
+ Segment selector size:          0
+ Min instruction length:         1
+ Max operations per instruction: 1
+ Initial value if 'is_stmt':     1
+ Line base:                      -5
+ Line range:                     14
+ Opcode base:                    13
+
+Opcodes:
+  [ 1]  0 arguments
+  [ 2]  1 argument
+  [ 3]  1 argument
+  [ 4]  1 argument
+  [ 5]  1 argument
+  [ 6]  0 arguments
+  [ 7]  0 arguments
+  [ 8]  0 arguments
+  [ 9]  1 argument
+  [10]  0 arguments
+  [11]  0 arguments
+  [12]  1 argument
+
+Directory table:
+
+File name table:
+ Entry Dir   Time      Size      Name
+ 1     0     0         0         testfile-zdebug.c
+
+Line number statements:
+ [    32] extended opcode 2:  set address to 0x4003c0
+ [    3d] special opcode 22: address+0 = 0x4003c0, line+4 = 5
+ [    3e] special opcode 20: address+0 = 0x4003c0, line+2 = 7
+ [    3f] special opcode 104: address+6 = 0x4003c6, line+2 = 9
+ [    40] special opcode 77: address+4 = 0x4003ca, line+3 = 12
+ [    41] special opcode 62: address+3 = 0x4003cd, line+2 = 14
+ [    42] special opcode 86: address+5 = 0x4003d2, line-2 = 12
+ [    43] special opcode 76: address+4 = 0x4003d6, line+2 = 14
+ [    44] special opcode 47: address+2 = 0x4003d8, line+1 = 15
+ [    45] advance address by 1 to 0x4003d9
+ [    47] extended opcode 1:  end of sequence
+EOF
+
+cat line.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=line testfile-debug
+
+cat line.out | sed -e "s/.debug_line' at offset 0x104c/.zdebug_line' at offset 0x1d53/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=line testfile-zdebug
+
+
+cat > frame.out << \EOF
+
+Call frame information section [16] '.eh_frame' at offset 0x5b8:
+
+ [     0] CIE length=20
+   CIE_id:                   0
+   version:                  1
+   augmentation:             "zR"
+   code_alignment_factor:    1
+   data_alignment_factor:    -8
+   return_address_register:  16
+   Augmentation data:        0x1b (FDE address encoding: sdata4 pcrel)
+
+   Program:
+     def_cfa r7 (rsp) at offset 8
+     offset r16 (rip) at cfa-8
+     nop
+     nop
+
+ [    18] FDE length=20 cie=[     0]
+   CIE_pointer:              28
+   initial_location:         0x00000000ffffff08 (offset: 0x4e0)
+   address_range:            0x2 (end offset: 0x4e2)
+
+   Program:
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+
+ [    30] FDE length=44 cie=[     0]
+   CIE_pointer:              52
+   initial_location:         0x00000000ffffff00 (offset: 0x4f0)
+   address_range:            0x89 (end offset: 0x579)
+
+   Program:
+     advance_loc 17 to 0x501
+     offset r12 (r12) at cfa-40
+     offset r6 (rbp) at cfa-48
+     advance_loc 31 to 0x520
+     def_cfa_offset 64
+     offset r3 (rbx) at cfa-56
+     offset r15 (r15) at cfa-16
+     offset r14 (r14) at cfa-24
+     offset r13 (r13) at cfa-32
+     advance_loc1 88 to 0x578
+     def_cfa_offset 8
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+
+ [    60] FDE length=36 cie=[     0]
+   CIE_pointer:              100
+   initial_location:         0x00000000fffffd80 (offset: 0x3a0)
+   address_range:            0x20 (end offset: 0x3c0)
+
+   Program:
+     def_cfa_offset 16
+     advance_loc 6 to 0x3a6
+     def_cfa_offset 24
+     advance_loc 10 to 0x3b0
+     def_cfa_expression 11
+          [ 0] breg7 8
+          [ 2] breg16 0
+          [ 4] lit15
+          [ 5] and
+          [ 6] lit11
+          [ 7] ge
+          [ 8] lit3
+          [ 9] shl
+          [10] plus
+     nop
+     nop
+     nop
+     nop
+
+ [    88] Zero terminator
+
+Call frame search table section [17] '.eh_frame_hdr':
+ version:          1
+ eh_frame_ptr_enc: 0x1b (sdata4 pcrel)
+ fde_count_enc:    0x3 (udata4)
+ table_enc:        0x3b (sdata4 datarel)
+ eh_frame_ptr:     0xffffffffffffff70 (offset: 0x5b8)
+ fde_count:        3
+ Table:
+  0xfffffd5c (offset:  0x3a0) -> 0xffffffd4 fde=[    60]
+  0xfffffe9c (offset:  0x4e0) -> 0xffffff8c fde=[    18]
+  0xfffffeac (offset:  0x4f0) -> 0xffffffa4 fde=[    30]
+
+DWARF section [36] '.debug_frame' at offset 0x29b8:
+
+ [     0] CIE length=20
+   CIE_id:                   18446744073709551615
+   version:                  1
+   augmentation:             ""
+   code_alignment_factor:    1
+   data_alignment_factor:    -8
+   return_address_register:  16
+
+   Program:
+     def_cfa r7 (rsp) at offset 8
+     offset r16 (rip) at cfa-8
+     nop
+     nop
+     nop
+     nop
+     nop
+     nop
+
+ [    18] FDE length=20 cie=[     0]
+   CIE_pointer:              0
+   initial_location:         0x00000000004003c0
+   address_range:            0x19
+
+   Program:
+EOF
+
+cat frame.out | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=frame testfile-debug
+
+cat frame.out | sed -e "s/.debug_frame' at offset 0x29b8/.zdebug_frame' at offset 0x2728/" | testrun_compare ${abs_top_builddir}/src/readelf -U --debug-dump=frame testfile-zdebug
+
+
diff --git a/tests/run-readelf-zp.sh b/tests/run-readelf-zp.sh
new file mode 100755
index 0000000..872126c
--- /dev/null
+++ b/tests/run-readelf-zp.sh
@@ -0,0 +1,271 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-readelf-zdebug.sh for testfile.
+
+testfiles testfile-zdebug
+testrun_compare ${abs_top_builddir}/src/readelf -z -p.zdebug_str testfile-zdebug <<\EOF
+
+String section [35] '.zdebug_str' contains 2431 bytes (6433 uncompressed) at offset 0x1da3:
+  [     0]  UINT64_MAX 18446744073709551615UL
+  [    22]  __DBL_DENORM_MIN__ ((double)4.94065645841246544177e-324L)
+  [    5c]  __linux 1
+  [    66]  __SIZEOF_SIZE_T__ 8
+  [    7a]  __UINTPTR_TYPE__ long unsigned int
+  [    9d]  __SIZEOF_POINTER__ 8
+  [    b2]  __UINT8_MAX__ 255
+  [    c4]  __PTRDIFF_MAX__ 9223372036854775807L
+  [    e9]  __DEC64_MANT_DIG__ 16
+  [    ff]  __FLT_RADIX__ 2
+  [   10f]  __DEC32_MIN__ 1E-95DF
+  [   125]  __unix__ 1
+  [   130]  testfile-zdebug.c
+  [   142]  __UINT_LEAST64_MAX__ 18446744073709551615UL
+  [   16e]  __SIZEOF_WINT_T__ 4
+  [   182]  __LONG_MAX__ 9223372036854775807L
+  [   1a4]  __LDBL_MIN__ 3.36210314311209350626e-4932L
+  [   1cf]  __GCC_ATOMIC_SHORT_LOCK_FREE 2
+  [   1ee]  __LP64__ 1
+  [   1f9]  __UINT64_C(c) c ## UL
+  [   20f]  __DBL_HAS_INFINITY__ 1
+  [   226]  __SSE2_MATH__ 1
+  [   236]  __linux__ 1
+  [   242]  __STDC_HOSTED__ 1
+  [   254]  __WINT_MIN__ 0U
+  [   264]  __x86_64__ 1
+  [   271]  __UINT32_TYPE__ unsigned int
+  [   28e]  __UINT_LEAST8_MAX__ 255
+  [   2a6]  __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD
+  [   2d7]  __FLT_MAX__ 3.40282346638528859812e+38F
+  [   2ff]  long unsigned int
+  [   311]  __DBL_MANT_DIG__ 53
+  [   325]  linux 1
+  [   32d]  __DBL_HAS_QUIET_NAN__ 1
+  [   345]  __UINT8_TYPE__ unsigned char
+  [   362]  __DEC32_MAX_EXP__ 97
+  [   377]  __INT32_TYPE__ int
+  [   38a]  __SIG_ATOMIC_TYPE__ int
+  [   3a2]  __DEC64_MAX_EXP__ 385
+  [   3b8]  __DBL_MIN_EXP__ (-1021)
+  [   3d0]  _LP64 1
+  [   3d8]  __LDBL_HAS_INFINITY__ 1
+  [   3f0]  __INT_FAST64_TYPE__ long int
+  [   40d]  __gnu_linux__ 1
+  [   41d]  __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2
+  [   43e]  __UINT_FAST64_TYPE__ long unsigned int
+  [   465]  __BYTE_ORDER__ __ORDER_LITTLE_ENDIAN__
+  [   48c]  __UINT16_MAX__ 65535
+  [   4a1]  __FLOAT_WORD_ORDER__ __ORDER_LITTLE_ENDIAN__
+  [   4ce]  __PRAGMA_REDEFINE_EXTNAME 1
+  [   4ea]  __INT_LEAST16_TYPE__ short int
+  [   509]  __k8__ 1
+  [   512]  __DECIMAL_DIG__ 21
+  [   525]  main
+  [   52a]  __DBL_MAX__ ((double)1.79769313486231570815e+308L)
+  [   55d]  __INT16_TYPE__ short int
+  [   576]  __LDBL_HAS_QUIET_NAN__ 1
+  [   58f]  __SIZEOF_DOUBLE__ 8
+  [   5a3]  __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF
+  [   5ca]  __ATOMIC_SEQ_CST 5
+  [   5dd]  __UINT64_TYPE__ long unsigned int
+  [   5ff]  __INT_LEAST32_TYPE__ int
+  [   618]  __INT_LEAST64_MAX__ 9223372036854775807L
+  [   641]  __OPTIMIZE__ 1
+  [   650]  __INTMAX_C(c) c ## L
+  [   665]  __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2
+  [   687]  __INT_FAST8_MAX__ 127
+  [   69d]  __PTRDIFF_TYPE__ long int
+  [   6b7]  __LDBL_MIN_EXP__ (-16381)
+  [   6d1]  __SIZEOF_LONG_LONG__ 8
+  [   6e8]  __FLT_DIG__ 6
+  [   6f6]  __UINTMAX_MAX__ 18446744073709551615UL
+  [   71d]  __SIZEOF_WCHAR_T__ 4
+  [   732]  __INT64_C(c) c ## L
+  [   746]  __UINTPTR_MAX__ 18446744073709551615UL
+  [   76d]  __FLT_MAX_10_EXP__ 38
+  [   783]  __FLT_MIN__ 1.17549435082228750797e-38F
+  [   7ab]  __UINT_LEAST64_TYPE__ long unsigned int
+  [   7d3]  __SIZEOF_LONG_DOUBLE__ 16
+  [   7ed]  __SIZE_MAX__ 18446744073709551615UL
+  [   811]  __INT8_C(c) c
+  [   81f]  __amd64__ 1
+  [   82b]  __INT_LEAST64_TYPE__ long int
+  [   849]  __INT_FAST64_MAX__ 9223372036854775807L
+  [   871]  __DEC_EVAL_METHOD__ 2
+  [   887]  __DEC32_MAX__ 9.999999E96DF
+  [   8a3]  __GNUC_MINOR__ 8
+  [   8b4]  __WCHAR_MAX__ 2147483647
+  [   8cd]  __SIZE_TYPE__ long unsigned int
+  [   8ed]  __INT8_MAX__ 127
+  [   8fe]  __INTMAX_MAX__ 9223372036854775807L
+  [   922]  __ATOMIC_HLE_RELEASE 131072
+  [   93e]  __FLT_HAS_QUIET_NAN__ 1
+  [   956]  __DBL_EPSILON__ ((double)2.22044604925031308085e-16L)
+  [   98c]  __FLT_MIN_EXP__ (-125)
+  [   9a3]  __INT_LEAST8_MAX__ 127
+  [   9ba]  __SIZEOF_INT128__ 16
+  [   9cf]  __INTPTR_MAX__ 9223372036854775807L
+  [   9f3]  __INTPTR_TYPE__ long int
+  [   a0c]  __LDBL_MIN_10_EXP__ (-4931)
+  [   a28]  __GCC_ATOMIC_POINTER_LOCK_FREE 2
+  [   a49]  __UINT_LEAST32_MAX__ 4294967295U
+  [   a6a]  __SIZEOF_SHORT__ 2
+  [   a7d]  __LDBL_MAX_10_EXP__ 4932
+  [   a96]  __INT16_C(c) c
+  [   aa5]  __MMX__ 1
+  [   aaf]  unix 1
+  [   ab6]  __FLT_MAX_EXP__ 128
+  [   aca]  __DEC64_MAX__ 9.999999999999999E384DD
+  [   af0]  __FLT_EPSILON__ 1.19209289550781250000e-7F
+  [   b1b]  __INT_FAST16_TYPE__ long int
+  [   b38]  __VERSION__ "4.8.2 20140120 (Red Hat 4.8.2-15)"
+  [   b68]  __GCC_ATOMIC_LLONG_LOCK_FREE 2
+  [   b87]  __DEC128_MIN_EXP__ (-6142)
+  [   ba2]  __ATOMIC_RELEASE 3
+  [   bb5]  __GNUC_PATCHLEVEL__ 2
+  [   bcb]  __UINT_FAST64_MAX__ 18446744073709551615UL
+  [   bf6]  __DBL_DECIMAL_DIG__ 17
+  [   c0d]  __DBL_DIG__ 15
+  [   c1c]  __FLT_MANT_DIG__ 24
+  [   c30]  __FLT_DECIMAL_DIG__ 9
+  [   c46]  __INT16_MAX__ 32767
+  [   c5a]  __DEC128_MIN__ 1E-6143DL
+  [   c73]  __BIGGEST_ALIGNMENT__ 16
+  [   c8c]  __INT64_MAX__ 9223372036854775807L
+  [   caf]  __INT_FAST32_TYPE__ long int
+  [   ccc]  __GCC_ATOMIC_INT_LOCK_FREE 2
+  [   ce9]  __DEC128_MAX_EXP__ 6145
+  [   d01]  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1
+  [   d26]  __FXSR__ 1
+  [   d31]  __INT8_TYPE__ signed char
+  [   d4b]  __ATOMIC_ACQ_REL 4
+  [   d5e]  __UINT_LEAST16_MAX__ 65535
+  [   d79]  __UINTMAX_TYPE__ long unsigned int
+  [   d9c]  __UINT_FAST8_MAX__ 255
+  [   db3]  __ORDER_BIG_ENDIAN__ 4321
+  [   dcd]  __INT_LEAST32_MAX__ 2147483647
+  [   dec]  __UINT_LEAST16_TYPE__ short unsigned int
+  [   e15]  __INT_FAST8_TYPE__ signed char
+  [   e34]  __DBL_MAX_EXP__ 1024
+  [   e49]  __STDC__ 1
+  [   e54]  __ELF__ 1
+  [   e5e]  __FLT_EVAL_METHOD__ 0
+  [   e74]  __ATOMIC_ACQUIRE 2
+  [   e87]  __DEC64_EPSILON__ 1E-15DD
+  [   ea1]  __INT32_MAX__ 2147483647
+  [   eba]  __GCC_ATOMIC_CHAR_LOCK_FREE 2
+  [   ed8]  __DEC128_EPSILON__ 1E-33DL
+  [   ef3]  __UINT_FAST8_TYPE__ unsigned char
+  [   f15]  __amd64 1
+  [   f1f]  __DEC32_MIN_EXP__ (-94)
+  [   f37]  __GCC_HAVE_DWARF2_CFI_ASM 1
+  [   f53]  __LDBL_DIG__ 18
+  [   f63]  __UINT32_MAX__ 4294967295U
+  [   f7e]  __GNUC_GNU_INLINE__ 1
+  [   f94]  __SSE2__ 1
+  [   f9f]  __ATOMIC_HLE_ACQUIRE 65536
+  [   fba]  __SSE_MATH__ 1
+  [   fc9]  __INT_FAST16_MAX__ 9223372036854775807L
+  [   ff1]  __LDBL_MAX__ 1.18973149535723176502e+4932L
+  [  101c]  __DBL_MIN__ ((double)2.22507385850720138309e-308L)
+  [  104f]  __DEC128_MANT_DIG__ 34
+  [  1066]  __INT32_C(c) c
+  [  1075]  __DEC64_MIN_EXP__ (-382)
+  [  108e]  __WCHAR_MIN__ (-__WCHAR_MAX__ - 1)
+  [  10b1]  __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2
+  [  10d3]  __LDBL_MAX_EXP__ 16384
+  [  10ea]  __DEC32_MANT_DIG__ 7
+  [  10ff]  __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL
+  [  1139]  __CHAR32_TYPE__ unsigned int
+  [  1156]  __INT_LEAST8_TYPE__ signed char
+  [  1176]  __UINT16_C(c) c
+  [  1186]  __GCC_ATOMIC_BOOL_LOCK_FREE 2
+  [  11a4]  __SIZEOF_FLOAT__ 4
+  [  11b7]  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_8 1
+  [  11dc]  __DBL_MAX_10_EXP__ 308
+  [  11f3]  __LDBL_EPSILON__ 1.08420217248550443401e-19L
+  [  1220]  __ORDER_PDP_ENDIAN__ 3412
+  [  123a]  __ORDER_LITTLE_ENDIAN__ 1234
+  [  1257]  __WINT_TYPE__ unsigned int
+  [  1272]  __unix 1
+  [  127b]  __ATOMIC_RELAXED 0
+  [  128e]  __UINT_FAST32_MAX__ 18446744073709551615UL
+  [  12b9]  __INT_FAST32_MAX__ 9223372036854775807L
+  [  12e1]  __SIG_ATOMIC_MAX__ 2147483647
+  [  12ff]  __UINT_FAST32_TYPE__ long unsigned int
+  [  1326]  __INT_MAX__ 2147483647
+  [  133d]  __GXX_ABI_VERSION 1002
+  [  1354]  __SIZEOF_INT__ 4
+  [  1365]  char
+  [  136a]  __UINT_FAST16_TYPE__ long unsigned int
+  [  1391]  __LDBL_DENORM_MIN__ 3.64519953188247460253e-4951L
+  [  13c3]  __WINT_MAX__ 4294967295U
+  [  13dc]  __FLT_HAS_INFINITY__ 1
+  [  13f3]  __SHRT_MAX__ 32767
+  [  1406]  __INT_LEAST16_MAX__ 32767
+  [  1420]  __LONG_LONG_MAX__ 9223372036854775807LL
+  [  1448]  __SIZEOF_LONG__ 8
+  [  145a]  __INTMAX_TYPE__ long int
+  [  1473]  __LDBL_HAS_DENORM__ 1
+  [  1489]  __code_model_small__ 1
+  [  14a0]  __REGISTER_PREFIX__ 
+  [  14b5]  __ATOMIC_CONSUME 1
+  [  14c8]  __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL
+  [  150d]  __GNUC__ 4
+  [  1518]  __UINT16_TYPE__ short unsigned int
+  [  153b]  __SSE__ 1
+  [  1545]  __UINT32_C(c) c ## U
+  [  155a]  __k8 1
+  [  1561]  __UINTMAX_C(c) c ## UL
+  [  1578]  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1
+  [  159d]  __SIZEOF_PTRDIFF_T__ 8
+  [  15b4]  __CHAR_BIT__ 8
+  [  15c3]  __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1)
+  [  15f0]  __DEC32_EPSILON__ 1E-6DF
+  [  1609]  __UINT_LEAST32_TYPE__ unsigned int
+  [  162c]  __DBL_HAS_DENORM__ 1
+  [  1641]  /tmp
+  [  1646]  __LDBL_MANT_DIG__ 64
+  [  165b]  __GCC_ATOMIC_LONG_LOCK_FREE 2
+  [  1679]  __DECIMAL_BID_FORMAT__ 1
+  [  1692]  __FLT_MIN_10_EXP__ (-37)
+  [  16ab]  __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 1
+  [  16cf]  __WCHAR_TYPE__ int
+  [  16e2]  __FINITE_MATH_ONLY__ 0
+  [  16f9]  argc
+  [  16fe]  __USER_LABEL_PREFIX__ 
+  [  1715]  __CHAR16_TYPE__ short unsigned int
+  [  1738]  __UINT64_MAX__ 18446744073709551615UL
+  [  175e]  __UINT8_C(c) c
+  [  176d]  __x86_64 1
+  [  1778]  __UINT_LEAST8_TYPE__ unsigned char
+  [  179b]  __INT64_TYPE__ long int
+  [  17b3]  __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1
+  [  17d8]  argv
+  [  17dd]  __GNUC_RH_RELEASE__ 15
+  [  17f4]  __UINT_FAST16_MAX__ 18446744073709551615UL
+  [  181f]  __FLT_HAS_DENORM__ 1
+  [  1834]  __DEC64_MIN__ 1E-383DD
+  [  184b]  __DBL_MIN_10_EXP__ (-307)
+  [  1865]  __FLT_DENORM_MIN__ 1.40129846432481707092e-45F
+  [  1894]  GNU C 4.8.2 20140120 (Red Hat 4.8.2-15) -mtune=generic -march=x86-64 -g3 -O3 -fuse-ld=gold -fno-asynchronous-unwind-tables
+  [  190f]  __SCHAR_MAX__ 127
+EOF
+
+exit 0
diff --git a/tests/run-readelf-zx.sh b/tests/run-readelf-zx.sh
new file mode 100755
index 0000000..994528c
--- /dev/null
+++ b/tests/run-readelf-zx.sh
@@ -0,0 +1,66 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-elfgetchdr.sh for testfiles.
+
+testfiles testfile-zgnu64
+testrun_compare ${abs_top_builddir}/src/readelf -z -x.zdebug_aranges testfile-zgnu64 <<\EOF
+
+Hex dump of section [2] '.zdebug_aranges', 50 bytes (96 uncompressed) at offset 0x260:
+  0x00000000 2c000000 02000000 00000800 00000000 ,...............
+  0x00000010 78004000 00000000 14000000 00000000 x.@.............
+  0x00000020 00000000 00000000 00000000 00000000 ................
+  0x00000030 2c000000 02005500 00000800 00000000 ,.....U.........
+  0x00000040 8c004000 00000000 16000000 00000000 ..@.............
+  0x00000050 00000000 00000000 00000000 00000000 ................
+EOF
+
+testfiles testfile-zgabi64
+testrun_compare ${abs_top_builddir}/src/readelf -z -x.debug_aranges testfile-zgabi64 <<\EOF
+
+Hex dump of section [2] '.debug_aranges', 62 bytes (96 uncompressed) at offset 0x260:
+  0x00000000 2c000000 02000000 00000800 00000000 ,...............
+  0x00000010 78004000 00000000 14000000 00000000 x.@.............
+  0x00000020 00000000 00000000 00000000 00000000 ................
+  0x00000030 2c000000 02005500 00000800 00000000 ,.....U.........
+  0x00000040 8c004000 00000000 16000000 00000000 ..@.............
+  0x00000050 00000000 00000000 00000000 00000000 ................
+EOF
+
+testfiles testfile-zgnu32
+testrun_compare ${abs_top_builddir}/src/readelf -z -x.zdebug_aranges testfile-zgnu32 <<\EOF
+
+Hex dump of section [2] '.zdebug_aranges', 49 bytes (64 uncompressed) at offset 0x1c0:
+  0x00000000 1c000000 02000000 00000400 00000000 ................
+  0x00000010 54800408 14000000 00000000 00000000 T...............
+  0x00000020 1c000000 02004d00 00000400 00000000 ......M.........
+  0x00000030 68800408 16000000 00000000 00000000 h...............
+EOF
+
+testfiles testfile-zgabi32
+testrun_compare ${abs_top_builddir}/src/readelf -z -x.debug_aranges testfile-zgabi32 <<\EOF
+
+Hex dump of section [2] '.debug_aranges', 49 bytes (64 uncompressed) at offset 0x1c0:
+  0x00000000 1c000000 02000000 00000400 00000000 ................
+  0x00000010 54800408 14000000 00000000 00000000 T...............
+  0x00000020 1c000000 02004d00 00000400 00000000 ......M.........
+  0x00000030 68800408 16000000 00000000 00000000 h...............
+EOF
+
+exit 0
diff --git a/tests/run-reloc-bpf.sh b/tests/run-reloc-bpf.sh
new file mode 100755
index 0000000..feb7557
--- /dev/null
+++ b/tests/run-reloc-bpf.sh
@@ -0,0 +1,33 @@
+#! /bin/sh
+# Copyright (C) 2018 Facebook, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# This test file is created with
+# $ cat t.c
+# struct tt {
+#   int a;
+#   char b;
+# };
+# int test(struct tt *t) {
+#    return t->a;
+# }
+# $ clang -O2 -g -emit-llvm -c t.c -o - | llc -march=bpf -filetype=obj -o t.o
+# $ mv t.o testfile-bpf-reloc.o
+
+testfiles testfile-bpf-reloc.o testfile-bpf-reloc.expect
+testrun_compare ${abs_top_builddir}/src/objdump -r testfile-bpf-reloc.o < testfile-bpf-reloc.expect
diff --git a/tests/run-rerequest_tag.sh b/tests/run-rerequest_tag.sh
new file mode 100755
index 0000000..f437284
--- /dev/null
+++ b/tests/run-rerequest_tag.sh
@@ -0,0 +1,25 @@
+#! /bin/sh
+# Copyright (C) 2011 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile56 testfile57
+
+testrun ${abs_builddir}/rerequest_tag testfile56
+testrun ${abs_builddir}/rerequest_tag testfile57
+
+exit 0
diff --git a/tests/run-retain.sh b/tests/run-retain.sh
new file mode 100755
index 0000000..c5376de
--- /dev/null
+++ b/tests/run-retain.sh
@@ -0,0 +1,44 @@
+# Copyright (C) 2020 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# - retian.s
+#   .section        .data.retain,"R" 
+#   .word   1
+#
+# as -o testfile-retain.o retain.s
+
+testfiles testfile-retain.o
+
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile-retain.o << EOF
+There are 9 section headers, starting at offset 0x158:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .text                PROGBITS     0000000000000000 00000040 00000000  0 AX     0   0  1
+[ 2] .data                PROGBITS     0000000000000000 00000040 00000000  0 WA     0   0  1
+[ 3] .bss                 NOBITS       0000000000000000 00000040 00000000  0 WA     0   0  1
+[ 4] .data.retain         PROGBITS     0000000000000000 00000040 00000002  0 WAR    0   0  1
+[ 5] .note.gnu.property   NOTE         0000000000000000 00000048 00000030  0 A      0   0  8
+[ 6] .symtab              SYMTAB       0000000000000000 00000078 00000090 24        7   6  8
+[ 7] .strtab              STRTAB       0000000000000000 00000108 00000001  0        0   0  1
+[ 8] .shstrtab            STRTAB       0000000000000000 00000109 0000004c  0        0   0  1
+
+EOF
+
+testrun ${abs_top_builddir}/src/elflint --gnu testfile-retain.o
diff --git a/tests/run-reverse-sections-self.sh b/tests/run-reverse-sections-self.sh
new file mode 100755
index 0000000..71afd6a
--- /dev/null
+++ b/tests/run-reverse-sections-self.sh
@@ -0,0 +1,45 @@
+#! /bin/sh
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+test_reverse_self ()
+{
+  in_file="$1"
+  base_name="$(basename ${in_file})"
+  out_file="${base_name}.rev"
+  out_file_mmap="${out_file}.mmap"
+
+  tempfiles ${out_file} ${out_file_mmap}
+
+  # Reverse the offsets (the files should still be the same otherwise)
+  testrun ${abs_builddir}/elfcopy --reverse-offs ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elflint --gnu ${out_file}
+  # An in-place nop will likely revert them back
+  testrun ${abs_builddir}/elfrdwrnop ${out_file}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elflint --gnu ${out_file}
+}
+
+# Only really makes sense for ET_REL files, but try all, just to check
+# it also works if we keep the order for the allocated sections.
+for file in $self_test_files; do
+  test_reverse_self $file
+done
+
+exit 0
diff --git a/tests/run-reverse-sections.sh b/tests/run-reverse-sections.sh
new file mode 100755
index 0000000..102a126
--- /dev/null
+++ b/tests/run-reverse-sections.sh
@@ -0,0 +1,69 @@
+#! /bin/sh
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+test_reverse ()
+{
+  in_file="$1"
+  out_file="${in_file}.rev"
+  out_file_mmap="${out_file}.mmap"
+
+  testfiles ${in_file}
+  tempfiles ${out_file} ${out_file_mmap}
+
+  # Reverse the offsets (the files should still be the same otherwise)
+  testrun ${abs_builddir}/elfcopy --reverse-offs ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elflint --gnu ${out_file}
+  # An in-place nop will likely revert them back
+  testrun ${abs_builddir}/elfrdwrnop ${out_file}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elflint --gnu ${out_file}
+}
+
+# A collection of random testfiles to test 32/64bit, little/big endian
+# and non-ET_REL (with phdrs)/ET_REL (without phdrs).
+
+# 32bit, big endian, rel
+test_reverse testfile29
+
+# 64bit, big endian, rel
+test_reverse testfile23
+
+# 32bit, little endian, rel
+test_reverse testfile9
+
+# 64bit, little endian, rel
+test_reverse testfile38
+
+# 32bit, big endian, non-rel
+test_reverse testfile26
+
+# 64bit, big endian, non-rel
+test_reverse testfile27
+
+# 32bit, little endian, non-rel
+test_reverse testfile
+
+# 64bit, little endian, non-rel
+# Don't use testfile10. It has section headers in the middle of the file.
+# Same for testfile12. It is legal, but not the point of this testcase.
+# test_reverse testfile10
+test_reverse testfile13
+
+exit 0
diff --git a/tests/run-show-abbrev.sh b/tests/run-show-abbrev.sh
new file mode 100755
index 0000000..40d0e36
--- /dev/null
+++ b/tests/run-show-abbrev.sh
@@ -0,0 +1,352 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile testfile2
+
+testrun_compare ${abs_builddir}/show-abbrev testfile testfile2 <<\EOF
+abbrev[0]: code = 1, tag = 17, children = 1
+abbrev[0]: attr[0]: code = 16, form = 6, offset = 0
+abbrev[0]: attr[1]: code = 18, form = 1, offset = 2
+abbrev[0]: attr[2]: code = 17, form = 1, offset = 4
+abbrev[0]: attr[3]: code = 3, form = 8, offset = 6
+abbrev[0]: attr[4]: code = 27, form = 8, offset = 8
+abbrev[0]: attr[5]: code = 37, form = 8, offset = 10
+abbrev[0]: attr[6]: code = 19, form = 11, offset = 12
+abbrev[19]: code = 2, tag = 46, children = 1
+abbrev[19]: attr[0]: code = 1, form = 19, offset = 19
+abbrev[19]: attr[1]: code = 63, form = 12, offset = 21
+abbrev[19]: attr[2]: code = 3, form = 8, offset = 23
+abbrev[19]: attr[3]: code = 58, form = 11, offset = 25
+abbrev[19]: attr[4]: code = 59, form = 11, offset = 27
+abbrev[19]: attr[5]: code = 39, form = 12, offset = 29
+abbrev[19]: attr[6]: code = 73, form = 19, offset = 31
+abbrev[19]: attr[7]: code = 17, form = 1, offset = 33
+abbrev[19]: attr[8]: code = 18, form = 1, offset = 35
+abbrev[19]: attr[9]: code = 64, form = 10, offset = 37
+abbrev[44]: code = 3, tag = 46, children = 1
+abbrev[44]: attr[0]: code = 1, form = 19, offset = 44
+abbrev[44]: attr[1]: code = 63, form = 12, offset = 46
+abbrev[44]: attr[2]: code = 3, form = 8, offset = 48
+abbrev[44]: attr[3]: code = 58, form = 11, offset = 50
+abbrev[44]: attr[4]: code = 59, form = 11, offset = 52
+abbrev[44]: attr[5]: code = 73, form = 19, offset = 54
+abbrev[44]: attr[6]: code = 60, form = 12, offset = 56
+abbrev[63]: code = 4, tag = 24, children = 0
+abbrev[68]: code = 5, tag = 46, children = 1
+abbrev[68]: attr[0]: code = 63, form = 12, offset = 68
+abbrev[68]: attr[1]: code = 3, form = 8, offset = 70
+abbrev[68]: attr[2]: code = 58, form = 11, offset = 72
+abbrev[68]: attr[3]: code = 59, form = 11, offset = 74
+abbrev[68]: attr[4]: code = 73, form = 19, offset = 76
+abbrev[68]: attr[5]: code = 60, form = 12, offset = 78
+abbrev[85]: code = 6, tag = 36, children = 0
+abbrev[85]: attr[0]: code = 3, form = 8, offset = 85
+abbrev[85]: attr[1]: code = 11, form = 11, offset = 87
+abbrev[85]: attr[2]: code = 62, form = 11, offset = 89
+abbrev[96]: code = 7, tag = 52, children = 0
+abbrev[96]: attr[0]: code = 3, form = 8, offset = 96
+abbrev[96]: attr[1]: code = 58, form = 11, offset = 98
+abbrev[96]: attr[2]: code = 59, form = 11, offset = 100
+abbrev[96]: attr[3]: code = 73, form = 19, offset = 102
+abbrev[96]: attr[4]: code = 63, form = 12, offset = 104
+abbrev[96]: attr[5]: code = 2, form = 10, offset = 106
+abbrev[0]: code = 1, tag = 17, children = 1
+abbrev[0]: attr[0]: code = 16, form = 6, offset = 114
+abbrev[0]: attr[1]: code = 18, form = 1, offset = 116
+abbrev[0]: attr[2]: code = 17, form = 1, offset = 118
+abbrev[0]: attr[3]: code = 3, form = 8, offset = 120
+abbrev[0]: attr[4]: code = 27, form = 8, offset = 122
+abbrev[0]: attr[5]: code = 37, form = 8, offset = 124
+abbrev[0]: attr[6]: code = 19, form = 11, offset = 126
+abbrev[19]: code = 2, tag = 46, children = 0
+abbrev[19]: attr[0]: code = 63, form = 12, offset = 133
+abbrev[19]: attr[1]: code = 3, form = 8, offset = 135
+abbrev[19]: attr[2]: code = 58, form = 11, offset = 137
+abbrev[19]: attr[3]: code = 59, form = 11, offset = 139
+abbrev[19]: attr[4]: code = 39, form = 12, offset = 141
+abbrev[19]: attr[5]: code = 73, form = 19, offset = 143
+abbrev[19]: attr[6]: code = 17, form = 1, offset = 145
+abbrev[19]: attr[7]: code = 18, form = 1, offset = 147
+abbrev[19]: attr[8]: code = 64, form = 10, offset = 149
+abbrev[42]: code = 3, tag = 36, children = 0
+abbrev[42]: attr[0]: code = 3, form = 8, offset = 156
+abbrev[42]: attr[1]: code = 11, form = 11, offset = 158
+abbrev[42]: attr[2]: code = 62, form = 11, offset = 160
+abbrev[53]: code = 4, tag = 22, children = 0
+abbrev[53]: attr[0]: code = 3, form = 8, offset = 167
+abbrev[53]: attr[1]: code = 58, form = 11, offset = 169
+abbrev[53]: attr[2]: code = 59, form = 11, offset = 171
+abbrev[53]: attr[3]: code = 73, form = 19, offset = 173
+abbrev[66]: code = 5, tag = 15, children = 0
+abbrev[66]: attr[0]: code = 11, form = 11, offset = 180
+abbrev[73]: code = 6, tag = 15, children = 0
+abbrev[73]: attr[0]: code = 11, form = 11, offset = 187
+abbrev[73]: attr[1]: code = 73, form = 19, offset = 189
+abbrev[82]: code = 7, tag = 19, children = 1
+abbrev[82]: attr[0]: code = 1, form = 19, offset = 196
+abbrev[82]: attr[1]: code = 11, form = 11, offset = 198
+abbrev[82]: attr[2]: code = 58, form = 11, offset = 200
+abbrev[82]: attr[3]: code = 59, form = 11, offset = 202
+abbrev[95]: code = 8, tag = 13, children = 0
+abbrev[95]: attr[0]: code = 3, form = 8, offset = 209
+abbrev[95]: attr[1]: code = 58, form = 11, offset = 211
+abbrev[95]: attr[2]: code = 59, form = 11, offset = 213
+abbrev[95]: attr[3]: code = 73, form = 19, offset = 215
+abbrev[95]: attr[4]: code = 56, form = 10, offset = 217
+abbrev[110]: code = 9, tag = 1, children = 1
+abbrev[110]: attr[0]: code = 1, form = 19, offset = 224
+abbrev[110]: attr[1]: code = 73, form = 19, offset = 226
+abbrev[119]: code = 10, tag = 33, children = 0
+abbrev[119]: attr[0]: code = 73, form = 19, offset = 233
+abbrev[119]: attr[1]: code = 47, form = 11, offset = 235
+abbrev[128]: code = 11, tag = 19, children = 1
+abbrev[128]: attr[0]: code = 1, form = 19, offset = 242
+abbrev[128]: attr[1]: code = 3, form = 8, offset = 244
+abbrev[128]: attr[2]: code = 11, form = 11, offset = 246
+abbrev[128]: attr[3]: code = 58, form = 11, offset = 248
+abbrev[128]: attr[4]: code = 59, form = 11, offset = 250
+abbrev[143]: code = 12, tag = 19, children = 0
+abbrev[143]: attr[0]: code = 3, form = 8, offset = 257
+abbrev[143]: attr[1]: code = 60, form = 12, offset = 259
+abbrev[152]: code = 13, tag = 13, children = 0
+abbrev[152]: attr[0]: code = 3, form = 8, offset = 266
+abbrev[152]: attr[1]: code = 58, form = 11, offset = 268
+abbrev[152]: attr[2]: code = 59, form = 5, offset = 270
+abbrev[152]: attr[3]: code = 73, form = 19, offset = 272
+abbrev[152]: attr[4]: code = 56, form = 10, offset = 274
+abbrev[167]: code = 14, tag = 22, children = 0
+abbrev[167]: attr[0]: code = 3, form = 8, offset = 281
+abbrev[167]: attr[1]: code = 58, form = 11, offset = 283
+abbrev[167]: attr[2]: code = 59, form = 5, offset = 285
+abbrev[167]: attr[3]: code = 73, form = 19, offset = 287
+abbrev[180]: code = 15, tag = 23, children = 1
+abbrev[180]: attr[0]: code = 1, form = 19, offset = 294
+abbrev[180]: attr[1]: code = 11, form = 11, offset = 296
+abbrev[180]: attr[2]: code = 58, form = 11, offset = 298
+abbrev[180]: attr[3]: code = 59, form = 11, offset = 300
+abbrev[193]: code = 16, tag = 13, children = 0
+abbrev[193]: attr[0]: code = 3, form = 8, offset = 307
+abbrev[193]: attr[1]: code = 58, form = 11, offset = 309
+abbrev[193]: attr[2]: code = 59, form = 11, offset = 311
+abbrev[193]: attr[3]: code = 73, form = 19, offset = 313
+abbrev[206]: code = 17, tag = 4, children = 1
+abbrev[206]: attr[0]: code = 1, form = 19, offset = 320
+abbrev[206]: attr[1]: code = 11, form = 11, offset = 322
+abbrev[206]: attr[2]: code = 58, form = 11, offset = 324
+abbrev[206]: attr[3]: code = 59, form = 11, offset = 326
+abbrev[219]: code = 18, tag = 40, children = 0
+abbrev[219]: attr[0]: code = 3, form = 8, offset = 333
+abbrev[219]: attr[1]: code = 28, form = 11, offset = 335
+abbrev[228]: code = 19, tag = 38, children = 0
+abbrev[228]: attr[0]: code = 73, form = 19, offset = 342
+abbrev[235]: code = 20, tag = 21, children = 1
+abbrev[235]: attr[0]: code = 1, form = 19, offset = 349
+abbrev[235]: attr[1]: code = 39, form = 12, offset = 351
+abbrev[235]: attr[2]: code = 73, form = 19, offset = 353
+abbrev[246]: code = 21, tag = 5, children = 0
+abbrev[246]: attr[0]: code = 73, form = 19, offset = 360
+abbrev[253]: code = 22, tag = 21, children = 1
+abbrev[253]: attr[0]: code = 1, form = 19, offset = 367
+abbrev[253]: attr[1]: code = 39, form = 12, offset = 369
+abbrev[262]: code = 23, tag = 33, children = 0
+abbrev[262]: attr[0]: code = 73, form = 19, offset = 376
+abbrev[262]: attr[1]: code = 47, form = 6, offset = 378
+abbrev[271]: code = 24, tag = 22, children = 0
+abbrev[271]: attr[0]: code = 3, form = 8, offset = 385
+abbrev[271]: attr[1]: code = 58, form = 11, offset = 387
+abbrev[271]: attr[2]: code = 59, form = 11, offset = 389
+abbrev[282]: code = 25, tag = 4, children = 1
+abbrev[282]: attr[0]: code = 1, form = 19, offset = 396
+abbrev[282]: attr[1]: code = 3, form = 8, offset = 398
+abbrev[282]: attr[2]: code = 11, form = 11, offset = 400
+abbrev[282]: attr[3]: code = 58, form = 11, offset = 402
+abbrev[282]: attr[4]: code = 59, form = 11, offset = 404
+abbrev[0]: code = 1, tag = 17, children = 1
+abbrev[0]: attr[0]: code = 16, form = 6, offset = 412
+abbrev[0]: attr[1]: code = 18, form = 1, offset = 414
+abbrev[0]: attr[2]: code = 17, form = 1, offset = 416
+abbrev[0]: attr[3]: code = 3, form = 8, offset = 418
+abbrev[0]: attr[4]: code = 27, form = 8, offset = 420
+abbrev[0]: attr[5]: code = 37, form = 8, offset = 422
+abbrev[0]: attr[6]: code = 19, form = 11, offset = 424
+abbrev[19]: code = 2, tag = 46, children = 0
+abbrev[19]: attr[0]: code = 63, form = 12, offset = 431
+abbrev[19]: attr[1]: code = 3, form = 8, offset = 433
+abbrev[19]: attr[2]: code = 58, form = 11, offset = 435
+abbrev[19]: attr[3]: code = 59, form = 11, offset = 437
+abbrev[19]: attr[4]: code = 39, form = 12, offset = 439
+abbrev[19]: attr[5]: code = 73, form = 19, offset = 441
+abbrev[19]: attr[6]: code = 17, form = 1, offset = 443
+abbrev[19]: attr[7]: code = 18, form = 1, offset = 445
+abbrev[19]: attr[8]: code = 64, form = 10, offset = 447
+abbrev[42]: code = 3, tag = 36, children = 0
+abbrev[42]: attr[0]: code = 3, form = 8, offset = 454
+abbrev[42]: attr[1]: code = 11, form = 11, offset = 456
+abbrev[42]: attr[2]: code = 62, form = 11, offset = 458
+abbrev[0]: code = 1, tag = 17, children = 1
+abbrev[0]: attr[0]: code = 16, form = 6, offset = 0
+abbrev[0]: attr[1]: code = 18, form = 1, offset = 2
+abbrev[0]: attr[2]: code = 17, form = 1, offset = 4
+abbrev[0]: attr[3]: code = 3, form = 8, offset = 6
+abbrev[0]: attr[4]: code = 27, form = 8, offset = 8
+abbrev[0]: attr[5]: code = 37, form = 8, offset = 10
+abbrev[0]: attr[6]: code = 19, form = 11, offset = 12
+abbrev[19]: code = 2, tag = 46, children = 0
+abbrev[19]: attr[0]: code = 63, form = 12, offset = 19
+abbrev[19]: attr[1]: code = 3, form = 8, offset = 21
+abbrev[19]: attr[2]: code = 58, form = 11, offset = 23
+abbrev[19]: attr[3]: code = 59, form = 11, offset = 25
+abbrev[19]: attr[4]: code = 39, form = 12, offset = 27
+abbrev[19]: attr[5]: code = 73, form = 19, offset = 29
+abbrev[19]: attr[6]: code = 17, form = 1, offset = 31
+abbrev[19]: attr[7]: code = 18, form = 1, offset = 33
+abbrev[19]: attr[8]: code = 64, form = 10, offset = 35
+abbrev[42]: code = 3, tag = 36, children = 0
+abbrev[42]: attr[0]: code = 3, form = 8, offset = 42
+abbrev[42]: attr[1]: code = 11, form = 11, offset = 44
+abbrev[42]: attr[2]: code = 62, form = 11, offset = 46
+abbrev[53]: code = 4, tag = 22, children = 0
+abbrev[53]: attr[0]: code = 3, form = 8, offset = 53
+abbrev[53]: attr[1]: code = 58, form = 11, offset = 55
+abbrev[53]: attr[2]: code = 59, form = 11, offset = 57
+abbrev[53]: attr[3]: code = 73, form = 19, offset = 59
+abbrev[66]: code = 5, tag = 1, children = 1
+abbrev[66]: attr[0]: code = 1, form = 19, offset = 66
+abbrev[66]: attr[1]: code = 3, form = 8, offset = 68
+abbrev[66]: attr[2]: code = 73, form = 19, offset = 70
+abbrev[77]: code = 6, tag = 33, children = 0
+abbrev[77]: attr[0]: code = 73, form = 19, offset = 77
+abbrev[77]: attr[1]: code = 47, form = 11, offset = 79
+abbrev[86]: code = 7, tag = 19, children = 1
+abbrev[86]: attr[0]: code = 1, form = 19, offset = 86
+abbrev[86]: attr[1]: code = 3, form = 8, offset = 88
+abbrev[86]: attr[2]: code = 11, form = 11, offset = 90
+abbrev[86]: attr[3]: code = 58, form = 11, offset = 92
+abbrev[86]: attr[4]: code = 59, form = 11, offset = 94
+abbrev[101]: code = 8, tag = 13, children = 0
+abbrev[101]: attr[0]: code = 3, form = 8, offset = 101
+abbrev[101]: attr[1]: code = 58, form = 11, offset = 103
+abbrev[101]: attr[2]: code = 59, form = 11, offset = 105
+abbrev[101]: attr[3]: code = 73, form = 19, offset = 107
+abbrev[101]: attr[4]: code = 56, form = 10, offset = 109
+abbrev[116]: code = 9, tag = 15, children = 0
+abbrev[116]: attr[0]: code = 11, form = 11, offset = 116
+abbrev[123]: code = 10, tag = 15, children = 0
+abbrev[123]: attr[0]: code = 11, form = 11, offset = 123
+abbrev[123]: attr[1]: code = 73, form = 19, offset = 125
+abbrev[132]: code = 11, tag = 19, children = 1
+abbrev[132]: attr[0]: code = 1, form = 19, offset = 132
+abbrev[132]: attr[1]: code = 11, form = 11, offset = 134
+abbrev[132]: attr[2]: code = 58, form = 11, offset = 136
+abbrev[132]: attr[3]: code = 59, form = 11, offset = 138
+abbrev[145]: code = 12, tag = 1, children = 1
+abbrev[145]: attr[0]: code = 1, form = 19, offset = 145
+abbrev[145]: attr[1]: code = 73, form = 19, offset = 147
+abbrev[154]: code = 13, tag = 22, children = 0
+abbrev[154]: attr[0]: code = 3, form = 8, offset = 154
+abbrev[154]: attr[1]: code = 58, form = 11, offset = 156
+abbrev[154]: attr[2]: code = 59, form = 5, offset = 158
+abbrev[154]: attr[3]: code = 73, form = 19, offset = 160
+abbrev[167]: code = 14, tag = 19, children = 0
+abbrev[167]: attr[0]: code = 3, form = 8, offset = 167
+abbrev[167]: attr[1]: code = 60, form = 12, offset = 169
+abbrev[176]: code = 15, tag = 22, children = 0
+abbrev[176]: attr[0]: code = 3, form = 8, offset = 176
+abbrev[176]: attr[1]: code = 58, form = 11, offset = 178
+abbrev[176]: attr[2]: code = 59, form = 11, offset = 180
+abbrev[187]: code = 16, tag = 21, children = 1
+abbrev[187]: attr[0]: code = 1, form = 19, offset = 187
+abbrev[187]: attr[1]: code = 39, form = 12, offset = 189
+abbrev[187]: attr[2]: code = 73, form = 19, offset = 191
+abbrev[198]: code = 17, tag = 5, children = 0
+abbrev[198]: attr[0]: code = 73, form = 19, offset = 198
+abbrev[205]: code = 18, tag = 38, children = 0
+abbrev[205]: attr[0]: code = 73, form = 19, offset = 205
+abbrev[0]: code = 1, tag = 17, children = 1
+abbrev[0]: attr[0]: code = 16, form = 6, offset = 213
+abbrev[0]: attr[1]: code = 18, form = 1, offset = 215
+abbrev[0]: attr[2]: code = 17, form = 1, offset = 217
+abbrev[0]: attr[3]: code = 3, form = 8, offset = 219
+abbrev[0]: attr[4]: code = 27, form = 8, offset = 221
+abbrev[0]: attr[5]: code = 37, form = 8, offset = 223
+abbrev[0]: attr[6]: code = 19, form = 11, offset = 225
+abbrev[19]: code = 2, tag = 46, children = 0
+abbrev[19]: attr[0]: code = 63, form = 12, offset = 232
+abbrev[19]: attr[1]: code = 3, form = 8, offset = 234
+abbrev[19]: attr[2]: code = 58, form = 11, offset = 236
+abbrev[19]: attr[3]: code = 59, form = 11, offset = 238
+abbrev[19]: attr[4]: code = 39, form = 12, offset = 240
+abbrev[19]: attr[5]: code = 73, form = 19, offset = 242
+abbrev[19]: attr[6]: code = 17, form = 1, offset = 244
+abbrev[19]: attr[7]: code = 18, form = 1, offset = 246
+abbrev[19]: attr[8]: code = 64, form = 10, offset = 248
+abbrev[42]: code = 3, tag = 36, children = 0
+abbrev[42]: attr[0]: code = 3, form = 8, offset = 255
+abbrev[42]: attr[1]: code = 11, form = 11, offset = 257
+abbrev[42]: attr[2]: code = 62, form = 11, offset = 259
+abbrev[0]: code = 1, tag = 17, children = 1
+abbrev[0]: attr[0]: code = 16, form = 6, offset = 267
+abbrev[0]: attr[1]: code = 18, form = 1, offset = 269
+abbrev[0]: attr[2]: code = 17, form = 1, offset = 271
+abbrev[0]: attr[3]: code = 3, form = 8, offset = 273
+abbrev[0]: attr[4]: code = 27, form = 8, offset = 275
+abbrev[0]: attr[5]: code = 37, form = 8, offset = 277
+abbrev[0]: attr[6]: code = 19, form = 11, offset = 279
+abbrev[19]: code = 2, tag = 46, children = 1
+abbrev[19]: attr[0]: code = 1, form = 19, offset = 286
+abbrev[19]: attr[1]: code = 63, form = 12, offset = 288
+abbrev[19]: attr[2]: code = 3, form = 8, offset = 290
+abbrev[19]: attr[3]: code = 58, form = 11, offset = 292
+abbrev[19]: attr[4]: code = 59, form = 11, offset = 294
+abbrev[19]: attr[5]: code = 39, form = 12, offset = 296
+abbrev[19]: attr[6]: code = 73, form = 19, offset = 298
+abbrev[19]: attr[7]: code = 17, form = 1, offset = 300
+abbrev[19]: attr[8]: code = 18, form = 1, offset = 302
+abbrev[19]: attr[9]: code = 64, form = 10, offset = 304
+abbrev[44]: code = 3, tag = 46, children = 1
+abbrev[44]: attr[0]: code = 1, form = 19, offset = 311
+abbrev[44]: attr[1]: code = 63, form = 12, offset = 313
+abbrev[44]: attr[2]: code = 3, form = 8, offset = 315
+abbrev[44]: attr[3]: code = 58, form = 11, offset = 317
+abbrev[44]: attr[4]: code = 59, form = 11, offset = 319
+abbrev[44]: attr[5]: code = 73, form = 19, offset = 321
+abbrev[44]: attr[6]: code = 60, form = 12, offset = 323
+abbrev[63]: code = 4, tag = 24, children = 0
+abbrev[68]: code = 5, tag = 46, children = 1
+abbrev[68]: attr[0]: code = 63, form = 12, offset = 335
+abbrev[68]: attr[1]: code = 3, form = 8, offset = 337
+abbrev[68]: attr[2]: code = 58, form = 11, offset = 339
+abbrev[68]: attr[3]: code = 59, form = 11, offset = 341
+abbrev[68]: attr[4]: code = 73, form = 19, offset = 343
+abbrev[68]: attr[5]: code = 60, form = 12, offset = 345
+abbrev[85]: code = 6, tag = 36, children = 0
+abbrev[85]: attr[0]: code = 3, form = 8, offset = 352
+abbrev[85]: attr[1]: code = 11, form = 11, offset = 354
+abbrev[85]: attr[2]: code = 62, form = 11, offset = 356
+abbrev[96]: code = 7, tag = 52, children = 0
+abbrev[96]: attr[0]: code = 3, form = 8, offset = 363
+abbrev[96]: attr[1]: code = 58, form = 11, offset = 365
+abbrev[96]: attr[2]: code = 59, form = 11, offset = 367
+abbrev[96]: attr[3]: code = 73, form = 19, offset = 369
+abbrev[96]: attr[4]: code = 63, form = 12, offset = 371
+abbrev[96]: attr[5]: code = 2, form = 10, offset = 373
+EOF
+
+exit 0
diff --git a/tests/run-show-die-info.sh b/tests/run-show-die-info.sh
new file mode 100755
index 0000000..f92ee48
--- /dev/null
+++ b/tests/run-show-die-info.sh
@@ -0,0 +1,985 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile5 testfile2
+
+testrun_compare ${abs_builddir}/show-die-info testfile5 testfile2 <<\EOF
+file: testfile5
+New CU: off = 0, hsize = 11, ab = 0, as = 4, os = 4
+     DW_TAG_compile_unit
+      Name      : b.c
+      Offset    : 11
+      CU offset : 11
+      Attrs     : name stmt_list low_pc high_pc language comp_dir producer
+      low PC    : 0x804842c
+      high PC   : 0x8048436
+      language  : 1
+      directory : /home/drepper/gnu/new-bu/build/ttt
+      producer  : GNU C 2.96 20000731 (Red Hat Linux 7.0)
+          DW_TAG_subprogram
+           Name      : bar
+           Offset    : 104
+           CU offset : 104
+           Attrs     : name low_pc high_pc prototyped decl_file decl_line external frame_base type
+           low PC    : 0x804842c
+           high PC   : 0x8048436
+          DW_TAG_base_type
+           Name      : int
+           Offset    : 127
+           CU offset : 127
+           Attrs     : name byte_size encoding
+           byte size : 4
+New CU: off = 135, hsize = 11, ab = 54, as = 4, os = 4
+     DW_TAG_compile_unit
+      Name      : f.c
+      Offset    : 146
+      CU offset : 11
+      Attrs     : name stmt_list low_pc high_pc language comp_dir producer
+      low PC    : 0x8048438
+      high PC   : 0x8048442
+      language  : 1
+      directory : /home/drepper/gnu/new-bu/build/ttt
+      producer  : GNU C 2.96 20000731 (Red Hat Linux 7.0)
+          DW_TAG_subprogram
+           Name      : foo
+           Offset    : 239
+           CU offset : 104
+           Attrs     : name low_pc high_pc prototyped decl_file decl_line external frame_base type
+           low PC    : 0x8048438
+           high PC   : 0x8048442
+          DW_TAG_base_type
+           Name      : int
+           Offset    : 262
+           CU offset : 127
+           Attrs     : name byte_size encoding
+           byte size : 4
+New CU: off = 270, hsize = 11, ab = 108, as = 4, os = 4
+     DW_TAG_compile_unit
+      Name      : m.c
+      Offset    : 281
+      CU offset : 11
+      Attrs     : name stmt_list low_pc high_pc language comp_dir producer
+      low PC    : 0x8048444
+      high PC   : 0x8048472
+      language  : 1
+      directory : /home/drepper/gnu/new-bu/build/ttt
+      producer  : GNU C 2.96 20000731 (Red Hat Linux 7.0)
+          DW_TAG_subprogram
+           Name      : main
+           Offset    : 374
+           CU offset : 104
+           Attrs     : sibling name low_pc high_pc prototyped decl_file decl_line external frame_base type
+           low PC    : 0x8048444
+           high PC   : 0x8048472
+               DW_TAG_subprogram
+                Name      : bar
+                Offset    : 402
+                CU offset : 132
+                Attrs     : sibling name decl_file decl_line declaration external type
+                    DW_TAG_unspecified_parameters
+                     Name      : * NO NAME *
+                     Offset    : 419
+                     CU offset : 149
+                     Attrs     :
+               DW_TAG_subprogram
+                Name      : foo
+                Offset    : 421
+                CU offset : 151
+                Attrs     : name decl_file decl_line declaration external type
+                    DW_TAG_unspecified_parameters
+                     Name      : * NO NAME *
+                     Offset    : 434
+                     CU offset : 164
+                     Attrs     :
+          DW_TAG_base_type
+           Name      : int
+           Offset    : 437
+           CU offset : 167
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_variable
+           Name      : a
+           Offset    : 444
+           CU offset : 174
+           Attrs     : location name decl_file decl_line external type
+file: testfile2
+New CU: off = 0, hsize = 11, ab = 0, as = 4, os = 4
+     DW_TAG_compile_unit
+      Name      : b.c
+      Offset    : 11
+      CU offset : 11
+      Attrs     : name stmt_list low_pc high_pc language comp_dir producer
+      low PC    : 0x10000470
+      high PC   : 0x10000490
+      language  : 1
+      directory : /shoggoth/drepper
+      producer  : GNU C 2.96-laurel-000912
+          DW_TAG_subprogram
+           Name      : bar
+           Offset    : 72
+           CU offset : 72
+           Attrs     : name low_pc high_pc prototyped decl_file decl_line external frame_base type
+           low PC    : 0x10000470
+           high PC   : 0x10000490
+          DW_TAG_base_type
+           Name      : int
+           Offset    : 95
+           CU offset : 95
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_typedef
+           Name      : size_t
+           Offset    : 102
+           CU offset : 102
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : unsigned int
+           Offset    : 116
+           CU offset : 116
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_typedef
+           Name      : __gnuc_va_list
+           Offset    : 132
+           CU offset : 132
+           Attrs     : name decl_file decl_line type
+          DW_TAG_array_type
+           Name      : __builtin_va_list
+           Offset    : 154
+           CU offset : 154
+           Attrs     : sibling name type
+               DW_TAG_subrange_type
+                Name      : * NO NAME *
+                Offset    : 181
+                CU offset : 181
+                Attrs     : upper_bound type
+          DW_TAG_base_type
+           Name      : unsigned int
+           Offset    : 188
+           CU offset : 188
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_structure_type
+           Name      : __va_list_tag
+           Offset    : 204
+           CU offset : 204
+           Attrs     : sibling name byte_size decl_file decl_line
+           byte size : 12
+               DW_TAG_member
+                Name      : gpr
+                Offset    : 226
+                CU offset : 226
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : fpr
+                Offset    : 240
+                CU offset : 240
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : overflow_arg_area
+                Offset    : 254
+                CU offset : 254
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : reg_save_area
+                Offset    : 282
+                CU offset : 282
+                Attrs     : name data_member_location decl_file decl_line type
+          DW_TAG_base_type
+           Name      : unsigned char
+           Offset    : 307
+           CU offset : 307
+           Attrs     : name byte_size encoding
+           byte size : 1
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 324
+           CU offset : 324
+           Attrs     : byte_size
+           byte size : 4
+          DW_TAG_typedef
+           Name      : __u_char
+           Offset    : 326
+           CU offset : 326
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __u_short
+           Offset    : 342
+           CU offset : 342
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : short unsigned int
+           Offset    : 359
+           CU offset : 359
+           Attrs     : name byte_size encoding
+           byte size : 2
+          DW_TAG_typedef
+           Name      : __u_int
+           Offset    : 381
+           CU offset : 381
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __u_long
+           Offset    : 396
+           CU offset : 396
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : long unsigned int
+           Offset    : 412
+           CU offset : 412
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_typedef
+           Name      : __u_quad_t
+           Offset    : 433
+           CU offset : 433
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : long long unsigned int
+           Offset    : 451
+           CU offset : 451
+           Attrs     : name byte_size encoding
+           byte size : 8
+          DW_TAG_typedef
+           Name      : __quad_t
+           Offset    : 477
+           CU offset : 477
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : long long int
+           Offset    : 493
+           CU offset : 493
+           Attrs     : name byte_size encoding
+           byte size : 8
+          DW_TAG_typedef
+           Name      : __int8_t
+           Offset    : 510
+           CU offset : 510
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : signed char
+           Offset    : 526
+           CU offset : 526
+           Attrs     : name byte_size encoding
+           byte size : 1
+          DW_TAG_typedef
+           Name      : __uint8_t
+           Offset    : 541
+           CU offset : 541
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __int16_t
+           Offset    : 558
+           CU offset : 558
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : short int
+           Offset    : 575
+           CU offset : 575
+           Attrs     : name byte_size encoding
+           byte size : 2
+          DW_TAG_typedef
+           Name      : __uint16_t
+           Offset    : 588
+           CU offset : 588
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __int32_t
+           Offset    : 606
+           CU offset : 606
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __uint32_t
+           Offset    : 623
+           CU offset : 623
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __int64_t
+           Offset    : 641
+           CU offset : 641
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __uint64_t
+           Offset    : 658
+           CU offset : 658
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __qaddr_t
+           Offset    : 676
+           CU offset : 676
+           Attrs     : name decl_file decl_line type
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 693
+           CU offset : 693
+           Attrs     : byte_size type
+           byte size : 4
+          DW_TAG_typedef
+           Name      : __dev_t
+           Offset    : 699
+           CU offset : 699
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __uid_t
+           Offset    : 714
+           CU offset : 714
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __gid_t
+           Offset    : 729
+           CU offset : 729
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __ino_t
+           Offset    : 744
+           CU offset : 744
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __mode_t
+           Offset    : 759
+           CU offset : 759
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __nlink_t
+           Offset    : 775
+           CU offset : 775
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __off_t
+           Offset    : 792
+           CU offset : 792
+           Attrs     : name decl_file decl_line type
+          DW_TAG_base_type
+           Name      : long int
+           Offset    : 807
+           CU offset : 807
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_typedef
+           Name      : __loff_t
+           Offset    : 819
+           CU offset : 819
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __pid_t
+           Offset    : 835
+           CU offset : 835
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __ssize_t
+           Offset    : 850
+           CU offset : 850
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __rlim_t
+           Offset    : 867
+           CU offset : 867
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __rlim64_t
+           Offset    : 883
+           CU offset : 883
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __id_t
+           Offset    : 901
+           CU offset : 901
+           Attrs     : name decl_file decl_line type
+          DW_TAG_structure_type
+           Name      : * NO NAME *
+           Offset    : 915
+           CU offset : 915
+           Attrs     : sibling byte_size decl_file decl_line
+           byte size : 8
+               DW_TAG_member
+                Name      : __val
+                Offset    : 923
+                CU offset : 923
+                Attrs     : name data_member_location decl_file decl_line type
+          DW_TAG_array_type
+           Name      : * NO NAME *
+           Offset    : 940
+           CU offset : 940
+           Attrs     : sibling type
+               DW_TAG_subrange_type
+                Name      : * NO NAME *
+                Offset    : 949
+                CU offset : 949
+                Attrs     : upper_bound type
+          DW_TAG_typedef
+           Name      : __fsid_t
+           Offset    : 956
+           CU offset : 956
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __daddr_t
+           Offset    : 972
+           CU offset : 972
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __caddr_t
+           Offset    : 989
+           CU offset : 989
+           Attrs     : name decl_file decl_line type
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 1006
+           CU offset : 1006
+           Attrs     : byte_size type
+           byte size : 4
+          DW_TAG_base_type
+           Name      : char
+           Offset    : 1012
+           CU offset : 1012
+           Attrs     : name byte_size encoding
+           byte size : 1
+          DW_TAG_typedef
+           Name      : __time_t
+           Offset    : 1020
+           CU offset : 1020
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __swblk_t
+           Offset    : 1036
+           CU offset : 1036
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __clock_t
+           Offset    : 1053
+           CU offset : 1053
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __fd_mask
+           Offset    : 1070
+           CU offset : 1070
+           Attrs     : name decl_file decl_line type
+          DW_TAG_structure_type
+           Name      : * NO NAME *
+           Offset    : 1087
+           CU offset : 1087
+           Attrs     : sibling byte_size decl_file decl_line
+           byte size : 128
+               DW_TAG_member
+                Name      : __fds_bits
+                Offset    : 1095
+                CU offset : 1095
+                Attrs     : name data_member_location decl_file decl_line type
+          DW_TAG_array_type
+           Name      : * NO NAME *
+           Offset    : 1117
+           CU offset : 1117
+           Attrs     : sibling type
+               DW_TAG_subrange_type
+                Name      : * NO NAME *
+                Offset    : 1126
+                CU offset : 1126
+                Attrs     : upper_bound type
+          DW_TAG_typedef
+           Name      : __fd_set
+           Offset    : 1133
+           CU offset : 1133
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __key_t
+           Offset    : 1149
+           CU offset : 1149
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __ipc_pid_t
+           Offset    : 1164
+           CU offset : 1164
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __blkcnt_t
+           Offset    : 1183
+           CU offset : 1183
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __blkcnt64_t
+           Offset    : 1201
+           CU offset : 1201
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __fsblkcnt_t
+           Offset    : 1221
+           CU offset : 1221
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __fsblkcnt64_t
+           Offset    : 1241
+           CU offset : 1241
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __fsfilcnt_t
+           Offset    : 1263
+           CU offset : 1263
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __fsfilcnt64_t
+           Offset    : 1283
+           CU offset : 1283
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __ino64_t
+           Offset    : 1305
+           CU offset : 1305
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __off64_t
+           Offset    : 1322
+           CU offset : 1322
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __t_scalar_t
+           Offset    : 1339
+           CU offset : 1339
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __t_uscalar_t
+           Offset    : 1359
+           CU offset : 1359
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : __intptr_t
+           Offset    : 1380
+           CU offset : 1380
+           Attrs     : name decl_file decl_line type
+          DW_TAG_structure_type
+           Name      : _IO_FILE
+           Offset    : 1398
+           CU offset : 1398
+           Attrs     : sibling name byte_size decl_file decl_line
+           byte size : 152
+               DW_TAG_member
+                Name      : _flags
+                Offset    : 1415
+                CU offset : 1415
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_read_ptr
+                Offset    : 1432
+                CU offset : 1432
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_read_end
+                Offset    : 1455
+                CU offset : 1455
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_read_base
+                Offset    : 1478
+                CU offset : 1478
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_write_base
+                Offset    : 1502
+                CU offset : 1502
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_write_ptr
+                Offset    : 1527
+                CU offset : 1527
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_write_end
+                Offset    : 1551
+                CU offset : 1551
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_buf_base
+                Offset    : 1575
+                CU offset : 1575
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_buf_end
+                Offset    : 1598
+                CU offset : 1598
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_save_base
+                Offset    : 1620
+                CU offset : 1620
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_backup_base
+                Offset    : 1644
+                CU offset : 1644
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _IO_save_end
+                Offset    : 1670
+                CU offset : 1670
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _markers
+                Offset    : 1693
+                CU offset : 1693
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _chain
+                Offset    : 1712
+                CU offset : 1712
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _fileno
+                Offset    : 1729
+                CU offset : 1729
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _blksize
+                Offset    : 1747
+                CU offset : 1747
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _old_offset
+                Offset    : 1766
+                CU offset : 1766
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _cur_column
+                Offset    : 1788
+                CU offset : 1788
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _vtable_offset
+                Offset    : 1810
+                CU offset : 1810
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _shortbuf
+                Offset    : 1835
+                CU offset : 1835
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _lock
+                Offset    : 1855
+                CU offset : 1855
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _offset
+                Offset    : 1871
+                CU offset : 1871
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _unused2
+                Offset    : 1889
+                CU offset : 1889
+                Attrs     : name data_member_location decl_file decl_line type
+          DW_TAG_structure_type
+           Name      : _IO_marker
+           Offset    : 1909
+           CU offset : 1909
+           Attrs     : sibling name byte_size decl_file decl_line
+           byte size : 12
+               DW_TAG_member
+                Name      : _next
+                Offset    : 1928
+                CU offset : 1928
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _sbuf
+                Offset    : 1944
+                CU offset : 1944
+                Attrs     : name data_member_location decl_file decl_line type
+               DW_TAG_member
+                Name      : _pos
+                Offset    : 1960
+                CU offset : 1960
+                Attrs     : name data_member_location decl_file decl_line type
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 1976
+           CU offset : 1976
+           Attrs     : byte_size type
+           byte size : 4
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 1982
+           CU offset : 1982
+           Attrs     : byte_size type
+           byte size : 4
+          DW_TAG_array_type
+           Name      : * NO NAME *
+           Offset    : 1988
+           CU offset : 1988
+           Attrs     : sibling type
+               DW_TAG_subrange_type
+                Name      : * NO NAME *
+                Offset    : 1997
+                CU offset : 1997
+                Attrs     : upper_bound type
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 2004
+           CU offset : 2004
+           Attrs     : byte_size
+           byte size : 4
+          DW_TAG_array_type
+           Name      : * NO NAME *
+           Offset    : 2006
+           CU offset : 2006
+           Attrs     : sibling type
+               DW_TAG_subrange_type
+                Name      : * NO NAME *
+                Offset    : 2015
+                CU offset : 2015
+                Attrs     : upper_bound type
+          DW_TAG_typedef
+           Name      : FILE
+           Offset    : 2022
+           CU offset : 2022
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : wchar_t
+           Offset    : 2034
+           CU offset : 2034
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : wint_t
+           Offset    : 2050
+           CU offset : 2050
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : _G_int16_t
+           Offset    : 2065
+           CU offset : 2065
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : _G_int32_t
+           Offset    : 2083
+           CU offset : 2083
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : _G_uint16_t
+           Offset    : 2101
+           CU offset : 2101
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : _G_uint32_t
+           Offset    : 2120
+           CU offset : 2120
+           Attrs     : name decl_file decl_line type
+          DW_TAG_structure_type
+           Name      : _IO_jump_t
+           Offset    : 2139
+           CU offset : 2139
+           Attrs     : name declaration
+          DW_TAG_typedef
+           Name      : _IO_lock_t
+           Offset    : 2152
+           CU offset : 2152
+           Attrs     : name decl_file decl_line
+          DW_TAG_typedef
+           Name      : _IO_FILE
+           Offset    : 2166
+           CU offset : 2166
+           Attrs     : name decl_file decl_line type
+          DW_TAG_structure_type
+           Name      : _IO_FILE_plus
+           Offset    : 2182
+           CU offset : 2182
+           Attrs     : name declaration
+          DW_TAG_typedef
+           Name      : __io_read_fn
+           Offset    : 2198
+           CU offset : 2198
+           Attrs     : name decl_file decl_line type
+          DW_TAG_subroutine_type
+           Name      : * NO NAME *
+           Offset    : 2219
+           CU offset : 2219
+           Attrs     : sibling prototyped type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2229
+                CU offset : 2229
+                Attrs     : type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2234
+                CU offset : 2234
+                Attrs     : type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2239
+                CU offset : 2239
+                Attrs     : type
+          DW_TAG_typedef
+           Name      : __io_write_fn
+           Offset    : 2245
+           CU offset : 2245
+           Attrs     : name decl_file decl_line type
+          DW_TAG_subroutine_type
+           Name      : * NO NAME *
+           Offset    : 2267
+           CU offset : 2267
+           Attrs     : sibling prototyped type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2277
+                CU offset : 2277
+                Attrs     : type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2282
+                CU offset : 2282
+                Attrs     : type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2287
+                CU offset : 2287
+                Attrs     : type
+          DW_TAG_pointer_type
+           Name      : * NO NAME *
+           Offset    : 2293
+           CU offset : 2293
+           Attrs     : byte_size type
+           byte size : 4
+          DW_TAG_const_type
+           Name      : * NO NAME *
+           Offset    : 2299
+           CU offset : 2299
+           Attrs     : type
+          DW_TAG_typedef
+           Name      : __io_seek_fn
+           Offset    : 2304
+           CU offset : 2304
+           Attrs     : name decl_file decl_line type
+          DW_TAG_subroutine_type
+           Name      : * NO NAME *
+           Offset    : 2325
+           CU offset : 2325
+           Attrs     : sibling prototyped type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2335
+                CU offset : 2335
+                Attrs     : type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2340
+                CU offset : 2340
+                Attrs     : type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2345
+                CU offset : 2345
+                Attrs     : type
+          DW_TAG_typedef
+           Name      : __io_close_fn
+           Offset    : 2351
+           CU offset : 2351
+           Attrs     : name decl_file decl_line type
+          DW_TAG_subroutine_type
+           Name      : * NO NAME *
+           Offset    : 2373
+           CU offset : 2373
+           Attrs     : sibling prototyped type
+               DW_TAG_formal_parameter
+                Name      : * NO NAME *
+                Offset    : 2383
+                CU offset : 2383
+                Attrs     : type
+          DW_TAG_typedef
+           Name      : fpos_t
+           Offset    : 2389
+           CU offset : 2389
+           Attrs     : name decl_file decl_line type
+          DW_TAG_typedef
+           Name      : off_t
+           Offset    : 2403
+           CU offset : 2403
+           Attrs     : name decl_file decl_line type
+New CU: off = 2418, hsize = 11, ab = 213, as = 4, os = 4
+     DW_TAG_compile_unit
+      Name      : f.c
+      Offset    : 2429
+      CU offset : 11
+      Attrs     : name stmt_list low_pc high_pc language comp_dir producer
+      low PC    : 0x10000490
+      high PC   : 0x100004b0
+      language  : 1
+      directory : /shoggoth/drepper
+      producer  : GNU C 2.96-laurel-000912
+          DW_TAG_subprogram
+           Name      : foo
+           Offset    : 2490
+           CU offset : 72
+           Attrs     : name low_pc high_pc prototyped decl_file decl_line external frame_base type
+           low PC    : 0x10000490
+           high PC   : 0x100004b0
+          DW_TAG_base_type
+           Name      : int
+           Offset    : 2513
+           CU offset : 95
+           Attrs     : name byte_size encoding
+           byte size : 4
+New CU: off = 2521, hsize = 11, ab = 267, as = 4, os = 4
+     DW_TAG_compile_unit
+      Name      : m.c
+      Offset    : 2532
+      CU offset : 11
+      Attrs     : name stmt_list low_pc high_pc language comp_dir producer
+      low PC    : 0x100004b0
+      high PC   : 0x10000514
+      language  : 1
+      directory : /shoggoth/drepper
+      producer  : GNU C 2.96-laurel-000912
+          DW_TAG_subprogram
+           Name      : main
+           Offset    : 2593
+           CU offset : 72
+           Attrs     : sibling name low_pc high_pc prototyped decl_file decl_line external frame_base type
+           low PC    : 0x100004b0
+           high PC   : 0x10000514
+               DW_TAG_subprogram
+                Name      : bar
+                Offset    : 2621
+                CU offset : 100
+                Attrs     : sibling name decl_file decl_line declaration external type
+                    DW_TAG_unspecified_parameters
+                     Name      : * NO NAME *
+                     Offset    : 2638
+                     CU offset : 117
+                     Attrs     :
+               DW_TAG_subprogram
+                Name      : foo
+                Offset    : 2640
+                CU offset : 119
+                Attrs     : name decl_file decl_line declaration external type
+                    DW_TAG_unspecified_parameters
+                     Name      : * NO NAME *
+                     Offset    : 2653
+                     CU offset : 132
+                     Attrs     :
+          DW_TAG_base_type
+           Name      : int
+           Offset    : 2656
+           CU offset : 135
+           Attrs     : name byte_size encoding
+           byte size : 4
+          DW_TAG_variable
+           Name      : a
+           Offset    : 2663
+           CU offset : 142
+           Attrs     : location name decl_file decl_line external type
+EOF
+
+exit 0
diff --git a/tests/run-srcfiles-self.sh b/tests/run-srcfiles-self.sh
new file mode 100755
index 0000000..515cc47
--- /dev/null
+++ b/tests/run-srcfiles-self.sh
@@ -0,0 +1,114 @@
+#! /usr/bin/env bash
+# Copyright (C) 2023 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/debuginfod-subr.sh
+
+# for test case debugging, uncomment:
+# set -x
+set -e
+base=14000
+get_ports
+
+# Test different command line combinations on the srcfiles binary itself.
+ET_EXEC="${abs_top_builddir}/src/srcfiles"
+ET_PID=$$
+
+SRC_NAME="srcfiles.cxx"
+
+# Ensure the output contains the expected source file srcfiles.cxx
+testrun $ET_EXEC -e $ET_EXEC | grep $SRC_NAME > /dev/null
+
+# Check if zip option is available (only available if libarchive is available.
+#   Debuginfod optional to fetch source files from debuginfod federation.)
+$ET_EXEC --help | grep -q zip && command -v unzip >/dev/null 2>&1 && zip=true || zip=false
+
+for null_arg in --null ""; do
+  for verbose_arg in --verbose ""; do
+    echo "Test with options $null_arg $verbose_arg"
+    testrun $ET_EXEC $null_arg $verbose_arg -p $ET_PID > /dev/null
+
+    # Ensure that the output contains srcfiles.cxx
+    cu_only=$(testrun $ET_EXEC $null_arg $verbose_arg -c -e $ET_EXEC)
+    default=$(testrun $ET_EXEC $null_arg $verbose_arg -e $ET_EXEC)
+    result1=$(echo "$cu_only" | grep "$SRC_NAME")
+    result2=$(echo "$default" | grep "$SRC_NAME")
+
+    if [ -z "$result1" ] || [ -z "$result2" ]; then
+      exit 1
+    fi
+
+    # Ensure that the output with the cu-only option contains fewer source files
+    if [ $(echo "$cu_only" | wc -m) -gt $(echo "$default" | wc -m) ]; then
+      exit 1
+    fi
+
+    if $zip; then
+      # Zip option tests
+        testrun $ET_EXEC $verbose_arg -z -e $ET_EXEC > test.zip
+        tempfiles test.zip
+
+        unzip -v test.zip
+        unzip -t test.zip
+
+        # Ensure unzipped srcfiles.cxx and its contents are the same as the original source file
+        unzip -j test.zip "*/$SRC_NAME"
+        diff "$SRC_NAME" $abs_srcdir/../src/$SRC_NAME
+        rm -f test.zip $SRC_NAME
+    fi
+  done
+done
+
+# Debuginfod source file downloading test.
+# Start debuginfod server on the elfutils build directory.
+if [ -x ${abs_builddir}/../debuginfod/debuginfod ] && $zip; then
+  LD_LIBRARY_PATH=$ldpath ${abs_builddir}/../debuginfod/debuginfod -vvvv -d debuginfod.sqlite3 -F -p $PORT1 ${abs_top_builddir}/src > debuginfod.log 2>&1 &
+  PID1=$!
+  tempfiles debuginfod.sqlite3 debuginfod.log
+  wait_ready $PORT1 'ready' 1
+  wait_ready $PORT1 'thread_work_total{role="traverse"}' 1
+  wait_ready $PORT1 'thread_work_pending{role="scan"}' 0
+  wait_ready4 $PORT1 'thread_busy{role="scan"}' 0 300 # lots of source files may be slow to index with $db on NFS
+
+  export DEBUGINFOD_URLS="http://localhost:${PORT1}/"
+  export DEBUGINFOD_VERBOSE=1
+  testrun $ET_EXEC -z -b -e $ET_EXEC > test.zip
+  tempfiles test.zip
+
+  unzip -v test.zip
+  unzip -t test.zip
+
+  # Extract the zip.
+  mkdir extracted
+  unzip test.zip -d extracted
+
+  # Ensure that source files for this tool have been archived.
+  source_files="srcfiles.cxx libdwfl.h gelf.h"
+  extracted_files=$(find extracted -type f)
+  for file in $source_files; do
+      echo "$extracted_files" | grep -q "$file" > /dev/null
+  done
+
+  # Compare between the extracted file and the actual source file srcfiles.cxx.
+  extracted_file=$(find extracted -name $SRC_NAME)
+  diff "$extracted_file" $abs_srcdir/../src/$SRC_NAME
+
+  rm -rf extracted
+
+  kill $PID1
+  wait
+  PID1=0
+fi
diff --git a/tests/run-stack-d-test.sh b/tests/run-stack-d-test.sh
new file mode 100755
index 0000000..a9f0380
--- /dev/null
+++ b/tests/run-stack-d-test.sh
@@ -0,0 +1,122 @@
+#! /bin/sh
+# Copyright (C) 2014, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# // g++ dwarfinlines.cpp -g -o testfiledwarfinlines -O2
+# int
+# fubar (int x)
+# {
+#   __asm__ ( "nop" ::: );
+#   return 42 / x - 2;
+# }
+#
+# void foobar (int z1, int z2)
+# {
+#   __asm__ ( "nop" ::: );
+#   int x = z1 + z2;
+#   while (z1 + x + 1 != 42)
+#     x = fubar (z1 + z2 + x);
+# }
+#
+# void bar (int z)
+# {
+#   int a, b;
+#   a = b = z / 2;
+#   foobar(a, b);
+# }
+#
+# void foo (int x)
+# {
+#   if (x > 0)
+#     bar(x - 2);
+# }
+#
+# void fu (int y)
+# {
+#   __asm__ ( "nop" ::: );
+#   foo (y + 1);
+# }
+#
+# int
+# main (int argc, char **argv)
+# {
+#   fu (argc);
+# }
+testfiles testfiledwarfinlines testfiledwarfinlines.core
+
+# Depending on whether we are running make check or make installcheck
+# the actual binary name under test might be different. It is used in
+# the error message, which we also try to match.
+if test "$elfutils_testrun" = "installed"; then
+STACKCMD=${bindir}/`program_transform stack`
+else
+STACKCMD=${abs_top_builddir}/src/stack
+fi
+
+# Disable valgrind while dumping because of a bug unmapping libc.so.
+# https://bugs.kde.org/show_bug.cgi?id=327427
+SAVED_VALGRIND_CMD="$VALGRIND_CMD"
+unset VALGRIND_CMD
+
+# Without -d the top function comes out as fu. Use --raw to not demangle.
+testrun_compare ${abs_top_builddir}/src/stack -r -n 2 -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 _Z2fui
+#1  0x00000000004004c5 main
+$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited)
+EOF
+
+# But when asking for source we see it is actually on line 6.
+# (Which is in function fubar, not fu). Use --raw to not demangle.
+testrun_compare ${abs_top_builddir}/src/stack -r -n 2 -s -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 _Z2fui
+    /home/mark/src/tests/dwarfinlines.cpp:6
+#1  0x00000000004004c5 main
+    /home/mark/src/tests/dwarfinlines.cpp:39
+$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited)
+EOF
+
+# So with --debugname we get the function correct as fubar.
+testrun_compare ${abs_top_builddir}/src/stack -n 2 -d -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fubar
+#1  0x00000000004004c5 main
+$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited)
+EOF
+
+# Which now matches the source line (again 6 of course).
+testrun_compare ${abs_top_builddir}/src/stack -n 2 -s -d -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fubar
+    /home/mark/src/tests/dwarfinlines.cpp:6
+#1  0x00000000004004c5 main
+    /home/mark/src/tests/dwarfinlines.cpp:39
+$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited)
+EOF
+
+if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
+  VALGRIND_CMD="$SAVED_VALGRIND_CMD"
+  export VALGRIND_CMD
+fi
+
+exit 0
diff --git a/tests/run-stack-demangled-test.sh b/tests/run-stack-demangled-test.sh
new file mode 100755
index 0000000..ac5bc61
--- /dev/null
+++ b/tests/run-stack-demangled-test.sh
@@ -0,0 +1,105 @@
+#! /bin/sh
+# Copyright (C) 2014, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+if test -n "$ELFUTILS_DISABLE_DEMANGLE"; then
+  echo "demangler unsupported"
+  exit 77
+fi
+
+. $srcdir/test-subr.sh
+
+# See run-stack-d-test.sh and run-stack-i-test.sh
+# Same tests, now with demangler support, no -r, and without -d.
+# Only change in output is an explicit fu(int) instead of _Z2fui.
+
+testfiles testfiledwarfinlines testfiledwarfinlines.core
+
+# Depending on whether we are running make check or make installcheck
+# the actual binary name under test might be different. It is used in
+# the error message, which we also try to match.
+if test "$elfutils_testrun" = "installed"; then
+STACKCMD=${bindir}/`program_transform stack`
+else
+STACKCMD=${abs_top_builddir}/src/stack
+fi
+
+# Disable valgrind while dumping because of a bug unmapping libc.so.
+# https://bugs.kde.org/show_bug.cgi?id=327427
+SAVED_VALGRIND_CMD="$VALGRIND_CMD"
+unset VALGRIND_CMD
+
+# Without -d the top function comes out as fu.
+testrun_compare ${abs_top_builddir}/src/stack -n 2 -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fu(int)
+#1  0x00000000004004c5 main
+$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited)
+EOF
+
+# But when asking for source we see it is actually on line 6.
+# (Which is in function fubar, not fu).
+testrun_compare ${abs_top_builddir}/src/stack -n 2 -s -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fu(int)
+    /home/mark/src/tests/dwarfinlines.cpp:6
+#1  0x00000000004004c5 main
+    /home/mark/src/tests/dwarfinlines.cpp:39
+$STACKCMD: tid 13654: shown max number of frames (2, use -n 0 for unlimited)
+EOF
+
+# With --inlines we get all inlined calls. Note they share the same
+# address.
+testrun_compare ${abs_top_builddir}/src/stack -n 6 -i -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fubar
+#1  0x00000000004006c8 foobar
+#2  0x00000000004006c8 bar
+#3  0x00000000004006c8 foo
+#4  0x00000000004006c8 fu(int)
+#5  0x00000000004004c5 main
+$STACKCMD: tid 13654: shown max number of frames (6, use -n 0 for unlimited)
+EOF
+
+# With --source we can also see where in the source the inlined frames
+# where originally called from.
+testrun_compare ${abs_top_builddir}/src/stack -n 6 -s -i -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fubar
+    /home/mark/src/tests/dwarfinlines.cpp:6
+#1  0x00000000004006c8 foobar
+    /home/mark/src/tests/dwarfinlines.cpp:14
+#2  0x00000000004006c8 bar
+    /home/mark/src/tests/dwarfinlines.cpp:21
+#3  0x00000000004006c8 foo
+    /home/mark/src/tests/dwarfinlines.cpp:27
+#4  0x00000000004006c8 fu(int)
+    /home/mark/src/tests/dwarfinlines.cpp:33
+#5  0x00000000004004c5 main
+    /home/mark/src/tests/dwarfinlines.cpp:39
+$STACKCMD: tid 13654: shown max number of frames (6, use -n 0 for unlimited)
+EOF
+
+if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
+  VALGRIND_CMD="$SAVED_VALGRIND_CMD"
+  export VALGRIND_CMD
+fi
+
+exit 0
diff --git a/tests/run-stack-i-test.sh b/tests/run-stack-i-test.sh
new file mode 100755
index 0000000..3722ab0
--- /dev/null
+++ b/tests/run-stack-i-test.sh
@@ -0,0 +1,81 @@
+#! /bin/sh
+# Copyright (C) 2014, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-stack-d-test.sh for dwarfinlines.cpp source.
+testfiles testfiledwarfinlines testfiledwarfinlines.core
+
+# Depending on whether we are running make check or make installcheck
+# the actual binary name under test might be different. It is used in
+# the error message, which we also try to match.
+if test "$elfutils_testrun" = "installed"; then
+STACKCMD=${bindir}/`program_transform stack`
+else
+STACKCMD=${abs_top_builddir}/src/stack
+fi
+
+# Disable valgrind while dumping because of a bug unmapping libc.so.
+# https://bugs.kde.org/show_bug.cgi?id=327427
+SAVED_VALGRIND_CMD="$VALGRIND_CMD"
+unset VALGRIND_CMD
+
+# Compare with run-stack-d-test.sh to see the output without --inlines.
+# Only two call frames are visible (there is a jump from main to fu or
+# fubar). Explicitly use --raw so demangler support being configured in
+# doesn't change the results.
+
+# With --inlines we get all inlined calls. Note they share the same
+# address.
+testrun_compare ${abs_top_builddir}/src/stack -r -n 6 -i -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fubar
+#1  0x00000000004006c8 foobar
+#2  0x00000000004006c8 bar
+#3  0x00000000004006c8 foo
+#4  0x00000000004006c8 _Z2fui
+#5  0x00000000004004c5 main
+$STACKCMD: tid 13654: shown max number of frames (6, use -n 0 for unlimited)
+EOF
+
+# With --source we can also see where in the source the inlined frames
+# where originally called from.
+testrun_compare ${abs_top_builddir}/src/stack -r -n 6 -s -i -e testfiledwarfinlines --core testfiledwarfinlines.core<<EOF
+PID 13654 - core
+TID 13654:
+#0  0x00000000004006c8 fubar
+    /home/mark/src/tests/dwarfinlines.cpp:6
+#1  0x00000000004006c8 foobar
+    /home/mark/src/tests/dwarfinlines.cpp:14
+#2  0x00000000004006c8 bar
+    /home/mark/src/tests/dwarfinlines.cpp:21
+#3  0x00000000004006c8 foo
+    /home/mark/src/tests/dwarfinlines.cpp:27
+#4  0x00000000004006c8 _Z2fui
+    /home/mark/src/tests/dwarfinlines.cpp:33
+#5  0x00000000004004c5 main
+    /home/mark/src/tests/dwarfinlines.cpp:39
+$STACKCMD: tid 13654: shown max number of frames (6, use -n 0 for unlimited)
+EOF
+
+if [ "x$SAVED_VALGRIND_CMD" != "x" ]; then
+  VALGRIND_CMD="$SAVED_VALGRIND_CMD"
+  export VALGRIND_CMD
+fi
+
+exit 0
diff --git a/tests/run-strings-test.sh b/tests/run-strings-test.sh
new file mode 100755
index 0000000..33f2d64
--- /dev/null
+++ b/tests/run-strings-test.sh
@@ -0,0 +1,470 @@
+#! /bin/sh
+# Copyright (C) 2005, 2006, 2008 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 2005.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+files="testfile `seq 2 9 | while read n; do echo testfile$n; done`"
+testfiles $files
+
+testrun_compare ${abs_top_builddir}/src/strings -tx -f $files <<\EOF
+testfile:      f4 /lib/ld-linux.so.2
+testfile:     1c9 __gmon_start__
+testfile:     1d8 libc.so.6
+testfile:     1e2 __cxa_finalize
+testfile:     1f1 __deregister_frame_info
+testfile:     209 _IO_stdin_used
+testfile:     218 __libc_start_main
+testfile:     22a __register_frame_info
+testfile:     240 GLIBC_2.1.3
+testfile:     24c GLIBC_2.0
+testfile:     338 PTRh
+testfile:     345 QVh,
+testfile2:     114 /lib/ld.so.1
+testfile2:     1f1 __gmon_start__
+testfile2:     200 __deregister_frame_info
+testfile2:     218 __register_frame_info
+testfile2:     22e libc.so.6
+testfile2:     238 __cxa_finalize
+testfile2:     247 _IO_stdin_used
+testfile2:     256 __libc_start_main
+testfile2:     268 GLIBC_2.1.3
+testfile2:     274 GLIBC_2.0
+testfile2:     488 }a[xN
+testfile2:     4a8 }a[xN
+testfile2:     50c }a[xN
+testfile2:     540 }?Kx
+testfile3:      f4 /lib/ld-linux.so.2
+testfile3:     1c9 __gmon_start__
+testfile3:     1d8 libc.so.6
+testfile3:     1e2 __cxa_finalize
+testfile3:     1f1 __deregister_frame_info
+testfile3:     209 _IO_stdin_used
+testfile3:     218 __libc_start_main
+testfile3:     22a __register_frame_info
+testfile3:     240 GLIBC_2.1.3
+testfile3:     24c GLIBC_2.0
+testfile3:     338 PTRh
+testfile3:     345 QVh,
+testfile4:      f4 /lib/ld-linux.so.2
+testfile4:     8e1 __gmon_start__
+testfile4:     8f0 __terminate_func
+testfile4:     901 stderr
+testfile4:     908 __tf9type_info
+testfile4:     917 __tf16__user_type_info
+testfile4:     92e __tf19__pointer_type_info
+testfile4:     948 __tf16__attr_type_info
+testfile4:     95f __tf16__func_type_info
+testfile4:     976 __vt_9type_info
+testfile4:     986 __vt_19__pointer_type_info
+testfile4:     9a1 __vt_16__attr_type_info
+testfile4:     9b9 __vt_16__func_type_info
+testfile4:     9d1 __vt_16__ptmf_type_info
+testfile4:     9e9 __vt_16__ptmd_type_info
+testfile4:     a01 __vt_17__array_type_info
+testfile4:     a1a __tiv
+testfile4:     a20 __vt_19__builtin_type_info
+testfile4:     a3b __tix
+testfile4:     a41 __til
+testfile4:     a47 __tii
+testfile4:     a4d __tis
+testfile4:     a53 __tib
+testfile4:     a59 __tic
+testfile4:     a5f __tiw
+testfile4:     a65 __tir
+testfile4:     a6b __tid
+testfile4:     a71 __tif
+testfile4:     a77 __tiUi
+testfile4:     a7e __tiUl
+testfile4:     a85 __tiUx
+testfile4:     a8c __tiUs
+testfile4:     a93 __tiUc
+testfile4:     a9a __tiSc
+testfile4:     aa1 __ti19__pointer_type_info
+testfile4:     abb __ti9type_info
+testfile4:     aca __ti16__attr_type_info
+testfile4:     ae1 __ti19__builtin_type_info
+testfile4:     afb __ti16__func_type_info
+testfile4:     b12 __ti16__ptmf_type_info
+testfile4:     b29 __ti16__ptmd_type_info
+testfile4:     b40 __ti17__array_type_info
+testfile4:     b58 __cplus_type_matcher
+testfile4:     b6d __vt_13bad_exception
+testfile4:     b82 __vt_9exception
+testfile4:     b92 _._13bad_exception
+testfile4:     ba5 __vt_8bad_cast
+testfile4:     bb4 _._8bad_cast
+testfile4:     bc1 __vt_10bad_typeid
+testfile4:     bd3 _._10bad_typeid
+testfile4:     be3 __ti9exception
+testfile4:     bf2 __ti13bad_exception
+testfile4:     c06 __vt_16__user_type_info
+testfile4:     c1e __vt_17__class_type_info
+testfile4:     c37 __vt_14__si_type_info
+testfile4:     c4d __ti8bad_cast
+testfile4:     c5b __ti10bad_typeid
+testfile4:     c6c __ti16__user_type_info
+testfile4:     c83 __ti14__si_type_info
+testfile4:     c98 __ti17__class_type_info
+testfile4:     cb0 libc.so.6
+testfile4:     cba __register_frame
+testfile4:     ccb pthread_create
+testfile4:     cda pthread_getspecific
+testfile4:     cee pthread_key_delete
+testfile4:     d01 __cxa_finalize
+testfile4:     d10 malloc
+testfile4:     d17 __frame_state_for
+testfile4:     d29 abort
+testfile4:     d2f __register_frame_table
+testfile4:     d46 fprintf
+testfile4:     d4e pthread_once
+testfile4:     d5b __deregister_frame_info
+testfile4:     d73 pthread_key_create
+testfile4:     d86 memset
+testfile4:     d8d strcmp
+testfile4:     d94 pthread_mutex_unlock
+testfile4:     da9 __deregister_frame
+testfile4:     dbc pthread_mutex_lock
+testfile4:     dcf _IO_stdin_used
+testfile4:     dde __libc_start_main
+testfile4:     df0 strlen
+testfile4:     df7 __register_frame_info_table
+testfile4:     e13 __register_frame_info
+testfile4:     e29 pthread_setspecific
+testfile4:     e3d free
+testfile4:     e42 GLIBC_2.1.3
+testfile4:     e4e GLIBC_2.0
+testfile4:    1308 PTRh<
+testfile4:    194b [^_]
+testfile4:    19bf [^_]
+testfile4:    1dd9 wT9L>
+testfile4:    1f3b [^_]
+testfile4:    1fae [^_]
+testfile4:    21c1 BZQRP
+testfile4:    237f [^_]
+testfile4:    2431 JWRV
+testfile4:    2454 [^_]
+testfile4:    2506 JWRV
+testfile4:    2529 [^_]
+testfile4:    2b6c [^_]
+testfile4:    2b9d ZYPV
+testfile4:    2c28 [^_]
+testfile4:    2c4d ZYPV
+testfile4:    2ce2 [^_]
+testfile4:    2dfb X^_]
+testfile4:    2fc8 [^_]
+testfile4:    307d tq;F
+testfile4:    315a [^_]
+testfile4:    31a5 :zt	1
+testfile4:    3238 [^_]
+testfile4:    32f8 AXY_VR
+testfile4:    334a [^_]
+testfile4:    37ab [^_]
+testfile4:    38b8 sU;E
+testfile4:    38f2 QRPV
+testfile4:    3926 [^_]
+testfile4:    3bfe QRWP
+testfile4:    3e65 [^_]
+testfile4:    4136 [^_]
+testfile4:    472d [^_]
+testfile4:    47a5 0[^_]
+testfile4:    48ab [^_]
+testfile4:    4ab1 _ZPV
+testfile4:    4b53 _ZPV
+testfile4:    4bd3 _ZPV
+testfile4:    4e05 PQWj
+testfile4:    4f75 [^_]
+testfile4:    4f9b u$;E u
+testfile4:    4feb [^_]
+testfile4:    5080 [^_]
+testfile4:    50a8 }$9u
+testfile4:    5149 [^_]
+testfile4:    51b0 [^_]
+testfile4:    539b [^_]
+testfile4:    53b5 E 9E
+testfile4:    540d x!)E 
+testfile4:    5598 U$	B
+testfile4:    571c [^_]
+testfile4:    5819 [^_]
+testfile4:    5922 [^_]
+testfile4:    59c2 [^_]
+testfile4:    5a62 [^_]
+testfile4:    5b02 [^_]
+testfile4:    5ba2 [^_]
+testfile4:    5c42 [^_]
+testfile4:    5ce2 [^_]
+testfile4:    6112 [^_]
+testfile4:    62bb [^_]
+testfile4:    639b [^_]
+testfile4:    6436 [^_]
+testfile4:    6468 val is zero
+testfile4:    6480 Internal Compiler Bug: No runtime type matcher.
+testfile4:    64dc 19__pointer_type_info
+testfile4:    64f2 16__attr_type_info
+testfile4:    6505 19__builtin_type_info
+testfile4:    651b 16__func_type_info
+testfile4:    652e 16__ptmf_type_info
+testfile4:    6541 16__ptmd_type_info
+testfile4:    6554 17__array_type_info
+testfile4:    6568 9exception
+testfile4:    6573 13bad_exception
+testfile4:    6583 9type_info
+testfile4:    658e 8bad_cast
+testfile4:    6598 10bad_typeid
+testfile4:    65a5 16__user_type_info
+testfile4:    65b8 14__si_type_info
+testfile4:    65c9 17__class_type_info
+testfile4:    6fc1 H. $
+testfile5:      f4 /lib/ld-linux.so.2
+testfile5:     1c9 __gmon_start__
+testfile5:     1d8 libc.so.6
+testfile5:     1e2 __cxa_finalize
+testfile5:     1f1 __deregister_frame_info
+testfile5:     209 _IO_stdin_used
+testfile5:     218 __libc_start_main
+testfile5:     22a __register_frame_info
+testfile5:     240 GLIBC_2.1.3
+testfile5:     24c GLIBC_2.0
+testfile5:     338 PTRh
+testfile5:     345 QVhD
+testfile6:     114 /lib/ld-linux.so.2
+testfile6:     3d9 libstdc++.so.5
+testfile6:     3e8 _ZTVSt16invalid_argument
+testfile6:     401 _ZNSaIcEC1Ev
+testfile6:     40e _ZTSSt16invalid_argument
+testfile6:     427 _ZTVN10__cxxabiv120__si_class_type_infoE
+testfile6:     450 _ZNSsD1Ev
+testfile6:     45a _ZdlPv
+testfile6:     461 __cxa_end_catch
+testfile6:     471 __gxx_personality_v0
+testfile6:     486 _ZTISt9exception
+testfile6:     497 _ZNSaIcED1Ev
+testfile6:     4a4 _ZTISt11logic_error
+testfile6:     4b8 _ZNSt16invalid_argumentD1Ev
+testfile6:     4d4 _ZTVN10__cxxabiv117__class_type_infoE
+testfile6:     4fa __cxa_throw
+testfile6:     506 _ZNSt16invalid_argumentC1ERKSs
+testfile6:     525 _ZNSsC1EPKcRKSaIcE
+testfile6:     538 _ZNSt11logic_errorD2Ev
+testfile6:     54f _ZTVN10__cxxabiv121__vmi_class_type_infoE
+testfile6:     579 _ZNSt16invalid_argumentD0Ev
+testfile6:     595 __cxa_begin_catch
+testfile6:     5a7 __cxa_allocate_exception
+testfile6:     5c0 _ZNKSt11logic_error4whatEv
+testfile6:     5db _Jv_RegisterClasses
+testfile6:     5ef _ZTISt16invalid_argument
+testfile6:     608 __gmon_start__
+testfile6:     617 libm.so.6
+testfile6:     621 _IO_stdin_used
+testfile6:     630 libgcc_s.so.1
+testfile6:     63e _Unwind_Resume
+testfile6:     64d libc.so.6
+testfile6:     657 __libc_start_main
+testfile6:     669 GCC_3.0
+testfile6:     671 GLIBC_2.0
+testfile6:     67b GLIBCPP_3.2
+testfile6:     687 CXXABI_1.2
+testfile6:     908 PTRh 
+testfile6:     e48 gdb.1
+testfile6:     ec8 N10__gnu_test9gnu_obj_1E
+testfile6:     ee1 N10__gnu_test9gnu_obj_2IiEE
+testfile6:     efd N10__gnu_test9gnu_obj_2IlEE
+testfile6:     f19 St16invalid_argument
+testfile7:     114 /lib/ld-linux.so.2
+testfile7:     3d9 libstdc++.so.5
+testfile7:     3e8 _ZTVSt16invalid_argument
+testfile7:     401 _ZNSaIcEC1Ev
+testfile7:     40e _ZTSSt16invalid_argument
+testfile7:     427 _ZTVN10__cxxabiv120__si_class_type_infoE
+testfile7:     450 _ZNSsD1Ev
+testfile7:     45a _ZdlPv
+testfile7:     461 __cxa_end_catch
+testfile7:     471 __gxx_personality_v0
+testfile7:     486 _ZTISt9exception
+testfile7:     497 _ZNSaIcED1Ev
+testfile7:     4a4 _ZTISt11logic_error
+testfile7:     4b8 _ZNSt16invalid_argumentD1Ev
+testfile7:     4d4 _ZTVN10__cxxabiv117__class_type_infoE
+testfile7:     4fa __cxa_throw
+testfile7:     506 _ZNSt16invalid_argumentC1ERKSs
+testfile7:     525 _ZNSsC1EPKcRKSaIcE
+testfile7:     538 _ZNSt11logic_errorD2Ev
+testfile7:     54f _ZTVN10__cxxabiv121__vmi_class_type_infoE
+testfile7:     579 _ZNSt16invalid_argumentD0Ev
+testfile7:     595 __cxa_begin_catch
+testfile7:     5a7 __cxa_allocate_exception
+testfile7:     5c0 _ZNKSt11logic_error4whatEv
+testfile7:     5db _Jv_RegisterClasses
+testfile7:     5ef _ZTISt16invalid_argument
+testfile7:     608 __gmon_start__
+testfile7:     617 libm.so.6
+testfile7:     621 _IO_stdin_used
+testfile7:     630 libgcc_s.so.1
+testfile7:     63e _Unwind_Resume
+testfile7:     64d libc.so.6
+testfile7:     657 __libc_start_main
+testfile7:     669 GCC_3.0
+testfile7:     671 GLIBC_2.0
+testfile7:     67b GLIBCPP_3.2
+testfile7:     687 CXXABI_1.2
+testfile7:     908 PTRh 
+testfile7:     e48 gdb.1
+testfile7:     ec8 N10__gnu_test9gnu_obj_1E
+testfile7:     ee1 N10__gnu_test9gnu_obj_2IiEE
+testfile7:     efd N10__gnu_test9gnu_obj_2IlEE
+testfile7:     f19 St16invalid_argument
+testfile8:      79 XZh;
+testfile8:      87 YXh<
+testfile8:     14f SQh[
+testfile8:     259 t5Wj
+testfile8:     502 WRVQ
+testfile8:    1fe7 ZYPj
+testfile8:    2115 u'Pj
+testfile8:    7bba FILE
+testfile8:    7bbf preserve-dates
+testfile8:    7bce remove-comment
+testfile8:    7bdd Remove .comment section
+testfile8:    7bf6 ${prefix}/share
+testfile8:    7c06 elfutils
+testfile8:    7c0f a.out
+testfile8:    7c15 0.58
+testfile8:    7c1a strip (Red Hat %s) %s
+testfile8:    7c31 2002
+testfile8:    7c36 Ulrich Drepper
+testfile8:    7c45 Written by %s.
+testfile8:    7c55 cannot stat input file "%s"
+testfile8:    7c71 %s: INTERNAL ERROR: %s
+testfile8:    7c88 while opening "%s"
+testfile8:    7c9b handle_elf
+testfile8:    7ca6 ../../src/strip.c
+testfile8:    7cb8 shdr_info[cnt].group_idx != 0
+testfile8:    7cd6 illformed file `%s'
+testfile8:    7cea elf_ndxscn (scn) == cnt
+testfile8:    7d02 .shstrtab
+testfile8:    7d0c while writing `%s': %s
+testfile8:    7d23 ((sym->st_info) & 0xf) == 3
+testfile8:    7d3f shndxdata != ((void *)0)
+testfile8:    7d58 scn != ((void *)0)
+testfile8:    7d6b .gnu_debuglink
+testfile8:    7d7a .comment
+testfile8:    7d83 cannot open `%s'
+testfile8:    7da0 Place stripped output into FILE
+testfile8:    7dc0 Extract the removed sections into FILE
+testfile8:    7e00 Copy modified/access timestamps to the output
+testfile8:    7e40 Only one input file allowed together with '-o' and '-f'
+testfile8:    7e80 Copyright (C) %s Red Hat, Inc.
+testfile8:    7e9f This is free software; see the source for copying conditions.  There is NO
+testfile8:    7eea warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+testfile8:    7f40 Report bugs to <drepper@redhat.com>.
+testfile8:    7f80 %s: File format not recognized
+testfile8:    7fa0 cannot set access and modification date of "%s"
+testfile8:    7fe0 cannot create new file `%s': %s
+testfile8:    8000 error while finishing `%s': %s
+testfile8:    8020 shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0
+testfile8:    8060 shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0
+testfile8:    80a0 %s: error while creating ELF header: %s
+testfile8:    80e0 %s: error while reading the file: %s
+testfile8:    8120 sec < 0xff00 || shndxdata != ((void *)0)
+testfile8:    8160 (versiondata->d_size / sizeof (GElf_Versym)) >= shdr_info[cnt].data->d_size / elsize
+testfile8:    81c0 shdr_info[cnt].shdr.sh_type == 11
+testfile8:    8200 (versiondata->d_size / sizeof (Elf32_Word)) >= shdr_info[cnt].data->d_size / elsize
+testfile8:    8260 shdr_info[cnt].shdr.sh_type == 18
+testfile8:    82a0 shdr_info[cnt].data != ((void *)0)
+testfile8:    82e0 elf_ndxscn (shdr_info[cnt].newscn) == idx
+testfile8:    8320 while create section header section: %s
+testfile8:    8360 cannot allocate section data: %s
+testfile8:    83a0 elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx
+testfile8:    83e0 while generating output file: %s
+testfile8:    8420 while preparing output for `%s'
+testfile8:    8440 shdr_info[cnt].shdr.sh_type == 2
+testfile8:    8480 shdr_info[idx].data != ((void *)0)
+testfile8:    84c0 cannot determine number of sections: %s
+testfile8:    8500 cannot get section header string table index
+testfile8:    85c0 Discard symbols from object files.
+testfile8:    85e3 [FILE...]
+testfile9:      79 XZh;
+testfile9:      87 YXh<
+testfile9:     14f SQh[
+testfile9:     259 t5Wj
+testfile9:     502 WRVQ
+testfile9:    1fe7 ZYPj
+testfile9:    2115 u'Pj
+testfile9:    3414 FILE
+testfile9:    3419 preserve-dates
+testfile9:    3428 remove-comment
+testfile9:    3437 Remove .comment section
+testfile9:    3450 ${prefix}/share
+testfile9:    3460 elfutils
+testfile9:    3469 a.out
+testfile9:    346f 0.58
+testfile9:    3474 strip (Red Hat %s) %s
+testfile9:    348b 2002
+testfile9:    3490 Ulrich Drepper
+testfile9:    349f Written by %s.
+testfile9:    34af cannot stat input file "%s"
+testfile9:    34cb %s: INTERNAL ERROR: %s
+testfile9:    34e2 while opening "%s"
+testfile9:    34f5 handle_elf
+testfile9:    3500 ../../src/strip.c
+testfile9:    3512 shdr_info[cnt].group_idx != 0
+testfile9:    3530 illformed file `%s'
+testfile9:    3544 elf_ndxscn (scn) == cnt
+testfile9:    355c .shstrtab
+testfile9:    3566 while writing `%s': %s
+testfile9:    357d ((sym->st_info) & 0xf) == 3
+testfile9:    3599 shndxdata != ((void *)0)
+testfile9:    35b2 scn != ((void *)0)
+testfile9:    35c5 .gnu_debuglink
+testfile9:    35d4 .comment
+testfile9:    35dd cannot open `%s'
+testfile9:    3600 Place stripped output into FILE
+testfile9:    3620 Extract the removed sections into FILE
+testfile9:    3660 Copy modified/access timestamps to the output
+testfile9:    36a0 Only one input file allowed together with '-o' and '-f'
+testfile9:    36e0 Copyright (C) %s Red Hat, Inc.
+testfile9:    36ff This is free software; see the source for copying conditions.  There is NO
+testfile9:    374a warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+testfile9:    37a0 Report bugs to <drepper@redhat.com>.
+testfile9:    37e0 %s: File format not recognized
+testfile9:    3800 cannot set access and modification date of "%s"
+testfile9:    3840 cannot create new file `%s': %s
+testfile9:    3860 error while finishing `%s': %s
+testfile9:    3880 shdr_info[shdr_info[cnt].shdr.sh_link].version_idx == 0
+testfile9:    38c0 shdr_info[shdr_info[cnt].shdr.sh_link].symtab_idx == 0
+testfile9:    3900 %s: error while creating ELF header: %s
+testfile9:    3940 %s: error while reading the file: %s
+testfile9:    3980 sec < 0xff00 || shndxdata != ((void *)0)
+testfile9:    39c0 (versiondata->d_size / sizeof (GElf_Versym)) >= shdr_info[cnt].data->d_size / elsize
+testfile9:    3a20 shdr_info[cnt].shdr.sh_type == 11
+testfile9:    3a60 (versiondata->d_size / sizeof (Elf32_Word)) >= shdr_info[cnt].data->d_size / elsize
+testfile9:    3ac0 shdr_info[cnt].shdr.sh_type == 18
+testfile9:    3b00 shdr_info[cnt].data != ((void *)0)
+testfile9:    3b40 elf_ndxscn (shdr_info[cnt].newscn) == idx
+testfile9:    3b80 while create section header section: %s
+testfile9:    3bc0 cannot allocate section data: %s
+testfile9:    3c00 elf_ndxscn (shdr_info[cnt].newscn) == shdr_info[cnt].idx
+testfile9:    3c40 while generating output file: %s
+testfile9:    3c80 while preparing output for `%s'
+testfile9:    3ca0 shdr_info[cnt].shdr.sh_type == 2
+testfile9:    3ce0 shdr_info[idx].data != ((void *)0)
+testfile9:    3d20 cannot determine number of sections: %s
+testfile9:    3d60 cannot get section header string table index
+testfile9:    3e20 Discard symbols from object files.
+testfile9:    3e43 [FILE...]
+EOF
+
+exit 0
diff --git a/tests/run-strip-g.sh b/tests/run-strip-g.sh
new file mode 100755
index 0000000..1592121
--- /dev/null
+++ b/tests/run-strip-g.sh
@@ -0,0 +1,102 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# When stripping just the debug sections/symbols we keep the symtab
+# in the main ELF file. There should be no symbols pointing into the
+# debug sections and so there should not be a copy in the debug file
+# except for a NOBITS one.
+
+tempfiles a.out strip.out debug.out readelf.out
+
+echo Create debug a.out.
+echo "int main() { return 1; }" | ${CC} -g -xc -
+
+echo strip -g to file with debug file
+testrun ${abs_top_builddir}/src/strip -g -o strip.out -f debug.out ||
+  { echo "*** failed to strip -g -o strip.out -f debug.out a.out"; exit -1; }
+
+status=0
+testrun ${abs_top_builddir}/src/readelf -S strip.out > readelf.out
+grep SYMTAB readelf.out || status=$?
+echo $status
+if test $status -ne 0; then
+  echo no symtab found in strip.out
+  exit 1
+fi
+
+status=0
+testrun ${abs_top_builddir}/src/readelf -S debug.out > readelf.out
+grep SYMTAB readelf.out || status=$?
+echo $status
+if test $status -ne 1; then
+  echo symtab found in debug.out
+  exit 1
+fi
+
+# arm (with data marker in .debug_frame). See tests/run-addrcfi.sh
+testfiles testfilearm
+
+echo arm strip -g to file with debug file
+testrun ${abs_top_builddir}/src/strip -g -o strip.out -f debug.out testfilearm ||
+  { echo "*** failed to strip -g -o strip.out -f debug.out a.out"; exit -1; }
+
+status=0
+testrun ${abs_top_builddir}/src/readelf -S strip.out > readelf.out
+grep SYMTAB readelf.out || status=$?
+echo $status
+if test $status -ne 0; then
+  echo no symtab found in strip.out
+  exit 1
+fi
+
+status=0
+testrun ${abs_top_builddir}/src/readelf -S debug.out > readelf.out
+grep SYMTAB readelf.out || status=$?
+echo $status
+if test $status -ne 1; then
+  echo symtab found in debug.out
+  exit 1
+fi
+
+# aarch64 (with data marker in .debug_frame). See tests/run-addrcfi.sh
+testfiles testfileaarch64
+
+echo aarch64 strip -g to file with debug file
+testrun ${abs_top_builddir}/src/strip -g -o strip.out -f debug.out testfileaarch64 ||
+  { echo "*** failed to strip -g -o strip.out -f debug.out a.out"; exit -1; }
+
+status=0
+testrun ${abs_top_builddir}/src/readelf -S strip.out > readelf.out
+grep SYMTAB readelf.out || status=$?
+echo $status
+if test $status -ne 0; then
+  echo no symtab found in strip.out
+  exit 1
+fi
+
+status=0
+testrun ${abs_top_builddir}/src/readelf -S debug.out > readelf.out
+grep SYMTAB readelf.out || status=$?
+echo $status
+if test $status -ne 1; then
+  echo symtab found in debug.out
+  exit 1
+fi
+
+exit 0
diff --git a/tests/run-strip-groups.sh b/tests/run-strip-groups.sh
new file mode 100755
index 0000000..1c836a4
--- /dev/null
+++ b/tests/run-strip-groups.sh
@@ -0,0 +1,55 @@
+#! /bin/sh
+# Copyright (C) 2011 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+# g++ -gdwarf-4 -c testfile58.cxx
+# class ct
+# {
+#   private:
+#   int i;
+#
+#   public:
+#   void foo ()
+#   {
+#     i = 1;
+#   }
+#
+#   int bar ()
+#   {
+#     return i;
+#   }
+# };
+#
+# int baz ()
+# {
+#   class ct c;
+#   c.foo ();
+#   return c.bar ();
+# }
+
+. $srcdir/test-subr.sh
+
+infile=testfile58
+outfile=$infile.stripped
+dbgfile=$infile.debug
+
+testfiles $infile
+tempfiles $outfile $dbgfile
+
+testrun ${abs_top_builddir}/src/strip -o $outfile -f $dbgfile $infile
+testrun ${abs_top_builddir}/src/elflint -q $infile
+testrun ${abs_top_builddir}/src/elflint -q $outfile
+testrun ${abs_top_builddir}/src/elflint -q -d $dbgfile
diff --git a/tests/run-strip-largealign.sh b/tests/run-strip-largealign.sh
new file mode 100755
index 0000000..4f81d3c
--- /dev/null
+++ b/tests/run-strip-largealign.sh
@@ -0,0 +1,35 @@
+#! /bin/sh
+# Copyright (C) 2021 Runsafe Security, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+. $srcdir/test-subr.sh
+
+# = testfile-largealign.S =
+# section .data
+# align 4096
+# dd 0x12345678
+#
+# nasm -f elf64 -o testfile-largealign.o testfile-largealign.S
+
+infile=testfile-largealign.o
+outfile=$infile.stripped
+
+testfiles $infile
+tempfiles $outfile
+
+testrun ${abs_top_builddir}/src/strip -o $outfile $infile
+testrun ${abs_top_builddir}/src/elflint --gnu $outfile
diff --git a/tests/run-strip-nobitsalign.sh b/tests/run-strip-nobitsalign.sh
new file mode 100755
index 0000000..db9b1d9
--- /dev/null
+++ b/tests/run-strip-nobitsalign.sh
@@ -0,0 +1,35 @@
+#! /bin/sh
+# Copyright (C) Red Hat, Inc., 2016.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# static unsigned char buffer[4096] __attribute((aligned (4096)));
+# 
+# char
+# f (int i)
+# {
+#   return buffer[i];
+# }
+# 
+# int
+# main (int argc, char **argv)
+# {
+#   return buffer[argc] == 0;
+# }
+
+original=testfile-nobitsalign
+stripped=testfile-nobitsalign.strip
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-nothing.sh b/tests/run-strip-nothing.sh
new file mode 100755
index 0000000..710c200
--- /dev/null
+++ b/tests/run-strip-nothing.sh
@@ -0,0 +1,62 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# If there is nothing to strip then -o output should be identical to input.
+# And there should not be an (empty) -f debug file.
+
+tempfiles a.out strip.out debug.out
+
+# Create no-debug a.out.
+echo "int main() { return 1; }" | ${CC} -s -xc -
+
+# strip to file
+testrun ${abs_top_builddir}/src/strip -g -o strip.out ||
+  { echo "*** failed to strip -g -o strip.out a.out"; exit -1; }
+
+testrun ${abs_top_builddir}/src/elfcmp a.out strip.out ||
+  { echo "*** failed strip.out different from a.out"; exit -1; }
+
+# strip original
+testrun ${abs_top_builddir}/src/strip -g ||
+  { echo "*** failed to strip -g a.out"; exit -1; }
+
+testrun ${abs_top_builddir}/src/elfcmp strip.out a.out ||
+  { echo "*** failed a.out different from strip.out"; exit -1; }
+
+# strip to file with debug file
+testrun ${abs_top_builddir}/src/strip -g -o strip.out -f debug.out ||
+  { echo "*** failed to strip -g -o strip.out -f debug.out a.out"; exit -1; }
+
+testrun ${abs_top_builddir}/src/elfcmp a.out strip.out ||
+  { echo "*** failed strip.out different from a.out (with debug)"; exit -1; }
+
+test ! -f debug.out ||
+  { echo "*** failed strip.out and debug.out exist"; exit -1; }
+
+# strip original with debug file
+testrun ${abs_top_builddir}/src/strip -g -f debug.out ||
+  { echo "*** failed to strip -g -f debug.out a.out"; exit -1; }
+
+testrun ${abs_top_builddir}/src/elfcmp strip.out a.out ||
+  { echo "*** failed a.out different from strip.out (with debug)"; exit -1; }
+
+test ! -f debug.out ||
+  { echo "*** failed a.out and debug.out exist"; exit -1; }
+
+exit 0
diff --git a/tests/run-strip-reloc-ko.sh b/tests/run-strip-reloc-ko.sh
new file mode 100755
index 0000000..55fa74d
--- /dev/null
+++ b/tests/run-strip-reloc-ko.sh
@@ -0,0 +1,51 @@
+#! /bin/sh
+
+. $srcdir/strip-reloc-subr.sh
+
+testfiles hello_i386.ko hello_x86_64.ko hello_ppc64.ko hello_s390.ko \
+	hello_aarch64.ko hello_m68k.ko hello_riscv64.ko hello_csky.ko \
+	hello_arc_hs4.ko
+
+# Most simple hello world kernel module for various architectures.
+# Make sure that it contains debuginfo with CONFIG_DEBUG_INFO=y.
+# ::::::::::::::
+# Makefile
+# ::::::::::::::
+# obj-m	:= hello.o
+# hello-y := init.o exit.o
+# 
+# all:
+# 	make -C /lib/modules/$(shell uname -r)/build M=$(PWD) \
+#		CONFIG_DEBUG_INFO=y modules
+# ::::::::::::::
+# init.c
+# ::::::::::::::
+# #include <linux/kernel.h>
+# #include <linux/module.h>
+# 
+# int init_module(void)
+# {
+#   printk(KERN_INFO "Hello, world!\n");
+#   return 0;
+# }
+# ::::::::::::::
+# exit.c
+# ::::::::::::::
+# #include <linux/kernel.h>
+# #include <linux/module.h>
+# 
+# void cleanup_module()
+# {
+#   printk(KERN_INFO "Goodbye, World!\n");
+# }
+runtest hello_i386.ko 1
+runtest hello_x86_64.ko 1
+runtest hello_ppc64.ko 1
+runtest hello_s390.ko 1
+runtest hello_aarch64.ko 1
+runtest hello_m68k.ko 1
+runtest hello_riscv64.ko 1
+runtest hello_csky.ko 1
+runtest hello_arc_hs4.ko 1
+
+exit $runtest_status
diff --git a/tests/run-strip-reloc-ppc64.sh b/tests/run-strip-reloc-ppc64.sh
new file mode 100755
index 0000000..239c34d
--- /dev/null
+++ b/tests/run-strip-reloc-ppc64.sh
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+. $srcdir/strip-reloc-subr.sh
+
+# See run-readelf-zdebug-rel.sh
+testfiles testfile-debug-rel-ppc64.o
+runtest testfile-debug-rel-ppc64.o 1
+
+testfiles testfile-debug-rel-ppc64-z.o
+runtest testfile-debug-rel-ppc64-z.o 1
+
+testfiles testfile-debug-rel-ppc64-g.o
+runtest testfile-debug-rel-ppc64-g.o 1
+
+exit $runtest_status
diff --git a/tests/run-strip-reloc-self.sh b/tests/run-strip-reloc-self.sh
new file mode 100755
index 0000000..68ed4cc
--- /dev/null
+++ b/tests/run-strip-reloc-self.sh
@@ -0,0 +1,20 @@
+#! /bin/sh
+
+. $srcdir/strip-reloc-subr.sh
+
+# self test, shouldn't impact non-ET_REL files at all.
+runtest ${abs_top_builddir}/src/strip 0
+runtest ${abs_top_builddir}/src/strip.o 1
+
+# Copy ET_REL file for self-test and make sure to run with/without
+# elf section compression.
+tempfiles strip-uncompressed.o strip-compressed.o
+testrun ${abs_top_builddir}/src/elfcompress -o strip-uncompressed.o -t none \
+  ${abs_top_builddir}/src/strip.o
+testrun ${abs_top_builddir}/src/elfcompress -o strip-compressed.o -t zlib \
+  --force ${abs_top_builddir}/src/strip.o
+
+runtest strip-uncompressed.o 1
+runtest strip-compressed.o 1
+
+exit $runtest_status
diff --git a/tests/run-strip-remove-keep.sh b/tests/run-strip-remove-keep.sh
new file mode 100755
index 0000000..92647fa
--- /dev/null
+++ b/tests/run-strip-remove-keep.sh
@@ -0,0 +1,688 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# strip -o output and -f debug files
+tempfiles testfile.elf testfile.debug
+
+# A random 32bit testfile
+testfiles testfile
+
+# Explicitly keep .strtab (but not .symtab, so .strtab will be in both). 32bit
+echo strip --keep-section=.strtab testfile
+testrun ${abs_top_builddir}/src/strip --keep-section=.strtab -o testfile.elf -f testfile.debug testfile
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 27 section headers, starting at offset 0xaf8:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              PROGBITS     080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 000108 000020  0 A      0   0  4
+[ 3] .hash                HASH         08048128 000128 000030  4 A      4   0  4
+[ 4] .dynsym              DYNSYM       08048158 000158 000070 16 A      5   1  4
+[ 5] .dynstr              STRTAB       080481c8 0001c8 00008e  0 A      0   0  1
+[ 6] .gnu.version         GNU_versym   08048256 000256 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       GNU_verneed  08048264 000264 000030  0 A      5   1  4
+[ 8] .rel.got             REL          08048294 000294 000008  8 A      4  19  4
+[ 9] .rel.plt             REL          0804829c 00029c 000020  8 A      4  11  4
+[10] .init                PROGBITS     080482bc 0002bc 000018  0 AX     0   0  4
+[11] .plt                 PROGBITS     080482d4 0002d4 000050  4 AX     0   0  4
+[12] .text                PROGBITS     08048330 000330 00018c  0 AX     0   0 16
+[13] .fini                PROGBITS     080484bc 0004bc 00001e  0 AX     0   0  4
+[14] .rodata              PROGBITS     080484dc 0004dc 000008  0 A      0   0  4
+[15] .data                PROGBITS     080494e4 0004e4 000010  0 WA     0   0  4
+[16] .eh_frame            PROGBITS     080494f4 0004f4 000004  0 WA     0   0  4
+[17] .ctors               PROGBITS     080494f8 0004f8 000008  0 WA     0   0  4
+[18] .dtors               PROGBITS     08049500 000500 000008  0 WA     0   0  4
+[19] .got                 PROGBITS     08049508 000508 000020  4 WA     0   0  4
+[20] .dynamic             DYNAMIC      08049528 000528 0000a0  8 WA     5   0  4
+[21] .bss                 NOBITS       080495c8 0005c8 00001c  0 WA     0   0  4
+[22] .comment             PROGBITS     00000000 0005c8 000170  0        0   0  1
+[23] .note                NOTE         00000000 000738 0000a0  0        0   0  1
+[24] .strtab              STRTAB       00000000 0007d8 000235  0        0   0  1
+[25] .gnu_debuglink       PROGBITS     00000000 000a10 000014  0        0   0  4
+[26] .shstrtab            STRTAB       00000000 000a24 0000d1  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 35 section headers, starting at offset 0x463c:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              NOBITS       080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 0000f4 000020  0 A      0   0  4
+[ 3] .hash                NOBITS       08048128 000114 000030  4 A      4   0  4
+[ 4] .dynsym              NOBITS       08048158 000114 000070 16 A      5   1  4
+[ 5] .dynstr              NOBITS       080481c8 000114 00008e  0 A      0   0  1
+[ 6] .gnu.version         NOBITS       08048256 000114 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       NOBITS       08048264 000114 000030  0 A      5   1  4
+[ 8] .rel.got             NOBITS       08048294 000114 000008  8 A      4  19  4
+[ 9] .rel.plt             NOBITS       0804829c 000114 000020  8 A      4  11  4
+[10] .init                NOBITS       080482bc 000114 000018  0 AX     0   0  4
+[11] .plt                 NOBITS       080482d4 000114 000050  4 AX     0   0  4
+[12] .text                NOBITS       08048330 000120 00018c  0 AX     0   0 16
+[13] .fini                NOBITS       080484bc 000120 00001e  0 AX     0   0  4
+[14] .rodata              NOBITS       080484dc 000120 000008  0 A      0   0  4
+[15] .data                NOBITS       080494e4 000120 000010  0 WA     0   0  4
+[16] .eh_frame            NOBITS       080494f4 000120 000004  0 WA     0   0  4
+[17] .ctors               NOBITS       080494f8 000120 000008  0 WA     0   0  4
+[18] .dtors               NOBITS       08049500 000120 000008  0 WA     0   0  4
+[19] .got                 NOBITS       08049508 000120 000020  4 WA     0   0  4
+[20] .dynamic             NOBITS       08049528 000120 0000a0  8 WA     5   0  4
+[21] .sbss                PROGBITS     080495c8 000120 000000  0 W      0   0  1
+[22] .bss                 NOBITS       080495c8 000120 00001c  0 WA     0   0  4
+[23] .stab                PROGBITS     00000000 000120 000720 12       24   0  4
+[24] .stabstr             STRTAB       00000000 000840 001934  0        0   0  1
+[25] .comment             NOBITS       00000000 002174 000170  0        0   0  1
+[26] .debug_aranges       PROGBITS     00000000 002174 000060  0        0   0  1
+[27] .debug_pubnames      PROGBITS     00000000 0021d4 000055  0        0   0  1
+[28] .debug_info          PROGBITS     00000000 002229 001678  0        0   0  1
+[29] .debug_abbrev        PROGBITS     00000000 0038a1 0001d2  0        0   0  1
+[30] .debug_line          PROGBITS     00000000 003a73 000223  0        0   0  1
+[31] .note                NOTE         00000000 003c96 0000a0  0        0   0  1
+[32] .shstrtab            STRTAB       00000000 003d36 00012e  0        0   0  1
+[33] .symtab              SYMTAB       00000000 003e64 0005a0 16       34  68  4
+[34] .strtab              STRTAB       00000000 004404 000235  0        0   0  1
+
+EOF
+
+# Explicitly keep .symtab (pulls in .strtab, so they will both be in elf). 32bit
+echo strip --keep-section=.symtab testfile
+testrun ${abs_top_builddir}/src/strip --keep-section=.symtab -o testfile.elf -f testfile.debug testfile
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 28 section headers, starting at offset 0x1010:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              PROGBITS     080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 000108 000020  0 A      0   0  4
+[ 3] .hash                HASH         08048128 000128 000030  4 A      4   0  4
+[ 4] .dynsym              DYNSYM       08048158 000158 000070 16 A      5   1  4
+[ 5] .dynstr              STRTAB       080481c8 0001c8 00008e  0 A      0   0  1
+[ 6] .gnu.version         GNU_versym   08048256 000256 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       GNU_verneed  08048264 000264 000030  0 A      5   1  4
+[ 8] .rel.got             REL          08048294 000294 000008  8 A      4  19  4
+[ 9] .rel.plt             REL          0804829c 00029c 000020  8 A      4  11  4
+[10] .init                PROGBITS     080482bc 0002bc 000018  0 AX     0   0  4
+[11] .plt                 PROGBITS     080482d4 0002d4 000050  4 AX     0   0  4
+[12] .text                PROGBITS     08048330 000330 00018c  0 AX     0   0 16
+[13] .fini                PROGBITS     080484bc 0004bc 00001e  0 AX     0   0  4
+[14] .rodata              PROGBITS     080484dc 0004dc 000008  0 A      0   0  4
+[15] .data                PROGBITS     080494e4 0004e4 000010  0 WA     0   0  4
+[16] .eh_frame            PROGBITS     080494f4 0004f4 000004  0 WA     0   0  4
+[17] .ctors               PROGBITS     080494f8 0004f8 000008  0 WA     0   0  4
+[18] .dtors               PROGBITS     08049500 000500 000008  0 WA     0   0  4
+[19] .got                 PROGBITS     08049508 000508 000020  4 WA     0   0  4
+[20] .dynamic             DYNAMIC      08049528 000528 0000a0  8 WA     5   0  4
+[21] .bss                 NOBITS       080495c8 0005c8 00001c  0 WA     0   0  4
+[22] .comment             PROGBITS     00000000 0005c8 000170  0        0   0  1
+[23] .note                NOTE         00000000 000738 0000a0  0        0   0  1
+[24] .symtab              SYMTAB       00000000 0007d8 000510 16       25  59  4
+[25] .strtab              STRTAB       00000000 000ce8 000235  0        0   0  1
+[26] .gnu_debuglink       PROGBITS     00000000 000f20 000014  0        0   0  4
+[27] .shstrtab            STRTAB       00000000 000f34 0000d9  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 35 section headers, starting at offset 0x3e64:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              NOBITS       080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 0000f4 000020  0 A      0   0  4
+[ 3] .hash                NOBITS       08048128 000114 000030  4 A      4   0  4
+[ 4] .dynsym              NOBITS       08048158 000114 000070 16 A      5   1  4
+[ 5] .dynstr              NOBITS       080481c8 000114 00008e  0 A      0   0  1
+[ 6] .gnu.version         NOBITS       08048256 000114 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       NOBITS       08048264 000114 000030  0 A      5   1  4
+[ 8] .rel.got             NOBITS       08048294 000114 000008  8 A      4  19  4
+[ 9] .rel.plt             NOBITS       0804829c 000114 000020  8 A      4  11  4
+[10] .init                NOBITS       080482bc 000114 000018  0 AX     0   0  4
+[11] .plt                 NOBITS       080482d4 000114 000050  4 AX     0   0  4
+[12] .text                NOBITS       08048330 000120 00018c  0 AX     0   0 16
+[13] .fini                NOBITS       080484bc 000120 00001e  0 AX     0   0  4
+[14] .rodata              NOBITS       080484dc 000120 000008  0 A      0   0  4
+[15] .data                NOBITS       080494e4 000120 000010  0 WA     0   0  4
+[16] .eh_frame            NOBITS       080494f4 000120 000004  0 WA     0   0  4
+[17] .ctors               NOBITS       080494f8 000120 000008  0 WA     0   0  4
+[18] .dtors               NOBITS       08049500 000120 000008  0 WA     0   0  4
+[19] .got                 NOBITS       08049508 000120 000020  4 WA     0   0  4
+[20] .dynamic             NOBITS       08049528 000120 0000a0  8 WA     5   0  4
+[21] .sbss                PROGBITS     080495c8 000120 000000  0 W      0   0  1
+[22] .bss                 NOBITS       080495c8 000120 00001c  0 WA     0   0  4
+[23] .stab                PROGBITS     00000000 000120 000720 12       24   0  4
+[24] .stabstr             STRTAB       00000000 000840 001934  0        0   0  1
+[25] .comment             NOBITS       00000000 002174 000170  0        0   0  1
+[26] .debug_aranges       PROGBITS     00000000 002174 000060  0        0   0  1
+[27] .debug_pubnames      PROGBITS     00000000 0021d4 000055  0        0   0  1
+[28] .debug_info          PROGBITS     00000000 002229 001678  0        0   0  1
+[29] .debug_abbrev        PROGBITS     00000000 0038a1 0001d2  0        0   0  1
+[30] .debug_line          PROGBITS     00000000 003a73 000223  0        0   0  1
+[31] .note                NOTE         00000000 003c96 0000a0  0        0   0  1
+[32] .shstrtab            STRTAB       00000000 003d36 00012e  0        0   0  1
+[33] .symtab              NOBITS       00000000 003e64 0005a0 16       34  68  4
+[34] .strtab              NOBITS       00000000 003e64 000235  0        0   0  1
+
+EOF
+
+# A random 64bit testfile
+testfiles testfile69.so
+# Explicitly keep .strtab (but not .symtab, so .strtab will be in both). 64bit
+echo strip --keep-section=.strtab testfile69.so
+testrun ${abs_top_builddir}/src/strip --keep-section=.strtab -o testfile.elf -f testfile.debug testfile69.so
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 27 section headers, starting at offset 0xad8:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            GNU_HASH     00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              DYNSYM       00000000000001f8 000001f8 00000108 24 A      4   2  8
+[ 4] .dynstr              STRTAB       0000000000000300 00000300 00000077  0 A      0   0  1
+[ 5] .gnu.version         GNU_versym   0000000000000378 00000378 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       GNU_verneed  0000000000000390 00000390 00000020  0 A      4   1  8
+[ 7] .rela.dyn            RELA         00000000000003b0 000003b0 00000060 24 A      3   0  8
+[ 8] .rela.plt            RELA         0000000000000410 00000410 00000018 24 A      3  10  8
+[ 9] .init                PROGBITS     0000000000000428 00000428 00000018  0 AX     0   0  4
+[10] .plt                 PROGBITS     0000000000000440 00000440 00000020 16 AX     0   0 16
+[11] .text                PROGBITS     0000000000000460 00000460 00000128  0 AX     0   0 16
+[12] .fini                PROGBITS     0000000000000588 00000588 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        PROGBITS     0000000000000598 00000598 00000024  0 A      0   0  4
+[14] .eh_frame            PROGBITS     00000000000005c0 000005c0 00000084  0 A      0   0  8
+[15] .ctors               PROGBITS     0000000000200648 00000648 00000010  0 WA     0   0  8
+[16] .dtors               PROGBITS     0000000000200658 00000658 00000010  0 WA     0   0  8
+[17] .jcr                 PROGBITS     0000000000200668 00000668 00000008  0 WA     0   0  8
+[18] .data.rel.ro         PROGBITS     0000000000200670 00000670 00000008  0 WA     0   0  8
+[19] .dynamic             DYNAMIC      0000000000200678 00000678 00000180 16 WA     4   0  8
+[20] .got                 PROGBITS     00000000002007f8 000007f8 00000018  8 WA     0   0  8
+[21] .got.plt             PROGBITS     0000000000200810 00000810 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 00000830 00000010  0 WA     0   0  8
+[23] .comment             PROGBITS     0000000000000000 00000830 0000002c  1 MS     0   0  1
+[24] .strtab              STRTAB       0000000000000000 0000085c 00000175  0        0   0  1
+[25] .gnu_debuglink       PROGBITS     0000000000000000 000009d4 00000014  0        0   0  4
+[26] .shstrtab            STRTAB       0000000000000000 000009e8 000000ee  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 27 section headers, starting at offset 0x918:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            NOBITS       00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              NOBITS       00000000000001f8 000001b8 00000108 24 A      4   2  8
+[ 4] .dynstr              NOBITS       0000000000000300 000001b8 00000077  0 A      0   0  1
+[ 5] .gnu.version         NOBITS       0000000000000378 000001b8 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       NOBITS       0000000000000390 000001b8 00000020  0 A      4   1  8
+[ 7] .rela.dyn            NOBITS       00000000000003b0 000001b8 00000060 24 A      3   0  8
+[ 8] .rela.plt            NOBITS       0000000000000410 000001b8 00000018 24 A      3  10  8
+[ 9] .init                NOBITS       0000000000000428 000001b8 00000018  0 AX     0   0  4
+[10] .plt                 NOBITS       0000000000000440 000001c0 00000020 16 AX     0   0 16
+[11] .text                NOBITS       0000000000000460 000001c0 00000128  0 AX     0   0 16
+[12] .fini                NOBITS       0000000000000588 000001c0 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        NOBITS       0000000000000598 000001c0 00000024  0 A      0   0  4
+[14] .eh_frame            NOBITS       00000000000005c0 000001c0 00000084  0 A      0   0  8
+[15] .ctors               NOBITS       0000000000200648 000001c0 00000010  0 WA     0   0  8
+[16] .dtors               NOBITS       0000000000200658 000001c0 00000010  0 WA     0   0  8
+[17] .jcr                 NOBITS       0000000000200668 000001c0 00000008  0 WA     0   0  8
+[18] .data.rel.ro         NOBITS       0000000000200670 000001c0 00000008  0 WA     0   0  8
+[19] .dynamic             NOBITS       0000000000200678 000001c0 00000180 16 WA     4   0  8
+[20] .got                 NOBITS       00000000002007f8 000001c0 00000018  8 WA     0   0  8
+[21] .got.plt             NOBITS       0000000000200810 000001c0 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 000001c0 00000010  0 WA     0   0  8
+[23] .comment             NOBITS       0000000000000000 000001c0 0000002c  1 MS     0   0  1
+[24] .shstrtab            STRTAB       0000000000000000 000001c0 000000e7  0        0   0  1
+[25] .symtab              SYMTAB       0000000000000000 000002a8 000004f8 24       26  44  8
+[26] .strtab              STRTAB       0000000000000000 000007a0 00000175  0        0   0  1
+
+EOF
+
+# Explicitly keep .symtab (pulls in .strtab, so they will both be in elf). 64bit
+# Use --remove-comment to make sure testfile.debug isn't empty.
+echo strip --keep-section=.symtab --remove-comment testfile69.so
+testrun ${abs_top_builddir}/src/strip --keep-section=.symtab --remove-comment -o testfile.elf -f testfile.debug testfile69.so
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 27 section headers, starting at offset 0xf90:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            GNU_HASH     00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              DYNSYM       00000000000001f8 000001f8 00000108 24 A      4   2  8
+[ 4] .dynstr              STRTAB       0000000000000300 00000300 00000077  0 A      0   0  1
+[ 5] .gnu.version         GNU_versym   0000000000000378 00000378 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       GNU_verneed  0000000000000390 00000390 00000020  0 A      4   1  8
+[ 7] .rela.dyn            RELA         00000000000003b0 000003b0 00000060 24 A      3   0  8
+[ 8] .rela.plt            RELA         0000000000000410 00000410 00000018 24 A      3  10  8
+[ 9] .init                PROGBITS     0000000000000428 00000428 00000018  0 AX     0   0  4
+[10] .plt                 PROGBITS     0000000000000440 00000440 00000020 16 AX     0   0 16
+[11] .text                PROGBITS     0000000000000460 00000460 00000128  0 AX     0   0 16
+[12] .fini                PROGBITS     0000000000000588 00000588 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        PROGBITS     0000000000000598 00000598 00000024  0 A      0   0  4
+[14] .eh_frame            PROGBITS     00000000000005c0 000005c0 00000084  0 A      0   0  8
+[15] .ctors               PROGBITS     0000000000200648 00000648 00000010  0 WA     0   0  8
+[16] .dtors               PROGBITS     0000000000200658 00000658 00000010  0 WA     0   0  8
+[17] .jcr                 PROGBITS     0000000000200668 00000668 00000008  0 WA     0   0  8
+[18] .data.rel.ro         PROGBITS     0000000000200670 00000670 00000008  0 WA     0   0  8
+[19] .dynamic             DYNAMIC      0000000000200678 00000678 00000180 16 WA     4   0  8
+[20] .got                 PROGBITS     00000000002007f8 000007f8 00000018  8 WA     0   0  8
+[21] .got.plt             PROGBITS     0000000000200810 00000810 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 00000830 00000010  0 WA     0   0  8
+[23] .symtab              SYMTAB       0000000000000000 00000830 000004e0 24       24  43  8
+[24] .strtab              STRTAB       0000000000000000 00000d10 00000175  0        0   0  1
+[25] .gnu_debuglink       PROGBITS     0000000000000000 00000e88 00000014  0        0   0  4
+[26] .shstrtab            STRTAB       0000000000000000 00000e9c 000000ed  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 27 section headers, starting at offset 0x2d8:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            NOBITS       00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              NOBITS       00000000000001f8 000001b8 00000108 24 A      4   2  8
+[ 4] .dynstr              NOBITS       0000000000000300 000001b8 00000077  0 A      0   0  1
+[ 5] .gnu.version         NOBITS       0000000000000378 000001b8 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       NOBITS       0000000000000390 000001b8 00000020  0 A      4   1  8
+[ 7] .rela.dyn            NOBITS       00000000000003b0 000001b8 00000060 24 A      3   0  8
+[ 8] .rela.plt            NOBITS       0000000000000410 000001b8 00000018 24 A      3  10  8
+[ 9] .init                NOBITS       0000000000000428 000001b8 00000018  0 AX     0   0  4
+[10] .plt                 NOBITS       0000000000000440 000001c0 00000020 16 AX     0   0 16
+[11] .text                NOBITS       0000000000000460 000001c0 00000128  0 AX     0   0 16
+[12] .fini                NOBITS       0000000000000588 000001c0 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        NOBITS       0000000000000598 000001c0 00000024  0 A      0   0  4
+[14] .eh_frame            NOBITS       00000000000005c0 000001c0 00000084  0 A      0   0  8
+[15] .ctors               NOBITS       0000000000200648 000001c0 00000010  0 WA     0   0  8
+[16] .dtors               NOBITS       0000000000200658 000001c0 00000010  0 WA     0   0  8
+[17] .jcr                 NOBITS       0000000000200668 000001c0 00000008  0 WA     0   0  8
+[18] .data.rel.ro         NOBITS       0000000000200670 000001c0 00000008  0 WA     0   0  8
+[19] .dynamic             NOBITS       0000000000200678 000001c0 00000180 16 WA     4   0  8
+[20] .got                 NOBITS       00000000002007f8 000001c0 00000018  8 WA     0   0  8
+[21] .got.plt             NOBITS       0000000000200810 000001c0 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 000001c0 00000010  0 WA     0   0  8
+[23] .comment             PROGBITS     0000000000000000 000001c0 0000002c  1 MS     0   0  1
+[24] .shstrtab            STRTAB       0000000000000000 000001ec 000000e7  0        0   0  1
+[25] .symtab              NOBITS       0000000000000000 000002d8 000004f8 24       26  44  8
+[26] .strtab              NOBITS       0000000000000000 000002d8 00000175  0        0   0  1
+
+EOF
+
+# Explicitly remove .symtab (but not .strtab, so it will be in both). 32bit
+echo strip -g --remove-section=.symtab testfile
+testrun ${abs_top_builddir}/src/strip -g --remove-section=.symtab -o testfile.elf -f testfile.debug testfile
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 28 section headers, starting at offset 0xafc:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              PROGBITS     080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 000108 000020  0 A      0   0  4
+[ 3] .hash                HASH         08048128 000128 000030  4 A      4   0  4
+[ 4] .dynsym              DYNSYM       08048158 000158 000070 16 A      5   1  4
+[ 5] .dynstr              STRTAB       080481c8 0001c8 00008e  0 A      0   0  1
+[ 6] .gnu.version         GNU_versym   08048256 000256 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       GNU_verneed  08048264 000264 000030  0 A      5   1  4
+[ 8] .rel.got             REL          08048294 000294 000008  8 A      4  19  4
+[ 9] .rel.plt             REL          0804829c 00029c 000020  8 A      4  11  4
+[10] .init                PROGBITS     080482bc 0002bc 000018  0 AX     0   0  4
+[11] .plt                 PROGBITS     080482d4 0002d4 000050  4 AX     0   0  4
+[12] .text                PROGBITS     08048330 000330 00018c  0 AX     0   0 16
+[13] .fini                PROGBITS     080484bc 0004bc 00001e  0 AX     0   0  4
+[14] .rodata              PROGBITS     080484dc 0004dc 000008  0 A      0   0  4
+[15] .data                PROGBITS     080494e4 0004e4 000010  0 WA     0   0  4
+[16] .eh_frame            PROGBITS     080494f4 0004f4 000004  0 WA     0   0  4
+[17] .ctors               PROGBITS     080494f8 0004f8 000008  0 WA     0   0  4
+[18] .dtors               PROGBITS     08049500 000500 000008  0 WA     0   0  4
+[19] .got                 PROGBITS     08049508 000508 000020  4 WA     0   0  4
+[20] .dynamic             DYNAMIC      08049528 000528 0000a0  8 WA     5   0  4
+[21] .sbss                PROGBITS     080495c8 0005c8 000000  0 W      0   0  1
+[22] .bss                 NOBITS       080495c8 0005c8 00001c  0 WA     0   0  4
+[23] .comment             PROGBITS     00000000 0005c8 000170  0        0   0  1
+[24] .note                NOTE         00000000 000738 0000a0  0        0   0  1
+[25] .strtab              STRTAB       00000000 0007d8 000235  0        0   0  1
+[26] .gnu_debuglink       PROGBITS     00000000 000a10 000014  0        0   0  4
+[27] .shstrtab            STRTAB       00000000 000a24 0000d7  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 35 section headers, starting at offset 0x463c:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              NOBITS       080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 0000f4 000020  0 A      0   0  4
+[ 3] .hash                NOBITS       08048128 000114 000030  4 A      4   0  4
+[ 4] .dynsym              NOBITS       08048158 000114 000070 16 A      5   1  4
+[ 5] .dynstr              NOBITS       080481c8 000114 00008e  0 A      0   0  1
+[ 6] .gnu.version         NOBITS       08048256 000114 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       NOBITS       08048264 000114 000030  0 A      5   1  4
+[ 8] .rel.got             NOBITS       08048294 000114 000008  8 A      4  19  4
+[ 9] .rel.plt             NOBITS       0804829c 000114 000020  8 A      4  11  4
+[10] .init                NOBITS       080482bc 000114 000018  0 AX     0   0  4
+[11] .plt                 NOBITS       080482d4 000114 000050  4 AX     0   0  4
+[12] .text                NOBITS       08048330 000120 00018c  0 AX     0   0 16
+[13] .fini                NOBITS       080484bc 000120 00001e  0 AX     0   0  4
+[14] .rodata              NOBITS       080484dc 000120 000008  0 A      0   0  4
+[15] .data                NOBITS       080494e4 000120 000010  0 WA     0   0  4
+[16] .eh_frame            NOBITS       080494f4 000120 000004  0 WA     0   0  4
+[17] .ctors               NOBITS       080494f8 000120 000008  0 WA     0   0  4
+[18] .dtors               NOBITS       08049500 000120 000008  0 WA     0   0  4
+[19] .got                 NOBITS       08049508 000120 000020  4 WA     0   0  4
+[20] .dynamic             NOBITS       08049528 000120 0000a0  8 WA     5   0  4
+[21] .sbss                NOBITS       080495c8 000120 000000  0 W      0   0  1
+[22] .bss                 NOBITS       080495c8 000120 00001c  0 WA     0   0  4
+[23] .stab                PROGBITS     00000000 000120 000720 12       24   0  4
+[24] .stabstr             STRTAB       00000000 000840 001934  0        0   0  1
+[25] .comment             NOBITS       00000000 002174 000170  0        0   0  1
+[26] .debug_aranges       PROGBITS     00000000 002174 000060  0        0   0  1
+[27] .debug_pubnames      PROGBITS     00000000 0021d4 000055  0        0   0  1
+[28] .debug_info          PROGBITS     00000000 002229 001678  0        0   0  1
+[29] .debug_abbrev        PROGBITS     00000000 0038a1 0001d2  0        0   0  1
+[30] .debug_line          PROGBITS     00000000 003a73 000223  0        0   0  1
+[31] .note                NOTE         00000000 003c96 0000a0  0        0   0  1
+[32] .shstrtab            STRTAB       00000000 003d36 00012e  0        0   0  1
+[33] .symtab              SYMTAB       00000000 003e64 0005a0 16       34  68  4
+[34] .strtab              STRTAB       00000000 004404 000235  0        0   0  1
+
+EOF
+
+# Explicitly remove both .symtab and .strtab. Keep .stab and .stabstr 32bit
+echo strip -g --remove-section=".s[yt][mr]tab" --keep-section=".stab*" testfile
+testrun ${abs_top_builddir}/src/strip -g --remove-section=".s[yt][mr]tab" --keep-section=".stab*" -o testfile.elf -f testfile.debug testfile
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 29 section headers, starting at offset 0x2920:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              PROGBITS     080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 000108 000020  0 A      0   0  4
+[ 3] .hash                HASH         08048128 000128 000030  4 A      4   0  4
+[ 4] .dynsym              DYNSYM       08048158 000158 000070 16 A      5   1  4
+[ 5] .dynstr              STRTAB       080481c8 0001c8 00008e  0 A      0   0  1
+[ 6] .gnu.version         GNU_versym   08048256 000256 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       GNU_verneed  08048264 000264 000030  0 A      5   1  4
+[ 8] .rel.got             REL          08048294 000294 000008  8 A      4  19  4
+[ 9] .rel.plt             REL          0804829c 00029c 000020  8 A      4  11  4
+[10] .init                PROGBITS     080482bc 0002bc 000018  0 AX     0   0  4
+[11] .plt                 PROGBITS     080482d4 0002d4 000050  4 AX     0   0  4
+[12] .text                PROGBITS     08048330 000330 00018c  0 AX     0   0 16
+[13] .fini                PROGBITS     080484bc 0004bc 00001e  0 AX     0   0  4
+[14] .rodata              PROGBITS     080484dc 0004dc 000008  0 A      0   0  4
+[15] .data                PROGBITS     080494e4 0004e4 000010  0 WA     0   0  4
+[16] .eh_frame            PROGBITS     080494f4 0004f4 000004  0 WA     0   0  4
+[17] .ctors               PROGBITS     080494f8 0004f8 000008  0 WA     0   0  4
+[18] .dtors               PROGBITS     08049500 000500 000008  0 WA     0   0  4
+[19] .got                 PROGBITS     08049508 000508 000020  4 WA     0   0  4
+[20] .dynamic             DYNAMIC      08049528 000528 0000a0  8 WA     5   0  4
+[21] .sbss                PROGBITS     080495c8 0005c8 000000  0 W      0   0  1
+[22] .bss                 NOBITS       080495c8 0005c8 00001c  0 WA     0   0  4
+[23] .stab                PROGBITS     00000000 0005c8 000720 12       24   0  4
+[24] .stabstr             STRTAB       00000000 000ce8 001934  0        0   0  1
+[25] .comment             PROGBITS     00000000 00261c 000170  0        0   0  1
+[26] .note                NOTE         00000000 00278c 0000a0  0        0   0  1
+[27] .gnu_debuglink       PROGBITS     00000000 00282c 000014  0        0   0  4
+[28] .shstrtab            STRTAB       00000000 002840 0000de  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 35 section headers, starting at offset 0x25e8:
+
+Section Headers:
+[Nr] Name                 Type         Addr     Off    Size   ES Flags Lk Inf Al
+[ 0]                      NULL         00000000 000000 000000  0        0   0  0
+[ 1] .interp              NOBITS       080480f4 0000f4 000013  0 A      0   0  1
+[ 2] .note.ABI-tag        NOTE         08048108 0000f4 000020  0 A      0   0  4
+[ 3] .hash                NOBITS       08048128 000114 000030  4 A      4   0  4
+[ 4] .dynsym              NOBITS       08048158 000114 000070 16 A      5   1  4
+[ 5] .dynstr              NOBITS       080481c8 000114 00008e  0 A      0   0  1
+[ 6] .gnu.version         NOBITS       08048256 000114 00000e  2 A      4   0  2
+[ 7] .gnu.version_r       NOBITS       08048264 000114 000030  0 A      5   1  4
+[ 8] .rel.got             NOBITS       08048294 000114 000008  8 A      4  19  4
+[ 9] .rel.plt             NOBITS       0804829c 000114 000020  8 A      4  11  4
+[10] .init                NOBITS       080482bc 000114 000018  0 AX     0   0  4
+[11] .plt                 NOBITS       080482d4 000114 000050  4 AX     0   0  4
+[12] .text                NOBITS       08048330 000120 00018c  0 AX     0   0 16
+[13] .fini                NOBITS       080484bc 000120 00001e  0 AX     0   0  4
+[14] .rodata              NOBITS       080484dc 000120 000008  0 A      0   0  4
+[15] .data                NOBITS       080494e4 000120 000010  0 WA     0   0  4
+[16] .eh_frame            NOBITS       080494f4 000120 000004  0 WA     0   0  4
+[17] .ctors               NOBITS       080494f8 000120 000008  0 WA     0   0  4
+[18] .dtors               NOBITS       08049500 000120 000008  0 WA     0   0  4
+[19] .got                 NOBITS       08049508 000120 000020  4 WA     0   0  4
+[20] .dynamic             NOBITS       08049528 000120 0000a0  8 WA     5   0  4
+[21] .sbss                NOBITS       080495c8 000120 000000  0 W      0   0  1
+[22] .bss                 NOBITS       080495c8 000120 00001c  0 WA     0   0  4
+[23] .stab                NOBITS       00000000 000120 000720 12       24   0  4
+[24] .stabstr             NOBITS       00000000 000120 001934  0        0   0  1
+[25] .comment             NOBITS       00000000 000120 000170  0        0   0  1
+[26] .debug_aranges       PROGBITS     00000000 000120 000060  0        0   0  1
+[27] .debug_pubnames      PROGBITS     00000000 000180 000055  0        0   0  1
+[28] .debug_info          PROGBITS     00000000 0001d5 001678  0        0   0  1
+[29] .debug_abbrev        PROGBITS     00000000 00184d 0001d2  0        0   0  1
+[30] .debug_line          PROGBITS     00000000 001a1f 000223  0        0   0  1
+[31] .note                NOTE         00000000 001c42 0000a0  0        0   0  1
+[32] .shstrtab            STRTAB       00000000 001ce2 00012e  0        0   0  1
+[33] .symtab              SYMTAB       00000000 001e10 0005a0 16       34  68  4
+[34] .strtab              STRTAB       00000000 0023b0 000235  0        0   0  1
+
+EOF
+
+# Explicitly remove .symtab (but not .strtab, so it will be in both). 64bit
+echo strip -g --remove-section=.symtab testfile69.so
+testrun ${abs_top_builddir}/src/strip -g --remove-section=.symtab -o testfile.elf -f testfile.debug testfile69.so
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 27 section headers, starting at offset 0xad8:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            GNU_HASH     00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              DYNSYM       00000000000001f8 000001f8 00000108 24 A      4   2  8
+[ 4] .dynstr              STRTAB       0000000000000300 00000300 00000077  0 A      0   0  1
+[ 5] .gnu.version         GNU_versym   0000000000000378 00000378 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       GNU_verneed  0000000000000390 00000390 00000020  0 A      4   1  8
+[ 7] .rela.dyn            RELA         00000000000003b0 000003b0 00000060 24 A      3   0  8
+[ 8] .rela.plt            RELA         0000000000000410 00000410 00000018 24 A      3  10  8
+[ 9] .init                PROGBITS     0000000000000428 00000428 00000018  0 AX     0   0  4
+[10] .plt                 PROGBITS     0000000000000440 00000440 00000020 16 AX     0   0 16
+[11] .text                PROGBITS     0000000000000460 00000460 00000128  0 AX     0   0 16
+[12] .fini                PROGBITS     0000000000000588 00000588 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        PROGBITS     0000000000000598 00000598 00000024  0 A      0   0  4
+[14] .eh_frame            PROGBITS     00000000000005c0 000005c0 00000084  0 A      0   0  8
+[15] .ctors               PROGBITS     0000000000200648 00000648 00000010  0 WA     0   0  8
+[16] .dtors               PROGBITS     0000000000200658 00000658 00000010  0 WA     0   0  8
+[17] .jcr                 PROGBITS     0000000000200668 00000668 00000008  0 WA     0   0  8
+[18] .data.rel.ro         PROGBITS     0000000000200670 00000670 00000008  0 WA     0   0  8
+[19] .dynamic             DYNAMIC      0000000000200678 00000678 00000180 16 WA     4   0  8
+[20] .got                 PROGBITS     00000000002007f8 000007f8 00000018  8 WA     0   0  8
+[21] .got.plt             PROGBITS     0000000000200810 00000810 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 00000830 00000010  0 WA     0   0  8
+[23] .comment             PROGBITS     0000000000000000 00000830 0000002c  1 MS     0   0  1
+[24] .strtab              STRTAB       0000000000000000 0000085c 00000175  0        0   0  1
+[25] .gnu_debuglink       PROGBITS     0000000000000000 000009d4 00000014  0        0   0  4
+[26] .shstrtab            STRTAB       0000000000000000 000009e8 000000ee  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 27 section headers, starting at offset 0x918:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            NOBITS       00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              NOBITS       00000000000001f8 000001b8 00000108 24 A      4   2  8
+[ 4] .dynstr              NOBITS       0000000000000300 000001b8 00000077  0 A      0   0  1
+[ 5] .gnu.version         NOBITS       0000000000000378 000001b8 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       NOBITS       0000000000000390 000001b8 00000020  0 A      4   1  8
+[ 7] .rela.dyn            NOBITS       00000000000003b0 000001b8 00000060 24 A      3   0  8
+[ 8] .rela.plt            NOBITS       0000000000000410 000001b8 00000018 24 A      3  10  8
+[ 9] .init                NOBITS       0000000000000428 000001b8 00000018  0 AX     0   0  4
+[10] .plt                 NOBITS       0000000000000440 000001c0 00000020 16 AX     0   0 16
+[11] .text                NOBITS       0000000000000460 000001c0 00000128  0 AX     0   0 16
+[12] .fini                NOBITS       0000000000000588 000001c0 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        NOBITS       0000000000000598 000001c0 00000024  0 A      0   0  4
+[14] .eh_frame            NOBITS       00000000000005c0 000001c0 00000084  0 A      0   0  8
+[15] .ctors               NOBITS       0000000000200648 000001c0 00000010  0 WA     0   0  8
+[16] .dtors               NOBITS       0000000000200658 000001c0 00000010  0 WA     0   0  8
+[17] .jcr                 NOBITS       0000000000200668 000001c0 00000008  0 WA     0   0  8
+[18] .data.rel.ro         NOBITS       0000000000200670 000001c0 00000008  0 WA     0   0  8
+[19] .dynamic             NOBITS       0000000000200678 000001c0 00000180 16 WA     4   0  8
+[20] .got                 NOBITS       00000000002007f8 000001c0 00000018  8 WA     0   0  8
+[21] .got.plt             NOBITS       0000000000200810 000001c0 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 000001c0 00000010  0 WA     0   0  8
+[23] .comment             NOBITS       0000000000000000 000001c0 0000002c  1 MS     0   0  1
+[24] .shstrtab            STRTAB       0000000000000000 000001c0 000000e7  0        0   0  1
+[25] .symtab              SYMTAB       0000000000000000 000002a8 000004f8 24       26  44  8
+[26] .strtab              STRTAB       0000000000000000 000007a0 00000175  0        0   0  1
+
+EOF
+
+# Explicitly remove both .symtab and .strtab. Keep .comment section. 64bit
+echo strip -g --remove-section=".s[yt][mr]tab" --keep-section=.comment testfile69.so
+testrun ${abs_top_builddir}/src/strip -g --remove-section=".s[yt][mr]tab" --keep-section=.comment -o testfile.elf -f testfile.debug testfile69.so
+echo elflint testfile.elf
+testrun ${abs_top_builddir}/src/elflint --gnu testfile.elf
+echo elflint testfile.debug
+testrun ${abs_top_builddir}/src/elflint --gnu -d testfile.debug
+echo readelf testfile.elf
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.elf <<\EOF
+There are 26 section headers, starting at offset 0x958:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            GNU_HASH     00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              DYNSYM       00000000000001f8 000001f8 00000108 24 A      4   2  8
+[ 4] .dynstr              STRTAB       0000000000000300 00000300 00000077  0 A      0   0  1
+[ 5] .gnu.version         GNU_versym   0000000000000378 00000378 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       GNU_verneed  0000000000000390 00000390 00000020  0 A      4   1  8
+[ 7] .rela.dyn            RELA         00000000000003b0 000003b0 00000060 24 A      3   0  8
+[ 8] .rela.plt            RELA         0000000000000410 00000410 00000018 24 A      3  10  8
+[ 9] .init                PROGBITS     0000000000000428 00000428 00000018  0 AX     0   0  4
+[10] .plt                 PROGBITS     0000000000000440 00000440 00000020 16 AX     0   0 16
+[11] .text                PROGBITS     0000000000000460 00000460 00000128  0 AX     0   0 16
+[12] .fini                PROGBITS     0000000000000588 00000588 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        PROGBITS     0000000000000598 00000598 00000024  0 A      0   0  4
+[14] .eh_frame            PROGBITS     00000000000005c0 000005c0 00000084  0 A      0   0  8
+[15] .ctors               PROGBITS     0000000000200648 00000648 00000010  0 WA     0   0  8
+[16] .dtors               PROGBITS     0000000000200658 00000658 00000010  0 WA     0   0  8
+[17] .jcr                 PROGBITS     0000000000200668 00000668 00000008  0 WA     0   0  8
+[18] .data.rel.ro         PROGBITS     0000000000200670 00000670 00000008  0 WA     0   0  8
+[19] .dynamic             DYNAMIC      0000000000200678 00000678 00000180 16 WA     4   0  8
+[20] .got                 PROGBITS     00000000002007f8 000007f8 00000018  8 WA     0   0  8
+[21] .got.plt             PROGBITS     0000000000200810 00000810 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 00000830 00000010  0 WA     0   0  8
+[23] .comment             PROGBITS     0000000000000000 00000830 0000002c  1 MS     0   0  1
+[24] .gnu_debuglink       PROGBITS     0000000000000000 0000085c 00000014  0        0   0  4
+[25] .shstrtab            STRTAB       0000000000000000 00000870 000000e6  0        0   0  1
+
+EOF
+echo readelf testfile.debug
+testrun_compare ${abs_top_builddir}/src/readelf -S testfile.debug <<\EOF
+There are 27 section headers, starting at offset 0x918:
+
+Section Headers:
+[Nr] Name                 Type         Addr             Off      Size     ES Flags Lk Inf Al
+[ 0]                      NULL         0000000000000000 00000000 00000000  0        0   0  0
+[ 1] .note.gnu.build-id   NOTE         0000000000000190 00000190 00000024  0 A      0   0  4
+[ 2] .gnu.hash            NOBITS       00000000000001b8 000001b8 0000003c  0 A      3   0  8
+[ 3] .dynsym              NOBITS       00000000000001f8 000001b8 00000108 24 A      4   2  8
+[ 4] .dynstr              NOBITS       0000000000000300 000001b8 00000077  0 A      0   0  1
+[ 5] .gnu.version         NOBITS       0000000000000378 000001b8 00000016  2 A      3   0  2
+[ 6] .gnu.version_r       NOBITS       0000000000000390 000001b8 00000020  0 A      4   1  8
+[ 7] .rela.dyn            NOBITS       00000000000003b0 000001b8 00000060 24 A      3   0  8
+[ 8] .rela.plt            NOBITS       0000000000000410 000001b8 00000018 24 A      3  10  8
+[ 9] .init                NOBITS       0000000000000428 000001b8 00000018  0 AX     0   0  4
+[10] .plt                 NOBITS       0000000000000440 000001c0 00000020 16 AX     0   0 16
+[11] .text                NOBITS       0000000000000460 000001c0 00000128  0 AX     0   0 16
+[12] .fini                NOBITS       0000000000000588 000001c0 0000000e  0 AX     0   0  4
+[13] .eh_frame_hdr        NOBITS       0000000000000598 000001c0 00000024  0 A      0   0  4
+[14] .eh_frame            NOBITS       00000000000005c0 000001c0 00000084  0 A      0   0  8
+[15] .ctors               NOBITS       0000000000200648 000001c0 00000010  0 WA     0   0  8
+[16] .dtors               NOBITS       0000000000200658 000001c0 00000010  0 WA     0   0  8
+[17] .jcr                 NOBITS       0000000000200668 000001c0 00000008  0 WA     0   0  8
+[18] .data.rel.ro         NOBITS       0000000000200670 000001c0 00000008  0 WA     0   0  8
+[19] .dynamic             NOBITS       0000000000200678 000001c0 00000180 16 WA     4   0  8
+[20] .got                 NOBITS       00000000002007f8 000001c0 00000018  8 WA     0   0  8
+[21] .got.plt             NOBITS       0000000000200810 000001c0 00000020  8 WA     0   0  8
+[22] .bss                 NOBITS       0000000000200830 000001c0 00000010  0 WA     0   0  8
+[23] .comment             NOBITS       0000000000000000 000001c0 0000002c  1 MS     0   0  1
+[24] .shstrtab            STRTAB       0000000000000000 000001c0 000000e7  0        0   0  1
+[25] .symtab              SYMTAB       0000000000000000 000002a8 000004f8 24       26  44  8
+[26] .strtab              STRTAB       0000000000000000 000007a0 00000175  0        0   0  1
+
+EOF
+
+exit 0
diff --git a/tests/run-strip-strmerge.sh b/tests/run-strip-strmerge.sh
new file mode 100755
index 0000000..aa9c1eb
--- /dev/null
+++ b/tests/run-strip-strmerge.sh
@@ -0,0 +1,79 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Generate a file with merged .shstrtab/.strtab table.
+# strip and unstrip it. Check all files with elflint.
+
+# A random ET_EXEC file
+input=${abs_top_builddir}/tests/elfstrmerge
+merged=merged.elf
+stripped=${merged}.stripped
+debugfile=${merged}.debug
+remerged=remerged.elf
+
+tempfiles $merged $stripped $debugfile $remerged
+
+echo elflint $input
+testrun ${abs_top_builddir}/src/elflint --gnu $input
+echo elfstrmerge
+testrun ${abs_top_builddir}/tests/elfstrmerge -o $merged $input
+echo elflint $merged
+testrun ${abs_top_builddir}/src/elflint --gnu $merged
+echo strip
+testrun ${abs_top_builddir}/src/strip -o $stripped -f $debugfile $merged
+echo elflint $stripped
+testrun ${abs_top_builddir}/src/elflint --gnu $stripped
+echo elflint $debugfile
+testrun ${abs_top_builddir}/src/elflint --gnu -d $debugfile
+echo unstrip
+testrun ${abs_top_builddir}/src/unstrip -o $remerged $stripped $debugfile
+echo elflint $remerged
+testrun ${abs_top_builddir}/src/elflint --gnu $remerged
+echo elfcmp
+testrun ${abs_top_builddir}/src/elfcmp $merged $remerged
+
+# A random ET_REL file
+input=${abs_top_builddir}/tests/elfstrmerge.o
+merged=merged.elf
+stripped=${merged}.stripped
+debugfile=${merged}.debug
+remerged=remerged.elf
+
+tempfiles $merged $stripped $debugfile $remerged
+
+echo elflint $input
+testrun ${abs_top_builddir}/src/elflint --gnu $input
+echo elfstrmerge
+testrun ${abs_top_builddir}/tests/elfstrmerge -o $merged $input
+echo elflint $merged
+testrun ${abs_top_builddir}/src/elflint --gnu $merged
+echo strip
+testrun ${abs_top_builddir}/src/strip -o $stripped -f $debugfile $merged
+echo elflint $stripped
+testrun ${abs_top_builddir}/src/elflint --gnu $stripped
+echo elflint $debugfile
+testrun ${abs_top_builddir}/src/elflint --gnu -d $debugfile
+echo unstrip
+testrun ${abs_top_builddir}/src/unstrip -o $remerged $stripped $debugfile
+echo elflint $remerged
+testrun ${abs_top_builddir}/src/elflint --gnu $remerged
+echo elfcmp
+testrun ${abs_top_builddir}/src/elfcmp $merged $remerged
+
+exit 0
diff --git a/tests/run-strip-test-many.sh b/tests/run-strip-test-many.sh
new file mode 100755
index 0000000..b0cbad8
--- /dev/null
+++ b/tests/run-strip-test-many.sh
@@ -0,0 +1,83 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+status=0
+
+# Use the original file from run-strip-test.sh but with many sections
+testfiles testfile
+tempfiles testfile1.strip testfile2.strip testfile1.debug testfile2.debug testfile.unstrip
+
+echo "Adding sections to testfile"
+testrun ${abs_builddir}/addsections 65535 testfile ||
+{ echo "*** failure addsections testfile"; status=1; }
+
+echo "Testing strip -o"
+testrun ${abs_top_builddir}/src/strip -o testfile1.strip -f testfile1.debug testfile ||
+{ echo "*** failure strip -o"; status=1; }
+
+# Do the parts check out?
+echo "elflint testfile1.strip"
+testrun ${abs_top_builddir}/src/elflint --gnu -q testfile1.strip ||
+{ echo "*** failure elflint testfile1.strip"; status=1; }
+
+echo "elflint testfile1.debug"
+testrun ${abs_top_builddir}/src/elflint --gnu -q -d testfile1.debug ||
+{ echo "*** failure elflint testfile1.debug"; status=1; }
+
+# Now test unstrip recombining those files.
+echo "unstrip"
+testrun ${abs_top_builddir}/src/unstrip -o testfile.unstrip testfile1.strip testfile1.debug ||
+{ echo "*** failure unstrip"; status=1; }
+
+echo "elfcmp"
+testrun ${abs_top_builddir}/src/elfcmp testfile testfile.unstrip ||
+{ echo "*** failure elfcmp"; status=1; }
+
+# test strip -g
+echo "Testing strip -g"
+testrun ${abs_top_builddir}/src/strip -g -o testfile2.strip -f testfile2.debug testfile ||
+{ echo "*** failure strip -g"; status=1; }
+
+# Do the parts check out?
+echo "elflint testfile2.strip"
+testrun ${abs_top_builddir}/src/elflint --gnu -q testfile2.strip ||
+{ echo "*** failure elflint testfile2.strip"; status=1; }
+
+echo "elflint testfile2.debug"
+testrun ${abs_top_builddir}/src/elflint --gnu -q -d testfile2.debug ||
+{ echo "*** failure elflint testfile2.debug"; status=1; }
+
+# Now strip "in-place" and make sure it is smaller.
+echo "Testing strip in-place"
+SIZE_original=$(stat -c%s testfile)
+echo "original size $SIZE_original"
+
+testrun ${abs_top_builddir}/src/strip testfile ||
+{ echo "*** failure strip in-place"; status=1; }
+
+SIZE_stripped=$(stat -c%s testfile)
+echo "stripped size $SIZE_stripped"
+test $SIZE_stripped -lt $SIZE_original ||
+  { echo "*** failure in-place strip file not smaller $original"; exit 1; }
+
+echo "elflint in-place"
+testrun ${abs_top_builddir}/src/elflint --gnu -q testfile ||
+{ echo "*** failure elflint in-place"; status=1; }
+
+exit $status
diff --git a/tests/run-strip-test.sh b/tests/run-strip-test.sh
new file mode 100755
index 0000000..317c225
--- /dev/null
+++ b/tests/run-strip-test.sh
@@ -0,0 +1,71 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2003, 2005, 2007, 2008 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+original=${original:-testfile11}
+stripped=${stripped:-testfile7}
+debugout=${debugfile:+-f testfile.debug.temp -F $debugfile}
+
+testfiles $original
+test x$stripped = xtestfile.temp || testfiles $stripped $debugfile
+
+tempfiles testfile.temp testfile.debug.temp testfile.unstrip
+
+testrun ${abs_top_builddir}/src/strip -o testfile.temp $debugout $original
+
+status=0
+
+cmp $stripped testfile.temp || status=$?
+
+# Check elflint and the expected result.
+testrun ${abs_top_builddir}/src/elflint --gnu -q testfile.temp || status=$?
+
+test -z "$debugfile" || {
+cmp $debugfile testfile.debug.temp || status=$?
+
+# Check elflint and the expected result.
+testrun ${abs_top_builddir}/src/elflint --gnu -q -d testfile.debug.temp || status=$?
+
+# Now test unstrip recombining those files.
+testrun ${abs_top_builddir}/src/unstrip -o testfile.unstrip testfile.temp testfile.debug.temp
+
+# Check that it came back whole.
+testrun ${abs_top_builddir}/src/elfcmp --hash-inexact $original testfile.unstrip
+}
+
+# test strip -g
+testrun ${abs_top_builddir}/src/strip -g -o testfile.temp $original
+
+# Buggy eu-strip created multiple .shstrtab sections
+shstrtab_SECS=$(testrun ${abs_top_builddir}/src/readelf -S testfile.temp | grep '.shstrtab' | wc --lines)
+test $shstrtab_SECS -eq 1 ||
+  { echo "*** failure not just one '.shstrtab' testfile.temp ($shstrtab_SECS)"; status=1; }
+
+# Now strip in-place and make sure it is smaller.
+SIZE_original=$(stat -c%s $original)
+testrun ${abs_top_builddir}/src/strip $original
+SIZE_stripped=$(stat -c%s $original)
+test $SIZE_stripped -lt $SIZE_original ||
+  { echo "*** failure in-place strip file not smaller $original"; status=1; }
+
+tempfiles testfile.sections
+testrun ${abs_top_builddir}/src/readelf -S testfile.temp > testfile.sections || status=$?
+grep -F ' .debug_' testfile.sections && status=1
+
+exit $status
diff --git a/tests/run-strip-test10.sh b/tests/run-strip-test10.sh
new file mode 100755
index 0000000..a867b1b
--- /dev/null
+++ b/tests/run-strip-test10.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+original=testfile-x32
+stripped=testfile-x32-d
+debugfile=testfile-x32-debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test11.sh b/tests/run-strip-test11.sh
new file mode 100755
index 0000000..0b1b0ab
--- /dev/null
+++ b/tests/run-strip-test11.sh
@@ -0,0 +1,4 @@
+original=testfile-m68k
+stripped=testfile-m68k-s
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test12.sh b/tests/run-strip-test12.sh
new file mode 100755
index 0000000..cb12098
--- /dev/null
+++ b/tests/run-strip-test12.sh
@@ -0,0 +1,4 @@
+original=testfile-riscv64
+stripped=testfile-riscv64-s
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test2.sh b/tests/run-strip-test2.sh
new file mode 100755
index 0000000..9217196
--- /dev/null
+++ b/tests/run-strip-test2.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+original=testfile8
+stripped=testfile9
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test3.sh b/tests/run-strip-test3.sh
new file mode 100755
index 0000000..fb37a76
--- /dev/null
+++ b/tests/run-strip-test3.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) 1999, 2000, 2002, 2003, 2005 Red Hat, Inc.
+# This file is part of elfutils.
+# Written by Ulrich Drepper <drepper@redhat.com>, 1999.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+original=testfile12
+stripped=testfile13
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test4.sh b/tests/run-strip-test4.sh
new file mode 100755
index 0000000..64924a9
--- /dev/null
+++ b/tests/run-strip-test4.sh
@@ -0,0 +1,5 @@
+original=testfile11
+stripped=testfile37
+debugfile=testfile37.debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test5.sh b/tests/run-strip-test5.sh
new file mode 100755
index 0000000..9fa9ebe
--- /dev/null
+++ b/tests/run-strip-test5.sh
@@ -0,0 +1,5 @@
+original=testfile8
+stripped=testfile16
+debugfile=testfile16.debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test6.sh b/tests/run-strip-test6.sh
new file mode 100755
index 0000000..c59bf5e
--- /dev/null
+++ b/tests/run-strip-test6.sh
@@ -0,0 +1,5 @@
+original=testfile12
+stripped=testfile35
+debugfile=testfile35.debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test7.sh b/tests/run-strip-test7.sh
new file mode 100755
index 0000000..c65cd05
--- /dev/null
+++ b/tests/run-strip-test7.sh
@@ -0,0 +1,5 @@
+original=testfile39
+stripped=testfile40
+debugfile=testfile40.debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test8.sh b/tests/run-strip-test8.sh
new file mode 100755
index 0000000..fb9fa08
--- /dev/null
+++ b/tests/run-strip-test8.sh
@@ -0,0 +1,5 @@
+original=testfile47
+stripped=testfile48
+debugfile=testfile48.debug
+
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-test9.sh b/tests/run-strip-test9.sh
new file mode 100755
index 0000000..0c6fae2
--- /dev/null
+++ b/tests/run-strip-test9.sh
@@ -0,0 +1,21 @@
+#! /bin/sh
+# Copyright (C) H.J. Lu <hjl.tools@gmail.com>, 2015.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+original=testfile-x32
+stripped=testfile-x32-s
+. $srcdir/run-strip-test.sh
diff --git a/tests/run-strip-version.sh b/tests/run-strip-version.sh
new file mode 100755
index 0000000..191e0aa
--- /dev/null
+++ b/tests/run-strip-version.sh
@@ -0,0 +1,58 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Generated on s390x with an older gas (2.29.1) that generates
+# badly aligned version notes.
+#
+# = testfile-version.s =
+#
+#	.section ".extra"
+#	.byte 42
+#
+#	.version "Sliding Snow"
+#	.version "Hurr durr 3.1"
+#
+#        .globl  _start
+#_start:
+#
+# gcc -nostartfiles -nodefaultlibs -o testfile-version testfile-version.s
+
+testfiles testfile-version
+tempfiles debug.out elf.out
+
+testrun ${abs_top_builddir}/src/strip -o elf.out -f debug.out \
+	testfile-version
+
+testrun ${abs_top_builddir}/src/elflint --gnu elf.out
+testrun ${abs_top_builddir}/src/elflint --gnu --debug debug.out
+
+testrun_compare ${abs_top_builddir}/src/readelf -n debug.out <<\EOF
+
+Note section [ 1] '.note.gnu.build-id' of 36 bytes at offset 0xb0:
+  Owner          Data size  Type
+  GNU                   20  GNU_BUILD_ID
+    Build ID: d3c84c0b307c06f50a37c6c0f59c82c4cb10720b
+
+Note section [ 3] '.note' of 56 bytes at offset 0xd5:
+  Owner          Data size  Type
+  Sliding Snow           0  VERSION
+  Hurr durr 3.1          0  VERSION
+EOF
+
+exit 0
diff --git a/tests/run-strptr.sh b/tests/run-strptr.sh
new file mode 100755
index 0000000..af90a02
--- /dev/null
+++ b/tests/run-strptr.sh
@@ -0,0 +1,98 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# A random 32bit and 64bit testfile
+testfiles testfile testfile10
+
+testrun_compare ${abs_top_builddir}/tests/strptr testfile <<\EOF
+Strings in section 32:
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.interp'
+[23] '.note.ABI-tag'
+[31] '.hash'
+[37] '.dynsym'
+[3f] '.dynstr'
+[47] '.gnu.version'
+[54] '.gnu.version_r'
+[63] '.rel.got'
+[6c] '.rel.plt'
+[75] '.init'
+[7b] '.plt'
+[80] '.text'
+[86] '.fini'
+[8c] '.rodata'
+[94] '.data'
+[9a] '.eh_frame'
+[a4] '.ctors'
+[ab] '.dtors'
+[b2] '.got'
+[b7] '.dynamic'
+[c0] '.sbss'
+[c6] '.bss'
+[cb] '.stab'
+[d1] '.stabstr'
+[da] '.comment'
+[e3] '.debug_aranges'
+[f2] '.debug_pubnames'
+[102] '.debug_info'
+[10e] '.debug_abbrev'
+[11c] '.debug_line'
+[128] '.note'
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/strptr testfile10 <<\EOF
+Strings in section 30:
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.hash'
+[21] '.dynsym'
+[29] '.dynstr'
+[31] '.gnu.version'
+[3e] '.gnu.version_r'
+[4d] '.rela.dyn'
+[57] '.init'
+[5d] '.text'
+[63] '.fini'
+[69] '.eh_frame'
+[73] '.data'
+[79] '.dynamic'
+[82] '.ctors'
+[89] '.dtors'
+[90] '.jcr'
+[95] '.plt'
+[9a] '.got'
+[9f] '.sdata'
+[a6] '.sbss'
+[ac] '.bss'
+[b1] '.comment'
+[ba] '.debug_aranges'
+[c9] '.debug_pubnames'
+[d9] '.debug_abbrev'
+[e7] '.debug_line'
+[f3] '.debug_frame'
+[100] '.debug_str'
+[10b] '.rela.debug_info'
+EOF
+
+exit 0
diff --git a/tests/run-test-archive64.sh b/tests/run-test-archive64.sh
new file mode 100755
index 0000000..2d8c21d
--- /dev/null
+++ b/tests/run-test-archive64.sh
@@ -0,0 +1,55 @@
+#! /bin/sh
+# Copyright (C) 2012, 2014 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# The test archive was produced on an s390x machine using the
+# following command sequence:
+#  echo 'int aaa(void){}' | gcc -x c /dev/stdin -c -o aaa.o
+#  echo 'int bbb(void){} int bbb2(void){}' | gcc -x c /dev/stdin -c -o bbb.o
+#  echo 'int ccc(void){} int ccc2(void){} int ccc3(void){}' \
+#    | gcc -x c /dev/stdin -c -o ccc.o
+#  ar cru testarchive64.a aaa.o bbb.o ccc.o
+testfiles testarchive64.a
+
+testrun_compare ${abs_top_builddir}/src/readelf -c testarchive64.a <<\EOF
+
+Index of archive 'testarchive64.a' has 7 entries:
+Archive member 'aaa.o' contains:
+	aaa
+Archive member 'bbb.o' contains:
+	bbb
+	bbb2
+Archive member 'ccc.o' contains:
+	ccc
+	ccc2
+	ccc3
+EOF
+
+testrun_compare ${abs_top_builddir}/src/nm -P -g testarchive64.a <<\EOF
+testarchive64.a[aaa.o]:
+aaa T 0000000000000000 0000000000000016
+testarchive64.a[bbb.o]:
+bbb T 0000000000000000 0000000000000016
+bbb2 T 0000000000000018 0000000000000016
+testarchive64.a[ccc.o]:
+ccc T 0000000000000000 0000000000000016
+ccc2 T 0000000000000018 0000000000000016
+ccc3 T 0000000000000030 0000000000000016
+EOF
+
+exit 0
diff --git a/tests/run-test-flag-nobits.sh b/tests/run-test-flag-nobits.sh
new file mode 100755
index 0000000..9bedf17
--- /dev/null
+++ b/tests/run-test-flag-nobits.sh
@@ -0,0 +1,22 @@
+#! /bin/sh
+# Copyright (C) 2010 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfile
+
+testrun ${abs_builddir}/test-flag-nobits testfile
diff --git a/tests/run-test-includes.sh b/tests/run-test-includes.sh
new file mode 100755
index 0000000..b107c6b
--- /dev/null
+++ b/tests/run-test-includes.sh
@@ -0,0 +1,26 @@
+# All public include headers should be usable "standalone".
+
+. $srcdir/test-subr.sh
+
+echo '#include "libelf.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf -xc -
+echo '#include "gelf.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf -xc -
+
+echo '#include "dwarf.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf \
+        -I ${abs_srcdir}/../libdw -xc -
+echo '#include "libdw.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf \
+        -I ${abs_srcdir}/../libdw -xc -
+
+echo '#include "libdwfl.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf \
+    -I ${abs_srcdir}/../libdw -I ${abs_srcdir}/../libdwfl -xc -
+echo '#include "libdwelf.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf \
+    -I ${abs_srcdir}/../libdw -I ${abs_srcdir}/../libdwelf -xc -
+
+echo '#include "libasm.h"' \
+  | ${CC} -c -o /dev/null -I ${abs_srcdir}/../libelf \
+    -I ${abs_srcdir}/../libasm -xc -
diff --git a/tests/run-typeiter-many.sh b/tests/run-typeiter-many.sh
new file mode 100755
index 0000000..39168f2
--- /dev/null
+++ b/tests/run-typeiter-many.sh
@@ -0,0 +1,31 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+
+# Like run-typeiter.sh but we first add many sections to make sure
+# dwarf_begin actually recognizes the debug section names.
+testfiles testfile-debug-types
+
+testrun ${abs_builddir}/addsections 65535 testfile-debug-types
+testrun_compare ${abs_builddir}/typeiter2 testfile-debug-types <<\EOF
+ok A [68]
+ok B [38]
+EOF
+
+exit 0
diff --git a/tests/run-typeiter.sh b/tests/run-typeiter.sh
new file mode 100755
index 0000000..2687bab
--- /dev/null
+++ b/tests/run-typeiter.sh
@@ -0,0 +1,62 @@
+#! /bin/sh
+# Copyright (C) 2012, 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# struct s1
+# {
+#   char c;
+#   short s;
+#   int i;
+#   long l;
+#   float f;
+#   double d;
+# };
+# 
+# s1 S1;
+# 
+# int func (s1 *p)
+# {
+#   return p->i;
+# }
+# 
+# int main()
+# {
+#   return func (&S1);
+# }
+#
+# g++ -gdwarf-4 -g -fdebug-types-section
+
+# echo 'struct A{ struct B {} x;};A a; A::B b;int main(){return 0;}' \
+#  | g++ -x c++  -g -fdebug-types-section -o testfile-debug-types -
+
+testfiles testfile59 testfile-debug-types
+
+testrun_compare ${abs_builddir}/typeiter testfile59 <<\EOF
+ok
+EOF
+
+testrun_compare ${abs_builddir}/typeiter2 testfile59 <<\EOF
+ok s1 [25]
+EOF
+
+testrun_compare ${abs_builddir}/typeiter2 testfile-debug-types <<\EOF
+ok A [68]
+ok B [38]
+EOF
+
+exit 0
diff --git a/tests/run-unit-info.sh b/tests/run-unit-info.sh
new file mode 100755
index 0000000..328fe78
--- /dev/null
+++ b/tests/run-unit-info.sh
@@ -0,0 +1,81 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See run-typeiter.sh
+testfiles testfile-debug-types
+
+testrun ${abs_builddir}/unit-info testfile-debug-types
+
+# see run-readelf-dwz-multi.sh
+testfiles testfile_multi_main testfile_multi.dwz
+
+testrun ${abs_builddir}/unit-info testfile_multi_main
+
+# see tests/run-dwflsyms.sh
+testfiles testfilebazdbgppc64.debug
+
+testrun ${abs_builddir}/unit-info testfilebazdbgppc64.debug
+
+# see tests/testfile-dwarf-45.source
+testfiles testfile-dwarf-4 testfile-dwarf-5
+testfiles testfile-splitdwarf-4 testfile-splitdwarf-5
+testfiles testfile-hello4.dwo testfile-hello5.dwo
+testfiles testfile-world4.dwo testfile-world5.dwo
+
+testrun ${abs_builddir}/unit-info testfile-dwarf-4
+testrun ${abs_builddir}/unit-info testfile-dwarf-5
+
+# The consistency checks should find most issue, but make sure the
+# output is also what we expect in case we break dwarf_get_units and
+# dwarf_cu_info at the same time.
+testrun_compare ${abs_builddir}/unit-info \
+		testfile-splitdwarf-4 testfile-splitdwarf-5 <<\EOF
+file: testfile-splitdwarf-4
+Iterate getting all info, compare with dwarf_cu_info.
+0 cu dietag: 11, subtag: 11, version 4, unit_type 4
+0 subdietag: 11, subtag: 0, version 4, unit_type 5
+1 cu dietag: 11, subtag: 11, version 4, unit_type 4
+1 subdietag: 11, subtag: 0, version 4, unit_type 5
+rechecking: testfile-splitdwarf-4
+Iterate no info, compare recorded info with dwarf_cu_info.
+0 re dietag: 11, subtag: 11, version 4, unit_type 4
+0 subdietag: 11, subtag: 0, version 4, unit_type 5
+1 re dietag: 11, subtag: 11, version 4, unit_type 4
+1 subdietag: 11, subtag: 0, version 4, unit_type 5
+
+file: testfile-splitdwarf-5
+Iterate getting all info, compare with dwarf_cu_info.
+0 cu dietag: 4a, subtag: 11, version 5, unit_type 4
+0 subdietag: 11, subtag: 0, version 5, unit_type 5
+1 cu dietag: 4a, subtag: 11, version 5, unit_type 4
+1 subdietag: 11, subtag: 0, version 5, unit_type 5
+rechecking: testfile-splitdwarf-5
+Iterate no info, compare recorded info with dwarf_cu_info.
+0 re dietag: 4a, subtag: 11, version 5, unit_type 4
+0 subdietag: 11, subtag: 0, version 5, unit_type 5
+1 re dietag: 4a, subtag: 11, version 5, unit_type 4
+1 subdietag: 11, subtag: 0, version 5, unit_type 5
+
+EOF
+
+# Self test (not on obj files, since those need relocation first).
+testrun_on_self_exe ${abs_builddir}/unit-info
+testrun_on_self_lib ${abs_builddir}/unit-info
+
+exit 0
diff --git a/tests/run-unstrip-M.sh b/tests/run-unstrip-M.sh
new file mode 100755
index 0000000..614a8aa
--- /dev/null
+++ b/tests/run-unstrip-M.sh
@@ -0,0 +1,51 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Linux /proc/PID/maps file with some non-file entries (and fake exe/lib names).
+tempfiles testmaps
+cat > testmaps <<EOF
+00400000-024aa000 r-xp 00000000 08:02 159659                             /opt/TestBins/bin/arwijn
+026aa000-026b2000 rwxp 020aa000 08:02 159659                             /opt/TestBins/bin/arwijn
+026b2000-026bf000 rwxp 00000000 00:00 0
+0335a000-03e6f000 rwxp 00000000 00:00 0                                  [heap]
+2b7b38282000-2b7b38302000 rwxs 00000000 00:06 493872                     socket:[493872]
+2b7b38302000-2b7b38312000 rwxs 00000000 00:06 493872                     socket:[493872]
+2b7b38312000-2b7b38b12000 r-xs 00000000 00:06 493872                     socket:[493872]
+2b7b38b12000-2b7b38b22000 rwxs 00000000 00:06 493872                     socket:[493872]
+2b7b38b22000-2b7b39322000 rwxs 00000000 00:06 493872                     socket:[493872]
+2b7b4439f000-2b7b45ea1000 rwxp 00000000 00:00 0
+7f31e7d9f000-7f31e7f29000 r-xp 00000000 fd:00 917531                     /lib64/libc-1.13.so
+7f31e7f29000-7f31e8128000 ---p 0018a000 fd:00 917531                     /lib64/libc-1.13.so
+7f31e8128000-7f31e812c000 r--p 00189000 fd:00 917531                     /lib64/libc-1.13.so
+7f31e812c000-7f31e812d000 rw-p 0018d000 fd:00 917531                     /lib64/libc-1.13.so
+7f31e812d000-7f31e8132000 rw-p 00000000 00:00 0 
+7f31ea3f9000-7f31ea3fc000 rw-s 00000000 00:09 3744                       anon_inode:kvm-vcpu
+7f31ea3fc000-7f31ea3ff000 rw-s 00000000 00:09 3744                       anon_inode:kvm-vcpu
+7f31ea400000-7f31ea402000 rw-p 00000000 00:00 0 
+7fff26cf7000-7fff26d0c000 rwxp 00000000 00:00 0                          [stack]
+7fff26dff000-7fff26e00000 r-xp 00000000 00:00 0                          [vdso]
+ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
+EOF
+
+testrun_compare ${abs_top_builddir}/src/unstrip -n -M testmaps <<\EOF
+0x400000+0x22b2000 - - - /opt/TestBins/bin/arwijn
+0x7f31e7d9f000+0x38e000 - - - /lib64/libc-1.13.so
+EOF
+
+exit 0
diff --git a/tests/run-unstrip-n.sh b/tests/run-unstrip-n.sh
new file mode 100755
index 0000000..37cbd60
--- /dev/null
+++ b/tests/run-unstrip-n.sh
@@ -0,0 +1,76 @@
+#! /bin/sh
+# Copyright (C) 2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# https://bugzilla.redhat.com/show_bug.cgi?id=805447
+# eu-unstrip emits garbage for librt.so.1
+#
+# #include <stdio.h>
+# #include <sys/mman.h>
+# 
+# int main(int argc, char **argv)
+# {
+#  // Yes, this crashes... That is the point.
+#  return shm_open(argv[1], 0, 0);
+# }
+# 
+# gcc -m32 -o rt_crash -lrt rt_crash.c
+
+testfiles testcore-rtlib testcore-rtlib-ppc
+
+testrun_compare ${abs_top_builddir}/src/unstrip -n --core=testcore-rtlib <<\EOF
+0x8048000+0x2000 f1c600bc36cb91bf01f9a63a634ecb79aa4c3199@0x8048178 . - [exe]
+0xf75e9000+0x1a000 29a103420abe341e92072fb14274e250e4072148@0xf75e9164 - - libpthread.so.0
+0xf7603000+0x1b0000 0b9bf374699e141e5dfc14757ff42b8c2373b4de@0xf7603184 - - libc.so.6
+0xf77b3000+0x9000 c6c5b5e35ab9589d4762ac85b4bd56b1b2720e37@0xf77b3164 - - librt.so.1
+0xf77d6000+0x1000 676560b1b765cde9c2e53f134f4ee354ea894747@0xf77d6210 . - linux-gate.so.1
+0xf77d7000+0x21000 6d2cb32650054f1c176d01d48713a4a5e5e84c1a@0xf77d7124 - - ld-linux.so.2
+EOF
+
+testrun_compare ${abs_top_builddir}/src/unstrip -n --core=testcore-rtlib-ppc <<\EOF
+0x100000+0x10000 708b900b05176964512a6b0fe90c2a0c9d73d726@0x100334 . - linux-vdso32.so.1
+0xfd50000+0x30000 3f7d21508470322d2f47acddc20ab10516edba99@0xfd50164 . - librt.so.1
+0xfdb0000+0x40000 f6ee91d4c629bc7dacc10534cb30056914e7e0b5@0xfdb0164 - - libpthread.so.0
+0xfdf0000+0x1c0000 edf3dd232e09d01b90683889bd16b9406c52d4de@0xfdf0184 - - libc.so.6
+0xffb0000+0x50000 edec437a85026a1cf8cda94003706202733130c1@0xffb0124 - - ld.so.1
+0x10000000+0x20000 979b7a26747cc09bd84a42b311b5288c704baea5@0x10000174 . - [exe]
+EOF
+
+# FAIL was 0x7f67f2caf000 for test-core-lib.so .
+# /lib64/libc.so.6 and /lib64/ld-linux-x86-64.so.2 from link map
+# do not have ELF header stored in the core file.
+# ELF headers in the core file:
+# Offset   VirtAddr          
+# 0x014000 0x00007f67f2caf000 ./test-core-lib.so
+# 0x03a000 0x00007fff1596c000 linux-vdso.so.1
+testfiles test-core.core test-core.exec
+rm -f test-core-lib.so
+outfile=test-core.out
+testrun_out $outfile ${abs_top_builddir}/src/unstrip -n -e test-core.exec --core=test-core.core
+outfile2=test-core.out2
+remove_files="$remove_files $outfile2"
+grep -v libc.so.6 $outfile | sort >$outfile2
+diff -u $outfile2 - <<EOF
+0x400000+0x202038 - test-core.exec - test-core.exec
+0x7f67f2aaf000+0x202000 - . - /home/jkratoch/redhat/elfutils-libregr/test-core-lib.so
+0x7fff1596c000+0x1000 a9cf37f53897b5468ee018655760be61b8633d3c@0x7fff1596c340 . - linux-vdso.so.1
+EOF
+
+test_cleanup
+
+exit 0
diff --git a/tests/run-unstrip-test.sh b/tests/run-unstrip-test.sh
new file mode 100755
index 0000000..8b7143a
--- /dev/null
+++ b/tests/run-unstrip-test.sh
@@ -0,0 +1,51 @@
+#! /bin/sh
+# Copyright (C) 2007-2010 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+original=${original:-testfile12}
+stripped=${stripped:-testfile17}
+debugfile=${debugfile:-${stripped}.debug}
+
+testfiles $original $stripped $debugfile
+tempfiles testfile.unstrip testfile.inplace
+
+# These are old reference output from run-test-strip6.sh, when
+# strip left the .debug file with unchanged sh_size in
+# stripped sections that shrank in the stripped file.  strip
+# no longer does that, but unstrip must still handle it.
+
+testrun ${abs_top_builddir}/src/unstrip -o testfile.unstrip $stripped $debugfile
+
+testrun ${abs_top_builddir}/src/elfcmp --hash-inexact $original testfile.unstrip
+
+tempfiles syms-orig syms-testfile
+
+# Check whether relocated symbols changed.
+testrun ${abs_top_builddir}/tests/elf-print-reloc-syms $original > syms-orig
+testrun ${abs_top_builddir}/tests/elf-print-reloc-syms testfile.unstrip > syms-testfile
+
+testrun diff syms-orig syms-testfile
+
+# Also test modifying the file in place.
+
+rm -f testfile.inplace
+cp $debugfile testfile.inplace
+chmod 644 testfile.inplace
+testrun ${abs_top_builddir}/src/unstrip $stripped testfile.inplace
+
+testrun ${abs_top_builddir}/src/elfcmp --hash-inexact $original testfile.inplace
diff --git a/tests/run-unstrip-test2.sh b/tests/run-unstrip-test2.sh
new file mode 100755
index 0000000..44074c1
--- /dev/null
+++ b/tests/run-unstrip-test2.sh
@@ -0,0 +1,5 @@
+original=testfile11
+stripped=testfile15
+debugfile=testfile15.debug
+
+. $srcdir/run-unstrip-test.sh
diff --git a/tests/run-unstrip-test3.sh b/tests/run-unstrip-test3.sh
new file mode 100755
index 0000000..5459e72
--- /dev/null
+++ b/tests/run-unstrip-test3.sh
@@ -0,0 +1,17 @@
+# Buggy binutils objdump might strip SHF_INFO_LINK from relocation sections.
+# With gcc5 we might have a .rela.plt section with that flag set.
+#
+# int main() 
+# {
+#     return 0;
+# }
+#
+# gcc -o testfile-info-link -g testprog.c
+# objcopy --only-keep-debug testfile-info-link testfile-info-link.debuginfo
+# eu-strip --strip-debug -o testfile-info-link.stripped testfile-info-link
+
+original=testfile-info-link
+stripped=testfile-info-link.stripped
+debugfile=testfile-info-link.debuginfo
+
+. $srcdir/run-unstrip-test.sh
diff --git a/tests/run-unstrip-test4.sh b/tests/run-unstrip-test4.sh
new file mode 100755
index 0000000..6ca5d0e
--- /dev/null
+++ b/tests/run-unstrip-test4.sh
@@ -0,0 +1,18 @@
+# Test whether unstrip can combine a stripped kernel object that has
+# limited .symtab/.strtab data, with a separate .debuginfo binary that
+# has full .symtab/.strtab data.
+#
+# This was generated as part of a Chromium OS kernel build:
+#
+#   emerge-kevin chromeos-kernel-4_4
+#
+# Setup instructions:
+#
+#   https://www.chromium.org/chromium-os/developer-guide
+#   https://www.chromium.org/chromium-os/how-tos-and-troubleshooting/kernel-faq
+
+original=testfile-strtab
+stripped=testfile-strtab.stripped
+debugfile=testfile-strtab.debuginfo
+
+. $srcdir/run-unstrip-test.sh
diff --git a/tests/run-varlocs-self.sh b/tests/run-varlocs-self.sh
new file mode 100755
index 0000000..760fe4d
--- /dev/null
+++ b/tests/run-varlocs-self.sh
@@ -0,0 +1,29 @@
+#! /bin/sh
+# Copyright (C) 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if test -n "$ELFUTILS_MEMORY_SANITIZER"; then
+  echo "binaries linked with memory sanitizer are too big"
+  exit 77
+fi
+
+# Make sure varlocs doesn't crash, doesn't trigger self-check/asserts
+# or leaks running under valgrind.
+testrun_on_self_exe ${abs_top_builddir}/tests/varlocs -e
+testrun_on_self_lib ${abs_top_builddir}/tests/varlocs -e
+testrun_on_self_obj ${abs_top_builddir}/tests/varlocs --exprlocs -e
diff --git a/tests/run-varlocs-vars.sh b/tests/run-varlocs-vars.sh
new file mode 100755
index 0000000..e7598bf
--- /dev/null
+++ b/tests/run-varlocs-vars.sh
@@ -0,0 +1,93 @@
+#! /bin/sh
+# Copyright (C) 2013, 2021 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# Testfiles generated with:
+#
+# $ cat foo.c
+# int x = 1;
+# int y = 2;
+#
+# for cc in gcc clang; do
+#   for v in 4 5; do
+#     for w in 32 64; do
+#       out="testfile-vars-$cc-dwarf$v-$w.o"
+#       "$cc" -m"$w" -Wall -Wextra -gdwarf-"$v" -c foo.c -o "$out"
+#     done
+#   done
+# done
+
+testfiles testfile-vars-clang-dwarf4-32.o
+testfiles testfile-vars-clang-dwarf4-64.o
+testfiles testfile-vars-clang-dwarf5-32.o
+testfiles testfile-vars-clang-dwarf5-64.o
+testfiles testfile-vars-gcc-dwarf4-32.o
+testfiles testfile-vars-gcc-dwarf4-64.o
+testfiles testfile-vars-gcc-dwarf5-32.o
+testfiles testfile-vars-gcc-dwarf5-64.o
+
+tempfiles varlocs.out
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-clang-dwarf4-32.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr(0x0)}
+    location (exprloc) {addr(0x4)}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-clang-dwarf4-64.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr(0x0)}
+    location (exprloc) {addr(0x4)}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-clang-dwarf5-32.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr: 0x0}
+    location (exprloc) {addr: 0x4}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-clang-dwarf5-32.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr: 0x0}
+    location (exprloc) {addr: 0x4}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-gcc-dwarf4-32.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr(0x0)}
+    location (exprloc) {addr(0x4)}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-gcc-dwarf4-64.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr(0x0)}
+    location (exprloc) {addr(0x4)}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-gcc-dwarf5-32.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr(0x0)}
+    location (exprloc) {addr(0x4)}
+EOF
+
+testrun ${abs_top_builddir}/tests/varlocs --debug --exprlocs -e testfile-vars-gcc-dwarf5-64.o | grep exprloc > varlocs.out
+diff -u varlocs.out - <<EOF
+    location (exprloc) {addr(0x0)}
+    location (exprloc) {addr(0x4)}
+EOF
+
+exit 0
diff --git a/tests/run-varlocs.sh b/tests/run-varlocs.sh
new file mode 100755
index 0000000..4ac5f36
--- /dev/null
+++ b/tests/run-varlocs.sh
@@ -0,0 +1,716 @@
+#! /bin/sh
+# Copyright (C) 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# See the source files testfile_const_type.c testfile_implicit_value.c
+# testfile_entry_value.c testfile_parameter_ref.c testfile_implicit_pointer.c
+# how to regenerate the test files (needs GCC 4.8+).
+
+testfiles testfile_const_type testfile_implicit_value testfile_entry_value
+testfiles testfile_parameter_ref testfile_implicit_pointer
+
+testrun_compare ${abs_top_builddir}/tests/varlocs -e testfile_const_type <<\EOF
+module 'testfile_const_type'
+[b] CU 'const_type.c'@0
+  [33] function 'f1'@80483f0
+    frame_base: {call_frame_cfa {bregx(4,4)}}
+    [4b] parameter 'd'
+      [80483f0,804841b) {fbreg(0)}
+    [57] variable 'w'
+      [80483f0,804841b) {fbreg(0), GNU_deref_type(8){long long int,signed,64@[25]}, GNU_const_type{long long int,signed,64@[25]}(8)[0000806745230100], div, GNU_convert{long long unsigned int,unsigned,64@[2c]}, stack_value}
+  [7d] function 'main'@80482f0
+    frame_base: {call_frame_cfa {bregx(4,4)}}
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/varlocs -e testfile_implicit_value <<\EOF
+module 'testfile_implicit_value'
+[b] CU 'implicit_value.c'@0
+  [25] function 'foo'@80483f0
+    frame_base: {call_frame_cfa {bregx(4,4)}}
+    [3e] variable 'a'
+      [80483f0,80483f6) {implicit_value(8){0200000000000000}, piece(8), implicit_value(8){1500000000000000}, piece(8)}
+  [86] function 'main'@80482f0
+    frame_base: {call_frame_cfa {bregx(4,4)}}
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/varlocs -e testfile_entry_value <<\EOF
+module 'testfile_entry_value'
+[b] CU 'entry_value.c'@0
+  [29] function 'foo'@400500
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [4a] parameter 'x'
+      [400500,400504) {reg5}
+    [55] parameter 'y'
+      [400500,400504) {reg4}
+  [68] function 'bar'@400510
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [89] parameter 'x'
+      [400510,40051c) {reg5}
+      [40051c,40052b) {reg6}
+      [40052b,400531) {GNU_entry_value(1) {reg5}, stack_value}
+    [96] parameter 'y'
+      [400510,40051c) {reg4}
+      [40051c,40052a) {reg3}
+      [40052a,400531) {GNU_entry_value(1) {reg4}, stack_value}
+    [a3] variable 'z'
+      [400524,400528) {reg0}
+      [400528,400529) {reg12}
+      [400529,40052e) {breg0(0), breg12(0), plus, stack_value}
+      [40052e,400531) {reg0}
+  [e9] function 'main'@400400
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [10a] parameter 'argc'
+      [400400,400406) {reg5}
+      [400406,40040a) {breg5(-1), stack_value}
+      [40040a,40040b) {GNU_entry_value(1) {reg5}, stack_value}
+    [119] parameter 'argv'
+      [400400,400403) {reg4}
+      [400403,40040b) {GNU_entry_value(1) {reg4}, stack_value}
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/varlocs -e testfile_parameter_ref <<\EOF
+module 'testfile_parameter_ref'
+[b] CU 'parameter_ref.c'@0
+  [77] function 'foo'@400510
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [92] parameter 'x'
+      [400510,400523) {reg5}
+    [99] parameter 'y'
+      [400510,400523) {GNU_parameter_ref[42], stack_value}
+    [a5] variable 'a'
+      [400510,400523) {breg5(0), lit1, shl, stack_value}
+    [b0] variable 'b'
+      [400510,400523) {GNU_parameter_ref[42], lit1, shl, stack_value}
+    [be] variable 'c'
+      <constant value>
+    [c4] parameter 'z'
+      <constant value>
+  [cb] function 'main'@400400
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [ec] parameter 'x'
+      [400400,400408) {reg5}
+      [400408,400421) {reg3}
+      [400421,400423) {GNU_entry_value(1) {reg5}, stack_value}
+    [f9] parameter 'argv'
+      [400400,400408) {reg4}
+      [400408,400423) {GNU_entry_value(1) {reg4}, stack_value}
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/varlocs -e testfile_implicit_pointer <<\EOF
+module 'testfile_implicit_pointer'
+[b] CU 'implicit_pointer.c'@0
+  [29] function 'foo'@400500
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [4a] parameter 'i'
+      [400500,400503) {reg5}
+    [55] variable 'p'
+      [400500,400503) {GNU_implicit_pointer([4a],0) {reg5}}
+  [73] function 'main'@400400
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+EOF
+
+# Multi CU DWARF5. See run-dwarf-ranges.sh.
+testfiles testfileranges5.debug
+testrun_compare ${abs_top_builddir}/tests/varlocs --debug -e testfileranges5.debug <<\EOF
+module 'testfileranges5.debug'
+[c] CU 'hello.c'@0
+  [2a] function 'no_say'@401160
+    frame_base: {call_frame_cfa {...}}
+    [4a] parameter 'prefix'
+      [401160,401169) {reg5}
+      [401169,40116a) {entry_value(1) {reg5}, stack_value}
+      [40116a,401175) {reg5}
+      [401175,40117a) {entry_value(1) {reg5}, stack_value}
+    [59] variable 'world'
+      [401160,40117a) {addr(0x402004), stack_value}
+  [bd] function 'main'@401050
+    frame_base: {call_frame_cfa {...}}
+    [dd] parameter 'argc'
+      [401050,401062) {reg5}
+      [401062,401067) {entry_value(1) {reg5}, stack_value}
+    [ec] parameter 'argv'
+      [401050,401066) {reg4}
+      [401066,401067) {entry_value(1) {reg4}, stack_value}
+  [fb] inlined function 'subject'@401053
+    [117] parameter 'count'
+      [401053,40105f) {reg5}
+    [120] parameter 'word'
+      [401053,40105f) {reg0}
+  [168] function 'subject'@401150
+    frame_base: {call_frame_cfa {...}}
+    [183] parameter 'word'
+      [401150,401160) {reg5}
+    [18a] parameter 'count'
+      [401150,401160) {reg4}
+module 'testfileranges5.debug'
+[1ab] CU 'world.c'@401180
+  [1cd] function 'no_main'@4011d0
+    frame_base: {call_frame_cfa {...}}
+    [1ef] parameter 'argc'
+      [4011d0,4011e2) {reg5}
+      [4011e2,4011e7) {entry_value(1) {reg5}, stack_value}
+    [1fe] parameter 'argv'
+      [4011d0,4011e6) {reg4}
+      [4011e6,4011e7) {entry_value(1) {reg4}, stack_value}
+  [20d] inlined function 'no_subject'@4011d3
+    [229] parameter 'count'
+      [4011d3,4011df) {reg5}
+    [232] parameter 'word'
+      [4011d3,4011df) {reg0}
+  [28d] function 'say'@401180
+    frame_base: {call_frame_cfa {...}}
+    [2af] parameter 'prefix'
+      [401180,40118e) {reg5}
+      [40118e,40119c) {reg3}
+      [40119c,4011a7) {entry_value(1) {reg5}, stack_value}
+      [4011a7,4011b5) {reg3}
+      [4011b5,4011c0) {entry_value(1) {reg5}, stack_value}
+    [2be] variable 'world'
+      [401193,40119b) {reg0}
+      [4011a7,4011b4) {reg0}
+  [2ce] inlined function 'happy'@40119b
+    [2e6] parameter 'w'
+      [4011a7,4011b4) {reg0}
+  [2ef] inlined function 'sad'@40119b
+    [303] parameter 'c'
+      [40119b,4011a6) {reg0}
+      [4011a6,4011a7) {entry_value(1) {reg5}}
+      [4011b4,4011bf) {reg0}
+  [36b] function 'no_subject'@4011c0
+    frame_base: {call_frame_cfa {...}}
+    [386] parameter 'word'
+      [4011c0,4011d0) {reg5}
+    [38d] parameter 'count'
+      [4011c0,4011d0) {reg4}
+EOF
+
+# Multi CU Split DWARF5. See run-dwarf-ranges.sh.
+# Note that the DIE numbers change, but the actual location addresses are
+# the same as above, even though the representation is totally different.
+testfiles testfilesplitranges5.debug
+testfiles testfile-ranges-hello5.dwo testfile-ranges-world5.dwo
+testrun_compare ${abs_top_builddir}/tests/varlocs --debug -e testfilesplitranges5.debug <<\EOF
+module 'testfilesplitranges5.debug'
+[14] CU 'hello.c'@0
+  [1d] function 'no_say'@401160
+    frame_base: {call_frame_cfa {...}}
+    [33] parameter 'prefix'
+      [401160,401169) {reg5}
+      [401169,40116a) {entry_value(1) {reg5}, stack_value}
+      [40116a,401175) {reg5}
+      [401175,40117a) {entry_value(1) {reg5}, stack_value}
+    [3c] variable 'world'
+      [401160,40117a) {addr: 0x402004, stack_value}
+  [7e] function 'main'@401050
+    frame_base: {call_frame_cfa {...}}
+    [94] parameter 'argc'
+      [401050,401062) {reg5}
+      [401062,401067) {entry_value(1) {reg5}, stack_value}
+    [9d] parameter 'argv'
+      [401050,401066) {reg4}
+      [401066,401067) {entry_value(1) {reg4}, stack_value}
+  [a6] inlined function 'subject'@401053
+    [bb] parameter 'count'
+      [401053,40105f) {reg5}
+    [c1] parameter 'word'
+      [401053,40105f) {reg0}
+  [f6] function 'subject'@401150
+    frame_base: {call_frame_cfa {...}}
+    [10a] parameter 'word'
+      [401150,401160) {reg5}
+    [111] parameter 'count'
+      [401150,401160) {reg4}
+module 'testfilesplitranges5.debug'
+[14] CU 'world.c'@401180
+  [1d] function 'no_main'@4011d0
+    frame_base: {call_frame_cfa {...}}
+    [35] parameter 'argc'
+      [4011d0,4011e2) {reg5}
+      [4011e2,4011e7) {entry_value(1) {reg5}, stack_value}
+    [3e] parameter 'argv'
+      [4011d0,4011e6) {reg4}
+      [4011e6,4011e7) {entry_value(1) {reg4}, stack_value}
+  [47] inlined function 'no_subject'@4011d3
+    [5c] parameter 'count'
+      [4011d3,4011df) {reg5}
+    [62] parameter 'word'
+      [4011d3,4011df) {reg0}
+  [a7] function 'say'@401180
+    frame_base: {call_frame_cfa {...}}
+    [c2] parameter 'prefix'
+      [401180,40118e) {reg5}
+      [40118e,40119c) {reg3}
+      [40119c,4011a7) {entry_value(1) {reg5}, stack_value}
+      [4011a7,4011b5) {reg3}
+      [4011b5,4011c0) {entry_value(1) {reg5}, stack_value}
+    [cb] variable 'world'
+      [401193,40119b) {reg0}
+      [4011a7,4011b4) {reg0}
+  [d5] inlined function 'happy'@40119b
+    [e3] parameter 'w'
+      [4011a7,4011b4) {reg0}
+  [e9] inlined function 'sad'@40119b
+    [f3] parameter 'c'
+      [40119b,4011a6) {reg0}
+      [4011a6,4011a7) {entry_value(1) {reg5}}
+      [4011b4,4011bf) {reg0}
+  [147] function 'no_subject'@4011c0
+    frame_base: {call_frame_cfa {...}}
+    [15b] parameter 'word'
+      [4011c0,4011d0) {reg5}
+    [162] parameter 'count'
+      [4011c0,4011d0) {reg4}
+EOF
+
+# GNU DebugFissuon Multi CU Split DWARF. See run-dwarf-ranges.sh.
+testfiles testfilesplitranges4.debug
+testfiles testfile-ranges-hello.dwo testfile-ranges-world.dwo
+testrun_compare ${abs_top_builddir}/tests/varlocs --debug -e testfilesplitranges4.debug <<\EOF
+module 'testfilesplitranges4.debug'
+[b] CU 'hello.c'@0
+  [18] function 'no_say'@4004f0
+    frame_base: {call_frame_cfa {...}}
+    [2f] parameter 'prefix'
+      [4004f0,4004fa) {reg5}
+      [4004fa,4004ff) {GNU_entry_value(1) {reg5}, stack_value}
+    [3b] variable 'world'
+      <no value>
+  [60] function 'main'@4003e0
+    frame_base: {call_frame_cfa {...}}
+    [77] parameter 'argc'
+      [4003e0,4003f2) {reg5}
+      [4003f2,4003f7) {GNU_entry_value(1) {reg5}, stack_value}
+    [83] parameter 'argv'
+      [4003e0,4003f6) {reg4}
+      [4003f6,1004003f5) {GNU_entry_value(1) {reg4}, stack_value}
+  [8f] inlined function 'subject'@4003e3
+    [a3] parameter 'count'
+      [4003e3,4003ef) {reg5}
+    [ac] parameter 'word'
+      [4003e3,4003ef) {reg0}
+  [e7] function 'subject'@4004e0
+    frame_base: {call_frame_cfa {...}}
+    [fb] parameter 'word'
+      [4004e0,4004f0) {reg5}
+    [102] parameter 'count'
+      [4004e0,4004f0) {reg4}
+module 'testfilesplitranges4.debug'
+[b] CU 'world.c'@400500
+  [18] function 'no_main'@400550
+    frame_base: {call_frame_cfa {...}}
+    [2f] parameter 'argc'
+      [400550,400562) {reg5}
+      [400562,400567) {GNU_entry_value(1) {reg5}, stack_value}
+    [3b] parameter 'argv'
+      [400550,400566) {reg4}
+      [400566,100400565) {GNU_entry_value(1) {reg4}, stack_value}
+  [47] inlined function 'no_subject'@400553
+    [5b] parameter 'count'
+      [400553,40055f) {reg5}
+    [64] parameter 'word'
+      [400553,40055f) {reg0}
+  [af] function 'say'@400500
+    frame_base: {call_frame_cfa {...}}
+    [c9] parameter 'prefix'
+      [400500,40050e) {reg5}
+      [40050e,40051c) {reg3}
+      [40051c,400527) {GNU_entry_value(1) {reg5}, stack_value}
+      [400527,400535) {reg3}
+      [400535,400540) {GNU_entry_value(1) {reg5}, stack_value}
+    [d5] variable 'world'
+      [400513,40051b) {reg0}
+      [400527,400534) {reg0}
+  [e1] inlined function 'happy'@40051c
+    [f1] parameter 'w'
+      [400527,400534) {reg0}
+  [fa] inlined function 'sad'@40051c
+    [106] parameter 'c'
+      [40051b,400526) {reg0}
+      [400526,400527) {GNU_entry_value(1) {reg5}}
+      [400534,40053f) {reg0}
+  [15c] function 'no_subject'@400540
+    frame_base: {call_frame_cfa {...}}
+    [170] parameter 'word'
+      [400540,400550) {reg5}
+    [177] parameter 'count'
+      [400540,400550) {reg4}
+EOF
+
+# DW_OP_addrx and DW_OP_constx testcases.
+#
+# int i, j, k;
+# __thread int l, m, n;
+#
+# int main ()
+# {
+#   int r1 = i + j + k;
+#   int r2 = l + m + n;
+#   int res = r1 + r2;
+#
+#   return res;
+# }
+#
+# gcc -O2 -gdwarf-5 -gsplit-dwarf -o addrx_constx-5.o -c addrx_constx.c
+# gcc -O2 -gdwarf-5 -gsplit-dwarf -o testfile-addrx_constx-5 addrx_constx-5.o
+# gcc -O2 -gdwarf-4 -gsplit-dwarf -o addrx_constx-4.o -c addrx_constx.c
+# gcc -O2 -gdwarf-4 -gsplit-dwarf -o testfile-addrx_constx-4 addrx_constx-4.o
+
+testfiles testfile-addrx_constx-5 addrx_constx-5.dwo
+testrun_compare ${abs_top_builddir}/tests/varlocs --exprlocs -e testfile-addrx_constx-5 <<\EOF
+module 'testfile-addrx_constx-5'
+[14] CU 'addrx_constx.c'@0
+  producer (strx)
+  language (data1)
+  name (strx)
+  comp_dir (strx)
+  [19] variable "i"
+    name (string)
+    decl_file (implicit_const)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {addr: 0x404038}
+  [25] base_type "int"
+    byte_size (data1)
+    encoding (data1)
+    name (string)
+  [2c] variable "j"
+    name (string)
+    decl_file (implicit_const)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {addr: 0x404034}
+  [38] variable "k"
+    name (string)
+    decl_file (implicit_const)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {addr: 0x40403c}
+  [44] variable "l"
+    name (string)
+    decl_file (implicit_const)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {const: 0x403e10, form_tls_address}
+  [51] variable "m"
+    name (string)
+    decl_file (implicit_const)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {const: 0x403e0c, form_tls_address}
+  [5e] variable "n"
+    name (string)
+    decl_file (implicit_const)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {const: 0x403e08, form_tls_address}
+  [6b] subprogram "main"
+    external (flag_present)
+    name (strx)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    low_pc (addrx)
+    high_pc (data8)
+    frame_base (exprloc) {call_frame_cfa {bregx(7,8)}}
+    call_all_calls (flag_present)
+    [7f] variable "r1"
+      name (string)
+      decl_file (implicit_const)
+      decl_line (data1)
+      decl_column (implicit_const)
+      type (ref4)
+      location (exprloc) {addr: 0x404038, deref_size(4), addr: 0x404034, deref_size(4), plus, addr: 0x40403c, deref_size(4), plus, stack_value}
+    [98] variable "r2"
+      name (string)
+      decl_file (implicit_const)
+      decl_line (data1)
+      decl_column (implicit_const)
+      type (ref4)
+      location (exprloc) {form_tls_address, const: 0x403e10, deref_size(4), form_tls_address, const: 0x403e0c, deref_size(4), plus, form_tls_address, const: 0x403e08, deref_size(4), plus, stack_value}
+    [b4] variable "res"
+      name (string)
+      decl_file (implicit_const)
+      decl_line (data1)
+      decl_column (implicit_const)
+      type (ref4)
+      location (exprloc) {addr: 0x404038, deref_size(4), form_tls_address, const: 0x403e08, deref_size(4), plus, form_tls_address, const: 0x403e0c, deref_size(4), plus, form_tls_address, const: 0x403e10, deref_size(4), plus, addr: 0x404034, deref_size(4), plus, addr: 0x40403c, deref_size(4), plus, stack_value}
+EOF
+
+testfiles testfile-addrx_constx-4 addrx_constx-4.dwo
+testrun_compare ${abs_top_builddir}/tests/varlocs --exprlocs -e testfile-addrx_constx-4 <<\EOF
+module 'testfile-addrx_constx-4'
+[b] CU 'addrx_constx.c'@0
+  producer (GNU_str_index)
+  language (data1)
+  name (GNU_str_index)
+  comp_dir (GNU_str_index)
+  GNU_dwo_id (data8)
+  [18] variable "i"
+    name (string)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {addr: 0x404038}
+  [25] base_type "int"
+    byte_size (data1)
+    encoding (data1)
+    name (string)
+  [2c] variable "j"
+    name (string)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {addr: 0x404034}
+  [39] variable "k"
+    name (string)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {addr: 0x40403c}
+  [46] variable "l"
+    name (string)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {const: 0x403e10, GNU_push_tls_address}
+  [54] variable "m"
+    name (string)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {const: 0x403e0c, GNU_push_tls_address}
+  [62] variable "n"
+    name (string)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    external (flag_present)
+    location (exprloc) {const: 0x403e08, GNU_push_tls_address}
+  [70] subprogram "main"
+    external (flag_present)
+    name (GNU_str_index)
+    decl_file (data1)
+    decl_line (data1)
+    decl_column (data1)
+    type (ref4)
+    low_pc (GNU_addr_index)
+    high_pc (data8)
+    frame_base (exprloc) {call_frame_cfa {bregx(7,8)}}
+    GNU_all_call_sites (flag_present)
+    [84] variable "r1"
+      name (string)
+      decl_file (data1)
+      decl_line (data1)
+      decl_column (data1)
+      type (ref4)
+      location (exprloc) {addr: 0x404038, deref_size(4), addr: 0x404034, deref_size(4), plus, addr: 0x40403c, deref_size(4), plus, stack_value}
+    [9f] variable "r2"
+      name (string)
+      decl_file (data1)
+      decl_line (data1)
+      decl_column (data1)
+      type (ref4)
+      location (exprloc) {GNU_push_tls_address, const: 0x403e10, deref_size(4), GNU_push_tls_address, const: 0x403e0c, deref_size(4), plus, GNU_push_tls_address, const: 0x403e08, deref_size(4), plus, stack_value}
+    [bd] variable "res"
+      name (string)
+      decl_file (data1)
+      decl_line (data1)
+      decl_column (data1)
+      type (ref4)
+      location (exprloc) {addr: 0x404038, deref_size(4), GNU_push_tls_address, const: 0x403e08, deref_size(4), plus, GNU_push_tls_address, const: 0x403e0c, deref_size(4), plus, GNU_push_tls_address, const: 0x403e10, deref_size(4), plus, addr: 0x404034, deref_size(4), plus, addr: 0x40403c, deref_size(4), plus, stack_value}
+EOF
+
+# See run-readelf-loc.sh
+testfiles testfile-splitdwarf4-not-split4.debug
+testfiles splitdwarf4-not-split4.dwo
+
+testrun_compare ${abs_top_builddir}/tests/varlocs --debug -e testfile-splitdwarf4-not-split4.debug <<\EOF
+module 'testfile-splitdwarf4-not-split4.debug'
+[b] CU 'splitdwarf4-not-split4.c'@0
+  [18] function 'main'@401050
+    frame_base: {call_frame_cfa {...}}
+    [30] parameter 'argc'
+      [401050,40106e) {reg5}
+      [40106e,401086) {reg12}
+      [401086,401095) {GNU_entry_value(1) {reg5}, stack_value}
+      [401095,40109c) {reg5}
+    [3d] parameter 'argv'
+      [401050,40106e) {reg4}
+      [40106e,401095) {GNU_entry_value(1) {reg4}, stack_value}
+      [401095,40109c) {reg4}
+    [4a] variable 'i'
+      [401050,40106e) {lit0, stack_value}
+      [401086,40108e) {breg12(0), breg6(0), plus, stack_value}
+      [40108e,401095) {reg0}
+      [401095,40109c) {lit0, stack_value}
+    [58] variable 'p'
+      [401050,40106e) {reg5}
+      [40106e,401090) {reg6}
+      [401095,40109c) {reg5}
+module 'testfile-splitdwarf4-not-split4.debug'
+[3f] CU 'popcount.c'@401180
+  [61] function 'popcount'@401180
+    frame_base: {call_frame_cfa {...}}
+    [83] parameter 'u'
+      [401180,401189) {reg5}
+      [401189,40119b) {reg1}
+      [40119b,40119d) {breg1(0), lit1, shr, stack_value}
+      [40119d,4011a1) {reg1}
+    [91] variable 'c'
+      [401180,401189) {lit0, stack_value}
+      [401189,4011a0) {reg0}
+      [4011a0,4011a1) {lit0, stack_value}
+EOF
+
+# See testfile-dwp.source.
+testfiles testfile-dwp-5 testfile-dwp-5.dwp
+testfiles testfile-dwp-4 testfile-dwp-4.dwp
+
+testrun_compare ${abs_builddir}/varlocs -e testfile-dwp-5 << EOF
+module 'testfile-dwp-5'
+[84] CU 'foo.cc'@401190
+  [c6] function 'foo'@4011c0
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [e1] parameter 'this'
+      [4011c0,401200) {reg5}
+    [ea] variable 'x'
+      [4011c2,4011d4) {reg0}
+      [4011d4,4011d7) {reg1}
+      [4011d7,4011d9) {breg1(1), stack_value}
+      [4011f1,401200) {reg0}
+  [f9] inlined function 'x_x'@4011cb
+    [104] parameter 'x'
+      [4011cb,4011eb) {reg0}
+      [4011f1,401200) {reg0}
+  [14a] function 'x_x'@401190
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [15b] parameter 'x'
+      [401190,4011a1) {reg5}
+      [4011a1,4011bd) {reg0}
+module 'testfile-dwp-5'
+[1fa] CU 'bar.cc'@401200
+  [23c] function 'bar'@401200
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [253] parameter 'this'
+      [401200,40121b) {reg5}
+module 'testfile-dwp-5'
+[272] CU 'main.cc'@0
+  [2c7] function 'main'@401020
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [2e0] parameter 'argc'
+      [401020,401068) {reg5}
+      [401068,401080) {fbreg(-40)}
+      [401080,401084) {breg5(0)}
+      [401084,401099) {entry_value(1) {reg5}, stack_value}
+      [401099,4010a0) {reg5}
+    [2ec] parameter 'argv'
+      [401020,40104b) {reg4}
+      [40104b,401099) {entry_value(1) {reg4}, stack_value}
+      [401099,4010a0) {reg4}
+    [2f8] variable 'myfoo'
+      [401020,4010a0) {fbreg(-40)}
+    [303] variable 'mybar'
+      [401020,4010a0) {fbreg(-32)}
+  [30d] inlined function 'fibonacci'@401030
+    [31c] parameter 'n'
+      [401030,401060) {reg5}
+      [401099,4010a0) {reg5}
+  [326] inlined function 'fibonacci'
+    [32f] parameter 'n'
+      <no value>
+EOF
+
+testrun_compare ${abs_builddir}/varlocs -e testfile-dwp-4 << EOF
+module 'testfile-dwp-4'
+[b] CU 'foo.cc'@401190
+  [54] function 'foo'@4011c0
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [6f] parameter 'this'
+      [4011c0,401200) {reg5}
+    [78] variable 'x'
+      [4011c2,4011d4) {reg0}
+      [4011d4,4011d7) {reg1}
+      [4011d7,4011d9) {breg1(1), stack_value}
+      [4011f1,401200) {reg0}
+  [8a] inlined function 'x_x'@4011cb
+    [98] parameter 'x'
+      [4011cb,4011eb) {reg0}
+      [4011f1,401200) {reg0}
+  [e7] function 'x_x'@401190
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [f8] parameter 'x'
+      [401190,4011a1) {reg5}
+      [4011a1,4011bd) {reg0}
+module 'testfile-dwp-4'
+[129] CU 'bar.cc'@401200
+  [172] function 'bar'@401200
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [189] parameter 'this'
+      [401200,40121b) {reg5}
+module 'testfile-dwp-4'
+[19f] CU 'main.cc'@0
+  [1fd] function 'main'@401020
+    frame_base: {call_frame_cfa {bregx(7,8)}}
+    [216] parameter 'argc'
+      [401020,401068) {reg5}
+      [401068,401080) {fbreg(-40)}
+      [401080,401084) {breg5(0)}
+      [401084,401097) {GNU_entry_value(1) {reg5}, stack_value}
+      [401099,4010a0) {reg5}
+    [228] parameter 'argv'
+      [401020,40104b) {reg4}
+      [40104b,401099) {GNU_entry_value(1) {reg4}, stack_value}
+      [401099,4010a0) {reg4}
+    [23a] variable 'myfoo'
+      [401020,4010a0) {fbreg(-40)}
+    [247] variable 'mybar'
+      [401020,4010a0) {fbreg(-32)}
+  [253] inlined function 'fibonacci'@401030
+    [265] parameter 'n'
+      [401030,401060) {reg5}
+      [401099,4010a0) {reg5}
+  [272] inlined function 'fibonacci'
+    [27e] parameter 'n'
+      <no value>
+EOF
+
+exit 0
diff --git a/tests/run-xlate-note.sh b/tests/run-xlate-note.sh
new file mode 100755
index 0000000..a907418
--- /dev/null
+++ b/tests/run-xlate-note.sh
@@ -0,0 +1,93 @@
+# Copyright (C) 2019 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+testfiles testfileppc32
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfileppc32 << EOF
+Notes in section 2:
+type: 1,1, namesz: 4,4, descsz: 16,16
+Notes in section 3:
+type: 3,3, namesz: 4,4, descsz: 20,20
+EOF
+
+testfiles testfileppc64
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfileppc64 << EOF
+Notes in section 2:
+type: 1,1, namesz: 4,4, descsz: 16,16
+Notes in section 3:
+type: 3,3, namesz: 4,4, descsz: 20,20
+EOF
+
+testfiles testfiles390
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfiles390 << EOF
+Notes in section 2:
+type: 1,1, namesz: 4,4, descsz: 16,16
+Notes in section 3:
+type: 3,3, namesz: 4,4, descsz: 20,20
+EOF
+
+testfiles testfiles390x
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfiles390x << EOF
+Notes in section 2:
+type: 1,1, namesz: 4,4, descsz: 16,16
+Notes in section 3:
+type: 3,3, namesz: 4,4, descsz: 20,20
+EOF
+
+testfiles testfileaarch64
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfileaarch64 << EOF
+Notes in section 2:
+type: 1,1, namesz: 4,4, descsz: 16,16
+Notes in section 3:
+type: 3,3, namesz: 4,4, descsz: 20,20
+EOF
+
+testfiles testfilearm
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfilearm << EOF
+Notes in section 2:
+type: 1,1, namesz: 4,4, descsz: 16,16
+Notes in section 3:
+type: 3,3, namesz: 4,4, descsz: 20,20
+EOF
+
+testfiles testfile_gnu_props.32be.o
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfile_gnu_props.32be.o << EOF
+Notes in section 4:
+type: 5,5, namesz: 4,4, descsz: 12,12
+type: 5,5, namesz: 4,4, descsz: 8,8
+EOF
+
+testfiles testfile_gnu_props.32le.o
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfile_gnu_props.32le.o << EOF
+Notes in section 4:
+type: 5,5, namesz: 4,4, descsz: 12,12
+type: 5,5, namesz: 4,4, descsz: 8,8
+EOF
+
+testfiles testfile_gnu_props.64be.o
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfile_gnu_props.64be.o << EOF
+Notes in section 4:
+type: 5,5, namesz: 4,4, descsz: 16,16
+type: 5,5, namesz: 4,4, descsz: 8,8
+EOF
+
+testfiles testfile_gnu_props.64le.o
+testrun_compare ${abs_top_builddir}/tests/xlate_notes testfile_gnu_props.64le.o << EOF
+Notes in section 4:
+type: 5,5, namesz: 4,4, descsz: 16,16
+type: 5,5, namesz: 4,4, descsz: 8,8
+EOF
diff --git a/tests/run-zstrptr.sh b/tests/run-zstrptr.sh
new file mode 100755
index 0000000..254dcd8
--- /dev/null
+++ b/tests/run-zstrptr.sh
@@ -0,0 +1,167 @@
+#! /bin/sh
+# Copyright (C) 2015 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+# A random 32bit and 64bit testfile
+testfiles testfile testfile10
+
+testrun_compare ${abs_top_builddir}/tests/zstrptr testfile <<\EOF
+Strings in section 32 (compressed):
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.interp'
+[23] '.note.ABI-tag'
+[31] '.hash'
+[37] '.dynsym'
+[3f] '.dynstr'
+[47] '.gnu.version'
+[54] '.gnu.version_r'
+[63] '.rel.got'
+[6c] '.rel.plt'
+[75] '.init'
+[7b] '.plt'
+[80] '.text'
+[86] '.fini'
+[8c] '.rodata'
+[94] '.data'
+[9a] '.eh_frame'
+[a4] '.ctors'
+[ab] '.dtors'
+[b2] '.got'
+[b7] '.dynamic'
+[c0] '.sbss'
+[c6] '.bss'
+[cb] '.stab'
+[d1] '.stabstr'
+[da] '.comment'
+[e3] '.debug_aranges'
+[f2] '.debug_pubnames'
+[102] '.debug_info'
+[10e] '.debug_abbrev'
+[11c] '.debug_line'
+[128] '.note'
+Strings in section 32 (uncompressed):
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.interp'
+[23] '.note.ABI-tag'
+[31] '.hash'
+[37] '.dynsym'
+[3f] '.dynstr'
+[47] '.gnu.version'
+[54] '.gnu.version_r'
+[63] '.rel.got'
+[6c] '.rel.plt'
+[75] '.init'
+[7b] '.plt'
+[80] '.text'
+[86] '.fini'
+[8c] '.rodata'
+[94] '.data'
+[9a] '.eh_frame'
+[a4] '.ctors'
+[ab] '.dtors'
+[b2] '.got'
+[b7] '.dynamic'
+[c0] '.sbss'
+[c6] '.bss'
+[cb] '.stab'
+[d1] '.stabstr'
+[da] '.comment'
+[e3] '.debug_aranges'
+[f2] '.debug_pubnames'
+[102] '.debug_info'
+[10e] '.debug_abbrev'
+[11c] '.debug_line'
+[128] '.note'
+EOF
+
+testrun_compare ${abs_top_builddir}/tests/zstrptr testfile10 <<\EOF
+Strings in section 30 (compressed):
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.hash'
+[21] '.dynsym'
+[29] '.dynstr'
+[31] '.gnu.version'
+[3e] '.gnu.version_r'
+[4d] '.rela.dyn'
+[57] '.init'
+[5d] '.text'
+[63] '.fini'
+[69] '.eh_frame'
+[73] '.data'
+[79] '.dynamic'
+[82] '.ctors'
+[89] '.dtors'
+[90] '.jcr'
+[95] '.plt'
+[9a] '.got'
+[9f] '.sdata'
+[a6] '.sbss'
+[ac] '.bss'
+[b1] '.comment'
+[ba] '.debug_aranges'
+[c9] '.debug_pubnames'
+[d9] '.debug_abbrev'
+[e7] '.debug_line'
+[f3] '.debug_frame'
+[100] '.debug_str'
+[10b] '.rela.debug_info'
+Strings in section 30 (uncompressed):
+[0] ''
+[1] '.symtab'
+[9] '.strtab'
+[11] '.shstrtab'
+[1b] '.hash'
+[21] '.dynsym'
+[29] '.dynstr'
+[31] '.gnu.version'
+[3e] '.gnu.version_r'
+[4d] '.rela.dyn'
+[57] '.init'
+[5d] '.text'
+[63] '.fini'
+[69] '.eh_frame'
+[73] '.data'
+[79] '.dynamic'
+[82] '.ctors'
+[89] '.dtors'
+[90] '.jcr'
+[95] '.plt'
+[9a] '.got'
+[9f] '.sdata'
+[a6] '.sbss'
+[ac] '.bss'
+[b1] '.comment'
+[ba] '.debug_aranges'
+[c9] '.debug_pubnames'
+[d9] '.debug_abbrev'
+[e7] '.debug_line'
+[f3] '.debug_frame'
+[100] '.debug_str'
+[10b] '.rela.debug_info'
+EOF
+
+exit 0
diff --git a/tests/saridx.c b/tests/saridx.c
new file mode 100644
index 0000000..e7f0c56
--- /dev/null
+++ b/tests/saridx.c
@@ -0,0 +1,257 @@
+/* Copyright (C) 1998, 1999, 2000, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include "system.h"
+
+
+static const char *machines[] =
+{
+#define MACHINE(name) [name] = #name
+  MACHINE (EM_NONE),
+  MACHINE (EM_M32),
+  MACHINE (EM_SPARC),
+  MACHINE (EM_386),
+  MACHINE (EM_68K),
+  MACHINE (EM_88K),
+  MACHINE (EM_860),
+  MACHINE (EM_MIPS),
+  MACHINE (EM_MIPS_RS3_LE),
+  MACHINE (EM_PARISC),
+  MACHINE (EM_VPP500),
+  MACHINE (EM_SPARC32PLUS),
+  MACHINE (EM_960),
+  MACHINE (EM_PPC),
+  MACHINE (EM_PPC64),
+  MACHINE (EM_V800),
+  MACHINE (EM_FR20),
+  MACHINE (EM_RH32),
+  MACHINE (EM_RCE),
+  MACHINE (EM_ARM),
+  MACHINE (EM_FAKE_ALPHA),
+  MACHINE (EM_SH),
+  MACHINE (EM_SPARCV9),
+  MACHINE (EM_TRICORE),
+  MACHINE (EM_ARC),
+  MACHINE (EM_H8_300),
+  MACHINE (EM_H8_300H),
+  MACHINE (EM_H8S),
+  MACHINE (EM_H8_500),
+  MACHINE (EM_IA_64),
+  MACHINE (EM_MIPS_X),
+  MACHINE (EM_COLDFIRE),
+  MACHINE (EM_68HC12),
+  MACHINE (EM_MMA),
+  MACHINE (EM_PCP),
+  MACHINE (EM_NCPU),
+  MACHINE (EM_NDR1),
+  MACHINE (EM_STARCORE),
+  MACHINE (EM_ME16),
+  MACHINE (EM_ST100),
+  MACHINE (EM_TINYJ),
+  MACHINE (EM_FX66),
+  MACHINE (EM_ST9PLUS),
+  MACHINE (EM_ST7),
+  MACHINE (EM_68HC16),
+  MACHINE (EM_68HC11),
+  MACHINE (EM_68HC08),
+  MACHINE (EM_68HC05),
+  MACHINE (EM_SVX),
+  MACHINE (EM_ST19),
+  MACHINE (EM_VAX)
+};
+
+
+int
+main (int argc, char *argv[])
+{
+  int fd;
+  Elf *elf;
+  Elf_Cmd cmd;
+  size_t n;
+  int arg = 1;
+  int verbose = 0;
+
+  /* Recognize optional verbosity flag.  */
+  if (arg < argc && strcmp (argv[arg], "-v") == 0)
+    {
+      verbose = 1;
+      ++arg;
+    }
+
+  /* Any more arguments available.  */
+  if (arg >= argc)
+    error (EXIT_FAILURE, 0, "No input file given");
+
+  /* Open the input file.  */
+  fd = open (argv[arg], O_RDONLY);
+  if (fd == -1)
+    {
+      perror ("cannot open input file");
+      exit (1);
+    }
+
+  /* Set the ELF version we are using here.  */
+  if (elf_version (EV_CURRENT) == EV_NONE)
+    {
+      puts ("ELF library too old");
+      exit (1);
+    }
+
+  /* Start reading the file.  */
+  cmd = ELF_C_READ;
+  elf = elf_begin (fd, cmd, NULL);
+  if (elf == NULL)
+    {
+      printf ("elf_begin: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* If it is no archive punt.  */
+  if (elf_kind (elf) != ELF_K_AR)
+    {
+      printf ("%s is not an archive\n", argv[1]);
+      exit (1);
+    }
+
+  if (verbose)
+    {
+      /* The verbose variant.  We print a lot of information.  */
+      Elf *subelf;
+      char buf[100];
+      time_t t;
+
+      /* Get the elements of the archive one after the other.  */
+      while ((subelf = elf_begin (fd, cmd, elf)) != NULL)
+	{
+	  /* The the header for this element.  */
+	  Elf_Arhdr *arhdr = elf_getarhdr (subelf);
+
+	  if (arhdr == NULL)
+	    {
+	      printf ("cannot get arhdr: %s\n", elf_errmsg (-1));
+	      break;
+	    }
+
+	  switch (elf_kind (subelf))
+	    {
+	    case ELF_K_ELF:
+	      fputs ("ELF file:\n", stdout);
+	      break;
+
+	    case ELF_K_AR:
+	      fputs ("archive:\n", stdout);
+	      break;
+
+	    default:
+	      fputs ("unknown file:\n", stdout);
+	      break;
+	    }
+
+	  /* Print general information.  */
+	  t = arhdr->ar_date;
+	  strftime (buf, sizeof buf, "%Y-%m-%dT%H:%M:%S%z", gmtime (&t));
+	  printf ("  name         : \"%s\"\n"
+		  "  time         : %s\n"
+		  "  uid          : %ld\n"
+		  "  gid          : %ld\n"
+		  "  mode         : %o\n"
+		  "  size         : %ld\n"
+		  "  rawname      : \"%s\"\n",
+		  arhdr->ar_name,
+		  buf,
+		  (long int) arhdr->ar_uid,
+		  (long int) arhdr->ar_gid,
+		  arhdr->ar_mode,
+		  (long int) arhdr->ar_size,
+		  arhdr->ar_rawname);
+
+	  /* For ELF files we can provide some more information.  */
+	  if (elf_kind (subelf) == ELF_K_ELF)
+	    {
+	      GElf_Ehdr ehdr;
+
+	      /* Get the ELF header.  */
+	      if (gelf_getehdr (subelf, &ehdr) == NULL)
+		printf ("  *** cannot get ELF header: %s\n", elf_errmsg (-1));
+	      else
+		{
+		  printf ("  binary class : %s\n",
+			  ehdr.e_ident[EI_CLASS] == ELFCLASS32
+			  ? "ELFCLASS32" : "ELFCLASS64");
+		  printf ("  data encoding: %s\n",
+			  ehdr.e_ident[EI_DATA] == ELFDATA2LSB
+			  ? "ELFDATA2LSB" : "ELFDATA2MSB");
+		  printf ("  binary type  : %s\n",
+			  ehdr.e_type == ET_REL
+			  ? "relocatable"
+			  : (ehdr.e_type == ET_EXEC
+			     ? "executable"
+			     : (ehdr.e_type == ET_DYN
+				? "dynamic"
+				: "core file")));
+		  printf ("  machine      : %s\n",
+			  (ehdr.e_machine >= (sizeof (machines)
+					      / sizeof (machines[0]))
+			   || machines[ehdr.e_machine] == NULL)
+			  ? "???"
+			  : machines[ehdr.e_machine]);
+		}
+	    }
+
+	  /* Get next archive element.  */
+	  cmd = elf_next (subelf);
+	  if (elf_end (subelf) != 0)
+	    printf ("error while freeing sub-ELF descriptor: %s\n",
+		    elf_errmsg (-1));
+	}
+    }
+  else
+    {
+      /* The simple version.  Only print a bit of information.  */
+      Elf_Arsym *arsym = elf_getarsym (elf, &n);
+
+      if (n == 0)
+	printf ("no symbol table in archive: %s\n", elf_errmsg (-1));
+      else
+	{
+	  --n;
+
+	  while (n-- > 0)
+	    printf ("name = \"%s\", offset = %ld, hash = %lx\n",
+		    arsym[n].as_name, (long int) arsym[n].as_off,
+		    arsym[n].as_hash);
+	}
+    }
+
+  /* Free the ELF handle.  */
+  if (elf_end (elf) != 0)
+    printf ("error while freeing ELF descriptor: %s\n", elf_errmsg (-1));
+
+  /* Close the underlying file.  */
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/scnnames.c b/tests/scnnames.c
new file mode 100644
index 0000000..7f26825
--- /dev/null
+++ b/tests/scnnames.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 1998, 1999, 2000, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  Elf *elf;
+  int fd;
+  GElf_Ehdr ehdr;
+  size_t strndx;
+  Elf_Scn *scn;
+
+  if (argc < 2)
+    {
+      puts ("missing parameter");
+      exit (1);
+    }
+
+  fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open \"%s\": %s\n", argv[1], strerror (errno));
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot open ELF file: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      printf ("\"%s\" is not an ELF file\n", argv[1]);
+      exit (1);
+    }
+
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    {
+      printf ("cannot get the ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  strndx = ehdr.e_shstrndx;
+
+  scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      char *name = NULL;
+      GElf_Shdr shdr;
+
+      if (gelf_getshdr (scn, &shdr) != NULL)
+	name = elf_strptr (elf, strndx, (size_t) shdr.sh_name);
+
+      printf ("section: `%s'\n", name);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("error while freeing ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/tests/sectiondump.c b/tests/sectiondump.c
new file mode 100644
index 0000000..661e644
--- /dev/null
+++ b/tests/sectiondump.c
@@ -0,0 +1,182 @@
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "system.h"
+
+
+/* Prototypes for local functions.  */
+static int handle_section (Elf *elf, Elf_Scn *scn);
+static void print_bytes (Elf_Data *data);
+static void print_symtab (Elf *elf, Elf_Data *data);
+
+
+int
+main (int argc, char *argv[])
+{
+  Elf *elf;
+  int fd;
+  int cnt;
+
+  if (argc <= 1)
+    exit (1);
+
+  /* Open the test file.  This is given as the first parameter to the
+     program.  */
+  fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    error (EXIT_FAILURE, errno, "cannot open input file `%s'", argv[1]);
+
+  /* Set the library version we expect.  */
+  elf_version (EV_CURRENT);
+
+  /* Create the ELF descriptor.  */
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    error (EXIT_FAILURE, 0, "cannot create ELF descriptor: %s",
+	   elf_errmsg (0));
+
+  /* Now process all the sections mentioned in the rest of the command line.  */
+  for (cnt = 2; cnt < argc; ++cnt)
+    if (handle_section (elf, elf_getscn (elf, atoi (argv[cnt]))) != 0)
+      /* When we encounter an error stop immediately.  */
+      error (EXIT_FAILURE, 0, "while processing section %d: %s", cnt,
+	   elf_errmsg (0));
+
+  /* Close the descriptor.  */
+  if (elf_end (elf) != 0)
+    error (EXIT_FAILURE, 0, "failure while closing ELF descriptor: %s",
+	   elf_errmsg (0));
+
+  return 0;
+}
+
+
+static int
+handle_section (Elf *elf, Elf_Scn *scn)
+{
+  GElf_Ehdr *ehdr;
+  GElf_Ehdr ehdr_mem;
+  GElf_Shdr *shdr;
+  GElf_Shdr shdr_mem;
+  Elf_Data *data;
+
+  /* First get the ELF and section header.  */
+  ehdr = gelf_getehdr (elf, &ehdr_mem);
+  shdr = gelf_getshdr (scn, &shdr_mem);
+  if (ehdr == NULL || shdr == NULL)
+    return 1;
+
+  /* Print the information from the ELF section header.   */
+  printf ("name      = %s\n"
+	  "type      = %" PRId32 "\n"
+	  "flags     = %" PRIx64 "\n"
+	  "addr      = %" PRIx64 "\n"
+	  "offset    = %" PRIx64 "\n"
+	  "size      = %" PRId64 "\n"
+	  "link      = %" PRId32 "\n"
+	  "info      = %" PRIx32 "\n"
+	  "addralign = %" PRIx64 "\n"
+	  "entsize   = %" PRId64 "\n",
+	  elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name),
+	  shdr->sh_type,
+	  shdr->sh_flags,
+	  shdr->sh_addr,
+	  shdr->sh_offset,
+	  shdr->sh_size,
+	  shdr->sh_link,
+	  shdr->sh_info,
+	  shdr->sh_addralign,
+	  shdr->sh_entsize);
+
+  /* Get the section data now.  */
+  data = elf_getdata (scn, NULL);
+  if (data == NULL)
+    return 1;
+
+  /* Now process the different section types accordingly.  */
+  switch (shdr->sh_type)
+    {
+    case SHT_SYMTAB:
+      print_symtab (elf, data);
+      break;
+
+    case SHT_PROGBITS:
+    default:
+      print_bytes (data);
+      break;
+    }
+
+  /* Separate form the next section.  */
+  puts ("");
+
+  /* All done correctly.  */
+  return 0;
+}
+
+
+static void
+print_bytes (Elf_Data *data)
+{
+  size_t size = data->d_size;
+  off_t offset = data->d_off;
+  unsigned char *buf = (unsigned char *) data->d_buf;
+  size_t cnt;
+
+  for (cnt = 0; cnt < size; cnt += 16)
+    {
+      size_t inner;
+
+      printf ("%*zx: ", sizeof (size_t) == 4 ? 8 : 16, (size_t) offset + cnt);
+
+      for (inner = 0; inner < 16 && cnt + inner < size; ++inner)
+	printf (" %02hhx", buf[cnt + inner]);
+
+      puts ("");
+    }
+}
+
+
+static void
+print_symtab (Elf *elf, Elf_Data *data)
+{
+  int class = gelf_getclass (elf);
+  size_t nsym = data->d_size / (class == ELFCLASS32
+				? sizeof (Elf32_Sym) : sizeof (Elf64_Sym));
+  size_t cnt;
+
+  for (cnt = 0; cnt < nsym; ++cnt)
+    {
+      GElf_Sym sym_mem;
+      GElf_Sym *sym = gelf_getsym (data, cnt, &sym_mem);
+
+      printf ("%5zu: %*" PRIx64 " %6" PRIx64 " %4d\n",
+	      cnt,
+	      class == ELFCLASS32 ? 8 : 16,
+	      sym->st_value,
+	      sym->st_size,
+	      GELF_ST_TYPE (sym->st_info));
+    }
+}
diff --git a/tests/show-abbrev.c b/tests/show-abbrev.c
new file mode 100644
index 0000000..002ae25
--- /dev/null
+++ b/tests/show-abbrev.c
@@ -0,0 +1,139 @@
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2004, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <fcntl.h>
+#include <inttypes.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+
+
+int
+main (int argc, char *argv[])
+{
+  int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if  (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[cnt], dwarf_errmsg (-1));
+	  close  (fd);
+	  continue;
+	}
+
+      Dwarf_Off cuoff = 0;
+      Dwarf_Off old_cuoff = 0;
+      size_t hsize;
+      while (dwarf_nextcu (dbg, cuoff, &cuoff, &hsize, NULL, NULL, NULL) == 0)
+	{
+	  /* Get the DIE for the CU.  */
+	  Dwarf_Die die;
+ 	  if (dwarf_offdie (dbg, old_cuoff + hsize, &die) == NULL)
+	    /* Something went wrong.  */
+	    break;
+
+	  /* Test something obviously wrong.  */
+	  Dwarf_Abbrev *a = dwarf_getabbrev (&die, (Dwarf_Off) -1, NULL);
+	  if (a != NULL)
+	    {
+	      printf ("dwarf_getabbrev -1 succeeded?\n");
+	      break;
+	    }
+
+	  Dwarf_Off offset = 0;
+
+	  while (1)
+	    {
+	      size_t length;
+	      Dwarf_Abbrev *abbrev = dwarf_getabbrev (&die, offset, &length);
+	      if (abbrev == NULL || abbrev == DWARF_END_ABBREV)
+		/* End of the list.  */
+		break;
+
+	      unsigned tag = dwarf_getabbrevtag (abbrev);
+	      if (tag == 0)
+		{
+		  printf ("dwarf_getabbrevtag at offset %llu returned error: %s\n",
+			  (unsigned long long int) offset,
+			  dwarf_errmsg (-1));
+		  break;
+		}
+
+	      unsigned code = dwarf_getabbrevcode (abbrev);
+	      if (code == 0)
+		{
+		  printf ("dwarf_getabbrevcode at offset %llu returned error: %s\n",
+			  (unsigned long long int) offset,
+			  dwarf_errmsg (-1));
+		  break;
+		}
+
+	      int children = dwarf_abbrevhaschildren (abbrev);
+	      if (children < 0)
+		{
+		  printf ("dwarf_abbrevhaschildren at offset %llu returned error: %s\n",
+			  (unsigned long long int) offset,
+			  dwarf_errmsg (-1));
+		  break;
+		}
+
+	      printf ("abbrev[%llu]: code = %u, tag = %u, children = %d\n",
+		      (unsigned long long int) offset, code, tag, children);
+
+	      size_t attrcnt;
+	      if (dwarf_getattrcnt (abbrev, &attrcnt) != 0)
+		{
+		  printf ("dwarf_getattrcnt at offset %llu returned error: %s\n",
+			  (unsigned long long int) offset,
+			  dwarf_errmsg (-1));
+		  break;
+		}
+
+	      unsigned int attr_num;
+	      unsigned int attr_form;
+	      Dwarf_Off aboffset;
+	      size_t j;
+	      for (j = 0; j < attrcnt; ++j)
+		if (dwarf_getabbrevattr (abbrev, j, &attr_num, &attr_form,
+					 &aboffset))
+		  printf ("dwarf_getabbrevattr for abbrev[%llu] and index %zu failed\n",
+			  (unsigned long long int) offset, j);
+		else
+		  printf ("abbrev[%llu]: attr[%zu]: code = %u, form = %u, offset = %" PRIu64 "\n",
+			  (unsigned long long int) offset, j, attr_num,
+			  attr_form, (uint64_t) aboffset);
+
+	      offset += length;
+	    }
+
+	  old_cuoff = cuoff;
+	}
+
+      if (dwarf_end (dbg) != 0)
+	printf ("dwarf_end failed for %s: %s\n", argv[cnt],
+		dwarf_errmsg (-1));
+
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/show-die-info.c b/tests/show-die-info.c
new file mode 100644
index 0000000..bda459a
--- /dev/null
+++ b/tests/show-die-info.c
@@ -0,0 +1,359 @@
+/* Copyright (C) 1998-2002, 2004, 2006, 2012, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <dwarf.h>
+#include <inttypes.h>
+#include <libelf.h>
+#include ELFUTILS_HEADER(dw)
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "../libdw/known-dwarf.h"
+#include "../lib/system.h"
+
+static const char *
+dwarf_tag_string (unsigned int tag)
+{
+  switch (tag)
+    {
+#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_TAG
+#undef DWARF_ONE_KNOWN_DW_TAG
+    default:
+      return NULL;
+    }
+}
+
+static const char *
+dwarf_attr_string (unsigned int attrnum)
+{
+  switch (attrnum)
+    {
+#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_AT
+#undef DWARF_ONE_KNOWN_DW_AT
+    default:
+      return NULL;
+    }
+}
+
+
+void
+handle (Dwarf *dbg, Dwarf_Die *die, int n)
+{
+  Dwarf_Die child;
+  unsigned int tag;
+  const char *str;
+  char buf[30];
+  const char *name;
+  Dwarf_Off off;
+  Dwarf_Off cuoff;
+  size_t cnt;
+  Dwarf_Addr addr;
+  int i;
+
+  tag = dwarf_tag (die);
+  if (tag != DW_TAG_invalid)
+    {
+      str = dwarf_tag_string (tag);
+      if (str == NULL)
+	{
+	  snprintf (buf, sizeof buf, "%#x", tag);
+	  str = buf;
+	}
+    }
+  else
+    str = "* NO TAG *";
+
+  name = dwarf_diename (die);
+  if (name == 0)
+    name = "* NO NAME *";
+
+  off = dwarf_dieoffset (die);
+  cuoff = dwarf_cuoffset (die);
+
+  printf ("%*sDW_TAG_%s\n", n * 5, "", str);
+  printf ("%*s Name      : %s\n", n * 5, "", name);
+  printf ("%*s Offset    : %lld\n", n * 5, "", (long long int) off);
+  printf ("%*s CU offset : %lld\n", n * 5, "", (long long int) cuoff);
+
+  printf ("%*s Attrs     :", n * 5, "");
+  for (cnt = 0; cnt < 0xffff; ++cnt)
+    if (dwarf_hasattr (die, cnt))
+      printf (" %s", dwarf_attr_string (cnt) ?: "<unknown>");
+  puts ("");
+
+  if (dwarf_hasattr (die, DW_AT_low_pc) && dwarf_lowpc (die, &addr) == 0)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Addr addr2;
+      printf ("%*s low PC    : %#llx\n",
+	      n * 5, "", (unsigned long long int) addr);
+
+      if (dwarf_attr (die, DW_AT_low_pc, &attr) == NULL
+	  || dwarf_formaddr (&attr, &addr2) != 0
+	  || addr != addr2)
+	puts ("************* DW_AT_low_pc verify failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_addr))
+	puts ("************* DW_AT_low_pc form failed ************");
+      else if (dwarf_whatform (&attr) != DW_FORM_addr)
+	puts ("************* DW_AT_low_pc form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_low_pc)
+	puts ("************* DW_AT_low_pc attr failed ************");
+    }
+  if (dwarf_hasattr (die, DW_AT_high_pc) && dwarf_highpc (die, &addr) == 0)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Addr addr2;
+      printf ("%*s high PC   : %#llx\n",
+	      n * 5, "", (unsigned long long int) addr);
+      if (dwarf_attr (die, DW_AT_high_pc, &attr) == NULL
+	  || dwarf_formaddr (&attr, &addr2) != 0
+	  || addr != addr2)
+	puts ("************* DW_AT_high_pc verify failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_addr))
+	puts ("************* DW_AT_high_pc form failed ************");
+      else if (dwarf_whatform (&attr) != DW_FORM_addr)
+	puts ("************* DW_AT_high_pc form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_high_pc)
+	puts ("************* DW_AT_high_pc attr failed ************");
+    }
+
+  if (dwarf_hasattr (die, DW_AT_byte_size) && (i = dwarf_bytesize (die)) != -1)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Word u2;
+      unsigned int u;
+      printf ("%*s byte size : %d\n", n * 5, "", i);
+      if (dwarf_attr (die, DW_AT_byte_size, &attr) == NULL
+	  || dwarf_formudata (&attr, &u2) != 0
+	  || i != (int) u2)
+	puts ("************* DW_AT_byte_size verify failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_data1)
+	       && ! dwarf_hasform (&attr, DW_FORM_data2)
+	       && ! dwarf_hasform (&attr, DW_FORM_data4)
+	       && ! dwarf_hasform (&attr, DW_FORM_data8)
+	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
+	       && ! dwarf_hasform (&attr, DW_FORM_udata))
+	puts ("************* DW_AT_byte_size form failed ************");
+      else if ((u = dwarf_whatform (&attr)) == 0
+	       || (u != DW_FORM_data1
+		   && u != DW_FORM_data2
+		   && u != DW_FORM_data4
+		   && u != DW_FORM_data8
+		   && u != DW_FORM_sdata
+		   && u != DW_FORM_udata))
+	puts ("************* DW_AT_byte_size form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_byte_size)
+	puts ("************* DW_AT_byte_size attr failed ************");
+    }
+  if (dwarf_hasattr (die, DW_AT_bit_size) && (i = dwarf_bitsize (die)) != -1)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Word u2;
+      unsigned int u;
+      printf ("%*s bit size  : %d\n", n * 5, "", i);
+      if (dwarf_attr (die, DW_AT_bit_size, &attr) == NULL
+	  || dwarf_formudata (&attr, &u2) != 0
+	  || i != (int) u2)
+	puts ("************* DW_AT_bit_size test failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_data1)
+	       && ! dwarf_hasform (&attr, DW_FORM_data2)
+	       && ! dwarf_hasform (&attr, DW_FORM_data4)
+	       && ! dwarf_hasform (&attr, DW_FORM_data8)
+	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
+	       && ! dwarf_hasform (&attr, DW_FORM_udata))
+	puts ("************* DW_AT_bit_size form failed ************");
+      else if ((u = dwarf_whatform (&attr)) == 0
+	       || (u != DW_FORM_data1
+		   && u != DW_FORM_data2
+		   && u != DW_FORM_data4
+		   && u != DW_FORM_data8
+		   && u != DW_FORM_sdata
+		   && u != DW_FORM_udata))
+	puts ("************* DW_AT_bit_size form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_bit_size)
+	puts ("************* DW_AT_bit_size attr failed ************");
+    }
+  if (dwarf_hasattr (die, DW_AT_bit_offset)
+      && (i = dwarf_bitoffset (die)) != -1)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Word u2;
+      unsigned int u;
+      printf ("%*s bit offset: %d\n", n * 5, "", i);
+      if (dwarf_attr (die, DW_AT_bit_offset, &attr) == NULL
+	  || dwarf_formudata (&attr, &u2) != 0
+	  || i != (int) u2)
+	puts ("************* DW_AT_bit_offset test failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_data1)
+	       && ! dwarf_hasform (&attr, DW_FORM_data2)
+	       && ! dwarf_hasform (&attr, DW_FORM_data4)
+	       && ! dwarf_hasform (&attr, DW_FORM_data8)
+	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
+	       && ! dwarf_hasform (&attr, DW_FORM_udata))
+	puts ("************* DW_AT_bit_offset form failed ************");
+      else if ((u = dwarf_whatform (&attr)) == 0
+	       || (u != DW_FORM_data1
+		   && u != DW_FORM_data2
+		   && u != DW_FORM_data4
+		   && u != DW_FORM_data8
+		   && u != DW_FORM_sdata
+		   && u != DW_FORM_udata))
+	puts ("************* DW_AT_bit_offset form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_bit_offset)
+	puts ("************* DW_AT_bit_offset attr failed ************");
+    }
+
+  if (dwarf_hasattr (die, DW_AT_language) && (i = dwarf_srclang (die)) != -1)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Word u2;
+      unsigned int u;
+      printf ("%*s language  : %d\n", n * 5, "", i);
+      if (dwarf_attr (die, DW_AT_language, &attr) == NULL
+	  || dwarf_formudata (&attr, &u2) != 0
+	  || i != (int) u2)
+	puts ("************* DW_AT_language test failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_data1)
+	       && ! dwarf_hasform (&attr, DW_FORM_data2)
+	       && ! dwarf_hasform (&attr, DW_FORM_data4)
+	       && ! dwarf_hasform (&attr, DW_FORM_data8)
+	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
+	       && ! dwarf_hasform (&attr, DW_FORM_udata))
+	puts ("************* DW_AT_language form failed ************");
+      else if ((u = dwarf_whatform (&attr)) == 0
+	       || (u != DW_FORM_data1
+		   && u != DW_FORM_data2
+		   && u != DW_FORM_data4
+		   && u != DW_FORM_data8
+		   && u != DW_FORM_sdata
+		   && u != DW_FORM_udata))
+	puts ("************* DW_AT_language form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_language)
+	puts ("************* DW_AT_language attr failed ************");
+    }
+
+  if (dwarf_hasattr (die, DW_AT_ordering)
+      && (i = dwarf_arrayorder (die)) != -1)
+    {
+      Dwarf_Attribute attr;
+      Dwarf_Word u2;
+      unsigned int u;
+      printf ("%*s ordering  : %d\n", n * 5, "", i);
+      if (dwarf_attr (die, DW_AT_ordering, &attr) == NULL
+	  || dwarf_formudata (&attr, &u2) != 0
+	  || i != (int) u2)
+	puts ("************* DW_AT_ordering test failed ************");
+      else if (! dwarf_hasform (&attr, DW_FORM_data1)
+	       && ! dwarf_hasform (&attr, DW_FORM_data2)
+	       && ! dwarf_hasform (&attr, DW_FORM_data4)
+	       && ! dwarf_hasform (&attr, DW_FORM_data8)
+	       && ! dwarf_hasform (&attr, DW_FORM_sdata)
+	       && ! dwarf_hasform (&attr, DW_FORM_udata))
+	puts ("************* DW_AT_ordering failed ************");
+      else if ((u = dwarf_whatform (&attr)) == 0
+	       || (u != DW_FORM_data1
+		   && u != DW_FORM_data2
+		   && u != DW_FORM_data4
+		   && u != DW_FORM_data8
+		   && u != DW_FORM_sdata
+		   && u != DW_FORM_udata))
+	puts ("************* DW_AT_ordering form (2) failed ************");
+      else if (dwarf_whatattr (&attr) != DW_AT_ordering)
+	puts ("************* DW_AT_ordering attr failed ************");
+    }
+
+  if (dwarf_hasattr (die, DW_AT_comp_dir))
+    {
+      Dwarf_Attribute attr;
+      if (dwarf_attr (die, DW_AT_comp_dir, &attr) == NULL
+	  || (name = dwarf_formstring (&attr)) == NULL)
+	puts ("************* DW_AT_comp_dir attr failed ************");
+      else
+	printf ("%*s directory : %s\n", n * 5, "", name);
+    }
+
+  if (dwarf_hasattr (die, DW_AT_producer))
+    {
+      Dwarf_Attribute attr;
+      if (dwarf_attr (die, DW_AT_producer, &attr) == NULL
+	  || (name = dwarf_formstring (&attr)) == NULL)
+	puts ("************* DW_AT_comp_dir attr failed ************");
+      else
+	printf ("%*s producer  : %s\n", n * 5, "", name);
+    }
+
+  if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
+    handle (dbg, &child, n + 1);
+  if (dwarf_siblingof (die, die) == 0)
+    handle (dbg, die, n);
+}
+
+
+int
+main (int argc, char *argv[])
+{
+ int cnt;
+
+  for (cnt = 1; cnt < argc; ++cnt)
+    {
+      int fd = open (argv[cnt], O_RDONLY);
+      Dwarf *dbg;
+
+      printf ("file: %s\n", xbasename (argv[cnt]));
+
+      dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable\n", argv[cnt]);
+	  close (fd);
+	  continue;
+	}
+
+      Dwarf_Off off = 0;
+      Dwarf_Off old_off = 0;
+      size_t hsize;
+      Dwarf_Off abbrev;
+      uint8_t addresssize;
+      uint8_t offsetsize;
+      while (dwarf_nextcu (dbg, off, &off, &hsize, &abbrev, &addresssize,
+			   &offsetsize) == 0)
+	{
+	  printf ("New CU: off = %llu, hsize = %zu, ab = %llu, as = %" PRIu8
+		  ", os = %" PRIu8 "\n",
+		  (unsigned long long int) old_off, hsize,
+		  (unsigned long long int) abbrev, addresssize,
+		  offsetsize);
+
+	  Dwarf_Die die;
+	  if (dwarf_offdie (dbg, old_off + hsize, &die) != NULL)
+	    handle (dbg, &die, 1);
+
+	  old_off = off;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+    }
+
+  return 0;
+}
diff --git a/tests/showptable.c b/tests/showptable.c
new file mode 100644
index 0000000..a794b0e
--- /dev/null
+++ b/tests/showptable.c
@@ -0,0 +1,139 @@
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 1998.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+main (int argc, char *argv[])
+{
+  Elf *elf;
+  int fd;
+  GElf_Ehdr ehdr;
+  int cnt;
+
+  if (argc < 2)
+    {
+      puts ("missing parameter");
+      exit (1);
+    }
+
+  fd = open (argv[1], O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open \"%s\": %s\n", argv[1], strerror (errno));
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot open ELF file: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_kind (elf) != ELF_K_ELF)
+    {
+      printf ("\"%s\" is not an ELF file\n", argv[1]);
+      exit (1);
+    }
+
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    {
+      printf ("cannot get the ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  printf ("idx type    %*s %*s %*s %*s %*s  align flags\n",
+	  gelf_getclass (elf) == ELFCLASS32 ? 9 : 17, "offset",
+	  gelf_getclass (elf) == ELFCLASS32 ? 10 : 18, "vaddr",
+	  gelf_getclass (elf) == ELFCLASS32 ? 10 : 18, "paddr",
+	  gelf_getclass (elf) == ELFCLASS32 ? 9 : 12, "filesz",
+	  gelf_getclass (elf) == ELFCLASS32 ? 9 : 12, "memsz");
+
+  for (cnt = 0; cnt < ehdr.e_phnum; ++cnt)
+    {
+      static const char *typenames[] =
+      {
+	[PT_NULL] = "NULL",
+	[PT_LOAD] = "LOAD",
+	[PT_DYNAMIC] = "DYNAMIC",
+	[PT_INTERP] = "INTERP",
+	[PT_NOTE] = "NOTE",
+	[PT_SHLIB] = "SHLIB",
+	[PT_PHDR] = "PHDR"
+      };
+      GElf_Phdr mem;
+      GElf_Phdr *phdr = gelf_getphdr (elf, cnt, &mem);
+      char buf[19];
+      const char *p_type = typenames[phdr->p_type];
+
+      /* If we don't know the name of the type we use the number value.  */
+      if (phdr->p_type >= PT_NUM)
+	{
+	  snprintf (buf, sizeof (buf), "%x", phdr->p_type);
+	  p_type = buf;
+	}
+
+      printf ("%3d %-7s %#0*llx %#0*llx %#0*llx %#0*llx %#0*llx %#6llx ",
+	      cnt, p_type,
+	      gelf_getclass (elf) == ELFCLASS32 ? 9 : 17,
+	      (unsigned long long int) phdr->p_offset,
+	      gelf_getclass (elf) == ELFCLASS32 ? 10 : 18,
+	      (unsigned long long int) phdr->p_vaddr,
+	      gelf_getclass (elf) == ELFCLASS32 ? 10 : 18,
+	      (unsigned long long int) phdr->p_paddr,
+	      gelf_getclass (elf) == ELFCLASS32 ? 9 : 12,
+	      (unsigned long long int) phdr->p_filesz,
+	      gelf_getclass (elf) == ELFCLASS32 ? 9 : 12,
+	      (unsigned long long int) phdr->p_memsz,
+	      (unsigned long long int) phdr->p_align);
+
+      putc_unlocked ((phdr->p_flags & PF_X) ? 'X' : ' ', stdout);
+      putc_unlocked ((phdr->p_flags & PF_W) ? 'W' : ' ', stdout);
+      putc_unlocked ((phdr->p_flags & PF_R) ? 'R' : ' ', stdout);
+
+      putc_unlocked ('\n', stdout);
+
+      if (phdr->p_type == PT_INTERP)
+	{
+	  /* We can show the user the name of the interpreter.  */
+	  size_t maxsize;
+	  char *filedata = elf_rawfile (elf, &maxsize);
+
+	  if (filedata != NULL && phdr->p_offset < maxsize)
+	    printf ("\t[Requesting program interpreter: %s]\n",
+		    filedata + phdr->p_offset);
+	}
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("error while freeing ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  return 0;
+}
diff --git a/tests/splitdwarf4-not-split4.dwo.bz2 b/tests/splitdwarf4-not-split4.dwo.bz2
new file mode 100644
index 0000000..4346b2e
--- /dev/null
+++ b/tests/splitdwarf4-not-split4.dwo.bz2
Binary files differ
diff --git a/tests/strip-reloc-subr.sh b/tests/strip-reloc-subr.sh
new file mode 100755
index 0000000..c4d55ce
--- /dev/null
+++ b/tests/strip-reloc-subr.sh
@@ -0,0 +1,79 @@
+#! /bin/sh
+# Copyright (C) 2011, 2013 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+. $srcdir/test-subr.sh
+
+if test -n "$ELFUTILS_MEMORY_SANITIZER"; then
+  echo "binaries linked with memory sanitizer are too big"
+  exit 77
+fi
+
+tempfiles readelf.out1 readelf.out2
+tempfiles out.stripped1 out.debug1 out.stripped2 out.debug2
+
+runtest_status=0
+runtest() {
+  infile=$1
+  is_ET_REL=$2
+  outfile1=out.stripped1
+  debugfile1=out.debug1
+  outfile2=out.stripped2
+  debugfile2=out.debug2
+
+  echo "runtest $infile"
+
+  rm -f $outfile1 $debugfile1 $outfile2 $debugfile2
+
+  testrun ${abs_top_builddir}/src/strip -o $outfile1 -f $debugfile1 $infile ||
+  { echo "*** failure strip $infile"; runtest_status=1; }
+
+  testrun ${abs_top_builddir}/src/strip --reloc-debug-sections -o $outfile2 \
+	-f $debugfile2 $infile ||
+  { echo "*** failure strip --reloc-debug-sections $infile"; runtest_status=1; }
+
+  testrun ${abs_top_builddir}/src/elfcmp $outfile1 $outfile2 ||
+  { echo "*** failure compare stripped files $infile"; runtest_status=1; }
+
+  # debug files however should be smaller, when ET_REL.
+  SIZE1=$(stat -c%s $debugfile1)
+  SIZE2=$(stat -c%s $debugfile2)
+  test \( \( $is_ET_REL -eq 1 \) -a \( $SIZE1 -gt $SIZE2 \) \) \
+	-o \( \( $is_ET_REL -eq 0 \) -a \( $SIZE1 -eq $SIZE2 \) \) ||
+  { echo "*** failure --reloc-debug-sections not smaller $infile"; runtest_status=1; }
+
+  # Strip of DWARF section lines, offset will not match.
+  # Everything else should match.
+  testrun ${abs_top_builddir}/src/readelf -N -w $debugfile1 \
+	| grep -v ^DWARF\ section > readelf.out1 ||
+  { echo "*** failure readelf -N -w debugfile1 $infile"; runtest_status=1; }
+
+  testrun ${abs_top_builddir}/src/readelf -N -w $debugfile2 \
+	| grep -v ^DWARF\ section > readelf.out2 ||
+  { echo "*** failure readelf -N -w debugfile2 $infile"; runtest_status=1; }
+
+  testrun_compare cat readelf.out1 < readelf.out2 ||
+  { echo "*** failure readelf -N -w compare $infile"; runtest_status=1; }
+
+  testrun ${abs_top_builddir}/src/strip --reloc-debug-sections-only \
+	  $debugfile1 ||
+  { echo "*** failure strip --reloc-debug-sections-only $debugfile1"; \
+    runtest_status=1; }
+
+  cmp $debugfile1 $debugfile2 ||
+  { echo "*** failure --reloc-debug-sections[-only] $debugfile1 $debugfile2"; \
+    runtest_status=1; }
+}
diff --git a/tests/strptr.c b/tests/strptr.c
new file mode 100644
index 0000000..759664a
--- /dev/null
+++ b/tests/strptr.c
@@ -0,0 +1,95 @@
+/* Test program for elf_strptr function.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 2)
+    {
+      printf ("No ELF file given as argument");
+      exit (1);
+    }
+
+  const char *fname = argv[1];
+
+  // Initialize libelf.
+  elf_version (EV_CURRENT);
+
+  /* Read the ELF from disk now.  */
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  size_t ndx;
+  if (elf_getshdrstrndx (elf, &ndx) != 0)
+    {
+      printf ("cannot get section header table index: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (ndx == SHN_UNDEF)
+    {
+      printf ("ELF file `%s' doesn't have a section header table index", fname);
+      exit (1);
+    }
+
+  printf ("Strings in section %zd:\n", ndx);
+
+  size_t off = 0;
+  const char *str = elf_strptr (elf, ndx, off);
+  while (str != NULL)
+    {
+      printf ("[%zx] '%s'\n", off, str);
+      off += strlen (str) + 1;
+      str = elf_strptr (elf, ndx, off);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/system-elf-gelf-test.c b/tests/system-elf-gelf-test.c
new file mode 100644
index 0000000..5a0e4e7
--- /dev/null
+++ b/tests/system-elf-gelf-test.c
@@ -0,0 +1,36 @@
+/* Explicit test compiling with system elf.h header plus libelf/gelf headers.
+
+   Copyright (C) Mark J. Wielaard <mark@klomp.org>
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <stddef.h>
+#include "../libelf/libelf.h"
+#include "../libelf/gelf.h"
+
+int
+main (void)
+{
+  /* Trivial test, this is really a compile test anyway.  */
+  if (elf_version (EV_CURRENT) == EV_NONE)
+    return -1;
+
+  /* This will obviously fail. It is just to check that gelf_getclass
+     available (both at compile time and runtime).  */
+  int cls = gelf_getclass (NULL);
+
+  return cls == ELFCLASSNONE ? 0 : -1;
+}
diff --git a/tests/system-elf-libelf-test.c b/tests/system-elf-libelf-test.c
new file mode 100644
index 0000000..7dfe498
--- /dev/null
+++ b/tests/system-elf-libelf-test.c
@@ -0,0 +1,35 @@
+/* Explicit test compiling with system elf.h header plus libelf header.
+
+   Copyright (C) 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <elf.h>
+#include <stddef.h>
+#include "../libelf/libelf.h"
+
+int
+main (void)
+{
+  /* Trivial test, this is really a compile test anyway.  */
+  if (elf_version (EV_CURRENT) == EV_NONE)
+    return -1;
+
+  /* This will obviously fail. It is just to check that Elf32_Chdr and
+     elf32_getchdr are available (both at compile time and runtime).  */
+  Elf32_Chdr *chdr = elf32_getchdr (NULL);
+
+  return chdr == NULL ? 0 : -1;
+}
diff --git a/tests/test-ar-duplicates.a.bz2 b/tests/test-ar-duplicates.a.bz2
new file mode 100644
index 0000000..e8168c6
--- /dev/null
+++ b/tests/test-ar-duplicates.a.bz2
Binary files differ
diff --git a/tests/test-copymany-subr.sh b/tests/test-copymany-subr.sh
new file mode 100755
index 0000000..054103b
--- /dev/null
+++ b/tests/test-copymany-subr.sh
@@ -0,0 +1,62 @@
+#! /bin/sh
+# Copyright (C) 2018 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+# Same as run-copyadd-sections.sh, but for many > 0xffff sections.
+# Doesn't use mmap for addsections since that doesn't work.
+# ELF_C_RDWR_MMAP needs mremap which will fail since it needs too 
+# much space and the original mmap cannot move.
+
+. $srcdir/test-subr.sh
+
+test_copy_and_add ()
+{
+  in_file="$1"
+  out_file="${in_file}.copy"
+  out_file_mmap="${out_file}.mmap"
+
+  tempfiles ${out_file} ${out_file_mmap} readelf.out
+
+  # Can we copy the file?
+  testrun ${abs_builddir}/elfcopy ${in_file} ${out_file}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file}
+
+  # Can we add a section (in-place)?
+  testrun ${abs_builddir}/addsections 32768 ${out_file}
+  testrun ${abs_top_builddir}/src/readelf -S ${out_file} > readelf.out
+  nr=$(grep '.extra' readelf.out | wc -l)
+  # We try twice...
+  if test ${nr} != 32768 -a ${nr} != 65536; then
+    # Show what went wrong
+    echo nr: ${nr}
+    testrun ${abs_top_builddir}/src/readelf -S ${out_file}
+    exit 1
+  fi
+
+  # Can we copy the file using ELF_C_WRITE_MMAP?
+  testrun ${abs_builddir}/elfcopy --mmap ${in_file} ${out_file_mmap}
+  testrun ${abs_top_builddir}/src/elfcmp ${in_file} ${out_file_mmap}
+
+  # Don't try to add using mmap (see above)
+}
+
+# A collection of random testfiles to test 32/64bit, little/big endian
+# and non-ET_REL (with phdrs)/ET_REL (without phdrs).
+# Try to add 0x0fff sections twice.
+
+# Separated out into subtests
+# run-copymany-be32.sh run-copymany-be64.sh
+# run-copymany-le32.sh run-copymany-le64.sh
diff --git a/tests/test-core-lib.so.bz2 b/tests/test-core-lib.so.bz2
new file mode 100755
index 0000000..bb2da88
--- /dev/null
+++ b/tests/test-core-lib.so.bz2
Binary files differ
diff --git a/tests/test-core.core.bz2 b/tests/test-core.core.bz2
new file mode 100644
index 0000000..4d4346b
--- /dev/null
+++ b/tests/test-core.core.bz2
Binary files differ
diff --git a/tests/test-core.exec.bz2 b/tests/test-core.exec.bz2
new file mode 100755
index 0000000..49ce551
--- /dev/null
+++ b/tests/test-core.exec.bz2
Binary files differ
diff --git a/tests/test-elf_cntl_gelf_getshdr.c b/tests/test-elf_cntl_gelf_getshdr.c
new file mode 100644
index 0000000..7371110
--- /dev/null
+++ b/tests/test-elf_cntl_gelf_getshdr.c
@@ -0,0 +1,107 @@
+/* Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <fcntl.h>
+#include <gelf.h>
+#include <libelf.h>
+#include <stdbool.h>
+#include <inttypes.h>
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 3)
+    {
+      fprintf (stderr, "Needs two arguments.\n");
+      fprintf (stderr, "First needs to be 'READ', 'MMAP' or 'FDREAD'\n");
+      fprintf (stderr, "Second is the ELF file to read.\n");
+      exit (2); /* user error */
+    }
+
+  bool do_mmap = false;
+  bool close_fd = false;
+  if (strcmp (argv[1], "READ") == 0)
+    {
+      do_mmap = false;
+      close_fd = false;
+    }
+  else if (strcmp (argv[1], "MMAP") == 0)
+    {
+      do_mmap = true;
+      close_fd = false;
+    }
+  else if  (strcmp (argv[1], "FDREAD") == 0)
+    {
+      do_mmap = false;
+      close_fd = true;
+    }
+  else
+    {
+      fprintf (stderr, "First arg needs to be 'READ', 'MMAP' or 'FDREAD'\n");
+      exit (2); /* user error */
+    }
+
+  elf_version (EV_CURRENT);
+
+  int fd = open (argv[2], O_RDONLY);
+  if (fd < 0)
+    {
+      fprintf (stderr, "Cannot open input file %s: %s\n", argv[2],
+	       strerror (errno));
+      exit (2);
+    }
+
+  Elf *elf = elf_begin (fd, do_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      fprintf (stderr, "elf_begin failed for %s: %s\n", argv[2],
+	       elf_errmsg (-1));
+      exit (2);
+    }
+
+  if (! do_mmap && close_fd)
+    {
+      if (elf_cntl (elf, ELF_C_FDREAD) < 0)
+	{
+	  fprintf (stderr, "elf_cntl failed for %s: %s\n", argv[2],
+		   elf_errmsg (-1));
+	  exit (1);
+	}
+      close (fd);
+    }
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      GElf_Shdr shdr_mem;
+      GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+      printf ("Section at offset %#0" PRIx64 "\n", shdr->sh_offset);
+    }
+
+  elf_end (elf);
+  exit (0);
+}
diff --git a/tests/test-flag-nobits.c b/tests/test-flag-nobits.c
new file mode 100644
index 0000000..15d44ea
--- /dev/null
+++ b/tests/test-flag-nobits.c
@@ -0,0 +1,42 @@
+/* Copyright (C) 2010 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <gelf.h>
+
+int
+main (int argc, char **argv)
+{
+  if (argc != 2)
+    abort ();
+
+  elf_version (EV_CURRENT);
+
+  int fd = open (argv[1], O_RDONLY);
+  Elf *stripped = elf_begin (fd, ELF_C_READ, NULL);
+
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (stripped, scn)) != NULL)
+    elf_flagdata (elf_getdata (scn, NULL), ELF_C_SET, ELF_F_DIRTY);
+
+  elf_end (stripped);
+  return 0;
+}
diff --git a/tests/test-nlist.c b/tests/test-nlist.c
new file mode 100644
index 0000000..679c911
--- /dev/null
+++ b/tests/test-nlist.c
@@ -0,0 +1,83 @@
+/* Copyright (C) 2000, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <nlist.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+
+int var = 1;
+
+int bss;
+
+
+int
+foo (int a)
+{
+  return a;
+}
+
+int
+main (int argc, char *argv[] __attribute__ ((unused)))
+{
+  struct nlist nl[6] =
+  {
+    [0] = { .n_name = "var" },
+    [1] = { .n_name = "bss" },
+    [2] = { .n_name = "main" },
+    [3] = { .n_name = "foo" },
+    [4] = { .n_name = "not-there" },
+    [5] = { .n_name = NULL },
+  };
+  int cnt;
+  int result = 0;
+
+  if (nlist (".libs/test-nlist", nl) != 0
+      && nlist ("./test-nlist", nl) != 0)
+    {
+      puts ("nlist failed");
+      exit (1);
+    }
+
+  for (cnt = 0; nl[cnt].n_name != NULL; ++cnt)
+    {
+      if (argc > 1)
+	/* For debugging.  */
+	printf ("nl[%d].n_name = \"%s\"\n"
+		"nl[%d].n_value = %ld\n"
+		"nl[%d].n_scnum = %d\n"
+		"nl[%d].n_type = %u\n"
+		"nl[%d].n_sclass = %d\n"
+		"nl[%d].n_numaux = %d\n\n",
+		cnt, nl[cnt].n_name,
+		cnt, nl[cnt].n_value,
+		cnt, nl[cnt].n_scnum,
+		cnt, nl[cnt].n_type,
+		cnt, nl[cnt].n_sclass,
+		cnt, nl[cnt].n_numaux);
+
+      if ((cnt != 4 && nl[cnt].n_value == 0 && nl[cnt].n_scnum == 0
+	   && nl[cnt].n_type == 0 && nl[cnt].n_sclass == 0
+	   && nl[cnt].n_numaux == 0)
+	  || (cnt == 4 && (nl[cnt].n_value != 0 || nl[cnt].n_scnum != 0
+			   || nl[cnt].n_type != 0 || nl[cnt].n_sclass != 0
+			   || nl[cnt].n_numaux != 0)))
+	result = 1;
+    }
+
+  return foo (result);
+}
diff --git a/tests/test-offset-loop.alt.bz2 b/tests/test-offset-loop.alt.bz2
new file mode 100644
index 0000000..c1906b6
--- /dev/null
+++ b/tests/test-offset-loop.alt.bz2
Binary files differ
diff --git a/tests/test-offset-loop.bz2 b/tests/test-offset-loop.bz2
new file mode 100755
index 0000000..62185c0
--- /dev/null
+++ b/tests/test-offset-loop.bz2
Binary files differ
diff --git a/tests/test-subr.sh b/tests/test-subr.sh
new file mode 100644
index 0000000..411e5f2
--- /dev/null
+++ b/tests/test-subr.sh
@@ -0,0 +1,214 @@
+#! /bin/sh
+# Copyright (C) 2005-2015, 2017 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# This file is sourced by ". $srcdir/test-subr.sh" at the start of
+# each test script.  It defines some functions they use and sets up
+# canonical sh state for test runs.
+
+set -e
+
+# Each test runs in its own directory to make sure they can run in parallel.
+test_dir="test-$$"
+mkdir -p "$test_dir"
+cd "$test_dir"
+
+#LC_ALL=C
+#export LC_ALL
+
+remove_files=
+
+# Tests that trap EXIT (0) themselves should call this explicitly.
+exit_cleanup()
+{
+  rm -f $remove_files; cd ..; rmdir $test_dir
+}
+trap exit_cleanup 0
+
+tempfiles()
+{
+  remove_files="$remove_files $*"
+}
+
+testfiles()
+{
+  for file; do
+    bunzip2 -c ${abs_srcdir}/${file}.bz2 > ${file} || exit 77
+    remove_files="$remove_files $file"
+  done
+}
+
+testrun_out()
+{
+  outfile="$1"
+  shift
+  remove_files="$remove_files $outfile"
+  testrun "$@" > $outfile 2>&1 || :
+}
+
+testrun_compare()
+{
+  outfile="${1##*/}.out"
+  testrun_out $outfile "$@"
+  diff -u $outfile -
+  # diff's exit status will kill the script.
+}
+
+test_cleanup()
+{
+  rm -f $remove_files
+  remove_files=
+}
+
+# See test-wrapper.sh, which sets the environment for this.
+testrun()
+{
+  ${elfutils_testrun}_testrun "$@"
+}
+
+built_testrun()
+{
+  LD_LIBRARY_PATH="${built_library_path}${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"\
+  $VALGRIND_CMD "$@"
+}
+
+installed_testrun()
+{
+  program="$1"
+  shift
+  case "$program" in
+  ${abs_builddir}/*)
+    if [ "x$elfutils_tests_rpath" != xno ]; then
+      echo >&2 installcheck not possible with --enable-tests-rpath
+      exit 77
+    fi
+    ;;
+  ${abs_top_builddir}/src/*)
+    program=${bindir}/`program_transform ${program##*/}`
+    ;;
+  esac
+  if [ "${libdir}" != /usr/lib ] && [ "${libdir}" != /usr/lib64 ]; then
+    LD_LIBRARY_PATH="${libdir}:${libdir}/elfutils\
+${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH" \
+    $VALGRIND_CMD $program ${1+"$@"}
+  else
+    $VALGRIND_CMD $program ${1+"$@"}
+  fi
+}
+
+program_transform()
+{
+  echo "$*" | sed "${program_transform_name}"
+}
+
+self_test_files_exe=`echo ${abs_top_builddir}/src/addr2line \
+${abs_top_builddir}/src/elfclassify \
+${abs_top_builddir}/src/stack \
+${abs_top_builddir}/src/unstrip`
+
+self_test_files_lib=`echo ${abs_top_builddir}/libelf/libelf.so \
+${abs_top_builddir}/libasm/libasm.so`
+
+self_test_files_obj=`echo ${abs_top_builddir}/src/size.o \
+${abs_top_builddir}/src/strip.o`
+
+self_test_files="$self_test_files_exe $self_test_files_lib $self_test_files_obj"
+
+# Provide a command to run on all self-test files with testrun.
+testrun_on_self()
+{
+  exit_status=0
+
+  for file in $self_test_files; do
+      testrun $* $file \
+	  || { echo "*** failure in $* $file"; exit_status=1; }
+  done
+
+  # Only exit if something failed
+  if test $exit_status != 0; then exit $exit_status; fi
+}
+
+testrun_on_self_exe()
+{
+  exit_status=0
+
+  for file in $self_test_files_exe; do
+      testrun $* $file \
+	  || { echo "*** failure in $* $file"; exit_status=1; }
+  done
+
+  # Only exit if something failed
+  if test $exit_status != 0; then exit $exit_status; fi
+}
+
+testrun_on_self_lib()
+{
+  exit_status=0
+
+  for file in $self_test_files_lib; do
+      testrun $* $file \
+	  || { echo "*** failure in $* $file"; exit_status=1; }
+  done
+
+  # Only exit if something failed
+  if test $exit_status != 0; then exit $exit_status; fi
+}
+
+testrun_on_self_obj()
+{
+  exit_status=0
+
+  for file in $self_test_files_obj; do
+      testrun $* $file \
+	  || { echo "*** failure in $* $file"; exit_status=1; }
+  done
+
+  # Only exit if something failed
+  if test $exit_status != 0; then exit $exit_status; fi
+}
+
+# Compress the files first. Compress both debug sections and symtab.
+testrun_on_self_compressed()
+{
+  exit_status=0
+
+  for file in $self_test_files; do
+      tempfiles ${file}z
+      testrun ${abs_top_builddir}/src/elfcompress -f -q -o ${file}z ${file}
+      testrun ${abs_top_builddir}/src/elfcompress -f -q --name='.s??tab' ${file}z
+
+      testrun $* ${file}z \
+	  || { echo "*** failure in $* ${file}z"; exit_status=1; }
+  done
+
+  # Only exit if something failed
+  if test $exit_status != 0; then exit $exit_status; fi
+}
+
+# Same as above, but redirects stdout to /dev/null
+testrun_on_self_quiet()
+{
+  exit_status=0
+
+  for file in $self_test_files; do
+      testrun $* $file > /dev/null \
+	  || { echo "*** failure in $* $file"; exit_status=1; }
+  done
+
+  # Only exit if something failed
+  if test $exit_status != 0; then exit $exit_status; fi
+}
diff --git a/tests/test-wrapper.sh b/tests/test-wrapper.sh
new file mode 100755
index 0000000..c5d3f15
--- /dev/null
+++ b/tests/test-wrapper.sh
@@ -0,0 +1,73 @@
+#! /bin/sh
+# Copyright (C) 2005-2012 Red Hat, Inc.
+# This file is part of elfutils.
+#
+# This file is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# elfutils is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+# We don't compile in an rpath because we want "make installcheck" to
+# use the installed libraries.  So for local test runs we need to point
+# the library path at this build.
+
+# This wrapper script is called by the makefile, in one of two ways:
+#	$(srcdir)/test-wrapper.sh ../libelf:... run-test.sh ...
+# or:
+#	$(srcdir)/test-wrapper.sh installed s,^,eu-, run-test.sh ...
+
+if [ "$1" = installed ]; then
+  shift
+  elfutils_tests_rpath=$1
+  shift
+  program_transform_name="$1"
+  shift
+  elfutils_testrun=installed
+else
+  built_library_path="$1"
+  shift
+  elfutils_testrun=built
+fi
+
+old_path="${LD_LIBRARY_PATH:+:}$LD_LIBRARY_PATH"
+
+case "$1" in
+*.sh)
+  export built_library_path program_transform_name elfutils_testrun
+  export elfutils_tests_rpath
+  is_shell_script="yes"
+  ;;
+*)
+  if [ $elfutils_testrun = built ]; then
+    LD_LIBRARY_PATH="$built_library_path$old_path"
+  elif [ $elfutils_tests_rpath = yes ]; then
+    echo >&2 installcheck not possible with --enable-tests-rpath
+    exit 77
+  elif [ "x$libdir" != x/usr/lib ] && [ "x$libdir" != x/usr/lib64 ]; then
+    LD_LIBRARY_PATH="${libdir}:${libdir}/elfutils$old_path"
+  fi
+  export LD_LIBRARY_PATH
+  is_shell_script="no"
+  ;;
+esac
+
+if [ "x$VALGRIND_CMD" != "x" ]; then
+  export VALGRIND_CMD
+fi
+
+# When it is a run-*.sh script the VALGRIND_CMD will be passed on
+# otherwise we'll need to run the binary explicitly under valgrind.
+if [ "x$is_shell_script" = xyes ]; then
+  exec "$@"
+else
+  exec $VALGRIND_CMD "$@"
+fi
diff --git a/tests/testarchive64.a.bz2 b/tests/testarchive64.a.bz2
new file mode 100644
index 0000000..4b54603
--- /dev/null
+++ b/tests/testarchive64.a.bz2
Binary files differ
diff --git a/tests/testcore-noncontig.bz2 b/tests/testcore-noncontig.bz2
new file mode 100644
index 0000000..514ad01
--- /dev/null
+++ b/tests/testcore-noncontig.bz2
Binary files differ
diff --git a/tests/testcore-rtlib-ppc.bz2 b/tests/testcore-rtlib-ppc.bz2
new file mode 100644
index 0000000..a3cec60
--- /dev/null
+++ b/tests/testcore-rtlib-ppc.bz2
Binary files differ
diff --git a/tests/testcore-rtlib.bz2 b/tests/testcore-rtlib.bz2
new file mode 100644
index 0000000..1dc0f1a
--- /dev/null
+++ b/tests/testcore-rtlib.bz2
Binary files differ
diff --git a/tests/testfile-ada-variant.bz2 b/tests/testfile-ada-variant.bz2
new file mode 100644
index 0000000..459774d
--- /dev/null
+++ b/tests/testfile-ada-variant.bz2
Binary files differ
diff --git a/tests/testfile-addrx_constx-4.bz2 b/tests/testfile-addrx_constx-4.bz2
new file mode 100755
index 0000000..cf10fbb
--- /dev/null
+++ b/tests/testfile-addrx_constx-4.bz2
Binary files differ
diff --git a/tests/testfile-addrx_constx-5.bz2 b/tests/testfile-addrx_constx-5.bz2
new file mode 100755
index 0000000..eb2a1f1
--- /dev/null
+++ b/tests/testfile-addrx_constx-5.bz2
Binary files differ
diff --git a/tests/testfile-annobingroup-i386.o.bz2 b/tests/testfile-annobingroup-i386.o.bz2
new file mode 100644
index 0000000..798eefd
--- /dev/null
+++ b/tests/testfile-annobingroup-i386.o.bz2
Binary files differ
diff --git a/tests/testfile-annobingroup-x86_64.o.bz2 b/tests/testfile-annobingroup-x86_64.o.bz2
new file mode 100644
index 0000000..ec389db
--- /dev/null
+++ b/tests/testfile-annobingroup-x86_64.o.bz2
Binary files differ
diff --git a/tests/testfile-annobingroup.o.bz2 b/tests/testfile-annobingroup.o.bz2
new file mode 100644
index 0000000..b1ca7ea
--- /dev/null
+++ b/tests/testfile-annobingroup.o.bz2
Binary files differ
diff --git a/tests/testfile-arm-flags.bz2 b/tests/testfile-arm-flags.bz2
new file mode 100755
index 0000000..d1b018a
--- /dev/null
+++ b/tests/testfile-arm-flags.bz2
Binary files differ
diff --git a/tests/testfile-backtrace-demangle.bz2 b/tests/testfile-backtrace-demangle.bz2
new file mode 100755
index 0000000..f0294df
--- /dev/null
+++ b/tests/testfile-backtrace-demangle.bz2
Binary files differ
diff --git a/tests/testfile-backtrace-demangle.cc b/tests/testfile-backtrace-demangle.cc
new file mode 100644
index 0000000..27fff68
--- /dev/null
+++ b/tests/testfile-backtrace-demangle.cc
@@ -0,0 +1,47 @@
+/* Test program for C++ demangled unwinding.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
+#define NOINLINE_NOCLONE __attribute__ ((noinline, noclone))
+#else
+#define NOINLINE_NOCLONE __attribute__ ((noinline))
+#endif
+
+void NOINLINE_NOCLONE
+cxxfunc (int i)
+{
+  *(volatile int *)0=0;
+  // Avoid tail call optimization.
+  asm volatile ("");
+}
+
+extern "C"
+{
+  void NOINLINE_NOCLONE
+  f (void)
+  {
+    cxxfunc(1);
+    // Avoid tail call optimization.
+    asm volatile ("");
+  }
+}
+
+int
+main()
+{
+  f();
+}
diff --git a/tests/testfile-backtrace-demangle.core.bz2 b/tests/testfile-backtrace-demangle.core.bz2
new file mode 100644
index 0000000..263c304
--- /dev/null
+++ b/tests/testfile-backtrace-demangle.core.bz2
Binary files differ
diff --git a/tests/testfile-bpf-dis1.expect.bz2 b/tests/testfile-bpf-dis1.expect.bz2
new file mode 100644
index 0000000..61a8afb
--- /dev/null
+++ b/tests/testfile-bpf-dis1.expect.bz2
Binary files differ
diff --git a/tests/testfile-bpf-dis1.o.bz2 b/tests/testfile-bpf-dis1.o.bz2
new file mode 100644
index 0000000..94bb612
--- /dev/null
+++ b/tests/testfile-bpf-dis1.o.bz2
Binary files differ
diff --git a/tests/testfile-bpf-reloc.expect.bz2 b/tests/testfile-bpf-reloc.expect.bz2
new file mode 100644
index 0000000..0ff8cc4
--- /dev/null
+++ b/tests/testfile-bpf-reloc.expect.bz2
Binary files differ
diff --git a/tests/testfile-bpf-reloc.o.bz2 b/tests/testfile-bpf-reloc.o.bz2
new file mode 100644
index 0000000..295634f
--- /dev/null
+++ b/tests/testfile-bpf-reloc.o.bz2
Binary files differ
diff --git a/tests/testfile-const-values.debug.bz2 b/tests/testfile-const-values.debug.bz2
new file mode 100755
index 0000000..167da16
--- /dev/null
+++ b/tests/testfile-const-values.debug.bz2
Binary files differ
diff --git a/tests/testfile-debug-rel-g.o.bz2 b/tests/testfile-debug-rel-g.o.bz2
new file mode 100644
index 0000000..b8c94e7
--- /dev/null
+++ b/tests/testfile-debug-rel-g.o.bz2
Binary files differ
diff --git a/tests/testfile-debug-rel-ppc64-g.o.bz2 b/tests/testfile-debug-rel-ppc64-g.o.bz2
new file mode 100644
index 0000000..8c5ec99
--- /dev/null
+++ b/tests/testfile-debug-rel-ppc64-g.o.bz2
Binary files differ
diff --git a/tests/testfile-debug-rel-ppc64-z.o.bz2 b/tests/testfile-debug-rel-ppc64-z.o.bz2
new file mode 100644
index 0000000..df50465
--- /dev/null
+++ b/tests/testfile-debug-rel-ppc64-z.o.bz2
Binary files differ
diff --git a/tests/testfile-debug-rel-ppc64.o.bz2 b/tests/testfile-debug-rel-ppc64.o.bz2
new file mode 100644
index 0000000..8340d0c
--- /dev/null
+++ b/tests/testfile-debug-rel-ppc64.o.bz2
Binary files differ
diff --git a/tests/testfile-debug-rel-z.o.bz2 b/tests/testfile-debug-rel-z.o.bz2
new file mode 100644
index 0000000..1cdac79
--- /dev/null
+++ b/tests/testfile-debug-rel-z.o.bz2
Binary files differ
diff --git a/tests/testfile-debug-rel.o.bz2 b/tests/testfile-debug-rel.o.bz2
new file mode 100644
index 0000000..a3f8dff
--- /dev/null
+++ b/tests/testfile-debug-rel.o.bz2
Binary files differ
diff --git a/tests/testfile-debug-types.bz2 b/tests/testfile-debug-types.bz2
new file mode 100755
index 0000000..a41f493
--- /dev/null
+++ b/tests/testfile-debug-types.bz2
Binary files differ
diff --git a/tests/testfile-debug.bz2 b/tests/testfile-debug.bz2
new file mode 100755
index 0000000..88e59de
--- /dev/null
+++ b/tests/testfile-debug.bz2
Binary files differ
diff --git a/tests/testfile-dw-form-indirect.bz2 b/tests/testfile-dw-form-indirect.bz2
new file mode 100755
index 0000000..e531c11
--- /dev/null
+++ b/tests/testfile-dw-form-indirect.bz2
Binary files differ
diff --git a/tests/testfile-dwarf-4.bz2 b/tests/testfile-dwarf-4.bz2
new file mode 100755
index 0000000..fd3aaea
--- /dev/null
+++ b/tests/testfile-dwarf-4.bz2
Binary files differ
diff --git a/tests/testfile-dwarf-45.source b/tests/testfile-dwarf-45.source
new file mode 100644
index 0000000..584c8f7
--- /dev/null
+++ b/tests/testfile-dwarf-45.source
@@ -0,0 +1,89 @@
+# Nonsensical program used to generate an example DWARF4 and DWARF5 file.
+# The generated code is the same, but the DWARF representation is different.
+
+# = hello.h =
+
+extern int m;
+extern int baz (int x);
+
+static inline int
+frob (int a, int b)
+{
+  int c = a;
+
+  if (a > b)
+    c -= b;
+
+  return baz (c);
+}
+
+# = hello.c =
+
+#include <stddef.h>
+#include "hello.h"
+
+extern int main (int, char **);
+int m = 2;
+
+wchar_t foo (wchar_t);
+int baz (int x)
+{
+  int r = x;
+
+  if (x > m)
+    r -= m;
+
+  r = foo (r);
+  return r;
+}
+
+wchar_t
+foo (wchar_t f)
+{
+  if (f < 0)
+    return main (f, NULL);
+
+  return f > 0 ? frob (f - 1, m) : 0;
+}
+
+# = world.c =
+
+#include "hello.h"
+#include <stdlib.h>
+
+int
+calc (const char *word)
+{
+  if (word == 0 || word[0] == '\0')
+    return 0;
+
+  return frob (word[0], m + 42);
+}
+
+int
+main (int argc, const char **argv)
+{
+  const char *n;
+  if (argc > 1)
+    n = argv[0];
+  else
+    n = "world";
+
+  exit (calc (n));
+}
+
+$ gcc -gdwarf-4 -gno-as-loc-support -gno-variable-location-views -O2 -c world.c
+$ gcc -gdwarf-4 -gno-as-loc-support -gno-variable-location-views -O2 -c hello.c
+$ gcc -o testfile-dwarf-4 hello.o world.o
+
+$ gcc -gdwarf-5 -gno-as-loc-support -gno-variable-location-views -O2 -c world.c
+$ gcc -gdwarf-5 -gno-as-loc-support -gno-variable-location-views -O2 -c hello.c
+$ gcc -o testfile-dwarf-5 hello.o world.o
+
+$ gcc -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2 -o testfile-world4.o -c world.c
+$ gcc -gdwarf-4 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2 -o testfile-hello4.o -c hello.c
+$ gcc -o testfile-splitdwarf-4 testfile-hello4.o testfile-world4.o
+
+$ gcc -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2 -o testfile-world5.o -c world.c
+$ gcc -gdwarf-5 -gsplit-dwarf -gno-as-loc-support -gno-variable-location-views -O2 -o testfile-hello5.o -c hello.c
+$ gcc -o testfile-splitdwarf-5 testfile-hello5.o testfile-world5.o
diff --git a/tests/testfile-dwarf-5.bz2 b/tests/testfile-dwarf-5.bz2
new file mode 100755
index 0000000..689fa4f
--- /dev/null
+++ b/tests/testfile-dwarf-5.bz2
Binary files differ
diff --git a/tests/testfile-dwarf5-fat-lto.o.bz2 b/tests/testfile-dwarf5-fat-lto.o.bz2
new file mode 100644
index 0000000..ce3659f
--- /dev/null
+++ b/tests/testfile-dwarf5-fat-lto.o.bz2
Binary files differ
diff --git a/tests/testfile-dwarf5-line-clang.bz2 b/tests/testfile-dwarf5-line-clang.bz2
new file mode 100755
index 0000000..bdd66e9
--- /dev/null
+++ b/tests/testfile-dwarf5-line-clang.bz2
Binary files differ
diff --git a/tests/testfile-dwfl-report-elf-align-shlib.so.bz2 b/tests/testfile-dwfl-report-elf-align-shlib.so.bz2
new file mode 100755
index 0000000..1f35df9
--- /dev/null
+++ b/tests/testfile-dwfl-report-elf-align-shlib.so.bz2
Binary files differ
diff --git a/tests/testfile-dwp-4-cu-index-overflow.bz2 b/tests/testfile-dwp-4-cu-index-overflow.bz2
new file mode 100755
index 0000000..2aaa4f4
--- /dev/null
+++ b/tests/testfile-dwp-4-cu-index-overflow.bz2
Binary files differ
diff --git a/tests/testfile-dwp-4-cu-index-overflow.dwp.bz2 b/tests/testfile-dwp-4-cu-index-overflow.dwp.bz2
new file mode 100644
index 0000000..0718c1b
--- /dev/null
+++ b/tests/testfile-dwp-4-cu-index-overflow.dwp.bz2
Binary files differ
diff --git a/tests/testfile-dwp-4-strict.bz2 b/tests/testfile-dwp-4-strict.bz2
new file mode 100755
index 0000000..4f419c0
--- /dev/null
+++ b/tests/testfile-dwp-4-strict.bz2
Binary files differ
diff --git a/tests/testfile-dwp-4-strict.dwp.bz2 b/tests/testfile-dwp-4-strict.dwp.bz2
new file mode 100644
index 0000000..8cc1bbe
--- /dev/null
+++ b/tests/testfile-dwp-4-strict.dwp.bz2
Binary files differ
diff --git a/tests/testfile-dwp-4.bz2 b/tests/testfile-dwp-4.bz2
new file mode 100755
index 0000000..ece5817
--- /dev/null
+++ b/tests/testfile-dwp-4.bz2
Binary files differ
diff --git a/tests/testfile-dwp-4.dwp.bz2 b/tests/testfile-dwp-4.dwp.bz2
new file mode 100644
index 0000000..1a63b42
--- /dev/null
+++ b/tests/testfile-dwp-4.dwp.bz2
Binary files differ
diff --git a/tests/testfile-dwp-5-cu-index-overflow.bz2 b/tests/testfile-dwp-5-cu-index-overflow.bz2
new file mode 100755
index 0000000..07185fe
--- /dev/null
+++ b/tests/testfile-dwp-5-cu-index-overflow.bz2
Binary files differ
diff --git a/tests/testfile-dwp-5-cu-index-overflow.dwp.bz2 b/tests/testfile-dwp-5-cu-index-overflow.dwp.bz2
new file mode 100644
index 0000000..dce34e3
--- /dev/null
+++ b/tests/testfile-dwp-5-cu-index-overflow.dwp.bz2
Binary files differ
diff --git a/tests/testfile-dwp-5.bz2 b/tests/testfile-dwp-5.bz2
new file mode 100755
index 0000000..2c768ea
--- /dev/null
+++ b/tests/testfile-dwp-5.bz2
Binary files differ
diff --git a/tests/testfile-dwp-5.dwp.bz2 b/tests/testfile-dwp-5.dwp.bz2
new file mode 100644
index 0000000..ba28e50
--- /dev/null
+++ b/tests/testfile-dwp-5.dwp.bz2
Binary files differ
diff --git a/tests/testfile-dwp-cu-index-overflow.source b/tests/testfile-dwp-cu-index-overflow.source
new file mode 100644
index 0000000..2de1544
--- /dev/null
+++ b/tests/testfile-dwp-cu-index-overflow.source
@@ -0,0 +1,86 @@
+# Dummy program that we patch to generate a dwp file with more than 4GB of
+# .debug_info.
+
+# Generate 2 dummy files that result in DWARF blocks.
+$ for (( i = 1; i <= 2; i++ )); do echo 'constexpr int filler'$i'[] = { 1 };' > filler$i.cc; done
+$ g++ -O2 -g -gsplit-dwarf -fdebug-types-section -dA -S filler{1,2}.cc foo.cc bar.cc main.cc
+# Patch the DWARF blocks to be 2GB.
+$ for (( i = 1; i <= 2; i++ )); do patch -p1 << EOF
+--- a/filler$i.s
++++ b/filler$i.s
+@@ -7,5 +7,5 @@
+ 	.section	.debug_info.dwo,"e",@progbits
+ .Ldebug_info0:
+-	.long	0x49	# Length of Compilation Unit Info
++	.long	0x80000048	# Length of Compilation Unit Info
+ 	.value	0x5	# DWARF version number
+ 	.byte	0x5	# DW_UT_split_compile
+@@ -51,9 +51,6 @@
+ 	.long	0x29	# DW_AT_type
+ 			# DW_AT_const_expr
+-	.byte	0x4	# DW_AT_const_value
+-	.byte	0x1	# fp or vector constant word 0
+-	.byte	0	# fp or vector constant word 1
+-	.byte	0	# fp or vector constant word 2
+-	.byte	0	# fp or vector constant word 3
++	.long	0x80000000	# DW_AT_const_value
++	.fill	0x80000000
+ 	.byte	0	# end of children of DIE 0x14
+ 	.section	.debug_info,"",@progbits
+@@ -171,5 +168,5 @@
+ 	.uleb128 0x19	# (DW_FORM_flag_present)
+ 	.uleb128 0x1c	# (DW_AT_const_value)
+-	.uleb128 0xa	# (DW_FORM_block1)
++	.uleb128 0x4	# (DW_FORM_block4)
+ 	.byte	0
+ 	.byte	0
+EOF
+done
+$ for (( i = 1; i <= 2; i++ )); do as filler$i.s -o filler$i.o; done
+$ as foo.s -o foo.o
+$ as bar.s -o bar.o
+$ as main.s -o main.o
+$ g++ filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-5-cu-index-overflow
+# -continue-on-cu-index-overflow was added in LLVM 17:
+# https://reviews.llvm.org/D144565.
+$ llvm-dwp -continue-on-cu-index-overflow filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-5-cu-index-overflow.dwp
+
+# Same thing for DWARF 4.
+$ g++ -O2 -g -gdwarf-4 -gsplit-dwarf -fdebug-types-section -dA -S filler{1,2}.cc foo.cc bar.cc main.cc
+$ for (( i = 1; i <= 2; i++ )); do patch -p1 << EOF
+--- a/filler$i.s
++++ b/filler$i.s
+@@ -6,5 +6,5 @@
+ 	.section	.debug_info.dwo,"e",@progbits
+ .Ldebug_info0:
+-	.long	0x48	# Length of Compilation Unit Info
++	.long	0x80000047	# Length of Compilation Unit Info
+ 	.value	0x4	# DWARF version number
+ 	.long	.Ldebug_abbrev0	# Offset Into Abbrev. Section
+@@ -49,9 +49,6 @@
+ 	.long	0x28	# DW_AT_type
+ 			# DW_AT_const_expr
+-	.byte	0x4	# DW_AT_const_value
+-	.byte	0x1	# fp or vector constant word 0
+-	.byte	0	# fp or vector constant word 1
+-	.byte	0	# fp or vector constant word 2
+-	.byte	0	# fp or vector constant word 3
++	.long	0x80000000	# DW_AT_const_value
++	.fill	0x80000000
+ 	.byte	0	# end of children of DIE 0xb
+ 	.section	.debug_info,"",@progbits
+@@ -172,5 +169,5 @@
+ 	.uleb128 0x19	# (DW_FORM_flag_present)
+ 	.uleb128 0x1c	# (DW_AT_const_value)
+-	.uleb128 0xa	# (DW_FORM_block1)
++	.uleb128 0x4	# (DW_FORM_block4)
+ 	.byte	0
+ 	.byte	0
+EOF
+done
+$ for (( i = 1; i <= 2; i++ )); do as filler$i.s -o filler$i.o; done
+$ as foo.s -o foo.o
+$ as bar.s -o bar.o
+$ as main.s -o main.o
+$ g++ filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-4-cu-index-overflow
+$ llvm-dwp -continue-on-cu-index-overflow filler1.o foo.o filler2.o bar.o main.o -o testfile-dwp-4-cu-index-overflow.dwp
diff --git a/tests/testfile-dwp.source b/tests/testfile-dwp.source
new file mode 100644
index 0000000..b0b0a97
--- /dev/null
+++ b/tests/testfile-dwp.source
@@ -0,0 +1,102 @@
+# Nonsensical program used to generate example DWARF package files with type
+# units, location lists, range lists, and macros.
+
+# = foobar.h =
+
+struct Foo
+{
+  int a, b;
+  int foo ();
+};
+
+struct Bar
+{
+  long a, b;
+  long bar ();
+};
+
+#define FROB(x) ((x) ^ 0x2a2a2a2a)
+#define FRY(x) ((x) * 0x100000001b3)
+
+inline long
+fibonacci (unsigned int n)
+{
+  if (n == 0)
+    return 0;
+  else
+    {
+      long a = 0;
+      long b = 1;
+      for (unsigned int i = 2; i < n; i++)
+	{
+	  long tmp = a + b;
+	  a = b;
+	  b = tmp;
+	}
+      return b;
+    }
+}
+
+# = foo.cc =
+
+#include "foobar.h"
+
+#define ZERO() (1 - 1)
+
+int
+x_x (int x)
+{
+  for (int i = x; i > ZERO(); i--)
+    x *= x;
+  return x;
+}
+
+int
+Foo::foo ()
+{
+  int x = a;
+  if (a > b)
+    x -= b;
+  return FROB (x_x (x));
+}
+
+# = bar.cc =
+
+#include "foobar.h"
+
+#define ONE 1
+
+long
+Bar::bar ()
+{
+  if (a == b)
+    return ONE;
+  else
+    return a > b ? b : a;
+}
+
+# = main.cc =
+
+#include "foobar.h"
+
+#define MAIN_ARGS int argc, char **argv
+
+int
+main(MAIN_ARGS)
+{
+  struct Foo myfoo { argc, FROB (argc) };
+  struct Bar mybar { fibonacci (argc), FRY (argc) };
+  return myfoo.foo() + mybar.bar();
+}
+
+# Built with GCC at commit 80048aa13a6b ("debug/111409 - don't generate COMDAT
+# macro sections for split DWARF").
+$ g++ -gdwarf-5 -gsplit-dwarf -fdebug-types-section -g3 -O2 foo.cc bar.cc main.cc -o testfile-dwp-5
+# GNU dwp as of binutils 2.41 only supports DWARF 4.
+$ llvm-dwp -e testfile-dwp-5 -o testfile-dwp-5.dwp
+
+$ g++ -gdwarf-4 -gsplit-dwarf -fdebug-types-section -g3 -O2 foo.cc bar.cc main.cc -o testfile-dwp-4
+$ dwp -e testfile-dwp-4
+
+$ g++ -gdwarf-4 -gstrict-dwarf -gsplit-dwarf -fdebug-types-section -g3 -O2 foo.cc bar.cc main.cc -o testfile-dwp-4-strict
+$ dwp -e testfile-dwp-4-strict
diff --git a/tests/testfile-dwzstr.bz2 b/tests/testfile-dwzstr.bz2
new file mode 100755
index 0000000..8d2d326
--- /dev/null
+++ b/tests/testfile-dwzstr.bz2
Binary files differ
diff --git a/tests/testfile-dwzstr.multi.bz2 b/tests/testfile-dwzstr.multi.bz2
new file mode 100644
index 0000000..5e84991
--- /dev/null
+++ b/tests/testfile-dwzstr.multi.bz2
Binary files differ
diff --git a/tests/testfile-gnu-property-note-aarch64.bz2 b/tests/testfile-gnu-property-note-aarch64.bz2
new file mode 100755
index 0000000..2fe37b1
--- /dev/null
+++ b/tests/testfile-gnu-property-note-aarch64.bz2
Binary files differ
diff --git a/tests/testfile-gnu-property-note.bz2 b/tests/testfile-gnu-property-note.bz2
new file mode 100755
index 0000000..c03bd9b
--- /dev/null
+++ b/tests/testfile-gnu-property-note.bz2
Binary files differ
diff --git a/tests/testfile-gnu-property-note.o.bz2 b/tests/testfile-gnu-property-note.o.bz2
new file mode 100644
index 0000000..5147c64
--- /dev/null
+++ b/tests/testfile-gnu-property-note.o.bz2
Binary files differ
diff --git a/tests/testfile-hello4.dwo.bz2 b/tests/testfile-hello4.dwo.bz2
new file mode 100644
index 0000000..fe02d65
--- /dev/null
+++ b/tests/testfile-hello4.dwo.bz2
Binary files differ
diff --git a/tests/testfile-hello5.dwo.bz2 b/tests/testfile-hello5.dwo.bz2
new file mode 100644
index 0000000..e911375
--- /dev/null
+++ b/tests/testfile-hello5.dwo.bz2
Binary files differ
diff --git a/tests/testfile-info-link.bz2 b/tests/testfile-info-link.bz2
new file mode 100755
index 0000000..073b761
--- /dev/null
+++ b/tests/testfile-info-link.bz2
Binary files differ
diff --git a/tests/testfile-info-link.debuginfo.bz2 b/tests/testfile-info-link.debuginfo.bz2
new file mode 100755
index 0000000..3225d19
--- /dev/null
+++ b/tests/testfile-info-link.debuginfo.bz2
Binary files differ
diff --git a/tests/testfile-info-link.stripped.bz2 b/tests/testfile-info-link.stripped.bz2
new file mode 100755
index 0000000..dcbc9a2
--- /dev/null
+++ b/tests/testfile-info-link.stripped.bz2
Binary files differ
diff --git a/tests/testfile-inlines-lto.bz2 b/tests/testfile-inlines-lto.bz2
new file mode 100755
index 0000000..7e2e2bf
--- /dev/null
+++ b/tests/testfile-inlines-lto.bz2
Binary files differ
diff --git a/tests/testfile-inlines.bz2 b/tests/testfile-inlines.bz2
new file mode 100755
index 0000000..6a0c7c5
--- /dev/null
+++ b/tests/testfile-inlines.bz2
Binary files differ
diff --git a/tests/testfile-largealign.o.bz2 b/tests/testfile-largealign.o.bz2
new file mode 100644
index 0000000..324c1ea
--- /dev/null
+++ b/tests/testfile-largealign.o.bz2
Binary files differ
diff --git a/tests/testfile-lex-inlines.bz2 b/tests/testfile-lex-inlines.bz2
new file mode 100755
index 0000000..716e792
--- /dev/null
+++ b/tests/testfile-lex-inlines.bz2
Binary files differ
diff --git a/tests/testfile-lto-gcc10.bz2 b/tests/testfile-lto-gcc10.bz2
new file mode 100755
index 0000000..e8ef621
--- /dev/null
+++ b/tests/testfile-lto-gcc10.bz2
Binary files differ
diff --git a/tests/testfile-lto-gcc8.bz2 b/tests/testfile-lto-gcc8.bz2
new file mode 100755
index 0000000..cf744d9
--- /dev/null
+++ b/tests/testfile-lto-gcc8.bz2
Binary files differ
diff --git a/tests/testfile-lto-gcc9.bz2 b/tests/testfile-lto-gcc9.bz2
new file mode 100755
index 0000000..df50361
--- /dev/null
+++ b/tests/testfile-lto-gcc9.bz2
Binary files differ
diff --git a/tests/testfile-m68k-core.bz2 b/tests/testfile-m68k-core.bz2
new file mode 100644
index 0000000..eda79d7
--- /dev/null
+++ b/tests/testfile-m68k-core.bz2
Binary files differ
diff --git a/tests/testfile-m68k-s.bz2 b/tests/testfile-m68k-s.bz2
new file mode 100755
index 0000000..44c3799
--- /dev/null
+++ b/tests/testfile-m68k-s.bz2
Binary files differ
diff --git a/tests/testfile-m68k.bz2 b/tests/testfile-m68k.bz2
new file mode 100755
index 0000000..97a1b28
--- /dev/null
+++ b/tests/testfile-m68k.bz2
Binary files differ
diff --git a/tests/testfile-macinfo.bz2 b/tests/testfile-macinfo.bz2
new file mode 100755
index 0000000..e6cc5f1
--- /dev/null
+++ b/tests/testfile-macinfo.bz2
Binary files differ
diff --git a/tests/testfile-macros-0xff.bz2 b/tests/testfile-macros-0xff.bz2
new file mode 100755
index 0000000..a19662a
--- /dev/null
+++ b/tests/testfile-macros-0xff.bz2
Binary files differ
diff --git a/tests/testfile-macros-0xff.s b/tests/testfile-macros-0xff.s
new file mode 100644
index 0000000..7fdd35c
--- /dev/null
+++ b/tests/testfile-macros-0xff.s
@@ -0,0 +1,153 @@
+	.file	"x.c"
+	.text
+.Ltext0:
+	.globl	main
+	.type	main, @function
+main:
+.LFB0:
+	.file 1 "x.c"
+	.loc 1 3 0
+	.cfi_startproc
+	pushq	%rbp
+	.cfi_def_cfa_offset 16
+	.cfi_offset 6, -16
+	movq	%rsp, %rbp
+	.cfi_def_cfa_register 6
+	.loc 1 3 0
+	movl	$0, %eax
+	popq	%rbp
+	.cfi_def_cfa 7, 8
+	ret
+	.cfi_endproc
+.LFE0:
+	.size	main, .-main
+.Letext0:
+	.section	.debug_info,"",@progbits
+.Ldebug_info0:
+	.long	0x52
+	.value	0x4
+	.long	.Ldebug_abbrev0
+	.byte	0x8
+	.uleb128 0x1
+	.long	.LASF244
+	.byte	0x4
+	.string	"x.c"
+	.long	.LASF245
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.long	.Ldebug_line0
+	.long	.Ldebug_macro0
+	.uleb128 0x2
+	.long	.LASF246
+	.byte	0x1
+	.byte	0x3
+	.long	0x4e
+	.quad	.LFB0
+	.quad	.LFE0-.LFB0
+	.uleb128 0x1
+	.byte	0x9c
+	.uleb128 0x3
+	.byte	0x4
+	.byte	0x5
+	.string	"int"
+	.byte	0
+	.section	.debug_abbrev,"",@progbits
+.Ldebug_abbrev0:
+	.uleb128 0x1
+	.uleb128 0x11
+	.byte	0x1
+	.uleb128 0x25
+	.uleb128 0xe
+	.uleb128 0x13
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.uleb128 0x1b
+	.uleb128 0xe
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x10
+	.uleb128 0x17
+	.uleb128 0x2119
+	.uleb128 0x17
+	.byte	0
+	.byte	0
+	.uleb128 0x2
+	.uleb128 0x2e
+	.byte	0
+	.uleb128 0x3f
+	.uleb128 0x19
+	.uleb128 0x3
+	.uleb128 0xe
+	.uleb128 0x3a
+	.uleb128 0xb
+	.uleb128 0x3b
+	.uleb128 0xb
+	.uleb128 0x49
+	.uleb128 0x13
+	.uleb128 0x11
+	.uleb128 0x1
+	.uleb128 0x12
+	.uleb128 0x7
+	.uleb128 0x40
+	.uleb128 0x18
+	.uleb128 0x2117
+	.uleb128 0x19
+	.byte	0
+	.byte	0
+	.uleb128 0x3
+	.uleb128 0x24
+	.byte	0
+	.uleb128 0xb
+	.uleb128 0xb
+	.uleb128 0x3e
+	.uleb128 0xb
+	.uleb128 0x3
+	.uleb128 0x8
+	.byte	0
+	.byte	0
+	.byte	0
+	.section	.debug_aranges,"",@progbits
+	.long	0x2c
+	.value	0x2
+	.long	.Ldebug_info0
+	.byte	0x8
+	.byte	0
+	.value	0
+	.value	0
+	.quad	.Ltext0
+	.quad	.Letext0-.Ltext0
+	.quad	0
+	.quad	0
+	.section	.debug_macro,"",@progbits
+.Ldebug_macro0:
+	.value	0x4
+	.byte	0x6
+	.long	.Ldebug_line0
+	.byte   0x1
+	.byte   0xff
+	.uleb128 0
+	.byte   0xff
+	.byte	0x3
+	.uleb128 0
+	.uleb128 0x1
+	.byte	0x5
+	.uleb128 0x1
+	.long	.LASF243
+	.byte	0x4
+	.byte	0
+	.section	.debug_line,"",@progbits
+.Ldebug_line0:
+	.section	.debug_str,"MS",@progbits,1
+.LASF245:
+	.string	"/home/petr/proj/elfutils/master/elfutils"
+.LASF244:
+	.string	"GNU C++ 4.9.0 20140422 (Red Hat 4.9.0-1) -mtune=generic -march=x86-64 -g3"
+.LASF243:
+	.string	"FOO 0"
+.LASF246:
+	.string	"main"
+	.ident	"GCC: (GNU) 4.9.0 20140422 (Red Hat 4.9.0-1)"
+	.section	.note.GNU-stack,"",@progbits
diff --git a/tests/testfile-macros-object.o.bz2 b/tests/testfile-macros-object.o.bz2
new file mode 100644
index 0000000..de5fa1a
--- /dev/null
+++ b/tests/testfile-macros-object.o.bz2
Binary files differ
diff --git a/tests/testfile-macros.bz2 b/tests/testfile-macros.bz2
new file mode 100755
index 0000000..d74df94
--- /dev/null
+++ b/tests/testfile-macros.bz2
Binary files differ
diff --git a/tests/testfile-nobitsalign.bz2 b/tests/testfile-nobitsalign.bz2
new file mode 100755
index 0000000..7f0d424
--- /dev/null
+++ b/tests/testfile-nobitsalign.bz2
Binary files differ
diff --git a/tests/testfile-nobitsalign.strip.bz2 b/tests/testfile-nobitsalign.strip.bz2
new file mode 100755
index 0000000..f72000c
--- /dev/null
+++ b/tests/testfile-nobitsalign.strip.bz2
Binary files differ
diff --git a/tests/testfile-nolfs.bz2 b/tests/testfile-nolfs.bz2
new file mode 100644
index 0000000..ab8351e
--- /dev/null
+++ b/tests/testfile-nolfs.bz2
Binary files differ
diff --git a/tests/testfile-only-debug-line.bz2 b/tests/testfile-only-debug-line.bz2
new file mode 100644
index 0000000..a931bcd
--- /dev/null
+++ b/tests/testfile-only-debug-line.bz2
Binary files differ
diff --git a/tests/testfile-phdrs.elf.bz2 b/tests/testfile-phdrs.elf.bz2
new file mode 100644
index 0000000..024ed79
--- /dev/null
+++ b/tests/testfile-phdrs.elf.bz2
Binary files differ
diff --git a/tests/testfile-ppc64-min-instr.bz2 b/tests/testfile-ppc64-min-instr.bz2
new file mode 100755
index 0000000..85bef57
--- /dev/null
+++ b/tests/testfile-ppc64-min-instr.bz2
Binary files differ
diff --git a/tests/testfile-ranges-hello.dwo.bz2 b/tests/testfile-ranges-hello.dwo.bz2
new file mode 100644
index 0000000..fac2467
--- /dev/null
+++ b/tests/testfile-ranges-hello.dwo.bz2
Binary files differ
diff --git a/tests/testfile-ranges-hello5.dwo.bz2 b/tests/testfile-ranges-hello5.dwo.bz2
new file mode 100644
index 0000000..5e6e9e2
--- /dev/null
+++ b/tests/testfile-ranges-hello5.dwo.bz2
Binary files differ
diff --git a/tests/testfile-ranges-world.dwo.bz2 b/tests/testfile-ranges-world.dwo.bz2
new file mode 100644
index 0000000..27ad06d
--- /dev/null
+++ b/tests/testfile-ranges-world.dwo.bz2
Binary files differ
diff --git a/tests/testfile-ranges-world5.dwo.bz2 b/tests/testfile-ranges-world5.dwo.bz2
new file mode 100644
index 0000000..6bde196
--- /dev/null
+++ b/tests/testfile-ranges-world5.dwo.bz2
Binary files differ
diff --git a/tests/testfile-retain.o.bz2 b/tests/testfile-retain.o.bz2
new file mode 100644
index 0000000..7571c0e
--- /dev/null
+++ b/tests/testfile-retain.o.bz2
Binary files differ
diff --git a/tests/testfile-riscv64-core.bz2 b/tests/testfile-riscv64-core.bz2
new file mode 100644
index 0000000..f5b472b
--- /dev/null
+++ b/tests/testfile-riscv64-core.bz2
Binary files differ
diff --git a/tests/testfile-riscv64-dis1.expect.bz2 b/tests/testfile-riscv64-dis1.expect.bz2
new file mode 100644
index 0000000..2740795
--- /dev/null
+++ b/tests/testfile-riscv64-dis1.expect.bz2
Binary files differ
diff --git a/tests/testfile-riscv64-dis1.o.bz2 b/tests/testfile-riscv64-dis1.o.bz2
new file mode 100644
index 0000000..50f95f2
--- /dev/null
+++ b/tests/testfile-riscv64-dis1.o.bz2
Binary files differ
diff --git a/tests/testfile-riscv64-s.bz2 b/tests/testfile-riscv64-s.bz2
new file mode 100755
index 0000000..149ae41
--- /dev/null
+++ b/tests/testfile-riscv64-s.bz2
Binary files differ
diff --git a/tests/testfile-riscv64.bz2 b/tests/testfile-riscv64.bz2
new file mode 100755
index 0000000..cae4919
--- /dev/null
+++ b/tests/testfile-riscv64.bz2
Binary files differ
diff --git a/tests/testfile-rng.debug.bz2 b/tests/testfile-rng.debug.bz2
new file mode 100644
index 0000000..58c1b76
--- /dev/null
+++ b/tests/testfile-rng.debug.bz2
Binary files differ
diff --git a/tests/testfile-s390x-hash-both.bz2 b/tests/testfile-s390x-hash-both.bz2
new file mode 100755
index 0000000..86e0bcc
--- /dev/null
+++ b/tests/testfile-s390x-hash-both.bz2
Binary files differ
diff --git a/tests/testfile-sizes1.o.bz2 b/tests/testfile-sizes1.o.bz2
new file mode 100644
index 0000000..479ecb2
--- /dev/null
+++ b/tests/testfile-sizes1.o.bz2
Binary files differ
diff --git a/tests/testfile-sizes2.o.bz2 b/tests/testfile-sizes2.o.bz2
new file mode 100644
index 0000000..7bd7b47
--- /dev/null
+++ b/tests/testfile-sizes2.o.bz2
Binary files differ
diff --git a/tests/testfile-sizes3.o.bz2 b/tests/testfile-sizes3.o.bz2
new file mode 100644
index 0000000..8633382
--- /dev/null
+++ b/tests/testfile-sizes3.o.bz2
Binary files differ
diff --git a/tests/testfile-sizes4.o.bz2 b/tests/testfile-sizes4.o.bz2
new file mode 100644
index 0000000..046e0a2
--- /dev/null
+++ b/tests/testfile-sizes4.o.bz2
Binary files differ
diff --git a/tests/testfile-sizes4.s b/tests/testfile-sizes4.s
new file mode 100644
index 0000000..a243021
--- /dev/null
+++ b/tests/testfile-sizes4.s
@@ -0,0 +1,77 @@
+        .section .debug_info
+.Lcu1_begin:
+        .4byte        .Lcu1_end - .Lcu1_start
+.Lcu1_start:
+        .2byte        4                 /* Version */
+        .4byte        .Labbrev1_begin   /* Abbrevs */
+        .byte        8                  /* Pointer size */
+        .uleb128        2               /* Abbrev (DW_TAG_compile_unit) */
+        .uleb128        3               /* Abbrev (DW_TAG_variable) */
+        .ascii        "v\0"
+        .4byte        .Llabel1 - .Lcu1_begin
+.Llabel1:
+        .uleb128        4               /* Abbrev (DW_TAG_array_type) */
+        .4byte        .Llabel2 - .Lcu1_begin
+        .uleb128        5               /* Abbrev (DW_TAG_subrange_type) */
+        .byte        -1
+        .2byte        255
+        .byte        0x0                /* Terminate children */
+.Llabel2:
+        .uleb128        6               /* Abbrev (DW_TAG_base_type) */
+        .byte        1
+        .byte        0x0                /* Terminate children */
+.Lcu1_end:
+        .section .note.gnu.build-id, "a", %note
+        .4byte        4
+        .4byte        8
+        .4byte        3
+        .ascii        "GNU\0"
+        .byte        0x01
+        .byte        0x02
+        .byte        0x03
+        .byte        0x04
+        .byte        0x05
+        .byte        0x06
+        .byte        0x07
+        .byte        0x08
+        .section .debug_abbrev
+.Labbrev1_begin:
+        .uleb128        2               /* Abbrev start */
+        .uleb128        0x11            /* DW_TAG_compile_unit */
+        .byte        1                  /* has_children */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .uleb128        3               /* Abbrev start */
+        .uleb128        0x34            /* DW_TAG_variable */
+        .byte        0                  /* has_children */
+        .uleb128        0x03            /* DW_AT_name */
+        .uleb128        0x08            /* DW_FORM_string */
+        .uleb128        0x49            /* DW_AT_type */
+        .uleb128        0x13            /* DW_FORM_ref4 */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .uleb128        4               /* Abbrev start */
+        .uleb128        0x01            /* DW_TAG_array_type */
+        .byte        1                  /* has_children */
+        .uleb128        0x49            /* DW_AT_type */
+        .uleb128        0x13            /* DW_FORM_ref4 */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .uleb128        5               /* Abbrev start */
+        .uleb128        0x21            /* DW_TAG_subrange_type */
+        .byte        0                  /* has_children */
+        .uleb128        0x22            /* DW_AT_lower_bound */
+        .uleb128        0x0b            /* DW_FORM_data1 */
+        .uleb128        0x2f            /* DW_AT_upper_bound */
+        .uleb128        0x05            /* DW_FORM_data2 */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .uleb128        6               /* Abbrev start */
+        .uleb128        0x24            /* DW_TAG_base_type */
+        .byte        0                  /* has_children */
+        .uleb128        0x0b            /* DW_AT_byte_size */
+        .uleb128        0x0b            /* DW_FORM_data1 */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
+        .byte        0x0                /* Terminator */
diff --git a/tests/testfile-splitdwarf-4.bz2 b/tests/testfile-splitdwarf-4.bz2
new file mode 100755
index 0000000..a1871e6
--- /dev/null
+++ b/tests/testfile-splitdwarf-4.bz2
Binary files differ
diff --git a/tests/testfile-splitdwarf-5.bz2 b/tests/testfile-splitdwarf-5.bz2
new file mode 100755
index 0000000..27ff3bd
--- /dev/null
+++ b/tests/testfile-splitdwarf-5.bz2
Binary files differ
diff --git a/tests/testfile-splitdwarf4-not-split4.debug.bz2 b/tests/testfile-splitdwarf4-not-split4.debug.bz2
new file mode 100755
index 0000000..6f4d701
--- /dev/null
+++ b/tests/testfile-splitdwarf4-not-split4.debug.bz2
Binary files differ
diff --git a/tests/testfile-stridex.bz2 b/tests/testfile-stridex.bz2
new file mode 100755
index 0000000..ff909f4
--- /dev/null
+++ b/tests/testfile-stridex.bz2
Binary files differ
diff --git a/tests/testfile-strtab.bz2 b/tests/testfile-strtab.bz2
new file mode 100644
index 0000000..4eda14d
--- /dev/null
+++ b/tests/testfile-strtab.bz2
Binary files differ
diff --git a/tests/testfile-strtab.debuginfo.bz2 b/tests/testfile-strtab.debuginfo.bz2
new file mode 100644
index 0000000..6fb8164
--- /dev/null
+++ b/tests/testfile-strtab.debuginfo.bz2
Binary files differ
diff --git a/tests/testfile-strtab.stripped.bz2 b/tests/testfile-strtab.stripped.bz2
new file mode 100644
index 0000000..779bfdb
--- /dev/null
+++ b/tests/testfile-strtab.stripped.bz2
Binary files differ
diff --git a/tests/testfile-urng.debug.bz2 b/tests/testfile-urng.debug.bz2
new file mode 100644
index 0000000..4697f36
--- /dev/null
+++ b/tests/testfile-urng.debug.bz2
Binary files differ
diff --git a/tests/testfile-vars-clang-dwarf4-32.o.bz2 b/tests/testfile-vars-clang-dwarf4-32.o.bz2
new file mode 100644
index 0000000..c1ddf81
--- /dev/null
+++ b/tests/testfile-vars-clang-dwarf4-32.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-clang-dwarf4-64.o.bz2 b/tests/testfile-vars-clang-dwarf4-64.o.bz2
new file mode 100644
index 0000000..df33299
--- /dev/null
+++ b/tests/testfile-vars-clang-dwarf4-64.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-clang-dwarf5-32.o.bz2 b/tests/testfile-vars-clang-dwarf5-32.o.bz2
new file mode 100644
index 0000000..b1d6b6c
--- /dev/null
+++ b/tests/testfile-vars-clang-dwarf5-32.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-clang-dwarf5-64.o.bz2 b/tests/testfile-vars-clang-dwarf5-64.o.bz2
new file mode 100644
index 0000000..adf6c6a
--- /dev/null
+++ b/tests/testfile-vars-clang-dwarf5-64.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-gcc-dwarf4-32.o.bz2 b/tests/testfile-vars-gcc-dwarf4-32.o.bz2
new file mode 100644
index 0000000..da9aac7
--- /dev/null
+++ b/tests/testfile-vars-gcc-dwarf4-32.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-gcc-dwarf4-64.o.bz2 b/tests/testfile-vars-gcc-dwarf4-64.o.bz2
new file mode 100644
index 0000000..2642164
--- /dev/null
+++ b/tests/testfile-vars-gcc-dwarf4-64.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-gcc-dwarf5-32.o.bz2 b/tests/testfile-vars-gcc-dwarf5-32.o.bz2
new file mode 100644
index 0000000..cb1c705
--- /dev/null
+++ b/tests/testfile-vars-gcc-dwarf5-32.o.bz2
Binary files differ
diff --git a/tests/testfile-vars-gcc-dwarf5-64.o.bz2 b/tests/testfile-vars-gcc-dwarf5-64.o.bz2
new file mode 100644
index 0000000..e286f8f
--- /dev/null
+++ b/tests/testfile-vars-gcc-dwarf5-64.o.bz2
Binary files differ
diff --git a/tests/testfile-version.bz2 b/tests/testfile-version.bz2
new file mode 100755
index 0000000..b2c0c0c
--- /dev/null
+++ b/tests/testfile-version.bz2
Binary files differ
diff --git a/tests/testfile-world4.dwo.bz2 b/tests/testfile-world4.dwo.bz2
new file mode 100644
index 0000000..297fe5f
--- /dev/null
+++ b/tests/testfile-world4.dwo.bz2
Binary files differ
diff --git a/tests/testfile-world5.dwo.bz2 b/tests/testfile-world5.dwo.bz2
new file mode 100644
index 0000000..d5c852c
--- /dev/null
+++ b/tests/testfile-world5.dwo.bz2
Binary files differ
diff --git a/tests/testfile-x32-core.bz2 b/tests/testfile-x32-core.bz2
new file mode 100644
index 0000000..d519851
--- /dev/null
+++ b/tests/testfile-x32-core.bz2
Binary files differ
diff --git a/tests/testfile-x32-d.bz2 b/tests/testfile-x32-d.bz2
new file mode 100755
index 0000000..ad5836e
--- /dev/null
+++ b/tests/testfile-x32-d.bz2
Binary files differ
diff --git a/tests/testfile-x32-debug.bz2 b/tests/testfile-x32-debug.bz2
new file mode 100755
index 0000000..d55a004
--- /dev/null
+++ b/tests/testfile-x32-debug.bz2
Binary files differ
diff --git a/tests/testfile-x32-s.bz2 b/tests/testfile-x32-s.bz2
new file mode 100755
index 0000000..a909d33
--- /dev/null
+++ b/tests/testfile-x32-s.bz2
Binary files differ
diff --git a/tests/testfile-x32.bz2 b/tests/testfile-x32.bz2
new file mode 100755
index 0000000..f6df180
--- /dev/null
+++ b/tests/testfile-x32.bz2
Binary files differ
diff --git a/tests/testfile-zdebug.bz2 b/tests/testfile-zdebug.bz2
new file mode 100755
index 0000000..784041c
--- /dev/null
+++ b/tests/testfile-zdebug.bz2
Binary files differ
diff --git a/tests/testfile-zgabi32.bz2 b/tests/testfile-zgabi32.bz2
new file mode 100755
index 0000000..6159dbc
--- /dev/null
+++ b/tests/testfile-zgabi32.bz2
Binary files differ
diff --git a/tests/testfile-zgabi32be.bz2 b/tests/testfile-zgabi32be.bz2
new file mode 100755
index 0000000..f1f5eb5
--- /dev/null
+++ b/tests/testfile-zgabi32be.bz2
Binary files differ
diff --git a/tests/testfile-zgabi64.bz2 b/tests/testfile-zgabi64.bz2
new file mode 100755
index 0000000..3b44f08
--- /dev/null
+++ b/tests/testfile-zgabi64.bz2
Binary files differ
diff --git a/tests/testfile-zgabi64be.bz2 b/tests/testfile-zgabi64be.bz2
new file mode 100755
index 0000000..d819ae3
--- /dev/null
+++ b/tests/testfile-zgabi64be.bz2
Binary files differ
diff --git a/tests/testfile-zgnu32.bz2 b/tests/testfile-zgnu32.bz2
new file mode 100755
index 0000000..9d622ca
--- /dev/null
+++ b/tests/testfile-zgnu32.bz2
Binary files differ
diff --git a/tests/testfile-zgnu32be.bz2 b/tests/testfile-zgnu32be.bz2
new file mode 100755
index 0000000..c1dd589
--- /dev/null
+++ b/tests/testfile-zgnu32be.bz2
Binary files differ
diff --git a/tests/testfile-zgnu64.bz2 b/tests/testfile-zgnu64.bz2
new file mode 100755
index 0000000..1bc2c09
--- /dev/null
+++ b/tests/testfile-zgnu64.bz2
Binary files differ
diff --git a/tests/testfile-zgnu64be.bz2 b/tests/testfile-zgnu64be.bz2
new file mode 100755
index 0000000..390c9c9
--- /dev/null
+++ b/tests/testfile-zgnu64be.bz2
Binary files differ
diff --git a/tests/testfile.bz2 b/tests/testfile.bz2
new file mode 100644
index 0000000..bde9b12
--- /dev/null
+++ b/tests/testfile.bz2
Binary files differ
diff --git a/tests/testfile10.bz2 b/tests/testfile10.bz2
new file mode 100644
index 0000000..e9dd504
--- /dev/null
+++ b/tests/testfile10.bz2
Binary files differ
diff --git a/tests/testfile11-debugframe.bz2 b/tests/testfile11-debugframe.bz2
new file mode 100644
index 0000000..5c07d16
--- /dev/null
+++ b/tests/testfile11-debugframe.bz2
Binary files differ
diff --git a/tests/testfile11.bz2 b/tests/testfile11.bz2
new file mode 100644
index 0000000..d094b84
--- /dev/null
+++ b/tests/testfile11.bz2
Binary files differ
diff --git a/tests/testfile12-debugframe.bz2 b/tests/testfile12-debugframe.bz2
new file mode 100644
index 0000000..b8cc19c
--- /dev/null
+++ b/tests/testfile12-debugframe.bz2
Binary files differ
diff --git a/tests/testfile12.bz2 b/tests/testfile12.bz2
new file mode 100644
index 0000000..8bb5ad3
--- /dev/null
+++ b/tests/testfile12.bz2
Binary files differ
diff --git a/tests/testfile13.bz2 b/tests/testfile13.bz2
new file mode 100644
index 0000000..3b0bcb9
--- /dev/null
+++ b/tests/testfile13.bz2
Binary files differ
diff --git a/tests/testfile14.bz2 b/tests/testfile14.bz2
new file mode 100644
index 0000000..ac7c69e
--- /dev/null
+++ b/tests/testfile14.bz2
Binary files differ
diff --git a/tests/testfile15.bz2 b/tests/testfile15.bz2
new file mode 100644
index 0000000..e75f457
--- /dev/null
+++ b/tests/testfile15.bz2
Binary files differ
diff --git a/tests/testfile15.debug.bz2 b/tests/testfile15.debug.bz2
new file mode 100644
index 0000000..5c86900
--- /dev/null
+++ b/tests/testfile15.debug.bz2
Binary files differ
diff --git a/tests/testfile16.bz2 b/tests/testfile16.bz2
new file mode 100644
index 0000000..4d7160c
--- /dev/null
+++ b/tests/testfile16.bz2
Binary files differ
diff --git a/tests/testfile16.debug.bz2 b/tests/testfile16.debug.bz2
new file mode 100644
index 0000000..f02a972
--- /dev/null
+++ b/tests/testfile16.debug.bz2
Binary files differ
diff --git a/tests/testfile17.bz2 b/tests/testfile17.bz2
new file mode 100644
index 0000000..5a12320
--- /dev/null
+++ b/tests/testfile17.bz2
Binary files differ
diff --git a/tests/testfile17.debug.bz2 b/tests/testfile17.debug.bz2
new file mode 100644
index 0000000..86a76ab
--- /dev/null
+++ b/tests/testfile17.debug.bz2
Binary files differ
diff --git a/tests/testfile18.bz2 b/tests/testfile18.bz2
new file mode 100644
index 0000000..8b5326c
--- /dev/null
+++ b/tests/testfile18.bz2
Binary files differ
diff --git a/tests/testfile19.bz2 b/tests/testfile19.bz2
new file mode 100644
index 0000000..f3e6512
--- /dev/null
+++ b/tests/testfile19.bz2
Binary files differ
diff --git a/tests/testfile19.index.bz2 b/tests/testfile19.index.bz2
new file mode 100644
index 0000000..c0a0a7a
--- /dev/null
+++ b/tests/testfile19.index.bz2
Binary files differ
diff --git a/tests/testfile2.bz2 b/tests/testfile2.bz2
new file mode 100644
index 0000000..0771311
--- /dev/null
+++ b/tests/testfile2.bz2
Binary files differ
diff --git a/tests/testfile20.bz2 b/tests/testfile20.bz2
new file mode 100644
index 0000000..a379f6b
--- /dev/null
+++ b/tests/testfile20.bz2
Binary files differ
diff --git a/tests/testfile20.index.bz2 b/tests/testfile20.index.bz2
new file mode 100644
index 0000000..08dedaf
--- /dev/null
+++ b/tests/testfile20.index.bz2
Binary files differ
diff --git a/tests/testfile21.bz2 b/tests/testfile21.bz2
new file mode 100644
index 0000000..bab7e6d
--- /dev/null
+++ b/tests/testfile21.bz2
Binary files differ
diff --git a/tests/testfile21.index.bz2 b/tests/testfile21.index.bz2
new file mode 100644
index 0000000..5192219
--- /dev/null
+++ b/tests/testfile21.index.bz2
Binary files differ
diff --git a/tests/testfile22.bz2 b/tests/testfile22.bz2
new file mode 100644
index 0000000..8c26270
--- /dev/null
+++ b/tests/testfile22.bz2
Binary files differ
diff --git a/tests/testfile23.bz2 b/tests/testfile23.bz2
new file mode 100644
index 0000000..cf0ce55
--- /dev/null
+++ b/tests/testfile23.bz2
Binary files differ
diff --git a/tests/testfile24.bz2 b/tests/testfile24.bz2
new file mode 100644
index 0000000..2320acb
--- /dev/null
+++ b/tests/testfile24.bz2
Binary files differ
diff --git a/tests/testfile25.bz2 b/tests/testfile25.bz2
new file mode 100644
index 0000000..51e0421
--- /dev/null
+++ b/tests/testfile25.bz2
Binary files differ
diff --git a/tests/testfile26.bz2 b/tests/testfile26.bz2
new file mode 100644
index 0000000..1f86285
--- /dev/null
+++ b/tests/testfile26.bz2
Binary files differ
diff --git a/tests/testfile27.bz2 b/tests/testfile27.bz2
new file mode 100644
index 0000000..9d06cd9
--- /dev/null
+++ b/tests/testfile27.bz2
Binary files differ
diff --git a/tests/testfile28.bz2 b/tests/testfile28.bz2
new file mode 100644
index 0000000..ca0dff3
--- /dev/null
+++ b/tests/testfile28.bz2
Binary files differ
diff --git a/tests/testfile28.rdwr.bz2 b/tests/testfile28.rdwr.bz2
new file mode 100644
index 0000000..4c65848
--- /dev/null
+++ b/tests/testfile28.rdwr.bz2
Binary files differ
diff --git a/tests/testfile29.bz2 b/tests/testfile29.bz2
new file mode 100644
index 0000000..b46451b
--- /dev/null
+++ b/tests/testfile29.bz2
Binary files differ
diff --git a/tests/testfile29.rdwr.bz2 b/tests/testfile29.rdwr.bz2
new file mode 100644
index 0000000..42eadc7
--- /dev/null
+++ b/tests/testfile29.rdwr.bz2
Binary files differ
diff --git a/tests/testfile3.bz2 b/tests/testfile3.bz2
new file mode 100644
index 0000000..30a456c
--- /dev/null
+++ b/tests/testfile3.bz2
Binary files differ
diff --git a/tests/testfile30.bz2 b/tests/testfile30.bz2
new file mode 100644
index 0000000..9ee93c0
--- /dev/null
+++ b/tests/testfile30.bz2
Binary files differ
diff --git a/tests/testfile31.bz2 b/tests/testfile31.bz2
new file mode 100644
index 0000000..73451d2
--- /dev/null
+++ b/tests/testfile31.bz2
Binary files differ
diff --git a/tests/testfile32.bz2 b/tests/testfile32.bz2
new file mode 100644
index 0000000..7e3c73e
--- /dev/null
+++ b/tests/testfile32.bz2
Binary files differ
diff --git a/tests/testfile33.bz2 b/tests/testfile33.bz2
new file mode 100644
index 0000000..f3dbc73
--- /dev/null
+++ b/tests/testfile33.bz2
Binary files differ
diff --git a/tests/testfile34.bz2 b/tests/testfile34.bz2
new file mode 100644
index 0000000..a417fcb
--- /dev/null
+++ b/tests/testfile34.bz2
Binary files differ
diff --git a/tests/testfile35.bz2 b/tests/testfile35.bz2
new file mode 100644
index 0000000..b591301
--- /dev/null
+++ b/tests/testfile35.bz2
Binary files differ
diff --git a/tests/testfile35.debug.bz2 b/tests/testfile35.debug.bz2
new file mode 100644
index 0000000..f191862
--- /dev/null
+++ b/tests/testfile35.debug.bz2
Binary files differ
diff --git a/tests/testfile36.bz2 b/tests/testfile36.bz2
new file mode 100644
index 0000000..e912a19
--- /dev/null
+++ b/tests/testfile36.bz2
Binary files differ
diff --git a/tests/testfile36.debug.bz2 b/tests/testfile36.debug.bz2
new file mode 100644
index 0000000..76aca42
--- /dev/null
+++ b/tests/testfile36.debug.bz2
Binary files differ
diff --git a/tests/testfile37.bz2 b/tests/testfile37.bz2
new file mode 100644
index 0000000..254ce32
--- /dev/null
+++ b/tests/testfile37.bz2
Binary files differ
diff --git a/tests/testfile37.debug.bz2 b/tests/testfile37.debug.bz2
new file mode 100644
index 0000000..74e46a8
--- /dev/null
+++ b/tests/testfile37.debug.bz2
Binary files differ
diff --git a/tests/testfile38.bz2 b/tests/testfile38.bz2
new file mode 100644
index 0000000..42adb77
--- /dev/null
+++ b/tests/testfile38.bz2
Binary files differ
diff --git a/tests/testfile39.bz2 b/tests/testfile39.bz2
new file mode 100644
index 0000000..42d0fbc
--- /dev/null
+++ b/tests/testfile39.bz2
Binary files differ
diff --git a/tests/testfile4.bz2 b/tests/testfile4.bz2
new file mode 100644
index 0000000..25b25df
--- /dev/null
+++ b/tests/testfile4.bz2
Binary files differ
diff --git a/tests/testfile40.bz2 b/tests/testfile40.bz2
new file mode 100644
index 0000000..ad41985
--- /dev/null
+++ b/tests/testfile40.bz2
Binary files differ
diff --git a/tests/testfile40.debug.bz2 b/tests/testfile40.debug.bz2
new file mode 100644
index 0000000..2eec4d7
--- /dev/null
+++ b/tests/testfile40.debug.bz2
Binary files differ
diff --git a/tests/testfile41.bz2 b/tests/testfile41.bz2
new file mode 100644
index 0000000..f9bf5a4
--- /dev/null
+++ b/tests/testfile41.bz2
Binary files differ
diff --git a/tests/testfile42.bz2 b/tests/testfile42.bz2
new file mode 100644
index 0000000..2530aba
--- /dev/null
+++ b/tests/testfile42.bz2
Binary files differ
diff --git a/tests/testfile42_noshdrs.bz2 b/tests/testfile42_noshdrs.bz2
new file mode 100644
index 0000000..e50f750
--- /dev/null
+++ b/tests/testfile42_noshdrs.bz2
Binary files differ
diff --git a/tests/testfile43.bz2 b/tests/testfile43.bz2
new file mode 100644
index 0000000..c99db24
--- /dev/null
+++ b/tests/testfile43.bz2
Binary files differ
diff --git a/tests/testfile44.S.bz2 b/tests/testfile44.S.bz2
new file mode 100644
index 0000000..4e87434
--- /dev/null
+++ b/tests/testfile44.S.bz2
Binary files differ
diff --git a/tests/testfile44.expect.bz2 b/tests/testfile44.expect.bz2
new file mode 100644
index 0000000..b3937b9
--- /dev/null
+++ b/tests/testfile44.expect.bz2
Binary files differ
diff --git a/tests/testfile45.S.bz2 b/tests/testfile45.S.bz2
new file mode 100644
index 0000000..00e819e
--- /dev/null
+++ b/tests/testfile45.S.bz2
Binary files differ
diff --git a/tests/testfile45.expect.bz2 b/tests/testfile45.expect.bz2
new file mode 100644
index 0000000..e502e15
--- /dev/null
+++ b/tests/testfile45.expect.bz2
Binary files differ
diff --git a/tests/testfile46.bz2 b/tests/testfile46.bz2
new file mode 100644
index 0000000..db83b27
--- /dev/null
+++ b/tests/testfile46.bz2
Binary files differ
diff --git a/tests/testfile47.bz2 b/tests/testfile47.bz2
new file mode 100644
index 0000000..334bd6c
--- /dev/null
+++ b/tests/testfile47.bz2
Binary files differ
diff --git a/tests/testfile48.bz2 b/tests/testfile48.bz2
new file mode 100644
index 0000000..da0d9da
--- /dev/null
+++ b/tests/testfile48.bz2
Binary files differ
diff --git a/tests/testfile48.debug.bz2 b/tests/testfile48.debug.bz2
new file mode 100644
index 0000000..7b84c4c
--- /dev/null
+++ b/tests/testfile48.debug.bz2
Binary files differ
diff --git a/tests/testfile49.bz2 b/tests/testfile49.bz2
new file mode 100644
index 0000000..8741a6b
--- /dev/null
+++ b/tests/testfile49.bz2
Binary files differ
diff --git a/tests/testfile5.bz2 b/tests/testfile5.bz2
new file mode 100644
index 0000000..247313e
--- /dev/null
+++ b/tests/testfile5.bz2
Binary files differ
diff --git a/tests/testfile50.bz2 b/tests/testfile50.bz2
new file mode 100644
index 0000000..fce4332
--- /dev/null
+++ b/tests/testfile50.bz2
Binary files differ
diff --git a/tests/testfile51.bz2 b/tests/testfile51.bz2
new file mode 100755
index 0000000..5ff45c6
--- /dev/null
+++ b/tests/testfile51.bz2
Binary files differ
diff --git a/tests/testfile52-32.noshdrs.so.bz2 b/tests/testfile52-32.noshdrs.so.bz2
new file mode 100755
index 0000000..01d2742
--- /dev/null
+++ b/tests/testfile52-32.noshdrs.so.bz2
Binary files differ
diff --git a/tests/testfile52-32.prelink.so.bz2 b/tests/testfile52-32.prelink.so.bz2
new file mode 100755
index 0000000..ccb9ae3
--- /dev/null
+++ b/tests/testfile52-32.prelink.so.bz2
Binary files differ
diff --git a/tests/testfile52-32.so.bz2 b/tests/testfile52-32.so.bz2
new file mode 100755
index 0000000..2a5b56e
--- /dev/null
+++ b/tests/testfile52-32.so.bz2
Binary files differ
diff --git a/tests/testfile52-32.so.debug.bz2 b/tests/testfile52-32.so.debug.bz2
new file mode 100755
index 0000000..818b36d
--- /dev/null
+++ b/tests/testfile52-32.so.debug.bz2
Binary files differ
diff --git a/tests/testfile52-64.noshdrs.so.bz2 b/tests/testfile52-64.noshdrs.so.bz2
new file mode 100755
index 0000000..5ca310f
--- /dev/null
+++ b/tests/testfile52-64.noshdrs.so.bz2
Binary files differ
diff --git a/tests/testfile52-64.prelink.so.bz2 b/tests/testfile52-64.prelink.so.bz2
new file mode 100755
index 0000000..8cb8f48
--- /dev/null
+++ b/tests/testfile52-64.prelink.so.bz2
Binary files differ
diff --git a/tests/testfile52-64.so.bz2 b/tests/testfile52-64.so.bz2
new file mode 100755
index 0000000..8009f07
--- /dev/null
+++ b/tests/testfile52-64.so.bz2
Binary files differ
diff --git a/tests/testfile52-64.so.debug.bz2 b/tests/testfile52-64.so.debug.bz2
new file mode 100755
index 0000000..4397788
--- /dev/null
+++ b/tests/testfile52-64.so.debug.bz2
Binary files differ
diff --git a/tests/testfile53-32.bz2 b/tests/testfile53-32.bz2
new file mode 100755
index 0000000..7bf48d9
--- /dev/null
+++ b/tests/testfile53-32.bz2
Binary files differ
diff --git a/tests/testfile53-32.debug.bz2 b/tests/testfile53-32.debug.bz2
new file mode 100755
index 0000000..79ea566
--- /dev/null
+++ b/tests/testfile53-32.debug.bz2
Binary files differ
diff --git a/tests/testfile53-32.prelink.bz2 b/tests/testfile53-32.prelink.bz2
new file mode 100755
index 0000000..8e05abf
--- /dev/null
+++ b/tests/testfile53-32.prelink.bz2
Binary files differ
diff --git a/tests/testfile53-64.bz2 b/tests/testfile53-64.bz2
new file mode 100755
index 0000000..235a763
--- /dev/null
+++ b/tests/testfile53-64.bz2
Binary files differ
diff --git a/tests/testfile53-64.debug.bz2 b/tests/testfile53-64.debug.bz2
new file mode 100755
index 0000000..675c6ea
--- /dev/null
+++ b/tests/testfile53-64.debug.bz2
Binary files differ
diff --git a/tests/testfile53-64.prelink.bz2 b/tests/testfile53-64.prelink.bz2
new file mode 100755
index 0000000..853aba7
--- /dev/null
+++ b/tests/testfile53-64.prelink.bz2
Binary files differ
diff --git a/tests/testfile54-32.noshdrs.so.bz2 b/tests/testfile54-32.noshdrs.so.bz2
new file mode 100755
index 0000000..846bc91
--- /dev/null
+++ b/tests/testfile54-32.noshdrs.so.bz2
Binary files differ
diff --git a/tests/testfile54-32.prelink.so.bz2 b/tests/testfile54-32.prelink.so.bz2
new file mode 100755
index 0000000..85c8526
--- /dev/null
+++ b/tests/testfile54-32.prelink.so.bz2
Binary files differ
diff --git a/tests/testfile54-32.so.bz2 b/tests/testfile54-32.so.bz2
new file mode 100755
index 0000000..4bc4fa3
--- /dev/null
+++ b/tests/testfile54-32.so.bz2
Binary files differ
diff --git a/tests/testfile54-32.so.debug.bz2 b/tests/testfile54-32.so.debug.bz2
new file mode 100755
index 0000000..79dd614
--- /dev/null
+++ b/tests/testfile54-32.so.debug.bz2
Binary files differ
diff --git a/tests/testfile54-64.noshdrs.so.bz2 b/tests/testfile54-64.noshdrs.so.bz2
new file mode 100755
index 0000000..3da726a
--- /dev/null
+++ b/tests/testfile54-64.noshdrs.so.bz2
Binary files differ
diff --git a/tests/testfile54-64.prelink.so.bz2 b/tests/testfile54-64.prelink.so.bz2
new file mode 100755
index 0000000..e296a1d
--- /dev/null
+++ b/tests/testfile54-64.prelink.so.bz2
Binary files differ
diff --git a/tests/testfile54-64.so.bz2 b/tests/testfile54-64.so.bz2
new file mode 100755
index 0000000..6072bf1
--- /dev/null
+++ b/tests/testfile54-64.so.bz2
Binary files differ
diff --git a/tests/testfile54-64.so.debug.bz2 b/tests/testfile54-64.so.debug.bz2
new file mode 100755
index 0000000..6b45390
--- /dev/null
+++ b/tests/testfile54-64.so.debug.bz2
Binary files differ
diff --git a/tests/testfile55-32.bz2 b/tests/testfile55-32.bz2
new file mode 100755
index 0000000..d4cc986
--- /dev/null
+++ b/tests/testfile55-32.bz2
Binary files differ
diff --git a/tests/testfile55-32.debug.bz2 b/tests/testfile55-32.debug.bz2
new file mode 100755
index 0000000..c5aa3f6
--- /dev/null
+++ b/tests/testfile55-32.debug.bz2
Binary files differ
diff --git a/tests/testfile55-32.prelink.bz2 b/tests/testfile55-32.prelink.bz2
new file mode 100755
index 0000000..4fc171a
--- /dev/null
+++ b/tests/testfile55-32.prelink.bz2
Binary files differ
diff --git a/tests/testfile55-64.bz2 b/tests/testfile55-64.bz2
new file mode 100755
index 0000000..27341fa
--- /dev/null
+++ b/tests/testfile55-64.bz2
Binary files differ
diff --git a/tests/testfile55-64.debug.bz2 b/tests/testfile55-64.debug.bz2
new file mode 100755
index 0000000..d975c70
--- /dev/null
+++ b/tests/testfile55-64.debug.bz2
Binary files differ
diff --git a/tests/testfile55-64.prelink.bz2 b/tests/testfile55-64.prelink.bz2
new file mode 100755
index 0000000..a4338fe
--- /dev/null
+++ b/tests/testfile55-64.prelink.bz2
Binary files differ
diff --git a/tests/testfile56.bz2 b/tests/testfile56.bz2
new file mode 100644
index 0000000..0e2257c
--- /dev/null
+++ b/tests/testfile56.bz2
Binary files differ
diff --git a/tests/testfile57.bz2 b/tests/testfile57.bz2
new file mode 100644
index 0000000..59dbde1
--- /dev/null
+++ b/tests/testfile57.bz2
Binary files differ
diff --git a/tests/testfile58.bz2 b/tests/testfile58.bz2
new file mode 100644
index 0000000..839efd9
--- /dev/null
+++ b/tests/testfile58.bz2
Binary files differ
diff --git a/tests/testfile59.bz2 b/tests/testfile59.bz2
new file mode 100755
index 0000000..bcee648
--- /dev/null
+++ b/tests/testfile59.bz2
Binary files differ
diff --git a/tests/testfile6.bz2 b/tests/testfile6.bz2
new file mode 100644
index 0000000..fd376b2
--- /dev/null
+++ b/tests/testfile6.bz2
Binary files differ
diff --git a/tests/testfile61.bz2 b/tests/testfile61.bz2
new file mode 100644
index 0000000..d139389
--- /dev/null
+++ b/tests/testfile61.bz2
Binary files differ
diff --git a/tests/testfile62.bz2 b/tests/testfile62.bz2
new file mode 100644
index 0000000..8a42cf6
--- /dev/null
+++ b/tests/testfile62.bz2
Binary files differ
diff --git a/tests/testfile63.bz2 b/tests/testfile63.bz2
new file mode 100644
index 0000000..4be87cd
--- /dev/null
+++ b/tests/testfile63.bz2
Binary files differ
diff --git a/tests/testfile64.bz2 b/tests/testfile64.bz2
new file mode 100644
index 0000000..674bd53
--- /dev/null
+++ b/tests/testfile64.bz2
Binary files differ
diff --git a/tests/testfile65.bz2 b/tests/testfile65.bz2
new file mode 100644
index 0000000..5e925f8
--- /dev/null
+++ b/tests/testfile65.bz2
Binary files differ
diff --git a/tests/testfile66.bz2 b/tests/testfile66.bz2
new file mode 100755
index 0000000..4797590
--- /dev/null
+++ b/tests/testfile66.bz2
Binary files differ
diff --git a/tests/testfile66.core.bz2 b/tests/testfile66.core.bz2
new file mode 100644
index 0000000..12e2d44
--- /dev/null
+++ b/tests/testfile66.core.bz2
Binary files differ
diff --git a/tests/testfile67.bz2 b/tests/testfile67.bz2
new file mode 100644
index 0000000..bb64745
--- /dev/null
+++ b/tests/testfile67.bz2
Binary files differ
diff --git a/tests/testfile68.bz2 b/tests/testfile68.bz2
new file mode 100644
index 0000000..3fe6792
--- /dev/null
+++ b/tests/testfile68.bz2
Binary files differ
diff --git a/tests/testfile69.core.bz2 b/tests/testfile69.core.bz2
new file mode 100644
index 0000000..9955318
--- /dev/null
+++ b/tests/testfile69.core.bz2
Binary files differ
diff --git a/tests/testfile69.so.bz2 b/tests/testfile69.so.bz2
new file mode 100755
index 0000000..fdddab9
--- /dev/null
+++ b/tests/testfile69.so.bz2
Binary files differ
diff --git a/tests/testfile7.bz2 b/tests/testfile7.bz2
new file mode 100644
index 0000000..73452bb
--- /dev/null
+++ b/tests/testfile7.bz2
Binary files differ
diff --git a/tests/testfile70.core.bz2 b/tests/testfile70.core.bz2
new file mode 100644
index 0000000..6c47c6d
--- /dev/null
+++ b/tests/testfile70.core.bz2
Binary files differ
diff --git a/tests/testfile70.exec.bz2 b/tests/testfile70.exec.bz2
new file mode 100644
index 0000000..f1b969a
--- /dev/null
+++ b/tests/testfile70.exec.bz2
Binary files differ
diff --git a/tests/testfile71.bz2 b/tests/testfile71.bz2
new file mode 100644
index 0000000..ce5b08f
--- /dev/null
+++ b/tests/testfile71.bz2
Binary files differ
diff --git a/tests/testfile8.bz2 b/tests/testfile8.bz2
new file mode 100644
index 0000000..1ff4994
--- /dev/null
+++ b/tests/testfile8.bz2
Binary files differ
diff --git a/tests/testfile9.bz2 b/tests/testfile9.bz2
new file mode 100644
index 0000000..40454bc
--- /dev/null
+++ b/tests/testfile9.bz2
Binary files differ
diff --git a/tests/testfile_aarch64_core.bz2 b/tests/testfile_aarch64_core.bz2
new file mode 100644
index 0000000..9d56268
--- /dev/null
+++ b/tests/testfile_aarch64_core.bz2
Binary files differ
diff --git a/tests/testfile_class_func.bz2 b/tests/testfile_class_func.bz2
new file mode 100755
index 0000000..e40dcf2
--- /dev/null
+++ b/tests/testfile_class_func.bz2
Binary files differ
diff --git a/tests/testfile_const_type.bz2 b/tests/testfile_const_type.bz2
new file mode 100755
index 0000000..fea4a9c
--- /dev/null
+++ b/tests/testfile_const_type.bz2
Binary files differ
diff --git a/tests/testfile_const_type.c b/tests/testfile_const_type.c
new file mode 100644
index 0000000..259007d
--- /dev/null
+++ b/tests/testfile_const_type.c
@@ -0,0 +1,14 @@
+// gcc -m32 -g -O2 -o const_type const_type.c
+
+__attribute__((noinline, noclone)) int
+f1 (long long d)
+{
+  long long w = d / 0x1234567800000LL;
+  return w;
+}
+
+int
+main ()
+{
+  return f1 (4LL) - f1 (4LL);
+}
diff --git a/tests/testfile_entry_value.bz2 b/tests/testfile_entry_value.bz2
new file mode 100755
index 0000000..fde86c6
--- /dev/null
+++ b/tests/testfile_entry_value.bz2
Binary files differ
diff --git a/tests/testfile_entry_value.c b/tests/testfile_entry_value.c
new file mode 100644
index 0000000..d2f232b
--- /dev/null
+++ b/tests/testfile_entry_value.c
@@ -0,0 +1,19 @@
+// gcc -g -O2 -o entry_value entry_value.c
+int __attribute__((noinline, noclone)) foo (int x, int y)
+{
+  return x + y;
+}
+
+int __attribute__((noinline, noclone)) bar (int x, int y)
+{
+  int z;
+  z = foo (x, y);
+  z += foo (y, x);
+  return z;
+}
+
+int
+main (int argc, char **argv)
+{
+  return bar (argc + 1, argc - 1);
+}
diff --git a/tests/testfile_gnu_props.32be.o.bz2 b/tests/testfile_gnu_props.32be.o.bz2
new file mode 100644
index 0000000..60a39fe
--- /dev/null
+++ b/tests/testfile_gnu_props.32be.o.bz2
Binary files differ
diff --git a/tests/testfile_gnu_props.32le.o.bz2 b/tests/testfile_gnu_props.32le.o.bz2
new file mode 100644
index 0000000..cb5d23c
--- /dev/null
+++ b/tests/testfile_gnu_props.32le.o.bz2
Binary files differ
diff --git a/tests/testfile_gnu_props.64be.o.bz2 b/tests/testfile_gnu_props.64be.o.bz2
new file mode 100644
index 0000000..784c98b
--- /dev/null
+++ b/tests/testfile_gnu_props.64be.o.bz2
Binary files differ
diff --git a/tests/testfile_gnu_props.64le.o.bz2 b/tests/testfile_gnu_props.64le.o.bz2
new file mode 100644
index 0000000..09df3d1
--- /dev/null
+++ b/tests/testfile_gnu_props.64le.o.bz2
Binary files differ
diff --git a/tests/testfile_i686_core.bz2 b/tests/testfile_i686_core.bz2
new file mode 100644
index 0000000..8412776
--- /dev/null
+++ b/tests/testfile_i686_core.bz2
Binary files differ
diff --git a/tests/testfile_implicit_pointer.bz2 b/tests/testfile_implicit_pointer.bz2
new file mode 100755
index 0000000..72f6a69
--- /dev/null
+++ b/tests/testfile_implicit_pointer.bz2
Binary files differ
diff --git a/tests/testfile_implicit_pointer.c b/tests/testfile_implicit_pointer.c
new file mode 100644
index 0000000..d7e28a0
--- /dev/null
+++ b/tests/testfile_implicit_pointer.c
@@ -0,0 +1,12 @@
+// gcc -g -O2 -o implicit_pointer implicit_pointer.c
+
+static __attribute__((noinline, noclone)) int foo (int i)
+{
+  int *p = &i;
+  return *p;
+}
+
+int main (void)
+{
+  return foo (23) - 23;
+}
diff --git a/tests/testfile_implicit_value.bz2 b/tests/testfile_implicit_value.bz2
new file mode 100755
index 0000000..c365a99
--- /dev/null
+++ b/tests/testfile_implicit_value.bz2
Binary files differ
diff --git a/tests/testfile_implicit_value.c b/tests/testfile_implicit_value.c
new file mode 100644
index 0000000..8885bbf
--- /dev/null
+++ b/tests/testfile_implicit_value.c
@@ -0,0 +1,12 @@
+// gcc -m32 -g -O2 -o implicit_value implicit_value.c
+
+static __attribute__((noinline, noclone)) int foo ()
+{
+  unsigned long long a[] = { 2, 21 };
+  return a[0] * a[1];
+}
+
+int main (void)
+{
+  return foo () - 42;
+}
diff --git a/tests/testfile_low_high_pc.bz2 b/tests/testfile_low_high_pc.bz2
new file mode 100755
index 0000000..f20814a
--- /dev/null
+++ b/tests/testfile_low_high_pc.bz2
Binary files differ
diff --git a/tests/testfile_multi.dwz.bz2 b/tests/testfile_multi.dwz.bz2
new file mode 100644
index 0000000..1f52fb6
--- /dev/null
+++ b/tests/testfile_multi.dwz.bz2
Binary files differ
diff --git a/tests/testfile_multi_main.bz2 b/tests/testfile_multi_main.bz2
new file mode 100755
index 0000000..bc6ca5f
--- /dev/null
+++ b/tests/testfile_multi_main.bz2
Binary files differ
diff --git a/tests/testfile_multi_noline.bz2 b/tests/testfile_multi_noline.bz2
new file mode 100755
index 0000000..39320d1
--- /dev/null
+++ b/tests/testfile_multi_noline.bz2
Binary files differ
diff --git a/tests/testfile_nested_funcs.bz2 b/tests/testfile_nested_funcs.bz2
new file mode 100755
index 0000000..d36b603
--- /dev/null
+++ b/tests/testfile_nested_funcs.bz2
Binary files differ
diff --git a/tests/testfile_nvidia_linemap.bz2 b/tests/testfile_nvidia_linemap.bz2
new file mode 100644
index 0000000..8a6d09f
--- /dev/null
+++ b/tests/testfile_nvidia_linemap.bz2
Binary files differ
diff --git a/tests/testfile_parameter_ref.bz2 b/tests/testfile_parameter_ref.bz2
new file mode 100755
index 0000000..8ff900d
--- /dev/null
+++ b/tests/testfile_parameter_ref.bz2
Binary files differ
diff --git a/tests/testfile_parameter_ref.c b/tests/testfile_parameter_ref.c
new file mode 100644
index 0000000..7fe985f
--- /dev/null
+++ b/tests/testfile_parameter_ref.c
@@ -0,0 +1,20 @@
+// gcc -g -O2 -o parameter_ref parameter_ref.c
+
+volatile int vv;
+
+/* Don't inline, but do allow clone to create specialized versions.  */
+static __attribute__((noinline)) int
+foo (int x, int y, int z)
+{
+  int a = x * 2;
+  int b = y * 2;
+  int c = z * 2;
+  vv++;
+  return x + z;
+}
+
+int
+main (int x, char **argv)
+{
+  return foo (x, 2, 3) + foo (x, 4, 3) + foo (x + 6, x, 3) + x;
+}
diff --git a/tests/testfile_pt_gnu_prop.bz2 b/tests/testfile_pt_gnu_prop.bz2
new file mode 100755
index 0000000..f030fb9
--- /dev/null
+++ b/tests/testfile_pt_gnu_prop.bz2
Binary files differ
diff --git a/tests/testfile_pt_gnu_prop32.bz2 b/tests/testfile_pt_gnu_prop32.bz2
new file mode 100755
index 0000000..6a7515a
--- /dev/null
+++ b/tests/testfile_pt_gnu_prop32.bz2
Binary files differ
diff --git a/tests/testfileaarch64-debugframe.bz2 b/tests/testfileaarch64-debugframe.bz2
new file mode 100755
index 0000000..e77494a
--- /dev/null
+++ b/tests/testfileaarch64-debugframe.bz2
Binary files differ
diff --git a/tests/testfileaarch64.bz2 b/tests/testfileaarch64.bz2
new file mode 100755
index 0000000..72e5ef0
--- /dev/null
+++ b/tests/testfileaarch64.bz2
Binary files differ
diff --git a/tests/testfilearm-debugframe.bz2 b/tests/testfilearm-debugframe.bz2
new file mode 100755
index 0000000..51ce2d3
--- /dev/null
+++ b/tests/testfilearm-debugframe.bz2
Binary files differ
diff --git a/tests/testfilearm.bz2 b/tests/testfilearm.bz2
new file mode 100755
index 0000000..d6cd090
--- /dev/null
+++ b/tests/testfilearm.bz2
Binary files differ
diff --git a/tests/testfilebasmin.bz2 b/tests/testfilebasmin.bz2
new file mode 100755
index 0000000..3843972
--- /dev/null
+++ b/tests/testfilebasmin.bz2
Binary files differ
diff --git a/tests/testfilebaxmin.bz2 b/tests/testfilebaxmin.bz2
new file mode 100755
index 0000000..c450cc8
--- /dev/null
+++ b/tests/testfilebaxmin.bz2
Binary files differ
diff --git a/tests/testfilebazdbg.bz2 b/tests/testfilebazdbg.bz2
new file mode 100755
index 0000000..8e58636
--- /dev/null
+++ b/tests/testfilebazdbg.bz2
Binary files differ
diff --git a/tests/testfilebazdbg.debug.bz2 b/tests/testfilebazdbg.debug.bz2
new file mode 100755
index 0000000..3b01176
--- /dev/null
+++ b/tests/testfilebazdbg.debug.bz2
Binary files differ
diff --git a/tests/testfilebazdbg_pl.bz2 b/tests/testfilebazdbg_pl.bz2
new file mode 100755
index 0000000..9e06a80
--- /dev/null
+++ b/tests/testfilebazdbg_pl.bz2
Binary files differ
diff --git a/tests/testfilebazdbg_plr.bz2 b/tests/testfilebazdbg_plr.bz2
new file mode 100755
index 0000000..1bc43dd
--- /dev/null
+++ b/tests/testfilebazdbg_plr.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64.bz2 b/tests/testfilebazdbgppc64.bz2
new file mode 100755
index 0000000..17e77d6
--- /dev/null
+++ b/tests/testfilebazdbgppc64.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64.debug.bz2 b/tests/testfilebazdbgppc64.debug.bz2
new file mode 100755
index 0000000..8faa17a
--- /dev/null
+++ b/tests/testfilebazdbgppc64.debug.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64_pl.bz2 b/tests/testfilebazdbgppc64_pl.bz2
new file mode 100755
index 0000000..9f372fb
--- /dev/null
+++ b/tests/testfilebazdbgppc64_pl.bz2
Binary files differ
diff --git a/tests/testfilebazdbgppc64_plr.bz2 b/tests/testfilebazdbgppc64_plr.bz2
new file mode 100755
index 0000000..70f8e00
--- /dev/null
+++ b/tests/testfilebazdbgppc64_plr.bz2
Binary files differ
diff --git a/tests/testfilebazdyn.bz2 b/tests/testfilebazdyn.bz2
new file mode 100755
index 0000000..bb623bb
--- /dev/null
+++ b/tests/testfilebazdyn.bz2
Binary files differ
diff --git a/tests/testfilebazdynppc64.bz2 b/tests/testfilebazdynppc64.bz2
new file mode 100755
index 0000000..2e01699
--- /dev/null
+++ b/tests/testfilebazdynppc64.bz2
Binary files differ
diff --git a/tests/testfilebazmdb.bz2 b/tests/testfilebazmdb.bz2
new file mode 100755
index 0000000..561eca1
--- /dev/null
+++ b/tests/testfilebazmdb.bz2
Binary files differ
diff --git a/tests/testfilebazmdbppc64.bz2 b/tests/testfilebazmdbppc64.bz2
new file mode 100755
index 0000000..16c2dd0
--- /dev/null
+++ b/tests/testfilebazmdbppc64.bz2
Binary files differ
diff --git a/tests/testfilebazmin.bz2 b/tests/testfilebazmin.bz2
new file mode 100755
index 0000000..12bcc6b
--- /dev/null
+++ b/tests/testfilebazmin.bz2
Binary files differ
diff --git a/tests/testfilebazmin_pl.bz2 b/tests/testfilebazmin_pl.bz2
new file mode 100755
index 0000000..73cef4a
--- /dev/null
+++ b/tests/testfilebazmin_pl.bz2
Binary files differ
diff --git a/tests/testfilebazmin_plr.bz2 b/tests/testfilebazmin_plr.bz2
new file mode 100755
index 0000000..e4fcf85
--- /dev/null
+++ b/tests/testfilebazmin_plr.bz2
Binary files differ
diff --git a/tests/testfilebazminppc64.bz2 b/tests/testfilebazminppc64.bz2
new file mode 100755
index 0000000..364d84c
--- /dev/null
+++ b/tests/testfilebazminppc64.bz2
Binary files differ
diff --git a/tests/testfilebazminppc64_pl.bz2 b/tests/testfilebazminppc64_pl.bz2
new file mode 100755
index 0000000..6686340
--- /dev/null
+++ b/tests/testfilebazminppc64_pl.bz2
Binary files differ
diff --git a/tests/testfilebazminppc64_plr.bz2 b/tests/testfilebazminppc64_plr.bz2
new file mode 100755
index 0000000..4610285
--- /dev/null
+++ b/tests/testfilebazminppc64_plr.bz2
Binary files differ
diff --git a/tests/testfilebaztab.bz2 b/tests/testfilebaztab.bz2
new file mode 100755
index 0000000..a99b739
--- /dev/null
+++ b/tests/testfilebaztab.bz2
Binary files differ
diff --git a/tests/testfilebaztabppc64.bz2 b/tests/testfilebaztabppc64.bz2
new file mode 100755
index 0000000..03afb8c
--- /dev/null
+++ b/tests/testfilebaztabppc64.bz2
Binary files differ
diff --git a/tests/testfilecsky.bz2 b/tests/testfilecsky.bz2
new file mode 100644
index 0000000..dfee449
--- /dev/null
+++ b/tests/testfilecsky.bz2
Binary files differ
diff --git a/tests/testfiledwarfinlines.bz2 b/tests/testfiledwarfinlines.bz2
new file mode 100755
index 0000000..db14f81
--- /dev/null
+++ b/tests/testfiledwarfinlines.bz2
Binary files differ
diff --git a/tests/testfiledwarfinlines.core.bz2 b/tests/testfiledwarfinlines.core.bz2
new file mode 100644
index 0000000..2299e1e
--- /dev/null
+++ b/tests/testfiledwarfinlines.core.bz2
Binary files differ
diff --git a/tests/testfilefoobarbaz.bz2 b/tests/testfilefoobarbaz.bz2
new file mode 100755
index 0000000..0e721ff
--- /dev/null
+++ b/tests/testfilefoobarbaz.bz2
Binary files differ
diff --git a/tests/testfilegdbindex5.bz2 b/tests/testfilegdbindex5.bz2
new file mode 100755
index 0000000..45ee945
--- /dev/null
+++ b/tests/testfilegdbindex5.bz2
Binary files differ
diff --git a/tests/testfilegdbindex7.bz2 b/tests/testfilegdbindex7.bz2
new file mode 100755
index 0000000..2a7c6c2
--- /dev/null
+++ b/tests/testfilegdbindex7.bz2
Binary files differ
diff --git a/tests/testfilegdbindex9-no-maininfo.bz2 b/tests/testfilegdbindex9-no-maininfo.bz2
new file mode 100755
index 0000000..043b8d3
--- /dev/null
+++ b/tests/testfilegdbindex9-no-maininfo.bz2
Binary files differ
diff --git a/tests/testfilegdbindex9.bz2 b/tests/testfilegdbindex9.bz2
new file mode 100755
index 0000000..9a2c189
--- /dev/null
+++ b/tests/testfilegdbindex9.bz2
Binary files differ
diff --git a/tests/testfileloc.bz2 b/tests/testfileloc.bz2
new file mode 100755
index 0000000..a436965
--- /dev/null
+++ b/tests/testfileloc.bz2
Binary files differ
diff --git a/tests/testfilemacro.bz2 b/tests/testfilemacro.bz2
new file mode 100755
index 0000000..7db51ff
--- /dev/null
+++ b/tests/testfilemacro.bz2
Binary files differ
diff --git a/tests/testfilenolines.bz2 b/tests/testfilenolines.bz2
new file mode 100755
index 0000000..23cd722
--- /dev/null
+++ b/tests/testfilenolines.bz2
Binary files differ
diff --git a/tests/testfileppc32-debugframe.bz2 b/tests/testfileppc32-debugframe.bz2
new file mode 100755
index 0000000..b6ae4ea
--- /dev/null
+++ b/tests/testfileppc32-debugframe.bz2
Binary files differ
diff --git a/tests/testfileppc32.bz2 b/tests/testfileppc32.bz2
new file mode 100755
index 0000000..f57763a
--- /dev/null
+++ b/tests/testfileppc32.bz2
Binary files differ
diff --git a/tests/testfileppc32attrs.o.bz2 b/tests/testfileppc32attrs.o.bz2
new file mode 100644
index 0000000..c8d80a9
--- /dev/null
+++ b/tests/testfileppc32attrs.o.bz2
Binary files differ
diff --git a/tests/testfileppc64-debugframe.bz2 b/tests/testfileppc64-debugframe.bz2
new file mode 100755
index 0000000..85c80ac
--- /dev/null
+++ b/tests/testfileppc64-debugframe.bz2
Binary files differ
diff --git a/tests/testfileppc64.bz2 b/tests/testfileppc64.bz2
new file mode 100755
index 0000000..870046b
--- /dev/null
+++ b/tests/testfileppc64.bz2
Binary files differ
diff --git a/tests/testfileppc64attrs.o.bz2 b/tests/testfileppc64attrs.o.bz2
new file mode 100644
index 0000000..5af2ab6
--- /dev/null
+++ b/tests/testfileppc64attrs.o.bz2
Binary files differ
diff --git a/tests/testfileranges4.debug.bz2 b/tests/testfileranges4.debug.bz2
new file mode 100755
index 0000000..67ba573
--- /dev/null
+++ b/tests/testfileranges4.debug.bz2
Binary files differ
diff --git a/tests/testfileranges5.debug.bz2 b/tests/testfileranges5.debug.bz2
new file mode 100755
index 0000000..ef28efc
--- /dev/null
+++ b/tests/testfileranges5.debug.bz2
Binary files differ
diff --git a/tests/testfiles390.bz2 b/tests/testfiles390.bz2
new file mode 100755
index 0000000..14ebf6c
--- /dev/null
+++ b/tests/testfiles390.bz2
Binary files differ
diff --git a/tests/testfiles390x.bz2 b/tests/testfiles390x.bz2
new file mode 100755
index 0000000..eb63ed8
--- /dev/null
+++ b/tests/testfiles390x.bz2
Binary files differ
diff --git a/tests/testfilesparc64attrs.o.bz2 b/tests/testfilesparc64attrs.o.bz2
new file mode 100644
index 0000000..7be7f88
--- /dev/null
+++ b/tests/testfilesparc64attrs.o.bz2
Binary files differ
diff --git a/tests/testfilesplitranges4.debug.bz2 b/tests/testfilesplitranges4.debug.bz2
new file mode 100755
index 0000000..df8e3ac
--- /dev/null
+++ b/tests/testfilesplitranges4.debug.bz2
Binary files differ
diff --git a/tests/testfilesplitranges5.debug.bz2 b/tests/testfilesplitranges5.debug.bz2
new file mode 100755
index 0000000..5796cbf
--- /dev/null
+++ b/tests/testfilesplitranges5.debug.bz2
Binary files differ
diff --git a/tests/testfilesyms32.bz2 b/tests/testfilesyms32.bz2
new file mode 100644
index 0000000..b3b7812
--- /dev/null
+++ b/tests/testfilesyms32.bz2
Binary files differ
diff --git a/tests/testfilesyms64.bz2 b/tests/testfilesyms64.bz2
new file mode 100644
index 0000000..cdec381
--- /dev/null
+++ b/tests/testfilesyms64.bz2
Binary files differ
diff --git a/tests/testlib_dynseg.so.bz2 b/tests/testlib_dynseg.so.bz2
new file mode 100755
index 0000000..94296a4
--- /dev/null
+++ b/tests/testlib_dynseg.so.bz2
Binary files differ
diff --git a/tests/typeiter.c b/tests/typeiter.c
new file mode 100644
index 0000000..dff4526
--- /dev/null
+++ b/tests/typeiter.c
@@ -0,0 +1,90 @@
+/* Copyright (C) 2012 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+#include <dwarf.h>
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; ++i)
+    {
+      int fd = open (argv[i], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg != NULL)
+	{
+	  Dwarf_Off off = 0;
+	  size_t cuhl;
+	  Dwarf_Off noff;
+
+	  while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+	    {
+	      Dwarf_Die die_mem;
+	      Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem);
+
+	      Dwarf_Die iter_mem;
+	      Dwarf_Die *iter = &iter_mem;
+	      dwarf_child (die, &iter_mem);
+
+	      while (1)
+		{
+		  if (dwarf_tag (iter) == DW_TAG_variable)
+		    {
+		      Dwarf_Attribute attr_mem;
+		      Dwarf_Die form_mem;
+		      dwarf_formref_die (dwarf_attr (iter, DW_AT_type,
+						     &attr_mem),
+					 &form_mem);
+		    }
+
+		  if (dwarf_siblingof (iter, &iter_mem) != 0)
+		    break;
+		}
+
+	      off = noff;
+	    }
+
+	  off = 0;
+	  uint64_t type_sig;
+
+	  while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL,
+				  NULL, &type_sig, NULL) == 0)
+	    {
+	      Dwarf_Die die_mem;
+	      Dwarf_Die *die = dwarf_offdie_types (dbg, off + cuhl, &die_mem);
+
+	      if (die == NULL)
+		printf ("fail\n");
+	      else
+		printf ("ok\n");
+
+	      off = noff;
+	    }
+
+	  dwarf_end (dbg);
+	}
+
+      close (fd);
+    }
+}
diff --git a/tests/typeiter2.c b/tests/typeiter2.c
new file mode 100644
index 0000000..35b6a12
--- /dev/null
+++ b/tests/typeiter2.c
@@ -0,0 +1,91 @@
+/* Copyright (C) 2012, 2013, 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <fcntl.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <unistd.h>
+#include <dwarf.h>
+#include <inttypes.h>
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; ++i)
+    {
+      int fd = open (argv[i], O_RDONLY);
+
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg != NULL)
+	{
+	  Dwarf_Off off = 0;
+	  size_t cuhl;
+	  Dwarf_Off noff;
+	  uint64_t type_sig;
+
+	  while (dwarf_next_unit (dbg, off, &noff, &cuhl, NULL, NULL, NULL,
+				  NULL, &type_sig, NULL) == 0)
+	    {
+	      Dwarf_Die die_mem;
+	      dwarf_offdie_types (dbg, off + cuhl, &die_mem);
+	      off = noff;
+	    }
+
+	  off = 0;
+
+	  while (dwarf_nextcu (dbg, off, &noff, &cuhl, NULL, NULL, NULL) == 0)
+	    {
+	      Dwarf_Die die_mem;
+	      Dwarf_Die *die = dwarf_offdie (dbg, off + cuhl, &die_mem);
+
+	      Dwarf_Die iter_mem;
+	      Dwarf_Die *iter = &iter_mem;
+	      dwarf_child (die, &iter_mem);
+
+	      while (1)
+		{
+		  if (dwarf_tag (iter) == DW_TAG_variable)
+		    {
+		      Dwarf_Attribute attr_mem;
+		      Dwarf_Die form_mem, *form;
+		      form = dwarf_formref_die (dwarf_attr (iter, DW_AT_type,
+							    &attr_mem),
+						&form_mem);
+
+		      if (form == NULL)
+			printf ("fail\n");
+		      else
+			printf ("ok %s [%" PRIx64 "]\n",
+				dwarf_diename (form), dwarf_dieoffset (form));
+		    }
+
+		  if (dwarf_siblingof (iter, &iter_mem) != 0)
+		    break;
+		}
+
+	      off = noff;
+	    }
+
+	  dwarf_end (dbg);
+	}
+
+      close (fd);
+    }
+}
diff --git a/tests/unit-info.c b/tests/unit-info.c
new file mode 100644
index 0000000..4fb9a98
--- /dev/null
+++ b/tests/unit-info.c
@@ -0,0 +1,323 @@
+/* Test dwarf_cu_info properties.
+   Copyright (C) 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include ELFUTILS_HEADER(dw)
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+/* Yeah, lazy, 16K CUs should be enough for everybody... */
+#define MAX_UNITS 16384
+struct info
+{
+  int dietag;
+  int subtag;
+  Dwarf_Half version;
+  uint8_t unit_type;
+  uint64_t id;
+  uint8_t addr_size;
+  uint8_t off_size;
+};
+static struct info unit_info[MAX_UNITS];
+
+int
+main (int argc, char *argv[])
+{
+  for (int i = 1; i < argc; i++)
+    {
+      printf ("file: %s\n", argv[i]);
+      int fd = open (argv[i], O_RDONLY);
+      Dwarf *dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      Dwarf_CU *cu = NULL;
+      Dwarf_Half version;
+      Dwarf_Die cudie, subdie;
+      uint8_t unit_type;
+      size_t u, units;
+      u = units = 0;
+      printf ("Iterate getting all info, compare with dwarf_cu_info.\n");
+      while (dwarf_get_units (dbg, cu, &cu, &version,
+			      &unit_type, &cudie, &subdie) == 0)
+	{
+	  int dietag = dwarf_tag (&cudie);
+	  int subtag = dwarf_tag (&subdie);
+
+	  unit_info[u].dietag = dietag;
+	  unit_info[u].subtag = subtag;
+	  unit_info[u].version = version;
+	  unit_info[u].unit_type = unit_type;
+
+	  printf ("%zu cu dietag: %x, subtag: %x, version %" PRIx32
+		  ", unit_type %" PRIx8 "\n",
+		  u, dietag, subtag, version, unit_type);
+
+	  uint64_t unit_id;
+	  uint8_t addr_size, off_size;
+	  if (dwarf_cu_info (cu,
+			     &version, &unit_type, &cudie, &subdie,
+			     &unit_id, &addr_size, &off_size) != 0)
+	    {
+	      printf ("Invalid dwarf_cu_info: %s\n", dwarf_errmsg (-1));
+	      return -1;
+	    }
+
+	  dietag = dwarf_tag (&cudie);
+	  subtag = dwarf_tag (&subdie);
+
+	  if (unit_info[u].dietag != dietag)
+	    {
+	      printf("Unequal dietags\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].subtag != subtag)
+	    {
+	      printf("Unequal subtags\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].version != version)
+	    {
+	      printf("Unequal versions\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].unit_type != unit_type)
+	    {
+	      printf("Unequal unit_types\n");
+	      return -1;
+	    }
+
+	  unit_info[u].id = unit_id;
+	  unit_info[u].addr_size = addr_size;
+	  unit_info[u].off_size = off_size;
+
+	  if (unit_type == DW_UT_skeleton)
+	    {
+	      if (dwarf_cu_info (subdie.cu,
+				 &version, &unit_type, &cudie, &subdie,
+				 &unit_id, &addr_size, &off_size) != 0)
+		{
+		  printf ("Invalid subdie dwarf_cu_info: %s\n",
+			  dwarf_errmsg (-1));
+		  return -1;
+		}
+
+	      dietag = dwarf_tag (&cudie);
+	      subtag = dwarf_tag (&subdie);
+
+	      printf ("%zu subdietag: %x, subtag: %x, version %" PRIx32
+		      ", unit_type %" PRIx8 "\n",
+		      u, dietag, subtag, version, unit_type);
+
+	      /* subdie is now cudie.  */
+	      if (unit_info[u].subtag != dietag)
+	      {
+		printf ("Inconsistent subdie tag\n");
+		return -1;
+	      }
+
+	      if (unit_info[u].id != unit_id)
+		{
+		  printf ("Unequal subdie ids\n");
+		  return -1;
+		}
+
+	      if (unit_info[u].addr_size != addr_size)
+		{
+		  printf ("Unequal subdie addr_size\n");
+		  return -1;
+		}
+
+	      if (unit_info[u].off_size != off_size)
+		{
+		  printf ("Unequal subdie off_size\n");
+		  return -1;
+		}
+	    }
+
+	  if (u >= MAX_UNITS)
+	    {
+	      printf ("Oops, more than 16K units...\n");
+	      return -1;
+	    }
+	  u = ++units;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+
+      /* And again... */
+      printf ("rechecking: %s\n", argv[i]);
+      fd = open (argv[i], O_RDONLY);
+      dbg = dwarf_begin (fd, DWARF_C_READ);
+      if (dbg == NULL)
+	{
+	  printf ("%s not usable: %s\n", argv[i], dwarf_errmsg (-1));
+	  return -1;
+	}
+
+      cu = NULL;
+      u = 0;
+      printf ("Iterate no info, compare recorded info with dwarf_cu_info.\n");
+      while (dwarf_get_units (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
+	{
+	  if (u > units)
+	    {
+	      printf ("Got too many units???\n");
+	      return -1;
+	    }
+
+	  uint64_t unit_id;
+	  uint8_t addr_size, off_size;
+	  if (dwarf_cu_info (cu,
+			     &version, &unit_type, &cudie, &subdie,
+			     &unit_id, &addr_size, &off_size) != 0)
+	    {
+	      printf ("Invalid dwarf_cu_info: %s\n", dwarf_errmsg (-1));
+	      return -1;
+	    }
+
+	  int dietag = dwarf_tag (&cudie);
+	  int subtag = dwarf_tag (&subdie);
+
+	  printf ("%zu re dietag: %x, subtag: %x, version %" PRIx32
+		  ", unit_type %" PRIx8 "\n",
+		  u, dietag, subtag, version, unit_type);
+
+	  if (unit_info[u].dietag != dietag)
+	    {
+	      printf("Unequal dietags %x != %x\n", unit_info[u].dietag, dietag);
+	      return -1;
+	    }
+
+	  if (unit_info[u].subtag != subtag)
+	    {
+	      printf("Unequal subtags\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].version != version)
+	    {
+	      printf("Unequal versions\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].unit_type != unit_type)
+	    {
+	      printf("Unequal unit_types\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].id != unit_id)
+	    {
+	      printf ("Unequal subdie ids\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].addr_size != addr_size)
+	    {
+	      printf ("Unequal subdie addr_size\n");
+	      return -1;
+	    }
+
+	  if (unit_info[u].off_size != off_size)
+	    {
+	      printf ("Unequal subdie off_size\n");
+	      return -1;
+	    }
+
+	  if (unit_type == DW_UT_skeleton)
+	    {
+	      if (dwarf_cu_info (subdie.cu,
+				 &version, &unit_type, &cudie, &subdie,
+				 &unit_id, &addr_size, &off_size) != 0)
+		{
+		  printf ("Invalid subdie dwarf_cu_info: %s\n",
+			  dwarf_errmsg (-1));
+		  return -1;
+		}
+
+	      dietag = dwarf_tag (&cudie);
+	      subtag = dwarf_tag (&subdie);
+
+	      printf ("%zu subdietag: %x, subtag: %x, version %" PRIx32
+		      ", unit_type %" PRIx8 "\n",
+		      u, dietag, subtag, version, unit_type);
+
+	      /* subdie is now cudie.  */
+	      subtag = dwarf_tag (&cudie);
+	      if (unit_info[u].subtag != subtag)
+	      {
+		printf ("Inconsistent subdie tag\n");
+		return -1;
+	      }
+
+	      if (unit_info[u].id != unit_id)
+		{
+		  printf ("Unequal subdie ids\n");
+		  return -1;
+		}
+
+	      if (unit_info[u].addr_size != addr_size)
+		{
+		  printf ("Unequal subdie addr_size\n");
+		  return -1;
+		}
+
+	      if (unit_info[u].off_size != off_size)
+		{
+		  printf ("Unequal subdie off_size\n");
+		  return -1;
+		}
+	    }
+
+	  if (u >= MAX_UNITS)
+	    {
+	      printf ("Oops, more than 16K units...\n");
+	      return -1;
+	    }
+	  u++;
+	}
+
+      if (u != units)
+	{
+	  printf ("Got not enough units???\n");
+	  return -1;
+	}
+
+      dwarf_end (dbg);
+      close (fd);
+
+      printf ("\n");
+    }
+
+  return 0;
+}
diff --git a/tests/update1.c b/tests/update1.c
new file mode 100644
index 0000000..b7be4e5
--- /dev/null
+++ b/tests/update1.c
@@ -0,0 +1,128 @@
+/* Test program for elf_update function.
+   Copyright (C) 2000, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+
+int
+main (int argc, char *argv[] __attribute__ ((unused)))
+{
+  const char *fname = "xxx_update1";
+  int fd;
+  Elf *elf;
+  Elf32_Ehdr *ehdr;
+  int i;
+
+  fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Create an ELF header.  */
+  ehdr = elf32_newehdr (elf);
+  if (ehdr == NULL)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  ehdr->e_ident[0] = 42;
+  ehdr->e_ident[4] = 1;
+  ehdr->e_ident[5] = 1;
+  ehdr->e_ident[6] = 2;
+  ehdr->e_ident[9] = 2;
+  ehdr->e_version = 1;
+  ehdr->e_ehsize = 1;
+
+  /* Write out the file.  */
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Create an ELF header.  */
+  ehdr = elf32_newehdr (elf);
+  if (ehdr == NULL)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  unlink (fname);
+
+  return 0;
+}
diff --git a/tests/update2.c b/tests/update2.c
new file mode 100644
index 0000000..7145563
--- /dev/null
+++ b/tests/update2.c
@@ -0,0 +1,151 @@
+/* Test program for elf_update function.
+   Copyright (C) 2000, 2002, 2005 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+
+int
+main (int argc, char *argv[] __attribute__ ((unused)))
+{
+  const char *fname = "xxx_update2";
+  int fd;
+  Elf *elf;
+  Elf32_Ehdr *ehdr;
+  Elf32_Phdr *phdr;
+  int i;
+
+  fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Create an ELF header.  */
+  ehdr = elf32_newehdr (elf);
+  if (ehdr == NULL)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  ehdr->e_ident[0] = 42;
+  ehdr->e_ident[4] = 1;
+  ehdr->e_ident[5] = 1;
+  ehdr->e_ident[6] = 2;
+  ehdr->e_type = ET_EXEC;
+  ehdr->e_version = 1;
+  ehdr->e_ehsize = 1;
+  elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  /* Create the program header.  */
+  phdr = elf32_newphdr (elf, 1);
+  if (phdr == NULL)
+    {
+      printf ("cannot create program header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  phdr[0].p_type = PT_PHDR;
+  elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  /* Let the library compute the internal structure information.  */
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  ehdr = elf32_getehdr (elf);
+
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_vaddr = ehdr->e_phoff;
+  phdr[0].p_paddr = ehdr->e_phoff;
+  phdr[0].p_flags = PF_R | PF_X;
+  phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_align = sizeof (Elf32_Word);
+
+  /* Write out the file.  */
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  unlink (fname);
+
+  return 0;
+}
diff --git a/tests/update3.c b/tests/update3.c
new file mode 100644
index 0000000..62f67f7
--- /dev/null
+++ b/tests/update3.c
@@ -0,0 +1,206 @@
+/* Test program for elf_update function.
+   Copyright (C) 2000, 2002, 2005, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(dwelf)
+
+
+int
+main (int argc, char *argv[] __attribute__ ((unused)))
+{
+  const char *fname = "xxx_update3";
+  int fd;
+  Elf *elf;
+  Elf32_Ehdr *ehdr;
+  Elf32_Phdr *phdr;
+  Elf_Scn *scn;
+  Elf32_Shdr *shdr;
+  Elf_Data *data;
+  Dwelf_Strtab *shst;
+  Dwelf_Strent *shstrtabse;
+  int i;
+
+  fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  elf_fill (0x42);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Create an ELF header.  */
+  ehdr = elf32_newehdr (elf);
+  if (ehdr == NULL)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  ehdr->e_ident[0] = 42;
+  ehdr->e_ident[4] = 1;
+  ehdr->e_ident[5] = 1;
+  ehdr->e_ident[6] = 2;
+  ehdr->e_type = ET_EXEC;
+  ehdr->e_version = 1;
+  ehdr->e_ehsize = 1;
+  elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  /* Create the program header.  */
+  phdr = elf32_newphdr (elf, 1);
+  if (phdr == NULL)
+    {
+      printf ("cannot create program header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  phdr[0].p_type = PT_PHDR;
+  elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  shst = dwelf_strtab_init (true);
+
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shstrtabse = dwelf_strtab_add (shst, ".shstrtab");
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_addralign = 1;
+  shdr->sh_entsize = 0;
+
+  /* We have to store the section index in the ELF header.  */
+  ehdr->e_shstrndx = elf_ndxscn (scn);
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* No more sections, finalize the section header string table.  */
+  dwelf_strtab_finalize (shst, data);
+
+  shdr->sh_name = dwelf_strent_off (shstrtabse);
+
+  /* Let the library compute the internal structure information.  */
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  ehdr = elf32_getehdr (elf);
+
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_vaddr = ehdr->e_phoff;
+  phdr[0].p_paddr = ehdr->e_phoff;
+  phdr[0].p_flags = PF_R | PF_X;
+  phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_align = sizeof (Elf32_Word);
+
+  /* Write out the file.  */
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* We don't need the string table anymore.  */
+  dwelf_strtab_free (shst);
+
+  /* And the data allocated in the .shstrtab section.  */
+  free (data->d_buf);
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  unlink (fname);
+
+  return 0;
+}
diff --git a/tests/update4.c b/tests/update4.c
new file mode 100644
index 0000000..a703b59
--- /dev/null
+++ b/tests/update4.c
@@ -0,0 +1,358 @@
+/* Test program for elf_update function.
+   Copyright (C) 2000, 2001, 2002, 2005, 2016 Red Hat, Inc.
+   This file is part of elfutils.
+   Written by Ulrich Drepper <drepper@redhat.com>, 2000.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <libelf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(dwelf)
+
+
+int
+main (int argc, char *argv[] __attribute__ ((unused)))
+{
+  const char fname[] = "xxx_update4";
+  int fd;
+  Elf *elf;
+  Elf32_Ehdr *ehdr;
+  Elf32_Phdr *phdr;
+  Elf_Scn *scn;
+  Elf32_Shdr *shdr;
+  Elf_Data *data;
+  Dwelf_Strtab *shst;
+  Dwelf_Strent *firstse;
+  Dwelf_Strent *secondse;
+  Dwelf_Strent *thirdse;
+  Dwelf_Strent *fourthse;
+  Dwelf_Strent *shstrtabse;
+  int i;
+
+  fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf_version (EV_CURRENT);
+
+  elf_fill (0x42);
+
+  elf = elf_begin (fd, ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Create an ELF header.  */
+  ehdr = elf32_newehdr (elf);
+  if (ehdr == NULL)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  ehdr->e_ident[0] = 42;
+  ehdr->e_ident[4] = 1;
+  ehdr->e_ident[5] = 1;
+  ehdr->e_ident[6] = 2;
+  ehdr->e_type = ET_EXEC;
+  ehdr->e_version = 1;
+  ehdr->e_ehsize = 1;
+  elf_flagehdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  /* Create the program header.  */
+  phdr = elf32_newphdr (elf, 1);
+  if (phdr == NULL)
+    {
+      printf ("cannot create program header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  phdr[0].p_type = PT_PHDR;
+  elf_flagphdr (elf, ELF_C_SET, ELF_F_DIRTY);
+
+  shst = dwelf_strtab_init (true);
+
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create first section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for first section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  firstse = dwelf_strtab_add (shst, ".first");
+
+  shdr->sh_type = SHT_PROGBITS;
+  shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+  shdr->sh_addr = 0;
+  shdr->sh_link = 0;
+  shdr->sh_info = 0;
+  shdr->sh_entsize = 1;
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data first section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = "hello";
+  data->d_type = ELF_T_BYTE;
+  data->d_version = EV_CURRENT;
+  data->d_size = 5;
+  data->d_align = 16;
+
+
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create second section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for second section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  secondse = dwelf_strtab_add (shst, ".second");
+
+  shdr->sh_type = SHT_PROGBITS;
+  shdr->sh_flags = SHF_ALLOC | SHF_WRITE;
+  shdr->sh_addr = 0;
+  shdr->sh_link = 0;
+  shdr->sh_info = 0;
+  shdr->sh_entsize = 1;
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data second section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = "world";
+  data->d_type = ELF_T_BYTE;
+  data->d_version = EV_CURRENT;
+  data->d_size = 5;
+  data->d_align = 16;
+
+
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create third section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for third section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  thirdse = dwelf_strtab_add (shst, ".third");
+
+  shdr->sh_type = SHT_PROGBITS;
+  shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+  shdr->sh_addr = 0;
+  shdr->sh_link = 0;
+  shdr->sh_info = 0;
+  shdr->sh_entsize = 1;
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data third section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = "!!!!!";
+  data->d_type = ELF_T_BYTE;
+  data->d_version = EV_CURRENT;
+  data->d_size = 5;
+  data->d_align = 16;
+
+
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create fourth section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for fourth section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  fourthse = dwelf_strtab_add (shst, ".fourth");
+
+  shdr->sh_type = SHT_NOBITS;
+  shdr->sh_flags = SHF_ALLOC | SHF_EXECINSTR;
+  shdr->sh_addr = 0;
+  shdr->sh_link = 0;
+  shdr->sh_info = 0;
+  shdr->sh_entsize = 1;
+  shdr->sh_size = 100;
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data fourth section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  data->d_buf = NULL;
+  data->d_type = ELF_T_BYTE;
+  data->d_version = EV_CURRENT;
+  data->d_size = 100;
+  data->d_align = 16;
+
+
+  scn = elf_newscn (elf);
+  if (scn == NULL)
+    {
+      printf ("cannot create SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+  shdr = elf32_getshdr (scn);
+  if (shdr == NULL)
+    {
+      printf ("cannot get header for SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  shstrtabse = dwelf_strtab_add (shst, ".shstrtab");
+
+  shdr->sh_type = SHT_STRTAB;
+  shdr->sh_flags = 0;
+  shdr->sh_addr = 0;
+  shdr->sh_link = SHN_UNDEF;
+  shdr->sh_info = SHN_UNDEF;
+  shdr->sh_entsize = 1;
+
+  /* We have to store the section index in the ELF header.  */
+  ehdr->e_shstrndx = elf_ndxscn (scn);
+
+  data = elf_newdata (scn);
+  if (data == NULL)
+    {
+      printf ("cannot create data SHSTRTAB section: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* No more sections, finalize the section header string table.  */
+  dwelf_strtab_finalize (shst, data);
+
+  elf32_getshdr (elf_getscn (elf, 1))->sh_name = dwelf_strent_off (firstse);
+  elf32_getshdr (elf_getscn (elf, 2))->sh_name = dwelf_strent_off (secondse);
+  elf32_getshdr (elf_getscn (elf, 3))->sh_name = dwelf_strent_off (thirdse);
+  elf32_getshdr (elf_getscn (elf, 4))->sh_name = dwelf_strent_off (fourthse);
+  shdr->sh_name = dwelf_strent_off (shstrtabse);
+
+  /* Let the library compute the internal structure information.  */
+  if (elf_update (elf, ELF_C_NULL) < 0)
+    {
+      printf ("failure in elf_update(NULL): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  ehdr = elf32_getehdr (elf);
+
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_offset = ehdr->e_phoff;
+  phdr[0].p_vaddr = ehdr->e_phoff;
+  phdr[0].p_paddr = ehdr->e_phoff;
+  phdr[0].p_flags = PF_R | PF_X;
+  phdr[0].p_filesz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_memsz = ehdr->e_phnum * elf32_fsize (ELF_T_PHDR, 1, EV_CURRENT);
+  phdr[0].p_align = sizeof (Elf32_Word);
+
+  /* Write out the file.  */
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* We don't need the string table anymore.  */
+  dwelf_strtab_free (shst);
+
+  /* And the data allocated in the .shstrtab section.  */
+  free (data->d_buf);
+
+  /* Print the ELF header values.  */
+  if (argc > 1)
+    {
+      for (i = 0; i < EI_NIDENT; ++i)
+	printf (" %02x", ehdr->e_ident[i]);
+      printf ("\
+\ntype = %hu\nmachine = %hu\nversion = %u\nentry = %u\nphoff = %u\n"
+	      "shoff = %u\nflags = %u\nehsize = %hu\nphentsize = %hu\n"
+	      "phnum = %hu\nshentsize = %hu\nshnum = %hu\nshstrndx = %hu\n",
+	      ehdr->e_type, ehdr->e_machine, ehdr->e_version, ehdr->e_entry,
+	      ehdr->e_phoff, ehdr->e_shoff, ehdr->e_flags, ehdr->e_ehsize,
+	      ehdr->e_phentsize, ehdr->e_phnum, ehdr->e_shentsize,
+	      ehdr->e_shnum, ehdr->e_shstrndx);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  unlink (fname);
+
+  return 0;
+}
diff --git a/tests/varlocs.c b/tests/varlocs.c
new file mode 100644
index 0000000..1004f96
--- /dev/null
+++ b/tests/varlocs.c
@@ -0,0 +1,1167 @@
+/* Test program for dwarf location functions.
+   Copyright (C) 2013, 2015, 2017, 2018 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <argp.h>
+#include <inttypes.h>
+#include <errno.h>
+#include ELFUTILS_HEADER(dw)
+#include ELFUTILS_HEADER(dwfl)
+#include <dwarf.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include "system.h"
+#include "../libdw/known-dwarf.h"
+
+// The Dwarf, Dwarf_CFIs and address bias of
+// cfi table to adjust DWARF addresses against.
+// Needed for DW_OP_call_frame_cfa.
+static Dwarf *dw;
+Dwarf_CFI *cfi_debug;
+Dwarf_Addr cfi_debug_bias;
+Dwarf_CFI *cfi_eh;
+Dwarf_Addr cfi_eh_bias;
+
+bool is_ET_REL;
+bool is_debug;
+
+// Whether the current function has a DW_AT_frame_base defined.
+// Needed for DW_OP_fbreg.
+bool has_frame_base;
+
+static void
+print_die (Dwarf_Die *die, const char *what, int indent)
+{
+  Dwarf_Addr entrypc;
+  const char *name = dwarf_diename (die) ?: "<unknown>";
+  if (dwarf_entrypc (die, &entrypc) == 0)
+    printf ("%*s[%" PRIx64 "] %s '%s'@%" PRIx64 "\n", indent * 2, "",
+	    dwarf_dieoffset (die), what, name, entrypc);
+  else
+    printf ("%*s[%" PRIx64 "] %s '%s'\n", indent * 2, "",
+	    dwarf_dieoffset (die), what, name);
+}
+
+static const char *
+dwarf_encoding_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_ATE(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_ATE
+#undef DWARF_ONE_KNOWN_DW_ATE
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return "<unknown encoding>";
+}
+
+static const char *
+dwarf_tag_string (unsigned int tag)
+{
+  switch (tag)
+    {
+#define DWARF_ONE_KNOWN_DW_TAG(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_TAG
+#undef DWARF_ONE_KNOWN_DW_TAG
+    default:
+      return "<unknown tag>";
+    }
+}
+
+static const char *
+dwarf_attr_string (unsigned int attrnum)
+{
+  switch (attrnum)
+    {
+#define DWARF_ONE_KNOWN_DW_AT(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_AT
+#undef DWARF_ONE_KNOWN_DW_AT
+    default:
+      return "<unknown attr>";
+    }
+}
+
+static const char *
+dwarf_form_string (unsigned int form)
+{
+  switch (form)
+    {
+#define DWARF_ONE_KNOWN_DW_FORM(NAME, CODE) case CODE: return #NAME;
+      DWARF_ALL_KNOWN_DW_FORM
+#undef DWARF_ONE_KNOWN_DW_FORM
+    default:
+      return "<unknown form>";
+    }
+}
+
+/* BASE must be a base type DIE referenced by a typed DWARF expression op.  */
+static void
+print_base_type (Dwarf_Die *base)
+{
+  if (dwarf_tag (base) != DW_TAG_base_type)
+    error (EXIT_FAILURE, 0, "not a base type");
+
+  Dwarf_Attribute encoding;
+  Dwarf_Word enctype = 0;
+  if (dwarf_attr (base, DW_AT_encoding, &encoding) == NULL
+      || dwarf_formudata (&encoding, &enctype) != 0)
+    error (EXIT_FAILURE, 0, "base type without encoding");
+
+  Dwarf_Attribute bsize;
+  Dwarf_Word bits;
+  if (dwarf_attr (base, DW_AT_byte_size, &bsize) != NULL
+      && dwarf_formudata (&bsize, &bits) == 0)
+    bits *= 8;
+  else if (dwarf_attr (base, DW_AT_bit_size, &bsize) == NULL
+	   || dwarf_formudata (&bsize, &bits) != 0)
+    error (EXIT_FAILURE, 0, "base type without byte or bit size");
+
+  printf ("{%s,%s,%" PRIu64 "@[%" PRIx64 "]}",
+	  dwarf_diename (base),
+	  dwarf_encoding_string (enctype),
+	  bits,
+	  dwarf_dieoffset (base));
+}
+
+static const char *
+dwarf_opcode_string (unsigned int code)
+{
+  static const char *const known[] =
+    {
+#define DWARF_ONE_KNOWN_DW_OP(NAME, CODE) [CODE] = #NAME,
+      DWARF_ALL_KNOWN_DW_OP
+#undef DWARF_ONE_KNOWN_DW_OP
+    };
+
+  if (likely (code < sizeof (known) / sizeof (known[0])))
+    return known[code];
+
+  return "<unknown opcode>";
+}
+
+// Forward reference for print_expr_block.
+static void print_expr (Dwarf_Attribute *, Dwarf_Op *, Dwarf_Addr, int);
+
+static void
+print_expr_block (Dwarf_Attribute *attr, Dwarf_Op *exprs, int len,
+		  Dwarf_Addr addr, int depth)
+{
+  printf ("{");
+  for (int i = 0; i < len; i++)
+    {
+      print_expr (attr, &exprs[i], addr, depth);
+      printf ("%s", (i + 1 < len ? ", " : ""));
+    }
+  printf ("}");
+}
+
+static void
+print_expr_block_addrs (Dwarf_Attribute *attr,
+			Dwarf_Addr begin, Dwarf_Addr end,
+			Dwarf_Op *exprs, int len)
+{
+  printf ("      [%" PRIx64 ",%" PRIx64 ") ", begin, end);
+  print_expr_block (attr, exprs, len, begin, 0);
+  printf ("\n");
+}
+
+static void
+print_expr (Dwarf_Attribute *attr, Dwarf_Op *expr, Dwarf_Addr addr, int depth)
+{
+#define MAX_DEPTH 64
+  if (depth++ > MAX_DEPTH)
+    error (EXIT_FAILURE, 0, "print_expr recursion depth exceeded");
+
+  uint8_t atom = expr->atom;
+  const char *opname = dwarf_opcode_string (atom);
+
+  switch (atom)
+    {
+    case DW_OP_deref:
+    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_lit0 ... DW_OP_lit31:
+    case DW_OP_reg0 ... DW_OP_reg31:
+    case DW_OP_nop:
+    case DW_OP_stack_value:
+      /* No arguments. */
+      printf ("%s", opname);
+      break;
+
+    case DW_OP_form_tls_address:
+      /* No arguments. Special. Pops an address and pushes the
+	 corresponding address in the current thread local
+	 storage. Uses the thread local storage block of the defining
+	 module (executable, shared library). */
+      printf ("%s", opname);
+      break;
+
+    case DW_OP_GNU_push_tls_address:
+      /* No arguments. Special. Not the same as DW_OP_form_tls_address.
+	 Pops an offset into the current thread local strorage and
+	 pushes back the actual address. */
+      printf ("%s", opname);
+      break;
+
+    case DW_OP_GNU_uninit:
+      /* No arguments. Special. It means the expression describes
+	 an value which hasn't been initialized (yet).  */
+      printf ("%s", opname);
+      break;
+
+    case DW_OP_call_frame_cfa:
+      /* No arguments. Special. Pushes Call Frame Address as computed
+	 by CFI data (dwarf_cfi_addrframe will fetch that info (either from
+	 the .eh_frame or .debug_frame CFI) and dwarf_frame_cfa translatesr
+         the CFI instructions into a plain DWARF expression.
+	 Never used in CFI itself. */
+
+      if (attr == NULL)
+	error (EXIT_FAILURE, 0, "%s used in CFI", opname);
+
+      printf ("%s ", opname);
+      if (cfi_eh == NULL && cfi_debug == NULL && !is_debug)
+	error (EXIT_FAILURE, 0, "DW_OP_call_frame_cfa used but no cfi found.");
+
+      Dwarf_Frame *frame;
+      if (dwarf_cfi_addrframe (cfi_eh, addr + cfi_eh_bias, &frame) == 0
+	  || dwarf_cfi_addrframe (cfi_debug, addr + cfi_debug_bias,
+				  &frame) == 0)
+	{
+	  Dwarf_Op *cfa_ops;
+	  size_t cfa_nops;
+	  if (dwarf_frame_cfa (frame, &cfa_ops, &cfa_nops) != 0)
+	    error (EXIT_FAILURE, 0, "dwarf_frame_cfa 0x%" PRIx64 ": %s",
+		   addr, dwarf_errmsg (-1));
+	  if (cfa_nops < 1)
+	    error (EXIT_FAILURE, 0, "dwarf_frame_cfa no ops");
+	  print_expr_block (NULL, cfa_ops, cfa_nops, 0, depth);
+	  free (frame);
+	}
+      else if (is_ET_REL || is_debug)
+	{
+	  /* XXX In ET_REL files there might be an .eh_frame with relocations
+	     we don't handle (e.g. X86_64_PC32). Maybe we should?  */
+	  printf ("{...}");
+	}
+      else
+	error (EXIT_FAILURE, 0, "dwarf_cfi_addrframe 0x%" PRIx64 ": %s",
+	       addr, dwarf_errmsg (-1));
+      break;
+
+    case DW_OP_push_object_address:
+      /* No arguments. Special. Pushes object address explicitly.
+       Normally only done implicitly by DW_AT_data_member_location.
+       Never used in CFI. */
+      if (attr == NULL)
+	error (EXIT_FAILURE, 0, "%s used in CFI", opname);
+      printf ("%s", opname);
+      break;
+
+    case DW_OP_addr:
+      /* 1 address argument. */
+      printf ("%s(0x%" PRIx64 ")", opname, (Dwarf_Addr) expr->number);
+      break;
+
+    case DW_OP_const1u:
+    case DW_OP_const2u:
+    case DW_OP_const4u:
+    case DW_OP_const8u:
+    case DW_OP_constu:
+    case DW_OP_pick:
+    case DW_OP_plus_uconst:
+    case DW_OP_regx:
+    case DW_OP_piece:
+    case DW_OP_deref_size:
+    case DW_OP_xderef_size:
+      /* 1 numeric unsigned argument. */
+      printf ("%s(%" PRIu64 ")", opname, expr->number);
+      break;
+
+    case DW_OP_call2:
+    case DW_OP_call4:
+    case DW_OP_call_ref:
+      /* 1 DIE offset argument for more ops in location attribute of DIE.
+         Never used in CFI.  */
+      {
+	if (attr == NULL)
+	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
+
+	Dwarf_Attribute call_attr;
+	if (dwarf_getlocation_attr (attr, expr, &call_attr) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for %s error %s",
+		 opname, dwarf_errmsg (-1));
+
+	Dwarf_Die call_die;
+	if (dwarf_getlocation_die (attr, expr, &call_die) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die for %s error %s",
+		 opname, dwarf_errmsg (-1));
+
+	Dwarf_Op *call_ops;
+	size_t call_len;
+	if (dwarf_getlocation (&call_attr, &call_ops, &call_len) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&call_die));
+	print_expr_block (&call_attr, call_ops, call_len, addr, depth);
+      }
+      break;
+
+    case DW_OP_const1s:
+    case DW_OP_const2s:
+    case DW_OP_const4s:
+    case DW_OP_const8s:
+    case DW_OP_consts:
+    case DW_OP_skip:
+    case DW_OP_bra:
+    case DW_OP_breg0 ... DW_OP_breg31:
+      /* 1 numeric signed argument. */
+      printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
+      break;
+
+    case DW_OP_fbreg:
+      /* 1 numeric signed argument. Offset from frame base. */
+      if (attr == NULL)
+	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
+
+      if (! has_frame_base)
+	error (EXIT_FAILURE, 0, "DW_OP_fbreg used without a frame base");
+
+      printf ("%s(%" PRId64 ")", opname, (Dwarf_Sword) expr->number);
+      break;
+
+    case DW_OP_bregx:
+      /* 2 arguments, unsigned register number, signed offset. */
+      printf ("%s(%" PRIu64 ",%" PRId64 ")", opname,
+	      expr->number, (Dwarf_Sword) expr->number2);
+      break;
+
+    case DW_OP_bit_piece:
+      /* 2 arguments, unsigned size, unsigned offset. */
+      printf ("%s(%" PRIu64 ",%" PRIu64 ")", opname,
+	      expr->number, expr->number2);
+      break;
+
+    case DW_OP_implicit_value:
+      /* Special, unsigned size plus block. */
+      {
+	Dwarf_Attribute const_attr;
+	Dwarf_Block block;
+	if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
+		 dwarf_errmsg (-1));
+
+	if (dwarf_formblock (&const_attr, &block) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_formblock: %s",
+		 dwarf_errmsg (-1));
+
+	/* This is the "old" way. Check they result in the same.  */
+	Dwarf_Block block_impl;
+	if (dwarf_getlocation_implicit_value (attr, expr, &block_impl) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_value: %s",
+		 dwarf_errmsg (-1));
+
+	assert (expr->number == block.length);
+	assert (block.length == block_impl.length);
+	printf ("%s(%" PRIu64 "){", opname, block.length);
+	for (size_t i = 0; i < block.length; i++)
+	  {
+	    printf ("%02x", block.data[i]);
+	    assert (block.data[i] == block_impl.data[i]);
+	  }
+	printf("}");
+      }
+      break;
+
+    case DW_OP_implicit_pointer:
+    case DW_OP_GNU_implicit_pointer:
+      /* Special, DIE offset, signed offset. Referenced DIE has a
+	 location or const_value attribute. */
+      {
+	if (attr == NULL)
+	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
+
+	Dwarf_Attribute attrval;
+	if (dwarf_getlocation_implicit_pointer (attr, expr, &attrval) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_implicit_pointer: %s",
+		 dwarf_errmsg (-1));
+
+	// Sanity check, results should be the same.
+	Dwarf_Attribute attrval2;
+	if (dwarf_getlocation_attr (attr, expr, &attrval2) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
+		 dwarf_errmsg (-1));
+
+	assert (dwarf_whatattr (&attrval) == dwarf_whatattr (&attrval2));
+	assert (dwarf_whatform (&attrval) == dwarf_whatform (&attrval2));
+	// In theory two different valp pointers could point to the same
+	// value. But here we really expect them to be the equal.
+	assert (attrval.valp == attrval2.valp);
+
+	Dwarf_Die impl_die;
+	if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("%s([%" PRIx64 "],%" PRId64 ") ", opname,
+		dwarf_dieoffset (&impl_die), expr->number2);
+
+	if (dwarf_whatattr (&attrval) == DW_AT_const_value)
+	  printf ("<constant value>"); // Lookup type...
+	else
+	  {
+	    // Lookup the location description at the current address.
+	    Dwarf_Op *exprval;
+	    size_t exprval_len;
+	    int locs = dwarf_getlocation_addr (&attrval, addr,
+					       &exprval, &exprval_len, 1);
+	    if (locs == 0)
+	      printf ("<no location>"); // This means "optimized out".
+	    else if (locs == 1)
+	      print_expr_block (&attrval, exprval, exprval_len, addr, depth);
+	    else
+	      error (EXIT_FAILURE, 0,
+		     "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
+		     ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
+	  }
+      }
+      break;
+
+    case DW_OP_GNU_variable_value:
+      /* Special, DIE offset. Referenced DIE has a location or const_value
+	 attribute. */
+      {
+	if (attr == NULL)
+	  error (EXIT_FAILURE, 0, "%s used in CFI", opname);
+
+	Dwarf_Attribute attrval;
+	if (dwarf_getlocation_attr (attr, expr, &attrval) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
+		 dwarf_errmsg (-1));
+
+	Dwarf_Die impl_die;
+	if (dwarf_getlocation_die (attr, expr, &impl_die) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("%s([%" PRIx64 "]) ", opname, dwarf_dieoffset (&impl_die));
+
+	if (dwarf_whatattr (&attrval) == DW_AT_const_value)
+	  printf ("<constant value>"); // Lookup type...
+	else
+	  {
+	    // Lookup the location description at the current address.
+	    Dwarf_Op *exprval;
+	    size_t exprval_len;
+	    int locs = dwarf_getlocation_addr (&attrval, addr,
+					       &exprval, &exprval_len, 1);
+	    if (locs == 0)
+	      printf ("<no location>"); // This means "optimized out".
+	    else if (locs == 1)
+	      print_expr_block (&attrval, exprval, exprval_len, addr, depth);
+	    else
+	      error (EXIT_FAILURE, 0,
+		     "dwarf_getlocation_addr attrval at addr 0x%" PRIx64
+		     ", locs (%d): %s", addr, locs, dwarf_errmsg (-1));
+	  }
+      }
+      break;
+
+    case DW_OP_entry_value:
+    case DW_OP_GNU_entry_value:
+      /* Special, unsigned size plus expression block. All registers
+	 inside the block should be interpreted as they had on
+	 entering the function. dwarf_getlocation_attr will return an
+	 attribute containing the block as locexpr which can be
+	 retrieved with dwarf_getlocation.  */
+      {
+	Dwarf_Attribute entry_attr;
+	if (dwarf_getlocation_attr (attr, expr, &entry_attr) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr: %s",
+		 dwarf_errmsg (-1));
+
+	Dwarf_Op *entry_ops;
+	size_t entry_len;
+	if (dwarf_getlocation (&entry_attr, &entry_ops, &entry_len) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation for entry: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("%s(%zd) ", opname, entry_len);
+	print_expr_block (attr, entry_ops, entry_len, addr, depth);
+      }
+      break;
+
+    case DW_OP_GNU_parameter_ref:
+      /* Special, unsigned CU relative DIE offset pointing to a
+	 DW_TAG_formal_parameter. The value that parameter had at the
+	 call site of the current function will be put on the DWARF
+	 stack. The value can be retrieved by finding the
+	 DW_TAG_GNU_call_site_parameter which has as
+	 DW_AT_abstract_origin the same formal parameter DIE. */
+      {
+	Dwarf_Die param;
+	if (dwarf_getlocation_die (attr, expr, &param) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+	// XXX actually lookup DW_TAG_GNU_call_site_parameter
+	printf ("%s[%" PRIx64 "]", opname, dwarf_dieoffset (&param));
+	assert (expr->number == dwarf_cuoffset (&param));
+	if (dwarf_tag (&param) != DW_TAG_formal_parameter)
+	  error (EXIT_FAILURE, 0, "Not a formal parameter");
+      }
+      break;
+
+    case DW_OP_convert:
+    case DW_OP_GNU_convert:
+    case DW_OP_reinterpret:
+    case DW_OP_GNU_reinterpret:
+      /* Special, unsigned CU relative DIE offset pointing to a
+	 DW_TAG_base_type. Pops a value, converts or reinterprets the
+	 value to the given type. When the argument is zero the value
+	 becomes untyped again. */
+      {
+	Dwarf_Die type;
+	Dwarf_Off off = expr->number;
+	if (off != 0)
+	  {
+	    if (dwarf_getlocation_die (attr, expr, &type) != 0)
+	      error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		     dwarf_errmsg (-1));
+	    off = dwarf_dieoffset (&type);
+	    assert (expr->number == dwarf_cuoffset (&type));
+	    printf ("%s", opname);
+	    print_base_type (&type);
+	  }
+	else
+	  printf ("%s[%" PRIu64 "]", opname, off);
+
+      }
+      break;
+
+    case DW_OP_regval_type:
+    case DW_OP_GNU_regval_type:
+      /* Special, unsigned register number plus unsigned CU relative
+         DIE offset pointing to a DW_TAG_base_type. */
+      {
+	Dwarf_Die type;
+	if (dwarf_getlocation_die (attr, expr, &type) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+	assert (expr->number2 == dwarf_cuoffset (&type));
+	// XXX check size against base_type size?
+	printf ("%s(reg%" PRIu64 ")", opname, expr->number);
+	print_base_type (&type);
+      }
+      break;
+
+    case DW_OP_deref_type:
+    case DW_OP_GNU_deref_type:
+      /* Special, unsigned size plus unsigned CU relative DIE offset
+	 pointing to a DW_TAG_base_type. */
+      {
+	Dwarf_Die type;
+	if (dwarf_getlocation_die (attr, expr, &type) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+	assert (expr->number2 == dwarf_cuoffset (&type));
+	// XXX check size against base_type size?
+	printf ("%s(%" PRIu64 ")", opname, expr->number);
+	print_base_type (&type);
+      }
+      break;
+
+    case DW_OP_xderef_type:
+      /* Special, unsigned size plus unsigned DIE offset
+	 pointing to a DW_TAG_base_type. */
+      {
+	Dwarf_Die type;
+	if (dwarf_getlocation_die (attr, expr, &type) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+	// XXX check size against base_type size?
+	printf ("%s(%" PRIu64 ")", opname, expr->number);
+	print_base_type (&type);
+      }
+      break;
+
+    case DW_OP_const_type:
+    case DW_OP_GNU_const_type:
+      /* Special, unsigned CU relative DIE offset pointing to a
+	 DW_TAG_base_type, an unsigned size length plus a block with
+	 the constant value. */
+      {
+	Dwarf_Die type;
+	if (dwarf_getlocation_die (attr, expr, &type) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_die: %s",
+		 dwarf_errmsg (-1));
+	assert (expr->number == dwarf_cuoffset (&type));
+
+	Dwarf_Attribute const_attr;
+	if (dwarf_getlocation_attr (attr, expr, &const_attr) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for type: %s",
+		 dwarf_errmsg (-1));
+	  
+	Dwarf_Block block;
+	if (dwarf_formblock (&const_attr, &block) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_formblock for type: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("%s", opname);
+	print_base_type (&type);
+	printf ("(%" PRIu64 ")[", block.length);
+	for (size_t i = 0; i < block.length; i++)
+	  printf ("%02x", block.data[i]);
+	printf("]");
+      }
+      break;
+
+    case DW_OP_GNU_addr_index:
+    case DW_OP_addrx:
+      /* Address from the .debug_addr section (indexed based on CU).  */
+      {
+	Dwarf_Attribute addr_attr;
+	if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
+		 dwarf_errmsg (-1));
+
+	Dwarf_Addr address;
+	if (dwarf_formaddr (&addr_attr, &address) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_formaddr address failed: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("addr: 0x%" PRIx64, address);
+      }
+      break;
+
+    case DW_OP_GNU_const_index:
+    case DW_OP_constx:
+      /* Constant from the .debug_addr section (indexed based on CU).  */
+      {
+	Dwarf_Attribute addr_attr;
+	if (dwarf_getlocation_attr (attr, expr, &addr_attr) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_getlocation_attr for addr: %s",
+		 dwarf_errmsg (-1));
+
+	Dwarf_Word constant;
+	if (dwarf_formudata (&addr_attr, &constant) != 0)
+	  error (EXIT_FAILURE, 0, "dwarf_formudata constant failed: %s",
+		 dwarf_errmsg (-1));
+
+	printf ("const: 0x%" PRIx64, constant);
+      }
+      break;
+
+    default:
+      error (EXIT_FAILURE, 0, "unhandled opcode: DW_OP_%s (0x%x)",
+	     opname, atom);
+    }
+}
+
+/* Get all variables and print their value expressions. */
+static void
+print_varlocs (Dwarf_Die *funcdie)
+{
+  // Display frame base for function if it exists.
+  // Should be used for DW_OP_fbreg.
+  has_frame_base = dwarf_hasattr (funcdie, DW_AT_frame_base);
+  if (has_frame_base)
+    {
+      Dwarf_Attribute fb_attr;
+      if (dwarf_attr (funcdie, DW_AT_frame_base, &fb_attr) == NULL)
+	error (EXIT_FAILURE, 0, "dwarf_attr fb: %s", dwarf_errmsg (-1));
+
+      Dwarf_Op *fb_expr;
+      size_t fb_exprlen;
+      if (dwarf_getlocation (&fb_attr, &fb_expr, &fb_exprlen) == 0)
+	{
+	  // Covers all of function.
+	  Dwarf_Addr entrypc;
+	  if (dwarf_entrypc (funcdie, &entrypc) != 0)
+	    error (EXIT_FAILURE, 0, "dwarf_entrypc: %s", dwarf_errmsg (-1));
+
+	  printf ("    frame_base: ");
+	  if (entrypc == 0)
+	    printf ("XXX zero address"); // XXX bad DWARF?
+	  else
+	    print_expr_block (&fb_attr, fb_expr, fb_exprlen, entrypc, 0);
+	  printf ("\n");
+	}
+      else
+	{
+	  Dwarf_Addr base, start, end;
+	  ptrdiff_t off = 0;
+	  printf ("    frame_base:\n");
+          while ((off = dwarf_getlocations (&fb_attr, off, &base,
+					    &start, &end,
+					    &fb_expr, &fb_exprlen)) > 0)
+	    {
+	      printf ("      (%" PRIx64 ",%" PRIx64 ") ", start, end);
+	      print_expr_block (&fb_attr, fb_expr, fb_exprlen, start, 0);
+	      printf ("\n");
+	    }
+
+	  if (off < 0)
+	    error (EXIT_FAILURE, 0, "dwarf_getlocations fb: %s",
+		   dwarf_errmsg (-1));
+	}
+    }
+  else if (dwarf_tag (funcdie) == DW_TAG_inlined_subroutine)
+    {
+      // See whether the subprogram we are inlined into has a frame
+      // base we should use.
+      Dwarf_Die *scopes;
+      int n = dwarf_getscopes_die (funcdie, &scopes);
+      if (n <= 0)
+	error (EXIT_FAILURE, 0, "dwarf_getscopes_die: %s", dwarf_errmsg (-1));
+
+      while (n-- > 0)
+	if (dwarf_tag (&scopes[n]) == DW_TAG_subprogram
+	    && dwarf_hasattr (&scopes[n], DW_AT_frame_base))
+	  {
+	    has_frame_base = true;
+	    break;
+	  }
+      free (scopes);
+    }
+
+  if (! dwarf_haschildren (funcdie))
+    return;
+
+  Dwarf_Die child;
+  int res = dwarf_child (funcdie, &child);
+  if (res < 0)
+    error (EXIT_FAILURE, 0, "dwarf_child: %s", dwarf_errmsg (-1));
+
+  /* We thought there was a child, but the child list was actually
+     empty. This isn't technically an error in the DWARF, but it is
+     certainly non-optimimal.  */
+  if (res == 1)
+    return;
+
+  do
+    {
+      int tag = dwarf_tag (&child);
+      if (tag == DW_TAG_variable || tag == DW_TAG_formal_parameter)
+	{
+	  const char *what = tag == DW_TAG_variable ? "variable" : "parameter";
+	  print_die (&child, what, 2);
+
+	  if (dwarf_hasattr (&child, DW_AT_location))
+	    {
+	      Dwarf_Attribute attr;
+	      if (dwarf_attr (&child, DW_AT_location, &attr) == NULL)
+		error (EXIT_FAILURE, 0, "dwarf_attr: %s", dwarf_errmsg (-1));
+
+	      Dwarf_Op *expr;
+	      size_t exprlen;
+	      if (dwarf_getlocation (&attr, &expr, &exprlen) == 0)
+		{
+		  // Covers all ranges of the function.
+		  // Evaluate the expression block for each range.
+		  ptrdiff_t offset = 0;
+		  Dwarf_Addr base, begin, end;
+		  do
+		    {
+		      offset = dwarf_ranges (funcdie, offset, &base,
+					     &begin, &end);
+		      if (offset < 0)
+			error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
+			       dwarf_errmsg (-1));
+
+		      if (offset > 0)
+			{
+			  if (exprlen == 0)
+			    printf ("      (%"
+				    PRIx64 ",%" PRIx64
+				    ") <empty expression>\n", begin, end);
+			  else
+			    print_expr_block_addrs (&attr, begin, end,
+						    expr, exprlen);
+			}
+		    }
+		  while (offset > 0);
+
+		  if (offset < 0)
+		    error (EXIT_FAILURE, 0, "dwarf_ranges: %s",
+			   dwarf_errmsg (-1));
+		}
+	      else
+		{
+		  Dwarf_Addr base, begin, end;
+		  ptrdiff_t offset = 0;
+		  while ((offset = dwarf_getlocations (&attr, offset,
+						       &base, &begin, &end,
+						       &expr, &exprlen)) > 0)
+		    if (begin >= end)
+		      printf ("      (%" PRIx64 ",%" PRIx64
+			      ") <empty range>\n", begin, end); // XXX report?
+		    else
+		      {
+			print_expr_block_addrs (&attr, begin, end,
+						expr, exprlen);
+
+			// Extra sanity check for dwarf_getlocation_addr
+			// Must at least find one range for begin and end-1.
+			Dwarf_Op *expraddr;
+			size_t expraddr_len;
+			int locs = dwarf_getlocation_addr (&attr, begin,
+							   &expraddr,
+							   &expraddr_len, 1);
+			assert (locs == 1);
+			locs = dwarf_getlocation_addr (&attr, end - 1,
+						       &expraddr,
+						       &expraddr_len, 1);
+			assert (locs == 1);
+		      }
+
+		  if (offset < 0)
+		    error (EXIT_FAILURE, 0, "dwarf_getlocations: %s",
+			   dwarf_errmsg (-1));
+		}
+	    }
+	  else if (dwarf_hasattr (&child, DW_AT_const_value))
+	    {
+	      printf ("      <constant value>\n"); // Lookup type and print.
+	    }
+	  else
+	    {
+	      printf ("      <no value>\n");
+	    }
+	}
+    }
+  while (dwarf_siblingof (&child, &child) == 0);
+}
+
+static int
+handle_instance (Dwarf_Die *funcdie, void *arg __attribute__ ((unused)))
+{
+  print_die (funcdie, "inlined function", 1);
+  print_varlocs (funcdie);
+
+  return DWARF_CB_OK;
+}
+
+static int
+handle_function (Dwarf_Die *funcdie, void *arg __attribute__((unused)))
+{
+  if (dwarf_func_inline (funcdie) > 0)
+    {
+      // abstract inline definition, find all inlined instances.
+
+      // Note this is convenient for listing all instances together
+      // so you can easily compare the location expressions describing
+      // the variables and parameters, but it isn't very efficient
+      // since it will walk the DIE tree multiple times.
+      if (dwarf_func_inline_instances (funcdie, &handle_instance, NULL) != 0)
+	error (EXIT_FAILURE, 0, "dwarf_func_inline_instances: %s",
+	       dwarf_errmsg (-1));
+    }
+  else
+    {
+      // Contains actual code, not just a declaration?
+      Dwarf_Addr entrypc;
+      if (dwarf_entrypc (funcdie, &entrypc) == 0)
+	{
+	  print_die (funcdie, "function", 1);
+	  print_varlocs (funcdie);
+	}
+    }
+
+  return DWARF_CB_OK;
+}
+
+struct attr_arg
+{
+  int depth;
+  Dwarf_Addr entrypc;
+};
+
+static int
+handle_attr (Dwarf_Attribute *attr, void *arg)
+{
+  int depth = ((struct attr_arg *) arg)->depth;
+  Dwarf_Addr entrypc = ((struct attr_arg *) arg)->entrypc;
+
+  unsigned int code = dwarf_whatattr (attr);
+  unsigned int form = dwarf_whatform (attr);
+
+  printf ("%*s%s (%s)", depth * 2, "",
+	  dwarf_attr_string (code), dwarf_form_string (form));
+
+  /* If we can get an DWARF expression (or location lists) from this
+     attribute we'll print it, otherwise we'll ignore it.  But if
+     there is an error while the attribute has the "correct" form then
+     we'll report an error (we can only really check DW_FORM_exprloc
+     other forms can be ambiguous).  */
+  Dwarf_Op *expr;
+  size_t exprlen;
+  bool printed = false;
+  int res = dwarf_getlocation (attr, &expr, &exprlen);
+  if (res == 0)
+    {
+      printf (" ");
+      print_expr_block (attr, expr, exprlen, entrypc, 0);
+      printf ("\n");
+      printed = true;
+    }
+  else if (form == DW_FORM_exprloc)
+    {
+      error (0, 0, "%s dwarf_getlocation failed: %s",
+	     dwarf_attr_string (code), dwarf_errmsg (-1));
+      return DWARF_CB_ABORT;
+    }
+  else
+    {
+      Dwarf_Addr base, begin, end;
+      ptrdiff_t offset = 0;
+      while ((offset = dwarf_getlocations (attr, offset,
+					   &base, &begin, &end,
+					   &expr, &exprlen)) > 0)
+	{
+	  if (! printed)
+	    printf ("\n");
+	  printf ("%*s", depth * 2, "");
+	  print_expr_block_addrs (attr, begin, end, expr, exprlen);
+	  printed = true;
+	}
+    }
+
+  if (! printed)
+    printf ("\n");
+
+  return DWARF_CB_OK;
+}
+
+static void
+handle_die (Dwarf_Die *die, int depth, bool outer_has_frame_base,
+	    Dwarf_Addr outer_entrypc)
+{
+  /* CU DIE already printed.  */
+  if (depth > 0)
+    {
+      const char *name = dwarf_diename (die);
+      if (name != NULL)
+	printf ("%*s[%" PRIx64 "] %s \"%s\"\n", depth * 2, "",
+		dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)),
+		name);
+      else
+	printf ("%*s[%" PRIx64 "] %s\n", depth * 2, "",
+		dwarf_dieoffset (die), dwarf_tag_string (dwarf_tag (die)));
+    }
+
+  struct attr_arg arg;
+  arg.depth = depth + 1;
+
+  /* The (lowest) address to use for (looking up) operands that depend
+     on address.  */
+  Dwarf_Addr die_entrypc;
+  if (dwarf_entrypc (die, &die_entrypc) != 0 || die_entrypc == 0)
+    {
+      /* Try to get the lowest address of the first range covered.  */
+      Dwarf_Addr base, start, end;
+      if (dwarf_ranges (die, 0, &base, &start, &end) <= 0 || start == 0)
+	die_entrypc = outer_entrypc;
+      else
+	die_entrypc = start;
+    }
+  arg.entrypc = die_entrypc;
+
+  /* Whether this or the any outer DIE has a frame base. Used as
+     sanity check when printing expressions that use DW_OP_fbreg.  */
+  bool die_has_frame_base = dwarf_hasattr (die, DW_AT_frame_base);
+  die_has_frame_base |= outer_has_frame_base;
+  has_frame_base = die_has_frame_base;
+
+  /* Look through all attributes to find those that contain DWARF
+     expressions and print those.  We expect to handle all attributes,
+     anything else is an error.  */
+  if (dwarf_getattrs (die, handle_attr, &arg, 0) != 1)
+    error (EXIT_FAILURE, 0, "Couldn't get all attributes: %s",
+	   dwarf_errmsg (-1));
+
+  /* Handle children and siblings recursively depth first.  */
+  Dwarf_Die child;
+  if (dwarf_haschildren (die) != 0 && dwarf_child (die, &child) == 0)
+    handle_die (&child, depth + 1, die_has_frame_base, die_entrypc);
+
+  Dwarf_Die sibling;
+  if (dwarf_siblingof (die, &sibling) == 0)
+    handle_die (&sibling, depth, outer_has_frame_base, outer_entrypc);
+}
+
+int
+main (int argc, char *argv[])
+{
+  /* With --exprlocs we process all DIEs looking for any attribute
+     which contains an DWARF expression (but not location lists) and
+     print those.  Otherwise we process all function DIEs and print
+     all DWARF expressions and location lists associated with
+     parameters and variables). It must be the first argument,
+     or the second, after --debug.  */
+  bool exprlocs = false;
+
+  /* With --debug we ignore not being able to find .eh_frame.
+     It must come as first argument.  */
+  is_debug = false;
+  if (argc > 1)
+    {
+      if (strcmp ("--exprlocs", argv[1]) == 0)
+	{
+	  exprlocs = true;
+	  argv[1] = "";
+	}
+      else if (strcmp ("--debug", argv[1]) == 0)
+	{
+	  is_debug = true;
+	  argv[1] = "";
+	}
+    }
+
+  if (argc > 2)
+    {
+      if (strcmp ("--exprlocs", argv[2]) == 0)
+	{
+	  exprlocs = true;
+	  argv[2] = "";
+	}
+    }
+
+  int remaining;
+  Dwfl *dwfl;
+  (void) argp_parse (dwfl_standard_argp (), argc, argv, 0, &remaining,
+                     &dwfl);
+  assert (dwfl != NULL);
+
+  Dwarf_Die *cu = NULL;
+  Dwarf_Addr dwbias;
+  bool found_cu = false;
+  while ((cu = dwfl_nextcu (dwfl, cu, &dwbias)) != NULL)
+    {
+      /* Only walk actual compile units (not partial units) that
+	 contain code if we are only interested in the function variable
+	 locations.  */
+      Dwarf_Die cudie;
+      Dwarf_Die subdie;
+      uint8_t unit_type;
+      if (dwarf_cu_info (cu->cu, NULL, &unit_type, &cudie, &subdie,
+		         NULL, NULL, NULL) != 0)
+	error (EXIT_FAILURE, 0, "dwarf_cu_info: %s", dwarf_errmsg (-1));
+      if (unit_type == DW_UT_skeleton)
+	cudie = subdie;
+
+      Dwarf_Addr cubase;
+      if (dwarf_tag (&cudie) == DW_TAG_compile_unit
+	  && (exprlocs || dwarf_lowpc (&cudie, &cubase) == 0))
+	{
+	  found_cu = true;
+
+	  Dwfl_Module *mod = dwfl_cumodule (cu);
+	  Dwarf_Addr modbias;
+	  dw = dwfl_module_getdwarf (mod, &modbias);
+	  assert (dwbias == modbias);
+
+	  const char *mainfile;
+	  const char *modname = dwfl_module_info (mod, NULL,
+						  NULL, NULL,
+						  NULL, NULL,
+						  &mainfile,
+						  NULL);
+	  if (modname == NULL)
+	    error (EXIT_FAILURE, 0, "dwfl_module_info: %s", dwarf_errmsg (-1));
+
+	  const char *name = (modname[0] != '\0'
+			      ? modname
+			      :  xbasename (mainfile));
+	  printf ("module '%s'\n", name);
+	  print_die (&cudie, "CU", 0);
+
+	  Dwarf_Addr elfbias;
+	  Elf *elf = dwfl_module_getelf (mod, &elfbias);
+
+	  // CFI. We need both since sometimes neither is complete.
+	  cfi_debug = dwfl_module_dwarf_cfi (mod, &cfi_debug_bias);
+	  cfi_eh = dwfl_module_eh_cfi (mod, &cfi_eh_bias);
+
+	  // No bias needed, same file.
+	  assert (cfi_debug == NULL || cfi_debug_bias == 0);
+
+	  // We are a bit forgiving for object files.  There might be
+	  // relocations we don't handle that are needed in some
+	  // places...
+	  GElf_Ehdr ehdr_mem, *ehdr = gelf_getehdr (elf, &ehdr_mem);
+	  is_ET_REL = ehdr->e_type == ET_REL;
+
+	  if (exprlocs)
+	    {
+	      Dwarf_Addr entrypc;
+	      if (dwarf_entrypc (&cudie, &entrypc) != 0)
+		entrypc = 0;
+
+	      /* XXX - Passing true for has_frame_base is not really true.
+		 We do it because we want to resolve all DIEs and all
+		 attributes. Technically we should check that the DIE
+		 (types) are referenced from variables that are defined in
+		 a context (function) that has a frame base.  */
+	      handle_die (&cudie, 0, true /* Should be false */, entrypc);
+	    }
+	  else if (dwarf_getfuncs (&cudie, handle_function, NULL, 0) != 0)
+	    error (EXIT_FAILURE, 0, "dwarf_getfuncs %s",
+		   dwarf_errmsg (-1));
+	}
+    }
+
+  if (! found_cu)
+    error (EXIT_FAILURE, 0, "No DWARF CU found?");
+
+  dwfl_end (dwfl);
+  return 0;
+}
diff --git a/tests/vdsosyms.c b/tests/vdsosyms.c
new file mode 100644
index 0000000..ff1a18a
--- /dev/null
+++ b/tests/vdsosyms.c
@@ -0,0 +1,112 @@
+/* Test program for getting symbol table from vdso module.
+   Copyright (C) 2014 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <config.h>
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include ELFUTILS_HEADER(dwfl)
+#include "system.h"
+
+#ifndef __linux__
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  printf ("Getting the vdso is unsupported.\n");
+  return 77;
+}
+#else /* __linux__ */
+static int vdso_syms = 0;
+
+static int
+module_callback (Dwfl_Module *mod, void **userdata __attribute__((unused)),
+		 const char *name, Dwarf_Addr start __attribute__((unused)),
+		 void *arg __attribute__((unused)))
+{
+  /* We can only recognize the vdso by inspecting the "magic name".  */
+  printf ("module name: %s\n", name);
+  if (startswith (name, "[vdso: "))
+    {
+      vdso_syms = dwfl_module_getsymtab (mod);
+      printf ("vdso syms: %d\n", vdso_syms);
+      if (vdso_syms < 0)
+	error (2, 0, "dwfl_module_getsymtab: %s", dwfl_errmsg (-1));
+
+      for (int i = 0; i < vdso_syms; i++)
+	{
+	  GElf_Sym sym;
+	  GElf_Addr addr;
+	  const char *sname = dwfl_module_getsym_info (mod, i, &sym, &addr,
+						       NULL, NULL, NULL);
+	  assert (sname != NULL);
+	  printf ("%d: '%s' %" PRIx64 " (%" PRIx64 ")\n",
+		  i, sname, sym.st_value, addr);
+	}
+    }
+
+  return DWARF_CB_OK;
+}
+
+int
+main (int argc __attribute__ ((unused)), char **argv __attribute__ ((unused)))
+{
+  static char *debuginfo_path;
+  static const Dwfl_Callbacks proc_callbacks =
+    {
+      .find_debuginfo = dwfl_standard_find_debuginfo,
+      .debuginfo_path = &debuginfo_path,
+
+      .find_elf = dwfl_linux_proc_find_elf,
+    };
+  Dwfl *dwfl = dwfl_begin (&proc_callbacks);
+  if (dwfl == NULL)
+    error (2, 0, "dwfl_begin: %s", dwfl_errmsg (-1));
+
+  /* Take ourself as "arbitrary" process to inspect.  This should work
+     even with "restricted ptrace".  */
+  pid_t pid = getpid();
+
+  int result = dwfl_linux_proc_report (dwfl, pid);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_report: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_report");
+
+  /* Also explicitly attach for older kernels (cannot read vdso otherwise).  */
+  result = dwfl_linux_proc_attach (dwfl, pid, false);
+  if (result < 0)
+    error (2, 0, "dwfl_linux_proc_attach: %s", dwfl_errmsg (-1));
+  else if (result > 0)
+    error (2, result, "dwfl_linux_proc_attach");
+
+  if (dwfl_report_end (dwfl, NULL, NULL) != 0)
+    error (2, 0, "dwfl_report_end: %s", dwfl_errmsg (-1));
+
+  if (dwfl_getmodules (dwfl, module_callback, NULL, 0) != 0)
+    error (1, 0, "dwfl_getmodules: %s", dwfl_errmsg (-1));
+
+  dwfl_end (dwfl);
+
+  /* No symbols is ok, then we haven't seen the vdso at all on this arch.  */
+  return vdso_syms >= 0 ? 0 : -1;
+}
+
+#endif /* ! __linux__ */
diff --git a/tests/vendorelf.c b/tests/vendorelf.c
new file mode 100644
index 0000000..8ce1e5e
--- /dev/null
+++ b/tests/vendorelf.c
@@ -0,0 +1,198 @@
+/* Test program for adding a program header to a vendor specific ELF file.
+   Copyright (C) 2016 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "system.h"
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+void
+check_elf (const char *fname, int class, int use_mmap)
+{
+  printf ("\nfname: %s\n", fname);
+
+  int fd = open (fname, O_RDWR | O_CREAT | O_TRUNC, DEFFILEMODE);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, use_mmap ? ELF_C_WRITE_MMAP : ELF_C_WRITE, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create an ELF header.
+  if (gelf_newehdr (elf, class) == 0)
+    {
+      printf ("cannot create ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Ehdr ehdr_mem;
+  GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
+  if (ehdr == NULL)
+    {
+      printf ("cannot get ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Initialize header.
+  ehdr->e_ident[EI_DATA] = class == ELFCLASS64 ? ELFDATA2LSB : ELFDATA2MSB;
+  ehdr->e_ident[EI_OSABI] = ELFOSABI_GNU;
+  ehdr->e_type = ET_LOOS + 1;
+  ehdr->e_machine = EM_X86_64;
+  ehdr->e_version = EV_CURRENT;
+
+  if (gelf_update_ehdr (elf, ehdr) == 0)
+    {
+      printf ("cannot update ELF header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Create a program header.
+  if (gelf_newphdr (elf, 1) == 0)
+    {
+      printf ("cannot create program header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Phdr phdr;
+  if (gelf_getphdr (elf, 0, &phdr) == NULL)
+    {
+      printf ("cannot get program header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Some random values to check later.
+  phdr.p_type = PT_NULL;
+  phdr.p_offset = 0;
+  phdr.p_vaddr = 0;
+  phdr.p_paddr = 1;
+  phdr.p_filesz = 0;
+  phdr.p_memsz = 1024;
+  phdr.p_flags = PF_R;
+  phdr.p_align = 16;
+
+  if (gelf_update_phdr (elf, 0, &phdr) == 0)
+    {
+      printf ("cannot update program header: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Write everything to disk.
+  if (elf_update (elf, ELF_C_WRITE) < 0)
+    {
+      printf ("failure in elf_update(WRITE): %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  /* Reread the ELF from disk now.  */
+  fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  elf = elf_begin (fd, use_mmap ? ELF_C_READ_MMAP : ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  // Is our phdr there?
+  size_t phnum;
+  if (elf_getphdrnum (elf, &phnum) != 0)
+    {
+      printf ("cannot get phdr num: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (phnum != 1)
+    {
+      printf ("Expected just 1 phdr, got: %zd\n", phnum);
+      exit (1);
+    }
+
+  if (gelf_getphdr (elf, 0, &phdr) == NULL)
+    {
+      printf ("cannot get program header from file: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (phdr.p_type != PT_NULL
+      || phdr.p_offset != 0
+      || phdr.p_vaddr != 0
+      || phdr.p_paddr != 1
+      || phdr.p_filesz != 0
+      || phdr.p_memsz != 1024
+      || phdr.p_flags != PF_R
+      || phdr.p_align != 16)
+    {
+      printf ("Unexpected phdr values\n");
+      exit (1);
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  unlink (fname);
+}
+
+int
+main (int argc __attribute__ ((unused)),
+      char *argv[] __attribute__ ((unused)))
+{
+  elf_version (EV_CURRENT);
+
+  check_elf ("vendor.elf.32", ELFCLASS32, 0);
+  check_elf ("vendor.elf.32.mmap", ELFCLASS32, 1);
+  check_elf ("vendor.elf.64", ELFCLASS64, 0);
+  check_elf ("vendor.elf.64.mmap", ELFCLASS64, 1);
+
+  return 0;
+}
diff --git a/tests/xlate_notes.c b/tests/xlate_notes.c
new file mode 100644
index 0000000..90a4ae2
--- /dev/null
+++ b/tests/xlate_notes.c
@@ -0,0 +1,157 @@
+/* Test program for extracting ELF Note headers and getting whole notes.
+   Copyright (C) 2019 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 2)
+    {
+      printf ("No ELF file given as argument\n");
+      exit (1);
+    }
+
+  const char *fname = argv[1];
+
+  // Initialize libelf.
+  elf_version (EV_CURRENT);
+
+  /* Read the ELF from disk now.  */
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open '%s': %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  GElf_Ehdr ehdr;
+  if (gelf_getehdr (elf, &ehdr) == NULL)
+    {
+      printf ("cannot get Ehdr: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  /* Search for all SHT_NOTE sections.  */
+  Elf_Scn *scn = NULL;
+  while ((scn = elf_nextscn (elf, scn)) != NULL)
+    {
+      /* Get the header.  */
+      GElf_Shdr shdr;
+      if (gelf_getshdr (scn, &shdr) == NULL)
+	{
+	  printf ("couldn't get shdr: %s\n", elf_errmsg (-1));
+	  exit (1);
+	}
+
+      if (shdr.sh_type == SHT_NOTE)
+	{
+	  printf ("Notes in section %zd:\n", elf_ndxscn (scn));
+
+	  Elf_Data *raw = elf_rawdata (scn, NULL);
+	  if (raw == NULL)
+	    {
+	      printf ("couldn't get raw data: %s\n", elf_errmsg (-1));
+	      exit (1);
+	    }
+
+	  Elf_Data *data = elf_getdata (scn, NULL);
+	  if (data == NULL)
+	    {
+	      printf ("couldn't get data: %s\n", elf_errmsg (-1));
+	      exit (1);
+	    }
+
+	  size_t off = 0;
+	  size_t next;
+	  GElf_Nhdr nhdr;
+	  size_t n_off;
+	  size_t d_off;
+	  while ((next = gelf_getnote (data, off, &nhdr, &n_off, &d_off)) > 0)
+	    {
+	      /* Now just get the note header "raw" (don't
+		 copy/translate the note data). This only handles
+		 traditional GNU ELF Notes, so we still use the next
+		 from gelf_getnote (padding is different for new style
+		 ELF_T_NHDR8 notes).  */
+	      Elf32_Nhdr nh;
+	      Elf_Data src =
+                {
+                  .d_version = EV_CURRENT, .d_type = ELF_T_NHDR,
+		  .d_size = sizeof nh
+                };
+	      Elf_Data dst = src;
+	      src.d_buf = raw->d_buf + off;
+	      dst.d_buf = &nh;
+
+	      if (elf32_xlatetom (&dst, &src, ehdr.e_ident[EI_DATA]) == NULL)
+		{
+		  printf ("couldn't xlate note: %s\n", elf_errmsg (-1));
+		  exit (1);
+		}
+
+	      printf ("type: %" PRId32 ",%" PRId32
+		      ", namesz: %" PRId32 ",%" PRId32
+		      ", descsz: %" PRId32 ",%" PRId32 "\n",
+		      nhdr.n_type, nh.n_type,
+		      nhdr.n_namesz, nh.n_namesz,
+		      nhdr.n_descsz, nh.n_descsz);
+
+	      if (nhdr.n_type != nh.n_type
+		  || nhdr.n_namesz != nh.n_namesz
+		  || nhdr.n_descsz != nh.n_descsz)
+		{
+		  printf ("Nhdrs not equal!\n");
+		  exit (1);
+		}
+
+	      off = next;
+	    }
+	}
+
+    }
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  return 0;
+}
diff --git a/tests/zstrptr.c b/tests/zstrptr.c
new file mode 100644
index 0000000..9fb42e2
--- /dev/null
+++ b/tests/zstrptr.c
@@ -0,0 +1,125 @@
+/* Test program for elf_strptr function.
+   Copyright (C) 2015 Red Hat, Inc.
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include ELFUTILS_HEADER(elf)
+#include <gelf.h>
+
+static void
+print_strings (Elf_Scn *scn, Elf *elf, size_t ndx)
+{
+  GElf_Shdr shdr_mem;
+  GElf_Shdr *shdr = gelf_getshdr (scn, &shdr_mem);
+
+  printf ("Strings in section %zd (%s):\n", ndx,
+	  ((shdr->sh_flags & SHF_COMPRESSED) != 0
+	   ? "compressed" : "uncompressed"));
+
+  size_t off = 0;
+  const char *str = elf_strptr (elf, ndx, off);
+  while (str != NULL)
+    {
+      printf ("[%zx] '%s'\n", off, str);
+      off += strlen (str) + 1;
+      str = elf_strptr (elf, ndx, off);
+    }
+}
+
+int
+main (int argc, char *argv[])
+{
+  if (argc != 2)
+    {
+      printf ("No ELF file given as argument");
+      exit (1);
+    }
+
+  const char *fname = argv[1];
+
+  // Initialize libelf.
+  elf_version (EV_CURRENT);
+
+  /* Read the ELF from disk now.  */
+  int fd = open (fname, O_RDONLY);
+  if (fd == -1)
+    {
+      printf ("cannot open `%s' read-only: %s\n", fname, strerror (errno));
+      exit (1);
+    }
+
+  Elf *elf = elf_begin (fd, ELF_C_READ, NULL);
+  if (elf == NULL)
+    {
+      printf ("cannot create ELF descriptor read-only: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  size_t ndx;
+  if (elf_getshdrstrndx (elf, &ndx) != 0)
+    {
+      printf ("cannot get section header table index: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (ndx == SHN_UNDEF)
+    {
+      printf ("ELF file `%s' doesn't have a section header table index", fname);
+      exit (1);
+    }
+
+  Elf_Scn *scn = elf_getscn (elf, ndx);
+  if (scn == NULL)
+    {
+      printf ("Couldn't get section %zd: %s\n", ndx, elf_errmsg (-1));
+      exit (1);
+    }
+
+  if (elf_compress (scn, ELFCOMPRESS_ZLIB, 0) < 0)
+    {
+      printf ("Couldn't compress section %zd: %s\n", ndx, elf_errmsg (-1));
+      exit (1);
+    }
+  print_strings (scn, elf, ndx);
+
+  if (elf_compress (scn, 0, 0) < 0)
+    {
+      printf ("Couldn't decompress section %zd: %s\n", ndx, elf_errmsg (-1));
+      exit (1);
+    }
+  print_strings (scn, elf, ndx);
+
+  if (elf_end (elf) != 0)
+    {
+      printf ("failure in elf_end: %s\n", elf_errmsg (-1));
+      exit (1);
+    }
+
+  close (fd);
+
+  return 0;
+}
diff --git a/version.h b/version.h
new file mode 100644
index 0000000..bf14d61
--- /dev/null
+++ b/version.h
@@ -0,0 +1,38 @@
+/* Version information about elfutils development libraries.
+   Copyright (C) 2008 Red Hat, Inc.
+
+   This file is part of elfutils.
+
+   This file is free software; you can redistribute it and/or modify
+   it under the terms of either
+
+     * the GNU Lesser General Public License as published by the Free
+       Software Foundation; either version 3 of the License, or (at
+       your option) any later version
+
+   or
+
+     * the GNU General Public License as published by the Free
+       Software Foundation; either version 2 of the License, or (at
+       your option) any later version
+
+   or both in parallel, as here.
+
+   elfutils is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received copies of the GNU General Public License and
+   the GNU Lesser General Public License along with this program.  If
+   not, see <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ELFUTILS_VERSION_H
+#define _ELFUTILS_VERSION_H	1
+
+#define _ELFUTILS_VERSION	191
+
+#define _ELFUTILS_PREREQ(major, minor) \
+  (_ELFUTILS_VERSION >= ((major) * 1000 + (minor)))
+
+#endif	/* elfutils/version.h */